diff --git a/categories/categories.go b/categories/categories.go index 75d3482..86faa01 100644 --- a/categories/categories.go +++ b/categories/categories.go @@ -23,8 +23,8 @@ package categories import "sync" -// listOfCategories returns unsorted names of all categories. -func listOfCategories() (categoryList []string) { +// ListOfCategories returns unsorted names of all categories. +func ListOfCategories() (categoryList []string) { mutex.RLock() for cat, _ := range categoryToHyphae { categoryList = append(categoryList, cat) @@ -44,8 +44,8 @@ func CategoriesWithHypha(hyphaName string) (categoryList []string) { } } -// hyphaeInCategory returns what hyphae are in the category. If the returned slice is empty, the category does not exist, and vice versa. The category name must be canonical. -func hyphaeInCategory(catName string) (hyphaList []string) { +// HyphaeInCategory returns what hyphae are in the category. If the returned slice is empty, the category does not exist, and vice versa. The category name must be canonical. +func HyphaeInCategory(catName string) (hyphaList []string) { mutex.RLock() defer mutex.RUnlock() if node, ok := categoryToHyphae[catName]; ok { @@ -75,8 +75,8 @@ func AddHyphaToCategory(hyphaName, catName string) { go saveToDisk() } -// removeHyphaFromCategory removes the hypha from the category and updates the records on the disk. If the hypha is not in the category, nothing happens. Pass canonical names. -func removeHyphaFromCategory(hyphaName, catName string) { +// RemoveHyphaFromCategory removes the hypha from the category and updates the records on the disk. If the hypha is not in the category, nothing happens. Pass canonical names. +func RemoveHyphaFromCategory(hyphaName, catName string) { mutex.Lock() if node, ok := hyphaToCategories[hyphaName]; ok { node.removeCategory(catName) diff --git a/categories/view_edit.html b/categories/view_edit.html deleted file mode 100644 index b8e93d6..0000000 --- a/categories/view_edit.html +++ /dev/null @@ -1,37 +0,0 @@ -{{define "edit category x"}}Edit category {{beautifulName .}}{{end}} -{{define "title"}}{{template "edit category x" .CatName}}{{end}} -{{define "body"}} -
-

{{block "edit category heading" .CatName}}Edit category {{beautifulName .}}{{end}}

- {{if len .Hyphae | not}} -

{{block "empty cat" .}}This category is empty{{end}}

- {{end}} - - {{if .GivenPermissionToModify}} -

{{block "add to category title" .}}Add a hypha to the category{{end}}

-
- - - - -
- - {{if len .Hyphae}} -

{{block "remove hyphae" .}}Remove hyphae from the category{{end}}

-
-
    - {{range .Hyphae}} -
  1. - - -
  2. - {{end}} -
- - - -
- {{end}}{{end}} -
-{{end}} diff --git a/categories/views.go b/categories/views.go index 6526ea7..0ceb0e5 100644 --- a/categories/views.go +++ b/categories/views.go @@ -1,45 +1,29 @@ package categories import ( - "embed" - "sort" - "github.com/bouncepaw/mycorrhiza/web/viewutil" ) const ruTranslation = ` -{{define "empty cat"}}Эта категория пуста.{{end}} -{{define "cat"}}Категория{{end}} -{{define "hypha name"}}Название гифы{{end}} +{{define "empty cat"}}{{end}} +{{define "cat"}}{{end}} +{{define "hypha name"}}{{end}} {{define "categories"}}Категории{{end}} {{define "placeholder"}}Название категории...{{end}} {{define "remove from category title"}}Убрать гифу из этой категории{{end}} -{{define "add to category title"}}Добавить гифу в эту категорию{{end}} -{{define "category list"}}Список категорий{{end}} -{{define "no categories"}}В этой вики нет категорий.{{end}} -{{define "category x"}}Категория {{. | beautifulName}}{{end}} +{{define "add to category title"}}{{end}} +{{define "category list"}}{{end}} +{{define "no categories"}}{{end}} +{{define "category x"}}{{end}} -{{define "edit category x"}}Редактирование категории {{beautifulName .}}{{end}} -{{define "edit category heading"}}Редактирование категории {{beautifulName .}}{{end}} -{{define "add"}}Добавить{{end}} -{{define "remove hyphae"}}Убрать гифы из этой категории{{end}} -{{define "remove"}}Убрать{{end}} -{{define "edit"}}Редактировать{{end}} +{{define "edit category x"}}{{end}} +{{define "edit category heading"}}{{end}} +{{define "add"}}{{end}} +{{define "remove hyphae"}}{{end}} +{{define "remove"}}{{end}} +{{define "edit"}}{{end}} ` -var ( - //go:embed *.html - fs embed.FS - viewListChain, viewPageChain, viewCardChain, viewEditChain viewutil.Chain -) - -func prepareViews() { - viewCardChain = viewutil.CopyEnRuWith(fs, "view_card.html", ruTranslation) - viewListChain = viewutil.CopyEnRuWith(fs, "view_list.html", ruTranslation) - viewPageChain = viewutil.CopyEnRuWith(fs, "view_page.html", ruTranslation) - viewEditChain = viewutil.CopyEnRuWith(fs, "view_edit.html", ruTranslation) -} - type catData struct { *viewutil.BaseData CatName string @@ -47,26 +31,8 @@ type catData struct { GivenPermissionToModify bool } -func categoryEdit(meta viewutil.Meta, catName string) { - viewutil.ExecutePage(meta, viewEditChain, catData{ - BaseData: &viewutil.BaseData{ - Addr: "/edit-category/" + catName, - }, - CatName: catName, - Hyphae: hyphaeInCategory(catName), - GivenPermissionToModify: meta.U.CanProceed("add-to-category"), - }) -} - func categoryPage(meta viewutil.Meta, catName string) { - viewutil.ExecutePage(meta, viewPageChain, catData{ - BaseData: &viewutil.BaseData{ - Addr: "/category/" + catName, - }, - CatName: catName, - Hyphae: hyphaeInCategory(catName), - GivenPermissionToModify: meta.U.CanProceed("add-to-category"), - }) + } type listData struct { @@ -75,12 +41,5 @@ type listData struct { } func categoryList(meta viewutil.Meta) { - cats := listOfCategories() - sort.Strings(cats) - viewutil.ExecutePage(meta, viewListChain, listData{ - BaseData: &viewutil.BaseData{ - Addr: "/category", - }, - Categories: cats, - }) + } diff --git a/categories/handlers.go b/web/cats.go similarity index 74% rename from categories/handlers.go rename to web/cats.go index 4b6b04e..931617b 100644 --- a/categories/handlers.go +++ b/web/cats.go @@ -1,41 +1,46 @@ -package categories +package web import ( + "github.com/bouncepaw/mycorrhiza/categories" "io" "log" + "log/slog" "net/http" + "sort" "strings" "github.com/bouncepaw/mycorrhiza/internal/user" "github.com/bouncepaw/mycorrhiza/util" "github.com/bouncepaw/mycorrhiza/web/viewutil" - "github.com/gorilla/mux" ) -// InitHandlers initializes HTTP handlers for the given router. Call somewhere in package web. -func InitHandlers(r *mux.Router) { - r.PathPrefix("/add-to-category").HandlerFunc(handlerAddToCategory).Methods("POST") - r.PathPrefix("/remove-from-category").HandlerFunc(handlerRemoveFromCategory).Methods("POST") - r.PathPrefix("/category/").HandlerFunc(handlerCategory).Methods("GET") - r.PathPrefix("/edit-category/").HandlerFunc(handlerEditCategory).Methods("GET") - r.PathPrefix("/category").HandlerFunc(handlerListCategory).Methods("GET") - prepareViews() -} - func handlerEditCategory(w http.ResponseWriter, rq *http.Request) { util.PrepareRq(rq) + meta := viewutil.MetaFrom(w, rq) catName := util.CanonicalName(strings.TrimPrefix(strings.TrimPrefix(rq.URL.Path, "/edit-category"), "/")) if catName == "" { - http.Error(w, "No category name", http.StatusBadRequest) + viewutil.HandlerNotFound(w, rq) return } - log.Println("Editing category", catName) - categoryEdit(viewutil.MetaFrom(w, rq), catName) + + slog.Info("Editing category", "name", catName) + _ = pageCatEdit.RenderTo(meta, map[string]any{ + "Addr": "/edit-category/" + catName, + "CatName": catName, + "Hyphae": categories.HyphaeInCategory(catName), + "GivenPermissionToModify": meta.U.CanProceed("add-to-category"), + }) } func handlerListCategory(w http.ResponseWriter, rq *http.Request) { - log.Println("Viewing list of categories") - categoryList(viewutil.MetaFrom(w, rq)) + slog.Info("Viewing list of categories") + cats := categories.ListOfCategories() + sort.Strings(cats) + + _ = pageCatList.RenderTo(viewutil.MetaFrom(w, rq), map[string]any{ + "Addr": "/category", + "Categories": cats, + }) } func handlerCategory(w http.ResponseWriter, rq *http.Request) { @@ -45,8 +50,15 @@ func handlerCategory(w http.ResponseWriter, rq *http.Request) { handlerListCategory(w, rq) return } - log.Println("Viewing category", catName) - categoryPage(viewutil.MetaFrom(w, rq), catName) + + meta := viewutil.MetaFrom(w, rq) + slog.Info("Viewing category", "name", catName) + _ = pageCatPage.RenderTo(meta, map[string]any{ + "Addr": "/category/" + catName, + "CatName": catName, + "Hyphae": categories.HyphaeInCategory(catName), + "GivenPermissionToModify": meta.U.CanProceed("add-to-category"), + }) } // A request for removal of hyphae can either remove one hypha (used in the card on /hypha) or many hyphae (used in /edit-category). Both approaches are handled by /remove-from-category. This function finds all passed hyphae. @@ -94,7 +106,7 @@ func handlerRemoveFromCategory(w http.ResponseWriter, rq *http.Request) { } for _, hyphaName := range hyphaNames { // TODO: Make it more effective. - removeHyphaFromCategory(hyphaName, catName) + categories.RemoveHyphaFromCategory(hyphaName, catName) } log.Printf("%s removed %q from category %s\n", u.Name, hyphaNames, catName) http.Redirect(w, rq, redirectTo, http.StatusSeeOther) @@ -117,6 +129,6 @@ func handlerAddToCategory(w http.ResponseWriter, rq *http.Request) { return } log.Println(user.FromRequest(rq).Name, "added", hyphaName, "to", catName) - AddHyphaToCategory(hyphaName, catName) + categories.AddHyphaToCategory(hyphaName, catName) http.Redirect(w, rq, redirectTo, http.StatusSeeOther) } diff --git a/web/pages.go b/web/pages.go index 2b32276..38cf691 100644 --- a/web/pages.go +++ b/web/pages.go @@ -12,7 +12,8 @@ var fs embed.FS var pageOrphans, pageBacklinks, pageUserList, pageChangePassword *newtmpl.Page var pageHyphaDelete, pageHyphaEdit, pageHyphaEmpty, pageHypha *newtmpl.Page var pageRevision, pageMedia *newtmpl.Page -var pageAuthLock, pageAuthLogin, pageAuthLogout, pageAuthRegister, pageAuthTelegram *newtmpl.Page +var pageAuthLock, pageAuthLogin, pageAuthLogout, pageAuthRegister *newtmpl.Page +var pageCatPage, pageCatList, pageCatEdit *newtmpl.Page var panelChain, listChain, newUserChain, editUserChain, deleteUserChain viewutil.Chain @@ -62,7 +63,7 @@ func initPages() { "describe your changes": `Опишите ваши правки`, "save": `Сохранить`, "preview": `Предпросмотр`, - "previewing hypha": `Предпросмотр «{{beautifulName .}}»`, + "previewing hypha": `Предпросмотр {{beautifulName .}}`, "preview tip": `Заметьте, эта гифа ещё не сохранена. Вот её предпросмотр:`, "markup": `Разметка`, @@ -176,4 +177,26 @@ func initPages() { "register on x": "Регистрация на {{.}}", }, "views/auth-telegram.html", "views/auth-register.html") + pageCatPage = newtmpl.NewPage(fs, map[string]string{ + "category x": "Категория {{. | beautifulName}}", + "edit": "Редактировать", + "cat": "Категория", + "empty cat": "Эта категория пуста.", + }, "views/cat-page.html") + + pageCatEdit = newtmpl.NewPage(fs, map[string]string{ + "edit category x": "Редактирование категории {{beautifulName .}}", + "edit category heading": "Редактирование категории {{beautifulName .}}", + "empty cat": "Эта категория пуста.", + "add to category title": "Добавить гифу в эту категорию", + "hypha name": "Название гифы", + "add": "Добавить", + "remove hyphae": "Убрать гифы из этой категории", + "remove": "Убрать", + }, "views/cat-edit.html") + + pageCatList = newtmpl.NewPage(fs, map[string]string{ + "category list": "Список категорий", + "no categories": "В этой вики нет категорий.", + }, "views/cat-list.html") } diff --git a/web/views/cat-edit.html b/web/views/cat-edit.html new file mode 100644 index 0000000..6fd61bb --- /dev/null +++ b/web/views/cat-edit.html @@ -0,0 +1,37 @@ +{{define "edit category x"}}Edit category {{beautifulName .}}{{end}} +{{define "title"}}{{template "edit category x" .CatName}}{{end}} +{{define "body"}} +
+

{{block "edit category heading" .CatName}}Edit category {{beautifulName .}}{{end}}

+ {{if len .Hyphae | not}} +

{{block "empty cat" .}}This category is empty{{end}}

+ {{end}} + + {{if .GivenPermissionToModify}} +

{{block "add to category title" .}}Add a hypha to the category{{end}}

+
+ + + + +
+ + {{if len .Hyphae}} +

{{block "remove hyphae" .}}Remove hyphae from the category{{end}}

+
+
    + {{range .Hyphae}} +
  1. + + +
  2. + {{end}} +
+ + + +
+ {{end}}{{end}} +
+{{end}} diff --git a/categories/view_list.html b/web/views/cat-list.html similarity index 100% rename from categories/view_list.html rename to web/views/cat-list.html diff --git a/categories/view_page.html b/web/views/cat-page.html similarity index 100% rename from categories/view_page.html rename to web/views/cat-page.html diff --git a/web/web.go b/web/web.go index 2887914..01ba4e6 100644 --- a/web/web.go +++ b/web/web.go @@ -16,7 +16,6 @@ import ( "net/url" "strings" - "github.com/bouncepaw/mycorrhiza/categories" "github.com/bouncepaw/mycorrhiza/help" "github.com/bouncepaw/mycorrhiza/history/histweb" "github.com/bouncepaw/mycorrhiza/hypview" @@ -73,12 +72,17 @@ func Handler() http.Handler { initReaders(r) initMutators(r) help.InitHandlers(r) - categories.InitHandlers(r) misc.InitHandlers(r) hypview.Init() histweb.InitHandlers(r) interwiki.InitHandlers(r) + r.PathPrefix("/add-to-category").HandlerFunc(handlerAddToCategory).Methods("POST") + r.PathPrefix("/remove-from-category").HandlerFunc(handlerRemoveFromCategory).Methods("POST") + r.PathPrefix("/category/").HandlerFunc(handlerCategory).Methods("GET") + r.PathPrefix("/edit-category/").HandlerFunc(handlerEditCategory).Methods("GET") + r.PathPrefix("/category").HandlerFunc(handlerListCategory).Methods("GET") + // Admin routes if cfg.UseAuth { adminRouter := r.PathPrefix("/admin").Subrouter()