Idea: Per-project folders + simple project picker (no file search) — with a working QuickAdd workaround #818
alekseiaxelrod-oss
started this conversation in
Ideas
Replies: 2 comments 1 reply
-
You can already customize this in Settings > TaskNotes > Appearance & UI > Project Autosuggest |
Beta Was this translation helpful? Give feedback.
1 reply
-
|
Good work, but some of my tasks have more than one project listed. I do this so they will appear in more than one tasks widget. I don't find it too much of a problem to move the task after saving. Or I created it inline in the project page, so it is saved in the same folder. |
Beta Was this translation helpful? Give feedback.
0 replies
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
What’s missing right now
Tasks created from Advanced Calendar end up in a single folder (e.g., TaskNotes/Tasks) and aren’t auto-routed to project folders.
The project picker in the modal is not convenient: you have to search for a file instead of picking from your existing projects.
Proposal
Add a built-in option for Project routing: when projects is set, automatically move the task note into the corresponding project’s folder, with clean filename numbering (Task.md, Task-2.md, Task-3.md, …).
Add a dropdown / fixed list of existing projects in the modal (instead of file search).
Optional post-save hook: as soon as projects is present, move the file.
Working workaround (today)
Until this exists natively, I’m using a QuickAdd macro that:
shows a fixed list of my projects (e.g., Project-1…Project-5),
writes projects: [[Project-N]] (short wiki link),
moves the task file to that project’s folder, with robust, readable numbering.
Setup (checklist)
Install QuickAdd (Community plugins).
Create folder /_scripts/quickadd/.
Create file /_scripts/quickadd/assign_project_and_move.js and paste the script below.
QuickAdd → Manage Macros → Add Macro Assign Project → Add Command → User script → select the file.
Hotkeys → set a shortcut for QuickAdd: Run Macro: Assign Project.
Flow: Create task in Advanced Calendar → press the hotkey → pick a project → file is routed to the project folder.
Customization
Edit the 5 project paths at the top of the script.
Toggle USE_TASKS_SUBFOLDER to place tasks in /tasks/.
Toggle filename style: -2 vs (2) via USE_PARENS_STYLE.
Notes / limitations
Project note filenames should be unique (Project-1.md, Project-2.md, …).
Script (QuickAdd User Script, )
Save as: /_scripts/quickadd/assign_project_and_move.js
module.exports = async (params) => {
const app = params.app;
const qa = params.quickAddApi;
// ==== CONFIG ====
const DEFAULT_TASKS_FOLDER = "TaskNotes/Tasks"; // where new tasks are created
const USE_TASKS_SUBFOLDER = false; // true → /tasks/
const USE_PARENS_STYLE = false; // filename style: "Task (2).md" instead of "Task-2.md"
const PROJECT_FILES = [
{ path: "TaskNotes/Projects/Project-1/Project-1.md" },
{ path: "TaskNotes/Projects/Project-2/Project-2.md" },
{ path: "TaskNotes/Projects/Project-3/Project-3.md" },
{ path: "TaskNotes/Projects/Project-4/Project-4.md" },
{ path: "TaskNotes/Projects/Project-5/Project-5.md" }
];
// ================
const basename = (p) => p.split("/").pop().replace(/.md$/, "");
// Map "Project-1" → "TaskNotes/Projects/Project-1/Project-1.md"
const NAME_TO_PATH = (() => {
const m = new Map();
for (const p of PROJECT_FILES) m.set(basename(p.path), p.path);
return m;
})();
// Strip trailing numeric suffix: "Task-7" → "Task", "Task (7)" → "Task"
const stripNum = (name) => {
let m = name.match(/^(.)\s((\d+))$/);
if (m) return { base: m[1].trim(), n: +m[2] };
m = name.match(/^(.*?)-(\d+)$/);
if (m) return { base: m[1], n: +m[2] };
return { base: name, n: null };
};
// Robust unique filename picker inside target folder
const pickUnique = (folder, fileName, selfPath) => {
const ext = fileName.endsWith(".md") ? ".md" : "";
const raw = ext ? fileName.slice(0, -3) : fileName;
const { base } = stripNum(raw);
};
// Ensure nested folders exist
const ensureFolder = async (path) => {
const segs = path.split("/");
for (let i = 1; i <= segs.length; i++) {
const sub = segs.slice(0, i).join("/");
if (!sub) continue;
if (!app.vault.getAbstractFileByPath(sub)) {
try { await app.vault.createFolder(sub); } catch (_) {}
}
}
};
// Find the "newest" task in DEFAULT_TASKS_FOLDER (prefer one without
projects)const findNewestTask = () => {
const files = app.vault.getMarkdownFiles()
.filter(f => f.path.startsWith(DEFAULT_TASKS_FOLDER + "/"));
if (!files.length) return null;
files.sort((a, b) => b.stat.ctime - a.stat.ctime);
for (const f of files) {
const fm = app.metadataCache.getFileCache(f)?.frontmatter ?? {};
if (!(fm.projects || fm.project)) return f; // prefer the one not assigned yet
}
return files[0];
};
try {
const file = findNewestTask();
if (!file) { new Notice("No recent task found in " + DEFAULT_TASKS_FOLDER); return; }
} catch (err) {
console.error(err);
new Notice("QuickAdd: script error. See console for details.");
}
};
Beta Was this translation helpful? Give feedback.
All reactions