mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-13 16:16:46 +08:00
feat: add editor to article header
This commit is contained in:
@@ -1,6 +1,38 @@
|
||||
import { createContext } from 'react';
|
||||
import { useQuery } from '@affine/core/hooks/use-query';
|
||||
import type { PagePropertyType } from '@affine/core/modules/properties/services/schema';
|
||||
import { WorkspaceFlavour } from '@affine/env/workspace';
|
||||
import { getWorkspacePageMetaByIdQuery } from '@affine/graphql';
|
||||
import { createContext, useContext } from 'react';
|
||||
import type { Middleware } from 'swr';
|
||||
|
||||
import type { PagePropertiesManager } from './page-properties-manager';
|
||||
|
||||
// @ts-expect-error this should always be set
|
||||
export const managerContext = createContext<PagePropertiesManager>();
|
||||
|
||||
export const useCloudPageMeta = (type: PagePropertyType) => {
|
||||
const manager = useContext(managerContext);
|
||||
const isCloud = manager.workspace.flavour === WorkspaceFlavour.AFFINE_CLOUD;
|
||||
const { data, error, isLoading } = useQuery({
|
||||
query: getWorkspacePageMetaByIdQuery,
|
||||
variables: {
|
||||
id: manager.workspace.id,
|
||||
pageId: manager.pageId,
|
||||
},
|
||||
});
|
||||
|
||||
if (!!error || !data?.workspace?.pageMeta) return { isCloud, isLoading };
|
||||
const pageMeta = data.workspace.pageMeta;
|
||||
return {
|
||||
isCloud,
|
||||
isLoading,
|
||||
metadata: pageMeta[type as keyof typeof pageMeta],
|
||||
};
|
||||
};
|
||||
|
||||
export const SWRCustomHandler: Middleware =
|
||||
next => (key, fetcher: any, config: any) => {
|
||||
const wrappedFetcher = (...args: any[]) =>
|
||||
fetcher?.(...args).catch(() => null);
|
||||
return next(key, wrappedFetcher, config);
|
||||
};
|
||||
|
||||
@@ -109,6 +109,10 @@ export const getDefaultIconName = (
|
||||
return 'checkBoxCheckLinear';
|
||||
case 'number':
|
||||
return 'number';
|
||||
case 'createdBy':
|
||||
return 'account';
|
||||
case 'updatedBy':
|
||||
return 'account';
|
||||
default:
|
||||
return 'text';
|
||||
}
|
||||
|
||||
+2
@@ -35,6 +35,8 @@ export const newPropertyTypes: PagePropertyType[] = [
|
||||
PagePropertyType.Number,
|
||||
PagePropertyType.Checkbox,
|
||||
PagePropertyType.Date,
|
||||
PagePropertyType.CreatedBy,
|
||||
PagePropertyType.UpdatedBy,
|
||||
// TODO(@Peng): add more
|
||||
];
|
||||
|
||||
|
||||
+72
-4
@@ -1,16 +1,25 @@
|
||||
import { Checkbox, DatePicker, Menu } from '@affine/component';
|
||||
import { Avatar, Checkbox, DatePicker, Menu } from '@affine/component';
|
||||
import { AuthService } from '@affine/core/modules/cloud';
|
||||
import type {
|
||||
PageInfoCustomProperty,
|
||||
PageInfoCustomPropertyMeta,
|
||||
PagePropertyType,
|
||||
} from '@affine/core/modules/properties/services/schema';
|
||||
import { i18nTime, useI18n } from '@affine/i18n';
|
||||
import { DocService, useService } from '@toeverything/infra';
|
||||
import { DocService, useLiveData, useService } from '@toeverything/infra';
|
||||
import { noop } from 'lodash-es';
|
||||
import type { ChangeEventHandler } from 'react';
|
||||
import { useCallback, useContext, useEffect, useRef, useState } from 'react';
|
||||
import {
|
||||
useCallback,
|
||||
useContext,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useRef,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { SWRConfig } from 'swr';
|
||||
|
||||
import { managerContext } from './common';
|
||||
import { managerContext, SWRCustomHandler, useCloudPageMeta } from './common';
|
||||
import * as styles from './styles.css';
|
||||
import { TagsInlineEditor } from './tags-inline-editor';
|
||||
|
||||
@@ -190,6 +199,63 @@ export const TagsValue = () => {
|
||||
);
|
||||
};
|
||||
|
||||
const CloudUserAvatar = (props: { type: PagePropertyType }) => {
|
||||
const session = useService(AuthService).session;
|
||||
const account = useLiveData(session.account$);
|
||||
const { isCloud, isLoading, metadata } = useCloudPageMeta(props.type);
|
||||
|
||||
const user = useMemo(() => {
|
||||
if (isCloud) {
|
||||
if (!metadata || typeof metadata !== 'object') return null;
|
||||
return metadata;
|
||||
} else {
|
||||
if (!account) return null;
|
||||
return { name: account.label, avatarUrl: account.avatar };
|
||||
}
|
||||
}, [account, isCloud, metadata]);
|
||||
|
||||
const t = useI18n();
|
||||
|
||||
if (isLoading) return null;
|
||||
if (isCloud) {
|
||||
if (user) {
|
||||
return (
|
||||
<>
|
||||
<Avatar url={user.avatarUrl || ''} name={user.name} size={20} />
|
||||
<span>{user.name}</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<>
|
||||
<Avatar name="?" size={20} />
|
||||
<span>
|
||||
{t['com.affine.page-properties.property-user-avatar-no-record']()}
|
||||
</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
if (account) {
|
||||
return (
|
||||
<>
|
||||
<Avatar url={account.avatar || ''} name={account.label} size={20} />
|
||||
<span>{account.label}</span>
|
||||
</>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export const UserValue = ({ meta }: PropertyRowValueProps) => {
|
||||
return (
|
||||
<div className={styles.propertyRowValueUserCell}>
|
||||
<SWRConfig value={parent => ({ ...parent, use: [SWRCustomHandler] })}>
|
||||
<CloudUserAvatar type={meta.type} />
|
||||
</SWRConfig>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const propertyValueRenderers: Record<
|
||||
PagePropertyType,
|
||||
typeof DateValue
|
||||
@@ -198,6 +264,8 @@ export const propertyValueRenderers: Record<
|
||||
checkbox: CheckboxValue,
|
||||
text: TextValue,
|
||||
number: NumberValue,
|
||||
createdBy: UserValue,
|
||||
updatedBy: UserValue,
|
||||
// TODO(@Peng): fix following
|
||||
tags: TagsValue,
|
||||
progress: TextValue,
|
||||
|
||||
@@ -349,6 +349,16 @@ export const propertyRowValueTextCell = style([
|
||||
},
|
||||
]);
|
||||
|
||||
export const propertyRowValueUserCell = style([
|
||||
propertyRowValueCell,
|
||||
{
|
||||
border: 'none',
|
||||
height: '100%',
|
||||
overflow: 'hidden',
|
||||
columnGap: '0.5rem',
|
||||
},
|
||||
]);
|
||||
|
||||
export const propertyRowValueTextarea = style([
|
||||
propertyRowValueCell,
|
||||
{
|
||||
|
||||
@@ -21,6 +21,8 @@ export enum PagePropertyType {
|
||||
Progress = 'progress',
|
||||
Checkbox = 'checkbox',
|
||||
Tags = 'tags',
|
||||
CreatedBy = 'createdBy',
|
||||
UpdatedBy = 'updatedBy',
|
||||
}
|
||||
|
||||
export const PagePropertyMetaBaseSchema = z.object({
|
||||
|
||||
@@ -856,6 +856,7 @@
|
||||
"com.affine.page-properties.page-info": "Info",
|
||||
"com.affine.page-properties.page-info.view": "View Info",
|
||||
"com.affine.page-properties.property-value-placeholder": "Empty",
|
||||
"com.affine.page-properties.property-user-avatar-no-record": "No Record",
|
||||
"com.affine.page-properties.property.always-hide": "Always hide",
|
||||
"com.affine.page-properties.property.always-show": "Always show",
|
||||
"com.affine.page-properties.property.checkbox": "Checkbox",
|
||||
@@ -870,6 +871,8 @@
|
||||
"com.affine.page-properties.property.show-in-view": "Show in view",
|
||||
"com.affine.page-properties.property.tags": "Tags",
|
||||
"com.affine.page-properties.property.text": "Text",
|
||||
"com.affine.page-properties.property.createdBy": "Created by",
|
||||
"com.affine.page-properties.property.updatedBy": "Updated by",
|
||||
"com.affine.page-properties.settings.title": "customize properties",
|
||||
"com.affine.page-properties.tags.open-tags-page": "Open tag page",
|
||||
"com.affine.page-properties.tags.selector-header-title": "Select tag or create one",
|
||||
|
||||
Reference in New Issue
Block a user