fix: routine properties의 finished를 enable로 변경하고 delete를 복구

This commit is contained in:
sechan100 2024-12-26 22:58:34 +09:00
parent db402b97ef
commit f12e70530f
6 changed files with 65 additions and 42 deletions

View file

@ -25,19 +25,16 @@ const validateName = ({
*/
const validateRoutineProperties = (p: any): Result<RoutineProperties, string> => {
if(typeof p !== 'object'){
return err('RoutineProperties validation target is not object.');
}
const propsErr = (propertyName: string, value: any, msg?: string): Err<RoutineProperties, string> => {
return err(`[Invalid RoutineProperties]: ${msg??"invalid format"}(${propertyName}: ${value})`);
return err('Internal error: Invalid frontmatter format');
}
if(
'order' in p &&
typeof p.order === 'number'
){
if(p.order < 0) return propsErr('order', p.order, "Order must be a non-negative integer.");
if(p.order < 0) return err("Order must be a non-negative integer.");
} else {
return propsErr('order', p.order);
return err("property 'order' is missing or not a number.");
}
if(
@ -46,7 +43,7 @@ const validateRoutineProperties = (p: any): Result<RoutineProperties, string> =>
){
//
} else {
return propsErr('group', p.group);
return err("property 'group' is missing or not a existing group name.");
}
if(
@ -55,16 +52,16 @@ const validateRoutineProperties = (p: any): Result<RoutineProperties, string> =>
){
//
} else {
return propsErr('showOnCalendar', p.showOnCalendar);
return err("property 'showOnCalendar' is missing or not a boolean.");
}
if(
'activeCriteria' in p &&
typeof p.activeCriteria === 'string'
){
if(!["week", "month"].includes(p.activeCriteria)) return propsErr('activeCriteria', p.activeCriteria);
if(!["week", "month"].includes(p.activeCriteria)) return err("property 'activeCriteria' must be either 'week' or 'month'");
} else {
return propsErr('activeCriteria', p.activeCriteria);
return err("property 'activeCriteria' is missing or not a string.");
}
if(
@ -72,11 +69,10 @@ const validateRoutineProperties = (p: any): Result<RoutineProperties, string> =>
Array.isArray(p.daysOfWeek)
){
for(const d of p.daysOfWeek){
if(typeof d !== 'string') return propsErr('daysOfWeek', p.daysOfWeek, `Invalid day of week: ${d}`);
if(!keys(DayOfWeek).includes(d)) return propsErr('daysOfWeek', p.daysOfWeek, `Invalid day of week: ${d}`);
if(!keys(DayOfWeek).includes(d)) return err(`Invalid property 'dayOfWeek': ${d}`);
}
} else {
return propsErr('daysOfWeek', p.daysOfWeek);
return err("property 'daysOfWeek' is missing or not an array of dayOfWeek.");
}
if(
@ -84,20 +80,20 @@ const validateRoutineProperties = (p: any): Result<RoutineProperties, string> =>
Array.isArray(p.daysOfMonth)
){
for(const d of p.daysOfMonth){
if(typeof d !== 'number') return propsErr('daysOfMonth', p.daysOfMonth, `Invalid day of month: ${d}`);
if(d < 0 || d > 31) return propsErr('daysOfMonth', p.daysOfMonth, `Range of day of month is 0~31: ${d}`);
if(typeof d !== 'number') return err(`property 'DayOfMonth' must be a number: ${d}`);
if(d < 0 || d > 31) return err(`property 'DayOfMonth' must be between 0 and 31: ${d}`);
}
} else {
return propsErr('daysOfMonth', p.daysOfMonth);
return err("property 'daysOfMonth' is missing or not an array of number.");
}
if(
'finished' in p &&
typeof p.finished === 'boolean'
'enabled' in p &&
typeof p.enabled === 'boolean'
){
//
} else {
return propsErr('finished', p.finished);
return err("property 'enabled' is missing or not a boolean.");
}
return ok(p as RoutineProperties);
@ -109,7 +105,7 @@ const validateRoutineProperties = (p: any): Result<RoutineProperties, string> =>
const isDueTo = (routine: Routine, day: Day): boolean => {
const p = routine.properties;
if(p.finished) return false;
if(!p.enabled) return false;
if(p.activeCriteria === "month"){
const days = Array.from(p.daysOfMonth);

View file

@ -30,7 +30,7 @@ export type RoutineProperties = {
activeCriteria: "week" | "month";
daysOfWeek: DayOfWeek[];
daysOfMonth: number[];
finished: boolean;
enabled: boolean;
};
export type RoutineGroup = RoutineElement & {

View file

@ -1,7 +1,7 @@
import { ensureArchive } from "@entities/archives";
import { compose } from "@shared/utils/compose";
import { fileAccessor } from "@shared/file/file-accessor";
import { stringifyYaml, TFile } from "obsidian";
import { Notice, stringifyYaml, TFile } from "obsidian";
import { GROUP_PREFIX, ROUTINE_PATH } from "./utils";
import { parseFrontmatter } from "@shared/file/parse-frontmatter";
import { RoutineEntity } from "../domain/routine";
@ -12,7 +12,10 @@ import { Routine } from "../domain/routine.type";
const parse = async (file: TFile): Promise<Routine> => {
const content = await fileAccessor.readFileAsReadonly(file);
const result = RoutineEntity.validateRoutineProperties(parseFrontmatter(content));
if(result.isErr()) throw new Error(`[Routine '${file.basename}' Parse Error] ${result.error}`);
if(result.isErr()){
new Notice(`Routine '${file.basename}' frontmatter error: ${result.error}`);
throw new Error(`[Routine '${file.basename}' Parse Error] ${result.error}`);
}
return {
name: file.basename,
routineElementType: "routine",
@ -32,7 +35,7 @@ export interface RoutineQuery {
}
export interface RoutineRepository extends RoutineQuery {
persist(entity: Routine): Promise<boolean>;
finish(routineName: string): Promise<void>;
delete(routineName: string): Promise<void>;
changeName(originalName: string, newName: string): Promise<void>;
update(routine: Routine): Promise<Routine>;
updateAll(routines: Routine[]): Promise<Routine[]>;
@ -66,11 +69,14 @@ export const routineRepository: RoutineRepository = {
return false;
}
},
async finish(routineName: string){
const routine = await routineRepository.load(routineName);
routine.properties.finished = true;
await routineRepository.update(routine);
async delete(routineName: string){
const composed = compose(
fileAccessor.deleteFile,
fileAccessor.loadFile,
ROUTINE_PATH
);
await composed(routineName);
},
async changeName(originalName: string, newName: string){

View file

@ -13,7 +13,7 @@ export const createNewRoutine = (): Routine => {
activeCriteria: "week",
daysOfWeek: Day.getDaysOfWeek(),
daysOfMonth: [Day.now().date],
finished: false
enabled: true
}
}
}

View file

@ -19,18 +19,34 @@ export const RoutineTaskWidget = React.memo(({ task, parent }: RoutineTaskProps)
const { mergeNotes } = useRoutineMutationMerge();
const { note, setNote } = useRoutineNote();
const finishRoutine = useCallback(async () => {
const finishConfirm = await doConfirm({
title: "Finish Routine",
confirmText: "Finish",
description: `Are you sure you want to finish the routine ${task.name}?`,
const disableRoutine = useCallback(async () => {
const disableConfirm = await doConfirm({
title: "Disable Routine",
confirmText: "Disable",
description: `Are you sure you want to disable the routine ${task.name}?`,
confirmBtnVariant: "accent"
})
if(!finishConfirm) return;
if(!disableConfirm) return;
await routineRepository.finish(task.name);
const routine = await routineRepository.load(task.name);
routine.properties.enabled = false;
await routineRepository.update(routine);
mergeNotes();
new Notice(`Routine ${task.name} has been finished 🪄`);
new Notice(`Routine '${task.name}' disabled.`);
}, [mergeNotes, task.name])
const deleteRoutine = useCallback(async () => {
const deleteConfirm = await doConfirm({
title: "Delete Routine",
confirmText: "Delete",
description: `Are you sure you want to delete the routine ${task.name}?`,
confirmBtnVariant: "destructive"
})
if(!deleteConfirm) return;
await routineRepository.delete(task.name);
mergeNotes();
new Notice(`Routine '${task.name}' deleted.`);
}, [mergeNotes, task.name])
const onOptionMenu = useCallback((m: Menu) => {
@ -51,11 +67,16 @@ export const RoutineTaskWidget = React.memo(({ task, parent }: RoutineTaskProps)
});
})
m.addItem(i => {
i.setTitle("Finish");
i.setTitle("Disable");
i.setIcon("alarm-clock-off");
i.onClick(finishRoutine);
i.onClick(disableRoutine);
})
}, [RoutineOptionModal, finishRoutine, note, setNote, task.name])
m.addItem(i => {
i.setTitle("Delete");
i.setIcon("trash");
i.onClick(deleteRoutine);
})
}, [RoutineOptionModal, deleteRoutine, disableRoutine, note, setNote, task.name])
return (
<>

View file

@ -11,7 +11,7 @@ export const deleteGroup = async (note: RoutineNote, groupName: string, deleteSu
if(deleteSubTasks){
const deleteTargets = routines.filter(routine => routine.properties.group === groupName);
for(const target of deleteTargets){
await routineRepository.finish(target.name);
await routineRepository.delete(target.name);
}
} else {
const ungroupTarget = routines.filter(routine => routine.properties.group === groupName);