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 = [
|
||||
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 sentry_sdk import last_event_id
|
||||
|
||||
from characters.models import Character
|
||||
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 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)
|
||||
def debug_css(request: HttpRequest) -> HttpResponse:
|
||||
css, source_map = get_css(debug=True)
|
||||
|
|
|
@ -1,6 +1,12 @@
|
|||
import {EditorView, minimalSetup} from "codemirror"
|
||||
import {markdownLanguage} from "@codemirror/lang-markdown"
|
||||
import {markdown, markdownLanguage} from "@codemirror/lang-markdown"
|
||||
import {foldGutter} from "@codemirror/language";
|
||||
import {
|
||||
autocompletion,
|
||||
Completion,
|
||||
CompletionContext,
|
||||
CompletionResult
|
||||
} from "@codemirror/autocomplete"
|
||||
|
||||
interface DraftSaveResponse {
|
||||
message: string
|
||||
|
@ -25,6 +31,53 @@ ids.forEach(function (id) {
|
|||
// color: "red",
|
||||
// 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 div = document.createElement("div")
|
||||
element.style.display = "none"
|
||||
|
@ -33,7 +86,11 @@ ids.forEach(function (id) {
|
|||
extensions: [
|
||||
minimalSetup,
|
||||
foldGutter(),
|
||||
markdownLanguage,
|
||||
markdown({base: markdownLanguage}),
|
||||
autocompletion({
|
||||
activateOnTyping: true,
|
||||
override: [myCompletions],
|
||||
}),
|
||||
EditorView.lineWrapping,
|
||||
EditorView.contentAttributes.of({spellcheck: "true"}),
|
||||
// yCollab(ytext, provider.awareness, {undoManager})
|
||||
|
@ -44,31 +101,31 @@ ids.forEach(function (id) {
|
|||
element.form!.addEventListener("submit", () => {
|
||||
element.value = view.state.doc.toString()
|
||||
})
|
||||
// const easyMDE = new EasyMDE({
|
||||
// element: element,
|
||||
// forceSync: true, // for "required" to work
|
||||
// spellChecker: false,
|
||||
// nativeSpellcheck: true,
|
||||
// autoDownloadFontAwesome: false,
|
||||
// autosave: {
|
||||
// delay: 1000,
|
||||
// submit_delay: 5000,
|
||||
// timeFormat: {
|
||||
// locale: 'de-AT',
|
||||
// format: {
|
||||
// year: 'numeric',
|
||||
// month: 'long',
|
||||
// day: '2-digit',
|
||||
// hour: '2-digit',
|
||||
// minute: '2-digit',
|
||||
// second: '2-digit',
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// inputStyle: "contenteditable",
|
||||
// status: ["lines", "words", "cursor", "saveStatus"],
|
||||
// });
|
||||
// window.editor = easyMDE
|
||||
// const easyMDE = new EasyMDE({
|
||||
// element: element,
|
||||
// forceSync: true, // for "required" to work
|
||||
// spellChecker: false,
|
||||
// nativeSpellcheck: true,
|
||||
// autoDownloadFontAwesome: false,
|
||||
// autosave: {
|
||||
// delay: 1000,
|
||||
// submit_delay: 5000,
|
||||
// timeFormat: {
|
||||
// locale: 'de-AT',
|
||||
// format: {
|
||||
// year: 'numeric',
|
||||
// month: 'long',
|
||||
// day: '2-digit',
|
||||
// hour: '2-digit',
|
||||
// minute: '2-digit',
|
||||
// second: '2-digit',
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// inputStyle: "contenteditable",
|
||||
// status: ["lines", "words", "cursor", "saveStatus"],
|
||||
// });
|
||||
// window.editor = easyMDE
|
||||
const originalLabel = labelEl.innerText
|
||||
setInterval(function () {
|
||||
const content = view.state.doc.toString();
|
||||
|
@ -88,4 +145,5 @@ ids.forEach(function (id) {
|
|||
})
|
||||
|
||||
}, 1000 * 30)
|
||||
});
|
||||
})
|
||||
;
|
||||
|
|
|
@ -3,9 +3,9 @@ import 'vite/modulepreload-polyfill'
|
|||
// import "./scss/main.scss"
|
||||
import "./js/sentry"
|
||||
// @ts-ignore
|
||||
import {default as Dropdown} from 'bootstrap/js/src/dropdown'
|
||||
import Dropdown from 'bootstrap/js/src/dropdown'
|
||||
// @ts-ignore
|
||||
import {default as Collapse} from 'bootstrap/js/src/collapse'
|
||||
import Collapse from 'bootstrap/js/src/collapse'
|
||||
|
||||
import "./js/autocomplete"
|
||||
import "./js/popover"
|
||||
|
|
Loading…
Reference in a new issue