refactor: client (#1092)

Reviewed-on: daoyoucloud/tachybase#1092
This commit is contained in:
sealday 2024-05-31 18:43:29 +08:00
parent a947d639fc
commit c882909bad
92 changed files with 289 additions and 356 deletions

View File

@ -1,68 +0,0 @@
import { dayjs } from '@tachybase/utils/client';
import { ConfigProvider, Spin } from 'antd';
import React, { createContext, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { useAPIClient, useRequest } from '../api-client';
import { Plugin } from '../application/Plugin';
import { loadConstrueLocale } from './loadConstrueLocale';
export const AppLangContext = createContext<any>({});
AppLangContext.displayName = 'AppLangContext';
export const useAppLangContext = () => {
return useContext(AppLangContext);
};
export function AntdConfigProvider(props) {
const { remoteLocale, ...others } = props;
const api = useAPIClient();
const { i18n } = useTranslation();
const { data, loading } = useRequest<{
data: {
lang: string;
resources: any;
moment: string;
antd: any;
cron: any;
};
}>(
{
url: 'app:getLang',
params: {
locale: api.auth.locale,
},
},
{
onSuccess(data) {
const locale = api.auth.locale;
if (data?.data?.lang && !locale) {
api.auth.setLocale(data?.data?.lang);
i18n.changeLanguage(data?.data?.lang);
}
Object.keys(data?.data?.resources || {}).forEach((key) => {
i18n.addResources(data?.data?.lang, key, data?.data?.resources[key] || {});
});
loadConstrueLocale(data?.data);
dayjs.locale(data?.data?.moment);
window['cronLocale'] = data?.data?.cron;
},
manual: !remoteLocale,
},
);
if (loading) {
return <Spin />;
}
return (
<AppLangContext.Provider value={data?.data}>
<ConfigProvider popupMatchSelectWidth={false} {...others} locale={data?.data?.antd || {}}>
{props.children}
</ConfigProvider>
</AppLangContext.Provider>
);
}
export class AntdConfigPlugin extends Plugin {
async load() {
this.app.use(AntdConfigProvider, this.options?.config || {});
}
}

View File

@ -1,7 +1,9 @@
import React from 'react';
import { APIClient as APIClientSDK, getSubAppName } from '@tachybase/sdk';
import { Result } from 'ahooks/es/useRequest/src/types';
import { notification } from 'antd';
import React from 'react';
import { Application } from '../application';
function notify(type, messages, instance) {

View File

@ -1,4 +1,5 @@
import React, { ReactNode } from 'react';
import { APIClient } from './APIClient';
import { APIClientContext } from './context';
@ -7,7 +8,7 @@ export interface APIClientProviderProps {
children?: ReactNode;
}
export const APIClientProvider: React.FC<APIClientProviderProps> = (props) => {
export const APIClientProvider = (props: APIClientProviderProps) => {
const { apiClient, children } = props;
return <APIClientContext.Provider value={apiClient}>{children}</APIClientContext.Provider>;
};

View File

@ -1,6 +1,7 @@
import { isPlainObject } from '@tachybase/utils/client';
import deepmerge from 'deepmerge';
import uniq from 'lodash/uniq';
import { uniq } from 'lodash';
type MergeStrategyType = 'merge' | 'deepMerge' | 'overwrite' | 'andMerge' | 'orMerge' | 'intersect' | 'union';
type MergeStrategyFunc = (x: any, y: any) => any;

View File

@ -1,4 +1,5 @@
import React, { createContext, useContext } from 'react';
import { useRequest } from '../api-client';
import { useAppSpin } from '../application/hooks/useAppSpin';

View File

@ -1 +0,0 @@
# AppInfo

View File

@ -5,16 +5,14 @@ import { useLocalStorageState } from 'ahooks';
import { SchemaComponentProvider } from '../schema-component/core';
import { ISchemaComponentProvider } from '../schema-component/types';
const getKeyByName = (name) => {
const getKeyByName = (name?: string) => {
if (!name) {
return 'tachybase_designable'.toUpperCase();
}
return `tachybase_${name}_designable`.toUpperCase();
};
const SchemaComponentProviderWithLocalStorageState: React.FC<ISchemaComponentProvider & { appName?: string }> = (
props,
) => {
const SchemaComponentProviderWithLocalStorageState = (props: ISchemaComponentProvider & { appName?: string }) => {
const [designable, setDesignable] = useLocalStorageState(getKeyByName(props.appName), {
defaultValue: props.designable ? true : false,
});
@ -29,7 +27,7 @@ const SchemaComponentProviderWithLocalStorageState: React.FC<ISchemaComponentPro
);
};
export const AppSchemaComponentProvider: React.FC<ISchemaComponentProvider> = (props) => {
export const AppSchemaComponentProvider = (props: ISchemaComponentProvider) => {
if (typeof props.designable === 'boolean') {
return <SchemaComponentProvider {...props} />;
}

View File

@ -9,13 +9,13 @@ import { I18nextProvider } from 'react-i18next';
import { Link, Navigate, NavLink } from 'react-router-dom';
import { APIClient, APIClientProvider } from '../api-client';
import { CSSVariableProvider } from '../css-variable';
import { CollectionField } from '../data-source/collection-field/CollectionField';
import { DataSourceApplicationProvider } from '../data-source/components/DataSourceApplicationProvider';
import { DataBlockProvider } from '../data-source/data-block/DataBlockProvider';
import { DataSourceManager, type DataSourceManagerOptions } from '../data-source/data-source/DataSourceManager';
import { AntdAppProvider, GlobalThemeProvider } from '../global-theme';
import { i18n } from '../i18n';
import { CSSVariableProvider } from '../style/css-variable';
import { AntdAppProvider, GlobalThemeProvider } from '../style/theme';
import { AppSchemaComponentProvider } from './AppSchemaComponentProvider';
import { AppComponent, BlankComponent, defaultAppComponents } from './components';
import type { Plugin } from './Plugin';
@ -215,7 +215,6 @@ export class Application {
let loadFailed = false;
this.ws.on('message', (event) => {
const data = JSON.parse(event.data);
console.log(data.payload);
if (data?.payload?.refresh) {
window.location.reload();
return;
@ -229,7 +228,6 @@ export class Application {
this.maintaining = true;
this.error = data.payload;
} else {
// console.log('loadFailed', loadFailed);
if (loadFailed) {
window.location.reload();
return;

View File

@ -1,4 +1,5 @@
import { TFuncKey, TOptions } from 'i18next';
import type { Application } from './Application';
export class Plugin<T = any> {

View File

@ -1,5 +1,6 @@
import { set } from 'lodash';
import React, { createElement } from 'react';
import { set } from 'lodash';
import { Outlet } from 'react-router-dom';
import { Icon } from '../icon';

View File

@ -116,7 +116,6 @@ export class WebSocketClient {
this.connected = true;
};
ws.onerror = async () => {
// setTimeout(() => this.connect(), this.reconnectInterval);
console.log('onerror', this.readyState, this._reconnectTimes);
};
ws.onclose = async (event) => {

View File

@ -1,8 +1,10 @@
import { useExpressionScope } from '@tachybase/schema';
import React, { ComponentType, useMemo } from 'react';
import { useDesignable } from '../../schema-component';
import { useExpressionScope } from '@tachybase/schema';
import _ from 'lodash';
import { useDesignable } from '../../schema-component';
const useDefaultSchemaProps = () => undefined;
interface WithSchemaHookOptions {

View File

@ -6,8 +6,6 @@ group:
# Application V2
<img src="https://tachybase.oss-cn-beijing.aliyuncs.com/5be7ebc2f47effef85be7a0c75cf76f9.png" style="max-width: 800px;" />
## Usage
### 基础用法

View File

@ -1,14 +1,14 @@
import { createForm } from '@tachybase/schema';
import { useField } from '@tachybase/schema';
import React, { createContext, useContext, useEffect, useMemo, useRef } from 'react';
import { createForm, useField } from '@tachybase/schema';
import { Spin } from 'antd';
import _ from 'lodash';
import React, { createContext, useContext, useEffect, useMemo, useRef } from 'react';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
import { useCollectionParentRecord } from '../data-source/collection-record/CollectionRecordProvider';
import { RecordProvider } from '../record-provider';
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
import { useParsedFilter } from './hooks';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
import { TemplateBlockProvider } from './TemplateBlockProvider';
export const DetailsBlockContext = createContext<any>({});
DetailsBlockContext.displayName = 'DetailsBlockContext';
@ -65,11 +65,9 @@ const InternalDetailsBlockProvider = (props) => {
export const DetailsBlockProvider = withDynamicSchemaProps((props) => {
return (
<TemplateBlockProvider>
<BlockProvider name="details" {...props}>
<InternalDetailsBlockProvider {...props} />
</BlockProvider>
</TemplateBlockProvider>
);
});

View File

@ -1,8 +1,9 @@
import React from 'react';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
import { DatePickerProvider } from '../schema-component';
import { DefaultValueProvider } from '../schema-settings';
import { FormBlockProvider } from './FormBlockProvider';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
export const FilterFormBlockProvider = withDynamicSchemaProps((props) => {
return (

View File

@ -11,7 +11,6 @@ import { useActionContext, useDesignable } from '../schema-component';
import { Templates as DataTemplateSelect } from '../schema-component/antd/form-v2/Templates';
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
import { FormActiveFieldsProvider } from './hooks/useFormActiveFields';
import { TemplateBlockProvider } from './TemplateBlockProvider';
export const FormBlockContext = createContext<{
form?: any;
@ -114,7 +113,6 @@ export const FormBlockProvider = withDynamicSchemaProps((props) => {
}
return (
<TemplateBlockProvider>
<BlockProvider
name={props.name || 'form'}
{...props}
@ -125,7 +123,6 @@ export const FormBlockProvider = withDynamicSchemaProps((props) => {
<InternalFormBlockProvider {...props} />
</FormActiveFieldsProvider>
</BlockProvider>
</TemplateBlockProvider>
);
});

View File

@ -1,9 +1,9 @@
import { createForm, onFormValuesChange } from '@tachybase/schema';
import { useField } from '@tachybase/schema';
import { autorun } from '@tachybase/schema';
import { forEach } from '@tachybase/utils/client';
import { Spin } from 'antd';
import React, { createContext, useContext, useEffect, useMemo } from 'react';
import { autorun, createForm, onFormValuesChange, useField } from '@tachybase/schema';
import { forEach } from '@tachybase/utils/client';
import { Spin } from 'antd';
import { useCollectionParentRecordData } from '../data-source/collection-record/CollectionRecordProvider';
import { RecordProvider } from '../record-provider';
import { BlockProvider, useBlockRequestContext } from './BlockProvider';

View File

@ -1,12 +1,11 @@
import { createForm } from '@tachybase/schema';
import { FormContext, useField, useFieldSchema } from '@tachybase/schema';
import React, { createContext, useContext, useMemo, useState } from 'react';
import { createForm, FormContext, useField, useFieldSchema } from '@tachybase/schema';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
import { useCollectionManager_deprecated } from '../collection-manager';
import { useTableBlockParams } from '../modules/blocks/data-blocks/table/hooks/useTableBlockDecoratorProps';
import { FixedBlockWrapper, SchemaComponentOptions } from '../schema-component';
import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider';
import { useParsedFilter } from './hooks';
import { useTableBlockParams } from '../modules/blocks/data-blocks/table/hooks/useTableBlockDecoratorProps';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
export const TableBlockContext = createContext<any>({});
TableBlockContext.displayName = 'TableBlockContext';

View File

@ -1,6 +1,6 @@
import { ArrayField, Field } from '@tachybase/schema';
import { useField, useFieldSchema } from '@tachybase/schema';
import React, { createContext, useContext, useEffect } from 'react';
import { ArrayField, Field, useField, useFieldSchema } from '@tachybase/schema';
import { APIClient } from '../api-client';
import { BlockProvider, useBlockRequestContext } from './BlockProvider';
import { useFormBlockContext } from './FormBlockProvider';
@ -23,9 +23,6 @@ const InternalTableFieldProvider = (props) => {
if (!formBlockCtx?.updateAssociationValues?.includes(fullFieldName)) {
formBlockCtx?.updateAssociationValues?.push(fullFieldName);
}
// if (service.loading) {
// return <Spin />;
// }
return (
<TableFieldContext.Provider
value={{
@ -59,7 +56,6 @@ export class TableFieldResource {
async list(options) {
this.field.data = this.field.data || {};
if (this.field.data.changed) {
console.log('list.dataSource', this.field.data.dataSource);
return {
data: {
data: this.field.data.dataSource,
@ -67,7 +63,6 @@ export class TableFieldResource {
};
}
if (!this.sourceId) {
console.log('list.sourceId', this.field.data.dataSource);
this.field.data.dataSource = [];
return {
data: {
@ -76,7 +71,6 @@ export class TableFieldResource {
};
}
const response = await this.resource.list(options);
console.log('list', response);
this.field.data.dataSource = response.data.data;
return {
data: {
@ -86,7 +80,6 @@ export class TableFieldResource {
}
async get(options) {
console.log('get', options);
const { filterByTk } = options;
return {
data: {
@ -96,21 +89,18 @@ export class TableFieldResource {
}
async create(options) {
console.log('create', options);
const { values } = options;
this.field.data.dataSource.push(values);
this.field.data.changed = true;
}
async update(options) {
console.log('update', options);
const { filterByTk, values } = options;
this.field.data.dataSource[filterByTk] = values;
this.field.data.changed = true;
}
async destroy(options) {
console.log('destroy', options);
let { filterByTk } = options;
if (!Array.isArray(filterByTk)) {
filterByTk = [filterByTk];

View File

@ -1,8 +1,9 @@
import { ArrayField } from '@tachybase/schema';
import { Schema, useField, useFieldSchema } from '@tachybase/schema';
import _ from 'lodash';
import uniq from 'lodash/uniq';
import React, { createContext, useContext, useEffect, useState } from 'react';
import { ArrayField, Schema, useField, useFieldSchema } from '@tachybase/schema';
import _, { uniq } from 'lodash';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
import { useCollectionManager_deprecated } from '../collection-manager';
import { useCollectionParentRecordData } from '../data-source/collection-record/CollectionRecordProvider';
import { isInFilterFormBlock } from '../filter-provider';
@ -11,7 +12,6 @@ import { RecordProvider, useRecord } from '../record-provider';
import { SchemaComponentOptions } from '../schema-component';
import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider';
import { useParsedFilter } from './hooks';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
type Params = {
filter?: any;
@ -54,9 +54,6 @@ const InternalTableSelectorProvider = (props) => {
const { resource, service } = useBlockRequestContext();
const [expandFlag, setExpandFlag] = useState(false);
const parentRecordData = useCollectionParentRecordData();
// if (service.loading) {
// return <Spin />;
// }
return (
<RecordProvider record={{}} parent={parentRecordData}>
<TableSelectorContext.Provider
@ -79,14 +76,6 @@ const InternalTableSelectorProvider = (props) => {
);
};
const useAssociationNames2 = (collection) => {
const { getCollectionFields } = useCollectionManager_deprecated();
const names = getCollectionFields(collection)
?.filter((field) => field.target)
.map((field) => field.name);
return names;
};
export const recursiveParent = (schema: Schema, component) => {
return schema['x-component'] === component
? schema

View File

@ -1,23 +0,0 @@
import React, { createContext, useContext, useState } from 'react';
const TemplateBlockContext = createContext<{
// 模板是否已经请求结束
templateFinshed?: boolean;
onTemplateSuccess?: Function;
}>({});
TemplateBlockContext.displayName = 'TemplateBlockContext';
export const useTemplateBlockContext = () => {
return useContext(TemplateBlockContext);
};
const TemplateBlockProvider = (props) => {
const [templateFinshed, setTemplateFinshed] = useState(false);
return (
<TemplateBlockContext.Provider value={{ templateFinshed, onTemplateSuccess: () => setTemplateFinshed(true) }}>
{props.children}
</TemplateBlockContext.Provider>
);
};
export { TemplateBlockProvider };

View File

@ -36,15 +36,6 @@ export * from './useFormActiveFields';
export * from './useParsedFilter';
export * from './useDataBlockSourceId';
export const usePickActionProps = () => {
const form = useForm();
return {
onClick() {
console.log('usePickActionProps', form.values);
},
};
};
function renderTemplate(str: string, data: any) {
const re = /\{\{\s*((\w+\.?)+)\s*\}\}/g;
return str.replace(re, function (_, key) {

View File

@ -1,7 +1,10 @@
import { useState } from 'react';
import { reaction } from '@tachybase/schema';
import { flatten, getValuesByPath } from '@tachybase/utils/client';
import { useDeepCompareEffect } from 'ahooks';
import _ from 'lodash';
import { useEffect, useState } from 'react';
import { useParseDataScopeFilter } from '../../schema-settings';
import { DEBOUNCE_WAIT } from '../../variables';
import { getPath } from '../../variables/utils/getPath';
@ -12,7 +15,7 @@ export function useParsedFilter({ filterOption }: { filterOption: any }) {
const { parseFilter, findVariable } = useParseDataScopeFilter();
const [filter, setFilter] = useState({});
useEffect(() => {
useDeepCompareEffect(() => {
if (!filterOption) return;
const _run = async () => {
@ -50,7 +53,7 @@ export function useParsedFilter({ filterOption }: { filterOption: any }) {
});
return flat;
}, run);
}, [JSON.stringify(filterOption)]);
}, [filterOption]);
return { filter };
}

View File

@ -1 +0,0 @@
# BlockProvider

View File

@ -12,7 +12,7 @@ import { Application } from '../application';
import { Plugin } from '../application/Plugin';
import { BlockSchemaComponentPlugin } from '../block-provider';
import { CollectionPlugin } from '../collection-manager';
import { AdminLayoutPlugin, RouteSchemaComponent } from '../route-switch';
import { RouteSchemaComponent } from '../route-switch';
import { AntdSchemaComponentPlugin, SchemaComponentPlugin } from '../schema-component';
import { ErrorFallback } from '../schema-component/antd/error-fallback';
import { AssociationFilterPlugin, SchemaInitializerPlugin } from '../schema-initializer';
@ -20,12 +20,15 @@ import { SchemaSettingsPlugin } from '../schema-settings';
import { BlockTemplateDetails, BlockTemplatePage } from '../schema-templates';
import { CurrentUserProvider, CurrentUserSettingsMenuProvider } from '../user';
import { ACLPlugin } from './acl';
import { AdminLayoutPlugin } from './admin-layout';
import { RemoteDocumentTitlePlugin } from './document-title';
import { LocalePlugin } from './locale/LocalePlugin';
import { PinnedListPlugin } from './pinned-list';
import { PMPlugin } from './pm';
import { SystemSettingsPlugin } from './system-settings';
export { AdminProvider } from './admin-layout';
interface AppStatusProps {
error: Error;
app: Application;
@ -224,11 +227,6 @@ const AppMaintaining = observer(
status={status}
title={app.i18n.t(title)}
subTitle={app.i18n.t(subTitle)}
// extra={[
// <Button type="primary" key="try" onClick={() => window.location.reload()}>
// {app.i18n.t('Try again')}
// </Button>,
// ]}
/>
</div>
);

View File

@ -3,7 +3,7 @@ import { setValidateLanguage } from '@tachybase/schema';
import { App, ConfigProvider } from 'antd';
import dayjs from 'dayjs';
import { loadConstrueLocale } from '../../antd-config-provider/loadConstrueLocale';
import { loadConstrueLocale } from './loadConstrueLocale';
import { Plugin } from '../../application/Plugin';
import { dayjsLocale } from '../../locale';

View File

@ -164,9 +164,7 @@ class CronstrueLocale {
}
export const loadConstrueLocale = (data) => {
// vite bug: https://github.com/vitejs/vite/issues/2139
const cronstrueVal = (cronstrue as any).default ? (cronstrue as any).default : cronstrue;
cronstrueVal.initialize({
cronstrue.initialize({
load(availableLocales) {
availableLocales[data?.lang] = new CronstrueLocale(data?.cronstrue);
},

View File

@ -3,9 +3,9 @@ import React, { memo, useCallback, useEffect, useMemo, useState } from 'react';
import { Spin } from 'antd';
import { useRequest } from '../../api-client';
import { useGlobalTheme } from '../../global-theme';
import { useStyles as useMarkdownStyles } from '../../schema-component/antd/markdown/style';
import { useParseMarkdown } from '../../schema-component/antd/markdown/util';
import { useGlobalTheme } from '../../style/theme';
import { useStyles } from './style';
const PLUGIN_STATICS_PATH = '/static/plugins/';

View File

@ -34,8 +34,6 @@ export const CollectionHistoryProvider = (props) => {
const location = useLocation();
// console.log('location', location);
const service = useRequest<{
data: any;
}>(options, {

View File

@ -478,7 +478,7 @@ export const useUpdateAction = (actionCallback?: (key: string, values: any) => v
await form.reset();
refresh();
} catch (e) {
console.log(e);
console.error(e);
} finally {
field.data.loading = false;
}

View File

@ -1,6 +1,8 @@
import { observer, useForm } from '@tachybase/schema';
import { cloneDeep } from 'lodash';
import React, { createContext, useContext, useState } from 'react';
import { observer, useForm } from '@tachybase/schema';
import { cloneDeep } from 'lodash';
import {
CollectionOptions,
CollectionProvider_deprecated,
@ -97,7 +99,6 @@ const useCreateAction = () => {
const { setVisible } = useActionContext();
return {
async run() {
console.log('form.values', form.values);
const dataSource = ctx.dataSource || [];
dataSource.push(cloneDeep(form.values));
ctx.setDataSource([...dataSource]);
@ -199,7 +200,6 @@ export const SubFieldDataSourceProvider_deprecated = observer(
},
{
onSuccess(data) {
console.log('dataSource1', data?.data);
setDataSource(data?.data);
},
},

View File

@ -1,13 +0,0 @@
import defaultTheme from './defaultTheme';
import { ThemeConfig } from './type';
// 兼容旧主题
function compatOldTheme(theme: ThemeConfig) {
if (!theme.token?.colorSettings) {
theme.token = { ...theme.token, ...defaultTheme.token };
}
return theme;
}
export default compatOldTheme;

View File

@ -40,5 +40,6 @@ export function useViewport() {
return () => {
restore();
};
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
}

View File

@ -18,27 +18,13 @@ Object.keys(locale).forEach((lang) => {
resources[lang] = locale[lang].resources;
});
i18n
// .use(Backend)
.use(initReactI18next)
.init({
i18n.use(initReactI18next).init({
lng: localStorage.getItem('TACHYBASE_LOCALE') || 'en-US',
// debug: true,
defaultNS: 'client',
// fallbackNS: 'client',
// backend: {
// // for all available options read the backend's repository readme file
// loadPath: '/api/locales/{{lng}}/{{ns}}.json',
// },
// parseMissingKeyHandler: (key) => {
// console.log('parseMissingKeyHandler', `'${key}': '${key}',`);
// return key;
// },
// ns: ['client'],
resources: {},
keySeparator: false,
nsSeparator: false,
});
});
i18n.on('languageChanged', (lng) => {
localStorage.setItem('TACHYBASE_LOCALE', lng);

View File

@ -4,7 +4,6 @@ import './global.less';
export * from '@emotion/css';
export * from './buildin-plugin/acl';
export * from './antd-config-provider';
export * from './api-client';
export * from './appInfo';
export * from './application';
@ -13,12 +12,12 @@ export * from './block-provider';
export * from './collection-manager';
export * from './common';
export * from './css-variable';
export * from './style/css-variable';
export * from './data-source';
export * from './buildin-plugin/document-title';
export * from './filter-provider';
export * from './flag-provider';
export * from './global-theme';
export * from './style/theme';
export * from './hooks';
export * from './i18n';
export * from './icon';
@ -35,7 +34,7 @@ export * from './schema-items';
export * from './schema-settings';
export * from './schema-templates';
export * from './style';
export type { CustomToken } from './global-theme';
export type { CustomToken } from './style/theme';
export * from './buildin-plugin/system-settings';
export * from './testUtils';
export * from './user';

View File

@ -1,13 +1,14 @@
import { ISchema } from '@tachybase/schema';
import { useField, useFieldSchema } from '@tachybase/schema';
import { ISchema, useField, useFieldSchema } from '@tachybase/schema';
import { useTranslation } from 'react-i18next';
import { useApp } from '../../../../application';
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
import { useCollectionManager_deprecated } from '../../../../collection-manager';
import { useDesignable } from '../../../../schema-component';
import { useAssociationFieldContext } from '../../../../schema-component/antd/association-field/hooks';
import { useColumnSchema } from '../../../../schema-component/antd/table-v2/Table.Column.Decorator';
import { SchemaSettingsDefaultValue, isPatternDisabled } from '../../../../schema-settings';
import { isPatternDisabled, SchemaSettingsDefaultValue } from '../../../../schema-settings';
import { useFieldComponentName } from './utils';
export const tableColumnSettings = new SchemaSettings({
@ -297,6 +298,7 @@ export const tableColumnSettings = new SchemaSettings({
useChildren() {
const app = useApp();
const fieldComponentName = useFieldComponentName();
console.log('🚀 ~ file: tableColumnSettings.tsx:300 ~ useChildren ~ fieldComponentName:', fieldComponentName);
const map = {
Select: 'Select',
DatePicker: 'DatePicker',
@ -309,6 +311,12 @@ export const tableColumnSettings = new SchemaSettings({
const componentSettings = app.schemaSettingsManager.get(
`fieldSettings:component:${map[fieldComponentName] || fieldComponentName}`,
);
console.log(
'🚀 ~ file: tableColumnSettings.tsx:313 ~ useChildren ~ componentSettings:',
componentSettings,
app.schemaSettingsManager.getAll(),
);
console.log(`fieldSettings:component:${map[fieldComponentName] || fieldComponentName}`, 'fieldComponentName');
return componentSettings?.items || [];
},
},

View File

@ -1,7 +1,8 @@
import { useFieldSchema } from '@tachybase/schema';
import { SchemaSettings } from '../../../../application/schema-settings/SchemaSettings';
import { SchemaSettingsDateFormat } from '../../../../schema-settings/SchemaSettingsDateFormat';
import { useColumnSchema } from '../../../../schema-component/antd/table-v2/Table.Column.Decorator';
import { SchemaSettingsDateFormat } from '../../../../schema-settings/SchemaSettingsDateFormat';
export const datePickerComponentFieldSettings = new SchemaSettings({
name: 'fieldSettings:component:DatePicker',

View File

@ -1,11 +1,13 @@
import React, { useCallback, useContext } from 'react';
import { FormLayout } from '@tachybase/components';
import { SchemaOptionsContext } from '@tachybase/schema';
import React, { useCallback, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { FormDialog, SchemaComponent, SchemaComponentOptions } from '../../schema-component';
import { SchemaInitializerItem, useSchemaInitializer } from '../../application';
import { useGlobalTheme } from '../../global-theme';
import { FormDialog, SchemaComponent, SchemaComponentOptions } from '../../schema-component';
import { useStyles } from '../../schema-component/antd/menu/MenuItemInitializers';
import { useGlobalTheme } from '../../style/theme';
export const GroupItem = () => {
const { insert } = useSchemaInitializer();

View File

@ -1,11 +1,13 @@
import React, { useCallback, useContext } from 'react';
import { FormLayout } from '@tachybase/components';
import { SchemaOptionsContext } from '@tachybase/schema';
import React, { useCallback, useContext } from 'react';
import { useTranslation } from 'react-i18next';
import { FormDialog, SchemaComponent, SchemaComponentOptions } from '../../schema-component';
import { SchemaInitializerItem, useSchemaInitializer } from '../../application';
import { useGlobalTheme } from '../../global-theme';
import { FormDialog, SchemaComponent, SchemaComponentOptions } from '../../schema-component';
import { useStyles } from '../../schema-component/antd/menu/MenuItemInitializers';
import { useGlobalTheme } from '../../style/theme';
export const LinkMenuItem = () => {
const { insert } = useSchemaInitializer();

View File

@ -1,12 +1,13 @@
import { FormLayout } from '@tachybase/components';
import { SchemaOptionsContext } from '@tachybase/schema';
import { uid } from '@tachybase/schema';
import React, { useCallback, useContext } from 'react';
import { FormLayout } from '@tachybase/components';
import { SchemaOptionsContext, uid } from '@tachybase/schema';
import { useTranslation } from 'react-i18next';
import { SchemaInitializerItem, useSchemaInitializer } from '../../application';
import { useGlobalTheme } from '../../global-theme';
import { FormDialog, SchemaComponent, SchemaComponentOptions } from '../../schema-component';
import { useStyles } from '../../schema-component/antd/menu/MenuItemInitializers';
import { useGlobalTheme } from '../../style/theme';
export const PageMenuItem = () => {
const { insert } = useSchemaInitializer();

View File

@ -2,7 +2,7 @@ import React from 'react';
import { useParams } from 'react-router-dom';
import { RemoteSchemaComponent } from '../../../';
import { RemoteSchemaComponent } from '..';
export function RouteSchemaComponent(props: any) {
const params = useParams<any>();

View File

@ -1,2 +0,0 @@
export * from '../../buildin-plugin/admin-layout';
export * from './route-schema-component';

View File

@ -1 +1 @@
export * from './antd';
export * from './RouteSchemaComponent';

View File

@ -1,5 +1,6 @@
import { theme } from 'antd';
import { CustomToken } from '../../../../global-theme';
import { CustomToken } from '../../../../style/theme';
interface Result extends ReturnType<typeof theme.useToken> {
token: CustomToken;

View File

@ -1,10 +1,11 @@
import type { CSSInterpolation, CSSObject } from '@ant-design/cssinjs';
import { useStyleRegister } from '@ant-design/cssinjs';
import { merge } from '@tachybase/schema';
import type { ComponentTokenMap, GlobalToken } from 'antd/es/theme/interface';
import { CustomToken } from '../../../global-theme';
import { useConfig, usePrefixCls, useToken } from './hooks';
import { useMemo } from 'react';
import { merge } from '@tachybase/schema';
import { useStyleRegister, type CSSInterpolation, type CSSObject } from '@ant-design/cssinjs';
import type { ComponentTokenMap, GlobalToken } from 'antd/es/theme/interface';
import { CustomToken } from '../../../style/theme';
import { useConfig, usePrefixCls, useToken } from './hooks';
export type OverrideComponent = keyof ComponentTokenMap | string;

View File

@ -68,7 +68,7 @@ export const Action: ComposedAction = withDynamicSchemaProps(
const openSize = fieldSchema?.['x-component-props']?.['openSize'];
const disabled = form.disabled || field.disabled || field.data?.disabled || propsDisabled;
const linkageRules = fieldSchema?.['x-linkage-rules'] || [];
const linkageRules = useMemo(() => fieldSchema?.['x-linkage-rules'] || [], [fieldSchema]);
const { designable } = useDesignable();
const tarComponent = useComponent(component) || component;
const { modal } = App.useApp();

View File

@ -50,7 +50,7 @@ export const useCloseAction = () => {
async run() {
setVisible(false);
form.submit((values) => {
console.log(values);
console.warn(values);
});
},
};

View File

@ -20,7 +20,7 @@ import { Modal, ModalProps, ThemeConfig } from 'antd';
import { createPortal } from 'react-dom';
import { createPortalProvider, createPortalRoot, loading, usePrefixCls, useToken } from '../__builtins__';
import { GlobalThemeProvider } from '../../../global-theme';
import { GlobalThemeProvider } from '../../../style/theme';
type FormDialogRenderer = React.ReactElement | ((form: Form) => React.ReactElement);

View File

@ -23,7 +23,6 @@ import { createStyles } from 'antd-style';
import { useActionContext } from '..';
import { useAttach, useComponent } from '../..';
import { withDynamicSchemaProps } from '../../../application/hoc/withDynamicSchemaProps';
import { useTemplateBlockContext } from '../../../block-provider/TemplateBlockProvider';
import { ActionType } from '../../../schema-settings/LinkageRules/type';
import { useLocalVariables, useVariables } from '../../../variables';
import { VariableOption, VariablesContextType } from '../../../variables/types';
@ -83,7 +82,6 @@ const FormDecorator: React.FC<FormProps> = (props) => {
<RecursionField basePath={f.address} schema={fieldSchema} onlyRenderProperties />
</Component>
</FieldContext.Provider>
{/* <FieldContext.Provider value={f}>{children}</FieldContext.Provider> */}
</FormLayout>
</FormContext.Provider>
</FieldContext.Provider>
@ -111,7 +109,6 @@ const WithForm = (props: WithFormProps) => {
const { setFormValueChanged } = useActionContext();
const variables = useVariables();
const localVariables = useLocalVariables({ currentForm: form });
const { templateFinshed } = useTemplateBlockContext();
const linkageRules: any[] =
(getLinkageRules(fieldSchema) || fieldSchema.parent?.['x-linkage-rules'])?.filter((k) => !k.disabled) || [];
@ -191,7 +188,7 @@ const WithForm = (props: WithFormProps) => {
dispose();
});
};
}, [linkageRules, templateFinshed]);
}, [linkageRules]);
return fieldSchema['x-decorator'] === 'FormV2' ? <FormDecorator {...props} /> : <FormComponent {...props} />;
};
@ -332,7 +329,6 @@ function getFieldValuesInCondition({ linkageRules, formValues }) {
return conditions
.map((condition) => {
// fix
if ('$and' in condition || '$or' in condition) {
return run(condition);
}

View File

@ -1,9 +1,11 @@
import React, { useState } from 'react';
import { observer, useField, useFieldSchema } from '@tachybase/schema';
import { Input as AntdInput, Button, Space, Spin } from 'antd';
import cls from 'classnames';
import React, { useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useGlobalTheme } from '../../../global-theme';
import { useGlobalTheme } from '../../../style/theme';
import { useDesignable } from '../../hooks/useDesignable';
import { MarkdownVoidDesigner } from './Markdown.Void.Designer';
import { useStyles } from './style';

View File

@ -1,8 +1,10 @@
import { LoadingOutlined } from '@ant-design/icons';
import { connect, mapProps, mapReadPretty } from '@tachybase/schema';
import { Input as AntdInput, Spin } from 'antd';
import React from 'react';
import { useGlobalTheme } from '../../../global-theme';
import { connect, mapProps, mapReadPretty } from '@tachybase/schema';
import { LoadingOutlined } from '@ant-design/icons';
import { Input as AntdInput, Spin } from 'antd';
import { useGlobalTheme } from '../../../style/theme';
import { ReadPretty as InputReadPretty } from '../input';
import { MarkdownVoid } from './Markdown.Void';
import { useStyles } from './style';

View File

@ -89,7 +89,6 @@ const HeaderMenu = ({
if (!menuItemSchema) {
return onSelect?.(info);
}
// TODO
setLoading(true);
const keys = findKeysByUid(schema, menuItemSchema['x-uid']);
setDefaultSelectedKeys(keys);
@ -262,7 +261,6 @@ export const Menu: ComposedMenu = observer(
if (mode === 'mix' && key) {
const s = schema.properties?.[key];
// fix T-934
if (s?.['x-component'] === 'Menu.SubMenu') {
return s;
}

View File

@ -1,12 +1,14 @@
import { customAlphabet as Alphabet } from 'nanoid';
import React, { useEffect } from 'react';
import { LoadingOutlined } from '@ant-design/icons';
import { connect, mapProps, mapReadPretty, useForm } from '@tachybase/schema';
import { LoadingOutlined } from '@ant-design/icons';
import { Input as AntdInput } from 'antd';
import { ReadPretty } from '../input';
import { useCollectionField } from '../../../data-source/collection-field/CollectionFieldProvider';
import { customAlphabet as Alphabet } from 'nanoid';
import { useTranslation } from 'react-i18next';
import { useCollectionField } from '../../../data-source/collection-field/CollectionFieldProvider';
import { ReadPretty } from '../input';
export const NanoIDInput = Object.assign(
connect(
AntdInput,

View File

@ -16,9 +16,9 @@ import { useAppSpin } from '../../../application/hooks/useAppSpin';
import { useStyles as useAClStyles } from '../../../buildin-plugin/acl/style';
import { useDocumentTitle } from '../../../buildin-plugin/document-title';
import { FilterBlockProvider } from '../../../filter-provider/FilterProvider';
import { useGlobalTheme } from '../../../global-theme';
import { Icon } from '../../../icon';
import { useGetAriaLabelOfSchemaInitializer } from '../../../schema-initializer/hooks/useGetAriaLabelOfSchemaInitializer';
import { useGlobalTheme } from '../../../style/theme';
import { DndContext } from '../../common';
import { SortableItem } from '../../common/sortable-item';
import { SchemaComponent, SchemaComponentOptions } from '../../core';

View File

@ -1,9 +1,8 @@
import { Field } from '@tachybase/schema';
import { useField } from '@tachybase/schema';
import { reaction } from '@tachybase/schema';
import { isArr, isValid, toArr as toArray } from '@tachybase/schema';
import { UploadFile } from 'antd/es/upload/interface';
import { useEffect } from 'react';
import { Field, isArr, isValid, reaction, toArr as toArray, useField } from '@tachybase/schema';
import { UploadFile } from 'antd/es/upload/interface';
import { useAPIClient } from '../../../api-client';
import { UPLOAD_PLACEHOLDER } from './placeholder';
import type { IUploadProps, UploadProps } from './type';
@ -202,7 +201,7 @@ export function useUploadProps<T extends IUploadProps = UploadProps>({ serviceEr
return {
abort() {
console.log('upload progress is aborted.');
console.warn('upload progress is aborted.');
},
};
},

View File

@ -152,7 +152,6 @@ function getSingleEndRange(nodes: ChildNode[], index: number, offset: number): [
let realIndex = 0;
let textOffset = 0;
for (let i = 0; i < index + 1; i++) {
// console.log(i, realIndex, textOffset);
if (nodes[i].nodeName === '#text') {
if (i !== index && nodes[i + 1] && nodes[i + 1].nodeName !== '#text') {
realIndex += 1;
@ -396,8 +395,6 @@ export function TextArea(props) {
},
},
}).replace(/\n/g, ' ');
// ev.clipboardData.setData('text/html', sanitizedHTML);
// console.log(input, sanitizedHTML);
setChanged(true);
pasteHTML(ev.currentTarget, sanitizedHTML);
setRange(getCurrentRange(ev.currentTarget));

View File

@ -1,5 +1,5 @@
import { Schema, SchemaExpressionScopeContext, SchemaOptionsContext } from '@tachybase/schema';
import { isValidElement, useContext } from 'react';
import { Schema, SchemaExpressionScopeContext, SchemaOptionsContext } from '@tachybase/schema';
interface Props {
/**
@ -46,7 +46,6 @@ export const useCompile = ({ noCache }: Props = { noCache: false }) => {
compileCache[cacheKey] = compileCache[cacheKey] || Schema.compile(source, mergedScope);
return compileCache[cacheKey];
} catch (e) {
console.log('useCompile error', source, e);
return Schema.compile(source, mergedScope);
}
}

View File

@ -1,11 +1,5 @@
import {
Application,
CSSVariableProvider,
Plugin,
SchemaInitializer,
useSchemaInitializerRender,
} from '@tachybase/client';
import React from 'react';
import { Application, Plugin, SchemaInitializer, useSchemaInitializerRender } from '@tachybase/client';
const myInitializer = new SchemaInitializer({
name: 'myInitializer',

View File

@ -1358,7 +1358,6 @@ export const createTableBlockSchema = (options) => {
},
},
};
// console.log(JSON.stringify(schema, null, 2));
return schema;
};

View File

@ -1,13 +1,14 @@
import { Field } from '@tachybase/schema';
import { connect, mapProps, observer } from '@tachybase/schema';
import { observable } from '@tachybase/schema';
import React, { useMemo } from 'react';
import { connect, Field, mapProps, observable, observer } from '@tachybase/schema';
import { Tree as AntdTree } from 'antd';
import _ from 'lodash';
import React, { useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { withDynamicSchemaProps } from '../../application/hoc/withDynamicSchemaProps';
import { useCollectionManager_deprecated } from '../../collection-manager';
import { mergeFilter } from '../../filter-provider/utils';
import { SchemaComponent, SchemaComponentContext, removeNullCondition, useProps } from '../../schema-component';
import { removeNullCondition, SchemaComponent, SchemaComponentContext, useProps } from '../../schema-component';
import { ITemplate } from '../../schema-component/antd/form-v2/Templates';
import { VariableInput } from '../VariableInput';
import { AsDefaultTemplate } from './components/AsDefaultTemplate';
@ -15,7 +16,6 @@ import { ArrayCollapse } from './components/DataTemplateTitle';
import { getSelectedIdFilter } from './components/Designer';
import { useCollectionState } from './hooks/useCollectionState';
import { useSyncFromForm } from './utils';
import { withDynamicSchemaProps } from '../../application/hoc/withDynamicSchemaProps';
const Tree = connect(
AntdTree,

View File

@ -1,6 +1,7 @@
import { Tag } from 'antd';
import React from 'react';
import { Tag } from 'antd';
export const TreeNode = (props) => {
const { tag, type } = props;
const text = {

View File

@ -1,6 +1,7 @@
import { ArrayBase } from '@tachybase/components';
import { Switch } from 'antd';
import React from 'react';
import { ArrayBase } from '@tachybase/components';
import { Switch } from 'antd';
import { useTranslation } from 'react-i18next';
export const AsDefaultTemplate = React.forwardRef((props: any, ref) => {

View File

@ -1,13 +1,13 @@
import { CopyOutlined } from '@ant-design/icons';
import React, { Fragment, useEffect, useState } from 'react';
import { ArrayBase } from '@tachybase/components';
import { ArrayField } from '@tachybase/schema';
import { ISchema, RecursionField, observer, useField, useFieldSchema } from '@tachybase/schema';
import { toArr, uid } from '@tachybase/schema';
import { ArrayField, ISchema, observer, RecursionField, toArr, uid, useField, useFieldSchema } from '@tachybase/schema';
import { CopyOutlined } from '@ant-design/icons';
import { Badge, Card, Collapse, CollapsePanelProps, CollapseProps, Empty, Input } from 'antd';
import cls from 'classnames';
import { clone } from 'lodash';
import React, { Fragment, useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useStyles } from './DataTemplateTitle.style';
const DataTemplateTitle = observer<{ index: number; item: any }>((props) => {

View File

@ -1,10 +1,11 @@
import { Field } from '@tachybase/schema';
import { ISchema, observer, useField, useFieldSchema } from '@tachybase/schema';
import React from 'react';
import { Field, ISchema, observer, useField, useFieldSchema } from '@tachybase/schema';
import { error } from '@tachybase/utils/client';
import { Select } from 'antd';
import _ from 'lodash';
import React from 'react';
import { useTranslation } from 'react-i18next';
import { GeneralSchemaDesigner, SchemaSettingsItem } from '../..';
import { useFormBlockContext } from '../../../block-provider';
import { useCollectionManager_deprecated } from '../../../collection-manager';

View File

@ -1,6 +1,6 @@
import { ArrayField } from '@tachybase/schema';
import { useField } from '@tachybase/schema';
import React, { useCallback, useState } from 'react';
import { ArrayField, useField } from '@tachybase/schema';
import { useCollectionManager_deprecated } from '../../../collection-manager';
import { useCompile } from '../../../schema-component';
import { TreeNode } from '../TreeLabel';

View File

@ -1,9 +1,9 @@
import { observer, useForm } from '@tachybase/schema';
import { action } from '@tachybase/schema';
import React from 'react';
import { action, observer, useForm } from '@tachybase/schema';
import { withDynamicSchemaProps } from '../../application/hoc/withDynamicSchemaProps';
import { useCollectionManager_deprecated } from '../../collection-manager';
import { SchemaComponent, useCompile, useProps } from '../../schema-component';
import { withDynamicSchemaProps } from '../../application/hoc/withDynamicSchemaProps';
export const EnableChildCollections = withDynamicSchemaProps(
observer((props: any) => {

View File

@ -2,7 +2,6 @@ import React, { createContext, useCallback, useContext, useMemo } from 'react';
import { useField, useFieldSchema } from '@tachybase/schema';
import { RemoteSchemaComponent, useDesignable, useSchemaComponentContext } from '..';
import { useTemplateBlockContext } from '../block-provider/TemplateBlockProvider';
import { useSchemaTemplateManager } from './useSchemaTemplateManager';
const BlockTemplateContext = createContext<any>({});
@ -20,14 +19,12 @@ export const BlockTemplate = (props: any) => {
const { dn } = useDesignable();
// eslint-disable-next-line react-hooks/exhaustive-deps
const template = useMemo(() => getTemplateById(templateId), [templateId]);
const { onTemplateSuccess } = useTemplateBlockContext();
const { refresh } = useSchemaComponentContext();
const onSuccess = useCallback(
(data) => {
fieldSchema['x-linkage-rules'] = data?.data?.['x-linkage-rules'] || [];
fieldSchema.setProperties(data?.data?.properties);
onTemplateSuccess?.();
refresh();
},
// eslint-disable-next-line react-hooks/exhaustive-deps

View File

@ -2,8 +2,8 @@ import { useEffect, useMemo } from 'react';
import { TinyColor } from '@ctrl/tinycolor';
import { defaultTheme } from '../global-theme';
import { useToken } from '../style';
import { useToken } from '..';
import { defaultTheme } from '../theme';
export const CSSVariableProvider = ({ children }) => {
const { token } = useToken();

View File

@ -1,7 +1,9 @@
import { App } from 'antd';
import React, { memo, useEffect } from 'react';
import { useAPIClient } from '../api-client';
import { useApp } from '../application';
import { App } from 'antd';
import { useAPIClient } from '../../api-client';
import { useApp } from '../../application';
const AppInner = memo(({ children }: { children: React.ReactNode }) => {
const app = useApp();
@ -11,6 +13,7 @@ const AppInner = memo(({ children }: { children: React.ReactNode }) => {
useEffect(() => {
apiClient.notification = notification;
app.notification = notification;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [notification]);
return <>{children}</>;

View File

@ -1,7 +1,8 @@
import { ConfigProvider, theme as antdTheme } from 'antd';
import _ from 'lodash';
import React, { createContext, useCallback, useMemo, useRef } from 'react';
import compatOldTheme from './compatOldTheme';
import { theme as antdTheme, ConfigProvider } from 'antd';
import _ from 'lodash';
import defaultTheme from './defaultTheme';
import { ThemeConfig } from './type';
@ -81,12 +82,11 @@ export const GlobalThemeProvider = ({ children, theme: themeFromProps }) => {
return (
<GlobalThemeContext.Provider value={value}>
<ConfigProvider theme={compatOldTheme(theme)}>{children}</ConfigProvider>
<ConfigProvider theme={theme}>{children}</ConfigProvider>
</GlobalThemeContext.Provider>
);
};
export { default as AntdAppProvider } from './AntdAppProvider';
export { default as compatOldTheme } from './compatOldTheme';
export * from './type';
export { defaultTheme };

View File

@ -1,6 +1,6 @@
import { theme } from 'antd';
import { CustomToken } from '../global-theme';
import { CustomToken } from './theme';
interface Result extends ReturnType<typeof theme.useToken> {
token: CustomToken;

View File

@ -14,7 +14,7 @@ const useCloseAction = () => {
async run() {
setVisible(false);
form.submit((values) => {
console.log(values);
console.warn(values);
});
},
};

View File

@ -27,6 +27,7 @@ export const useCurrentRoles = () => {
});
}
return roles;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [allowAnonymous, data?.data?.roles]);
return options;
};

View File

@ -21,7 +21,7 @@ const useCloseAction = () => {
async run() {
setVisible(false);
form.submit((values) => {
console.log(values);
console.warn(values);
});
},
};

View File

@ -154,6 +154,7 @@ const VariablesProvider = ({ children }) => {
return compile(_.isFunction(current) ? current() : current);
},
// eslint-disable-next-line react-hooks/exhaustive-deps
[getCollectionJoinField],
);
@ -296,7 +297,6 @@ function shouldToRequest(value) {
// value 有可能是一个响应式对象,使用 untracked 可以避免意外触发 autorun
untracked(() => {
// fix
// 兼容 `对多` 和 `对一` 子表单子表格字段的情况
if (JSON.stringify(value) === '[{}]' || JSON.stringify(value) === '{}') {
result = true;

View File

@ -1,11 +1,12 @@
import React from 'react';
import { SchemaExpressionScopeContext, SchemaOptionsContext } from '@tachybase/schema';
import { act, renderHook, waitFor } from '@tachybase/test/client';
import React from 'react';
import { APIClientProvider } from '../../api-client';
import { mockAPIClient } from '../../testUtils';
import { CurrentUserProvider } from '../../user';
import VariablesProvider from '../VariablesProvider';
import useVariables from '../hooks/useVariables';
import VariablesProvider from '../VariablesProvider';
vi.mock('../../collection-manager', async () => {
return {

View File

@ -1,5 +1,6 @@
import { dayjs } from '@tachybase/utils/client';
import { useMemo } from 'react';
import { dayjs } from '@tachybase/utils/client';
import { useCurrentUserVariable, useDatetimeVariable } from '../../schema-settings';
import { useCurrentRoleVariable } from '../../schema-settings/VariableInput/hooks/useRoleVariable';
import { VariableOption } from '../types';

View File

@ -1,4 +1,5 @@
import { useMemo } from 'react';
import { useTableBlockContext } from '../../block-provider';
import { VariableOption } from '../types';

View File

@ -1,5 +1,6 @@
import { Form } from '@tachybase/schema';
import { useMemo } from 'react';
import { Form } from '@tachybase/schema';
import { useCollection_deprecated } from '../../collection-manager';
import { useBlockCollection } from '../../schema-settings/VariableInput/hooks/useBlockCollection';
import { useDatetimeVariable } from '../../schema-settings/VariableInput/hooks/useDateVariable';

View File

@ -1,4 +1,5 @@
import { useContext } from 'react';
import { VariablesContext } from '../VariablesProvider';
const useVariables = () => {

View File

@ -1,4 +1,5 @@
import type { Dispatch, SetStateAction } from 'react';
import { CollectionFieldOptions_deprecated } from '../collection-manager';
export interface VariablesContextType {

View File

@ -3,7 +3,7 @@ import { css, useRequest } from '@tachybase/client';
import { dayjs } from '@tachybase/utils/client';
import { BellOutlined } from '@ant-design/icons';
import { Badge, Button, List, message, Popover } from 'antd';
import { Badge, Button, List, Popover } from 'antd';
import { useNavigate } from 'react-router-dom';
import { useInitializationLinkKey, useLinkKey } from '../../hooks/useNotifications';
@ -28,7 +28,6 @@ export const Notifications = () => {
{
onSuccess() {
run();
message.info('成功');
},
},
);

View File

@ -0,0 +1,69 @@
import React from 'react';
import { Plugin, SchemaSettings, SchemaSettingsModalItem, useCollection, useDesignable } from '@tachybase/client';
import { ISchema, useField, useFieldSchema } from '@tachybase/schema';
import { get, set } from 'lodash';
const SchemaSettingsAppends = () => {
const fieldSchema = useFieldSchema();
const field = useField();
const c = useCollection();
const { dn } = useDesignable();
return (
<SchemaSettingsModalItem
key="appends"
title="设置加载关联字段"
schema={
{
type: 'object',
title: '设置加载关联字段',
properties: {
appends: {
default: get(fieldSchema, 'x-component-props.service.params.appends', []),
'x-decorator': 'FormItem',
'x-component': 'Select',
'x-component-props': {
mode: 'multiple',
},
enum: c?.fields.map((item) => item.name),
},
},
} as ISchema
}
onSubmit={({ appends }) => {
set(field.componentProps, 'service.params.appends', appends);
fieldSchema['x-component-props'] = field.componentProps;
const path = field.path?.splice(field.path?.length - 1, 1);
field.form.query(`${path.concat(`*.` + fieldSchema.name)}`).forEach((f) => {
f.componentProps.service = f.componentProps.service || { params: {} };
f.componentProps.service.params.appends = appends;
});
dn.emit('patch', {
schema: {
['x-uid']: fieldSchema['x-uid'],
'x-component-props': field.componentProps,
},
});
dn.refresh();
}}
/>
);
};
export const customFieldComponentFieldSettings = new SchemaSettings({
name: 'fieldSettings:component:CustomField',
items: [
{
name: 'appends',
Component: SchemaSettingsAppends,
},
],
});
export class PluginCustomComponents extends Plugin {
async load() {
this.schemaSettingsManager.add(customFieldComponentFieldSettings);
}
}

View File

@ -16,6 +16,7 @@ import {
import { PluginAssistant } from './features/assistant';
import { PluginGroupBlock } from './features/block-group';
import { PluginContextMenu } from './features/context-menu';
import { PluginCustomComponents } from './features/custom-components';
import { DepartmentsPlugin } from './features/departments';
import { EmbedPlugin } from './features/embed';
import { PluginExtendedFilterForm } from './features/extended-filter-form';
@ -88,6 +89,7 @@ export class PluginCoreClient extends Plugin {
await this.app.pm.add(PluginOutbound);
// await this.app.pm.add(PluginModeHighlight);
await this.app.pm.add(PluginFieldAppends);
await this.app.pm.add(PluginCustomComponents);
}
async registerSettings() {

View File

@ -10,6 +10,7 @@
"devDependencies": {
"@ant-design/icons": "^5.3.6",
"@tachybase/schema": "workspace:*",
"@types/lodash": "4.17.4",
"ahooks": "^3.7.2",
"antd": "5.16.1",
"dayjs": "^1.11.8",

View File

@ -81,7 +81,6 @@ export const RecordDetails: CustomFunctionComponent = () => {
productItem[key].count += count;
} else {
productItem[key] = {
key: item.product.category_id,
label: item.product.name,
sort: item.product.category.sort,
unit,

View File

@ -1,7 +1,7 @@
import React, { FC } from 'react';
import React from 'react';
import { CurrentAppInfoProvider, SchemaComponentOptions } from '@tachybase/client';
export const DuplicatorProvider: FC = function (props) {
export const DuplicatorProvider = function (props) {
return (
<CurrentAppInfoProvider>
<SchemaComponentOptions>{props.children}</SchemaComponentOptions>

View File

@ -1,5 +1,5 @@
import React from 'react';
import { AppNotFound, createRouterManager, Plugin, RouterManager, RouteSchemaComponent } from '@tachybase/client';
import { createRouterManager, Plugin, RouterManager } from '@tachybase/client';
import { Navigate, Outlet } from 'react-router-dom';
@ -72,7 +72,7 @@ export class MobileClientPlugin extends Plugin {
});
router.add('mobile.page', {
path: '/mobile/:name',
element: <RouteSchemaComponent />,
Component: 'RouteSchemaComponent',
});
this.mobileRouter = router;
}

View File

@ -1726,6 +1726,9 @@ importers:
'@tachybase/schema':
specifier: workspace:*
version: link:../../../core/schema
'@types/lodash':
specifier: 4.17.4
version: 4.17.4
ahooks:
specifier: ^3.7.2
version: 3.7.8(react@18.2.0)
@ -12262,6 +12265,10 @@ packages:
/@types/lodash@4.17.0:
resolution: {integrity: sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==}
/@types/lodash@4.17.4:
resolution: {integrity: sha512-wYCP26ZLxaT3R39kiN2+HcJ4kTd3U1waI/cY7ivWYqFP6pW3ZNpvi6Wd6PHZx7T/t8z0vlkXMg3QYLa7DZ/IJQ==}
dev: true
/@types/luxon@3.3.7:
resolution: {integrity: sha512-gKc9P2d4g5uYwmy4s/MO/yOVPmvHyvzka1YH6i5dM03UrFofHSmgc0D0ymbDRStFWHusk6cwwF6nhLm/ckBbbQ==}