@nocobase/plugin-data-visualization 0.10.1-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +88 -0
- package/client.d.ts +3 -0
- package/client.js +65 -0
- package/lib/client/Settings.d.ts +2 -0
- package/lib/client/Settings.js +81 -0
- package/lib/client/block/ChartBlock.d.ts +2 -0
- package/lib/client/block/ChartBlock.js +73 -0
- package/lib/client/block/ChartBlockDesigner.d.ts +2 -0
- package/lib/client/block/ChartBlockDesigner.js +35 -0
- package/lib/client/block/ChartBlockInitializer.d.ts +6 -0
- package/lib/client/block/ChartBlockInitializer.js +114 -0
- package/lib/client/block/ChartConfigure.d.ts +33 -0
- package/lib/client/block/ChartConfigure.js +501 -0
- package/lib/client/block/formatters.d.ts +15 -0
- package/lib/client/block/formatters.js +58 -0
- package/lib/client/block/index.d.ts +4 -0
- package/lib/client/block/index.js +49 -0
- package/lib/client/block/schemas/configure.d.ts +4 -0
- package/lib/client/block/schemas/configure.js +492 -0
- package/lib/client/block/transformers.d.ts +6 -0
- package/lib/client/block/transformers.js +69 -0
- package/lib/client/hooks.d.ts +312 -0
- package/lib/client/hooks.js +275 -0
- package/lib/client/index.d.ts +5 -0
- package/lib/client/index.js +70 -0
- package/lib/client/locale/en-US.d.ts +23 -0
- package/lib/client/locale/en-US.js +29 -0
- package/lib/client/locale/index.d.ts +3 -0
- package/lib/client/locale/index.js +39 -0
- package/lib/client/locale/ja-JP.d.ts +2 -0
- package/lib/client/locale/ja-JP.js +8 -0
- package/lib/client/locale/pt-BR.d.ts +23 -0
- package/lib/client/locale/pt-BR.js +29 -0
- package/lib/client/locale/ru-RU.d.ts +2 -0
- package/lib/client/locale/ru-RU.js +8 -0
- package/lib/client/locale/tr-TR.d.ts +2 -0
- package/lib/client/locale/tr-TR.js +8 -0
- package/lib/client/locale/zh-CN.d.ts +70 -0
- package/lib/client/locale/zh-CN.js +76 -0
- package/lib/client/renderer/ChartLibrary.d.ts +71 -0
- package/lib/client/renderer/ChartLibrary.js +140 -0
- package/lib/client/renderer/ChartRenderer.d.ts +7 -0
- package/lib/client/renderer/ChartRenderer.js +258 -0
- package/lib/client/renderer/ChartRendererProvider.d.ts +43 -0
- package/lib/client/renderer/ChartRendererProvider.js +38 -0
- package/lib/client/renderer/index.d.ts +4 -0
- package/lib/client/renderer/index.js +49 -0
- package/lib/client/renderer/library/AntdLibrary.d.ts +2 -0
- package/lib/client/renderer/library/AntdLibrary.js +123 -0
- package/lib/client/renderer/library/G2PlotLibrary.d.ts +2 -0
- package/lib/client/renderer/library/G2PlotLibrary.js +288 -0
- package/lib/client/renderer/library/index.d.ts +3 -0
- package/lib/client/renderer/library/index.js +15 -0
- package/lib/client/utils.d.ts +96 -0
- package/lib/client/utils.js +137 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +13 -0
- package/lib/server/actions/formatter.d.ts +3 -0
- package/lib/server/actions/formatter.js +44 -0
- package/lib/server/actions/query.d.ts +86 -0
- package/lib/server/actions/query.js +326 -0
- package/lib/server/index.d.ts +1 -0
- package/lib/server/index.js +13 -0
- package/lib/server/plugin.d.ts +13 -0
- package/lib/server/plugin.js +64 -0
- package/package.json +23 -0
- package/server.d.ts +3 -0
- package/server.js +65 -0
- package/src/client/Settings.tsx +43 -0
- package/src/client/__tests__/chart-configure.test.tsx +14 -0
- package/src/client/__tests__/chart-library.test.ts +78 -0
- package/src/client/__tests__/chart-renderer.test.tsx +30 -0
- package/src/client/__tests__/hooks.test.ts +261 -0
- package/src/client/block/ChartBlock.tsx +22 -0
- package/src/client/block/ChartBlockDesigner.tsx +19 -0
- package/src/client/block/ChartBlockInitializer.tsx +83 -0
- package/src/client/block/ChartConfigure.tsx +450 -0
- package/src/client/block/formatters.ts +70 -0
- package/src/client/block/index.ts +4 -0
- package/src/client/block/schemas/configure.ts +474 -0
- package/src/client/block/transformers.ts +52 -0
- package/src/client/hooks.ts +239 -0
- package/src/client/index.tsx +41 -0
- package/src/client/locale/en-US.ts +23 -0
- package/src/client/locale/index.ts +19 -0
- package/src/client/locale/ja-JP.ts +1 -0
- package/src/client/locale/pt-BR.ts +23 -0
- package/src/client/locale/ru-RU.ts +1 -0
- package/src/client/locale/tr-TR.ts +1 -0
- package/src/client/locale/zh-CN.ts +71 -0
- package/src/client/renderer/ChartLibrary.tsx +178 -0
- package/src/client/renderer/ChartRenderer.tsx +201 -0
- package/src/client/renderer/ChartRendererProvider.tsx +58 -0
- package/src/client/renderer/index.ts +4 -0
- package/src/client/renderer/library/AntdLibrary.tsx +94 -0
- package/src/client/renderer/library/G2PlotLibrary.tsx +236 -0
- package/src/client/renderer/library/index.tsx +4 -0
- package/src/client/utils.ts +102 -0
- package/src/index.ts +1 -0
- package/src/server/__tests__/api.test.ts +105 -0
- package/src/server/__tests__/formatter.test.ts +49 -0
- package/src/server/__tests__/query.test.ts +220 -0
- package/src/server/actions/formatter.ts +49 -0
- package/src/server/actions/query.ts +285 -0
- package/src/server/collections/.gitkeep +0 -0
- package/src/server/index.ts +1 -0
- package/src/server/plugin.ts +37 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Context, Next } from '@nocobase/actions';
|
|
2
|
+
import { Cache } from '@nocobase/cache';
|
|
3
|
+
declare type MeasureProps = {
|
|
4
|
+
field: string | string[];
|
|
5
|
+
type?: string;
|
|
6
|
+
aggregation?: string;
|
|
7
|
+
alias?: string;
|
|
8
|
+
};
|
|
9
|
+
declare type DimensionProps = {
|
|
10
|
+
field: string | string[];
|
|
11
|
+
type?: string;
|
|
12
|
+
alias?: string;
|
|
13
|
+
format?: string;
|
|
14
|
+
};
|
|
15
|
+
declare type OrderProps = {
|
|
16
|
+
field: string | string[];
|
|
17
|
+
alias?: string;
|
|
18
|
+
order?: 'asc' | 'desc';
|
|
19
|
+
};
|
|
20
|
+
declare type QueryParams = Partial<{
|
|
21
|
+
uid: string;
|
|
22
|
+
collection: string;
|
|
23
|
+
measures: MeasureProps[];
|
|
24
|
+
dimensions: DimensionProps[];
|
|
25
|
+
orders: OrderProps[];
|
|
26
|
+
filter: any;
|
|
27
|
+
limit: number;
|
|
28
|
+
sql: {
|
|
29
|
+
fields?: string;
|
|
30
|
+
clauses?: string;
|
|
31
|
+
};
|
|
32
|
+
cache: {
|
|
33
|
+
enabled: boolean;
|
|
34
|
+
ttl: number;
|
|
35
|
+
};
|
|
36
|
+
refresh: boolean;
|
|
37
|
+
}>;
|
|
38
|
+
export declare const parseFieldAndAssociations: (ctx: Context, params: QueryParams) => {
|
|
39
|
+
where: any;
|
|
40
|
+
measures: {
|
|
41
|
+
field: any;
|
|
42
|
+
name: string;
|
|
43
|
+
type: any;
|
|
44
|
+
alias: string;
|
|
45
|
+
}[];
|
|
46
|
+
dimensions: {
|
|
47
|
+
field: any;
|
|
48
|
+
name: string;
|
|
49
|
+
type: any;
|
|
50
|
+
alias: string;
|
|
51
|
+
}[];
|
|
52
|
+
orders: {
|
|
53
|
+
field: any;
|
|
54
|
+
name: string;
|
|
55
|
+
type: any;
|
|
56
|
+
alias: string;
|
|
57
|
+
}[];
|
|
58
|
+
include: any[];
|
|
59
|
+
};
|
|
60
|
+
export declare const parseBuilder: (ctx: Context, builder: QueryParams) => {
|
|
61
|
+
queryParams: {
|
|
62
|
+
where: any;
|
|
63
|
+
attributes: any[];
|
|
64
|
+
include: any[];
|
|
65
|
+
group: any[];
|
|
66
|
+
order: any[];
|
|
67
|
+
limit: number;
|
|
68
|
+
raw: boolean;
|
|
69
|
+
};
|
|
70
|
+
fieldMap: {};
|
|
71
|
+
};
|
|
72
|
+
export declare const processData: (ctx: Context, data: any[], fieldMap: {
|
|
73
|
+
[source: string]: {
|
|
74
|
+
type?: string;
|
|
75
|
+
};
|
|
76
|
+
}) => any[];
|
|
77
|
+
export declare const queryData: (ctx: Context, builder: QueryParams) => Promise<any[]>;
|
|
78
|
+
export declare const cacheWrap: (cache: Cache, options: {
|
|
79
|
+
func: () => Promise<any>;
|
|
80
|
+
key: string;
|
|
81
|
+
ttl?: number;
|
|
82
|
+
useCache?: boolean;
|
|
83
|
+
refresh?: boolean;
|
|
84
|
+
}) => Promise<any>;
|
|
85
|
+
export declare const query: (ctx: Context, next: Next) => Promise<void>;
|
|
86
|
+
export {};
|
|
@@ -0,0 +1,326 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.queryData = exports.query = exports.processData = exports.parseFieldAndAssociations = exports.parseBuilder = exports.cacheWrap = void 0;
|
|
7
|
+
function _database() {
|
|
8
|
+
const data = require("@nocobase/database");
|
|
9
|
+
_database = function _database() {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
var _formatter = require("./formatter");
|
|
15
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
16
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
17
|
+
function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
18
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
|
|
19
|
+
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
|
|
20
|
+
function _toPropertyKey(arg) { var key = _toPrimitive(arg, "string"); return typeof key === "symbol" ? key : String(key); }
|
|
21
|
+
function _toPrimitive(input, hint) { if (typeof input !== "object" || input === null) return input; var prim = input[Symbol.toPrimitive]; if (prim !== undefined) { var res = prim.call(input, hint || "default"); if (typeof res !== "object") return res; throw new TypeError("@@toPrimitive must return a primitive value."); } return (hint === "string" ? String : Number)(input); }
|
|
22
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
23
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
24
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
25
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
|
|
26
|
+
function _iterableToArrayLimit(arr, i) { var _i = null == arr ? null : "undefined" != typeof Symbol && arr[Symbol.iterator] || arr["@@iterator"]; if (null != _i) { var _s, _e, _x, _r, _arr = [], _n = !0, _d = !1; try { if (_x = (_i = _i.call(arr)).next, 0 === i) { if (Object(_i) !== _i) return; _n = !1; } else for (; !(_n = (_s = _x.call(_i)).done) && (_arr.push(_s.value), _arr.length !== i); _n = !0); } catch (err) { _d = !0, _e = err; } finally { try { if (!_n && null != _i.return && (_r = _i.return(), Object(_r) !== _r)) return; } finally { if (_d) throw _e; } } return _arr; } }
|
|
27
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
28
|
+
const parseFieldAndAssociations = (ctx, params) => {
|
|
29
|
+
const collectionName = params.collection,
|
|
30
|
+
measures = params.measures,
|
|
31
|
+
dimensions = params.dimensions,
|
|
32
|
+
orders = params.orders,
|
|
33
|
+
filter = params.filter;
|
|
34
|
+
const collection = ctx.db.getCollection(collectionName);
|
|
35
|
+
const fields = collection.fields;
|
|
36
|
+
const underscored = ctx.db.options.underscored;
|
|
37
|
+
const models = {};
|
|
38
|
+
const parseField = selected => {
|
|
39
|
+
var _fields$get;
|
|
40
|
+
let target;
|
|
41
|
+
let name;
|
|
42
|
+
if (!Array.isArray(selected.field)) {
|
|
43
|
+
name = selected.field;
|
|
44
|
+
} else if (selected.field.length === 1) {
|
|
45
|
+
name = selected.field[0];
|
|
46
|
+
} else if (selected.field.length > 1) {
|
|
47
|
+
var _selected$field = _slicedToArray(selected.field, 2);
|
|
48
|
+
target = _selected$field[0];
|
|
49
|
+
name = _selected$field[1];
|
|
50
|
+
}
|
|
51
|
+
let field = underscored ? (0, _database().snakeCase)(name) : name;
|
|
52
|
+
let type = (_fields$get = fields.get(name)) === null || _fields$get === void 0 ? void 0 : _fields$get.type;
|
|
53
|
+
if (target) {
|
|
54
|
+
var _fields$get2;
|
|
55
|
+
field = `${target}.${field}`;
|
|
56
|
+
name = `${target}.${name}`;
|
|
57
|
+
type = (_fields$get2 = fields.get(target)) === null || _fields$get2 === void 0 ? void 0 : _fields$get2.type;
|
|
58
|
+
if (!models[target]) {
|
|
59
|
+
models[target] = {
|
|
60
|
+
type
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
field = `${collectionName}.${field}`;
|
|
65
|
+
}
|
|
66
|
+
return _objectSpread(_objectSpread({}, selected), {}, {
|
|
67
|
+
field,
|
|
68
|
+
name,
|
|
69
|
+
type,
|
|
70
|
+
alias: selected.alias || name
|
|
71
|
+
});
|
|
72
|
+
};
|
|
73
|
+
const parsedMeasures = (measures === null || measures === void 0 ? void 0 : measures.map(parseField)) || [];
|
|
74
|
+
const parsedDimensions = (dimensions === null || dimensions === void 0 ? void 0 : dimensions.map(parseField)) || [];
|
|
75
|
+
const parsedOrders = (orders === null || orders === void 0 ? void 0 : orders.map(parseField)) || [];
|
|
76
|
+
const include = Object.entries(models).map(([target, {
|
|
77
|
+
type
|
|
78
|
+
}]) => _objectSpread({
|
|
79
|
+
association: target,
|
|
80
|
+
attributes: []
|
|
81
|
+
}, type === 'belongsToMany' ? {
|
|
82
|
+
through: {
|
|
83
|
+
attributes: []
|
|
84
|
+
}
|
|
85
|
+
} : {}));
|
|
86
|
+
const filterParser = new (_database().FilterParser)(filter, {
|
|
87
|
+
collection
|
|
88
|
+
});
|
|
89
|
+
const _filterParser$toSeque = filterParser.toSequelizeParams(),
|
|
90
|
+
where = _filterParser$toSeque.where,
|
|
91
|
+
filterInclude = _filterParser$toSeque.include;
|
|
92
|
+
const parsedFilterInclude = filterInclude === null || filterInclude === void 0 ? void 0 : filterInclude.map(item => {
|
|
93
|
+
var _fields$get3;
|
|
94
|
+
if (((_fields$get3 = fields.get(item.association)) === null || _fields$get3 === void 0 ? void 0 : _fields$get3.type) === 'belongsToMany') {
|
|
95
|
+
item.through = {
|
|
96
|
+
attributes: []
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
return item;
|
|
100
|
+
});
|
|
101
|
+
return {
|
|
102
|
+
where,
|
|
103
|
+
measures: parsedMeasures,
|
|
104
|
+
dimensions: parsedDimensions,
|
|
105
|
+
orders: parsedOrders,
|
|
106
|
+
include: [...include, ...(parsedFilterInclude || [])]
|
|
107
|
+
};
|
|
108
|
+
};
|
|
109
|
+
exports.parseFieldAndAssociations = parseFieldAndAssociations;
|
|
110
|
+
const parseBuilder = (ctx, builder) => {
|
|
111
|
+
const sequelize = ctx.db.sequelize;
|
|
112
|
+
const limit = builder.limit;
|
|
113
|
+
const _parseFieldAndAssocia = parseFieldAndAssociations(ctx, builder),
|
|
114
|
+
measures = _parseFieldAndAssocia.measures,
|
|
115
|
+
dimensions = _parseFieldAndAssocia.dimensions,
|
|
116
|
+
orders = _parseFieldAndAssocia.orders,
|
|
117
|
+
include = _parseFieldAndAssocia.include,
|
|
118
|
+
where = _parseFieldAndAssocia.where;
|
|
119
|
+
const attributes = [];
|
|
120
|
+
const group = [];
|
|
121
|
+
const order = [];
|
|
122
|
+
const fieldMap = {};
|
|
123
|
+
let hasAgg = false;
|
|
124
|
+
measures.forEach(measure => {
|
|
125
|
+
const field = measure.field,
|
|
126
|
+
aggregation = measure.aggregation,
|
|
127
|
+
alias = measure.alias;
|
|
128
|
+
const attribute = [];
|
|
129
|
+
const col = sequelize.col(field);
|
|
130
|
+
if (aggregation) {
|
|
131
|
+
hasAgg = true;
|
|
132
|
+
attribute.push(sequelize.fn(aggregation, col));
|
|
133
|
+
} else {
|
|
134
|
+
attribute.push(col);
|
|
135
|
+
}
|
|
136
|
+
if (alias) {
|
|
137
|
+
attribute.push(alias);
|
|
138
|
+
}
|
|
139
|
+
attributes.push(attribute.length > 1 ? attribute : attribute[0]);
|
|
140
|
+
fieldMap[alias || field] = measure;
|
|
141
|
+
});
|
|
142
|
+
dimensions.forEach(dimension => {
|
|
143
|
+
const field = dimension.field,
|
|
144
|
+
format = dimension.format,
|
|
145
|
+
alias = dimension.alias,
|
|
146
|
+
type = dimension.type;
|
|
147
|
+
const attribute = [];
|
|
148
|
+
const col = sequelize.col(field);
|
|
149
|
+
if (format) {
|
|
150
|
+
attribute.push((0, _formatter.formatter)(sequelize, type, field, format));
|
|
151
|
+
} else {
|
|
152
|
+
attribute.push(col);
|
|
153
|
+
}
|
|
154
|
+
if (alias) {
|
|
155
|
+
attribute.push(alias);
|
|
156
|
+
}
|
|
157
|
+
attributes.push(attribute.length > 1 ? attribute : attribute[0]);
|
|
158
|
+
if (hasAgg) {
|
|
159
|
+
group.push(attribute[0]);
|
|
160
|
+
}
|
|
161
|
+
fieldMap[alias || field] = dimension;
|
|
162
|
+
});
|
|
163
|
+
orders.forEach(item => {
|
|
164
|
+
const name = hasAgg ? sequelize.literal(`"${item.alias}"`) : sequelize.col(item.field);
|
|
165
|
+
order.push([name, item.order || 'ASC']);
|
|
166
|
+
});
|
|
167
|
+
return {
|
|
168
|
+
queryParams: {
|
|
169
|
+
where,
|
|
170
|
+
attributes,
|
|
171
|
+
include,
|
|
172
|
+
group,
|
|
173
|
+
order,
|
|
174
|
+
limit: limit > 2000 ? 2000 : limit,
|
|
175
|
+
raw: true
|
|
176
|
+
},
|
|
177
|
+
fieldMap
|
|
178
|
+
};
|
|
179
|
+
};
|
|
180
|
+
exports.parseBuilder = parseBuilder;
|
|
181
|
+
const processData = (ctx, data, fieldMap) => {
|
|
182
|
+
const sequelize = ctx.db.sequelize;
|
|
183
|
+
const dialect = sequelize.getDialect();
|
|
184
|
+
switch (dialect) {
|
|
185
|
+
case 'postgres':
|
|
186
|
+
// https://github.com/sequelize/sequelize/issues/4550
|
|
187
|
+
return data.map(record => {
|
|
188
|
+
const result = {};
|
|
189
|
+
Object.entries(record).forEach(([key, value]) => {
|
|
190
|
+
const _ref = fieldMap[key] || {},
|
|
191
|
+
type = _ref.type;
|
|
192
|
+
switch (type) {
|
|
193
|
+
case 'bigInt':
|
|
194
|
+
case 'integer':
|
|
195
|
+
case 'float':
|
|
196
|
+
case 'double':
|
|
197
|
+
value = Number(value);
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
result[key] = value;
|
|
201
|
+
});
|
|
202
|
+
return result;
|
|
203
|
+
});
|
|
204
|
+
default:
|
|
205
|
+
return data;
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
exports.processData = processData;
|
|
209
|
+
const queryData = /*#__PURE__*/function () {
|
|
210
|
+
var _ref2 = _asyncToGenerator(function* (ctx, builder) {
|
|
211
|
+
const collection = builder.collection,
|
|
212
|
+
measures = builder.measures,
|
|
213
|
+
dimensions = builder.dimensions,
|
|
214
|
+
orders = builder.orders,
|
|
215
|
+
filter = builder.filter,
|
|
216
|
+
limit = builder.limit,
|
|
217
|
+
sql = builder.sql;
|
|
218
|
+
const model = ctx.db.getModel(collection);
|
|
219
|
+
const _parseBuilder = parseBuilder(ctx, {
|
|
220
|
+
collection,
|
|
221
|
+
measures,
|
|
222
|
+
dimensions,
|
|
223
|
+
orders,
|
|
224
|
+
filter,
|
|
225
|
+
limit
|
|
226
|
+
}),
|
|
227
|
+
queryParams = _parseBuilder.queryParams,
|
|
228
|
+
fieldMap = _parseBuilder.fieldMap;
|
|
229
|
+
const data = yield model.findAll(queryParams);
|
|
230
|
+
return processData(ctx, data, fieldMap);
|
|
231
|
+
// if (!sql) {
|
|
232
|
+
// return await repository.find(parseBuilder(ctx, { collection, measures, dimensions, orders, filter, limit }));
|
|
233
|
+
// }
|
|
234
|
+
// const statement = `SELECT ${sql.fields} FROM ${collection} ${sql.clauses}`;
|
|
235
|
+
// const [data] = await ctx.db.sequelize.query(statement);
|
|
236
|
+
// return data;
|
|
237
|
+
});
|
|
238
|
+
return function queryData(_x2, _x3) {
|
|
239
|
+
return _ref2.apply(this, arguments);
|
|
240
|
+
};
|
|
241
|
+
}();
|
|
242
|
+
exports.queryData = queryData;
|
|
243
|
+
const cacheWrap = /*#__PURE__*/function () {
|
|
244
|
+
var _ref3 = _asyncToGenerator(function* (cache, options) {
|
|
245
|
+
const func = options.func,
|
|
246
|
+
key = options.key,
|
|
247
|
+
ttl = options.ttl,
|
|
248
|
+
useCache = options.useCache,
|
|
249
|
+
refresh = options.refresh;
|
|
250
|
+
if (useCache && !refresh) {
|
|
251
|
+
const data = yield cache.get(key);
|
|
252
|
+
if (data) {
|
|
253
|
+
return data;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
const data = yield func();
|
|
257
|
+
if (useCache) {
|
|
258
|
+
yield cache.set(key, data, ttl);
|
|
259
|
+
}
|
|
260
|
+
return data;
|
|
261
|
+
});
|
|
262
|
+
return function cacheWrap(_x4, _x5) {
|
|
263
|
+
return _ref3.apply(this, arguments);
|
|
264
|
+
};
|
|
265
|
+
}();
|
|
266
|
+
exports.cacheWrap = cacheWrap;
|
|
267
|
+
const query = /*#__PURE__*/function () {
|
|
268
|
+
var _ref4 = _asyncToGenerator(function* (ctx, next) {
|
|
269
|
+
const _ctx$action$params$va = ctx.action.params.values,
|
|
270
|
+
uid = _ctx$action$params$va.uid,
|
|
271
|
+
collection = _ctx$action$params$va.collection,
|
|
272
|
+
measures = _ctx$action$params$va.measures,
|
|
273
|
+
dimensions = _ctx$action$params$va.dimensions,
|
|
274
|
+
orders = _ctx$action$params$va.orders,
|
|
275
|
+
filter = _ctx$action$params$va.filter,
|
|
276
|
+
limit = _ctx$action$params$va.limit,
|
|
277
|
+
sql = _ctx$action$params$va.sql,
|
|
278
|
+
cacheConfig = _ctx$action$params$va.cache,
|
|
279
|
+
refresh = _ctx$action$params$va.refresh;
|
|
280
|
+
const roleName = ctx.state.currentRole || 'anonymous';
|
|
281
|
+
const can = ctx.app.acl.can({
|
|
282
|
+
role: roleName,
|
|
283
|
+
resource: collection,
|
|
284
|
+
action: 'list'
|
|
285
|
+
});
|
|
286
|
+
if (!can && roleName !== 'root') {
|
|
287
|
+
ctx.throw(403, 'No permissions');
|
|
288
|
+
}
|
|
289
|
+
const plugin = ctx.app.getPlugin('data-visualization');
|
|
290
|
+
const cache = plugin.cache;
|
|
291
|
+
const useCache = (cacheConfig === null || cacheConfig === void 0 ? void 0 : cacheConfig.enabled) && uid;
|
|
292
|
+
try {
|
|
293
|
+
ctx.body = yield cacheWrap(cache, {
|
|
294
|
+
func: function () {
|
|
295
|
+
var _func = _asyncToGenerator(function* () {
|
|
296
|
+
return yield queryData(ctx, {
|
|
297
|
+
collection,
|
|
298
|
+
measures,
|
|
299
|
+
dimensions,
|
|
300
|
+
orders,
|
|
301
|
+
filter,
|
|
302
|
+
limit,
|
|
303
|
+
sql
|
|
304
|
+
});
|
|
305
|
+
});
|
|
306
|
+
function func() {
|
|
307
|
+
return _func.apply(this, arguments);
|
|
308
|
+
}
|
|
309
|
+
return func;
|
|
310
|
+
}(),
|
|
311
|
+
key: uid,
|
|
312
|
+
ttl: (cacheConfig === null || cacheConfig === void 0 ? void 0 : cacheConfig.ttl) || 30,
|
|
313
|
+
useCache: useCache ? true : false,
|
|
314
|
+
refresh
|
|
315
|
+
});
|
|
316
|
+
} catch (err) {
|
|
317
|
+
ctx.app.logger.error('charts query: ', err);
|
|
318
|
+
ctx.throw(500, err);
|
|
319
|
+
}
|
|
320
|
+
yield next();
|
|
321
|
+
});
|
|
322
|
+
return function query(_x6, _x7) {
|
|
323
|
+
return _ref4.apply(this, arguments);
|
|
324
|
+
};
|
|
325
|
+
}();
|
|
326
|
+
exports.query = query;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './plugin';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "default", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function get() {
|
|
9
|
+
return _plugin.default;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
var _plugin = _interopRequireDefault(require("./plugin"));
|
|
13
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Cache } from '@nocobase/cache';
|
|
2
|
+
import { InstallOptions, Plugin } from '@nocobase/server';
|
|
3
|
+
export declare class DataVisualizationPlugin extends Plugin {
|
|
4
|
+
cache: Cache;
|
|
5
|
+
afterAdd(): void;
|
|
6
|
+
beforeLoad(): void;
|
|
7
|
+
load(): Promise<void>;
|
|
8
|
+
install(options?: InstallOptions): Promise<void>;
|
|
9
|
+
afterEnable(): Promise<void>;
|
|
10
|
+
afterDisable(): Promise<void>;
|
|
11
|
+
remove(): Promise<void>;
|
|
12
|
+
}
|
|
13
|
+
export default DataVisualizationPlugin;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.default = exports.DataVisualizationPlugin = void 0;
|
|
7
|
+
function _cache() {
|
|
8
|
+
const data = require("@nocobase/cache");
|
|
9
|
+
_cache = function _cache() {
|
|
10
|
+
return data;
|
|
11
|
+
};
|
|
12
|
+
return data;
|
|
13
|
+
}
|
|
14
|
+
function _server() {
|
|
15
|
+
const data = require("@nocobase/server");
|
|
16
|
+
_server = function _server() {
|
|
17
|
+
return data;
|
|
18
|
+
};
|
|
19
|
+
return data;
|
|
20
|
+
}
|
|
21
|
+
var _query = require("./actions/query");
|
|
22
|
+
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) { try { var info = gen[key](arg); var value = info.value; } catch (error) { reject(error); return; } if (info.done) { resolve(value); } else { Promise.resolve(value).then(_next, _throw); } }
|
|
23
|
+
function _asyncToGenerator(fn) { return function () { var self = this, args = arguments; return new Promise(function (resolve, reject) { var gen = fn.apply(self, args); function _next(value) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value); } function _throw(err) { asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err); } _next(undefined); }); }; }
|
|
24
|
+
class DataVisualizationPlugin extends _server().Plugin {
|
|
25
|
+
constructor(...args) {
|
|
26
|
+
super(...args);
|
|
27
|
+
this.cache = void 0;
|
|
28
|
+
}
|
|
29
|
+
afterAdd() {}
|
|
30
|
+
beforeLoad() {
|
|
31
|
+
this.app.resource({
|
|
32
|
+
name: 'charts',
|
|
33
|
+
actions: {
|
|
34
|
+
query: _query.query
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
this.app.acl.allow('charts', 'query', 'loggedIn');
|
|
38
|
+
}
|
|
39
|
+
load() {
|
|
40
|
+
var _this = this;
|
|
41
|
+
return _asyncToGenerator(function* () {
|
|
42
|
+
_this.cache = (0, _cache().createCache)({
|
|
43
|
+
ttl: 30,
|
|
44
|
+
max: 1000,
|
|
45
|
+
store: 'memory'
|
|
46
|
+
});
|
|
47
|
+
})();
|
|
48
|
+
}
|
|
49
|
+
install(options) {
|
|
50
|
+
return _asyncToGenerator(function* () {})();
|
|
51
|
+
}
|
|
52
|
+
afterEnable() {
|
|
53
|
+
return _asyncToGenerator(function* () {})();
|
|
54
|
+
}
|
|
55
|
+
afterDisable() {
|
|
56
|
+
return _asyncToGenerator(function* () {})();
|
|
57
|
+
}
|
|
58
|
+
remove() {
|
|
59
|
+
return _asyncToGenerator(function* () {})();
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.DataVisualizationPlugin = DataVisualizationPlugin;
|
|
63
|
+
var _default = DataVisualizationPlugin;
|
|
64
|
+
exports.default = _default;
|
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nocobase/plugin-data-visualization",
|
|
3
|
+
"version": "0.10.1-alpha.1",
|
|
4
|
+
"main": "lib/server/index.js",
|
|
5
|
+
"devDependencies": {
|
|
6
|
+
"@nocobase/actions": "0.10.1-alpha.1",
|
|
7
|
+
"@nocobase/cache": "0.10.1-alpha.1",
|
|
8
|
+
"@nocobase/server": "0.10.1-alpha.1",
|
|
9
|
+
"@nocobase/test": "0.10.1-alpha.1",
|
|
10
|
+
"@testing-library/react": "^14.0.0",
|
|
11
|
+
"lodash": "^4.17.21"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@ant-design/plots": "^1.2.5",
|
|
15
|
+
"dayjs": "^1.11.7",
|
|
16
|
+
"react-error-boundary": "^4.0.4"
|
|
17
|
+
},
|
|
18
|
+
"displayName": "Data Visualization",
|
|
19
|
+
"displayName.zh-CN": "数据可视化",
|
|
20
|
+
"description": "Provides business intelligence and data visualization features",
|
|
21
|
+
"description.zh-CN": "提供BI面板和数据可视化功能",
|
|
22
|
+
"gitHead": "8f415f5e0ee2e72d681f9ab16af5911b52c374a9"
|
|
23
|
+
}
|
package/server.d.ts
ADDED
package/server.js
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function _getRequireWildcardCache(nodeInterop) {
|
|
4
|
+
if (typeof WeakMap !== 'function') return null;
|
|
5
|
+
var cacheBabelInterop = new WeakMap();
|
|
6
|
+
var cacheNodeInterop = new WeakMap();
|
|
7
|
+
return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) {
|
|
8
|
+
return nodeInterop ? cacheNodeInterop : cacheBabelInterop;
|
|
9
|
+
})(nodeInterop);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function _interopRequireWildcard(obj, nodeInterop) {
|
|
13
|
+
if (!nodeInterop && obj && obj.__esModule) {
|
|
14
|
+
return obj;
|
|
15
|
+
}
|
|
16
|
+
if (obj === null || (typeof obj !== 'object' && typeof obj !== 'function')) {
|
|
17
|
+
return { default: obj };
|
|
18
|
+
}
|
|
19
|
+
var cache = _getRequireWildcardCache(nodeInterop);
|
|
20
|
+
if (cache && cache.has(obj)) {
|
|
21
|
+
return cache.get(obj);
|
|
22
|
+
}
|
|
23
|
+
var newObj = {};
|
|
24
|
+
var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor;
|
|
25
|
+
for (var key in obj) {
|
|
26
|
+
if (key !== 'default' && Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
27
|
+
var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null;
|
|
28
|
+
if (desc && (desc.get || desc.set)) {
|
|
29
|
+
Object.defineProperty(newObj, key, desc);
|
|
30
|
+
} else {
|
|
31
|
+
newObj[key] = obj[key];
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
newObj.default = obj;
|
|
36
|
+
if (cache) {
|
|
37
|
+
cache.set(obj, newObj);
|
|
38
|
+
}
|
|
39
|
+
return newObj;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
var _index = _interopRequireWildcard(require('./lib/server'));
|
|
43
|
+
|
|
44
|
+
Object.defineProperty(exports, '__esModule', {
|
|
45
|
+
value: true,
|
|
46
|
+
});
|
|
47
|
+
var _exportNames = {};
|
|
48
|
+
Object.defineProperty(exports, 'default', {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function get() {
|
|
51
|
+
return _index.default;
|
|
52
|
+
},
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
Object.keys(_index).forEach(function (key) {
|
|
56
|
+
if (key === 'default' || key === '__esModule') return;
|
|
57
|
+
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
|
|
58
|
+
if (key in exports && exports[key] === _index[key]) return;
|
|
59
|
+
Object.defineProperty(exports, key, {
|
|
60
|
+
enumerable: true,
|
|
61
|
+
get: function get() {
|
|
62
|
+
return _index[key];
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
});
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { CheckOutlined } from '@ant-design/icons';
|
|
2
|
+
import { css } from '@emotion/css';
|
|
3
|
+
import { Form, FormItem } from '@formily/antd';
|
|
4
|
+
import { Button, Card } from 'antd';
|
|
5
|
+
import cls from 'classnames';
|
|
6
|
+
import React, { useContext } from 'react';
|
|
7
|
+
import { useChartsTranslation } from './locale';
|
|
8
|
+
import { ChartLibraryContext, useToggleChartLibrary } from './renderer';
|
|
9
|
+
|
|
10
|
+
export const Settings = () => {
|
|
11
|
+
const { t } = useChartsTranslation();
|
|
12
|
+
const libraries = useContext(ChartLibraryContext);
|
|
13
|
+
const { toggle } = useToggleChartLibrary();
|
|
14
|
+
const list = Object.entries(libraries).map(([library, { enabled }]) => {
|
|
15
|
+
return (
|
|
16
|
+
<Button
|
|
17
|
+
key={library}
|
|
18
|
+
icon={enabled ? <CheckOutlined /> : ''}
|
|
19
|
+
className={cls(
|
|
20
|
+
css`
|
|
21
|
+
margin: 8px 8px 8px 0;
|
|
22
|
+
`,
|
|
23
|
+
enabled
|
|
24
|
+
? css`
|
|
25
|
+
color: #40a9ff;
|
|
26
|
+
border-color: #40a9ff;
|
|
27
|
+
`
|
|
28
|
+
: '',
|
|
29
|
+
)}
|
|
30
|
+
onClick={() => toggle(library)}
|
|
31
|
+
>
|
|
32
|
+
{library}
|
|
33
|
+
</Button>
|
|
34
|
+
);
|
|
35
|
+
});
|
|
36
|
+
return (
|
|
37
|
+
<Card>
|
|
38
|
+
<Form layout="vertical">
|
|
39
|
+
<FormItem label={t('Enabled Chart Library')}>{list}</FormItem>
|
|
40
|
+
</Form>
|
|
41
|
+
</Card>
|
|
42
|
+
);
|
|
43
|
+
};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { vi } from 'vitest';
|
|
2
|
+
|
|
3
|
+
describe('ChartConfigure', () => {
|
|
4
|
+
afterEach(() => {
|
|
5
|
+
vi.restoreAllMocks();
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
it('should render correctly', () => {
|
|
9
|
+
// vi.spyOn(client, 'useDesignable').mockReturnValue({} as any);
|
|
10
|
+
// render(<ChartConfigure insert={(schema, options) => {}} />);
|
|
11
|
+
// const modal = document.querySelector('.ant-modal-content') as HTMLInputElement;
|
|
12
|
+
// expect(modal).toBeInTheDocument();
|
|
13
|
+
});
|
|
14
|
+
});
|