@dxos/react-ui-form 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/index.mjs +223 -205
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/index.mjs +223 -205
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/ControlSection/ControlSection.stories.d.ts +5 -5
- package/dist/types/src/components/FieldEditor/FieldEditor.stories.d.ts +5 -5
- package/dist/types/src/components/Form/ArrayField.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.d.ts +5 -4
- package/dist/types/src/components/Form/Form.d.ts.map +1 -1
- package/dist/types/src/components/Form/Form.stories.d.ts +47 -33
- package/dist/types/src/components/Form/Form.stories.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormActions.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContent.d.ts.map +1 -1
- package/dist/types/src/components/Form/FormContext.d.ts +3 -3
- package/dist/types/src/components/Form/FormContext.d.ts.map +1 -1
- package/dist/types/src/components/Form/Input.d.ts +2 -2
- package/dist/types/src/components/Form/Input.d.ts.map +1 -1
- package/dist/types/src/components/Form/RefField.d.ts +1 -0
- package/dist/types/src/components/Form/RefField.d.ts.map +1 -1
- package/dist/types/src/components/Form/custom/SelectOptionsInput.stories.d.ts +5 -5
- package/dist/types/src/components/Form/factory.d.ts +2 -2
- package/dist/types/src/components/Form/factory.d.ts.map +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.d.ts.map +1 -1
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts +6 -5
- package/dist/types/src/components/ObjectPicker/ObjectPicker.stories.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts +11 -9
- package/dist/types/src/components/ViewEditor/ViewEditor.d.ts.map +1 -1
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts +8 -8
- package/dist/types/src/components/ViewEditor/ViewEditor.stories.d.ts.map +1 -1
- package/dist/types/src/hooks/useForm.d.ts +4 -4
- package/dist/types/src/hooks/useForm.d.ts.map +1 -1
- package/dist/types/src/hooks/useQueryRefOptions.d.ts +1 -0
- package/dist/types/src/hooks/useQueryRefOptions.d.ts.map +1 -1
- package/dist/types/src/hooks/useRefQueryLookupHandler.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +5 -5
- package/dist/types/src/util/field.d.ts +3 -3
- package/dist/types/src/util/field.d.ts.map +1 -1
- package/dist/types/src/util/formatting.d.ts +2 -2
- package/dist/types/src/util/formatting.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -31
- package/src/components/ControlSection/ControlSection.stories.tsx +1 -1
- package/src/components/FieldEditor/FieldEditor.stories.tsx +2 -2
- package/src/components/FieldEditor/FieldEditor.tsx +3 -3
- package/src/components/Form/ArrayField.tsx +3 -1
- package/src/components/Form/Defaults.tsx +1 -1
- package/src/components/Form/Form.stories.tsx +24 -24
- package/src/components/Form/Form.tsx +8 -5
- package/src/components/Form/FormActions.tsx +7 -2
- package/src/components/Form/FormContent.tsx +53 -13
- package/src/components/Form/FormContext.tsx +4 -4
- package/src/components/Form/Input.tsx +2 -2
- package/src/components/Form/RefField.tsx +16 -2
- package/src/components/Form/custom/SelectOptionsInput.tsx +1 -1
- package/src/components/Form/factory.tsx +7 -4
- package/src/components/ObjectPicker/ObjectPicker.stories.tsx +25 -25
- package/src/components/ObjectPicker/ObjectPicker.tsx +14 -14
- package/src/components/ViewEditor/ViewEditor.stories.tsx +46 -32
- package/src/components/ViewEditor/ViewEditor.test.tsx +4 -3
- package/src/components/ViewEditor/ViewEditor.tsx +41 -97
- package/src/hooks/useForm.ts +8 -7
- package/src/hooks/useQueryRefOptions.ts +6 -3
- package/src/hooks/useRefQueryLookupHandler.ts +5 -5
- package/src/translations.ts +5 -5
- package/src/util/field.ts +25 -25
- package/src/util/formatting.ts +22 -22
- package/src/util/refs.ts +6 -6
|
@@ -9,12 +9,11 @@ import { expect, fn, userEvent, within } from 'storybook/test';
|
|
|
9
9
|
|
|
10
10
|
import { Obj } from '@dxos/echo';
|
|
11
11
|
import { faker } from '@dxos/random';
|
|
12
|
-
import { useClient } from '@dxos/react-client';
|
|
13
12
|
import { Filter, useQuery } from '@dxos/react-client/echo';
|
|
14
13
|
import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
|
|
15
14
|
import { Button } from '@dxos/react-ui';
|
|
16
15
|
import { withTheme } from '@dxos/react-ui/testing';
|
|
17
|
-
import {
|
|
16
|
+
import { Person } from '@dxos/types';
|
|
18
17
|
|
|
19
18
|
import { translations } from '../../translations';
|
|
20
19
|
|
|
@@ -23,19 +22,18 @@ import { ObjectPicker } from './ObjectPicker';
|
|
|
23
22
|
faker.seed(1);
|
|
24
23
|
|
|
25
24
|
const createPerson = () =>
|
|
26
|
-
Obj.make(
|
|
25
|
+
Obj.make(Person.Person, {
|
|
27
26
|
fullName: faker.person.fullName(),
|
|
28
27
|
});
|
|
29
28
|
|
|
30
29
|
const omitId = Schema.omit<any, any, ['id']>('id');
|
|
31
|
-
const personSchema = omitId(
|
|
30
|
+
const personSchema = omitId(Person.Person);
|
|
32
31
|
|
|
33
32
|
// Mock functions for testing
|
|
34
33
|
const mockHandleSelect = fn();
|
|
35
34
|
const mockHandleCreate = fn();
|
|
36
35
|
|
|
37
36
|
const DefaultStory = () => {
|
|
38
|
-
const client = useClient();
|
|
39
37
|
const { space } = useClientProvider();
|
|
40
38
|
const [isOpen, setIsOpen] = useState(false);
|
|
41
39
|
|
|
@@ -67,7 +65,7 @@ const DefaultStory = () => {
|
|
|
67
65
|
(values: any) => {
|
|
68
66
|
console.log('[on create]', values);
|
|
69
67
|
if (!space) return;
|
|
70
|
-
const newPerson = space.db.add(Obj.make(
|
|
68
|
+
const newPerson = space.db.add(Obj.make(Person.Person, values));
|
|
71
69
|
mockHandleCreate(values);
|
|
72
70
|
return newPerson;
|
|
73
71
|
},
|
|
@@ -103,7 +101,7 @@ const meta = {
|
|
|
103
101
|
decorators: [
|
|
104
102
|
withTheme,
|
|
105
103
|
withClientProvider({
|
|
106
|
-
types: [
|
|
104
|
+
types: [Person.Person],
|
|
107
105
|
createIdentity: true,
|
|
108
106
|
createSpace: true,
|
|
109
107
|
}),
|
|
@@ -119,37 +117,39 @@ export default meta;
|
|
|
119
117
|
|
|
120
118
|
type Story = StoryObj<typeof meta>;
|
|
121
119
|
|
|
122
|
-
export const Default: Story = {
|
|
120
|
+
export const Default: Story = {};
|
|
121
|
+
|
|
122
|
+
export const WithTest: Story = {
|
|
123
123
|
play: async ({ canvasElement }) => {
|
|
124
124
|
const canvas = within(canvasElement);
|
|
125
125
|
const body = within(document.body);
|
|
126
126
|
|
|
127
|
-
// Find and click the trigger button
|
|
127
|
+
// Find and click the trigger button.
|
|
128
128
|
const triggerButton = await canvas.findByTestId('trigger', undefined, { timeout: 5000 });
|
|
129
129
|
await expect(triggerButton).toBeVisible();
|
|
130
130
|
await userEvent.click(triggerButton);
|
|
131
131
|
|
|
132
|
-
// Check that the listbox renders when the trigger is clicked
|
|
132
|
+
// Check that the listbox renders when the trigger is clicked.
|
|
133
133
|
const listbox = await body.findByRole('listbox', undefined, { timeout: 5000 });
|
|
134
134
|
await expect(listbox).toBeVisible();
|
|
135
135
|
|
|
136
|
-
// Find the search input
|
|
136
|
+
// Find the search input.
|
|
137
137
|
const searchInput = await body.findByPlaceholderText('Search…');
|
|
138
138
|
await expect(searchInput).toBeVisible();
|
|
139
139
|
|
|
140
|
-
// Test searching filters the results - get initial options count
|
|
140
|
+
// Test searching filters the results - get initial options count.
|
|
141
141
|
const initialOptions = await body.findAllByRole('option');
|
|
142
142
|
const initialCount = initialOptions.length;
|
|
143
143
|
await expect(initialCount).toBeGreaterThan(0);
|
|
144
144
|
|
|
145
|
-
// Type a search term that should filter results
|
|
145
|
+
// Type a search term that should filter results.
|
|
146
146
|
await userEvent.type(searchInput, 'John');
|
|
147
147
|
|
|
148
|
-
// Wait a moment for filtering
|
|
148
|
+
// Wait a moment for filtering.
|
|
149
149
|
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
150
150
|
|
|
151
151
|
// Check that results are filtered (should be fewer options)
|
|
152
|
-
const
|
|
152
|
+
const _filteredOptions = await body.findAllByRole('option');
|
|
153
153
|
// Note: We expect either fewer results or the same if no John exists
|
|
154
154
|
|
|
155
155
|
// Clear search and test selecting a result
|
|
@@ -160,46 +160,46 @@ export const Default: Story = {
|
|
|
160
160
|
const firstOption = updatedOptions[0];
|
|
161
161
|
await expect(firstOption).toBeVisible();
|
|
162
162
|
|
|
163
|
-
const
|
|
163
|
+
const _firstOptionText = firstOption.textContent;
|
|
164
164
|
await userEvent.click(firstOption);
|
|
165
165
|
|
|
166
166
|
// Check that clicking a result fires onSelect with that id
|
|
167
167
|
// The onSelect should have been called with the selected option's id
|
|
168
168
|
await expect(mockHandleSelect).toHaveBeenCalled();
|
|
169
169
|
|
|
170
|
-
// Re-open the picker to test create functionality
|
|
170
|
+
// Re-open the picker to test create functionality.
|
|
171
171
|
await userEvent.click(triggerButton);
|
|
172
172
|
|
|
173
|
-
// Wait for listbox to appear again
|
|
173
|
+
// Wait for listbox to appear again.
|
|
174
174
|
const newListbox = await body.findByRole('listbox', undefined, { timeout: 5000 });
|
|
175
175
|
await expect(newListbox).toBeVisible();
|
|
176
176
|
|
|
177
177
|
const newSearchInput = await body.findByPlaceholderText('Search…');
|
|
178
178
|
|
|
179
|
-
// Test searching an unrelated term provides the __create__ option
|
|
179
|
+
// Test searching an unrelated term provides the __create__ option.
|
|
180
180
|
const unrelatedTerm = 'ZxyUnrelatedName123';
|
|
181
181
|
await userEvent.type(newSearchInput, unrelatedTerm);
|
|
182
182
|
|
|
183
|
-
// Wait for the create option to appear
|
|
183
|
+
// Wait for the create option to appear.
|
|
184
184
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
185
185
|
|
|
186
|
-
// Look for the create option
|
|
186
|
+
// Look for the create option.
|
|
187
187
|
const createOption = await body.findByRole('option', undefined, { timeout: 3000 });
|
|
188
188
|
await expect(createOption).toBeVisible();
|
|
189
189
|
|
|
190
|
-
// Click the create option - this should change state to the form field
|
|
190
|
+
// Click the create option - this should change state to the form field.
|
|
191
191
|
await userEvent.click(createOption);
|
|
192
192
|
|
|
193
|
-
// Check that clicking that option changes state to the form field
|
|
193
|
+
// Check that clicking that option changes state to the form field.
|
|
194
194
|
const form = await body.findByTestId('create-referenced-object-form', undefined, { timeout: 5000 });
|
|
195
195
|
await expect(form).toBeVisible();
|
|
196
196
|
|
|
197
|
-
// Find and click the save button
|
|
197
|
+
// Find and click the save button.
|
|
198
198
|
const saveButton = await within(form).findByTestId('save-button');
|
|
199
199
|
await expect(saveButton).toBeVisible();
|
|
200
200
|
await userEvent.click(saveButton);
|
|
201
201
|
|
|
202
|
-
// Check that clicking the save button calls onCreate with expected values
|
|
202
|
+
// Check that clicking the save button calls onCreate with expected values.
|
|
203
203
|
await expect(mockHandleCreate).toHaveBeenCalledWith({
|
|
204
204
|
fullName: unrelatedTerm,
|
|
205
205
|
});
|
|
@@ -6,7 +6,7 @@ import type * as Schema from 'effect/Schema';
|
|
|
6
6
|
import React, { type KeyboardEvent, type MouseEvent, forwardRef, useCallback, useMemo, useState } from 'react';
|
|
7
7
|
|
|
8
8
|
import { Icon, Popover, type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
9
|
-
import {
|
|
9
|
+
import { Combobox } from '@dxos/react-ui-searchlist';
|
|
10
10
|
|
|
11
11
|
import { type QueryTag } from '../../hooks';
|
|
12
12
|
import { translationKey } from '../../translations';
|
|
@@ -99,7 +99,7 @@ const ObjectPickerContent = forwardRef<HTMLDivElement, ObjectPickerContentProps>
|
|
|
99
99
|
);
|
|
100
100
|
|
|
101
101
|
return (
|
|
102
|
-
<
|
|
102
|
+
<Combobox.Content
|
|
103
103
|
{...props}
|
|
104
104
|
ref={ref}
|
|
105
105
|
filter={(value, search) => (value === '__create__' || labelById[value]?.includes(search.toLowerCase()) ? 1 : 0)}
|
|
@@ -118,15 +118,15 @@ const ObjectPickerContent = forwardRef<HTMLDivElement, ObjectPickerContentProps>
|
|
|
118
118
|
</Popover.Viewport>
|
|
119
119
|
) : (
|
|
120
120
|
<>
|
|
121
|
-
<
|
|
121
|
+
<Combobox.Input
|
|
122
122
|
placeholder={t('ref field combobox input placeholder')}
|
|
123
123
|
value={searchString}
|
|
124
124
|
onValueChange={setSearchString}
|
|
125
125
|
autoFocus
|
|
126
126
|
/>
|
|
127
|
-
<
|
|
127
|
+
<Combobox.List>
|
|
128
128
|
{options.map((option) => (
|
|
129
|
-
<
|
|
129
|
+
<Combobox.Item
|
|
130
130
|
key={option.id}
|
|
131
131
|
value={option.id}
|
|
132
132
|
onSelect={() => onSelect(option.id)}
|
|
@@ -134,19 +134,19 @@ const ObjectPickerContent = forwardRef<HTMLDivElement, ObjectPickerContentProps>
|
|
|
134
134
|
>
|
|
135
135
|
<span className='grow'>{option.label}</span>
|
|
136
136
|
{selectedIds?.includes(option.id) && <Icon icon='ph--check--regular' />}
|
|
137
|
-
</
|
|
137
|
+
</Combobox.Item>
|
|
138
138
|
))}
|
|
139
139
|
{searchString.length > 0 && createOptionLabel && createOptionIcon && createSchema && onCreate && (
|
|
140
|
-
<
|
|
140
|
+
<Combobox.Item value='__create__' classNames='flex items-center gap-2'>
|
|
141
141
|
<Icon icon={createOptionIcon} />
|
|
142
142
|
{t(createOptionLabel[0], { ns: createOptionLabel[1].ns, text: searchString })}
|
|
143
|
-
</
|
|
143
|
+
</Combobox.Item>
|
|
144
144
|
)}
|
|
145
|
-
</
|
|
145
|
+
</Combobox.List>
|
|
146
146
|
</>
|
|
147
147
|
)}
|
|
148
|
-
<
|
|
149
|
-
</
|
|
148
|
+
<Combobox.Arrow />
|
|
149
|
+
</Combobox.Content>
|
|
150
150
|
);
|
|
151
151
|
},
|
|
152
152
|
);
|
|
@@ -154,8 +154,8 @@ const ObjectPickerContent = forwardRef<HTMLDivElement, ObjectPickerContentProps>
|
|
|
154
154
|
ObjectPickerContent.displayName = 'ObjectPickerContent';
|
|
155
155
|
|
|
156
156
|
export const ObjectPicker = {
|
|
157
|
-
Root:
|
|
158
|
-
Trigger:
|
|
159
|
-
VirtualTrigger:
|
|
157
|
+
Root: Combobox.Root,
|
|
158
|
+
Trigger: Combobox.Trigger,
|
|
159
|
+
VirtualTrigger: Combobox.VirtualTrigger,
|
|
160
160
|
Content: ObjectPickerContent,
|
|
161
161
|
};
|
|
@@ -6,35 +6,45 @@ import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
|
6
6
|
import * as Schema from 'effect/Schema';
|
|
7
7
|
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
8
8
|
|
|
9
|
-
import { DXN, Filter, Obj, Query, Type } from '@dxos/echo';
|
|
10
|
-
import { type EchoSchema, Format
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import { withClientProvider } from '@dxos/react-client/testing';
|
|
9
|
+
import { DXN, Filter, Obj, Query, type QueryAST, Tag, Type } from '@dxos/echo';
|
|
10
|
+
import { type EchoSchema, Format } from '@dxos/echo/internal';
|
|
11
|
+
import { useQuery } from '@dxos/react-client/echo';
|
|
12
|
+
import { useClientProvider, withClientProvider } from '@dxos/react-client/testing';
|
|
14
13
|
import { useAsyncEffect } from '@dxos/react-ui';
|
|
15
14
|
import { withTheme } from '@dxos/react-ui/testing';
|
|
16
|
-
import { type
|
|
15
|
+
import { type ProjectionModel, View, getTypenameFromQuery } from '@dxos/schema';
|
|
16
|
+
import { Employer, Organization, Person, Project } from '@dxos/types';
|
|
17
17
|
|
|
18
18
|
import { translations } from '../../translations';
|
|
19
19
|
import { TestLayout, TestPanel, VIEW_EDITOR_DEBUG_SYMBOL } from '../testing';
|
|
20
20
|
|
|
21
21
|
import { ViewEditor, type ViewEditorProps } from './ViewEditor';
|
|
22
22
|
|
|
23
|
+
const types = [
|
|
24
|
+
// TODO(burdon): Get label from annotation.
|
|
25
|
+
{ value: Organization.Organization.typename, label: 'Organization' },
|
|
26
|
+
{ value: Person.Person.typename, label: 'Person' },
|
|
27
|
+
{ value: Type.getTypename(Project.Project), label: 'Project' },
|
|
28
|
+
{ value: Employer.Employer.typename, label: 'Employer' },
|
|
29
|
+
];
|
|
30
|
+
|
|
23
31
|
// Type definition for debug objects exposed to tests.
|
|
24
32
|
export type ViewEditorDebugObjects = {
|
|
25
33
|
schema: EchoSchema;
|
|
26
|
-
view:
|
|
34
|
+
view: View.View;
|
|
27
35
|
projection: ProjectionModel;
|
|
28
36
|
};
|
|
29
37
|
|
|
30
38
|
type StoryProps = Pick<ViewEditorProps, 'readonly' | 'mode'>;
|
|
31
39
|
|
|
32
40
|
const DefaultStory = (props: StoryProps) => {
|
|
33
|
-
const space =
|
|
41
|
+
const { space } = useClientProvider();
|
|
34
42
|
const [schema, setSchema] = useState<EchoSchema>();
|
|
35
|
-
const [view, setView] = useState<
|
|
43
|
+
const [view, setView] = useState<View.View>();
|
|
36
44
|
const projectionRef = useRef<ProjectionModel>(null);
|
|
37
45
|
|
|
46
|
+
const tags = useQuery(space, Filter.type(Tag.Tag));
|
|
47
|
+
|
|
38
48
|
useAsyncEffect(async () => {
|
|
39
49
|
if (space) {
|
|
40
50
|
const TestSchema = Schema.Struct({
|
|
@@ -60,12 +70,10 @@ const DefaultStory = (props: StoryProps) => {
|
|
|
60
70
|
);
|
|
61
71
|
|
|
62
72
|
const [testSchema] = await space.db.schemaRegistry.register([TestSchema, AlternateSchema]);
|
|
63
|
-
const view =
|
|
73
|
+
const view = View.make({
|
|
64
74
|
name: 'Test',
|
|
65
75
|
query: Query.select(Filter.type(TestSchema)),
|
|
66
|
-
|
|
67
|
-
jsonSchema: toJsonSchema(TestSchema),
|
|
68
|
-
presentation: Obj.make(Type.Expando, {}),
|
|
76
|
+
jsonSchema: Type.toJsonSchema(TestSchema),
|
|
69
77
|
});
|
|
70
78
|
|
|
71
79
|
setSchema(testSchema);
|
|
@@ -74,38 +82,31 @@ const DefaultStory = (props: StoryProps) => {
|
|
|
74
82
|
}, [space]);
|
|
75
83
|
|
|
76
84
|
const updateViewQuery = useCallback(
|
|
77
|
-
async (
|
|
85
|
+
async (newQuery: QueryAST.Query, target?: string) => {
|
|
78
86
|
if (!schema || !view || !space) {
|
|
79
87
|
return;
|
|
80
88
|
}
|
|
81
89
|
|
|
82
|
-
if (props.mode === '
|
|
83
|
-
view.query.string = queryString;
|
|
84
|
-
|
|
85
|
-
const builder = new QueryBuilder();
|
|
86
|
-
const filter = builder.build(queryString) ?? Filter.nothing();
|
|
90
|
+
if (props.mode === 'tag') {
|
|
87
91
|
const queue = target && DXN.tryParse(target) ? target : undefined;
|
|
88
|
-
const
|
|
89
|
-
view.query.ast =
|
|
92
|
+
const query = queue ? Query.fromAst(newQuery).options({ queues: [queue] }) : Query.fromAst(newQuery);
|
|
93
|
+
view.query.ast = query.ast;
|
|
90
94
|
|
|
91
|
-
const typename = getTypenameFromQuery(
|
|
95
|
+
const typename = getTypenameFromQuery(query.ast);
|
|
92
96
|
const [newSchema] = await space.db.schemaRegistry.query({ typename }).run();
|
|
93
97
|
if (!newSchema) {
|
|
94
98
|
return;
|
|
95
99
|
}
|
|
96
100
|
|
|
97
|
-
const newView =
|
|
98
|
-
query
|
|
101
|
+
const newView = View.make({
|
|
102
|
+
query,
|
|
99
103
|
jsonSchema: newSchema.jsonSchema,
|
|
100
|
-
presentation: Obj.make(Type.Expando, {}),
|
|
101
104
|
});
|
|
102
105
|
view.projection = Obj.getSnapshot(newView).projection;
|
|
103
106
|
setSchema(() => newSchema);
|
|
104
107
|
} else {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
view.query.ast = newQuery.ast;
|
|
108
|
-
schema.updateTypename(typename);
|
|
108
|
+
view.query.ast = newQuery;
|
|
109
|
+
schema.updateTypename(getTypenameFromQuery(newQuery));
|
|
109
110
|
}
|
|
110
111
|
},
|
|
111
112
|
[view, schema],
|
|
@@ -147,6 +148,8 @@ const DefaultStory = (props: StoryProps) => {
|
|
|
147
148
|
registry={space?.db.schemaRegistry}
|
|
148
149
|
mode={props.mode}
|
|
149
150
|
readonly={props.readonly}
|
|
151
|
+
types={types}
|
|
152
|
+
tags={tags}
|
|
150
153
|
onQueryChanged={updateViewQuery}
|
|
151
154
|
onDelete={handleDelete}
|
|
152
155
|
/>
|
|
@@ -158,7 +161,18 @@ const DefaultStory = (props: StoryProps) => {
|
|
|
158
161
|
const meta = {
|
|
159
162
|
title: 'ui/react-ui-form/ViewEditor',
|
|
160
163
|
render: DefaultStory,
|
|
161
|
-
decorators: [
|
|
164
|
+
decorators: [
|
|
165
|
+
withClientProvider({
|
|
166
|
+
createSpace: true,
|
|
167
|
+
types: [Tag.Tag],
|
|
168
|
+
onCreateSpace: ({ space }) => {
|
|
169
|
+
space.db.add(Tag.make({ label: 'Important' }));
|
|
170
|
+
space.db.add(Tag.make({ label: 'Investor' }));
|
|
171
|
+
space.db.add(Tag.make({ label: 'New' }));
|
|
172
|
+
},
|
|
173
|
+
}),
|
|
174
|
+
withTheme,
|
|
175
|
+
],
|
|
162
176
|
parameters: {
|
|
163
177
|
layout: 'fullscreen',
|
|
164
178
|
translations,
|
|
@@ -177,8 +191,8 @@ export const Readonly: Story = {
|
|
|
177
191
|
},
|
|
178
192
|
};
|
|
179
193
|
|
|
180
|
-
export const
|
|
194
|
+
export const TagQueryMode: Story = {
|
|
181
195
|
args: {
|
|
182
|
-
mode: '
|
|
196
|
+
mode: 'tag',
|
|
183
197
|
},
|
|
184
198
|
};
|
|
@@ -7,7 +7,7 @@ import { cleanup, fireEvent, screen, waitFor } from '@testing-library/react';
|
|
|
7
7
|
import { afterEach, describe, expect, test } from 'vitest';
|
|
8
8
|
|
|
9
9
|
import { EchoSchema, isInstanceOf } from '@dxos/echo/internal';
|
|
10
|
-
import {
|
|
10
|
+
import { ProjectionModel, View } from '@dxos/schema';
|
|
11
11
|
|
|
12
12
|
import { VIEW_EDITOR_DEBUG_SYMBOL } from '../testing';
|
|
13
13
|
|
|
@@ -20,7 +20,7 @@ const getViewEditorDebugObjects = (): ViewEditorDebugObjects => {
|
|
|
20
20
|
const debugObjects = (window as any)[VIEW_EDITOR_DEBUG_SYMBOL] as ViewEditorDebugObjects;
|
|
21
21
|
expect(debugObjects).toBeDefined();
|
|
22
22
|
expect(debugObjects.schema).toBeInstanceOf(EchoSchema);
|
|
23
|
-
expect(isInstanceOf(
|
|
23
|
+
expect(isInstanceOf(View.View, debugObjects.view)).toBeTruthy();
|
|
24
24
|
expect(debugObjects.projection).toBeInstanceOf(ProjectionModel);
|
|
25
25
|
return debugObjects;
|
|
26
26
|
};
|
|
@@ -134,7 +134,8 @@ describe('ViewEditor', () => {
|
|
|
134
134
|
expect(addedPropertyProjection!.props.property).toBe('added_property');
|
|
135
135
|
});
|
|
136
136
|
|
|
137
|
-
|
|
137
|
+
// TODO(mykola): Fix flaky test.
|
|
138
|
+
test('delete property', { retry: 2 }, async () => {
|
|
138
139
|
await Default.run();
|
|
139
140
|
await waitForViewEditor();
|
|
140
141
|
|