mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-12 04:18:54 +00:00
@@ -7,11 +7,12 @@ import { useI18n } from '@affine/i18n';
|
||||
import { track } from '@affine/track';
|
||||
import type { DocMode } from '@blocksuite/affine/blocks';
|
||||
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 { nanoid } from 'nanoid';
|
||||
import {
|
||||
type PropsWithChildren,
|
||||
type ComponentType,
|
||||
type MouseEvent,
|
||||
useCallback,
|
||||
useMemo,
|
||||
useRef,
|
||||
@@ -21,20 +22,20 @@ import { Link } from 'react-router-dom';
|
||||
|
||||
import * as styles from './styles.css';
|
||||
|
||||
export function AffinePageReference({
|
||||
pageId,
|
||||
wrapper: Wrapper,
|
||||
params,
|
||||
className,
|
||||
}: {
|
||||
interface AffinePageReferenceProps {
|
||||
pageId: string;
|
||||
wrapper?: React.ComponentType<PropsWithChildren>;
|
||||
params?: URLSearchParams;
|
||||
className?: string;
|
||||
}) {
|
||||
Icon?: ComponentType;
|
||||
onClick?: (e: MouseEvent) => void;
|
||||
}
|
||||
|
||||
function AffinePageReferenceInner({
|
||||
pageId,
|
||||
params,
|
||||
Icon: UserIcon,
|
||||
}: AffinePageReferenceProps) {
|
||||
const docDisplayMetaService = useService(DocDisplayMetaService);
|
||||
const journalService = useService(JournalService);
|
||||
const isJournal = !!useLiveData(journalService.journalDate$(pageId));
|
||||
const i18n = useI18n();
|
||||
|
||||
let linkWithMode: DocMode | null = null;
|
||||
@@ -48,22 +49,40 @@ export function AffinePageReference({
|
||||
}
|
||||
|
||||
const Icon = useLiveData(
|
||||
docDisplayMetaService.icon$(pageId, {
|
||||
mode: linkWithMode ?? undefined,
|
||||
reference: true,
|
||||
referenceToNode: linkToNode,
|
||||
LiveData.computed(get => {
|
||||
if (UserIcon) {
|
||||
return UserIcon;
|
||||
}
|
||||
return get(
|
||||
docDisplayMetaService.icon$(pageId, {
|
||||
mode: linkWithMode ?? undefined,
|
||||
reference: true,
|
||||
referenceToNode: linkToNode,
|
||||
})
|
||||
);
|
||||
})
|
||||
);
|
||||
const title = useLiveData(
|
||||
docDisplayMetaService.title$(pageId, { reference: true })
|
||||
);
|
||||
|
||||
const el = (
|
||||
return (
|
||||
<>
|
||||
<Icon className={styles.pageReferenceIcon} />
|
||||
<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);
|
||||
|
||||
@@ -74,6 +93,12 @@ export function AffinePageReference({
|
||||
|
||||
const onClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
userOnClick?.(e);
|
||||
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isJournal) {
|
||||
track.doc.editor.pageRef.navigate({
|
||||
to: 'journal',
|
||||
@@ -99,7 +124,7 @@ export function AffinePageReference({
|
||||
|
||||
return;
|
||||
},
|
||||
[isInPeekView, isJournal, peekView]
|
||||
[isInPeekView, isJournal, peekView, userOnClick]
|
||||
);
|
||||
|
||||
const query = useMemo(() => {
|
||||
@@ -117,7 +142,7 @@ export function AffinePageReference({
|
||||
onClick={onClick}
|
||||
className={clsx(styles.pageReferenceLink, className)}
|
||||
>
|
||||
{Wrapper ? <Wrapper>{el}</Wrapper> : el}
|
||||
<AffinePageReferenceInner pageId={pageId} params={params} Icon={Icon} />
|
||||
</WorkbenchLink>
|
||||
);
|
||||
}
|
||||
@@ -125,43 +150,14 @@ export function AffinePageReference({
|
||||
export function AffineSharedPageReference({
|
||||
pageId,
|
||||
docCollection,
|
||||
wrapper: Wrapper,
|
||||
params,
|
||||
}: {
|
||||
pageId: string;
|
||||
Icon,
|
||||
onClick: userOnClick,
|
||||
}: AffinePageReferenceProps & {
|
||||
docCollection: DocCollection;
|
||||
wrapper?: React.ComponentType<PropsWithChildren>;
|
||||
params?: URLSearchParams;
|
||||
}) {
|
||||
const docDisplayMetaService = useService(DocDisplayMetaService);
|
||||
const journalService = useService(JournalService);
|
||||
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);
|
||||
|
||||
@@ -169,6 +165,12 @@ export function AffineSharedPageReference({
|
||||
|
||||
const onClick = useCallback(
|
||||
(e: React.MouseEvent) => {
|
||||
userOnClick?.(e);
|
||||
|
||||
if (e.defaultPrevented) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isJournal) {
|
||||
track.doc.editor.pageRef.navigate({
|
||||
to: 'journal',
|
||||
@@ -183,7 +185,7 @@ export function AffineSharedPageReference({
|
||||
|
||||
return;
|
||||
},
|
||||
[isJournal]
|
||||
[isJournal, userOnClick]
|
||||
);
|
||||
|
||||
const query = useMemo(() => {
|
||||
@@ -201,7 +203,7 @@ export function AffineSharedPageReference({
|
||||
onClick={onClick}
|
||||
className={styles.pageReferenceLink}
|
||||
>
|
||||
{Wrapper ? <Wrapper>{el}</Wrapper> : el}
|
||||
<AffinePageReferenceInner pageId={pageId} params={params} Icon={Icon} />
|
||||
</Link>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import { globalStyle, style } from '@vanilla-extract/css';
|
||||
|
||||
export const wrapper = style({
|
||||
@@ -9,6 +10,9 @@ export const wrapper = style({
|
||||
flexDirection: 'row',
|
||||
alignItems: 'center',
|
||||
padding: 4,
|
||||
':hover': {
|
||||
background: cssVarV2('layer/background/hoverOverlay'),
|
||||
},
|
||||
});
|
||||
|
||||
globalStyle(`${wrapper} svg`, {
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { PropertyCollapsibleSection } from '@affine/component';
|
||||
import type { Backlink, Link } from '@affine/core/modules/doc-link';
|
||||
import type { MouseEvent } from 'react';
|
||||
|
||||
import { AffinePageReference } from '../../affine/reference-link';
|
||||
import * as styles from './links-row.css';
|
||||
@@ -13,7 +14,7 @@ export const LinksRow = ({
|
||||
references: Backlink[] | Link[];
|
||||
label: string;
|
||||
className?: string;
|
||||
onClick?: () => void;
|
||||
onClick?: (e: MouseEvent) => void;
|
||||
}) => {
|
||||
return (
|
||||
<PropertyCollapsibleSection
|
||||
@@ -25,9 +26,8 @@ export const LinksRow = ({
|
||||
key={index}
|
||||
pageId={link.docId}
|
||||
params={'params' in link ? link.params : undefined}
|
||||
wrapper={props => (
|
||||
<div className={styles.wrapper} onClick={onClick} {...props} />
|
||||
)}
|
||||
className={styles.wrapper}
|
||||
onClick={onClick}
|
||||
/>
|
||||
))}
|
||||
</PropertyCollapsibleSection>
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import {
|
||||
Button,
|
||||
Menu,
|
||||
MenuItem,
|
||||
PropertyCollapsibleContent,
|
||||
PropertyCollapsibleSection,
|
||||
PropertyName,
|
||||
@@ -27,20 +26,15 @@ import {
|
||||
} from '@toeverything/infra';
|
||||
import clsx from 'clsx';
|
||||
import type React from 'react';
|
||||
import type { HTMLProps, PropsWithChildren } from 'react';
|
||||
import type { HTMLProps } from 'react';
|
||||
import { forwardRef, useCallback, useState } from 'react';
|
||||
|
||||
import { AffinePageReference } from '../affine/reference-link';
|
||||
import { DocPropertyIcon } from './icons/doc-property-icon';
|
||||
import { CreatePropertyMenuItems } from './menu/create-doc-property';
|
||||
import { EditDocPropertyMenuItems } from './menu/edit-doc-property';
|
||||
import * as styles from './table.css';
|
||||
import { DocPropertyTypes, isSupportedDocPropertyType } from './types/constant';
|
||||
|
||||
type DocBacklinksPopupProps = PropsWithChildren<{
|
||||
backlinks: { docId: string; blockId: string; title: string }[];
|
||||
}>;
|
||||
|
||||
export type DefaultOpenProperty =
|
||||
| {
|
||||
type: 'workspace';
|
||||
@@ -55,35 +49,6 @@ export interface DocPropertiesTableProps {
|
||||
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 {
|
||||
className?: string;
|
||||
style?: React.CSSProperties;
|
||||
|
||||
@@ -71,14 +71,12 @@ export const DocPropertyTypes = {
|
||||
value: UpdatedDateValue,
|
||||
name: 'com.affine.page-properties.property.updatedAt',
|
||||
renameable: false,
|
||||
uniqueId: 'updatedAt',
|
||||
},
|
||||
createdAt: {
|
||||
icon: HistoryIcon,
|
||||
value: CreateDateValue,
|
||||
name: 'com.affine.page-properties.property.createdAt',
|
||||
renameable: false,
|
||||
uniqueId: 'createdAt',
|
||||
},
|
||||
docPrimaryMode: {
|
||||
icon: FileIcon,
|
||||
|
||||
@@ -65,7 +65,7 @@ const MetaDateValueFactory = ({
|
||||
const date = value ? i18nTime(value) : null;
|
||||
|
||||
return (
|
||||
<Tooltip content={date}>
|
||||
<Tooltip content={date} side="top" align="end">
|
||||
<PropertyValue
|
||||
className={relativeDate ? '' : styles.empty}
|
||||
isEmpty={!relativeDate}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { cssVar } from '@toeverything/theme';
|
||||
import { cssVarV2 } from '@toeverything/theme/v2';
|
||||
import { globalStyle, style } from '@vanilla-extract/css';
|
||||
import { style } from '@vanilla-extract/css';
|
||||
|
||||
export const root = style({
|
||||
display: 'flex',
|
||||
@@ -41,7 +41,3 @@ export const cellList = style({
|
||||
flexDirection: 'column',
|
||||
gap: 4,
|
||||
});
|
||||
|
||||
globalStyle(`${docRefLink} .affine-reference-title`, {
|
||||
border: 'none',
|
||||
});
|
||||
|
||||
@@ -7,7 +7,7 @@ import {
|
||||
import { AffinePageReference } from '@affine/core/components/affine/reference-link';
|
||||
import { useI18n } from '@affine/i18n';
|
||||
import type { DatabaseBlockDataSource } from '@blocksuite/affine/blocks';
|
||||
import { DatabaseTableViewIcon } from '@blocksuite/icons/rc';
|
||||
import { DatabaseTableViewIcon, PageIcon } from '@blocksuite/icons/rc';
|
||||
import {
|
||||
DocService,
|
||||
LiveData,
|
||||
@@ -117,6 +117,7 @@ const DatabaseBacklinkRow = ({
|
||||
className={styles.docRefLink}
|
||||
pageId={row.docId}
|
||||
params={pageRefParams}
|
||||
Icon={PageIcon}
|
||||
/>
|
||||
}
|
||||
>
|
||||
|
||||
Reference in New Issue
Block a user