fix(core): db properties ui issues (#8638)

fix AF-1562
fix BS-1711
This commit is contained in:
pengx17
2024-10-31 04:46:50 +00:00
parent afcf595626
commit d96cc097c2
8 changed files with 68 additions and 102 deletions

View File

@@ -7,11 +7,12 @@ import { useI18n } from '@affine/i18n';
import { track } from '@affine/track'; import { track } from '@affine/track';
import type { DocMode } from '@blocksuite/affine/blocks'; import type { DocMode } from '@blocksuite/affine/blocks';
import type { DocCollection } from '@blocksuite/affine/store'; import type { DocCollection } from '@blocksuite/affine/store';
import { useLiveData, useService } from '@toeverything/infra'; import { LiveData, useLiveData, useService } from '@toeverything/infra';
import clsx from 'clsx'; import clsx from 'clsx';
import { nanoid } from 'nanoid'; import { nanoid } from 'nanoid';
import { import {
type PropsWithChildren, type ComponentType,
type MouseEvent,
useCallback, useCallback,
useMemo, useMemo,
useRef, useRef,
@@ -21,20 +22,20 @@ import { Link } from 'react-router-dom';
import * as styles from './styles.css'; import * as styles from './styles.css';
export function AffinePageReference({ interface AffinePageReferenceProps {
pageId,
wrapper: Wrapper,
params,
className,
}: {
pageId: string; pageId: string;
wrapper?: React.ComponentType<PropsWithChildren>;
params?: URLSearchParams; params?: URLSearchParams;
className?: string; className?: string;
}) { Icon?: ComponentType;
onClick?: (e: MouseEvent) => void;
}
function AffinePageReferenceInner({
pageId,
params,
Icon: UserIcon,
}: AffinePageReferenceProps) {
const docDisplayMetaService = useService(DocDisplayMetaService); const docDisplayMetaService = useService(DocDisplayMetaService);
const journalService = useService(JournalService);
const isJournal = !!useLiveData(journalService.journalDate$(pageId));
const i18n = useI18n(); const i18n = useI18n();
let linkWithMode: DocMode | null = null; let linkWithMode: DocMode | null = null;
@@ -48,22 +49,40 @@ export function AffinePageReference({
} }
const Icon = useLiveData( const Icon = useLiveData(
docDisplayMetaService.icon$(pageId, { LiveData.computed(get => {
mode: linkWithMode ?? undefined, if (UserIcon) {
reference: true, return UserIcon;
referenceToNode: linkToNode, }
return get(
docDisplayMetaService.icon$(pageId, {
mode: linkWithMode ?? undefined,
reference: true,
referenceToNode: linkToNode,
})
);
}) })
); );
const title = useLiveData( const title = useLiveData(
docDisplayMetaService.title$(pageId, { reference: true }) docDisplayMetaService.title$(pageId, { reference: true })
); );
const el = ( return (
<> <>
<Icon className={styles.pageReferenceIcon} /> <Icon className={styles.pageReferenceIcon} />
<span className="affine-reference-title">{i18n.t(title)}</span> <span className="affine-reference-title">{i18n.t(title)}</span>
</> </>
); );
}
export function AffinePageReference({
pageId,
params,
className,
Icon,
onClick: userOnClick,
}: AffinePageReferenceProps) {
const journalService = useService(JournalService);
const isJournal = !!useLiveData(journalService.journalDate$(pageId));
const ref = useRef<HTMLAnchorElement>(null); const ref = useRef<HTMLAnchorElement>(null);
@@ -74,6 +93,12 @@ export function AffinePageReference({
const onClick = useCallback( const onClick = useCallback(
(e: React.MouseEvent) => { (e: React.MouseEvent) => {
userOnClick?.(e);
if (e.defaultPrevented) {
return;
}
if (isJournal) { if (isJournal) {
track.doc.editor.pageRef.navigate({ track.doc.editor.pageRef.navigate({
to: 'journal', to: 'journal',
@@ -99,7 +124,7 @@ export function AffinePageReference({
return; return;
}, },
[isInPeekView, isJournal, peekView] [isInPeekView, isJournal, peekView, userOnClick]
); );
const query = useMemo(() => { const query = useMemo(() => {
@@ -117,7 +142,7 @@ export function AffinePageReference({
onClick={onClick} onClick={onClick}
className={clsx(styles.pageReferenceLink, className)} className={clsx(styles.pageReferenceLink, className)}
> >
{Wrapper ? <Wrapper>{el}</Wrapper> : el} <AffinePageReferenceInner pageId={pageId} params={params} Icon={Icon} />
</WorkbenchLink> </WorkbenchLink>
); );
} }
@@ -125,43 +150,14 @@ export function AffinePageReference({
export function AffineSharedPageReference({ export function AffineSharedPageReference({
pageId, pageId,
docCollection, docCollection,
wrapper: Wrapper,
params, params,
}: { Icon,
pageId: string; onClick: userOnClick,
}: AffinePageReferenceProps & {
docCollection: DocCollection; docCollection: DocCollection;
wrapper?: React.ComponentType<PropsWithChildren>;
params?: URLSearchParams;
}) { }) {
const docDisplayMetaService = useService(DocDisplayMetaService);
const journalService = useService(JournalService); const journalService = useService(JournalService);
const isJournal = !!useLiveData(journalService.journalDate$(pageId)); const isJournal = !!useLiveData(journalService.journalDate$(pageId));
const i18n = useI18n();
let linkWithMode: DocMode | null = null;
let linkToNode = false;
if (params) {
const m = params.get('mode');
if (m && (m === 'page' || m === 'edgeless')) {
linkWithMode = m as DocMode;
}
linkToNode = params.has('blockIds') || params.has('elementIds');
}
const Icon = useLiveData(
docDisplayMetaService.icon$(pageId, {
mode: linkWithMode ?? undefined,
reference: true,
referenceToNode: linkToNode,
})
);
const title = useLiveData(docDisplayMetaService.title$(pageId));
const el = (
<>
<Icon className={styles.pageReferenceIcon} />
<span className="affine-reference-title">{i18n.t(title)}</span>
</>
);
const ref = useRef<HTMLAnchorElement>(null); const ref = useRef<HTMLAnchorElement>(null);
@@ -169,6 +165,12 @@ export function AffineSharedPageReference({
const onClick = useCallback( const onClick = useCallback(
(e: React.MouseEvent) => { (e: React.MouseEvent) => {
userOnClick?.(e);
if (e.defaultPrevented) {
return;
}
if (isJournal) { if (isJournal) {
track.doc.editor.pageRef.navigate({ track.doc.editor.pageRef.navigate({
to: 'journal', to: 'journal',
@@ -183,7 +185,7 @@ export function AffineSharedPageReference({
return; return;
}, },
[isJournal] [isJournal, userOnClick]
); );
const query = useMemo(() => { const query = useMemo(() => {
@@ -201,7 +203,7 @@ export function AffineSharedPageReference({
onClick={onClick} onClick={onClick}
className={styles.pageReferenceLink} className={styles.pageReferenceLink}
> >
{Wrapper ? <Wrapper>{el}</Wrapper> : el} <AffinePageReferenceInner pageId={pageId} params={params} Icon={Icon} />
</Link> </Link>
); );
} }

View File

@@ -1,4 +1,5 @@
import { cssVar } from '@toeverything/theme'; import { cssVar } from '@toeverything/theme';
import { cssVarV2 } from '@toeverything/theme/v2';
import { globalStyle, style } from '@vanilla-extract/css'; import { globalStyle, style } from '@vanilla-extract/css';
export const wrapper = style({ export const wrapper = style({
@@ -9,6 +10,9 @@ export const wrapper = style({
flexDirection: 'row', flexDirection: 'row',
alignItems: 'center', alignItems: 'center',
padding: 4, padding: 4,
':hover': {
background: cssVarV2('layer/background/hoverOverlay'),
},
}); });
globalStyle(`${wrapper} svg`, { globalStyle(`${wrapper} svg`, {

View File

@@ -1,5 +1,6 @@
import { PropertyCollapsibleSection } from '@affine/component'; import { PropertyCollapsibleSection } from '@affine/component';
import type { Backlink, Link } from '@affine/core/modules/doc-link'; import type { Backlink, Link } from '@affine/core/modules/doc-link';
import type { MouseEvent } from 'react';
import { AffinePageReference } from '../../affine/reference-link'; import { AffinePageReference } from '../../affine/reference-link';
import * as styles from './links-row.css'; import * as styles from './links-row.css';
@@ -13,7 +14,7 @@ export const LinksRow = ({
references: Backlink[] | Link[]; references: Backlink[] | Link[];
label: string; label: string;
className?: string; className?: string;
onClick?: () => void; onClick?: (e: MouseEvent) => void;
}) => { }) => {
return ( return (
<PropertyCollapsibleSection <PropertyCollapsibleSection
@@ -25,9 +26,8 @@ export const LinksRow = ({
key={index} key={index}
pageId={link.docId} pageId={link.docId}
params={'params' in link ? link.params : undefined} params={'params' in link ? link.params : undefined}
wrapper={props => ( className={styles.wrapper}
<div className={styles.wrapper} onClick={onClick} {...props} /> onClick={onClick}
)}
/> />
))} ))}
</PropertyCollapsibleSection> </PropertyCollapsibleSection>

View File

@@ -1,7 +1,6 @@
import { import {
Button, Button,
Menu, Menu,
MenuItem,
PropertyCollapsibleContent, PropertyCollapsibleContent,
PropertyCollapsibleSection, PropertyCollapsibleSection,
PropertyName, PropertyName,
@@ -27,20 +26,15 @@ import {
} from '@toeverything/infra'; } from '@toeverything/infra';
import clsx from 'clsx'; import clsx from 'clsx';
import type React from 'react'; import type React from 'react';
import type { HTMLProps, PropsWithChildren } from 'react'; import type { HTMLProps } from 'react';
import { forwardRef, useCallback, useState } from 'react'; import { forwardRef, useCallback, useState } from 'react';
import { AffinePageReference } from '../affine/reference-link';
import { DocPropertyIcon } from './icons/doc-property-icon'; import { DocPropertyIcon } from './icons/doc-property-icon';
import { CreatePropertyMenuItems } from './menu/create-doc-property'; import { CreatePropertyMenuItems } from './menu/create-doc-property';
import { EditDocPropertyMenuItems } from './menu/edit-doc-property'; import { EditDocPropertyMenuItems } from './menu/edit-doc-property';
import * as styles from './table.css'; import * as styles from './table.css';
import { DocPropertyTypes, isSupportedDocPropertyType } from './types/constant'; import { DocPropertyTypes, isSupportedDocPropertyType } from './types/constant';
type DocBacklinksPopupProps = PropsWithChildren<{
backlinks: { docId: string; blockId: string; title: string }[];
}>;
export type DefaultOpenProperty = export type DefaultOpenProperty =
| { | {
type: 'workspace'; type: 'workspace';
@@ -55,35 +49,6 @@ export interface DocPropertiesTableProps {
defaultOpenProperty?: DefaultOpenProperty; defaultOpenProperty?: DefaultOpenProperty;
} }
export const DocBacklinksPopup = ({
backlinks,
children,
}: DocBacklinksPopupProps) => {
return (
<Menu
contentOptions={{
className: styles.backLinksMenu,
onClick(e) {
e.stopPropagation();
},
}}
items={
<div className={styles.backlinksList}>
{backlinks.map(link => (
<AffinePageReference
key={link.docId + ':' + link.blockId}
wrapper={MenuItem}
pageId={link.docId}
/>
))}
</div>
}
>
{children}
</Menu>
);
};
interface DocPropertiesTableHeaderProps { interface DocPropertiesTableHeaderProps {
className?: string; className?: string;
style?: React.CSSProperties; style?: React.CSSProperties;

View File

@@ -71,14 +71,12 @@ export const DocPropertyTypes = {
value: UpdatedDateValue, value: UpdatedDateValue,
name: 'com.affine.page-properties.property.updatedAt', name: 'com.affine.page-properties.property.updatedAt',
renameable: false, renameable: false,
uniqueId: 'updatedAt',
}, },
createdAt: { createdAt: {
icon: HistoryIcon, icon: HistoryIcon,
value: CreateDateValue, value: CreateDateValue,
name: 'com.affine.page-properties.property.createdAt', name: 'com.affine.page-properties.property.createdAt',
renameable: false, renameable: false,
uniqueId: 'createdAt',
}, },
docPrimaryMode: { docPrimaryMode: {
icon: FileIcon, icon: FileIcon,

View File

@@ -65,7 +65,7 @@ const MetaDateValueFactory = ({
const date = value ? i18nTime(value) : null; const date = value ? i18nTime(value) : null;
return ( return (
<Tooltip content={date}> <Tooltip content={date} side="top" align="end">
<PropertyValue <PropertyValue
className={relativeDate ? '' : styles.empty} className={relativeDate ? '' : styles.empty}
isEmpty={!relativeDate} isEmpty={!relativeDate}

View File

@@ -1,6 +1,6 @@
import { cssVar } from '@toeverything/theme'; import { cssVar } from '@toeverything/theme';
import { cssVarV2 } from '@toeverything/theme/v2'; import { cssVarV2 } from '@toeverything/theme/v2';
import { globalStyle, style } from '@vanilla-extract/css'; import { style } from '@vanilla-extract/css';
export const root = style({ export const root = style({
display: 'flex', display: 'flex',
@@ -41,7 +41,3 @@ export const cellList = style({
flexDirection: 'column', flexDirection: 'column',
gap: 4, gap: 4,
}); });
globalStyle(`${docRefLink} .affine-reference-title`, {
border: 'none',
});

View File

@@ -7,7 +7,7 @@ import {
import { AffinePageReference } from '@affine/core/components/affine/reference-link'; import { AffinePageReference } from '@affine/core/components/affine/reference-link';
import { useI18n } from '@affine/i18n'; import { useI18n } from '@affine/i18n';
import type { DatabaseBlockDataSource } from '@blocksuite/affine/blocks'; import type { DatabaseBlockDataSource } from '@blocksuite/affine/blocks';
import { DatabaseTableViewIcon } from '@blocksuite/icons/rc'; import { DatabaseTableViewIcon, PageIcon } from '@blocksuite/icons/rc';
import { import {
DocService, DocService,
LiveData, LiveData,
@@ -117,6 +117,7 @@ const DatabaseBacklinkRow = ({
className={styles.docRefLink} className={styles.docRefLink}
pageId={row.docId} pageId={row.docId}
params={pageRefParams} params={pageRefParams}
Icon={PageIcon}
/> />
} }
> >