update
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
export const PROJECTS_ROOT = "projects";
|
||||
export const TO_UPDATE_DIR = "_to-update";
|
||||
export const IDEAS_DIR = "_ideas";
|
||||
|
||||
export const VIEW_TYPE_PROJECT_VIEW = "projektkontext-projects";
|
||||
export const VIEW_TYPE_PROJECT_DETAILS_VIEW = "projektkontext-overview";
|
||||
|
||||
23
src/fs.ts
23
src/fs.ts
@@ -1,7 +1,7 @@
|
||||
import { App, TFile, TFolder, normalizePath } from "obsidian";
|
||||
import { PROJECTS_ROOT, PROJECT_FILES, TO_UPDATE_DIR } from "./const";
|
||||
import { PROJECTS_ROOT, PROJECT_FILES, TO_UPDATE_DIR, IDEAS_DIR } from "./const";
|
||||
|
||||
export type Zone = "ready" | "to-update";
|
||||
export type Zone = "ready" | "to-update" | "ideas";
|
||||
|
||||
export function projectsPath(): string {
|
||||
return PROJECTS_ROOT;
|
||||
@@ -15,8 +15,14 @@ export function toUpdatePath(project: string): string {
|
||||
return normalizePath(`${PROJECTS_ROOT}/${project}/${TO_UPDATE_DIR}`);
|
||||
}
|
||||
|
||||
export function ideasPath(project: string): string {
|
||||
return normalizePath(`${PROJECTS_ROOT}/${project}/${IDEAS_DIR}`);
|
||||
}
|
||||
|
||||
export function zoneRootPath(project: string, zone: Zone): string {
|
||||
return zone === "ready" ? projectPath(project) : toUpdatePath(project);
|
||||
if (zone === "ready") return projectPath(project);
|
||||
if (zone === "to-update") return toUpdatePath(project);
|
||||
return ideasPath(project);
|
||||
}
|
||||
|
||||
export function collectionPath(project: string, collection: string, zone: Zone = "ready"): string {
|
||||
@@ -54,7 +60,7 @@ export function listFolders(app: App, path: string): TFolder[] {
|
||||
if (!(folder instanceof TFolder)) return [];
|
||||
return folder.children
|
||||
.filter((c): c is TFolder => c instanceof TFolder)
|
||||
.filter((c) => !c.name.startsWith("__"))
|
||||
.filter((c) => !c.name.startsWith("_") || c.name.startsWith("__"))
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
}
|
||||
|
||||
@@ -65,7 +71,7 @@ export function listMarkdownFiles(app: App, path: string, exclude: string[] = []
|
||||
return folder.children
|
||||
.filter((c): c is TFile => c instanceof TFile && c.extension === "md")
|
||||
.filter((f) => !exclude.includes(f.name))
|
||||
.filter((f) => !f.basename.startsWith("__"))
|
||||
.filter((f) => !f.basename.startsWith("_") || f.basename.startsWith("__"))
|
||||
.sort((a, b) => a.basename.localeCompare(b.basename));
|
||||
}
|
||||
|
||||
@@ -105,7 +111,7 @@ export async function createCollection(
|
||||
collection: string,
|
||||
zone: Zone = "to-update",
|
||||
): Promise<void> {
|
||||
if (zone === "to-update") await ensureFolder(app, toUpdatePath(project));
|
||||
if (zone !== "ready") await ensureFolder(app, zoneRootPath(project, zone));
|
||||
await ensureFolder(app, collectionPath(project, collection, zone));
|
||||
}
|
||||
|
||||
@@ -134,7 +140,7 @@ export async function createProjectFeature(
|
||||
feature: string,
|
||||
zone: Zone = "to-update",
|
||||
): Promise<TFile> {
|
||||
if (zone === "to-update") await ensureFolder(app, toUpdatePath(project));
|
||||
if (zone !== "ready") await ensureFolder(app, zoneRootPath(project, zone));
|
||||
return await ensureFile(app, projectFeaturePath(project, feature, zone), "");
|
||||
}
|
||||
|
||||
@@ -155,6 +161,9 @@ export function parseProjectFilePath(path: string): ProjectFileLocation | null {
|
||||
if (rest[0] === TO_UPDATE_DIR) {
|
||||
zone = "to-update";
|
||||
rest.shift();
|
||||
} else if (rest[0] === IDEAS_DIR) {
|
||||
zone = "ideas";
|
||||
rest.shift();
|
||||
}
|
||||
if (rest.length === 1) return { project, zone };
|
||||
if (rest.length === 2) return { project, collection: rest[0], zone };
|
||||
|
||||
@@ -16,12 +16,10 @@ import {
|
||||
PROJECT_FILES,
|
||||
CORE_FILE,
|
||||
TARGET_FILE,
|
||||
TO_UPDATE_DIR,
|
||||
} from "../const";
|
||||
import {
|
||||
Zone,
|
||||
projectPath,
|
||||
toUpdatePath,
|
||||
zoneRootPath,
|
||||
listFolders,
|
||||
listMarkdownFiles,
|
||||
@@ -147,35 +145,33 @@ export class ProjectDetailsView extends ItemView {
|
||||
|
||||
private renderCollections(parent: HTMLElement): void {
|
||||
const section = parent.createDiv({ cls: "pk-areas-section" });
|
||||
section.addEventListener("contextmenu", (ev) => {
|
||||
if (ev.defaultPrevented) return;
|
||||
ev.preventDefault();
|
||||
menu(ev, [
|
||||
{ title: "Neue Collection", icon: "plus", onClick: () => this.openCreateCollection() },
|
||||
{ title: "Neues Feature", icon: "plus", onClick: () => this.openCreateProjectFeature() },
|
||||
]);
|
||||
});
|
||||
|
||||
const ready = this.collectZoneItems("ready");
|
||||
const toUpdate = this.collectZoneItems("to-update");
|
||||
const ideas = this.collectZoneItems("ideas");
|
||||
|
||||
this.renderZone(section, "ready", ready);
|
||||
section.createEl("hr", { cls: "pk-zone-divider" });
|
||||
this.renderZone(section, "to-update", toUpdate);
|
||||
section.createEl("hr", { cls: "pk-zone-divider" });
|
||||
this.renderZone(section, "ideas", ideas);
|
||||
}
|
||||
|
||||
private collectZoneItems(zone: Zone): { collections: TFolder[]; features: TFile[] } {
|
||||
const root = zoneRootPath(this.project, zone);
|
||||
const folders = listFolders(this.app, root);
|
||||
const collections = zone === "ready"
|
||||
? folders.filter((f) => f.name !== TO_UPDATE_DIR)
|
||||
: folders;
|
||||
const features = listMarkdownFiles(
|
||||
this.app,
|
||||
root,
|
||||
zone === "ready" ? [...PROJECT_FILES] : [],
|
||||
);
|
||||
return { collections, features };
|
||||
return { collections: folders, features };
|
||||
}
|
||||
|
||||
private zoneEmptyText(zone: Zone): string {
|
||||
if (zone === "ready") return "Keine fertigen Features";
|
||||
if (zone === "to-update") return "Keine unfertigen Features";
|
||||
return "Keine neuen Features";
|
||||
}
|
||||
|
||||
private renderZone(
|
||||
@@ -187,6 +183,14 @@ export class ProjectDetailsView extends ItemView {
|
||||
cls: `pk-areas-flex pk-zone-${zone}`,
|
||||
attr: { "data-zone": zone },
|
||||
});
|
||||
flex.addEventListener("contextmenu", (ev) => {
|
||||
if (ev.defaultPrevented) return;
|
||||
ev.preventDefault();
|
||||
menu(ev, [
|
||||
{ title: "Neue Collection", icon: "plus", onClick: () => this.openCreateCollection(zone) },
|
||||
{ title: "Neues Feature", icon: "plus", onClick: () => this.openCreateProjectFeature(zone) },
|
||||
]);
|
||||
});
|
||||
flex.addEventListener("dragover", (ev) => {
|
||||
if (!ev.dataTransfer?.types.includes(PK_DND_MIME)) return;
|
||||
ev.preventDefault();
|
||||
@@ -214,7 +218,7 @@ export class ProjectDetailsView extends ItemView {
|
||||
this.renderProjectFeatureCard(flex, zone, f);
|
||||
}
|
||||
if (items.collections.length === 0 && items.features.length === 0) {
|
||||
flex.createDiv({ cls: "pk-zone-placeholder", text: "Keine Features" });
|
||||
flex.createDiv({ cls: "pk-zone-placeholder", text: this.zoneEmptyText(zone) });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -237,7 +241,7 @@ export class ProjectDetailsView extends ItemView {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
menu(ev, [
|
||||
{ title: "Neue Collection", icon: "plus", onClick: () => this.openCreateCollection() },
|
||||
{ title: "Neue Collection", icon: "plus", onClick: () => this.openCreateCollection(zone) },
|
||||
{ title: "Collection umbenennen", icon: "pencil", onClick: () => this.openRenameCollectionAt(folderPath, collection.name, takenCollections) },
|
||||
{ title: "Collection löschen", icon: "trash", onClick: () => this.openDeletePath(folderPath) },
|
||||
]);
|
||||
@@ -330,7 +334,7 @@ export class ProjectDetailsView extends ItemView {
|
||||
ev.preventDefault();
|
||||
ev.stopPropagation();
|
||||
menu(ev, [
|
||||
{ title: "Neues Feature", icon: "plus", onClick: () => this.openCreateProjectFeatureInZone(zone) },
|
||||
{ title: "Neues Feature", icon: "plus", onClick: () => this.openCreateProjectFeature(zone) },
|
||||
{ title: "Feature löschen", icon: "trash", onClick: () => this.openDeletePath(file.path) },
|
||||
]);
|
||||
});
|
||||
@@ -356,7 +360,7 @@ export class ProjectDetailsView extends ItemView {
|
||||
: data.name;
|
||||
const newPath = normalizePath(`${root}/${targetName}`);
|
||||
if (data.sourcePath === newPath) return;
|
||||
if (zone === "to-update") await ensureFolder(this.app, toUpdatePath(this.project));
|
||||
if (zone !== "ready") await ensureFolder(this.app, root);
|
||||
await this.movePath(data.sourcePath, newPath);
|
||||
}
|
||||
|
||||
@@ -384,11 +388,7 @@ export class ProjectDetailsView extends ItemView {
|
||||
await this.render();
|
||||
}
|
||||
|
||||
private openCreateProjectFeature(): void {
|
||||
this.openCreateProjectFeatureInZone("to-update");
|
||||
}
|
||||
|
||||
private openCreateProjectFeatureInZone(zone: Zone): void {
|
||||
private openCreateProjectFeature(zone: Zone = "to-update"): void {
|
||||
const root = zoneRootPath(this.project, zone);
|
||||
const existing = listMarkdownFiles(
|
||||
this.app,
|
||||
@@ -408,18 +408,18 @@ export class ProjectDetailsView extends ItemView {
|
||||
}).open();
|
||||
}
|
||||
|
||||
private openCreateCollection(): void {
|
||||
const ready = listFolders(this.app, projectPath(this.project))
|
||||
.filter((f) => f.name !== TO_UPDATE_DIR).map((a) => a.name);
|
||||
const inToUpdate = listFolders(this.app, toUpdatePath(this.project)).map((a) => a.name);
|
||||
const taken = [...ready, ...inToUpdate];
|
||||
private openCreateCollection(zone: Zone = "to-update"): void {
|
||||
const allZones: Zone[] = ["ready", "to-update", "ideas"];
|
||||
const taken = allZones.flatMap((z) =>
|
||||
listFolders(this.app, zoneRootPath(this.project, z)).map((a) => a.name),
|
||||
);
|
||||
new NameModal(this.app, {
|
||||
title: "Neue Collection",
|
||||
label: "Collection-Name",
|
||||
cta: "Erstellen",
|
||||
validate: (n) => validateName(n, taken),
|
||||
onSubmit: async (name) => {
|
||||
await createCollection(this.app, this.project, name);
|
||||
await createCollection(this.app, this.project, name, zone);
|
||||
await this.render();
|
||||
},
|
||||
}).open();
|
||||
|
||||
@@ -249,6 +249,7 @@
|
||||
text-align: center;
|
||||
padding: 30px 12px;
|
||||
pointer-events: none;
|
||||
column-span: all;
|
||||
}
|
||||
|
||||
.pk-area-card {
|
||||
|
||||
Reference in New Issue
Block a user