Skip to content

Commit

Permalink
feat: database view collection (nocobase#1587)
Browse files Browse the repository at this point in the history
* test: create view collection

* feat: view collection class

* feat: list view

* chore: skip sync view collection

* test: should create view collection in difference schema

* test: create view collection in collection manager

* feat: create view collection by user sql

* test: view resourcer

* feat: view collection

* feat: view collection cannot be added, deleted, or modified

* feat: view collection cannot be added, deleted, or modified

* feat: view collection cannot be added, deleted, or modified

* feat: view collection cannot be added, deleted, or modified

* refactor: connect to database view

* refactor: sync from database

* chore: rename list view sql

* chore: list view fields api

* chore: create collection without viewName

* feat: bring out fields when selecting a view

* chore: bring out fields when selecting a view

* feat: view field inference class

* chore: bring out fields when selecting a view

* chore: sync form database view

* chore: sync form database view

* refactor: view collection local

* feat: view get api

* feat: database type infer

* feat: integer map

* chore: remove from in view list

* chore: build error

* chore: uniq collection

* fix: typo

* chore: replace collection list source field

* fix: destroy view collection

* chore: timestamp field map

* refactor: interface avalableTypes

* refactor: interface avalableTypes

* chore: list fields test

* refactor: interface avalableTypes

* chore: uiSchema response in field source

* fix: view query

* chore: collection snippet

* refactor: view collection support preview

* fix: handle field source

* fix: typo

* fix: configure fileds title

* fix: configure fileds title

* fix: configure fileds title

* fix: sync from databse interface

* fix: sync from databse interface

* feat: set fields api

* fix: sync from databse fix

* feat: possibleTypes

* chore: fields get

* fix: sync from databse

* fix: list view test

* fix: view test in difference schema

* chore: comment

* feat: when there is only one source  collection, the view is a subset of a Collection

* feat: view collection add field

* fix: inherit query with schema

* fix: test

* fix: ci test

* fix: test with schema

* chore: set pg default search path

* chore: mysql test

* fix: test with schema

* chore: test

* chore: action test

* chore: view column usage return type

* feat: mysql field inference

* fix: tableName

* chore: node sql parser

* fix: sql build

* fix: database build

* fix: mysql test

* feat: view collection uiSchema title

* fix: incorrect field source display  when switching views

* refactor: view collection not allow modify

* fix: view collection is allow add, delete, and modify

* fix: mysql test

* fix: sqlite test

* fix: sqlite test

* fix: sqlite test

* fix: sqlite test

* chore: add id field as default target key

* style: style improve

* feat: load source field options

* style: style improve

* chore: disable remove column in view collection

* chore: support creating view collection with different schemas with the same name

* chore: support creating view collection with different schemas with the same name

* fix: query view in difference schema

* refactor: view collection viewname

* fix: query view collection in difference schema

* fix: field load

* chore: field options

* fix: mysql test

* fix: uiSchema component error when using a view field in a block

* fix: sqlite test

* chore: test

* fix: dump user views

* fix: view collection can be updated and edited in table block

* chore: sync from database display last field configuration

* chore: loadCollections

* chore: sync from database display last field configuration

* fix: field options merge issues

* style: preview table

* fix: view collection is allow using in kanban blocks

* refactor: code improve

* fix: view collection can be updated an edited in calendar block

* chore: disable infer field without interface

* feat: preview only shows source or interface fields

* fix: test

* refactor: locale

* feat: sql parser

* chore: remove node-sql-parser

* fix: yarn.lock

* test: view repository

* fix: view repository test

* chore: console.log

* chore: console.log

* fix: mysql without schema

* fix: mysql without schema

* chore: preview with field schema

* chore: tableActionInitializers

* style: preview style improve

* chore:  parameter is filter when there is no filterByTk

* fix: preview pagination

* fix: preview pagination

* style: preview table style improve

* fix: sync from database loading

* chore: preview performance optimization

* chore: preview performance optimization

* feat: limit & offset

* chore: preview performance optimization

* test: field with dot column

* fix: datetime interface display

* fix: missing boolean type

* fix: sync

* fix: sync from database

* style: style improve

* style: style improve

* style: style improve

* chore: preview table

* chore: preview table

* chore: preview table

* fix: styling

---------

Co-authored-by: katherinehhh <[email protected]>
Co-authored-by: chenos <[email protected]>
  • Loading branch information
3 people authored Apr 1, 2023
1 parent bcc417a commit 4f87de7
Show file tree
Hide file tree
Showing 104 changed files with 14,610 additions and 217 deletions.
4 changes: 3 additions & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ services:
networks:
- nocobase
postgres:
image: postgres:10
image: postgres:latest
restart: always
networks:
- nocobase
command: postgres -c wal_level=logical
ports:
- "${DB_POSTGRES_PORT}:5432"
volumes:
- ./storage/db/postgres/backups:/backups
environment:
POSTGRES_USER: ${DB_USER}
POSTGRES_DB: ${DB_DATABASE}
Expand Down
1 change: 1 addition & 0 deletions packages/core/actions/src/__tests__/create-action.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ describe('create action', () => {

beforeEach(async () => {
app = mockServer();
await app.db.clean({ drop: true });
registerActions(app);

Post = app.collection({
Expand Down
2 changes: 2 additions & 0 deletions packages/core/actions/src/__tests__/remove-action.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ describe('remove action', () => {
app = mockServer();
registerActions(app);

await app.db.clean({ drop: true });

PostTag = app.collection({
name: 'posts_tags',
fields: [{ type: 'string', name: 'tagged_at' }],
Expand Down
1 change: 1 addition & 0 deletions packages/core/actions/src/__tests__/set-action.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ describe('set action', () => {

beforeEach(async () => {
app = mockServer();
await app.db.clean({ drop: true });
registerActions(app);

PostTag = app.collection({
Expand Down
1 change: 1 addition & 0 deletions packages/core/actions/src/__tests__/toggle-action.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ describe('toggle action', () => {

beforeEach(async () => {
app = mockServer();
await app.db.clean({ drop: true });
registerActions(app);

PostTag = app.collection({
Expand Down
20 changes: 19 additions & 1 deletion packages/core/client/src/block-provider/BlockProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -292,9 +292,27 @@ export const useSourceIdFromParentRecord = () => {

export const useParamsFromRecord = () => {
const filterByTk = useFilterByTk();
return {
const record = useRecord();
const { fields } = useCollection();
const filterFields = fields
.filter((v) => {
return ['boolean', 'date', 'integer', 'radio', 'sort', 'string', 'time', 'uid', 'uuid'].includes(v.type);
})
.map((v) => v.name);
const filter = Object.keys(record)
.filter((key) => filterFields.includes(key))
.reduce((result, key) => {
result[key] = record[key];
return result;
}, {});

const obj = {
filterByTk: filterByTk,
};
if (!filterByTk) {
obj['filter'] = filter;
}
return obj;
};

export const RecordLink = (props) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ const InternalField: React.FC = (props) => {
const fieldSchema = useFieldSchema();
const { name, interface: interfaceType, uiSchema, defaultValue } = useCollectionField();
const collectionField = useCollectionField();
const component = useComponent(uiSchema?.['x-component']);
const component = useComponent(uiSchema?.['x-component'] || 'Input');
const compile = useCompile();
const setFieldProps = (key, value) => {
field[key] = typeof field[key] === 'undefined' ? value : field[key];
Expand Down Expand Up @@ -73,7 +73,6 @@ const InternalField: React.FC = (props) => {
if (!uiSchema) {
return null;
}

return React.createElement(component, props, props.children);
};

Expand Down Expand Up @@ -107,7 +106,6 @@ export const CollectionField = connect((props) => {
const fieldSchema = useFieldSchema();
const field = fieldSchema?.['x-component-props']?.['field'];
const { snapshot } = useActionContext();

return (
<CollectionFieldProvider
name={fieldSchema.name}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import {
ConfigurationTabs,
EditCategory,
EditCategoryAction,
SyncFieldsAction,
SyncFieldsActionCom
} from './Configuration';

import { CollectionCategroriesProvider } from './CollectionManagerProvider';
Expand Down Expand Up @@ -81,6 +83,8 @@ export const CollectionManagerPane = () => {
ViewFieldAction,
EditCategory,
EditCategoryAction,
SyncFieldsAction,
SyncFieldsActionCom
}}
/>
// </Card>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,9 @@ const getSchema = (schema, category, compile): ISchema => {
properties['defaultValue']['x-decorator'] = 'FormItem';
}
const initialValue: any = {
name: `t_${uid()}`,
name: schema.name !== 'view' ? `t_${uid()}` : null,
template: schema.name,
view: schema.name === 'view',
category,
...cloneDeep(schema.default),
};
Expand Down Expand Up @@ -201,7 +202,7 @@ const useCreateCollection = (schema?: any) => {
if (schema?.events?.beforeSubmit) {
schema.events.beforeSubmit(values);
}
const fields = useDefaultCollectionFields(values);
const fields = values?.template !== 'view' ? useDefaultCollectionFields(values) : values.fields;
if (values.autoCreateReverseField) {
} else {
delete values.reverseField;
Expand Down Expand Up @@ -235,8 +236,15 @@ export const AddCollectionAction = (props) => {
const [schema, setSchema] = useState({});
const compile = useCompile();
const { t } = useTranslation();
const items = templateOptions().map((option) => {
return { label: compile(option.title), key: option.name };
const collectionTemplates = templateOptions();
const items = [];
collectionTemplates.forEach((item) => {
if (item.divider) {
items.push({
type: 'divider',
});
}
items.push({ label: compile(item.title), key: item.name });
});
const {
state: { category },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -212,72 +212,74 @@ export const AddFieldAction = (props) => {
return optionArr;
};
return (
<RecordProvider record={record}>
<ActionContext.Provider value={{ visible, setVisible }}>
<Dropdown
getPopupContainer={getContainer}
trigger={trigger}
align={align}
overlay={
<Menu
style={{
maxHeight: '60vh',
overflow: 'auto',
}}
onClick={(e) => {
//@ts-ignore
const targetScope = e.item.props['data-targetScope'];
targetScope && setTargetScope(targetScope);
const schema = getSchema(getInterface(e.key), record, compile);
if (schema) {
setSchema(schema);
setVisible(true);
}
}}
>
{getFieldOptions().map((option) => {
return (
option.children.length > 0 && (
<Menu.ItemGroup key={option.label} title={compile(option.label)}>
{option.children
.filter((child) => !['o2o', 'subTable'].includes(child.name))
.map((child) => {
return (
<Menu.Item key={child.name} data-targetScope={child.targetScope}>
{compile(child.title)}
</Menu.Item>
);
})}
</Menu.ItemGroup>
)
);
})}
</Menu>
}
>
{children || (
<Button icon={<PlusOutlined />} type={'primary'}>
{t('Add field')}
</Button>
)}
</Dropdown>
<SchemaComponent
schema={schema}
components={{ ...components, ArrayTable }}
scope={{
getContainer,
useCancelAction,
createOnly: true,
isOverride: false,
override: false,
useCreateCollectionField,
record,
showReverseFieldConfig: true,
targetScope,
...scope,
}}
/>
</ActionContext.Provider>
</RecordProvider>
record.template !== 'view' && (
<RecordProvider record={record}>
<ActionContext.Provider value={{ visible, setVisible }}>
<Dropdown
getPopupContainer={getContainer}
trigger={trigger}
align={align}
overlay={
<Menu
style={{
maxHeight: '60vh',
overflow: 'auto',
}}
onClick={(e) => {
//@ts-ignore
const targetScope = e.item.props['data-targetScope'];
targetScope && setTargetScope(targetScope);
const schema = getSchema(getInterface(e.key), record, compile);
if (schema) {
setSchema(schema);
setVisible(true);
}
}}
>
{getFieldOptions().map((option) => {
return (
option.children.length > 0 && (
<Menu.ItemGroup key={option.label} title={compile(option.label)}>
{option.children
.filter((child) => !['o2o', 'subTable'].includes(child.name))
.map((child) => {
return (
<Menu.Item key={child.name} data-targetScope={child.targetScope}>
{compile(child.title)}
</Menu.Item>
);
})}
</Menu.ItemGroup>
)
);
})}
</Menu>
}
>
{children || (
<Button icon={<PlusOutlined />} type={'primary'}>
{t('Add field')}
</Button>
)}
</Dropdown>
<SchemaComponent
schema={schema}
components={{ ...components, ArrayTable }}
scope={{
getContainer,
useCancelAction,
createOnly: true,
isOverride: false,
override: false,
useCreateCollectionField,
record,
showReverseFieldConfig: true,
targetScope,
...scope,
}}
/>
</ActionContext.Provider>
</RecordProvider>
)
);
};
Loading

0 comments on commit 4f87de7

Please sign in to comment.