feat: improve code
This commit is contained in:
		
							parent
							
								
									aa1c84e72a
								
							
						
					
					
						commit
						afab15327e
					
				@ -1,5 +1,5 @@
 | 
			
		||||
import { mockServer } from './index';
 | 
			
		||||
import { registerActions } from '@nocobase/actions';
 | 
			
		||||
import { mockServer } from './index';
 | 
			
		||||
 | 
			
		||||
describe('list action', () => {
 | 
			
		||||
  let app;
 | 
			
		||||
@ -112,7 +112,7 @@ describe('list action', () => {
 | 
			
		||||
    const response = await app
 | 
			
		||||
      .agent()
 | 
			
		||||
      .resource('posts.tags', 1)
 | 
			
		||||
      .list({ fields: ['id', 'posts_tags.createdAt'], sort: ['id'] });
 | 
			
		||||
      .list({ fields: ['id', 'postsTags.createdAt'], sort: ['id'] });
 | 
			
		||||
 | 
			
		||||
    const body = response.body;
 | 
			
		||||
    expect(body.count).toEqual(2);
 | 
			
		||||
 | 
			
		||||
@ -101,13 +101,13 @@ export class APIClient {
 | 
			
		||||
        } else {
 | 
			
		||||
          config['method'] = 'post';
 | 
			
		||||
        }
 | 
			
		||||
        return (params?: ActionParams) => {
 | 
			
		||||
        return async (params?: ActionParams) => {
 | 
			
		||||
          const { values, ...others } = params || {};
 | 
			
		||||
          config['params'] = others;
 | 
			
		||||
          if (config.method !== 'get') {
 | 
			
		||||
            config['data'] = values || {};
 | 
			
		||||
          }
 | 
			
		||||
          return this.request(config);
 | 
			
		||||
          return await this.request(config);
 | 
			
		||||
        };
 | 
			
		||||
      },
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@ -11,7 +11,7 @@ export const updatedAt: IField = {
 | 
			
		||||
  sortable: true,
 | 
			
		||||
  default: {
 | 
			
		||||
    type: 'date',
 | 
			
		||||
    field: 'updated_at',
 | 
			
		||||
    field: 'updatedAt',
 | 
			
		||||
    // name,
 | 
			
		||||
    uiSchema: {
 | 
			
		||||
      type: 'datetime',
 | 
			
		||||
 | 
			
		||||
@ -34,7 +34,7 @@ const InternalAdminLayout = (props: any) => {
 | 
			
		||||
  return (
 | 
			
		||||
    <Layout>
 | 
			
		||||
      <Layout.Header style={{ height: 46, lineHeight: '46px', position: 'relative', paddingLeft: 0 }}>
 | 
			
		||||
        <div style={{ display: 'flex' }}>
 | 
			
		||||
        <div style={{ display: 'flex', height: '100%' }}>
 | 
			
		||||
          <div style={{ width: 200, display: 'inline-flex', color: '#fff', padding: '0', alignItems: 'center' }}>
 | 
			
		||||
            <img
 | 
			
		||||
              className={css`
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,7 @@ export const LinkToFieldInitializer = (props) => {
 | 
			
		||||
    item.find,
 | 
			
		||||
    item.remove,
 | 
			
		||||
  );
 | 
			
		||||
  const targetKey = item.field.targetKey || 'id';
 | 
			
		||||
  return (
 | 
			
		||||
    <SchemaInitializer.Item
 | 
			
		||||
      onClick={() => {
 | 
			
		||||
@ -20,17 +21,17 @@ export const LinkToFieldInitializer = (props) => {
 | 
			
		||||
        }
 | 
			
		||||
        insert({
 | 
			
		||||
          ...item.schema,
 | 
			
		||||
          default: [
 | 
			
		||||
            { id: 1, name: 'name1' },
 | 
			
		||||
            { id: 2, name: 'name2' },
 | 
			
		||||
          ],
 | 
			
		||||
          // default: [
 | 
			
		||||
          //   { id: 1, name: 'name1' },
 | 
			
		||||
          //   { id: 2, name: 'name2' },
 | 
			
		||||
          // ],
 | 
			
		||||
          // 'x-decorator': 'FormItem',
 | 
			
		||||
          'x-component': 'CollectionField',
 | 
			
		||||
          'x-component-props': {
 | 
			
		||||
            mode: 'tags',
 | 
			
		||||
            fieldNames: {
 | 
			
		||||
              label: 'name',
 | 
			
		||||
              value: 'id',
 | 
			
		||||
              label: targetKey,
 | 
			
		||||
              value: targetKey,
 | 
			
		||||
            },
 | 
			
		||||
          },
 | 
			
		||||
          properties: {
 | 
			
		||||
@ -59,22 +60,22 @@ export const LinkToFieldInitializer = (props) => {
 | 
			
		||||
                  'x-designer': 'Table.Void.Designer',
 | 
			
		||||
                  'x-component': 'CardItem',
 | 
			
		||||
                  properties: {
 | 
			
		||||
                    actions: {
 | 
			
		||||
                      type: 'void',
 | 
			
		||||
                      'x-initializer': 'TableActionInitializers',
 | 
			
		||||
                      'x-component': 'ActionBar',
 | 
			
		||||
                      'x-component-props': {
 | 
			
		||||
                        style: {
 | 
			
		||||
                          marginBottom: 16,
 | 
			
		||||
                        },
 | 
			
		||||
                      },
 | 
			
		||||
                      properties: {},
 | 
			
		||||
                    },
 | 
			
		||||
                    // actions: {
 | 
			
		||||
                    //   type: 'void',
 | 
			
		||||
                    //   'x-initializer': 'TableActionInitializers',
 | 
			
		||||
                    //   'x-component': 'ActionBar',
 | 
			
		||||
                    //   'x-component-props': {
 | 
			
		||||
                    //     style: {
 | 
			
		||||
                    //       marginBottom: 16,
 | 
			
		||||
                    //     },
 | 
			
		||||
                    //   },
 | 
			
		||||
                    //   properties: {},
 | 
			
		||||
                    // },
 | 
			
		||||
                    table: {
 | 
			
		||||
                      // type: 'void',
 | 
			
		||||
                      'x-component': 'Table.RowSelection',
 | 
			
		||||
                      'x-component-props': {
 | 
			
		||||
                        rowKey: 'id',
 | 
			
		||||
                        rowKey: targetKey,
 | 
			
		||||
                        objectValue: true,
 | 
			
		||||
                        rowSelection: {
 | 
			
		||||
                          type: 'checkbox',
 | 
			
		||||
@ -83,60 +84,29 @@ export const LinkToFieldInitializer = (props) => {
 | 
			
		||||
                      },
 | 
			
		||||
                      'x-initializer': 'TableColumnInitializers',
 | 
			
		||||
                      properties: {
 | 
			
		||||
                        actions: {
 | 
			
		||||
                          type: 'void',
 | 
			
		||||
                          title: '{{ t("Actions") }}',
 | 
			
		||||
                          'x-decorator': 'Table.Column.ActionBar',
 | 
			
		||||
                          'x-component': 'Table.Column',
 | 
			
		||||
                          'x-designer': 'Table.RowActionDesigner',
 | 
			
		||||
                          'x-initializer': 'TableRecordActionInitializers',
 | 
			
		||||
                          properties: {
 | 
			
		||||
                            actions: {
 | 
			
		||||
                              type: 'void',
 | 
			
		||||
                              'x-decorator': 'DndContext',
 | 
			
		||||
                              'x-component': 'Space',
 | 
			
		||||
                              'x-component-props': {
 | 
			
		||||
                                split: '|',
 | 
			
		||||
                              },
 | 
			
		||||
                              properties: {},
 | 
			
		||||
                            },
 | 
			
		||||
                          },
 | 
			
		||||
                        },
 | 
			
		||||
                        // actions: {
 | 
			
		||||
                        //   type: 'void',
 | 
			
		||||
                        //   title: '{{ t("Actions") }}',
 | 
			
		||||
                        //   'x-decorator': 'Table.Column.ActionBar',
 | 
			
		||||
                        //   'x-component': 'Table.Column',
 | 
			
		||||
                        //   'x-designer': 'Table.RowActionDesigner',
 | 
			
		||||
                        //   'x-initializer': 'TableRecordActionInitializers',
 | 
			
		||||
                        //   properties: {
 | 
			
		||||
                        //     actions: {
 | 
			
		||||
                        //       type: 'void',
 | 
			
		||||
                        //       'x-decorator': 'DndContext',
 | 
			
		||||
                        //       'x-component': 'Space',
 | 
			
		||||
                        //       'x-component-props': {
 | 
			
		||||
                        //         split: '|',
 | 
			
		||||
                        //       },
 | 
			
		||||
                        //       properties: {},
 | 
			
		||||
                        //     },
 | 
			
		||||
                        //   },
 | 
			
		||||
                        // },
 | 
			
		||||
                      },
 | 
			
		||||
                    },
 | 
			
		||||
                  },
 | 
			
		||||
                },
 | 
			
		||||
                // input: {
 | 
			
		||||
                //   type: 'array',
 | 
			
		||||
                //   title: `编辑模式`,
 | 
			
		||||
                //   'x-component': 'Table.RowSelection',
 | 
			
		||||
                //   'x-component-props': {
 | 
			
		||||
                //     rowKey: 'id',
 | 
			
		||||
                //     objectValue: true,
 | 
			
		||||
                //     rowSelection: {
 | 
			
		||||
                //       type: 'checkbox',
 | 
			
		||||
                //     },
 | 
			
		||||
                //     dataSource: [
 | 
			
		||||
                //       { id: 1, name: 'Name1' },
 | 
			
		||||
                //       { id: 2, name: 'Name2' },
 | 
			
		||||
                //       { id: 3, name: 'Name3' },
 | 
			
		||||
                //     ],
 | 
			
		||||
                //   },
 | 
			
		||||
                //   properties: {
 | 
			
		||||
                //     column1: {
 | 
			
		||||
                //       type: 'void',
 | 
			
		||||
                //       title: 'Name',
 | 
			
		||||
                //       'x-component': 'Table.Column',
 | 
			
		||||
                //       properties: {
 | 
			
		||||
                //         name: {
 | 
			
		||||
                //           type: 'string',
 | 
			
		||||
                //           'x-component': 'Input',
 | 
			
		||||
                //           'x-read-pretty': true,
 | 
			
		||||
                //         },
 | 
			
		||||
                //       },
 | 
			
		||||
                //     },
 | 
			
		||||
                //   },
 | 
			
		||||
                // },
 | 
			
		||||
              },
 | 
			
		||||
            },
 | 
			
		||||
            item: {
 | 
			
		||||
 | 
			
		||||
@ -4,7 +4,7 @@ import { useField, useFieldSchema } from '@formily/react';
 | 
			
		||||
import { Space } from 'antd';
 | 
			
		||||
import classNames from 'classnames';
 | 
			
		||||
import React from 'react';
 | 
			
		||||
import { DragHandler, useDesignable } from '../schema-component';
 | 
			
		||||
import { DragHandler, useCompile, useDesignable } from '../schema-component';
 | 
			
		||||
import { SchemaSettings } from './SchemaSettings';
 | 
			
		||||
 | 
			
		||||
const titleCss = css`
 | 
			
		||||
@ -27,6 +27,7 @@ export const GeneralSchemaDesigner = (props: any) => {
 | 
			
		||||
  const { dn, designable } = useDesignable();
 | 
			
		||||
  const field = useField();
 | 
			
		||||
  const fieldSchema = useFieldSchema();
 | 
			
		||||
  const compile = useCompile();
 | 
			
		||||
  const schemaSettingsProps = {
 | 
			
		||||
    dn,
 | 
			
		||||
    field,
 | 
			
		||||
@ -37,7 +38,7 @@ export const GeneralSchemaDesigner = (props: any) => {
 | 
			
		||||
  }
 | 
			
		||||
  return (
 | 
			
		||||
    <div className={'general-schema-designer'}>
 | 
			
		||||
      {title && <div className={classNames('general-schema-designer-title', titleCss)}>{title}</div>}
 | 
			
		||||
      {title && <div className={classNames('general-schema-designer-title', titleCss)}>{compile(title)}</div>}
 | 
			
		||||
      <div className={'general-schema-designer-icons'}>
 | 
			
		||||
        <Space size={2} align={'center'}>
 | 
			
		||||
          <DragHandler>
 | 
			
		||||
 | 
			
		||||
@ -91,15 +91,13 @@ const useSignup = () => {
 | 
			
		||||
  return {
 | 
			
		||||
    async run() {
 | 
			
		||||
      await form.submit();
 | 
			
		||||
      const response = await api.resource('users').signup({
 | 
			
		||||
      await api.resource('users').signup({
 | 
			
		||||
        values: form.values,
 | 
			
		||||
      });
 | 
			
		||||
      if (response?.data) {
 | 
			
		||||
        message.success('注册成功,即将跳转登录页');
 | 
			
		||||
        setTimeout(() => {
 | 
			
		||||
          history.push('/signin');
 | 
			
		||||
        }, 2000);
 | 
			
		||||
      }
 | 
			
		||||
      message.success('注册成功,即将跳转登录页');
 | 
			
		||||
      setTimeout(() => {
 | 
			
		||||
        history.push('/signin');
 | 
			
		||||
      }, 2000);
 | 
			
		||||
    },
 | 
			
		||||
  };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -184,7 +184,7 @@ describe('collection sync', () => {
 | 
			
		||||
 | 
			
		||||
    const tableFields = await (<any>model).queryInterface.describeTable(`${db.getTablePrefix()}posts`);
 | 
			
		||||
 | 
			
		||||
    expect(tableFields['user_id']).toBeUndefined();
 | 
			
		||||
    expect(tableFields['userId']).toBeUndefined();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
  test('sync with association', async () => {
 | 
			
		||||
@ -211,7 +211,7 @@ describe('collection sync', () => {
 | 
			
		||||
 | 
			
		||||
    const model = collection.model;
 | 
			
		||||
    await collection.sync();
 | 
			
		||||
    const tableFields = await (<any>model).queryInterface.describeTable(`${db.getTablePrefix()}posts_tags`);
 | 
			
		||||
    const tableFields = await (<any>model).queryInterface.describeTable(`${db.getTablePrefix()}postsTags`);
 | 
			
		||||
    expect(tableFields['postId']).toBeDefined();
 | 
			
		||||
    expect(tableFields['tagId']).toBeDefined();
 | 
			
		||||
  });
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import { Database } from '../../database';
 | 
			
		||||
import { mockDatabase } from '../';
 | 
			
		||||
import { Database } from '../../database';
 | 
			
		||||
 | 
			
		||||
describe('belongs to many field', () => {
 | 
			
		||||
  let db: Database;
 | 
			
		||||
@ -22,14 +22,14 @@ describe('belongs to many field', () => {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    expect(Post.model.associations.tags).toBeUndefined();
 | 
			
		||||
    expect(db.getCollection('posts_tags')).toBeUndefined();
 | 
			
		||||
    expect(db.getCollection('postsTags')).toBeUndefined();
 | 
			
		||||
 | 
			
		||||
    const Tag = db.collection({
 | 
			
		||||
      name: 'tags',
 | 
			
		||||
      fields: [{ type: 'string', name: 'name' }],
 | 
			
		||||
    });
 | 
			
		||||
    expect(Post.model.associations.tags).toBeDefined();
 | 
			
		||||
    const Through = db.getCollection('posts_tags');
 | 
			
		||||
    const Through = db.getCollection('postsTags');
 | 
			
		||||
    expect(Through).toBeDefined();
 | 
			
		||||
 | 
			
		||||
    expect(Through.model.rawAttributes['postId']).toBeDefined();
 | 
			
		||||
@ -46,14 +46,14 @@ describe('belongs to many field', () => {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    expect(Post.model.associations.tags).toBeUndefined();
 | 
			
		||||
    expect(db.getCollection('posts_tags')).toBeUndefined();
 | 
			
		||||
    expect(db.getCollection('postsTags')).toBeUndefined();
 | 
			
		||||
 | 
			
		||||
    const Tag = db.collection({
 | 
			
		||||
      name: 'tags',
 | 
			
		||||
      fields: [{ type: 'string', name: 'name' }],
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    const PostTag = db.collection({ name: 'posts_tags' });
 | 
			
		||||
    const PostTag = db.collection({ name: 'postsTags' });
 | 
			
		||||
 | 
			
		||||
    expect(PostTag.model.rawAttributes['postId']).toBeDefined();
 | 
			
		||||
    expect(PostTag.model.rawAttributes['tagId']).toBeDefined();
 | 
			
		||||
 | 
			
		||||
@ -159,7 +159,7 @@ export class Collection<
 | 
			
		||||
        collection: this,
 | 
			
		||||
      },
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    this.removeField(name);
 | 
			
		||||
    this.fields.set(name, field);
 | 
			
		||||
    this.emit('field.afterAdd', field);
 | 
			
		||||
    return field;
 | 
			
		||||
@ -187,6 +187,9 @@ export class Collection<
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  removeField(name) {
 | 
			
		||||
    if (!this.fields.has(name)) {
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    const field = this.fields.get(name);
 | 
			
		||||
    const bool = this.fields.delete(name);
 | 
			
		||||
    if (bool) {
 | 
			
		||||
 | 
			
		||||
@ -158,10 +158,10 @@ export class Database extends EventEmitter implements AsyncEmitter {
 | 
			
		||||
  getRepository<R extends RelationRepository>(name: string, relationId?: string | number): Repository | R {
 | 
			
		||||
    if (relationId) {
 | 
			
		||||
      const [collection, relation] = name.split('.');
 | 
			
		||||
      return this.getRepository(collection).relation(relation).of(relationId) as R;
 | 
			
		||||
      return this.getRepository(collection)?.relation(relation)?.of(relationId) as R;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return this.getCollection(name).repository;
 | 
			
		||||
    return this.getCollection(name)?.repository;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  addPendingField(field: RelationField) {
 | 
			
		||||
 | 
			
		||||
@ -1,16 +1,18 @@
 | 
			
		||||
import { omit } from 'lodash';
 | 
			
		||||
import { BelongsToManyOptions as SequelizeBelongsToManyOptions } from 'sequelize';
 | 
			
		||||
import { BelongsToManyOptions as SequelizeBelongsToManyOptions, Utils } from 'sequelize';
 | 
			
		||||
import { Collection } from '../collection';
 | 
			
		||||
import { BaseRelationFieldOptions, MultipleRelationFieldOptions, RelationField } from './relation-field';
 | 
			
		||||
import { MultipleRelationFieldOptions, RelationField } from './relation-field';
 | 
			
		||||
 | 
			
		||||
export class BelongsToManyField extends RelationField {
 | 
			
		||||
  get through() {
 | 
			
		||||
    return (
 | 
			
		||||
      this.options.through ||
 | 
			
		||||
      [this.context.collection.model.name, this.target]
 | 
			
		||||
        .map((name) => name.toLowerCase())
 | 
			
		||||
        .sort()
 | 
			
		||||
        .join('_')
 | 
			
		||||
      Utils.camelize(
 | 
			
		||||
        [this.context.collection.model.name, this.target]
 | 
			
		||||
          .map((name) => name.toLowerCase())
 | 
			
		||||
          .sort()
 | 
			
		||||
          .join('_'),
 | 
			
		||||
      )
 | 
			
		||||
    );
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
@ -49,6 +51,12 @@ export class BelongsToManyField extends RelationField {
 | 
			
		||||
    if (!this.options.sourceKey) {
 | 
			
		||||
      this.options.sourceKey = association.sourceKey;
 | 
			
		||||
    }
 | 
			
		||||
    if (!this.options.otherKey) {
 | 
			
		||||
      this.options.otherKey = association.otherKey;
 | 
			
		||||
    }
 | 
			
		||||
    if (!this.options.through) {
 | 
			
		||||
      this.options.through = this.through;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
import { mockServer } from '@nocobase/test';
 | 
			
		||||
import PluginUiSchema from '@nocobase/plugin-ui-schema-storage';
 | 
			
		||||
import PluginCollectionManager from '@nocobase/plugin-collection-manager';
 | 
			
		||||
import PluginUiSchema from '@nocobase/plugin-ui-schema-storage';
 | 
			
		||||
import { mockServer } from '@nocobase/test';
 | 
			
		||||
import PluginACL from '../server';
 | 
			
		||||
 | 
			
		||||
let mockRole: string = 'admin';
 | 
			
		||||
@ -33,5 +33,7 @@ export async function prepareApp() {
 | 
			
		||||
  app.plugin(PluginACL);
 | 
			
		||||
  await app.loadAndInstall();
 | 
			
		||||
 | 
			
		||||
  await app.db.sync();
 | 
			
		||||
 | 
			
		||||
  return app;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
import { MockServer } from '@nocobase/test';
 | 
			
		||||
import { Database, Model } from '@nocobase/database';
 | 
			
		||||
import { prepareApp } from './prepare';
 | 
			
		||||
import { CollectionRepository } from '@nocobase/plugin-collection-manager';
 | 
			
		||||
import { MockServer } from '@nocobase/test';
 | 
			
		||||
import { prepareApp } from './prepare';
 | 
			
		||||
 | 
			
		||||
describe('role resource api', () => {
 | 
			
		||||
  let app: MockServer;
 | 
			
		||||
@ -54,6 +54,9 @@ describe('role resource api', () => {
 | 
			
		||||
      .agent()
 | 
			
		||||
      .resource('roles.collections', 'admin')
 | 
			
		||||
      .list({
 | 
			
		||||
        filter: {
 | 
			
		||||
          $or: [{ name: 'c1' }, { name: 'c2' }],
 | 
			
		||||
        },
 | 
			
		||||
        sort: ['sort'],
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -12,7 +12,9 @@ const roleCollectionsResource = {
 | 
			
		||||
      const collectionRepository = db.getRepository('collections');
 | 
			
		||||
 | 
			
		||||
      // all collections
 | 
			
		||||
      const collections = await collectionRepository.find();
 | 
			
		||||
      const collections = await collectionRepository.find({
 | 
			
		||||
        filter: ctx.action.params.filter,
 | 
			
		||||
      });
 | 
			
		||||
 | 
			
		||||
      // role collections
 | 
			
		||||
      const roleResources = await db.getRepository('rolesResources').find({
 | 
			
		||||
 | 
			
		||||
@ -2,6 +2,7 @@ import { CollectionOptions } from '@nocobase/database';
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
  name: 'roles',
 | 
			
		||||
  title: '{{t("Roles")}}',
 | 
			
		||||
  autoGenId: false,
 | 
			
		||||
  model: 'RoleModel',
 | 
			
		||||
  fields: [
 | 
			
		||||
@ -10,11 +11,21 @@ export default {
 | 
			
		||||
      name: 'name',
 | 
			
		||||
      prefix: 'r_',
 | 
			
		||||
      primaryKey: true,
 | 
			
		||||
      uiSchema: {
 | 
			
		||||
        type: 'string',
 | 
			
		||||
        title: '{{t("Role UID")}}',
 | 
			
		||||
        'x-component': 'Input',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      type: 'string',
 | 
			
		||||
      name: 'title',
 | 
			
		||||
      unique: true,
 | 
			
		||||
      uiSchema: {
 | 
			
		||||
        type: 'string',
 | 
			
		||||
        title: '{{t("Role name")}}',
 | 
			
		||||
        'x-component': 'Input',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      type: 'boolean',
 | 
			
		||||
@ -45,6 +56,7 @@ export default {
 | 
			
		||||
      type: 'belongsToMany',
 | 
			
		||||
      name: 'menuUiSchemas',
 | 
			
		||||
      target: 'uiSchemas',
 | 
			
		||||
      targetKey: 'x-uid',
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      type: 'hasMany',
 | 
			
		||||
 | 
			
		||||
@ -259,6 +259,13 @@ export class PluginACL extends Plugin {
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async install() {
 | 
			
		||||
    const repo = this.db.getRepository<any>('collections');
 | 
			
		||||
    if (repo) {
 | 
			
		||||
      await repo.db2cm('roles');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async load() {
 | 
			
		||||
    await this.app.db.import({
 | 
			
		||||
      directory: resolve(__dirname, 'collections'),
 | 
			
		||||
 | 
			
		||||
@ -14,4 +14,22 @@ export class CollectionRepository extends Repository {
 | 
			
		||||
      await instance.load({ skipExist });
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  async db2cm(collectionName: string) {
 | 
			
		||||
    const collection = this.database.getCollection(collectionName);
 | 
			
		||||
    const options = collection.options;
 | 
			
		||||
    const fields = [];
 | 
			
		||||
    for (const [name, field] of collection.fields) {
 | 
			
		||||
      fields.push({
 | 
			
		||||
        name,
 | 
			
		||||
        ...field.options,
 | 
			
		||||
      });
 | 
			
		||||
    }
 | 
			
		||||
    await this.create({
 | 
			
		||||
      values: {
 | 
			
		||||
        ...options,
 | 
			
		||||
        fields,
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -6,7 +6,7 @@ export default {
 | 
			
		||||
  sortable: 'sort',
 | 
			
		||||
  fields: [
 | 
			
		||||
    {
 | 
			
		||||
      interface: 'string',
 | 
			
		||||
      interface: 'input',
 | 
			
		||||
      type: 'string',
 | 
			
		||||
      name: 'nickname',
 | 
			
		||||
      uiSchema: {
 | 
			
		||||
@ -47,10 +47,11 @@ export default {
 | 
			
		||||
      otherKey: 'roleName',
 | 
			
		||||
      sourceKey: 'id',
 | 
			
		||||
      targetKey: 'name',
 | 
			
		||||
      through: 'rolesUsers',
 | 
			
		||||
      uiSchema: {
 | 
			
		||||
        type: 'array',
 | 
			
		||||
        title: '{{t("Roles")}}',
 | 
			
		||||
        'x-component': 'Select.Drawer',
 | 
			
		||||
        'x-component': 'RecordPicker',
 | 
			
		||||
        'x-component-props': {
 | 
			
		||||
          multiple: true,
 | 
			
		||||
          fieldNames: {
 | 
			
		||||
@ -58,12 +59,9 @@ export default {
 | 
			
		||||
            value: 'name',
 | 
			
		||||
          },
 | 
			
		||||
        },
 | 
			
		||||
        'x-decorator': 'FormItem',
 | 
			
		||||
        'x-designable-bar': 'Select.Drawer.DesignableBar',
 | 
			
		||||
      },
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
      interface: 'select',
 | 
			
		||||
      type: 'string',
 | 
			
		||||
      name: 'appLang',
 | 
			
		||||
    },
 | 
			
		||||
 | 
			
		||||
@ -83,5 +83,9 @@ export default class UsersPlugin extends Plugin {
 | 
			
		||||
        roles: ['admin'],
 | 
			
		||||
      },
 | 
			
		||||
    });
 | 
			
		||||
    const repo = this.db.getRepository<any>('collections');
 | 
			
		||||
    if (repo) {
 | 
			
		||||
      await repo.db2cm('users');
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user