moved modal on expenseModal.ts. Some cosmetics: setCta & remove, add form validation before posting
This commit is contained in:
parent
9d7f899386
commit
47e238ff48
|
@ -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();
|
||||||
|
}
|
||||||
|
}
|
202
main.ts
202
main.ts
|
@ -12,6 +12,7 @@ import {
|
||||||
Setting,
|
Setting,
|
||||||
setIcon,
|
setIcon,
|
||||||
} from "obsidian";
|
} from "obsidian";
|
||||||
|
import { ExpenseModal } from "./expenseModal";
|
||||||
|
|
||||||
interface BudgetSettings {
|
interface BudgetSettings {
|
||||||
expenseCategories: object;
|
expenseCategories: object;
|
||||||
|
@ -19,7 +20,7 @@ interface BudgetSettings {
|
||||||
expenseValues: object;
|
expenseValues: object;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DEFAULT_SETTINGS: BudgetSettings = {
|
export const DEFAULT_SETTINGS: BudgetSettings = {
|
||||||
expenseCategories: [
|
expenseCategories: [
|
||||||
{ name: "Eat", icon: "carrot" },
|
{ name: "Eat", icon: "carrot" },
|
||||||
{ name: "Home", icon: "home" },
|
{ name: "Home", icon: "home" },
|
||||||
|
@ -46,31 +47,27 @@ export default class budgetPlugin extends Plugin {
|
||||||
async onload() {
|
async onload() {
|
||||||
await this.loadSettings();
|
await this.loadSettings();
|
||||||
|
|
||||||
const ribbonIconEl = this.addRibbonIcon(
|
this.addRibbonIcon("dollar-sign", "New Expense", (evt: MouseEvent) => {
|
||||||
"dollar-sign",
|
new Notice("New Expense Modal");
|
||||||
"New Expense",
|
// need to start modal
|
||||||
(evt: MouseEvent) => {
|
new ExpenseModal(
|
||||||
new Notice("New Expense Modal");
|
this.app,
|
||||||
// need to start modal
|
this,
|
||||||
new ExpenseModal(
|
(
|
||||||
this.app,
|
expenseAmount,
|
||||||
this,
|
expenseCategory,
|
||||||
(
|
expenseAccount,
|
||||||
expenseAmount,
|
expenseValue
|
||||||
expenseCategory,
|
) => {
|
||||||
expenseAccount,
|
new Notice(
|
||||||
expenseValue
|
`${expenseAmount}, ${expenseCategory}, ${expenseAccount}, ${expenseValue}`
|
||||||
) => {
|
);
|
||||||
new Notice(
|
}
|
||||||
`${expenseAmount}, ${expenseCategory}, ${expenseAccount}, ${expenseValue}`
|
).open();
|
||||||
);
|
|
||||||
}
|
|
||||||
).open();
|
|
||||||
|
|
||||||
// need to set active md file to budget
|
// need to set active md file to budget
|
||||||
console.log("Debug: trigger new expense modal from ribbon");
|
console.log("Debug: trigger new expense modal from ribbon");
|
||||||
}
|
});
|
||||||
);
|
|
||||||
// Adds a setting tag so the user can configure the aspects of the plugin
|
// Adds a setting tag so the user can configure the aspects of the plugin
|
||||||
this.addSettingTab(new ExpenseSettingTab(this.app, this));
|
this.addSettingTab(new ExpenseSettingTab(this.app, this));
|
||||||
}
|
}
|
||||||
|
@ -90,161 +87,6 @@ export default class budgetPlugin extends Plugin {
|
||||||
onunload(): void {}
|
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 {
|
class ExpenseSettingTab extends PluginSettingTab {
|
||||||
plugin: budgetPlugin;
|
plugin: budgetPlugin;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue