feat(database): support field get in view preview (#2482)

* feat: support field get in view preview

* chore: test

* refactor: dbViews fieldtypes

* refactor: dbViews fieldtypes

* refactor: dbViews fieldtypes

* refactor: dbViews fieldtypes

---------

Co-authored-by: katherinehhh <katherine_15995@163.com>
This commit is contained in:
ChengLei Shao 2023-08-22 10:59:45 +08:00 committed by GitHub
parent 9d33da0437
commit a625fc538d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 116 additions and 9 deletions

View File

@ -6,6 +6,7 @@ import { EllipsisWithTooltip, useCompile } from '../../../';
import { useAPIClient } from '../../../api-client';
import { useCollectionManager } from '../../hooks/useCollectionManager';
const mapFields = ['lineString', 'point', 'circle', 'polygon'];
export const PreviewTable = (props) => {
const { databaseView, schema, viewName, fields } = props;
const [previewColumns, setPreviewColumns] = useState([]);
@ -20,7 +21,7 @@ export const PreviewTable = (props) => {
if (databaseView) {
getPreviewData();
}
}, [databaseView]);
}, [form.values.fields]);
useEffect(() => {
const pColumns = formatPreviewColumns(fields);
@ -28,10 +29,16 @@ export const PreviewTable = (props) => {
}, [form.values.fields]);
const getPreviewData = () => {
const fieldTypes = {};
form.values.fields.map((v) => {
if (mapFields.includes(v.type)) {
fieldTypes[v.name] = v.type;
}
});
setLoading(true);
api
.resource(`dbViews`)
.query({ filterByTk: viewName, schema })
.query({ filterByTk: viewName, schema, fieldTypes })
.then(({ data }) => {
if (data) {
setLoading(false);
@ -58,7 +65,13 @@ export const PreviewTable = (props) => {
const objSchema: any = {
type: 'object',
properties: {
[item.name]: { ...schema, default: content, 'x-read-pretty': true, title: null },
[item.name]: {
name: `${item.name}`,
'x-component': schema && fieldSource ? 'CollectionField' : 'Input',
'x-read-pretty': true,
'x-collection-field': fieldSource?.join('.'),
default: content,
},
},
};
return (
@ -98,7 +111,7 @@ export const PreviewTable = (props) => {
columns={previewColumns}
dataSource={previewData}
scroll={{ x: 1000, y: 300 }}
key={viewName}
key={`${viewName}-preview`}
/>
</>
)}

View File

@ -27,7 +27,7 @@ export const ReadPrettyInternalViewer: React.FC = observer(
(props: any) => {
const fieldSchema = useFieldSchema();
const recordCtx = useRecord();
const { enableLink } = fieldSchema['x-component-props'];
const { enableLink } = fieldSchema['x-component-props'] || {};
// value 做了转换,但 props.value 和原来 useField().value 的值不一致
const field = useField();
const fieldNames = useFieldNames(props);

View File

@ -1,4 +1,4 @@
import { Database, Repository } from '@nocobase/database';
import { Database, Repository, Field, DataTypes } from '@nocobase/database';
import { MockServer } from '@nocobase/test';
import { uid } from '@nocobase/utils';
import { createApp } from '../index';
@ -54,6 +54,73 @@ SELECT * FROM numbers;
await app.destroy();
});
it('should support preview field with getter', async () => {
class TestField extends Field {
get dataType() {
return DataTypes.STRING;
}
constructor(options: any, context: any) {
const { name } = options;
super(
{
get() {
return 'test_' + this.getDataValue(name);
},
...options,
},
context,
);
}
}
db.registerFieldTypes({
test: TestField,
});
const C1 = db.collection({
name: 'c1',
fields: [
{
type: 'test',
name: 'test_field',
},
],
});
await db.sync();
await C1.repository.create({
values: {
test_field: '1',
},
});
const c1 = await C1.repository.findOne();
expect(c1.get('test_field')).toEqual('test_1');
// create view from C1
const viewName = `test_view_${uid(6)}`;
await db.sequelize.query(`DROP VIEW IF EXISTS ${viewName}`);
const createSQL = `CREATE VIEW ${viewName} AS SELECT * FROM ${C1.quotedTableName()}`;
await db.sequelize.query(createSQL);
const response = await agent.resource('dbViews').query({
filterByTk: viewName,
pageSize: 20,
fieldTypes: {
test_field: 'test',
},
});
expect(response.status).toBe(200);
const data = response.body.data;
const firstRow = data[0];
expect(firstRow.test_field).toEqual('test_1');
});
it('should list views', async () => {
const response = await agent.resource('dbViews').list();
expect(response.status).toBe(200);

View File

@ -1,4 +1,4 @@
import Database, { Repository, ViewCollection, ViewFieldInference } from '@nocobase/database';
import Database, { Field, Repository, ViewCollection, ViewFieldInference, DataTypes } from '@nocobase/database';
import Application from '@nocobase/server';
import { uid } from '@nocobase/utils';
import { createApp } from '../index';

View File

@ -56,7 +56,7 @@ export default {
},
async query(ctx, next) {
const { filterByTk, schema = 'public', page = 1, pageSize = 10 } = ctx.action.params;
const { filterByTk, fieldTypes, schema = 'public', page = 1, pageSize = 10 } = ctx.action.params;
const offset = (page - 1) * pageSize;
const limit = 1 * pageSize;
@ -66,7 +66,34 @@ export default {
ctx.app.db.utils.addSchema(filterByTk, schema),
)} LIMIT ${limit} OFFSET ${offset}`;
ctx.body = await ctx.app.db.sequelize.query(sql, { type: 'SELECT' });
const rawValues = await ctx.app.db.sequelize.query(sql, { type: 'SELECT' });
if (fieldTypes) {
for (const raw of rawValues) {
const fakeInstance = {
dataValues: raw,
getDataValue: (key) => raw[key],
};
for (const fieldName of Object.keys(fieldTypes)) {
const fieldType = fieldTypes[fieldName];
const FieldClass = ctx.app.db.fieldTypes.get(fieldType);
const fieldOptions = new FieldClass(
{ name: fieldName },
{
db: ctx.app.db,
},
).options;
if (fieldOptions.get) {
const newValue = fieldOptions.get.apply(fakeInstance);
raw[fieldName] = newValue;
}
}
}
}
ctx.body = rawValues;
await next();
},
},