1
0
mirror of https://github.com/osmarks/mycorrhiza.git synced 2024-12-13 05:50:27 +00:00

Render tree

This commit is contained in:
Timur Ismagilov 2020-06-22 18:58:12 +05:00
parent cea18eaa03
commit 6e50ecf6a3
9 changed files with 144 additions and 24 deletions

View File

@ -1,9 +1,14 @@
/* Genealogy is all about relationships between hyphae. For now, the only goal of this file is to help find children of hyphae as they are not marked during the hypha search phase. /* Genealogy is all about relationships between hyphae.*/
TODO: make use of family relations.
*/
package main package main
import (
"fmt"
"log"
"path/filepath"
"sort"
"strings"
)
// setRelations fills in all children names based on what hyphae call their parents. // setRelations fills in all children names based on what hyphae call their parents.
func setRelations(hyphae map[string]*Hypha) { func setRelations(hyphae map[string]*Hypha) {
for name, h := range hyphae { for name, h := range hyphae {
@ -17,3 +22,86 @@ func setRelations(hyphae map[string]*Hypha) {
func (h *Hypha) AddChild(childName string) { func (h *Hypha) AddChild(childName string) {
h.ChildrenNames = append(h.ChildrenNames, childName) h.ChildrenNames = append(h.ChildrenNames, childName)
} }
// If Name == "", the tree is empty.
type Tree struct {
Name string
Ancestors []string
Siblings []string
Descendants []*Tree
Root bool
}
// GetTree generates a Tree for the given hypha name.
// It can also generate trees for non-existent hyphae, that's why we use `name string` instead of making it a method on `Hypha`.
// In `root` is `false`, siblings will not be fetched.
// Parameter `limit` is unused now but it is meant to limit how many subhyphae can be shown.
func GetTree(name string, root bool, limit ...int) *Tree {
t := &Tree{Name: name, Root: root}
for hyphaName, _ := range hyphae {
t.compareNamesAndAppend(hyphaName)
}
sort.Slice(t.Ancestors, func(i, j int) bool {
return strings.Count(t.Ancestors[i], "/") < strings.Count(t.Ancestors[j], "/")
})
sort.Strings(t.Siblings)
sort.Slice(t.Descendants, func(i, j int) bool {
a := t.Descendants[i].Name
b := t.Descendants[j].Name
return len(a) < len(b)
})
log.Printf("Generate tree for %v: %v %v\n", t.Name, t.Ancestors, t.Siblings)
return t
}
// Compares names appends name2 to an array of `t`:
func (t *Tree) compareNamesAndAppend(name2 string) {
switch {
case t.Name == name2:
case strings.HasPrefix(t.Name, name2):
t.Ancestors = append(t.Ancestors, name2)
case t.Root && (strings.Count(t.Name, "/") == strings.Count(name2, "/") &&
(filepath.Dir(t.Name) == filepath.Dir(name2))):
t.Siblings = append(t.Siblings, name2)
case strings.HasPrefix(name2, t.Name):
t.Descendants = append(t.Descendants, GetTree(name2, false))
}
}
// AsHtml returns HTML representation of a tree.
// It recursively itself on the tree's children.
// TODO: redo with templates. I'm not in mood for it now.
func (t *Tree) AsHtml() (html string) {
if t.Name == "" {
return ""
}
html += `<ul class="navitree__node">`
if t.Root {
for _, ancestor := range t.Ancestors {
html += navitreeEntry(ancestor)
}
}
html += navitreeEntry(t.Name)
if t.Root {
for _, siblingName := range t.Siblings {
html += navitreeEntry(siblingName)
}
}
for _, subtree := range t.Descendants {
html += subtree.AsHtml()
}
html += `</ul>`
return html
}
// navitreeEntry is a small utility function that makes generating html easier.
// Someone please redo it in templates.
func navitreeEntry(name string) string {
return fmt.Sprintf(`<li class="navitree__entry">
<a class="navitree__link" href="/%s">%s</a>
</li>
`, name, filepath.Base(name))
}

View File

@ -167,12 +167,21 @@ func HandlerUpdate(w http.ResponseWriter, rq *http.Request) {
vars := mux.Vars(rq) vars := mux.Vars(rq)
log.Println("Attempt to update hypha", mux.Vars(rq)["hypha"]) log.Println("Attempt to update hypha", mux.Vars(rq)["hypha"])
h, isNew := getHypha(vars["hypha"]) h, isNew := getHypha(vars["hypha"])
oldRev := h.GetNewestRevision() var oldRev Revision
if !isNew {
oldRev = h.GetNewestRevision()
} else {
h = &Hypha{
FullName: vars["hypha"],
Path: filepath.Join(rootWikiDir, vars["hypha"]),
Revisions: make(map[string]*Revision),
parentName: filepath.Dir(vars["hypha"]),
}
h.CreateDir()
oldRev = Revision{}
}
newRev := revisionFromHttpData(h, rq) newRev := revisionFromHttpData(h, rq)
if isNew {
h.CreateDir()
}
err := writeTextFileFromHttpData(newRev, rq) err := writeTextFileFromHttpData(newRev, rq)
if err != nil { if err != nil {
log.Println(err) log.Println(err)
@ -186,6 +195,9 @@ func HandlerUpdate(w http.ResponseWriter, rq *http.Request) {
h.Revisions[newRev.IdAsStr()] = newRev h.Revisions[newRev.IdAsStr()] = newRev
h.SaveJson() h.SaveJson()
if isNew {
hyphae[h.FullName] = h
}
log.Println("Current hyphae storage is", hyphae) log.Println("Current hyphae storage is", hyphae)

View File

@ -66,7 +66,7 @@ func (h *Hypha) MetaJsonPath() string {
// CreateDir creates directory where the hypha must reside. // CreateDir creates directory where the hypha must reside.
// It is meant to be used with new hyphae. // It is meant to be used with new hyphae.
func (h *Hypha) CreateDir() error { func (h *Hypha) CreateDir() error {
return os.MkdirAll(h.Path, 0644) return os.MkdirAll(h.Path, os.ModePerm)
} }
// SaveJson dumps the hypha's metadata to `meta.json` file. // SaveJson dumps the hypha's metadata to `meta.json` file.

View File

@ -3,9 +3,7 @@ package main
import ( import (
"bytes" "bytes"
"fmt" "fmt"
"io/ioutil"
"path" "path"
"path/filepath"
"text/template" "text/template"
) )
@ -27,9 +25,10 @@ func EditHyphaPage(name, textMime, content, tags string) string {
// HyphaPage returns HTML page of hypha viewer. // HyphaPage returns HTML page of hypha viewer.
func HyphaPage(rev Revision, content string) string { func HyphaPage(rev Revision, content string) string {
sidebar := DefaultSidebar sidebar := DefaultSidebar
bside, err := ioutil.ReadFile(filepath.Join(templatesDir, "Hypha/view/sidebar.html")) if bside := renderFromMap(map[string]string{
if err == nil { "Tree": GetTree(rev.FullName, true).AsHtml(),
sidebar = string(bside) }, "Hypha/view/sidebar.html"); bside != "" {
sidebar = bside
} }
keys := map[string]string{ keys := map[string]string{
"Title": fmt.Sprintf(TitleTemplate, rev.FullName), "Title": fmt.Sprintf(TitleTemplate, rev.FullName),

View File

Before

Width:  |  Height:  |  Size: 427 KiB

After

Width:  |  Height:  |  Size: 427 KiB

View File

@ -39,7 +39,7 @@
}, },
"4": { "4": {
"tags": null, "tags": null,
"name": "", "name": "Apple",
"comment": "copypaste from wikipedia", "comment": "copypaste from wikipedia",
"author": "", "author": "",
"time": 1592663126, "time": 1592663126,
@ -49,4 +49,4 @@
"binary_name": "4.jpg" "binary_name": "4.jpg"
} }
} }
} }

View File

@ -0,0 +1,3 @@
A **pear** is a sweet fruit, usually with a green skin and a lot of juice, that has a round base and is slightly pointed towards the stem.
Source of info: [cambridge dict](https://dictionary.cambridge.org/ru/словарь/английский/pear)

19
w/m/Fruit/Pear/meta.json Normal file
View File

@ -0,0 +1,19 @@
{
"views": 0,
"deleted": false,
"revisions": {
"1": {
"tags": [
""
],
"name": "Pear",
"comment": "Create Fruit/Pear",
"author": "",
"time": 1592834186,
"text_mime": "text/markdown",
"binary_mime": "",
"text_name": "1.markdown",
"binary_name": ""
}
}
}

View File

@ -1,8 +1,7 @@
<div class="hypha-actions"> <ul class="hypha-actions">
<ul> <li><a href="?action=edit">Edit</a></li>
<li><a href="?action=edit">Edit</a></li> <li><a href="?action=getBinary">Download</a></li>
<li><a href="?action=getBinary">Download</a></li> <li><a href="?action=zen">Zen mode</a></li>
<li><a href="?action=zen">Zen mode</a></li> <li><a href="?action=raw">View raw</a></li>
<li><a href="?action=raw">View raw</a></li> </ul>
</ul> {{ .Tree }}
</div>