PhoenixKitProjects (PhoenixKitProjects v0.24.0)

Copy Markdown View Source

Projects module for PhoenixKit.

Provides a reusable task library, projects that pull tasks in as assignments (with team/department/person assignees), and task dependency chains within each project.

Summary

Functions

One-time data repairs for installs that predate a change here. Core calls this on every boot, so each repair carries its own "already done" flag and runs exactly once.

Notification preference types (Step 7 of the hub rework): the actions below fan out through core's activity→notification bridge whenever their entries carry a target_uuid (the affected user — assignees on task actions, the member on membership actions). Users tune each sub-type — and its Email/Telegram routing — in their notification preferences.

Places a dashboard may be shown inside this module — the duck-typed phoenix_kit_dashboard_slots/0 contract (no dependency on phoenix_kit_dashboards, no @impl, exactly like phoenix_kit_widgets/0).

Resolves "my project" for a viewer — the viewer bind source in the dashboards package.

Functions

ai_translatables()

handle_ai_usage(request)

migrate_legacy()

One-time data repairs for installs that predate a change here. Core calls this on every boot, so each repair carries its own "already done" flag and runs exactly once.

  • projects.admin_all is granted to every role that already holds the base projects key, preserving the pre-split behavior.
  • Projects carrying the old, incomplete "simple to-do list" preset get the three flags that preset should always have turned off.

Both are deliberately one-way and one-time: re-deciding on every boot would fight the Owner, handing back a permission they revoked or re-disabling a feature they turned on.

notification_types()

Notification preference types (Step 7 of the hub rework): the actions below fan out through core's activity→notification bridge whenever their entries carry a target_uuid (the affected user — assignees on task actions, the member on membership actions). Users tune each sub-type — and its Email/Telegram routing — in their notification preferences.

phoenix_kit_dashboard_slots()

@spec phoenix_kit_dashboard_slots() :: [map()]

Places a dashboard may be shown inside this module — the duck-typed phoenix_kit_dashboard_slots/0 contract (no dependency on phoenix_kit_dashboards, no @impl, exactly like phoenix_kit_widgets/0).

Declaring these is CONSENT. The dashboards package is able to inject a sub-tab under any module's sidebar entry without asking — core groups sub-tabs by parent id with no ownership check — and deliberately does not. Nothing appears under Projects that is not declared right here.

Two places:

  • Projects dashboard — a sidebar sub-tab beside the list and the Overview. Context-free: it is about the whole module, so widgets bound to "the project this page is about" have nothing to read and say so. A widget bound to the viewer's own project resolves fine here, which is what makes one shared board work for every project manager.
  • Project page — the Dashboard tab inside a project. It supplies projects.project, so one shared board serves every project instead of needing a copy each. It is the SAME tab this module's dashboard extension contributes, and the two settle by specificity: a project that picks its own board in its Modules panel overrides the placement, everything else follows it.

The list stays the project list: neither slot is a landing page. The boss's rule that "an overview and a dashboard are different things" is why Dashboard sits next to Overview rather than replacing it.

phoenix_kit_dashboard_viewer_context(arg1, scope)

@spec phoenix_kit_dashboard_viewer_context(String.t(), term()) :: String.t() | nil

Resolves "my project" for a viewer — the viewer bind source in the dashboards package.

This is the half of the design that a page subject cannot supply: a shared "Project managers" dashboard in the sidebar has no current project, yet each manager needs their own. Only this module can answer that question, so the dashboards package asks rather than guessing.

Deliberately conservative. It answers only when there is exactly ONE project the viewer can reach, and otherwise nil — which renders as "pick a project" rather than a confident wrong answer. Guessing "most recently visited" was considered and rejected: it is wrong every Monday morning, and being silently shown the wrong project's numbers is worse than being shown none.

phoenix_kit_project_extensions()

phoenix_kit_widgets()