@dxos/plugin-pipeline 0.8.4-main.fcfe5033a5 → 0.9.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.
- package/LICENSE +102 -5
- package/PLUGIN.mdl +345 -0
- package/README.md +1 -1
- package/dist/lib/neutral/PipelineArticle-6JIVXMYF.mjs +69 -0
- package/dist/lib/neutral/PipelineArticle-6JIVXMYF.mjs.map +7 -0
- package/dist/lib/neutral/PipelinePlugin.mjs +38 -0
- package/dist/lib/neutral/PipelinePlugin.mjs.map +7 -0
- package/dist/lib/neutral/PipelinePlugin.node.mjs +21 -0
- package/dist/lib/neutral/PipelinePlugin.node.mjs.map +7 -0
- package/dist/lib/neutral/PipelinePlugin.workerd.mjs +16 -0
- package/dist/lib/neutral/PipelinePlugin.workerd.mjs.map +7 -0
- package/dist/lib/neutral/PipelineProperties-JZQYG2CN.mjs +209 -0
- package/dist/lib/neutral/PipelineProperties-JZQYG2CN.mjs.map +7 -0
- package/dist/lib/neutral/app-graph-builder-ZLGRWRJU.mjs +44 -0
- package/dist/lib/neutral/app-graph-builder-ZLGRWRJU.mjs.map +7 -0
- package/dist/lib/neutral/capabilities/index.mjs +11 -0
- package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
- package/dist/lib/neutral/chunk-CYXDAAKN.mjs +35 -0
- package/dist/lib/neutral/chunk-CYXDAAKN.mjs.map +7 -0
- package/dist/lib/neutral/components/index.mjs +203 -0
- package/dist/lib/neutral/components/index.mjs.map +7 -0
- package/dist/lib/neutral/containers/index.mjs +9 -0
- package/dist/lib/neutral/containers/index.mjs.map +7 -0
- package/dist/lib/neutral/create-object-6Z4MMGX4.mjs +26 -0
- package/dist/lib/neutral/create-object-6Z4MMGX4.mjs.map +7 -0
- package/dist/lib/neutral/hooks/index.mjs +69 -0
- package/dist/lib/neutral/hooks/index.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +7 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/neutral/meta.mjs +7 -0
- package/dist/lib/neutral/meta.mjs.map +7 -0
- package/dist/lib/neutral/plugin.mjs +11 -0
- package/dist/lib/neutral/plugin.mjs.map +7 -0
- package/dist/lib/neutral/react-surface-QG7QSZSS.mjs +49 -0
- package/dist/lib/neutral/react-surface-QG7QSZSS.mjs.map +7 -0
- package/dist/lib/neutral/translations.mjs +39 -0
- package/dist/lib/neutral/translations.mjs.map +7 -0
- package/dist/lib/neutral/types/index.mjs.map +7 -0
- package/dist/types/src/PipelinePlugin.d.ts +1 -0
- package/dist/types/src/PipelinePlugin.d.ts.map +1 -1
- package/dist/types/src/PipelinePlugin.node.d.ts +4 -0
- package/dist/types/src/PipelinePlugin.node.d.ts.map +1 -0
- package/dist/types/src/PipelinePlugin.test.d.ts +2 -0
- package/dist/types/src/PipelinePlugin.test.d.ts.map +1 -0
- package/dist/types/src/PipelinePlugin.workerd.d.ts +4 -0
- package/dist/types/src/PipelinePlugin.workerd.d.ts.map +1 -0
- package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -1
- package/dist/types/src/capabilities/create-object.d.ts +11 -0
- package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +6 -0
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/components/PipelineComponent/PipelineColumn.d.ts +4 -4
- package/dist/types/src/components/PipelineComponent/PipelineColumn.d.ts.map +1 -1
- package/dist/types/src/components/PipelineComponent/PipelineComponent.d.ts +4 -0
- package/dist/types/src/components/PipelineComponent/PipelineComponent.d.ts.map +1 -1
- package/dist/types/src/components/PipelineComponent/PipelineComponent.stories.d.ts +44 -25
- package/dist/types/src/components/PipelineComponent/PipelineComponent.stories.d.ts.map +1 -1
- package/dist/types/src/containers/PipelineArticle/PipelineArticle.d.ts +6 -0
- package/dist/types/src/containers/PipelineArticle/PipelineArticle.d.ts.map +1 -0
- package/dist/types/src/containers/PipelineArticle/PipelineArticle.stories.d.ts +76 -0
- package/dist/types/src/containers/PipelineArticle/PipelineArticle.stories.d.ts.map +1 -0
- package/dist/types/src/containers/PipelineArticle/index.d.ts +2 -0
- package/dist/types/src/containers/PipelineArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/PipelineProperties/PipelineProperties.d.ts.map +1 -1
- package/dist/types/src/containers/index.d.ts +1 -1
- package/dist/types/src/containers/index.d.ts.map +1 -1
- package/dist/types/src/hooks/usePipelineBoardModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +0 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +1 -1
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/plugin.d.ts +3 -0
- package/dist/types/src/plugin.d.ts.map +1 -0
- package/dist/types/src/templates/research.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +44 -26
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +100 -64
- package/src/PipelinePlugin.node.ts +19 -0
- package/src/PipelinePlugin.test.ts +27 -0
- package/src/PipelinePlugin.tsx +10 -29
- package/src/PipelinePlugin.workerd.ts +16 -0
- package/src/capabilities/create-object.ts +30 -0
- package/src/capabilities/index.ts +1 -0
- package/src/capabilities/react-surface.tsx +3 -3
- package/src/components/PipelineComponent/PipelineColumn.tsx +23 -33
- package/src/components/PipelineComponent/PipelineComponent.stories.tsx +6 -8
- package/src/components/PipelineComponent/PipelineComponent.tsx +2 -2
- package/src/containers/{PipelineContainer/PipelineContainer.stories.tsx → PipelineArticle/PipelineArticle.stories.tsx} +18 -22
- package/src/containers/{PipelineContainer/PipelineContainer.tsx → PipelineArticle/PipelineArticle.tsx} +6 -8
- package/src/containers/PipelineArticle/index.ts +5 -0
- package/src/containers/PipelineProperties/PipelineProperties.tsx +45 -53
- package/src/containers/index.ts +1 -1
- package/src/hooks/usePipelineBoardModel.ts +8 -9
- package/src/index.ts +0 -1
- package/src/meta.ts +19 -6
- package/src/plugin.ts +9 -0
- package/src/templates/research.ts +2 -2
- package/src/translations.ts +2 -1
- package/src/vite-env.d.ts +10 -0
- package/dist/lib/browser/index.mjs +0 -98
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/types/src/containers/PipelineContainer/PipelineContainer.d.ts +0 -6
- package/dist/types/src/containers/PipelineContainer/PipelineContainer.d.ts.map +0 -1
- package/dist/types/src/containers/PipelineContainer/PipelineContainer.stories.d.ts +0 -57
- package/dist/types/src/containers/PipelineContainer/PipelineContainer.stories.d.ts.map +0 -1
- package/dist/types/src/containers/PipelineContainer/index.d.ts +0 -2
- package/dist/types/src/containers/PipelineContainer/index.d.ts.map +0 -1
- package/src/containers/PipelineContainer/index.ts +0 -5
- /package/dist/lib/{browser/types → neutral}/index.mjs.map +0 -0
- /package/dist/lib/{browser → neutral}/types/index.mjs +0 -0
|
@@ -8,26 +8,25 @@ import * as Layer from 'effect/Layer';
|
|
|
8
8
|
import React from 'react';
|
|
9
9
|
|
|
10
10
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
11
|
-
import { Filter, Ref } from '@dxos/
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import { createFeedServiceLayer } from '@dxos/echo-db';
|
|
15
|
-
import { ClientPlugin } from '@dxos/plugin-client';
|
|
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';
|
|
16
14
|
import { initializeIdentity } from '@dxos/plugin-client/testing';
|
|
17
|
-
import { InboxPlugin } from '@dxos/plugin-inbox';
|
|
18
|
-
import { PreviewPlugin } from '@dxos/plugin-preview';
|
|
15
|
+
import { InboxPlugin } from '@dxos/plugin-inbox/plugin';
|
|
16
|
+
import { PreviewPlugin } from '@dxos/plugin-preview/testing';
|
|
19
17
|
import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
|
|
20
18
|
import { random } from '@dxos/random';
|
|
21
19
|
import { useDatabase, useQuery } from '@dxos/react-client/echo';
|
|
22
|
-
import { translations as stackTranslations } from '@dxos/react-ui-stack';
|
|
20
|
+
import { translations as stackTranslations } from '@dxos/react-ui-stack/translations';
|
|
23
21
|
import { withLayout } from '@dxos/react-ui/testing';
|
|
24
22
|
import { ViewModel } from '@dxos/schema';
|
|
25
23
|
import { createObjectFactory } from '@dxos/schema/testing';
|
|
26
24
|
import { Message, Organization, Person, Pipeline, Task } from '@dxos/types';
|
|
27
25
|
|
|
28
|
-
import { translations } from '
|
|
26
|
+
import { translations } from '#translations';
|
|
27
|
+
|
|
29
28
|
import PipelineProperties from '../PipelineProperties';
|
|
30
|
-
import {
|
|
29
|
+
import { PipelineArticle } from './PipelineArticle';
|
|
31
30
|
|
|
32
31
|
random.seed(0);
|
|
33
32
|
|
|
@@ -42,14 +41,14 @@ const DefaultStory = () => {
|
|
|
42
41
|
|
|
43
42
|
return (
|
|
44
43
|
<div className='grow grid grid-cols-[1fr_350px] overflow-hidden h-full w-full'>
|
|
45
|
-
<
|
|
44
|
+
<PipelineArticle role='article' subject={pipeline} attendableId='test' />
|
|
46
45
|
<PipelineProperties pipeline={pipeline} classNames='border-s border-separator' />
|
|
47
46
|
</div>
|
|
48
47
|
);
|
|
49
48
|
};
|
|
50
49
|
|
|
51
50
|
const meta = {
|
|
52
|
-
title: 'plugins/plugin-pipeline/containers/
|
|
51
|
+
title: 'plugins/plugin-pipeline/containers/PipelineArticle',
|
|
53
52
|
render: DefaultStory,
|
|
54
53
|
decorators: [
|
|
55
54
|
withLayout({ layout: 'fullscreen' }),
|
|
@@ -74,7 +73,7 @@ const meta = {
|
|
|
74
73
|
|
|
75
74
|
yield* Effect.gen(function* () {
|
|
76
75
|
const tag = yield* Database.add(Tag.make({ label: 'important', hue: 'green' }));
|
|
77
|
-
const
|
|
76
|
+
const tagUri = Obj.getURI(tag);
|
|
78
77
|
|
|
79
78
|
// Create a view for Contacts.
|
|
80
79
|
const personView = ViewModel.make({
|
|
@@ -84,13 +83,13 @@ const meta = {
|
|
|
84
83
|
|
|
85
84
|
// Create a view for Organizations.
|
|
86
85
|
const organizationView = ViewModel.make({
|
|
87
|
-
query: Query.select(Filter.type(Organization.Organization)).select(Filter.tag(
|
|
86
|
+
query: Query.select(Filter.type(Organization.Organization)).select(Filter.tag(tagUri)),
|
|
88
87
|
jsonSchema: JsonSchema.toJsonSchema(Organization.Organization),
|
|
89
88
|
});
|
|
90
89
|
|
|
91
90
|
// Create a view for Tasks.
|
|
92
91
|
const taskView = ViewModel.make({
|
|
93
|
-
query: Query.select(Filter.type(Task.Task)).select(Filter.tag(
|
|
92
|
+
query: Query.select(Filter.type(Task.Task)).select(Filter.tag(tagUri)),
|
|
94
93
|
jsonSchema: JsonSchema.toJsonSchema(Task.Task),
|
|
95
94
|
});
|
|
96
95
|
|
|
@@ -111,11 +110,8 @@ const meta = {
|
|
|
111
110
|
);
|
|
112
111
|
yield* Feed.append(messageFeed, messages);
|
|
113
112
|
|
|
114
|
-
const messageQueueDxn = Feed.getQueueDxn(messageFeed)!.toString();
|
|
115
113
|
const messageView = ViewModel.make({
|
|
116
|
-
query: Query.select(Filter.type(Message.Message)).from(
|
|
117
|
-
queues: [messageQueueDxn],
|
|
118
|
-
}),
|
|
114
|
+
query: Query.select(Filter.type(Message.Message)).from(Scope.feed(Obj.getURI(messageFeed))),
|
|
119
115
|
jsonSchema: JsonSchema.toJsonSchema(Message.Message),
|
|
120
116
|
});
|
|
121
117
|
|
|
@@ -167,7 +163,7 @@ const meta = {
|
|
|
167
163
|
yield* Database.add(
|
|
168
164
|
Obj.make(Organization.Organization, {
|
|
169
165
|
[Obj.Meta]: {
|
|
170
|
-
tags: random.datatype.boolean() ? [
|
|
166
|
+
tags: random.datatype.boolean() ? [tagUri] : [],
|
|
171
167
|
},
|
|
172
168
|
name: random.company.name(),
|
|
173
169
|
website: random.internet.url(),
|
|
@@ -182,7 +178,7 @@ const meta = {
|
|
|
182
178
|
yield* Database.add(
|
|
183
179
|
Obj.make(Task.Task, {
|
|
184
180
|
[Obj.Meta]: {
|
|
185
|
-
tags: random.datatype.boolean() ? [
|
|
181
|
+
tags: random.datatype.boolean() ? [tagUri] : [],
|
|
186
182
|
},
|
|
187
183
|
title: random.lorem.sentence(),
|
|
188
184
|
status: random.helpers.arrayElement(['todo', 'in-progress', 'done']) as any,
|
|
@@ -220,7 +216,7 @@ const meta = {
|
|
|
220
216
|
layout: 'fullscreen',
|
|
221
217
|
translations: [...translations, ...stackTranslations],
|
|
222
218
|
},
|
|
223
|
-
} satisfies Meta<typeof
|
|
219
|
+
} satisfies Meta<typeof PipelineArticle>;
|
|
224
220
|
|
|
225
221
|
export default meta;
|
|
226
222
|
|
|
@@ -5,16 +5,14 @@
|
|
|
5
5
|
import React, { useCallback, useEffect } from 'react';
|
|
6
6
|
|
|
7
7
|
import { Capabilities } from '@dxos/app-framework';
|
|
8
|
-
import { useCapability } from '@dxos/app-framework/ui';
|
|
9
|
-
import {
|
|
10
|
-
import { Surface } from '@dxos/app-framework/ui';
|
|
8
|
+
import { Surface, useCapability, useOperationInvoker } from '@dxos/app-framework/ui';
|
|
9
|
+
import { LayoutOperation } from '@dxos/app-toolkit';
|
|
11
10
|
import {
|
|
12
11
|
AppSurface,
|
|
13
12
|
OBJECT_ACTIONS_CONTRIBUTION_ID,
|
|
14
13
|
OBJECT_ACTIONS_CONTRIBUTION_PRIORITY,
|
|
15
14
|
useObjectMenuItems,
|
|
16
15
|
} from '@dxos/app-toolkit/ui';
|
|
17
|
-
import { DeckOperation } from '@dxos/plugin-deck/operations';
|
|
18
16
|
import { Panel } from '@dxos/react-ui';
|
|
19
17
|
import { linkedSegment } from '@dxos/react-ui-attention';
|
|
20
18
|
import { useAttention } from '@dxos/react-ui-attention';
|
|
@@ -26,9 +24,9 @@ import { usePipelineBoardModel } from '#hooks';
|
|
|
26
24
|
|
|
27
25
|
const PIPELINE_ITEM = 'PipelineItem';
|
|
28
26
|
|
|
29
|
-
export type
|
|
27
|
+
export type PipelineArticleProps = AppSurface.ObjectArticleProps<Pipeline.Pipeline>;
|
|
30
28
|
|
|
31
|
-
export const
|
|
29
|
+
export const PipelineArticle = ({ role, subject: pipeline, attendableId }: PipelineArticleProps) => {
|
|
32
30
|
const registry = useCapability(Capabilities.AtomRegistry);
|
|
33
31
|
const model = usePipelineBoardModel(pipeline, registry);
|
|
34
32
|
const { invokePromise } = useOperationInvoker();
|
|
@@ -36,8 +34,8 @@ export const PipelineContainer = ({ role, subject: pipeline, attendableId }: Pip
|
|
|
36
34
|
|
|
37
35
|
const handleColumnAdd = useCallback(
|
|
38
36
|
() =>
|
|
39
|
-
invokePromise(
|
|
40
|
-
|
|
37
|
+
invokePromise(LayoutOperation.UpdateCompanion, {
|
|
38
|
+
subject: linkedSegment('settings'),
|
|
41
39
|
}),
|
|
42
40
|
[invokePromise],
|
|
43
41
|
);
|
|
@@ -7,15 +7,16 @@ import React, { useCallback, useMemo, useRef, useState } from 'react';
|
|
|
7
7
|
|
|
8
8
|
import { resolveSchemaWithRegistry } from '@dxos/app-toolkit/query';
|
|
9
9
|
import { useTypeOptions } from '@dxos/app-toolkit/ui';
|
|
10
|
-
import {
|
|
11
|
-
import { type
|
|
12
|
-
import {
|
|
10
|
+
import { EID, Filter, JsonSchema, Obj, Query, type QueryAST, Ref, Scope, Tag, type Type } from '@dxos/echo';
|
|
11
|
+
import { type Mutable } from '@dxos/echo/Obj';
|
|
12
|
+
import { SchemaEx } from '@dxos/effect';
|
|
13
|
+
import { useObject, useQuery } from '@dxos/react-client/echo';
|
|
13
14
|
import { IconButton, type ThemedClassName, useAsyncEffect, useTranslation } from '@dxos/react-ui';
|
|
14
15
|
import { Form, ViewEditor } from '@dxos/react-ui-form';
|
|
15
16
|
import { List } from '@dxos/react-ui-list';
|
|
16
17
|
import { type ProjectionModel, ViewModel } from '@dxos/schema';
|
|
17
18
|
import { Pipeline } from '@dxos/types';
|
|
18
|
-
import { mx, osTranslations
|
|
19
|
+
import { mx, osTranslations } from '@dxos/ui-theme';
|
|
19
20
|
import { arrayMove } from '@dxos/util';
|
|
20
21
|
|
|
21
22
|
import { meta } from '#meta';
|
|
@@ -34,19 +35,16 @@ export type PipelinePropertiesProps = ThemedClassName<{
|
|
|
34
35
|
*/
|
|
35
36
|
export const PipelineProperties = ({ classNames, pipeline }: PipelinePropertiesProps) => {
|
|
36
37
|
const { t } = useTranslation(meta.id);
|
|
37
|
-
const
|
|
38
|
+
const db = Obj.getDatabase(pipeline);
|
|
38
39
|
const [expandedId, setExpandedId] = useState<string>();
|
|
39
40
|
const [columns, updateColumns] = useObject(pipeline, 'columns');
|
|
40
|
-
const column = useMemo(
|
|
41
|
-
() => columns.find((column) => column.view.dxn.toString() === expandedId),
|
|
42
|
-
[columns, expandedId],
|
|
43
|
-
);
|
|
41
|
+
const column = useMemo(() => columns.find((column) => column.view.uri === expandedId), [columns, expandedId]);
|
|
44
42
|
const [view, updateView] = useObject(column?.view);
|
|
45
|
-
const [
|
|
43
|
+
const [type, setType] = useState<Type.AnyEntity>();
|
|
46
44
|
const projectionRef = useRef<ProjectionModel>(null);
|
|
47
|
-
const tags = useQuery(
|
|
45
|
+
const tags = useQuery(db, Filter.type(Tag.Tag));
|
|
48
46
|
const types = useTypeOptions({
|
|
49
|
-
|
|
47
|
+
db,
|
|
50
48
|
annotation: {
|
|
51
49
|
location: ['database', 'runtime'],
|
|
52
50
|
kind: ['user'],
|
|
@@ -54,15 +52,15 @@ export const PipelineProperties = ({ classNames, pipeline }: PipelinePropertiesP
|
|
|
54
52
|
});
|
|
55
53
|
|
|
56
54
|
useAsyncEffect(async () => {
|
|
57
|
-
if (!view?.query || !
|
|
55
|
+
if (!view?.query || !db) {
|
|
58
56
|
return;
|
|
59
57
|
}
|
|
60
58
|
|
|
61
|
-
const
|
|
62
|
-
if (
|
|
63
|
-
|
|
59
|
+
const foundType = await resolveSchemaWithRegistry(db, view.query.ast);
|
|
60
|
+
if (foundType && foundType !== type) {
|
|
61
|
+
setType(() => foundType);
|
|
64
62
|
}
|
|
65
|
-
}, [
|
|
63
|
+
}, [db, view, type]);
|
|
66
64
|
|
|
67
65
|
const handleMove = useCallback(
|
|
68
66
|
(fromIndex: number, toIndex: number) =>
|
|
@@ -73,38 +71,38 @@ export const PipelineProperties = ({ classNames, pipeline }: PipelinePropertiesP
|
|
|
73
71
|
);
|
|
74
72
|
|
|
75
73
|
const handleQueryChanged = useCallback(
|
|
76
|
-
async (newQuery: QueryAST.Query, target?:
|
|
77
|
-
if (!view || !
|
|
74
|
+
async (newQuery: QueryAST.Query, target?: EID.EID) => {
|
|
75
|
+
if (!view || !db) {
|
|
78
76
|
return;
|
|
79
77
|
}
|
|
80
78
|
|
|
81
|
-
const queue = target
|
|
82
|
-
const query = queue ? Query.fromAst(newQuery).from(
|
|
79
|
+
const queue = target;
|
|
80
|
+
const query = queue ? Query.fromAst(newQuery).from([Scope.feed(String(queue))]) : Query.fromAst(newQuery);
|
|
83
81
|
updateView((view) => {
|
|
84
82
|
view.query.ast = query.ast as Mutable<typeof query.ast>;
|
|
85
83
|
});
|
|
86
|
-
const
|
|
87
|
-
if (!
|
|
84
|
+
const newType = await resolveSchemaWithRegistry(db, query.ast);
|
|
85
|
+
if (!newType) {
|
|
88
86
|
return;
|
|
89
87
|
}
|
|
90
88
|
|
|
91
89
|
const newView = ViewModel.make({
|
|
92
90
|
query,
|
|
93
|
-
jsonSchema:
|
|
91
|
+
jsonSchema: newType.jsonSchema,
|
|
94
92
|
});
|
|
95
93
|
updateView((view) => {
|
|
96
94
|
view.projection = Obj.getSnapshot(newView).projection as Mutable<typeof view.projection>;
|
|
97
95
|
});
|
|
98
96
|
|
|
99
|
-
|
|
97
|
+
setType(() => newType);
|
|
100
98
|
},
|
|
101
|
-
[view, updateView,
|
|
99
|
+
[db, view, updateView, type],
|
|
102
100
|
);
|
|
103
101
|
|
|
104
102
|
const handleColumnValuesChanged = useCallback(
|
|
105
103
|
(column: Pipeline.Column) =>
|
|
106
|
-
(newValues: { name?: string }, { changed }: { changed: Record<JsonPath, boolean> }) => {
|
|
107
|
-
if (changed['name' as JsonPath]) {
|
|
104
|
+
(newValues: { name?: string }, { changed }: { changed: Record<SchemaEx.JsonPath, boolean> }) => {
|
|
105
|
+
if (changed['name' as SchemaEx.JsonPath]) {
|
|
108
106
|
const columnIndex = columns.findIndex((c) => c === column);
|
|
109
107
|
if (columnIndex === -1) {
|
|
110
108
|
return;
|
|
@@ -118,14 +116,12 @@ export const PipelineProperties = ({ classNames, pipeline }: PipelinePropertiesP
|
|
|
118
116
|
);
|
|
119
117
|
|
|
120
118
|
const handleToggleField = useCallback((column: Pipeline.Column) => {
|
|
121
|
-
setExpandedId((prevExpandedId) =>
|
|
122
|
-
prevExpandedId === column.view.dxn.toString() ? undefined : column.view.dxn.toString(),
|
|
123
|
-
);
|
|
119
|
+
setExpandedId((prevExpandedId) => (prevExpandedId === column.view.uri ? undefined : column.view.uri));
|
|
124
120
|
}, []);
|
|
125
121
|
|
|
126
122
|
const handleDelete = useCallback(
|
|
127
123
|
async (column: Pipeline.Column) => {
|
|
128
|
-
if (column.view.
|
|
124
|
+
if (column.view.uri === expandedId) {
|
|
129
125
|
setExpandedId(undefined);
|
|
130
126
|
}
|
|
131
127
|
|
|
@@ -134,20 +130,20 @@ export const PipelineProperties = ({ classNames, pipeline }: PipelinePropertiesP
|
|
|
134
130
|
updateColumns((columns) => {
|
|
135
131
|
columns.splice(index, 1);
|
|
136
132
|
});
|
|
137
|
-
|
|
133
|
+
db?.remove(viewToRemove);
|
|
138
134
|
},
|
|
139
|
-
[expandedId, columns, updateColumns,
|
|
135
|
+
[expandedId, columns, updateColumns, db],
|
|
140
136
|
);
|
|
141
137
|
|
|
142
138
|
const handleAdd = useCallback(() => {
|
|
143
|
-
if (!
|
|
139
|
+
if (!db) {
|
|
144
140
|
return;
|
|
145
141
|
}
|
|
146
142
|
const newView = ViewModel.make({
|
|
147
143
|
query: Query.select(Filter.nothing()),
|
|
148
144
|
jsonSchema: JsonSchema.toJsonSchema(Schema.Struct({})),
|
|
149
145
|
});
|
|
150
|
-
|
|
146
|
+
db.add(newView);
|
|
151
147
|
updateColumns((columns) => {
|
|
152
148
|
columns.push({
|
|
153
149
|
name: '',
|
|
@@ -157,16 +153,16 @@ export const PipelineProperties = ({ classNames, pipeline }: PipelinePropertiesP
|
|
|
157
153
|
});
|
|
158
154
|
});
|
|
159
155
|
setExpandedId(newView.id);
|
|
160
|
-
}, [
|
|
156
|
+
}, [db, updateColumns]);
|
|
161
157
|
|
|
162
158
|
return (
|
|
163
|
-
<div
|
|
159
|
+
<div className={mx('py-form-padding overflow-y-auto', classNames)}>
|
|
164
160
|
<h2 className='text-sm text-description py-1'>{t('views.label')}</h2>
|
|
165
161
|
|
|
166
162
|
<List.Root<Pipeline.Column>
|
|
167
163
|
items={columns}
|
|
168
164
|
isItem={Schema.is(Pipeline.Column)}
|
|
169
|
-
getId={(column) => column.view.
|
|
165
|
+
getId={(column) => column.view.uri}
|
|
170
166
|
onMove={handleMove}
|
|
171
167
|
>
|
|
172
168
|
{({ items: columns }) => (
|
|
@@ -174,12 +170,12 @@ export const PipelineProperties = ({ classNames, pipeline }: PipelinePropertiesP
|
|
|
174
170
|
<div role='list' className={mx(listGrid)}>
|
|
175
171
|
{columns.map((column) => (
|
|
176
172
|
<List.Item<Pipeline.Column>
|
|
177
|
-
key={column.view.
|
|
173
|
+
key={column.view.uri}
|
|
178
174
|
item={column}
|
|
179
175
|
classNames={listItemGrid}
|
|
180
|
-
aria-expanded={expandedId === column.view.
|
|
176
|
+
aria-expanded={expandedId === column.view.uri}
|
|
181
177
|
>
|
|
182
|
-
<div
|
|
178
|
+
<div className={mx(listItemGrid, 'dx-hover rounded-xs cursor-pointer min-h-10')}>
|
|
183
179
|
<List.ItemDragHandle />
|
|
184
180
|
<List.ItemTitle onClick={() => handleToggleField(column)}>
|
|
185
181
|
{column.name || t('untitled-view.title')}
|
|
@@ -194,16 +190,12 @@ export const PipelineProperties = ({ classNames, pipeline }: PipelinePropertiesP
|
|
|
194
190
|
iconOnly
|
|
195
191
|
variant='ghost'
|
|
196
192
|
label={t('toggle-expand.label', { ns: osTranslations })}
|
|
197
|
-
icon={
|
|
198
|
-
expandedId === column.view.dxn.toString()
|
|
199
|
-
? 'ph--caret-down--regular'
|
|
200
|
-
: 'ph--caret-right--regular'
|
|
201
|
-
}
|
|
193
|
+
icon={expandedId === column.view.uri ? 'ph--caret-down--regular' : 'ph--caret-right--regular'}
|
|
202
194
|
onClick={() => handleToggleField(column)}
|
|
203
195
|
/>
|
|
204
196
|
</div>
|
|
205
|
-
{expandedId === column.view.
|
|
206
|
-
<div
|
|
197
|
+
{expandedId === column.view.uri && column?.view.target && (
|
|
198
|
+
<div className='col-span-5 my-2 border border-separator rounded-md'>
|
|
207
199
|
<Form.Root
|
|
208
200
|
schema={ColumnFormSchema}
|
|
209
201
|
values={column}
|
|
@@ -217,10 +209,10 @@ export const PipelineProperties = ({ classNames, pipeline }: PipelinePropertiesP
|
|
|
217
209
|
ref={projectionRef}
|
|
218
210
|
mode='tag'
|
|
219
211
|
readonly
|
|
220
|
-
|
|
212
|
+
type={type}
|
|
221
213
|
view={column.view.target}
|
|
222
|
-
registry={
|
|
223
|
-
db={
|
|
214
|
+
registry={db?.graph.registry}
|
|
215
|
+
db={db}
|
|
224
216
|
tags={tags}
|
|
225
217
|
types={types}
|
|
226
218
|
onQueryChanged={handleQueryChanged}
|
|
@@ -234,7 +226,7 @@ export const PipelineProperties = ({ classNames, pipeline }: PipelinePropertiesP
|
|
|
234
226
|
)}
|
|
235
227
|
</List.Root>
|
|
236
228
|
|
|
237
|
-
<div
|
|
229
|
+
<div className='my-form-padding'>
|
|
238
230
|
<IconButton icon='ph--plus--regular' label={t('add-view.label')} onClick={handleAdd} classNames='w-full' />
|
|
239
231
|
</div>
|
|
240
232
|
</div>
|
package/src/containers/index.ts
CHANGED
|
@@ -4,5 +4,5 @@
|
|
|
4
4
|
|
|
5
5
|
import { type ComponentType, lazy } from 'react';
|
|
6
6
|
|
|
7
|
-
export const
|
|
7
|
+
export const PipelineArticle: ComponentType<any> = lazy(() => import('./PipelineArticle'));
|
|
8
8
|
export const PipelineProperties: ComponentType<any> = lazy(() => import('./PipelineProperties'));
|
|
@@ -8,7 +8,6 @@ import { useMemo } from 'react';
|
|
|
8
8
|
|
|
9
9
|
import { getQueryTarget } from '@dxos/app-toolkit/query';
|
|
10
10
|
import { Obj, Query } from '@dxos/echo';
|
|
11
|
-
import { AtomObj, AtomQuery } from '@dxos/echo-atom';
|
|
12
11
|
import { getSpace, isSpace } from '@dxos/react-client/echo';
|
|
13
12
|
import { type BoardModel } from '@dxos/react-ui-mosaic';
|
|
14
13
|
import { Pipeline } from '@dxos/types';
|
|
@@ -23,11 +22,11 @@ export const usePipelineBoardModel = (
|
|
|
23
22
|
}
|
|
24
23
|
|
|
25
24
|
const space = getSpace(pipeline);
|
|
26
|
-
const columnsAtom =
|
|
25
|
+
const columnsAtom = Obj.atomProperty(pipeline, 'columns');
|
|
27
26
|
const columnAtomFamily = Atom.family<string, Atom.Atom<Pipeline.Column | undefined>>((viewKey: string) =>
|
|
28
27
|
Atom.make((get) => {
|
|
29
28
|
const columns = get(columnsAtom);
|
|
30
|
-
return columns.find((c) => c.view.
|
|
29
|
+
return columns.find((c) => c.view.uri === viewKey);
|
|
31
30
|
}),
|
|
32
31
|
);
|
|
33
32
|
|
|
@@ -37,7 +36,7 @@ export const usePipelineBoardModel = (
|
|
|
37
36
|
if (column == null) {
|
|
38
37
|
return [];
|
|
39
38
|
}
|
|
40
|
-
const viewSnapshot = get(
|
|
39
|
+
const viewSnapshot = get(Obj.atom(column.view));
|
|
41
40
|
if (!viewSnapshot?.query?.ast) {
|
|
42
41
|
return [];
|
|
43
42
|
}
|
|
@@ -46,20 +45,20 @@ export const usePipelineBoardModel = (
|
|
|
46
45
|
if (!queryTarget) {
|
|
47
46
|
return [];
|
|
48
47
|
}
|
|
49
|
-
const raw = get(
|
|
48
|
+
const raw = get(queryTarget.query(query).atom);
|
|
50
49
|
return isSpace(queryTarget) ? raw : [...raw].reverse();
|
|
51
50
|
}),
|
|
52
51
|
);
|
|
53
52
|
|
|
54
53
|
return {
|
|
55
|
-
getColumnId: (data) => (data as Pipeline.Column).view.
|
|
54
|
+
getColumnId: (data) => (data as Pipeline.Column).view.uri,
|
|
56
55
|
getItemId: (data) => (data as Obj.Unknown).id,
|
|
57
56
|
isColumn: (obj: unknown): obj is Pipeline.Column => Schema.is(Pipeline.Column)(obj),
|
|
58
57
|
isItem: (obj: unknown): obj is Obj.Unknown => Obj.isObject(obj),
|
|
59
58
|
columns: columnsAtom,
|
|
60
|
-
items: (column) => itemsAtomFamily(column.view.
|
|
59
|
+
items: (column) => itemsAtomFamily(column.view.uri),
|
|
61
60
|
getColumns: () => [...registry.get(columnsAtom)],
|
|
62
|
-
getItems: (column) => registry.get(itemsAtomFamily(column.view.
|
|
61
|
+
getItems: (column) => registry.get(itemsAtomFamily(column.view.uri)) ?? [],
|
|
63
62
|
};
|
|
64
63
|
}, [pipeline, registry]);
|
|
65
64
|
|
|
@@ -68,7 +67,7 @@ const emptyColumnsAtom = Atom.make(() => [] as Pipeline.Column[]);
|
|
|
68
67
|
const emptyItemsAtom = Atom.make(() => [] as Obj.Unknown[]);
|
|
69
68
|
|
|
70
69
|
const emptyPipelineModel: BoardModel<Pipeline.Column, Obj.Unknown> = {
|
|
71
|
-
getColumnId: (data) => (data as Pipeline.Column).view.
|
|
70
|
+
getColumnId: (data) => (data as Pipeline.Column).view.uri,
|
|
72
71
|
getItemId: (data) => (data as Obj.Unknown).id,
|
|
73
72
|
isColumn: (obj: unknown): obj is Pipeline.Column => Schema.is(Pipeline.Column)(obj),
|
|
74
73
|
isItem: (obj): obj is Obj.Unknown => Obj.isObject(obj),
|
package/src/index.ts
CHANGED
package/src/meta.ts
CHANGED
|
@@ -2,18 +2,31 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import {
|
|
5
|
+
import { Plugin } from '@dxos/app-framework';
|
|
6
|
+
import { DXN } from '@dxos/keys';
|
|
6
7
|
import { trim } from '@dxos/util';
|
|
7
8
|
|
|
8
|
-
export const meta
|
|
9
|
-
|
|
9
|
+
export const meta = Plugin.makeMeta({
|
|
10
|
+
key: DXN.make('org.dxos.plugin.pipeline'),
|
|
10
11
|
name: 'Pipelines',
|
|
12
|
+
author: 'DXOS',
|
|
11
13
|
description: trim`
|
|
12
|
-
|
|
13
|
-
|
|
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.
|
|
14
26
|
`,
|
|
15
27
|
icon: 'ph--path--regular',
|
|
16
28
|
iconHue: 'purple',
|
|
17
29
|
source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-pipeline',
|
|
30
|
+
spec: 'PLUGIN.mdl',
|
|
18
31
|
tags: ['labs'],
|
|
19
|
-
};
|
|
32
|
+
});
|
package/src/plugin.ts
ADDED
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
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
|
|
6
|
+
import { Mailbox } from '@dxos/plugin-inbox';
|
|
7
|
+
import { Markdown } from '@dxos/plugin-markdown';
|
|
8
8
|
import { ViewModel } from '@dxos/schema';
|
|
9
9
|
import { Message, Organization, Person, Pipeline } from '@dxos/types';
|
|
10
10
|
|
package/src/translations.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { Type } from '@dxos/echo';
|
|
1
2
|
import { type Resource } from '@dxos/react-ui';
|
|
2
3
|
import { Pipeline } from '@dxos/types';
|
|
3
4
|
//
|
|
@@ -9,7 +10,7 @@ import { meta } from '#meta';
|
|
|
9
10
|
export const translations = [
|
|
10
11
|
{
|
|
11
12
|
'en-US': {
|
|
12
|
-
[Pipeline.Pipeline
|
|
13
|
+
[Type.getTypename(Pipeline.Pipeline)]: {
|
|
13
14
|
'typename.label': 'Pipeline',
|
|
14
15
|
'typename.label_zero': 'Pipelines',
|
|
15
16
|
'typename.label_one': 'Pipeline',
|