super-productivity/docs
Johannes Millan 91d8dd80ba
feat(plainspace): add integration for shared projects (#8424)
* docs(plainspace): add integration plan for shared projects

* feat(plainspace): prototype 'assigned to others' work-view panel

UI-only prototype of the dual-list shared-project view: a read-only
component that lists Plainspace tasks owned by other members, grouped by
assignee, rendered as a collapsible panel in the project work view.

Uses hard-coded sample data; foreign tasks never enter the SP task store
or op-log sync. See docs/plainspace-integration-plan.md.

* refactor(plainspace): apply review fixes to prototype panel

- use defined --text-color-muted / --s-half / --s2 tokens instead of an
  undefined token and redundant spacing fallbacks
- drop unused PLAINSPACE.DONE i18n key
- note avatarUrl sanitization needed before live API data
- clarify plan doc: icon registration in GlobalThemeService, issueType
  union widening, and which phases are design-only vs implemented

* feat(plainspace): add mock-backed issue provider + share-on-create toggle

Phase 1: register PLAINSPACE as an issue provider (config form, API
service with mock mode, IssueServiceInterface impl, issue.model/const/
service registration, icon, issue-content config). Tasks assigned to me or
unassigned import via the normal issue->backlog pipeline; tasks assigned to
others are excluded here (shown read-only by the separate panel).

Phase 3: add a 'Share on Plainspace' toggle to the create-project dialog
that provisions a (mock) space and a bound provider via
PlainspaceShareService.

All Plainspace calls are mocked (PLAINSPACE_USE_MOCK) so the flow works
without a live backend; the real HTTP contract is isolated in
PlainspaceApiService. Build + lint:ts + lint:scss pass; added a spec for
the provider's mock/filter logic (unit run blocked: no browser in env).

* refactor(plainspace): address review feedback on provider + share flow

- add a Plainspace tile to the issue-provider setup overview so the
  provider is addable manually (connect to an existing space), not only
  via the share-on-create toggle
- make PlainspaceShareService self-contained: catch errors, surface a
  snack, never reject (safe to fire-and-forget); log ids only
- strip the transient isShareOnPlainspace flag before it can reach
  sessionStorage on the dialog cancel path
- add a getIssueProviderTooltip case for PLAINSPACE (was falling through
  to the raw key)
- drop a redundant cast now that PlainspaceIssue is in IssueDataReduced

* feat(plainspace): add account login / identity (Phase 2, mock)

- PlainspaceAccountService: signals (account/isLoggedIn/currentUserId),
  mock login/logout, localStorage-persisted (local-only, never synced)
- 'mine' in the import filter now derives from the signed-in identity
  instead of a hard-coded constant; not-logged-in => only unassigned
- the Share-on-Plainspace flow prompts (mock) sign-in if needed and
  refuses to provision a space when the user declines
- move the mock user-id constant to the plainspace feature folder to
  avoid a cross-folder import cycle
- specs for the account service and updated api-service spec (sign in
  before asserting the mine/unassigned split)

Identity is mocked (fixed user id) so the assigned/unassigned split lines
up with the mock space data; real OAuth/token exchange is future work.

* feat(plainspace): feed 'assigned to others' panel from live mock data

Wire the work-view panel to a new PlainspaceSharedTasksService instead of
hard-coded sample data: for a project with a bound enabled PLAINSPACE
provider, it fetches the space's tasks, keeps only those assigned to
others (assigneeId !== me), maps them to read-only rows, and threads them
through project-task-page -> work-view as an input. The panel now appears
only for shared projects (not every project), and foreign tasks still
never enter the SP task store / op-log.

Removes the prototype data const; adds a service spec.

* refactor(plainspace): replace 'assigned to others' list with a claim pool

Reframe around task ownership: SP shows only tasks assigned to me (first-
class) plus a read-only 'claim pool' of unclaimed tasks. Tasks assigned to
others are no longer represented in SP.

- import filter is now assigned-to-me only (was mine+unassigned)
- new claim flow: PlainspaceApiService.claimTask$ (assign-to-self) +
  PlainspaceClaimPoolService.claim -> IssueService.addTaskFromIssue, with
  pool refresh; claimed task leaves the pool
- rename AssignedToOthers component/service -> claim-pool; panel is
  collapsed by default (a pool you reach for, not active work)
- drop assignee badges (redundant: list is all 'mine'; provider icon
  already marks Plainspace tasks)
- mock data made resettable for test isolation; specs updated/added
- docs: capture the ownership model + rationale for dropping the list

* docs(plainspace): fix remaining stale claim-pool reference

* feat(plainspace): connect provider to the real integration API

Replace the mock-backed PlainspaceApiService with the real PAT-authed
{host}/api/integration endpoints (me, tasks, claimable-tasks, claim,
spaces, done PATCH) and map the wire SPTask -> the internal PlainspaceIssue
so the rest of the provider depends on one stable shape.

- the server scopes /tasks to the caller, so drop client-side identity and
  the mock data/identity consts; "mine" is decided server-side
- store the personal API token (PAT) in PlainspaceCfg like other providers'
  secrets; keep a local-only account cache to bootstrap share-on-create
- add a token field to the config form; the share flow prompts for and
  validates a PAT via /me before provisioning a space
- isEnabled now requires a token; testConnection hits /me; issueLink uses
  the task's real url

Adds docs/plainspace-api-extension-plan.md documenting the server contract
this client consumes (the endpoints added to Johannesjo/spaces).

* feat(plainspace): guided connect dialog with token steps + link

Replace the bare one-line API-token prompt with PlainspaceConnectDialog,
which shows where to create a personal API token and validates it before
closing:

- numbered step-by-step (Space -> People -> Advanced -> API tokens) plus an
  "Open Plainspace" link button
- inline validation via /me; an invalid token shows an error and keeps the
  dialog open instead of failing silently
- wire it into the share-on-create flow and sharpen the config-form token
  description to point at the same place

Adds the CONNECT i18n block (regenerates t.const) and drops the now-unused
LOGIN_PROMPT string; a new component spec covers connect/cancel + template.

* feat(plainspace): auto-import + two-way done sync

- default isAutoAddToBacklog to true so tasks assigned to me auto-import
  into the bound project's backlog (poll-to-backlog), matching the seamless
  intent
- add PlainspaceSyncAdapterService, registered for 'PLAINSPACE' in the
  two-way-sync effect, so completing/reopening a task in SP pushes the done
  state back to Plainspace via PATCH /tasks/:id { done }

Only isDone is pushed (the integration API's one writable field); title and
done changes from Plainspace are pulled by the existing update polling. Adds
an adapter spec and a Plainspace adapter spy in the two-way-sync effect spec.

* fix(plainspace): match bound space by slug or id so tasks import

getMyTasks$ filtered by `task.projectId === cfg.spaceId`, but the value users
copy from the space URL is the slug while SPTask.projectId is the UUID — so a
slug-configured provider matched zero tasks and imported nothing, even though
the /tasks response was full.

Match spaceId against both projectId and projectSlug (getMyTasks$ and the claim
pool), drop the server ?projectId= param (UUID-only) in favour of the same
client-side match, and point the Space ID help text at the slug in the URL.

* chore(plainspace): log import counts to diagnose missing imports

getMyTasks$ now logs total vs space-matched task counts (ids/counts only,
no task content) so we can tell whether the space filter or the import is
dropping tasks. Temporary diagnostic.

* feat: add picker for plainspace

* feat: improve wording

* feat(plainspace): use two-circle brand mark for provider icon

* refactor(plainspace): type create-project form to drop isShareOnPlainspace any-cast

* refactor(plainspace): remove temporary getMyTasks$ diagnostic log

* feat(plainspace): push scheduled time (dueWithTime → remindAt)

* fix(plainspace): seed two-way-sync baseline so write-back actually fires

* feat(plainspace): import remindAt as dueWithTime so schedule shows in app

* refactor(plainspace): align client to scheduledAt/isRecurring API contract

* feat(plainspace): flag recurring tasks in the claim pool

* feat(plainspace): pull scheduledAt into dueWithTime on poll (schedule existing + recurring tasks)

* feat(plainspace): push title changes back to Plainspace

* fix(plainspace): address multi-review findings (perf, UX, cleanup)

Performance:
- claim pool no longer re-fetches /claimable-tasks on every task
  add/complete/reorder (distinct on project id + provider identity)
- poll imported tasks via one getMyTasks$ instead of N getById$ calls

UX:
- gate the "Share on Plainspace" toggle to project create (was a dead
  control in edit mode)
- success/failure snacks on claim and share (silent 409/offline before)
- distinct error state in the space-picker (vs misleading "no spaces yet")

Correctness/cleanup:
- normalize scheduledAt to canonical UTC ISO on read so the push guard
  can't silently drop a reschedule on a benign reformat
- drop dead PLAINSPACE_INITIAL_POLL_DELAY, PlainspaceMember, assignee
- translate the "Advanced Config" form label

* docs(plainspace): reconcile token storage + forward-compat rollout note

- document that the PAT lives in synced provider cfg like other providers
  (the earlier "not stored here" note was never true in the shipped code)
- add the typia forward-compat rollout requirement for the new built-in
  PLAINSPACE issue-provider key to the Risks section
- fix stale "assigned to others" wording (now the claim pool)

* feat(plainspace): trim redundant Notes button + issue panel

Plainspace mirrors title/done/schedule onto native task fields, so the
detail panel only echoed the task and the chat button opened an
essentially empty drawer.

- Treat PLAINSPACE like ICAL: don't show the *persistent* toggle button
  just because the task carries an issueId. Keep it for real notes, a
  remote update (issueWasUpdated) and the open-panel close state.
- Keep the panel reachable: the hover-only "open detail panel" button
  (task-hover-controls) now covers PLAINSPACE too — it's the exact
  complement of the persistent button, so plain/iCal/Plainspace tasks all
  get a hover affordance and there's never a double button.
- Replace the redundant title-as-"Summary" link with the two things not
  already on the task: a clear "Open in Plainspace" link and a recurrence
  indicator rendered with the same `repeat` mat-icon the claim pool uses
  (new 'plainspace-recurring' custom field).
- Add unit coverage for the new content config.

---------

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-18 17:58:06 +02:00
..
long-term-plans docs: remove outdated and implemented plan docs 2026-06-08 12:38:51 +02:00
plans feat(focus-mode): focus screen UX overhaul (#7586) 2026-06-12 11:59:56 +02:00
promotion build: better organize stuff 2025-06-27 09:03:16 +02:00
research feat(task-repeat): RFC 5545 RRULE recurring schedules — EPIC · Phase 1/13 (Closes #4020) (#7948) 2026-06-09 11:25:35 +02:00
screens docs/wiki content v0.8 (#7068) 2026-04-01 12:40:28 +02:00
sync-and-op-log refactor(sync-core): drop shared-schema vector-clock compat re-export anda app enum (#8441) 2026-06-17 16:21:26 +02:00
wiki feat(focus-mode): surface session-done + notify on countdown completion (#8475) 2026-06-18 17:33:02 +02:00
add-new-integration.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
android-edge-to-edge-keyboard.md fix(android): inset WebView for IME under enforced edge-to-edge (draft) 2026-06-16 17:00:55 +02:00
apple-release-automation.md ci: auto-submit iOS and macOS App Store builds for review (#7857) 2026-06-01 11:42:16 +02:00
build-and-publish-notes.md fix(ci): prevent duplicate unsigned exe files in GitHub Releases 2026-03-19 18:58:52 +01:00
documentation-guide.md Housekeeping for various docs, templates, and actions (#7451) 2026-05-02 13:58:25 +02:00
ENV_SETUP.md build: final approach 2025-07-14 20:52:51 +02:00
github-access-token-instructions.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
gitlab-access-token-instructions.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
how-to-rate.md feat(rate-dialog): action-aware prompt with feedback split 2026-05-04 17:27:11 +02:00
howto-refresh-snap-credentials.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
i18n-script-usage.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
legacy-webview-analysis.md 16.2.1 2025-11-01 13:22:58 +01:00
mac-app-store-code-signing-guide.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
performance-project-tag-report.md docs: add performance report 2025-11-13 18:23:50 +01:00
plainspace-api-extension-plan.md feat(plainspace): add integration for shared projects (#8424) 2026-06-18 17:58:06 +02:00
plainspace-integration-plan.md feat(plainspace): add integration for shared projects (#8424) 2026-06-18 17:58:06 +02:00
plugin-development.md fix(plugins): expose focused task API to iframe plugins (#8291) 2026-06-15 14:57:34 +02:00
styling-guide.md fix(onboarding): harden sync setup dismissal 2026-06-03 19:54:14 +02:00
theming-contract.md feat(theme): add Plainspace built-in theme 2026-06-15 14:06:21 +02:00
TRANSLATING.md Fix frequency translations (#8000) 2026-06-05 10:53:26 +02:00
unused-translations-analysis.md chore(i18n): remove additional 86 orphan translation keys 2026-01-09 14:59:05 +01:00
update-android-app.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00
update-mac-certificates.md docs: clean up and organize project documentation 2026-03-10 10:22:56 +01:00