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:
parent
9d33da0437
commit
a625fc538d
@ -6,6 +6,7 @@ import { EllipsisWithTooltip, useCompile } from '../../../';
|
|||||||
import { useAPIClient } from '../../../api-client';
|
import { useAPIClient } from '../../../api-client';
|
||||||
import { useCollectionManager } from '../../hooks/useCollectionManager';
|
import { useCollectionManager } from '../../hooks/useCollectionManager';
|
||||||
|
|
||||||
|
const mapFields = ['lineString', 'point', 'circle', 'polygon'];
|
||||||
export const PreviewTable = (props) => {
|
export const PreviewTable = (props) => {
|
||||||
const { databaseView, schema, viewName, fields } = props;
|
const { databaseView, schema, viewName, fields } = props;
|
||||||
const [previewColumns, setPreviewColumns] = useState([]);
|
const [previewColumns, setPreviewColumns] = useState([]);
|
||||||
@ -20,7 +21,7 @@ export const PreviewTable = (props) => {
|
|||||||
if (databaseView) {
|
if (databaseView) {
|
||||||
getPreviewData();
|
getPreviewData();
|
||||||
}
|
}
|
||||||
}, [databaseView]);
|
}, [form.values.fields]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const pColumns = formatPreviewColumns(fields);
|
const pColumns = formatPreviewColumns(fields);
|
||||||
@ -28,10 +29,16 @@ export const PreviewTable = (props) => {
|
|||||||
}, [form.values.fields]);
|
}, [form.values.fields]);
|
||||||
|
|
||||||
const getPreviewData = () => {
|
const getPreviewData = () => {
|
||||||
|
const fieldTypes = {};
|
||||||
|
form.values.fields.map((v) => {
|
||||||
|
if (mapFields.includes(v.type)) {
|
||||||
|
fieldTypes[v.name] = v.type;
|
||||||
|
}
|
||||||
|
});
|
||||||
setLoading(true);
|
setLoading(true);
|
||||||
api
|
api
|
||||||
.resource(`dbViews`)
|
.resource(`dbViews`)
|
||||||
.query({ filterByTk: viewName, schema })
|
.query({ filterByTk: viewName, schema, fieldTypes })
|
||||||
.then(({ data }) => {
|
.then(({ data }) => {
|
||||||
if (data) {
|
if (data) {
|
||||||
setLoading(false);
|
setLoading(false);
|
||||||
@ -58,7 +65,13 @@ export const PreviewTable = (props) => {
|
|||||||
const objSchema: any = {
|
const objSchema: any = {
|
||||||
type: 'object',
|
type: 'object',
|
||||||
properties: {
|
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 (
|
return (
|
||||||
@ -98,7 +111,7 @@ export const PreviewTable = (props) => {
|
|||||||
columns={previewColumns}
|
columns={previewColumns}
|
||||||
dataSource={previewData}
|
dataSource={previewData}
|
||||||
scroll={{ x: 1000, y: 300 }}
|
scroll={{ x: 1000, y: 300 }}
|
||||||
key={viewName}
|
key={`${viewName}-preview`}
|
||||||
/>
|
/>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
|
@ -27,7 +27,7 @@ export const ReadPrettyInternalViewer: React.FC = observer(
|
|||||||
(props: any) => {
|
(props: any) => {
|
||||||
const fieldSchema = useFieldSchema();
|
const fieldSchema = useFieldSchema();
|
||||||
const recordCtx = useRecord();
|
const recordCtx = useRecord();
|
||||||
const { enableLink } = fieldSchema['x-component-props'];
|
const { enableLink } = fieldSchema['x-component-props'] || {};
|
||||||
// value 做了转换,但 props.value 和原来 useField().value 的值不一致
|
// value 做了转换,但 props.value 和原来 useField().value 的值不一致
|
||||||
const field = useField();
|
const field = useField();
|
||||||
const fieldNames = useFieldNames(props);
|
const fieldNames = useFieldNames(props);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import { Database, Repository } from '@nocobase/database';
|
import { Database, Repository, Field, DataTypes } from '@nocobase/database';
|
||||||
import { MockServer } from '@nocobase/test';
|
import { MockServer } from '@nocobase/test';
|
||||||
import { uid } from '@nocobase/utils';
|
import { uid } from '@nocobase/utils';
|
||||||
import { createApp } from '../index';
|
import { createApp } from '../index';
|
||||||
@ -54,6 +54,73 @@ SELECT * FROM numbers;
|
|||||||
await app.destroy();
|
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 () => {
|
it('should list views', async () => {
|
||||||
const response = await agent.resource('dbViews').list();
|
const response = await agent.resource('dbViews').list();
|
||||||
expect(response.status).toBe(200);
|
expect(response.status).toBe(200);
|
||||||
|
@ -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 Application from '@nocobase/server';
|
||||||
import { uid } from '@nocobase/utils';
|
import { uid } from '@nocobase/utils';
|
||||||
import { createApp } from '../index';
|
import { createApp } from '../index';
|
||||||
|
@ -56,7 +56,7 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
async query(ctx, next) {
|
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 offset = (page - 1) * pageSize;
|
||||||
const limit = 1 * pageSize;
|
const limit = 1 * pageSize;
|
||||||
@ -66,7 +66,34 @@ export default {
|
|||||||
ctx.app.db.utils.addSchema(filterByTk, schema),
|
ctx.app.db.utils.addSchema(filterByTk, schema),
|
||||||
)} LIMIT ${limit} OFFSET ${offset}`;
|
)} 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();
|
await next();
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Loading…
Reference in New Issue
Block a user