@dxos/plugin-space 0.6.14-staging.54a8bab → 0.6.14-staging.7b35391
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/browser/{chunk-AVLRQF6L.mjs → chunk-DJE2HYFV.mjs} +3 -2
- package/dist/lib/browser/{chunk-AVLRQF6L.mjs.map → chunk-DJE2HYFV.mjs.map} +2 -2
- package/dist/lib/browser/{chunk-WZAM3FNP.mjs → chunk-OWZKSWMX.mjs} +1 -1
- package/dist/lib/browser/{chunk-WZAM3FNP.mjs.map → chunk-OWZKSWMX.mjs.map} +2 -2
- package/dist/lib/browser/index.mjs +586 -576
- package/dist/lib/browser/index.mjs.map +4 -4
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/browser/meta.mjs +1 -1
- package/dist/lib/browser/types/index.mjs +1 -1
- package/dist/lib/node/{chunk-HTAM5LQD.cjs → chunk-FYWGZYJB.cjs} +4 -4
- package/dist/lib/node/{chunk-HTAM5LQD.cjs.map → chunk-FYWGZYJB.cjs.map} +2 -2
- package/dist/lib/node/{chunk-P4XUXM7Y.cjs → chunk-JFDDZI4Y.cjs} +6 -5
- package/dist/lib/node/{chunk-P4XUXM7Y.cjs.map → chunk-JFDDZI4Y.cjs.map} +2 -2
- package/dist/lib/node/index.cjs +816 -805
- package/dist/lib/node/index.cjs.map +4 -4
- package/dist/lib/node/meta.cjs +5 -5
- package/dist/lib/node/meta.cjs.map +1 -1
- package/dist/lib/node/meta.json +1 -1
- package/dist/lib/node/types/index.cjs +11 -11
- package/dist/lib/node/types/index.cjs.map +1 -1
- package/dist/lib/node-esm/{chunk-YPQGKWHJ.mjs → chunk-DVUZ7A7G.mjs} +3 -2
- package/dist/lib/node-esm/{chunk-YPQGKWHJ.mjs.map → chunk-DVUZ7A7G.mjs.map} +2 -2
- package/dist/lib/node-esm/{chunk-TRJKV4PK.mjs → chunk-MCEAI4CV.mjs} +1 -1
- package/dist/lib/node-esm/{chunk-TRJKV4PK.mjs.map → chunk-MCEAI4CV.mjs.map} +2 -2
- package/dist/lib/node-esm/index.mjs +586 -576
- package/dist/lib/node-esm/index.mjs.map +4 -4
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/lib/node-esm/meta.mjs +1 -1
- package/dist/lib/node-esm/types/index.mjs +1 -1
- package/dist/types/src/SpacePlugin.d.ts +9 -1
- package/dist/types/src/SpacePlugin.d.ts.map +1 -1
- package/dist/types/src/components/JoinDialog.d.ts +7 -0
- package/dist/types/src/components/JoinDialog.d.ts.map +1 -0
- package/dist/types/src/components/ShareSpaceButton.d.ts +3 -2
- package/dist/types/src/components/ShareSpaceButton.d.ts.map +1 -1
- package/dist/types/src/components/{SpaceSettings.d.ts → SpacePluginSettings.d.ts} +2 -2
- package/dist/types/src/components/SpacePluginSettings.d.ts.map +1 -0
- package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts +10 -0
- package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.d.ts.map +1 -0
- package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.stories.d.ts +7 -0
- package/dist/types/src/components/SpaceSettings/SpaceSettingsDialog.stories.d.ts.map +1 -0
- package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.d.ts.map +1 -0
- package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.stories.d.ts +7 -0
- package/dist/types/src/components/SpaceSettings/SpaceSettingsPanel.stories.d.ts.map +1 -0
- package/dist/types/src/components/SpaceSettings/index.d.ts +3 -0
- package/dist/types/src/components/SpaceSettings/index.d.ts.map +1 -0
- package/dist/types/src/components/index.d.ts +2 -2
- package/dist/types/src/components/index.d.ts.map +1 -1
- package/dist/types/src/meta.d.ts +3 -2
- package/dist/types/src/meta.d.ts.map +1 -1
- package/dist/types/src/translations.d.ts +4 -0
- package/dist/types/src/translations.d.ts.map +1 -1
- package/dist/types/src/types/types.d.ts +5 -0
- package/dist/types/src/types/types.d.ts.map +1 -1
- package/dist/types/src/util.d.ts +8 -4
- package/dist/types/src/util.d.ts.map +1 -1
- package/package.json +35 -34
- package/src/SpacePlugin.tsx +225 -146
- package/src/components/AwaitingObject.tsx +1 -1
- package/src/components/JoinDialog.tsx +100 -0
- package/src/components/ShareSpaceButton.tsx +10 -6
- package/src/components/{SpaceSettings.tsx → SpacePluginSettings.tsx} +1 -1
- package/src/components/SpaceSettings/SpaceSettingsDialog.stories.tsx +44 -0
- package/src/components/SpaceSettings/SpaceSettingsDialog.tsx +103 -0
- package/src/components/SpaceSettings/SpaceSettingsPanel.stories.tsx +32 -0
- package/src/components/{SpaceSettingsPanel.tsx → SpaceSettings/SpaceSettingsPanel.tsx} +15 -20
- package/src/components/SpaceSettings/index.ts +6 -0
- package/src/components/index.ts +2 -2
- package/src/meta.ts +2 -1
- package/src/translations.ts +4 -0
- package/src/types/types.ts +6 -0
- package/src/util.tsx +51 -23
- package/dist/types/src/components/SpaceMain/SpaceMain.d.ts +0 -10
- package/dist/types/src/components/SpaceMain/SpaceMain.d.ts.map +0 -1
- package/dist/types/src/components/SpaceMain/SpaceMembersSection.d.ts +0 -6
- package/dist/types/src/components/SpaceMain/SpaceMembersSection.d.ts.map +0 -1
- package/dist/types/src/components/SpaceMain/index.d.ts +0 -2
- package/dist/types/src/components/SpaceMain/index.d.ts.map +0 -1
- package/dist/types/src/components/SpaceSettings.d.ts.map +0 -1
- package/dist/types/src/components/SpaceSettingsPanel.d.ts.map +0 -1
- package/src/components/SpaceMain/SpaceMain.tsx +0 -60
- package/src/components/SpaceMain/SpaceMembersSection.tsx +0 -205
- package/src/components/SpaceMain/index.ts +0 -5
- /package/dist/types/src/components/{SpaceSettingsPanel.d.ts → SpaceSettings/SpaceSettingsPanel.d.ts} +0 -0
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useCallback } from 'react';
|
|
6
|
+
|
|
7
|
+
import { LayoutAction, NavigationAction, useIntentDispatcher } from '@dxos/app-framework';
|
|
8
|
+
import { useGraph } from '@dxos/plugin-graph';
|
|
9
|
+
import { ObservabilityAction } from '@dxos/plugin-observability/meta';
|
|
10
|
+
import { useSpaces } from '@dxos/react-client/echo';
|
|
11
|
+
import { type InvitationResult } from '@dxos/react-client/invitations';
|
|
12
|
+
import { Dialog, useTranslation } from '@dxos/react-ui';
|
|
13
|
+
import { JoinPanel, type JoinPanelProps } from '@dxos/shell/react';
|
|
14
|
+
|
|
15
|
+
import { SPACE_PLUGIN } from '../meta';
|
|
16
|
+
|
|
17
|
+
export type JoinDialogProps = JoinPanelProps & {
|
|
18
|
+
navigableCollections?: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const JoinDialog = ({ navigableCollections, ...props }: JoinDialogProps) => {
|
|
22
|
+
const { t } = useTranslation(SPACE_PLUGIN);
|
|
23
|
+
const dispatch = useIntentDispatcher();
|
|
24
|
+
const spaces = useSpaces();
|
|
25
|
+
const { graph } = useGraph();
|
|
26
|
+
|
|
27
|
+
const handleDone = useCallback(
|
|
28
|
+
async (result: InvitationResult | null) => {
|
|
29
|
+
if (result?.spaceKey) {
|
|
30
|
+
await Promise.all([
|
|
31
|
+
dispatch({
|
|
32
|
+
action: LayoutAction.SET_LAYOUT,
|
|
33
|
+
data: {
|
|
34
|
+
element: 'toast',
|
|
35
|
+
subject: {
|
|
36
|
+
id: `${SPACE_PLUGIN}/join-success`,
|
|
37
|
+
duration: 5_000,
|
|
38
|
+
title: t('join success label'),
|
|
39
|
+
closeLabel: t('dismiss label'),
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
}),
|
|
43
|
+
dispatch({
|
|
44
|
+
action: LayoutAction.SET_LAYOUT,
|
|
45
|
+
data: {
|
|
46
|
+
element: 'dialog',
|
|
47
|
+
state: false,
|
|
48
|
+
},
|
|
49
|
+
}),
|
|
50
|
+
]);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const space = spaces.find(({ key }) => result?.spaceKey?.equals(key));
|
|
54
|
+
const target = result?.target || (navigableCollections ? space?.id : undefined);
|
|
55
|
+
if (target) {
|
|
56
|
+
// Wait for up to 1 second before navigating to the target node.
|
|
57
|
+
// If the target has not yet replicated, this will trigger a loading toast.
|
|
58
|
+
await graph.waitForPath({ target }).catch(() => {});
|
|
59
|
+
await Promise.all([
|
|
60
|
+
dispatch({
|
|
61
|
+
action: NavigationAction.OPEN,
|
|
62
|
+
data: {
|
|
63
|
+
activeParts: { main: [target] },
|
|
64
|
+
},
|
|
65
|
+
}),
|
|
66
|
+
dispatch({
|
|
67
|
+
action: NavigationAction.EXPOSE,
|
|
68
|
+
data: {
|
|
69
|
+
id: target,
|
|
70
|
+
},
|
|
71
|
+
}),
|
|
72
|
+
]);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (space) {
|
|
76
|
+
await dispatch({
|
|
77
|
+
action: ObservabilityAction.SEND_EVENT,
|
|
78
|
+
data: {
|
|
79
|
+
name: 'space.join',
|
|
80
|
+
properties: {
|
|
81
|
+
spaceId: space.id,
|
|
82
|
+
},
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
},
|
|
87
|
+
[dispatch, spaces],
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
return (
|
|
91
|
+
<Dialog.Content>
|
|
92
|
+
<JoinPanel
|
|
93
|
+
{...props}
|
|
94
|
+
exitActionParent={<Dialog.Close asChild />}
|
|
95
|
+
doneActionParent={<Dialog.Close asChild />}
|
|
96
|
+
onDone={handleDone}
|
|
97
|
+
/>
|
|
98
|
+
</Dialog.Content>
|
|
99
|
+
);
|
|
100
|
+
};
|
|
@@ -5,14 +5,15 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
7
|
import { useIntentDispatcher } from '@dxos/app-framework';
|
|
8
|
-
import {
|
|
8
|
+
import { type Space } from '@dxos/react-client/echo';
|
|
9
|
+
import { IconButton, useTranslation } from '@dxos/react-ui';
|
|
9
10
|
|
|
10
11
|
import { SPACE_PLUGIN, SpaceAction } from '../meta';
|
|
11
12
|
|
|
12
|
-
export const ShareSpaceButton = ({
|
|
13
|
+
export const ShareSpaceButton = ({ space }: { space: Space }) => {
|
|
13
14
|
const dispatch = useIntentDispatcher();
|
|
14
15
|
|
|
15
|
-
return <ShareSpaceButtonImpl onClick={() => dispatch({ action: SpaceAction.SHARE, data: {
|
|
16
|
+
return <ShareSpaceButtonImpl onClick={() => dispatch({ action: SpaceAction.SHARE, data: { space } })} />;
|
|
16
17
|
};
|
|
17
18
|
|
|
18
19
|
// TODO(wittjosiah): Better way to name pure/impure components?
|
|
@@ -20,8 +21,11 @@ export const ShareSpaceButtonImpl = ({ onClick }: { onClick: () => void }) => {
|
|
|
20
21
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
21
22
|
|
|
22
23
|
return (
|
|
23
|
-
<
|
|
24
|
-
|
|
25
|
-
|
|
24
|
+
<IconButton
|
|
25
|
+
data-testid='spacePlugin.shareSpaceButton'
|
|
26
|
+
icon='ph--users--regular'
|
|
27
|
+
label={t('share space label')}
|
|
28
|
+
onClick={onClick}
|
|
29
|
+
/>
|
|
26
30
|
);
|
|
27
31
|
};
|
|
@@ -11,7 +11,7 @@ import { DeprecatedFormInput } from '@dxos/react-ui-data';
|
|
|
11
11
|
import { SpaceAction, SPACE_PLUGIN } from '../meta';
|
|
12
12
|
import { parseSpaceInitPlugin, type SpaceSettingsProps } from '../types';
|
|
13
13
|
|
|
14
|
-
export const
|
|
14
|
+
export const SpacePluginSettings = ({ settings }: { settings: SpaceSettingsProps }) => {
|
|
15
15
|
const { t } = useTranslation(SPACE_PLUGIN);
|
|
16
16
|
const dispatch = useIntentDispatcher();
|
|
17
17
|
const plugins = useResolvePlugins(parseSpaceInitPlugin);
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import '@dxos-theme';
|
|
6
|
+
|
|
7
|
+
import { type Meta, type StoryObj } from '@storybook/react';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
|
|
10
|
+
import { useStoryClientData, withClientProvider } from '@dxos/react-client/testing';
|
|
11
|
+
import { Dialog } from '@dxos/react-ui';
|
|
12
|
+
import { osTranslations } from '@dxos/shell/react';
|
|
13
|
+
import { withLayout, withTheme } from '@dxos/storybook-utils';
|
|
14
|
+
|
|
15
|
+
import { SpaceSettingsDialog, type SpaceSettingsDialogProps } from './SpaceSettingsDialog';
|
|
16
|
+
import translations from '../../translations';
|
|
17
|
+
|
|
18
|
+
const Story = (args: Partial<SpaceSettingsDialogProps>) => {
|
|
19
|
+
const { space } = useStoryClientData();
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<Dialog.Root open>
|
|
23
|
+
<Dialog.Overlay blockAlign='start'>
|
|
24
|
+
<SpaceSettingsDialog {...args} space={space!} />
|
|
25
|
+
</Dialog.Overlay>
|
|
26
|
+
</Dialog.Root>
|
|
27
|
+
);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const meta: Meta = {
|
|
31
|
+
title: 'plugins/plugin-space/SpaceSettingsDialog',
|
|
32
|
+
component: SpaceSettingsDialog,
|
|
33
|
+
render: Story,
|
|
34
|
+
decorators: [
|
|
35
|
+
withClientProvider({ createIdentity: true, createSpace: true }),
|
|
36
|
+
withTheme,
|
|
37
|
+
withLayout({ tooltips: true }),
|
|
38
|
+
],
|
|
39
|
+
parameters: { translations: [...translations, osTranslations] },
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default meta;
|
|
43
|
+
|
|
44
|
+
export const Default: StoryObj<typeof SpaceSettingsDialog> = {};
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import React, { useState } from 'react';
|
|
6
|
+
|
|
7
|
+
import { useClient } from '@dxos/react-client';
|
|
8
|
+
import { Button, Dialog, Icon, toLocalizedString, useTranslation } from '@dxos/react-ui';
|
|
9
|
+
import { Tabs, type TabsRootProps, type TabsActivePart } from '@dxos/react-ui-tabs';
|
|
10
|
+
import { ClipboardProvider, SpacePanel, type SpacePanelProps } from '@dxos/shell/react';
|
|
11
|
+
|
|
12
|
+
import { SpaceSettingsPanel, type SpaceSettingsPanelProps } from './SpaceSettingsPanel';
|
|
13
|
+
import { SPACE_PLUGIN } from '../../meta';
|
|
14
|
+
import { COMPOSER_SPACE_LOCK, getSpaceDisplayName } from '../../util';
|
|
15
|
+
|
|
16
|
+
export type SpaceSettingsTab = 'members' | 'settings';
|
|
17
|
+
|
|
18
|
+
export type SpaceSettingsDialogProps = {
|
|
19
|
+
initialTab?: SpaceSettingsTab;
|
|
20
|
+
namesCache?: Record<string, string>;
|
|
21
|
+
} & SpaceSettingsPanelProps &
|
|
22
|
+
Pick<SpacePanelProps, 'createInvitationUrl' | 'target'>;
|
|
23
|
+
|
|
24
|
+
export const SpaceSettingsDialog = ({
|
|
25
|
+
space,
|
|
26
|
+
target,
|
|
27
|
+
createInvitationUrl,
|
|
28
|
+
initialTab = 'members',
|
|
29
|
+
namesCache,
|
|
30
|
+
}: SpaceSettingsDialogProps) => {
|
|
31
|
+
const { t } = useTranslation(SPACE_PLUGIN);
|
|
32
|
+
const client = useClient();
|
|
33
|
+
const [tabsActivePart, setTabsActivePart] = useState<TabsActivePart>('list');
|
|
34
|
+
const [selected, setSelected] = useState<SpaceSettingsTab>(initialTab);
|
|
35
|
+
const locked = space.properties[COMPOSER_SPACE_LOCK];
|
|
36
|
+
const name = getSpaceDisplayName(space, { personal: client.spaces.default === space, namesCache });
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
// TODO(wittjosiah): The tablist dialog pattern is copied from @dxos/plugin-manager.
|
|
40
|
+
// Consider factoring it out to the tabs package.
|
|
41
|
+
<Dialog.Content classNames='p-0 bs-content min-bs-[15rem] max-bs-full md:max-is-[40rem] overflow-hidden'>
|
|
42
|
+
<div role='none' className='flex justify-between pbs-3 pis-2 pie-3 @md:pbs-4 @md:pis-4 @md:pie-5'>
|
|
43
|
+
<Dialog.Title
|
|
44
|
+
onClick={() => setTabsActivePart('list')}
|
|
45
|
+
aria-description={t('click to return to tablist description')}
|
|
46
|
+
classNames='flex cursor-pointer items-center group/title'
|
|
47
|
+
>
|
|
48
|
+
<Icon
|
|
49
|
+
icon='ph--caret-left--regular'
|
|
50
|
+
size={4}
|
|
51
|
+
classNames={['@md:hidden', tabsActivePart === 'list' && 'invisible']}
|
|
52
|
+
/>
|
|
53
|
+
<span
|
|
54
|
+
className={
|
|
55
|
+
tabsActivePart !== 'list'
|
|
56
|
+
? 'group-hover/title:underline @md:group-hover/title:no-underline underline-offset-4 decoration-1'
|
|
57
|
+
: ''
|
|
58
|
+
}
|
|
59
|
+
>
|
|
60
|
+
{toLocalizedString(name, t)}
|
|
61
|
+
</span>
|
|
62
|
+
</Dialog.Title>
|
|
63
|
+
<Dialog.Close asChild>
|
|
64
|
+
<Button density='fine' variant='ghost' autoFocus>
|
|
65
|
+
<Icon icon='ph--x--regular' size={3} />
|
|
66
|
+
</Button>
|
|
67
|
+
</Dialog.Close>
|
|
68
|
+
</div>
|
|
69
|
+
<Tabs.Root
|
|
70
|
+
orientation='vertical'
|
|
71
|
+
value={selected}
|
|
72
|
+
onValueChange={setSelected as TabsRootProps['onValueChange']}
|
|
73
|
+
activePart={tabsActivePart}
|
|
74
|
+
onActivePartChange={setTabsActivePart}
|
|
75
|
+
classNames='flex flex-col flex-1 mbs-2'
|
|
76
|
+
>
|
|
77
|
+
<Tabs.Viewport classNames='flex-1 min-bs-0'>
|
|
78
|
+
<div role='none' className='overflow-y-auto pli-3 @md:pis-2 @md:pie-0 mbe-4 border-r border-separator'>
|
|
79
|
+
<Tabs.Tablist classNames='flex flex-col max-bs-none min-is-[200px] gap-4 overflow-y-auto'>
|
|
80
|
+
<div role='none' className='flex flex-col ml-1'>
|
|
81
|
+
<Tabs.Tab value='settings'>{t('settings tab label')}</Tabs.Tab>
|
|
82
|
+
<Tabs.Tab value='members' disabled={locked}>
|
|
83
|
+
{t('members tab label')}
|
|
84
|
+
</Tabs.Tab>
|
|
85
|
+
</div>
|
|
86
|
+
</Tabs.Tablist>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<Tabs.Tabpanel value='settings' classNames='pli-3 @md:pli-5 max-bs-dvh overflow-y-auto'>
|
|
90
|
+
<SpaceSettingsPanel space={space} />
|
|
91
|
+
</Tabs.Tabpanel>
|
|
92
|
+
|
|
93
|
+
{/* TODO(wittjosiah): Weird focus ring when tabpanel is focused. */}
|
|
94
|
+
<Tabs.Tabpanel value='members' classNames='pli-3 @md:pli-5 max-bs-dvh overflow-y-auto'>
|
|
95
|
+
<ClipboardProvider>
|
|
96
|
+
<SpacePanel space={space} hideHeading target={target} createInvitationUrl={createInvitationUrl} />
|
|
97
|
+
</ClipboardProvider>
|
|
98
|
+
</Tabs.Tabpanel>
|
|
99
|
+
</Tabs.Viewport>
|
|
100
|
+
</Tabs.Root>
|
|
101
|
+
</Dialog.Content>
|
|
102
|
+
);
|
|
103
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2024 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
import '@dxos-theme';
|
|
6
|
+
|
|
7
|
+
import { type Meta, type StoryObj } from '@storybook/react';
|
|
8
|
+
import React from 'react';
|
|
9
|
+
|
|
10
|
+
import { useStoryClientData, withClientProvider } from '@dxos/react-client/testing';
|
|
11
|
+
import { withTheme } from '@dxos/storybook-utils';
|
|
12
|
+
|
|
13
|
+
import { SpaceSettingsPanel, type SpaceSettingsPanelProps } from './SpaceSettingsPanel';
|
|
14
|
+
import translations from '../../translations';
|
|
15
|
+
|
|
16
|
+
const Story = (args: Partial<SpaceSettingsPanelProps>) => {
|
|
17
|
+
const { space } = useStoryClientData();
|
|
18
|
+
|
|
19
|
+
return <SpaceSettingsPanel {...args} space={space!} />;
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const meta: Meta = {
|
|
23
|
+
title: 'plugins/plugin-space/SpaceSettingsPanel',
|
|
24
|
+
component: SpaceSettingsPanel,
|
|
25
|
+
render: Story,
|
|
26
|
+
decorators: [withClientProvider({ createIdentity: true, createSpace: true }), withTheme],
|
|
27
|
+
parameters: { translations },
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export default meta;
|
|
31
|
+
|
|
32
|
+
export const Default: StoryObj<typeof SpaceSettingsPanel> = {};
|
|
@@ -10,8 +10,9 @@ import { useClient } from '@dxos/react-client';
|
|
|
10
10
|
import { type Space } from '@dxos/react-client/echo';
|
|
11
11
|
import { DeviceType, useDevices } from '@dxos/react-client/halo';
|
|
12
12
|
import { Input, useTranslation } from '@dxos/react-ui';
|
|
13
|
+
import { DeprecatedFormInput } from '@dxos/react-ui-data';
|
|
13
14
|
|
|
14
|
-
import { SPACE_PLUGIN } from '
|
|
15
|
+
import { SPACE_PLUGIN } from '../../meta';
|
|
15
16
|
|
|
16
17
|
export type SpaceSettingsPanelProps = {
|
|
17
18
|
space: Space;
|
|
@@ -43,26 +44,20 @@ export const SpaceSettingsPanel = ({ space }: SpaceSettingsPanelProps) => {
|
|
|
43
44
|
);
|
|
44
45
|
|
|
45
46
|
return (
|
|
46
|
-
<div role='form' className='flex flex-col
|
|
47
|
-
<
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
/>
|
|
57
|
-
</div>
|
|
58
|
-
</Input.Root>
|
|
47
|
+
<div role='form' className='flex flex-col'>
|
|
48
|
+
<DeprecatedFormInput label={t('name label')}>
|
|
49
|
+
<Input.TextInput
|
|
50
|
+
placeholder={t('unnamed space label')}
|
|
51
|
+
value={space.properties.name ?? ''}
|
|
52
|
+
onChange={(event) => {
|
|
53
|
+
space.properties.name = event.target.value;
|
|
54
|
+
}}
|
|
55
|
+
/>
|
|
56
|
+
</DeprecatedFormInput>
|
|
59
57
|
{edgeReplicationAvailable && (
|
|
60
|
-
<
|
|
61
|
-
<
|
|
62
|
-
|
|
63
|
-
<Input.Switch checked={edgeReplication} onCheckedChange={toggleEdgeReplication} />
|
|
64
|
-
</div>
|
|
65
|
-
</Input.Root>
|
|
58
|
+
<DeprecatedFormInput label={t('edge replication label')}>
|
|
59
|
+
<Input.Switch checked={edgeReplication} onCheckedChange={toggleEdgeReplication} />
|
|
60
|
+
</DeprecatedFormInput>
|
|
66
61
|
)}
|
|
67
62
|
</div>
|
|
68
63
|
);
|
package/src/components/index.ts
CHANGED
|
@@ -6,13 +6,13 @@ export * from './AwaitingObject';
|
|
|
6
6
|
export * from './CollectionMain';
|
|
7
7
|
export * from './CollectionSection';
|
|
8
8
|
export * from './DefaultObjectSettings';
|
|
9
|
+
export * from './JoinDialog';
|
|
9
10
|
export * from './MenuFooter';
|
|
10
11
|
export * from './PersistenceStatus';
|
|
11
12
|
export * from './PopoverRenameObject';
|
|
12
13
|
export * from './PopoverRenameSpace';
|
|
13
14
|
export * from './ShareSpaceButton';
|
|
14
|
-
export * from './SpaceMain';
|
|
15
15
|
export * from './SpacePresence';
|
|
16
|
+
export * from './SpacePluginSettings';
|
|
16
17
|
export * from './SpaceSettings';
|
|
17
|
-
export * from './SpaceSettingsPanel';
|
|
18
18
|
export * from './SyncStatus';
|
package/src/meta.ts
CHANGED
|
@@ -25,9 +25,10 @@ export enum SpaceAction {
|
|
|
25
25
|
CLOSE = `${SPACE_ACTION}/close`,
|
|
26
26
|
MIGRATE = `${SPACE_ACTION}/migrate`,
|
|
27
27
|
ADD_OBJECT = `${SPACE_ACTION}/add-object`,
|
|
28
|
-
|
|
28
|
+
REMOVE_OBJECTS = `${SPACE_ACTION}/remove-objects`,
|
|
29
29
|
RENAME_OBJECT = `${SPACE_ACTION}/rename-object`,
|
|
30
30
|
DUPLICATE_OBJECT = `${SPACE_ACTION}/duplicate-object`,
|
|
31
31
|
WAIT_FOR_OBJECT = `${SPACE_ACTION}/wait-for-object`,
|
|
32
32
|
TOGGLE_HIDDEN = `${SPACE_ACTION}/toggle-hidden`,
|
|
33
|
+
OPEN_SETTINGS = `${SPACE_ACTION}/open-settings`,
|
|
33
34
|
}
|
package/src/translations.ts
CHANGED
|
@@ -47,6 +47,7 @@ export default [
|
|
|
47
47
|
'delete object label': 'Delete item',
|
|
48
48
|
'collection deleted label': 'Collection deleted',
|
|
49
49
|
'object deleted label': 'Item deleted',
|
|
50
|
+
'objects deleted label': 'Items deleted',
|
|
50
51
|
'go to object label': 'Open item',
|
|
51
52
|
'found object label': 'Ready.',
|
|
52
53
|
'found object description': 'The requested object is now available.',
|
|
@@ -100,6 +101,9 @@ export default [
|
|
|
100
101
|
'offline persisted label': 'Saved to disk (offline)',
|
|
101
102
|
'remote synced label': 'Synced with peers',
|
|
102
103
|
'open settings panel label': 'Show Settings',
|
|
104
|
+
'open space settings label': 'Space Settings',
|
|
105
|
+
'members tab label': 'Members',
|
|
106
|
+
'settings tab label': 'Settings',
|
|
103
107
|
},
|
|
104
108
|
},
|
|
105
109
|
},
|
package/src/types/types.ts
CHANGED
|
@@ -55,6 +55,12 @@ export type PluginState = {
|
|
|
55
55
|
*/
|
|
56
56
|
// TODO(wittjosiah): Factor out to sdk. Migration running should probably be a space state.
|
|
57
57
|
sdkMigrationRunning: Record<string, boolean>;
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Whether or not the user can navigate to collections in the graph.
|
|
61
|
+
* Determined by whether or not there is an available plugin that can render a collection.
|
|
62
|
+
*/
|
|
63
|
+
navigableCollections: boolean;
|
|
58
64
|
};
|
|
59
65
|
|
|
60
66
|
export type SpaceSettingsProps = {
|
package/src/util.tsx
CHANGED
|
@@ -92,15 +92,18 @@ export const getSpaceDisplayName = (
|
|
|
92
92
|
};
|
|
93
93
|
|
|
94
94
|
const getCollectionGraphNodePartials = ({
|
|
95
|
+
navigable,
|
|
95
96
|
collection,
|
|
96
97
|
space,
|
|
97
98
|
resolve,
|
|
98
99
|
}: {
|
|
100
|
+
navigable: boolean;
|
|
99
101
|
collection: CollectionType;
|
|
100
102
|
space: Space;
|
|
101
103
|
resolve: MetadataResolver;
|
|
102
104
|
}) => {
|
|
103
105
|
return {
|
|
106
|
+
disabled: !navigable,
|
|
104
107
|
acceptPersistenceClass: new Set(['echo']),
|
|
105
108
|
acceptPersistenceKey: new Set([space.id]),
|
|
106
109
|
role: 'branch',
|
|
@@ -176,11 +179,13 @@ const checkPendingMigration = (space: Space) => {
|
|
|
176
179
|
|
|
177
180
|
export const constructSpaceNode = ({
|
|
178
181
|
space,
|
|
182
|
+
navigable = false,
|
|
179
183
|
personal,
|
|
180
184
|
namesCache,
|
|
181
185
|
resolve,
|
|
182
186
|
}: {
|
|
183
187
|
space: Space;
|
|
188
|
+
navigable?: boolean;
|
|
184
189
|
personal?: boolean;
|
|
185
190
|
namesCache?: Record<string, string>;
|
|
186
191
|
resolve: MetadataResolver;
|
|
@@ -189,7 +194,7 @@ export const constructSpaceNode = ({
|
|
|
189
194
|
const collection = space.state.get() === SpaceState.SPACE_READY && space.properties[CollectionType.typename];
|
|
190
195
|
const partials =
|
|
191
196
|
space.state.get() === SpaceState.SPACE_READY && collection instanceof CollectionType
|
|
192
|
-
? getCollectionGraphNodePartials({ collection, space, resolve })
|
|
197
|
+
? getCollectionGraphNodePartials({ collection, space, resolve, navigable })
|
|
193
198
|
: {};
|
|
194
199
|
|
|
195
200
|
return {
|
|
@@ -201,13 +206,21 @@ export const constructSpaceNode = ({
|
|
|
201
206
|
label: getSpaceDisplayName(space, { personal, namesCache }),
|
|
202
207
|
description: space.state.get() === SpaceState.SPACE_READY && space.properties.description,
|
|
203
208
|
icon: 'ph--planet--regular',
|
|
204
|
-
disabled: space.state.get() !== SpaceState.SPACE_READY || hasPendingMigration,
|
|
209
|
+
disabled: !navigable || space.state.get() !== SpaceState.SPACE_READY || hasPendingMigration,
|
|
205
210
|
testId: 'spacePlugin.space',
|
|
206
211
|
},
|
|
207
212
|
};
|
|
208
213
|
};
|
|
209
214
|
|
|
210
|
-
export const constructSpaceActionGroups = ({
|
|
215
|
+
export const constructSpaceActionGroups = ({
|
|
216
|
+
space,
|
|
217
|
+
navigable,
|
|
218
|
+
dispatch,
|
|
219
|
+
}: {
|
|
220
|
+
space: Space;
|
|
221
|
+
navigable: boolean;
|
|
222
|
+
dispatch: IntentDispatcher;
|
|
223
|
+
}) => {
|
|
211
224
|
const state = space.state.get();
|
|
212
225
|
const hasPendingMigration = checkPendingMigration(space);
|
|
213
226
|
const getId = (id: string) => `${id}/${space.id}`;
|
|
@@ -226,8 +239,6 @@ export const constructSpaceActionGroups = ({ space, dispatch }: { space: Space;
|
|
|
226
239
|
label: ['create object in space label', { ns: SPACE_PLUGIN }],
|
|
227
240
|
icon: 'ph--plus--regular',
|
|
228
241
|
disposition: 'toolbar',
|
|
229
|
-
// TODO(wittjosiah): This is currently a navtree feature. Address this with cmd+k integration.
|
|
230
|
-
// mainAreaDisposition: 'in-flow',
|
|
231
242
|
menuType: 'searchList',
|
|
232
243
|
testId: 'spacePlugin.createObject',
|
|
233
244
|
},
|
|
@@ -242,9 +253,13 @@ export const constructSpaceActionGroups = ({ space, dispatch }: { space: Space;
|
|
|
242
253
|
action: SpaceAction.ADD_OBJECT,
|
|
243
254
|
data: { target: collection, object: create(CollectionType, { objects: [], views: {} }) },
|
|
244
255
|
},
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
256
|
+
...(navigable
|
|
257
|
+
? [
|
|
258
|
+
{
|
|
259
|
+
action: NavigationAction.OPEN,
|
|
260
|
+
},
|
|
261
|
+
]
|
|
262
|
+
: []),
|
|
248
263
|
]),
|
|
249
264
|
properties: {
|
|
250
265
|
label: ['create collection label', { ns: SPACE_PLUGIN }],
|
|
@@ -286,7 +301,6 @@ export const constructSpaceActions = ({
|
|
|
286
301
|
label: ['migrate space label', { ns: SPACE_PLUGIN }],
|
|
287
302
|
icon: 'ph--database--regular',
|
|
288
303
|
disposition: 'toolbar',
|
|
289
|
-
mainAreaDisposition: 'in-flow',
|
|
290
304
|
disabled: migrating || Migrations.running(space),
|
|
291
305
|
},
|
|
292
306
|
});
|
|
@@ -302,7 +316,7 @@ export const constructSpaceActions = ({
|
|
|
302
316
|
if (locked) {
|
|
303
317
|
return;
|
|
304
318
|
}
|
|
305
|
-
await dispatch({ plugin: SPACE_PLUGIN, action: SpaceAction.SHARE, data: {
|
|
319
|
+
await dispatch({ plugin: SPACE_PLUGIN, action: SpaceAction.SHARE, data: { space } });
|
|
306
320
|
},
|
|
307
321
|
properties: {
|
|
308
322
|
label: ['share space label', { ns: SPACE_PLUGIN }],
|
|
@@ -312,7 +326,6 @@ export const constructSpaceActions = ({
|
|
|
312
326
|
macos: 'meta+.',
|
|
313
327
|
windows: 'alt+.',
|
|
314
328
|
},
|
|
315
|
-
mainAreaDisposition: 'absent',
|
|
316
329
|
},
|
|
317
330
|
},
|
|
318
331
|
{
|
|
@@ -343,12 +356,23 @@ export const constructSpaceActions = ({
|
|
|
343
356
|
macos: 'shift+F6',
|
|
344
357
|
windows: 'shift+F6',
|
|
345
358
|
},
|
|
346
|
-
|
|
359
|
+
},
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
id: getId(SpaceAction.OPEN_SETTINGS),
|
|
363
|
+
type: ACTION_TYPE,
|
|
364
|
+
data: async () => {
|
|
365
|
+
await dispatch({ plugin: SPACE_PLUGIN, action: SpaceAction.OPEN_SETTINGS, data: { space } });
|
|
366
|
+
},
|
|
367
|
+
properties: {
|
|
368
|
+
label: ['open space settings label', { ns: SPACE_PLUGIN }],
|
|
369
|
+
icon: 'ph--gear--regular',
|
|
347
370
|
},
|
|
348
371
|
},
|
|
349
372
|
);
|
|
350
373
|
}
|
|
351
374
|
|
|
375
|
+
// TODO(wittjosiah): Consider moving close space into the space settings dialog.
|
|
352
376
|
if (state !== SpaceState.SPACE_INACTIVE && !hasPendingMigration) {
|
|
353
377
|
actions.push({
|
|
354
378
|
id: getId(SpaceAction.CLOSE),
|
|
@@ -359,7 +383,6 @@ export const constructSpaceActions = ({
|
|
|
359
383
|
properties: {
|
|
360
384
|
label: ['close space label', { ns: SPACE_PLUGIN }],
|
|
361
385
|
icon: 'ph--x--regular',
|
|
362
|
-
mainAreaDisposition: 'menu',
|
|
363
386
|
disabled: personal,
|
|
364
387
|
},
|
|
365
388
|
});
|
|
@@ -376,7 +399,6 @@ export const constructSpaceActions = ({
|
|
|
376
399
|
label: ['open space label', { ns: SPACE_PLUGIN }],
|
|
377
400
|
icon: 'ph--clock-counter-clockwise--regular',
|
|
378
401
|
disposition: 'toolbar',
|
|
379
|
-
mainAreaDisposition: 'in-flow',
|
|
380
402
|
},
|
|
381
403
|
});
|
|
382
404
|
}
|
|
@@ -387,10 +409,12 @@ export const constructSpaceActions = ({
|
|
|
387
409
|
export const createObjectNode = ({
|
|
388
410
|
object,
|
|
389
411
|
space,
|
|
412
|
+
navigable = false,
|
|
390
413
|
resolve,
|
|
391
414
|
}: {
|
|
392
415
|
object: EchoReactiveObject<any>;
|
|
393
416
|
space: Space;
|
|
417
|
+
navigable?: boolean;
|
|
394
418
|
resolve: MetadataResolver;
|
|
395
419
|
}) => {
|
|
396
420
|
const type = getTypename(object);
|
|
@@ -405,7 +429,7 @@ export const createObjectNode = ({
|
|
|
405
429
|
|
|
406
430
|
const partials =
|
|
407
431
|
object instanceof CollectionType
|
|
408
|
-
? getCollectionGraphNodePartials({ collection: object, space, resolve })
|
|
432
|
+
? getCollectionGraphNodePartials({ collection: object, space, resolve, navigable })
|
|
409
433
|
: metadata.graphProps;
|
|
410
434
|
|
|
411
435
|
return {
|
|
@@ -427,9 +451,11 @@ export const createObjectNode = ({
|
|
|
427
451
|
|
|
428
452
|
export const constructObjectActionGroups = ({
|
|
429
453
|
object,
|
|
454
|
+
navigable,
|
|
430
455
|
dispatch,
|
|
431
456
|
}: {
|
|
432
457
|
object: EchoReactiveObject<any>;
|
|
458
|
+
navigable: boolean;
|
|
433
459
|
dispatch: IntentDispatcher;
|
|
434
460
|
}) => {
|
|
435
461
|
if (!(object instanceof CollectionType)) {
|
|
@@ -447,8 +473,6 @@ export const constructObjectActionGroups = ({
|
|
|
447
473
|
label: ['create object in collection label', { ns: SPACE_PLUGIN }],
|
|
448
474
|
icon: 'ph--plus--regular',
|
|
449
475
|
disposition: 'toolbar',
|
|
450
|
-
// TODO(wittjosiah): This is currently a navtree feature. Address this with cmd+k integration.
|
|
451
|
-
// mainAreaDisposition: 'in-flow',
|
|
452
476
|
menuType: 'searchList',
|
|
453
477
|
testId: 'spacePlugin.createObject',
|
|
454
478
|
},
|
|
@@ -463,9 +487,13 @@ export const constructObjectActionGroups = ({
|
|
|
463
487
|
action: SpaceAction.ADD_OBJECT,
|
|
464
488
|
data: { target: collection, object: create(CollectionType, { objects: [], views: {} }) },
|
|
465
489
|
},
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
490
|
+
...(navigable
|
|
491
|
+
? [
|
|
492
|
+
{
|
|
493
|
+
action: NavigationAction.OPEN,
|
|
494
|
+
},
|
|
495
|
+
]
|
|
496
|
+
: []),
|
|
469
497
|
]),
|
|
470
498
|
properties: {
|
|
471
499
|
label: ['create collection label', { ns: SPACE_PLUGIN }],
|
|
@@ -511,7 +539,7 @@ export const constructObjectActions = ({
|
|
|
511
539
|
},
|
|
512
540
|
},
|
|
513
541
|
{
|
|
514
|
-
id: getId(SpaceAction.
|
|
542
|
+
id: getId(SpaceAction.REMOVE_OBJECTS),
|
|
515
543
|
type: ACTION_TYPE,
|
|
516
544
|
data: async () => {
|
|
517
545
|
const graph = getGraph(node);
|
|
@@ -520,8 +548,8 @@ export const constructObjectActions = ({
|
|
|
520
548
|
.find(({ data }) => data instanceof CollectionType)?.data;
|
|
521
549
|
await dispatch([
|
|
522
550
|
{
|
|
523
|
-
action: SpaceAction.
|
|
524
|
-
data: { object, collection },
|
|
551
|
+
action: SpaceAction.REMOVE_OBJECTS,
|
|
552
|
+
data: { objects: [object], collection },
|
|
525
553
|
},
|
|
526
554
|
]);
|
|
527
555
|
},
|