Merge pull request #381 from TriliumNext/bootstrap

Upgrade bootstrap from v4 to v5
This commit is contained in:
Elian Doran 2024-09-12 20:09:19 +03:00 committed by GitHub
commit 8bfa4461b0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
78 changed files with 4760 additions and 3930 deletions

7598
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -58,7 +58,7 @@
"autocomplete.js": "^0.38.1", "autocomplete.js": "^0.38.1",
"axios": "^1.7.7", "axios": "^1.7.7",
"better-sqlite3": "^11.1.2", "better-sqlite3": "^11.1.2",
"bootstrap": "^4.6.2", "bootstrap": "^5.3.3",
"boxicons": "2.1.4", "boxicons": "2.1.4",
"chokidar": "3.6.0", "chokidar": "3.6.0",
"cls-hooked": "4.2.2", "cls-hooked": "4.2.2",

View File

@ -105,28 +105,23 @@ function initNoteAutocomplete($el, options) {
$el.addClass("note-autocomplete-input"); $el.addClass("note-autocomplete-input");
const $clearTextButton = $("<a>") const $clearTextButton = $("<button>")
.addClass("input-group-text input-clearer-button bx bxs-tag-x") .addClass("input-group-text input-clearer-button bx bxs-tag-x")
.prop("title", "Clear text field"); .prop("title", "Clear text field");
const $showRecentNotesButton = $("<a>") const $showRecentNotesButton = $("<button>")
.addClass("input-group-text show-recent-notes-button bx bx-time") .addClass("input-group-text show-recent-notes-button bx bx-time")
.prop("title", "Show recent notes"); .prop("title", "Show recent notes");
const $goToSelectedNoteButton = $("<a>") const $goToSelectedNoteButton = $("<button>")
.addClass("input-group-text go-to-selected-note-button bx bx-arrow-to-right"); .addClass("input-group-text go-to-selected-note-button bx bx-arrow-to-right");
const $sideButtons = $("<div>") $el.after($clearTextButton).after($showRecentNotesButton);
.addClass("input-group-append")
.append($clearTextButton)
.append($showRecentNotesButton);
if (!options.hideGoToSelectedNoteButton) { if (!options.hideGoToSelectedNoteButton) {
$sideButtons.append($goToSelectedNoteButton); $el.after($goToSelectedNoteButton);
} }
$el.after($sideButtons);
$clearTextButton.on('click', () => clearText($el)); $clearTextButton.on('click', () => clearText($el));
$showRecentNotesButton.on('click', e => { $showRecentNotesButton.on('click', e => {
@ -180,13 +175,13 @@ function initNoteAutocomplete($el, options) {
} }
if (suggestion.action === 'create-note') { if (suggestion.action === 'create-note') {
const {success, noteType, templateNoteId} = await noteCreateService.chooseNoteType(); const { success, noteType, templateNoteId } = await noteCreateService.chooseNoteType();
if (!success) { if (!success) {
return; return;
} }
const {note} = await noteCreateService.createNote(suggestion.parentNoteId, { const { note } = await noteCreateService.createNote(suggestion.parentNoteId, {
title: suggestion.noteTitle, title: suggestion.noteTitle,
activate: false, activate: false,
type: noteType, type: noteType,

View File

@ -2,15 +2,18 @@ import ws from "./ws.js";
import utils from "./utils.js"; import utils from "./utils.js";
function toast(options) { function toast(options) {
const $toast = $(`<div class="toast" role="alert" aria-live="assertive" aria-atomic="true"> const $toast = $(
`<div class="toast" role="alert" aria-live="assertive" aria-atomic="true">
<div class="toast-header"> <div class="toast-header">
<strong class="mr-auto"><span class="bx bx-${options.icon}"></span> <span class="toast-title"></span></strong> <strong class="me-auto">
<button type="button" class="ml-2 mb-1 close" data-dismiss="toast" aria-label="Close"> <span class="bx bx-${options.icon}"></span>
<span aria-hidden="true">&times;</span> <span class="toast-title"></span>
</button> </strong>
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
</div> </div>
<div class="toast-body"></div> <div class="toast-body"></div>
</div>`); </div>`
);
$toast.find('.toast-title').text(options.title); $toast.find('.toast-title').text(options.title);
$toast.find('.toast-body').text(options.message); $toast.find('.toast-body').text(options.message);

View File

@ -201,7 +201,7 @@ function getMimeTypeClass(mime) {
function closeActiveDialog() { function closeActiveDialog() {
if (glob.activeDialog) { if (glob.activeDialog) {
glob.activeDialog.modal('hide'); bootstrap.Modal.getOrCreateInstance(glob.activeDialog).hide();
glob.activeDialog = null; glob.activeDialog = null;
} }
} }
@ -245,8 +245,7 @@ async function openDialog($dialog, closeActDialog = true) {
} }
saveFocusedElement(); saveFocusedElement();
bootstrap.Modal.getOrCreateInstance($dialog).show();
$dialog.modal();
$dialog.on('hidden.bs.modal', () => { $dialog.on('hidden.bs.modal', () => {
$(".aa-input").autocomplete("close"); $(".aa-input").autocomplete("close");

View File

@ -97,7 +97,7 @@ const TPL = `
<tr class="attr-row-promoted" <tr class="attr-row-promoted"
title="${t('attribute_detail.promoted_title')}"> title="${t('attribute_detail.promoted_title')}">
<th>${t('attribute_detail.promoted')}</th> <th>${t('attribute_detail.promoted')}</th>
<td><input type="checkbox" class="attr-input-promoted form-control form-control-sm" /></td> <td><input type="checkbox" class="attr-input-promoted form-check" /></td>
</tr> </tr>
<tr class="attr-row-promoted-alias"> <tr class="attr-row-promoted-alias">
<th title="${t('attribute_detail.promoted_alias_title')}">${t('attribute_detail.promoted_alias')}</th> <th title="${t('attribute_detail.promoted_alias_title')}">${t('attribute_detail.promoted_alias')}</th>
@ -134,10 +134,8 @@ const TPL = `
<td> <td>
<div class="input-group"> <div class="input-group">
<input type="number" class="form-control attr-input-number-precision" style="text-align: right"> <input type="number" class="form-control attr-input-number-precision" style="text-align: right">
<div class="input-group-append">
<span class="input-group-text">${t('attribute_detail.digits')}</span> <span class="input-group-text">${t('attribute_detail.digits')}</span>
</div> </div>
</div>
</td> </td>
</tr> </tr>
<tr class="attr-row-inverse-relation"> <tr class="attr-row-inverse-relation">
@ -150,7 +148,7 @@ const TPL = `
</tr> </tr>
<tr title="${t('attribute_detail.inheritable_title')}"> <tr title="${t('attribute_detail.inheritable_title')}">
<th>${t('attribute_detail.inheritable')}</th> <th>${t('attribute_detail.inheritable')}</th>
<td><input type="checkbox" class="attr-input-inheritable form-control form-control-sm" /></td> <td><input type="checkbox" class="attr-input-inheritable form-check" /></td>
</tr> </tr>
</table> </table>
@ -349,7 +347,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
this.$rowTargetNote = this.$widget.find('.attr-row-target-note'); this.$rowTargetNote = this.$widget.find('.attr-row-target-note');
this.$inputTargetNote = this.$widget.find('.attr-input-target-note'); this.$inputTargetNote = this.$widget.find('.attr-input-target-note');
noteAutocompleteService.initNoteAutocomplete(this.$inputTargetNote, {allowCreatingNotes: true}) noteAutocompleteService.initNoteAutocomplete(this.$inputTargetNote, { allowCreatingNotes: true })
.on('autocomplete:noteselected', (event, suggestion, dataset) => { .on('autocomplete:noteselected', (event, suggestion, dataset) => {
if (!suggestion.notePath) { if (!suggestion.notePath) {
return false; return false;
@ -403,7 +401,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
}); });
} }
async showAttributeDetail({allAttributes, attribute, isOwned, x, y, focus}) { async showAttributeDetail({ allAttributes, attribute, isOwned, x, y, focus }) {
if (!attribute) { if (!attribute) {
this.hide(); this.hide();
@ -545,7 +543,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
} }
} }
return {left, right}; return { left, right };
} }
async saveAndClose() { async saveAndClose() {
@ -589,19 +587,19 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
} }
async updateRelatedNotes() { async updateRelatedNotes() {
let {results, count} = await server.post('search-related', this.attribute); let { results, count } = await server.post('search-related', this.attribute);
for (const res of results) { for (const res of results) {
res.noteId = res.notePathArray[res.notePathArray.length - 1]; res.noteId = res.notePathArray[res.notePathArray.length - 1];
} }
results = results.filter(({noteId}) => noteId !== this.noteId); results = results.filter(({ noteId }) => noteId !== this.noteId);
if (results.length === 0) { if (results.length === 0) {
this.$relatedNotesContainer.hide(); this.$relatedNotesContainer.hide();
} else { } else {
this.$relatedNotesContainer.show(); this.$relatedNotesContainer.show();
this.$relatedNotesTitle.text(t("attribute_detail.other_notes_with_name", {attributeType: this.attribute.type, attributeName: this.attribute.name})); this.$relatedNotesTitle.text(t("attribute_detail.other_notes_with_name", { attributeType: this.attribute.type, attributeName: this.attribute.name }));
this.$relatedNotesList.empty(); this.$relatedNotesList.empty();
@ -611,7 +609,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
for (const note of displayedNotes) { for (const note of displayedNotes) {
const notePath = note.getBestNotePathString(hoistedNoteId); const notePath = note.getBestNotePathString(hoistedNoteId);
const $noteLink = await linkService.createLink(notePath, {showNotePath: true}); const $noteLink = await linkService.createLink(notePath, { showNotePath: true });
this.$relatedNotesList.append( this.$relatedNotesList.append(
$("<li>").append($noteLink) $("<li>").append($noteLink)
@ -619,7 +617,7 @@ export default class AttributeDetailWidget extends NoteContextAwareWidget {
} }
if (results.length > DISPLAYED_NOTES) { if (results.length > DISPLAYED_NOTES) {
this.$relatedNotesMoreNotes.show().text(t("attribute_detail.and_more", {count: count - DISPLAYED_NOTES})); this.$relatedNotesMoreNotes.show().text(t("attribute_detail.and_more", { count: count - DISPLAYED_NOTES }));
} else { } else {
this.$relatedNotesMoreNotes.hide(); this.$relatedNotesMoreNotes.hide();
} }

View File

@ -15,7 +15,7 @@ const TPL = `
<td class="button-column"> <td class="button-column">
<div style="display: flex"> <div style="display: flex">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
${t('execute_script.help_text')} ${t('execute_script.help_text')}

View File

@ -21,7 +21,7 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
<p>${t("add_label.help_text")}</p> <p>${t("add_label.help_text")}</p>
@ -30,7 +30,7 @@ const TPL = `
<li>${t("add_label.help_text_item2")}</li> <li>${t("add_label.help_text_item2")}</li>
</ul> </ul>
<p>${t("add_label.help_text_note")}</p> ${t("add_label.help_text_note")}
</div> </div>
</div> </div>

View File

@ -21,11 +21,11 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
<p>${t("update_label_value.help_text")}</p> <p>${t("update_label_value.help_text")}</p>
<p>${t("update_label_value.help_text_note")}</p> ${t("update_label_value.help_text_note")}
</div> </div>
</div> </div>

View File

@ -10,13 +10,13 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
<p>${t("delete_note.delete_matched_notes_description")}</p> <p>${t("delete_note.delete_matched_notes_description")}</p>
<p>${t("delete_note.undelete_notes_instruction")}</p> <p>${t("delete_note.undelete_notes_instruction")}</p>
<p>${t("delete_note.erase_notes_instruction")}</p> ${t("delete_note.erase_notes_instruction")}
</div> </div>
</div> </div>

View File

@ -9,7 +9,7 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
${t('delete_revisions.all_past_note_revisions')} ${t('delete_revisions.all_past_note_revisions')}
</div> </div>

View File

@ -18,11 +18,11 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
<p>${t('move_note.on_all_matched_notes')}:</p> <p>${t('move_note.on_all_matched_notes')}:</p>
<ul> <ul style="margin-bottom: 0;">
<li>${t('move_note.move_note_new_parent')}</li> <li>${t('move_note.move_note_new_parent')}</li>
<li>${t('move_note.clone_note_new_parent')}</li> <li>${t('move_note.clone_note_new_parent')}</li>
<li>${t('move_note.nothing_will_happen')}</li> <li>${t('move_note.nothing_will_happen')}</li>

View File

@ -16,7 +16,7 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
<p>${t('rename_note.evaluated_as_js_string')}</p> <p>${t('rename_note.evaluated_as_js_string')}</p>

View File

@ -25,9 +25,9 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
<p>${t('add_relation.create_relation_on_all_matched_notes')}</p> ${t('add_relation.create_relation_on_all_matched_notes')}
</div> </div>
</div> </div>

View File

@ -25,11 +25,11 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
<p>${t('update_relation_target.on_all_matched_notes')}:</p> <p>${t('update_relation_target.on_all_matched_notes')}:</p>
<ul> <ul style="margin-bottom: 0;">
<li>${t('update_relation_target.create_given_relation')}</li> <li>${t('update_relation_target.create_given_relation')}</li>
<li>${t('update_relation_target.change_target_note')}</li> <li>${t('update_relation_target.change_target_note')}</li>
</ul> </ul>

View File

@ -1,7 +1,7 @@
import NoteContextAwareWidget from "../note_context_aware_widget.js"; import NoteContextAwareWidget from "../note_context_aware_widget.js";
const TPL = `<button class="button-widget bx" const TPL = `<button class="button-widget bx"
data-toggle="tooltip" data-bs-toggle="tooltip"
title=""></button>`; title=""></button>`;
export default class AbstractButtonWidget extends NoteContextAwareWidget { export default class AbstractButtonWidget extends NoteContextAwareWidget {
@ -22,10 +22,13 @@ export default class AbstractButtonWidget extends NoteContextAwareWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.tooltip = new bootstrap.Tooltip(this.$widget, {
html: true, title: () => this.getTitle(), trigger: 'hover'
})
if (this.settings.onContextMenu) { if (this.settings.onContextMenu) {
this.$widget.on("contextmenu", e => { this.$widget.on("contextmenu", e => {
this.$widget.tooltip("hide"); this.tooltip.hide();
this.settings.onContextMenu(e); this.settings.onContextMenu(e);
@ -35,12 +38,6 @@ export default class AbstractButtonWidget extends NoteContextAwareWidget {
this.$widget.attr("data-placement", this.settings.titlePlacement); this.$widget.attr("data-placement", this.settings.titlePlacement);
this.$widget.tooltip({
html: true,
title: () => this.getTitle(),
trigger: "hover"
});
super.doRender(); super.doRender();
} }

View File

@ -27,7 +27,7 @@ const TPL = `
} }
</style> </style>
<button type="button" data-toggle="dropdown" aria-haspopup="true" <button type="button" data-bs-toggle="dropdown" aria-haspopup="true"
aria-expanded="false" class="icon-action icon-action-always-border bx bx-dots-vertical-rounded" aria-expanded="false" class="icon-action icon-action-always-border bx bx-dots-vertical-rounded"
style="position: relative; top: 3px;"></button> style="position: relative; top: 3px;"></button>
@ -61,7 +61,8 @@ export default class AttachmentActionsWidget extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$widget.on('click', '.dropdown-item', () => this.$widget.find("[data-toggle='dropdown']").dropdown('toggle')); this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
this.$widget.on('click', '.dropdown-item', () => this.dropdown.toggle());
this.$uploadNewRevisionInput = this.$widget.find(".attachment-upload-new-revision-input"); this.$uploadNewRevisionInput = this.$widget.find(".attachment-upload-new-revision-input");
this.$uploadNewRevisionInput.on('change', async () => { this.$uploadNewRevisionInput.on('change', async () => {
@ -94,7 +95,7 @@ export default class AttachmentActionsWidget extends BasicWidget {
); );
} }
} }
if (!isElectron){ if (!isElectron) {
const $openAttachmentCustomButton = this.$widget.find("[data-trigger-command='openAttachmentCustom']"); const $openAttachmentCustomButton = this.$widget.find("[data-trigger-command='openAttachmentCustom']");
$openAttachmentCustomButton $openAttachmentCustomButton
.addClass("disabled") .addClass("disabled")
@ -138,7 +139,7 @@ export default class AttachmentActionsWidget extends BasicWidget {
return; return;
} }
const {note: newNote} = await server.post(`attachments/${this.attachmentId}/convert-to-note`) const { note: newNote } = await server.post(`attachments/${this.attachmentId}/convert-to-note`)
toastService.showMessage(t('attachments_actions.convert_success', { title: this.attachment.title })); toastService.showMessage(t('attachments_actions.convert_success', { title: this.attachment.title }));
await ws.waitForMaxKnownEntityChangeId(); await ws.waitForMaxKnownEntityChangeId();
await appContext.tabManager.getActiveContext().setNote(newNote.noteId); await appContext.tabManager.getActiveContext().setNote(newNote.noteId);
@ -155,6 +156,6 @@ export default class AttachmentActionsWidget extends BasicWidget {
return; return;
} }
await server.put(`attachments/${this.attachmentId}/rename`, {title: attachmentTitle}); await server.put(`attachments/${this.attachmentId}/rename`, { title: attachmentTitle });
} }
} }

View File

@ -123,7 +123,7 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
if (note) { if (note) {
appContext.tabManager.getActiveContext().setNote(note.noteId); appContext.tabManager.getActiveContext().setNote(note.noteId);
this.hideDropdown(); this.dropdown.hide();
} }
else { else {
toastService.showError(t("calendar.cannot_find_day_note")); toastService.showError(t("calendar.cannot_find_day_note"));
@ -140,9 +140,9 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
this.firstDayOfWeek = options.getInt("firstDayOfWeek"); this.firstDayOfWeek = options.getInt("firstDayOfWeek");
// Generate the list of days of the week taking into consideration the user's selected first day of week. // Generate the list of days of the week taking into consideration the user's selected first day of week.
let localeDaysOfWeek = [ ...DAYS_OF_WEEK ]; let localeDaysOfWeek = [...DAYS_OF_WEEK];
const daysToBeAddedAtEnd = localeDaysOfWeek.splice(0, this.firstDayOfWeek); const daysToBeAddedAtEnd = localeDaysOfWeek.splice(0, this.firstDayOfWeek);
localeDaysOfWeek = [ ...localeDaysOfWeek, ...daysToBeAddedAtEnd ]; localeDaysOfWeek = [...localeDaysOfWeek, ...daysToBeAddedAtEnd];
this.$weekHeader.html(localeDaysOfWeek.map((el) => `<span>${el}</span>`)); this.$weekHeader.html(localeDaysOfWeek.map((el) => `<span>${el}</span>`));
} }
@ -238,7 +238,7 @@ export default class CalendarWidget extends RightDropdownButtonWidget {
this.$yearSelect.val(this.date.getFullYear()); this.$yearSelect.val(this.date.getFullYear());
} }
async entitiesReloadedEvent({loadResults}) { async entitiesReloadedEvent({ loadResults }) {
if (!loadResults.getOptionNames().includes("firstDayOfWeek")) { if (!loadResults.getOptionNames().includes("firstDayOfWeek")) {
return; return;
} }

View File

@ -11,7 +11,7 @@ export default class CommandButtonWidget extends AbstractButtonWidget {
if (this.settings.command) { if (this.settings.command) {
this.$widget.on("click", () => { this.$widget.on("click", () => {
this.$widget.tooltip("hide"); this.tooltip.hide();
this.triggerCommand(this._command); this.triggerCommand(this._command);
}); });

View File

@ -5,7 +5,7 @@ import UpdateAvailableWidget from "./update_available.js";
import options from "../../services/options.js"; import options from "../../services/options.js";
const TPL = ` const TPL = `
<div class="dropdown global-menu dropright"> <div class="dropdown global-menu dropend">
<style> <style>
.global-menu { .global-menu {
width: 53px; width: 53px;
@ -102,10 +102,9 @@ const TPL = `
} }
</style> </style>
<button type="button" data-toggle="dropdown" data-placement="right" <button type="button" data-bs-toggle="dropdown" aria-haspopup="true"
aria-haspopup="true" aria-expanded="false" aria-expanded="false" class="icon-action global-menu-button">
class="icon-action global-menu-button" title="${t('global_menu.menu')}"> <svg viewBox="0 0 256 256" data-bs-toggle="tooltip" title="${t('global_menu.menu')}">
<svg viewBox="0 0 256 256">
<g> <g>
<path class="st0" d="m202.9 112.7c-22.5 16.1-54.5 12.8-74.9 6.3l14.8-11.8 14.1-11.3 49.1-39.3-51.2 35.9-14.3 10-14.9 10.5c0.7-21.2 7-49.9 28.6-65.4 1.8-1.3 3.9-2.6 6.1-3.8 2.7-1.5 5.7-2.9 8.8-4.1 27.1-11.1 68.5-15.3 85.2-9.5 0.1 16.2-15.9 45.4-33.9 65.9-2.4 2.8-4.9 5.4-7.4 7.8-3.4 3.5-6.8 6.4-10.1 8.8z"/> <path class="st0" d="m202.9 112.7c-22.5 16.1-54.5 12.8-74.9 6.3l14.8-11.8 14.1-11.3 49.1-39.3-51.2 35.9-14.3 10-14.9 10.5c0.7-21.2 7-49.9 28.6-65.4 1.8-1.3 3.9-2.6 6.1-3.8 2.7-1.5 5.7-2.9 8.8-4.1 27.1-11.1 68.5-15.3 85.2-9.5 0.1 16.2-15.9 45.4-33.9 65.9-2.4 2.8-4.9 5.4-7.4 7.8-3.4 3.5-6.8 6.4-10.1 8.8z"/>
<path class="st1" d="m213.1 104c-22.2 12.6-51.4 9.3-70.3 3.2l14.1-11.3 49.1-39.3-51.2 35.9-14.3 10c0.5-18.1 4.9-42.1 19.7-58.6 2.7-1.5 5.7-2.9 8.8-4.1 27.1-11.1 68.5-15.3 85.2-9.5 0.1 16.2-15.9 45.4-33.9 65.9-2.3 2.8-4.8 5.4-7.2 7.8z"/> <path class="st1" d="m213.1 104c-22.2 12.6-51.4 9.3-70.3 3.2l14.1-11.3 49.1-39.3-51.2 35.9-14.3 10c0.5-18.1 4.9-42.1 19.7-58.6 2.7-1.5 5.7-2.9 8.8-4.1 27.1-11.1 68.5-15.3 85.2-9.5 0.1 16.2-15.9 45.4-33.9 65.9-2.3 2.8-4.8 5.4-7.2 7.8z"/>
@ -259,10 +258,9 @@ export default class GlobalMenuWidget extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$dropdown = this.$widget.find("[data-toggle='dropdown']"); this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
const $button = this.$widget.find(".global-menu-button");
$button.tooltip({ trigger: "hover" }); this.tooltip = new bootstrap.Tooltip(this.$widget.find("[data-bs-toggle='tooltip']"), { trigger: "hover" });
$button.on("click", () => $button.tooltip("hide"));
this.$widget.find(".show-about-dialog-button").on('click', () => this.triggerCommand("openAboutDialog")); this.$widget.find(".show-about-dialog-button").on('click', () => this.triggerCommand("openAboutDialog"));
@ -278,8 +276,11 @@ export default class GlobalMenuWidget extends BasicWidget {
return; return;
} }
this.$dropdown.dropdown('toggle'); this.dropdown.toggle();
}); });
this.$widget.on('click', '.dropdown-submenu', e => {
e.stopPropagation();
})
this.$widget.find(".global-menu-button-update-available").append( this.$widget.find(".global-menu-button-update-available").append(
this.updateAvailableWidget.render() this.updateAvailableWidget.render()
@ -292,7 +293,12 @@ export default class GlobalMenuWidget extends BasicWidget {
} }
this.$zoomState = this.$widget.find(".zoom-state"); this.$zoomState = this.$widget.find(".zoom-state");
this.$widget.on('show.bs.dropdown', () => this.updateZoomState()); this.$widget.on('show.bs.dropdown', () => {
this.updateZoomState();
this.tooltip.hide();
this.tooltip.disable();
});
this.$widget.on('hide.bs.dropdown', () => this.tooltip.enable());
this.$widget.find(".zoom-buttons").on("click", this.$widget.find(".zoom-buttons").on("click",
// delay to wait for the actual zoom change // delay to wait for the actual zoom change
@ -342,10 +348,10 @@ export default class GlobalMenuWidget extends BasicWidget {
} }
activeContextChangedEvent() { activeContextChangedEvent() {
this.$dropdown.dropdown('hide'); this.dropdown.hide();
} }
noteSwitchedEvent() { noteSwitchedEvent() {
this.$dropdown.dropdown('hide'); this.dropdown.hide();
} }
} }

View File

@ -27,7 +27,7 @@ const TPL = `
} }
</style> </style>
<button type="button" data-toggle="dropdown" aria-haspopup="true" <button type="button" data-bs-toggle="dropdown" aria-haspopup="true"
aria-expanded="false" class="icon-action bx bx-dots-vertical-rounded"></button> aria-expanded="false" class="icon-action bx bx-dots-vertical-rounded"></button>
<div class="dropdown-menu dropdown-menu-right"> <div class="dropdown-menu dropdown-menu-right">
@ -82,7 +82,7 @@ export default class NoteActionsWidget extends NoteContextAwareWidget {
this.$importNoteButton = this.$widget.find('.import-files-button'); this.$importNoteButton = this.$widget.find('.import-files-button');
this.$importNoteButton.on("click", () => this.triggerCommand("showImportDialog", {noteId: this.noteId})); this.$importNoteButton.on("click", () => this.triggerCommand("showImportDialog", {noteId: this.noteId}));
this.$widget.on('click', '.dropdown-item', () => this.$widget.find("[data-toggle='dropdown']").dropdown('toggle')); this.$widget.on('click', '.dropdown-item', () => this.$widget.find("[data-bs-toggle='dropdown']").dropdown('toggle'));
this.$openNoteExternallyButton = this.$widget.find(".open-note-externally-button"); this.$openNoteExternallyButton = this.$widget.find(".open-note-externally-button");
this.$openNoteCustomButton = this.$widget.find(".open-note-custom-button"); this.$openNoteCustomButton = this.$widget.find(".open-note-custom-button");

View File

@ -1,17 +1,19 @@
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
const TPL = ` const TPL = `
<div class="dropdown right-dropdown-widget dropright"> <div class="dropdown right-dropdown-widget dropend">
<style> <style>
.right-dropdown-widget { .right-dropdown-widget {
height: 53px; height: 53px;
} }
</style> </style>
<button type="button" data-toggle="dropdown" data-placement="right" <button type="button" data-bs-toggle="dropdown" data-placement="right"
aria-haspopup="true" aria-expanded="false" aria-haspopup="true" aria-expanded="false"
class="bx right-dropdown-button launcher-button"></button> class="bx right-dropdown-button launcher-button"></button>
<div class="tooltip-trigger"></div>
<div class="dropdown-menu dropdown-menu-right"></div> <div class="dropdown-menu dropdown-menu-right"></div>
</div> </div>
`; `;
@ -28,12 +30,16 @@ export default class RightDropdownButtonWidget extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$dropdownMenu = this.$widget.find(".dropdown-menu"); this.$dropdownMenu = this.$widget.find(".dropdown-menu");
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
const $button = this.$widget.find(".right-dropdown-button") this.$tooltip = this.$widget.find(".tooltip-trigger").attr("title", this.title);
this.tooltip = new bootstrap.Tooltip(this.$tooltip);
this.$widget.find(".right-dropdown-button")
.addClass(this.iconClass) .addClass(this.iconClass)
.attr("title", this.title) .on("click", () => this.tooltip.hide())
.tooltip({ trigger: "hover" }) .on('mouseenter', () => this.tooltip.show())
.on("click", () => $button.tooltip("hide")); .on('mouseleave', () => this.tooltip.hide());
this.$widget.on('show.bs.dropdown', async () => { this.$widget.on('show.bs.dropdown', async () => {
await this.dropdownShown(); await this.dropdownShown();
@ -51,10 +57,5 @@ export default class RightDropdownButtonWidget extends BasicWidget {
} }
// to be overridden // to be overridden
async dropdownShow() {} async dropdownShow() { }
hideDropdown() {
this.$widget.dropdown("hide");
this.$dropdownMenu.removeClass("show");
}
} }

View File

@ -10,11 +10,8 @@ const TPL = `
<div class="modal-dialog modal-lg" role="document"> <div class="modal-dialog modal-lg" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t("about.title")}</h5> <h5 class="modal-title">${t("about.title")}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0;">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<table class="table table-borderless text-nowrap"> <table class="table table-borderless text-nowrap">

View File

@ -9,13 +9,9 @@ const TPL = `
<div class="modal-dialog modal-lg" style="max-width: 1000px" role="document"> <div class="modal-dialog modal-lg" style="max-width: 1000px" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t('add_link.add_link')}</h5> <h5 class="modal-title flex-grow-1">${t('add_link.add_link')}</h5>
<button type="button" class="help-button" title="${t('add_link.help_on_links')}" data-help-page="links.html">?</button> <button type="button" class="help-button" title="${t('add_link.help_on_links')}" data-help-page="links.html">?</button>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('add_link.close')}"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="${t('add_link.close')}" style="margin-left: 0 !important;">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<form class="add-link-form"> <form class="add-link-form">
<div class="modal-body"> <div class="modal-body">

View File

@ -14,13 +14,9 @@ const TPL = `<div class="branch-prefix-dialog modal fade mx-auto" tabindex="-1"
<form class="branch-prefix-form"> <form class="branch-prefix-form">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t('branch_prefix.edit_branch_prefix')}</h5> <h5 class="modal-title flex-grow-1">${t('branch_prefix.edit_branch_prefix')}</h5>
<button class="help-button" type="button" data-help-page="tree-concepts.html#prefix" title="${t('branch_prefix.help_on_tree_prefix')}">?</button> <button class="help-button" type="button" data-help-page="tree-concepts.html#prefix" title="${t('branch_prefix.help_on_tree_prefix')}">?</button>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('branch_prefix.close')}"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="${t('branch_prefix.close')}" style="margin-left: 0;">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <div class="form-group">
@ -28,13 +24,10 @@ const TPL = `<div class="branch-prefix-dialog modal fade mx-auto" tabindex="-1"
<div class="input-group"> <div class="input-group">
<input class="branch-prefix-input form-control"> <input class="branch-prefix-input form-control">
<div class="input-group-append">
<div class="branch-prefix-note-title input-group-text"></div> <div class="branch-prefix-note-title input-group-text"></div>
</div> </div>
</div> </div>
</div> </div>
</div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn btn-primary btn-sm">${t('branch_prefix.save')}</button> <button class="btn btn-primary btn-sm">${t('branch_prefix.save')}</button>
</div> </div>
@ -46,6 +39,7 @@ const TPL = `<div class="branch-prefix-dialog modal fade mx-auto" tabindex="-1"
export default class BranchPrefixDialog extends BasicWidget { export default class BranchPrefixDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$form = this.$widget.find(".branch-prefix-form"); this.$form = this.$widget.find(".branch-prefix-form");
this.$treePrefixInput = this.$widget.find(".branch-prefix-input"); this.$treePrefixInput = this.$widget.find(".branch-prefix-input");
this.$noteTitle = this.$widget.find('.branch-prefix-note-title'); this.$noteTitle = this.$widget.find('.branch-prefix-note-title');
@ -60,7 +54,7 @@ export default class BranchPrefixDialog extends BasicWidget {
} }
async refresh(notePath) { async refresh(notePath) {
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromUrl(notePath); const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
if (!noteId || !parentNoteId) { if (!noteId || !parentNoteId) {
return; return;
@ -97,9 +91,9 @@ export default class BranchPrefixDialog extends BasicWidget {
async savePrefix() { async savePrefix() {
const prefix = this.$treePrefixInput.val(); const prefix = this.$treePrefixInput.val();
await server.put(`branches/${branchId}/set-prefix`, {prefix: prefix}); await server.put(`branches/${branchId}/set-prefix`, { prefix: prefix });
this.$widget.modal('hide'); this.modal.hide();
toastService.showMessage(t('branch_prefix.branch_prefix_saved')); toastService.showMessage(t('branch_prefix.branch_prefix_saved'));
} }

View File

@ -38,20 +38,15 @@ const TPL = `
<div class="modal-dialog modal-xl" role="document"> <div class="modal-dialog modal-xl" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t('bulk_actions.bulk_actions')}</h5> <h5 class="modal-title">${t('bulk_actions.bulk_actions')}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('bulk_actions.close')}"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="${t('bulk_actions.close')}">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<h4>${t('bulk_actions.affected_notes')}: <span class="affected-note-count">0</span></h4> <h4>${t('bulk_actions.affected_notes')}: <span class="affected-note-count">0</span></h4>
<div class="form-check"> <div class="form-check">
<label class="form-check-label">
<input class="include-descendants form-check-input" type="checkbox" value=""> <input class="include-descendants form-check-input" type="checkbox" value="">
${t('bulk_actions.include_descendants')} <label class="form-check-label">${t('bulk_actions.include_descendants')}</label>
</label>
</div> </div>
<h4>${t('bulk_actions.available_actions')}</h4> <h4>${t('bulk_actions.available_actions')}</h4>
@ -72,7 +67,6 @@ const TPL = `
export default class BulkActionsDialog extends BasicWidget { export default class BulkActionsDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$includeDescendants = this.$widget.find(".include-descendants"); this.$includeDescendants = this.$widget.find(".include-descendants");
this.$includeDescendants.on("change", () => this.refresh()); this.$includeDescendants.on("change", () => this.refresh());

View File

@ -13,13 +13,9 @@ const TPL = `
<div class="modal-dialog modal-lg" style="max-width: 1000px" role="document"> <div class="modal-dialog modal-lg" style="max-width: 1000px" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t('clone_to.clone_notes_to')}</h5> <h5 class="modal-title flex-grow-1">${t('clone_to.clone_notes_to')}</h5>
<button type="button" class="help-button" title="${t('clone_to.help_on_links')}" data-help-page="cloning-notes.html">?</button> <button type="button" class="help-button" title="${t('clone_to.help_on_links')}" data-help-page="cloning-notes.html">?</button>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<form class="clone-to-form"> <form class="clone-to-form">
<div class="modal-body"> <div class="modal-body">
@ -81,9 +77,9 @@ export default class CloneToDialog extends BasicWidget {
}); });
} }
async cloneNoteIdsToEvent({noteIds}) { async cloneNoteIdsToEvent({ noteIds }) {
if (!noteIds || noteIds.length === 0) { if (!noteIds || noteIds.length === 0) {
noteIds = [ appContext.tabManager.getActiveContextNoteId() ]; noteIds = [appContext.tabManager.getActiveContextNoteId()];
} }
this.clonedNoteIds = []; this.clonedNoteIds = [];
@ -111,7 +107,7 @@ export default class CloneToDialog extends BasicWidget {
} }
async cloneNotesTo(notePath) { async cloneNotesTo(notePath) {
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromUrl(notePath); const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
const targetBranchId = await froca.getBranchId(parentNoteId, noteId); const targetBranchId = await froca.getBranchId(parentNoteId, noteId);
for (const cloneNoteId of this.clonedNoteIds) { for (const cloneNoteId of this.clonedNoteIds) {
@ -120,7 +116,7 @@ export default class CloneToDialog extends BasicWidget {
const clonedNote = await froca.getNote(cloneNoteId); const clonedNote = await froca.getNote(cloneNoteId);
const targetNote = await froca.getBranch(targetBranchId).getNote(); const targetNote = await froca.getBranch(targetBranchId).getNote();
toastService.showMessage(t('clone_to.note_cloned', {clonedTitle: clonedNote.title, targetTitle: targetNote.title})); toastService.showMessage(t('clone_to.note_cloned', { clonedTitle: clonedNote.title, targetTitle: targetNote.title }));
} }
} }
} }

View File

@ -8,11 +8,8 @@ const TPL = `
<div class="modal-dialog modal-dialog-scrollable" role="document"> <div class="modal-dialog modal-dialog-scrollable" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t('confirm.confirmation')}</h5> <h5 class="modal-title">${t('confirm.confirmation')}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="confirm-dialog-content"></div> <div class="confirm-dialog-content"></div>
@ -40,6 +37,7 @@ export default class ConfirmDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$confirmContent = this.$widget.find(".confirm-dialog-content"); this.$confirmContent = this.$widget.find(".confirm-dialog-content");
this.$okButton = this.$widget.find(".confirm-dialog-ok-button"); this.$okButton = this.$widget.find(".confirm-dialog-ok-button");
this.$cancelButton = this.$widget.find(".confirm-dialog-cancel-button"); this.$cancelButton = this.$widget.find(".confirm-dialog-cancel-button");
@ -62,7 +60,7 @@ export default class ConfirmDialog extends BasicWidget {
this.$okButton.on('click', () => this.doResolve(true)); this.$okButton.on('click', () => this.doResolve(true));
} }
showConfirmDialogEvent({message, callback}) { showConfirmDialogEvent({ message, callback }) {
this.$originallyFocused = $(':focus'); this.$originallyFocused = $(':focus');
this.$custom.hide(); this.$custom.hide();
@ -75,15 +73,15 @@ export default class ConfirmDialog extends BasicWidget {
this.$confirmContent.empty().append(message); this.$confirmContent.empty().append(message);
this.$widget.modal(); this.modal.show();
this.resolve = callback; this.resolve = callback;
} }
showConfirmDeleteNoteBoxWithNoteDialogEvent({title, callback}) { showConfirmDeleteNoteBoxWithNoteDialogEvent({ title, callback }) {
glob.activeDialog = this.$widget; glob.activeDialog = this.$widget;
this.$confirmContent.text(`${t('confirm.are_you_sure_remove_note', {title: title})}`); this.$confirmContent.text(`${t('confirm.are_you_sure_remove_note', { title: title })}`);
this.$custom.empty() this.$custom.empty()
.append("<br/>") .append("<br/>")
@ -104,7 +102,7 @@ export default class ConfirmDialog extends BasicWidget {
this.$custom.show(); this.$custom.show();
this.$widget.modal(); this.modal.show();
this.resolve = callback; this.resolve = callback;
} }
@ -117,6 +115,6 @@ export default class ConfirmDialog extends BasicWidget {
this.resolve = null; this.resolve = null;
this.$widget.modal("hide"); this.modal.hide();
} }
} }

View File

@ -10,27 +10,18 @@ const TPL = `
<div class="modal-dialog modal-dialog-scrollable modal-xl" role="document"> <div class="modal-dialog modal-dialog-scrollable modal-xl" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h4 class="modal-title mr-auto">${t('delete_notes.delete_notes_preview')}</h4> <h4 class="modal-title">${t('delete_notes.delete_notes_preview')}</h4>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="checkbox"> <div class="form-checkbox">
<label> <input class="delete-all-clones form-check-input" value="1" type="checkbox">
<input class="delete-all-clones" value="1" type="checkbox"> <label class="form-check-label">${t('delete_notes.delete_all_clones_description')}</label>
${t('delete_notes.delete_all_clones_description')}
</label>
</div> </div>
<div class="checkbox"> <div class="form-checkbox" style="margin-bottom: 1rem">
<label title="${t('delete_notes.erase_notes_description')}"> <input class="erase-notes form-check-input" value="1" type="checkbox">
<input class="erase-notes" value="1" type="checkbox"> <label class="form-check-label">${t('delete_notes.erase_notes_warning')}</label>
${t('delete_notes.erase_notes_warning')}
</label>
</div> </div>
<div class="delete-notes-list-wrapper"> <div class="delete-notes-list-wrapper">

View File

@ -34,9 +34,7 @@ const TPL = `
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title">${t('export.export_note_title')} <span class="export-note-title"></span></h5> <h5 class="modal-title">${t('export.export_note_title')} <span class="export-note-title"></span></h5>
<button type="button" class="close" data-dismiss="modal" aria-label="${t('export.close')}"> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('export.close')}"></button>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<form class="export-form"> <form class="export-form">
<div class="modal-body"> <div class="modal-body">
@ -127,6 +125,7 @@ export default class ExportDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$form = this.$widget.find(".export-form"); this.$form = this.$widget.find(".export-form");
this.$noteTitle = this.$widget.find(".export-note-title"); this.$noteTitle = this.$widget.find(".export-note-title");
this.$subtreeFormats = this.$widget.find(".export-subtree-formats"); this.$subtreeFormats = this.$widget.find(".export-subtree-formats");
@ -137,7 +136,7 @@ export default class ExportDialog extends BasicWidget {
this.$opmlVersions = this.$widget.find(".opml-versions"); this.$opmlVersions = this.$widget.find(".opml-versions");
this.$form.on('submit', () => { this.$form.on('submit', () => {
this.$widget.modal('hide'); this.modal.hide();
const exportType = this.$widget.find("input[name='export-type']:checked").val(); const exportType = this.$widget.find("input[name='export-type']:checked").val();
@ -188,7 +187,7 @@ export default class ExportDialog extends BasicWidget {
}); });
} }
async showExportDialogEvent({notePath, defaultType}) { async showExportDialogEvent({ notePath, defaultType }) {
this.taskId = ''; this.taskId = '';
this.$exportButton.removeAttr("disabled"); this.$exportButton.removeAttr("disabled");
@ -208,7 +207,7 @@ export default class ExportDialog extends BasicWidget {
utils.openDialog(this.$widget); utils.openDialog(this.$widget);
const {noteId, parentNoteId} = treeService.getNoteIdAndParentIdFromUrl(notePath); const { noteId, parentNoteId } = treeService.getNoteIdAndParentIdFromUrl(notePath);
this.branchId = await froca.getBranchId(parentNoteId, noteId); this.branchId = await froca.getBranchId(parentNoteId, noteId);
this.$noteTitle.text(await treeService.getNoteTitle(noteId)); this.$noteTitle.text(await treeService.getNoteTitle(noteId));

View File

@ -7,14 +7,11 @@ const TPL = `
<div class="modal-dialog" role="document" style="min-width: 100%; height: 100%; margin: 0;"> <div class="modal-dialog" role="document" style="min-width: 100%; height: 100%; margin: 0;">
<div class="modal-content" style="height: auto;"> <div class="modal-content" style="height: auto;">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t('help.fullDocumentation')}</h5> <h5 class="modal-title">${t('help.fullDocumentation')}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('help.close')}"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="${t('help.close')}">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body" style="overflow: auto; height: calc(100vh - 70px);"> <div class="modal-body" style="overflow: auto; height: calc(100vh - 70px);">
<div class="card-columns help-cards"> <div class="help-cards row row-cols-3 g-3">
<div class="card"> <div class="card">
<div class="card-body"> <div class="card-body">
<h5 class="card-title">${t('help.noteNavigation')}</h5> <h5 class="card-title">${t('help.noteNavigation')}</h5>

View File

@ -11,9 +11,7 @@ const TPL = `
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title">${t('import.importIntoNote')}</h5> <h5 class="modal-title">${t('import.importIntoNote')}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="${t('import.close')}"> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t('import.close')}"></button>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<form class="import-form"> <form class="import-form">
<div class="modal-body"> <div class="modal-body">
@ -29,21 +27,21 @@ const TPL = `
<strong>${t('import.options')}:</strong> <strong>${t('import.options')}:</strong>
<div class="checkbox"> <div class="checkbox">
<label data-toggle="tooltip" title="${t('import.safeImportTooltip')}"> <label data-bs-toggle="tooltip" title="${t('import.safeImportTooltip')}">
<input class="safe-import-checkbox" value="1" type="checkbox" checked> <input class="safe-import-checkbox" value="1" type="checkbox" checked>
<span>${t('import.safeImport')}</span> <span>${t('import.safeImport')}</span>
</label> </label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label data-toggle="tooltip" title="${t('import.explodeArchivesTooltip')}"> <label data-bs-toggle="tooltip" title="${t('import.explodeArchivesTooltip')}">
<input class="explode-archives-checkbox" value="1" type="checkbox" checked> <input class="explode-archives-checkbox" value="1" type="checkbox" checked>
<span>${t('import.explodeArchives')}</span> <span>${t('import.explodeArchives')}</span>
</label> </label>
</div> </div>
<div class="checkbox"> <div class="checkbox">
<label data-toggle="tooltip" title="${t('import.shrinkImagesTooltip')}"> <label data-bs-toggle="tooltip" title="${t('import.shrinkImagesTooltip')}">
<input class="shrink-images-checkbox" value="1" type="checkbox" checked> <span>${t('import.shrinkImages')}</span> <input class="shrink-images-checkbox" value="1" type="checkbox" checked> <span>${t('import.shrinkImages')}</span>
</label> </label>
</div> </div>
@ -86,6 +84,8 @@ export default class ImportDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$form = this.$widget.find(".import-form"); this.$form = this.$widget.find(".import-form");
this.$noteTitle = this.$widget.find(".import-note-title"); this.$noteTitle = this.$widget.find(".import-note-title");
this.$fileUploadInput = this.$widget.find(".import-file-upload-input"); this.$fileUploadInput = this.$widget.find(".import-file-upload-input");
@ -115,12 +115,14 @@ export default class ImportDialog extends BasicWidget {
} }
}); });
this.$widget.find('[data-toggle="tooltip"]').tooltip({ let _ = [...this.$widget.find('[data-bs-toggle="tooltip"]')].forEach(element => {
bootstrap.Tooltip.getOrCreateInstance(element, {
html: true html: true
}); });
});
} }
async showImportDialogEvent({noteId}) { async showImportDialogEvent({ noteId }) {
this.parentNoteId = noteId; this.parentNoteId = noteId;
this.$fileUploadInput.val('').trigger('change'); // to trigger Import button disabling listener below this.$fileUploadInput.val('').trigger('change'); // to trigger Import button disabling listener below

View File

@ -11,9 +11,7 @@ const TPL = `
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title">${t('include_note.dialog_title')}</h5> <h5 class="modal-title">${t('include_note.dialog_title')}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<form class="include-note-form"> <form class="include-note-form">
<div class="modal-body"> <div class="modal-body">
@ -27,22 +25,16 @@ const TPL = `
${t('include_note.box_size_prompt')} ${t('include_note.box_size_prompt')}
<div class="form-check"> <div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="include-note-box-size" value="small"> <input class="form-check-input" type="radio" name="include-note-box-size" value="small">
${t('include_note.box_size_small')} <label class="form-check-label">${t('include_note.box_size_small')}</label>
</label>
</div> </div>
<div class="form-check"> <div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="include-note-box-size" value="medium" checked> <input class="form-check-input" type="radio" name="include-note-box-size" value="medium" checked>
${t('include_note.box_size_medium')} <label class="form-check-label">${t('include_note.box_size_medium')}</label>
</label>
</div> </div>
<div class="form-check"> <div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="include-note-box-size" value="full"> <input class="form-check-input" type="radio" name="include-note-box-size" value="full">
${t('include_note.box_size_full')} <label class="form-check-label">${t('include_note.box_size_full')}</label>
</label>
</div> </div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
@ -56,13 +48,14 @@ const TPL = `
export default class IncludeNoteDialog extends BasicWidget { export default class IncludeNoteDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$form = this.$widget.find(".include-note-form"); this.$form = this.$widget.find(".include-note-form");
this.$autoComplete = this.$widget.find(".include-note-autocomplete"); this.$autoComplete = this.$widget.find(".include-note-autocomplete");
this.$form.on('submit', () => { this.$form.on('submit', () => {
const notePath = this.$autoComplete.getSelectedNotePath(); const notePath = this.$autoComplete.getSelectedNotePath();
if (notePath) { if (notePath) {
this.$widget.modal('hide'); this.modal.hide();
this.includeNote(notePath); this.includeNote(notePath);
} else { } else {
logError("No noteId to include."); logError("No noteId to include.");
@ -72,7 +65,7 @@ export default class IncludeNoteDialog extends BasicWidget {
}) })
} }
async showIncludeNoteDialogEvent({textTypeWidget}) { async showIncludeNoteDialogEvent({ textTypeWidget }) {
this.textTypeWidget = textTypeWidget; this.textTypeWidget = textTypeWidget;
await this.refresh(); await this.refresh();
utils.openDialog(this.$widget); utils.openDialog(this.$widget);

View File

@ -7,11 +7,8 @@ const TPL = `
<div class="modal-dialog" role="document"> <div class="modal-dialog" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t("info.modalTitle")}</h5> <h5 class="modal-title">${t("info.modalTitle")}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("info.closeButton")}"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="${t("info.closeButton")}">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="info-dialog-content"></div> <div class="info-dialog-content"></div>
@ -33,6 +30,7 @@ export default class InfoDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$infoContent = this.$widget.find(".info-dialog-content"); this.$infoContent = this.$widget.find(".info-dialog-content");
this.$okButton = this.$widget.find(".info-dialog-ok-button"); this.$okButton = this.$widget.find(".info-dialog-ok-button");
@ -49,10 +47,10 @@ export default class InfoDialog extends BasicWidget {
} }
}); });
this.$okButton.on('click', () => this.$widget.modal("hide")); this.$okButton.on('click', () => this.modal.hide());
} }
showInfoDialogEvent({message, callback}) { showInfoDialogEvent({ message, callback }) {
this.$originallyFocused = $(':focus'); this.$originallyFocused = $(':focus');
this.$infoContent.text(message); this.$infoContent.text(message);

View File

@ -12,10 +12,7 @@ const TPL = `<div class="jump-to-note-dialog modal mx-auto" tabindex="-1" role="
<div class="input-group"> <div class="input-group">
<input class="jump-to-note-autocomplete form-control" placeholder="${t('jump_to_note.search_placeholder')}"> <input class="jump-to-note-autocomplete form-control" placeholder="${t('jump_to_note.search_placeholder')}">
</div> </div>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="algolia-autocomplete-container jump-to-note-results"></div> <div class="algolia-autocomplete-container jump-to-note-results"></div>
@ -38,6 +35,8 @@ export default class JumpToNoteDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$autoComplete = this.$widget.find(".jump-to-note-autocomplete"); this.$autoComplete = this.$widget.find(".jump-to-note-autocomplete");
this.$results = this.$widget.find(".jump-to-note-results"); this.$results = this.$widget.find(".jump-to-note-results");
this.$showInFullTextButton = this.$widget.find(".show-in-full-text-button"); this.$showInFullTextButton = this.$widget.find(".show-in-full-text-button");
@ -94,8 +93,8 @@ export default class JumpToNoteDialog extends BasicWidget {
const searchString = this.$autoComplete.val(); const searchString = this.$autoComplete.val();
this.triggerCommand('searchNotes', {searchString}); this.triggerCommand('searchNotes', { searchString });
this.$widget.modal('hide'); this.modal.hide();
} }
} }

View File

@ -12,9 +12,7 @@ const TPL = `
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title">${t("markdown_import.dialog_title")}</h5> <h5 class="modal-title">${t("markdown_import.dialog_title")}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<p>${t("markdown_import.modal_body_text")}</p> <p>${t("markdown_import.modal_body_text")}</p>
@ -37,6 +35,7 @@ export default class MarkdownImportDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$importTextarea = this.$widget.find('.markdown-import-textarea'); this.$importTextarea = this.$widget.find('.markdown-import-textarea');
this.$importButton = this.$widget.find('.markdown-import-button'); this.$importButton = this.$widget.find('.markdown-import-button');
@ -48,7 +47,7 @@ export default class MarkdownImportDialog extends BasicWidget {
} }
async convertMarkdownToHtml(markdownContent) { async convertMarkdownToHtml(markdownContent) {
const {htmlContent} = await server.post('other/render-markdown', { markdownContent }); const { htmlContent } = await server.post('other/render-markdown', { markdownContent });
const textEditor = await appContext.tabManager.getActiveContext().getTextEditor(); const textEditor = await appContext.tabManager.getActiveContext().getTextEditor();
@ -70,7 +69,7 @@ export default class MarkdownImportDialog extends BasicWidget {
} }
if (utils.isElectron()) { if (utils.isElectron()) {
const {clipboard} = utils.dynamicRequire('electron'); const { clipboard } = utils.dynamicRequire('electron');
const text = clipboard.readText(); const text = clipboard.readText();
this.convertMarkdownToHtml(text); this.convertMarkdownToHtml(text);
@ -83,7 +82,7 @@ export default class MarkdownImportDialog extends BasicWidget {
async sendForm() { async sendForm() {
const text = this.$importTextarea.val(); const text = this.$importTextarea.val();
this.$widget.modal('hide'); this.modal.hide();
await this.convertMarkdownToHtml(text); await this.convertMarkdownToHtml(text);

View File

@ -5,18 +5,15 @@ import froca from "../../services/froca.js";
import branchService from "../../services/branches.js"; import branchService from "../../services/branches.js";
import treeService from "../../services/tree.js"; import treeService from "../../services/tree.js";
import BasicWidget from "../basic_widget.js"; import BasicWidget from "../basic_widget.js";
import { t } from "../../services/i18n.js"; // Added import import { t } from "../../services/i18n.js";
const TPL = ` const TPL = `
<div class="move-to-dialog modal mx-auto" tabindex="-1" role="dialog"> <div class="move-to-dialog modal mx-auto" tabindex="-1" role="dialog">
<div class="modal-dialog modal-lg" style="max-width: 1000px" role="document"> <div class="modal-dialog modal-lg" style="max-width: 1000px" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t("move_to.dialog_title")}</h5> <h5 class="modal-title me-auto">${t("move_to.dialog_title")}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<form class="move-to-form"> <form class="move-to-form">
<div class="modal-body"> <div class="modal-body">

View File

@ -23,17 +23,16 @@ const TPL = `
<div class="modal-dialog" style="max-width: 500px;" role="document"> <div class="modal-dialog" style="max-width: 500px;" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t("note_type_chooser.modal_title")}</h5> <h5 class="modal-title">${t("note_type_chooser.modal_title")}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
${t("note_type_chooser.modal_body")} ${t("note_type_chooser.modal_body")}
<div class="dropdown"> <div class="dropdown" style="display: flex;">
<button class="note-type-dropdown-trigger" type="button" style="display: none;" data-toggle="dropdown"></button> <button class="note-type-dropdown-trigger" type="button" style="display: none;"
data-bs-toggle="dropdown" data-bs-display="static">
</button>
<div class="note-type-dropdown dropdown-menu"></div> <div class="note-type-dropdown dropdown-menu"></div>
</div> </div>
@ -53,13 +52,14 @@ export default class NoteTypeChooserDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown"); this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown");
this.$noteTypeDropdownTrigger = this.$widget.find(".note-type-dropdown-trigger"); this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find(".note-type-dropdown-trigger"));
this.$noteTypeDropdownTrigger.dropdown();
this.$widget.on("hidden.bs.modal", () => { this.$widget.on("hidden.bs.modal", () => {
if (this.resolve) { if (this.resolve) {
this.resolve({success: false}); this.resolve({ success: false });
} }
if (this.$originalFocused) { if (this.$originalFocused) {
@ -94,7 +94,7 @@ export default class NoteTypeChooserDialog extends BasicWidget {
}); });
} }
async chooseNoteTypeEvent({callback}) { async chooseNoteTypeEvent({ callback }) {
this.$originalFocused = $(':focus'); this.$originalFocused = $(':focus');
const noteTypes = await noteTypesService.getNoteTypeItems(); const noteTypes = await noteTypesService.getNoteTypeItems();
@ -116,11 +116,11 @@ export default class NoteTypeChooserDialog extends BasicWidget {
} }
} }
this.$noteTypeDropdownTrigger.dropdown('show'); this.dropdown.show();
this.$originalDialog = glob.activeDialog; this.$originalDialog = glob.activeDialog;
glob.activeDialog = this.$widget; glob.activeDialog = this.modal;
this.$widget.modal(); this.modal.show();
this.$noteTypeDropdown.find(".dropdown-item:first").focus(); this.$noteTypeDropdown.find(".dropdown-item:first").focus();
@ -139,6 +139,6 @@ export default class NoteTypeChooserDialog extends BasicWidget {
}); });
this.resolve = null; this.resolve = null;
this.$widget.modal("hide"); this.modal.hide();
} }
} }

View File

@ -7,11 +7,8 @@ const TPL = `
<div class="modal-dialog modal-md" role="document"> <div class="modal-dialog modal-md" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t("password_not_set.title")}</h5> <h5 class="modal-title">${t("password_not_set.title")}</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0;">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
${t("password_not_set.body1")} ${t("password_not_set.body1")}
@ -26,8 +23,10 @@ const TPL = `
export default class PasswordNoteSetDialog extends BasicWidget { export default class PasswordNoteSetDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$openPasswordOptionsButton = this.$widget.find(".open-password-options-button"); this.$openPasswordOptionsButton = this.$widget.find(".open-password-options-button");
this.$openPasswordOptionsButton.on("click", () => { this.$openPasswordOptionsButton.on("click", () => {
this.modal.hide();
this.triggerCommand("showOptions", { section: '_optionsPassword' }); this.triggerCommand("showOptions", { section: '_optionsPassword' });
}); });
} }

View File

@ -8,13 +8,10 @@ const TPL = `
<div class="modal-content"> <div class="modal-content">
<form class="prompt-dialog-form"> <form class="prompt-dialog-form">
<div class="modal-header"> <div class="modal-header">
<h5 class="prompt-title modal-title mr-auto">${t("prompt.title")}</h5> <h5 class="prompt-title modal-title">${t("prompt.title")}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
</div> </div>
<div class="modal-body"></div>
<div class="modal-footer"> <div class="modal-footer">
<button class="prompt-dialog-ok-button btn btn-primary btn-sm">${t("prompt.ok")}</button> <button class="prompt-dialog-ok-button btn btn-primary btn-sm">${t("prompt.ok")}</button>
</div> </div>
@ -33,6 +30,7 @@ export default class PromptDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$dialogBody = this.$widget.find(".modal-body"); this.$dialogBody = this.$widget.find(".modal-body");
this.$form = this.$widget.find(".prompt-dialog-form"); this.$form = this.$widget.find(".prompt-dialog-form");
this.$question = null; this.$question = null;
@ -61,7 +59,7 @@ export default class PromptDialog extends BasicWidget {
e.preventDefault(); e.preventDefault();
this.resolve(this.$answer.val()); this.resolve(this.$answer.val());
this.$widget.modal('hide'); this.modal.hide();
}); });
} }

View File

@ -8,22 +8,14 @@ const TPL = `
<div class="modal-dialog modal-md" role="document"> <div class="modal-dialog modal-md" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t("protected_session_password.modal_title")}</h5> <h5 class="modal-title flex-grow-1">${t("protected_session_password.modal_title")}</h5>
<button class="help-button" type="button" data-help-page="protected-notes.html" title="${t("protected_session_password.help_title")}">?</button> <button class="help-button" type="button" data-help-page="protected-notes.html" title="${t("protected_session_password.help_title")}">?</button>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="${t("protected_session_password.close_label")}"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="${t("protected_session_password.close_label")}" style="margin-left: 0;">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<form class="protected-session-password-form"> <form class="protected-session-password-form">
<div class="modal-body"> <div class="modal-body">
<div class="form-group"> <label class="col-form-label">${t("protected_session_password.form_label")}</label>
<label>
${t("protected_session_password.form_label")}
<input class="form-control protected-session-password" type="password"> <input class="form-control protected-session-password" type="password">
</label>
</div>
</div> </div>
<div class="modal-footer"> <div class="modal-footer">
<button class="btn btn-primary">${t("protected_session_password.start_button")}</button> <button class="btn btn-primary">${t("protected_session_password.start_button")}</button>
@ -36,6 +28,8 @@ const TPL = `
export default class ProtectedSessionPasswordDialog extends BasicWidget { export default class ProtectedSessionPasswordDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$passwordForm = this.$widget.find(".protected-session-password-form"); this.$passwordForm = this.$widget.find(".protected-session-password-form");
this.$passwordInput = this.$widget.find(".protected-session-password"); this.$passwordInput = this.$widget.find(".protected-session-password");
this.$passwordForm.on('submit', () => { this.$passwordForm.on('submit', () => {
@ -55,6 +49,6 @@ export default class ProtectedSessionPasswordDialog extends BasicWidget {
} }
closeProtectedSessionPasswordDialogEvent() { closeProtectedSessionPasswordDialogEvent() {
this.$widget.modal('hide'); this.modal.hide();
} }
} }

View File

@ -15,14 +15,9 @@ const TPL = `
<div class="modal-dialog modal-lg modal-dialog-scrollable" role="document"> <div class="modal-dialog modal-lg modal-dialog-scrollable" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t('recent_changes.title')}</h5> <h5 class="modal-title flex-grow-1">${t('recent_changes.title')}</h5>
<button class="erase-deleted-notes-now-button btn btn-sm" style="padding: 0 10px">${t('recent_changes.erase_notes_button')}</button>
<button class="erase-deleted-notes-now-button btn btn-sm" style="padding: 0 10px"> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
${t('recent_changes.erase_notes_button')}</button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div class="recent-changes-content"></div> <div class="recent-changes-content"></div>
@ -34,6 +29,8 @@ const TPL = `
export default class RecentChangesDialog extends BasicWidget { export default class RecentChangesDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$content = this.$widget.find(".recent-changes-content"); this.$content = this.$widget.find(".recent-changes-content");
this.$eraseDeletedNotesNow = this.$widget.find(".erase-deleted-notes-now-button"); this.$eraseDeletedNotesNow = this.$widget.find(".erase-deleted-notes-now-button");
this.$eraseDeletedNotesNow.on("click", () => { this.$eraseDeletedNotesNow.on("click", () => {
@ -45,7 +42,7 @@ export default class RecentChangesDialog extends BasicWidget {
}); });
} }
async showRecentChangesEvent({ancestorNoteId}) { async showRecentChangesEvent({ ancestorNoteId }) {
this.ancestorNoteId = ancestorNoteId; this.ancestorNoteId = ancestorNoteId;
await this.refresh(); await this.refresh();
@ -93,7 +90,7 @@ export default class RecentChangesDialog extends BasicWidget {
if (await dialogService.confirm(text)) { if (await dialogService.confirm(text)) {
await server.put(`notes/${change.noteId}/undelete`); await server.put(`notes/${change.noteId}/undelete`);
this.$widget.modal('hide'); this.modal.hide();
await ws.waitForMaxKnownEntityChangeId(); await ws.waitForMaxKnownEntityChangeId();

View File

@ -40,21 +40,18 @@ const TPL = `
<div class="modal-dialog modal-xl" role="document"> <div class="modal-dialog modal-xl" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t("revisions.note_revisions")}</h5> <h5 class="modal-title flex-grow-1">${t("revisions.note_revisions")}</h5>
<button class="revisions-erase-all-revisions-button btn btn-sm" <button class="revisions-erase-all-revisions-button btn btn-sm"
title="${t("revisions.delete_all_revisions")}" title="${t("revisions.delete_all_revisions")}"
style="padding: 0 10px 0 10px;" type="button">${t("revisions.delete_all_button")}</button> style="padding: 0 10px 0 10px;" type="button">${t("revisions.delete_all_button")}</button>
<button class="help-button" type="button" data-help-page="note-revisions.html" title="${t("revisions.help_title")}">?</button> <button class="help-button" type="button" data-help-page="note-revisions.html" title="${t("revisions.help_title")}">?</button>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;">
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<div class="modal-body" style="display: flex; height: 80vh;"> <div class="modal-body" style="display: flex; height: 80vh;">
<div class="dropdown"> <div class="dropdown">
<button class="revision-list-dropdown" type="button" style="display: none;" data-toggle="dropdown"></button> <button class="revision-list-dropdown" type="button" style="display: none;"
data-bs-toggle="dropdown" data-bs-display="static">
</button>
<div class="revision-list dropdown-menu" style="position: static; height: 100%; overflow: auto;"></div> <div class="revision-list dropdown-menu" style="position: static; height: 100%; overflow: auto;"></div>
</div> </div>
@ -84,6 +81,8 @@ export default class RevisionsDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$list = this.$widget.find(".revision-list"); this.$list = this.$widget.find(".revision-list");
this.$listDropdown = this.$widget.find(".revision-list-dropdown"); this.$listDropdown = this.$widget.find(".revision-list-dropdown");
this.$content = this.$widget.find(".revision-content"); this.$content = this.$widget.find(".revision-content");
@ -111,7 +110,7 @@ export default class RevisionsDialog extends BasicWidget {
if (await dialogService.confirm(text)) { if (await dialogService.confirm(text)) {
await server.remove(`notes/${this.note.noteId}/revisions`); await server.remove(`notes/${this.note.noteId}/revisions`);
this.$widget.modal('hide'); this.modal.hide();
toastService.showMessage(t("revisions.revisions_deleted")); toastService.showMessage(t("revisions.revisions_deleted"));
} }
@ -131,7 +130,7 @@ export default class RevisionsDialog extends BasicWidget {
}); });
} }
async showRevisionsEvent({noteId = appContext.tabManager.getActiveContextNoteId()}) { async showRevisionsEvent({ noteId = appContext.tabManager.getActiveContextNoteId() }) {
utils.openDialog(this.$widget); utils.openDialog(this.$widget);
await this.loadRevisions(noteId); await this.loadRevisions(noteId);
@ -191,7 +190,7 @@ export default class RevisionsDialog extends BasicWidget {
if (await dialogService.confirm(text)) { if (await dialogService.confirm(text)) {
await server.post(`revisions/${revisionItem.revisionId}/restore`); await server.post(`revisions/${revisionItem.revisionId}/restore`);
this.$widget.modal('hide'); this.modal.hide();
toastService.showMessage(t("revisions.revision_restored")); toastService.showMessage(t("revisions.revision_restored"));
} }
@ -241,7 +240,7 @@ export default class RevisionsDialog extends BasicWidget {
if (this.$content.find('span.math-tex').length > 0) { if (this.$content.find('span.math-tex').length > 0) {
await libraryLoader.requireLibrary(libraryLoader.KATEX); await libraryLoader.requireLibrary(libraryLoader.KATEX);
renderMathInElement(this.$content[0], {trust: true}); renderMathInElement(this.$content[0], { trust: true });
} }
} else if (revisionItem.type === 'code') { } else if (revisionItem.type === 'code') {
this.$content.html($("<pre>").text(fullRevision.content)); this.$content.html($("<pre>").text(fullRevision.content));
@ -274,7 +273,7 @@ export default class RevisionsDialog extends BasicWidget {
} }
this.$content.html($table); this.$content.html($table);
} else if ([ "canvas", "mindMap" ].includes(revisionItem.type)) { } else if (["canvas", "mindMap"].includes(revisionItem.type)) {
const encodedTitle = encodeURIComponent(revisionItem.title); const encodedTitle = encodeURIComponent(revisionItem.title);
this.$content.html($("<img>") this.$content.html($("<img>")

View File

@ -7,61 +7,45 @@ const TPL = `<div class="sort-child-notes-dialog modal mx-auto" tabindex="-1" ro
<div class="modal-dialog modal-lg" style="max-width: 500px" role="document"> <div class="modal-dialog modal-lg" style="max-width: 500px" role="document">
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title mr-auto">${t("sort_child_notes.sort_children_by")}</h5> <h5 class="modal-title">${t("sort_child_notes.sort_children_by")}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close" style="margin-left: 0 !important;"> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<form class="sort-child-notes-form"> <form class="sort-child-notes-form">
<div class="modal-body"> <div class="modal-body">
<h5>${t("sort_child_notes.sorting_criteria")}</h5> <h5>${t("sort_child_notes.sorting_criteria")}</h5>
<div class="form-check"> <div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="sort-by" value="title" checked> <input class="form-check-input" type="radio" name="sort-by" value="title" checked>
${t("sort_child_notes.title")} <label class="form-check-label">${t("sort_child_notes.title")}</label>
</label>
</div> </div>
<div class="form-check"> <div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="sort-by" value="dateCreated"> <input class="form-check-input" type="radio" name="sort-by" value="dateCreated">
${t("sort_child_notes.date_created")} <label class="form-check-label">${t("sort_child_notes.date_created")}</label>
</label>
</div> </div>
<div class="form-check"> <div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="sort-by" value="dateModified"> <input class="form-check-input" type="radio" name="sort-by" value="dateModified">
${t("sort_child_notes.date_modified")} <label class="form-check-label">${t("sort_child_notes.date_modified")}</label>
</label>
</div> </div>
<br/> <br/>
<h5>${t("sort_child_notes.sorting_direction")}</h5> <h5>${t("sort_child_notes.sorting_direction")}</h5>
<div class="form-check"> <div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="sort-direction" value="asc" checked> <input class="form-check-input" type="radio" name="sort-direction" value="asc" checked>
${t("sort_child_notes.ascending")} <label class="form-check-label">${t("sort_child_notes.ascending")}</label>
</label>
</div> </div>
<div class="form-check"> <div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="radio" name="sort-direction" value="desc"> <input class="form-check-input" type="radio" name="sort-direction" value="desc">
${t("sort_child_notes.descending")} <label class="form-check-label">${t("sort_child_notes.descending")}</label>
</label>
</div> </div>
<br /> <br />
<h5>${t("sort_child_notes.folders")}</h5> <h5>${t("sort_child_notes.folders")}</h5>
<div class="form-check"> <div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="sort-folders-first" value="1"> <input class="form-check-input" type="checkbox" name="sort-folders-first" value="1">
${t("sort_child_notes.sort_folders_at_top")} <label class="form-check-label">${t("sort_child_notes.sort_folders_at_top")}</label>
</label>
</div> </div>
<br /> <br />
<h5>${t("sort_child_notes.natural_sort")}</h5> <h5>${t("sort_child_notes.natural_sort")}</h5>
<div class="form-check"> <div class="form-check">
<label class="form-check-label">
<input class="form-check-input" type="checkbox" name="sort-natural" value="1"> <input class="form-check-input" type="checkbox" name="sort-natural" value="1">
${t("sort_child_notes.sort_with_respect_to_different_character_sorting")} <label class="form-check-label">${t("sort_child_notes.sort_with_respect_to_different_character_sorting")}</label>
</label>
</div> </div>
<br /> <br />
<div class="form-check"> <div class="form-check">

View File

@ -11,9 +11,7 @@ const TPL = `
<div class="modal-content"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<h5 class="modal-title">${t("upload_attachments.upload_attachments_to_note")}</h5> <h5 class="modal-title">${t("upload_attachments.upload_attachments_to_note")}</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close"> <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
<span aria-hidden="true">&times;</span>
</button>
</div> </div>
<form class="upload-attachment-form"> <form class="upload-attachment-form">
<div class="modal-body"> <div class="modal-body">
@ -26,8 +24,8 @@ const TPL = `
<div class="form-group"> <div class="form-group">
<strong>${t("upload_attachments.options")}:</strong> <strong>${t("upload_attachments.options")}:</strong>
<div class="checkbox"> <div class="checkbox">
<label data-toggle="tooltip" title="${t("upload_attachments.tooltip")}"> <label data-bs-toggle="tooltip" title="${t("upload_attachments.tooltip")}">
<input class="shrink-images-checkbox" value="1" type="checkbox" checked> <span>${t("upload_attachments.shrink_images")}</span> <input class="shrink-images-checkbox form-check-input" value="1" type="checkbox" checked> <span>${t("upload_attachments.shrink_images")}</span>
</label> </label>
</div> </div>
</div> </div>
@ -49,6 +47,8 @@ export default class UploadAttachmentsDialog extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.modal = bootstrap.Modal.getOrCreateInstance(this.$widget);
this.$form = this.$widget.find(".upload-attachment-form"); this.$form = this.$widget.find(".upload-attachment-form");
this.$noteTitle = this.$widget.find(".upload-attachment-note-title"); this.$noteTitle = this.$widget.find(".upload-attachment-note-title");
this.$fileUploadInput = this.$widget.find(".upload-attachment-file-upload-input"); this.$fileUploadInput = this.$widget.find(".upload-attachment-file-upload-input");
@ -71,12 +71,12 @@ export default class UploadAttachmentsDialog extends BasicWidget {
} }
}); });
this.$widget.find('[data-toggle="tooltip"]').tooltip({ bootstrap.Tooltip.getOrCreateInstance(this.$widget.find('[data-bs-toggle="tooltip"]'), {
html: true html: true
}); });
} }
async showUploadAttachmentsDialogEvent({noteId}) { async showUploadAttachmentsDialogEvent({ noteId }) {
this.parentNoteId = noteId; this.parentNoteId = noteId;
this.$fileUploadInput.val('').trigger('change'); // to trigger upload button disabling listener below this.$fileUploadInput.val('').trigger('change'); // to trigger upload button disabling listener below
@ -96,7 +96,7 @@ export default class UploadAttachmentsDialog extends BasicWidget {
shrinkImages: boolToString(this.$shrinkImagesCheckbox), shrinkImages: boolToString(this.$shrinkImagesCheckbox),
}; };
this.$widget.modal('hide'); this.modal.hide();
await importService.uploadFiles('attachments', parentNoteId, files, options); await importService.uploadFiles('attachments', parentNoteId, files, options);
} }

View File

@ -15,7 +15,7 @@ const TPL = `
white-space: normal; white-space: normal;
} }
</style> </style>
<button type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm dropdown-toggle editability-button"> <button type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm dropdown-toggle editability-button">
<span class="editability-active-desc">${t("editability_select.auto")}</span> <span class="editability-active-desc">${t("editability_select.auto")}</span>
<span class="caret"></span> <span class="caret"></span>
</button> </button>
@ -43,11 +43,13 @@ export default class EditabilitySelectWidget extends NoteContextAwareWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
this.$editabilityActiveDesc = this.$widget.find(".editability-active-desc"); this.$editabilityActiveDesc = this.$widget.find(".editability-active-desc");
this.$widget.on('click', '.dropdown-item', this.$widget.on('click', '.dropdown-item',
async e => { async e => {
this.$widget.find('.dropdown-toggle').dropdown('toggle'); this.dropdown.toggle();
const editability = $(e.target).closest("[data-editability]").attr("data-editability"); const editability = $(e.target).closest("[data-editability]").attr("data-editability");
@ -85,7 +87,7 @@ export default class EditabilitySelectWidget extends NoteContextAwareWidget {
this.$editabilityActiveDesc.text(labels[editability]); this.$editabilityActiveDesc.text(labels[editability]);
} }
entitiesReloadedEvent({loadResults}) { entitiesReloadedEvent({ loadResults }) {
if (loadResults.getAttributeRows().find(attr => attr.noteId === this.noteId)) { if (loadResults.getAttributeRows().find(attr => attr.noteId === this.noteId)) {
this.refresh(); this.refresh();
} }

View File

@ -47,24 +47,18 @@ const TPL = `
<div class="find-widget-box"> <div class="find-widget-box">
<div class="input-group find-widget-search-term-input-group"> <div class="input-group find-widget-search-term-input-group">
<input type="text" class="form-control find-widget-search-term-input"> <input type="text" class="form-control find-widget-search-term-input">
<div class="input-group-append">
<button class="btn btn-outline-secondary bx bxs-chevron-up find-widget-previous-button" type="button"></button> <button class="btn btn-outline-secondary bx bxs-chevron-up find-widget-previous-button" type="button"></button>
<button class="btn btn-outline-secondary bx bxs-chevron-down find-widget-next-button" type="button"></button> <button class="btn btn-outline-secondary bx bxs-chevron-down find-widget-next-button" type="button"></button>
</div> </div>
</div>
<div class="form-check"> <div class="form-check">
<label tabIndex="-1" class="form-check-label">
<input type="checkbox" class="form-check-input find-widget-case-sensitive-checkbox"> <input type="checkbox" class="form-check-input find-widget-case-sensitive-checkbox">
case sensitive <label tabIndex="-1" class="form-check-label">case sensitive</label>
</label>
</div> </div>
<div class="form-check"> <div class="form-check">
<label tabIndex="-1" class="form-check-label">
<input type="checkbox" class="form-check-input find-widget-match-words-checkbox"> <input type="checkbox" class="form-check-input find-widget-match-words-checkbox">
match words <label tabIndex="-1" class="form-check-label">match words</label>
</label>
</div> </div>
<div class="find-widget-found-wrapper"> <div class="find-widget-found-wrapper">

View File

@ -28,7 +28,6 @@ const TPL = `<div class="highlights-list-widget">
cursor: pointer; cursor: pointer;
margin-bottom: 3px; margin-bottom: 3px;
text-align: justify; text-align: justify;
text-justify: distribute;
word-wrap: break-word; word-wrap: break-word;
hyphens: auto; hyphens: auto;
} }

View File

@ -1,3 +1,4 @@
import { t } from "../services/i18n.js";
import NoteContextAwareWidget from "./note_context_aware_widget.js"; import NoteContextAwareWidget from "./note_context_aware_widget.js";
import attributeService from "../services/attributes.js"; import attributeService from "../services/attributes.js";
import server from "../services/server.js"; import server from "../services/server.js";
@ -66,7 +67,7 @@ const TPL = `
} }
</style> </style>
<button class="btn dropdown-toggle note-icon" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="Change note icon"></button> <button class="btn dropdown-toggle note-icon" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" title="${t("note_icon.change_note_icon")}"></button>
<div class="dropdown-menu" aria-labelledby="note-path-list-button" style="width: 610px;"> <div class="dropdown-menu" aria-labelledby="note-path-list-button" style="width: 610px;">
<div class="filter-row"> <div class="filter-row">
<span>Category:</span> <select name="icon-category" class="form-control"></select> <span>Category:</span> <select name="icon-category" class="form-control"></select>

View File

@ -35,7 +35,7 @@ const TPL = `
overflow-x: hidden; overflow-x: hidden;
} }
</style> </style>
<button type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm dropdown-toggle note-type-button"> <button type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false" class="btn btn-sm dropdown-toggle note-type-button">
<span class="note-type-desc"></span> <span class="note-type-desc"></span>
<span class="caret"></span> <span class="caret"></span>
</button> </button>
@ -47,14 +47,15 @@ export default class NoteTypeWidget extends NoteContextAwareWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
this.$widget.on('show.bs.dropdown', () => this.renderDropdown()); this.$widget.on('show.bs.dropdown', () => this.renderDropdown());
this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown"); this.$noteTypeDropdown = this.$widget.find(".note-type-dropdown");
this.$noteTypeButton = this.$widget.find(".note-type-button"); this.$noteTypeButton = this.$widget.find(".note-type-button");
this.$noteTypeDesc = this.$widget.find(".note-type-desc"); this.$noteTypeDesc = this.$widget.find(".note-type-desc");
this.$widget.on('click', '.dropdown-item', this.$widget.on('click', '.dropdown-item', () => this.dropdown.toggle());
() => this.$widget.find('.dropdown-toggle').dropdown('toggle'));
} }
async refreshWithNote(note) { async refreshWithNote(note) {
@ -63,7 +64,7 @@ export default class NoteTypeWidget extends NoteContextAwareWidget {
this.$noteTypeDesc.text(await this.findTypeTitle(note.type, note.mime)); this.$noteTypeDesc.text(await this.findTypeTitle(note.type, note.mime));
this.$noteTypeButton.dropdown('hide'); this.dropdown.hide();
} }
/** the actual body is rendered lazily on note-type button click */ /** the actual body is rendered lazily on note-type button click */
@ -161,7 +162,7 @@ export default class NoteTypeWidget extends NoteContextAwareWidget {
return await dialogService.confirm("It is not recommended to change note type when note content is not empty. Do you want to continue anyway?"); return await dialogService.confirm("It is not recommended to change note type when note content is not empty. Do you want to continue anyway?");
} }
async entitiesReloadedEvent({loadResults}) { async entitiesReloadedEvent({ loadResults }) {
if (loadResults.isNoteReloaded(this.noteId)) { if (loadResults.isNoteReloaded(this.noteId)) {
this.refresh(); this.refresh();
} }

View File

@ -30,13 +30,12 @@ const TPL = `
</style> </style>
<div class="input-group-prepend"> <div class="input-group-prepend">
<button class="btn btn-outline-secondary search-button" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <button class="btn btn-outline-secondary search-button" type="button" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="bx bx-search"></span> <span class="bx bx-search"></span>
</button> </button>
<div class="dropdown-menu dropdown-menu-left"></div> <div class="dropdown-menu dropdown-menu-left"></div>
</div> </div>
<input type="text" class="form-control form-control-sm search-string" placeholder="Quick search"> <input type="text" class="form-control form-control-sm search-string" placeholder="Quick search">
</div>
</div>`; </div>`;
const MAX_DISPLAYED_NOTES = 15; const MAX_DISPLAYED_NOTES = 15;
@ -44,21 +43,20 @@ const MAX_DISPLAYED_NOTES = 15;
export default class QuickSearchWidget extends BasicWidget { export default class QuickSearchWidget extends BasicWidget {
doRender() { doRender() {
this.$widget = $(TPL); this.$widget = $(TPL);
this.dropdown = bootstrap.Dropdown.getOrCreateInstance(this.$widget.find("[data-bs-toggle='dropdown']"));
this.$searchString = this.$widget.find('.search-string'); this.$searchString = this.$widget.find('.search-string');
this.$dropdownMenu = this.$widget.find('.dropdown-menu'); this.$dropdownMenu = this.$widget.find('.dropdown-menu');
this.$dropdownToggle = this.$widget.find('.search-button');
this.$dropdownToggle.dropdown();
this.$widget.find('.input-group-prepend').on('shown.bs.dropdown', () => this.search()); this.$widget.find('.input-group-prepend').on('shown.bs.dropdown', () => this.search());
if(utils.isMobile()) { if (utils.isMobile()) {
this.$searchString.keydown(e =>{ this.$searchString.keydown(e => {
if(e.which === 13) { if (e.which === 13) {
if (this.$dropdownMenu.is(":visible")) { if (this.$dropdownMenu.is(":visible")) {
this.search(); // just update already visible dropdown this.search(); // just update already visible dropdown
} else { } else {
this.$dropdownToggle.dropdown('show'); this.dropdown.show();
} }
e.preventDefault(); e.preventDefault();
e.stopPropagation(); e.stopPropagation();
@ -70,7 +68,7 @@ export default class QuickSearchWidget extends BasicWidget {
if (this.$dropdownMenu.is(":visible")) { if (this.$dropdownMenu.is(":visible")) {
this.search(); // just update already visible dropdown this.search(); // just update already visible dropdown
} else { } else {
this.$dropdownToggle.dropdown('show'); this.dropdown.show();
} }
this.$searchString.focus(); this.$searchString.focus();
@ -81,7 +79,7 @@ export default class QuickSearchWidget extends BasicWidget {
}); });
shortcutService.bindElShortcut(this.$searchString, 'esc', () => { shortcutService.bindElShortcut(this.$searchString, 'esc', () => {
this.$dropdownToggle.dropdown('hide'); this.dropdown.hide();
}); });
return this.$widget; return this.$widget;
@ -91,25 +89,25 @@ export default class QuickSearchWidget extends BasicWidget {
const searchString = this.$searchString.val().trim(); const searchString = this.$searchString.val().trim();
if (!searchString) { if (!searchString) {
this.$dropdownToggle.dropdown("hide"); this.dropdown.hide();
return; return;
} }
this.$dropdownMenu.empty(); this.$dropdownMenu.empty();
this.$dropdownMenu.append('<span class="dropdown-item disabled"><span class="bx bx-loader bx-spin"></span> Searching ...</span>'); this.$dropdownMenu.append('<span class="dropdown-item disabled"><span class="bx bx-loader bx-spin"></span> Searching ...</span>');
const {searchResultNoteIds, error} = await server.get(`quick-search/${encodeURIComponent(searchString)}`); const { searchResultNoteIds, error } = await server.get(`quick-search/${encodeURIComponent(searchString)}`);
if (error) { if (error) {
this.$searchString.tooltip({ let tooltip = new bootstrap.Tooltip(this.$searchString, {
trigger: 'manual', trigger: 'manual',
title: `Search error: ${error}`, title: `Search error: ${error}`,
placement: 'right' placement: 'right'
}); });
this.$searchString.tooltip("show"); tooltip.show();
setTimeout(() => this.$searchString.tooltip("dispose"), 4000); setTimeout(() => tooltip.dispose(), 4000);
} }
const displayedNoteIds = searchResultNoteIds.slice(0, Math.min(MAX_DISPLAYED_NOTES, searchResultNoteIds.length)); const displayedNoteIds = searchResultNoteIds.slice(0, Math.min(MAX_DISPLAYED_NOTES, searchResultNoteIds.length));
@ -121,11 +119,11 @@ export default class QuickSearchWidget extends BasicWidget {
} }
for (const note of await froca.getNotes(displayedNoteIds)) { for (const note of await froca.getNotes(displayedNoteIds)) {
const $link = await linkService.createLink(note.noteId, {showNotePath: true}); const $link = await linkService.createLink(note.noteId, { showNotePath: true });
$link.addClass('dropdown-item'); $link.addClass('dropdown-item');
$link.attr("tabIndex", "0"); $link.attr("tabIndex", "0");
$link.on('click', e => { $link.on('click', e => {
this.$dropdownToggle.dropdown("hide"); this.dropdown.hide();
if (!e.target || e.target.nodeName !== 'A') { if (!e.target || e.target.nodeName !== 'A') {
// click on the link is handled by link handling, but we want the whole item clickable // click on the link is handled by link handling, but we want the whole item clickable
@ -133,7 +131,7 @@ export default class QuickSearchWidget extends BasicWidget {
} }
}); });
shortcutService.bindElShortcut($link, 'return', () => { shortcutService.bindElShortcut($link, 'return', () => {
this.$dropdownToggle.dropdown("hide"); this.dropdown.hide();
appContext.tabManager.getActiveContext().setNote(note.noteId); appContext.tabManager.getActiveContext().setNote(note.noteId);
}); });
@ -156,11 +154,11 @@ export default class QuickSearchWidget extends BasicWidget {
shortcutService.bindElShortcut(this.$dropdownMenu.find('.dropdown-item:first'), 'up', () => this.$searchString.focus()); shortcutService.bindElShortcut(this.$dropdownMenu.find('.dropdown-item:first'), 'up', () => this.$searchString.focus());
this.$dropdownToggle.dropdown('update'); this.dropdown.update();
} }
async showInFullSearch() { async showInFullSearch() {
this.$dropdownToggle.dropdown("hide"); this.dropdown.hide();
await appContext.triggerCommand('searchNotes', { await appContext.triggerCommand('searchNotes', {
searchString: this.$searchString.val() searchString: this.$searchString.val()

View File

@ -18,7 +18,7 @@ const TPL = `
<div style="display: flex; align-items: baseline"> <div style="display: flex; align-items: baseline">
<span style="white-space: nowrap">${t("book_properties.view_type")}:&nbsp; &nbsp;</span> <span style="white-space: nowrap">${t("book_properties.view_type")}:&nbsp; &nbsp;</span>
<select class="view-type-select form-control form-control-sm"> <select class="view-type-select form-select form-select-sm">
<option value="grid">${t("book_properties.grid")}</option> <option value="grid">${t("book_properties.grid")}</option>
<option value="list">${t("book_properties.list")}</option> <option value="list">${t("book_properties.list")}</option>
</select> </select>

View File

@ -71,7 +71,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
const promotedDefAttrs = note.getPromotedDefinitionAttributes(); const promotedDefAttrs = note.getPromotedDefinitionAttributes();
if (promotedDefAttrs.length === 0) { if (promotedDefAttrs.length === 0) {
return {show: false}; return { show: false };
} }
return { return {
@ -167,7 +167,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
return; return;
} }
attributeValues = attributeValues.map(attribute => ({value: attribute})); attributeValues = attributeValues.map(attribute => ({ value: attribute }));
$input.autocomplete({ $input.autocomplete({
appendTo: document.querySelector('body'), appendTo: document.querySelector('body'),
@ -229,9 +229,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
.prop("title", t("promoted_attributes.open_external_link")) .prop("title", t("promoted_attributes.open_external_link"))
.on('click', () => window.open($input.val(), '_blank')); .on('click', () => window.open($input.val(), '_blank'));
$input.after($("<div>") $input.after($openButton);
.addClass("input-group-append")
.append($openButton));
} }
else { else {
ws.logError(t("promoted_attributes.unknown_label_type", { type: definitionAttr.labelType })); ws.logError(t("promoted_attributes.unknown_label_type", { type: definitionAttr.labelType }));
@ -244,7 +242,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
if (utils.isDesktop()) { if (utils.isDesktop()) {
// no need to wait for this // no need to wait for this
noteAutocompleteService.initNoteAutocomplete($input, {allowCreatingNotes: true}); noteAutocompleteService.initNoteAutocomplete($input, { allowCreatingNotes: true });
$input.on('autocomplete:noteselected', (event, suggestion, dataset) => { $input.on('autocomplete:noteselected', (event, suggestion, dataset) => {
this.promotedAttributeChanged(event); this.promotedAttributeChanged(event);
@ -257,7 +255,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
} }
} }
else { else {
ws.logError(t(`promoted_attributes.unknown_attribute_type`, {type: valueAttr.type})); ws.logError(t(`promoted_attributes.unknown_attribute_type`, { type: valueAttr.type }));
return; return;
} }
@ -346,7 +344,7 @@ export default class PromotedAttributesWidget extends NoteContextAwareWidget {
this.$widget.find(".promoted-attribute-input:first").focus(); this.$widget.find(".promoted-attribute-input:first").focus();
} }
entitiesReloadedEvent({loadResults}) { entitiesReloadedEvent({ loadResults }) {
if (loadResults.getAttributeRows(this.componentId).find(attr => attributeService.isAffecting(attr, this.note))) { if (loadResults.getAttributeRows(this.componentId).find(attr => attributeService.isAffecting(attr, this.note))) {
this.refresh(); this.refresh();
} }

View File

@ -119,7 +119,7 @@ const TPL = `
</button> </button>
<div class="dropdown" style="display: inline-block;"> <div class="dropdown" style="display: inline-block;">
<button class="btn btn-sm dropdown-toggle action-add-toggle" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> <button class="btn btn-sm dropdown-toggle action-add-toggle" type="button" id="dropdownMenuButton" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
<span class="bx bxs-zap"></span> <span class="bx bxs-zap"></span>
${t('search_definition.action')} ${t('search_definition.action')}
</button> </button>
@ -219,7 +219,7 @@ export default class SearchDefinitionWidget extends NoteContextAwareWidget {
}); });
this.$widget.on('click', '[data-action-add]', async event => { this.$widget.on('click', '[data-action-add]', async event => {
this.$widget.find('.action-add-toggle').dropdown('toggle'); bootstrap.Dropdown.getOrCreateInstance(this.$widget.find('.action-add-toggle'));
const actionName = $(event.target).attr('data-action-add'); const actionName = $(event.target).attr('data-action-add');

View File

@ -13,7 +13,7 @@ const TPL = `
<div style="margin-left: 10px; margin-right: 10px">${t('ancestor.depth_label')}:</div> <div style="margin-left: 10px; margin-right: 10px">${t('ancestor.depth_label')}:</div>
<select name="depth" class="form-control d-inline ancestor-depth" style="flex-shrink: 3"> <select name="depth" class="form-select d-inline ancestor-depth" style="flex-shrink: 3">
<option value="">${t('ancestor.depth_doesnt_matter')}</option> <option value="">${t('ancestor.depth_doesnt_matter')}</option>
<option value="eq1">${t('ancestor.depth_eq', {count: 1})} (${t('ancestor.direct_children')})</option> <option value="eq1">${t('ancestor.depth_eq', {count: 1})} (${t('ancestor.direct_children')})</option>
<option value="eq2">${t('ancestor.depth_eq', {count: 2})}</option> <option value="eq2">${t('ancestor.depth_eq', {count: 2})}</option>

View File

@ -9,10 +9,10 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
<p>${t("debug.debug_info")}</p> <p>${t("debug.debug_info")}</p>
<p>${t("debug.access_info")}</p> ${t("debug.access_info")}
</div> </div>
</div> </div>
<span class="bx bx-x icon-action search-option-del"></span> <span class="bx bx-x icon-action search-option-del"></span>

View File

@ -9,7 +9,7 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
${t('fast_search.description')} ${t('fast_search.description')}
</div> </div>

View File

@ -12,7 +12,7 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
${t('limit.take_first_x_results')} ${t('limit.take_first_x_results')}
</div> </div>

View File

@ -14,7 +14,7 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
<p>${t('search_script.description1')}</p> <p>${t('search_script.description1')}</p>
@ -24,7 +24,7 @@ const TPL = `
<pre>${t('search_script.example_code')}</pre> <pre>${t('search_script.example_code')}</pre>
<p>${t('search_script.note')}</p> ${t('search_script.note')}
</div> </div>
</div> </div>

View File

@ -13,11 +13,11 @@ const TPL = `
</td> </td>
<td class="button-column"> <td class="button-column">
<div class="dropdown help-dropdown"> <div class="dropdown help-dropdown">
<span class="bx bx-help-circle icon-action" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span> <span class="bx bx-help-circle icon-action" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false"></span>
<div class="dropdown-menu dropdown-menu-right p-4"> <div class="dropdown-menu dropdown-menu-right p-4">
<strong>${t('search_string.search_syntax')}</strong> - ${t('search_string.also_see')} <button class="btn btn-sm" type="button" data-help-page="search.html">${t('search_string.complete_help')}</button> <strong>${t('search_string.search_syntax')}</strong> - ${t('search_string.also_see')} <a href="#" data-help-page="search.html">${t('search_string.complete_help')}</a>
<p>
<ul> <ul style="marigin-bottom: 0;">
<li>${t('search_string.full_text_search')}</li> <li>${t('search_string.full_text_search')}</li>
<li><code>#abc</code> - ${t('search_string.label_abc')}</li> <li><code>#abc</code> - ${t('search_string.label_abc')}</li>
<li><code>#year = 2019</code> - ${t('search_string.label_year')}</li> <li><code>#year = 2019</code> - ${t('search_string.label_year')}</li>
@ -26,7 +26,6 @@ const TPL = `
<li><code>#year &lt;= 2000</code> - ${t('search_string.label_year_comparison')}</li> <li><code>#year &lt;= 2000</code> - ${t('search_string.label_year_comparison')}</li>
<li><code>note.dateCreated >= MONTH-1</code> - ${t('search_string.label_date_created')}</li> <li><code>note.dateCreated >= MONTH-1</code> - ${t('search_string.label_date_created')}</li>
</ul> </ul>
</p>
</div> </div>
</div> </div>
@ -74,16 +73,16 @@ export default class SearchString extends AbstractSearchOption {
return $option; return $option;
} }
showSearchErrorEvent({error}) { showSearchErrorEvent({ error }) {
this.$searchString.tooltip({ let tooltip = new bootstrap.Tooltip(this.$searchString, {
trigger: 'manual', trigger: 'manual',
title: `${t('search_string.error', {error})}`, title: `${t('search_string.error', { error })}`,
placement: 'bottom' placement: 'bottom'
}); });
this.$searchString.tooltip("show"); tooltip.show();
setTimeout(() => this.$searchString.tooltip("dispose"), 4000); setTimeout(() => tooltip.dispose(), 4000);
} }
focusOnSearchDefinitionEvent() { focusOnSearchDefinitionEvent() {

View File

@ -1,3 +1,4 @@
import { t } from "../services/i18n.js";
import BasicWidget from "./basic_widget.js"; import BasicWidget from "./basic_widget.js";
import ws from "../services/ws.js"; import ws from "../services/ws.js";
import options from "../services/options.js"; import options from "../services/options.js";
@ -39,36 +40,30 @@ const TPL = `
<div class="sync-status"> <div class="sync-status">
<span class="sync-status-icon sync-status-unknown bx bx-time" <span class="sync-status-icon sync-status-unknown bx bx-time"
data-toggle="tooltip" data-bs-toggle="tooltip"
data-placement="right" title="${t("sync_status.unknown")}">
title="<p>Sync status will be known once the next sync attempt starts.</p><p>Click to trigger sync now.</p>">
</span> </span>
<span class="sync-status-icon sync-status-connected-with-changes bx bx-wifi" <span class="sync-status-icon sync-status-connected-with-changes bx bx-wifi"
data-toggle="tooltip" data-bs-toggle="tooltip"
data-placement="right" title="${t("sync_status.connected_with_changes")}">
title="<p>Connected to the sync server. <br>There are some outstanding changes yet to be synced.</p><p>Click to trigger sync.</p>">
<span class="bx bxs-star sync-status-sub-icon"></span> <span class="bx bxs-star sync-status-sub-icon"></span>
</span> </span>
<span class="sync-status-icon sync-status-connected-no-changes bx bx-wifi" <span class="sync-status-icon sync-status-connected-no-changes bx bx-wifi"
data-toggle="tooltip" data-bs-toggle="tooltip"
data-placement="right" title="${t("sync_status.connected_no_changes")}">
title="<p>Connected to the sync server.<br>All changes have been already synced.</p><p>Click to trigger sync.</p>">
</span> </span>
<span class="sync-status-icon sync-status-disconnected-with-changes bx bx-wifi-off" <span class="sync-status-icon sync-status-disconnected-with-changes bx bx-wifi-off"
data-toggle="tooltip" data-bs-toggle="tooltip"
data-placement="right" title="${t("sync_status.disconnected_with_changes")}">
title="<p>Establishing the connection to the sync server was unsuccessful.<br>There are some outstanding changes yet to be synced.</p><p>Click to trigger sync.</p>">
<span class="bx bxs-star sync-status-sub-icon"></span> <span class="bx bxs-star sync-status-sub-icon"></span>
</span> </span>
<span class="sync-status-icon sync-status-disconnected-no-changes bx bx-wifi-off" <span class="sync-status-icon sync-status-disconnected-no-changes bx bx-wifi-off"
data-toggle="tooltip" data-bs-toggle="tooltip"
data-placement="right" title="${t("sync_status.disconnected_no_changes")}">
title="<p>Establishing the connection to the sync server was unsuccessful.<br>All known changes have been synced.</p><p>Click to trigger sync.</p>">
</span> </span>
<span class="sync-status-icon sync-status-in-progress bx bx-analyse bx-spin" <span class="sync-status-icon sync-status-in-progress bx bx-analyse bx-spin"
data-toggle="tooltip" data-bs-toggle="tooltip"
data-placement="right" title="${t("sync_status.in_progress")}">
title="Sync with the server is in progress.">
</span> </span>
</div> </div>
</div> </div>
@ -86,10 +81,6 @@ export default class SyncStatusWidget extends BasicWidget {
this.$widget = $(TPL); this.$widget = $(TPL);
this.$widget.hide(); this.$widget.hide();
this.$widget.find('[data-toggle="tooltip"]').tooltip({
html: true
});
this.$widget.find('.sync-status-icon:not(.sync-status-in-progress)') this.$widget.find('.sync-status-icon:not(.sync-status-in-progress)')
.on('click', () => syncService.syncNow()); .on('click', () => syncService.syncNow());
@ -102,6 +93,11 @@ export default class SyncStatusWidget extends BasicWidget {
return; return;
} }
bootstrap.Tooltip.getOrCreateInstance(this.$widget.find(`.sync-status-${className}`), {
html: true,
placement: 'right',
});
this.$widget.show(); this.$widget.show();
this.$widget.find('.sync-status-icon').hide(); this.$widget.find('.sync-status-icon').hide();
this.$widget.find(`.sync-status-${className}`).show(); this.$widget.find(`.sync-status-${className}`).show();

View File

@ -40,7 +40,6 @@ const TPL = `<div class="toc-widget">
.toc li { .toc li {
cursor: pointer; cursor: pointer;
text-align: justify; text-align: justify;
text-justify: distribute;
word-wrap: break-word; word-wrap: break-word;
hyphens: auto; hyphens: auto;
} }

View File

@ -37,7 +37,7 @@ const TPL = `
<div class="form-group row"> <div class="form-group row">
<div class="col-6"> <div class="col-6">
<label>${t("fonts.font_family")}</label> <label>${t("fonts.font_family")}</label>
<select class="main-font-family form-control"></select> <select class="main-font-family form-select"></select>
</div> </div>
<div class="col-6"> <div class="col-6">
@ -45,19 +45,17 @@ const TPL = `
<div class="input-group"> <div class="input-group">
<input type="number" class="main-font-size form-control options-number-input" min="50" max="200" step="10"/> <input type="number" class="main-font-size form-control options-number-input" min="50" max="200" step="10"/>
<div class="input-group-append">
<span class="input-group-text">%</span> <span class="input-group-text">%</span>
</div> </div>
</div> </div>
</div> </div>
</div>
<h5>${t("fonts.note_tree_font")}</h5> <h5>${t("fonts.note_tree_font")}</h5>
<div class="form-group row"> <div class="form-group row">
<div class="col-4"> <div class="col-4">
<label>${t("fonts.font_family")}</label> <label>${t("fonts.font_family")}</label>
<select class="tree-font-family form-control"></select> <select class="tree-font-family form-select"></select>
</div> </div>
<div class="col-6"> <div class="col-6">
@ -65,19 +63,17 @@ const TPL = `
<div class="input-group"> <div class="input-group">
<input type="number" class="tree-font-size form-control options-number-input" min="50" max="200" step="10"/> <input type="number" class="tree-font-size form-control options-number-input" min="50" max="200" step="10"/>
<div class="input-group-append">
<span class="input-group-text">%</span> <span class="input-group-text">%</span>
</div> </div>
</div> </div>
</div> </div>
</div>
<h5>${t("fonts.note_detail_font")}</h5> <h5>${t("fonts.note_detail_font")}</h5>
<div class="form-group row"> <div class="form-group row">
<div class="col-4"> <div class="col-4">
<label>${t("fonts.font_family")}</label> <label>${t("fonts.font_family")}</label>
<select class="detail-font-family form-control"></select> <select class="detail-font-family form-select"></select>
</div> </div>
<div class="col-6"> <div class="col-6">
@ -85,19 +81,17 @@ const TPL = `
<div class="input-group"> <div class="input-group">
<input type="number" class="detail-font-size form-control options-number-input" min="50" max="200" step="10"/> <input type="number" class="detail-font-size form-control options-number-input" min="50" max="200" step="10"/>
<div class="input-group-append">
<span class="input-group-text">%</span> <span class="input-group-text">%</span>
</div> </div>
</div> </div>
</div> </div>
</div>
<h5>${t("fonts.monospace_font")}</h5> <h5>${t("fonts.monospace_font")}</h5>
<div class="form-group row"> <div class="form-group row">
<div class="col-4"> <div class="col-4">
<label>${t("fonts.font_family")}</label> <label>${t("fonts.font_family")}</label>
<select class="monospace-font-family form-control"></select> <select class="monospace-font-family form-select"></select>
</div> </div>
<div class="col-6"> <div class="col-6">
@ -105,12 +99,10 @@ const TPL = `
<div class="input-group"> <div class="input-group">
<input type="number" class="monospace-font-size form-control options-number-input" min="50" max="200" step="10"/> <input type="number" class="monospace-font-size form-control options-number-input" min="50" max="200" step="10"/>
<div class="input-group-append">
<span class="input-group-text">%</span> <span class="input-group-text">%</span>
</div> </div>
</div> </div>
</div> </div>
</div>
<p>${t("fonts.note_tree_and_detail_font_sizing")}</p> <p>${t("fonts.note_tree_and_detail_font_sizing")}</p>

View File

@ -10,12 +10,12 @@ const TPL = `
<div class="form-group row"> <div class="form-group row">
<div class="col-6"> <div class="col-6">
<label>${t("i18n.language")}</label> <label>${t("i18n.language")}</label>
<select class="locale-select form-control"></select> <select class="locale-select form-select"></select>
</div> </div>
<div class="col-6"> <div class="col-6">
<label>${t("i18n.first-day-of-the-week")}</label> <label>${t("i18n.first-day-of-the-week")}</label>
<select class="first-day-of-week-select form-control"> <select class="first-day-of-week-select form-select">
<option value="0">${t("i18n.sunday")}</option> <option value="0">${t("i18n.sunday")}</option>
<option value="1">${t("i18n.monday")}</option> <option value="1">${t("i18n.monday")}</option>
</select> </select>

View File

@ -5,12 +5,12 @@ const TPL = `
<div class="options-section"> <div class="options-section">
<h4>${t('ribbon.widgets')}</h4> <h4>${t('ribbon.widgets')}</h4>
<label> <label>
<input type="checkbox" class="promoted-attributes-open-in-ribbon"> <input type="checkbox" class="promoted-attributes-open-in-ribbon form-check-input">
${t('ribbon.promoted_attributes_message')} ${t('ribbon.promoted_attributes_message')}
</label> </label>
<label> <label>
<input type="checkbox" class="edited-notes-open-in-ribbon"> <input type="checkbox" class="edited-notes-open-in-ribbon form-check-input">
${t('ribbon.edited_notes_message')} ${t('ribbon.edited_notes_message')}
</label> </label>
</div>`; </div>`;

View File

@ -10,12 +10,14 @@ const TPL = `
<div class="form-group row"> <div class="form-group row">
<div class="col-6"> <div class="col-6">
<label>${t("theme.theme_label")}</label> <label>${t("theme.theme_label")}</label>
<select class="theme-select form-control"></select> <select class="theme-select form-select"></select>
</div> </div>
<div class="col-6"> <div class="col-6">
<label>${t("theme.override_theme_fonts_label")}</label> <label>${t("theme.override_theme_fonts_label")}</label>
<input type="checkbox" class="override-theme-fonts form-control"> <div class="form-check">
<input type="checkbox" class="override-theme-fonts form-check-input">
</div>
</div> </div>
</div> </div>
</div>`; </div>`;

View File

@ -12,19 +12,19 @@ const TPL = `
<ul style="list-style: none"> <ul style="list-style: none">
<li> <li>
<label> <label>
<input type="checkbox" class="daily-backup-enabled"> <input type="checkbox" class="daily-backup-enabled form-check-input">
${t('backup.enable_daily_backup')} ${t('backup.enable_daily_backup')}
</label> </label>
</li> </li>
<li> <li>
<label> <label>
<input type="checkbox" class="weekly-backup-enabled"> <input type="checkbox" class="weekly-backup-enabled form-check-input">
${t('backup.enable_weekly_backup')} ${t('backup.enable_weekly_backup')}
</label> </label>
</li> </li>
<li> <li>
<label> <label>
<input type="checkbox" class="monthly-backup-enabled"> <input type="checkbox" class="monthly-backup-enabled form-check-input">
${t('backup.enable_monthly_backup')} ${t('backup.enable_monthly_backup')}
</label> </label>
</li> </li>

View File

@ -24,7 +24,7 @@ export default class CodeMimeTypesOptions extends OptionsWidget {
const id = "code-mime-type-" + (idCtr++); const id = "code-mime-type-" + (idCtr++);
this.$mimeTypes.append($("<li>") this.$mimeTypes.append($("<li>")
.append($('<input type="checkbox">') .append($('<input type="checkbox" class="form-check-input">')
.attr("id", id) .attr("id", id)
.attr("data-mime-type", mimeType.mime) .attr("data-mime-type", mimeType.mime)
.prop("checked", mimeType.enabled)) .prop("checked", mimeType.enabled))

View File

@ -5,7 +5,7 @@ const TPL = `
<div class="options-section"> <div class="options-section">
<h4>${t('vim_key_bindings.use_vim_keybindings_in_code_notes')}</h4> <h4>${t('vim_key_bindings.use_vim_keybindings_in_code_notes')}</h4>
<label> <label>
<input type="checkbox" class="vim-keymap-enabled"> <input type="checkbox" class="vim-keymap-enabled form-check-input">
${t('vim_key_bindings.enable_vim_keybindings')} ${t('vim_key_bindings.enable_vim_keybindings')}
</label> </label>
</div>`; </div>`;

View File

@ -5,7 +5,7 @@ const TPL = `
<div class="options-section"> <div class="options-section">
<h4>${t("wrap_lines.wrap_lines_in_code_notes")}</h4> <h4>${t("wrap_lines.wrap_lines_in_code_notes")}</h4>
<label> <label>
<input type="checkbox" class="line-wrap-enabled"> <input type="checkbox" class="line-wrap-enabled form-check-input">
${t("wrap_lines.enable_line_wrap")} ${t("wrap_lines.enable_line_wrap")}
</label> </label>
</div>`; </div>`;

View File

@ -6,7 +6,7 @@ const TPL = `
<h4>${t("network_connections.network_connections_title")}</h4> <h4>${t("network_connections.network_connections_title")}</h4>
<label> <label>
<input class="check-for-updates" type="checkbox" name="check-for-updates"> <input class="check-for-updates form-check-input" type="checkbox" name="check-for-updates">
${t("network_connections.check_for_updates")} ${t("network_connections.check_for_updates")}
</label> </label>
</div>`; </div>`;

View File

@ -5,7 +5,7 @@ const TPL = `
<div class="options-section"> <div class="options-section">
<h4>${t("heading_style.title")}</h4> <h4>${t("heading_style.title")}</h4>
<select class="heading-style form-control"> <select class="heading-style form-select">
<option value="plain">${t("heading_style.plain")}</option> <option value="plain">${t("heading_style.plain")}</option>
<option value="underline">${t("heading_style.underline")}</option> <option value="underline">${t("heading_style.underline")}</option>
<option value="markdown">${t("heading_style.markdown")}</option> <option value="markdown">${t("heading_style.markdown")}</option>

View File

@ -8,11 +8,11 @@ const TPL = `
<p>${t("highlights_list.description")}</p> <p>${t("highlights_list.description")}</p>
</div> </div>
<label><input type="checkbox" class="highlights-list-check" value="bold"> ${t("highlights_list.bold")} &nbsp;</label> <label><input type="checkbox" class="highlights-list-check form-check-input" value="bold"> ${t("highlights_list.bold")} &nbsp;</label>
<label><input type="checkbox" class="highlights-list-check" value="italic"> ${t("highlights_list.italic")} &nbsp;</label> <label><input type="checkbox" class="highlights-list-check form-check-input" value="italic"> ${t("highlights_list.italic")} &nbsp;</label>
<label><input type="checkbox" class="highlights-list-check" value="underline"> ${t("highlights_list.underline")} &nbsp;</label> <label><input type="checkbox" class="highlights-list-check form-check-input" value="underline"> ${t("highlights_list.underline")} &nbsp;</label>
<label><input type="checkbox" class="highlights-list-check" value="color"> ${t("highlights_list.color")} &nbsp;</label> <label><input type="checkbox" class="highlights-list-check form-check-input" value="color"> ${t("highlights_list.color")} &nbsp;</label>
<label><input type="checkbox" class="highlights-list-check" value="bgColor"> ${t("highlights_list.bg_color")} &nbsp;</label> <label><input type="checkbox" class="highlights-list-check form-check-input" value="bgColor"> ${t("highlights_list.bg_color")} &nbsp;</label>
</div> </div>
<br/><br/> <br/><br/>

View File

@ -100,6 +100,10 @@
font-weight: bold; font-weight: bold;
} }
.calendar-dropdown-widget a {
text-decoration: none;
}
.calendar-dropdown-widget .calendar-date-exists { .calendar-dropdown-widget .calendar-date-exists {
text-decoration: underline !important; text-decoration: underline !important;
} }
@ -107,3 +111,4 @@
.calendar-dropdown-widget .calendar-date:not(.calendar-date-active) { .calendar-dropdown-widget .calendar-date:not(.calendar-date-active) {
cursor: pointer; cursor: pointer;
} }

View File

@ -36,22 +36,78 @@ a, a:visited, a:hover {
color: var(--link-color); color: var(--link-color);
} }
input, select, textarea { .note-list-widget a {
color: var(--input-text-color) !important; text-decoration: none;
background: var(--input-background-color) !important;
} }
#left-pane input, select, textarea { .note-list-widget a:hover {
color: var(--left-pane-text-color) !important; text-decoration: underline;
background: var(--left-pane-background-color) !important;
} }
input::placeholder { input,
select,
textarea,
.form-control,
.form-select {
color: var(--input-text-color);
background: var(--input-background-color);
}
.form-control:focus {
color: var(--input-text-color);
background: var(--input-background-color);
}
.form-select {
background: var(--input-background-color) url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='%23ffffff' stroke='%23343a40' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/></svg>") right .75rem center/15px 20px no-repeat;
}
/* Hide number input arrows */
input[type="number"]::-webkit-inner-spin-button,
input[type="number"]::-webkit-outer-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox browser */
input[type="number"] {
-moz-appearance: textfield;
}
/* Show number input arrows when focus or hover */
input[type="number"]:focus::-webkit-inner-spin-button,
input[type="number"]:focus::-webkit-outer-spin-button,
input[type="number"]:hover::-webkit-inner-spin-button,
input[type="number"]:hover::-webkit-outer-spin-button {
-webkit-appearance: inner-spin-button;
}
/* Restore default apperance */
input[type="number"]:focus,
input[type="number"]:hover {
appearance: auto;
}
#left-pane input,
#left-pane select,
#left-pane textarea {
color: var(--left-pane-text-color);
background: var(--left-pane-background-color);
}
input::placeholder,
.form-control::placeholder,
#left-pane input::placeholder {
color: var(--muted-text-color); color: var(--muted-text-color);
} }
table td, table th { .table thead th,
.table td,
.table th {
/* Fix center vertical alignment of table cells */
vertical-align: middle;
color: var(--main-text-color); color: var(--main-text-color);
background: transparent;
} }
.ck .todo-list__checkmark { .ck .todo-list__checkmark {
@ -184,10 +240,15 @@ div.ui-tooltip {
display: none; display: none;
} }
.dropdown-divider {
background-color: var(--menu-text-color);
}
.dropdown-menu { .dropdown-menu {
border: 1px solid var(--dropdown-border-color); border: 1px solid var(--dropdown-border-color);
color: var(--menu-text-color) !important; color: var(--menu-text-color) !important;
background-color: var(--menu-background-color) !important; background-color: var(--menu-background-color) !important;
font-size: inherit;
} }
.dropdown-menu .disabled { .dropdown-menu .disabled {
@ -281,6 +342,10 @@ body .CodeMirror {
border-color: var(--button-border-color); border-color: var(--button-border-color);
} }
.btn:hover {
border-color: var(--hover-item-border-color);
}
button.btn, button.btn-sm { button.btn, button.btn-sm {
font-size: inherit; font-size: inherit;
} }
@ -397,48 +462,83 @@ table.promoted-attributes-in-tooltip td, table.promoted-attributes-in-tooltip th
font-size: var(--main-font-size) !important; font-size: var(--main-font-size) !important;
} }
.bs-tooltip-bottom .arrow::before { border-bottom-color: var(--main-border-color) !important; } .tooltip-trigger {
.bs-tooltip-top .arrow::before { border-top-color: var(--main-border-color) !important; }
.bs-tooltip-left .arrow::before { border-left-color: var(--main-border-color) !important; }
.bs-tooltip-right .arrow::before { border-right-color: var(--main-border-color) !important; }
.bs-tooltip-bottom .arrow::after { border-bottom-color: var(--tooltip-background-color) !important; }
.bs-tooltip-top .arrow::after { border-top-color: var(--tooltip-background-color) !important; }
.bs-tooltip-left .arrow::after { border-left-color: var(--tooltip-background-color) !important; }
.bs-tooltip-right .arrow::after { border-right-color: var(--tooltip-background-color) !important; }
.tooltip .arrow::after {
position: absolute; position: absolute;
content: ''; top: 0;
border-color: transparent; left: 0;
border-style: solid; width: 100%;
height: 100%;
background: transparent;
pointer-events: none;
} }
.bs-tooltip-auto[x-placement^='left'] .arrow::after, .bs-tooltip-bottom .tooltip-arrow::before { border-bottom-color: var(--main-border-color) !important; }
.bs-tooltip-left .arrow::after { .bs-tooltip-top .tooltip-arrow::before { border-top-color: var(--main-border-color) !important; }
.bs-tooltip-left .tooltip-arrow::before { border-left-color: var(--main-border-color) !important; }
.bs-tooltip-right .tooltip-arrow::before { border-right-color: var(--main-border-color) !important; }
.bs-tooltip-bottom .tooltip-arrow::after { border-bottom-color: var(--tooltip-background-color) !important; }
.bs-tooltip-top .tooltip-arrow::after { border-top-color: var(--tooltip-background-color) !important; }
.bs-tooltip-left .tooltip-arrow::after { border-left-color: var(--tooltip-background-color) !important; }
.bs-tooltip-right .tooltip-arrow::after { border-right-color: var(--tooltip-background-color) !important; }
.bs-tooltip-auto[data-popper-placement^='left'] .tooltip-arrow::before,
.bs-tooltip-left .tooltip-arrow::before {
left: -1px; left: -1px;
border-width: 0.4rem 0 0.4rem 0.4rem; border-width: 0.4rem 0 0.4rem 0.4rem;
border-left-color: var(--main-border-color) !important;
} }
.bs-tooltip-auto[x-placement^='bottom'] .arrow::after, .bs-tooltip-auto[data-popper-placement^='bottom'] .tooltip-arrow::before,
.bs-tooltip-bottom .arrow::after { .bs-tooltip-bottom .tooltip-arrow::before {
bottom: -1px; bottom: -1px;
border-width: 0 0.4rem 0.4rem; border-width: 0 0.4rem 0.4rem;
border-bottom-color: var(--main-border-color) !important;
} }
.bs-tooltip-auto[x-placement^='right'] .arrow::after, .bs-tooltip-auto[data-popper-placement^='right'] .tooltip-arrow::before,
.bs-tooltip-right .arrow::after { .bs-tooltip-right .tooltip-arrow::before {
right: -1px; right: -1px;
border-width: 0.4rem 0.4rem 0.4rem 0; border-width: 0.4rem 0.4rem 0.4rem 0;
border-right-color: var(--main-border-color) !important;
} }
.bs-tooltip-auto[x-placement^='top'] .arrow::after, .bs-tooltip-auto[data-popper-placement^='top'] .tooltip-arrow::before,
.bs-tooltip-top .arrow::after { .bs-tooltip-top .tooltip-arrow::before {
top: -1px; top: -1px;
border-width: 0.4rem 0.4rem 0; border-width: 0.4rem 0.4rem 0;
border-top-color: var(--main-border-color) !important;
} }
.note-tooltip.tooltip .arrow { .bs-tooltip-auto[data-popper-placement^='left'] .tooltip-arrow::after,
.bs-tooltip-left .tooltip-arrow::after {
left: -1px;
border-width: 0.4rem 0 0.4rem 0.4rem;
border-left-color: var(--tooltip-background-color) !important;
}
.bs-tooltip-auto[data-popper-placement^='bottom'] .tooltip-arrow::after,
.bs-tooltip-bottom .tooltip-arrow::after {
bottom: -1px;
border-width: 0 0.4rem 0.4rem;
border-bottom-color: var(--tooltip-background-color) !important;
}
.bs-tooltip-auto[data-popper-placement^='right'] .tooltip-arrow::after,
.bs-tooltip-right .tooltip-arrow::after {
right: -1px;
border-width: 0.4rem 0.4rem 0.4rem 0;
border-right-color: var(--tooltip-background-color) !important;
}
.bs-tooltip-auto[data-popper-placement^='top'] .tooltip-arrow::after,
.bs-tooltip-top .tooltip-arrow::after {
top: -1px;
border-width: 0.4rem 0.4rem 0;
border-top-color: var(--tooltip-background-color) !important;
}
.note-tooltip.tooltip .tooltip-arrow {
display: none; display: none;
} }
@ -651,6 +751,7 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
} }
.card { .card {
color: inherit !important;
background-color: inherit !important; background-color: inherit !important;
border-color: var(--main-border-color) !important; border-color: var(--main-border-color) !important;
} }
@ -667,7 +768,7 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
} }
.modal-header { .modal-header {
padding: 0.7rem 1rem 0 1rem !important; /* make modal header padding slightly smaller */ padding: 0.5rem 1rem 0.5rem 1rem !important; /* make modal header padding slightly smaller */
} }
#toast-container { #toast-container {
@ -682,7 +783,6 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
color: var(--main-text-color) !important; color: var(--main-text-color) !important;
z-index: 9999999999 !important; z-index: 9999999999 !important;
pointer-events: all; pointer-events: all;
flex-basis: 0; /* otherwise toast is always at least 350px tall (happens since 4.5.1, perhaps a bug) */
} }
.toast-header { .toast-header {
@ -789,10 +889,6 @@ a.external:not(.no-arrow):after, a[href^="http://"]:not(.no-arrow):after, a[href
cursor: row-resize; cursor: row-resize;
} }
.dropdown-menu {
font-size: inherit;
}
#context-menu-container { #context-menu-container {
max-height: 100vh; max-height: 100vh;
/* !!! Cannot set overflow: auto, submenus will break !!! */ /* !!! Cannot set overflow: auto, submenus will break !!! */
@ -846,7 +942,7 @@ li.dropdown-submenu:hover > ul.dropdown-menu {
background-color: inherit; background-color: inherit;
} }
[data-toggle="tooltip"]:not(.button-widget) span { [data-bs-toggle="tooltip"]:not(.button-widget) span {
padding-bottom: 0; padding-bottom: 0;
border-bottom: 1px dotted; border-bottom: 1px dotted;
} }
@ -954,11 +1050,6 @@ li.dropdown-submenu:hover > ul.dropdown-menu {
background-color: var(--launcher-pane-background-color); background-color: var(--launcher-pane-background-color);
} }
input {
background-color: transparent !important;
}
#right-pane { #right-pane {
overflow: auto; overflow: auto;
} }
@ -1059,7 +1150,6 @@ button.close:hover {
} }
.options-number-input { .options-number-input {
text-align: right;
/* overriding settings from .form-control */ /* overriding settings from .form-control */
width: 10em !important; width: 10em !important;
flex-grow: 0 !important; flex-grow: 0 !important;
@ -1069,12 +1159,6 @@ textarea {
cursor: auto; cursor: auto;
} }
.table thead th,
.table td, .table th {
/* Fix center vertical alignment of table cells */
vertical-align: middle;
}
.ck-powered-by-balloon { .ck-powered-by-balloon {
display: none !important; display: none !important;
} }
@ -1092,7 +1176,6 @@ textarea {
.jump-to-note-dialog .modal-header { .jump-to-note-dialog .modal-header {
align-items: center; align-items: center;
padding-bottom: 1rem !important;
} }
.jump-to-note-dialog .modal-body { .jump-to-note-dialog .modal-body {

View File

@ -88,3 +88,7 @@ body .CodeMirror {
body .todo-list input[type="checkbox"]:not(:checked):before { body .todo-list input[type="checkbox"]:not(:checked):before {
border-color: var(--muted-text-color) !important; border-color: var(--muted-text-color) !important;
} }
.btn-close {
filter: invert(1);
}

View File

@ -468,8 +468,8 @@
"to": "到", "to": "到",
"target_parent_note": "目标父笔记", "target_parent_note": "目标父笔记",
"on_all_matched_notes": "对于所有匹配的笔记", "on_all_matched_notes": "对于所有匹配的笔记",
"move_note_new_parent": "", "move_note_new_parent": "如果笔记只有一个父级(即旧分支被移除并创建新分支到新父级),则将笔记移动到新父级",
"clone_note_new_parent": "", "clone_note_new_parent": "如果笔记有多个克隆/分支(不清楚应该移除哪个分支),则将笔记克隆到新父级",
"nothing_will_happen": "如果笔记无法移动到目标笔记(即这会创建一个树循环),则不会发生任何事情" "nothing_will_happen": "如果笔记无法移动到目标笔记(即这会创建一个树循环),则不会发生任何事情"
}, },
"rename_note": { "rename_note": {
@ -477,7 +477,7 @@
"rename_note_title_to": "重命名笔记标题为", "rename_note_title_to": "重命名笔记标题为",
"new_note_title": "新笔记标题", "new_note_title": "新笔记标题",
"click_help_icon": "点击右侧的帮助图标查看所有选项", "click_help_icon": "点击右侧的帮助图标查看所有选项",
"evaluated_as_js_string": "给定的值被评估为JavaScript字符串因此可以通过注入的<code>note</code>变量(正在重命名的笔记)丰富动态内容。 例如:", "evaluated_as_js_string": "给定的值被评估为 JavaScript 字符串,因此可以通过注入的 <code>note</code> 变量(正在重命名的笔记)丰富动态内容。 例如:",
"example_note": "<code>Note</code> - 所有匹配的笔记都被重命名为“Note”", "example_note": "<code>Note</code> - 所有匹配的笔记都被重命名为“Note”",
"example_new_title": "<code>NEW: ${note.title}</code> - 匹配的笔记标题以“NEW: ”为前缀", "example_new_title": "<code>NEW: ${note.title}</code> - 匹配的笔记标题以“NEW: ”为前缀",
"example_date_prefix": "<code>${note.dateCreatedObj.format('MM-DD:')}: ${note.title}</code> - 匹配的笔记以笔记的创建月份-日期为前缀", "example_date_prefix": "<code>${note.dateCreatedObj.format('MM-DD:')}: ${note.title}</code> - 匹配的笔记以笔记的创建月份-日期为前缀",
@ -593,6 +593,14 @@
"about": "关于 TriliumNext 笔记", "about": "关于 TriliumNext 笔记",
"logout": "登出" "logout": "登出"
}, },
"sync_status": {
"unknown": "<p>同步状态将在下一次同步尝试开始后显示。</p><p>点击以立即触发同步。</p>",
"connected_with_changes": "<p>已连接到同步服务器。<br>有一些未同步的变更。</p><p>点击以触发同步。</p>",
"connected_no_changes": "<p>已连接到同步服务器。<br>所有变更均已同步。</p><p>点击以触发同步。</p>",
"disconnected_with_changes": "<p>连接同步服务器失败。<br>有一些未同步的变更。</p><p>点击以触发同步。</p>",
"disconnected_no_changes": "<p>连接同步服务器失败。<br>所有已知变更均已同步。</p><p>点击以触发同步。</p>",
"in_progress": "正在与服务器进行同步。"
},
"left_pane_toggle": { "left_pane_toggle": {
"hide_panel": "隐藏面板", "hide_panel": "隐藏面板",
"show_panel": "显示面板" "show_panel": "显示面板"
@ -662,6 +670,9 @@
"error_cannot_get_branch_id": "无法获取 notePath '{{notePath}}' 的 branchId", "error_cannot_get_branch_id": "无法获取 notePath '{{notePath}}' 的 branchId",
"error_unrecognized_command": "无法识别的命令 {{command}}" "error_unrecognized_command": "无法识别的命令 {{command}}"
}, },
"note_icon": {
"change_note_icon": "更改笔记图标"
},
"basic_properties": { "basic_properties": {
"note_type": "笔记类型", "note_type": "笔记类型",
"editable": "可编辑", "editable": "可编辑",
@ -1023,8 +1034,8 @@
"title": "下拉菜单可用的MIME文件类型" "title": "下拉菜单可用的MIME文件类型"
}, },
"vim_key_bindings": { "vim_key_bindings": {
"use_vim_keybindings_in_code_notes": "", "use_vim_keybindings_in_code_notes": "Vim 快捷键",
"enable_vim_keybindings": "" "enable_vim_keybindings": "在代码笔记中启用 Vim 快捷键(不包含 ex 模式)"
}, },
"wrap_lines": { "wrap_lines": {
"wrap_lines_in_code_notes": "代码笔记自动换行", "wrap_lines_in_code_notes": "代码笔记自动换行",
@ -1090,11 +1101,11 @@
"highlights_list": { "highlights_list": {
"title": "高亮列表", "title": "高亮列表",
"description": "您可以自定义右侧面板中显示的高亮列表:", "description": "您可以自定义右侧面板中显示的高亮列表:",
"bold": "", "bold": "粗体",
"italic": "", "italic": "斜体",
"underline": "", "underline": "下划线",
"color": "", "color": "字体颜色",
"bg_color": "", "bg_color": "背景颜色",
"visibility_title": "高亮列表可见性", "visibility_title": "高亮列表可见性",
"visibility_description": "您可以通过添加 #hideHighlightWidget 标签来隐藏每个笔记的高亮小部件。", "visibility_description": "您可以通过添加 #hideHighlightWidget 标签来隐藏每个笔记的高亮小部件。",
"shortcut_info": "您可以在选项 -> 快捷键中为快速切换右侧面板(包括高亮列表)配置键盘快捷键(名称为 'toggleRightPane')。" "shortcut_info": "您可以在选项 -> 快捷键中为快速切换右侧面板(包括高亮列表)配置键盘快捷键(名称为 'toggleRightPane')。"

View File

@ -593,6 +593,14 @@
"about": "About TriliumNext Notes", "about": "About TriliumNext Notes",
"logout": "Logout" "logout": "Logout"
}, },
"sync_status": {
"unknown": "<p>Sync status will be known once the next sync attempt starts.</p><p>Click to trigger sync now.</p>",
"connected_with_changes": "<p>Connected to the sync server. <br>There are some outstanding changes yet to be synced.</p><p>Click to trigger sync.</p>",
"connected_no_changes":"<p>Connected to the sync server.<br>All changes have been already synced.</p><p>Click to trigger sync.</p>",
"disconnected_with_changes":"<p>Establishing the connection to the sync server was unsuccessful.<br>There are some outstanding changes yet to be synced.</p><p>Click to trigger sync.</p>",
"disconnected_no_changes":"<p>Establishing the connection to the sync server was unsuccessful.<br>All known changes have been synced.</p><p>Click to trigger sync.</p>",
"in_progress":"Sync with the server is in progress."
},
"left_pane_toggle": { "left_pane_toggle": {
"show_panel": "Show panel", "show_panel": "Show panel",
"hide_panel": "Hide panel" "hide_panel": "Hide panel"
@ -665,6 +673,9 @@
"error_cannot_get_branch_id": "Cannot get branchId for notePath '{{notePath}}'", "error_cannot_get_branch_id": "Cannot get branchId for notePath '{{notePath}}'",
"error_unrecognized_command": "Unrecognized command {{command}}" "error_unrecognized_command": "Unrecognized command {{command}}"
}, },
"note_icon": {
"change_note_icon": "Change note icon"
},
"basic_properties": { "basic_properties": {
"note_type": "Note type", "note_type": "Note type",
"editable": "Editable", "editable": "Editable",