From df4d71b0c82a6728c27b759fdb4217607011222e Mon Sep 17 00:00:00 2001 From: JimmFly Date: Fri, 1 Sep 2023 02:16:58 +0800 Subject: [PATCH] feat: add worksapce type label (#4045) Co-authored-by: Alex Yang --- .../new-workspace-setting-detail/index.tsx | 2 + .../new-workspace-setting-detail/labels.tsx | 103 ++++++++++++++++++ .../new-workspace-setting-detail/style.css.ts | 23 ++++ .../src/components/pure/header/style.css.tsx | 1 + .../pure/workspace-list-modal/index.tsx | 4 +- .../pure/workspace-list-modal/styles.ts | 5 +- .../WorkspaceSelector/styles.ts | 17 ++- .../WorkspaceSelector/workspace-selector.tsx | 76 +++++++++++-- .../src/components/app-sidebar/index.css.ts | 2 +- 9 files changed, 213 insertions(+), 20 deletions(-) create mode 100644 apps/core/src/components/affine/new-workspace-setting-detail/labels.tsx diff --git a/apps/core/src/components/affine/new-workspace-setting-detail/index.tsx b/apps/core/src/components/affine/new-workspace-setting-detail/index.tsx index 18c295585f..1822150ea9 100644 --- a/apps/core/src/components/affine/new-workspace-setting-detail/index.tsx +++ b/apps/core/src/components/affine/new-workspace-setting-detail/index.tsx @@ -14,6 +14,7 @@ import { useMemo } from 'react'; import { useWorkspace } from '../../../hooks/use-workspace'; import { DeleteLeaveWorkspace } from './delete-leave-workspace'; import { ExportPanel } from './export'; +import { LabelsPanel } from './labels'; import { MembersPanel } from './members'; import { ProfilePanel } from './profile'; import { PublishPanel } from './publish'; @@ -69,6 +70,7 @@ export const WorkspaceSettingDetail = (props: WorkspaceSettingDetailProps) => { spreadCol={false} > + diff --git a/apps/core/src/components/affine/new-workspace-setting-detail/labels.tsx b/apps/core/src/components/affine/new-workspace-setting-detail/labels.tsx new file mode 100644 index 0000000000..f6005c3f23 --- /dev/null +++ b/apps/core/src/components/affine/new-workspace-setting-detail/labels.tsx @@ -0,0 +1,103 @@ +import type { AffineOfficialWorkspace } from '@affine/env/workspace'; +import { useMemo } from 'react'; + +import { type WorkspaceSettingDetailProps } from './index'; +import * as style from './style.css'; + +export interface LabelsPanelProps extends WorkspaceSettingDetailProps { + workspace: AffineOfficialWorkspace; +} + +type WorkspaceStatus = + | 'local' + | 'syncCloud' + | 'syncDocker' + | 'selfHosted' + | 'joinedWorkspace' + | 'availableOffline' + | 'publishedToWeb'; + +type LabelProps = { + value: string; + background: string; +}; + +type LabelMap = { + [key in WorkspaceStatus]: LabelProps; +}; +type labelConditionsProps = { + condition: boolean; + label: WorkspaceStatus; +}; +const Label = ({ value, background }: LabelProps) => { + return ( +
+
+ {value} +
+
+ ); +}; +export const LabelsPanel = ({ workspace, isOwner }: LabelsPanelProps) => { + const labelMap: LabelMap = useMemo( + () => ({ + local: { + value: 'Local', + background: 'var(--affine-tag-orange)', + }, + syncCloud: { + value: 'Sync with AFFiNE Cloud', + background: 'var(--affine-tag-blue)', + }, + syncDocker: { + value: 'Sync with AFFiNE Docker', + background: 'var(--affine-tag-green)', + }, + selfHosted: { + value: 'Self-Hosted Server', + background: 'var(--affine-tag-purple)', + }, + joinedWorkspace: { + value: 'Joined Workspace', + background: 'var(--affine-tag-yellow)', + }, + availableOffline: { + value: 'Available Offline', + background: 'var(--affine-tag-green)', + }, + publishedToWeb: { + value: 'Published to Web', + background: 'var(--affine-tag-blue)', + }, + }), + [] + ); + const labelConditions: labelConditionsProps[] = [ + { condition: !isOwner, label: 'joinedWorkspace' }, + { condition: workspace.flavour === 'local', label: 'local' }, + { condition: workspace.flavour === 'affine-cloud', label: 'syncCloud' }, + { + condition: workspace.flavour === 'affine-public', + label: 'publishedToWeb', + }, + //TODO: add these labels + // { status==="synced", label: 'availableOffline' } + // { workspace.flavour === 'affine-Docker', label: 'syncDocker' } + // { workspace.flavour === 'self-hosted', label: 'selfHosted' } + ]; + + return ( +
+ {labelConditions.map( + ({ condition, label }) => + condition && ( +
+ ); +}; diff --git a/apps/core/src/components/affine/new-workspace-setting-detail/style.css.ts b/apps/core/src/components/affine/new-workspace-setting-detail/style.css.ts index 366d229771..6881c116a7 100644 --- a/apps/core/src/components/affine/new-workspace-setting-detail/style.css.ts +++ b/apps/core/src/components/affine/new-workspace-setting-detail/style.css.ts @@ -12,6 +12,15 @@ export const profileHandlerWrapper = style({ marginLeft: '20px', }); +export const labelWrapper = style({ + width: '100%', + display: 'flex', + alignItems: 'center', + marginTop: '24px', + gap: '10px', + flexWrap: 'wrap', +}); + export const avatarWrapper = style({ width: '56px', height: '56px', @@ -146,3 +155,17 @@ export const label = style({ color: 'var(--affine-text-secondary-color)', marginBottom: '5px', }); +export const workspaceLabel = style({ + width: '100%', + display: 'flex', + flexWrap: 'wrap', + justifyContent: 'center', + alignItems: 'center', + borderRadius: '6px', + padding: '2px 10px', + border: '1px solid var(--affine-white-30)', + fontSize: 'var(--affine-font-xs)', + color: 'var(--affine-text-primary-color)', + lineHeight: '20px', + whiteSpace: 'nowrap', +}); diff --git a/apps/core/src/components/pure/header/style.css.tsx b/apps/core/src/components/pure/header/style.css.tsx index 17c6d72a0c..8a90c0116d 100644 --- a/apps/core/src/components/pure/header/style.css.tsx +++ b/apps/core/src/components/pure/header/style.css.tsx @@ -7,6 +7,7 @@ export const header = style({ position: 'relative', padding: '0 16px', minHeight: '52px', + background: 'var(--affine-background-primary-color)', borderBottom: '1px solid var(--affine-border-color)', zIndex: 2, selectors: { diff --git a/apps/core/src/components/pure/workspace-list-modal/index.tsx b/apps/core/src/components/pure/workspace-list-modal/index.tsx index 9396daa361..ed16caf3fc 100644 --- a/apps/core/src/components/pure/workspace-list-modal/index.tsx +++ b/apps/core/src/components/pure/workspace-list-modal/index.tsx @@ -110,9 +110,9 @@ const CloudWorkSpaceList = ({ <> - + {t['com.affine.workspace.cloud']()} - + diff --git a/apps/core/src/components/pure/workspace-list-modal/styles.ts b/apps/core/src/components/pure/workspace-list-modal/styles.ts index 8af728d9be..0e7d76672b 100644 --- a/apps/core/src/components/pure/workspace-list-modal/styles.ts +++ b/apps/core/src/components/pure/workspace-list-modal/styles.ts @@ -236,9 +236,8 @@ export const StyledModalBody = styled('div')(() => { export const StyledWorkspaceFlavourTitle = styled('div')(() => { return { - fontSize: '12px', - fontWeight: 600, + fontSize: 'var(--affine-font-xs)', color: 'var(--affine-text-secondary-color)', - lineHeight: '20px', + marginBottom: '4px', }; }); diff --git a/apps/core/src/components/pure/workspace-slider-bar/WorkspaceSelector/styles.ts b/apps/core/src/components/pure/workspace-slider-bar/WorkspaceSelector/styles.ts index ceabd79481..1aa77e2000 100644 --- a/apps/core/src/components/pure/workspace-slider-bar/WorkspaceSelector/styles.ts +++ b/apps/core/src/components/pure/workspace-slider-bar/WorkspaceSelector/styles.ts @@ -1,6 +1,10 @@ import { displayFlex, textEllipsis } from '@affine/component'; import { styled } from '@affine/component'; -export const StyledSelectorContainer = styled('div')(() => { +export const StyledSelectorContainer = styled('div')(({ + disableHoverBackground, +}: { + disableHoverBackground: boolean; +}) => { return { height: '58px', display: 'flex', @@ -10,7 +14,7 @@ export const StyledSelectorContainer = styled('div')(() => { color: 'var(--affine-text-primary-color)', ':hover': { cursor: 'pointer', - background: 'var(--affine-hover-color)', + background: disableHoverBackground ? '' : 'var(--affine-hover-color)', }, }; }); @@ -38,10 +42,17 @@ export const StyledWorkspaceStatus = styled('div')(() => { fontSize: 'var(--affine-font-sm)', color: 'var(--affine-text-secondary-color)', userSelect: 'none', + padding: '0 4px', + gap: '4px', + zIndex: '1', svg: { color: 'var(--affine-icon-color)', fontSize: 'var(--affine-font-base)', - marginRight: '4px', + }, + ':hover': { + cursor: 'pointer', + borderRadius: '4px', + background: 'var(--affine-hover-color)', }, }; }); diff --git a/apps/core/src/components/pure/workspace-slider-bar/WorkspaceSelector/workspace-selector.tsx b/apps/core/src/components/pure/workspace-slider-bar/WorkspaceSelector/workspace-selector.tsx index 17f290c219..79f3cdd373 100644 --- a/apps/core/src/components/pure/workspace-slider-bar/WorkspaceSelector/workspace-selector.tsx +++ b/apps/core/src/components/pure/workspace-slider-bar/WorkspaceSelector/workspace-selector.tsx @@ -1,9 +1,16 @@ import { WorkspaceAvatar } from '@affine/component/workspace-avatar'; -import { CloudWorkspaceIcon, LocalWorkspaceIcon } from '@blocksuite/icons'; +import { + CloudWorkspaceIcon, + LocalWorkspaceIcon, + NoNetworkIcon, +} from '@blocksuite/icons'; +import { Tooltip } from '@toeverything/components/tooltip'; import { useBlockSuiteWorkspaceName } from '@toeverything/hooks/use-block-suite-workspace-name'; import type React from 'react'; -import { useCallback } from 'react'; +import { useCallback, useMemo, useState } from 'react'; +import { useCurrentLoginStatus } from '../../../../hooks/affine/use-current-login-status'; +import { useSystemOnline } from '../../../../hooks/use-system-online'; import type { AllWorkspace } from '../../../../shared'; import { workspaceAvatarStyle } from './index.css'; import { @@ -29,7 +36,8 @@ export const WorkspaceSelector = ({ const [name] = useBlockSuiteWorkspaceName( currentWorkspace.blockSuiteWorkspace ); - + const [isHovered, setIsHovered] = useState(false); + const [container, setContainer] = useState(null); // Open dialog when `Enter` or `Space` pressed // TODO-Doma Refactor with `@radix-ui/react-dialog` or other libraries that handle these out of the box and be accessible by default // TODO: Delete this? @@ -43,13 +51,48 @@ export const WorkspaceSelector = ({ }, [onClick] ); + const loginStatus = useCurrentLoginStatus(); + const isOnline = useSystemOnline(); + const content = useMemo(() => { + if (!isOnline) { + return 'Disconnected, please check your network connection'; + } + if ( + loginStatus === 'authenticated' && + currentWorkspace.flavour !== 'local' + ) { + return 'Sync with AFFiNE Cloud'; + } + return 'Saved locally'; + }, [currentWorkspace.flavour, isOnline, loginStatus]); + const WorkspaceStatus = () => { + if (!isOnline) { + return ( + <> + + Offline + + ); + } + return ( + <> + {currentWorkspace.flavour === 'local' ? ( + + ) : ( + + )} + {currentWorkspace.flavour === 'local' ? 'Local' : 'AFFiNE Cloud'} + + ); + }; return ( @@ -63,14 +106,25 @@ export const WorkspaceSelector = ({ {name} - - {currentWorkspace.flavour === 'local' ? ( - - ) : ( - - )} - {currentWorkspace.flavour === 'local' ? 'Local' : 'AFFiNE Cloud'} - +
+ + { + setIsHovered(true); + }} + ref={setContainer} + onMouseLeave={() => setIsHovered(false)} + onClick={e => e.stopPropagation()} + > + + + +
); diff --git a/packages/component/src/components/app-sidebar/index.css.ts b/packages/component/src/components/app-sidebar/index.css.ts index 25f377c32d..16a9940d1f 100644 --- a/packages/component/src/components/app-sidebar/index.css.ts +++ b/packages/component/src/components/app-sidebar/index.css.ts @@ -13,7 +13,7 @@ export const navWrapperStyle = style({ width: navWidthVar, minWidth: navWidthVar, height: '100%', - zIndex: 1, + zIndex: 3, paddingBottom: '8px', backgroundColor: 'transparent', '@media': {