From 47e238ff4888b6c81405678df7c0566029b6e6e9 Mon Sep 17 00:00:00 2001 From: steeven Date: Fri, 12 Apr 2024 19:29:19 +0200 Subject: [PATCH] moved modal on expenseModal.ts. Some cosmetics: setCta & remove, add form validation before posting --- expenseModal.ts | 199 +++++++++++++++++++++++++++++++++++++++++++++++ main.ts | 202 ++++++------------------------------------------ 2 files changed, 221 insertions(+), 180 deletions(-) create mode 100644 expenseModal.ts diff --git a/expenseModal.ts b/expenseModal.ts new file mode 100644 index 0000000..2f9d14f --- /dev/null +++ b/expenseModal.ts @@ -0,0 +1,199 @@ +import { + App, + Modal, + Notice, + ButtonComponent, + MarkdownView, + Setting, +} from "obsidian"; +import budgetPlugin from "./main"; +import { DEFAULT_SETTINGS } from "./main"; + +export class ExpenseModal extends Modal { + plugin: budgetPlugin = DEFAULT_SETTINGS; + expenseAmount: string; + expenseAccount: string; + expenseCategory: string; + expenseValue: string; + + onSubmit: ( + expenseAmount: string, + expenseCategory: string, + expenseAccount: string, + expenseValue: string + ) => void; + + constructor( + app: App, + plugin: budgetPlugin, + onSubmit: ( + expenseAmount: string, + expenseCategory: string, + expenseAccount: string, + expenseValue: string + ) => void + ) { + super(app); + this.plugin = plugin; + this.onSubmit = onSubmit; + } + + async onOpen() { + const { contentEl } = this; + contentEl.createEl("h1", { text: "Enter new Expense" }); + + // get the data from the plugin settings + const pluginData = await this.plugin.loadData(); + + // create a currency formatter + // to do : get regional settings from obsidian + const formatter = new Intl.NumberFormat("fr-FR", { + style: "currency", + currency: pluginData.currency, + }); + + // input field for the expense amount + // todo: add focus on this field + new Setting(contentEl).setName("Amount").addText((text) => + text.onChange((value) => { + this.expenseAmount = value; + }) + ); + + // create category button with icon and tooltip + const categorySetting = new Setting(contentEl).setName("Category"); + + let selectedButton: ButtonComponent | null = null; + + Object.entries(pluginData.expenseCategories).forEach( + ([key, value]: [string, { icon: string; name: string }]) => { + categorySetting.addButton((btn: ButtonComponent) => + btn + .setButtonText(key) + .setIcon(value.icon) + .setTooltip(value.name) + .onClick(() => { + // remove the cta from the previous button + if (selectedButton) { + selectedButton.removeCta(); + } + selectedButton = btn; + this.expenseCategory = value.name; + new Notice(`Selected Category: ${value.name}`); + btn.setCta(); + }) + ); + } + ); + + // create account button with icon and tooltip + const accountSetting = new Setting(contentEl).setName("Account"); + + let selectedButton2: ButtonComponent | null = null; + + Object.entries(pluginData.expenseAccounts).forEach( + ([key, value]: [string, { icon: string; name: string }]) => { + accountSetting.addButton((btn: ButtonComponent) => + btn + .setButtonText(key) + .setIcon(value.icon) + .setTooltip(value.name) + .onClick(() => { + // remove the cta from the previous button + if (selectedButton2) { + selectedButton2.removeCta(); + } + selectedButton2 = btn; + this.expenseAccount = value.name; + new Notice(`Selected Account: ${value.name}`); + btn.setCta(); + }) + ); + } + ); + + const valueSetting = new Setting(contentEl).setName("Value"); + + let selectedButton3: ButtonComponent | null = null; + + Object.entries(pluginData.expenseValues).forEach( + ([key, value]: [string, { icon: string; name: string }]) => { + valueSetting.addButton((btn: ButtonComponent) => + btn + .setButtonText(key) + .setIcon(value.icon) + .setTooltip(value.name) + .onClick(() => { + // remove the cta from the previous button + if (selectedButton3) { + selectedButton3.removeCta(); + } + selectedButton3 = btn; + this.expenseValue = value.name; + new Notice(`Selected Value: ${value.name}`); + btn.setCta(); + }) + ); + } + ); + + // submit button + new Setting(contentEl).addButton((btn) => + btn + .setButtonText("Submit") + .setCta() + .onClick(() => { + // check if all fields are filled + if ( + this.expenseAmount && + this.expenseCategory && + this.expenseAccount && + this.expenseValue + ) { + new Notice("Expense added"); + this.close(); + this.onSubmit( + this.expenseAmount, + this.expenseCategory, + this.expenseAccount, + this.expenseValue + ); + const file = this.app.workspace.getActiveFile(); + if (file) { + const editor = + this.app.workspace.getActiveViewOfType( + MarkdownView + ); + if (editor) { + // get today date and format YYYY-MM-DD + const today = new Date(); + const todayFormatted = today + .toISOString() + .split("T")[0]; + + // move the cursor on start of line 3 + editor.editor.setCursor(2, 0); + // insert the new expense on line 3 + editor.editor.replaceSelection( + `| ${todayFormatted} | ${formatter.format( + Number(this.expenseAmount) + )} | ${this.expenseCategory} | ${ + this.expenseAccount + } | ${this.expenseValue} | \n` + ); + } + } else { + console.log("Debug: no active file"); + } + } else { + new Notice("Please fill all the fields"); + return; + } + }) + ); + } + onClose() { + const { contentEl } = this; + contentEl.empty(); + } +} diff --git a/main.ts b/main.ts index 4c70458..1578770 100644 --- a/main.ts +++ b/main.ts @@ -12,6 +12,7 @@ import { Setting, setIcon, } from "obsidian"; +import { ExpenseModal } from "./expenseModal"; interface BudgetSettings { expenseCategories: object; @@ -19,7 +20,7 @@ interface BudgetSettings { expenseValues: object; } -const DEFAULT_SETTINGS: BudgetSettings = { +export const DEFAULT_SETTINGS: BudgetSettings = { expenseCategories: [ { name: "Eat", icon: "carrot" }, { name: "Home", icon: "home" }, @@ -46,31 +47,27 @@ export default class budgetPlugin extends Plugin { async onload() { await this.loadSettings(); - const ribbonIconEl = this.addRibbonIcon( - "dollar-sign", - "New Expense", - (evt: MouseEvent) => { - new Notice("New Expense Modal"); - // need to start modal - new ExpenseModal( - this.app, - this, - ( - expenseAmount, - expenseCategory, - expenseAccount, - expenseValue - ) => { - new Notice( - `${expenseAmount}, ${expenseCategory}, ${expenseAccount}, ${expenseValue}` - ); - } - ).open(); + this.addRibbonIcon("dollar-sign", "New Expense", (evt: MouseEvent) => { + new Notice("New Expense Modal"); + // need to start modal + new ExpenseModal( + this.app, + this, + ( + expenseAmount, + expenseCategory, + expenseAccount, + expenseValue + ) => { + new Notice( + `${expenseAmount}, ${expenseCategory}, ${expenseAccount}, ${expenseValue}` + ); + } + ).open(); - // need to set active md file to budget - console.log("Debug: trigger new expense modal from ribbon"); - } - ); + // need to set active md file to budget + console.log("Debug: trigger new expense modal from ribbon"); + }); // Adds a setting tag so the user can configure the aspects of the plugin this.addSettingTab(new ExpenseSettingTab(this.app, this)); } @@ -90,161 +87,6 @@ export default class budgetPlugin extends Plugin { onunload(): void {} } -export class ExpenseModal extends Modal { - plugin: budgetPlugin = DEFAULT_SETTINGS; - expenseAmount: string; - expenseAccount: string; - expenseCategory: string; - expenseValue: string; - - onSubmit: ( - expenseAmount: string, - expenseCategory: string, - expenseAccount: string, - expenseValue: string - ) => void; - - constructor( - app: App, - plugin: budgetPlugin, - onSubmit: ( - expenseAmount: string, - expenseCategory: string, - expenseAccount: string, - expenseValue: string - ) => void - ) { - super(app); - this.plugin = plugin; - this.onSubmit = onSubmit; - } - - async onOpen() { - const { contentEl } = this; - contentEl.createEl("h1", { text: "Enter new Expense" }); - - // get the data from the plugin settings - const pluginData = await this.plugin.loadData(); - - // create a currency formatter - const formatter = new Intl.NumberFormat("fr-FR", { - style: "currency", - currency: pluginData.currency, - }); - - // input field for the expense amount - new Setting(contentEl).setName("Amount").addText((text) => - text.onChange((value) => { - this.expenseAmount = value; - }) - ); - - // create category button with icon and tooltip - const categorySetting = new Setting(contentEl).setName("Category"); - - Object.entries(pluginData.expenseCategories).forEach( - ([key, value]: [string, { icon: string; name: string }]) => { - categorySetting.addButton((btn: ButtonComponent) => - btn - .setButtonText(key) - .setIcon(value.icon) - .setTooltip(value.name) - .onClick(() => { - this.expenseCategory = value.name; - new Notice(`Selected Category: ${value.name}`); - btn.setCta(); - }) - ); - } - ); - - // create account button with icon and tooltip - const accountSetting = new Setting(contentEl).setName("Account"); - - Object.entries(pluginData.expenseAccounts).forEach( - ([key, value]: [string, { icon: string; name: string }]) => { - accountSetting.addButton((btn: ButtonComponent) => - btn - .setButtonText(key) - .setIcon(value.icon) - .setTooltip(value.name) - .onClick(() => { - this.expenseAccount = value.name; - new Notice(`Selected Account: ${value.name}`); - btn.setCta(); - }) - ); - } - ); - - const valueSetting = new Setting(contentEl).setName("Value"); - - Object.entries(pluginData.expenseValues).forEach( - ([key, value]: [string, { icon: string; name: string }]) => { - valueSetting.addButton((btn: ButtonComponent) => - btn - .setButtonText(key) - .setIcon(value.icon) - .setTooltip(value.name) - .onClick(() => { - this.expenseValue = value.name; - new Notice(`Selected Value: ${value.name}`); - btn.setCta(); - }) - ); - } - ); - - new Setting(contentEl).addButton((btn) => - btn - .setButtonText("Submit") - .setCta() - .onClick(() => { - this.close(); - this.onSubmit( - this.expenseAmount, - this.expenseCategory, - this.expenseAccount, - this.expenseValue - ); - const file = this.app.workspace.getActiveFile(); - if (file) { - console.log("Debug: active file", file.basename); - const editor = - this.app.workspace.getActiveViewOfType( - MarkdownView - ); - if (editor) { - console.log("Debug: active editor", editor); - // get today date and format YYYY-MM-DD - const today = new Date(); - const todayFormatted = today - .toISOString() - .split("T")[0]; - - // move the cursor on start of line 3 - editor.editor.setCursor(2, 0); - // insert the new expense on line 3 - editor.editor.replaceSelection( - `| ${todayFormatted} | ${formatter.format( - Number(this.expenseAmount) - )} | ${this.expenseCategory} | ${ - this.expenseAccount - } | ${this.expenseValue} | \n` - ); - } - } else { - console.log("Debug: no active file"); - } - }) - ); - } - onClose() { - const { contentEl } = this; - contentEl.empty(); - } -} - class ExpenseSettingTab extends PluginSettingTab { plugin: budgetPlugin;