@dxos/plugin-kanban 0.8.4-main.2c6827d → 0.8.4-main.3c1ae3b

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/lib/browser/{chunk-HO3LQ5T7.mjs → chunk-PEQVHFOX.mjs} +24 -9
  2. package/dist/lib/browser/chunk-PEQVHFOX.mjs.map +7 -0
  3. package/dist/lib/browser/index.mjs +22 -24
  4. package/dist/lib/browser/index.mjs.map +3 -3
  5. package/dist/lib/browser/{intent-resolver-OPYUDNSU.mjs → intent-resolver-NHCWHMPW.mjs} +11 -11
  6. package/dist/lib/browser/intent-resolver-NHCWHMPW.mjs.map +7 -0
  7. package/dist/lib/browser/meta.json +1 -1
  8. package/dist/lib/browser/{react-surface-X54TNDDN.mjs → react-surface-NSCKM4QW.mjs} +74 -92
  9. package/dist/lib/browser/react-surface-NSCKM4QW.mjs.map +7 -0
  10. package/dist/lib/browser/types/index.mjs +5 -3
  11. package/dist/lib/node-esm/{chunk-QZMZU5HM.mjs → chunk-LTCOYU73.mjs} +24 -9
  12. package/dist/lib/node-esm/chunk-LTCOYU73.mjs.map +7 -0
  13. package/dist/lib/node-esm/index.mjs +22 -24
  14. package/dist/lib/node-esm/index.mjs.map +3 -3
  15. package/dist/lib/node-esm/{intent-resolver-BDKNXV3R.mjs → intent-resolver-L2OEBOJW.mjs} +11 -11
  16. package/dist/lib/node-esm/intent-resolver-L2OEBOJW.mjs.map +7 -0
  17. package/dist/lib/node-esm/meta.json +1 -1
  18. package/dist/lib/node-esm/{react-surface-CVDMIHSC.mjs → react-surface-WXYTWOY2.mjs} +74 -92
  19. package/dist/lib/node-esm/react-surface-WXYTWOY2.mjs.map +7 -0
  20. package/dist/lib/node-esm/types/index.mjs +5 -3
  21. package/dist/types/src/KanbanPlugin.d.ts.map +1 -1
  22. package/dist/types/src/capabilities/intent-resolver.d.ts.map +1 -1
  23. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
  24. package/dist/types/src/components/KanbanContainer.d.ts +3 -3
  25. package/dist/types/src/components/KanbanContainer.d.ts.map +1 -1
  26. package/dist/types/src/components/KanbanContainer.stories.d.ts +21 -8
  27. package/dist/types/src/components/KanbanContainer.stories.d.ts.map +1 -1
  28. package/dist/types/src/components/KanbanViewEditor.d.ts +3 -3
  29. package/dist/types/src/components/KanbanViewEditor.d.ts.map +1 -1
  30. package/dist/types/src/translations.d.ts +21 -9
  31. package/dist/types/src/translations.d.ts.map +1 -1
  32. package/dist/types/src/types/schema.d.ts +5 -1
  33. package/dist/types/src/types/schema.d.ts.map +1 -1
  34. package/dist/types/tsconfig.tsbuildinfo +1 -1
  35. package/package.json +32 -32
  36. package/src/KanbanPlugin.tsx +9 -15
  37. package/src/capabilities/artifact-definition.ts +1 -1
  38. package/src/capabilities/intent-resolver.ts +4 -11
  39. package/src/capabilities/react-surface.tsx +15 -21
  40. package/src/components/KanbanContainer.stories.tsx +21 -47
  41. package/src/components/KanbanContainer.tsx +16 -30
  42. package/src/components/KanbanViewEditor.tsx +24 -34
  43. package/src/translations.ts +5 -5
  44. package/src/types/schema.ts +17 -6
  45. package/dist/lib/browser/chunk-HO3LQ5T7.mjs.map +0 -7
  46. package/dist/lib/browser/intent-resolver-OPYUDNSU.mjs.map +0 -7
  47. package/dist/lib/browser/react-surface-X54TNDDN.mjs.map +0 -7
  48. package/dist/lib/node-esm/chunk-QZMZU5HM.mjs.map +0 -7
  49. package/dist/lib/node-esm/intent-resolver-BDKNXV3R.mjs.map +0 -7
  50. package/dist/lib/node-esm/react-surface-CVDMIHSC.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.2c6827d",
3
+ "version": "0.8.4-main.3c1ae3b",
4
4
  "description": "Kanban DXOS Surface plugin",
5
5
  "homepage": "https://dxos.org",
6
6
  "bugs": "https://github.com/dxos/dxos/issues",
@@ -38,29 +38,29 @@
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/ai": "0.8.4-main.2c6827d",
42
- "@dxos/async": "0.8.4-main.2c6827d",
43
- "@dxos/assistant": "0.8.4-main.2c6827d",
44
- "@dxos/blueprints": "0.8.4-main.2c6827d",
45
- "@dxos/echo": "0.8.4-main.2c6827d",
46
- "@dxos/effect": "0.8.4-main.2c6827d",
47
- "@dxos/app-framework": "0.8.4-main.2c6827d",
48
- "@dxos/functions": "0.8.4-main.2c6827d",
49
- "@dxos/plugin-client": "0.8.4-main.2c6827d",
50
- "@dxos/plugin-graph": "0.8.4-main.2c6827d",
51
- "@dxos/invariant": "0.8.4-main.2c6827d",
52
- "@dxos/plugin-search": "0.8.4-main.2c6827d",
53
- "@dxos/plugin-space": "0.8.4-main.2c6827d",
54
- "@dxos/random": "0.8.4-main.2c6827d",
55
- "@dxos/react-client": "0.8.4-main.2c6827d",
56
- "@dxos/react-ui": "0.8.4-main.2c6827d",
57
- "@dxos/react-ui-form": "0.8.4-main.2c6827d",
58
- "@dxos/react-ui-stack": "0.8.4-main.2c6827d",
59
- "@dxos/schema": "0.8.4-main.2c6827d",
60
- "@dxos/react-ui-kanban": "0.8.4-main.2c6827d",
61
- "@dxos/types": "0.8.4-main.2c6827d",
62
- "@dxos/util": "0.8.4-main.2c6827d",
63
- "@dxos/log": "0.8.4-main.2c6827d"
41
+ "@dxos/ai": "0.8.4-main.3c1ae3b",
42
+ "@dxos/app-framework": "0.8.4-main.3c1ae3b",
43
+ "@dxos/assistant": "0.8.4-main.3c1ae3b",
44
+ "@dxos/blueprints": "0.8.4-main.3c1ae3b",
45
+ "@dxos/effect": "0.8.4-main.3c1ae3b",
46
+ "@dxos/echo": "0.8.4-main.3c1ae3b",
47
+ "@dxos/async": "0.8.4-main.3c1ae3b",
48
+ "@dxos/invariant": "0.8.4-main.3c1ae3b",
49
+ "@dxos/functions": "0.8.4-main.3c1ae3b",
50
+ "@dxos/plugin-client": "0.8.4-main.3c1ae3b",
51
+ "@dxos/log": "0.8.4-main.3c1ae3b",
52
+ "@dxos/plugin-graph": "0.8.4-main.3c1ae3b",
53
+ "@dxos/plugin-search": "0.8.4-main.3c1ae3b",
54
+ "@dxos/plugin-space": "0.8.4-main.3c1ae3b",
55
+ "@dxos/random": "0.8.4-main.3c1ae3b",
56
+ "@dxos/react-ui": "0.8.4-main.3c1ae3b",
57
+ "@dxos/react-client": "0.8.4-main.3c1ae3b",
58
+ "@dxos/react-ui-form": "0.8.4-main.3c1ae3b",
59
+ "@dxos/react-ui-kanban": "0.8.4-main.3c1ae3b",
60
+ "@dxos/schema": "0.8.4-main.3c1ae3b",
61
+ "@dxos/react-ui-stack": "0.8.4-main.3c1ae3b",
62
+ "@dxos/util": "0.8.4-main.3c1ae3b",
63
+ "@dxos/types": "0.8.4-main.3c1ae3b"
64
64
  },
65
65
  "devDependencies": {
66
66
  "@types/react": "~19.2.2",
@@ -68,19 +68,19 @@
68
68
  "react": "~19.2.0",
69
69
  "react-dom": "~19.2.0",
70
70
  "vite": "7.1.9",
71
- "@dxos/plugin-preview": "0.8.4-main.2c6827d",
72
- "@dxos/plugin-theme": "0.8.4-main.2c6827d",
73
- "@dxos/storybook-utils": "0.8.4-main.2c6827d",
74
- "@dxos/react-ui-syntax-highlighter": "0.8.4-main.2c6827d",
75
- "@dxos/test-utils": "0.8.4-main.2c6827d",
76
- "@dxos/react-ui-theme": "0.8.4-main.2c6827d"
71
+ "@dxos/plugin-preview": "0.8.4-main.3c1ae3b",
72
+ "@dxos/plugin-theme": "0.8.4-main.3c1ae3b",
73
+ "@dxos/react-ui-theme": "0.8.4-main.3c1ae3b",
74
+ "@dxos/react-ui-syntax-highlighter": "0.8.4-main.3c1ae3b",
75
+ "@dxos/storybook-utils": "0.8.4-main.3c1ae3b",
76
+ "@dxos/test-utils": "0.8.4-main.3c1ae3b"
77
77
  },
78
78
  "peerDependencies": {
79
79
  "effect": "^3.13.3",
80
80
  "react": "^19.0.0",
81
81
  "react-dom": "^19.0.0",
82
- "@dxos/react-ui": "0.8.4-main.2c6827d",
83
- "@dxos/react-ui-theme": "0.8.4-main.2c6827d"
82
+ "@dxos/react-ui": "0.8.4-main.3c1ae3b",
83
+ "@dxos/react-ui-theme": "0.8.4-main.3c1ae3b"
84
84
  },
85
85
  "publishConfig": {
86
86
  "access": "public"
@@ -3,9 +3,9 @@
3
3
  //
4
4
 
5
5
  import { Capabilities, Events, contributes, createIntent, defineModule, definePlugin } from '@dxos/app-framework';
6
- import { ClientEvents } from '@dxos/plugin-client';
7
- import { SpaceCapabilities } from '@dxos/plugin-space';
8
- import { defineObjectForm } from '@dxos/plugin-space/types';
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,26 +25,20 @@ export const KanbanPlugin = definePlugin(meta, () => [
25
25
  activatesOn: Events.SetupMetadata,
26
26
  activate: () =>
27
27
  contributes(Capabilities.Metadata, {
28
- id: Kanban.Kanban.typename,
28
+ id: Type.getTypename(Kanban.Kanban),
29
29
  metadata: {
30
30
  icon: 'ph--kanban--regular',
31
31
  iconHue: 'green',
32
+ inputSchema: CreateKanbanSchema,
33
+ createObjectIntent: ((props, options) =>
34
+ createIntent(KanbanAction.Create, { ...props, space: options.space })) satisfies CreateObjectIntent,
32
35
  },
33
36
  }),
34
37
  }),
35
38
  defineModule({
36
- id: `${meta.id}/module/object-form`,
39
+ id: `${meta.id}/module/schema`,
37
40
  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 }),
46
- }),
47
- ),
41
+ activate: () => contributes(ClientCapabilities.Schema, [Kanban.Kanban]),
48
42
  }),
49
43
  defineModule({
50
44
  id: `${meta.id}/module/react-surface`,
@@ -124,7 +124,7 @@ 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(View.View), Filter.ids(id))))
127
+ .query(Query.select(Filter.and(Filter.type(View.View), Filter.id(id))))
128
128
  .first()) as View.View;
129
129
 
130
130
  const kanban = await view.presentation.load();
@@ -4,10 +4,9 @@
4
4
 
5
5
  import { Capabilities, type PluginContext, contributes, createResolver } from '@dxos/app-framework';
6
6
  import { invariant } from '@dxos/invariant';
7
- import { ClientCapabilities } from '@dxos/plugin-client';
8
7
  import { getSpace } from '@dxos/react-client/echo';
9
8
  import { Kanban } from '@dxos/react-ui-kanban/types';
10
- import { ProjectionModel, getTypenameFromQuery } from '@dxos/schema';
9
+ import { ProjectionModel, View, getTypenameFromQuery } from '@dxos/schema';
11
10
 
12
11
  import { meta } from '../meta';
13
12
  import { KanbanAction } from '../types';
@@ -17,15 +16,9 @@ export default (context: PluginContext) =>
17
16
  createResolver({
18
17
  intent: KanbanAction.Create,
19
18
  resolve: async ({ space, name, typename, initialPivotColumn }) => {
20
- const client = context.getCapability(ClientCapabilities.Client);
21
- const { view } = await Kanban.makeView({
22
- client,
23
- space,
24
- name,
25
- typename,
26
- pivotFieldName: initialPivotColumn,
27
- });
28
- return { data: { object: view } };
19
+ const { view } = await View.makeFromSpace({ space, typename, pivotFieldName: initialPivotColumn });
20
+ const kanban = Kanban.make({ name, view });
21
+ return { data: { object: kanban } };
29
22
  },
30
23
  }),
31
24
  createResolver({
@@ -6,14 +6,12 @@ import type * as Schema from 'effect/Schema';
6
6
  import React, { useMemo } from 'react';
7
7
 
8
8
  import { Capabilities, contributes, createSurface } from '@dxos/app-framework';
9
- import { useCapabilities } from '@dxos/app-framework/react';
10
9
  import { Obj, Type } from '@dxos/echo';
11
10
  import { findAnnotation } from '@dxos/effect';
12
- import { ClientCapabilities } from '@dxos/plugin-client';
13
11
  import { type Space, getSpace, isSpace } from '@dxos/react-client/echo';
14
- import { type InputProps, SelectInput, useFormValues } from '@dxos/react-ui-form';
12
+ import { type FormFieldComponentProps, SelectField, useFormValues } from '@dxos/react-ui-form';
15
13
  import { Kanban } from '@dxos/react-ui-kanban/types';
16
- import { type Collection, View } from '@dxos/schema';
14
+ import { type Collection } from '@dxos/schema';
17
15
 
18
16
  import { KanbanContainer, KanbanViewEditor } from '../components';
19
17
  import { meta } from '../meta';
@@ -24,17 +22,15 @@ export default () =>
24
22
  createSurface({
25
23
  id: meta.id,
26
24
  role: ['article', 'section'],
27
- filter: (data): data is { subject: View.View } =>
28
- Obj.instanceOf(View.View, data.subject) && Obj.instanceOf(Kanban.Kanban, data.subject.presentation.target),
29
- 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} />,
30
27
  }),
31
28
  createSurface({
32
29
  id: `${meta.id}/object-settings`,
33
30
  role: 'object-settings',
34
31
  position: 'hoist',
35
- filter: (data): data is { subject: View.View } =>
36
- Obj.instanceOf(View.View, data.subject) && Obj.instanceOf(Kanban.Kanban, data.subject.presentation.target),
37
- 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} />,
38
34
  }),
39
35
  createSurface({
40
36
  id: `${meta.id}/create-initial-schema-form-[pivot-column]`,
@@ -50,21 +46,19 @@ export default () =>
50
46
  return !!annotation;
51
47
  },
52
48
  component: ({ data: { target }, ...inputProps }) => {
53
- const props = inputProps as any as InputProps;
49
+ const props = inputProps as any as FormFieldComponentProps;
54
50
  const space = isSpace(target) ? target : getSpace(target);
55
51
  if (!space) {
56
52
  return null;
57
53
  }
58
- const { typename } = useFormValues();
59
- // TODO(wittjosiah): Unify this schema lookup.
60
- const schemaWhitelists = useCapabilities(ClientCapabilities.SchemaWhiteList);
61
- const staticSchema = schemaWhitelists.flat().find((schema) => Type.getTypename(schema) === typename);
62
- const [selectedSchema] = space?.db.schemaRegistry.query({ typename }).runSync();
63
54
 
55
+ const { typename } = useFormValues('KanbanForm');
56
+ const [selectedSchema] = useMemo(
57
+ () => space?.db.schemaRegistry.query({ location: ['database', 'runtime'], typename }).runSync(),
58
+ [space, typename],
59
+ );
64
60
  const singleSelectColumns = useMemo(() => {
65
- const properties = staticSchema
66
- ? Type.toJsonSchema(staticSchema).properties
67
- : selectedSchema?.jsonSchema?.properties;
61
+ const properties = Type.toJsonSchema(selectedSchema).properties;
68
62
  if (!properties) {
69
63
  return [];
70
64
  }
@@ -77,13 +71,13 @@ export default () =>
77
71
  }, []);
78
72
 
79
73
  return columns;
80
- }, [selectedSchema?.jsonSchema, staticSchema]);
74
+ }, [selectedSchema]);
81
75
 
82
76
  if (!typename) {
83
77
  return null;
84
78
  }
85
79
 
86
- return <SelectInput {...props} options={singleSelectColumns.map((column) => ({ value: column }))} />;
80
+ return <SelectField {...props} options={singleSelectColumns.map((column) => ({ value: column }))} />;
87
81
  },
88
82
  }),
89
83
  ]);
@@ -3,7 +3,7 @@
3
3
  //
4
4
 
5
5
  import { type Meta, type StoryObj } from '@storybook/react-vite';
6
- import React, { useCallback, useEffect, useState } from 'react';
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';
@@ -16,15 +16,14 @@ import { SpacePlugin } from '@dxos/plugin-space';
16
16
  import { StorybookLayoutPlugin } from '@dxos/plugin-storybook-layout';
17
17
  import { ThemePlugin } from '@dxos/plugin-theme';
18
18
  import { faker } from '@dxos/random';
19
- import { useClient } from '@dxos/react-client';
20
19
  import { Filter, useQuery, useSchema, useSpaces } from '@dxos/react-client/echo';
21
20
  import { withTheme } from '@dxos/react-ui/testing';
22
21
  import { ViewEditor } from '@dxos/react-ui-form';
23
- import { Kanban as KanbanComponent, useKanbanModel } from '@dxos/react-ui-kanban';
22
+ import { Kanban as KanbanComponent, useKanbanModel, useProjectionModel } from '@dxos/react-ui-kanban';
24
23
  import { Kanban } from '@dxos/react-ui-kanban/types';
25
- import { SyntaxHighlighter } from '@dxos/react-ui-syntax-highlighter';
24
+ import { JsonFilter } from '@dxos/react-ui-syntax-highlighter';
26
25
  import { defaultTx } from '@dxos/react-ui-theme';
27
- import { ProjectionModel, View, getTypenameFromQuery } from '@dxos/schema';
26
+ import { View, getTypenameFromQuery } from '@dxos/schema';
28
27
  import { Organization, Person } from '@dxos/types';
29
28
 
30
29
  import { translations } from '../translations';
@@ -44,37 +43,18 @@ const rollOrg = () => ({
44
43
  });
45
44
 
46
45
  const StorybookKanban = () => {
47
- const client = useClient();
48
46
  const spaces = useSpaces();
49
47
  const space = spaces[spaces.length - 1];
50
- const views = useQuery(space, Filter.type(View.View));
51
- const [view, setView] = useState<View.View>();
52
- const [projection, setProjection] = useState<ProjectionModel>();
53
- const typename = view?.query ? getTypenameFromQuery(view.query.ast) : undefined;
54
- const schema = useSchema(client, space, typename);
55
-
56
- useEffect(() => {
57
- if (views.length && !view) {
58
- const view = views[0];
59
- setView(view);
60
- }
61
- }, [views]);
62
-
63
- useEffect(() => {
64
- if (view?.projection && schema) {
65
- const jsonSchema = Type.toJsonSchema(schema);
66
- setProjection(new ProjectionModel(jsonSchema, view.projection));
67
- }
68
- // TODO(ZaymonFC): Is there a better way to get notified about deep changes in the json schema?
69
- // @dmaretskyi? Once resolved, update in multiple places (e.g., storybooks).
70
- }, [view?.projection, schema, JSON.stringify(schema ? Type.toJsonSchema(schema) : {})]);
48
+ const [object] = useQuery(space, Filter.type(Kanban.Kanban));
49
+ const typename = object?.view.target?.query ? getTypenameFromQuery(object.view.target.query.ast) : undefined;
50
+ const schema = useSchema(space, typename);
71
51
 
72
52
  const objects = useQuery(space, schema ? Filter.type(schema) : Filter.nothing());
73
53
  const filteredObjects = useGlobalFilteredObjects(objects);
74
54
 
55
+ const projection = useProjectionModel(schema, object);
75
56
  const model = useKanbanModel({
76
- view,
77
- schema,
57
+ object,
78
58
  projection,
79
59
  items: filteredObjects,
80
60
  });
@@ -95,49 +75,43 @@ const StorybookKanban = () => {
95
75
  [space, schema, model],
96
76
  );
97
77
 
98
- const handleRemoveCard = useCallback((card: { id: string }) => space.db.remove(card), [space]);
78
+ const handleRemoveCard = useCallback((card: { id: string }) => Obj.isObject(card) && space?.db.remove(card), [space]);
99
79
 
100
80
  const handleUpdateQuery = useCallback(
101
81
  (newQuery: QueryAST.Query) => {
102
82
  invariant(schema);
103
83
  invariant(Type.isMutable(schema));
104
- invariant(view);
84
+ invariant(object.view.target);
105
85
 
106
86
  schema.updateTypename(getTypenameFromQuery(newQuery));
107
- view.query.ast = newQuery;
87
+ object.view.target.query.ast = newQuery;
108
88
  },
109
- [view, schema],
89
+ [object, schema],
110
90
  );
111
91
 
112
- if (!schema || !view) {
92
+ if (!schema || !object.view.target) {
113
93
  return null;
114
94
  }
115
95
 
116
96
  return (
117
- <div className='grow grid grid-cols-[1fr_350px]'>
97
+ <div className='grow grid grid-cols-[1fr_350px] overflow-hidden'>
118
98
  {model ? <KanbanComponent model={model} onAddCard={handleAddCard} onRemoveCard={handleRemoveCard} /> : <div />}
119
- <div className='flex flex-col bs-full border-is border-separator overflow-y-auto'>
99
+ <div className='flex flex-col bs-full overflow-hidden'>
120
100
  <ViewEditor
121
101
  registry={space?.db.schemaRegistry}
122
102
  schema={schema}
123
- view={view}
103
+ view={object.view.target}
124
104
  onQueryChanged={handleUpdateQuery}
125
105
  onDelete={(fieldId: string) => {
126
106
  console.log('[ViewEditor]', 'onDelete', fieldId);
127
107
  }}
128
108
  />
129
- <SyntaxHighlighter language='json' className='text-xs'>
130
- {JSON.stringify({ view, schema }, null, 2)}
131
- </SyntaxHighlighter>
109
+ <JsonFilter data={{ view: object.view.target, schema }} classNames='text-xs' />
132
110
  </div>
133
111
  </div>
134
112
  );
135
113
  };
136
114
 
137
- type StoryProps = {
138
- rows?: number;
139
- };
140
-
141
115
  //
142
116
  // Story definitions.
143
117
  //
@@ -156,13 +130,13 @@ const meta = {
156
130
  await client.halo.createIdentity();
157
131
  const space = await client.spaces.create();
158
132
  await space.waitUntilReady();
159
- const { view } = await Kanban.makeView({
160
- client,
133
+ const { view } = await View.makeFromSpace({
161
134
  space,
162
135
  typename: Organization.Organization.typename,
163
136
  pivotFieldName: 'status',
164
137
  });
165
- space.db.add(view);
138
+ const kanban = Kanban.make({ view });
139
+ space.db.add(kanban);
166
140
 
167
141
  // TODO(burdon): Replace with sdk/schema/testing.
168
142
  Array.from({ length: 80 }).map(() => {
@@ -2,38 +2,31 @@
2
2
  // Copyright 2024 DXOS.org
3
3
  //
4
4
 
5
- import React, { useCallback, useEffect, useMemo, useState } from 'react';
5
+ import React, { useCallback, useEffect, useState } from 'react';
6
6
 
7
7
  import { createIntent } from '@dxos/app-framework';
8
- import { useIntentDispatcher } from '@dxos/app-framework/react';
8
+ import { useCapabilities, useIntentDispatcher } from '@dxos/app-framework/react';
9
9
  import { Filter, Obj, Type } from '@dxos/echo';
10
- import { EchoSchema, type TypedObject } from '@dxos/echo/internal';
10
+ import { type TypedObject } from '@dxos/echo/internal';
11
+ import { ClientCapabilities } from '@dxos/plugin-client';
11
12
  import { useGlobalFilteredObjects } from '@dxos/plugin-search';
12
- import { useClient } from '@dxos/react-client';
13
13
  import { getSpace, useQuery } from '@dxos/react-client/echo';
14
- 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';
15
16
  import { StackItem } from '@dxos/react-ui-stack';
16
- import { ProjectionModel, type View, getTypenameFromQuery } from '@dxos/schema';
17
+ import { getTypenameFromQuery } from '@dxos/schema';
17
18
 
18
19
  import { KanbanAction } from '../types';
19
20
 
20
- export const KanbanContainer = ({ view }: { view: View.View; role: string }) => {
21
- const client = useClient();
21
+ export const KanbanContainer = ({ object }: { object: Kanban.Kanban; role: string }) => {
22
+ const schemas = useCapabilities(ClientCapabilities.Schema);
22
23
  const [cardSchema, setCardSchema] = useState<TypedObject<any, any>>();
23
- const [projection, setProjection] = useState<ProjectionModel>();
24
- const space = getSpace(view);
24
+ const space = getSpace(object);
25
25
  const { dispatchPromise: dispatch } = useIntentDispatcher();
26
- const typename = view.query ? getTypenameFromQuery(view.query.ast) : undefined;
27
-
28
- const jsonSchema = useMemo(() => {
29
- if (!cardSchema) {
30
- return undefined;
31
- }
32
- return cardSchema instanceof EchoSchema ? cardSchema.jsonSchema : Type.toJsonSchema(cardSchema);
33
- }, [cardSchema]);
26
+ const typename = object.view.target?.query ? getTypenameFromQuery(object.view.target.query.ast) : undefined;
34
27
 
35
28
  useEffect(() => {
36
- const staticSchema = client.graph.schemaRegistry.schemas.find((schema) => Type.getTypename(schema) === typename);
29
+ const staticSchema = schemas.flat().find((schema) => Type.getTypename(schema) === typename);
37
30
  if (staticSchema) {
38
31
  setCardSchema(() => staticSchema as TypedObject<any, any>);
39
32
  }
@@ -50,21 +43,14 @@ export const KanbanContainer = ({ view }: { view: View.View; role: string }) =>
50
43
  );
51
44
  return unsubscribe;
52
45
  }
53
- }, [typename, space]);
54
-
55
- useEffect(() => {
56
- if (jsonSchema) {
57
- setProjection(new ProjectionModel(jsonSchema, view.projection));
58
- }
59
- // TODO(ZaymonFC): Is there a better way to get notified about deep changes in the json schema?
60
- }, [view.projection, JSON.stringify(jsonSchema)]);
46
+ }, [schemas, space, typename]);
61
47
 
62
48
  const objects = useQuery(space, cardSchema ? Filter.type(cardSchema) : Filter.nothing());
63
49
  const filteredObjects = useGlobalFilteredObjects(objects);
64
50
 
51
+ const projection = useProjectionModel(cardSchema, object);
65
52
  const model = useKanbanModel({
66
- view,
67
- schema: cardSchema,
53
+ object,
68
54
  projection,
69
55
  items: filteredObjects,
70
56
  });
@@ -90,7 +76,7 @@ export const KanbanContainer = ({ view }: { view: View.View; role: string }) =>
90
76
 
91
77
  return (
92
78
  <StackItem.Content>
93
- {model && <Kanban model={model} onAddCard={handleAddCard} onRemoveCard={handleRemoveCard} />}
79
+ {model && <KanbanComponent model={model} onAddCard={handleAddCard} onRemoveCard={handleRemoveCard} />}
94
80
  </StackItem.Content>
95
81
  );
96
82
  };
@@ -4,61 +4,51 @@
4
4
 
5
5
  import React, { useCallback, useMemo } from 'react';
6
6
 
7
- import { Type } from '@dxos/echo';
8
- import { EchoSchema, FormatEnum } from '@dxos/echo/internal';
9
- import { useClient } from '@dxos/react-client';
7
+ import { Format } from '@dxos/echo/internal';
8
+ import { invariant } from '@dxos/invariant';
10
9
  import { getSpace, useSchema } from '@dxos/react-client/echo';
11
- import { type CustomInputMap, Form, SelectInput } from '@dxos/react-ui-form';
12
- import { Kanban } from '@dxos/react-ui-kanban/types';
13
- import { ProjectionModel, type View, getTypenameFromQuery } from '@dxos/schema';
10
+ import { Form, type FormFieldMap, SelectField } from '@dxos/react-ui-form';
11
+ import { useProjectionModel } from '@dxos/react-ui-kanban';
12
+ import { type Kanban } from '@dxos/react-ui-kanban/types';
13
+ import { getTypenameFromQuery } from '@dxos/schema';
14
14
 
15
- type KanbanViewEditorProps = { view: View.View };
15
+ import { SettingsSchema } from '../types';
16
16
 
17
- export const KanbanViewEditor = ({ view }: KanbanViewEditorProps) => {
18
- const client = useClient();
19
- const space = getSpace(view);
20
- const currentTypename = view.query ? getTypenameFromQuery(view.query.ast) : undefined;
21
- const schema = useSchema(client, space, currentTypename);
17
+ type KanbanViewEditorProps = { object: Kanban.Kanban };
22
18
 
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)]);
19
+ export const KanbanViewEditor = ({ object }: KanbanViewEditorProps) => {
20
+ const space = getSpace(object);
21
+ const view = object.view.target;
22
+ const currentTypename = view?.query ? getTypenameFromQuery(view.query.ast) : undefined;
23
+ const schema = useSchema(space, currentTypename);
24
+ const projection = useProjectionModel(schema, object);
31
25
 
32
26
  const fieldProjections = projection?.getFieldProjections() || [];
33
27
  const selectFields = fieldProjections
34
- .filter((field) => field.props.format === FormatEnum.SingleSelect)
28
+ .filter((field) => field.props.format === Format.TypeFormat.SingleSelect)
35
29
  .map(({ field }) => ({ value: field.id, label: field.path }));
36
30
 
37
31
  const handleSave = useCallback(
38
32
  (values: Partial<{ columnFieldId: string }>) => {
33
+ invariant(view);
39
34
  view.projection.pivotFieldId = values.columnFieldId;
40
35
  },
41
36
  [view],
42
37
  );
43
38
 
44
39
  const initialValues = useMemo(
45
- () => ({ columnFieldId: view.projection.pivotFieldId }),
46
- [view.projection.pivotFieldId],
40
+ () => ({ columnFieldId: view?.projection.pivotFieldId }),
41
+ [view?.projection.pivotFieldId],
47
42
  );
48
- const custom: CustomInputMap = useMemo(
49
- () => ({ columnFieldId: (props) => <SelectInput {...props} options={selectFields} /> }),
43
+
44
+ const fieldMap: FormFieldMap = useMemo(
45
+ () => ({ columnFieldId: (props) => <SelectField {...props} options={selectFields} /> }),
50
46
  [selectFields],
51
47
  );
52
48
 
53
49
  return (
54
- <Form
55
- Custom={custom}
56
- schema={Kanban.SettingsSchema}
57
- values={initialValues}
58
- onSave={handleSave}
59
- autoSave
60
- outerSpacing={false}
61
- classNames='pbs-inputSpacingBlock'
62
- />
50
+ <Form.Root schema={SettingsSchema} values={initialValues} fieldMap={fieldMap} autoSave onSave={handleSave}>
51
+ <Form.FieldSet />
52
+ </Form.Root>
63
53
  );
64
54
  };
@@ -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.typename]: {
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
  },