@dxos/plugin-pipeline 0.8.4-staging.60fe92afc8 → 0.9.1-main.c7dcc2e112

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 (78) hide show
  1. package/dist/lib/neutral/{PipelineArticle-6JIVXMYF.mjs → PipelineArticle-DG4TCEML.mjs} +2 -2
  2. package/dist/lib/neutral/{PipelineArticle-6JIVXMYF.mjs.map → PipelineArticle-DG4TCEML.mjs.map} +2 -2
  3. package/dist/lib/neutral/PipelinePlugin.mjs +5 -3
  4. package/dist/lib/neutral/PipelinePlugin.mjs.map +4 -4
  5. package/dist/lib/neutral/{PipelineProperties-JZQYG2CN.mjs → PipelineProperties-JW7AWWU4.mjs} +28 -55
  6. package/dist/lib/neutral/PipelineProperties-JW7AWWU4.mjs.map +7 -0
  7. package/dist/lib/neutral/app-graph-builder-DULKWFOE.mjs +81 -0
  8. package/dist/lib/neutral/app-graph-builder-DULKWFOE.mjs.map +7 -0
  9. package/dist/lib/neutral/capabilities/index.mjs +5 -3
  10. package/dist/lib/neutral/capabilities/index.mjs.map +3 -3
  11. package/dist/lib/neutral/chunk-OF66INHQ.mjs +9 -0
  12. package/dist/lib/neutral/chunk-OF66INHQ.mjs.map +7 -0
  13. package/dist/lib/neutral/chunk-RHSONY5F.mjs +44 -0
  14. package/dist/lib/neutral/chunk-RHSONY5F.mjs.map +7 -0
  15. package/dist/lib/neutral/components/index.mjs +11 -9
  16. package/dist/lib/neutral/components/index.mjs.map +3 -3
  17. package/dist/lib/neutral/containers/index.mjs +2 -2
  18. package/dist/lib/neutral/{create-object-6Z4MMGX4.mjs → create-object-VIRI2DY5.mjs} +6 -2
  19. package/dist/lib/neutral/create-object-VIRI2DY5.mjs.map +7 -0
  20. package/dist/lib/neutral/index.mjs +1 -1
  21. package/dist/lib/neutral/meta.json +1 -1
  22. package/dist/lib/neutral/meta.mjs +1 -1
  23. package/dist/lib/neutral/navigation-resolver-PB6XKEAG.mjs +12 -0
  24. package/dist/lib/neutral/navigation-resolver-PB6XKEAG.mjs.map +7 -0
  25. package/dist/lib/neutral/plugin.mjs +1 -1
  26. package/dist/lib/neutral/{react-surface-QG7QSZSS.mjs → react-surface-U7OOZHUQ.mjs} +2 -2
  27. package/dist/lib/neutral/{react-surface-QG7QSZSS.mjs.map → react-surface-U7OOZHUQ.mjs.map} +3 -3
  28. package/dist/lib/neutral/translations.mjs +4 -5
  29. package/dist/lib/neutral/translations.mjs.map +3 -3
  30. package/dist/types/dx.config.d.ts +28 -0
  31. package/dist/types/dx.config.d.ts.map +1 -0
  32. package/dist/types/src/PipelinePlugin.d.ts.map +1 -1
  33. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
  34. package/dist/types/src/capabilities/index.d.ts +4 -8
  35. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  36. package/dist/types/src/capabilities/navigation-resolver.d.ts +6 -0
  37. package/dist/types/src/capabilities/navigation-resolver.d.ts.map +1 -0
  38. package/dist/types/src/capabilities/react-surface.d.ts +2 -2
  39. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  40. package/dist/types/src/components/PipelineComponent/PipelineComponent.stories.d.ts +6 -8
  41. package/dist/types/src/components/PipelineComponent/PipelineComponent.stories.d.ts.map +1 -1
  42. package/dist/types/src/containers/PipelineArticle/PipelineArticle.stories.d.ts +6 -8
  43. package/dist/types/src/containers/PipelineArticle/PipelineArticle.stories.d.ts.map +1 -1
  44. package/dist/types/src/containers/PipelineProperties/PipelineProperties.d.ts +3 -5
  45. package/dist/types/src/containers/PipelineProperties/PipelineProperties.d.ts.map +1 -1
  46. package/dist/types/src/containers/PipelineProperties/PipelineProperties.stories.d.ts +147 -0
  47. package/dist/types/src/containers/PipelineProperties/PipelineProperties.stories.d.ts.map +1 -0
  48. package/dist/types/src/meta.d.ts +28 -2
  49. package/dist/types/src/meta.d.ts.map +1 -1
  50. package/dist/types/src/paths.d.ts +3 -0
  51. package/dist/types/src/paths.d.ts.map +1 -0
  52. package/dist/types/src/translations.d.ts +6 -8
  53. package/dist/types/src/translations.d.ts.map +1 -1
  54. package/dist/types/tsconfig.tsbuildinfo +1 -1
  55. package/dx.config.ts +32 -0
  56. package/package.json +39 -37
  57. package/src/PipelinePlugin.test.ts +1 -1
  58. package/src/PipelinePlugin.tsx +3 -2
  59. package/src/capabilities/app-graph-builder.ts +38 -4
  60. package/src/capabilities/create-object.ts +3 -1
  61. package/src/capabilities/index.ts +1 -0
  62. package/src/capabilities/navigation-resolver.ts +18 -0
  63. package/src/capabilities/react-surface.tsx +1 -1
  64. package/src/components/PipelineComponent/PipelineColumn.tsx +10 -13
  65. package/src/components/PipelineComponent/PipelineComponent.tsx +1 -1
  66. package/src/containers/PipelineArticle/PipelineArticle.stories.tsx +4 -4
  67. package/src/containers/PipelineArticle/PipelineArticle.tsx +1 -1
  68. package/src/containers/PipelineProperties/PipelineProperties.stories.tsx +150 -0
  69. package/src/containers/PipelineProperties/PipelineProperties.tsx +65 -89
  70. package/src/meta.ts +2 -25
  71. package/src/paths.ts +12 -0
  72. package/src/translations.ts +8 -8
  73. package/dist/lib/neutral/PipelineProperties-JZQYG2CN.mjs.map +0 -7
  74. package/dist/lib/neutral/app-graph-builder-ZLGRWRJU.mjs +0 -44
  75. package/dist/lib/neutral/app-graph-builder-ZLGRWRJU.mjs.map +0 -7
  76. package/dist/lib/neutral/chunk-CYXDAAKN.mjs +0 -35
  77. package/dist/lib/neutral/chunk-CYXDAAKN.mjs.map +0 -7
  78. package/dist/lib/neutral/create-object-6Z4MMGX4.mjs.map +0 -7
package/dx.config.ts ADDED
@@ -0,0 +1,32 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { Config2 } from '@dxos/app-framework/config';
6
+ import { trim } from '@dxos/util';
7
+
8
+ export default Config2.make({
9
+ plugin: {
10
+ key: 'org.dxos.plugin.pipeline',
11
+ name: 'Pipelines',
12
+ author: 'DXOS',
13
+ description: trim`
14
+ A multi-column Kanban-style pipeline plugin for DXOS Composer.
15
+ Each Pipeline holds an ordered set of Columns; each Column is backed by a ViewModel whose query
16
+ can select any ECHO object type — messages, contacts, documents, or custom types — from the active space.
17
+
18
+ Columns are fully configurable through the Settings companion panel, where users can add, rename,
19
+ reorder, and delete columns and edit the underlying query and projection for each column.
20
+ Objects can be dragged between columns and the full pipeline state, including column order and
21
+ per-column item order, persists collaboratively via ECHO.
22
+
23
+ A built-in Research template scaffolds a four-column pipeline wired to the Mailbox, Contacts,
24
+ Organizations, and Notes objects in the space, providing an out-of-the-box CRM-style workflow.
25
+ Pipeline articles also expose Invocations and Automation companion tabs for AI-driven automation.
26
+ `,
27
+ source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-pipeline',
28
+ icon: { key: 'ph--path--regular', hue: 'purple' },
29
+ spec: 'PLUGIN.mdl',
30
+ tags: ['labs'],
31
+ },
32
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dxos/plugin-pipeline",
3
- "version": "0.8.4-staging.60fe92afc8",
3
+ "version": "0.9.1-main.c7dcc2e112",
4
4
  "description": "Pipeline plugin for Composer",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -81,6 +81,7 @@
81
81
  "types": "dist/types/src/index.d.ts",
82
82
  "files": [
83
83
  "dist",
84
+ "dx.config.ts",
84
85
  "src",
85
86
  "PLUGIN.mdl"
86
87
  ],
@@ -89,30 +90,31 @@
89
90
  "@radix-ui/react-context": "1.1.1",
90
91
  "@radix-ui/react-slot": "1.1.2",
91
92
  "effect": "3.21.3",
92
- "@dxos/app-toolkit": "0.8.4-staging.60fe92afc8",
93
- "@dxos/compute": "0.8.4-staging.60fe92afc8",
94
- "@dxos/app-framework": "0.8.4-staging.60fe92afc8",
95
- "@dxos/echo": "0.8.4-staging.60fe92afc8",
96
- "@dxos/echo-query": "0.8.4-staging.60fe92afc8",
97
- "@dxos/devtools": "0.8.4-staging.60fe92afc8",
98
- "@dxos/keys": "0.8.4-staging.60fe92afc8",
99
- "@dxos/log": "0.8.4-staging.60fe92afc8",
100
- "@dxos/plugin-graph": "0.8.4-staging.60fe92afc8",
101
- "@dxos/effect": "0.8.4-staging.60fe92afc8",
102
- "@dxos/plugin-client": "0.8.4-staging.60fe92afc8",
103
- "@dxos/plugin-inbox": "0.8.4-staging.60fe92afc8",
104
- "@dxos/plugin-space": "0.8.4-staging.60fe92afc8",
105
- "@dxos/plugin-markdown": "0.8.4-staging.60fe92afc8",
106
- "@dxos/react-client": "0.8.4-staging.60fe92afc8",
107
- "@dxos/react-ui-attention": "0.8.4-staging.60fe92afc8",
108
- "@dxos/react-ui-form": "0.8.4-staging.60fe92afc8",
109
- "@dxos/react-ui-menu": "0.8.4-staging.60fe92afc8",
110
- "@dxos/react-ui-mosaic": "0.8.4-staging.60fe92afc8",
111
- "@dxos/schema": "0.8.4-staging.60fe92afc8",
112
- "@dxos/react-ui-stack": "0.8.4-staging.60fe92afc8",
113
- "@dxos/react-ui-list": "0.8.4-staging.60fe92afc8",
114
- "@dxos/types": "0.8.4-staging.60fe92afc8",
115
- "@dxos/util": "0.8.4-staging.60fe92afc8"
93
+ "@dxos/app-toolkit": "0.9.1-main.c7dcc2e112",
94
+ "@dxos/app-framework": "0.9.1-main.c7dcc2e112",
95
+ "@dxos/compute": "0.9.1-main.c7dcc2e112",
96
+ "@dxos/client": "0.9.1-main.c7dcc2e112",
97
+ "@dxos/devtools": "0.9.1-main.c7dcc2e112",
98
+ "@dxos/effect": "0.9.1-main.c7dcc2e112",
99
+ "@dxos/echo-query": "0.9.1-main.c7dcc2e112",
100
+ "@dxos/keys": "0.9.1-main.c7dcc2e112",
101
+ "@dxos/echo": "0.9.1-main.c7dcc2e112",
102
+ "@dxos/plugin-client": "0.9.1-main.c7dcc2e112",
103
+ "@dxos/plugin-graph": "0.9.1-main.c7dcc2e112",
104
+ "@dxos/plugin-inbox": "0.9.1-main.c7dcc2e112",
105
+ "@dxos/log": "0.9.1-main.c7dcc2e112",
106
+ "@dxos/plugin-markdown": "0.9.1-main.c7dcc2e112",
107
+ "@dxos/plugin-space": "0.9.1-main.c7dcc2e112",
108
+ "@dxos/react-client": "0.9.1-main.c7dcc2e112",
109
+ "@dxos/react-ui-attention": "0.9.1-main.c7dcc2e112",
110
+ "@dxos/react-ui-menu": "0.9.1-main.c7dcc2e112",
111
+ "@dxos/react-ui-list": "0.9.1-main.c7dcc2e112",
112
+ "@dxos/react-ui-form": "0.9.1-main.c7dcc2e112",
113
+ "@dxos/react-ui-mosaic": "0.9.1-main.c7dcc2e112",
114
+ "@dxos/react-ui-stack": "0.9.1-main.c7dcc2e112",
115
+ "@dxos/types": "0.9.1-main.c7dcc2e112",
116
+ "@dxos/util": "0.9.1-main.c7dcc2e112",
117
+ "@dxos/schema": "0.9.1-main.c7dcc2e112"
116
118
  },
117
119
  "devDependencies": {
118
120
  "@effect-atom/atom-react": "^0.5.0",
@@ -121,24 +123,24 @@
121
123
  "react": "~19.2.3",
122
124
  "react-dom": "~19.2.3",
123
125
  "vite": "^8.0.16",
124
- "@dxos/echo-client": "0.8.4-staging.60fe92afc8",
125
- "@dxos/plugin-attention": "0.8.4-staging.60fe92afc8",
126
- "@dxos/plugin-inbox": "0.8.4-staging.60fe92afc8",
127
- "@dxos/plugin-preview": "0.8.4-staging.60fe92afc8",
128
- "@dxos/plugin-testing": "0.8.4-staging.60fe92afc8",
129
- "@dxos/react-ui": "0.8.4-staging.60fe92afc8",
130
- "@dxos/storybook-utils": "0.8.4-staging.60fe92afc8",
131
- "@dxos/random": "0.8.4-staging.60fe92afc8",
132
- "@dxos/ui-theme": "0.8.4-staging.60fe92afc8",
133
- "@dxos/plugin-theme": "0.8.4-staging.60fe92afc8"
126
+ "@dxos/echo-client": "0.9.1-main.c7dcc2e112",
127
+ "@dxos/plugin-inbox": "0.9.1-main.c7dcc2e112",
128
+ "@dxos/plugin-preview": "0.9.1-main.c7dcc2e112",
129
+ "@dxos/plugin-attention": "0.9.1-main.c7dcc2e112",
130
+ "@dxos/plugin-testing": "0.9.1-main.c7dcc2e112",
131
+ "@dxos/react-ui": "0.9.1-main.c7dcc2e112",
132
+ "@dxos/random": "0.9.1-main.c7dcc2e112",
133
+ "@dxos/storybook-utils": "0.9.1-main.c7dcc2e112",
134
+ "@dxos/ui-theme": "0.9.1-main.c7dcc2e112",
135
+ "@dxos/plugin-theme": "0.9.1-main.c7dcc2e112"
134
136
  },
135
137
  "peerDependencies": {
136
138
  "@effect-atom/atom-react": "^0.5.0",
137
139
  "effect": "3.21.3",
138
140
  "react": "~19.2.3",
139
141
  "react-dom": "~19.2.3",
140
- "@dxos/react-ui": "0.8.4-staging.60fe92afc8",
141
- "@dxos/ui-theme": "0.8.4-staging.60fe92afc8"
142
+ "@dxos/ui-theme": "0.9.1-main.c7dcc2e112",
143
+ "@dxos/react-ui": "0.9.1-main.c7dcc2e112"
142
144
  },
143
145
  "publishConfig": {
144
146
  "access": "public"
@@ -11,7 +11,7 @@ import { PipelinePlugin } from '#plugin';
11
11
 
12
12
  import { meta } from './meta';
13
13
 
14
- const moduleId = (name: string) => `${meta.id}.module.${name}`;
14
+ const moduleId = (name: string) => `${meta.profile.key}.module.${name}`;
15
15
 
16
16
  describe('PipelinePlugin', () => {
17
17
  test('modules activate on the expected events', async ({ expect }) => {
@@ -6,7 +6,7 @@ import { Plugin } from '@dxos/app-framework';
6
6
  import { AppPlugin } from '@dxos/app-toolkit';
7
7
  import { Pipeline } from '@dxos/types';
8
8
 
9
- import { AppGraphBuilder, CreateObject, ReactSurface } from '#capabilities';
9
+ import { AppGraphBuilder, CreateObject, NavigationResolver, ReactSurface } from '#capabilities';
10
10
  import { meta } from '#meta';
11
11
  import { translations } from '#translations';
12
12
 
@@ -16,11 +16,12 @@ import pluginSpec from '../PLUGIN.mdl?raw';
16
16
  export const PipelinePlugin = Plugin.define(meta).pipe(
17
17
  AppPlugin.addAppGraphModule({ activate: AppGraphBuilder }),
18
18
  AppPlugin.addCreateObjectModule({ activate: CreateObject }),
19
+ AppPlugin.addNavigationResolverModule({ activate: NavigationResolver }),
19
20
  AppPlugin.addSchemaModule({ schema: [Pipeline.Pipeline] }),
20
21
  AppPlugin.addSurfaceModule({ activate: ReactSurface }),
21
22
  AppPlugin.addTranslationsModule({ translations }),
22
23
  AppPlugin.addPluginAssetModule({
23
- asset: { pluginId: meta.id, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },
24
+ asset: { pluginId: meta.profile.key, path: 'PLUGIN.mdl', content: pluginSpec, mimeType: 'application/x-mdl' },
24
25
  }),
25
26
  Plugin.make,
26
27
  );
@@ -3,17 +3,51 @@
3
3
  //
4
4
 
5
5
  import * as Effect from 'effect/Effect';
6
+ import * as Option from 'effect/Option';
6
7
 
7
8
  import { Capability } from '@dxos/app-framework';
8
- import { AppCapabilities, AppNode } from '@dxos/app-toolkit';
9
- import { GraphBuilder } from '@dxos/plugin-graph';
9
+ import { AppCapabilities, AppNode, TypeSection } from '@dxos/app-toolkit';
10
+ import { isSpace } from '@dxos/client/echo';
11
+ import { Operation } from '@dxos/compute';
12
+ import { Type } from '@dxos/echo';
13
+ import { GraphBuilder, Node } from '@dxos/plugin-graph';
14
+ import { SpaceOperation } from '@dxos/plugin-space';
10
15
  import { Pipeline } from '@dxos/types';
11
16
 
12
17
  import { meta } from '#meta';
13
18
 
19
+ import { getPipelinesPath } from '../paths';
20
+
14
21
  export default Capability.makeModule(
15
22
  Effect.fnUntraced(function* () {
16
23
  const extensions = yield* Effect.all([
24
+ TypeSection.createTypeSectionExtension(Pipeline.Pipeline),
25
+
26
+ GraphBuilder.createExtension({
27
+ id: 'pipelinesSectionActions',
28
+ match: (node) => {
29
+ const space = isSpace(node.properties.space) ? node.properties.space : undefined;
30
+ return node.type === Type.getTypename(Pipeline.Pipeline) && space ? Option.some(space) : Option.none();
31
+ },
32
+ actions: (space) =>
33
+ Effect.succeed([
34
+ Node.makeAction({
35
+ id: 'create-pipeline',
36
+ data: () =>
37
+ Operation.invoke(SpaceOperation.OpenCreateObject, {
38
+ target: space.db,
39
+ typename: Type.getTypename(Pipeline.Pipeline),
40
+ targetNodeId: getPipelinesPath(space.db.spaceId),
41
+ }),
42
+ properties: {
43
+ label: ['add-object.label', { ns: Type.getTypename(Pipeline.Pipeline) }],
44
+ icon: 'ph--plus--regular',
45
+ disposition: 'list-item-primary',
46
+ },
47
+ }),
48
+ ]),
49
+ }),
50
+
17
51
  GraphBuilder.createTypeExtension({
18
52
  id: 'triggers',
19
53
  type: Pipeline.Pipeline,
@@ -21,13 +55,13 @@ export default Capability.makeModule(
21
55
  Effect.succeed([
22
56
  AppNode.makeCompanion({
23
57
  id: 'invocations',
24
- label: ['pipeline-invocations.label', { ns: meta.id }],
58
+ label: ['pipeline-invocations.label', { ns: meta.profile.key }],
25
59
  icon: 'ph--clock-countdown--regular',
26
60
  data: 'invocations',
27
61
  }),
28
62
  AppNode.makeCompanion({
29
63
  id: 'automation',
30
- label: ['pipeline-automation.label', { ns: meta.id }],
64
+ label: ['pipeline-automation.label', { ns: meta.profile.key }],
31
65
  icon: 'ph--lightning--regular',
32
66
  data: 'automation',
33
67
  }),
@@ -11,6 +11,8 @@ import { SpaceOperation } from '@dxos/plugin-space';
11
11
  import { SpaceCapabilities } from '@dxos/plugin-space';
12
12
  import { Pipeline } from '@dxos/types';
13
13
 
14
+ import { getPipelinesPath } from '../paths';
15
+
14
16
  export default Capability.makeModule(
15
17
  Effect.fnUntraced(function* () {
16
18
  return Capability.contributes(SpaceCapabilities.CreateObjectEntry, {
@@ -22,7 +24,7 @@ export default Capability.makeModule(
22
24
  object,
23
25
  target: options.target,
24
26
  hidden: true,
25
- targetNodeId: options.targetNodeId,
27
+ targetNodeId: options.targetNodeId ?? getPipelinesPath(options.db.spaceId),
26
28
  });
27
29
  }),
28
30
  });
@@ -6,4 +6,5 @@ import { Capability } from '@dxos/app-framework';
6
6
 
7
7
  export const AppGraphBuilder = Capability.lazy('AppGraphBuilder', () => import('./app-graph-builder'));
8
8
  export const CreateObject = Capability.lazy('CreateObject', () => import('./create-object'));
9
+ export const NavigationResolver = Capability.lazy('NavigationResolver', () => import('./navigation-resolver'));
9
10
  export const ReactSurface = Capability.lazy('ReactSurface', () => import('./react-surface'));
@@ -0,0 +1,18 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import * as Effect from 'effect/Effect';
6
+
7
+ import { Capability } from '@dxos/app-framework';
8
+ import { AppCapabilities, TypeSection } from '@dxos/app-toolkit';
9
+ import { Pipeline } from '@dxos/types';
10
+
11
+ export default Capability.makeModule(
12
+ Effect.fnUntraced(function* () {
13
+ return Capability.contributes(
14
+ AppCapabilities.NavigationPathResolver,
15
+ TypeSection.createTypeSectionPathResolver(Pipeline.Pipeline),
16
+ );
17
+ }),
18
+ );
@@ -46,7 +46,7 @@ export default Capability.makeModule(() =>
46
46
  Surface.create({
47
47
  id: 'objectProperties',
48
48
  filter: AppSurface.object(AppSurface.ObjectProperties, Pipeline.Pipeline),
49
- component: ({ data }) => <PipelineProperties pipeline={data.subject} />,
49
+ component: ({ data }) => <PipelineProperties subject={data.subject} />,
50
50
  }),
51
51
  ]),
52
52
  ),
@@ -8,8 +8,8 @@ import React, { forwardRef, useMemo, useRef, useState } from 'react';
8
8
  import { resolveSchemaWithRegistry } from '@dxos/app-toolkit/query';
9
9
  import { Filter, Obj, Query, Type } from '@dxos/echo';
10
10
  import { useObject } from '@dxos/react-client/echo';
11
- import { Panel, Toolbar, useAsyncEffect, useTranslation } from '@dxos/react-ui';
12
- import { Card } from '@dxos/react-ui';
11
+ import { Panel, useAsyncEffect, useTranslation } from '@dxos/react-ui';
12
+ import { Card, Icon, IconButton } from '@dxos/react-ui';
13
13
  import { Menu } from '@dxos/react-ui-menu';
14
14
  import { Board, Focus, Mosaic, type MosaicTileProps } from '@dxos/react-ui-mosaic';
15
15
  import { ProjectionModel, createEchoChangeCallback } from '@dxos/schema';
@@ -29,7 +29,7 @@ export type PipelineColumnProps = Pick<MosaicTileProps<Pipeline.Column>, 'classN
29
29
 
30
30
  // TODO(wittjosiah): Support item DnD reordering (ordering needs to be stored on the view presentation collection).
31
31
  export const PipelineColumn = ({ data: column, location, classNames, debug }: PipelineColumnProps) => {
32
- const { t } = useTranslation(meta.id);
32
+ const { t } = useTranslation(meta.profile.key);
33
33
  const [dragHandle, setDragHandle] = useState<HTMLButtonElement | null>(null);
34
34
  // Subscribe to the view target for reactivity.
35
35
  const [viewSnapshot] = useObject(column.view);
@@ -88,7 +88,7 @@ export const PipelineColumn = ({ data: column, location, classNames, debug }: Pi
88
88
  <Panel.Toolbar asChild>
89
89
  <Board.Column.Header
90
90
  classNames='_opacity-10'
91
- label={column.name || t('untitled-view.title')}
91
+ label={column.name || t('untitled-column.title')}
92
92
  dragHandleRef={setDragHandle}
93
93
  />
94
94
  </Panel.Toolbar>
@@ -125,20 +125,17 @@ const ItemTile = forwardRef<HTMLDivElement, ItemTileProps>(
125
125
  <Focus.Item asChild>
126
126
  <Card.Root classNames={classNames} ref={composedRef}>
127
127
  <Card.Header>
128
- <Card.Icon icon={icon} />
128
+ <Card.Block>
129
+ <Icon icon={icon} />
130
+ </Card.Block>
129
131
  <Card.Title>{Obj.getLabel(data, { fallback: 'typename' })}</Card.Title>
130
132
  {/* TODO(wittjosiah): Reconcile with Card.Menu. */}
131
- <Card.IconBlock>
133
+ <Card.Block end>
132
134
  <Menu.Trigger asChild>
133
- <Toolbar.IconButton
134
- iconOnly
135
- variant='ghost'
136
- icon='ph--dots-three-vertical--regular'
137
- label='Actions'
138
- />
135
+ <IconButton iconOnly variant='ghost' icon='ph--dots-three-vertical--regular' label='Actions' />
139
136
  </Menu.Trigger>
140
137
  <Menu.Content />
141
- </Card.IconBlock>
138
+ </Card.Block>
142
139
  </Card.Header>
143
140
  <Card.Body>
144
141
  <Item {...itemProps} />
@@ -112,7 +112,7 @@ PipelineColumns.displayName = PIPELINE_COLUMNS_NAME;
112
112
  const PIPELINE_TOOLBAR_NAME = 'Pipeline.Toolbar';
113
113
 
114
114
  export const PipelineToolbar = composable<HTMLDivElement, ToolbarRootProps>(({ children, ...props }, forwardedRef) => {
115
- const { t } = useTranslation(meta.id);
115
+ const { t } = useTranslation(meta.profile.key);
116
116
  const { onAddColumn } = usePipeline(PIPELINE_TOOLBAR_NAME);
117
117
 
118
118
  return (
@@ -42,7 +42,9 @@ const DefaultStory = () => {
42
42
  return (
43
43
  <div className='grow grid grid-cols-[1fr_350px] overflow-hidden h-full w-full'>
44
44
  <PipelineArticle role='article' subject={pipeline} attendableId='test' />
45
- <PipelineProperties pipeline={pipeline} classNames='border-s border-separator' />
45
+ <div className='overflow-y-auto border-is border-separator'>
46
+ <PipelineProperties subject={pipeline} />
47
+ </div>
46
48
  </div>
47
49
  );
48
50
  };
@@ -201,9 +203,7 @@ const meta = {
201
203
  );
202
204
  }
203
205
  }).pipe(
204
- Effect.provide(
205
- Layer.merge(Database.layer(personalSpace.db), createFeedServiceLayer(personalSpace.queues)),
206
- ),
206
+ Effect.provide(Layer.merge(Database.layer(personalSpace.db), createFeedServiceLayer(personalSpace.db))),
207
207
  );
208
208
  }),
209
209
  }),
@@ -73,7 +73,7 @@ const PipelineItem = ({ item, projectionModel }: ItemProps) => {
73
73
 
74
74
  return (
75
75
  <Surface.Surface
76
- type={AppSurface.Card}
76
+ type={AppSurface.CardContent}
77
77
  data={{
78
78
  subject: item,
79
79
  projection: projectionModel,
@@ -0,0 +1,150 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { type Meta, type StoryObj } from '@storybook/react-vite';
6
+ import * as Effect from 'effect/Effect';
7
+ import * as Layer from 'effect/Layer';
8
+ import React from 'react';
9
+
10
+ import { withPluginManager } from '@dxos/app-framework/testing';
11
+ import { Collection, Database, Feed, Filter, JsonSchema, Obj, Query, Ref, Scope, Tag, View } from '@dxos/echo';
12
+ import { createFeedServiceLayer } from '@dxos/echo-client';
13
+ import { ClientPlugin } from '@dxos/plugin-client/plugin';
14
+ import { initializeIdentity } from '@dxos/plugin-client/testing';
15
+ import { PreviewPlugin } from '@dxos/plugin-preview/testing';
16
+ import { corePlugins } from '@dxos/plugin-testing';
17
+ import { random } from '@dxos/random';
18
+ import { useQuery, useSpaces } from '@dxos/react-client/echo';
19
+ import { ObjectProperties } from '@dxos/react-ui-form';
20
+ import { translations as formTranslations } from '@dxos/react-ui-form/translations';
21
+ import { translations as stackTranslations } from '@dxos/react-ui-stack/translations';
22
+ import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
23
+ import { ViewModel } from '@dxos/schema';
24
+ import { createObjectFactory } from '@dxos/schema/testing';
25
+ import { Message, Organization, Person, Pipeline, Task } from '@dxos/types';
26
+
27
+ import { translations } from '#translations';
28
+
29
+ import { PipelineProperties } from './PipelineProperties';
30
+
31
+ random.seed(0);
32
+
33
+ const DefaultStory = () => {
34
+ const [space] = useSpaces();
35
+ const pipelines = useQuery(space?.db, Filter.type(Pipeline.Pipeline));
36
+ const pipeline = pipelines.find((pipeline) => (pipeline.columns?.length ?? 0) > 0);
37
+ if (!pipeline) {
38
+ return <Loading data={{ pipelines: pipelines.length }} />;
39
+ }
40
+
41
+ return (
42
+ <ObjectProperties object={pipeline}>
43
+ <PipelineProperties subject={pipeline} />
44
+ </ObjectProperties>
45
+ );
46
+ };
47
+
48
+ const meta = {
49
+ title: 'plugins/plugin-pipeline/containers/PipelineProperties',
50
+ render: DefaultStory,
51
+ decorators: [
52
+ withTheme(),
53
+ withLayout({ layout: 'column' }),
54
+ withPluginManager({
55
+ plugins: [
56
+ ...corePlugins(),
57
+ ClientPlugin({
58
+ types: [
59
+ Tag.Tag,
60
+ Feed.Feed,
61
+ Pipeline.Pipeline,
62
+ View.View,
63
+ Collection.Collection,
64
+ Organization.Organization,
65
+ Task.Task,
66
+ Person.Person,
67
+ Message.Message,
68
+ ],
69
+ onClientInitialized: Effect.fnUntraced(function* ({ client }) {
70
+ const { personalSpace } = yield* initializeIdentity(client);
71
+
72
+ yield* Effect.gen(function* () {
73
+ const tag = yield* Database.add(Tag.make({ label: 'important', hue: 'green' }));
74
+ const tagUri = Obj.getURI(tag);
75
+
76
+ // Create a view for Contacts.
77
+ const personView = ViewModel.make({
78
+ query: Query.select(Filter.type(Person.Person)),
79
+ jsonSchema: JsonSchema.toJsonSchema(Person.Person),
80
+ });
81
+
82
+ // Create a view for Organizations.
83
+ const organizationView = ViewModel.make({
84
+ query: Query.select(Filter.type(Organization.Organization)).select(Filter.tag(tagUri)),
85
+ jsonSchema: JsonSchema.toJsonSchema(Organization.Organization),
86
+ });
87
+
88
+ // Create a view for Tasks.
89
+ const taskView = ViewModel.make({
90
+ query: Query.select(Filter.type(Task.Task)).select(Filter.tag(tagUri)),
91
+ jsonSchema: JsonSchema.toJsonSchema(Task.Task),
92
+ });
93
+
94
+ // Create a feed for Messages.
95
+ const messageFeed = yield* Database.add(Feed.make({ name: 'Messages' }));
96
+ const messageView = ViewModel.make({
97
+ query: Query.select(Filter.type(Message.Message)).from(Scope.feed(Obj.getURI(messageFeed))),
98
+ jsonSchema: JsonSchema.toJsonSchema(Message.Message),
99
+ });
100
+
101
+ // Create pipeline with columns.
102
+ const pipeline = Pipeline.make({
103
+ columns: [
104
+ {
105
+ name: 'Contacts',
106
+ view: Ref.make(personView),
107
+ order: [],
108
+ },
109
+ {
110
+ name: 'Organizations',
111
+ view: Ref.make(organizationView),
112
+ order: [],
113
+ },
114
+ {
115
+ name: 'Tasks',
116
+ view: Ref.make(taskView),
117
+ order: [],
118
+ },
119
+ {
120
+ name: 'Messages',
121
+ view: Ref.make(messageView),
122
+ order: [],
123
+ },
124
+ ],
125
+ });
126
+ yield* Database.add(pipeline);
127
+
128
+ // Generate sample Contacts.
129
+ const factory = createObjectFactory(personalSpace.db, random as any);
130
+ yield* Effect.promise(() => factory([{ type: Person.Person, count: 12 }]));
131
+ }).pipe(
132
+ Effect.provide(Layer.merge(Database.layer(personalSpace.db), createFeedServiceLayer(personalSpace.db))),
133
+ );
134
+ }),
135
+ }),
136
+ PreviewPlugin(),
137
+ ],
138
+ }),
139
+ ],
140
+ parameters: {
141
+ layout: 'fullscreen',
142
+ translations: [...translations, ...formTranslations, ...stackTranslations],
143
+ },
144
+ } satisfies Meta<typeof PipelineProperties>;
145
+
146
+ export default meta;
147
+
148
+ type Story = StoryObj<typeof meta>;
149
+
150
+ export const Default: Story = {};