@dxos/plugin-kanban 0.8.4-main.fcfe5033a5 → 0.8.4-staging.60fe92afc8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +102 -5
- package/PLUGIN.mdl +398 -0
- package/README.md +1 -1
- package/dist/lib/neutral/KanbanArticle-T4CPKAZH.mjs +132 -0
- package/dist/lib/neutral/KanbanArticle-T4CPKAZH.mjs.map +7 -0
- package/dist/lib/neutral/KanbanPlugin.mjs +44 -0
- package/dist/lib/neutral/KanbanPlugin.mjs.map +7 -0
- package/dist/lib/neutral/KanbanPlugin.node.mjs +27 -0
- package/dist/lib/neutral/KanbanPlugin.node.mjs.map +7 -0
- package/dist/lib/neutral/KanbanPlugin.workerd.mjs +21 -0
- package/dist/lib/neutral/KanbanPlugin.workerd.mjs.map +7 -0
- package/dist/lib/neutral/KanbanSettings-5WOS4CUE.mjs +83 -0
- package/dist/lib/neutral/KanbanSettings-5WOS4CUE.mjs.map +7 -0
- package/dist/lib/neutral/blueprint-definition-6DV3Q5MC.mjs +15 -0
- package/dist/lib/neutral/blueprint-definition-6DV3Q5MC.mjs.map +7 -0
- package/dist/lib/neutral/blueprints/index.mjs +8 -0
- package/dist/lib/neutral/capabilities/index.mjs +17 -0
- package/dist/lib/neutral/capabilities/index.mjs.map +7 -0
- package/dist/lib/neutral/chunk-6ZHHQWO5.mjs +39 -0
- package/dist/lib/neutral/chunk-6ZHHQWO5.mjs.map +7 -0
- package/dist/lib/neutral/chunk-DAKIZO46.mjs +246 -0
- package/dist/lib/neutral/chunk-DAKIZO46.mjs.map +7 -0
- package/dist/lib/neutral/chunk-M5ISZWZU.mjs +8 -0
- package/dist/lib/neutral/chunk-M5ISZWZU.mjs.map +7 -0
- package/dist/lib/{browser/blueprints/index.mjs → neutral/chunk-ZTQW5KQS.mjs} +4 -5
- package/dist/lib/neutral/chunk-ZTQW5KQS.mjs.map +7 -0
- package/dist/lib/neutral/components/index.mjs +243 -0
- package/dist/lib/neutral/components/index.mjs.map +7 -0
- package/dist/lib/neutral/containers/index.mjs +11 -0
- package/dist/lib/neutral/containers/index.mjs.map +7 -0
- package/dist/lib/neutral/create-object-DKBSI46K.mjs +40 -0
- package/dist/lib/neutral/create-object-DKBSI46K.mjs.map +7 -0
- package/dist/lib/{browser/delete-card-VPNVIWOA.mjs → neutral/delete-card-VNAV3CZV.mjs} +6 -14
- package/dist/lib/neutral/delete-card-VNAV3CZV.mjs.map +7 -0
- package/dist/lib/neutral/delete-card-field-XHOLGS6L.mjs +39 -0
- package/dist/lib/neutral/delete-card-field-XHOLGS6L.mjs.map +7 -0
- package/dist/lib/neutral/hooks/index.mjs +431 -0
- package/dist/lib/neutral/hooks/index.mjs.map +7 -0
- package/dist/lib/neutral/index.mjs +34 -0
- package/dist/lib/neutral/index.mjs.map +7 -0
- package/dist/lib/neutral/meta.json +1 -0
- package/dist/lib/neutral/meta.mjs +8 -0
- package/dist/lib/neutral/meta.mjs.map +7 -0
- package/dist/lib/neutral/operation-handler-B7IW6MXU.mjs +13 -0
- package/dist/lib/neutral/operation-handler-B7IW6MXU.mjs.map +7 -0
- package/dist/lib/neutral/operations/index.mjs +8 -0
- package/dist/lib/neutral/operations/index.mjs.map +7 -0
- package/dist/lib/neutral/plugin.mjs +16 -0
- package/dist/lib/neutral/plugin.mjs.map +7 -0
- package/dist/lib/neutral/react-surface-VZEVEJL5.mjs +91 -0
- package/dist/lib/neutral/react-surface-VZEVEJL5.mjs.map +7 -0
- package/dist/lib/{browser/restore-card-4GG2RYKR.mjs → neutral/restore-card-EKVEPATL.mjs} +6 -14
- package/dist/lib/neutral/restore-card-EKVEPATL.mjs.map +7 -0
- package/dist/lib/neutral/restore-card-field-TQCTGGNO.mjs +37 -0
- package/dist/lib/neutral/restore-card-field-TQCTGGNO.mjs.map +7 -0
- package/dist/lib/neutral/testing/index.mjs +62 -0
- package/dist/lib/neutral/testing/index.mjs.map +7 -0
- package/dist/lib/neutral/translations.mjs +44 -0
- package/dist/lib/neutral/translations.mjs.map +7 -0
- package/dist/lib/neutral/types/index.mjs +22 -0
- package/dist/lib/neutral/types/index.mjs.map +7 -0
- package/dist/lib/neutral/undo-mappings-6CHW6BOF.mjs +42 -0
- package/dist/lib/neutral/undo-mappings-6CHW6BOF.mjs.map +7 -0
- package/dist/types/src/KanbanPlugin.d.ts +1 -0
- package/dist/types/src/KanbanPlugin.d.ts.map +1 -1
- package/dist/types/src/KanbanPlugin.node.d.ts +4 -0
- package/dist/types/src/KanbanPlugin.node.d.ts.map +1 -0
- package/dist/types/src/KanbanPlugin.test.d.ts +2 -0
- package/dist/types/src/KanbanPlugin.test.d.ts.map +1 -0
- package/dist/types/src/KanbanPlugin.workerd.d.ts +4 -0
- package/dist/types/src/KanbanPlugin.workerd.d.ts.map +1 -0
- package/dist/types/src/blueprints/kanban-blueprint.d.ts +2 -2
- package/dist/types/src/blueprints/kanban-blueprint.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/blueprint-definition.d.ts.map +1 -1
- package/dist/types/src/capabilities/create-object.d.ts +11 -0
- package/dist/types/src/capabilities/create-object.d.ts.map +1 -0
- package/dist/types/src/capabilities/index.d.ts +9 -2
- package/dist/types/src/capabilities/index.d.ts.map +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts +1 -1
- package/dist/types/src/capabilities/operation-handler.d.ts.map +1 -1
- package/dist/types/src/capabilities/react-surface.d.ts.map +1 -1
- package/dist/types/src/capabilities/undo-mappings.d.ts.map +1 -1
- package/dist/types/src/components/KanbanBoard/KanbanBoard.d.ts +9 -29
- package/dist/types/src/components/KanbanBoard/KanbanBoard.d.ts.map +1 -1
- package/dist/types/src/components/KanbanBoard/KanbanBoard.stories.d.ts +24 -24
- package/dist/types/src/components/KanbanBoard/KanbanBoard.stories.d.ts.map +1 -1
- package/dist/types/src/components/KanbanBoard/KanbanCard.d.ts +2 -3
- package/dist/types/src/components/KanbanBoard/KanbanCard.d.ts.map +1 -1
- package/dist/types/src/components/KanbanBoard/KanbanColumn.d.ts +2 -3
- package/dist/types/src/components/KanbanBoard/KanbanColumn.d.ts.map +1 -1
- package/dist/types/src/components/KanbanBoard/context.d.ts +38 -0
- package/dist/types/src/components/KanbanBoard/context.d.ts.map +1 -0
- package/dist/types/src/containers/KanbanArticle/KanbanArticle.d.ts +6 -0
- package/dist/types/src/containers/KanbanArticle/KanbanArticle.d.ts.map +1 -0
- package/dist/types/src/containers/{KanbanContainer/KanbanContainer.stories.d.ts → KanbanArticle/KanbanArticle.stories.d.ts} +26 -26
- package/dist/types/src/containers/KanbanArticle/KanbanArticle.stories.d.ts.map +1 -0
- package/dist/types/src/containers/KanbanArticle/index.d.ts +2 -0
- package/dist/types/src/containers/KanbanArticle/index.d.ts.map +1 -0
- package/dist/types/src/containers/KanbanSettings/KanbanSettings.d.ts +13 -0
- package/dist/types/src/containers/KanbanSettings/KanbanSettings.d.ts.map +1 -0
- package/dist/types/src/containers/KanbanSettings/index.d.ts +2 -0
- package/dist/types/src/containers/KanbanSettings/index.d.ts.map +1 -0
- package/dist/types/src/containers/index.d.ts +2 -2
- package/dist/types/src/containers/index.d.ts.map +1 -1
- package/dist/types/src/hooks/index.d.ts +1 -0
- package/dist/types/src/hooks/index.d.ts.map +1 -1
- package/dist/types/src/hooks/useEchoChangeCallback.d.ts.map +1 -1
- package/dist/types/src/hooks/useItemsProjection.d.ts +10 -0
- package/dist/types/src/hooks/useItemsProjection.d.ts.map +1 -0
- package/dist/types/src/hooks/useKanbanBoardModel.browser.test.d.ts +2 -0
- package/dist/types/src/hooks/useKanbanBoardModel.browser.test.d.ts.map +1 -0
- package/dist/types/src/hooks/useKanbanBoardModel.d.ts.map +1 -1
- package/dist/types/src/hooks/useKanbanColumnEventHandler.d.ts +1 -1
- package/dist/types/src/hooks/useKanbanColumnEventHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useKanbanItemEventHandler.d.ts +1 -1
- package/dist/types/src/hooks/useKanbanItemEventHandler.d.ts.map +1 -1
- package/dist/types/src/hooks/useProjectionModel.d.ts.map +1 -1
- package/dist/types/src/index.d.ts +3 -1
- package/dist/types/src/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +1 -1
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/operations/delete-card-field.d.ts +3 -3
- package/dist/types/src/operations/delete-card-field.d.ts.map +1 -1
- package/dist/types/src/operations/delete-card.d.ts +3 -3
- package/dist/types/src/operations/delete-card.d.ts.map +1 -1
- package/dist/types/src/operations/index.d.ts +1 -2
- package/dist/types/src/operations/index.d.ts.map +1 -1
- package/dist/types/src/operations/restore-card-field.d.ts +3 -3
- package/dist/types/src/operations/restore-card-field.d.ts.map +1 -1
- package/dist/types/src/operations/restore-card.d.ts +3 -3
- package/dist/types/src/operations/restore-card.d.ts.map +1 -1
- package/dist/types/src/playwright/board-manager.d.ts.map +1 -1
- package/dist/types/src/playwright/playwright.config.d.ts.map +1 -1
- package/dist/types/src/plugin.d.ts +4 -0
- package/dist/types/src/plugin.d.ts.map +1 -0
- package/dist/types/src/translations.d.ts +24 -24
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/Kanban.d.ts +66 -9
- package/dist/types/src/types/Kanban.d.ts.map +1 -1
- package/dist/types/src/{operations/definitions.d.ts → types/KanbanOperation.d.ts} +4 -4
- package/dist/types/src/types/KanbanOperation.d.ts.map +1 -0
- package/dist/types/src/types/constants.d.ts +3 -3
- package/dist/types/src/types/constants.d.ts.map +1 -1
- package/dist/types/src/types/index.d.ts +2 -1
- package/dist/types/src/types/index.d.ts.map +1 -1
- package/dist/types/src/types/schema.d.ts +15 -1
- package/dist/types/src/types/schema.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +2 -2
- package/dist/types/src/util/arrangement.d.ts +8 -4
- package/dist/types/src/util/arrangement.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +110 -76
- package/src/KanbanPlugin.node.ts +21 -0
- package/src/KanbanPlugin.test.ts +31 -0
- package/src/KanbanPlugin.tsx +12 -39
- package/src/KanbanPlugin.workerd.ts +18 -0
- package/src/blueprints/kanban-blueprint.ts +2 -3
- package/src/capabilities/artifact-definition.ts +10 -9
- package/src/capabilities/blueprint-definition.ts +6 -4
- package/src/capabilities/create-object.ts +40 -0
- package/src/capabilities/index.ts +9 -2
- package/src/capabilities/operation-handler.ts +1 -1
- package/src/capabilities/react-surface.tsx +31 -14
- package/src/capabilities/undo-mappings.ts +1 -1
- package/src/components/KanbanBoard/KanbanBoard.stories.tsx +9 -6
- package/src/components/KanbanBoard/KanbanBoard.tsx +22 -51
- package/src/components/KanbanBoard/KanbanCard.tsx +75 -60
- package/src/components/KanbanBoard/KanbanColumn.tsx +16 -13
- package/src/components/KanbanBoard/context.ts +54 -0
- package/src/containers/{KanbanContainer/KanbanContainer.stories.tsx → KanbanArticle/KanbanArticle.stories.tsx} +48 -42
- package/src/containers/KanbanArticle/KanbanArticle.tsx +179 -0
- package/src/containers/KanbanArticle/index.ts +5 -0
- package/src/containers/KanbanSettings/KanbanSettings.tsx +94 -0
- package/src/containers/KanbanSettings/index.ts +5 -0
- package/src/containers/index.ts +2 -2
- package/src/hooks/index.ts +1 -0
- package/src/hooks/useEchoChangeCallback.ts +2 -2
- package/src/hooks/useItemsProjection.ts +44 -0
- package/src/hooks/{useKanbanBoardModel.test.ts → useKanbanBoardModel.browser.test.ts} +14 -19
- package/src/hooks/useKanbanBoardModel.ts +19 -7
- package/src/hooks/useProjectionModel.ts +4 -4
- package/src/index.ts +3 -2
- package/src/meta.ts +22 -5
- package/src/operations/delete-card-field.ts +11 -16
- package/src/operations/delete-card.ts +3 -3
- package/src/operations/index.ts +1 -3
- package/src/operations/restore-card-field.ts +11 -16
- package/src/operations/restore-card.ts +3 -3
- package/src/playwright/smoke.spec.ts +3 -3
- package/src/plugin.ts +11 -0
- package/src/testing/KanbanCardTileSimple.tsx +6 -6
- package/src/types/Kanban.ts +86 -23
- package/src/{operations/definitions.ts → types/KanbanOperation.ts} +25 -9
- package/src/types/index.ts +3 -1
- package/src/types/schema.ts +20 -2
- package/src/types/types.ts +2 -2
- package/src/util/arrangement.test.ts +22 -13
- package/src/util/arrangement.ts +25 -15
- package/src/vite-env.d.ts +10 -0
- package/dist/lib/browser/blueprints/index.mjs.map +0 -7
- package/dist/lib/browser/chunk-A3PBV3S5.mjs +0 -105
- package/dist/lib/browser/chunk-A3PBV3S5.mjs.map +0 -7
- package/dist/lib/browser/delete-card-VPNVIWOA.mjs.map +0 -7
- package/dist/lib/browser/delete-card-field-4HHF2GYX.mjs +0 -50
- package/dist/lib/browser/delete-card-field-4HHF2GYX.mjs.map +0 -7
- package/dist/lib/browser/index.mjs +0 -121
- package/dist/lib/browser/index.mjs.map +0 -7
- package/dist/lib/browser/meta.json +0 -1
- package/dist/lib/browser/operations/index.mjs +0 -13
- package/dist/lib/browser/operations/index.mjs.map +0 -7
- package/dist/lib/browser/restore-card-4GG2RYKR.mjs.map +0 -7
- package/dist/lib/browser/restore-card-field-3T26ACYX.mjs +0 -48
- package/dist/lib/browser/restore-card-field-3T26ACYX.mjs.map +0 -7
- package/dist/lib/browser/types/index.mjs +0 -100
- package/dist/lib/browser/types/index.mjs.map +0 -7
- package/dist/lib/node-esm/blueprints/index.mjs +0 -28
- package/dist/lib/node-esm/blueprints/index.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-6LELYA2G.mjs +0 -106
- package/dist/lib/node-esm/chunk-6LELYA2G.mjs.map +0 -7
- package/dist/lib/node-esm/chunk-HSLMI22Q.mjs +0 -11
- package/dist/lib/node-esm/delete-card-5PW5OMFN.mjs +0 -33
- package/dist/lib/node-esm/delete-card-5PW5OMFN.mjs.map +0 -7
- package/dist/lib/node-esm/delete-card-field-KPJU2AQ3.mjs +0 -51
- package/dist/lib/node-esm/delete-card-field-KPJU2AQ3.mjs.map +0 -7
- package/dist/lib/node-esm/index.mjs +0 -122
- package/dist/lib/node-esm/index.mjs.map +0 -7
- package/dist/lib/node-esm/meta.json +0 -1
- package/dist/lib/node-esm/operations/index.mjs +0 -14
- package/dist/lib/node-esm/operations/index.mjs.map +0 -7
- package/dist/lib/node-esm/restore-card-X2TKMU5A.mjs +0 -30
- package/dist/lib/node-esm/restore-card-X2TKMU5A.mjs.map +0 -7
- package/dist/lib/node-esm/restore-card-field-IUTL4RTR.mjs +0 -49
- package/dist/lib/node-esm/restore-card-field-IUTL4RTR.mjs.map +0 -7
- package/dist/lib/node-esm/types/index.mjs +0 -101
- package/dist/lib/node-esm/types/index.mjs.map +0 -7
- package/dist/types/src/containers/KanbanContainer/KanbanContainer.d.ts +0 -6
- package/dist/types/src/containers/KanbanContainer/KanbanContainer.d.ts.map +0 -1
- package/dist/types/src/containers/KanbanContainer/KanbanContainer.stories.d.ts.map +0 -1
- package/dist/types/src/containers/KanbanContainer/index.d.ts +0 -2
- package/dist/types/src/containers/KanbanContainer/index.d.ts.map +0 -1
- package/dist/types/src/containers/KanbanViewEditor/KanbanViewEditor.d.ts +0 -6
- package/dist/types/src/containers/KanbanViewEditor/KanbanViewEditor.d.ts.map +0 -1
- package/dist/types/src/containers/KanbanViewEditor/index.d.ts +0 -2
- package/dist/types/src/containers/KanbanViewEditor/index.d.ts.map +0 -1
- package/dist/types/src/hooks/useKanbanBoardModel.test.d.ts +0 -2
- package/dist/types/src/hooks/useKanbanBoardModel.test.d.ts.map +0 -1
- package/dist/types/src/operations/definitions.d.ts.map +0 -1
- package/src/containers/KanbanContainer/KanbanContainer.tsx +0 -96
- package/src/containers/KanbanContainer/index.ts +0 -5
- package/src/containers/KanbanViewEditor/KanbanViewEditor.tsx +0 -63
- package/src/containers/KanbanViewEditor/index.ts +0 -5
- /package/dist/lib/{browser/chunk-J5LGTIGS.mjs.map → neutral/blueprints/index.mjs.map} +0 -0
- /package/dist/lib/{browser → neutral}/chunk-J5LGTIGS.mjs +0 -0
- /package/dist/lib/{node-esm/chunk-HSLMI22Q.mjs.map → neutral/chunk-J5LGTIGS.mjs.map} +0 -0
|
@@ -6,8 +6,7 @@ import { Atom, RegistryContext } from '@effect-atom/atom-react';
|
|
|
6
6
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
7
7
|
import React, { useCallback, useContext, useEffect, useMemo, useState } from 'react';
|
|
8
8
|
|
|
9
|
-
import { Filter, JsonSchema, Obj, Query } from '@dxos/echo';
|
|
10
|
-
import { type View } from '@dxos/echo';
|
|
9
|
+
import { Filter, JsonSchema, Obj, Query, type View } from '@dxos/echo';
|
|
11
10
|
import { random } from '@dxos/random';
|
|
12
11
|
import { withMosaic } from '@dxos/react-ui-mosaic/testing';
|
|
13
12
|
import { Loading, withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
@@ -17,9 +16,9 @@ import { Organization } from '@dxos/types';
|
|
|
17
16
|
|
|
18
17
|
import { createEchoChangeCallback as createKanbanChangeCallback } from '#hooks';
|
|
19
18
|
import { KanbanCardTileSimple } from '#testing';
|
|
19
|
+
import { translations } from '#translations';
|
|
20
20
|
import { Kanban } from '#types';
|
|
21
21
|
|
|
22
|
-
import { translations } from '../../translations';
|
|
23
22
|
import { KanbanBoard } from './KanbanBoard';
|
|
24
23
|
|
|
25
24
|
random.seed(1);
|
|
@@ -48,7 +47,7 @@ const DefaultStory = () => {
|
|
|
48
47
|
|
|
49
48
|
useEffect(() => {
|
|
50
49
|
const view = ViewModel.make({
|
|
51
|
-
query: Query.select(Filter.
|
|
50
|
+
query: Query.select(Filter.type(Organization.Organization)),
|
|
52
51
|
jsonSchema: JsonSchema.toJsonSchema(Organization.Organization),
|
|
53
52
|
pivotFieldName: 'status',
|
|
54
53
|
});
|
|
@@ -79,7 +78,9 @@ const DefaultStory = () => {
|
|
|
79
78
|
|
|
80
79
|
const handleCardAdd = useCallback(
|
|
81
80
|
(columnValue: string | undefined) => {
|
|
82
|
-
if (!state || !columnFieldPath || !registry)
|
|
81
|
+
if (!state || !columnFieldPath || !registry) {
|
|
82
|
+
return undefined;
|
|
83
|
+
}
|
|
83
84
|
const card = Obj.make(Organization.Organization, {
|
|
84
85
|
...createOrg(),
|
|
85
86
|
...(columnFieldPath ? { [columnFieldPath]: columnValue } : {}),
|
|
@@ -93,7 +94,9 @@ const DefaultStory = () => {
|
|
|
93
94
|
|
|
94
95
|
const handleCardRemove = useCallback(
|
|
95
96
|
(card: Obj.Unknown) => {
|
|
96
|
-
if (!registry)
|
|
97
|
+
if (!registry) {
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
97
100
|
const current = registry.get(items) ?? [];
|
|
98
101
|
registry.set(
|
|
99
102
|
items,
|
|
@@ -3,64 +3,30 @@
|
|
|
3
3
|
//
|
|
4
4
|
|
|
5
5
|
import { type Atom, RegistryContext } from '@effect-atom/atom-react';
|
|
6
|
-
import {
|
|
7
|
-
import React, {
|
|
8
|
-
type ComponentPropsWithoutRef,
|
|
9
|
-
type ComponentType,
|
|
10
|
-
type PropsWithChildren,
|
|
11
|
-
useCallback,
|
|
12
|
-
useContext,
|
|
13
|
-
useMemo,
|
|
14
|
-
} from 'react';
|
|
6
|
+
import React, { type ComponentPropsWithoutRef, type PropsWithChildren, useCallback, useContext, useMemo } from 'react';
|
|
15
7
|
|
|
16
8
|
import { Obj } from '@dxos/echo';
|
|
17
9
|
import { useTranslation } from '@dxos/react-ui';
|
|
10
|
+
import { composable, composableProps } from '@dxos/react-ui';
|
|
18
11
|
import { Board, useBoard } from '@dxos/react-ui-mosaic';
|
|
19
12
|
import type { ProjectionModel } from '@dxos/schema';
|
|
20
|
-
import { composable, composableProps } from '@dxos/ui-theme';
|
|
21
13
|
|
|
22
14
|
import { useKanbanBoardModel, useKanbanColumnEventHandler } from '#hooks';
|
|
23
15
|
import { meta } from '#meta';
|
|
24
|
-
import { type Kanban,
|
|
25
|
-
|
|
26
|
-
import {
|
|
27
|
-
|
|
16
|
+
import { type Kanban, UNCATEGORIZED_ATTRIBUTES, UNCATEGORIZED_VALUE } from '#types';
|
|
17
|
+
|
|
18
|
+
import {
|
|
19
|
+
KanbanBoardContext,
|
|
20
|
+
type KanbanBoardContextValue,
|
|
21
|
+
type KanbanCardProps,
|
|
22
|
+
type KanbanColumnProps,
|
|
23
|
+
useKanbanBoard,
|
|
24
|
+
} from './context';
|
|
25
|
+
import { KanbanCard } from './KanbanCard';
|
|
26
|
+
import { KanbanColumn } from './KanbanColumn';
|
|
28
27
|
|
|
29
28
|
// TODO(burdon): Rename Kanban.
|
|
30
29
|
|
|
31
|
-
//
|
|
32
|
-
// Context
|
|
33
|
-
//
|
|
34
|
-
|
|
35
|
-
const KANBAN_BOARD_NAME = 'KanbanBoard.Context';
|
|
36
|
-
|
|
37
|
-
/**
|
|
38
|
-
* Context value for the Kanban board.
|
|
39
|
-
* Items are Echo objects (Obj.Unknown).
|
|
40
|
-
*/
|
|
41
|
-
type KanbanBoardContextValue = {
|
|
42
|
-
kanbanId: string;
|
|
43
|
-
projection: ProjectionModel | undefined;
|
|
44
|
-
columnFieldPath: string | undefined;
|
|
45
|
-
change: KanbanChangeCallback<Obj.Unknown>;
|
|
46
|
-
pivotFieldId: string | undefined;
|
|
47
|
-
getPivotAttributes: (columnValue: string) => { title: string; color: string };
|
|
48
|
-
itemTile?: ComponentType<KanbanCardProps>; // TODO(burdon): Prop.
|
|
49
|
-
onCardAdd?: (columnValue: string | undefined) => string | undefined;
|
|
50
|
-
onCardRemove?: (card: Obj.Unknown) => void;
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
const [KanbanBoardContext, useKanbanBoard] = createContext<KanbanBoardContextValue>(KANBAN_BOARD_NAME, {
|
|
54
|
-
kanbanId: 'never',
|
|
55
|
-
projection: undefined,
|
|
56
|
-
columnFieldPath: undefined,
|
|
57
|
-
change: { kanban: () => {}, setItemField: () => {} },
|
|
58
|
-
pivotFieldId: undefined,
|
|
59
|
-
getPivotAttributes: (id: string) =>
|
|
60
|
-
id === UNCATEGORIZED_VALUE ? UNCATEGORIZED_ATTRIBUTES : { title: id, color: 'neutral' },
|
|
61
|
-
itemTile: (() => null) as ComponentType<KanbanCardProps>,
|
|
62
|
-
});
|
|
63
|
-
|
|
64
30
|
//
|
|
65
31
|
// Root
|
|
66
32
|
//
|
|
@@ -94,15 +60,20 @@ export const KanbanBoardRoot = ({
|
|
|
94
60
|
const { t } = useTranslation(meta.id);
|
|
95
61
|
const model = useKanbanBoardModel(kanban, projection, items, registry);
|
|
96
62
|
const columns = model?.getColumns?.() ?? [];
|
|
97
|
-
const view = kanban?.view
|
|
63
|
+
const view = kanban?.spec.kind === 'view' ? kanban.spec.view.target : undefined;
|
|
98
64
|
const pivotFieldId = view?.projection?.pivotFieldId;
|
|
99
65
|
const columnFieldPath = useMemo(() => {
|
|
66
|
+
// Items-variant kanbans use the property name itself as the pivot field
|
|
67
|
+
// (no view/projection translation layer).
|
|
68
|
+
if (kanban?.spec.kind === 'items') {
|
|
69
|
+
return kanban.spec.pivotField;
|
|
70
|
+
}
|
|
100
71
|
if (pivotFieldId === undefined || !projection) {
|
|
101
72
|
return undefined;
|
|
102
73
|
}
|
|
103
74
|
|
|
104
75
|
return projection.tryGetFieldProjection(pivotFieldId)?.props.property;
|
|
105
|
-
}, [projection, pivotFieldId]);
|
|
76
|
+
}, [kanban?.spec, projection, pivotFieldId]);
|
|
106
77
|
|
|
107
78
|
const getPivotAttributes = useCallback<KanbanBoardContextValue['getPivotAttributes']>(
|
|
108
79
|
(columnValue) => {
|
|
@@ -119,7 +90,7 @@ export const KanbanBoardRoot = ({
|
|
|
119
90
|
|
|
120
91
|
if (columns.length === 0) {
|
|
121
92
|
return (
|
|
122
|
-
<div
|
|
93
|
+
<div className='flex flex-1 items-center justify-center p-8 text-center text-description'>
|
|
123
94
|
{t('select-pivot.placeholder')}
|
|
124
95
|
</div>
|
|
125
96
|
);
|
|
@@ -127,7 +98,7 @@ export const KanbanBoardRoot = ({
|
|
|
127
98
|
|
|
128
99
|
return (
|
|
129
100
|
<KanbanBoardContext
|
|
130
|
-
kanbanId={Obj.
|
|
101
|
+
kanbanId={Obj.getURI(kanban)}
|
|
131
102
|
projection={projection}
|
|
132
103
|
columnFieldPath={columnFieldPath}
|
|
133
104
|
pivotFieldId={pivotFieldId}
|
|
@@ -9,78 +9,93 @@ import { AppSurface, useObjectMenuItems } from '@dxos/app-toolkit/ui';
|
|
|
9
9
|
import { Obj } from '@dxos/echo';
|
|
10
10
|
import { Card, Toolbar, useTranslation } from '@dxos/react-ui';
|
|
11
11
|
import { Menu, createMenuAction } from '@dxos/react-ui-menu';
|
|
12
|
-
import { Focus, Mosaic,
|
|
12
|
+
import { Focus, Mosaic, useBoard } from '@dxos/react-ui-mosaic';
|
|
13
13
|
|
|
14
14
|
import { meta } from '#meta';
|
|
15
15
|
|
|
16
|
-
import { useKanbanBoard } from './
|
|
16
|
+
import { type KanbanCardProps, useKanbanBoard } from './context';
|
|
17
17
|
|
|
18
|
-
|
|
18
|
+
export { type KanbanCardProps };
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
const KANBAN_CARD_TILE_NAME = 'KanbanBoard.Card';
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Mosaic Tile for Kanban card.
|
|
24
24
|
* Uses Surface for content; requires plugin manager context.
|
|
25
25
|
*/
|
|
26
|
-
export const KanbanCard = forwardRef<HTMLDivElement, KanbanCardProps>(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
26
|
+
export const KanbanCard = forwardRef<HTMLDivElement, KanbanCardProps>(
|
|
27
|
+
({ data, location, debug, draggable }, forwardedRef) => {
|
|
28
|
+
const { t } = useTranslation(meta.id);
|
|
29
|
+
const { model } = useBoard(KANBAN_CARD_TILE_NAME);
|
|
30
|
+
const { projection, columnFieldPath, onCardRemove } = useKanbanBoard(KANBAN_CARD_TILE_NAME);
|
|
31
|
+
const [dragHandle, setDragHandle] = useState<HTMLButtonElement | null>(null);
|
|
32
|
+
const dragHandleRef = useCallback((el: HTMLButtonElement | null) => setDragHandle(el), []);
|
|
32
33
|
|
|
33
|
-
|
|
34
|
+
const objectMenuItems = useObjectMenuItems(data);
|
|
34
35
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
const menuItems = useMemo(
|
|
37
|
+
() => [
|
|
38
|
+
...objectMenuItems,
|
|
39
|
+
...(onCardRemove
|
|
40
|
+
? [
|
|
41
|
+
createMenuAction('remove', () => onCardRemove(data), {
|
|
42
|
+
label: t('remove-card.label'),
|
|
43
|
+
icon: 'ph--trash--regular',
|
|
44
|
+
}),
|
|
45
|
+
]
|
|
46
|
+
: []),
|
|
47
|
+
],
|
|
48
|
+
[objectMenuItems, onCardRemove, data, t],
|
|
49
|
+
);
|
|
49
50
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
<
|
|
62
|
-
<Card.
|
|
63
|
-
<Card.
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
<
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
51
|
+
return (
|
|
52
|
+
<Menu.Root>
|
|
53
|
+
<Mosaic.Tile
|
|
54
|
+
asChild
|
|
55
|
+
id={model.getItemId(data)}
|
|
56
|
+
data={data}
|
|
57
|
+
location={location}
|
|
58
|
+
debug={debug}
|
|
59
|
+
draggable={draggable}
|
|
60
|
+
dragHandle={dragHandle}
|
|
61
|
+
>
|
|
62
|
+
<Focus.Item asChild>
|
|
63
|
+
<Card.Root ref={forwardedRef} data-testid='board-item'>
|
|
64
|
+
<Card.Header>
|
|
65
|
+
<Card.DragHandle ref={dragHandleRef} testId='mosaicBoard.cardDragHandle' />
|
|
66
|
+
<Card.Title data-testid='mosaicBoard.cardTitle'>{Obj.getLabel(data)}</Card.Title>
|
|
67
|
+
{/* TODO(wittjosiah): Reconcile with Card.Menu. */}
|
|
68
|
+
<Menu.Trigger asChild disabled={!menuItems?.length}>
|
|
69
|
+
<Toolbar.IconButton
|
|
70
|
+
iconOnly
|
|
71
|
+
variant='ghost'
|
|
72
|
+
icon='ph--dots-three-vertical--regular'
|
|
73
|
+
label={t('action-menu.label')}
|
|
74
|
+
/>
|
|
75
|
+
</Menu.Trigger>
|
|
76
|
+
<Menu.Content items={menuItems} />
|
|
77
|
+
</Card.Header>
|
|
78
|
+
<Card.Body>
|
|
79
|
+
{projection && (
|
|
80
|
+
<Surface.Surface
|
|
81
|
+
type={AppSurface.Card}
|
|
82
|
+
limit={1}
|
|
83
|
+
data={{
|
|
84
|
+
subject: data,
|
|
85
|
+
projection,
|
|
86
|
+
// Hide the pivot field: its value is already conveyed by
|
|
87
|
+
// which column the card sits in.
|
|
88
|
+
ignorePaths: columnFieldPath ? [columnFieldPath] : undefined,
|
|
89
|
+
}}
|
|
90
|
+
/>
|
|
91
|
+
)}
|
|
92
|
+
</Card.Body>
|
|
93
|
+
</Card.Root>
|
|
94
|
+
</Focus.Item>
|
|
95
|
+
</Mosaic.Tile>
|
|
96
|
+
</Menu.Root>
|
|
97
|
+
);
|
|
98
|
+
},
|
|
99
|
+
);
|
|
85
100
|
|
|
86
101
|
KanbanCard.displayName = KANBAN_CARD_TILE_NAME;
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import React, { FC, forwardRef,
|
|
5
|
+
import React, { FC, forwardRef, useState } from 'react';
|
|
6
6
|
|
|
7
7
|
import type { Obj } from '@dxos/echo';
|
|
8
8
|
import { Board, type MosaicTileProps, useBoard } from '@dxos/react-ui-mosaic';
|
|
@@ -10,23 +10,23 @@ import { Board, type MosaicTileProps, useBoard } from '@dxos/react-ui-mosaic';
|
|
|
10
10
|
import { useKanbanItemEventHandler } from '#hooks';
|
|
11
11
|
import { type ColumnStructure, UNCATEGORIZED_VALUE } from '#types';
|
|
12
12
|
|
|
13
|
-
import { useKanbanBoard } from './
|
|
13
|
+
import { type KanbanColumnProps, useKanbanBoard } from './context';
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
export { type KanbanColumnProps };
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
const KANBAN_COLUMN_NAME = 'KanbanBoard.Column';
|
|
18
18
|
|
|
19
19
|
/**
|
|
20
20
|
* Mosaic Tile for Kanban column.
|
|
21
21
|
*/
|
|
22
22
|
export const KanbanColumn = forwardRef<HTMLDivElement, KanbanColumnProps>(
|
|
23
|
-
({ data: column, location, debug }, forwardedRef) => {
|
|
23
|
+
({ data: column, location, debug, draggable }, forwardedRef) => {
|
|
24
24
|
const { model } = useBoard<ColumnStructure, Obj.Unknown>(KANBAN_COLUMN_NAME);
|
|
25
25
|
const { columnFieldPath, change, onCardAdd, getPivotAttributes, itemTile } = useKanbanBoard(KANBAN_COLUMN_NAME);
|
|
26
26
|
|
|
27
27
|
const { title } = getPivotAttributes(column.columnValue);
|
|
28
28
|
const uncategorized = column.columnValue === UNCATEGORIZED_VALUE;
|
|
29
|
-
const
|
|
29
|
+
const [dragHandle, setDragHandle] = useState<HTMLButtonElement | null>(null);
|
|
30
30
|
|
|
31
31
|
const eventHandler = useKanbanItemEventHandler({
|
|
32
32
|
column,
|
|
@@ -41,7 +41,8 @@ export const KanbanColumn = forwardRef<HTMLDivElement, KanbanColumnProps>(
|
|
|
41
41
|
location={location}
|
|
42
42
|
classNames='grid grid-rows-[var(--dx-rail-action)_1fr_var(--dx-rail-action)]'
|
|
43
43
|
debug={debug}
|
|
44
|
-
|
|
44
|
+
draggable={draggable}
|
|
45
|
+
dragHandle={dragHandle}
|
|
45
46
|
ref={forwardedRef}
|
|
46
47
|
>
|
|
47
48
|
{uncategorized ? (
|
|
@@ -49,18 +50,20 @@ export const KanbanColumn = forwardRef<HTMLDivElement, KanbanColumnProps>(
|
|
|
49
50
|
<span className='font-medium'>{title}</span>
|
|
50
51
|
</div>
|
|
51
52
|
) : (
|
|
52
|
-
<Board.Column.Header label={title} dragHandleRef={
|
|
53
|
+
<Board.Column.Header label={title} dragHandleRef={setDragHandle} />
|
|
53
54
|
)}
|
|
54
55
|
<Board.Column.Body
|
|
55
56
|
data={column}
|
|
56
57
|
eventHandler={eventHandler}
|
|
57
58
|
Tile={itemTile as FC<MosaicTileProps<Obj.Unknown>>}
|
|
58
59
|
/>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
<Board.Column.Footer
|
|
61
|
+
onAdd={
|
|
62
|
+
onCardAdd
|
|
63
|
+
? () => onCardAdd(column.columnValue === UNCATEGORIZED_VALUE ? undefined : column.columnValue)
|
|
64
|
+
: undefined
|
|
65
|
+
}
|
|
66
|
+
/>
|
|
64
67
|
</Board.Column.Root>
|
|
65
68
|
);
|
|
66
69
|
},
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import { createContext } from '@radix-ui/react-context';
|
|
6
|
+
import { type ComponentType } from 'react';
|
|
7
|
+
|
|
8
|
+
import { type Obj } from '@dxos/echo';
|
|
9
|
+
import { type MosaicTileProps } from '@dxos/react-ui-mosaic';
|
|
10
|
+
import { type ProjectionModel } from '@dxos/schema';
|
|
11
|
+
|
|
12
|
+
import { type ColumnStructure, type KanbanChangeCallback, UNCATEGORIZED_ATTRIBUTES, UNCATEGORIZED_VALUE } from '#types';
|
|
13
|
+
|
|
14
|
+
const KANBAN_BOARD_NAME = 'KanbanBoard.Context';
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Card tile props. Defined here (rather than in `KanbanCard.tsx`) so the
|
|
18
|
+
* context type can reference it without forming a cycle through that
|
|
19
|
+
* module's runtime exports — webkit treats the resulting TDZ as a hard
|
|
20
|
+
* error while other engines are lenient.
|
|
21
|
+
*/
|
|
22
|
+
export type KanbanCardProps = Pick<MosaicTileProps<Obj.Unknown>, 'location' | 'data' | 'debug' | 'draggable'>;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Column tile props. See note on {@link KanbanCardProps}.
|
|
26
|
+
*/
|
|
27
|
+
export type KanbanColumnProps = Pick<MosaicTileProps<ColumnStructure>, 'location' | 'data' | 'debug' | 'draggable'>;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Context value for the Kanban board.
|
|
31
|
+
* Items are Echo objects (Obj.Unknown).
|
|
32
|
+
*/
|
|
33
|
+
export type KanbanBoardContextValue = {
|
|
34
|
+
kanbanId: string;
|
|
35
|
+
projection: ProjectionModel | undefined;
|
|
36
|
+
columnFieldPath: string | undefined;
|
|
37
|
+
change: KanbanChangeCallback<Obj.Unknown>;
|
|
38
|
+
pivotFieldId: string | undefined;
|
|
39
|
+
getPivotAttributes: (columnValue: string) => { title: string; color: string };
|
|
40
|
+
itemTile?: ComponentType<KanbanCardProps>; // TODO(burdon): Prop.
|
|
41
|
+
onCardAdd?: (columnValue: string | undefined) => string | undefined;
|
|
42
|
+
onCardRemove?: (card: Obj.Unknown) => void;
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
export const [KanbanBoardContext, useKanbanBoard] = createContext<KanbanBoardContextValue>(KANBAN_BOARD_NAME, {
|
|
46
|
+
kanbanId: 'never',
|
|
47
|
+
projection: undefined,
|
|
48
|
+
columnFieldPath: undefined,
|
|
49
|
+
change: { kanban: () => {}, setItemField: () => {} },
|
|
50
|
+
pivotFieldId: undefined,
|
|
51
|
+
getPivotAttributes: (id: string) =>
|
|
52
|
+
id === UNCATEGORIZED_VALUE ? UNCATEGORIZED_ATTRIBUTES : { title: id, color: 'neutral' },
|
|
53
|
+
itemTile: (() => null) as ComponentType<KanbanCardProps>,
|
|
54
|
+
});
|
|
@@ -11,29 +11,30 @@ import { expect, waitFor, within } from 'storybook/test';
|
|
|
11
11
|
import { withPluginManager } from '@dxos/app-framework/testing';
|
|
12
12
|
import { Surface } from '@dxos/app-framework/ui';
|
|
13
13
|
import { AppSurface } from '@dxos/app-toolkit/ui';
|
|
14
|
-
import { Obj, type QueryAST, Type } from '@dxos/echo';
|
|
15
|
-
import {
|
|
16
|
-
import { type Mutable } from '@dxos/echo/internal';
|
|
14
|
+
import { Filter, Obj, type QueryAST, Type, View } from '@dxos/echo';
|
|
15
|
+
import { type Mutable } from '@dxos/echo/Obj';
|
|
17
16
|
import { invariant } from '@dxos/invariant';
|
|
18
|
-
|
|
17
|
+
// `/plugin` entrypoints used here for the same reason as `corePlugins()` —
|
|
18
|
+
// see `@dxos/plugin-testing/src/core.ts` for the rationale.
|
|
19
|
+
import { ClientPlugin } from '@dxos/plugin-client/testing';
|
|
19
20
|
import { initializeIdentity } from '@dxos/plugin-client/testing';
|
|
20
|
-
import { PreviewPlugin } from '@dxos/plugin-preview';
|
|
21
|
-
import { SpacePlugin } from '@dxos/plugin-space';
|
|
21
|
+
import { PreviewPlugin } from '@dxos/plugin-preview/testing';
|
|
22
|
+
import { SpacePlugin } from '@dxos/plugin-space/testing';
|
|
22
23
|
import { StorybookPlugin, corePlugins } from '@dxos/plugin-testing';
|
|
23
24
|
import { random } from '@dxos/random';
|
|
24
|
-
import {
|
|
25
|
+
import { type Space, useQuery, useType, useSpaces } from '@dxos/react-client/echo';
|
|
25
26
|
import { ViewEditor } from '@dxos/react-ui-form';
|
|
26
|
-
import {
|
|
27
|
+
import { Syntax } from '@dxos/react-ui-syntax-highlighter';
|
|
27
28
|
import { withLayout } from '@dxos/react-ui/testing';
|
|
28
|
-
import { ViewModel,
|
|
29
|
+
import { ViewModel, getTypeURIFromQuery } from '@dxos/schema';
|
|
29
30
|
// TODO(wittjosiah): Replace with echo/testing.
|
|
30
31
|
import { Organization, Person } from '@dxos/types';
|
|
31
32
|
|
|
32
33
|
import { useProjectionModel } from '#hooks';
|
|
34
|
+
import { translations } from '#translations';
|
|
33
35
|
import { Kanban } from '#types';
|
|
34
36
|
|
|
35
37
|
import { KanbanPlugin } from '../../KanbanPlugin';
|
|
36
|
-
import { translations } from '../../translations';
|
|
37
38
|
|
|
38
39
|
random.seed(0);
|
|
39
40
|
|
|
@@ -56,7 +57,7 @@ type ClientSetupOptions = {
|
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
59
|
* Creates the standard plugin manager decorator with client configuration.
|
|
59
|
-
* Includes KanbanPlugin so the Surface resolves to
|
|
60
|
+
* Includes KanbanPlugin so the Surface resolves to KanbanArticle.
|
|
60
61
|
*/
|
|
61
62
|
const withKanbanPlugins = ({ types = [], onSpaceCreated }: ClientSetupOptions): Decorator =>
|
|
62
63
|
withPluginManager({
|
|
@@ -80,7 +81,7 @@ const withKanbanPlugins = ({ types = [], onSpaceCreated }: ClientSetupOptions):
|
|
|
80
81
|
});
|
|
81
82
|
|
|
82
83
|
/**
|
|
83
|
-
* Renders the first Kanban in the space via Surface (resolves to
|
|
84
|
+
* Renders the first Kanban in the space via Surface (resolves to KanbanArticle),
|
|
84
85
|
* with a sidebar containing ViewEditor and Json filter.
|
|
85
86
|
*/
|
|
86
87
|
const DefaultComponent = () => {
|
|
@@ -88,36 +89,37 @@ const DefaultComponent = () => {
|
|
|
88
89
|
const spaces = useSpaces();
|
|
89
90
|
const space = spaces[spaces.length - 1];
|
|
90
91
|
const [kanban] = useQuery(space?.db, Filter.type(Kanban.Kanban));
|
|
91
|
-
const
|
|
92
|
-
const
|
|
93
|
-
const
|
|
92
|
+
const viewRef = kanban && kanban.spec.kind === 'view' ? kanban.spec.view : undefined;
|
|
93
|
+
const view = viewRef?.target;
|
|
94
|
+
const typeUri = view?.query ? getTypeURIFromQuery(view.query.ast) : undefined;
|
|
95
|
+
const type = useType(space?.db, typeUri);
|
|
96
|
+
const projection = useProjectionModel(type, kanban, registry);
|
|
94
97
|
|
|
95
98
|
const data = useMemo(() => (kanban ? { subject: kanban, attendableId: 'story' } : undefined), [kanban]);
|
|
96
99
|
|
|
97
100
|
const handleUpdateQuery = useCallback(
|
|
98
101
|
(newQuery: QueryAST.Query) => {
|
|
99
|
-
invariant(
|
|
100
|
-
invariant(
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Obj.change(kanban.view.target, (view) => {
|
|
102
|
+
invariant(type);
|
|
103
|
+
invariant(view);
|
|
104
|
+
// NOTE: persisted Type.Type typename is immutable; only the view's
|
|
105
|
+
// query is updated here.
|
|
106
|
+
Obj.update(view, (view) => {
|
|
105
107
|
view.query.ast = newQuery as Mutable<QueryAST.Query>;
|
|
106
108
|
});
|
|
107
109
|
},
|
|
108
|
-
[
|
|
110
|
+
[view, type],
|
|
109
111
|
);
|
|
110
112
|
|
|
111
113
|
const handleDeleteField = useCallback(
|
|
112
114
|
(fieldId: string) => {
|
|
113
|
-
if (
|
|
115
|
+
if (type && Type.getDatabase(type) != null && projection) {
|
|
114
116
|
projection.deleteFieldProjection(fieldId);
|
|
115
117
|
}
|
|
116
118
|
},
|
|
117
|
-
[
|
|
119
|
+
[type, projection],
|
|
118
120
|
);
|
|
119
121
|
|
|
120
|
-
if (!
|
|
122
|
+
if (!type || !view) {
|
|
121
123
|
return null;
|
|
122
124
|
}
|
|
123
125
|
|
|
@@ -126,18 +128,20 @@ const DefaultComponent = () => {
|
|
|
126
128
|
<Surface.Surface type={AppSurface.Article} data={data} limit={1} />
|
|
127
129
|
<div className='flex flex-col h-full overflow-hidden border-l border-separator'>
|
|
128
130
|
<ViewEditor
|
|
129
|
-
registry={space?.db.
|
|
130
|
-
|
|
131
|
-
view={
|
|
131
|
+
registry={space?.db.graph.registry}
|
|
132
|
+
type={type}
|
|
133
|
+
view={view}
|
|
132
134
|
onQueryChanged={handleUpdateQuery}
|
|
133
|
-
onDelete={
|
|
135
|
+
onDelete={type && Type.getDatabase(type) != null ? handleDeleteField : undefined}
|
|
134
136
|
/>
|
|
135
|
-
<
|
|
136
|
-
<
|
|
137
|
-
<
|
|
138
|
-
<
|
|
139
|
-
|
|
140
|
-
|
|
137
|
+
<Syntax.Root data={{ view, schema: Type.getSchema(type) }}>
|
|
138
|
+
<Syntax.Content>
|
|
139
|
+
<Syntax.Filter />
|
|
140
|
+
<Syntax.Viewport>
|
|
141
|
+
<Syntax.Code classNames='text-xs' />
|
|
142
|
+
</Syntax.Viewport>
|
|
143
|
+
</Syntax.Content>
|
|
144
|
+
</Syntax.Root>
|
|
141
145
|
</div>
|
|
142
146
|
</div>
|
|
143
147
|
);
|
|
@@ -173,7 +177,7 @@ export const Default: Story = {
|
|
|
173
177
|
onSpaceCreated: async (space) => {
|
|
174
178
|
const { view } = await ViewModel.makeFromDatabase({
|
|
175
179
|
db: space.db,
|
|
176
|
-
typename: Organization.Organization
|
|
180
|
+
typename: Type.getTypename(Organization.Organization),
|
|
177
181
|
pivotFieldName: 'status',
|
|
178
182
|
});
|
|
179
183
|
const kanban = Kanban.make({ view });
|
|
@@ -217,7 +221,7 @@ export const Default: Story = {
|
|
|
217
221
|
await expect(activeCards.length).toBeGreaterThan(0);
|
|
218
222
|
await expect(prospectCards.length).toBeGreaterThan(0);
|
|
219
223
|
|
|
220
|
-
// Verify cards have drag handles (Card.
|
|
224
|
+
// Verify cards have drag handles (Card.Header includes drag handle).
|
|
221
225
|
const firstActiveCard = activeCards[0];
|
|
222
226
|
const buttons = firstActiveCard.querySelectorAll('button');
|
|
223
227
|
await expect(buttons.length).toBeGreaterThan(0);
|
|
@@ -234,7 +238,7 @@ export const Default: Story = {
|
|
|
234
238
|
};
|
|
235
239
|
|
|
236
240
|
/**
|
|
237
|
-
* Story variant that uses a
|
|
241
|
+
* Story variant that uses a database-stored Type.Type entity (mutable schema).
|
|
238
242
|
* This allows testing schema mutations like adding/removing fields.
|
|
239
243
|
*/
|
|
240
244
|
// TODO(wittjosiah): Card previews (e.g., OrganizationCard) are type-specific and hard-coded.
|
|
@@ -245,12 +249,14 @@ export const MutableSchema: Story = {
|
|
|
245
249
|
decorators: [
|
|
246
250
|
withKanbanPlugins({
|
|
247
251
|
onSpaceCreated: async (space) => {
|
|
248
|
-
//
|
|
249
|
-
const
|
|
252
|
+
// Persist the schema in the database to make it mutable (stored Type.Type).
|
|
253
|
+
const type = await space.db.addType(Organization.Organization);
|
|
250
254
|
|
|
251
255
|
const { view } = await ViewModel.makeFromDatabase({
|
|
252
256
|
db: space.db,
|
|
253
|
-
|
|
257
|
+
// `db.addType` returns a persisted `Type.Type` entity; its typename lives in the
|
|
258
|
+
// type metadata, so read it via `Type.getTypename` rather than a `.typename` prop.
|
|
259
|
+
typename: Type.getTypename(type),
|
|
254
260
|
pivotFieldName: 'status',
|
|
255
261
|
});
|
|
256
262
|
const kanban = Kanban.make({ view });
|
|
@@ -264,7 +270,7 @@ export const MutableSchema: Story = {
|
|
|
264
270
|
...Array.from({ length: 1 }, () => createOrg('commit')),
|
|
265
271
|
...Array.from({ length: 1 }, () => createOrg('reject')),
|
|
266
272
|
];
|
|
267
|
-
requiredOrgs.forEach((org) => space.db.add(Obj.make(
|
|
273
|
+
requiredOrgs.forEach((org) => space.db.add(Obj.make(type, org)));
|
|
268
274
|
},
|
|
269
275
|
}),
|
|
270
276
|
],
|