fix: multi-level nesting

This commit is contained in:
chenos 2021-01-30 19:06:01 +08:00
parent 1ea08e62b6
commit d83cebac56
4 changed files with 143 additions and 16 deletions

View File

@ -8,27 +8,38 @@ import { Spin } from '@nocobase/client';
import { Helmet } from 'umi'; import { Helmet } from 'umi';
export function CollectionSingle(props) { export function CollectionSingle(props) {
console.log(props); // console.log(props);
const { item = {} } = props; const { item = {} } = props;
const { tabs = [] } = props.collection; const { data: collections = [], loading: collectionLoading } = useRequest(() => api.resource(props.match.params['collection']).getCollections({
const activeTab = tabs.find(tab => tab.name == item.tabName)||{}; values: {
console.log(activeTab); tabs: props.match.params['items']
const { data = {}, loading } = useRequest(() => activeTab && api.resource(activeTab.collection_name).getPageInfo({ }
resourceKey: item.itemId,
})); }));
// const { data = {}, loading } = useRequest(() => currentTab && api.resource(currentTab.collection_name).getPageInfo({
// resourceKey: item.itemId,
// }));
const [activing, setActiving] = useState(false); const [activing, setActiving] = useState(false);
if (collectionLoading) {
return <Spin/>;
}
const collection = collections[props.itemIndex]||{};
const { tabs = [] } = collection;
const activeTab = tabs.find(tab => tab.name == item.tabName)||{};
console.log({tabs, activeTab, item});
if (!activeTab) { if (!activeTab) {
return null; return null;
} }
if (loading) {
return <Spin/>;
}
return ( return (
<div> <div>
<Helmet> <Helmet>
<title>{data.pageTitle}</title> <title>{collection.pageTitle}</title>
</Helmet> </Helmet>
<PageHeader <PageHeader
ghost={false} ghost={false}
@ -38,7 +49,7 @@ export function CollectionSingle(props) {
removeLastItem: true, removeLastItem: true,
}); });
}} }}
title={data.pageTitle} title={collection.pageTitle}
// subTitle="This is a subtitle" // subTitle="This is a subtitle"
extra={[ extra={[
// <Button key="3">Operation</Button>, // <Button key="3">Operation</Button>,
@ -68,7 +79,7 @@ export function CollectionSingle(props) {
} }
/> />
<div className={'collection-content'}> <div className={'collection-content'}>
<CollectionTabPane {...props} loading={activing} pageInfo={data} activeTab={activeTab}/> <CollectionTabPane {...props} collection={collection} loading={activing} activeTab={activeTab}/>
</div> </div>
</div> </div>
); );

View File

@ -3,8 +3,9 @@ import Breadcrumb from './Breadcrumb';
import CollectionIndex from './CollectionIndex'; import CollectionIndex from './CollectionIndex';
import CollectionSingle from './CollectionSingle'; import CollectionSingle from './CollectionSingle';
import './style.less'; import './style.less';
import { useRequest, request, Spin } from '@nocobase/client'; import { request, Spin } from '@nocobase/client';
import api from '@/api-client'; import api from '@/api-client';
import { useRequest } from 'umi';
export function CollectionLoader(props: any) { export function CollectionLoader(props: any) {
let { path, pagepath, collection } = props.match.params; let { path, pagepath, collection } = props.match.params;
@ -27,6 +28,14 @@ export function CollectionLoader(props: any) {
console.log('props.match', props.match, path); console.log('props.match', props.match, path);
const { data = {}, error, loading, run } = useRequest(() => api.resource(collection).getCollection()); const { data = {}, error, loading, run } = useRequest(() => api.resource(collection).getCollection());
// const { data: collections = [], loading } = useRequest(() => api.resource(collection).getCollections({
// values: {
// tabs: items,
// },
// }), {
// // refreshDeps: [items],
// });
if (loading) { if (loading) {
return <Spin/>; return <Spin/>;
} }
@ -34,17 +43,17 @@ export function CollectionLoader(props: any) {
return ( return (
<div className={'collection'}> <div className={'collection'}>
<div className={'collection-index'}> <div className={'collection-index'}>
{ items.length === 0 && <CollectionIndex collection={data.data||{}} {...props}/> } { items.length === 0 && <CollectionIndex collection={data} {...props}/> }
</div> </div>
{items.length > 0 && ( {items.length > 0 && (
<div className={'collection-item'}> <div className={'collection-item'}>
{/* <Breadcrumb> {/* <Breadcrumb>
{items.map(item => <Breadcrumb.Item/>)} {items.map(item => <Breadcrumb.Item/>)}
</Breadcrumb> */} </Breadcrumb> */}
{items.map(item => { {items.map((item, index) => {
return ( return (
<div className={'collection-single'}> <div className={'collection-single'}>
<CollectionSingle item={item} collection={data.data||{}} {...props}/> <CollectionSingle itemIndex={index} item={item} {...props}/>
</div> </div>
); );
})} })}

View File

@ -0,0 +1,105 @@
import { Model, ModelCtor } from '@nocobase/database';
import _ from 'lodash';
async function getPageTitle(ctx, {resourceName, resourceKey}) {
// const { resourceName, resourceKey } = ctx.action.params;
const M = ctx.db.getModel(resourceName) as ModelCtor<Model>;
const model = await M.findByPk(resourceKey);
const Field = ctx.db.getModel('fields') as ModelCtor<Model>;
const field = await Field.findOne({
where: {
collection_name: resourceName,
type: 'string',
},
order: [['sort', 'asc']],
});
return field ? (model.get(field.get('name')) || `#${model.get(M.primaryKeyAttribute)} 无标题`) : model.get(M.primaryKeyAttribute);
};
async function getCollection(ctx, resourceName) {
const [Collection, Field, Tab, View] = ctx.db.getModels(['collections', 'fields', 'tabs', 'views']) as ModelCtor<Model>[];
const collection = await Collection.findOne(Collection.parseApiJson({
filter: {
name: resourceName,
},
}));
const permissions = (await ctx.ac.isRoot() || collection.developerMode || collection.internal)
? await ctx.ac.can(resourceName).getRootPermissions()
: await ctx.ac.can(resourceName).permissions();
const defaultView = await collection.getViews({
where: {
default: true,
},
limit: 1,
plain: true,
});
collection.setDataValue('defaultViewName', defaultView.get('name'));
const options = Tab.parseApiJson({
filter: ctx.state.developerMode ? {
'id.in': permissions.tabs,
enabled: true,
} : {
'id.in': permissions.tabs,
enabled: true,
developerMode: {'$isFalsy': true},
},
fields: {
appends: ['associationField'],
},
sort: ['sort'],
});
const tabs = await collection.getTabs(options) as Model[];
const tabItems = [];
for (const tab of tabs) {
const itemTab = {
...tab.get(),
};
if (itemTab.type === 'details' && !itemTab.viewName) {
itemTab.viewName = 'details';
}
// if (itemTab.type == 'association') {
// itemTab.field = await collection.getFields({
// where: {
// name: itemTab.association,
// },
// limit: 1,
// plain: true,
// });
// }
tabItems.push(itemTab);
}
return {
...collection.toJSON(),
tabs: tabItems,
};
}
export default async (ctx, next) => {
const { resourceName, values = {} } = ctx.action.params;
const { tabs: items = [] } = values;
// console.log({items})
const collection = await getCollection(ctx, resourceName);
ctx.body = [
collection,
];
const lastItem = items.pop();
for (const item of items) {
const lastCollection = ctx.body[ctx.body.length-1];
lastCollection.pageTitle = await getPageTitle(ctx, {resourceName: lastCollection.name, resourceKey: item.itemId});
const activeTab = _.find(lastCollection.tabs, tab => tab.name == item.tabName)||{};
if (activeTab && activeTab.type === 'association') {
// console.log(activeTab.associationField.target);
const nextCollection = await getCollection(ctx, activeTab.associationField.target);
ctx.body.push(nextCollection);
}
}
const lastCollection = ctx.body[ctx.body.length-1];
lastCollection.pageTitle = await getPageTitle(ctx, {resourceName: lastCollection.name, resourceKey: lastItem.itemId});
await next();
}

View File

@ -6,6 +6,7 @@ import getView from './actions/getView';
import getRoutes from './actions/getRoutes'; import getRoutes from './actions/getRoutes';
import getPageInfo from './actions/getPageInfo'; import getPageInfo from './actions/getPageInfo';
import * as rolesPagesActions from './actions/roles.pages'; import * as rolesPagesActions from './actions/roles.pages';
import getCollections from './actions/getCollections';
export default async function (options = {}) { export default async function (options = {}) {
const database: Database = this.database; const database: Database = this.database;
@ -18,6 +19,7 @@ export default async function (options = {}) {
resourcer.registerActionHandler('getCollection', getCollection); resourcer.registerActionHandler('getCollection', getCollection);
resourcer.registerActionHandler('getView', getView); resourcer.registerActionHandler('getView', getView);
resourcer.registerActionHandler('getPageInfo', getPageInfo); resourcer.registerActionHandler('getPageInfo', getPageInfo);
resourcer.registerActionHandler('getCollections', getCollections);
resourcer.registerActionHandler('pages:getRoutes', getRoutes); resourcer.registerActionHandler('pages:getRoutes', getRoutes);
Object.keys(rolesPagesActions).forEach(actionName => { Object.keys(rolesPagesActions).forEach(actionName => {