mirror of
https://github.com/nocobase/nocobase
synced 2024-11-15 09:47:10 +00:00
fix: multi-level nesting
This commit is contained in:
parent
1ea08e62b6
commit
d83cebac56
@ -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>
|
||||||
);
|
);
|
||||||
|
@ -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>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
|
105
packages/plugin-pages/src/actions/getCollections.ts
Normal file
105
packages/plugin-pages/src/actions/getCollections.ts
Normal 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();
|
||||||
|
}
|
@ -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 => {
|
||||||
|
Loading…
Reference in New Issue
Block a user