diff --git a/genealogy.go b/genealogy.go index 0e3502a..8b2a0af 100644 --- a/genealogy.go +++ b/genealogy.go @@ -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. - -TODO: make use of family relations. -*/ +/* Genealogy is all about relationships between hyphae.*/ package main +import ( + "fmt" + "log" + "path/filepath" + "sort" + "strings" +) + // setRelations fills in all children names based on what hyphae call their parents. func setRelations(hyphae map[string]*Hypha) { for name, h := range hyphae { @@ -17,3 +22,86 @@ func setRelations(hyphae map[string]*Hypha) { func (h *Hypha) AddChild(childName string) { 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 += `` + 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(`
  • + %s +
  • +`, name, filepath.Base(name)) +} diff --git a/handlers.go b/handlers.go index 1b19e9e..a15a4eb 100644 --- a/handlers.go +++ b/handlers.go @@ -167,12 +167,21 @@ func HandlerUpdate(w http.ResponseWriter, rq *http.Request) { vars := mux.Vars(rq) log.Println("Attempt to update hypha", mux.Vars(rq)["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) - if isNew { - h.CreateDir() - } err := writeTextFileFromHttpData(newRev, rq) if err != nil { log.Println(err) @@ -186,6 +195,9 @@ func HandlerUpdate(w http.ResponseWriter, rq *http.Request) { h.Revisions[newRev.IdAsStr()] = newRev h.SaveJson() + if isNew { + hyphae[h.FullName] = h + } log.Println("Current hyphae storage is", hyphae) diff --git a/hypha.go b/hypha.go index 2eb9f09..ec95063 100644 --- a/hypha.go +++ b/hypha.go @@ -66,7 +66,7 @@ func (h *Hypha) MetaJsonPath() string { // CreateDir creates directory where the hypha must reside. // It is meant to be used with new hyphae. 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. diff --git a/render.go b/render.go index 9c8b528..90bec60 100644 --- a/render.go +++ b/render.go @@ -3,9 +3,7 @@ package main import ( "bytes" "fmt" - "io/ioutil" "path" - "path/filepath" "text/template" ) @@ -27,9 +25,10 @@ func EditHyphaPage(name, textMime, content, tags string) string { // HyphaPage returns HTML page of hypha viewer. func HyphaPage(rev Revision, content string) string { sidebar := DefaultSidebar - bside, err := ioutil.ReadFile(filepath.Join(templatesDir, "Hypha/view/sidebar.html")) - if err == nil { - sidebar = string(bside) + if bside := renderFromMap(map[string]string{ + "Tree": GetTree(rev.FullName, true).AsHtml(), + }, "Hypha/view/sidebar.html"); bside != "" { + sidebar = bside } keys := map[string]string{ "Title": fmt.Sprintf(TitleTemplate, rev.FullName), diff --git a/w/m/Fruit/Apple/4.bin b/w/m/Fruit/Apple/4.jpg similarity index 100% rename from w/m/Fruit/Apple/4.bin rename to w/m/Fruit/Apple/4.jpg diff --git a/w/m/Fruit/Apple/meta.json b/w/m/Fruit/Apple/meta.json index b244423..39ff1ec 100644 --- a/w/m/Fruit/Apple/meta.json +++ b/w/m/Fruit/Apple/meta.json @@ -39,7 +39,7 @@ }, "4": { "tags": null, - "name": "", + "name": "Apple", "comment": "copypaste from wikipedia", "author": "", "time": 1592663126, @@ -49,4 +49,4 @@ "binary_name": "4.jpg" } } -} \ No newline at end of file +} diff --git a/w/m/Fruit/Pear/1.markdown b/w/m/Fruit/Pear/1.markdown new file mode 100644 index 0000000..93010b8 --- /dev/null +++ b/w/m/Fruit/Pear/1.markdown @@ -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) \ No newline at end of file diff --git a/w/m/Fruit/Pear/meta.json b/w/m/Fruit/Pear/meta.json new file mode 100644 index 0000000..648d1be --- /dev/null +++ b/w/m/Fruit/Pear/meta.json @@ -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": "" + } + } +} \ No newline at end of file diff --git a/w/templates/Hypha/view/sidebar.html b/w/templates/Hypha/view/sidebar.html index e26616d..9a79ac8 100644 --- a/w/templates/Hypha/view/sidebar.html +++ b/w/templates/Hypha/view/sidebar.html @@ -1,8 +1,7 @@ -
    - -
    + +{{ .Tree }}