mirror of
https://github.com/osmarks/mycorrhiza.git
synced 2024-12-11 13:00:26 +00:00
Interwiki: Fix some bugs
* Actually, you could not edit interwiki entries before * Fix faulty template in English locale
This commit is contained in:
parent
c2619a6b82
commit
fe4fd09cee
@ -29,6 +29,32 @@ func Init() {
|
||||
log.Printf("Loaded %d interwiki entries\n", len(listOfEntries))
|
||||
}
|
||||
|
||||
func dropEmptyStrings(ss []string) (clean []string) {
|
||||
for _, s := range ss {
|
||||
if s != "" {
|
||||
clean = append(clean, s)
|
||||
}
|
||||
}
|
||||
return clean
|
||||
}
|
||||
|
||||
// difference returns the elements in `a` that aren't in `b`.
|
||||
// Taken from https://stackoverflow.com/a/45428032
|
||||
// CC BY-SA 4.0, no changes made
|
||||
func difference(a, b []string) []string {
|
||||
mb := make(map[string]struct{}, len(b))
|
||||
for _, x := range b {
|
||||
mb[x] = struct{}{}
|
||||
}
|
||||
var diff []string
|
||||
for _, x := range a {
|
||||
if _, found := mb[x]; !found {
|
||||
diff = append(diff, x)
|
||||
}
|
||||
}
|
||||
return diff
|
||||
}
|
||||
|
||||
func areNamesFree(names []string) (bool, string) {
|
||||
for _, name := range names {
|
||||
if _, found := entriesByName[name]; found {
|
||||
@ -40,21 +66,59 @@ func areNamesFree(names []string) (bool, string) {
|
||||
|
||||
var mutex sync.Mutex
|
||||
|
||||
func addEntry(wiki *Wiki) error {
|
||||
func replaceEntry(oldWiki *Wiki, newWiki *Wiki) error {
|
||||
diff := difference(
|
||||
append(newWiki.Aliases, newWiki.Name),
|
||||
append(oldWiki.Aliases, oldWiki.Name),
|
||||
)
|
||||
if ok, name := areNamesFree(diff); !ok {
|
||||
return errors.New(name)
|
||||
}
|
||||
deleteEntry(oldWiki)
|
||||
return addEntry(newWiki)
|
||||
}
|
||||
|
||||
func deleteEntry(wiki *Wiki) {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
|
||||
var (
|
||||
// non-empty names only
|
||||
names = func(names []string) []string {
|
||||
var result []string
|
||||
for _, name := range names {
|
||||
if name != "" {
|
||||
result = append(result, name)
|
||||
}
|
||||
// I'm being fancy here. Come on, the code here is already a mess.
|
||||
// Let me have some fun.
|
||||
var wg sync.WaitGroup
|
||||
|
||||
wg.Add(2)
|
||||
go func() {
|
||||
names := append(wiki.Aliases, wiki.Name)
|
||||
for _, name := range names {
|
||||
name := name // I guess we need that
|
||||
delete(entriesByName, name)
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
go func() {
|
||||
for i, w := range listOfEntries {
|
||||
i, w := i, w
|
||||
if w.Name == wiki.Name {
|
||||
log.Println("It came to delete")
|
||||
// Drop ith element.
|
||||
listOfEntries[i] = listOfEntries[len(listOfEntries)-1]
|
||||
listOfEntries = listOfEntries[:len(listOfEntries)-1]
|
||||
break
|
||||
}
|
||||
return result
|
||||
}(append(wiki.Aliases, wiki.Name))
|
||||
}
|
||||
wg.Done()
|
||||
}()
|
||||
|
||||
wg.Wait()
|
||||
}
|
||||
|
||||
func addEntry(wiki *Wiki) error {
|
||||
mutex.Lock()
|
||||
defer mutex.Unlock()
|
||||
wiki.Aliases = dropEmptyStrings(wiki.Aliases)
|
||||
var (
|
||||
names = append(wiki.Aliases, wiki.Name)
|
||||
ok, name = areNamesFree(names)
|
||||
)
|
||||
if !ok {
|
||||
|
@ -5,6 +5,8 @@
|
||||
{{define "aliases (,)"}}Aliases (separated by commas):{{end}}
|
||||
{{define "engine"}}Engine:{{end}}
|
||||
{{define "engine/mycorrhiza"}}Mycorrhiza{{end}}
|
||||
{{define "engine/betula"}}Betula{{end}}
|
||||
{{define "engine/agora"}}Agora{{end}}
|
||||
{{define "engine/generic"}}Generic (any website){{end}}
|
||||
{{define "url"}}URL{{end}}
|
||||
{{define "link href format"}}Link href attribute format string:{{end}}
|
||||
@ -53,7 +55,7 @@
|
||||
<form method="post" action="/interwiki/modify-entry/{{.Name}}">
|
||||
<p>
|
||||
<label for="name{{$i}}" class="required-field">{{template "name"}}</label>
|
||||
<input type="text" id="name" name="name{{$i}}" required
|
||||
<input type="text" id="name{{$i}}" name="name" required
|
||||
value="{{.Name}}">
|
||||
</p>
|
||||
<p>
|
||||
@ -125,7 +127,7 @@
|
||||
<input type="url" id="img-src-format" name="img-src-format"
|
||||
placeholder="https://wiki.example.org/media/{NAME}">
|
||||
</p>
|
||||
<input type="submit" class="btn">
|
||||
<input type="submit" class="btn" value="Add entry">
|
||||
</form>
|
||||
{{end}}
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
<main class="main-width">
|
||||
<h1>{{block "heading" .}}Name taken{{end}}</h1>
|
||||
<p>{{block "tip" .TakenName}}Name <kbd>{{.}}</kbd> is already taken, please choose a different one.{{end}}</p>
|
||||
<form method="post" action="/interwiki/add-entry">
|
||||
<form method="post" action="/interwiki/{{.Action}}">
|
||||
<p>
|
||||
<label for="name" class="required-field">Name:</label>
|
||||
<input type="text" id="name" name="name" required
|
||||
|
@ -4,6 +4,7 @@ import (
|
||||
"embed"
|
||||
"github.com/bouncepaw/mycorrhiza/viewutil"
|
||||
"github.com/gorilla/mux"
|
||||
"log"
|
||||
"net/http"
|
||||
"strings"
|
||||
)
|
||||
@ -37,9 +38,10 @@ func InitHandlers(rtr *mux.Router) {
|
||||
chainNameTaken = viewutil.CopyEnRuWith(fs, "view_name_taken.html", ruTranslation)
|
||||
rtr.HandleFunc("/interwiki", handlerInterwiki)
|
||||
rtr.HandleFunc("/interwiki/add-entry", handlerAddEntry).Methods(http.MethodPost)
|
||||
rtr.HandleFunc("/interwiki/modify-entry/{target}", handlerModifyEntry).Methods(http.MethodPost)
|
||||
}
|
||||
|
||||
func handlerAddEntry(w http.ResponseWriter, rq *http.Request) {
|
||||
func readInterwikiEntryFromRequest(rq *http.Request) Wiki {
|
||||
wiki := Wiki{
|
||||
Name: rq.PostFormValue("name"),
|
||||
Aliases: strings.Split(rq.PostFormValue("aliases"), ","),
|
||||
@ -49,8 +51,38 @@ func handlerAddEntry(w http.ResponseWriter, rq *http.Request) {
|
||||
Engine: WikiEngine(rq.PostFormValue("engine")),
|
||||
}
|
||||
wiki.canonize()
|
||||
return wiki
|
||||
}
|
||||
|
||||
func handlerModifyEntry(w http.ResponseWriter, rq *http.Request) {
|
||||
var (
|
||||
oldData *Wiki
|
||||
ok bool
|
||||
name = mux.Vars(rq)["target"]
|
||||
newData = readInterwikiEntryFromRequest(rq)
|
||||
)
|
||||
|
||||
if oldData, ok = entriesByName[name]; !ok {
|
||||
log.Printf("Could not modify interwiki entry ‘%s’ because it does not exist", name)
|
||||
viewutil.HandlerNotFound(w, rq)
|
||||
return
|
||||
}
|
||||
|
||||
if err := replaceEntry(oldData, &newData); err != nil {
|
||||
log.Printf("Could not modify interwiki entry ‘%s’ because one of the proposed aliases/name is taken\n", name)
|
||||
viewNameTaken(viewutil.MetaFrom(w, rq), oldData, err.Error(), "modify-entry/"+name)
|
||||
return
|
||||
}
|
||||
|
||||
saveInterwikiJson()
|
||||
log.Printf("Modified interwiki entry ‘%s’\n", name)
|
||||
http.Redirect(w, rq, "/interwiki", http.StatusSeeOther)
|
||||
}
|
||||
|
||||
func handlerAddEntry(w http.ResponseWriter, rq *http.Request) {
|
||||
wiki := readInterwikiEntryFromRequest(rq)
|
||||
if err := addEntry(&wiki); err != nil {
|
||||
viewNameTaken(viewutil.MetaFrom(w, rq), &wiki, err.Error())
|
||||
viewNameTaken(viewutil.MetaFrom(w, rq), &wiki, err.Error(), "add-entry")
|
||||
return
|
||||
}
|
||||
saveInterwikiJson()
|
||||
@ -61,13 +93,15 @@ type nameTakenData struct {
|
||||
*viewutil.BaseData
|
||||
*Wiki
|
||||
TakenName string
|
||||
Action string
|
||||
}
|
||||
|
||||
func viewNameTaken(meta viewutil.Meta, wiki *Wiki, takenName string) {
|
||||
func viewNameTaken(meta viewutil.Meta, wiki *Wiki, takenName, action string) {
|
||||
viewutil.ExecutePage(meta, chainNameTaken, nameTakenData{
|
||||
BaseData: &viewutil.BaseData{},
|
||||
Wiki: wiki,
|
||||
TakenName: takenName,
|
||||
Action: action,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -26,3 +26,9 @@ func HttpErr(meta Meta, status int, name, errMsg string) {
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
// HandlerNotFound prints the simples 404 page. Use in rare places that cannot be achieved normally.
|
||||
func HandlerNotFound(w http.ResponseWriter, _ *http.Request) {
|
||||
w.WriteHeader(http.StatusNotFound)
|
||||
w.Write([]byte("404 Page not found"))
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user