@nocobase/app-plugin-office-flows-example 0.0.0-stage → 0.1.0-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (189) hide show
  1. package/CHANGELOG.md +44 -0
  2. package/README.md +55 -2
  3. package/dist/client/components/flow-ui.d.ts +111 -0
  4. package/dist/client/components/flow-ui.d.ts.map +1 -0
  5. package/dist/client/components/flow-ui.js +175 -0
  6. package/dist/client/components/flow-ui.js.map +1 -0
  7. package/dist/client/components/page-container.d.ts +4 -0
  8. package/dist/client/components/page-container.d.ts.map +1 -0
  9. package/dist/client/components/page-container.js +6 -0
  10. package/dist/client/components/page-container.js.map +1 -0
  11. package/dist/client/components/page-header.d.ts +8 -0
  12. package/dist/client/components/page-header.d.ts.map +1 -0
  13. package/dist/client/components/page-header.js +5 -0
  14. package/dist/client/components/page-header.js.map +1 -0
  15. package/dist/client/components/ui/badge.d.ts +7 -0
  16. package/dist/client/components/ui/badge.d.ts.map +1 -0
  17. package/dist/client/components/ui/badge.js +19 -0
  18. package/dist/client/components/ui/badge.js.map +1 -0
  19. package/dist/client/components/ui/button.d.ts +8 -0
  20. package/dist/client/components/ui/button.d.ts.map +1 -0
  21. package/dist/client/components/ui/button.js +25 -0
  22. package/dist/client/components/ui/button.js.map +1 -0
  23. package/dist/client/components/ui/card.d.ts +11 -0
  24. package/dist/client/components/ui/card.d.ts.map +1 -0
  25. package/dist/client/components/ui/card.js +19 -0
  26. package/dist/client/components/ui/card.js.map +1 -0
  27. package/dist/client/components/ui/input.d.ts +4 -0
  28. package/dist/client/components/ui/input.d.ts.map +1 -0
  29. package/dist/client/components/ui/input.js +8 -0
  30. package/dist/client/components/ui/input.js.map +1 -0
  31. package/dist/client/components/ui/select.d.ts +16 -0
  32. package/dist/client/components/ui/select.d.ts.map +1 -0
  33. package/dist/client/components/ui/select.js +36 -0
  34. package/dist/client/components/ui/select.js.map +1 -0
  35. package/dist/client/index.d.ts +2 -0
  36. package/dist/client/index.d.ts.map +1 -0
  37. package/dist/client/index.js +4 -0
  38. package/dist/client/index.js.map +1 -0
  39. package/dist/client/lib/api.d.ts +93 -0
  40. package/dist/client/lib/api.d.ts.map +1 -0
  41. package/dist/client/lib/api.js +67 -0
  42. package/dist/client/lib/api.js.map +1 -0
  43. package/dist/client/lib/format.d.ts +4 -0
  44. package/dist/client/lib/format.d.ts.map +1 -0
  45. package/dist/client/lib/format.js +8 -0
  46. package/dist/client/lib/format.js.map +1 -0
  47. package/dist/client/lib/labels.d.ts +5 -0
  48. package/dist/client/lib/labels.d.ts.map +1 -0
  49. package/dist/client/lib/labels.js +38 -0
  50. package/dist/client/lib/labels.js.map +1 -0
  51. package/dist/client/lib/use-loader.d.ts +10 -0
  52. package/dist/client/lib/use-loader.d.ts.map +1 -0
  53. package/dist/client/lib/use-loader.js +43 -0
  54. package/dist/client/lib/use-loader.js.map +1 -0
  55. package/dist/client/lib/utils.d.ts +2 -0
  56. package/dist/client/lib/utils.d.ts.map +1 -0
  57. package/dist/client/lib/utils.js +2 -0
  58. package/dist/client/lib/utils.js.map +1 -0
  59. package/dist/client/locales/en-US.d.ts +99 -0
  60. package/dist/client/locales/en-US.d.ts.map +1 -0
  61. package/dist/client/locales/en-US.js +92 -0
  62. package/dist/client/locales/en-US.js.map +1 -0
  63. package/dist/client/locales/index.d.ts +4 -0
  64. package/dist/client/locales/index.d.ts.map +1 -0
  65. package/dist/client/locales/index.js +7 -0
  66. package/dist/client/locales/index.js.map +1 -0
  67. package/dist/client/locales/zh-CN.d.ts +4 -0
  68. package/dist/client/locales/zh-CN.d.ts.map +1 -0
  69. package/dist/client/locales/zh-CN.js +92 -0
  70. package/dist/client/locales/zh-CN.js.map +1 -0
  71. package/dist/client/pages/configuration.d.ts +4 -0
  72. package/dist/client/pages/configuration.d.ts.map +1 -0
  73. package/dist/client/pages/configuration.js +34 -0
  74. package/dist/client/pages/configuration.js.map +1 -0
  75. package/dist/client/pages/data-requests.d.ts +3 -0
  76. package/dist/client/pages/data-requests.d.ts.map +1 -0
  77. package/dist/client/pages/data-requests.js +216 -0
  78. package/dist/client/pages/data-requests.js.map +1 -0
  79. package/dist/client/pages/incoming.d.ts +3 -0
  80. package/dist/client/pages/incoming.d.ts.map +1 -0
  81. package/dist/client/pages/incoming.js +128 -0
  82. package/dist/client/pages/incoming.js.map +1 -0
  83. package/dist/client/pages/tasks.d.ts +3 -0
  84. package/dist/client/pages/tasks.d.ts.map +1 -0
  85. package/dist/client/pages/tasks.js +116 -0
  86. package/dist/client/pages/tasks.js.map +1 -0
  87. package/dist/client/plugin.d.ts +4 -0
  88. package/dist/client/plugin.d.ts.map +1 -0
  89. package/dist/client/plugin.js +10 -0
  90. package/dist/client/plugin.js.map +1 -0
  91. package/dist/client/routes.d.ts +4 -0
  92. package/dist/client/routes.d.ts.map +1 -0
  93. package/dist/client/routes.js +51 -0
  94. package/dist/client/routes.js.map +1 -0
  95. package/dist/database/migrations/.manifest.json +9 -0
  96. package/dist/database/migrations/202610010001_office_flows_example_create_collections.d.ts +4 -0
  97. package/dist/database/migrations/202610010001_office_flows_example_create_collections.d.ts.map +1 -0
  98. package/dist/database/migrations/202610010001_office_flows_example_create_collections.js +280 -0
  99. package/dist/database/migrations/202610010001_office_flows_example_create_collections.js.map +1 -0
  100. package/dist/database/seeds/.manifest.json +9 -0
  101. package/dist/database/seeds/202610010002_office_flows_example_seed_configuration.d.ts +10 -0
  102. package/dist/database/seeds/202610010002_office_flows_example_seed_configuration.d.ts.map +1 -0
  103. package/dist/database/seeds/202610010002_office_flows_example_seed_configuration.js +104 -0
  104. package/dist/database/seeds/202610010002_office_flows_example_seed_configuration.js.map +1 -0
  105. package/dist/server/calendar.d.ts +35 -0
  106. package/dist/server/calendar.d.ts.map +1 -0
  107. package/dist/server/calendar.js +103 -0
  108. package/dist/server/calendar.js.map +1 -0
  109. package/dist/server/index.d.ts +2 -0
  110. package/dist/server/index.d.ts.map +1 -0
  111. package/dist/server/index.js +2 -0
  112. package/dist/server/index.js.map +1 -0
  113. package/dist/server/lifecycles/data-request.d.ts +36 -0
  114. package/dist/server/lifecycles/data-request.d.ts.map +1 -0
  115. package/dist/server/lifecycles/data-request.js +182 -0
  116. package/dist/server/lifecycles/data-request.js.map +1 -0
  117. package/dist/server/lifecycles/extraction.d.ts +21 -0
  118. package/dist/server/lifecycles/extraction.d.ts.map +1 -0
  119. package/dist/server/lifecycles/extraction.js +60 -0
  120. package/dist/server/lifecycles/extraction.js.map +1 -0
  121. package/dist/server/lifecycles/incoming.d.ts +27 -0
  122. package/dist/server/lifecycles/incoming.d.ts.map +1 -0
  123. package/dist/server/lifecycles/incoming.js +177 -0
  124. package/dist/server/lifecycles/incoming.js.map +1 -0
  125. package/dist/server/lifecycles/index.d.ts +8 -0
  126. package/dist/server/lifecycles/index.d.ts.map +1 -0
  127. package/dist/server/lifecycles/index.js +20 -0
  128. package/dist/server/lifecycles/index.js.map +1 -0
  129. package/dist/server/lifecycles/tasks.d.ts +63 -0
  130. package/dist/server/lifecycles/tasks.d.ts.map +1 -0
  131. package/dist/server/lifecycles/tasks.js +259 -0
  132. package/dist/server/lifecycles/tasks.js.map +1 -0
  133. package/dist/server/plugin.d.ts +4 -0
  134. package/dist/server/plugin.d.ts.map +1 -0
  135. package/dist/server/plugin.js +16 -0
  136. package/dist/server/plugin.js.map +1 -0
  137. package/dist/server/providers/index.d.ts +4 -0
  138. package/dist/server/providers/index.d.ts.map +1 -0
  139. package/dist/server/providers/index.js +6 -0
  140. package/dist/server/providers/index.js.map +1 -0
  141. package/dist/server/providers/office-flows.d.ts +23 -0
  142. package/dist/server/providers/office-flows.d.ts.map +1 -0
  143. package/dist/server/providers/office-flows.js +90 -0
  144. package/dist/server/providers/office-flows.js.map +1 -0
  145. package/dist/server/routes/index.d.ts +8 -0
  146. package/dist/server/routes/index.d.ts.map +1 -0
  147. package/dist/server/routes/index.js +553 -0
  148. package/dist/server/routes/index.js.map +1 -0
  149. package/dist/server/routes/schemas.d.ts +157 -0
  150. package/dist/server/routes/schemas.d.ts.map +1 -0
  151. package/dist/server/routes/schemas.js +188 -0
  152. package/dist/server/routes/schemas.js.map +1 -0
  153. package/dist/server/scope.d.ts +23 -0
  154. package/dist/server/scope.d.ts.map +1 -0
  155. package/dist/server/scope.js +23 -0
  156. package/dist/server/scope.js.map +1 -0
  157. package/dist/server/services/office-flows.d.ts +151 -0
  158. package/dist/server/services/office-flows.d.ts.map +1 -0
  159. package/dist/server/services/office-flows.js +603 -0
  160. package/dist/server/services/office-flows.js.map +1 -0
  161. package/dist/server/services/store.d.ts +119 -0
  162. package/dist/server/services/store.d.ts.map +1 -0
  163. package/dist/server/services/store.js +389 -0
  164. package/dist/server/services/store.js.map +1 -0
  165. package/dist/server/tokens.d.ts +4 -0
  166. package/dist/server/tokens.d.ts.map +1 -0
  167. package/dist/server/tokens.js +3 -0
  168. package/dist/server/tokens.js.map +1 -0
  169. package/dist/shared/data-request.d.ts +73 -0
  170. package/dist/shared/data-request.d.ts.map +1 -0
  171. package/dist/shared/data-request.js +182 -0
  172. package/dist/shared/data-request.js.map +1 -0
  173. package/dist/shared/fields.d.ts +12 -0
  174. package/dist/shared/fields.d.ts.map +1 -0
  175. package/dist/shared/fields.js +48 -0
  176. package/dist/shared/fields.js.map +1 -0
  177. package/dist/shared/people.d.ts +29 -0
  178. package/dist/shared/people.d.ts.map +1 -0
  179. package/dist/shared/people.js +54 -0
  180. package/dist/shared/people.js.map +1 -0
  181. package/dist/shared/routes.d.ts +7 -0
  182. package/dist/shared/routes.d.ts.map +1 -0
  183. package/dist/shared/routes.js +7 -0
  184. package/dist/shared/routes.js.map +1 -0
  185. package/dist/shared/text.d.ts +3 -0
  186. package/dist/shared/text.d.ts.map +1 -0
  187. package/dist/shared/text.js +9 -0
  188. package/dist/shared/text.js.map +1 -0
  189. package/package.json +72 -3
package/CHANGELOG.md ADDED
@@ -0,0 +1,44 @@
1
+ # @nocobase/app-plugin-office-flows-example
2
+
3
+ ## 0.1.0-beta.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 71dbc34: Add `@nocobase/lifecycle`, record lifecycles for applications: a business record keeps its state in one of its own fields, every change is a transition declared in source, and the effects a transition owes run after it commits
8
+
9
+ `defineLifecycle()` declares states, transitions with `from`, `to`, `guard`, `validate`, `accept`, `route` and `set`, `onEnter` effects, and triggers that fire a transition on records idle in a state for longer than a parameter allows; it rejects an unknown state, a multi-target transition without a route, or a trigger waiting where its transition cannot start when the module loads. `defineEffect()` declares an effect with retries, a stable idempotency key per run, and `onSuccess`/`onFailure` transitions, fired with the effect's result or its error as input; an effect that throws an `EffectFailure` fails at once, unless it asks to be retried, and hands its `code` and `details` to `onFailure`, so the next transition branches on a code rather than on a message. `LifecycleRuntime.fire()` checks the state, writes the record, a transition log entry and the effect runs it owes in one transaction, guarded by a conditional update on the state and on a version every transition increments, so concurrent transitions of one record, self-transitions included, cannot both commit, and dispatches the effects after commit; an attempt `recover()` took back cannot record a result, an effect's outcome and the transition it continues with commit together, and a run interrupted on every attempt becomes `dead` rather than running forever; `runTriggers()` finds idle records by a query rather than a timer per record, and `recover()` hands over queued runs and takes back attempts whose process stopped. A guard refuses with a message or `{ code, message, kind }`, which `available()`, `can()` and the refusal from `fire()` report as blockers, each a `permission` refusal unless the guard marks it a `precondition` that nobody may get past until the record changes; `validate` may return a list of field problems, checked before the guards in `fire()` and in a `can()` given input, so a guard there reads only input that passed, while `available()`, `view()` and a `can()` without input ask the guards with `{}`, which a guard must answer as well; `can()` takes the input a button would send and answers its problems or blockers without throwing, for a transition whose answer depends on its input; `addGuard()` lets other code veto transitions without touching the definition; and `create()` starts a record in an initial state with a log entry and the state's `onEnter` effects, so a record's history starts at its creation, after checking the definition's `create`: `validate` over the values, then `guard` over the values, the state and the actor, refusing as a transition does, so who may create what is one rule for every route, import and script. `fire()` and `create()` take a `transaction` to join — the handle an `onTransition` receives, or the `@nocobase/db` connection of the caller's own transaction — nested in it as a savepoint, so a parent creates its children and a child moves its parent on in one commit, a refusal undoes only the nested call, and effects and listeners wait for the outermost commit and are dropped on rollback. `onTransition` writes related rows inside a transition's transaction, and `on()` tells listeners about `completed`, `entered` and `announce` events after commit. States and transitions carry titles, `final` and `meta`, `from` takes `'*'` or `{ except }`, the definition refuses unreachable states and states with no way out that are not final, and `toMermaid()` draws a description as a state diagram. Effects take a backoff factor, a cap, `shouldRetry` and `timeoutMs`; `fire()` takes a `requestId` that makes a repeated request a replay, refuses one already used for another transition on the record, or by another actor, with `REQUEST_REUSED` rather than replaying it, and refuses an empty one, or one starting with `$`, which the library keeps for its own log entries, with `INVALID_REQUEST_ID`; and `listEffectRuns()`, `retryRun()`, `cancelRun()` and `prune()` let an operator see, rerun, stop and clear effect runs; a continuation is logged under a request id naming its run and outcome, so a run continues its record at most once per outcome, and `retryRun()` refuses with `RUN_SETTLED` a run whose `onFailure` already moved the record on, or waits to, unless given `force`, the only settled runs it refuses, so a caller checks the record before retrying a dead or cancelled one. A continuation is nested in the transaction that records its effect's outcome, so a refusal, its own or one raised by a lifecycle call in its `onTransition`, rolls back the whole continuation and leaves the outcome recorded; a refusal saying its own record moved on leaves nothing to follow, while any other refusal, such as a parent a lifecycle call in its `onTransition` could not move yet, an old definition in a rolling deploy or a bug in `set`, keeps the continuation on the run as `continuation`, which `reclaim()` tries again once due, backing off from a minute to an hour, taking at most a configurable batch per sweep, trying a `CONFLICT` again soon without counting it, backing an error that is not a refusal, such as a database outage, off as a refusal without counting it toward giving up, so an outage never gives up on a continuation and a bug that throws an ordinary error is tried at most hourly and logged on its 1st, 2nd, 4th… try, and giving up after a configurable number of refused tries, ten by default or about four hours, by marking it `abandonedAt` and saying so once; a write that clears or rewrites a continuation is conditioned on the continuation it read, so two sweeps cannot both act on it; a continuation needs its lifecycle but not its effect, and a process that does not register the lifecycle puts it off rather than letting it hold the batch; `continueRun()` tries one at once, given up on or not, refusing a run whose lifecycle is unknown with `UNKNOWN_LIFECYCLE`, `listEffectRuns({ continuationPending: true })` lists the waiting ones and `listEffectRuns({ continuationAbandoned: true })` the ones given up on, which usually need a person to continue them once the parent they waited for is ready, and `prune()` keeps both, since such a run is the only record of an outcome its record never followed; neither runs the effect again, which only a `CONFLICT` or a failure that is not a refusal does; and the continuation of an `onEnter` effect follows only the stay its run was queued for, so once the lifecycle has logged another transition of the record, a self-transition included, since it enters the state again and queues its `onEnter` effects anew, it is dropped rather than moving the new round on, while an edit that only advances the version leaves it in place, and the continuation of an effect the transition itself declares is checked only against the state the record is in, as any transition is; its listeners and effects come before those of what its `onTransition` started; and an `EffectFailure` whose `details` are not JSON is recorded as an ordinary failure without them. An attempt whose outcome could not be recorded goes back in the queue after its backoff rather than staying claimed, `reclaim()` hands over again, without waiting for a restart, attempts whose lease expired and queued runs whose dispatch was lost, a retry counts its attempts on from the ones before so a late attempt cannot pass for a new one, and a trigger pages past the records its guard refuses so they cannot starve the ones behind them, passing over its own refusals quietly and logging one a lifecycle call inside the transition raised on the 1st, 2nd, 4th… sweep it recurs on for that record. `@nocobase/lifecycle/jobs` provides `createLifecycleJobs()`, the dispatcher that runs effects as `@nocobase/jobs` jobs, waits out backoffs, and sweeps triggers and expired attempts on a schedule. The library ships no HTTP routes, which belong to the plugin under its namespace and declared for the application's API document: `lifecycleErrorFields()` turns a refusal into the fields of the standard error body for an `ApiError`, with the blockers and problems in `metadata`, answering a guard refusal whose blockers are all preconditions with `FAILED_PRECONDITION` and any other with `PERMISSION_DENIED`, and, given `continuation: true`, answering a refusal `continueRun()` threw as a `FAILED_PRECONDITION` with its own code as the reason, a `RECORD_NOT_FOUND` or `UNKNOWN_LIFECYCLE` raised inside the continuation included, while a route answers a record or a run its URL names that does not exist with `404` before calling it, and `lifecycleDescriptionView()` builds what a page draws a lifecycle from. `@nocobase/lifecycle/react` provides `createLifecycleHook()`, configured once with a plugin's transport and base path so a page calls a single hook, built on `useLifecycle()` over any transport with `request()`, such as an application's API client; it calls the record routes the guide lists, reads `{ data }`, and rejects a refusal with the standard body's `reason`, blockers and problems. `createRepositoryLifecycleStore()` persists through `@nocobase/db` Repositories, and hands registered service factories the transaction's connection so a guard can read other collections inside the transition, since on SQLite a read elsewhere would wait for the only connection. The plugin that owns the lifecycles declares the log tables in its own migration: the transition log keeps the caller's nullable `requestId` and a not-null `requestKey`, the `requestId` or `$v:<version>` without one, under a unique index on `(lifecycle, recordId, requestKey)`, a plain index that behaves the same on every dialect, Oracle, Dameng and MSSQL included, and the effect runs keep a nullable `continuation`, a nullable `continuationDueAt` the sweep finds the due ones by, and a nullable `continuationAbandonedAt` an operations page finds the ones given up on by. A plugin declares `@nocobase/lifecycle` as a peer and the application provides it, because plugins share one runtime and recognise its errors by identity. `@nocobase/lifecycle/testing` runs a lifecycle on a memory store with a fake clock, in-process effects and simulated failures, so waits, retries and continuations are unit tests: its `InProcessDispatcher` holds a retry until the fake clock passes its backoff, and `runDue()` runs it, unless `retries: 'immediate'` asks for every retry at once, and the memory store's rollback undoes only the failed transaction's own writes, so a run a worker claimed meanwhile stays claimed.
10
+
11
+ Add `@nocobase/app-plugin-lifecycle-example`, which runs two lifecycles on the application's database and jobs service behind pages shaped like the products they model: a help desk where customers file tickets, agents take them from a queue and reply, a ticket left waiting closes itself and a customer can reopen it, with the conversation read from the transition log and each email's delivery shown under its reply; and expense reports with itemized lines, routed by amount to automatic approval or to the manager and finance, which approvers approve, send back or reject with a reason, an idle manager is passed over for theirs, and payment runs as an effect that marks the report paid with its reference. One person can act as every role, and each record shows its transitions and effect runs, with buttons to retry, cancel or continue a run — continue rather than retry when a run's continuation waits, which the run also says it is waiting on, or that the sweep gave up on it — and a continuation refused again is answered `400 FAILED_PRECONDITION` with the refusal's code as the reason. Its routes live under `/api/lifecycleExample`, page their lists, change only the fields a `PATCH` sends and move the report's version on with every edit, so a submit decided on the report before an edit landed is refused with `409` rather than routed on the old amount, answer `{ data }`, refuse in the standard error body, a refusal the record's state causes with `400 FAILED_PRECONDITION` and one the person causes with `403`, and are declared in the API document. The examples template registers the plugin's server and client.
12
+
13
+ Add `@nocobase/app-plugin-office-flows-example`, two office processes built from six lifecycles: a data usage request whose form asks follow-up questions by answer, passes three managers and reaches an acceptance that cannot return it once an extraction task exists nor finish while one is open, with extraction tasks created for each period and moved off weekends and the 2026 public holidays; and an incoming document approved by the office and distributed to departments, whose clerks countersign and may hand it to execution teams, executors or assisting departments, with each person reminded once per document and level and every distribution traced on the document. Its routes live under `/api/officeFlowsExample`, page their lists, take only the fields a state lets the persona edit and change only those a `PATCH` sends, answer `{ data }`, refuse in the standard error body, a refusal the record's state causes with `400 FAILED_PRECONDITION`, one the person causes with `403`, and a missing or unknown field the request names with a field violation, and are declared in the API document. The examples template registers the plugin's server and client.
14
+
15
+ ### Patch Changes
16
+
17
+ - 71dbc34: Persist whether each effect run belongs to the entered state in the required boolean `stayBound` field. Preserve transition-owned continuations when a hook immediately moves the record onward, even when the same effect also appears in `onEnter`, and keep a run's binding stable across definition changes. Update both examples' unreleased migrations and the lifecycle example API schema.
18
+ - 71dbc34: Use the shared cn package for client class names so example plugins install and pack against the current workspace catalog.
19
+ - 71dbc34: Let a second layer of state run while a record waits in a state, such as the tasks of an approval stage or a conversation with an assistant. `runtime.transaction(work)` runs one transaction across every registered lifecycle: `tx.fire()` and `tx.create()` check what `fire()` and `create()` check, `tx.read()` reads through the transaction store, `tx.handle` writes rows of the caller's own, and `tx.afterCommit()` schedules a best-effort callback; events, effects and callbacks follow the commit in the order they were registered, a callback registered before a `tx.fire()` running before that transition's events, and none of them happen on a rollback, and each lifecycle call uses a savepoint, so a caught refusal undoes only that call. `onEnterState` and `onLeaveState` declare hooks that run in the transaction of every transition entering or leaving a state, `runtime.create()` included, a self-transition running both; they and `onTransition` receive the transaction as `tx`. A hook or `onTransition` that fires its own record onward through `tx`, or through a lifecycle call given its transaction handle, directly or through a call it made in turn, ends the transition that ran it: the hooks still to come do not run, the entered state's `onEnter` effects are not queued while the transition's own effects are, nothing announces the state it entered, and `fire()` or `create()` returns the record as the hook's transition left it. Only a transition of the same lifecycle on the same record counts, so a hook that advances the version itself, as a fence or an edit does, or fires another lifecycle sharing the record's version field, lets the transition carry on. A state definition may carry its own `onEnterState` and `onLeaveState`, which run before the lifecycle's for that state, so a module can provide a whole state for a business to list. A transition declared `manual: false` is fired only by server code: `fire()` refuses human actions marked with `manual: true` with `NOT_MANUAL`, `available()` leaves it out, `can()` refuses it with a `manual` blocker, `announce` skips it and `toMermaid()` marks it. The memory store keeps field-level rollback and explicit `within` transaction nesting, and adds `records()` to list a collection's rows.
20
+
21
+ Mark human actions in the lifecycle and office-flow example routes so system-only transitions cannot be fired through those endpoints.
22
+
23
+ - 71dbc34: Retry confirmed deadlocks during standalone serial allocation with a bounded backoff, while propagating errors from caller-owned transactions and uncertain commit outcomes.
24
+ - 71dbc34: Query personal tasks through transactional assignee memberships so incoming document workflows work on database drivers without JSON filtering.
25
+ - Updated dependencies [bb8484b]
26
+ - Updated dependencies [b9f1157]
27
+ - Updated dependencies [71dbc34]
28
+ - Updated dependencies [71dbc34]
29
+ - Updated dependencies [71dbc34]
30
+ - Updated dependencies [71dbc34]
31
+ - @nocobase/app-client@2.0.0-beta.2
32
+ - @nocobase/app-plugin-authentication@2.0.0-beta.2
33
+ - @nocobase/lifecycle@0.1.0-beta.0
34
+ - @nocobase/app-server@2.0.0-beta.1
35
+ - @nocobase/db@1.0.0-beta.18
36
+ - @nocobase/i18n@1.0.0-beta.5
37
+ - @nocobase/jobs@0.1.0-beta.2
38
+ - @nocobase/service-provider@0.0.2-beta.1
39
+
40
+ ## 0.0.1
41
+
42
+ ### Patch Changes
43
+
44
+ - Add an example of two office processes on record lifecycles: a data usage request with scheduled extraction tasks, and incoming document distribution with three levels of sub-tasks.
package/README.md CHANGED
@@ -1,3 +1,56 @@
1
- # Temporary Holding Version
1
+ # @nocobase/app-plugin-office-flows-example
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Two office processes built on `@nocobase/lifecycle`, each document a record with its own lifecycle and each sub-task a record that points at its parent. There is no workflow engine and no process instance: where a document stands is its `status`, and every change is a transition declared in `server/lifecycles/`.
4
+
5
+ | Page | What it shows |
6
+ | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
7
+ | 数据使用申请 | A form whose questions depend on earlier answers; three managers; acceptance that cannot return the request once an extraction task exists, nor finish while one is open; extraction tasks created for each period and moved off weekends and holidays |
8
+ | 收文 | Two office approvals, then distribution: department rows bring in their people from configuration, management groups come from configuration or by hand, and re-approval followed by a second distribution reminds nobody twice |
9
+ | 我的待办 | Clerk tasks with a countersign, execution-team and executor tasks, assisting departments created beside the clerk task, the processing lists of every level, and each person's reminders |
10
+ | 配置 | The departments, management groups and the 2026 holiday calendar the processes read |
11
+
12
+ The process vocabulary — field names, options, states and steps — is Chinese, as the process is; the page chrome is translated through `client/locales/`. Each page lets you act as any of the example's people (`shared/people.ts`) so one person can play every role; a real application takes the actor from the signed-in user and authorizes each action. Attachments keep their file names only.
13
+
14
+ ## Where each rule lives
15
+
16
+ | Rule | Where |
17
+ | --------------------------------------------------------- | ------------------------------------------------------------------------------------------ |
18
+ | Which form fields appear, and their validation | `shared/data-request.ts`, used by the page and by the `submit` transition |
19
+ | Who may approve, return, accept or exit | The `guard` of each transition |
20
+ | No return once a task exists; no finish while one is open | Guards reading extraction tasks through the transition's own transaction |
21
+ | Extraction dates, weekends and holidays | `server/calendar.ts`, and the sweep in `OfficeFlowsService.runSchedule()` |
22
+ | Creating sub-tasks from department rows | `OfficeStore.dispatch()`, run as an effect of a self-transition, one row claimed at a time |
23
+ | One reminder per person, document and level | `OfficeStore.notify()`, a ledger with a unique key |
24
+ | Distribution traces on the root document | The clerk-task effects; team and executor feedback is not traced on the root |
25
+
26
+ ## Patterns worth copying
27
+
28
+ | Problem | Pattern | Where |
29
+ | ------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- |
30
+ | A parent waits for its children | Children are records with their own lifecycle; the parent's guard counts them through the transition's transaction and refuses with `kind: 'precondition'`, answered `400 FAILED_PRECONDITION` | `complete` in `server/lifecycles/data-request.ts` |
31
+ | Creating children cannot race the parent's decision | The child's insert runs in a transaction that bumps the parent's `lifecycleVersion` while it is still in the right state | `OfficeStore.createExtraction()` |
32
+ | Concurrent edits keep each other's fields, and a decision made before them is refused | An edit writes only the fields it sends, on the `lifecycleVersion` it read, and moves it on; one that loses reads again and reapplies its patch, so edits of different fields both stay while the later of two edits of one field wins, and a transition that read the record before the edit meets `CONFLICT` | `OfficeFlowsService.edit()` |
33
+ | Dispatching several times from one state | A self-transition with an effect; the effect claims each row and writes children under unique keys, so a retry repeats nothing | `dispatchClerks` in `server/lifecycles/incoming.ts` |
34
+ | A countersign: everyone agrees, or one objection ends it | A self-transition whose `route` stays in `signing` until every assignee has signed and leaves on the first objection; a second signature is refused to that clerk alone, as `kind: 'permission'` | `sign` in `server/lifecycles/tasks.ts` |
35
+ | One approve button across several levels | `from` lists every level, `route` picks the next by the current state, `set` changes the approver | `approve` in both root lifecycles |
36
+ | Something created on entering a state | `onEnter` | `onEnter.accepting: [createOneTimeExtraction]` |
37
+ | An external action that may run twice but must count once | The effect's `idempotencyKey` as the unique key of a ledger or trace row | `OfficeStore.trace()`, `OfficeStore.notify()` |
38
+
39
+ ## Assumptions
40
+
41
+ The source requirements leave these open; the example takes the first reading and says so here. A date falling on a weekend or holiday moves to the next workday, or the workday before when that would pass the last delivery date. "每季度第几天" counts from the first day of the quarter. "其他固定频次" creates no task by itself. All three managers may return a request, and accepting it finishes it. A department's clerks all countersign "[C]" before its task moves on, while "[Y]" or "[B]" from any of them ends it. Voided extraction tasks do not count against returning or finishing a request. Reminders are deduplicated per root document and level.
42
+
43
+ Task dispatch stores each assignee in `officeFlowsTaskAssignees` in the same transaction as the task. The personal task list filters those scalar memberships before loading tasks; it does not require a database driver's JSON filtering support. The task's `assignees` array remains the snapshot used by its guards.
44
+
45
+ Serial allocation retries a confirmed deadlock at most five times when it owns the transaction. Inside a caller transaction it propagates the failure so the caller can retry the whole operation; a connection error with an uncertain commit outcome is never retried here.
46
+
47
+ ## Testing
48
+
49
+ `tests/calendar.test.ts` and `tests/data-request-form.test.ts` cover the scheduling and the form rules as plain functions. `tests/flows.test.ts` runs both processes on the test database (SQLite by default) with the migration and seed applied, and their routes on the real service; `tests/routes.test.ts` covers the HTTP boundary.
50
+
51
+ ```bash
52
+ pnpm --filter @nocobase/app-plugin-office-flows-example lint
53
+ pnpm --filter @nocobase/app-plugin-office-flows-example typecheck
54
+ pnpm --filter @nocobase/app-plugin-office-flows-example test
55
+ pnpm --filter @nocobase/app-plugin-office-flows-example build
56
+ ```
@@ -0,0 +1,111 @@
1
+ import { type ReactElement, type ReactNode } from 'react';
2
+ import type { Available, Config, Plain, ProcessingLevel, RecordView } from '../lib/api.js';
3
+ export declare function PersonaSelect({ value, onChange, }: {
4
+ readonly value: string;
5
+ readonly onChange: (id: string) => void;
6
+ }): ReactElement;
7
+ export declare function Section({ title, actions, children, className, }: {
8
+ readonly title: ReactNode;
9
+ readonly actions?: ReactNode;
10
+ readonly children: ReactNode;
11
+ readonly className?: string;
12
+ }): ReactElement;
13
+ export declare function Field({ label, required, error, children, wide, }: {
14
+ readonly label: string;
15
+ readonly required?: boolean;
16
+ readonly error?: string | undefined;
17
+ readonly children: ReactNode;
18
+ readonly wide?: boolean;
19
+ }): ReactElement;
20
+ export declare function ReadField({ label, value, wide, }: {
21
+ readonly label: string;
22
+ readonly value: ReactNode;
23
+ readonly wide?: boolean;
24
+ }): ReactElement;
25
+ export declare function TextArea({ value, onChange, disabled, label, }: {
26
+ readonly value: string;
27
+ readonly onChange: (value: string) => void;
28
+ readonly disabled?: boolean;
29
+ readonly label: string;
30
+ }): ReactElement;
31
+ /** A single choice shown as a row of buttons, so every option is visible. */
32
+ export declare function Choice<T extends string | number | boolean>({ options, value, onChange, disabled, }: {
33
+ readonly options: readonly {
34
+ readonly value: T;
35
+ readonly label: string;
36
+ }[];
37
+ readonly value: T | null | '';
38
+ readonly onChange: (value: T) => void;
39
+ readonly disabled?: boolean;
40
+ }): ReactElement;
41
+ export declare function MultiChoice({ options, values, onChange, disabled, }: {
42
+ readonly options: readonly string[];
43
+ readonly values: readonly string[];
44
+ readonly onChange: (values: string[]) => void;
45
+ readonly disabled?: boolean;
46
+ }): ReactElement;
47
+ /**
48
+ * Attachments as file names. The example keeps the names only; a real
49
+ * application stores the files through the file plugin.
50
+ */
51
+ export declare function FilesField({ value, onChange, disabled, label, }: {
52
+ readonly value: readonly string[];
53
+ readonly onChange: (value: string[]) => void;
54
+ readonly disabled?: boolean;
55
+ readonly label: string;
56
+ }): ReactElement;
57
+ /** The lifecycle's states in order, the current one marked. */
58
+ export declare function StateBar({ lifecycle, view, }: {
59
+ readonly lifecycle: string;
60
+ readonly view: RecordView;
61
+ }): ReactElement;
62
+ /**
63
+ * The transitions the record's state allows; those the persona may not fire
64
+ * stay visible but disabled. Transitions listed in `needsReason` take the
65
+ * text in the box as their `reason`.
66
+ */
67
+ export declare function Actions({ available, busy, needsReason, hidden, onFire, }: {
68
+ readonly available: readonly Available[];
69
+ readonly busy: boolean;
70
+ readonly needsReason?: readonly string[];
71
+ readonly hidden?: readonly string[];
72
+ readonly onFire: (transition: string, input: Plain) => void;
73
+ }): ReactElement;
74
+ /** Transitions with the effects they caused, and the record's traces, newest first. */
75
+ export declare function History({ lifecycle, view, }: {
76
+ readonly lifecycle: string;
77
+ readonly view: RecordView;
78
+ }): ReactElement;
79
+ /**
80
+ * Distribution rows: a department, its people as the row's checkboxes
81
+ * chose them from the department configuration, and whether it went out.
82
+ */
83
+ export declare function RowsTable({ rows, config, editable, allowAssist, dispatchLabel, onAdd, onRemove, onDispatch, busy, }: {
84
+ readonly rows: readonly Plain[];
85
+ readonly config: Config | undefined;
86
+ readonly editable: boolean;
87
+ readonly allowAssist?: boolean;
88
+ readonly dispatchLabel: string;
89
+ readonly onAdd: (row: Plain) => void;
90
+ readonly onRemove: (rowId: string) => void;
91
+ readonly onDispatch: () => void;
92
+ readonly busy: boolean;
93
+ }): ReactElement;
94
+ /**
95
+ * 处理列表: per level, the opinion its tasks answered, each department's
96
+ * feedback, and the tasks themselves.
97
+ */
98
+ export declare function Processing({ levels, onOpen, }: {
99
+ readonly levels: readonly ProcessingLevel[];
100
+ readonly onOpen?: (kind: string, id: string) => void;
101
+ }): ReactElement;
102
+ /** A list of records to pick from: number, a summary and the current state. */
103
+ export declare function RecordList({ records, lifecycle, selected, summarize, onSelect, empty, }: {
104
+ readonly records: readonly Plain[];
105
+ readonly lifecycle: string;
106
+ readonly selected: string | undefined;
107
+ readonly summarize: (record: Plain) => string;
108
+ readonly onSelect: (id: string) => void;
109
+ readonly empty: string;
110
+ }): ReactElement;
111
+ //# sourceMappingURL=flow-ui.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-ui.d.ts","sourceRoot":"","sources":["../../../client/components/flow-ui.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,175 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ import { useState } from 'react';
3
+ import { useTranslation } from '@nocobase/i18n/client';
4
+ import { PEOPLE, personName } from '../../shared/people.js';
5
+ import { CREATE_TRANSITION, list } from '../lib/api.js';
6
+ import { NAMESPACE, names } from '../lib/format.js';
7
+ import { stateLabel, TASK_LIFECYCLE } from '../lib/labels.js';
8
+ import { cn } from '../lib/utils.js';
9
+ import { Badge } from './ui/badge.js';
10
+ import { Button } from './ui/button.js';
11
+ import { Card, CardContent, CardHeader, CardTitle } from './ui/card.js';
12
+ import { Input } from './ui/input.js';
13
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from './ui/select.js';
14
+ import { text } from '../../shared/text.js';
15
+ export function PersonaSelect({ value, onChange, }) {
16
+ const { t } = useTranslation(NAMESPACE);
17
+ const items = PEOPLE.map((person) => ({
18
+ value: person.id,
19
+ label: `${person.name} · ${person.title}`,
20
+ }));
21
+ return (_jsxs("div", { className: 'flex items-center gap-2', children: [_jsx("span", { className: 'text-sm text-muted-foreground', children: t('common.actAs') }), _jsxs(Select, { items: items, value: value, onValueChange: (next) => {
22
+ if (typeof next === 'string')
23
+ onChange(next);
24
+ }, children: [_jsx(SelectTrigger, { "aria-label": t('common.actAs'), className: 'min-w-56', children: _jsx(SelectValue, {}) }), _jsx(SelectContent, { children: items.map((item) => (_jsx(SelectItem, { value: item.value, children: item.label }, item.value))) })] })] }));
25
+ }
26
+ export function Section({ title, actions, children, className, }) {
27
+ return (_jsxs(Card, { className: cn('min-w-0', className), children: [_jsx(CardHeader, { children: _jsxs("div", { className: 'flex flex-wrap items-center justify-between gap-2', children: [_jsx(CardTitle, { children: title }), actions] }) }), _jsx(CardContent, { className: 'space-y-4', children: children })] }));
28
+ }
29
+ export function Field({ label, required, error, children, wide, }) {
30
+ return (_jsxs("div", { role: 'group', "aria-label": label, className: cn('min-w-0 space-y-1.5', wide && 'sm:col-span-2'), children: [_jsxs("div", { className: 'text-sm font-medium', children: [label, required ? _jsx("span", { className: 'ml-0.5 text-destructive', children: "*" }) : null] }), children, error ? _jsx("p", { className: 'text-xs text-destructive', children: error }) : null] }));
31
+ }
32
+ export function ReadField({ label, value, wide, }) {
33
+ return (_jsxs("div", { className: cn('min-w-0', wide && 'sm:col-span-2'), children: [_jsx("div", { className: 'text-xs text-muted-foreground', children: label }), _jsx("div", { className: 'text-sm break-words whitespace-pre-wrap', children: value || '—' })] }));
34
+ }
35
+ export function TextArea({ value, onChange, disabled, label, }) {
36
+ return (_jsx("textarea", { "aria-label": label, className: 'min-h-20 w-full rounded-lg border border-input bg-transparent px-2.5 py-2 text-sm outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:opacity-60', maxLength: 4000, value: value, disabled: disabled, onChange: (event) => onChange(event.target.value) }));
37
+ }
38
+ /** A single choice shown as a row of buttons, so every option is visible. */
39
+ export function Choice({ options, value, onChange, disabled, }) {
40
+ return (_jsx("div", { className: 'flex flex-wrap gap-1.5', role: 'radiogroup', children: options.map((option) => (_jsx(Button, { type: 'button', size: 'sm', role: 'radio', "aria-checked": value === option.value, variant: value === option.value ? 'default' : 'outline', disabled: disabled, onClick: () => onChange(option.value), children: option.label }, text(option.value)))) }));
41
+ }
42
+ export function MultiChoice({ options, values, onChange, disabled, }) {
43
+ return (_jsx("div", { className: 'flex flex-wrap gap-1.5', children: options.map((option) => {
44
+ const on = values.includes(option);
45
+ return (_jsx(Button, { type: 'button', size: 'sm', "aria-pressed": on, variant: on ? 'default' : 'outline', disabled: disabled, onClick: () => onChange(on
46
+ ? values.filter((item) => item !== option)
47
+ : [...values, option]), children: option }, option));
48
+ }) }));
49
+ }
50
+ /**
51
+ * Attachments as file names. The example keeps the names only; a real
52
+ * application stores the files through the file plugin.
53
+ */
54
+ export function FilesField({ value, onChange, disabled, label, }) {
55
+ const { t } = useTranslation(NAMESPACE);
56
+ return (_jsxs("div", { className: 'space-y-1.5', children: [_jsxs("div", { className: 'flex flex-wrap gap-1.5', children: [value.map((name) => (_jsxs(Badge, { variant: 'secondary', children: [name, disabled ? null : (_jsx("button", { type: 'button', className: 'ml-1 text-muted-foreground hover:text-foreground', "aria-label": t('common.remove', { name }), onClick: () => onChange(value.filter((item) => item !== name)), children: "\u00D7" }))] }, name))), !value.length && disabled ? (_jsx("span", { className: 'text-sm text-muted-foreground', children: "\u2014" })) : null] }), disabled ? null : (_jsx("input", { type: 'file', multiple: true, "aria-label": label, className: 'text-sm file:mr-2 file:rounded-md file:border file:border-input file:bg-transparent file:px-2 file:py-1 file:text-sm', onChange: (event) => {
57
+ const picked = [...(event.target.files ?? [])].map((file) => file.name);
58
+ onChange([...new Set([...value, ...picked])]);
59
+ event.target.value = '';
60
+ } }))] }));
61
+ }
62
+ /** The lifecycle's states in order, the current one marked. */
63
+ export function StateBar({ lifecycle, view, }) {
64
+ return (_jsx("ol", { className: 'flex flex-wrap gap-1.5', children: view.description.states.map((state) => (_jsx("li", { "aria-current": state === view.record.status ? 'step' : undefined, className: cn('rounded-full border px-2.5 py-0.5 text-xs', state === view.record.status
65
+ ? 'border-primary bg-primary text-primary-foreground'
66
+ : 'text-muted-foreground'), children: stateLabel(lifecycle, state) }, state))) }));
67
+ }
68
+ /**
69
+ * The transitions the record's state allows; those the persona may not fire
70
+ * stay visible but disabled. Transitions listed in `needsReason` take the
71
+ * text in the box as their `reason`.
72
+ */
73
+ export function Actions({ available, busy, needsReason = [], hidden = [], onFire, }) {
74
+ const { t } = useTranslation(NAMESPACE);
75
+ const [reason, setReason] = useState('');
76
+ const shown = available.filter((item) => !hidden.includes(item.name));
77
+ const wantsReason = shown.some((item) => item.allowed && needsReason.includes(item.name));
78
+ if (!shown.length)
79
+ return _jsx("p", { className: 'text-sm text-muted-foreground', children: t('common.final') });
80
+ return (_jsxs("div", { className: 'space-y-2', children: [wantsReason ? (_jsx(Input, { "aria-label": t('common.reason'), placeholder: t('common.reason'), value: reason, onChange: (event) => setReason(event.target.value) })) : null, _jsx("div", { className: 'flex flex-wrap gap-2', children: shown.map((item) => (_jsx(Button, { variant: 'secondary', disabled: busy || !item.allowed, title: item.allowed ? undefined : t('common.notAllowed'), onClick: () => {
81
+ onFire(item.name, needsReason.includes(item.name) ? { reason } : {});
82
+ setReason('');
83
+ }, children: item.title }, item.name))) })] }));
84
+ }
85
+ function time(value) {
86
+ const date = new Date(text(value));
87
+ return Number.isNaN(date.getTime())
88
+ ? text(value)
89
+ : date.toLocaleString('zh-CN', { hour12: false });
90
+ }
91
+ /** Transitions with the effects they caused, and the record's traces, newest first. */
92
+ export function History({ lifecycle, view, }) {
93
+ const { t } = useTranslation(NAMESPACE);
94
+ const titles = new Map(view.description.transitions.map((item) => [item.name, item.title]));
95
+ const entries = [
96
+ ...view.history.transitions.map((entry) => ({
97
+ key: `t${entry.id}`,
98
+ at: entry.at,
99
+ node: (_jsxs("div", { className: 'space-y-1', children: [_jsxs("p", { className: 'text-sm', children: [_jsx("span", { className: 'font-medium', children: entry.transition === CREATE_TRANSITION
100
+ ? t('common.created')
101
+ : (titles.get(entry.transition) ?? entry.transition) }), ' ', _jsxs("span", { className: 'text-muted-foreground', children: [entry.from === null
102
+ ? ''
103
+ : `${stateLabel(lifecycle, entry.from)} → `, stateLabel(lifecycle, entry.to)] })] }), _jsxs("p", { className: 'text-xs text-muted-foreground', children: [personName(entry.actorId), " \u00B7 ", time(entry.at), Object.keys(entry.input).filter((key) => key !== 'rowIds').length
104
+ ? ` · ${JSON.stringify(Object.fromEntries(Object.entries(entry.input).filter(([key]) => key !== 'rowIds')))}`
105
+ : ''] }), view.history.effectRuns
106
+ .filter((run) => run.transitionId === entry.id)
107
+ .map((run) => (_jsxs("p", { className: 'text-xs', children: [_jsx("code", { className: 'font-mono', children: run.effect }), ' ', _jsx(Badge, { variant: run.status === 'failed' ? 'destructive' : 'outline', children: t(`runs.${run.status}`) }), ' ', run.error ? (_jsx("span", { className: 'text-destructive', children: run.error })) : null] }, run.id)))] })),
108
+ })),
109
+ ...view.traces.map((trace) => ({
110
+ key: `r${trace.id}`,
111
+ at: trace.at,
112
+ node: (_jsxs("div", { className: 'space-y-1 rounded-md bg-muted/60 px-3 py-2', children: [_jsx("p", { className: 'text-sm font-medium', children: trace.action }), _jsxs("p", { className: 'text-xs text-muted-foreground', children: [personName(trace.actorId), " \u00B7 ", time(trace.at)] }), _jsx(TraceDetail, { detail: trace.detail })] })),
113
+ })),
114
+ ].sort((left, right) => text(right.at).localeCompare(text(left.at)));
115
+ if (!entries.length)
116
+ return (_jsx("p", { className: 'text-sm text-muted-foreground', children: t('common.noHistory') }));
117
+ return (_jsx("ol", { className: 'space-y-3 border-l pl-4', children: entries.map((entry) => (_jsx("li", { children: entry.node }, entry.key))) }));
118
+ }
119
+ function TraceDetail({ detail }) {
120
+ const { t } = useTranslation(NAMESPACE);
121
+ const departments = list(detail.departments);
122
+ const groups = list(detail.groups);
123
+ return (_jsxs("div", { className: 'space-y-0.5 text-xs', children: [departments.length ? (_jsxs("p", { children: [t('trace.departments'), "\uFF1A", departments.join('、'), list(detail.numbers).length
124
+ ? `(${list(detail.numbers).join('、')})`
125
+ : ''] })) : null, groups.length ? (_jsxs("p", { children: [t('trace.groups'), "\uFF1A", groups.join('、')] })) : null, _jsxs("p", { children: [t('trace.notified'), "\uFF1A", names(detail.notified)] }), list(detail.skipped).length ? (_jsxs("p", { className: 'text-muted-foreground', children: [t('trace.skipped'), "\uFF1A", names(detail.skipped)] })) : null] }));
126
+ }
127
+ /**
128
+ * Distribution rows: a department, its people as the row's checkboxes
129
+ * chose them from the department configuration, and whether it went out.
130
+ */
131
+ export function RowsTable({ rows, config, editable, allowAssist, dispatchLabel, onAdd, onRemove, onDispatch, busy, }) {
132
+ const { t } = useTranslation(NAMESPACE);
133
+ const [department, setDepartment] = useState('');
134
+ const [heads, setHeads] = useState(false);
135
+ const [leaders, setLeaders] = useState(false);
136
+ const [assist, setAssist] = useState(false);
137
+ const pending = rows.filter((row) => !row.dispatched).length;
138
+ const departments = (config?.departments ?? []).map((item) => ({
139
+ value: item.name,
140
+ label: item.name,
141
+ }));
142
+ return (_jsxs("div", { className: 'space-y-3', children: [_jsx("div", { className: 'overflow-x-auto rounded-lg border', children: _jsxs("table", { className: 'w-full text-sm', children: [_jsx("thead", { className: 'bg-muted/50 text-left text-xs text-muted-foreground', children: _jsxs("tr", { children: [_jsx("th", { className: 'px-3 py-2 font-medium', children: t('rows.department') }), _jsx("th", { className: 'px-3 py-2 font-medium', children: t('rows.clerks') }), _jsx("th", { className: 'px-3 py-2 font-medium', children: t('rows.heads') }), _jsx("th", { className: 'px-3 py-2 font-medium', children: t('rows.leaders') }), _jsx("th", { className: 'px-3 py-2 font-medium', children: t('rows.dispatched') }), _jsx("th", { className: 'px-3 py-2' })] }) }), _jsx("tbody", { children: rows.length ? (rows.map((row) => (_jsxs("tr", { className: 'border-t', children: [_jsxs("td", { className: 'px-3 py-2', children: [text(row.departmentName), row.origin ? (_jsx("span", { className: 'ml-1 text-xs text-muted-foreground', children: t('rows.assist') })) : null] }), _jsx("td", { className: 'px-3 py-2', children: names(row.assignees) }), _jsx("td", { className: 'px-3 py-2', children: names(row.ccHeads) }), _jsx("td", { className: 'px-3 py-2', children: names(row.ccLeaders) }), _jsx("td", { className: 'px-3 py-2', children: _jsx(Badge, { variant: row.dispatched ? 'default' : 'outline', children: row.dispatched ? t('rows.yes') : t('rows.no') }) }), _jsx("td", { className: 'px-3 py-2 text-right', children: editable && !row.dispatched ? (_jsx(Button, { size: 'sm', variant: 'ghost', onClick: () => onRemove(text(row.id)), children: t('common.delete') })) : null })] }, text(row.id))))) : (_jsx("tr", { children: _jsx("td", { colSpan: 6, className: 'px-3 py-4 text-center text-muted-foreground', children: t('rows.empty') }) })) })] }) }), editable ? (_jsxs("div", { className: 'flex flex-wrap items-end gap-3 rounded-lg border border-dashed p-3', children: [_jsxs("div", { className: 'space-y-1', children: [_jsx("div", { className: 'text-xs text-muted-foreground', children: t('rows.department') }), _jsxs(Select, { items: departments, value: department, onValueChange: (next) => {
143
+ if (typeof next === 'string')
144
+ setDepartment(next);
145
+ }, children: [_jsx(SelectTrigger, { "aria-label": t('rows.department'), className: 'min-w-36', children: _jsx(SelectValue, { placeholder: t('rows.pickDepartment') }) }), _jsx(SelectContent, { children: departments.map((item) => (_jsx(SelectItem, { value: item.value, children: item.label }, item.value))) })] })] }), _jsxs("div", { className: 'flex flex-wrap gap-1.5', children: [_jsx(Button, { size: 'sm', variant: 'default', "aria-pressed": true, disabled: true, children: t('rows.clerks') }), _jsx(Button, { size: 'sm', "aria-pressed": heads, variant: heads ? 'default' : 'outline', onClick: () => setHeads(!heads), children: t('rows.heads') }), _jsx(Button, { size: 'sm', "aria-pressed": leaders, variant: leaders ? 'default' : 'outline', onClick: () => setLeaders(!leaders), children: t('rows.leaders') }), allowAssist ? (_jsx(Button, { size: 'sm', "aria-pressed": assist, variant: assist ? 'default' : 'outline', onClick: () => setAssist(!assist), children: t('rows.assistOther') })) : null] }), _jsx(Button, { size: 'sm', variant: 'secondary', disabled: !department || busy, onClick: () => {
146
+ onAdd({
147
+ departmentName: department,
148
+ includeClerks: true,
149
+ includeHeads: heads,
150
+ includeLeaders: leaders,
151
+ assistOther: assist,
152
+ });
153
+ setDepartment('');
154
+ setAssist(false);
155
+ }, children: assist ? t('rows.addAssist') : t('rows.add') }), _jsxs(Button, { size: 'sm', disabled: !pending || busy, onClick: onDispatch, children: [dispatchLabel, "\uFF08", pending, "\uFF09"] })] })) : null] }));
156
+ }
157
+ /**
158
+ * 处理列表: per level, the opinion its tasks answered, each department's
159
+ * feedback, and the tasks themselves.
160
+ */
161
+ export function Processing({ levels, onOpen, }) {
162
+ const { t } = useTranslation(NAMESPACE);
163
+ const [index, setIndex] = useState(0);
164
+ const level = levels[Math.min(index, levels.length - 1)];
165
+ if (!level)
166
+ return _jsx(_Fragment, {});
167
+ return (_jsxs("div", { className: 'space-y-3', children: [_jsx("div", { className: 'flex flex-wrap gap-1.5', role: 'tablist', children: levels.map((item, position) => (_jsxs(Button, { size: 'sm', role: 'tab', "aria-selected": position === index, variant: position === index ? 'default' : 'outline', onClick: () => setIndex(position), children: [item.title, "\uFF08", item.tasks.length, "\uFF09"] }, item.title))) }), _jsx(ReadField, { label: level.opinionLabel, value: level.opinion }), _jsx("div", { className: 'overflow-x-auto rounded-lg border', children: _jsxs("table", { className: 'w-full text-sm', children: [_jsx("thead", { className: 'bg-muted/50 text-left text-xs text-muted-foreground', children: _jsxs("tr", { children: [_jsx("th", { className: 'px-3 py-2 font-medium', children: t('processing.number') }), _jsx("th", { className: 'px-3 py-2 font-medium', children: t('processing.node') }), _jsx("th", { className: 'px-3 py-2 font-medium', children: t('processing.assignees') }), _jsx("th", { className: 'px-3 py-2 font-medium', children: t('rows.department') }), _jsx("th", { className: 'px-3 py-2 font-medium', children: t('processing.feedback') }), _jsx("th", { className: 'px-3 py-2 font-medium', children: t('processing.attachments') })] }) }), _jsx("tbody", { children: level.tasks.length ? (level.tasks.map((task) => (_jsxs("tr", { className: 'border-t align-top', children: [_jsx("td", { className: 'px-3 py-2 font-mono text-xs', children: onOpen ? (_jsx("button", { type: 'button', className: 'text-primary underline-offset-2 hover:underline', onClick: () => onOpen(level.kind, text(task.id)), children: text(task.number) })) : (text(task.number)) }), _jsx("td", { className: 'px-3 py-2', children: stateLabel(TASK_LIFECYCLE[level.kind], task.status) }), _jsx("td", { className: 'px-3 py-2', children: names(task.assignees) }), _jsx("td", { className: 'px-3 py-2', children: text(task.departmentName) }), _jsx("td", { className: 'px-3 py-2 whitespace-pre-wrap', children: text(task.feedback ?? '') || '—' }), _jsx("td", { className: 'px-3 py-2', children: list(task.attachments).join('、') || '—' })] }, text(task.id))))) : (_jsx("tr", { children: _jsx("td", { colSpan: 6, className: 'px-3 py-4 text-center text-muted-foreground', children: t('processing.empty') }) })) })] }) })] }));
168
+ }
169
+ /** A list of records to pick from: number, a summary and the current state. */
170
+ export function RecordList({ records, lifecycle, selected, summarize, onSelect, empty, }) {
171
+ if (!records.length)
172
+ return _jsx("p", { className: 'text-sm text-muted-foreground', children: empty });
173
+ return (_jsx("ul", { className: 'space-y-1', children: records.map((record) => (_jsx("li", { children: _jsxs("button", { type: 'button', onClick: () => onSelect(text(record.id)), className: cn('flex w-full items-center justify-between gap-3 rounded-md px-3 py-2 text-left text-sm hover:bg-muted focus-visible:outline-2 focus-visible:outline-ring', selected === text(record.id) && 'bg-muted'), children: [_jsxs("span", { className: 'min-w-0', children: [_jsx("span", { className: 'block font-mono text-xs text-muted-foreground', children: text(record.number) }), _jsx("span", { className: 'block truncate', children: summarize(record) })] }), _jsx(Badge, { variant: 'secondary', children: stateLabel(lifecycle, record.status) })] }) }, text(record.id)))) }));
174
+ }
175
+ //# sourceMappingURL=flow-ui.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow-ui.js","sourceRoot":"","sources":["../../../client/components/flow-ui.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { ComponentProps, ReactElement } from 'react';
2
+ export type PageContainerProps = ComponentProps<'section'>;
3
+ export declare function PageContainer({ className, ...props }: PageContainerProps): ReactElement;
4
+ //# sourceMappingURL=page-container.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-container.d.ts","sourceRoot":"","sources":["../../../client/components/page-container.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1D,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;AAE3D,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,kBAAkB,GAAG,YAAY,CAOnC"}
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cn } from 'cn';
3
+ export function PageContainer({ className, ...props }) {
4
+ return (_jsx("section", { className: cn('w-full space-y-6 p-6 md:p-8', className), ...props }));
5
+ }
6
+ //# sourceMappingURL=page-container.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-container.js","sourceRoot":"","sources":["../../../client/components/page-container.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AAIxB,MAAM,UAAU,aAAa,CAAC,EAC5B,SAAS,EACT,GAAG,KAAK,EACW;IACnB,OAAO,CACL,kBACE,SAAS,EAAE,EAAE,CAAC,6BAA6B,EAAE,SAAS,CAAC,KACnD,KAAK,GACT,CACH,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ReactElement, ReactNode } from 'react';
2
+ export interface PageHeaderProps {
3
+ readonly title: ReactNode;
4
+ readonly description?: ReactNode;
5
+ readonly actions?: ReactNode;
6
+ }
7
+ export declare function PageHeader({ actions, description, title, }: PageHeaderProps): ReactElement;
8
+ //# sourceMappingURL=page-header.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-header.d.ts","sourceRoot":"","sources":["../../../client/components/page-header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;CAC9B;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,WAAW,EACX,KAAK,GACN,EAAE,eAAe,GAAG,YAAY,CAkBhC"}
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ export function PageHeader({ actions, description, title, }) {
3
+ return (_jsxs("header", { className: 'flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between', children: [_jsxs("div", { className: 'min-w-0', children: [_jsx("h1", { className: 'font-heading text-3xl font-semibold tracking-[-0.035em]', children: title }), description ? (_jsx("p", { className: 'mt-2 max-w-2xl text-sm leading-6 text-muted-foreground', children: description })) : null] }), actions ? (_jsx("div", { className: 'flex shrink-0 items-center gap-2', children: actions })) : null] }));
4
+ }
5
+ //# sourceMappingURL=page-header.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"page-header.js","sourceRoot":"","sources":["../../../client/components/page-header.tsx"],"names":[],"mappings":";AAQA,MAAM,UAAU,UAAU,CAAC,EACzB,OAAO,EACP,WAAW,EACX,KAAK,GACW;IAChB,OAAO,CACL,kBAAQ,SAAS,EAAC,iEAAiE,aACjF,eAAK,SAAS,EAAC,SAAS,aACtB,aAAI,SAAS,EAAC,yDAAyD,YACpE,KAAK,GACH,EACJ,WAAW,CAAC,CAAC,CAAC,CACb,YAAG,SAAS,EAAC,wDAAwD,YAClE,WAAW,GACV,CACL,CAAC,CAAC,CAAC,IAAI,IACJ,EACL,OAAO,CAAC,CAAC,CAAC,CACT,cAAK,SAAS,EAAC,kCAAkC,YAAE,OAAO,GAAO,CAClE,CAAC,CAAC,CAAC,IAAI,IACD,CACV,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { ComponentProps, ReactElement } from 'react';
2
+ type BadgeVariantProps = {
3
+ readonly variant?: 'default' | 'secondary' | 'outline' | 'destructive';
4
+ };
5
+ declare function Badge({ className, variant, ...props }: ComponentProps<'span'> & BadgeVariantProps): ReactElement;
6
+ export { Badge };
7
+ //# sourceMappingURL=badge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../../../client/components/ui/badge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAK1D,KAAK,iBAAiB,GAAG;IACvB,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,GAAG,SAAS,GAAG,aAAa,CAAC;CACxE,CAAC;AAkBF,iBAAS,KAAK,CAAC,EACb,SAAS,EACT,OAAO,EACP,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,MAAM,CAAC,GAAG,iBAAiB,GAAG,YAAY,CAQ3D;AAED,OAAO,EAAE,KAAK,EAAE,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { cva } from 'class-variance-authority';
3
+ import { cn } from '../../lib/utils.js';
4
+ const badgeVariants = cva('inline-flex h-5 w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-4xl border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap', {
5
+ variants: {
6
+ variant: {
7
+ default: 'bg-primary text-primary-foreground',
8
+ secondary: 'bg-secondary text-secondary-foreground',
9
+ outline: 'border-border text-foreground',
10
+ destructive: 'bg-destructive/10 text-destructive dark:bg-destructive/20',
11
+ },
12
+ },
13
+ defaultVariants: { variant: 'default' },
14
+ });
15
+ function Badge({ className, variant, ...props }) {
16
+ return (_jsx("span", { "data-slot": 'badge', className: cn(badgeVariants({ variant }), className), ...props }));
17
+ }
18
+ export { Badge };
19
+ //# sourceMappingURL=badge.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"badge.js","sourceRoot":"","sources":["../../../../client/components/ui/badge.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAE/C,OAAO,EAAE,EAAE,EAAE,MAAM,oBAAoB,CAAC;AAMxC,MAAM,aAAa,GAA0C,GAAG,CAC9D,0KAA0K,EAC1K;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EAAE,oCAAoC;YAC7C,SAAS,EAAE,wCAAwC;YACnD,OAAO,EAAE,+BAA+B;YACxC,WAAW,EACT,2DAA2D;SAC9D;KACF;IACD,eAAe,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE;CACxC,CACF,CAAC;AAEF,SAAS,KAAK,CAAC,EACb,SAAS,EACT,OAAO,EACP,GAAG,KAAK,EACmC;IAC3C,OAAO,CACL,4BACY,OAAO,EACjB,SAAS,EAAE,EAAE,CAAC,aAAa,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,SAAS,CAAC,KAChD,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,KAAK,EAAE,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { ReactElement } from 'react';
2
+ import { Button as ButtonPrimitive } from '@base-ui/react/button';
3
+ export type ButtonProps = ButtonPrimitive.Props & {
4
+ readonly variant?: 'default' | 'outline' | 'secondary' | 'ghost' | 'destructive';
5
+ readonly size?: 'default' | 'sm' | 'lg';
6
+ };
7
+ export declare function Button({ className, size, variant, ...props }: ButtonProps): ReactElement;
8
+ //# sourceMappingURL=button.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../client/components/ui/button.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAmClE,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC,KAAK,GAAG;IAChD,QAAQ,CAAC,OAAO,CAAC,EACf,SAAS,GAAG,SAAS,GAAG,WAAW,GAAG,OAAO,GAAG,aAAa,CAAC;IAChE,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,CAAC;CACzC,CAAC;AAEF,wBAAgB,MAAM,CAAC,EACrB,SAAS,EACT,IAAI,EACJ,OAAO,EACP,GAAG,KAAK,EACT,EAAE,WAAW,GAAG,YAAY,CAQ5B"}