Static dir configuration and tree view of notes
This commit is contained in:
parent
99a15aa567
commit
cb9d95bcb2
@ -23,6 +23,10 @@ type Config struct {
|
||||
Password string
|
||||
}
|
||||
|
||||
Application struct {
|
||||
StaticDir string
|
||||
}
|
||||
|
||||
Session struct {
|
||||
DaysValid int
|
||||
}
|
||||
|
31
main.go
31
main.go
@ -59,11 +59,12 @@ func main() {// {{{
|
||||
connectionManager = NewConnectionManager()
|
||||
go connectionManager.BroadcastLoop()
|
||||
|
||||
static = http.FileServer(http.Dir("./static"))
|
||||
static = http.FileServer(http.Dir(config.Application.StaticDir))
|
||||
http.HandleFunc("/css_updated", cssUpdateHandler)
|
||||
http.HandleFunc("/session/create", sessionCreate)
|
||||
http.HandleFunc("/session/retrieve", sessionRetrieve)
|
||||
http.HandleFunc("/session/authenticate", sessionAuthenticate)
|
||||
http.HandleFunc("/node/tree", nodeTree)
|
||||
http.HandleFunc("/node/retrieve", nodeRetrieve)
|
||||
http.HandleFunc("/node/create", nodeCreate)
|
||||
http.HandleFunc("/node/update", nodeUpdate)
|
||||
@ -185,6 +186,32 @@ func sessionAuthenticate(w http.ResponseWriter, r *http.Request) {// {{{
|
||||
})
|
||||
}// }}}
|
||||
|
||||
func nodeTree(w http.ResponseWriter, r *http.Request) {// {{{
|
||||
var err error
|
||||
var session Session
|
||||
|
||||
if session, _, err = ValidateSession(r, true); err != nil {
|
||||
responseError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
req := struct { StartNodeID int }{}
|
||||
if err = parseRequest(r, &req); err != nil {
|
||||
responseError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
nodes, err := session.NodeTree(req.StartNodeID)
|
||||
if err != nil {
|
||||
responseError(w, err)
|
||||
return
|
||||
}
|
||||
|
||||
responseData(w, map[string]interface{}{
|
||||
"OK": true,
|
||||
"Nodes": nodes,
|
||||
})
|
||||
}// }}}
|
||||
func nodeRetrieve(w http.ResponseWriter, r *http.Request) {// {{{
|
||||
log.Println("/node/retrieve")
|
||||
var err error
|
||||
@ -332,7 +359,7 @@ func newTemplate(requestPath string) (tmpl *template.Template, err error) {// {{
|
||||
if p[len(p)-1] == '/' {
|
||||
p += "index.html"
|
||||
}
|
||||
p = "static" + p
|
||||
p = config.Application.StaticDir + p
|
||||
|
||||
base := path.Base(p)
|
||||
if tmpl, err = template.New(base).ParseFiles(p); err != nil { return }
|
||||
|
66
node.go
66
node.go
@ -5,7 +5,7 @@ import (
|
||||
"github.com/jmoiron/sqlx"
|
||||
|
||||
// Standard
|
||||
|
||||
"time"
|
||||
)
|
||||
|
||||
type Node struct {
|
||||
@ -14,11 +14,75 @@ type Node struct {
|
||||
ParentID int `db:"parent_id"`
|
||||
Name string
|
||||
Content string
|
||||
Updated time.Time
|
||||
Children []Node
|
||||
Crumbs []Node
|
||||
Complete bool
|
||||
Level int
|
||||
}
|
||||
|
||||
func (session Session) NodeTree(startNodeID int) (nodes []Node, err error) {// {{{
|
||||
var rows *sqlx.Rows
|
||||
rows, err = db.Queryx(`
|
||||
WITH RECURSIVE nodetree AS (
|
||||
SELECT
|
||||
*,
|
||||
array[name::text] AS path,
|
||||
0 AS level
|
||||
FROM node
|
||||
WHERE
|
||||
user_id = $1 AND
|
||||
CASE $2::int
|
||||
WHEN 0 THEN parent_id IS NULL
|
||||
ELSE parent_id = $2
|
||||
END
|
||||
|
||||
UNION ALL
|
||||
|
||||
SELECT
|
||||
n.*,
|
||||
path||n.name::text AS path,
|
||||
nt.level + 1 AS level
|
||||
FROM node n
|
||||
INNER JOIN nodetree nt ON n.parent_id = nt.id
|
||||
)
|
||||
|
||||
SELECT
|
||||
id,
|
||||
user_id,
|
||||
COALESCE(parent_id, 0) AS parent_id,
|
||||
name,
|
||||
updated,
|
||||
level
|
||||
FROM nodetree
|
||||
ORDER BY
|
||||
path ASC
|
||||
`,
|
||||
session.UserID,
|
||||
startNodeID,
|
||||
)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer rows.Close()
|
||||
|
||||
type resultRow struct {
|
||||
Node
|
||||
Level int
|
||||
}
|
||||
|
||||
nodes = []Node{}
|
||||
for rows.Next() {
|
||||
node := Node{}
|
||||
node.Complete = false
|
||||
if err = rows.StructScan(&node); err != nil {
|
||||
return
|
||||
}
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
|
||||
return
|
||||
}// }}}
|
||||
func (session Session) RootNode() (node Node, err error) {// {{{
|
||||
var rows *sqlx.Rows
|
||||
rows, err = db.Queryx(`
|
||||
|
@ -158,6 +158,9 @@ header .menu {
|
||||
border-radius: 8px;
|
||||
height: 48px;
|
||||
}
|
||||
.tree {
|
||||
padding: 16px;
|
||||
}
|
||||
@media only screen and (max-width: 100ex) {
|
||||
.node-content {
|
||||
width: 100%;
|
||||
|
@ -7,6 +7,7 @@ export class NodeUI extends Component {
|
||||
constructor() {//{{{
|
||||
super()
|
||||
this.menu = signal(false)
|
||||
this.tree = signal(null)
|
||||
this.node = signal(null)
|
||||
this.nodeContent = createRef()
|
||||
window.addEventListener('popstate', evt=>{
|
||||
@ -21,6 +22,11 @@ export class NodeUI extends Component {
|
||||
return
|
||||
|
||||
let node = this.node.value
|
||||
let tree = this.tree.value
|
||||
|
||||
let treeHTML = html`Tree`
|
||||
if(tree !== null)
|
||||
treeHTML = this.renderTree(tree)
|
||||
|
||||
let crumbs = [
|
||||
html`<div class="crumb" onclick=${()=>this.goToNode(0)}>Start</div>`
|
||||
@ -58,6 +64,10 @@ export class NodeUI extends Component {
|
||||
<div class="crumbs">${crumbs}</crumbs>
|
||||
|
||||
${children.length > 0 ? html`<div class="child-nodes">${children}</div>` : html``}
|
||||
<div class="tree" onclick=${()=>this.retrieveTree()} style="color: #000">
|
||||
<div class="node">Start</div>
|
||||
${treeHTML}
|
||||
</div>
|
||||
|
||||
${node.ID > 0 ? html`
|
||||
<div class="node-name">${node.Name}</div>
|
||||
@ -146,6 +156,16 @@ export class NodeUI extends Component {
|
||||
})
|
||||
.catch(this.props.app.responseError)
|
||||
}//}}}
|
||||
retrieveTree() {//{{{
|
||||
this.props.app.request('/node/tree', { StartNodeID: this.node.value.ID })
|
||||
.then(res=>{
|
||||
this.tree.value = res.Nodes
|
||||
})
|
||||
.catch(this.props.app.responseError)
|
||||
}//}}}
|
||||
renderTree(tree) {//{{{
|
||||
return tree.map(node=>html`<div class="node" style="margin-left: ${(node.Level+1) * 32}px">${node.Name}</div>`)
|
||||
}//}}}
|
||||
}
|
||||
|
||||
class NodeContent extends Component {
|
||||
|
@ -188,6 +188,10 @@ header {
|
||||
}
|
||||
}
|
||||
|
||||
.tree {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 100ex) {
|
||||
.node-content {
|
||||
width: 100%;
|
||||
|
Loading…
Reference in New Issue
Block a user