Problem: wiki does not support spaced repetition

Solution: implement spaced repetition for review of blocks
This commit is contained in:
Peter Stuifzand 2022-01-17 00:15:00 +01:00
parent 7d898afb03
commit 6c7b66f4ab
6 changed files with 82 additions and 34 deletions

View File

@ -4,6 +4,7 @@ import './styles.scss'
import Editor from './editor' import Editor from './editor'
import MD from './markdown' import MD from './markdown'
import wikiGraph from "./graph"; import wikiGraph from "./graph";
import "./sr";
moment.locale('nl') moment.locale('nl')
// mermaid.initialize({startOnLoad: true}) // mermaid.initialize({startOnLoad: true})

View File

@ -49,6 +49,7 @@ function startQuery(query, opt) {
} }
$.each(data.hits, (key, value) => { $.each(data.hits, (key, value) => {
actualResult.push({ actualResult.push({
id: value.id,
ref: value.fields.page, ref: value.fields.page,
title: value.fields.title, title: value.fields.title,
line: value.fields.text, line: value.fields.text,

View File

@ -4,8 +4,13 @@
@import "~bulma/sass/base/_all"; @import "~bulma/sass/base/_all";
@import "~bulma/sass/elements/title.sass"; @import "~bulma/sass/elements/title.sass";
@import "~bulma/sass/elements/content.sass"; @import "~bulma/sass/elements/content.sass";
@import "~bulma/sass/elements/button.sass";
@import "~bulma/sass/form/shared.sass";
@import "~bulma/sass/form/input-textarea.sass";
@import "~bulma/sass/elements/other.sass";
@import "~bulma/sass/components/breadcrumb.sass"; @import "~bulma/sass/components/breadcrumb.sass";
@import "~bulma/sass/components/navbar.sass"; @import "~bulma/sass/components/navbar.sass";
@import "~bulma/sass/components/modal.sass";
@import '~jquery-contextmenu/dist/jquery.contextMenu.css'; @import '~jquery-contextmenu/dist/jquery.contextMenu.css';
//@import '~vis-network/styles/vis-network.css'; //@import '~vis-network/styles/vis-network.css';
@ -671,3 +676,6 @@ input.input-line, input.input-line:active {
border-radius: 3px; border-radius: 3px;
padding: 2px 4px; padding: 2px 4px;
} }
.review {
}

73
main.go
View File

@ -37,6 +37,7 @@ import (
"strings" "strings"
"time" "time"
"github.com/davecgh/go-spew/spew"
"p83.nl/go/ekster/pkg/util" "p83.nl/go/ekster/pkg/util"
"p83.nl/go/indieauth" "p83.nl/go/indieauth"
"p83.nl/go/wiki/link" "p83.nl/go/wiki/link"
@ -1114,6 +1115,29 @@ func main() {
} }
} }
})) }))
http.HandleFunc("/api/block/replace", wrapAuth(func(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm()
if err != nil {
http.Error(w, err.Error(), 400)
return
}
id := r.Form.Get("id")
if id == "" {
http.Error(w, "missing id", 400)
return
}
repo := blockRepo{
dirname: "data",
}
block, err := repo.Load(id)
block.Text = r.Form.Get("text")
err = repo.Save(id, block)
searchObjects, err := createSearchObjects(id)
for _, so := range searchObjects {
searchIndex.Index(so.ID, so)
}
return
}))
http.HandleFunc("/api/block/append", wrapAuth(func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/api/block/append", wrapAuth(func(w http.ResponseWriter, r *http.Request) {
err := r.ParseForm() err := r.ParseForm()
if err != nil { if err != nil {
@ -1125,47 +1149,28 @@ func main() {
http.Error(w, "missing id", 400) http.Error(w, "missing id", 400)
return return
} }
repo := blockRepo{
// FIXME: loads the whole page to save one new block dirname: "data",
page := mp.Get(id) }
log.Println(page.Content) newBlock := Block{
var listItems []ListItem Text: r.Form.Get("text"),
id = page.Name // Use the name that was actually loaded Children: []string{},
Parent: id,
err = json.NewDecoder(strings.NewReader(page.Content)).Decode(&listItems)
if err != nil && err != io.EOF {
http.Error(w, fmt.Sprintf("while decoding: %s", err.Error()), 500)
return
} }
newId := &ID{"1", true} newId := &ID{"1", true}
generatedID := newId.NewID() generatedID := newId.NewID()
listItems = append(listItems, ListItem{ err = repo.Save(generatedID, newBlock)
ID: generatedID, block, err := repo.Load(id)
Indented: 0, block.Children = append(block.Children, generatedID)
Text: r.Form.Get("text"), err = repo.Save(id, block)
Fleeting: false,
})
var buf bytes.Buffer searchObjects, err := createSearchObjects(id)
spew.Dump("searchObjects", searchObjects)
err = json.NewEncoder(&buf).Encode(&listItems) for _, so := range searchObjects {
if err != nil { searchIndex.Index(so.ID, so)
http.Error(w, fmt.Sprintf("while encoding: %s", err.Error()), 500)
return
} }
page.Content = buf.String()
page.Name = id
page.Title = id
err = mp.Save(id, page, "", "")
if err != nil {
http.Error(w, fmt.Sprintf("while saving: %s", err.Error()), 500)
return
}
fmt.Println(generatedID)
return return
})) }))
http.HandleFunc("/links.json", func(w http.ResponseWriter, r *http.Request) { http.HandleFunc("/links.json", func(w http.ResponseWriter, r *http.Request) {

View File

@ -250,6 +250,13 @@ func createSearchObjects(rootBlockID string) ([]pageBlock, error) {
return nil, err return nil, err
} }
if len(blocks.Parents) > 0 {
page := blocks.Parents[len(blocks.Parents)-1]
if page != rootBlockID {
blocks, err = loadBlocks("data", page)
}
}
var pageBlocks []pageBlock var pageBlocks []pageBlock
queue := []string{blocks.PageID} queue := []string{blocks.PageID}

View File

@ -23,6 +23,31 @@
</div> </div>
</div> </div>
</div> </div>
<div class="modal review-modal">
<div class="modal-background"></div>
<div class="modal-card">
<header class="modal-card-head">
<p class="modal-card-title">Review</p>
<button class="delete" aria-label="close"></button>
</header>
<section class="modal-card-body" style="min-height: 400px">
<h3 class="block-title is-title"></h3>
<textarea class="textarea block-text" style="height:380px"></textarea>
<div class="end-of-review hide">All tasks are reviewed.</p>
</section>
<div class="modal-card-foot" style="justify-content: center">
<button class="button normal is-danger review" data-review="again">Again</button>
<button class="button hard is-warning review" data-review="soon">Soon</button>
<button class="button easy is-success review" data-review="later">Later</button>
<button class="button easy is-default review" data-review="never">Never</button>
<button class="button end-of-review hide close">Close</button>
</div>
</div>
</div>
{{ end }} {{ end }}
{{ define "navbar" }} {{ define "navbar" }}
@ -32,6 +57,7 @@
<a href="/recent/" class="navbar-item">Recent Changes</a> <a href="/recent/" class="navbar-item">Recent Changes</a>
<a href="/graph/" class="navbar-item">Graph</a> <a href="/graph/" class="navbar-item">Graph</a>
<a href="/{{ .TodayPage }}" class="navbar-item">Today</a> <a href="/{{ .TodayPage }}" class="navbar-item">Today</a>
<a href="" class="navbar-item start-review">Review</a>
<a href="/auth/logout" class="navbar-item">Logout</a> <a href="/auth/logout" class="navbar-item">Logout</a>
<span class="navbar-item"><b>{{ $.Session.Me }}</b></span> <span class="navbar-item"><b>{{ $.Session.Me }}</b></span>
{{ else }} {{ else }}