refactor: fsd 모듈을 alias로 참조

ex) features/routine -> @features/routine
This commit is contained in:
sechan100 2024-11-13 09:31:43 +09:00
parent 6bd8f646c6
commit 9e21e7f5a3
51 changed files with 368 additions and 231 deletions

135
RoutineNote.tsx Normal file
View file

@ -0,0 +1,135 @@
/** @jsxImportSource @emotion/react */
import { RoutineNote as RoutineNoteEntity, routineNoteService, routineNoteArchiver, UseRoutineNoteProvider, useRoutineNote } from '@entities/note';
import { useStartRoutineModal } from "@features/routine";
import { Weeks } from "@features/weeks";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Day } from "@shared/day";
import { dr } from "@shared/daily-routine-bem";
import { MenuComponent } from "@shared/components/Menu";
import { Menu } from "obsidian";
import { RoutineTask, TaskDndContext, TodoTask } from '@widgets/tasks';
import { useAddTodoModal } from '@features/todo';
interface RoutineNoteProps {
day: Day;
}
export const RoutineNote = ({ day }: RoutineNoteProps) => {
const [ note, setNote ] = useState<RoutineNoteEntity | null>(null);
useEffect(() => {
// note가 존재하면 가지고오고, 없으면 생성하고 저장은 하지 않고 반환한다. 다만, 생성한 노트가 오늘 노트라면 저장까지 해준다.
(async () => {
let routineNote = await routineNoteArchiver.load(day);
if(!routineNote){
routineNote = await routineNoteService.create(day);
if(day.isToday()){
await routineNoteArchiver.persist(routineNote, false);
}
}
setNote(routineNote);
})();
}, [day]);
if(!note) return (<div>Loading...</div>);
return (
<UseRoutineNoteProvider
data={note}
onDataChange={(s, note) => s.setState({
note: note
})}
>
<RoutineNotePage />
</UseRoutineNoteProvider>
);
}
const RoutineNotePage = () => {
const { note, setNote } = useRoutineNote();
const percentage = useMemo(() => routineNoteService.getTaskCompletion(note).percentageRounded, [note]);
const AddTodoModal = useAddTodoModal();
const StartRoutineModal = useStartRoutineModal();
const onNoteMenuShow = useCallback((m: Menu) => {
// Start New Routine
m.addItem(item => {
item.setIcon("alarm-clock-plus");
item.setTitle("Start New Routine");
item.onClick(() => {
StartRoutineModal.open({});
});
});
m.addSeparator();
// Add Todo
m.addItem(item => {
item.setIcon("square-check-big");
item.setTitle("Add Todo");
item.onClick(() => {
AddTodoModal.open({});
});
});
}, [AddTodoModal, StartRoutineModal]);
const bem = useMemo(() => dr("note"), []);
return (
<div
className={bem()}
css={{
height: "100%",
display: "flex",
flexDirection: "column",
overflow: "hidden",
}}
>
<Weeks
className={bem("weeks")}
currentDay={note.day}
currentDayPercentage={percentage}
/>
<header
css={{
display: "flex",
alignItems: "center",
justifyContent: "space-between",
padding: "0.5em 1em",
// height: "4.5em",
}}
className={bem("header")}
>
<span css={{
fontWeight: "bold",
fontSize: "1.2em",
}}>
{note.day.getBaseFormat() + " / " + note.day.getDayOfWeek()}
</span>
<MenuComponent onMenuShow={onNoteMenuShow} icon="ellipsis" />
</header>
<div
className={bem("tasks")}
css={{
flexGrow: 1,
overflowY: "auto",
}}
>
<TaskDndContext>
{note.tasks.map(task => {
switch(task.type){
case "routine": return <RoutineTask key={task.name} task={task} />
case "todo": return <TodoTask key={task.name} task={task} />
default: task as never;
}
})}
</TaskDndContext>
</div>
<AddTodoModal />
<StartRoutineModal />
</div>
);
}

View file

@ -1,59 +1,20 @@
import EventEmitter from "events";
import _moment from "moment";
/** Basic obsidian abstraction for any file or folder in a vault. */
export abstract class TAbstractFile {
/**
* @public
*/
vault: Vault;
/**
* @public
*/
path: string;
/**
* @public
*/
name: string;
/**
* @public
*/
parent: TFolder;
path: string;
name: string;
}
/** Tracks file created/modified time as well as file system size. */
export interface FileStats {
/** @public */
ctime: number;
/** @public */
mtime: number;
/** @public */
size: number;
}
/** A regular file in the vault. */
export class TFile extends TAbstractFile {
stat: FileStats;
basename: string;
extension: string;
basename: string;
}
/** A folder in the vault. */
export class TFolder extends TAbstractFile {
children: TAbstractFile[];
isRoot(): boolean {
return false;
}
children: TAbstractFile[];
}
export class Vault extends EventEmitter {
getFiles() {
return [];
}
trigger(name: string, ...data: any[]): void {
this.emit(name, ...data);
}
}
export const moment = _moment;

6
__mocks__/plugin.ts Normal file
View file

@ -0,0 +1,6 @@
import { DailyRoutinePluginSettings, DEFAULT_SETTINGS } from "@app/settings/DailyRoutineSettingTab";
export const plugin = () => ({
settings: DEFAULT_SETTINGS
})

View file

@ -2,4 +2,17 @@ module.exports = {
preset: "ts-jest",
testEnvironment: "jsdom",
moduleDirectories: ["node_modules", "src"],
};
// 모듈 매칭 우선순위가 있기 때문에, mock은 위에 배치.
moduleNameMapper: {
"^@shared/plugin-service-locator$": "<rootDir>/__mocks__/plugin",
// FSD {
"^@app/(.*)$": "<rootDir>/src/app/$1",
"^@pages/(.*)$": "<rootDir>/src/pages/$1",
"^@widgets/(.*)$": "<rootDir>/src/widgets/$1",
"^@features/(.*)$": "<rootDir>/src/features/$1",
"^@entities/(.*)$": "<rootDir>/src/entities/$1",
"^@shared/(.*)$": "<rootDir>/src/shared/$1",
// }
},
}

View file

@ -1,17 +1,17 @@
/** @jsxImportSource @emotion/react */
import { css } from "@emotion/react";
import { RoutineNote } from 'pages/routine-note';
import { RoutineCalendar } from "pages/calendar";
import { RoutineNote } from '@pages/routine-note';
import { RoutineCalendar } from "@pages/calendar";
import { useCallback, useEffect, useMemo } from "react";
import { Day } from "shared/day";
import { Day } from "@shared/day";
import { usePageRoute } from "./use-page-route";
import "./style.css";
import { DailyRoutineObsidianView } from './obsidian-view';
import { useLeaf } from 'shared/view/react-view';
import { useLeaf } from '@shared/view/react-view';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import { MUIThemeProvider } from './MUIThemProvider';
import { Icon } from "shared/components/Icon";
import { Icon } from "@shared/components/Icon";

View file

@ -1,4 +1,4 @@
import { ReactView } from "shared/view/react-view";
import { ReactView } from "@shared/view/react-view";
import { WorkspaceLeaf } from "obsidian";
import { DailyRoutineView } from "./DailyRoutineView";

View file

@ -1,17 +1,16 @@
import DailyRoutinePlugin from "main";
import DailyRoutinePlugin from "src/main";
import { App, normalizePath, Notice, PluginSettingTab, Setting } from "obsidian";
import { FileSuggest } from "./suggesters/FileSuggester";
import { Day } from "shared/day";
export interface DailyRoutinePluginSettings {
routineFolderPath: string;
routineArchiveFolderPath: string;
noteFolderPath: string;
}
export const DEFAULT_SETTINGS: DailyRoutinePluginSettings = {
routineFolderPath: "daily-routine/routines",
routineArchiveFolderPath: "daily-routine/archive"
noteFolderPath: "daily-routine/archive"
}
@ -43,15 +42,15 @@ export class DailyRoutineSettingTab extends PluginSettingTab {
// Routine Archive Path
new Setting(containerEl)
.setName("Routine Archive Path")
.setName("Note Archive Path")
.setDesc("The path to the routine archive folder.")
.addText(text => {
new FileSuggest(text.inputEl, "folder");
text
.setPlaceholder("daily-routine/archive")
.setValue(this.plugin.settings.routineArchiveFolderPath??"")
.setValue(this.plugin.settings.noteFolderPath??"")
.onChange(async (value) => {
this.save({ routineArchiveFolderPath: normalizePath(value)});
this.save({ noteFolderPath: normalizePath(value)});
})
});
}
@ -61,7 +60,7 @@ export class DailyRoutineSettingTab extends PluginSettingTab {
const settings = {...this.plugin.settings, ...partial};
// 루틴폴더와 루틴아카이브폴더의 경로 일치 검사
if(settings.routineArchiveFolderPath === settings.routineFolderPath){
if(settings.noteFolderPath === settings.routineFolderPath){
new Notice("Routine folder path and routine archive folder path cannot be the same.");
return;
}

View file

@ -2,7 +2,7 @@
import { TAbstractFile, TFile, TFolder } from "obsidian";
import { TextInputSuggest } from "./suggest";
import { plugin } from "shared/plugin-service-locator";
import { plugin } from "@shared/plugin-service-locator";
export class FileSuggest extends TextInputSuggest<TAbstractFile> {

View file

@ -2,7 +2,7 @@
import { ISuggestOwner, Scope } from "obsidian";
import { createPopper, Instance as PopperInstance } from "@popperjs/core";
import { plugin } from "shared/plugin-service-locator";
import { plugin } from "@shared/plugin-service-locator";
const wrapAround = (value: number, size: number): number => {
return ((value % size) + size) % size;

View file

@ -1,4 +1,4 @@
import { Day } from "shared/day";
import { Day } from "@shared/day";
import { create } from "zustand";

View file

@ -1,4 +1,4 @@
import { RoutineNote } from "entities/note";
import { RoutineNote } from "@entities/note";

View file

@ -3,7 +3,7 @@
* .
*/
import { RoutineNote } from "entities/note";
import { RoutineNote } from "@entities/note";
import { NoteDependent } from "./NoteDependent";

View file

@ -1,4 +1,4 @@
import { RoutineNote, Task, TodoTask } from "entities/note";
import { RoutineNote, Task, TodoTask } from "@entities/note";
import { NoteDependent } from "./NoteDependent";

View file

@ -2,4 +2,4 @@
* , routine들이 .
* api들을 slice.
*/
export { registerRoutineNotesSynchronize } from "./synchronize";
export { executeRoutineNotesSynchronize } from "./synchronize";

View file

@ -1,7 +1,7 @@
import { RoutineNote, routineNoteArchiver, routineNoteService } from "entities/note";
import { RoutineNote, routineNoteArchiver, routineNoteService } from "@entities/note";
import { TaskCheckedStateNoteDep } from "./dependents/TaskCheckedStateNoteDep";
import { TodoTaskNoteDep } from "./dependents/TodoTaskNoteDep";
import { Day } from "shared/day";
import { Day } from "@shared/day";
@ -16,7 +16,7 @@ export interface RoutineNoteSynchronizer {
(cb: AllRecreatedNoteCb): void;
/**
* , day로 RoutineNote를 .
* , day로 RoutineNote를 cb의 .
* note가 transient한 note .
* @param day cb로
*/
@ -25,8 +25,9 @@ export interface RoutineNoteSynchronizer {
(): void;
}
export const registerRoutineNotesSynchronize: RoutineNoteSynchronizer
export const executeRoutineNotesSynchronize: RoutineNoteSynchronizer
= (cb?, day?) => {
// 모든 등록된 비동기 로직 이후에 실행을 예약
Promise.resolve().then(async () => {
const notes = await routineNoteArchiver.loadBetween(Day.now(), Day.max());
const syncedNotes: RoutineNote[] = [];

View file

@ -1,10 +1,10 @@
import { RoutineNote, routineNoteService } from "./routine-note-service";
import { fileAccessor } from "shared/file/file-accessor";
import { plugin } from "shared/plugin-service-locator";
import { fileAccessor } from "@shared/file/file-accessor";
import { plugin } from "@shared/plugin-service-locator";
import { TAbstractFile, TFile } from "obsidian";
import { Day } from "shared/day";
import { FileNotFoundError } from "shared/file/errors";
import { openConfirmModal } from "shared/components/modal/confirm-modal";
import { Day } from "@shared/day";
import { FileNotFoundError } from "@shared/file/errors";
import { openConfirmModal } from "@shared/components/modal/confirm-modal";
@ -59,7 +59,7 @@ export const routineNoteArchiver: RoutineNoteArchiver = {
async loadBetween(start: Day, end: Day): Promise<RoutineNote[]> {
const notes: RoutineNote[] = [];
const routineNoteFiles: TAbstractFile[] = fileAccessor.getFolder(plugin().settings.routineArchiveFolderPath).children.filter(file => file instanceof TFile);
const routineNoteFiles: TAbstractFile[] = fileAccessor.getFolder(plugin().settings.noteFolderPath).children.filter(file => file instanceof TFile);
for(const file of routineNoteFiles){
if(!(file instanceof TFile)) continue;
const day = Day.fromString(file.basename);
@ -167,5 +167,5 @@ const parseFile = async (file: TFile): Promise<RoutineNote> => {
* .
*/
const getRoutineArchivePath = (routineNoteTitle: string) => {
return `${plugin().settings.routineArchiveFolderPath}/${routineNoteTitle}.md`;
return `${plugin().settings.noteFolderPath}/${routineNoteTitle}.md`;
}

View file

@ -1,5 +1,5 @@
import { routineManager, Routine } from "entities/routine";
import { Day } from "shared/day";
import { routineManager, Routine } from "@entities/routine";
import { Day } from "@shared/day";
export type TaskType = "routine" | "todo";

View file

@ -2,9 +2,9 @@
* routine note는 , .
*/
import { createStoreContext } from "shared/zustand/create-store-context";
import { createStoreContext } from "@shared/zustand/create-store-context";
import { RoutineNote, routineNoteService } from "./routine-note-service";
import { Day } from "shared/day";
import { Day } from "@shared/day";
import { routineNoteArchiver } from "./routine-note-archive";

View file

@ -1,5 +1,5 @@
import { getFrontMatterInfo, Notice, parseYaml, stringifyYaml } from "obsidian";
import { DayOfWeek } from "shared/day";
import { DayOfWeek } from "@shared/day";
import { validateRoutineProperties, RoutineProperties } from "./types";

View file

@ -1,6 +1,6 @@
import { TFile } from "obsidian";
import { fileAccessor } from "shared/file/file-accessor";
import { plugin } from "shared/plugin-service-locator";
import { fileAccessor } from "@shared/file/file-accessor";
import { plugin } from "@shared/plugin-service-locator";
import { RoutineFrontMatter } from "./front-matter";
import { validateRoutineProperties } from "./types";
import { Routine, RoutineProperties } from "./types";
@ -166,7 +166,7 @@ const getRoutinePath = (routineName: string) =>{
/**
* .
*/
const getRoutineFolderPath = () => {
const getRoutineFolderPath = () => {
const path = plugin().settings.routineFolderPath;
if(!path) {
throw new Error('Routine folder path is not set.');

View file

@ -1,6 +1,6 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { keys } from "lodash";
import { DayOfWeek } from "shared/day";
import { DayOfWeek } from "@shared/day";
/**

View file

@ -1,6 +1,6 @@
import { routineNoteArchiver, RoutineNote, routineNoteService } from 'entities/note';
import { Day } from "shared/day";
import { PercentageCircle } from "shared/components/PercentageCircle";
import { routineNoteArchiver, RoutineNote, routineNoteService } from '@entities/note';
import { Day } from "@shared/day";
import { PercentageCircle } from "@shared/components/PercentageCircle";
import Calendar from "react-calendar"
import { moment } from "obsidian";
import { useCallback, useEffect, useState } from "react";

View file

@ -1,18 +1,18 @@
/** @jsxImportSource @emotion/react */
import { routineManager } from 'entities/routine';
import { Routine, RoutineProperties } from 'entities/routine';
import { routineManager } from '@entities/routine';
import { Routine, RoutineProperties } from '@entities/routine';
import { Notice } from "obsidian";
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import React from "react";
import { ActiveCriteriaOption } from "./ui/ ActiveCriteriaOption";
import { Button } from 'shared/components/Button';
import { TextEditComponent } from 'shared/components/TextEditComponent';
import { dr } from 'shared/daily-routine-bem';
import { openConfirmModal } from 'shared/components/modal/confirm-modal';
import { Modal } from 'shared/components/modal/styled';
import { createModal, ModalApi } from 'shared/components/modal/create-modal';
import { useRoutineNote } from 'entities/note';
import { registerRoutineNotesSynchronize } from 'entities/note-synchronize';
import { Button } from '@shared/components/Button';
import { TextEditComponent } from '@shared/components/TextEditComponent';
import { dr } from '@shared/daily-routine-bem';
import { openConfirmModal } from '@shared/components/modal/confirm-modal';
import { Modal } from '@shared/components/modal/styled';
import { createModal, ModalApi } from '@shared/components/modal/create-modal';
import { useRoutineNote } from '@entities/note';
import { executeRoutineNotesSynchronize } from '@entities/note-synchronize';
@ -35,7 +35,7 @@ export const useRoutineOptionModal = createModal(({ routine: propsRoutine, modal
}
await routineManager.editProperties(originalName, routine.properties);
registerRoutineNotesSynchronize(note => setNote(note), note.day);
executeRoutineNotesSynchronize(note => setNote(note), note.day);
})}, [modal, note, originalName, routine, setNote]);
@ -56,7 +56,7 @@ export const useRoutineOptionModal = createModal(({ routine: propsRoutine, modal
routineManager.delete(routine.name);
new Notice(`Routine ${routine.name} deleted.`);
registerRoutineNotesSynchronize(note => setNote(note), note.day);
executeRoutineNotesSynchronize(note => setNote(note), note.day);
modal.closeWithoutOnClose();
}

View file

@ -1,18 +1,18 @@
/** @jsxImportSource @emotion/react */
import { routineManager } from "entities/routine";
import { Routine } from "entities/routine";
import { routineManager } from "@entities/routine";
import { Routine } from "@entities/routine";
import { Notice } from "obsidian";
import { ActiveCriteriaOption } from "./ui/ ActiveCriteriaOption";
import { DAYS_OF_WEEK } from "shared/day";
import { DAYS_OF_WEEK } from "@shared/day";
import { useCallback, useState, useMemo } from "react";
import { createModal } from "shared/components/modal/create-modal";
import { TextEditComponent } from "shared/components/TextEditComponent";
import { dr } from "shared/daily-routine-bem";
import { Modal } from "shared/components/modal/styled";
import { ModalApi } from "shared/components/modal/create-modal";
import { Button } from "shared/components/Button";
import { registerRoutineNotesSynchronize } from "entities/note-synchronize";
import { useRoutineNote } from "entities/note";
import { createModal } from "@shared/components/modal/create-modal";
import { TextEditComponent } from "@shared/components/TextEditComponent";
import { dr } from "@shared/daily-routine-bem";
import { Modal } from "@shared/components/modal/styled";
import { ModalApi } from "@shared/components/modal/create-modal";
import { Button } from "@shared/components/Button";
import { executeRoutineNotesSynchronize } from "@entities/note-synchronize";
import { useRoutineNote } from "@entities/note";
import { set } from "lodash";
@ -48,7 +48,7 @@ export const useStartRoutineModal = createModal(({ modal }: { modal: ModalApi})
await routineManager.create(routine);
new Notice(`Routine '${routine.name}' started! 🎉`);
registerRoutineNotesSynchronize(note => setNote(note), note.day);
executeRoutineNotesSynchronize(note => setNote(note), note.day);
modal.close();
} catch(e) {

View file

@ -1,10 +1,10 @@
/** @jsxImportSource @emotion/react */
import { RoutineProperties } from "entities/routine";
import { RoutineProperties } from "@entities/routine";
import { useCallback, useEffect, useMemo, useState } from "react";
import clsx from "clsx";
import Calendar from "react-calendar";
import { dr } from "shared/daily-routine-bem";
import { Button } from "shared/components/Button";
import { dr } from "@shared/daily-routine-bem";
import { Button } from "@shared/components/Button";
import ReactDOM from "react-dom";
import { css } from "@emotion/react";
import { WeekOption } from "./WeekOption";

View file

@ -1,7 +1,7 @@
/** @jsxImportSource @emotion/react */
import { css } from "@emotion/react";
import { Button } from "shared/components/Button";
import { Button } from "@shared/components/Button";
import clsx from "clsx";
import { useState, useMemo, useEffect, useCallback } from "react";
import Calendar from "react-calendar";

View file

@ -2,9 +2,9 @@
import { css } from "@emotion/react";
import { useMemo, useCallback } from "react";
import { Button } from "shared/components/Button";
import { dr } from "shared/daily-routine-bem";
import { DayOfWeek, DAYS_OF_WEEK } from "shared/day";
import { Button } from "@shared/components/Button";
import { dr } from "@shared/daily-routine-bem";
import { DayOfWeek, DAYS_OF_WEEK } from "@shared/day";
interface WeekOptionProps {
daysOfWeek: DayOfWeek[];

View file

@ -3,13 +3,13 @@
* todo task에 , note에 .
*/
/** @jsxImportSource @emotion/react */
import { routineNoteArchiver, routineNoteService, TodoTask, useRoutineNote } from "entities/note";
import { routineNoteArchiver, routineNoteService, TodoTask, useRoutineNote } from "@entities/note";
import { useCallback, useEffect, useMemo, useState } from "react";
import { createModal, ModalApi } from "shared/components/modal/create-modal";
import { Modal } from "shared/components/modal/styled";
import { TextEditComponent } from "shared/components/TextEditComponent";
import { Button } from "shared/components/Button";
import { dr } from "shared/daily-routine-bem";
import { createModal, ModalApi } from "@shared/components/modal/create-modal";
import { Modal } from "@shared/components/modal/styled";
import { TextEditComponent } from "@shared/components/TextEditComponent";
import { Button } from "@shared/components/Button";
import { dr } from "@shared/daily-routine-bem";

View file

@ -1,5 +1,5 @@
import { RoutineNote, routineNoteArchiver, routineNoteService, Task, TodoTask } from "entities/note";
import { Day } from "shared/day";
import { RoutineNote, routineNoteArchiver, routineNoteService, Task, TodoTask } from "@entities/note";
import { Day } from "@shared/day";
/**
* task의 .

View file

@ -2,15 +2,15 @@
import { Notice } from "obsidian";
import { memo, useCallback, useEffect, useMemo, useRef, useState } from "react";
import React from "react";
import { Button } from 'shared/components/Button';
import { TextEditComponent } from 'shared/components/TextEditComponent';
import { createModal, ModalApi } from 'shared/components/modal/create-modal';
import { dr } from 'shared/daily-routine-bem';
import { openConfirmModal } from 'shared/components/modal/confirm-modal';
import { Modal } from 'shared/components/modal/styled';
import { routineNoteArchiver, routineNoteService, TodoTask, useRoutineNote } from 'entities/note';
import { Button } from '@shared/components/Button';
import { TextEditComponent } from '@shared/components/TextEditComponent';
import { createModal, ModalApi } from '@shared/components/modal/create-modal';
import { dr } from '@shared/daily-routine-bem';
import { openConfirmModal } from '@shared/components/modal/confirm-modal';
import { Modal } from '@shared/components/modal/styled';
import { routineNoteArchiver, routineNoteService, TodoTask, useRoutineNote } from '@entities/note';
import { rescheduleTodo } from "./reschedule-todo";
import { Day } from "shared/day";
import { Day } from "@shared/day";

View file

@ -1,12 +1,12 @@
/** @jsxImportSource @emotion/react */
import { Day } from "shared/day";
import { Day } from "@shared/day";
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { PercentageCircle } from "shared/components/PercentageCircle";
import { PercentageCircle } from "@shared/components/PercentageCircle";
import { Navigation } from 'swiper/modules';
import { Swiper, SwiperClass, SwiperRef, SwiperSlide } from 'swiper/react';
import 'swiper/swiper-bundle.css';
import { useRoutineNote } from 'entities/note';
import { dr } from "shared/daily-routine-bem";
import { useRoutineNote } from '@entities/note';
import { dr } from "@shared/daily-routine-bem";
import { loadWeeks } from "./load-weeks";

View file

@ -1,6 +1,6 @@
import { routineNoteArchiver, routineNoteService } from "entities/note";
import { routineNoteArchiver, routineNoteService } from "@entities/note";
import { Notice } from "obsidian";
import { Day } from "shared/day";
import { Day } from "@shared/day";
import { WeeksDayNode } from "./types";

View file

@ -1,4 +1,4 @@
import { Day } from "shared/day";
import { Day } from "@shared/day";
export type WeeksDayNode = {

View file

@ -1,9 +1,9 @@
/* eslint-disable @typescript-eslint/no-var-requires */
import { Plugin } from 'obsidian';
import { setPlugin } from './shared/plugin-service-locator';
import { DailyRoutinePluginSettings, DailyRoutineSettingTab, DEFAULT_SETTINGS } from './app/settings/DailyRoutineSettingTab';
import { setPlugin } from '@shared/plugin-service-locator';
import { DailyRoutinePluginSettings, DailyRoutineSettingTab, DEFAULT_SETTINGS } from '@app/settings/DailyRoutineSettingTab';
import { DailyRoutineObsidianView } from './app';
import { activateView } from './shared/view/activate-view';
import { activateView } from '@shared/view/activate-view';
export default class DailyRoutinePlugin extends Plugin {

View file

@ -1,5 +1,5 @@
import { RoutineCalendar as RoutineCalendarFeature } from "features/calendar"
import { Day } from "shared/day";
import { RoutineCalendar as RoutineCalendarFeature } from "@features/calendar"
import { Day } from "@shared/day";

View file

@ -1,16 +1,16 @@
/** @jsxImportSource @emotion/react */
import { RoutineNote as RoutineNoteEntity, routineNoteService, routineNoteArchiver, UseRoutineNoteProvider, useRoutineNote } from 'entities/note';
import { useStartRoutineModal } from "features/routine";
import { Weeks } from "features/weeks";
import { RoutineNote as RoutineNoteEntity, routineNoteService, routineNoteArchiver, UseRoutineNoteProvider, useRoutineNote } from '@entities/note';
import { useStartRoutineModal } from "@features/routine";
import { Weeks } from "@features/weeks";
import { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Day } from "shared/day";
import { dr } from "shared/daily-routine-bem";
import { MenuComponent } from "shared/components/Menu";
import { Day } from "@shared/day";
import { dr } from "@shared/daily-routine-bem";
import { MenuComponent } from "@shared/components/Menu";
import { Menu } from "obsidian";
import { RoutineTask, TaskDndContext, TodoTask } from 'widgets/tasks';
import { useAddTodoModal } from 'features/todo';
import { Icon } from 'shared/components/Icon';
import { Button } from 'shared/components/Button';
import { RoutineTask, TaskDndContext, TodoTask } from '@widgets/tasks';
import { useAddTodoModal } from '@features/todo';
import { Icon } from '@shared/components/Icon';
import { Button } from '@shared/components/Button';
interface RoutineNoteProps {

View file

@ -2,7 +2,7 @@
import { css } from "@emotion/react";
import { TextComponent } from "obsidian";
import { useRef, useState, useEffect, memo } from "react";
import { dr } from "shared/daily-routine-bem";
import { dr } from "@shared/daily-routine-bem";
import { Button } from "./Button";
import clsx from "clsx";

View file

@ -2,7 +2,7 @@
import { useEffect, useRef } from "react";
import { Button } from "../Button";
import { Modal } from "obsidian";
import { plugin } from "shared/plugin-service-locator";
import { plugin } from "@shared/plugin-service-locator";
import { createRoot } from "react-dom/client";

View file

@ -1,7 +1,7 @@
import React, { useCallback, useEffect, useMemo, useRef } from 'react';
import ReactDOM from 'react-dom';
import { Modal } from 'obsidian';
import { plugin } from 'shared/plugin-service-locator';
import { plugin } from '@shared/plugin-service-locator';
import { create } from 'zustand';

View file

@ -1,15 +1,63 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { TFile, TFolder } from "obsidian";
import { plugin } from "shared/plugin-service-locator";
import { plugin } from "@shared/plugin-service-locator";
import { FileNotFoundError } from "./errors";
export const fileAccessor = {
export interface FileAccessor {
/**
* vault의 .
* @throws FileNotFoundError folder인
*/
getFile: (path: string) => TFile;
/**
* vault의 .
* file인
*/
getFolder: (path: string) => TFolder;
/**
* .
*/
readFileAsReadonly: (file: TFile) => Promise<string>;
/**
* .
* .
*/
readFileFromDisk: (file: TFile) => Promise<string>;
/**
* .
*/
renameFileWithLinks: (file: TFile, newName: string) => Promise<void>;
/**
* .
*/
writeFile: (file: TFile, contentSupplier: (data: string) => string) => Promise<string>;
/**
* .
*/
createFile: (path: string, content: string) => Promise<TFile>;
/**
* .
*/
deleteFile: (file: TFile) => Promise<void>;
/**
* frontmatter를 .
* frontmatter json object로 .
*/
writeFrontMatter: (file: TFile, frontMatterModifier: (frontmatter: any) => any) => Promise<void>;
}
export const fileAccessor: FileAccessor = {
getFile: (path: string): TFile => {
const file = plugin().app.vault.getAbstractFileByPath(path);
if(file && file instanceof TFile) {
@ -19,11 +67,6 @@ export const fileAccessor = {
}
},
/**
* vault의 .
* file인
*/
getFolder: (path: string) => {
const file = plugin().app.vault.getAbstractFileByPath(path);
if(file && file instanceof TFolder) {
@ -33,60 +76,32 @@ export const fileAccessor = {
}
},
/**
* .
*/
readFileAsReadonly: async (file: TFile) => {
return plugin().app.vault.cachedRead(file);
},
/**
* .
* .
*/
readFileFromDisk: async (file: TFile) => {
return plugin().app.vault.read(file);
},
/**
* .
*/
renameFileWithLinks: async (file: TFile, newName: string) => {
return plugin().app.fileManager.renameFile(file, newName);
},
/**
* .
*/
writeFile: async (file: TFile, contentSupplier: (data: string) => string) => {
return plugin().app.vault.process(file, contentSupplier);
},
/**
* .
*/
createFile: async (path: string, content: string) => {
return plugin().app.vault.create(path, content);
},
/**
* .
*/
deleteFile: async (file: TFile) => {
return plugin().app.vault.delete(file);
},
/**
* frontmatter를 .
* frontmatter json object로 .
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
writeFrontMatter: async (file: TFile, frontMatterModifier: (frontmatter: any) => any) => {
return plugin().app.fileManager.processFrontMatter(file, (fm) => {
writeFrontMatter: async (file: TFile, frontMatterModifier) => {
return plugin().app.fileManager.processFrontMatter(file, (fm: any) => {
const newFm = frontMatterModifier(fm);
Object.assign(fm, newFm);
});

View file

@ -1,4 +1,4 @@
import DailyRoutinePlugin from "main";
import DailyRoutinePlugin from "src/main";
let pluginThisRef: DailyRoutinePlugin | null = null;

View file

@ -1,5 +1,5 @@
import { WorkspaceLeaf } from "obsidian";
import { plugin } from "shared/plugin-service-locator";
import { plugin } from "@shared/plugin-service-locator";
/**
* viewType에 .

View file

@ -1,9 +1,9 @@
import { RoutineTask as RoutineTaskEntity, Task, useRoutineNote } from "entities/note";
import { routineManager } from "entities/routine";
import { useRoutineOptionModal } from "features/routine";
import { RoutineTask as RoutineTaskEntity, Task, useRoutineNote } from "@entities/note";
import { routineManager } from "@entities/routine";
import { useRoutineOptionModal } from "@features/routine";
import { AbstractTask } from "./ui/AbstractTask";
import React, { useCallback, useEffect } from "react"
import { registerRoutineNotesSynchronize } from "entities/note-synchronize";
import { executeRoutineNotesSynchronize } from "@entities/note-synchronize";
interface RoutineTaskProps {
@ -20,7 +20,7 @@ export const RoutineTask = React.memo(({ task }: RoutineTaskProps) => {
const onTaskReorder = useCallback(async (tasks: Task[]) => {
await routineManager.reorder(tasks.filter(t => t.type === "routine").map(r => r.name))
registerRoutineNotesSynchronize();
executeRoutineNotesSynchronize();
}, [])

View file

@ -1,7 +1,7 @@
import { TodoTask as TodoTaskEntity, Task, useRoutineNote } from "entities/note";
import { TodoTask as TodoTaskEntity, Task, useRoutineNote } from "@entities/note";
import { AbstractTask } from "./ui/AbstractTask";
import React, { useCallback } from "react"
import { useTodoOptionModal } from 'features/todo';
import { useTodoOptionModal } from '@features/todo';
interface TodoTaskProps {

View file

@ -1,9 +1,9 @@
/** @jsxImportSource @emotion/react */
import { useRoutineNote, RoutineNote, Task } from "entities/note";
import { useRoutineNote, RoutineNote, Task } from "@entities/note";
import { useRef, useCallback, useEffect, RefObject, useState } from "react";
import { useDrag, XYCoord, useDrop } from "react-dnd";
import { useLeaf } from "shared/view/react-view";
import { useLeaf } from "@shared/view/react-view";

View file

@ -1,11 +1,11 @@
/** @jsxImportSource @emotion/react */
import { RoutineNote, routineNoteArchiver, routineNoteService, Task as TaskEntity } from 'entities/note';
import { RoutineNote, routineNoteArchiver, routineNoteService, Task as TaskEntity } from '@entities/note';
import React, { useCallback, useMemo, useRef, useState } from "react"
import { useRoutineNote } from "entities/note";
import { useRoutineNote } from "@entities/note";
import _ from "lodash";
import { Touchable } from 'shared/components/Touchable';
import { dr } from 'shared/daily-routine-bem';
import { Icon } from 'shared/components/Icon';
import { Touchable } from '@shared/components/Touchable';
import { dr } from '@shared/daily-routine-bem';
import { Icon } from '@shared/components/Icon';
import { TaskName } from './TaskName';
import { Checkbox } from './Checkbox';
import { css } from '@emotion/react';

View file

@ -1,5 +1,5 @@
/** @jsxImportSource @emotion/react */
import { DailyRoutineBEM } from "shared/daily-routine-bem";
import { DailyRoutineBEM } from "@shared/daily-routine-bem";

View file

@ -1,5 +1,5 @@
/** @jsxImportSource @emotion/react */
import { DailyRoutineBEM } from "shared/daily-routine-bem"
import { DailyRoutineBEM } from "@shared/daily-routine-bem"

View file

@ -1,14 +1,14 @@
/** @jsxImportSource @emotion/react */
import { Task as TaskEntity } from 'entities/note';
import { Task as TaskEntity } from '@entities/note';
import { CSSProperties, useEffect, useMemo, useRef } from 'react';
import { useDragLayer } from 'react-dnd';
import { Icon } from 'shared/components/Icon';
import { dr } from 'shared/daily-routine-bem';
import { Icon } from '@shared/components/Icon';
import { dr } from '@shared/daily-routine-bem';
import { Checkbox } from './Checkbox';
import { TaskName } from './TaskName';
import { DragItem } from '../hooks/use-task-dnd';
import { plugin } from 'shared/plugin-service-locator';
import { useLeaf } from 'shared/view/react-view';
import { plugin } from '@shared/plugin-service-locator';
import { useLeaf } from '@shared/view/react-view';

View file

@ -1,7 +1,7 @@
import { Routine } from "entities/routine";
import { moment } from "obsidian";
import { DAYS_OF_WEEK } from "shared/day";
import { plugin } from "shared/plugin-service-locator";
import { executeRoutineNotesSynchronize } from "@entities/note-synchronize";
import { Routine } from "@entities/routine";
import { DAYS_OF_WEEK } from "@shared/day";
import { fileAccessor } from "@shared/file/file-accessor";
@ -17,7 +17,6 @@ describe('executeRoutineSync', () => {
}
test('should execute a routine synchronously', () => {
console.log(moment().format("YYYY-MM-DD"));
expect(routine.name).toBe("test routine 1");
});

View file

@ -1,6 +1,6 @@
{
"compilerOptions": {
"baseUrl": "src/",
"baseUrl": "",
"jsx": "react-jsx",
"inlineSourceMap": true,
"inlineSources": true,
@ -19,7 +19,15 @@
"ES5",
"ES6",
"ES7"
]
],
"paths" : {
"@app/*": ["src/app/*"],
"@pages/*": ["src/pages/*"],
"@widgets/*": ["src/widgets/*"],
"@features/*": ["src/features/*"],
"@entities/*": ["src/entities/*"],
"@shared/*": ["src/shared/*"],
}
},
"include": ["**/*.ts", "**/*.tsx", "src/index.d.ts"],
}