fix(setting-tab): cleanup

This commit is contained in:
EloiMusk 2023-03-09 14:32:09 +01:00
parent f9c7b5fd95
commit edd77c6a53
No known key found for this signature in database
GPG key ID: A59863E13934DD4F
5 changed files with 318 additions and 68 deletions

32
main.ts
View file

@ -1,11 +1,10 @@
import {App, Editor, MarkdownView, Modal, Notice, Plugin} from 'obsidian';
import {Editor, MarkdownView, Plugin} from 'obsidian';
import {PrioPluginSettings} from "./utils/Settings";
import {SettingTab} from "./utils/SettingTab";
import {decreasePrio, increasePrio, removePrio, setPrio} from "./utils/Priority";
const DEFAULT_SETTINGS: PrioPluginSettings = {
selectedPreset: 'default',
levels: 6,
levelAliases: [
'Major',
@ -38,19 +37,6 @@ export default class PrioPlugin extends Plugin {
async onload() {
await this.loadSettings();
// This creates an icon in the left ribbon.
const ribbonIconEl = this.addRibbonIcon('dice', 'Sample Plugin', (evt: MouseEvent) => {
// Called when the user clicks the icon.
new Notice('This is a notice!');
});
// Perform additional things with the ribbon
ribbonIconEl.addClass('my-plugin-ribbon-class');
// This adds a status bar item to the bottom of the app. Does not work on mobile apps.
const statusBarItemEl = this.addStatusBarItem();
statusBarItemEl.setText('Status Bar Text');
this.addCommand({
id: 'set-prio',
name: 'Set priority',
@ -124,20 +110,4 @@ export default class PrioPlugin extends Plugin {
}
}
class SampleModal extends Modal {
constructor(app: App) {
super(app);
}
onOpen() {
const {contentEl} = this;
contentEl.setText('Woah!');
}
onClose() {
const {contentEl} = this;
contentEl.empty();
}
}

View file

@ -1,11 +1,11 @@
{
"id": "obsidian-prio-plugin",
"name": "Obsidian Prio Plugin",
"id": "prioritize",
"name": "Prioritize",
"version": "1.0.0",
"minAppVersion": "0.15.0",
"description": "A plugin to prioritize your tasks and notes in Obsidian",
"description": "Prioritize your tasks and notes in Obsidian.",
"author": "EloiMusk",
"authorUrl": "https://github.com/EloiMusk/",
"fundingUrl": "",
"fundingUrl": "https://www.buymeacoffee.com/eloimusk",
"isDesktopOnly": true
}

View file

@ -1,7 +1,7 @@
/*Preset list setting*/
.preset-list {
display: flex;
flex-wrap: nowrap;
flex-flow: column nowrap;
width: 100%;
border: 1px solid var(--color-base-10);
box-shadow: inset var(--shadow-stationary);
@ -87,3 +87,51 @@
}
/*---------------------*/
/*Preset Modal*/
.preset-modal {
display: flex;
flex-flow: column nowrap;
width: 100%;
padding: 10px;
}
.preset-modal-title {
margin: 5px;
}
.preset-input {
margin: 5px;
}
.preset-save-btn-group {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
width: 100%;
}
/*---------------------*/
/*Save confirm modal*/
.save-confirm-modal{
display: flex;
flex-flow: column nowrap;
width: 100%;
padding: 10px;
}
.save-confirm-modal-title {
}
.save-confirm-modal-text {
margin: 5px;
}
.save-btn-group {
display: flex;
flex-flow: row nowrap;
justify-content: space-between;
width: 100%;
}
/*---------------------*/

View file

@ -6,16 +6,19 @@ import {PrioPluginSettings} from "./Settings";
export class SettingTab extends PluginSettingTab {
plugin: PrioPlugin;
saveConfirm: SaveConfirm;
addPresetModal: AddPresetModal;
modified = false;
constructor(app: App, plugin: PrioPlugin) {
super(app, plugin);
this.plugin = plugin;
this.saveConfirm = new SaveConfirm(this);
this.addPresetModal = new AddPresetModal(this);
}
hide(): any {
hide() {
if (this.modified) {
this.saveConfirm.setSettingsTab(this);
this.saveConfirm.open();
return;
}
@ -56,11 +59,29 @@ export class SettingTab extends PluginSettingTab {
});
}
const presetListContainer = createEl('div', {
cls: 'preset-list-container',
parent: containerEl
})
const presetList = createEl('ol', {
cls: 'preset-list',
parent: containerEl
parent: presetListContainer
});
const addPresetButton = createEl('button', {
text: 'Add Preset',
cls: ['mod-cta', 'mod-primary', 'btn'],
parent: presetListContainer
});
addPresetButton.addEventListener('click', () => {
this.addPresetModal.setPresetsList(presetList);
this.addPresetModal.open();
});
this.generatePresetList(presets, presetList);
const levelSliderSetting = new Setting(containerEl);
let levelSlider: SliderComponent;
const levelText = createEl('input', {
@ -89,7 +110,6 @@ export class SettingTab extends PluginSettingTab {
this.generateLevelAliasList(this.plugin.settings, levelAliasesList, [saveButton]);
});
this.generatePresetList(presets, presetList);
levelSliderSetting
.setName('Levels')
@ -120,7 +140,7 @@ export class SettingTab extends PluginSettingTab {
containerEl.append(saveButton);
saveButton.addEventListener('click', () => {
if (!this.isValid(levelAliasesList, [saveButton])) {
if (!this.isValid(levelAliasesList)) {
return;
}
this.setAliases(this.plugin.settings, levelAliasesList);
@ -159,6 +179,9 @@ export class SettingTab extends PluginSettingTab {
})
input.addEventListener('blur', (event) => {
const valid = this.validateLevelAlias((event.target as HTMLInputElement).value, parseInt((event.target as HTMLInputElement).parentElement?.textContent ?? '') - 1, settings.levelAliases.slice(0, settings.levels));
if (valid) {
this.plugin.settings.levelAliases[parseInt((event.target as HTMLInputElement).parentElement?.textContent ?? '') - 1] = (event.target as HTMLInputElement).value;
}
for (const button of buttons) {
button.disabled = !valid;
}
@ -169,39 +192,147 @@ export class SettingTab extends PluginSettingTab {
return els;
}
generatePresetList = (presets: Preset[], presetList: HTMLOListElement) => (presets || []).map(preset => {
const el = createEl('li', {
text: preset.name,
cls: 'preset-list-item',
parent: presetList
});
const btnGroup = el.createEl('div', {
cls: 'btn-group'
});
generatePresetId = () => {
return Date.now().toString(36) + Math.random().toString(36);
}
btnGroup.createEl('button', {
text: 'Apply',
cls: ['preset-list-item-apply', 'btn', 'btn-primary'],
attr: {
'onclick': 'alert("Preset Selected")'
}
})
btnGroup.createEl('button', {
text: 'Overwrite',
cls: ['preset-list-item-save', 'btn', 'btn-primary'],
attr: {
'onclick': 'alert("Save Preset")'
}
})
return el;
});
addPreset = (name: string, settings: PrioPluginSettings, presetList: HTMLOListElement) => {
if (!name || !settings || !this.presetIsValid(name, settings.presets ?? [], this.plugin.settings.presets?.length ?? 0 - 1)) {
return;
}
isValid = (levelAliasesList: HTMLOListElement, buttons: HTMLButtonElement[]) => {
if (this.plugin.settings.presets) {
this.plugin.settings.presets.push({
id: `${this.generatePresetId()}`,
name,
settings: {
levels: this.plugin.settings.levels,
levelAliases: this.plugin.settings.levelAliases.slice(0, this.plugin.settings.levels),
}
});
} else {
this.plugin.settings.presets = [{
id: `${this.generatePresetId()}`,
name,
settings: {
levels: this.plugin.settings.levels,
levelAliases: this.plugin.settings.levelAliases.slice(0, this.plugin.settings.levels),
}
}];
}
this.generatePresetList(this.plugin.settings.presets, presetList);
this.plugin.saveSettings().then(() => {
this.plugin.loadSettings().then(() => {
new Notice('Preset applied successfully!');
});
});
this.display();
}
applyPreset = (preset: Preset, presetList: HTMLOListElement) => {
if (!preset || !presetList) {
return;
}
if (this.plugin.settings.presets) {
this.plugin.settings.levels = preset.settings.levels.valueOf();
this.plugin.settings.levelAliases = [...preset.settings.levelAliases];
}
this.generatePresetList(this.plugin.settings.presets ?? [], presetList);
this.display();
new Notice('Preset applied successfully!');
}
deletePreset = (preset: Preset, presetList: HTMLOListElement) => {
if (this.plugin.settings.presets) {
this.plugin.settings.presets.remove(preset);
}
this.generatePresetList(this.plugin.settings.presets ?? [], presetList);
this.display();
new Notice('Preset deleted successfully!');
}
overwritePreset = (preset: Preset, presetList: HTMLOListElement) => {
if (!preset || !presetList) {
return;
}
if (this.plugin.settings.presets) {
this.plugin.settings.presets[this.plugin.settings.presets.indexOf(preset)].settings.levels = this.plugin.settings.levels.valueOf();
this.plugin.settings.presets[this.plugin.settings.presets.indexOf(preset)].settings.levelAliases = [...this.plugin.settings.levelAliases];
}
this.generatePresetList(this.plugin.settings.presets ?? [], presetList);
this.display();
new Notice('Preset overwritten successfully!');
}
generatePresetList = (presets: Preset[], presetList: HTMLOListElement) => {
presetList.empty();
(presets || []).map(preset => {
const el = createEl('li', {
cls: 'preset-list-item',
parent: presetList
});
const presetListInput = el.createEl('input', {
cls: 'preset-list-item-input',
value: preset.name
});
presetListInput.addEventListener('change', (event) => {
if (
presets &&
presets.length >= presetList.children.length - 1 &&
(event.target as HTMLInputElement).parentElement &&
this.presetIsValid(
(event.target as HTMLInputElement).value,
presets,
((event.target as HTMLInputElement).parentElement as HTMLElement).indexOf((event.target as HTMLInputElement)))) {
presets[presetList.children.length - 1].name = (event.target as HTMLInputElement).value;
}
});
const btnGroup = el.createEl('div', {
cls: 'btn-group'
});
const applyButton = btnGroup.createEl('button', {
text: 'Apply',
cls: ['preset-list-item-apply', 'btn', 'btn-primary'],
})
const overwriteButton = btnGroup.createEl('button', {
text: 'Overwrite',
cls: ['preset-list-item-overwrite', 'btn', 'btn-primary'],
})
const deleteButton = btnGroup.createEl('button', {
text: 'Delete',
cls: ['preset-list-item-delete', 'btn', 'mod-danger'],
})
applyButton.addEventListener('click', () => {
this.applyPreset(preset, presetList);
});
overwriteButton.addEventListener('click', () => {
this.overwritePreset(preset, presetList);
});
deleteButton.addEventListener('click', () => {
this.deletePreset(preset, presetList);
});
return el;
});
}
isValid = (levelAliasesList: HTMLOListElement) => {
const inputs = levelAliasesList.querySelectorAll('input');
const aliases: string[] = [];
inputs.forEach(input => {
aliases.push((input as HTMLInputElement).value);
});
inputs.forEach(input => {
if (!this.validateLevelAlias((input as HTMLInputElement).value, aliases.indexOf((input as HTMLInputElement).value), aliases)) {
return false;
}
});
if (aliases.length !== new Set(aliases).size) {
new Notice('Level aliases must be unique.');
return false;
@ -228,6 +359,23 @@ export class SettingTab extends PluginSettingTab {
}
return true;
}
presetIsValid = (preset: string, presets: Preset[], index: number) => {
if (preset.length < 1) {
new Notice('Preset name must be at least 1 character long!');
return false;
}
if (preset.match(/[^a-zA-Z0-9]/)) {
new Notice('Preset name must only contain alphanumeric characters!');
return false;
}
const searchPreset = presets.find(p => p.name === preset);
if (searchPreset && presets.indexOf(searchPreset) !== index && presets.some(p => p.name === preset)) {
new Notice('Preset name already exists!');
return false;
}
return true;
}
}
class SaveConfirm extends Modal {
@ -238,13 +386,27 @@ class SaveConfirm extends Modal {
this.settingsTab = settingsTab;
}
setSettingsTab(settingsTab: SettingTab) {
this.settingsTab = settingsTab;
}
open() {
super.open();
}
onOpen() {
const {contentEl} = this;
contentEl.setText('You have unsaved changes. Would you like to save them?');
contentEl.classList.add('save-confirm-modal');
contentEl.createEl('h2', {
text: 'Unsaved Changes',
cls: 'save-confirm-title'
});
contentEl.createEl('p', {
text: 'You have unsaved changes. Would you like to save them?',
cls: 'save-confirm-text'
})
const btnGroup = contentEl.createEl('div', {
cls: 'save-btn-group'
@ -285,3 +447,74 @@ class SaveConfirm extends Modal {
this.settingsTab.modified = false;
}
}
class AddPresetModal extends Modal {
private settingsTab: SettingTab;
private presetsList: HTMLOListElement;
constructor(settingsTab: SettingTab) {
super(settingsTab.app);
this.settingsTab = settingsTab;
}
setPresetsList(presetsList: HTMLOListElement) {
this.presetsList = presetsList;
}
open() {
super.open();
}
onOpen() {
const {contentEl} = this;
contentEl.classList.add('preset-modal');
contentEl.createEl('h2', {
text: 'Add Preset',
cls: 'preset-modal-title'
})
let presetName = '';
const presetNameInput = contentEl.createEl('input', {
cls: 'preset-input',
placeholder: 'Preset Name'
});
presetNameInput.addEventListener('input', () => {
if (presetNameInput.value.length > 0) {
presetNameInput.classList.remove('invalid');
presetName = presetNameInput.value;
} else {
presetNameInput.classList.add('invalid');
}
});
const btnGroup = contentEl.createEl('div', {
cls: 'preset-save-btn-group'
});
const addButton = createEl('button', {
text: 'Add',
cls: ['btn', 'mod-cta'],
});
const cancelButton = createEl('button', {
text: 'Cancel',
cls: ['btn'],
});
addButton.addEventListener('click', () => {
this.settingsTab.addPreset(presetName, this.settingsTab.plugin.settings, this.presetsList);
this.close();
});
cancelButton.addEventListener('click', () => {
this.close();
});
btnGroup.append(addButton);
btnGroup.append(cancelButton);
}
onClose() {
const {contentEl} = this;
contentEl.empty();
}
}

View file

@ -1,7 +1,6 @@
import {Preset} from "./Presets";
export interface PrioPluginSettings {
selectedPreset?: string;
levels: number;
levelAliases: string[];
presets?: Preset[];