140 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			140 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import { ISchema, useFieldSchema } from '@formily/react';
 | |
| import { uid } from '@formily/shared';
 | |
| import { Spin } from 'antd';
 | |
| import { cloneDeep } from 'lodash';
 | |
| import React, { createContext, useContext, useMemo } from 'react';
 | |
| import { useAPIClient, useRequest } from '../api-client';
 | |
| import { RouteSwitchContext } from '../route-switch';
 | |
| import { SchemaComponentOptions } from '../schema-component';
 | |
| import { BlockTemplate } from './BlockTemplate';
 | |
| 
 | |
| export const SchemaTemplateManagerContext = createContext<any>({});
 | |
| 
 | |
| const SchemaTemplateRouteProvider = (props) => {
 | |
|   const { routes, ...others } = useContext(RouteSwitchContext);
 | |
|   routes[1].routes.unshift(
 | |
|     {
 | |
|       type: 'route',
 | |
|       path: '/admin/block-templates/:key',
 | |
|       component: 'BlockTemplateDetails',
 | |
|     },
 | |
|     {
 | |
|       type: 'route',
 | |
|       path: '/admin/block-templates',
 | |
|       component: 'BlockTemplatePage',
 | |
|     },
 | |
|   );
 | |
|   return <RouteSwitchContext.Provider value={{ ...others, routes }}>{props.children}</RouteSwitchContext.Provider>;
 | |
| };
 | |
| 
 | |
| export const SchemaTemplateManagerProvider: React.FC<any> = (props) => {
 | |
|   const { templates, refresh } = props;
 | |
|   return (
 | |
|     <SchemaTemplateManagerContext.Provider value={{ templates, refresh }}>
 | |
|       <SchemaTemplateRouteProvider>
 | |
|         <SchemaComponentOptions components={{ BlockTemplate }}>{props.children}</SchemaComponentOptions>
 | |
|       </SchemaTemplateRouteProvider>
 | |
|     </SchemaTemplateManagerContext.Provider>
 | |
|   );
 | |
| };
 | |
| 
 | |
| const regenerateUid = (s: ISchema) => {
 | |
|   s['x-uid'] = uid();
 | |
|   Object.keys(s.properties || {}).forEach((key) => {
 | |
|     regenerateUid(s.properties[key]);
 | |
|   });
 | |
| };
 | |
| 
 | |
| export const useSchemaTemplate = () => {
 | |
|   const { getTemplateBySchemaId } = useSchemaTemplateManager();
 | |
|   const fieldSchema = useFieldSchema();
 | |
|   const schemaId = fieldSchema['x-uid'];
 | |
|   return useMemo(() => getTemplateBySchemaId(schemaId), [schemaId]);
 | |
| };
 | |
| 
 | |
| export const useSchemaTemplateManager = () => {
 | |
|   const { refresh, templates = [] } = useContext(SchemaTemplateManagerContext);
 | |
|   const api = useAPIClient();
 | |
|   return {
 | |
|     templates,
 | |
|     refresh,
 | |
|     async getTemplateSchemaByMode(options) {
 | |
|       const { mode, template } = options;
 | |
|       if (mode === 'copy') {
 | |
|         const { data } = await api.request({
 | |
|           url: `/uiSchemas:getJsonSchema/${template.uid}?includeAsyncNode=true`,
 | |
|         });
 | |
|         const s = data?.data || {};
 | |
|         regenerateUid(s);
 | |
|         return cloneDeep(s);
 | |
|       } else if (mode === 'reference') {
 | |
|         return {
 | |
|           type: 'void',
 | |
|           'x-component': 'BlockTemplate',
 | |
|           'x-component-props': {
 | |
|             templateId: template.key,
 | |
|           },
 | |
|         };
 | |
|       }
 | |
|     },
 | |
|     async copyTemplateSchema(template) {
 | |
|       const { data } = await api.request({
 | |
|         url: `/uiSchemas:getJsonSchema/${template.uid}?includeAsyncNode=true`,
 | |
|       });
 | |
|       const s = data?.data || {};
 | |
|       regenerateUid(s);
 | |
|       return cloneDeep(s);
 | |
|     },
 | |
|     async saveAsTemplate(values) {
 | |
|       const { uid: schemaId } = values;
 | |
|       const key = uid();
 | |
|       await api.resource('uiSchemas').saveAsTemplate({
 | |
|         filterByTk: schemaId,
 | |
|         values: {
 | |
|           key,
 | |
|           ...values,
 | |
|         },
 | |
|       });
 | |
|       await refresh();
 | |
|       return { key };
 | |
|     },
 | |
|     getTemplateBySchemaId(schemaId) {
 | |
|       return templates?.find((template) => template.uid === schemaId);
 | |
|     },
 | |
|     getTemplateById(key) {
 | |
|       return templates?.find((template) => template.key === key);
 | |
|     },
 | |
|     getTemplatesByCollection(collectionName: string) {
 | |
|       const items = templates?.filter?.((template) => template.collectionName === collectionName);
 | |
|       return items || [];
 | |
|     },
 | |
|   };
 | |
| };
 | |
| 
 | |
| export const RemoteSchemaTemplateManagerProvider: React.FC = (props) => {
 | |
|   const api = useAPIClient();
 | |
|   const options = {
 | |
|     resource: 'uiSchemaTemplates',
 | |
|     action: 'list',
 | |
|     params: {
 | |
|       appends: ['collection'],
 | |
|       paginate: false,
 | |
|     },
 | |
|   };
 | |
|   const service = useRequest(options);
 | |
|   if (service.loading) {
 | |
|     return <Spin />;
 | |
|   }
 | |
|   return (
 | |
|     <SchemaTemplateManagerProvider
 | |
|       refresh={async () => {
 | |
|         const { data } = await api.request(options);
 | |
|         service.mutate(data);
 | |
|       }}
 | |
|       templates={service?.data?.data}
 | |
|     >
 | |
|       {props.children}
 | |
|     </SchemaTemplateManagerProvider>
 | |
|   );
 | |
| };
 |