chore(client/ts): port widgets/note_type_chooser

This commit is contained in:
Elian Doran 2024-12-21 23:06:40 +02:00
parent 7565fdfd5c
commit 88d5aa973c
No known key found for this signature in database
2 changed files with 49 additions and 22 deletions

View File

@ -2,17 +2,21 @@ import server from "./server.js";
import froca from "./froca.js"; import froca from "./froca.js";
import { t } from "./i18n.js"; import { t } from "./i18n.js";
type NoteTypeItem = { interface NoteTypeSeparator {
title: "----"
}
export interface NoteType {
title: string; title: string;
command: string; command?: string;
type: string; type: string;
uiIcon: string; uiIcon: string;
templateNoteId?: string; templateNoteId?: string;
} | { }
title: "----"
};
async function getNoteTypeItems(command: string) { type NoteTypeItem = NoteType | NoteTypeSeparator;
async function getNoteTypeItems(command?: string) {
const items: NoteTypeItem[] = [ const items: NoteTypeItem[] = [
{ title: t("note_types.text"), command: command, type: "text", uiIcon: "bx bx-note" }, { title: t("note_types.text"), command: command, type: "text", uiIcon: "bx bx-note" },
{ title: t("note_types.code"), command: command, type: "code", uiIcon: "bx bx-code" }, { title: t("note_types.code"), command: command, type: "code", uiIcon: "bx bx-code" },

View File

@ -1,5 +1,5 @@
import { t } from "../../services/i18n.js"; import { t } from "../../services/i18n.js";
import noteTypesService from "../../services/note_types.js"; import noteTypesService, { NoteType } from "../../services/note_types.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
const TPL = ` const TPL = `
@ -41,9 +41,25 @@ const TPL = `
</div> </div>
</div>`; </div>`;
interface CallbackData {
success: boolean;
noteType?: string;
templateNoteId?: string;
}
type Callback = (data: CallbackData) => void;
export default class NoteTypeChooserDialog extends BasicWidget { export default class NoteTypeChooserDialog extends BasicWidget {
constructor(props) {
super(props); private resolve: Callback | null;
private dropdown!: bootstrap.Dropdown;
private modal!: JQuery<HTMLElement>;
private $noteTypeDropdown!: JQuery<HTMLElement>;
private $originalFocused: JQuery<HTMLElement> | null;
private $originalDialog: JQuery<HTMLElement> | null;
constructor(props: {}) {
super();
this.resolve = null; this.resolve = null;
this.$originalFocused = null; // element focused before the dialog was opened, so we can return to it afterward this.$originalFocused = null; // element focused before the dialog was opened, so we can return to it afterward
@ -52,9 +68,13 @@ export default class NoteTypeChooserDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
// TODO: Remove once we import bootstrap the right way
//@ts-ignore
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget); this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown"); this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown");
// TODO: Remove once we import bootstrap the right way
//@ts-ignore
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find(".note-type-dropdown-trigger")); this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find(".note-type-dropdown-trigger"));
this.$widget.on("hidden.bs.modal", () => { this.$widget.on("hidden.bs.modal", () => {
@ -88,13 +108,15 @@ export default class NoteTypeChooserDialog extends BasicWidget {
this.$noteTypeDropdown.parent().on('hide.bs.dropdown', e => { this.$noteTypeDropdown.parent().on('hide.bs.dropdown', e => {
// prevent closing dropdown by clicking outside // prevent closing dropdown by clicking outside
// TODO: Check if this actually works.
//@ts-ignore
if (e.clickEvent) { if (e.clickEvent) {
e.preventDefault(); e.preventDefault();
} }
}); });
} }
async chooseNoteTypeEvent({ callback }) { async chooseNoteTypeEvent({ callback }: { callback: Callback }) {
this.$originalFocused = $(':focus'); this.$originalFocused = $(':focus');
const noteTypes = await noteTypesService.getNoteTypeItems(); const noteTypes = await noteTypesService.getNoteTypeItems();
@ -104,13 +126,12 @@ export default class NoteTypeChooserDialog extends BasicWidget {
for (const noteType of noteTypes) { for (const noteType of noteTypes) {
if (noteType.title === '----') { if (noteType.title === '----') {
this.$noteTypeDropdown.append($('<h6 class="dropdown-header">').append(t("note_type_chooser.templates"))); this.$noteTypeDropdown.append($('<h6 class="dropdown-header">').append(t("note_type_chooser.templates")));
} } else {
else {
this.$noteTypeDropdown.append( this.$noteTypeDropdown.append(
$('<a class="dropdown-item" tabindex="0">') $('<a class="dropdown-item" tabindex="0">')
.attr("data-note-type", noteType.type) .attr("data-note-type", (noteType as NoteType).type)
.attr("data-template-note-id", noteType.templateNoteId) .attr("data-template-note-id", (noteType as NoteType).templateNoteId || "")
.append($("<span>").addClass(noteType.uiIcon)) .append($("<span>").addClass((noteType as NoteType).uiIcon))
.append(` ${noteType.title}`) .append(` ${noteType.title}`)
); );
} }
@ -127,16 +148,18 @@ export default class NoteTypeChooserDialog extends BasicWidget {
this.resolve = callback; this.resolve = callback;
} }
doResolve(e) { doResolve(e: JQuery.KeyDownEvent | JQuery.ClickEvent) {
const $item = $(e.target).closest(".dropdown-item"); const $item = $(e.target).closest(".dropdown-item");
const noteType = $item.attr("data-note-type"); const noteType = $item.attr("data-note-type");
const templateNoteId = $item.attr("data-template-note-id"); const templateNoteId = $item.attr("data-template-note-id");
if (this.resolve) {
this.resolve({ this.resolve({
success: true, success: true,
noteType, noteType,
templateNoteId templateNoteId
}); });
}
this.resolve = null; this.resolve = null;
this.modal.hide(); this.modal.hide();