options split into individual classes

This commit is contained in:
zadam 2019-08-21 20:24:37 +02:00
parent dddb02a286
commit c11479de58
10 changed files with 414 additions and 406 deletions

View file

@ -6,5 +6,8 @@
<option name="TAB_SIZE" value="2" />
</value>
</option>
<JSCodeStyleSettings version="0">
<option name="USE_EXPLICIT_JS_EXTENSION" value="TRUE" />
</JSCodeStyleSettings>
</code_scheme>
</component>

View file

@ -1,22 +1,10 @@
"use strict";
import protectedSessionHolder from '../services/protected_session_holder.js';
import server from '../services/server.js';
import infoService from "../services/info.js";
import zoomService from "../services/zoom.js";
import utils from "../services/utils.js";
import cssLoader from "../services/css_loader.js";
import optionsInit from "../services/options_init.js";
import libraryLoader from "../services/library_loader.js";
const $dialog = $("#options-dialog");
const tabHandlers = [];
function addTabHandler(handler) {
tabHandlers.push(handler);
}
export async function showDialog() {
utils.closeActiveDialog();
@ -26,392 +14,19 @@ export async function showDialog() {
$dialog.modal();
for (const handler of tabHandlers) {
if (handler.optionsLoaded) {
handler.optionsLoaded(options);
}
}
}
async function saveOptions(options) {
await server.put('options', options);
infoService.showMessage("Options change have been saved.");
}
addTabHandler((function() {
const $themeSelect = $("#theme-select");
const $zoomFactorSelect = $("#zoom-factor-select");
const $oneTabDisplaySelect = $("#one-tab-display-select");
const $leftPaneMinWidth = $("#left-pane-min-width");
const $leftPaneWidthPercent = $("#left-pane-width-percent");
const $mainFontSize = $("#main-font-size");
const $treeFontSize = $("#tree-font-size");
const $detailFontSize = $("#detail-font-size");
const $body = $("body");
const $container = $("#container");
async function optionsLoaded(options) {
const themes = [
{ val: 'white', title: 'White' },
{ val: 'dark', title: 'Dark' },
{ val: 'black', title: 'Black' }
].concat(await server.get('options/user-themes'));
$themeSelect.empty();
for (const theme of themes) {
$themeSelect.append($("<option>")
.attr("value", theme.val)
.attr("data-note-id", theme.noteId)
.html(theme.title));
}
$themeSelect.val(options.theme);
if (utils.isElectron()) {
$zoomFactorSelect.val(options.zoomFactor);
}
else {
$zoomFactorSelect.prop('disabled', true);
}
$oneTabDisplaySelect.val(options.hideTabRowForOneTab === 'true' ? 'hide' : 'show');
$leftPaneMinWidth.val(options.leftPaneMinWidth);
$leftPaneWidthPercent.val(options.leftPaneWidthPercent);
$mainFontSize.val(options.mainFontSize);
$treeFontSize.val(options.treeFontSize);
$detailFontSize.val(options.detailFontSize);
}
$themeSelect.change(function() {
const newTheme = $(this).val();
for (const clazz of Array.from($body[0].classList)) { // create copy to safely iterate over while removing classes
if (clazz.startsWith("theme-")) {
$body.removeClass(clazz);
}
}
const noteId = $(this).find(":selected").attr("data-note-id");
if (noteId) {
// make sure the CSS is loaded
// if the CSS has been loaded and then updated then the changes won't take effect though
cssLoader.requireCss(`/api/notes/download/${noteId}`);
}
$body.addClass("theme-" + newTheme);
server.put('options/theme/' + newTheme);
});
$zoomFactorSelect.change(function() { zoomService.setZoomFactorAndSave($(this).val()); });
function resizeLeftPanel() {
const leftPanePercent = parseInt($leftPaneWidthPercent.val());
const rightPanePercent = 100 - leftPanePercent;
const leftPaneMinWidth = $leftPaneMinWidth.val();
$container.css("grid-template-columns", `minmax(${leftPaneMinWidth}px, ${leftPanePercent}fr) ${rightPanePercent}fr`);
}
$oneTabDisplaySelect.change(function() {
const hideTabRowForOneTab = $(this).val() === 'hide' ? 'true' : 'false';
server.put('options/hideTabRowForOneTab/' + hideTabRowForOneTab)
.then(optionsInit.loadOptions);
});
$leftPaneMinWidth.change(async function() {
await server.put('options/leftPaneMinWidth/' + $(this).val());
resizeLeftPanel();
});
$leftPaneWidthPercent.change(async function() {
await server.put('options/leftPaneWidthPercent/' + $(this).val());
resizeLeftPanel();
});
function applyFontSizes() {
console.log($mainFontSize.val() + "% !important");
$body.get(0).style.setProperty("--main-font-size", $mainFontSize.val() + "%");
$body.get(0).style.setProperty("--tree-font-size", $treeFontSize.val() + "%");
$body.get(0).style.setProperty("--detail-font-size", $detailFontSize.val() + "%");
}
$mainFontSize.change(async function() {
await server.put('options/mainFontSize/' + $(this).val());
applyFontSizes();
});
$treeFontSize.change(async function() {
await server.put('options/treeFontSize/' + $(this).val());
applyFontSizes();
});
$detailFontSize.change(async function() {
await server.put('options/detailFontSize/' + $(this).val());
applyFontSizes();
});
return {
optionsLoaded
};
})());
addTabHandler((function() {
const $form = $("#change-password-form");
const $oldPassword = $("#old-password");
const $newPassword1 = $("#new-password1");
const $newPassword2 = $("#new-password2");
function optionsLoaded(options) {
}
$form.submit(() => {
const oldPassword = $oldPassword.val();
const newPassword1 = $newPassword1.val();
const newPassword2 = $newPassword2.val();
$oldPassword.val('');
$newPassword1.val('');
$newPassword2.val('');
if (newPassword1 !== newPassword2) {
alert("New passwords are not the same.");
return false;
}
server.post('password/change', {
'current_password': oldPassword,
'new_password': newPassword1
}).then(result => {
if (result.success) {
alert("Password has been changed. Trilium will be reloaded after you press OK.");
// password changed so current protected session is invalid and needs to be cleared
protectedSessionHolder.resetProtectedSession();
}
else {
infoService.showError(result.message);
(await Promise.all([
import('./options/advanced.js'),
import('./options/appearance.js'),
import('./options/change_password.js'),
import('./options/note_revisions.js'),
import('./options/protected_session.js'),
import('./options/sidebar.js'),
import('./options/sync.js'),
]))
.map(m => new m.default)
.forEach(tab => {
if (tab.optionsLoaded) {
tab.optionsLoaded(options)
}
});
return false;
});
return {
optionsLoaded
};
})());
addTabHandler((function() {
const $form = $("#protected-session-timeout-form");
const $protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
function optionsLoaded(options) {
$protectedSessionTimeout.val(options['protectedSessionTimeout']);
}
$form.submit(() => {
const protectedSessionTimeout = $protectedSessionTimeout.val();
saveOptions({ 'protectedSessionTimeout': protectedSessionTimeout }).then(() => {
optionsInit.loadOptions();
});
return false;
});
return {
optionsLoaded
};
})());
addTabHandler((function () {
const $form = $("#note-revision-snapshot-time-interval-form");
const $timeInterval = $("#note-revision-snapshot-time-interval-in-seconds");
function optionsLoaded(options) {
$timeInterval.val(options['noteRevisionSnapshotTimeInterval']);
}
$form.submit(() => {
saveOptions({ 'noteRevisionSnapshotTimeInterval': $timeInterval.val() });
return false;
});
return {
optionsLoaded
};
})());
addTabHandler((function() {
const $form = $("#sync-setup-form");
const $syncServerHost = $("#sync-server-host");
const $syncServerTimeout = $("#sync-server-timeout");
const $syncProxy = $("#sync-proxy");
const $testSyncButton = $("#test-sync-button");
function optionsLoaded(options) {
$syncServerHost.val(options['syncServerHost']);
$syncServerTimeout.val(options['syncServerTimeout']);
$syncProxy.val(options['syncProxy']);
}
$form.submit(() => {
saveOptions({
'syncServerHost': $syncServerHost.val(),
'syncServerTimeout': $syncServerTimeout.val(),
'syncProxy': $syncProxy.val()
});
return false;
});
$testSyncButton.click(async () => {
const result = await server.post('sync/test');
if (result.success) {
infoService.showMessage(result.message);
}
else {
infoService.showError("Sync server handshake failed, error: " + result.message);
}
});
return {
optionsLoaded
};
})());
addTabHandler((async function () {
const $forceFullSyncButton = $("#force-full-sync-button");
const $fillSyncRowsButton = $("#fill-sync-rows-button");
const $anonymizeButton = $("#anonymize-button");
const $cleanupSoftDeletedButton = $("#cleanup-soft-deleted-items-button");
const $cleanupUnusedImagesButton = $("#cleanup-unused-images-button");
const $vacuumDatabaseButton = $("#vacuum-database-button");
$forceFullSyncButton.click(async () => {
await server.post('sync/force-full-sync');
infoService.showMessage("Full sync triggered");
});
$fillSyncRowsButton.click(async () => {
await server.post('sync/fill-sync-rows');
infoService.showMessage("Sync rows filled successfully");
});
$anonymizeButton.click(async () => {
await server.post('anonymization/anonymize');
infoService.showMessage("Created anonymized database");
});
$cleanupSoftDeletedButton.click(async () => {
if (confirm("Do you really want to clean up soft-deleted items?")) {
await server.post('cleanup/cleanup-soft-deleted-items');
infoService.showMessage("Soft deleted items have been cleaned up");
}
});
$cleanupUnusedImagesButton.click(async () => {
if (confirm("Do you really want to clean up unused images?")) {
await server.post('cleanup/cleanup-unused-images');
infoService.showMessage("Unused images have been cleaned up");
}
});
$vacuumDatabaseButton.click(async () => {
await server.post('cleanup/vacuum-database');
infoService.showMessage("Database has been vacuumed");
});
return {};
})());
addTabHandler((async function() {
const $sidebarMinWidth = $("#sidebar-min-width");
const $sidebarWidthPercent = $("#sidebar-width-percent");
const $showSidebarInNewTab = $("#show-sidebar-in-new-tab");
const $widgetsActive = $("#widgets-active");
const $widgetsInactive = $("#widgets-inactive");
await libraryLoader.requireLibrary(libraryLoader.SORTABLE);
new Sortable($widgetsActive[0], {
group: 'shared',
animation: 150
});
new Sortable($widgetsInactive[0], {
group: 'shared',
animation: 150
});
async function optionsLoaded(options) {
$sidebarMinWidth.val(options.sidebarMinWidth);
$sidebarWidthPercent.val(options.sidebarWidthPercent);
if (parseInt(options.showSidebarInNewTab)) {
$showSidebarInNewTab.attr("checked", "checked");
}
else {
$showSidebarInNewTab.removeAttr("checked");
}
}
function resizeSidebar() {
const sidebarWidthPercent = parseInt($sidebarWidthPercent.val());
const sidebarMinWidth = $sidebarMinWidth.val();
// need to find them dynamically since they change
const $sidebar = $(".note-detail-sidebar");
console.log("Resizing to ", sidebarWidthPercent, sidebarMinWidth);
$sidebar.css("width", sidebarWidthPercent + '%');
$sidebar.css("min-width", sidebarMinWidth + 'px');
}
$sidebarMinWidth.change(async function() {
await server.put('options/sidebarMinWidth/' + $(this).val());
resizeSidebar();
});
$sidebarWidthPercent.change(async function() {
await server.put('options/sidebarWidthPercent/' + $(this).val());
resizeSidebar();
});
$showSidebarInNewTab.change(async function() {
const flag = $(this).is(":checked") ? 1 : 0;
await server.put('options/showSidebarInNewTab/' + flag);
optionsInit.loadOptions();
});
return {
optionsLoaded
};
})());
}

View file

@ -0,0 +1,53 @@
import server from "../../services/server.js";
import infoService from "../../services/info.js";
export default class AdvancedOptions {
constructor() {
this.$forceFullSyncButton = $("#force-full-sync-button");
this.$fillSyncRowsButton = $("#fill-sync-rows-button");
this.$anonymizeButton = $("#anonymize-button");
this.$cleanupSoftDeletedButton = $("#cleanup-soft-deleted-items-button");
this.$cleanupUnusedImagesButton = $("#cleanup-unused-images-button");
this.$vacuumDatabaseButton = $("#vacuum-database-button");
this.$forceFullSyncButton.click(async () => {
await server.post('sync/force-full-sync');
infoService.showMessage("Full sync triggered");
});
this.$fillSyncRowsButton.click(async () => {
await server.post('sync/fill-sync-rows');
infoService.showMessage("Sync rows filled successfully");
});
this.$anonymizeButton.click(async () => {
await server.post('anonymization/anonymize');
infoService.showMessage("Created anonymized database");
});
this.$cleanupSoftDeletedButton.click(async () => {
if (confirm("Do you really want to clean up soft-deleted items?")) {
await server.post('cleanup/cleanup-soft-deleted-items');
infoService.showMessage("Soft deleted items have been cleaned up");
}
});
this.$cleanupUnusedImagesButton.click(async () => {
if (confirm("Do you really want to clean up unused images?")) {
await server.post('cleanup/cleanup-unused-images');
infoService.showMessage("Unused images have been cleaned up");
}
});
this.$vacuumDatabaseButton.click(async () => {
await server.post('cleanup/vacuum-database');
infoService.showMessage("Database has been vacuumed");
});
}
}

View file

@ -0,0 +1,130 @@
import server from "../../services/server.js";
import utils from "../../services/utils.js";
import cssLoader from "../../services/css_loader.js";
import zoomService from "../../services/zoom.js";
import optionsInit from "../../services/options_init.js";
export default class ApperanceOptions {
constructor() {
this.$themeSelect = $("#theme-select");
this.$zoomFactorSelect = $("#zoom-factor-select");
this.$oneTabDisplaySelect = $("#one-tab-display-select");
this.$leftPaneMinWidth = $("#left-pane-min-width");
this.$leftPaneWidthPercent = $("#left-pane-width-percent");
this.$mainFontSize = $("#main-font-size");
this.$treeFontSize = $("#tree-font-size");
this.$detailFontSize = $("#detail-font-size");
this.$body = $("body");
this.$container = $("#container");
this.$themeSelect.change(() => {
const newTheme = this.$themeSelect.val();
for (const clazz of Array.from(this.$body[0].classList)) { // create copy to safely iterate over while removing classes
if (clazz.startsWith("theme-")) {
this.$body.removeClass(clazz);
}
}
const noteId = $(this).find(":selected").attr("data-note-id");
if (noteId) {
// make sure the CSS is loaded
// if the CSS has been loaded and then updated then the changes won't take effect though
cssLoader.requireCss(`/api/notes/download/${noteId}`);
}
this.$body.addClass("theme-" + newTheme);
server.put('options/theme/' + newTheme);
});
this.$zoomFactorSelect.change(() => { zoomService.setZoomFactorAndSave(this.$zoomFactorSelect.val()); });
this.$oneTabDisplaySelect.change(() => {
const hideTabRowForOneTab = this.$oneTabDisplaySelect.val() === 'hide' ? 'true' : 'false';
server.put('options/hideTabRowForOneTab/' + hideTabRowForOneTab)
.then(optionsInit.loadOptions);
});
this.$leftPaneMinWidth.change(async () => {
await server.put('options/leftPaneMinWidth/' + this.$leftPaneMinWidth.val());
this.resizeLeftPanel();
});
this.$leftPaneWidthPercent.change(async () => {
await server.put('options/leftPaneWidthPercent/' + this.$leftPaneWidthPercent.val());
this.resizeLeftPanel();
});
this.$mainFontSize.change(async () => {
await server.put('options/mainFontSize/' + this.$mainFontSize.val());
this.applyFontSizes();
});
this.$treeFontSize.change(async () => {
await server.put('options/treeFontSize/' + this.$treeFontSize.val());
this.applyFontSizes();
});
this.$detailFontSize.change(async () => {
await server.put('options/detailFontSize/' + this.$detailFontSize.val());
this.applyFontSizes();
});
}
async optionsLoaded(options) {
const themes = [
{ val: 'white', title: 'White' },
{ val: 'dark', title: 'Dark' },
{ val: 'black', title: 'Black' }
].concat(await server.get('options/user-themes'));
this.$themeSelect.empty();
for (const theme of themes) {
this.$themeSelect.append($("<option>")
.attr("value", theme.val)
.attr("data-note-id", theme.noteId)
.html(theme.title));
}
this.$themeSelect.val(options.theme);
if (utils.isElectron()) {
this.$zoomFactorSelect.val(options.zoomFactor);
}
else {
this.$zoomFactorSelect.prop('disabled', true);
}
this.$oneTabDisplaySelect.val(options.hideTabRowForOneTab === 'true' ? 'hide' : 'show');
this.$leftPaneMinWidth.val(options.leftPaneMinWidth);
this.$leftPaneWidthPercent.val(options.leftPaneWidthPercent);
this.$mainFontSize.val(options.mainFontSize);
this.$treeFontSize.val(options.treeFontSize);
this.$detailFontSize.val(options.detailFontSize);
}
resizeLeftPanel() {
const leftPanePercent = parseInt(this.$leftPaneWidthPercent.val());
const rightPanePercent = 100 - leftPanePercent;
const leftPaneMinWidth = this.$leftPaneMinWidth.val();
this.$container.css("grid-template-columns", `minmax(${leftPaneMinWidth}px, ${leftPanePercent}fr) ${rightPanePercent}fr`);
}
applyFontSizes() {
this.$body.get(0).style.setProperty("--main-font-size", this.$mainFontSize.val() + "%");
this.$body.get(0).style.setProperty("--tree-font-size", this.$treeFontSize.val() + "%");
this.$body.get(0).style.setProperty("--detail-font-size", this.$detailFontSize.val() + "%");
}
}

View file

@ -0,0 +1,48 @@
import server from "../../services/server.js";
import protectedSessionHolder from "../../services/protected_session_holder.js";
import infoService from "../../services/info.js";
export default class ChangePasswordOptions {
constructor() {
this.$form = $("#change-password-form");
this.$oldPassword = $("#old-password");
this.$newPassword1 = $("#new-password1");
this.$newPassword2 = $("#new-password2");
this.$form.submit(() => this.save());
}
optionsLoaded(options) {}
save() {
const oldPassword = this.$oldPassword.val();
const newPassword1 = this.$newPassword1.val();
const newPassword2 = this.$newPassword2.val();
this.$oldPassword.val('');
this.$newPassword1.val('');
this.$newPassword2.val('');
if (newPassword1 !== newPassword2) {
alert("New passwords are not the same.");
return false;
}
server.post('password/change', {
'current_password': oldPassword,
'new_password': newPassword1
}).then(result => {
if (result.success) {
alert("Password has been changed. Trilium will be reloaded after you press OK.");
// password changed so current protected session is invalid and needs to be cleared
protectedSessionHolder.resetProtectedSession();
}
else {
infoService.showError(result.message);
}
});
return false;
}
}

View file

@ -0,0 +1,20 @@
import server from "../../services/server.js";
import infoService from "../../services/info.js";
export default class NoteRevisionsOptions {
constructor() {
this.$form = $("#note-revision-snapshot-time-interval-form");
this.$timeInterval = $("#note-revision-snapshot-time-interval-in-seconds");
this.$form.submit(() => {
const opts = { 'noteRevisionSnapshotTimeInterval': this.$timeInterval.val() };
server.put('options', opts).then(() => infoService.showMessage("Options change have been saved."));
return false;
});
}
optionsLoaded(options) {
this.$timeInterval.val(options['noteRevisionSnapshotTimeInterval']);
}
}

View file

@ -0,0 +1,28 @@
import optionsInit from "../../services/options_init.js";
import server from "../../services/server.js";
import infoService from "../../services/info.js";
export default class ProtectedSessionOptions {
constructor() {
this.$form = $("#protected-session-timeout-form");
this.$protectedSessionTimeout = $("#protected-session-timeout-in-seconds");
this.$form.submit(() => this.save());
}
optionsLoaded(options) {
this.$protectedSessionTimeout.val(options['protectedSessionTimeout']);
}
save() {
const protectedSessionTimeout = this.$protectedSessionTimeout.val();
server.put('options', { 'protectedSessionTimeout': protectedSessionTimeout }).then(() => {
optionsInit.loadOptions();
infoService.showMessage("Options change have been saved.");
});
return false;
}
}

View file

@ -0,0 +1,68 @@
import libraryLoader from "../../services/library_loader.js";
import server from "../../services/server.js";
import optionsInit from "../../services/options_init.js";
export default class SidebarOptions {
constructor() {
this.$sidebarMinWidth = $("#sidebar-min-width");
this.$sidebarWidthPercent = $("#sidebar-width-percent");
this.$showSidebarInNewTab = $("#show-sidebar-in-new-tab");
this.$widgetsActive = $("#widgets-active");
this.$widgetsInactive = $("#widgets-inactive");
libraryLoader.requireLibrary(libraryLoader.SORTABLE).then(() => {
new Sortable(this.$widgetsActive[0], {
group: 'shared',
animation: 150
});
new Sortable(this.$widgetsInactive[0], {
group: 'shared',
animation: 150
});
});
this.$sidebarMinWidth.change(async () => {
await server.put('options/sidebarMinWidth/' + this.$sidebarMinWidth.val());
this.resizeSidebar();
});
this.$sidebarWidthPercent.change(async () => {
await server.put('options/sidebarWidthPercent/' + this.$sidebarWidthPercent.val());
this.resizeSidebar();
});
this.$showSidebarInNewTab.change(async () => {
const flag = this.$showSidebarInNewTab.is(":checked") ? 1 : 0;
await server.put('options/showSidebarInNewTab/' + flag);
optionsInit.loadOptions();
});
}
async optionsLoaded(options) {
this.$sidebarMinWidth.val(options.sidebarMinWidth);
this.$sidebarWidthPercent.val(options.sidebarWidthPercent);
if (parseInt(options.showSidebarInNewTab)) {
this.$showSidebarInNewTab.attr("checked", "checked");
}
else {
this.$showSidebarInNewTab.removeAttr("checked");
}
}
resizeSidebar() {
const sidebarWidthPercent = parseInt(this.$sidebarWidthPercent.val());
const sidebarMinWidth = this.$sidebarMinWidth.val();
// need to find them dynamically since they change
const $sidebar = $(".note-detail-sidebar");
$sidebar.css("width", sidebarWidthPercent + '%');
$sidebar.css("min-width", sidebarMinWidth + 'px');
}
}

View file

@ -0,0 +1,43 @@
import server from "../../services/server.js";
import infoService from "../../services/info.js";
export default class SyncOptions {
constructor() {
this.$form = $("#sync-setup-form");
this.$syncServerHost = $("#sync-server-host");
this.$syncServerTimeout = $("#sync-server-timeout");
this.$syncProxy = $("#sync-proxy");
this.$testSyncButton = $("#test-sync-button");
this.$form.submit(() => this.save());
this.$testSyncButton.click(async () => {
const result = await server.post('sync/test');
if (result.success) {
infoService.showMessage(result.message);
}
else {
infoService.showError("Sync server handshake failed, error: " + result.message);
}
});
}
optionsLoaded(options) {
this.$syncServerHost.val(options['syncServerHost']);
this.$syncServerTimeout.val(options['syncServerTimeout']);
this.$syncProxy.val(options['syncProxy']);
}
save() {
const opts = {
'syncServerHost': this.$syncServerHost.val(),
'syncServerTimeout': this.$syncServerTimeout.val(),
'syncProxy': this.$syncProxy.val()
};
server.put('options', opts).then(() => infoService.showMessage("Options change have been saved."));
return false;
}
}

View file

@ -53,13 +53,13 @@ class Sidebar {
this.widgets = [];
this.$widgetContainer.empty();
const widgetClasses = [
await import("../widgets/note_info.js"),
await import("../widgets/link_map.js"),
await import("../widgets/note_revisions.js"),
await import("../widgets/attributes.js"),
await import("../widgets/what_links_here.js")
].map(m => m.default);
const widgetClasses = (await Promise.all([
import("../widgets/note_info.js"),
import("../widgets/link_map.js"),
import("../widgets/note_revisions.js"),
import("../widgets/attributes.js"),
import("../widgets/what_links_here.js")
])).map(m => m.default);
const widgetRelations = await this.ctx.note.getRelations('widget');