mirror of
https://github.com/Findus23/RPGnotes.git
synced 2024-09-19 15:43:45 +02:00
autocomplete names in the editor
This commit is contained in:
parent
3609095a4e
commit
46388002f5
4 changed files with 130 additions and 30 deletions
|
@ -4,4 +4,5 @@ from common import views
|
||||||
|
|
||||||
urlpatterns = [
|
urlpatterns = [
|
||||||
path("api/draft/save", views.save_draft, name="save_draft"),
|
path("api/draft/save", views.save_draft, name="save_draft"),
|
||||||
|
path("api/suggestions",views.name_completions,name="name_completions"),
|
||||||
]
|
]
|
||||||
|
|
|
@ -7,7 +7,12 @@ from django.views.generic import TemplateView
|
||||||
from ipware import get_client_ip
|
from ipware import get_client_ip
|
||||||
from sentry_sdk import last_event_id
|
from sentry_sdk import last_event_id
|
||||||
|
|
||||||
|
from characters.models import Character
|
||||||
from common.models import Draft
|
from common.models import Draft
|
||||||
|
from factions.models import Faction
|
||||||
|
from locations.models import Location
|
||||||
|
from loot.models import Loot
|
||||||
|
from notes.models import Note
|
||||||
from rpg_notes.secrets import SENTRY_DSN
|
from rpg_notes.secrets import SENTRY_DSN
|
||||||
from utils.assets import get_css, get_file_hash
|
from utils.assets import get_css, get_file_hash
|
||||||
|
|
||||||
|
@ -51,6 +56,42 @@ def save_draft(request: HttpRequest) -> HttpResponse:
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def name_completions(request: HttpRequest) -> HttpResponse:
|
||||||
|
response_data = []
|
||||||
|
|
||||||
|
for obj in (list(Location.objects.all()) +
|
||||||
|
list(Note.objects.all()) +
|
||||||
|
list(Faction.objects.all()) +
|
||||||
|
list(Loot.objects.all())):
|
||||||
|
response_data.append({
|
||||||
|
"name": obj.name
|
||||||
|
})
|
||||||
|
if obj.aliases:
|
||||||
|
for alias in obj.aliases:
|
||||||
|
response_data.append({
|
||||||
|
"name": alias,
|
||||||
|
"details":obj.name
|
||||||
|
})
|
||||||
|
for char in Character.objects.all():
|
||||||
|
response_data.append({
|
||||||
|
"name": char.name,
|
||||||
|
"details": char.subtitle
|
||||||
|
})
|
||||||
|
if char.aliases:
|
||||||
|
for alias in char.aliases:
|
||||||
|
response_data.append({
|
||||||
|
"name": alias,
|
||||||
|
"details":char.name
|
||||||
|
})
|
||||||
|
|
||||||
|
|
||||||
|
response = JsonResponse({
|
||||||
|
"suggestions": response_data
|
||||||
|
})
|
||||||
|
response['Cache-Control'] = f'max-age={24 * 60 * 60}'
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
@condition(etag_func=calc_etag)
|
@condition(etag_func=calc_etag)
|
||||||
def debug_css(request: HttpRequest) -> HttpResponse:
|
def debug_css(request: HttpRequest) -> HttpResponse:
|
||||||
css, source_map = get_css(debug=True)
|
css, source_map = get_css(debug=True)
|
||||||
|
|
|
@ -1,6 +1,12 @@
|
||||||
import {EditorView, minimalSetup} from "codemirror"
|
import {EditorView, minimalSetup} from "codemirror"
|
||||||
import {markdownLanguage} from "@codemirror/lang-markdown"
|
import {markdown, markdownLanguage} from "@codemirror/lang-markdown"
|
||||||
import {foldGutter} from "@codemirror/language";
|
import {foldGutter} from "@codemirror/language";
|
||||||
|
import {
|
||||||
|
autocompletion,
|
||||||
|
Completion,
|
||||||
|
CompletionContext,
|
||||||
|
CompletionResult
|
||||||
|
} from "@codemirror/autocomplete"
|
||||||
|
|
||||||
interface DraftSaveResponse {
|
interface DraftSaveResponse {
|
||||||
message: string
|
message: string
|
||||||
|
@ -25,6 +31,53 @@ ids.forEach(function (id) {
|
||||||
// color: "red",
|
// color: "red",
|
||||||
// colorLight: "lightred"
|
// colorLight: "lightred"
|
||||||
// })
|
// })
|
||||||
|
|
||||||
|
interface Element {
|
||||||
|
name: string,
|
||||||
|
details?: string
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HTTPResponse {
|
||||||
|
suggestions: Element[]
|
||||||
|
}
|
||||||
|
|
||||||
|
let names: Element[] = []
|
||||||
|
fetch("/api/suggestions", {})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then((data: HTTPResponse) => {
|
||||||
|
names = data.suggestions
|
||||||
|
})
|
||||||
|
|
||||||
|
function myCompletions(context: CompletionContext): CompletionResult | null {
|
||||||
|
if (names.length == 0) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
let word
|
||||||
|
if (!context.explicit) {
|
||||||
|
word = context.matchBefore(/@\w*/)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
word = context.matchBefore(/\w*/)
|
||||||
|
}
|
||||||
|
if (!word) {
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
if (word.from == word.to)
|
||||||
|
return null
|
||||||
|
|
||||||
|
const options = names.map((s: Element): Completion => ({
|
||||||
|
label: "@" + s.name,
|
||||||
|
apply: s.name,
|
||||||
|
displayLabel: s.name,
|
||||||
|
detail: s.details
|
||||||
|
}))
|
||||||
|
return {
|
||||||
|
from: word.from,
|
||||||
|
options: options
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
const labelEl = element.labels[0]
|
const labelEl = element.labels[0]
|
||||||
const div = document.createElement("div")
|
const div = document.createElement("div")
|
||||||
element.style.display = "none"
|
element.style.display = "none"
|
||||||
|
@ -33,7 +86,11 @@ ids.forEach(function (id) {
|
||||||
extensions: [
|
extensions: [
|
||||||
minimalSetup,
|
minimalSetup,
|
||||||
foldGutter(),
|
foldGutter(),
|
||||||
markdownLanguage,
|
markdown({base: markdownLanguage}),
|
||||||
|
autocompletion({
|
||||||
|
activateOnTyping: true,
|
||||||
|
override: [myCompletions],
|
||||||
|
}),
|
||||||
EditorView.lineWrapping,
|
EditorView.lineWrapping,
|
||||||
EditorView.contentAttributes.of({spellcheck: "true"}),
|
EditorView.contentAttributes.of({spellcheck: "true"}),
|
||||||
// yCollab(ytext, provider.awareness, {undoManager})
|
// yCollab(ytext, provider.awareness, {undoManager})
|
||||||
|
@ -44,31 +101,31 @@ ids.forEach(function (id) {
|
||||||
element.form!.addEventListener("submit", () => {
|
element.form!.addEventListener("submit", () => {
|
||||||
element.value = view.state.doc.toString()
|
element.value = view.state.doc.toString()
|
||||||
})
|
})
|
||||||
// const easyMDE = new EasyMDE({
|
// const easyMDE = new EasyMDE({
|
||||||
// element: element,
|
// element: element,
|
||||||
// forceSync: true, // for "required" to work
|
// forceSync: true, // for "required" to work
|
||||||
// spellChecker: false,
|
// spellChecker: false,
|
||||||
// nativeSpellcheck: true,
|
// nativeSpellcheck: true,
|
||||||
// autoDownloadFontAwesome: false,
|
// autoDownloadFontAwesome: false,
|
||||||
// autosave: {
|
// autosave: {
|
||||||
// delay: 1000,
|
// delay: 1000,
|
||||||
// submit_delay: 5000,
|
// submit_delay: 5000,
|
||||||
// timeFormat: {
|
// timeFormat: {
|
||||||
// locale: 'de-AT',
|
// locale: 'de-AT',
|
||||||
// format: {
|
// format: {
|
||||||
// year: 'numeric',
|
// year: 'numeric',
|
||||||
// month: 'long',
|
// month: 'long',
|
||||||
// day: '2-digit',
|
// day: '2-digit',
|
||||||
// hour: '2-digit',
|
// hour: '2-digit',
|
||||||
// minute: '2-digit',
|
// minute: '2-digit',
|
||||||
// second: '2-digit',
|
// second: '2-digit',
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// },
|
// },
|
||||||
// inputStyle: "contenteditable",
|
// inputStyle: "contenteditable",
|
||||||
// status: ["lines", "words", "cursor", "saveStatus"],
|
// status: ["lines", "words", "cursor", "saveStatus"],
|
||||||
// });
|
// });
|
||||||
// window.editor = easyMDE
|
// window.editor = easyMDE
|
||||||
const originalLabel = labelEl.innerText
|
const originalLabel = labelEl.innerText
|
||||||
setInterval(function () {
|
setInterval(function () {
|
||||||
const content = view.state.doc.toString();
|
const content = view.state.doc.toString();
|
||||||
|
@ -88,4 +145,5 @@ ids.forEach(function (id) {
|
||||||
})
|
})
|
||||||
|
|
||||||
}, 1000 * 30)
|
}, 1000 * 30)
|
||||||
});
|
})
|
||||||
|
;
|
||||||
|
|
|
@ -3,9 +3,9 @@ import 'vite/modulepreload-polyfill'
|
||||||
// import "./scss/main.scss"
|
// import "./scss/main.scss"
|
||||||
import "./js/sentry"
|
import "./js/sentry"
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import {default as Dropdown} from 'bootstrap/js/src/dropdown'
|
import Dropdown from 'bootstrap/js/src/dropdown'
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import {default as Collapse} from 'bootstrap/js/src/collapse'
|
import Collapse from 'bootstrap/js/src/collapse'
|
||||||
|
|
||||||
import "./js/autocomplete"
|
import "./js/autocomplete"
|
||||||
import "./js/popover"
|
import "./js/popover"
|
||||||
|
|
Loading…
Reference in a new issue