Skip to content

Commit

Permalink
feat: add start/end setting to journal
Browse files Browse the repository at this point in the history
  • Loading branch information
srg-kostyrko committed Aug 26, 2024
1 parent 47d44e5 commit df2b945
Show file tree
Hide file tree
Showing 8 changed files with 85 additions and 16 deletions.
12 changes: 11 additions & 1 deletion src/components/obsidian/ObsidianNumberInput.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,21 @@
defineProps<{
placeholder?: string;
disabled?: boolean;
min?: number;
max?: number;
}>();
const model = defineModel<number>();
</script>

<template>
<input v-model="model" type="number" :placeholder="placeholder" :disabled="disabled" spellcheck="false" />
<input
v-model="model"
type="number"
:placeholder="placeholder"
:disabled="disabled"
:min="min"
:max="max"
spellcheck="false"
/>
</template>
5 changes: 1 addition & 4 deletions src/defaults.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,7 @@ export const defaultJournalSettings: JournalSettings = {
folder: "",
templates: [],

start: {
enabled: false,
date: "",
},
start: "",

end: {
type: "never",
Expand Down
7 changes: 7 additions & 0 deletions src/journals/fixed-interval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type { IntervalResolver, JournalInterval } from "../types/journal.types";
import type { FixedWriteIntervals, JournalCommand } from "../types/settings.types";
import { FRONTMATTER_DATE_FORMAT } from "../constants";
import type { MomentDate } from "../types/date.types";
import { date } from "../calendar";

// TODO: write tests
export class FixedInterval implements IntervalResolver {
Expand Down Expand Up @@ -57,6 +58,12 @@ export class FixedInterval implements IntervalResolver {
return null;
}

countRepeats(startDate: string, endDate: string): number {
const start = date(startDate);
const end = date(endDate);
return Math.ceil(start.diff(end, this.#settings.value.type));
}

#buildInterval(base: MomentDate): JournalInterval {
const type = this.#settings.value.type;
const start_date = base.startOf(type).format(FRONTMATTER_DATE_FORMAT);
Expand Down
23 changes: 22 additions & 1 deletion src/journals/journal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import {
FRONTMATTER_START_DATE_KEY,
} from "../constants";
import { FixedInterval } from "./fixed-interval";
import { today } from "../calendar";
import { date, today } from "../calendar";

export class Journal {
#config: ComputedRef<JournalSettings>;
Expand Down Expand Up @@ -67,6 +67,7 @@ export class Journal {
if (metadata) return metadata;
const interval = this.#intervalResolver.resolveForDate(date);
if (!interval) return null;
if (!this.#checkBounds(interval)) return null;
return await this.#buildMetadata(interval);
}

Expand All @@ -79,6 +80,7 @@ export class Journal {
if (!interval) return null;
const nextMetadata = plugin$.value.index.find(this.id, interval.start_date);
if (nextMetadata) return nextMetadata;
if (!this.#checkBounds(interval)) return null;
return await this.#buildMetadata(interval);
}

Expand All @@ -91,6 +93,7 @@ export class Journal {
if (!interval) return null;
const previousMetadata = plugin$.value.index.find(this.id, interval.end_date);
if (previousMetadata) return previousMetadata;
if (!this.#checkBounds(interval)) return null;
return await this.#buildMetadata(interval);
}

Expand Down Expand Up @@ -229,4 +232,22 @@ export class Journal {
if (command.context === "only_open_note") return null;
return today().format(FRONTMATTER_DATE_FORMAT);
}

#checkBounds(interval: JournalInterval): boolean {
if (this.#config.value.start) {
const startDate = date(this.#config.value.start);
if (startDate.isValid() && date(interval.end_date).isBefore(startDate)) return false;
}

if (this.#config.value.end.type === "date" && this.#config.value.end.date) {
const endDate = date(this.#config.value.end.date);
if (endDate.isValid() && date(interval.start_date).isAfter(endDate)) return false;
}
if (this.#config.value.end.type === "repeats" && this.#config.value.end.repeats && this.#config.value.start) {
const repeats = this.#intervalResolver.countRepeats(this.#config.value.start, interval.start_date);
if (repeats > this.#config.value.end.repeats) return false;
}

return true;
}
}
5 changes: 0 additions & 5 deletions src/settings/JournalSettingsDashboard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import type { JournalSettings, NotesProcessing } from "../types/settings.types";
import { plugin$ } from "../stores/obsidian.store";
import { updateLocale } from "../calendar";
import DatePicker from "../components/DatePicker.vue";
const emit = defineEmits<(event: "edit", id: string) => void>();
const fow = moment().localeData().firstDayOfWeek();
Expand Down Expand Up @@ -61,9 +59,6 @@ function remove(id: string): void {
</script>

<template>
<ObsidianSetting>
<DatePicker />
</ObsidianSetting>
<ObsidianSetting name="Start week on" description="Which day to consider as first day of week.">
<ObsidianDropdown v-model="weekStart">
<option value="-1">Locale default ({{ fowText }})</option>
Expand Down
42 changes: 41 additions & 1 deletion src/settings/JournalSettingsEdit.vue
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<script setup lang="ts">
import { computed } from "vue";
import { computed, watch } from "vue";
import { journals$, pluginSettings$ } from "../stores/settings.store";
import { app$ } from "../stores/obsidian.store";
import { canApplyTemplater } from "../utils/template";
import type { JournalCommand } from "../types/settings.types";
import ObsidianSetting from "../components/obsidian/ObsidianSetting.vue";
import ObsidianTextInput from "../components/obsidian/ObsidianTextInput.vue";
import ObsidianNumberInput from "../components/obsidian/ObsidianNumberInput.vue";
import ObsidianIconButton from "../components/obsidian/ObsidianIconButton.vue";
import ObsidianButton from "../components/obsidian/ObsidianButton.vue";
import ObsidianDropdown from "../components/obsidian/ObsidianDropdown.vue";
Expand All @@ -14,6 +15,7 @@ import DateFormatPreview from "../components/DateFormatPreview.vue";
import VariableReferenceHint from "../components/VariableReferenceHint.vue";
import EditCommandModal from "./EditCommand.modal.vue";
import { VueModal } from "../components/modals/vue-modal";
import DatePicker from "../components/DatePicker.vue";
const props = defineProps<{
journalId: string;
Expand Down Expand Up @@ -48,6 +50,15 @@ function deleteCommand(index: number): void {
journal.value.commands.splice(index, 1);
pluginSettings$.value.showReloadHint = true;
}
watch(
() => journal.value.end.type,
() => {
if (journal.value.end.type === "repeats" && !journal.value.end.repeats) {
journal.value.end.repeats = 1;
}
},
);
</script>

<template>
Expand All @@ -58,10 +69,39 @@ function deleteCommand(index: number): void {
</template>
<ObsidianIconButton icon="chevron-left" tooltip="Back to list" @click="$emit('back')" />
</ObsidianSetting>

<ObsidianSetting name="Journal name">
<ObsidianTextInput v-model="journal.name" />
</ObsidianSetting>

<ObsidianSetting name="Start writing on">
<template #description>
New notes prior to this date won't be created.
<div v-if="journal.end.type === 'repeats' && !journal.start" class="journal-important">
Start date should be defined for journal that ends after some number of repeats.
</div>
</template>
<DatePicker v-model="journal.start" />
<ObsidianIconButton v-if="journal.start" icon="trash" tooltip="Clear start date" @click="journal.start = ''" />
</ObsidianSetting>

<ObsidianSetting name="End writing">
<template #description>
<div v-if="journal.end.type === 'repeats'">After creating this many notes, new notes won't be created.</div>
<div v-if="journal.end.type === 'date'">New notes after this date won't be created.</div>
</template>
<ObsidianDropdown v-model="journal.end.type">
<option value="never">Never</option>
<option value="date">After date</option>
<option value="repeats">After repeating</option>
</ObsidianDropdown>
<DatePicker v-if="journal.end.type === 'date'" v-model="journal.end.date" />
<template v-if="journal.end.type === 'repeats'">
<ObsidianNumberInput v-model="journal.end.repeats" :min="1" />
times
</template>
</ObsidianSetting>

<ObsidianSetting name="Open note">
<ObsidianDropdown v-model="journal.openMode">
<option value="active">Replacing active note</option>
Expand Down
2 changes: 2 additions & 0 deletions src/types/journal.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,4 +19,6 @@ export interface IntervalResolver {
resolveNext(date: string): JournalInterval | null;
resolvePrevious(date: string): JournalInterval | null;
resolveDateForCommand(date: string, command: JournalCommand["type"]): string | null;

countRepeats(startDate: string, endDate: string): number;
}
5 changes: 1 addition & 4 deletions src/types/settings.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,7 @@ export interface JournalSettings {
folder: string;
templates: string[];

start: {
enabled: boolean;
date: string;
};
start: string;

end: EndWritingNever | EndWritingDate | EndWritingAfterNTimes;

Expand Down

0 comments on commit df2b945

Please sign in to comment.