Project

Manage projects with tasks, priorities, due dates, and assignees. Views show overdue and active tasks.

A project management template. Create a Project note as the root, then add Task notes as children. The project has two custom views — Overdue Tasks and Active Tasks — that filter and sort tasks by due date.

Project template screenshot

Downloads

How to use

  1. Import project.rhai in Settings → Scripts → Import Script
  2. Create a new note and choose Project as the type
  3. Set the project status (Planning, Active, On Hold, or Done)
  4. Add children and choose Task as the type for each
  5. Fill in the task name, status, priority, due date, and assignee
  6. Switch between the Overdue Tasks and Active Tasks views

How it works

Project schema — on_save hook

When you save a Project, the health field is automatically computed from the project status:

StatusHealth
PlanningPlanning
ActiveActive
On HoldOn Hold
DoneDone

Task schema — on_save hook

When you save a Task, the title is set to a formatted string with a status indicator: [ ] Name for TODO, [→] Name for WIP, and [✓] Name for DONE.

The priority_label field is derived from the priority selection with coloured indicators (High, Medium, Low).

Overdue Tasks view

Filters all child tasks that are not DONE and whose due date is before today. Results are sorted by due date (earliest first) and displayed in a table with status, priority, due date, and assignee columns.

Active Tasks view

Shows all tasks that are not DONE, sorted with dated tasks first (by due date) followed by undated tasks. Displayed as a table with the same columns.

Hover previews

Hovering a Project shows its health indicator and task completion ratio (e.g. “3/7 done”). Hovering a Task shows its status, priority, and due date.

Schema

schema("Project", #{
    version: 1,
    title_can_edit: true,
    allowed_children_schemas: ["TextNote", "Task"],
    fields: [
        #{ name: "status",      type: "select",   required: true,
           options: ["Planning", "Active", "On Hold", "Done"]                  },
        #{ name: "priority",    type: "select",   required: false,
           options: ["low", "medium", "high"]                                  },
        #{ name: "start_date",  type: "date",     required: false              },
        #{ name: "due_date",    type: "date",     required: false              },
        #{ name: "description", type: "textarea", required: false              },
        #{ name: "health",      type: "text",     required: false,
           can_edit: false                                                      },
    ],
    on_save: |note| {
        let status = note.fields["status"];

        set_field(note.id, "health",
            if status == "Done"          { "✅ Done" }
            else if status == "Active"   { "🚧 Active" }
            else if status == "On Hold"  { "⏸ On Hold" }
            else                         { "📋 Planning" });

        commit();
    }
});

schema("Task", #{
    version: 1,
    title_can_edit: false,
    allowed_parent_schemas: ["Project"],
    fields: [
        #{ name: "name",           type: "text",     required: true                     },
        #{ name: "status",         type: "select",   required: true,
           options: ["TODO", "WIP", "DONE"]                                             },
        #{ name: "priority",       type: "select",   required: false,
           options: ["low", "medium", "high"]                                           },
        #{ name: "due_date",       type: "date",     required: false                    },
        #{ name: "assignee",       type: "text",     required: false                    },
        #{ name: "notes",          type: "textarea", required: false                    },
        #{ name: "priority_label", type: "text",     required: false,
           can_edit: false                                                               },
    ],
    on_save: |note| {
        let name   = note.fields["name"];
        let status = note.fields["status"];

        let symbol = if status == "DONE" { "✓" }
                     else if status == "WIP" { "→" }
                     else { " " };

        set_title(note.id, "[" + symbol + "] " + name);

        let priority = note.fields["priority"];
        set_field(note.id, "priority_label",
            if priority == "high"        { "🔴 High" }
            else if priority == "medium" { "🟡 Medium" }
            else if priority == "low"    { "🟢 Low" }
            else                         { "" });

        commit();
    }
});