Browse Source

Problem: wiki does not support spaced repetition

Solution: implement spaced repetition for review of blocks
master
Peter Stuifzand 4 months ago
parent
commit
6c7b66f4ab
  1. 1
      editor/src/index.js
  2. 1
      editor/src/search.js
  3. 8
      editor/src/styles.scss
  4. 73
      main.go
  5. 7
      search.go
  6. 26
      templates/view.html

1
editor/src/index.js

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

1
editor/src/search.js

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

8
editor/src/styles.scss

@ -4,8 +4,13 @@ @@ -4,8 +4,13 @@
@import "~bulma/sass/base/_all";
@import "~bulma/sass/elements/title.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/navbar.sass";
@import "~bulma/sass/components/modal.sass";
@import '~jquery-contextmenu/dist/jquery.contextMenu.css';
//@import '~vis-network/styles/vis-network.css';
@ -671,3 +676,6 @@ input.input-line, input.input-line:active { @@ -671,3 +676,6 @@ input.input-line, input.input-line:active {
border-radius: 3px;
padding: 2px 4px;
}
.review {
}

73
main.go

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

7
search.go

@ -250,6 +250,13 @@ func createSearchObjects(rootBlockID string) ([]pageBlock, error) { @@ -250,6 +250,13 @@ func createSearchObjects(rootBlockID string) ([]pageBlock, error) {
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
queue := []string{blocks.PageID}

26
templates/view.html

@ -23,6 +23,31 @@ @@ -23,6 +23,31 @@
</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 }}
{{ define "navbar" }}
@ -32,6 +57,7 @@ @@ -32,6 +57,7 @@
<a href="/recent/" class="navbar-item">Recent Changes</a>
<a href="/graph/" class="navbar-item">Graph</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>
<span class="navbar-item"><b>{{ $.Session.Me }}</b></span>
{{ else }}

Loading…
Cancel
Save