import { Field } from '@formily/core'; import { useField } from '@formily/react'; import { useRequest } from 'ahooks'; import template from 'lodash/template'; import React, { createContext, useContext } from 'react'; import { Link } from 'react-router-dom'; import { ACLCollectionProvider, TableFieldResource, useAPIClient, useRecord } from '../'; import { CollectionProvider, useCollection, useCollectionManager } from '../collection-manager'; import { useRecordIndex } from '../record-provider'; export const BlockResourceContext = createContext(null); export const BlockAssociationContext = createContext(null); const BlockRequestContext = createContext(null); export const useBlockResource = () => { return useContext(BlockResourceContext); }; interface UseReousrceProps { resource: any; association?: any; useSourceId?: any; block?: any; } const useAssociation = (props) => { const { association } = props; const { getCollectionField } = useCollectionManager(); if (typeof association === 'string') { return getCollectionField(association); } else if (association?.collectionName && association?.name) { return getCollectionField(`${association?.collectionName}.${association?.name}`); } }; const useReousrce = (props: UseReousrceProps) => { const { block, resource, useSourceId } = props; const record = useRecord(); const api = useAPIClient(); const association = useAssociation(props); const sourceId = useSourceId?.(); const field = useField(); if (block === 'TableField') { const options = { field, api, resource, sourceId: sourceId || record[association?.sourceKey || 'id'], }; return new TableFieldResource(options); } const __parent = useContext(BlockRequestContext); if (__parent?.block === 'TableField' && __parent?.resource instanceof TableFieldResource) { return __parent.resource; } if (!association) { return api.resource(resource); } if (sourceId) { return api.resource(resource, sourceId); } return api.resource(resource, record[association?.sourceKey || 'id']); }; const useActionParams = (props) => { const { useParams } = props; const params = useParams?.() || {}; return { ...props.params, ...params }; }; export const useResourceAction = (props, opts = {}) => { const { resource, action } = props; const { fields } = useCollection(); const appends = fields?.filter((field) => field.target).map((field) => field.name); const params = useActionParams(props); if (appends?.length) { params['appends'] = appends; } const result = useRequest( (params) => (action ? resource[action](params).then((res) => res.data) : Promise.resolve({})), { ...opts, defaultParams: [params], }, ); return result; }; const MaybeCollectionProvider = (props) => { const { collection } = props; return collection ? ( {props.children} ) : ( <>{props.children} ); }; const BlockRequestProvider = (props) => { const field = useField(); const resource = useBlockResource(); const service = useResourceAction( { ...props, resource }, { ...props.requestOptions, }, ); const __parent = useContext(BlockRequestContext); return ( {props.children} ); }; export const useBlockRequestContext = () => { return useContext(BlockRequestContext); }; export const BlockProvider = (props) => { const { collection, association } = props; const resource = useReousrce(props); return ( {props.children} ); }; export const useBlockAssociationContext = () => { return useContext(BlockAssociationContext); }; export const useFilterByTk = () => { const { resource, __parent } = useContext(BlockRequestContext); const recordIndex = useRecordIndex(); const record = useRecord(); const collection = useCollection(); const { getCollectionField } = useCollectionManager(); const assoc = useContext(BlockAssociationContext); if (resource instanceof TableFieldResource || __parent?.block === 'TableField') { return recordIndex; } if (assoc) { const association = getCollectionField(assoc); return record?.[association.targetKey || 'id']; } return record?.[collection.filterTargetKey || 'id']; }; export const useSourceIdFromRecord = () => { const record = useRecord(); const { getCollectionField } = useCollectionManager(); const assoc = useContext(BlockAssociationContext); if (assoc) { const association = getCollectionField(assoc); return record?.[association.sourceKey || 'id']; } }; export const useSourceIdFromParentRecord = () => { const record = useRecord(); const { getCollectionField } = useCollectionManager(); const assoc = useContext(BlockAssociationContext); if (assoc) { const association = getCollectionField(assoc); return record?.__parent?.[association.sourceKey || 'id']; } }; export const useParamsFromRecord = () => { const filterByTk = useFilterByTk(); return { filterByTk: filterByTk, }; }; export const RecordLink = (props) => { const field = useField(); const record = useRecord(); const { title, to, ...others } = props; const compiled = template(to || ''); return ( {field.title} ); };