Skip to content

Commit

Permalink
feat: add decorations for days
Browse files Browse the repository at this point in the history
  • Loading branch information
srg-kostyrko committed Sep 22, 2024
1 parent 237d296 commit 5f96aaf
Show file tree
Hide file tree
Showing 11 changed files with 107 additions and 52 deletions.
13 changes: 11 additions & 2 deletions src/components/calendar/CalendarDay.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,22 @@
<script setup lang="ts">
import { toRefs } from "vue";
import type { MomentDate } from "../../types/date.types";
defineProps<{
import { useDecorations } from "@/composables/use-decorations";
import CalendarDecoration from "./CalendarDecoration.vue";
import { decorationsForDays$ } from "@/stores/settings.store";
const props = defineProps<{
date: MomentDate;
}>();
const { date } = toRefs(props);
const decorationsStyles = useDecorations(date, decorationsForDays$);
</script>

<template>
<button>
{{ date.format("D") }}
<CalendarDecoration :styles="decorationsStyles">
{{ date.format("D") }}
</CalendarDecoration>
</button>
</template>

Expand Down
4 changes: 2 additions & 2 deletions src/components/calendar/CalendarMonthButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { useDecorations } from "@/composables/use-decorations";
import type { MomentDate } from "@/types/date.types";
import CalendarDecoration from "./CalendarDecoration.vue";
import { journalsWithMonths$ } from "@/stores/settings.store";
import { decorationsForMonths$, journalsWithMonths$ } from "@/stores/settings.store";
import ObsidianButton from "../obsidian/ObsidianButton.vue";
import { toRefs } from "vue";
Expand All @@ -12,7 +12,7 @@ const props = defineProps<{
const { date } = toRefs(props);
const emit = defineEmits<(e: "select", event: MouseEvent, date: MomentDate) => void>();
const decorationsStyles = useDecorations(date, journalsWithMonths$);
const decorationsStyles = useDecorations(date, decorationsForMonths$);
function select(event: MouseEvent) {
if (!journalsWithMonths$.value.length) {
return;
Expand Down
4 changes: 2 additions & 2 deletions src/components/calendar/CalendarQuarterButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { useDecorations } from "@/composables/use-decorations";
import type { MomentDate } from "@/types/date.types";
import CalendarDecoration from "./CalendarDecoration.vue";
import { journalsWithQuarters$ } from "@/stores/settings.store";
import { decorationsForQuarters$, journalsWithQuarters$ } from "@/stores/settings.store";
import ObsidianButton from "../obsidian/ObsidianButton.vue";
import { toRefs } from "vue";
Expand All @@ -12,7 +12,7 @@ const props = defineProps<{
const { date } = toRefs(props);
const emit = defineEmits<(e: "select", event: MouseEvent, date: MomentDate) => void>();
const decorationsStyles = useDecorations(date, journalsWithQuarters$);
const decorationsStyles = useDecorations(date, decorationsForQuarters$);
function select(event: MouseEvent) {
if (!journalsWithQuarters$.value.length) {
return;
Expand Down
4 changes: 2 additions & 2 deletions src/components/calendar/CalendarWeekNumber.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,14 @@
import { useDecorations } from "@/composables/use-decorations";
import type { MomentDate } from "@/types/date.types";
import CalendarDecoration from "./CalendarDecoration.vue";
import { journalsWithWeeks$ } from "@/stores/settings.store";
import { decorationsForWeeks$ } from "@/stores/settings.store";
import { toRefs } from "vue";
const props = defineProps<{
date: MomentDate;
}>();
const { date } = toRefs(props);
const decorationsStyles = useDecorations(date, journalsWithWeeks$);
const decorationsStyles = useDecorations(date, decorationsForWeeks$);
</script>

<template>
Expand Down
4 changes: 2 additions & 2 deletions src/components/calendar/CalendarYearButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { useDecorations } from "@/composables/use-decorations";
import type { MomentDate } from "@/types/date.types";
import CalendarDecoration from "./CalendarDecoration.vue";
import { journalsWithYears$ } from "@/stores/settings.store";
import { decorationsForYears$, journalsWithYears$ } from "@/stores/settings.store";
import ObsidianButton from "../obsidian/ObsidianButton.vue";
import { toRefs } from "vue";
Expand All @@ -12,7 +12,7 @@ const props = defineProps<{
const { date } = toRefs(props);
const emit = defineEmits<(e: "select", event: MouseEvent, date: MomentDate) => void>();
const decorationsStyles = useDecorations(date, journalsWithYears$);
const decorationsStyles = useDecorations(date, decorationsForYears$);
function select(event: MouseEvent) {
if (!journalsWithYears$.value.length) {
return;
Expand Down
2 changes: 1 addition & 1 deletion src/components/modals/EditDecoration.modal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ const conditionTypes = computed(() => {
if (props.writeType.type === "day") {
return ["title", "tag", "property", "date", "weekday", "has-note", "has-open-task", "all-tasks-completed"] as const;
}
return ["title", "tag", "property", "offset", "has-note", "has-open-task", "all-tasks-completed"] as const;
return ["title", "tag", "property", "has-note", "has-open-task", "all-tasks-completed"] as const;
});
const conditions = ref<JournalDecorationCondition[]>(props.decoration ? deepCopy(props.decoration.conditions) : []);
Expand Down
91 changes: 50 additions & 41 deletions src/composables/use-decorations.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type { MomentDate } from "@/types/date.types";
import type {
JournalDecoration,
JournalDecorationCondition,
JournalDecorationDateCondition,
JournalDecorationOffsetCondition,
Expand All @@ -9,59 +10,70 @@ import type {
JournalDecorationTitleCondition,
JournalDecorationWeekdayCondition,
} from "@/types/settings.types";
import { computed, toRef, type ComputedRef, type MaybeRefOrGetter } from "vue";
import { computed, toRef, unref, type ComputedRef, type MaybeRefOrGetter } from "vue";
import { useJournalDate } from "./use-journal-date";
import type { JournalNoteData } from "@/types/journal.types";
import { pluginSettings$ } from "@/stores/settings.store";
import { useJournal } from "./use-journal";

export function useDecorations(
date: MaybeRefOrGetter<MomentDate>,
journals: MaybeRefOrGetter<string[]>,
dateRef: MaybeRefOrGetter<MomentDate>,
decorationsList: MaybeRefOrGetter<
{
journalName: string;
decoration: JournalDecoration;
}[]
>,
): ComputedRef<JournalDecorationsStyle[]> {
const _date = toRef(date);
const _journals = toRef(journals);
const _date = unref(dateRef);
const _decorationsList = toRef(decorationsList);
return computed(() => {
return _journals.value
.map((journal) => {
return useJournalDecorations(_date, journal).value;
return _decorationsList.value
.map(({ journalName, decoration }) => {
return useJournalDecorations(_date, journalName, decoration).value;
})
.flat();
});
}

export function useJournalDecorations(
date: MaybeRefOrGetter<MomentDate>,
journalName: MaybeRefOrGetter<string>,
journalName: string,
decoration: MaybeRefOrGetter<JournalDecoration>,
): ComputedRef<JournalDecorationsStyle[]> {
const _date = toRef(date);
const _journalName = toRef(journalName);
const _journalSettings = computed(() => pluginSettings$.value.journals[_journalName.value]);
const _decoration = toRef(decoration);

return computed(() => {
const { noteData } = useJournalDate(_date, _journalName.value);
return _journalSettings.value.decorations
.filter((decoration) => {
return checkDecorationConditions(_date.value, noteData.value, decoration.mode, decoration.conditions);
})
.map((decoration) => {
return decoration.styles;
})
.flat();
const { noteData } = useJournalDate(_date, _journalName);
return checkDecorationConditions(
_date.value,
_journalName.value,
noteData.value,
_decoration.value.mode,
_decoration.value.conditions,
)
? _decoration.value.styles
: [];
});
}

function checkDecorationConditions(
date: MomentDate,
journalName: string,
noteDate: JournalNoteData | null,
mode: "and" | "or",
conditions: JournalDecorationCondition[],
): boolean {
if (conditions.length === 0) return false;
if (mode === "or") return conditions.some((condition) => checkDecorationCondition(date, noteDate, condition));
return conditions.every((condition) => checkDecorationCondition(date, noteDate, condition));
if (mode === "or")
return conditions.some((condition) => checkDecorationCondition(date, journalName, noteDate, condition));
return conditions.every((condition) => checkDecorationCondition(date, journalName, noteDate, condition));
}

function checkDecorationCondition(
date: MomentDate,
journalName: string,
noteData: JournalNoteData | null,
condition: JournalDecorationCondition,
): boolean {
Expand All @@ -71,13 +83,13 @@ function checkDecorationCondition(
case "tag":
return checkDecorationTagCondition(noteData, condition);
case "date":
return checkDecorationDateCondition(date, noteData, condition);
return checkDecorationDateCondition(date, condition);
case "property":
return checkDecorationPropertyCondition(noteData, condition);
case "weekday":
return checkDecorationWeekdayCondition(date, noteData, condition);
return checkDecorationWeekdayCondition(date, condition);
case "offset":
return checkDecorationOffsetCondition(date, noteData, condition);
return checkDecorationOffsetCondition(date, journalName, condition);
case "all-tasks-completed":
return checkDecorationAllTasksCompletedCondition(noteData);
case "has-note":
Expand Down Expand Up @@ -124,12 +136,11 @@ function checkDecorationTagCondition(
}
}

function checkDecorationDateCondition(
_date: MomentDate,
_noteDate: JournalNoteData | null,
_condition: JournalDecorationDateCondition,
): boolean {
return false;
function checkDecorationDateCondition(date: MomentDate, condition: JournalDecorationDateCondition): boolean {
if (condition.day !== -1 && date.date() !== condition.day) return false;
if (condition.month !== -1 && date.month() !== condition.month) return false;
if (condition.year && date.year() !== condition.year) return false;
return true;
}

function checkDecorationPropertyCondition(
Expand Down Expand Up @@ -189,20 +200,18 @@ function checkDecorationPropertyCondition(
return false;
}

function checkDecorationWeekdayCondition(
_date: MomentDate,
_noteDate: JournalNoteData | null,
_condition: JournalDecorationWeekdayCondition,
): boolean {
return false;
function checkDecorationWeekdayCondition(date: MomentDate, condition: JournalDecorationWeekdayCondition): boolean {
return condition.weekdays.includes(date.day());
}

function checkDecorationOffsetCondition(
_date: MomentDate,
_noteDate: JournalNoteData | null,
_condition: JournalDecorationOffsetCondition,
date: MomentDate,
journalName: string,
condition: JournalDecorationOffsetCondition,
): boolean {
return false;
const [positive, negative] = useJournal(journalName).value?.calculateOffset(date) ?? [0, 0];
if (condition.offset < 0) return negative === condition.offset;
return positive === condition.offset;
}

function checkDecorationAllTasksCompletedCondition(noteDate: JournalNoteData | null): boolean {
Expand Down
10 changes: 10 additions & 0 deletions src/journals/fixed-interval.ts
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,16 @@ export class FixedIntervalResolver implements AnchorDateResolver {
return Math.ceil(start.diff(end, this.#settings.value.type));
}

calculateOffset(date: MomentDate): [positive: number, negative: number] {
const anchorDate = this.#resolveAnchorDate(date);
if (!anchorDate) return [0, 0];
const start = date_from_string(anchorDate).startOf(this.#settings.value.type);
const end = start.clone().endOf(this.#settings.value.type);

if (date.isBefore(start) || date.isAfter(end)) return [0, 0];
return [start.diff(date, "days"), end.diff(date, "days")];
}

#resolveAnchorDate(base: MomentDate): JournalAnchorDate {
const type = this.#settings.value.type;
const start_date = base.startOf(type);
Expand Down
5 changes: 5 additions & 0 deletions src/journals/journal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { FixedIntervalResolver } from "./fixed-interval";
import { date_from_string, today } from "../calendar";
import { VueModal } from "@/components/modals/vue-modal";
import ConfirmNoteCreationModal from "@/components/modals/ConfirmNoteCreation.modal.vue";
import type { MomentDate } from "@/types/date.types";

export class Journal {
readonly name$: ComputedRef<string>;
Expand All @@ -34,6 +35,10 @@ export class Journal {
);
}

calculateOffset(date: MomentDate): [positive: number, negative: number] {
return this.#anchorDateResolver.calculateOffset(date);
}

registerCommands(): void {
for (const command of this.#config.value.commands) {
plugin$.value.addCommand({
Expand Down
20 changes: 20 additions & 0 deletions src/stores/settings.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,23 @@ export const journalsWithQuarters$ = computed(() => {
export const journalsWithYears$ = computed(() => {
return journalsList$.value.filter((journal) => journal.write.type === "year").map((journal) => journal.name);
});

function decorationsForType(type: "day" | "week" | "month" | "quarter" | "year") {
return computed(() => {
return journalsList$.value
.filter((journal) => journal.write.type === type)
.map((journal) =>
journal.decorations.map((decoration) => ({
journalName: journal.name,
decoration,
})),
)
.flat();
});
}

export const decorationsForDays$ = decorationsForType("day");
export const decorationsForWeeks$ = decorationsForType("week");
export const decorationsForMonths$ = decorationsForType("month");
export const decorationsForQuarters$ = decorationsForType("quarter");
export const decorationsForYears$ = decorationsForType("year");
2 changes: 2 additions & 0 deletions src/types/journal.types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { MomentDate } from "./date.types";
import type { JournalCommand } from "./settings.types";

export type JournalAnchorDate = string & { _journal_anchor_date: true };
Expand Down Expand Up @@ -34,5 +35,6 @@ export interface AnchorDateResolver {
resolveStartDate(anchorDate: JournalAnchorDate): string;
resolveEndDate(anchorDate: JournalAnchorDate): string;

calculateOffset(date: MomentDate): [positive: number, negative: number];
countRepeats(startDate: string, endDate: string): number;
}

0 comments on commit 5f96aaf

Please sign in to comment.