Migrate cat views
This commit is contained in:
parent
bd155622af
commit
ec57251f58
@ -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)
|
||||
|
||||
@ -1,37 +0,0 @@
|
||||
{{define "edit category x"}}Edit category {{beautifulName .}}{{end}}
|
||||
{{define "title"}}{{template "edit category x" .CatName}}{{end}}
|
||||
{{define "body"}}
|
||||
<main class="main-width category">
|
||||
<h1>{{block "edit category heading" .CatName}}Edit category <a href="/category/{{.}}">{{beautifulName .}}</a>{{end}}</h1>
|
||||
{{if len .Hyphae | not}}
|
||||
<p>{{block "empty cat" .}}This category is empty{{end}}</p>
|
||||
{{end}}
|
||||
|
||||
{{if .GivenPermissionToModify}}
|
||||
<h2>{{block "add to category title" .}}Add a hypha to the category{{end}}</h2>
|
||||
<form method="POST" action="/add-to-category" class="add-to-category">
|
||||
<input type="text" name="hypha" id="_hypha-name"
|
||||
placeholder="{{block `hypha name` .}}Hypha name{{end}}">
|
||||
<input type="hidden" name="cat" value="{{.CatName}}">
|
||||
<input type="hidden" name="redirect-to" value="/category/{{.CatName}}">
|
||||
<input type="submit" class="btn" value="{{block `add` .}}Add{{end}}">
|
||||
</form>
|
||||
|
||||
{{if len .Hyphae}}
|
||||
<h2>{{block "remove hyphae" .}}Remove hyphae from the category{{end}}</h2>
|
||||
<form method="POST" action="/remove-from-category" class="multi-remove-from-category">
|
||||
<ol>
|
||||
{{range .Hyphae}}
|
||||
<li>
|
||||
<input type="checkbox" name="_{{.}}" id="_{{.}}">
|
||||
<label for="_{{.}}"><a href="/hypha/{{.}}">{{beautifulName .}}</a></label>
|
||||
</li>
|
||||
{{end}}
|
||||
</ol>
|
||||
<input type="hidden" name="cat" value="{{.CatName}}">
|
||||
<input type="hidden" name="redirect-to" value="/edit-category/{{.CatName}}">
|
||||
<input type="submit" class="btn" value="{{block `remove` .}}Remove{{end}}">
|
||||
</form>
|
||||
{{end}}{{end}}
|
||||
</main>
|
||||
{{end}}
|
||||
@ -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"}}Редактирование категории <a href="/category/{{.}}">{{beautifulName .}}</a>{{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,
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
@ -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)
|
||||
}
|
||||
27
web/pages.go
27
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": "Редактирование категории <a href=\"/category/{{.}}\">{{beautifulName .}}</a>",
|
||||
"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")
|
||||
}
|
||||
|
||||
37
web/views/cat-edit.html
Normal file
37
web/views/cat-edit.html
Normal file
@ -0,0 +1,37 @@
|
||||
{{define "edit category x"}}Edit category {{beautifulName .}}{{end}}
|
||||
{{define "title"}}{{template "edit category x" .CatName}}{{end}}
|
||||
{{define "body"}}
|
||||
<main class="main-width category">
|
||||
<h1>{{block "edit category heading" .CatName}}Edit category <a href="/category/{{.}}">{{beautifulName .}}</a>{{end}}</h1>
|
||||
{{if len .Hyphae | not}}
|
||||
<p>{{block "empty cat" .}}This category is empty{{end}}</p>
|
||||
{{end}}
|
||||
|
||||
{{if .GivenPermissionToModify}}
|
||||
<h2>{{block "add to category title" .}}Add a hypha to the category{{end}}</h2>
|
||||
<form method="POST" action="/add-to-category" class="add-to-category">
|
||||
<input type="text" name="hypha" id="_hypha-name"
|
||||
placeholder="{{block `hypha name` .}}Hypha name{{end}}">
|
||||
<input type="hidden" name="cat" value="{{.CatName}}">
|
||||
<input type="hidden" name="redirect-to" value="/category/{{.CatName}}">
|
||||
<input type="submit" class="btn" value="{{block `add` .}}Add{{end}}">
|
||||
</form>
|
||||
|
||||
{{if len .Hyphae}}
|
||||
<h2>{{block "remove hyphae" .}}Remove hyphae from the category{{end}}</h2>
|
||||
<form method="POST" action="/remove-from-category" class="multi-remove-from-category">
|
||||
<ol>
|
||||
{{range .Hyphae}}
|
||||
<li>
|
||||
<input type="checkbox" name="_{{.}}" id="_{{.}}">
|
||||
<label for="_{{.}}"><a href="/hypha/{{.}}">{{beautifulName .}}</a></label>
|
||||
</li>
|
||||
{{end}}
|
||||
</ol>
|
||||
<input type="hidden" name="cat" value="{{.CatName}}">
|
||||
<input type="hidden" name="redirect-to" value="/edit-category/{{.CatName}}">
|
||||
<input type="submit" class="btn" value="{{block `remove` .}}Remove{{end}}">
|
||||
</form>
|
||||
{{end}}{{end}}
|
||||
</main>
|
||||
{{end}}
|
||||
@ -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()
|
||||
|
||||
Loading…
Reference in New Issue
Block a user