mirror of
https://github.com/jacobtread/obsidian-timekeep.git
synced 2026-07-22 10:10:27 +00:00
321 lines
8.6 KiB
TypeScript
321 lines
8.6 KiB
TypeScript
import { Store } from "@/store";
|
|
import TimekeepPlugin from "@/main";
|
|
import { App, Setting, PluginSettingTab } from "obsidian";
|
|
import {
|
|
SortOrder,
|
|
DurationFormat,
|
|
UnstartedOrder,
|
|
defaultSettings,
|
|
TimekeepSettings,
|
|
PdfExportBehavior,
|
|
} from "@/settings";
|
|
|
|
export class TimekeepSettingsTab extends PluginSettingTab {
|
|
settingsStore: Store<TimekeepSettings>;
|
|
|
|
constructor(app: App, plugin: TimekeepPlugin) {
|
|
super(app, plugin);
|
|
|
|
this.settingsStore = plugin.settingsStore;
|
|
}
|
|
|
|
display(): void {
|
|
this.containerEl.empty();
|
|
this.containerEl.createEl("h2", { text: "Settings" });
|
|
|
|
const settings = this.settingsStore.getState();
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("Timestamp display format")
|
|
.setDesc(
|
|
createFragment((f) => {
|
|
f.createSpan({
|
|
text: "The way that timestamps in time tracker tables should be displayed. Uses ",
|
|
});
|
|
f.createEl("a", {
|
|
text: "moment.js",
|
|
href: "https://momentjs.com/docs/#/parsing/string-format/",
|
|
});
|
|
f.createSpan({ text: " syntax." });
|
|
})
|
|
)
|
|
.addText((t) => {
|
|
t.setValue(String(settings.timestampFormat));
|
|
t.onChange((v) => {
|
|
// Only use a custom format if the value is not blank
|
|
const newFormat = v.length
|
|
? v
|
|
: defaultSettings.timestampFormat;
|
|
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
timestampFormat: newFormat,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("PDF title")
|
|
.setDesc("The title to include on generated PDFs")
|
|
|
|
.addText((t) => {
|
|
t.setValue(String(settings.pdfTitle));
|
|
t.onChange((v) => {
|
|
// Only use a custom format if the value is not blank
|
|
const newPdfTitle = v.length ? v : defaultSettings.pdfTitle;
|
|
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
pdfTitle: newPdfTitle,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("PDF footnote")
|
|
.setDesc("The footnote to include PDFs")
|
|
|
|
.addTextArea((t) => {
|
|
t.setValue(String(settings.pdfFootnote));
|
|
t.onChange((v) => {
|
|
// Only use a custom format if the value is not blank
|
|
const newPdfFootnote = v.length
|
|
? v
|
|
: defaultSettings.pdfFootnote;
|
|
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
pdfFootnote: newPdfFootnote,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("PDF export behavior")
|
|
.setDesc("What to do after a pdf file has been exported")
|
|
|
|
.addDropdown((t) => {
|
|
t.addOptions({
|
|
[PdfExportBehavior.NONE]: "Do nothing",
|
|
[PdfExportBehavior.OPEN_FILE]:
|
|
"Open exported file with default app",
|
|
[PdfExportBehavior.OPEN_PATH]:
|
|
"Open directory containing the exported file",
|
|
});
|
|
t.setValue(String(settings.pdfExportBehavior));
|
|
t.onChange((v) => {
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
pdfExportBehavior: v as PdfExportBehavior,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("Pdf date format")
|
|
.setDesc(
|
|
createFragment((f) => {
|
|
f.createSpan({
|
|
text: "The way the date at the top of the pdf is formatted. Uses ",
|
|
});
|
|
f.createEl("a", {
|
|
text: "moment.js",
|
|
href: "https://momentjs.com/docs/#/parsing/string-format/",
|
|
});
|
|
f.createSpan({ text: " syntax." });
|
|
})
|
|
)
|
|
.addText((t) => {
|
|
t.setValue(String(settings.pdfDateFormat));
|
|
t.onChange((v) => {
|
|
// Only use a custom format if the value is not blank
|
|
const newPdfDateFormat = v.length
|
|
? v
|
|
: defaultSettings.pdfDateFormat;
|
|
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
pdfDateFormat: newPdfDateFormat,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("Pdf row date format")
|
|
.setDesc(
|
|
createFragment((f) => {
|
|
f.createSpan({
|
|
text: "The way the date for each row of the pdf is formatted. Uses ",
|
|
});
|
|
f.createEl("a", {
|
|
text: "moment.js",
|
|
href: "https://momentjs.com/docs/#/parsing/string-format/",
|
|
});
|
|
f.createSpan({ text: " syntax." });
|
|
})
|
|
)
|
|
.addText((t) => {
|
|
t.setValue(String(settings.pdfRowDateFormat));
|
|
t.onChange((v) => {
|
|
// Only use a custom format if the value is not blank
|
|
const newPdfRowDateFormat = v.length
|
|
? v
|
|
: defaultSettings.pdfRowDateFormat;
|
|
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
pdfRowDateFormat: newPdfRowDateFormat,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("CSV heading row")
|
|
.setDesc(
|
|
"Whether to use the first row of generated CSV as a title row"
|
|
)
|
|
.addToggle((t) => {
|
|
t.setValue(settings.csvTitle);
|
|
t.onChange((v) => {
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
csvTitle: v,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("CSV delimiter")
|
|
.setDesc(
|
|
"The delimiter character that should be used when copying a tracker table as CSV. For example, some languages use a semicolon instead of a comma."
|
|
)
|
|
.addText((t) => {
|
|
t.setValue(String(settings.csvDelimiter));
|
|
t.onChange((v) => {
|
|
const newCsvDelimiter = v.length
|
|
? v
|
|
: defaultSettings.csvDelimiter;
|
|
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
csvDelimiter: newCsvDelimiter,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("Show decimal hours")
|
|
.setDesc(
|
|
"Whether to show the shortened hour only durations under the current and total timers (12h 8m 39s would be shown as 12.14h)"
|
|
)
|
|
.addToggle((t) => {
|
|
t.setValue(settings.showDecimalHours);
|
|
t.onChange((v) => {
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
showDecimalHours: v,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("Sort order")
|
|
.setDesc(
|
|
"How entries should be sorted both when viewing and exporting"
|
|
)
|
|
|
|
.addDropdown((t) => {
|
|
t.addOptions({
|
|
[SortOrder.INSERTION]:
|
|
"Insertion - Don't sort, leave entries in the order they were created",
|
|
[SortOrder.REVERSE_INSERTION]:
|
|
"Reverse Insertion - Opposite order to how entries were inserted",
|
|
[SortOrder.NEWEST_START]:
|
|
"Newest First - Sort most recently started entries to the start",
|
|
[SortOrder.OLDEST_START]:
|
|
"Newest Last - Sort most recently started entries to the end",
|
|
});
|
|
t.setValue(String(settings.sortOrder));
|
|
t.onChange((v) => {
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
sortOrder: v as SortOrder,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("Unstarted Sort order")
|
|
.setDesc(
|
|
"Where in the order should unstarted entries be put (Only applied when using 'Newest First' or 'Newest Last' sort order)"
|
|
)
|
|
|
|
.addDropdown((t) => {
|
|
t.addOptions({
|
|
[UnstartedOrder.FIRST]:
|
|
"First - Put non started entries at the top of the list",
|
|
[UnstartedOrder.LAST]:
|
|
"Last - Put non started entries at the bottom of the list",
|
|
});
|
|
t.setValue(String(settings.unstartedOrder));
|
|
t.onChange((v) => {
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
unstartedOrder: v as UnstartedOrder,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("Limit table height")
|
|
.setDesc(
|
|
"Whether to limit the height of the table, will clamp the height and make the table scrollable"
|
|
)
|
|
.addToggle((t) => {
|
|
t.setValue(settings.limitTableSize);
|
|
t.onChange((v) => {
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
limitTableSize: v,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("CSV/Markdown duration format")
|
|
.setDesc("Format to show durations as when copying as CSV/Markdown")
|
|
|
|
.addDropdown((t) => {
|
|
t.addOptions({
|
|
[DurationFormat.LONG]:
|
|
"Long - Format including all units (1h 30m 25s)",
|
|
[DurationFormat.SHORT]:
|
|
"Short - Format just including hours (1.5h)",
|
|
[DurationFormat.DECIMAL]:
|
|
"Decimal - Short format without units (1.5)",
|
|
});
|
|
t.setValue(String(settings.exportDurationFormat));
|
|
t.onChange((v) => {
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
exportDurationFormat: v as DurationFormat,
|
|
}));
|
|
});
|
|
});
|
|
|
|
new Setting(this.containerEl)
|
|
.setName("Format copied JSON")
|
|
.setDesc(
|
|
"Whether to format the JSON contents before copying them to clipboard."
|
|
)
|
|
.addToggle((t) => {
|
|
t.setValue(settings.formatCopiedJSON);
|
|
t.onChange((v) => {
|
|
this.settingsStore.setState((currentValue) => ({
|
|
...currentValue,
|
|
formatCopiedJSON: v,
|
|
}));
|
|
});
|
|
});
|
|
}
|
|
}
|