@dxos/plugin-kanban 0.8.4-main.5ad4a44 → 0.8.4-main.66e292d
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/{chunk-K7KYFJ3P.mjs → chunk-B7EZTXV2.mjs} +32 -11
- package/dist/lib/browser/chunk-B7EZTXV2.mjs.map +7 -0
- package/dist/lib/browser/index.mjs +23 -24
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/{intent-resolver-LR3SDMKQ.mjs → intent-resolver-ANBDVEJ2.mjs} +11 -8
- package/dist/lib/browser/intent-resolver-ANBDVEJ2.mjs.map +7 -0
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/{react-surface-R2ORFB43.mjs → react-surface-7ONRKYBB.mjs} +60 -73
- package/dist/lib/browser/react-surface-7ONRKYBB.mjs.map +7 -0
- package/dist/lib/browser/types/index.mjs +5 -3
- package/dist/lib/node-esm/{chunk-VDWYSHP4.mjs → chunk-WBN5YQGD.mjs} +32 -11
- package/dist/lib/node-esm/chunk-WBN5YQGD.mjs.map +7 -0
- package/dist/lib/node-esm/index.mjs +23 -24
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/{intent-resolver-CKDNVLND.mjs → intent-resolver-X4UZDRI7.mjs} +11 -8
- package/dist/lib/node-esm/intent-resolver-X4UZDRI7.mjs.map +7 -0
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/{react-surface-RMRLHCOY.mjs → react-surface-D7XTGTZL.mjs} +60 -73
- package/dist/lib/node-esm/react-surface-D7XTGTZL.mjs.map +7 -0
- package/dist/lib/node-esm/types/index.mjs +5 -3
- 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/intent-resolver.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/components/KanbanContainer.d.ts +3 -3
- package/dist/types/src/components/KanbanContainer.d.ts.map +1 -1
- package/dist/types/src/components/KanbanContainer.stories.d.ts +21 -8
- package/dist/types/src/components/KanbanContainer.stories.d.ts.map +1 -1
- package/dist/types/src/components/KanbanViewEditor.d.ts +3 -3
- package/dist/types/src/components/KanbanViewEditor.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +21 -9
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +7 -3
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +33 -32
- package/src/KanbanPlugin.tsx +10 -15
- package/src/capabilities/artifact-definition.ts +6 -6
- package/src/capabilities/intent-resolver.ts +4 -9
- package/src/capabilities/react-surface.tsx +18 -19
- package/src/components/KanbanContainer.stories.tsx +25 -41
- package/src/components/KanbanContainer.tsx +13 -26
- package/src/components/KanbanViewEditor.tsx +18 -21
- package/src/meta.ts +6 -2
- package/src/translations.ts +5 -5
- package/src/types/schema.ts +19 -7
- package/dist/lib/browser/chunk-K7KYFJ3P.mjs.map +0 -7
- package/dist/lib/browser/intent-resolver-LR3SDMKQ.mjs.map +0 -7
- package/dist/lib/browser/react-surface-R2ORFB43.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-VDWYSHP4.mjs.map +0 -7
- package/dist/lib/node-esm/intent-resolver-CKDNVLND.mjs.map +0 -7
- package/dist/lib/node-esm/react-surface-RMRLHCOY.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.66e292d",
|
|
4
4
|
"description": "Kanban DXOS Surface plugin",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
@@ -38,48 +38,49 @@
|
|
|
38
38
|
"@preact-signals/safe-react": "^0.9.0",
|
|
39
39
|
"@preact/signals-core": "^1.12.1",
|
|
40
40
|
"effect": "3.18.3",
|
|
41
|
-
"@dxos/
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/
|
|
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/react-
|
|
56
|
-
"@dxos/react-ui
|
|
57
|
-
"@dxos/react-ui-
|
|
58
|
-
"@dxos/
|
|
59
|
-
"@dxos/
|
|
60
|
-
"@dxos/schema": "0.8.4-main.
|
|
61
|
-
"@dxos/
|
|
62
|
-
"@dxos/
|
|
41
|
+
"@dxos/app-framework": "0.8.4-main.66e292d",
|
|
42
|
+
"@dxos/assistant": "0.8.4-main.66e292d",
|
|
43
|
+
"@dxos/blueprints": "0.8.4-main.66e292d",
|
|
44
|
+
"@dxos/echo": "0.8.4-main.66e292d",
|
|
45
|
+
"@dxos/effect": "0.8.4-main.66e292d",
|
|
46
|
+
"@dxos/invariant": "0.8.4-main.66e292d",
|
|
47
|
+
"@dxos/functions": "0.8.4-main.66e292d",
|
|
48
|
+
"@dxos/async": "0.8.4-main.66e292d",
|
|
49
|
+
"@dxos/ai": "0.8.4-main.66e292d",
|
|
50
|
+
"@dxos/log": "0.8.4-main.66e292d",
|
|
51
|
+
"@dxos/plugin-client": "0.8.4-main.66e292d",
|
|
52
|
+
"@dxos/plugin-search": "0.8.4-main.66e292d",
|
|
53
|
+
"@dxos/plugin-graph": "0.8.4-main.66e292d",
|
|
54
|
+
"@dxos/random": "0.8.4-main.66e292d",
|
|
55
|
+
"@dxos/react-client": "0.8.4-main.66e292d",
|
|
56
|
+
"@dxos/react-ui": "0.8.4-main.66e292d",
|
|
57
|
+
"@dxos/react-ui-form": "0.8.4-main.66e292d",
|
|
58
|
+
"@dxos/react-ui-kanban": "0.8.4-main.66e292d",
|
|
59
|
+
"@dxos/react-ui-stack": "0.8.4-main.66e292d",
|
|
60
|
+
"@dxos/schema": "0.8.4-main.66e292d",
|
|
61
|
+
"@dxos/plugin-space": "0.8.4-main.66e292d",
|
|
62
|
+
"@dxos/types": "0.8.4-main.66e292d",
|
|
63
|
+
"@dxos/util": "0.8.4-main.66e292d"
|
|
63
64
|
},
|
|
64
65
|
"devDependencies": {
|
|
65
66
|
"@types/react": "~19.2.2",
|
|
66
|
-
"@types/react-dom": "~19.2.
|
|
67
|
+
"@types/react-dom": "~19.2.2",
|
|
67
68
|
"react": "~19.2.0",
|
|
68
69
|
"react-dom": "~19.2.0",
|
|
69
70
|
"vite": "7.1.9",
|
|
70
|
-
"@dxos/plugin-preview": "0.8.4-main.
|
|
71
|
-
"@dxos/
|
|
72
|
-
"@dxos/react-ui-
|
|
73
|
-
"@dxos/
|
|
74
|
-
"@dxos/
|
|
75
|
-
"@dxos/
|
|
71
|
+
"@dxos/plugin-preview": "0.8.4-main.66e292d",
|
|
72
|
+
"@dxos/plugin-theme": "0.8.4-main.66e292d",
|
|
73
|
+
"@dxos/react-ui-syntax-highlighter": "0.8.4-main.66e292d",
|
|
74
|
+
"@dxos/react-ui-theme": "0.8.4-main.66e292d",
|
|
75
|
+
"@dxos/storybook-utils": "0.8.4-main.66e292d",
|
|
76
|
+
"@dxos/test-utils": "0.8.4-main.66e292d"
|
|
76
77
|
},
|
|
77
78
|
"peerDependencies": {
|
|
78
79
|
"effect": "^3.13.3",
|
|
79
80
|
"react": "^19.0.0",
|
|
80
81
|
"react-dom": "^19.0.0",
|
|
81
|
-
"@dxos/react-ui": "0.8.4-main.
|
|
82
|
-
"@dxos/react-ui-theme": "0.8.4-main.
|
|
82
|
+
"@dxos/react-ui": "0.8.4-main.66e292d",
|
|
83
|
+
"@dxos/react-ui-theme": "0.8.4-main.66e292d"
|
|
83
84
|
},
|
|
84
85
|
"publishConfig": {
|
|
85
86
|
"access": "public"
|
package/src/KanbanPlugin.tsx
CHANGED
|
@@ -3,9 +3,9 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { Capabilities, Events, contributes, createIntent, defineModule, definePlugin } from '@dxos/app-framework';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
6
|
+
import { Type } from '@dxos/echo';
|
|
7
|
+
import { ClientCapabilities, ClientEvents } from '@dxos/plugin-client';
|
|
8
|
+
import { type CreateObjectIntent } from '@dxos/plugin-space/types';
|
|
9
9
|
import { translations as kanbanTranslations } from '@dxos/react-ui-kanban';
|
|
10
10
|
import { Kanban } from '@dxos/react-ui-kanban/types';
|
|
11
11
|
|
|
@@ -25,25 +25,20 @@ export const KanbanPlugin = definePlugin(meta, () => [
|
|
|
25
25
|
activatesOn: Events.SetupMetadata,
|
|
26
26
|
activate: () =>
|
|
27
27
|
contributes(Capabilities.Metadata, {
|
|
28
|
-
id: Kanban.Kanban
|
|
28
|
+
id: Type.getTypename(Kanban.Kanban),
|
|
29
29
|
metadata: {
|
|
30
30
|
icon: 'ph--kanban--regular',
|
|
31
|
+
iconHue: 'green',
|
|
32
|
+
inputSchema: CreateKanbanSchema,
|
|
33
|
+
createObjectIntent: ((props, options) =>
|
|
34
|
+
createIntent(KanbanAction.Create, { ...props, space: options.space })) satisfies CreateObjectIntent,
|
|
31
35
|
},
|
|
32
36
|
}),
|
|
33
37
|
}),
|
|
34
38
|
defineModule({
|
|
35
|
-
id: `${meta.id}/module/
|
|
39
|
+
id: `${meta.id}/module/schema`,
|
|
36
40
|
activatesOn: ClientEvents.SetupSchema,
|
|
37
|
-
activate: () =>
|
|
38
|
-
contributes(
|
|
39
|
-
SpaceCapabilities.ObjectForm,
|
|
40
|
-
defineObjectForm({
|
|
41
|
-
objectSchema: Kanban.Kanban,
|
|
42
|
-
formSchema: CreateKanbanSchema,
|
|
43
|
-
hidden: true,
|
|
44
|
-
getIntent: (props, options) => createIntent(KanbanAction.Create, { ...props, space: options.space }),
|
|
45
|
-
}),
|
|
46
|
-
),
|
|
41
|
+
activate: () => contributes(ClientCapabilities.Schema, [Kanban.Kanban]),
|
|
47
42
|
}),
|
|
48
43
|
defineModule({
|
|
49
44
|
id: `${meta.id}/module/react-surface`,
|
|
@@ -15,9 +15,9 @@ import { defineArtifact } from '@dxos/blueprints';
|
|
|
15
15
|
import { Obj, Query } from '@dxos/echo';
|
|
16
16
|
import { invariant } from '@dxos/invariant';
|
|
17
17
|
import { SpaceAction } from '@dxos/plugin-space/types';
|
|
18
|
-
import { Filter, type Space
|
|
18
|
+
import { Filter, type Space } from '@dxos/react-client/echo';
|
|
19
19
|
import { KanbanView } from '@dxos/react-ui-kanban';
|
|
20
|
-
import {
|
|
20
|
+
import { View } from '@dxos/schema';
|
|
21
21
|
import { isNonNullable } from '@dxos/util';
|
|
22
22
|
|
|
23
23
|
import { meta } from '../meta';
|
|
@@ -94,7 +94,7 @@ export default () => {
|
|
|
94
94
|
execute: async (_input, { extensions }) => {
|
|
95
95
|
invariant(extensions?.space, 'No space');
|
|
96
96
|
const space = extensions.space;
|
|
97
|
-
const { objects } = await space.db.query(Filter.type(
|
|
97
|
+
const { objects } = await space.db.query(Filter.type(View.View)).run();
|
|
98
98
|
|
|
99
99
|
const boardInfo = await Promise.all(
|
|
100
100
|
objects.map(async (view) => {
|
|
@@ -104,7 +104,7 @@ export default () => {
|
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
return {
|
|
107
|
-
id:
|
|
107
|
+
id: Obj.getDXN(view).toString(),
|
|
108
108
|
name: view.name ?? 'Unnamed Kanban',
|
|
109
109
|
typename: view.query.typename,
|
|
110
110
|
};
|
|
@@ -124,8 +124,8 @@ export default () => {
|
|
|
124
124
|
const space = extensions.space;
|
|
125
125
|
const view = (await space.db
|
|
126
126
|
// TODO(wittjosiah): Filter.and should aggregate type
|
|
127
|
-
.query(Query.select(Filter.and(Filter.type(
|
|
128
|
-
.first()) as
|
|
127
|
+
.query(Query.select(Filter.and(Filter.type(View.View), Filter.ids(id))))
|
|
128
|
+
.first()) as View.View;
|
|
129
129
|
|
|
130
130
|
const kanban = await view.presentation.load();
|
|
131
131
|
invariant(Obj.instanceOf(KanbanView, kanban));
|
|
@@ -7,7 +7,7 @@ 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, getTypenameFromQuery } from '@dxos/schema';
|
|
10
|
+
import { ProjectionModel, View, getTypenameFromQuery } from '@dxos/schema';
|
|
11
11
|
|
|
12
12
|
import { meta } from '../meta';
|
|
13
13
|
import { KanbanAction } from '../types';
|
|
@@ -18,14 +18,9 @@ export default (context: PluginContext) =>
|
|
|
18
18
|
intent: KanbanAction.Create,
|
|
19
19
|
resolve: async ({ space, name, typename, initialPivotColumn }) => {
|
|
20
20
|
const client = context.getCapability(ClientCapabilities.Client);
|
|
21
|
-
const { view } = await
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
name,
|
|
25
|
-
typename,
|
|
26
|
-
pivotFieldName: initialPivotColumn,
|
|
27
|
-
});
|
|
28
|
-
return { data: { object: view } };
|
|
21
|
+
const { view } = await View.makeFromSpace({ client, space, typename, pivotFieldName: initialPivotColumn });
|
|
22
|
+
const kanban = Kanban.make({ name, view });
|
|
23
|
+
return { data: { object: kanban } };
|
|
29
24
|
},
|
|
30
25
|
}),
|
|
31
26
|
createResolver({
|
|
@@ -5,14 +5,13 @@
|
|
|
5
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
9
|
import { Obj, Type } from '@dxos/echo';
|
|
10
10
|
import { findAnnotation } from '@dxos/effect';
|
|
11
|
-
import { ClientCapabilities } from '@dxos/plugin-client';
|
|
12
11
|
import { type Space, getSpace, isSpace } from '@dxos/react-client/echo';
|
|
13
12
|
import { type InputProps, SelectInput, useFormValues } from '@dxos/react-ui-form';
|
|
14
13
|
import { Kanban } from '@dxos/react-ui-kanban/types';
|
|
15
|
-
import {
|
|
14
|
+
import { type Collection } from '@dxos/schema';
|
|
16
15
|
|
|
17
16
|
import { KanbanContainer, KanbanViewEditor } from '../components';
|
|
18
17
|
import { meta } from '../meta';
|
|
@@ -23,24 +22,26 @@ export default () =>
|
|
|
23
22
|
createSurface({
|
|
24
23
|
id: meta.id,
|
|
25
24
|
role: ['article', 'section'],
|
|
26
|
-
filter: (data): data is { subject:
|
|
27
|
-
|
|
28
|
-
component: ({ data, role }) => <KanbanContainer view={data.subject} role={role} />,
|
|
25
|
+
filter: (data): data is { subject: Kanban.Kanban } => Obj.instanceOf(Kanban.Kanban, data.subject),
|
|
26
|
+
component: ({ data, role }) => <KanbanContainer object={data.subject} role={role} />,
|
|
29
27
|
}),
|
|
30
28
|
createSurface({
|
|
31
29
|
id: `${meta.id}/object-settings`,
|
|
32
30
|
role: 'object-settings',
|
|
33
31
|
position: 'hoist',
|
|
34
|
-
filter: (data): data is { subject:
|
|
35
|
-
|
|
36
|
-
component: ({ data }) => <KanbanViewEditor view={data.subject} />,
|
|
32
|
+
filter: (data): data is { subject: Kanban.Kanban } => Obj.instanceOf(Kanban.Kanban, data.subject),
|
|
33
|
+
component: ({ data }) => <KanbanViewEditor object={data.subject} />,
|
|
37
34
|
}),
|
|
38
35
|
createSurface({
|
|
39
36
|
id: `${meta.id}/create-initial-schema-form-[pivot-column]`,
|
|
40
37
|
role: 'form-input',
|
|
41
38
|
filter: (
|
|
42
39
|
data,
|
|
43
|
-
): data is {
|
|
40
|
+
): data is {
|
|
41
|
+
prop: string;
|
|
42
|
+
schema: Schema.Schema<any>;
|
|
43
|
+
target: Space | Collection.Collection | undefined;
|
|
44
|
+
} => {
|
|
44
45
|
const annotation = findAnnotation<boolean>((data.schema as Schema.Schema.All).ast, PivotColumnAnnotationId);
|
|
45
46
|
return !!annotation;
|
|
46
47
|
},
|
|
@@ -50,16 +51,14 @@ export default () =>
|
|
|
50
51
|
if (!space) {
|
|
51
52
|
return null;
|
|
52
53
|
}
|
|
53
|
-
const { typename } = useFormValues();
|
|
54
|
-
// TODO(wittjosiah): Unify this schema lookup.
|
|
55
|
-
const schemaWhitelists = useCapabilities(ClientCapabilities.SchemaWhiteList);
|
|
56
|
-
const staticSchema = schemaWhitelists.flat().find((schema) => Type.getTypename(schema) === typename);
|
|
57
|
-
const [selectedSchema] = space?.db.schemaRegistry.query({ typename }).runSync();
|
|
58
54
|
|
|
55
|
+
const { typename } = useFormValues();
|
|
56
|
+
const [selectedSchema] = useMemo(
|
|
57
|
+
() => space?.db.schemaRegistry.query({ location: ['database', 'runtime'], typename }).runSync(),
|
|
58
|
+
[space, typename],
|
|
59
|
+
);
|
|
59
60
|
const singleSelectColumns = useMemo(() => {
|
|
60
|
-
const properties =
|
|
61
|
-
? Type.toJsonSchema(staticSchema).properties
|
|
62
|
-
: selectedSchema?.jsonSchema?.properties;
|
|
61
|
+
const properties = Type.toJsonSchema(selectedSchema).properties;
|
|
63
62
|
if (!properties) {
|
|
64
63
|
return [];
|
|
65
64
|
}
|
|
@@ -72,7 +71,7 @@ export default () =>
|
|
|
72
71
|
}, []);
|
|
73
72
|
|
|
74
73
|
return columns;
|
|
75
|
-
}, [selectedSchema
|
|
74
|
+
}, [selectedSchema]);
|
|
76
75
|
|
|
77
76
|
if (!typename) {
|
|
78
77
|
return null;
|
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
6
|
-
import React, { useCallback
|
|
6
|
+
import React, { useCallback } from 'react';
|
|
7
7
|
|
|
8
8
|
import { IntentPlugin, SettingsPlugin } from '@dxos/app-framework';
|
|
9
9
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
10
|
-
import { Obj,
|
|
10
|
+
import { Obj, type QueryAST, Type } from '@dxos/echo';
|
|
11
11
|
import { invariant } from '@dxos/invariant';
|
|
12
12
|
import { ClientPlugin } from '@dxos/plugin-client';
|
|
13
13
|
import { PreviewPlugin } from '@dxos/plugin-preview';
|
|
@@ -20,11 +20,12 @@ import { useClient } from '@dxos/react-client';
|
|
|
20
20
|
import { Filter, useQuery, useSchema, useSpaces } from '@dxos/react-client/echo';
|
|
21
21
|
import { withTheme } from '@dxos/react-ui/testing';
|
|
22
22
|
import { ViewEditor } from '@dxos/react-ui-form';
|
|
23
|
-
import { Kanban as KanbanComponent, useKanbanModel } from '@dxos/react-ui-kanban';
|
|
23
|
+
import { Kanban as KanbanComponent, useKanbanModel, useProjectionModel } from '@dxos/react-ui-kanban';
|
|
24
24
|
import { Kanban } from '@dxos/react-ui-kanban/types';
|
|
25
25
|
import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
|
|
26
26
|
import { defaultTx } from '@dxos/react-ui-theme';
|
|
27
|
-
import {
|
|
27
|
+
import { View, getTypenameFromQuery } from '@dxos/schema';
|
|
28
|
+
import { Organization, Person } from '@dxos/types';
|
|
28
29
|
|
|
29
30
|
import { translations } from '../translations';
|
|
30
31
|
|
|
@@ -39,41 +40,23 @@ const rollOrg = () => ({
|
|
|
39
40
|
description: faker.lorem.paragraph(),
|
|
40
41
|
image: faker.image.url(),
|
|
41
42
|
website: faker.internet.url(),
|
|
42
|
-
status: faker.helpers.arrayElement(
|
|
43
|
+
status: faker.helpers.arrayElement(Organization.StatusOptions).id as Organization.Organization['status'],
|
|
43
44
|
});
|
|
44
45
|
|
|
45
46
|
const StorybookKanban = () => {
|
|
46
47
|
const client = useClient();
|
|
47
48
|
const spaces = useSpaces();
|
|
48
49
|
const space = spaces[spaces.length - 1];
|
|
49
|
-
const
|
|
50
|
-
const
|
|
51
|
-
const [projection, setProjection] = useState<ProjectionModel>();
|
|
52
|
-
const typename = view?.query ? getTypenameFromQuery(view.query.ast) : undefined;
|
|
50
|
+
const [object] = useQuery(space, Filter.type(Kanban.Kanban));
|
|
51
|
+
const typename = object?.view.target?.query ? getTypenameFromQuery(object.view.target.query.ast) : undefined;
|
|
53
52
|
const schema = useSchema(client, space, typename);
|
|
54
53
|
|
|
55
|
-
useEffect(() => {
|
|
56
|
-
if (views.length && !view) {
|
|
57
|
-
const view = views[0];
|
|
58
|
-
setView(view);
|
|
59
|
-
}
|
|
60
|
-
}, [views]);
|
|
61
|
-
|
|
62
|
-
useEffect(() => {
|
|
63
|
-
if (view?.projection && schema) {
|
|
64
|
-
const jsonSchema = Type.toJsonSchema(schema);
|
|
65
|
-
setProjection(new ProjectionModel(jsonSchema, view.projection));
|
|
66
|
-
}
|
|
67
|
-
// TODO(ZaymonFC): Is there a better way to get notified about deep changes in the json schema?
|
|
68
|
-
// @dmaretskyi? Once resolved, update in multiple places (e.g., storybooks).
|
|
69
|
-
}, [view?.projection, schema, JSON.stringify(schema ? Type.toJsonSchema(schema) : {})]);
|
|
70
|
-
|
|
71
54
|
const objects = useQuery(space, schema ? Filter.type(schema) : Filter.nothing());
|
|
72
55
|
const filteredObjects = useGlobalFilteredObjects(objects);
|
|
73
56
|
|
|
57
|
+
const projection = useProjectionModel(schema, object);
|
|
74
58
|
const model = useKanbanModel({
|
|
75
|
-
|
|
76
|
-
schema,
|
|
59
|
+
object,
|
|
77
60
|
projection,
|
|
78
61
|
items: filteredObjects,
|
|
79
62
|
});
|
|
@@ -94,21 +77,21 @@ const StorybookKanban = () => {
|
|
|
94
77
|
[space, schema, model],
|
|
95
78
|
);
|
|
96
79
|
|
|
97
|
-
const handleRemoveCard = useCallback((card: { id: string }) => space
|
|
80
|
+
const handleRemoveCard = useCallback((card: { id: string }) => Obj.isObject(card) && space?.db.remove(card), [space]);
|
|
98
81
|
|
|
99
82
|
const handleUpdateQuery = useCallback(
|
|
100
|
-
(
|
|
83
|
+
(newQuery: QueryAST.Query) => {
|
|
101
84
|
invariant(schema);
|
|
102
85
|
invariant(Type.isMutable(schema));
|
|
103
|
-
invariant(view);
|
|
86
|
+
invariant(object.view.target);
|
|
104
87
|
|
|
105
|
-
schema.updateTypename(
|
|
106
|
-
view.query.ast =
|
|
88
|
+
schema.updateTypename(getTypenameFromQuery(newQuery));
|
|
89
|
+
object.view.target.query.ast = newQuery;
|
|
107
90
|
},
|
|
108
|
-
[
|
|
91
|
+
[object, schema],
|
|
109
92
|
);
|
|
110
93
|
|
|
111
|
-
if (!schema || !view) {
|
|
94
|
+
if (!schema || !object.view.target) {
|
|
112
95
|
return null;
|
|
113
96
|
}
|
|
114
97
|
|
|
@@ -119,14 +102,14 @@ const StorybookKanban = () => {
|
|
|
119
102
|
<ViewEditor
|
|
120
103
|
registry={space?.db.schemaRegistry}
|
|
121
104
|
schema={schema}
|
|
122
|
-
view={view}
|
|
105
|
+
view={object.view.target}
|
|
123
106
|
onQueryChanged={handleUpdateQuery}
|
|
124
107
|
onDelete={(fieldId: string) => {
|
|
125
108
|
console.log('[ViewEditor]', 'onDelete', fieldId);
|
|
126
109
|
}}
|
|
127
110
|
/>
|
|
128
111
|
<SyntaxHighlighter language='json' className='text-xs'>
|
|
129
|
-
{JSON.stringify({ view, schema }, null, 2)}
|
|
112
|
+
{JSON.stringify({ view: object.view.target, schema }, null, 2)}
|
|
130
113
|
</SyntaxHighlighter>
|
|
131
114
|
</div>
|
|
132
115
|
</div>
|
|
@@ -150,22 +133,23 @@ const meta = {
|
|
|
150
133
|
withPluginManager({
|
|
151
134
|
plugins: [
|
|
152
135
|
ClientPlugin({
|
|
153
|
-
types: [
|
|
136
|
+
types: [Organization.Organization, Person.Person, View.View, Kanban.Kanban],
|
|
154
137
|
onClientInitialized: async ({ client }) => {
|
|
155
138
|
await client.halo.createIdentity();
|
|
156
139
|
const space = await client.spaces.create();
|
|
157
140
|
await space.waitUntilReady();
|
|
158
|
-
const { view } = await
|
|
141
|
+
const { view } = await View.makeFromSpace({
|
|
159
142
|
client,
|
|
160
143
|
space,
|
|
161
|
-
typename:
|
|
144
|
+
typename: Organization.Organization.typename,
|
|
162
145
|
pivotFieldName: 'status',
|
|
163
146
|
});
|
|
164
|
-
|
|
147
|
+
const kanban = Kanban.make({ view });
|
|
148
|
+
space.db.add(kanban);
|
|
165
149
|
|
|
166
150
|
// TODO(burdon): Replace with sdk/schema/testing.
|
|
167
151
|
Array.from({ length: 80 }).map(() => {
|
|
168
|
-
return space.db.add(Obj.make(
|
|
152
|
+
return space.db.add(Obj.make(Organization.Organization, rollOrg()));
|
|
169
153
|
});
|
|
170
154
|
},
|
|
171
155
|
}),
|
|
@@ -2,34 +2,28 @@
|
|
|
2
2
|
// Copyright 2024 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { useCallback, useEffect,
|
|
5
|
+
import React, { useCallback, useEffect, 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 {
|
|
10
|
+
import { 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
|
-
import { Kanban, useKanbanModel } from '@dxos/react-ui-kanban';
|
|
14
|
+
import { Kanban as KanbanComponent, useKanbanModel, useProjectionModel } from '@dxos/react-ui-kanban';
|
|
15
|
+
import { type Kanban } from '@dxos/react-ui-kanban/types';
|
|
14
16
|
import { StackItem } from '@dxos/react-ui-stack';
|
|
15
|
-
import {
|
|
17
|
+
import { getTypenameFromQuery } from '@dxos/schema';
|
|
16
18
|
|
|
17
19
|
import { KanbanAction } from '../types';
|
|
18
20
|
|
|
19
|
-
export const KanbanContainer = ({
|
|
21
|
+
export const KanbanContainer = ({ object }: { object: Kanban.Kanban; role: string }) => {
|
|
20
22
|
const client = useClient();
|
|
21
23
|
const [cardSchema, setCardSchema] = useState<TypedObject<any, any>>();
|
|
22
|
-
const
|
|
23
|
-
const space = getSpace(view);
|
|
24
|
+
const space = getSpace(object);
|
|
24
25
|
const { dispatchPromise: dispatch } = useIntentDispatcher();
|
|
25
|
-
const typename = view.query ? getTypenameFromQuery(view.query.ast) : undefined;
|
|
26
|
-
|
|
27
|
-
const jsonSchema = useMemo(() => {
|
|
28
|
-
if (!cardSchema) {
|
|
29
|
-
return undefined;
|
|
30
|
-
}
|
|
31
|
-
return cardSchema instanceof EchoSchema ? cardSchema.jsonSchema : Type.toJsonSchema(cardSchema);
|
|
32
|
-
}, [cardSchema]);
|
|
26
|
+
const typename = object.view.target?.query ? getTypenameFromQuery(object.view.target.query.ast) : undefined;
|
|
33
27
|
|
|
34
28
|
useEffect(() => {
|
|
35
29
|
const staticSchema = client.graph.schemaRegistry.schemas.find((schema) => Type.getTypename(schema) === typename);
|
|
@@ -51,19 +45,12 @@ export const KanbanContainer = ({ view }: { view: DataType.View; role: string })
|
|
|
51
45
|
}
|
|
52
46
|
}, [typename, space]);
|
|
53
47
|
|
|
54
|
-
useEffect(() => {
|
|
55
|
-
if (jsonSchema) {
|
|
56
|
-
setProjection(new ProjectionModel(jsonSchema, view.projection));
|
|
57
|
-
}
|
|
58
|
-
// TODO(ZaymonFC): Is there a better way to get notified about deep changes in the json schema?
|
|
59
|
-
}, [view.projection, JSON.stringify(jsonSchema)]);
|
|
60
|
-
|
|
61
48
|
const objects = useQuery(space, cardSchema ? Filter.type(cardSchema) : Filter.nothing());
|
|
62
49
|
const filteredObjects = useGlobalFilteredObjects(objects);
|
|
63
50
|
|
|
51
|
+
const projection = useProjectionModel(cardSchema, object);
|
|
64
52
|
const model = useKanbanModel({
|
|
65
|
-
|
|
66
|
-
schema: cardSchema,
|
|
53
|
+
object,
|
|
67
54
|
projection,
|
|
68
55
|
items: filteredObjects,
|
|
69
56
|
});
|
|
@@ -89,7 +76,7 @@ export const KanbanContainer = ({ view }: { view: DataType.View; role: string })
|
|
|
89
76
|
|
|
90
77
|
return (
|
|
91
78
|
<StackItem.Content>
|
|
92
|
-
{model && <
|
|
79
|
+
{model && <KanbanComponent model={model} onAddCard={handleAddCard} onRemoveCard={handleRemoveCard} />}
|
|
93
80
|
</StackItem.Content>
|
|
94
81
|
);
|
|
95
82
|
};
|
|
@@ -4,46 +4,43 @@
|
|
|
4
4
|
|
|
5
5
|
import React, { useCallback, useMemo } from 'react';
|
|
6
6
|
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
7
|
+
import { Format } from '@dxos/echo/internal';
|
|
8
|
+
import { invariant } from '@dxos/invariant';
|
|
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
|
-
import {
|
|
13
|
-
import { type
|
|
12
|
+
import { useProjectionModel } from '@dxos/react-ui-kanban';
|
|
13
|
+
import { type Kanban } from '@dxos/react-ui-kanban/types';
|
|
14
|
+
import { getTypenameFromQuery } from '@dxos/schema';
|
|
14
15
|
|
|
15
|
-
|
|
16
|
+
import { SettingsSchema } from '../types';
|
|
16
17
|
|
|
17
|
-
|
|
18
|
+
type KanbanViewEditorProps = { object: Kanban.Kanban };
|
|
19
|
+
|
|
20
|
+
export const KanbanViewEditor = ({ object }: KanbanViewEditorProps) => {
|
|
18
21
|
const client = useClient();
|
|
19
|
-
const space = getSpace(
|
|
20
|
-
const
|
|
22
|
+
const space = getSpace(object);
|
|
23
|
+
const view = object.view.target;
|
|
24
|
+
const currentTypename = view?.query ? getTypenameFromQuery(view.query.ast) : undefined;
|
|
21
25
|
const schema = useSchema(client, space, currentTypename);
|
|
22
|
-
|
|
23
|
-
const projection = useMemo(() => {
|
|
24
|
-
if (schema) {
|
|
25
|
-
const jsonSchema = schema instanceof EchoSchema ? schema.jsonSchema : Type.toJsonSchema(schema);
|
|
26
|
-
const projection = new ProjectionModel(jsonSchema, view.projection);
|
|
27
|
-
projection.normalizeView();
|
|
28
|
-
return projection;
|
|
29
|
-
}
|
|
30
|
-
}, [view.projection, JSON.stringify(schema)]);
|
|
26
|
+
const projection = useProjectionModel(schema, object);
|
|
31
27
|
|
|
32
28
|
const fieldProjections = projection?.getFieldProjections() || [];
|
|
33
29
|
const selectFields = fieldProjections
|
|
34
|
-
.filter((field) => field.props.format ===
|
|
30
|
+
.filter((field) => field.props.format === Format.TypeFormat.SingleSelect)
|
|
35
31
|
.map(({ field }) => ({ value: field.id, label: field.path }));
|
|
36
32
|
|
|
37
33
|
const handleSave = useCallback(
|
|
38
34
|
(values: Partial<{ columnFieldId: string }>) => {
|
|
35
|
+
invariant(view);
|
|
39
36
|
view.projection.pivotFieldId = values.columnFieldId;
|
|
40
37
|
},
|
|
41
38
|
[view],
|
|
42
39
|
);
|
|
43
40
|
|
|
44
41
|
const initialValues = useMemo(
|
|
45
|
-
() => ({ columnFieldId: view
|
|
46
|
-
[view
|
|
42
|
+
() => ({ columnFieldId: view?.projection.pivotFieldId }),
|
|
43
|
+
[view?.projection.pivotFieldId],
|
|
47
44
|
);
|
|
48
45
|
const custom: CustomInputMap = useMemo(
|
|
49
46
|
() => ({ columnFieldId: (props) => <SelectInput {...props} options={selectFields} /> }),
|
|
@@ -53,7 +50,7 @@ export const KanbanViewEditor = ({ view }: KanbanViewEditorProps) => {
|
|
|
53
50
|
return (
|
|
54
51
|
<Form
|
|
55
52
|
Custom={custom}
|
|
56
|
-
schema={
|
|
53
|
+
schema={SettingsSchema}
|
|
57
54
|
values={initialValues}
|
|
58
55
|
onSave={handleSave}
|
|
59
56
|
autoSave
|
package/src/meta.ts
CHANGED
|
@@ -3,13 +3,17 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type PluginMeta } from '@dxos/app-framework';
|
|
6
|
+
import { trim } from '@dxos/util';
|
|
6
7
|
|
|
7
8
|
export const meta: PluginMeta = {
|
|
8
9
|
id: 'dxos.org/plugin/kanban',
|
|
9
10
|
name: 'Kanban',
|
|
10
|
-
description:
|
|
11
|
-
|
|
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
|
+
`,
|
|
12
15
|
icon: 'ph--kanban--regular',
|
|
16
|
+
iconHue: 'green',
|
|
13
17
|
source: 'https://github.com/dxos/dxos/tree/main/packages/plugins/plugin-kanban',
|
|
14
18
|
screenshots: ['https://dxos.network/plugin-details-kanban-dark.png'],
|
|
15
19
|
};
|
package/src/translations.ts
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
// Copyright 2023 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
+
import { Type } from '@dxos/echo';
|
|
5
6
|
import { type Resource } from '@dxos/react-ui';
|
|
6
7
|
import { Kanban } from '@dxos/react-ui-kanban/types';
|
|
7
8
|
|
|
@@ -10,24 +11,23 @@ import { meta } from './meta';
|
|
|
10
11
|
export const translations = [
|
|
11
12
|
{
|
|
12
13
|
'en-US': {
|
|
13
|
-
[Kanban.Kanban
|
|
14
|
+
[Type.getTypename(Kanban.Kanban)]: {
|
|
14
15
|
'typename label': 'Kanban',
|
|
15
16
|
'typename label_zero': 'Kanbans',
|
|
16
17
|
'typename label_one': 'Kanban',
|
|
17
18
|
'typename label_other': 'Kanbans',
|
|
18
19
|
'object name placeholder': 'New kanban',
|
|
20
|
+
'rename object label': 'Rename kanban',
|
|
21
|
+
'delete object label': 'Delete kanban',
|
|
22
|
+
'object deleted label': 'Kanban deleted',
|
|
19
23
|
},
|
|
20
24
|
[meta.id]: {
|
|
21
25
|
'plugin name': 'Kanban',
|
|
22
26
|
'kanban title label': 'Title',
|
|
23
27
|
'column title label': 'Column title',
|
|
24
28
|
'column title placeholder': 'New column',
|
|
25
|
-
'item title label': 'Item title',
|
|
26
|
-
'item title placeholder': 'New item',
|
|
27
29
|
'add column label': 'Add column',
|
|
28
|
-
'add item label': 'Add card',
|
|
29
30
|
'delete column label': 'Delete column',
|
|
30
|
-
'delete item label': 'Delete card',
|
|
31
31
|
'card field deleted label': 'Card field deleted',
|
|
32
32
|
'card deleted label': 'Card deleted',
|
|
33
33
|
},
|