@dxos/plugin-kanban 0.8.4-main.dedc0f3 → 0.8.4-main.e8ec1fe
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-KHOAFPNN.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-UBRYXDKS.mjs → react-surface-X54TNDDN.mjs} +20 -16
- 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-MKO5HVES.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-B2FPS52G.mjs → react-surface-CVDMIHSC.mjs} +20 -16
- 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 -10
- 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 +25 -21
- package/src/components/KanbanContainer.tsx +6 -5
- 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-KHOAFPNN.mjs.map +0 -7
- package/dist/lib/browser/react-surface-UBRYXDKS.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-5B3LKGA7.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-MKO5HVES.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-B2FPS52G.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.e8ec1fe",
|
|
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/app-framework": "0.8.4-main.
|
|
44
|
-
"@dxos/
|
|
45
|
-
"@dxos/
|
|
46
|
-
"@dxos/
|
|
47
|
-
"@dxos/
|
|
48
|
-
"@dxos/
|
|
49
|
-
"@dxos/
|
|
50
|
-
"@dxos/
|
|
51
|
-
"@dxos/plugin-
|
|
52
|
-
"@dxos/plugin-search": "0.8.4-main.
|
|
53
|
-
"@dxos/plugin-
|
|
54
|
-
"@dxos/
|
|
55
|
-
"@dxos/
|
|
56
|
-
"@dxos/react-
|
|
57
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
58
|
-
"@dxos/react-ui-
|
|
59
|
-
"@dxos/
|
|
60
|
-
"@dxos/
|
|
61
|
-
"@dxos/
|
|
62
|
-
"@dxos/random": "0.8.4-main.
|
|
63
|
-
"@dxos/
|
|
39
|
+
"@preact/signals-core": "^1.12.1",
|
|
40
|
+
"effect": "3.18.3",
|
|
41
|
+
"@dxos/assistant": "0.8.4-main.e8ec1fe",
|
|
42
|
+
"@dxos/async": "0.8.4-main.e8ec1fe",
|
|
43
|
+
"@dxos/app-framework": "0.8.4-main.e8ec1fe",
|
|
44
|
+
"@dxos/blueprints": "0.8.4-main.e8ec1fe",
|
|
45
|
+
"@dxos/effect": "0.8.4-main.e8ec1fe",
|
|
46
|
+
"@dxos/echo": "0.8.4-main.e8ec1fe",
|
|
47
|
+
"@dxos/functions": "0.8.4-main.e8ec1fe",
|
|
48
|
+
"@dxos/invariant": "0.8.4-main.e8ec1fe",
|
|
49
|
+
"@dxos/log": "0.8.4-main.e8ec1fe",
|
|
50
|
+
"@dxos/plugin-client": "0.8.4-main.e8ec1fe",
|
|
51
|
+
"@dxos/plugin-graph": "0.8.4-main.e8ec1fe",
|
|
52
|
+
"@dxos/plugin-search": "0.8.4-main.e8ec1fe",
|
|
53
|
+
"@dxos/plugin-space": "0.8.4-main.e8ec1fe",
|
|
54
|
+
"@dxos/react-client": "0.8.4-main.e8ec1fe",
|
|
55
|
+
"@dxos/react-ui": "0.8.4-main.e8ec1fe",
|
|
56
|
+
"@dxos/react-ui-form": "0.8.4-main.e8ec1fe",
|
|
57
|
+
"@dxos/react-ui-kanban": "0.8.4-main.e8ec1fe",
|
|
58
|
+
"@dxos/react-ui-stack": "0.8.4-main.e8ec1fe",
|
|
59
|
+
"@dxos/schema": "0.8.4-main.e8ec1fe",
|
|
60
|
+
"@dxos/util": "0.8.4-main.e8ec1fe",
|
|
61
|
+
"@dxos/types": "0.8.4-main.e8ec1fe",
|
|
62
|
+
"@dxos/random": "0.8.4-main.e8ec1fe",
|
|
63
|
+
"@dxos/ai": "0.8.4-main.e8ec1fe"
|
|
64
64
|
},
|
|
65
65
|
"devDependencies": {
|
|
66
|
-
"@types/react": "~
|
|
67
|
-
"@types/react-dom": "~
|
|
68
|
-
"react": "~
|
|
69
|
-
"react-dom": "~
|
|
70
|
-
"vite": "7.1.
|
|
71
|
-
"@dxos/plugin-preview": "0.8.4-main.
|
|
72
|
-
"@dxos/
|
|
73
|
-
"@dxos/
|
|
74
|
-
"@dxos/
|
|
75
|
-
"@dxos/
|
|
76
|
-
"@dxos/
|
|
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-preview": "0.8.4-main.e8ec1fe",
|
|
72
|
+
"@dxos/react-ui-theme": "0.8.4-main.e8ec1fe",
|
|
73
|
+
"@dxos/test-utils": "0.8.4-main.e8ec1fe",
|
|
74
|
+
"@dxos/storybook-utils": "0.8.4-main.e8ec1fe",
|
|
75
|
+
"@dxos/react-ui-syntax-highlighter": "0.8.4-main.e8ec1fe",
|
|
76
|
+
"@dxos/plugin-theme": "0.8.4-main.e8ec1fe"
|
|
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.e8ec1fe",
|
|
83
|
+
"@dxos/react-ui-theme": "0.8.4-main.e8ec1fe"
|
|
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,
|
|
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(
|
|
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,
|
|
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,17 @@ 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 typename = view?.query ?
|
|
53
|
+
const typename = view?.query ? getTypenameFromQuery(view.query.ast) : undefined;
|
|
55
54
|
const schema = useSchema(client, space, typename);
|
|
56
55
|
|
|
57
56
|
useEffect(() => {
|
|
@@ -99,13 +98,13 @@ const StorybookKanban = () => {
|
|
|
99
98
|
const handleRemoveCard = useCallback((card: { id: string }) => space.db.remove(card), [space]);
|
|
100
99
|
|
|
101
100
|
const handleUpdateQuery = useCallback(
|
|
102
|
-
(
|
|
101
|
+
(newQuery: QueryAST.Query) => {
|
|
103
102
|
invariant(schema);
|
|
104
103
|
invariant(Type.isMutable(schema));
|
|
105
104
|
invariant(view);
|
|
106
105
|
|
|
107
|
-
schema.updateTypename(
|
|
108
|
-
view.query =
|
|
106
|
+
schema.updateTypename(getTypenameFromQuery(newQuery));
|
|
107
|
+
view.query.ast = newQuery;
|
|
109
108
|
},
|
|
110
109
|
[view, schema],
|
|
111
110
|
);
|
|
@@ -147,14 +146,12 @@ const meta = {
|
|
|
147
146
|
title: 'plugins/plugin-kanban/Kanban',
|
|
148
147
|
component: StorybookKanban,
|
|
149
148
|
render: () => <StorybookKanban />,
|
|
150
|
-
parameters: { translations },
|
|
151
149
|
decorators: [
|
|
152
|
-
|
|
150
|
+
withTheme,
|
|
153
151
|
withPluginManager({
|
|
154
152
|
plugins: [
|
|
155
|
-
ThemePlugin({ tx: defaultTx }),
|
|
156
153
|
ClientPlugin({
|
|
157
|
-
types: [
|
|
154
|
+
types: [Organization.Organization, Person.Person, View.View, Kanban.Kanban],
|
|
158
155
|
onClientInitialized: async ({ client }) => {
|
|
159
156
|
await client.halo.createIdentity();
|
|
160
157
|
const space = await client.spaces.create();
|
|
@@ -162,25 +159,32 @@ const meta = {
|
|
|
162
159
|
const { view } = await Kanban.makeView({
|
|
163
160
|
client,
|
|
164
161
|
space,
|
|
165
|
-
typename:
|
|
162
|
+
typename: Organization.Organization.typename,
|
|
166
163
|
pivotFieldName: 'status',
|
|
167
164
|
});
|
|
168
165
|
space.db.add(view);
|
|
169
166
|
|
|
170
167
|
// TODO(burdon): Replace with sdk/schema/testing.
|
|
171
168
|
Array.from({ length: 80 }).map(() => {
|
|
172
|
-
return space.db.add(Obj.make(
|
|
169
|
+
return space.db.add(Obj.make(Organization.Organization, rollOrg()));
|
|
173
170
|
});
|
|
174
171
|
},
|
|
175
172
|
}),
|
|
176
|
-
|
|
177
|
-
PreviewPlugin(),
|
|
178
|
-
SpacePlugin(),
|
|
173
|
+
SpacePlugin({}),
|
|
179
174
|
IntentPlugin(),
|
|
180
175
|
SettingsPlugin(),
|
|
176
|
+
|
|
177
|
+
// UI
|
|
178
|
+
ThemePlugin({ tx: defaultTx }),
|
|
179
|
+
PreviewPlugin(),
|
|
180
|
+
StorybookLayoutPlugin({}),
|
|
181
181
|
],
|
|
182
182
|
}),
|
|
183
183
|
],
|
|
184
|
+
parameters: {
|
|
185
|
+
layout: 'fullscreen',
|
|
186
|
+
translations,
|
|
187
|
+
},
|
|
184
188
|
} satisfies Meta<typeof StorybookKanban>;
|
|
185
189
|
|
|
186
190
|
export default meta;
|
|
@@ -4,25 +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();
|
|
25
|
-
const typename = view.query ?
|
|
26
|
+
const typename = view.query ? getTypenameFromQuery(view.query.ast) : undefined;
|
|
26
27
|
|
|
27
28
|
const jsonSchema = useMemo(() => {
|
|
28
29
|
if (!cardSchema) {
|
|
@@ -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 = view.query ?
|
|
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(
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../../../src/types/schema.ts", "../../../src/meta.ts"],
|
|
4
|
-
"sourcesContent": ["//\n// Copyright 2025 DXOS.org\n//\n\nimport { Schema } from 'effect';\n\nimport { SpaceSchema } from '@dxos/react-client/echo';\nimport { DataType, FieldSchema, TypenameAnnotationId } from '@dxos/schema';\n\nimport { KANBAN_PLUGIN } from '../meta';\n\n/**\n * Kanban data model.\n * A Kanban board is a collection of columns, each of which contains a collection of items.\n * The layout of columns and items is controlled by models.\n * The underlying data model may be represented by direct object relationships\n * (e.g., a column object containing an array of ordered items) or projections constructed\n * by the model (e.g., a query of items based on metadata within a column object).\n */\n\n// TODO(wittjosiah): Factor out?\nexport const PivotColumnAnnotationId = Symbol.for('@dxos/plugin-kanban/annotation/PivotColumn');\n\nexport const CreateKanbanSchema = Schema.Struct({\n name: Schema.optional(Schema.String),\n typename: Schema.optional(\n Schema.String.annotations({\n [TypenameAnnotationId]: ['used-static', 'dynamic'],\n title: 'Select card record type (leave empty to start fresh)',\n }),\n ),\n initialPivotColumn: Schema.optional(\n Schema.String.annotations({\n [PivotColumnAnnotationId]: true,\n title: 'Pivot column',\n }),\n ),\n});\n\nexport namespace KanbanAction {\n const KANBAN_ACTION = `${KANBAN_PLUGIN}/action`;\n\n export class Create extends Schema.TaggedClass<Create>()(`${KANBAN_ACTION}/create`, {\n input: Schema.extend(Schema.Struct({ space: SpaceSchema }), CreateKanbanSchema),\n output: Schema.Struct({\n object: DataType.View,\n }),\n }) {}\n\n export class DeleteCardField extends Schema.TaggedClass<DeleteCardField>()(`${KANBAN_ACTION}/delete-card-field`, {\n input: Schema.Struct({\n view: DataType.View,\n fieldId: Schema.String,\n // TODO(wittjosiah): Separate fields for undo data?\n deletionData: Schema.optional(\n Schema.Struct({\n field: FieldSchema,\n // TODO(wittjosiah): This creates a type error.\n // props: PropertySchema,\n props: Schema.Any,\n index: Schema.Number,\n }),\n ),\n }),\n output: Schema.Void,\n }) {}\n\n export class DeleteCard extends Schema.TaggedClass<DeleteCard>()(`${KANBAN_ACTION}/delete-card`, {\n input: Schema.Struct({\n card: Schema.Any, // The card object to delete\n }),\n output: Schema.Void,\n }) {}\n}\n", "//\n// Copyright 2023 DXOS.org\n//\n\nimport { type PluginMeta } from '@dxos/app-framework';\n\nexport const KANBAN_PLUGIN = 'dxos.org/plugin/kanban';\n\nexport const meta: PluginMeta = {\n id: KANBAN_PLUGIN,\n name: 'Kanban',\n description:\n 'Kanban allows you to explore Table data in sorted columns defined by your custom schema. You can use Kanbans to track progress or trigger custom automations when cards are moved from one state to another.',\n icon: 'ph--kanban--regular',\n source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-kanban',\n screenshots: ['https://dxos.network/plugin-details-kanban-dark.png'],\n};\n"],
|
|
5
|
-
"mappings": ";AAIA,SAASA,cAAc;AAEvB,SAASC,mBAAmB;AAC5B,SAASC,UAAUC,aAAaC,4BAA4B;;;ACDrD,IAAMC,gBAAgB;AAEtB,IAAMC,OAAmB;EAC9BC,IAAIF;EACJG,MAAM;EACNC,aACE;EACFC,MAAM;EACNC,QAAQ;EACRC,aAAa;IAAC;;AAChB;;;ADKO,IAAMC,0BAA0BC,OAAOC,IAAI,4CAAA;AAE3C,IAAMC,qBAAqBC,OAAOC,OAAO;EAC9CC,MAAMF,OAAOG,SAASH,OAAOI,MAAM;EACnCC,UAAUL,OAAOG,SACfH,OAAOI,OAAOE,YAAY;IACxB,CAACC,oBAAAA,GAAuB;MAAC;MAAe;;IACxCC,OAAO;EACT,CAAA,CAAA;EAEFC,oBAAoBT,OAAOG,SACzBH,OAAOI,OAAOE,YAAY;IACxB,CAACV,uBAAAA,GAA0B;IAC3BY,OAAO;EACT,CAAA,CAAA;AAEJ,CAAA;UAEiBE,eAAAA;AACf,QAAMC,gBAAgB,GAAGC,aAAAA;EAElB,MAAMC,eAAeb,OAAOc,YAAW,EAAW,GAAGH,aAAAA,WAAwB;IAClFI,OAAOf,OAAOgB,OAAOhB,OAAOC,OAAO;MAAEgB,OAAOC;IAAY,CAAA,GAAInB,kBAAAA;IAC5DoB,QAAQnB,OAAOC,OAAO;MACpBmB,QAAQC,SAASC;IACnB,CAAA;EACF,CAAA,EAAA;EAAI;gBALST,SAAAA;EAON,MAAMU,wBAAwBvB,OAAOc,YAAW,EAAoB,GAAGH,aAAAA,sBAAmC;IAC/GI,OAAOf,OAAOC,OAAO;MACnBuB,MAAMH,SAASC;MACfG,SAASzB,OAAOI;;MAEhBsB,cAAc1B,OAAOG,SACnBH,OAAOC,OAAO;QACZ0B,OAAOC;;;QAGPC,OAAO7B,OAAO8B;QACdC,OAAO/B,OAAOgC;MAChB,CAAA,CAAA;IAEJ,CAAA;IACAb,QAAQnB,OAAOiC;EACjB,CAAA,EAAA;EAAI;gBAhBSV,kBAAAA;EAkBN,MAAMW,mBAAmBlC,OAAOc,YAAW,EAAe,GAAGH,aAAAA,gBAA6B;IAC/FI,OAAOf,OAAOC,OAAO;MACnBkC,MAAMnC,OAAO8B;IACf,CAAA;IACAX,QAAQnB,OAAOiC;EACjB,CAAA,EAAA;EAAI;gBALSC,aAAAA;AAMf,GAlCiBxB,iBAAAA,eAAAA,CAAAA,EAAAA;;",
|
|
6
|
-
"names": ["Schema", "SpaceSchema", "DataType", "FieldSchema", "TypenameAnnotationId", "KANBAN_PLUGIN", "meta", "id", "name", "description", "icon", "source", "screenshots", "PivotColumnAnnotationId", "Symbol", "for", "CreateKanbanSchema", "Schema", "Struct", "name", "optional", "String", "typename", "annotations", "TypenameAnnotationId", "title", "initialPivotColumn", "KanbanAction", "KANBAN_ACTION", "KANBAN_PLUGIN", "Create", "TaggedClass", "input", "extend", "space", "SpaceSchema", "output", "object", "DataType", "View", "DeleteCardField", "view", "fieldId", "deletionData", "field", "FieldSchema", "props", "Any", "index", "Number", "Void", "DeleteCard", "card"]
|
|
7
|
-
}
|