@dxos/plugin-kanban 0.8.4-main.5ea62a8 → 0.8.4-main.72ec0f3
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/dist/lib/browser/{blueprint-definition-GFG7LX2C.mjs → blueprint-definition-UYVX622Q.mjs} +3 -3
- package/dist/lib/browser/{blueprint-definition-GFG7LX2C.mjs.map → blueprint-definition-UYVX622Q.mjs.map} +1 -1
- package/dist/lib/browser/{chunk-NCNNL74W.mjs → chunk-HO3LQ5T7.mjs} +14 -10
- package/dist/lib/browser/chunk-HO3LQ5T7.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +7 -8
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-2IYZ7TZE.mjs → intent-resolver-OPYUDNSU.mjs} +10 -10
- package/dist/lib/browser/intent-resolver-OPYUDNSU.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-XRHHQ4OI.mjs → react-surface-X54TNDDN.mjs} +21 -19
- package/dist/lib/browser/react-surface-X54TNDDN.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +1 -1
- package/dist/lib/node-esm/{blueprint-definition-MIMDXMUM.mjs → blueprint-definition-42P47FUY.mjs} +3 -3
- package/dist/lib/node-esm/{blueprint-definition-MIMDXMUM.mjs.map → blueprint-definition-42P47FUY.mjs.map} +1 -1
- package/dist/lib/node-esm/{chunk-5B3LKGA7.mjs → chunk-QZMZU5HM.mjs} +14 -10
- package/dist/lib/node-esm/chunk-QZMZU5HM.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +7 -8
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{intent-resolver-T7CEL6EN.mjs → intent-resolver-BDKNXV3R.mjs} +10 -10
- package/dist/lib/node-esm/intent-resolver-BDKNXV3R.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-BTB5JAKG.mjs → react-surface-CVDMIHSC.mjs} +21 -19
- package/dist/lib/node-esm/react-surface-CVDMIHSC.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +1 -1
- package/dist/types/src/KanbanPlugin.d.ts +1 -1
- package/dist/types/src/KanbanPlugin.d.ts.map +1 -1
- package/dist/types/src/capabilities/artifact-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/blueprint-definition.d.ts +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/components/KanbanContainer.d.ts +2 -2
- package/dist/types/src/components/KanbanContainer.d.ts.map +1 -1
- package/dist/types/src/components/KanbanContainer.stories.d.ts +2 -2
- package/dist/types/src/components/KanbanContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/KanbanViewEditor.d.ts +2 -2
- package/dist/types/src/components/KanbanViewEditor.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +0 -1
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +10 -43
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +41 -41
- package/src/KanbanPlugin.tsx +47 -47
- package/src/capabilities/artifact-definition.ts +9 -8
- package/src/capabilities/intent-resolver.ts +5 -5
- package/src/capabilities/react-surface.tsx +13 -8
- package/src/components/KanbanContainer.stories.tsx +29 -24
- package/src/components/KanbanContainer.tsx +7 -6
- package/src/components/KanbanViewEditor.tsx +7 -5
- package/src/meta.ts +7 -5
- package/src/types/schema.ts +7 -6
- package/dist/lib/browser/chunk-NCNNL74W.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-2IYZ7TZE.mjs.map +0 -7
- package/dist/lib/browser/react-surface-XRHHQ4OI.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-5B3LKGA7.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-T7CEL6EN.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-BTB5JAKG.mjs.map +0 -7
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/plugin-kanban",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.72ec0f3",
|
|
4
4
|
"description": "Kanban DXOS Surface plugin",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -36,51 +36,51 @@
|
|
|
36
36
|
],
|
|
37
37
|
"dependencies": {
|
|
38
38
|
"@preact-signals/safe-react": "^0.9.0",
|
|
39
|
-
"@preact/signals-core": "^1.
|
|
40
|
-
"effect": "3.
|
|
41
|
-
"@dxos/
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/
|
|
44
|
-
"@dxos/
|
|
45
|
-
"@dxos/
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/
|
|
49
|
-
"@dxos/
|
|
50
|
-
"@dxos/
|
|
51
|
-
"@dxos/
|
|
52
|
-
"@dxos/plugin-
|
|
53
|
-
"@dxos/plugin-
|
|
54
|
-
"@dxos/plugin-search": "0.8.4-main.
|
|
55
|
-
"@dxos/random": "0.8.4-main.
|
|
56
|
-
"@dxos/react-
|
|
57
|
-
"@dxos/react-ui
|
|
58
|
-
"@dxos/react-ui-
|
|
59
|
-
"@dxos/react-
|
|
60
|
-
"@dxos/react-ui-stack": "0.8.4-main.
|
|
61
|
-
"@dxos/schema": "0.8.4-main.
|
|
62
|
-
"@dxos/
|
|
63
|
-
"@dxos/util": "0.8.4-main.
|
|
39
|
+
"@preact/signals-core": "^1.12.1",
|
|
40
|
+
"effect": "3.18.3",
|
|
41
|
+
"@dxos/ai": "0.8.4-main.72ec0f3",
|
|
42
|
+
"@dxos/assistant": "0.8.4-main.72ec0f3",
|
|
43
|
+
"@dxos/app-framework": "0.8.4-main.72ec0f3",
|
|
44
|
+
"@dxos/echo": "0.8.4-main.72ec0f3",
|
|
45
|
+
"@dxos/async": "0.8.4-main.72ec0f3",
|
|
46
|
+
"@dxos/effect": "0.8.4-main.72ec0f3",
|
|
47
|
+
"@dxos/functions": "0.8.4-main.72ec0f3",
|
|
48
|
+
"@dxos/blueprints": "0.8.4-main.72ec0f3",
|
|
49
|
+
"@dxos/log": "0.8.4-main.72ec0f3",
|
|
50
|
+
"@dxos/plugin-client": "0.8.4-main.72ec0f3",
|
|
51
|
+
"@dxos/invariant": "0.8.4-main.72ec0f3",
|
|
52
|
+
"@dxos/plugin-space": "0.8.4-main.72ec0f3",
|
|
53
|
+
"@dxos/plugin-graph": "0.8.4-main.72ec0f3",
|
|
54
|
+
"@dxos/plugin-search": "0.8.4-main.72ec0f3",
|
|
55
|
+
"@dxos/random": "0.8.4-main.72ec0f3",
|
|
56
|
+
"@dxos/react-client": "0.8.4-main.72ec0f3",
|
|
57
|
+
"@dxos/react-ui": "0.8.4-main.72ec0f3",
|
|
58
|
+
"@dxos/react-ui-form": "0.8.4-main.72ec0f3",
|
|
59
|
+
"@dxos/react-ui-kanban": "0.8.4-main.72ec0f3",
|
|
60
|
+
"@dxos/react-ui-stack": "0.8.4-main.72ec0f3",
|
|
61
|
+
"@dxos/schema": "0.8.4-main.72ec0f3",
|
|
62
|
+
"@dxos/types": "0.8.4-main.72ec0f3",
|
|
63
|
+
"@dxos/util": "0.8.4-main.72ec0f3"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@types/react": "~
|
|
67
|
-
"@types/react-dom": "~
|
|
68
|
-
"react": "~
|
|
69
|
-
"react-dom": "~
|
|
70
|
-
"vite": "7.1.
|
|
71
|
-
"@dxos/plugin-theme": "0.8.4-main.
|
|
72
|
-
"@dxos/plugin-preview": "0.8.4-main.
|
|
73
|
-
"@dxos/react-ui-
|
|
74
|
-
"@dxos/react-ui-
|
|
75
|
-
"@dxos/storybook-utils": "0.8.4-main.
|
|
76
|
-
"@dxos/test-utils": "0.8.4-main.
|
|
66
|
+
"@types/react": "~19.2.2",
|
|
67
|
+
"@types/react-dom": "~19.2.2",
|
|
68
|
+
"react": "~19.2.0",
|
|
69
|
+
"react-dom": "~19.2.0",
|
|
70
|
+
"vite": "7.1.9",
|
|
71
|
+
"@dxos/plugin-theme": "0.8.4-main.72ec0f3",
|
|
72
|
+
"@dxos/plugin-preview": "0.8.4-main.72ec0f3",
|
|
73
|
+
"@dxos/react-ui-theme": "0.8.4-main.72ec0f3",
|
|
74
|
+
"@dxos/react-ui-syntax-highlighter": "0.8.4-main.72ec0f3",
|
|
75
|
+
"@dxos/storybook-utils": "0.8.4-main.72ec0f3",
|
|
76
|
+
"@dxos/test-utils": "0.8.4-main.72ec0f3"
|
|
77
77
|
},
|
|
78
78
|
"peerDependencies": {
|
|
79
79
|
"effect": "^3.13.3",
|
|
80
|
-
"react": "
|
|
81
|
-
"react-dom": "
|
|
82
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
83
|
-
"@dxos/react-ui-theme": "0.8.4-main.
|
|
80
|
+
"react": "^19.0.0",
|
|
81
|
+
"react-dom": "^19.0.0",
|
|
82
|
+
"@dxos/react-ui": "0.8.4-main.72ec0f3",
|
|
83
|
+
"@dxos/react-ui-theme": "0.8.4-main.72ec0f3"
|
|
84
84
|
},
|
|
85
85
|
"publishConfig": {
|
|
86
86
|
"access": "public"
|
package/src/KanbanPlugin.tsx
CHANGED
|
@@ -14,51 +14,51 @@ import { meta } from './meta';
|
|
|
14
14
|
import { translations } from './translations';
|
|
15
15
|
import { CreateKanbanSchema, KanbanAction } from './types';
|
|
16
16
|
|
|
17
|
-
export const KanbanPlugin = () =>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
17
|
+
export const KanbanPlugin = definePlugin(meta, () => [
|
|
18
|
+
defineModule({
|
|
19
|
+
id: `${meta.id}/module/translations`,
|
|
20
|
+
activatesOn: Events.SetupTranslations,
|
|
21
|
+
activate: () => contributes(Capabilities.Translations, [...translations, ...kanbanTranslations]),
|
|
22
|
+
}),
|
|
23
|
+
defineModule({
|
|
24
|
+
id: `${meta.id}/module/metadata`,
|
|
25
|
+
activatesOn: Events.SetupMetadata,
|
|
26
|
+
activate: () =>
|
|
27
|
+
contributes(Capabilities.Metadata, {
|
|
28
|
+
id: Kanban.Kanban.typename,
|
|
29
|
+
metadata: {
|
|
30
|
+
icon: 'ph--kanban--regular',
|
|
31
|
+
iconHue: 'green',
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
}),
|
|
35
|
+
defineModule({
|
|
36
|
+
id: `${meta.id}/module/object-form`,
|
|
37
|
+
activatesOn: ClientEvents.SetupSchema,
|
|
38
|
+
activate: () =>
|
|
39
|
+
contributes(
|
|
40
|
+
SpaceCapabilities.ObjectForm,
|
|
41
|
+
defineObjectForm({
|
|
42
|
+
objectSchema: Kanban.Kanban,
|
|
43
|
+
formSchema: CreateKanbanSchema,
|
|
44
|
+
hidden: true,
|
|
45
|
+
getIntent: (props, options) => createIntent(KanbanAction.Create, { ...props, space: options.space }),
|
|
33
46
|
}),
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
activate: ReactSurface,
|
|
53
|
-
}),
|
|
54
|
-
defineModule({
|
|
55
|
-
id: `${meta.id}/module/intent-resolver`,
|
|
56
|
-
activatesOn: Events.SetupIntentResolver,
|
|
57
|
-
activate: IntentResolver,
|
|
58
|
-
}),
|
|
59
|
-
defineModule({
|
|
60
|
-
id: `${meta.id}/module/blueprint`,
|
|
61
|
-
activatesOn: Events.SetupArtifactDefinition,
|
|
62
|
-
activate: BlueprintDefinition,
|
|
63
|
-
}),
|
|
64
|
-
]);
|
|
47
|
+
),
|
|
48
|
+
}),
|
|
49
|
+
defineModule({
|
|
50
|
+
id: `${meta.id}/module/react-surface`,
|
|
51
|
+
activatesOn: Events.SetupReactSurface,
|
|
52
|
+
activate: ReactSurface,
|
|
53
|
+
}),
|
|
54
|
+
defineModule({
|
|
55
|
+
id: `${meta.id}/module/intent-resolver`,
|
|
56
|
+
activatesOn: Events.SetupIntentResolver,
|
|
57
|
+
activate: IntentResolver,
|
|
58
|
+
}),
|
|
59
|
+
defineModule({
|
|
60
|
+
id: `${meta.id}/module/blueprint`,
|
|
61
|
+
activatesOn: Events.SetupArtifactDefinition,
|
|
62
|
+
activate: BlueprintDefinition,
|
|
63
|
+
}),
|
|
64
|
+
]);
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
// ISSUE(burdon): defineArtifact
|
|
6
6
|
// @ts-nocheck
|
|
7
7
|
|
|
8
|
-
import
|
|
8
|
+
import * as Function from 'effect/Function';
|
|
9
|
+
import * as Schema from 'effect/Schema';
|
|
9
10
|
|
|
10
11
|
import { ToolResult, createTool } from '@dxos/ai';
|
|
11
12
|
import { Capabilities, type PromiseIntentDispatcher, chain, contributes, createIntent } from '@dxos/app-framework';
|
|
@@ -14,9 +15,9 @@ import { defineArtifact } from '@dxos/blueprints';
|
|
|
14
15
|
import { Obj, Query } from '@dxos/echo';
|
|
15
16
|
import { invariant } from '@dxos/invariant';
|
|
16
17
|
import { SpaceAction } from '@dxos/plugin-space/types';
|
|
17
|
-
import { Filter, type Space
|
|
18
|
+
import { Filter, type Space } from '@dxos/react-client/echo';
|
|
18
19
|
import { KanbanView } from '@dxos/react-ui-kanban';
|
|
19
|
-
import {
|
|
20
|
+
import { View } from '@dxos/schema';
|
|
20
21
|
import { isNonNullable } from '@dxos/util';
|
|
21
22
|
|
|
22
23
|
import { meta } from '../meta';
|
|
@@ -68,7 +69,7 @@ export default () => {
|
|
|
68
69
|
return ToolResult.Error(`Schema not found: ${typename}`);
|
|
69
70
|
}
|
|
70
71
|
|
|
71
|
-
const intent = pipe(
|
|
72
|
+
const intent = Function.pipe(
|
|
72
73
|
createIntent(KanbanAction.Create, {
|
|
73
74
|
space: extensions.space,
|
|
74
75
|
typename,
|
|
@@ -93,7 +94,7 @@ export default () => {
|
|
|
93
94
|
execute: async (_input, { extensions }) => {
|
|
94
95
|
invariant(extensions?.space, 'No space');
|
|
95
96
|
const space = extensions.space;
|
|
96
|
-
const { objects } = await space.db.query(Filter.type(
|
|
97
|
+
const { objects } = await space.db.query(Filter.type(View.View)).run();
|
|
97
98
|
|
|
98
99
|
const boardInfo = await Promise.all(
|
|
99
100
|
objects.map(async (view) => {
|
|
@@ -103,7 +104,7 @@ export default () => {
|
|
|
103
104
|
}
|
|
104
105
|
|
|
105
106
|
return {
|
|
106
|
-
id:
|
|
107
|
+
id: Obj.getDXN(view).toString(),
|
|
107
108
|
name: view.name ?? 'Unnamed Kanban',
|
|
108
109
|
typename: view.query.typename,
|
|
109
110
|
};
|
|
@@ -123,8 +124,8 @@ export default () => {
|
|
|
123
124
|
const space = extensions.space;
|
|
124
125
|
const view = (await space.db
|
|
125
126
|
// TODO(wittjosiah): Filter.and should aggregate type
|
|
126
|
-
.query(Query.select(Filter.and(Filter.type(
|
|
127
|
-
.first()) as
|
|
127
|
+
.query(Query.select(Filter.and(Filter.type(View.View), Filter.ids(id))))
|
|
128
|
+
.first()) as View.View;
|
|
128
129
|
|
|
129
130
|
const kanban = await view.presentation.load();
|
|
130
131
|
invariant(Obj.instanceOf(KanbanView, kanban));
|
|
@@ -7,9 +7,9 @@ import { invariant } from '@dxos/invariant';
|
|
|
7
7
|
import { ClientCapabilities } from '@dxos/plugin-client';
|
|
8
8
|
import { getSpace } from '@dxos/react-client/echo';
|
|
9
9
|
import { Kanban } from '@dxos/react-ui-kanban/types';
|
|
10
|
-
import { ProjectionModel } from '@dxos/schema';
|
|
10
|
+
import { ProjectionModel, getTypenameFromQuery } from '@dxos/schema';
|
|
11
11
|
|
|
12
|
-
import {
|
|
12
|
+
import { meta } from '../meta';
|
|
13
13
|
import { KanbanAction } from '../types';
|
|
14
14
|
|
|
15
15
|
export default (context: PluginContext) =>
|
|
@@ -31,7 +31,7 @@ export default (context: PluginContext) =>
|
|
|
31
31
|
createResolver({
|
|
32
32
|
intent: KanbanAction.DeleteCardField,
|
|
33
33
|
resolve: async ({ view, fieldId, deletionData }, undo) => {
|
|
34
|
-
const schema = getSpace(view)?.db.schemaRegistry.getSchema(view.query.
|
|
34
|
+
const schema = getSpace(view)?.db.schemaRegistry.getSchema(getTypenameFromQuery(view.query.ast)!);
|
|
35
35
|
invariant(schema);
|
|
36
36
|
const projection = new ProjectionModel(schema.jsonSchema, view.projection);
|
|
37
37
|
|
|
@@ -39,7 +39,7 @@ export default (context: PluginContext) =>
|
|
|
39
39
|
const { deleted, index } = projection.deleteFieldProjection(fieldId);
|
|
40
40
|
return {
|
|
41
41
|
undoable: {
|
|
42
|
-
message: ['card field deleted label', { ns:
|
|
42
|
+
message: ['card field deleted label', { ns: meta.id }],
|
|
43
43
|
data: { deletionData: { ...deleted, index } },
|
|
44
44
|
},
|
|
45
45
|
};
|
|
@@ -59,7 +59,7 @@ export default (context: PluginContext) =>
|
|
|
59
59
|
space.db.remove(card);
|
|
60
60
|
return {
|
|
61
61
|
undoable: {
|
|
62
|
-
message: ['card deleted label', { ns:
|
|
62
|
+
message: ['card deleted label', { ns: meta.id }],
|
|
63
63
|
data: { card },
|
|
64
64
|
},
|
|
65
65
|
};
|
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import type * as Schema from 'effect/Schema';
|
|
6
6
|
import React, { useMemo } from 'react';
|
|
7
7
|
|
|
8
|
-
import { Capabilities, contributes, createSurface
|
|
8
|
+
import { Capabilities, contributes, createSurface } from '@dxos/app-framework';
|
|
9
|
+
import { useCapabilities } from '@dxos/app-framework/react';
|
|
9
10
|
import { Obj, Type } from '@dxos/echo';
|
|
10
11
|
import { findAnnotation } from '@dxos/effect';
|
|
11
12
|
import { ClientCapabilities } from '@dxos/plugin-client';
|
|
12
13
|
import { type Space, getSpace, isSpace } from '@dxos/react-client/echo';
|
|
13
14
|
import { type InputProps, SelectInput, useFormValues } from '@dxos/react-ui-form';
|
|
14
15
|
import { Kanban } from '@dxos/react-ui-kanban/types';
|
|
15
|
-
import {
|
|
16
|
+
import { type Collection, View } from '@dxos/schema';
|
|
16
17
|
|
|
17
18
|
import { KanbanContainer, KanbanViewEditor } from '../components';
|
|
18
19
|
import { meta } from '../meta';
|
|
@@ -23,16 +24,16 @@ export default () =>
|
|
|
23
24
|
createSurface({
|
|
24
25
|
id: meta.id,
|
|
25
26
|
role: ['article', 'section'],
|
|
26
|
-
filter: (data): data is { subject:
|
|
27
|
-
Obj.instanceOf(
|
|
27
|
+
filter: (data): data is { subject: View.View } =>
|
|
28
|
+
Obj.instanceOf(View.View, data.subject) && Obj.instanceOf(Kanban.Kanban, data.subject.presentation.target),
|
|
28
29
|
component: ({ data, role }) => <KanbanContainer view={data.subject} role={role} />,
|
|
29
30
|
}),
|
|
30
31
|
createSurface({
|
|
31
32
|
id: `${meta.id}/object-settings`,
|
|
32
33
|
role: 'object-settings',
|
|
33
34
|
position: 'hoist',
|
|
34
|
-
filter: (data): data is { subject:
|
|
35
|
-
Obj.instanceOf(
|
|
35
|
+
filter: (data): data is { subject: View.View } =>
|
|
36
|
+
Obj.instanceOf(View.View, data.subject) && Obj.instanceOf(Kanban.Kanban, data.subject.presentation.target),
|
|
36
37
|
component: ({ data }) => <KanbanViewEditor view={data.subject} />,
|
|
37
38
|
}),
|
|
38
39
|
createSurface({
|
|
@@ -40,7 +41,11 @@ export default () =>
|
|
|
40
41
|
role: 'form-input',
|
|
41
42
|
filter: (
|
|
42
43
|
data,
|
|
43
|
-
): data is {
|
|
44
|
+
): data is {
|
|
45
|
+
prop: string;
|
|
46
|
+
schema: Schema.Schema<any>;
|
|
47
|
+
target: Space | Collection.Collection | undefined;
|
|
48
|
+
} => {
|
|
44
49
|
const annotation = findAnnotation<boolean>((data.schema as Schema.Schema.All).ast, PivotColumnAnnotationId);
|
|
45
50
|
return !!annotation;
|
|
46
51
|
},
|
|
@@ -2,14 +2,12 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
6
|
import React, { useCallback, useEffect, useState } from 'react';
|
|
9
7
|
|
|
10
8
|
import { IntentPlugin, SettingsPlugin } from '@dxos/app-framework';
|
|
11
9
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
12
|
-
import { Obj, Type } from '@dxos/echo';
|
|
10
|
+
import { Obj, type QueryAST, Type } from '@dxos/echo';
|
|
13
11
|
import { invariant } from '@dxos/invariant';
|
|
14
12
|
import { ClientPlugin } from '@dxos/plugin-client';
|
|
15
13
|
import { PreviewPlugin } from '@dxos/plugin-preview';
|
|
@@ -20,13 +18,14 @@ import { ThemePlugin } from '@dxos/plugin-theme';
|
|
|
20
18
|
import { faker } from '@dxos/random';
|
|
21
19
|
import { useClient } from '@dxos/react-client';
|
|
22
20
|
import { Filter, useQuery, useSchema, useSpaces } from '@dxos/react-client/echo';
|
|
21
|
+
import { withTheme } from '@dxos/react-ui/testing';
|
|
23
22
|
import { ViewEditor } from '@dxos/react-ui-form';
|
|
24
23
|
import { Kanban as KanbanComponent, useKanbanModel } from '@dxos/react-ui-kanban';
|
|
25
24
|
import { Kanban } from '@dxos/react-ui-kanban/types';
|
|
26
25
|
import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
|
|
27
26
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
28
|
-
import {
|
|
29
|
-
import {
|
|
27
|
+
import { ProjectionModel, View, getTypenameFromQuery } from '@dxos/schema';
|
|
28
|
+
import { Organization, Person } from '@dxos/types';
|
|
30
29
|
|
|
31
30
|
import { translations } from '../translations';
|
|
32
31
|
|
|
@@ -41,17 +40,18 @@ const rollOrg = () => ({
|
|
|
41
40
|
description: faker.lorem.paragraph(),
|
|
42
41
|
image: faker.image.url(),
|
|
43
42
|
website: faker.internet.url(),
|
|
44
|
-
status: faker.helpers.arrayElement(
|
|
43
|
+
status: faker.helpers.arrayElement(Organization.StatusOptions).id as Organization.Organization['status'],
|
|
45
44
|
});
|
|
46
45
|
|
|
47
46
|
const StorybookKanban = () => {
|
|
48
47
|
const client = useClient();
|
|
49
48
|
const spaces = useSpaces();
|
|
50
49
|
const space = spaces[spaces.length - 1];
|
|
51
|
-
const views = useQuery(space, Filter.type(
|
|
52
|
-
const [view, setView] = useState<
|
|
50
|
+
const views = useQuery(space, Filter.type(View.View));
|
|
51
|
+
const [view, setView] = useState<View.View>();
|
|
53
52
|
const [projection, setProjection] = useState<ProjectionModel>();
|
|
54
|
-
const
|
|
53
|
+
const typename = view?.query ? getTypenameFromQuery(view.query.ast) : undefined;
|
|
54
|
+
const schema = useSchema(client, space, typename);
|
|
55
55
|
|
|
56
56
|
useEffect(() => {
|
|
57
57
|
if (views.length && !view) {
|
|
@@ -97,14 +97,14 @@ const StorybookKanban = () => {
|
|
|
97
97
|
|
|
98
98
|
const handleRemoveCard = useCallback((card: { id: string }) => space.db.remove(card), [space]);
|
|
99
99
|
|
|
100
|
-
const
|
|
101
|
-
(
|
|
100
|
+
const handleUpdateQuery = useCallback(
|
|
101
|
+
(newQuery: QueryAST.Query) => {
|
|
102
102
|
invariant(schema);
|
|
103
103
|
invariant(Type.isMutable(schema));
|
|
104
104
|
invariant(view);
|
|
105
105
|
|
|
106
|
-
schema.updateTypename(
|
|
107
|
-
view.query.
|
|
106
|
+
schema.updateTypename(getTypenameFromQuery(newQuery));
|
|
107
|
+
view.query.ast = newQuery;
|
|
108
108
|
},
|
|
109
109
|
[view, schema],
|
|
110
110
|
);
|
|
@@ -121,12 +121,12 @@ const StorybookKanban = () => {
|
|
|
121
121
|
registry={space?.db.schemaRegistry}
|
|
122
122
|
schema={schema}
|
|
123
123
|
view={view}
|
|
124
|
-
|
|
124
|
+
onQueryChanged={handleUpdateQuery}
|
|
125
125
|
onDelete={(fieldId: string) => {
|
|
126
126
|
console.log('[ViewEditor]', 'onDelete', fieldId);
|
|
127
127
|
}}
|
|
128
128
|
/>
|
|
129
|
-
<SyntaxHighlighter language='json' className='
|
|
129
|
+
<SyntaxHighlighter language='json' className='text-xs'>
|
|
130
130
|
{JSON.stringify({ view, schema }, null, 2)}
|
|
131
131
|
</SyntaxHighlighter>
|
|
132
132
|
</div>
|
|
@@ -146,14 +146,12 @@ const meta = {
|
|
|
146
146
|
title: 'plugins/plugin-kanban/Kanban',
|
|
147
147
|
component: StorybookKanban,
|
|
148
148
|
render: () => <StorybookKanban />,
|
|
149
|
-
parameters: { translations },
|
|
150
149
|
decorators: [
|
|
151
|
-
|
|
150
|
+
withTheme,
|
|
152
151
|
withPluginManager({
|
|
153
152
|
plugins: [
|
|
154
|
-
ThemePlugin({ tx: defaultTx }),
|
|
155
153
|
ClientPlugin({
|
|
156
|
-
types: [
|
|
154
|
+
types: [Organization.Organization, Person.Person, View.View, Kanban.Kanban],
|
|
157
155
|
onClientInitialized: async ({ client }) => {
|
|
158
156
|
await client.halo.createIdentity();
|
|
159
157
|
const space = await client.spaces.create();
|
|
@@ -161,25 +159,32 @@ const meta = {
|
|
|
161
159
|
const { view } = await Kanban.makeView({
|
|
162
160
|
client,
|
|
163
161
|
space,
|
|
164
|
-
typename:
|
|
162
|
+
typename: Organization.Organization.typename,
|
|
165
163
|
pivotFieldName: 'status',
|
|
166
164
|
});
|
|
167
165
|
space.db.add(view);
|
|
168
166
|
|
|
169
167
|
// TODO(burdon): Replace with sdk/schema/testing.
|
|
170
168
|
Array.from({ length: 80 }).map(() => {
|
|
171
|
-
return space.db.add(Obj.make(
|
|
169
|
+
return space.db.add(Obj.make(Organization.Organization, rollOrg()));
|
|
172
170
|
});
|
|
173
171
|
},
|
|
174
172
|
}),
|
|
175
|
-
|
|
176
|
-
PreviewPlugin(),
|
|
177
|
-
SpacePlugin(),
|
|
173
|
+
SpacePlugin({}),
|
|
178
174
|
IntentPlugin(),
|
|
179
175
|
SettingsPlugin(),
|
|
176
|
+
|
|
177
|
+
// UI
|
|
178
|
+
ThemePlugin({ tx: defaultTx }),
|
|
179
|
+
PreviewPlugin(),
|
|
180
|
+
StorybookLayoutPlugin({}),
|
|
180
181
|
],
|
|
181
182
|
}),
|
|
182
183
|
],
|
|
184
|
+
parameters: {
|
|
185
|
+
layout: 'fullscreen',
|
|
186
|
+
translations,
|
|
187
|
+
},
|
|
183
188
|
} satisfies Meta<typeof StorybookKanban>;
|
|
184
189
|
|
|
185
190
|
export default meta;
|
|
@@ -4,24 +4,26 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
6
6
|
|
|
7
|
-
import { createIntent
|
|
7
|
+
import { createIntent } from '@dxos/app-framework';
|
|
8
|
+
import { useIntentDispatcher } from '@dxos/app-framework/react';
|
|
8
9
|
import { Filter, Obj, Type } from '@dxos/echo';
|
|
9
|
-
import { EchoSchema, type TypedObject } from '@dxos/echo
|
|
10
|
+
import { EchoSchema, type TypedObject } from '@dxos/echo/internal';
|
|
10
11
|
import { useGlobalFilteredObjects } from '@dxos/plugin-search';
|
|
11
12
|
import { useClient } from '@dxos/react-client';
|
|
12
13
|
import { getSpace, useQuery } from '@dxos/react-client/echo';
|
|
13
14
|
import { Kanban, useKanbanModel } from '@dxos/react-ui-kanban';
|
|
14
15
|
import { StackItem } from '@dxos/react-ui-stack';
|
|
15
|
-
import { type
|
|
16
|
+
import { ProjectionModel, type View, getTypenameFromQuery } from '@dxos/schema';
|
|
16
17
|
|
|
17
18
|
import { KanbanAction } from '../types';
|
|
18
19
|
|
|
19
|
-
export const KanbanContainer = ({ view }: { view:
|
|
20
|
+
export const KanbanContainer = ({ view }: { view: View.View; role: string }) => {
|
|
20
21
|
const client = useClient();
|
|
21
22
|
const [cardSchema, setCardSchema] = useState<TypedObject<any, any>>();
|
|
22
23
|
const [projection, setProjection] = useState<ProjectionModel>();
|
|
23
24
|
const space = getSpace(view);
|
|
24
25
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
26
|
+
const typename = view.query ? getTypenameFromQuery(view.query.ast) : undefined;
|
|
25
27
|
|
|
26
28
|
const jsonSchema = useMemo(() => {
|
|
27
29
|
if (!cardSchema) {
|
|
@@ -31,7 +33,6 @@ export const KanbanContainer = ({ view }: { view: DataType.View; role: string })
|
|
|
31
33
|
}, [cardSchema]);
|
|
32
34
|
|
|
33
35
|
useEffect(() => {
|
|
34
|
-
const typename = view.query.typename;
|
|
35
36
|
const staticSchema = client.graph.schemaRegistry.schemas.find((schema) => Type.getTypename(schema) === typename);
|
|
36
37
|
if (staticSchema) {
|
|
37
38
|
setCardSchema(() => staticSchema as TypedObject<any, any>);
|
|
@@ -49,7 +50,7 @@ export const KanbanContainer = ({ view }: { view: DataType.View; role: string })
|
|
|
49
50
|
);
|
|
50
51
|
return unsubscribe;
|
|
51
52
|
}
|
|
52
|
-
}, [
|
|
53
|
+
}, [typename, space]);
|
|
53
54
|
|
|
54
55
|
useEffect(() => {
|
|
55
56
|
if (jsonSchema) {
|
|
@@ -5,25 +5,27 @@
|
|
|
5
5
|
import React, { useCallback, useMemo } from 'react';
|
|
6
6
|
|
|
7
7
|
import { Type } from '@dxos/echo';
|
|
8
|
-
import { EchoSchema, FormatEnum } from '@dxos/echo
|
|
8
|
+
import { EchoSchema, FormatEnum } from '@dxos/echo/internal';
|
|
9
9
|
import { useClient } from '@dxos/react-client';
|
|
10
10
|
import { getSpace, useSchema } from '@dxos/react-client/echo';
|
|
11
11
|
import { type CustomInputMap, Form, SelectInput } from '@dxos/react-ui-form';
|
|
12
12
|
import { Kanban } from '@dxos/react-ui-kanban/types';
|
|
13
|
-
import { type
|
|
13
|
+
import { ProjectionModel, type View, getTypenameFromQuery } from '@dxos/schema';
|
|
14
14
|
|
|
15
|
-
type KanbanViewEditorProps = { view:
|
|
15
|
+
type KanbanViewEditorProps = { view: View.View };
|
|
16
16
|
|
|
17
17
|
export const KanbanViewEditor = ({ view }: KanbanViewEditorProps) => {
|
|
18
18
|
const client = useClient();
|
|
19
19
|
const space = getSpace(view);
|
|
20
|
-
const currentTypename =
|
|
20
|
+
const currentTypename = view.query ? getTypenameFromQuery(view.query.ast) : undefined;
|
|
21
21
|
const schema = useSchema(client, space, currentTypename);
|
|
22
22
|
|
|
23
23
|
const projection = useMemo(() => {
|
|
24
24
|
if (schema) {
|
|
25
25
|
const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : Type.toJsonSchema(schema);
|
|
26
|
-
|
|
26
|
+
const projection = new ProjectionModel(jsonSchema, view.projection);
|
|
27
|
+
projection.normalizeView();
|
|
28
|
+
return projection;
|
|
27
29
|
}
|
|
28
30
|
}, [view.projection, JSON.stringify(schema)]);
|
|
29
31
|
|
package/src/meta.ts
CHANGED
|
@@ -3,15 +3,17 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type PluginMeta } from '@dxos/app-framework';
|
|
6
|
-
|
|
7
|
-
export const KANBAN_PLUGIN = 'dxos.org/plugin/kanban';
|
|
6
|
+
import { trim } from '@dxos/util';
|
|
8
7
|
|
|
9
8
|
export const meta: PluginMeta = {
|
|
10
|
-
id:
|
|
9
|
+
id: 'dxos.org/plugin/kanban',
|
|
11
10
|
name: 'Kanban',
|
|
12
|
-
description:
|
|
13
|
-
|
|
11
|
+
description: trim`
|
|
12
|
+
Visual project management using customizable kanban boards to track workflow progress.
|
|
13
|
+
Organize table data into columns, drag and drop items between stages, and trigger automations based on status changes.
|
|
14
|
+
`,
|
|
14
15
|
icon: 'ph--kanban--regular',
|
|
16
|
+
iconHue: 'green',
|
|
15
17
|
source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-kanban',
|
|
16
18
|
screenshots: ['https://dxos.network/plugin-details-kanban-dark.png'],
|
|
17
19
|
};
|
package/src/types/schema.ts
CHANGED
|
@@ -2,12 +2,12 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import
|
|
5
|
+
import * as Schema from 'effect/Schema';
|
|
6
6
|
|
|
7
7
|
import { SpaceSchema } from '@dxos/react-client/echo';
|
|
8
|
-
import {
|
|
8
|
+
import { FieldSchema, TypenameAnnotationId, View } from '@dxos/schema';
|
|
9
9
|
|
|
10
|
-
import {
|
|
10
|
+
import { meta } from '../meta';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Kanban data model.
|
|
@@ -23,6 +23,7 @@ export const PivotColumnAnnotationId = Symbol.for('@dxos/plugin-kanban/annotatio
|
|
|
23
23
|
|
|
24
24
|
export const CreateKanbanSchema = Schema.Struct({
|
|
25
25
|
name: Schema.optional(Schema.String),
|
|
26
|
+
// TODO(wittjosiah): This should be a query input instead.
|
|
26
27
|
typename: Schema.optional(
|
|
27
28
|
Schema.String.annotations({
|
|
28
29
|
[TypenameAnnotationId]: ['used-static', 'dynamic'],
|
|
@@ -38,18 +39,18 @@ export const CreateKanbanSchema = Schema.Struct({
|
|
|
38
39
|
});
|
|
39
40
|
|
|
40
41
|
export namespace KanbanAction {
|
|
41
|
-
const KANBAN_ACTION = `${
|
|
42
|
+
const KANBAN_ACTION = `${meta.id}/action`;
|
|
42
43
|
|
|
43
44
|
export class Create extends Schema.TaggedClass<Create>()(`${KANBAN_ACTION}/create`, {
|
|
44
45
|
input: Schema.extend(Schema.Struct({ space: SpaceSchema }), CreateKanbanSchema),
|
|
45
46
|
output: Schema.Struct({
|
|
46
|
-
object:
|
|
47
|
+
object: View.View,
|
|
47
48
|
}),
|
|
48
49
|
}) {}
|
|
49
50
|
|
|
50
51
|
export class DeleteCardField extends Schema.TaggedClass<DeleteCardField>()(`${KANBAN_ACTION}/delete-card-field`, {
|
|
51
52
|
input: Schema.Struct({
|
|
52
|
-
view:
|
|
53
|
+
view: View.View,
|
|
53
54
|
fieldId: Schema.String,
|
|
54
55
|
// TODO(wittjosiah): Separate fields for undo data?
|
|
55
56
|
deletionData: Schema.optional(
|