mirror of
https://github.com/zadam/trilium.git
synced 2025-06-06 18:08:33 +02:00
converted note type chooser dialog to new pattern
This commit is contained in:
parent
ebd715ca1b
commit
1347d3fcc2
@ -1,94 +0,0 @@
|
|||||||
import noteTypesService from "../services/note_types.js";
|
|
||||||
|
|
||||||
const $dialog = $("#note-type-chooser-dialog");
|
|
||||||
const $noteTypeDropdown = $("#note-type-dropdown");
|
|
||||||
const $noteTypeDropdownTrigger = $("#note-type-dropdown-trigger");
|
|
||||||
$noteTypeDropdownTrigger.dropdown();
|
|
||||||
|
|
||||||
let resolve;
|
|
||||||
let $originalFocused; // element focused before the dialog was opened, so we can return to it afterwards
|
|
||||||
let $originalDialog;
|
|
||||||
|
|
||||||
export async function chooseNoteType() {
|
|
||||||
$originalFocused = $(':focus');
|
|
||||||
|
|
||||||
const noteTypes = await noteTypesService.getNoteTypeItems();
|
|
||||||
|
|
||||||
$noteTypeDropdown.empty();
|
|
||||||
|
|
||||||
for (const noteType of noteTypes) {
|
|
||||||
if (noteType.title === '----') {
|
|
||||||
$noteTypeDropdown.append($('<h6 class="dropdown-header">').append("Templates:"));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
$noteTypeDropdown.append(
|
|
||||||
$('<a class="dropdown-item" tabindex="0">')
|
|
||||||
.attr("data-note-type", noteType.type)
|
|
||||||
.attr("data-template-note-id", noteType.templateNoteId)
|
|
||||||
.append($("<span>").addClass(noteType.uiIcon))
|
|
||||||
.append(" " + noteType.title)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$noteTypeDropdownTrigger.dropdown('show');
|
|
||||||
|
|
||||||
$originalDialog = glob.activeDialog;
|
|
||||||
glob.activeDialog = $dialog;
|
|
||||||
$dialog.modal();
|
|
||||||
|
|
||||||
$noteTypeDropdown.find(".dropdown-item:first").focus();
|
|
||||||
|
|
||||||
return new Promise((res, rej) => { resolve = res; });
|
|
||||||
}
|
|
||||||
|
|
||||||
$dialog.on("hidden.bs.modal", () => {
|
|
||||||
if (resolve) {
|
|
||||||
resolve({success: false});
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($originalFocused) {
|
|
||||||
$originalFocused.trigger('focus');
|
|
||||||
$originalFocused = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
glob.activeDialog = $originalDialog;
|
|
||||||
});
|
|
||||||
|
|
||||||
function doResolve(e) {
|
|
||||||
const $item = $(e.target).closest(".dropdown-item");
|
|
||||||
const noteType = $item.attr("data-note-type");
|
|
||||||
const templateNoteId = $item.attr("data-template-note-id");
|
|
||||||
|
|
||||||
resolve({
|
|
||||||
success: true,
|
|
||||||
noteType,
|
|
||||||
templateNoteId
|
|
||||||
});
|
|
||||||
resolve = null;
|
|
||||||
|
|
||||||
$dialog.modal("hide");
|
|
||||||
}
|
|
||||||
|
|
||||||
$noteTypeDropdown.on('click', '.dropdown-item', e => doResolve(e));
|
|
||||||
|
|
||||||
$noteTypeDropdown.on('focus', '.dropdown-item', e => {
|
|
||||||
$noteTypeDropdown.find('.dropdown-item').each((i, el) => {
|
|
||||||
$(el).toggleClass('active', el === e.target);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$noteTypeDropdown.on('keydown', '.dropdown-item', e => {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
doResolve(e);
|
|
||||||
e.preventDefault();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
$noteTypeDropdown.parent().on('hide.bs.dropdown', e => {
|
|
||||||
// prevent closing dropdown by clicking outside
|
|
||||||
if (e.clickEvent) {
|
|
||||||
e.preventDefault();
|
|
||||||
}
|
|
||||||
});
|
|
@ -60,6 +60,7 @@ import BranchPrefixDialog from "../widgets/dialogs/branch_prefix.js";
|
|||||||
import SortChildNotesDialog from "../widgets/dialogs/sort_child_notes.js";
|
import SortChildNotesDialog from "../widgets/dialogs/sort_child_notes.js";
|
||||||
import PasswordNoteSetDialog from "../widgets/dialogs/password_not_set.js";
|
import PasswordNoteSetDialog from "../widgets/dialogs/password_not_set.js";
|
||||||
import IncludeNoteDialog from "../widgets/dialogs/include_note.js";
|
import IncludeNoteDialog from "../widgets/dialogs/include_note.js";
|
||||||
|
import NoteTypeChooserDialog from "../widgets/dialogs/note_type_chooser.js";
|
||||||
|
|
||||||
export default class DesktopLayout {
|
export default class DesktopLayout {
|
||||||
constructor(customWidgets) {
|
constructor(customWidgets) {
|
||||||
@ -194,6 +195,7 @@ export default class DesktopLayout {
|
|||||||
.child(new BranchPrefixDialog())
|
.child(new BranchPrefixDialog())
|
||||||
.child(new SortChildNotesDialog())
|
.child(new SortChildNotesDialog())
|
||||||
.child(new PasswordNoteSetDialog())
|
.child(new PasswordNoteSetDialog())
|
||||||
.child(new IncludeNoteDialog());
|
.child(new IncludeNoteDialog())
|
||||||
|
.child(new NoteTypeChooserDialog());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -172,8 +172,7 @@ function initNoteAutocomplete($el, options) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (suggestion.action === 'create-note') {
|
if (suggestion.action === 'create-note') {
|
||||||
const noteTypeChooserDialog = await import('../dialogs/note_type_chooser.js');
|
const {success, noteType, templateNoteId} = await noteCreateService.chooseNoteType();
|
||||||
const {success, noteType, templateNoteId} = await noteTypeChooserDialog.chooseNoteType();
|
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return;
|
return;
|
||||||
|
@ -75,9 +75,14 @@ async function createNote(parentNotePath, options = {}) {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function chooseNoteType() {
|
||||||
|
return new Promise(res => {
|
||||||
|
appContext.triggerCommand("chooseNoteType", {callback: res});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
async function createNoteWithTypePrompt(parentNotePath, options = {}) {
|
async function createNoteWithTypePrompt(parentNotePath, options = {}) {
|
||||||
const noteTypeChooserDialog = await import('../dialogs/note_type_chooser.js');
|
const {success, noteType, templateNoteId} = await chooseNoteType();
|
||||||
const {success, noteType, templateNoteId} = await noteTypeChooserDialog.chooseNoteType();
|
|
||||||
|
|
||||||
if (!success) {
|
if (!success) {
|
||||||
return;
|
return;
|
||||||
@ -121,5 +126,6 @@ async function duplicateSubtree(noteId, parentNotePath) {
|
|||||||
export default {
|
export default {
|
||||||
createNote,
|
createNote,
|
||||||
createNoteWithTypePrompt,
|
createNoteWithTypePrompt,
|
||||||
duplicateSubtree
|
duplicateSubtree,
|
||||||
|
chooseNoteType
|
||||||
};
|
};
|
||||||
|
138
src/public/app/widgets/dialogs/note_type_chooser.js
Normal file
138
src/public/app/widgets/dialogs/note_type_chooser.js
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
import noteTypesService from "../../services/note_types.js";
|
||||||
|
import BasicWidget from "../basic_widget.js";
|
||||||
|
|
||||||
|
const TPL = `
|
||||||
|
<div class="note-type-chooser-dialog modal mx-auto" tabindex="-1" role="dialog">
|
||||||
|
<style>
|
||||||
|
.note-type-dropdown {
|
||||||
|
position: relative;
|
||||||
|
font-size: large;
|
||||||
|
padding: 20px;
|
||||||
|
width: 100%;
|
||||||
|
margin-top: 15px;
|
||||||
|
max-height: 80vh;
|
||||||
|
overflow: auto;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<div class="modal-dialog" style="max-width: 500px;" role="document">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title mr-auto">Choose note type</h5>
|
||||||
|
|
||||||
|
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;">
|
||||||
|
<span aria-hidden="true">×</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
Choose note type / template of the new note:
|
||||||
|
|
||||||
|
<div class="dropdown">
|
||||||
|
<button class="note-type-dropdown-trigger" type="button" style="display: none;" data-toggle="dropdown">Dropdown trigger</button>
|
||||||
|
|
||||||
|
<div class="note-type-dropdown dropdown-menu"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>`;
|
||||||
|
|
||||||
|
export default class NoteTypeChooserDialog extends BasicWidget {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
|
||||||
|
this.resolve = null;
|
||||||
|
this.$originalFocused = null; // element focused before the dialog was opened, so we can return to it afterwards
|
||||||
|
this.$originalDialog = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
doRender() {
|
||||||
|
this.$widget = $(TPL);
|
||||||
|
this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown");
|
||||||
|
this.$noteTypeDropdownTrigger = this.$widget.find(".note-type-dropdown-trigger");
|
||||||
|
this.$noteTypeDropdownTrigger.dropdown();
|
||||||
|
|
||||||
|
this.$widget.on("hidden.bs.modal", () => {
|
||||||
|
if (this.resolve) {
|
||||||
|
this.resolve({success: false});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.$originalFocused) {
|
||||||
|
this.$originalFocused.trigger('focus');
|
||||||
|
this.$originalFocused = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
glob.activeDialog = this.$originalDialog;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$noteTypeDropdown.on('click', '.dropdown-item', e => this.doResolve(e));
|
||||||
|
|
||||||
|
this.$noteTypeDropdown.on('focus', '.dropdown-item', e => {
|
||||||
|
this.$noteTypeDropdown.find('.dropdown-item').each((i, el) => {
|
||||||
|
$(el).toggleClass('active', el === e.target);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$noteTypeDropdown.on('keydown', '.dropdown-item', e => {
|
||||||
|
if (e.key === 'Enter') {
|
||||||
|
this.doResolve(e);
|
||||||
|
e.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
this.$noteTypeDropdown.parent().on('hide.bs.dropdown', e => {
|
||||||
|
// prevent closing dropdown by clicking outside
|
||||||
|
if (e.clickEvent) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async chooseNoteTypeEvent({callback}) {
|
||||||
|
this.$originalFocused = $(':focus');
|
||||||
|
|
||||||
|
const noteTypes = await noteTypesService.getNoteTypeItems();
|
||||||
|
|
||||||
|
this.$noteTypeDropdown.empty();
|
||||||
|
|
||||||
|
for (const noteType of noteTypes) {
|
||||||
|
if (noteType.title === '----') {
|
||||||
|
this.$noteTypeDropdown.append($('<h6 class="dropdown-header">').append("Templates:"));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.$noteTypeDropdown.append(
|
||||||
|
$('<a class="dropdown-item" tabindex="0">')
|
||||||
|
.attr("data-note-type", noteType.type)
|
||||||
|
.attr("data-template-note-id", noteType.templateNoteId)
|
||||||
|
.append($("<span>").addClass(noteType.uiIcon))
|
||||||
|
.append(" " + noteType.title)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.$noteTypeDropdownTrigger.dropdown('show');
|
||||||
|
|
||||||
|
this.$originalDialog = glob.activeDialog;
|
||||||
|
glob.activeDialog = this.$widget;
|
||||||
|
this.$widget.modal();
|
||||||
|
|
||||||
|
this.$noteTypeDropdown.find(".dropdown-item:first").focus();
|
||||||
|
|
||||||
|
this.resolve = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
doResolve(e) {
|
||||||
|
const $item = $(e.target).closest(".dropdown-item");
|
||||||
|
const noteType = $item.attr("data-note-type");
|
||||||
|
const templateNoteId = $item.attr("data-template-note-id");
|
||||||
|
|
||||||
|
this.resolve({
|
||||||
|
success: true,
|
||||||
|
noteType,
|
||||||
|
templateNoteId
|
||||||
|
});
|
||||||
|
this.resolve = null;
|
||||||
|
|
||||||
|
this.$widget.modal("hide");
|
||||||
|
}
|
||||||
|
}
|
@ -31,7 +31,6 @@
|
|||||||
<%- include('dialogs/clone_to.ejs') %>
|
<%- include('dialogs/clone_to.ejs') %>
|
||||||
<%- include('dialogs/move_to.ejs') %>
|
<%- include('dialogs/move_to.ejs') %>
|
||||||
<%- include('dialogs/delete_notes.ejs') %>
|
<%- include('dialogs/delete_notes.ejs') %>
|
||||||
<%- include('dialogs/note_type_chooser.ejs') %>
|
|
||||||
|
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
global = globalThis; /* fixes https://github.com/webpack/webpack/issues/10035 */
|
global = globalThis; /* fixes https://github.com/webpack/webpack/issues/10035 */
|
||||||
|
@ -1,34 +0,0 @@
|
|||||||
<style>
|
|
||||||
#note-type-dropdown {
|
|
||||||
position: relative;
|
|
||||||
font-size: large;
|
|
||||||
padding: 20px;
|
|
||||||
width: 100%;
|
|
||||||
margin-top: 15px;
|
|
||||||
max-height: 80vh;
|
|
||||||
overflow: auto;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<div id="note-type-chooser-dialog" class="modal mx-auto" tabindex="-1" role="dialog">
|
|
||||||
<div class="modal-dialog" style="max-width: 500px;" role="document">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title mr-auto">Choose note type</h5>
|
|
||||||
|
|
||||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;">
|
|
||||||
<span aria-hidden="true">×</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
Choose note type / template of the new note:
|
|
||||||
|
|
||||||
<div class="dropdown">
|
|
||||||
<button id="note-type-dropdown-trigger" type="button" style="display: none;" data-toggle="dropdown">Dropdown trigger</button>
|
|
||||||
|
|
||||||
<div id="note-type-dropdown" class="dropdown-menu"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
Loading…
x
Reference in New Issue
Block a user