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

View File

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

View File

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

View File

@ -1,4 +1,5 @@
import React, { createContext, useContext } from 'react'; import React, { createContext, useContext } from 'react';
import { useRequest } from '../api-client'; import { useRequest } from '../api-client';
import { useAppSpin } from '../application/hooks/useAppSpin'; 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 { SchemaComponentProvider } from '../schema-component/core';
import { ISchemaComponentProvider } from '../schema-component/types'; import { ISchemaComponentProvider } from '../schema-component/types';
const getKeyByName = (name) => { const getKeyByName = (name?: string) => {
if (!name) { if (!name) {
return 'tachybase_designable'.toUpperCase(); return 'tachybase_designable'.toUpperCase();
} }
return `tachybase_${name}_designable`.toUpperCase(); return `tachybase_${name}_designable`.toUpperCase();
}; };
const SchemaComponentProviderWithLocalStorageState: React.FC<ISchemaComponentProvider & { appName?: string }> = ( const SchemaComponentProviderWithLocalStorageState = (props: ISchemaComponentProvider & { appName?: string }) => {
props,
) => {
const [designable, setDesignable] = useLocalStorageState(getKeyByName(props.appName), { const [designable, setDesignable] = useLocalStorageState(getKeyByName(props.appName), {
defaultValue: props.designable ? true : false, 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') { if (typeof props.designable === 'boolean') {
return <SchemaComponentProvider {...props} />; return <SchemaComponentProvider {...props} />;
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,8 +1,9 @@
import React from 'react'; import React from 'react';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
import { DatePickerProvider } from '../schema-component'; import { DatePickerProvider } from '../schema-component';
import { DefaultValueProvider } from '../schema-settings'; import { DefaultValueProvider } from '../schema-settings';
import { FormBlockProvider } from './FormBlockProvider'; import { FormBlockProvider } from './FormBlockProvider';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
export const FilterFormBlockProvider = withDynamicSchemaProps((props) => { export const FilterFormBlockProvider = withDynamicSchemaProps((props) => {
return ( 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 { Templates as DataTemplateSelect } from '../schema-component/antd/form-v2/Templates';
import { BlockProvider, useBlockRequestContext } from './BlockProvider'; import { BlockProvider, useBlockRequestContext } from './BlockProvider';
import { FormActiveFieldsProvider } from './hooks/useFormActiveFields'; import { FormActiveFieldsProvider } from './hooks/useFormActiveFields';
import { TemplateBlockProvider } from './TemplateBlockProvider';
export const FormBlockContext = createContext<{ export const FormBlockContext = createContext<{
form?: any; form?: any;
@ -114,18 +113,16 @@ export const FormBlockProvider = withDynamicSchemaProps((props) => {
} }
return ( return (
<TemplateBlockProvider> <BlockProvider
<BlockProvider name={props.name || 'form'}
name={props.name || 'form'} {...props}
{...props} block={'form'}
block={'form'} parentRecord={parentRecord || parentRecordData}
parentRecord={parentRecord || parentRecordData} >
> <FormActiveFieldsProvider name="form">
<FormActiveFieldsProvider name="form"> <InternalFormBlockProvider {...props} />
<InternalFormBlockProvider {...props} /> </FormActiveFieldsProvider>
</FormActiveFieldsProvider> </BlockProvider>
</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 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 { useCollectionParentRecordData } from '../data-source/collection-record/CollectionRecordProvider';
import { RecordProvider } from '../record-provider'; import { RecordProvider } from '../record-provider';
import { BlockProvider, useBlockRequestContext } from './BlockProvider'; 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 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 { useCollectionManager_deprecated } from '../collection-manager';
import { useTableBlockParams } from '../modules/blocks/data-blocks/table/hooks/useTableBlockDecoratorProps';
import { FixedBlockWrapper, SchemaComponentOptions } from '../schema-component'; import { FixedBlockWrapper, SchemaComponentOptions } from '../schema-component';
import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider'; 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>({}); export const TableBlockContext = createContext<any>({});
TableBlockContext.displayName = 'TableBlockContext'; 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 React, { createContext, useContext, useEffect } from 'react';
import { ArrayField, Field, useField, useFieldSchema } from '@tachybase/schema';
import { APIClient } from '../api-client'; import { APIClient } from '../api-client';
import { BlockProvider, useBlockRequestContext } from './BlockProvider'; import { BlockProvider, useBlockRequestContext } from './BlockProvider';
import { useFormBlockContext } from './FormBlockProvider'; import { useFormBlockContext } from './FormBlockProvider';
@ -23,9 +23,6 @@ const InternalTableFieldProvider = (props) => {
if (!formBlockCtx?.updateAssociationValues?.includes(fullFieldName)) { if (!formBlockCtx?.updateAssociationValues?.includes(fullFieldName)) {
formBlockCtx?.updateAssociationValues?.push(fullFieldName); formBlockCtx?.updateAssociationValues?.push(fullFieldName);
} }
// if (service.loading) {
// return <Spin />;
// }
return ( return (
<TableFieldContext.Provider <TableFieldContext.Provider
value={{ value={{
@ -59,7 +56,6 @@ export class TableFieldResource {
async list(options) { async list(options) {
this.field.data = this.field.data || {}; this.field.data = this.field.data || {};
if (this.field.data.changed) { if (this.field.data.changed) {
console.log('list.dataSource', this.field.data.dataSource);
return { return {
data: { data: {
data: this.field.data.dataSource, data: this.field.data.dataSource,
@ -67,7 +63,6 @@ export class TableFieldResource {
}; };
} }
if (!this.sourceId) { if (!this.sourceId) {
console.log('list.sourceId', this.field.data.dataSource);
this.field.data.dataSource = []; this.field.data.dataSource = [];
return { return {
data: { data: {
@ -76,7 +71,6 @@ export class TableFieldResource {
}; };
} }
const response = await this.resource.list(options); const response = await this.resource.list(options);
console.log('list', response);
this.field.data.dataSource = response.data.data; this.field.data.dataSource = response.data.data;
return { return {
data: { data: {
@ -86,7 +80,6 @@ export class TableFieldResource {
} }
async get(options) { async get(options) {
console.log('get', options);
const { filterByTk } = options; const { filterByTk } = options;
return { return {
data: { data: {
@ -96,21 +89,18 @@ export class TableFieldResource {
} }
async create(options) { async create(options) {
console.log('create', options);
const { values } = options; const { values } = options;
this.field.data.dataSource.push(values); this.field.data.dataSource.push(values);
this.field.data.changed = true; this.field.data.changed = true;
} }
async update(options) { async update(options) {
console.log('update', options);
const { filterByTk, values } = options; const { filterByTk, values } = options;
this.field.data.dataSource[filterByTk] = values; this.field.data.dataSource[filterByTk] = values;
this.field.data.changed = true; this.field.data.changed = true;
} }
async destroy(options) { async destroy(options) {
console.log('destroy', options);
let { filterByTk } = options; let { filterByTk } = options;
if (!Array.isArray(filterByTk)) { if (!Array.isArray(filterByTk)) {
filterByTk = [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 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 { useCollectionManager_deprecated } from '../collection-manager';
import { useCollectionParentRecordData } from '../data-source/collection-record/CollectionRecordProvider'; import { useCollectionParentRecordData } from '../data-source/collection-record/CollectionRecordProvider';
import { isInFilterFormBlock } from '../filter-provider'; import { isInFilterFormBlock } from '../filter-provider';
@ -11,7 +12,6 @@ import { RecordProvider, useRecord } from '../record-provider';
import { SchemaComponentOptions } from '../schema-component'; import { SchemaComponentOptions } from '../schema-component';
import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider'; import { BlockProvider, RenderChildrenWithAssociationFilter, useBlockRequestContext } from './BlockProvider';
import { useParsedFilter } from './hooks'; import { useParsedFilter } from './hooks';
import { withDynamicSchemaProps } from '../application/hoc/withDynamicSchemaProps';
type Params = { type Params = {
filter?: any; filter?: any;
@ -54,9 +54,6 @@ const InternalTableSelectorProvider = (props) => {
const { resource, service } = useBlockRequestContext(); const { resource, service } = useBlockRequestContext();
const [expandFlag, setExpandFlag] = useState(false); const [expandFlag, setExpandFlag] = useState(false);
const parentRecordData = useCollectionParentRecordData(); const parentRecordData = useCollectionParentRecordData();
// if (service.loading) {
// return <Spin />;
// }
return ( return (
<RecordProvider record={{}} parent={parentRecordData}> <RecordProvider record={{}} parent={parentRecordData}>
<TableSelectorContext.Provider <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) => { export const recursiveParent = (schema: Schema, component) => {
return schema['x-component'] === component return schema['x-component'] === component
? schema ? 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 './useParsedFilter';
export * from './useDataBlockSourceId'; export * from './useDataBlockSourceId';
export const usePickActionProps = () => {
const form = useForm();
return {
onClick() {
console.log('usePickActionProps', form.values);
},
};
};
function renderTemplate(str: string, data: any) { function renderTemplate(str: string, data: any) {
const re = /\{\{\s*((\w+\.?)+)\s*\}\}/g; const re = /\{\{\s*((\w+\.?)+)\s*\}\}/g;
return str.replace(re, function (_, key) { return str.replace(re, function (_, key) {

View File

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

View File

@ -1 +0,0 @@
# BlockProvider

View File

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

View File

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

View File

@ -164,9 +164,7 @@ class CronstrueLocale {
} }
export const loadConstrueLocale = (data) => { export const loadConstrueLocale = (data) => {
// vite bug: https://github.com/vitejs/vite/issues/2139 cronstrue.initialize({
const cronstrueVal = (cronstrue as any).default ? (cronstrue as any).default : cronstrue;
cronstrueVal.initialize({
load(availableLocales) { load(availableLocales) {
availableLocales[data?.lang] = new CronstrueLocale(data?.cronstrue); 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 { Spin } from 'antd';
import { useRequest } from '../../api-client'; import { useRequest } from '../../api-client';
import { useGlobalTheme } from '../../global-theme';
import { useStyles as useMarkdownStyles } from '../../schema-component/antd/markdown/style'; import { useStyles as useMarkdownStyles } from '../../schema-component/antd/markdown/style';
import { useParseMarkdown } from '../../schema-component/antd/markdown/util'; import { useParseMarkdown } from '../../schema-component/antd/markdown/util';
import { useGlobalTheme } from '../../style/theme';
import { useStyles } from './style'; import { useStyles } from './style';
const PLUGIN_STATICS_PATH = '/static/plugins/'; const PLUGIN_STATICS_PATH = '/static/plugins/';

View File

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

View File

@ -478,7 +478,7 @@ export const useUpdateAction = (actionCallback?: (key: string, values: any) => v
await form.reset(); await form.reset();
refresh(); refresh();
} catch (e) { } catch (e) {
console.log(e); console.error(e);
} finally { } finally {
field.data.loading = false; 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 React, { createContext, useContext, useState } from 'react';
import { observer, useForm } from '@tachybase/schema';
import { cloneDeep } from 'lodash';
import { import {
CollectionOptions, CollectionOptions,
CollectionProvider_deprecated, CollectionProvider_deprecated,
@ -97,7 +99,6 @@ const useCreateAction = () => {
const { setVisible } = useActionContext(); const { setVisible } = useActionContext();
return { return {
async run() { async run() {
console.log('form.values', form.values);
const dataSource = ctx.dataSource || []; const dataSource = ctx.dataSource || [];
dataSource.push(cloneDeep(form.values)); dataSource.push(cloneDeep(form.values));
ctx.setDataSource([...dataSource]); ctx.setDataSource([...dataSource]);
@ -199,7 +200,6 @@ export const SubFieldDataSourceProvider_deprecated = observer(
}, },
{ {
onSuccess(data) { onSuccess(data) {
console.log('dataSource1', data?.data);
setDataSource(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 () => { return () => {
restore(); 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; resources[lang] = locale[lang].resources;
}); });
i18n i18n.use(initReactI18next).init({
// .use(Backend) lng: localStorage.getItem('TACHYBASE_LOCALE') || 'en-US',
.use(initReactI18next) defaultNS: 'client',
.init({ resources: {},
lng: localStorage.getItem('TACHYBASE_LOCALE') || 'en-US', keySeparator: false,
// debug: true, nsSeparator: false,
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) => { i18n.on('languageChanged', (lng) => {
localStorage.setItem('TACHYBASE_LOCALE', lng); localStorage.setItem('TACHYBASE_LOCALE', lng);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@ import React from 'react';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { RemoteSchemaComponent } from '../../../'; import { RemoteSchemaComponent } from '..';
export function RouteSchemaComponent(props: any) { export function RouteSchemaComponent(props: any) {
const params = useParams<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 { theme } from 'antd';
import { CustomToken } from '../../../../global-theme';
import { CustomToken } from '../../../../style/theme';
interface Result extends ReturnType<typeof theme.useToken> { interface Result extends ReturnType<typeof theme.useToken> {
token: CustomToken; 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 { 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; 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 openSize = fieldSchema?.['x-component-props']?.['openSize'];
const disabled = form.disabled || field.disabled || field.data?.disabled || propsDisabled; 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 { designable } = useDesignable();
const tarComponent = useComponent(component) || component; const tarComponent = useComponent(component) || component;
const { modal } = App.useApp(); const { modal } = App.useApp();

View File

@ -50,7 +50,7 @@ export const useCloseAction = () => {
async run() { async run() {
setVisible(false); setVisible(false);
form.submit((values) => { 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 { createPortal } from 'react-dom';
import { createPortalProvider, createPortalRoot, loading, usePrefixCls, useToken } from '../__builtins__'; 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); type FormDialogRenderer = React.ReactElement | ((form: Form) => React.ReactElement);

View File

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

View File

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

View File

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

View File

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

View File

@ -16,9 +16,9 @@ import { useAppSpin } from '../../../application/hooks/useAppSpin';
import { useStyles as useAClStyles } from '../../../buildin-plugin/acl/style'; import { useStyles as useAClStyles } from '../../../buildin-plugin/acl/style';
import { useDocumentTitle } from '../../../buildin-plugin/document-title'; import { useDocumentTitle } from '../../../buildin-plugin/document-title';
import { FilterBlockProvider } from '../../../filter-provider/FilterProvider'; import { FilterBlockProvider } from '../../../filter-provider/FilterProvider';
import { useGlobalTheme } from '../../../global-theme';
import { Icon } from '../../../icon'; import { Icon } from '../../../icon';
import { useGetAriaLabelOfSchemaInitializer } from '../../../schema-initializer/hooks/useGetAriaLabelOfSchemaInitializer'; import { useGetAriaLabelOfSchemaInitializer } from '../../../schema-initializer/hooks/useGetAriaLabelOfSchemaInitializer';
import { useGlobalTheme } from '../../../style/theme';
import { DndContext } from '../../common'; import { DndContext } from '../../common';
import { SortableItem } from '../../common/sortable-item'; import { SortableItem } from '../../common/sortable-item';
import { SchemaComponent, SchemaComponentOptions } from '../../core'; 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 { 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 { useAPIClient } from '../../../api-client';
import { UPLOAD_PLACEHOLDER } from './placeholder'; import { UPLOAD_PLACEHOLDER } from './placeholder';
import type { IUploadProps, UploadProps } from './type'; import type { IUploadProps, UploadProps } from './type';
@ -202,7 +201,7 @@ export function useUploadProps<T extends IUploadProps = UploadProps>({ serviceEr
return { return {
abort() { 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 realIndex = 0;
let textOffset = 0; let textOffset = 0;
for (let i = 0; i < index + 1; i++) { for (let i = 0; i < index + 1; i++) {
// console.log(i, realIndex, textOffset);
if (nodes[i].nodeName === '#text') { if (nodes[i].nodeName === '#text') {
if (i !== index && nodes[i + 1] && nodes[i + 1].nodeName !== '#text') { if (i !== index && nodes[i + 1] && nodes[i + 1].nodeName !== '#text') {
realIndex += 1; realIndex += 1;
@ -396,8 +395,6 @@ export function TextArea(props) {
}, },
}, },
}).replace(/\n/g, ' '); }).replace(/\n/g, ' ');
// ev.clipboardData.setData('text/html', sanitizedHTML);
// console.log(input, sanitizedHTML);
setChanged(true); setChanged(true);
pasteHTML(ev.currentTarget, sanitizedHTML); pasteHTML(ev.currentTarget, sanitizedHTML);
setRange(getCurrentRange(ev.currentTarget)); setRange(getCurrentRange(ev.currentTarget));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -1,10 +1,11 @@
import { Field } from '@tachybase/schema'; import React from 'react';
import { ISchema, observer, useField, useFieldSchema } from '@tachybase/schema'; import { Field, ISchema, observer, useField, useFieldSchema } from '@tachybase/schema';
import { error } from '@tachybase/utils/client'; import { error } from '@tachybase/utils/client';
import { Select } from 'antd'; import { Select } from 'antd';
import _ from 'lodash'; import _ from 'lodash';
import React from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { GeneralSchemaDesigner, SchemaSettingsItem } from '../..'; import { GeneralSchemaDesigner, SchemaSettingsItem } from '../..';
import { useFormBlockContext } from '../../../block-provider'; import { useFormBlockContext } from '../../../block-provider';
import { useCollectionManager_deprecated } from '../../../collection-manager'; 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 React, { useCallback, useState } from 'react';
import { ArrayField, useField } from '@tachybase/schema';
import { useCollectionManager_deprecated } from '../../../collection-manager'; import { useCollectionManager_deprecated } from '../../../collection-manager';
import { useCompile } from '../../../schema-component'; import { useCompile } from '../../../schema-component';
import { TreeNode } from '../TreeLabel'; 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 React from 'react';
import { action, observer, useForm } from '@tachybase/schema';
import { withDynamicSchemaProps } from '../../application/hoc/withDynamicSchemaProps';
import { useCollectionManager_deprecated } from '../../collection-manager'; import { useCollectionManager_deprecated } from '../../collection-manager';
import { SchemaComponent, useCompile, useProps } from '../../schema-component'; import { SchemaComponent, useCompile, useProps } from '../../schema-component';
import { withDynamicSchemaProps } from '../../application/hoc/withDynamicSchemaProps';
export const EnableChildCollections = withDynamicSchemaProps( export const EnableChildCollections = withDynamicSchemaProps(
observer((props: any) => { observer((props: any) => {

View File

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

View File

@ -1,7 +1,9 @@
import { App } from 'antd';
import React, { memo, useEffect } from 'react'; 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 AppInner = memo(({ children }: { children: React.ReactNode }) => {
const app = useApp(); const app = useApp();
@ -11,6 +13,7 @@ const AppInner = memo(({ children }: { children: React.ReactNode }) => {
useEffect(() => { useEffect(() => {
apiClient.notification = notification; apiClient.notification = notification;
app.notification = notification; app.notification = notification;
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [notification]); }, [notification]);
return <>{children}</>; 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 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 defaultTheme from './defaultTheme';
import { ThemeConfig } from './type'; import { ThemeConfig } from './type';
@ -81,12 +82,11 @@ export const GlobalThemeProvider = ({ children, theme: themeFromProps }) => {
return ( return (
<GlobalThemeContext.Provider value={value}> <GlobalThemeContext.Provider value={value}>
<ConfigProvider theme={compatOldTheme(theme)}>{children}</ConfigProvider> <ConfigProvider theme={theme}>{children}</ConfigProvider>
</GlobalThemeContext.Provider> </GlobalThemeContext.Provider>
); );
}; };
export { default as AntdAppProvider } from './AntdAppProvider'; export { default as AntdAppProvider } from './AntdAppProvider';
export { default as compatOldTheme } from './compatOldTheme';
export * from './type'; export * from './type';
export { defaultTheme }; export { defaultTheme };

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,7 +3,7 @@ import { css, useRequest } from '@tachybase/client';
import { dayjs } from '@tachybase/utils/client'; import { dayjs } from '@tachybase/utils/client';
import { BellOutlined } from '@ant-design/icons'; 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 { useNavigate } from 'react-router-dom';
import { useInitializationLinkKey, useLinkKey } from '../../hooks/useNotifications'; import { useInitializationLinkKey, useLinkKey } from '../../hooks/useNotifications';
@ -28,7 +28,6 @@ export const Notifications = () => {
{ {
onSuccess() { onSuccess() {
run(); 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 { PluginAssistant } from './features/assistant';
import { PluginGroupBlock } from './features/block-group'; import { PluginGroupBlock } from './features/block-group';
import { PluginContextMenu } from './features/context-menu'; import { PluginContextMenu } from './features/context-menu';
import { PluginCustomComponents } from './features/custom-components';
import { DepartmentsPlugin } from './features/departments'; import { DepartmentsPlugin } from './features/departments';
import { EmbedPlugin } from './features/embed'; import { EmbedPlugin } from './features/embed';
import { PluginExtendedFilterForm } from './features/extended-filter-form'; 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(PluginOutbound);
// await this.app.pm.add(PluginModeHighlight); // await this.app.pm.add(PluginModeHighlight);
await this.app.pm.add(PluginFieldAppends); await this.app.pm.add(PluginFieldAppends);
await this.app.pm.add(PluginCustomComponents);
} }
async registerSettings() { async registerSettings() {

View File

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

View File

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

View File

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

View File

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

View File

@ -1726,6 +1726,9 @@ importers:
'@tachybase/schema': '@tachybase/schema':
specifier: workspace:* specifier: workspace:*
version: link:../../../core/schema version: link:../../../core/schema
'@types/lodash':
specifier: 4.17.4
version: 4.17.4
ahooks: ahooks:
specifier: ^3.7.2 specifier: ^3.7.2
version: 3.7.8(react@18.2.0) version: 3.7.8(react@18.2.0)
@ -12262,6 +12265,10 @@ packages:
/@types/lodash@4.17.0: /@types/lodash@4.17.0:
resolution: {integrity: sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==} 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: /@types/luxon@3.3.7:
resolution: {integrity: sha512-gKc9P2d4g5uYwmy4s/MO/yOVPmvHyvzka1YH6i5dM03UrFofHSmgc0D0ymbDRStFWHusk6cwwF6nhLm/ckBbbQ==} resolution: {integrity: sha512-gKc9P2d4g5uYwmy4s/MO/yOVPmvHyvzka1YH6i5dM03UrFofHSmgc0D0ymbDRStFWHusk6cwwF6nhLm/ckBbbQ==}