@@ -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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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`, {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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,
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
@@ -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',
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -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}
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
>
|
>
|
||||||
|
|||||||
Reference in New Issue
Block a user