@@ -1,13 +1,5 @@
|
|||||||
import type { DragEndEvent } from '@dnd-kit/core';
|
|
||||||
import { DndContext, MouseSensor, useSensor, useSensors } from '@dnd-kit/core';
|
|
||||||
import {
|
|
||||||
restrictToParentElement,
|
|
||||||
restrictToVerticalAxis,
|
|
||||||
} from '@dnd-kit/modifiers';
|
|
||||||
import { arrayMove, SortableContext, useSortable } from '@dnd-kit/sortable';
|
|
||||||
import type { WorkspaceMetadata } from '@toeverything/infra';
|
import type { WorkspaceMetadata } from '@toeverything/infra';
|
||||||
import type { CSSProperties } from 'react';
|
import { Suspense } from 'react';
|
||||||
import { Suspense, useCallback, useEffect, useMemo, useState } from 'react';
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
WorkspaceCard,
|
WorkspaceCard,
|
||||||
@@ -23,7 +15,6 @@ export interface WorkspaceListProps {
|
|||||||
onClick: (workspace: WorkspaceMetadata) => void;
|
onClick: (workspace: WorkspaceMetadata) => void;
|
||||||
onSettingClick: (workspace: WorkspaceMetadata) => void;
|
onSettingClick: (workspace: WorkspaceMetadata) => void;
|
||||||
onEnableCloudClick?: (meta: WorkspaceMetadata) => void;
|
onEnableCloudClick?: (meta: WorkspaceMetadata) => void;
|
||||||
onDragEnd: (event: DragEndEvent) => void;
|
|
||||||
useIsWorkspaceOwner: (
|
useIsWorkspaceOwner: (
|
||||||
workspaceMetadata: WorkspaceMetadata
|
workspaceMetadata: WorkspaceMetadata
|
||||||
) => boolean | undefined;
|
) => boolean | undefined;
|
||||||
@@ -40,7 +31,6 @@ interface SortableWorkspaceItemProps extends Omit<WorkspaceListProps, 'items'> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const SortableWorkspaceItem = ({
|
const SortableWorkspaceItem = ({
|
||||||
disabled,
|
|
||||||
item,
|
item,
|
||||||
openingId,
|
openingId,
|
||||||
useIsWorkspaceOwner,
|
useIsWorkspaceOwner,
|
||||||
@@ -51,33 +41,11 @@ const SortableWorkspaceItem = ({
|
|||||||
onSettingClick,
|
onSettingClick,
|
||||||
onEnableCloudClick,
|
onEnableCloudClick,
|
||||||
}: SortableWorkspaceItemProps) => {
|
}: SortableWorkspaceItemProps) => {
|
||||||
const { setNodeRef, attributes, listeners, transform, transition } =
|
|
||||||
useSortable({
|
|
||||||
id: item.id,
|
|
||||||
});
|
|
||||||
const style: CSSProperties = useMemo(
|
|
||||||
() => ({
|
|
||||||
transform: transform
|
|
||||||
? `translate3d(${transform.x}px, ${transform.y}px, 0)`
|
|
||||||
: undefined,
|
|
||||||
transition,
|
|
||||||
pointerEvents: disabled ? 'none' : undefined,
|
|
||||||
opacity: disabled ? 0.6 : undefined,
|
|
||||||
}),
|
|
||||||
[disabled, transform, transition]
|
|
||||||
);
|
|
||||||
const isOwner = useIsWorkspaceOwner?.(item);
|
const isOwner = useIsWorkspaceOwner?.(item);
|
||||||
const avatar = useWorkspaceAvatar?.(item);
|
const avatar = useWorkspaceAvatar?.(item);
|
||||||
const name = useWorkspaceName?.(item);
|
const name = useWorkspaceName?.(item);
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={workspaceItemStyle} data-testid="draggable-item">
|
||||||
className={workspaceItemStyle}
|
|
||||||
data-testid="draggable-item"
|
|
||||||
style={style}
|
|
||||||
ref={setNodeRef}
|
|
||||||
{...attributes}
|
|
||||||
{...listeners}
|
|
||||||
>
|
|
||||||
<WorkspaceCard
|
<WorkspaceCard
|
||||||
currentWorkspaceId={currentWorkspaceId}
|
currentWorkspaceId={currentWorkspaceId}
|
||||||
meta={item}
|
meta={item}
|
||||||
@@ -93,48 +61,12 @@ const SortableWorkspaceItem = ({
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const modifiers = [restrictToParentElement, restrictToVerticalAxis];
|
|
||||||
|
|
||||||
export const WorkspaceList = (props: WorkspaceListProps) => {
|
export const WorkspaceList = (props: WorkspaceListProps) => {
|
||||||
const sensors = useSensors(
|
|
||||||
useSensor(MouseSensor, {
|
|
||||||
activationConstraint: {
|
|
||||||
distance: 8,
|
|
||||||
},
|
|
||||||
})
|
|
||||||
);
|
|
||||||
const workspaceList = props.items;
|
const workspaceList = props.items;
|
||||||
const [optimisticList, setOptimisticList] = useState(workspaceList);
|
|
||||||
|
|
||||||
useEffect(() => {
|
return workspaceList.map(item => (
|
||||||
setOptimisticList(workspaceList);
|
<Suspense fallback={<WorkspaceCardSkeleton />} key={item.id}>
|
||||||
}, [workspaceList]);
|
<SortableWorkspaceItem key={item.id} {...props} item={item} />
|
||||||
|
</Suspense>
|
||||||
const onDragEnd = useCallback(
|
));
|
||||||
(event: DragEndEvent) => {
|
|
||||||
const { active, over } = event;
|
|
||||||
if (active.id !== over?.id) {
|
|
||||||
setOptimisticList(workspaceList => {
|
|
||||||
const oldIndex = workspaceList.findIndex(w => w.id === active.id);
|
|
||||||
const newIndex = workspaceList.findIndex(w => w.id === over?.id);
|
|
||||||
const newList = arrayMove(workspaceList, oldIndex, newIndex);
|
|
||||||
return newList;
|
|
||||||
});
|
|
||||||
props.onDragEnd(event);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[props]
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<DndContext sensors={sensors} onDragEnd={onDragEnd} modifiers={modifiers}>
|
|
||||||
<SortableContext items={optimisticList}>
|
|
||||||
{optimisticList.map(item => (
|
|
||||||
<Suspense fallback={<WorkspaceCardSkeleton />} key={item.id}>
|
|
||||||
<SortableWorkspaceItem key={item.id} {...props} item={item} />
|
|
||||||
</Suspense>
|
|
||||||
))}
|
|
||||||
</SortableContext>
|
|
||||||
</DndContext>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ import { AuthService } from '@affine/core/modules/cloud';
|
|||||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||||
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
import { useAFFiNEI18N } from '@affine/i18n/hooks';
|
||||||
import { CloudWorkspaceIcon, LocalWorkspaceIcon } from '@blocksuite/icons';
|
import { CloudWorkspaceIcon, LocalWorkspaceIcon } from '@blocksuite/icons';
|
||||||
import type { DragEndEvent } from '@dnd-kit/core';
|
|
||||||
import type { WorkspaceMetadata } from '@toeverything/infra';
|
import type { WorkspaceMetadata } from '@toeverything/infra';
|
||||||
import {
|
import {
|
||||||
GlobalContextService,
|
GlobalContextService,
|
||||||
@@ -46,7 +45,6 @@ interface WorkspaceModalProps {
|
|||||||
onClickEnableCloud?: (meta: WorkspaceMetadata) => void;
|
onClickEnableCloud?: (meta: WorkspaceMetadata) => void;
|
||||||
onNewWorkspace: () => void;
|
onNewWorkspace: () => void;
|
||||||
onAddWorkspace: () => void;
|
onAddWorkspace: () => void;
|
||||||
onDragEnd: (event: DragEndEvent) => void;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CloudWorkSpaceList = ({
|
const CloudWorkSpaceList = ({
|
||||||
@@ -55,7 +53,6 @@ const CloudWorkSpaceList = ({
|
|||||||
onClickWorkspace,
|
onClickWorkspace,
|
||||||
onClickWorkspaceSetting,
|
onClickWorkspaceSetting,
|
||||||
currentWorkspaceId,
|
currentWorkspaceId,
|
||||||
onDragEnd,
|
|
||||||
}: WorkspaceModalProps) => {
|
}: WorkspaceModalProps) => {
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
if (workspaces.length === 0) {
|
if (workspaces.length === 0) {
|
||||||
@@ -77,7 +74,6 @@ const CloudWorkSpaceList = ({
|
|||||||
currentWorkspaceId={currentWorkspaceId}
|
currentWorkspaceId={currentWorkspaceId}
|
||||||
onClick={onClickWorkspace}
|
onClick={onClickWorkspace}
|
||||||
onSettingClick={onClickWorkspaceSetting}
|
onSettingClick={onClickWorkspaceSetting}
|
||||||
onDragEnd={onDragEnd}
|
|
||||||
useIsWorkspaceOwner={useIsWorkspaceOwner}
|
useIsWorkspaceOwner={useIsWorkspaceOwner}
|
||||||
useWorkspaceName={useWorkspaceName}
|
useWorkspaceName={useWorkspaceName}
|
||||||
useWorkspaceAvatar={useWorkspaceAvatar}
|
useWorkspaceAvatar={useWorkspaceAvatar}
|
||||||
@@ -94,7 +90,6 @@ const LocalWorkspaces = ({
|
|||||||
onClickEnableCloud,
|
onClickEnableCloud,
|
||||||
openingId,
|
openingId,
|
||||||
currentWorkspaceId,
|
currentWorkspaceId,
|
||||||
onDragEnd,
|
|
||||||
}: WorkspaceModalProps) => {
|
}: WorkspaceModalProps) => {
|
||||||
const t = useAFFiNEI18N();
|
const t = useAFFiNEI18N();
|
||||||
if (workspaces.length === 0) {
|
if (workspaces.length === 0) {
|
||||||
@@ -118,7 +113,6 @@ const LocalWorkspaces = ({
|
|||||||
onClick={onClickWorkspace}
|
onClick={onClickWorkspace}
|
||||||
onSettingClick={onClickWorkspaceSetting}
|
onSettingClick={onClickWorkspaceSetting}
|
||||||
onEnableCloudClick={onClickEnableCloud}
|
onEnableCloudClick={onClickEnableCloud}
|
||||||
onDragEnd={onDragEnd}
|
|
||||||
useIsWorkspaceOwner={useIsWorkspaceOwner}
|
useIsWorkspaceOwner={useIsWorkspaceOwner}
|
||||||
useWorkspaceName={useWorkspaceName}
|
useWorkspaceName={useWorkspaceName}
|
||||||
useWorkspaceAvatar={useWorkspaceAvatar}
|
useWorkspaceAvatar={useWorkspaceAvatar}
|
||||||
@@ -190,15 +184,6 @@ export const AFFiNEWorkspaceList = ({
|
|||||||
[confirmEnableCloud, workspacesService]
|
[confirmEnableCloud, workspacesService]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onMoveWorkspace = useCallback((_activeId: string, _overId: string) => {
|
|
||||||
// TODO: order
|
|
||||||
// const oldIndex = workspaces.findIndex(w => w.id === activeId);
|
|
||||||
// const newIndex = workspaces.findIndex(w => w.id === overId);
|
|
||||||
// startTransition(() => {
|
|
||||||
// setWorkspaces(workspaces => arrayMove(workspaces, oldIndex, newIndex));
|
|
||||||
// });
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const onClickWorkspace = useCallback(
|
const onClickWorkspace = useCallback(
|
||||||
(workspaceMetadata: WorkspaceMetadata) => {
|
(workspaceMetadata: WorkspaceMetadata) => {
|
||||||
jumpToSubPath(workspaceMetadata.id, WorkspaceSubPath.ALL);
|
jumpToSubPath(workspaceMetadata.id, WorkspaceSubPath.ALL);
|
||||||
@@ -207,16 +192,6 @@ export const AFFiNEWorkspaceList = ({
|
|||||||
[jumpToSubPath, onEventEnd]
|
[jumpToSubPath, onEventEnd]
|
||||||
);
|
);
|
||||||
|
|
||||||
const onDragEnd = useCallback(
|
|
||||||
(event: DragEndEvent) => {
|
|
||||||
const { active, over } = event;
|
|
||||||
if (active.id !== over?.id) {
|
|
||||||
onMoveWorkspace(active.id as string, over?.id as string);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
[onMoveWorkspace]
|
|
||||||
);
|
|
||||||
|
|
||||||
const onNewWorkspace = useCallback(() => {
|
const onNewWorkspace = useCallback(() => {
|
||||||
setOpenCreateWorkspaceModal('new');
|
setOpenCreateWorkspaceModal('new');
|
||||||
onEventEnd?.();
|
onEventEnd?.();
|
||||||
@@ -241,7 +216,6 @@ export const AFFiNEWorkspaceList = ({
|
|||||||
onNewWorkspace={onNewWorkspace}
|
onNewWorkspace={onNewWorkspace}
|
||||||
onAddWorkspace={onAddWorkspace}
|
onAddWorkspace={onAddWorkspace}
|
||||||
currentWorkspaceId={currentWorkspaceId}
|
currentWorkspaceId={currentWorkspaceId}
|
||||||
onDragEnd={onDragEnd}
|
|
||||||
/>
|
/>
|
||||||
{localWorkspaces.length > 0 && cloudWorkspaces.length > 0 ? (
|
{localWorkspaces.length > 0 && cloudWorkspaces.length > 0 ? (
|
||||||
<Divider size="thinner" />
|
<Divider size="thinner" />
|
||||||
@@ -256,7 +230,6 @@ export const AFFiNEWorkspaceList = ({
|
|||||||
onNewWorkspace={onNewWorkspace}
|
onNewWorkspace={onNewWorkspace}
|
||||||
onAddWorkspace={onAddWorkspace}
|
onAddWorkspace={onAddWorkspace}
|
||||||
currentWorkspaceId={currentWorkspaceId}
|
currentWorkspaceId={currentWorkspaceId}
|
||||||
onDragEnd={onDragEnd}
|
|
||||||
/>
|
/>
|
||||||
</ScrollableContainer>
|
</ScrollableContainer>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ test('create one workspace in the workspace list', async ({
|
|||||||
expect(currentWorkspace.meta.flavour).toContain('local');
|
expect(currentWorkspace.meta.flavour).toContain('local');
|
||||||
});
|
});
|
||||||
|
|
||||||
test('create multi workspace in the workspace list', async ({
|
test.skip('create multi workspace in the workspace list', async ({
|
||||||
page,
|
page,
|
||||||
workspace,
|
workspace,
|
||||||
}) => {
|
}) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user