@dxos/plugin-pipeline 0.8.4-main.3eb6e50203 → 0.8.4-main.3fbcb4aa9b

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 (162) hide show
  1. package/dist/lib/neutral/PipelineContainer-7MK2SS76.mjs +69 -0
  2. package/dist/lib/neutral/PipelineContainer-7MK2SS76.mjs.map +7 -0
  3. package/dist/lib/neutral/PipelinePlugin.mjs +26 -0
  4. package/dist/lib/neutral/PipelinePlugin.mjs.map +7 -0
  5. package/dist/lib/neutral/PipelinePlugin.node.mjs +21 -0
  6. package/dist/lib/neutral/PipelinePlugin.node.mjs.map +7 -0
  7. package/dist/lib/{browser/PipelineSettings-YSGSJHBT.mjs → neutral/PipelineProperties-RRPQ3V6I.mjs} +75 -77
  8. package/dist/lib/neutral/PipelineProperties-RRPQ3V6I.mjs.map +7 -0
  9. package/dist/lib/neutral/app-graph-builder-ZLGRWRJU.mjs +44 -0
  10. package/dist/lib/neutral/app-graph-builder-ZLGRWRJU.mjs.map +7 -0
  11. package/dist/lib/neutral/capabilities/index.mjs +11 -0
  12. package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
  13. package/dist/lib/{browser/chunk-QWNKLHBY.mjs → neutral/chunk-ULB5DKWO.mjs} +2 -9
  14. package/dist/lib/{browser/chunk-QWNKLHBY.mjs.map → neutral/chunk-ULB5DKWO.mjs.map} +3 -3
  15. package/dist/lib/neutral/components/index.mjs +206 -0
  16. package/dist/lib/neutral/components/index.mjs.map +7 -0
  17. package/dist/lib/neutral/containers/index.mjs +9 -0
  18. package/dist/lib/neutral/containers/index.mjs.map +7 -0
  19. package/dist/lib/neutral/create-object-ZJYFACOI.mjs +25 -0
  20. package/dist/lib/neutral/create-object-ZJYFACOI.mjs.map +7 -0
  21. package/dist/lib/neutral/hooks/index.mjs +70 -0
  22. package/dist/lib/neutral/hooks/index.mjs.map +7 -0
  23. package/dist/lib/neutral/index.mjs +7 -0
  24. package/dist/lib/neutral/meta.json +1 -0
  25. package/dist/lib/neutral/meta.mjs +7 -0
  26. package/dist/lib/neutral/meta.mjs.map +7 -0
  27. package/dist/lib/neutral/plugin.mjs +11 -0
  28. package/dist/lib/neutral/plugin.mjs.map +7 -0
  29. package/dist/lib/neutral/react-surface-TW6TRMO6.mjs +49 -0
  30. package/dist/lib/neutral/react-surface-TW6TRMO6.mjs.map +7 -0
  31. package/dist/lib/neutral/translations.mjs +38 -0
  32. package/dist/lib/neutral/translations.mjs.map +7 -0
  33. package/dist/lib/neutral/types/index.mjs +1 -0
  34. package/dist/lib/neutral/types/index.mjs.map +7 -0
  35. package/dist/types/src/PipelinePlugin.d.ts +1 -0
  36. package/dist/types/src/PipelinePlugin.d.ts.map +1 -1
  37. package/dist/types/src/PipelinePlugin.node.d.ts +4 -0
  38. package/dist/types/src/PipelinePlugin.node.d.ts.map +1 -0
  39. package/dist/types/src/PipelinePlugin.test.d.ts +2 -0
  40. package/dist/types/src/PipelinePlugin.test.d.ts.map +1 -0
  41. package/dist/types/src/capabilities/app-graph-builder.d.ts +6 -0
  42. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  43. package/dist/types/src/capabilities/create-object.d.ts +11 -0
  44. package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
  45. package/dist/types/src/capabilities/index.d.ts +9 -3
  46. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  47. package/dist/types/src/capabilities/react-surface.d.ts +5 -0
  48. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  49. package/dist/types/src/components/PipelineComponent/PipelineColumn.d.ts +9 -0
  50. package/dist/types/src/components/PipelineComponent/PipelineColumn.d.ts.map +1 -0
  51. package/dist/types/src/components/PipelineComponent/PipelineComponent.d.ts +53 -0
  52. package/dist/types/src/components/PipelineComponent/PipelineComponent.d.ts.map +1 -0
  53. package/dist/types/src/components/PipelineComponent/PipelineComponent.stories.d.ts +62 -0
  54. package/dist/types/src/components/PipelineComponent/PipelineComponent.stories.d.ts.map +1 -0
  55. package/dist/types/src/components/PipelineComponent/index.d.ts +3 -0
  56. package/dist/types/src/components/PipelineComponent/index.d.ts.map +1 -0
  57. package/dist/types/src/components/index.d.ts +1 -4
  58. package/dist/types/src/components/index.d.ts.map +1 -1
  59. package/dist/types/src/containers/PipelineContainer/PipelineContainer.d.ts +6 -0
  60. package/dist/types/src/containers/PipelineContainer/PipelineContainer.d.ts.map +1 -0
  61. package/dist/types/src/containers/PipelineContainer/PipelineContainer.stories.d.ts +76 -0
  62. package/dist/types/src/containers/PipelineContainer/PipelineContainer.stories.d.ts.map +1 -0
  63. package/dist/types/src/containers/PipelineContainer/index.d.ts +2 -0
  64. package/dist/types/src/containers/PipelineContainer/index.d.ts.map +1 -0
  65. package/dist/types/src/containers/PipelineProperties/PipelineProperties.d.ts +11 -0
  66. package/dist/types/src/containers/PipelineProperties/PipelineProperties.d.ts.map +1 -0
  67. package/dist/types/src/containers/PipelineProperties/index.d.ts +2 -0
  68. package/dist/types/src/containers/PipelineProperties/index.d.ts.map +1 -0
  69. package/dist/types/src/containers/index.d.ts +4 -0
  70. package/dist/types/src/containers/index.d.ts.map +1 -0
  71. package/dist/types/src/hooks/index.d.ts +2 -0
  72. package/dist/types/src/hooks/index.d.ts.map +1 -0
  73. package/dist/types/src/hooks/usePipelineBoardModel.d.ts +6 -0
  74. package/dist/types/src/hooks/usePipelineBoardModel.d.ts.map +1 -0
  75. package/dist/types/src/index.d.ts +0 -1
  76. package/dist/types/src/index.d.ts.map +1 -1
  77. package/dist/types/src/plugin.d.ts +3 -0
  78. package/dist/types/src/plugin.d.ts.map +1 -0
  79. package/dist/types/src/templates/research.d.ts.map +1 -1
  80. package/dist/types/src/translations.d.ts +44 -25
  81. package/dist/types/src/translations.d.ts.map +1 -1
  82. package/dist/types/src/types/index.d.ts +0 -2
  83. package/dist/types/src/types/index.d.ts.map +1 -1
  84. package/dist/types/tsconfig.tsbuildinfo +1 -1
  85. package/package.json +100 -53
  86. package/src/PipelinePlugin.node.ts +19 -0
  87. package/src/PipelinePlugin.test.ts +27 -0
  88. package/src/PipelinePlugin.tsx +7 -31
  89. package/src/capabilities/app-graph-builder.ts +40 -0
  90. package/src/capabilities/create-object.ts +29 -0
  91. package/src/capabilities/index.ts +5 -3
  92. package/src/capabilities/react-surface.tsx +53 -0
  93. package/src/components/PipelineComponent/PipelineColumn.tsx +164 -0
  94. package/src/components/{PipelineComponent.stories.tsx → PipelineComponent/PipelineComponent.stories.tsx} +45 -30
  95. package/src/components/PipelineComponent/PipelineComponent.tsx +140 -0
  96. package/src/components/PipelineComponent/index.ts +6 -0
  97. package/src/components/index.ts +1 -7
  98. package/src/containers/PipelineContainer/PipelineContainer.stories.tsx +230 -0
  99. package/src/containers/PipelineContainer/PipelineContainer.tsx +84 -0
  100. package/src/containers/PipelineContainer/index.ts +5 -0
  101. package/src/{components/PipelineSettings.tsx → containers/PipelineProperties/PipelineProperties.tsx} +77 -65
  102. package/src/containers/PipelineProperties/index.ts +5 -0
  103. package/src/containers/index.ts +8 -0
  104. package/src/hooks/index.ts +5 -0
  105. package/src/hooks/usePipelineBoardModel.ts +79 -0
  106. package/src/index.ts +0 -1
  107. package/src/meta.ts +1 -1
  108. package/src/plugin.ts +9 -0
  109. package/src/templates/research.ts +16 -17
  110. package/src/translations.ts +22 -21
  111. package/src/types/index.ts +0 -3
  112. package/dist/lib/browser/PipelineContainer-I3TPA7ZN.mjs +0 -217
  113. package/dist/lib/browser/PipelineContainer-I3TPA7ZN.mjs.map +0 -7
  114. package/dist/lib/browser/PipelineSettings-YSGSJHBT.mjs.map +0 -7
  115. package/dist/lib/browser/app-graph-builder-NUJB33F7.mjs +0 -65
  116. package/dist/lib/browser/app-graph-builder-NUJB33F7.mjs.map +0 -7
  117. package/dist/lib/browser/chunk-7GVESVYR.mjs +0 -42
  118. package/dist/lib/browser/chunk-7GVESVYR.mjs.map +0 -7
  119. package/dist/lib/browser/index.mjs +0 -109
  120. package/dist/lib/browser/index.mjs.map +0 -7
  121. package/dist/lib/browser/meta.json +0 -1
  122. package/dist/lib/browser/react-surface-JMMCTIL3.mjs +0 -57
  123. package/dist/lib/browser/react-surface-JMMCTIL3.mjs.map +0 -7
  124. package/dist/lib/browser/types/index.mjs +0 -10
  125. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts +0 -6
  126. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +0 -1
  127. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +0 -3
  128. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +0 -1
  129. package/dist/types/src/capabilities/operation-resolver/index.d.ts +0 -2
  130. package/dist/types/src/capabilities/operation-resolver/index.d.ts.map +0 -1
  131. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts +0 -5
  132. package/dist/types/src/capabilities/operation-resolver/operation-resolver.d.ts.map +0 -1
  133. package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
  134. package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
  135. package/dist/types/src/capabilities/react-surface/react-surface.d.ts +0 -5
  136. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
  137. package/dist/types/src/components/PipelineColumn.d.ts +0 -10
  138. package/dist/types/src/components/PipelineColumn.d.ts.map +0 -1
  139. package/dist/types/src/components/PipelineComponent.d.ts +0 -38
  140. package/dist/types/src/components/PipelineComponent.d.ts.map +0 -1
  141. package/dist/types/src/components/PipelineComponent.stories.d.ts +0 -42
  142. package/dist/types/src/components/PipelineComponent.stories.d.ts.map +0 -1
  143. package/dist/types/src/components/PipelineContainer.d.ts +0 -7
  144. package/dist/types/src/components/PipelineContainer.d.ts.map +0 -1
  145. package/dist/types/src/components/PipelineContainer.stories.d.ts +0 -56
  146. package/dist/types/src/components/PipelineContainer.stories.d.ts.map +0 -1
  147. package/dist/types/src/components/PipelineSettings.d.ts +0 -12
  148. package/dist/types/src/components/PipelineSettings.d.ts.map +0 -1
  149. package/dist/types/src/types/PipelineAction.d.ts +0 -25
  150. package/dist/types/src/types/PipelineAction.d.ts.map +0 -1
  151. package/src/capabilities/app-graph-builder/app-graph-builder.ts +0 -51
  152. package/src/capabilities/app-graph-builder/index.ts +0 -7
  153. package/src/capabilities/operation-resolver/index.ts +0 -5
  154. package/src/capabilities/operation-resolver/operation-resolver.ts +0 -29
  155. package/src/capabilities/react-surface/index.ts +0 -7
  156. package/src/capabilities/react-surface/react-surface.tsx +0 -50
  157. package/src/components/PipelineColumn.tsx +0 -145
  158. package/src/components/PipelineComponent.tsx +0 -103
  159. package/src/components/PipelineContainer.stories.tsx +0 -226
  160. package/src/components/PipelineContainer.tsx +0 -57
  161. package/src/types/PipelineAction.ts +0 -29
  162. /package/dist/lib/{browser/types → neutral}/index.mjs.map +0 -0
@@ -5,43 +5,43 @@
5
5
  import * as Schema from 'effect/Schema';
6
6
  import React, { useCallback, useMemo, useRef, useState } from 'react';
7
7
 
8
- import { DXN, Filter, Obj, Query, type QueryAST, Ref, Tag, Type } from '@dxos/echo';
9
- import { type Mutable } from '@dxos/echo/internal';
10
- import { useTypeOptions } from '@dxos/plugin-space';
11
- import { resolveSchemaWithRegistry } from '@dxos/plugin-space';
12
- import { getSpace, useQuery } from '@dxos/react-client/echo';
8
+ import { resolveSchemaWithRegistry } from '@dxos/app-toolkit/query';
9
+ import { useTypeOptions } from '@dxos/app-toolkit/ui';
10
+ import { DXN, Filter, JsonSchema, Obj, Query, type QueryAST, Ref, Tag } from '@dxos/echo';
11
+ import { type JsonPath, type Mutable } from '@dxos/echo/internal';
12
+ import { getSpace, useObject, useQuery } from '@dxos/react-client/echo';
13
13
  import { IconButton, type ThemedClassName, useAsyncEffect, useTranslation } from '@dxos/react-ui';
14
14
  import { Form, ViewEditor } from '@dxos/react-ui-form';
15
15
  import { List } from '@dxos/react-ui-list';
16
- import { type ProjectionModel, View } from '@dxos/schema';
17
- import { Pipeline, Task } from '@dxos/types';
16
+ import { type ProjectionModel, ViewModel } from '@dxos/schema';
17
+ import { Pipeline } from '@dxos/types';
18
18
  import { mx, osTranslations, subtleHover } from '@dxos/ui-theme';
19
19
  import { arrayMove } from '@dxos/util';
20
20
 
21
- import { meta } from '../meta';
21
+ import { meta } from '#meta';
22
22
 
23
23
  const listGrid = 'grid grid-cols-[min-content_1fr_min-content_min-content_min-content]';
24
24
  const listItemGrid = 'grid grid-cols-subgrid col-span-5';
25
25
 
26
26
  const ColumnFormSchema = Pipeline.Column.pipe(Schema.mutable, Schema.pick('name'));
27
27
 
28
- // TODO(burdon): Standardize Object/Plugin settings.
29
- export type PipelineObjectSettingsProps = ThemedClassName<{
28
+ export type PipelinePropertiesProps = ThemedClassName<{
30
29
  pipeline: Pipeline.Pipeline;
31
30
  }>;
32
31
 
33
32
  /**
34
33
  * Supports editing the pipeline view.
35
34
  */
36
- export const PipelineObjectSettings = ({ classNames, pipeline }: PipelineObjectSettingsProps) => {
35
+ export const PipelineProperties = ({ classNames, pipeline }: PipelinePropertiesProps) => {
37
36
  const { t } = useTranslation(meta.id);
38
37
  const space = getSpace(pipeline);
39
38
  const [expandedId, setExpandedId] = useState<string>();
39
+ const [columns, updateColumns] = useObject(pipeline, 'columns');
40
40
  const column = useMemo(
41
- () => pipeline.columns.find((column) => column.view.dxn.toString() === expandedId),
42
- [pipeline.columns, expandedId],
41
+ () => columns.find((column) => column.view.dxn.toString() === expandedId),
42
+ [columns, expandedId],
43
43
  );
44
- const view = column?.view.target;
44
+ const [view, updateView] = useObject(column?.view);
45
45
  const [schema, setSchema] = useState<Schema.Schema.AnyNoContext>(() => Schema.Struct({}));
46
46
  const projectionRef = useRef<ProjectionModel>(null);
47
47
  const tags = useQuery(space?.db, Filter.type(Tag.Tag));
@@ -50,7 +50,6 @@ export const PipelineObjectSettings = ({ classNames, pipeline }: PipelineObjectS
50
50
  annotation: {
51
51
  location: ['database', 'runtime'],
52
52
  kind: ['user'],
53
- registered: ['registered', 'unregistered'],
54
53
  },
55
54
  });
56
55
 
@@ -67,10 +66,10 @@ export const PipelineObjectSettings = ({ classNames, pipeline }: PipelineObjectS
67
66
 
68
67
  const handleMove = useCallback(
69
68
  (fromIndex: number, toIndex: number) =>
70
- Obj.change(pipeline, (p) => {
71
- arrayMove(p.columns, fromIndex, toIndex);
69
+ updateColumns((columns) => {
70
+ arrayMove(columns, fromIndex, toIndex);
72
71
  }),
73
- [pipeline],
72
+ [updateColumns],
74
73
  );
75
74
 
76
75
  const handleQueryChanged = useCallback(
@@ -80,26 +79,42 @@ export const PipelineObjectSettings = ({ classNames, pipeline }: PipelineObjectS
80
79
  }
81
80
 
82
81
  const queue = target && DXN.tryParse(target) ? target : undefined;
83
- const query = queue ? Query.fromAst(newQuery).options({ queues: [queue] }) : Query.fromAst(newQuery);
84
- Obj.change(view, (v) => {
85
- v.query.ast = query.ast as Mutable<typeof query.ast>;
82
+ const query = queue ? Query.fromAst(newQuery).from({ queues: [queue] }) : Query.fromAst(newQuery);
83
+ updateView((view) => {
84
+ view.query.ast = query.ast as Mutable<typeof query.ast>;
86
85
  });
87
86
  const newSchema = await resolveSchemaWithRegistry(space.db.schemaRegistry, query.ast);
88
87
  if (!newSchema) {
89
88
  return;
90
89
  }
91
90
 
92
- const newView = View.make({
91
+ const newView = ViewModel.make({
93
92
  query,
94
- jsonSchema: Type.toJsonSchema(newSchema),
93
+ jsonSchema: JsonSchema.toJsonSchema(newSchema),
95
94
  });
96
- Obj.change(view, (v) => {
97
- v.projection = Obj.getSnapshot(newView).projection as Mutable<typeof v.projection>;
95
+ updateView((view) => {
96
+ view.projection = Obj.getSnapshot(newView).projection as Mutable<typeof view.projection>;
98
97
  });
99
98
 
100
99
  setSchema(() => newSchema);
101
100
  },
102
- [view, schema],
101
+ [view, updateView, schema],
102
+ );
103
+
104
+ const handleColumnValuesChanged = useCallback(
105
+ (column: Pipeline.Column) =>
106
+ (newValues: { name?: string }, { changed }: { changed: Record<JsonPath, boolean> }) => {
107
+ if (changed['name' as JsonPath]) {
108
+ const columnIndex = columns.findIndex((c) => c === column);
109
+ if (columnIndex === -1) {
110
+ return;
111
+ }
112
+ updateColumns((cols) => {
113
+ cols[columnIndex].name = newValues.name ?? '';
114
+ });
115
+ }
116
+ },
117
+ [columns, updateColumns],
103
118
  );
104
119
 
105
120
  const handleToggleField = useCallback((column: Pipeline.Column) => {
@@ -114,50 +129,42 @@ export const PipelineObjectSettings = ({ classNames, pipeline }: PipelineObjectS
114
129
  setExpandedId(undefined);
115
130
  }
116
131
 
117
- const index = pipeline.columns.findIndex((l) => l === column);
132
+ const index = columns.findIndex((l) => l === column);
118
133
  const viewToRemove = await column.view.load();
119
- Obj.change(pipeline, (p) => {
120
- p.columns.splice(index, 1);
134
+ updateColumns((columns) => {
135
+ columns.splice(index, 1);
121
136
  });
122
137
  space?.db.remove(viewToRemove);
123
138
  },
124
- [expandedId, pipeline.columns, space],
139
+ [expandedId, columns, updateColumns, space],
125
140
  );
126
141
 
127
142
  const handleAdd = useCallback(() => {
128
- const newView = View.make({
129
- query: Query.select(Filter.type(Task.Task)),
130
- jsonSchema: Type.toJsonSchema(Task.Task),
143
+ if (!space) {
144
+ return;
145
+ }
146
+ const newView = ViewModel.make({
147
+ query: Query.select(Filter.nothing()),
148
+ jsonSchema: JsonSchema.toJsonSchema(Schema.Struct({})),
131
149
  });
132
- Obj.change(pipeline, (p) => {
133
- p.columns.push({
134
- name: 'Tasks',
150
+ space.db.add(newView);
151
+ updateColumns((columns) => {
152
+ columns.push({
153
+ name: '',
135
154
  // Type assertion needed due to QueryAST type variance.
136
- view: Ref.make(newView) as (typeof p.columns)[number]['view'],
155
+ view: Ref.make(newView) as (typeof columns)[number]['view'],
137
156
  order: [],
138
157
  });
139
158
  });
140
159
  setExpandedId(newView.id);
141
- }, [pipeline]);
142
-
143
- const handleColumnSave = useCallback(
144
- (values: Schema.Schema.Type<typeof ColumnFormSchema>) => {
145
- if (column) {
146
- const columnIndex = pipeline.columns.findIndex((c) => c === column);
147
- Obj.change(pipeline, (p) => {
148
- p.columns[columnIndex].name = values.name;
149
- });
150
- }
151
- },
152
- [column, pipeline],
153
- );
160
+ }, [space, updateColumns]);
154
161
 
155
162
  return (
156
- <div role='none' className={mx('plb-cardSpacingBlock overflow-y-auto', classNames)}>
157
- <h2 className='text-sm text-description plb-1'>{t('views label')}</h2>
163
+ <div className={mx('py-form-padding overflow-y-auto', classNames)}>
164
+ <h2 className='text-sm text-description py-1'>{t('views.label')}</h2>
158
165
 
159
166
  <List.Root<Pipeline.Column>
160
- items={pipeline.columns}
167
+ items={columns}
161
168
  isItem={Schema.is(Pipeline.Column)}
162
169
  getId={(column) => column.view.dxn.toString()}
163
170
  onMove={handleMove}
@@ -172,11 +179,13 @@ export const PipelineObjectSettings = ({ classNames, pipeline }: PipelineObjectS
172
179
  classNames={listItemGrid}
173
180
  aria-expanded={expandedId === column.view.dxn.toString()}
174
181
  >
175
- <div role='none' className={mx(subtleHover, listItemGrid, 'rounded-sm cursor-pointer min-bs-10')}>
182
+ <div className={mx(subtleHover, listItemGrid, 'rounded-xs cursor-pointer min-h-10')}>
176
183
  <List.ItemDragHandle />
177
- <List.ItemTitle onClick={() => handleToggleField(column)}>{column.name}</List.ItemTitle>
184
+ <List.ItemTitle onClick={() => handleToggleField(column)}>
185
+ {column.name || t('untitled-view.title')}
186
+ </List.ItemTitle>
178
187
  <List.ItemDeleteButton
179
- label={t('delete view label')}
188
+ label={t('delete-view.label')}
180
189
  autoHide={false}
181
190
  onClick={() => handleDelete(column)}
182
191
  data-testid='view.delete'
@@ -184,7 +193,7 @@ export const PipelineObjectSettings = ({ classNames, pipeline }: PipelineObjectS
184
193
  <IconButton
185
194
  iconOnly
186
195
  variant='ghost'
187
- label={t('toggle expand label', { ns: osTranslations })}
196
+ label={t('toggle-expand.label', { ns: osTranslations })}
188
197
  icon={
189
198
  expandedId === column.view.dxn.toString()
190
199
  ? 'ph--caret-down--regular'
@@ -193,9 +202,13 @@ export const PipelineObjectSettings = ({ classNames, pipeline }: PipelineObjectS
193
202
  onClick={() => handleToggleField(column)}
194
203
  />
195
204
  </div>
196
- {expandedId === column.view.dxn.toString() && view && (
197
- <div role='none' className='col-span-5 mlb-2 border border-separator rounded-md'>
198
- <Form.Root schema={ColumnFormSchema} values={column} autoSave onSave={handleColumnSave}>
205
+ {expandedId === column.view.dxn.toString() && column?.view.target && (
206
+ <div className='col-span-5 my-2 border border-separator rounded-md'>
207
+ <Form.Root
208
+ schema={ColumnFormSchema}
209
+ values={column}
210
+ onValuesChanged={handleColumnValuesChanged(column)}
211
+ >
199
212
  <Form.Content>
200
213
  <Form.FieldSet />
201
214
  </Form.Content>
@@ -205,8 +218,9 @@ export const PipelineObjectSettings = ({ classNames, pipeline }: PipelineObjectS
205
218
  mode='tag'
206
219
  readonly
207
220
  schema={schema}
208
- view={view}
221
+ view={column.view.target}
209
222
  registry={space?.db.schemaRegistry}
223
+ db={space?.db}
210
224
  tags={tags}
211
225
  types={types}
212
226
  onQueryChanged={handleQueryChanged}
@@ -220,11 +234,9 @@ export const PipelineObjectSettings = ({ classNames, pipeline }: PipelineObjectS
220
234
  )}
221
235
  </List.Root>
222
236
 
223
- <div role='none' className='mlb-cardSpacingBlock'>
224
- <IconButton icon='ph--plus--regular' label={t('add view label')} onClick={handleAdd} classNames='is-full' />
237
+ <div className='my-form-padding'>
238
+ <IconButton icon='ph--plus--regular' label={t('add-view.label')} onClick={handleAdd} classNames='w-full' />
225
239
  </div>
226
240
  </div>
227
241
  );
228
242
  };
229
-
230
- export default PipelineObjectSettings;
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export { PipelineProperties as default } from './PipelineProperties';
@@ -0,0 +1,8 @@
1
+ //
2
+ // Copyright 2023 DXOS.org
3
+ //
4
+
5
+ import { type ComponentType, lazy } from 'react';
6
+
7
+ export const PipelineContainer: ComponentType<any> = lazy(() => import('./PipelineContainer'));
8
+ export const PipelineProperties: ComponentType<any> = lazy(() => import('./PipelineProperties'));
@@ -0,0 +1,5 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ export * from './usePipelineBoardModel';
@@ -0,0 +1,79 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Atom, type Registry } from '@effect-atom/atom-react';
6
+ import * as Schema from 'effect/Schema';
7
+ import { useMemo } from 'react';
8
+
9
+ import { getQueryTarget } from '@dxos/app-toolkit/query';
10
+ import { Obj, Query } from '@dxos/echo';
11
+ import { AtomObj, AtomQuery } from '@dxos/echo-atom';
12
+ import { getSpace, isSpace } from '@dxos/react-client/echo';
13
+ import { type BoardModel } from '@dxos/react-ui-mosaic';
14
+ import { Pipeline } from '@dxos/types';
15
+
16
+ export const usePipelineBoardModel = (
17
+ pipeline: Pipeline.Pipeline | undefined,
18
+ registry: Registry.Registry,
19
+ ): BoardModel<Pipeline.Column, Obj.Unknown> =>
20
+ useMemo<BoardModel<Pipeline.Column, Obj.Unknown>>(() => {
21
+ if (pipeline == null) {
22
+ return emptyPipelineModel;
23
+ }
24
+
25
+ const space = getSpace(pipeline);
26
+ const columnsAtom = AtomObj.makeProperty(pipeline, 'columns');
27
+ const columnAtomFamily = Atom.family<string, Atom.Atom<Pipeline.Column | undefined>>((viewKey: string) =>
28
+ Atom.make((get) => {
29
+ const columns = get(columnsAtom);
30
+ return columns.find((c) => c.view.dxn.toString() === viewKey);
31
+ }),
32
+ );
33
+
34
+ const itemsAtomFamily = Atom.family<string, Atom.Atom<Obj.Unknown[]>>((viewKey: string) =>
35
+ Atom.make((get) => {
36
+ const column = get(columnAtomFamily(viewKey));
37
+ if (column == null) {
38
+ return [];
39
+ }
40
+ const viewSnapshot = get(AtomObj.make(column.view));
41
+ if (!viewSnapshot?.query?.ast) {
42
+ return [];
43
+ }
44
+ const query = Query.fromAst(JSON.parse(JSON.stringify(viewSnapshot.query.ast)));
45
+ const queryTarget = space ? getQueryTarget(query.ast, space) : undefined;
46
+ if (!queryTarget) {
47
+ return [];
48
+ }
49
+ const raw = get(AtomQuery.make(queryTarget, query));
50
+ return isSpace(queryTarget) ? raw : [...raw].reverse();
51
+ }),
52
+ );
53
+
54
+ return {
55
+ getColumnId: (data) => (data as Pipeline.Column).view.dxn.toString(),
56
+ getItemId: (data) => (data as Obj.Unknown).id,
57
+ isColumn: (obj: unknown): obj is Pipeline.Column => Schema.is(Pipeline.Column)(obj),
58
+ isItem: (obj: unknown): obj is Obj.Unknown => Obj.isObject(obj),
59
+ columns: columnsAtom,
60
+ items: (column) => itemsAtomFamily(column.view.dxn.toString()),
61
+ getColumns: () => [...registry.get(columnsAtom)],
62
+ getItems: (column) => registry.get(itemsAtomFamily(column.view.dxn.toString())) ?? [],
63
+ };
64
+ }, [pipeline, registry]);
65
+
66
+ const emptyColumnsAtom = Atom.make(() => [] as Pipeline.Column[]);
67
+
68
+ const emptyItemsAtom = Atom.make(() => [] as Obj.Unknown[]);
69
+
70
+ const emptyPipelineModel: BoardModel<Pipeline.Column, Obj.Unknown> = {
71
+ getColumnId: (data) => (data as Pipeline.Column).view.dxn.toString(),
72
+ getItemId: (data) => (data as Obj.Unknown).id,
73
+ isColumn: (obj: unknown): obj is Pipeline.Column => Schema.is(Pipeline.Column)(obj),
74
+ isItem: (obj): obj is Obj.Unknown => Obj.isObject(obj),
75
+ columns: emptyColumnsAtom,
76
+ items: () => emptyItemsAtom,
77
+ getColumns: () => [],
78
+ getItems: () => [],
79
+ };
package/src/index.ts CHANGED
@@ -3,4 +3,3 @@
3
3
  //
4
4
 
5
5
  export * from './meta';
6
- export * from './PipelinePlugin';
package/src/meta.ts CHANGED
@@ -6,7 +6,7 @@ import { type Plugin } from '@dxos/app-framework';
6
6
  import { trim } from '@dxos/util';
7
7
 
8
8
  export const meta: Plugin.Meta = {
9
- id: 'dxos.org/plugin/pipeline',
9
+ id: 'org.dxos.plugin.pipeline',
10
10
  name: 'Pipelines',
11
11
  description: trim`
12
12
  Pipelines for organizing tasks, milestones, and deliverables.
package/src/plugin.ts ADDED
@@ -0,0 +1,9 @@
1
+ //
2
+ // Copyright 2025 DXOS.org
3
+ //
4
+
5
+ import { Plugin } from '@dxos/app-framework';
6
+
7
+ import { meta } from './meta';
8
+
9
+ export const PipelinePlugin = Plugin.lazy(meta, () => import('#plugin'));
@@ -2,10 +2,10 @@
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
4
 
5
- import { type Database, Filter, Query, Ref, Type } from '@dxos/echo';
6
- import { Mailbox } from '@dxos/plugin-inbox/types';
7
- import { Markdown } from '@dxos/plugin-markdown/types';
8
- import { View } from '@dxos/schema';
5
+ import { type Database, Filter, JsonSchema, Query, Ref } from '@dxos/echo';
6
+ import { Mailbox } from '@dxos/plugin-inbox';
7
+ import { Markdown } from '@dxos/plugin-markdown';
8
+ import { ViewModel } from '@dxos/schema';
9
9
  import { Message, Organization, Person, Pipeline } from '@dxos/types';
10
10
 
11
11
  export const createResearchProject = async (
@@ -13,34 +13,33 @@ export const createResearchProject = async (
13
13
  name?: string,
14
14
  ): Promise<Pipeline.Pipeline | null> => {
15
15
  const mailboxes = await db.query(Filter.type(Mailbox.Mailbox)).run();
16
- if (!mailboxes.length) {
16
+ const mailbox = mailboxes[0];
17
+ const feed = await mailbox?.feed?.tryLoad();
18
+ if (!mailbox || !feed) {
17
19
  return null;
18
20
  }
19
21
 
20
- const mailbox = mailboxes[0];
21
- const mailboxView = View.make({
22
- query: Query.select(Filter.type(Message.Message)).options({
23
- queues: [mailbox.queue.dxn.toString()],
24
- }),
25
- jsonSchema: Type.toJsonSchema(Message.Message),
22
+ const mailboxView = ViewModel.make({
23
+ query: Query.select(Filter.type(Message.Message)).from(feed),
24
+ jsonSchema: JsonSchema.toJsonSchema(Message.Message),
26
25
  });
27
26
 
28
27
  const contactsQuery = Query.select(Filter.type(Person.Person));
29
- const contactsView = View.make({
28
+ const contactsView = ViewModel.make({
30
29
  query: contactsQuery,
31
- jsonSchema: Type.toJsonSchema(Person.Person),
30
+ jsonSchema: JsonSchema.toJsonSchema(Person.Person),
32
31
  });
33
32
 
34
33
  const organizationsQuery = Query.select(Filter.type(Organization.Organization));
35
- const organizationsView = View.make({
34
+ const organizationsView = ViewModel.make({
36
35
  query: organizationsQuery,
37
- jsonSchema: Type.toJsonSchema(Organization.Organization),
36
+ jsonSchema: JsonSchema.toJsonSchema(Organization.Organization),
38
37
  });
39
38
 
40
39
  const notesQuery = Query.select(Filter.type(Markdown.Document));
41
- const notesView = View.make({
40
+ const notesView = ViewModel.make({
42
41
  query: notesQuery,
43
- jsonSchema: Type.toJsonSchema(Markdown.Document),
42
+ jsonSchema: JsonSchema.toJsonSchema(Markdown.Document),
44
43
  });
45
44
 
46
45
  return Pipeline.make({
@@ -4,34 +4,35 @@ import { Pipeline } from '@dxos/types';
4
4
  // Copyright 2023 DXOS.org
5
5
  //
6
6
 
7
- import { meta } from './meta';
7
+ import { meta } from '#meta';
8
8
 
9
9
  export const translations = [
10
10
  {
11
11
  'en-US': {
12
12
  [Pipeline.Pipeline.typename]: {
13
- 'typename label': 'Pipeline',
14
- 'typename label_zero': 'Pipelines',
15
- 'typename label_one': 'Pipeline',
16
- 'typename label_other': 'Pipelines',
17
- 'object name placeholder': 'New pipeline',
18
- 'rename object label': 'Rename pipeline',
19
- 'delete object label': 'Delete pipeline',
20
- 'object deleted label': 'Pipeline deleted',
13
+ 'typename.label': 'Pipeline',
14
+ 'typename.label_zero': 'Pipelines',
15
+ 'typename.label_one': 'Pipeline',
16
+ 'typename.label_other': 'Pipelines',
17
+ 'object-name.placeholder': 'New pipeline',
18
+ 'add-object.label': 'Add pipeline',
19
+ 'rename-object.label': 'Rename pipeline',
20
+ 'delete-object.label': 'Delete pipeline',
21
+ 'object-deleted.label': 'Pipeline deleted',
21
22
  },
22
23
  [meta.id]: {
23
- 'plugin name': 'Pipelines',
24
- 'add column label': 'Add column',
25
- 'add card label': 'Add object',
26
- 'untitled view title': 'New view',
27
- 'enumerating tab label': 'List',
28
- 'editing tab label': 'Edit',
29
- 'views label': 'Views',
30
- 'pipeline invocations label': 'Invocations',
31
- 'pipeline automation label': 'Automations',
32
- 'toggle expand label': 'Toggle expand',
33
- 'delete view label': 'Delete view',
34
- 'add view label': 'Add view',
24
+ 'plugin.name': 'Pipelines',
25
+ 'add-column.label': 'Add column',
26
+ 'add-card.label': 'Add object',
27
+ 'untitled-view.title': 'New view',
28
+ 'enumerating-tab.label': 'List',
29
+ 'editing-tab.label': 'Edit',
30
+ 'views.label': 'Views',
31
+ 'pipeline-invocations.label': 'Invocations',
32
+ 'pipeline-automation.label': 'Automations',
33
+ 'toggle-expand.label': 'Toggle expand',
34
+ 'delete-view.label': 'Delete view',
35
+ 'add-view.label': 'Add view',
35
36
  },
36
37
  },
37
38
  },
@@ -1,6 +1,3 @@
1
1
  //
2
2
  // Copyright 2025 DXOS.org
3
3
  //
4
-
5
- export * as PipelineAction from './PipelineAction';
6
- export { PipelineOperation } from './PipelineAction';