Extend CreateEffortExoCommand.ts by creation under effort

This commit is contained in:
kitelev 2025-01-03 22:32:58 +05:00
parent 1158fdade9
commit 88e9eb714c
8 changed files with 106 additions and 33 deletions

View File

@ -0,0 +1,26 @@
import ExoCommand from "./ExoCommand";
import ExoContext from "../../../../common/ExoContext";
import Area from "../../../../core/src/domain/Area";
import Effort from "../../../../core/src/domain/effort/Effort";
export default class CreateEffortExoCommand implements ExoCommand {
name = "Create Effort";
slug = "create-effort";
constructor(private ctx: ExoContext) {
}
async execute() {
const activeFile = this.ctx.appUtils.getActiveFileOrThrow();
const activeKo = await this.ctx.kObjectCreator.createFromTFileTyped(activeFile);
if (activeKo instanceof Area) {
let effort = await this.ctx.createEffortUseCase.taskUnderArea(activeKo);
await this.ctx.appUtils.openKObject(effort);
}
if (activeKo instanceof Effort) {
let effort = await this.ctx.createEffortUseCase.taskUnderEffort(activeKo);
await this.ctx.appUtils.openKObject(effort);
}
}
}

View File

@ -1,23 +0,0 @@
import ExoCommand from "./ExoCommand";
import ExoContext from "../../../../common/ExoContext";
import Area from "../../../../core/src/domain/Area";
export default class CreateEffortUnderAreaExoCommand implements ExoCommand {
name = "Create Effort Under Area";
slug = "create-effort-under-area";
constructor(private ctx: ExoContext) {
}
async execute() {
const activeFile = this.ctx.appUtils.getActiveFileOrThrow();
const activeKo = this.ctx.kObjectCreator.createFromTFileTyped(activeFile);
if (!(activeKo instanceof Area)) {
throw new Error("Active file is not an Area");
}
let effort = await this.ctx.createEffortUseCase.taskUnderArea(activeKo);
await this.ctx.appUtils.openKObject(effort);
}
}

View File

@ -6,7 +6,7 @@ import GetActiveFileTagsExoCommand from "./GetActiveFileTagsExoCommand";
import GetCurrentKOCExoCommand from "./GetCurrentKOCExoCommand";
import OpenCurrentDailyNoteExoCommand from "./OpenCurrentDailyNoteExoCommand";
import ExoContext from "../../../../common/ExoContext";
import CreateEffortUnderAreaExoCommand from "./CreateEffortUnderAreaExoCommand";
import CreateEffortExoCommand from "./CreateEffortExoCommand";
export default class ExoCommands {
static all(ctx: ExoContext): ExoCommand[] {
@ -17,7 +17,7 @@ export default class ExoCommands {
new GetActiveFileTagsExoCommand(ctx),
new GetCurrentKOCExoCommand(ctx),
new OpenCurrentDailyNoteExoCommand(ctx, ctx.getCurrentDNUseCase),
new CreateEffortUnderAreaExoCommand(ctx)
new CreateEffortExoCommand(ctx)
];
}

View File

@ -23,7 +23,7 @@ export default class EffortPersistenceAdapter implements EffortRepository {
private serializeData(effort: Effort) {
let result = "";
result += "---\n"; // frontmatter start
result += "---\n";
result += "tags:\n";
result += " - EMS/Effort\n";
result += "uid: " + effort.id + "\n";
@ -35,9 +35,12 @@ export default class EffortPersistenceAdapter implements EffortRepository {
result += "ended: " + effort.ended + "\n";
}
if (effort.area) {
result += "area: \"" + this.getLinkToArea(effort.area) + "\"\n";
result += "area: \'" + this.getLinkToArea(effort.area) + "\'\n";
}
result += "---\n"; // frontmatter end
if (effort.parent) {
result += "e-parent: \'" + this.getLinkToEffort(effort.parent) + "\'\n";
}
result += "---\n";
result += effort.body;
return result;
}
@ -45,4 +48,8 @@ export default class EffortPersistenceAdapter implements EffortRepository {
private getLinkToArea(area: Area): string {
return `[[${area.name}]]`;
}
private getLinkToEffort(parent: Effort): string {
return `[[${parent.title}]]`;
}
}

View File

@ -54,6 +54,16 @@ export default class AppUtils {
return this.app.workspace.getActiveFile();
}
getTFileFromStrLink(strLink: string): TFile {
if (strLink.contains("/")) {
const areaFileName = strLink.replace("[[", "").replace("]]", "");
return this.getFileByPathOrThrow(areaFileName + ".md");
} else {
const areaFileName = strLink.replace("[[", "").replace("]]", "");
return this.getFileByName(areaFileName + ".md");
}
}
getFrontmatterOrNull(file: TFile): FrontMatterCache | null {
try {
return this.getFrontmatterOrThrow(file)
@ -88,11 +98,19 @@ export default class AppUtils {
return [];
}
// TODO rename and add `orThrow`
getFileByName(parentFileName: string): TFile {
return this.app.vault.getMarkdownFiles().filter(f => f.name == parentFileName)[0];
}
getFileByPathOrThrow(filePath: string): TFile {
let file = this.app.vault.getFileByPath(filePath);
if (!file) {
throw new Error("File not found by path " + filePath);
}
return file;
}
getAllMdFiles() {
return this.app.vault.getMarkdownFiles();
}
@ -125,4 +143,8 @@ export default class AppUtils {
});
return a[0];
}
getFileBody(file: TFile) {
return this.app.vault.read(file);
}
}

View File

@ -4,6 +4,8 @@ import {KOC} from "../../../core/src/domain/KOC";
import AppUtils from "./AppUtils";
import Area from "../../../core/src/domain/Area";
import {UUID} from "node:crypto";
import Effort from "../../../core/src/domain/effort/Effort";
import {EffortStatus} from "../../../core/src/domain/effort/EffortStatus";
export default class KObjectCreator {
constructor(private appUtils: AppUtils) {
@ -16,11 +18,13 @@ export default class KObjectCreator {
return new KObject(id, koc);
}
createFromTFileTyped(file: TFile) {
async createFromTFileTyped(file: TFile) {
const koc = this.getFileKoc(file);
switch (koc) {
case KOC.EMS_AREA:
return this.createArea(file);
case KOC.EMS_EFFORT:
return await this.createEffort(file);
default:
throw new Error("Not implemented createFromTFileTyped")
}
@ -34,14 +38,39 @@ export default class KObjectCreator {
let parentArea: Area | null = null;
const parentStr: string = koProperties["a-parent"];
if (parentStr) {
const parentFileName = parentStr.replace("[[", "").replace("]]", "");
const parentAreaFile: TFile = this.appUtils.getFileByName(parentFileName + ".md");
parentArea = this.createArea(parentAreaFile);
const file = this.appUtils.getTFileFromStrLink(parentStr);
parentArea = this.createArea(file);
}
return new Area(id, file.name.replace(".md", ""), parentArea)
}
async createEffort(file: TFile): Promise<Effort> {
const koProperties = this.appUtils.getFrontmatterOrThrow(file);
const id: UUID = koProperties["uid"] as UUID;
const status: EffortStatus = koProperties["e-status"] as EffortStatus;
const started: Date | null = koProperties["started"] ? koProperties["started"] as Date : null;
const ended: Date | null = koProperties["ended"] ? koProperties["ended"] as Date : null;
let area: Area | null = null;
const areaStr: string = koProperties["area"];
if (areaStr) {
const file = this.appUtils.getTFileFromStrLink(areaStr);
area = this.createArea(file);
}
let parent: Effort | null = null;
const parentStr: string = koProperties["e-parent"];
if (parentStr) {
const file = this.appUtils.getTFileFromStrLink(areaStr);
parent = await this.createEffort(file);
}
const body: string = await this.appUtils.getFileBody(file);
return new Effort(id, file.name.replace(".md", ""), status, started, ended, area, parent, body);
}
getFileKoc(file: TFile): KOC {
const tags = this.appUtils.getTagsFromFile(file);

View File

@ -3,4 +3,6 @@ import Area from "../../domain/Area";
export default interface CreateEffortUseCase {
taskUnderArea(area: Area): Promise<Effort>;
taskUnderEffort(parentEffort: Effort): Promise<Effort>;
}

View File

@ -19,4 +19,14 @@ export default class CreateEffortService implements CreateEffortUseCase {
return effort;
}
async taskUnderEffort(parentEffort: Effort): Promise<Effort> {
const title = crypto.randomUUID();
const id = crypto.randomUUID() as UUID;
const effort = new Effort(id, title, EffortStatus.DRAFT, null, null, null, parentEffort, "Body");
await this.effortRepository.save(effort);
return effort;
}
}