@vuu-ui/vuu-data-test 4.0.0-alpha.3 → 4.0.0-alpha.30
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/README.md +38 -0
- package/package.json +10 -9
- package/src/TickingArrayDataSource.js +7 -2
- package/src/basket/BasketModule.js +105 -40
- package/src/basket/basket-schemas.js +16 -0
- package/src/basket/reference-data/constituent-data.js +2 -0
- package/src/basket/reference-data/constituents.js +6 -74
- package/src/basket/reference-data/prices.js +9 -3
- package/src/core/filter/PermissionFilter.js +60 -0
- package/src/core/filter/PermissionFilteredTable.js +59 -0
- package/src/core/module/VuuModule.js +30 -4
- package/src/core/table/TableContainer.js +51 -8
- package/src/core/user/CurrentUser.js +13 -0
- package/src/index.js +4 -0
- package/src/local-datasource-provider/LocalDatasourceProvider.js +64 -44
- package/src/module-admin/ModuleAdminModule.js +84 -20
- package/src/module-admin/module-admin-schemas.js +5 -9
- package/src/module-admin/snapshot-projection.js +3 -31
- package/src/notifications/NotificationModule.js +131 -0
- package/src/notifications/NotificationsSchema.js +52 -0
- package/src/notifications/index.js +6 -0
- package/src/notifications/simulated/DismissNotificationRpcHandler.js +36 -0
- package/src/notifications/simulated/SimulatedNotificationsModule.js +18 -0
- package/src/notifications/simulated/SimulatedNotificationsProvider.js +151 -0
- package/src/notifications/simulated/notificationsModule.js +3 -0
- package/src/user-admin/UserAdminModule.js +163 -8
- package/src/user-admin/initialSnapshot.js +49 -65
- package/types/TickingArrayDataSource.d.ts +1 -1
- package/types/basket/BasketModule.d.ts +2 -0
- package/types/basket/reference-data/constituents.d.ts +3 -3
- package/types/basket/reference-data/prices.d.ts +2 -1
- package/types/core/filter/PermissionFilter.d.ts +41 -0
- package/types/core/filter/PermissionFilteredTable.d.ts +24 -0
- package/types/core/module/VuuModule.d.ts +19 -0
- package/types/core/table/TableContainer.d.ts +1 -1
- package/types/core/user/CurrentUser.d.ts +14 -0
- package/types/index.d.ts +4 -0
- package/types/local-datasource-provider/LocalDatasourceProvider.d.ts +18 -2
- package/types/module-admin/ModuleAdminModule.d.ts +12 -3
- package/types/module-admin/index.d.ts +1 -1
- package/types/module-admin/snapshot-projection.d.ts +3 -4
- package/types/notifications/NotificationModule.d.ts +60 -0
- package/types/notifications/NotificationsSchema.d.ts +20 -0
- package/types/notifications/index.d.ts +6 -0
- package/types/notifications/simulated/DismissNotificationRpcHandler.d.ts +8 -0
- package/types/notifications/simulated/SimulatedNotificationsModule.d.ts +9 -0
- package/types/notifications/simulated/SimulatedNotificationsProvider.d.ts +21 -0
- package/types/notifications/simulated/notificationsModule.d.ts +5 -0
- package/types/user-admin/UserAdminModule.d.ts +5 -1
- package/src/basket/reference-data/ftse100.js +0 -686
- package/src/basket/reference-data/hsi.js +0 -1047
- package/src/basket/reference-data/nasdaq100.js +0 -812
- package/src/basket/reference-data/sp500.js +0 -315
|
@@ -1,76 +1,8 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const [ric, name, lastTrade, change, volume] = row;
|
|
8
|
-
const basketId = ".FTSE100";
|
|
9
|
-
const side = "BUY";
|
|
10
|
-
const weighting = 1;
|
|
11
|
-
basketConstituentData.push([
|
|
12
|
-
basketId,
|
|
13
|
-
change,
|
|
14
|
-
name,
|
|
15
|
-
lastTrade,
|
|
16
|
-
ric,
|
|
17
|
-
`${ric}-${basketId}`,
|
|
18
|
-
side,
|
|
19
|
-
volume,
|
|
20
|
-
weighting
|
|
21
|
-
]);
|
|
22
|
-
}
|
|
23
|
-
for (const row of hsi){
|
|
24
|
-
const [name, ric, lastTrade, change, , volume] = row;
|
|
25
|
-
const basketId = ".HSI";
|
|
26
|
-
const side = "BUY";
|
|
27
|
-
const weighting = 1;
|
|
28
|
-
basketConstituentData.push([
|
|
29
|
-
basketId,
|
|
30
|
-
change,
|
|
31
|
-
name,
|
|
32
|
-
lastTrade,
|
|
33
|
-
ric,
|
|
34
|
-
`${ric}-${basketId}`,
|
|
35
|
-
side,
|
|
36
|
-
volume,
|
|
37
|
-
weighting
|
|
38
|
-
]);
|
|
39
|
-
}
|
|
40
|
-
for (const row of nasdaq100){
|
|
41
|
-
const [name, ric, weighting, lastTrade, change] = row;
|
|
42
|
-
const basketId = ".NASDAQ100";
|
|
43
|
-
const side = "BUY";
|
|
44
|
-
const volume = 1000;
|
|
45
|
-
basketConstituentData.push([
|
|
46
|
-
basketId,
|
|
47
|
-
change,
|
|
48
|
-
name,
|
|
49
|
-
lastTrade,
|
|
50
|
-
ric,
|
|
51
|
-
`${ric}-${basketId}`,
|
|
52
|
-
side,
|
|
53
|
-
volume,
|
|
54
|
-
weighting
|
|
55
|
-
]);
|
|
56
|
-
}
|
|
57
|
-
for (const row of sp500){
|
|
58
|
-
const [name, ric, weighting, , change] = row;
|
|
59
|
-
const basketId = ".SP500";
|
|
60
|
-
const side = "BUY";
|
|
61
|
-
const volume = 1000;
|
|
62
|
-
const lastTrade = 0;
|
|
63
|
-
basketConstituentData.push([
|
|
64
|
-
basketId,
|
|
65
|
-
change,
|
|
66
|
-
name,
|
|
67
|
-
lastTrade,
|
|
68
|
-
ric,
|
|
69
|
-
`${ric}-${basketId}`,
|
|
70
|
-
side,
|
|
71
|
-
volume,
|
|
72
|
-
weighting
|
|
73
|
-
]);
|
|
74
|
-
}
|
|
1
|
+
import constituent_data from "./constituent-data.js";
|
|
2
|
+
import { schemas } from "../basket-schemas.js";
|
|
3
|
+
const basketConstituentData = constituent_data.map((constituent)=>{
|
|
4
|
+
const values = constituent;
|
|
5
|
+
return schemas.basketConstituent.columns.map(({ name })=>values[name]);
|
|
6
|
+
});
|
|
75
7
|
var constituents = basketConstituentData;
|
|
76
8
|
export default constituents;
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { buildDataColumnMap } from "../../Table.js";
|
|
1
|
+
import { Table, buildDataColumnMap } from "../../Table.js";
|
|
2
2
|
import { BaseUpdateGenerator } from "../../UpdateGenerator.js";
|
|
3
3
|
import { schemas } from "../../simul/simul-schemas.js";
|
|
4
4
|
import constituents from "./constituents.js";
|
|
5
5
|
import { initBidAsk, nextRandomDouble, random } from "../../data-utils.js";
|
|
6
|
-
import TableContainer from "../../core/table/TableContainer.js";
|
|
7
6
|
const { bid: prices_bid, bidSize: prices_bidSize, ask: prices_ask, askSize: prices_askSize, last: prices_last } = buildDataColumnMap(schemas, "prices");
|
|
8
7
|
const pricesUpdateGenerator = new BaseUpdateGenerator({
|
|
9
8
|
bid: prices_bid,
|
|
@@ -13,9 +12,12 @@ const pricesUpdateGenerator = new BaseUpdateGenerator({
|
|
|
13
12
|
last: prices_last
|
|
14
13
|
});
|
|
15
14
|
const prices = [];
|
|
15
|
+
const seen = new Set();
|
|
16
16
|
for (const [, , , lastTrade, ric] of constituents){
|
|
17
|
+
if (seen.has(String(ric))) continue;
|
|
17
18
|
const priceSeed = parseFloat(String(lastTrade));
|
|
18
19
|
if (!isNaN(priceSeed)) {
|
|
20
|
+
seen.add(String(ric));
|
|
19
21
|
const [bid, ask] = initBidAsk(5, nextRandomDouble);
|
|
20
22
|
const askSize = random(1000, 3000);
|
|
21
23
|
const bidSize = random(1000, 3000);
|
|
@@ -38,6 +40,10 @@ for (const [, , , lastTrade, ric] of constituents){
|
|
|
38
40
|
]);
|
|
39
41
|
}
|
|
40
42
|
}
|
|
41
|
-
const pricesTable =
|
|
43
|
+
const pricesTable = new Table(schemas.prices, prices, buildDataColumnMap(schemas, "prices"), pricesUpdateGenerator);
|
|
44
|
+
pricesUpdateGenerator.setRange({
|
|
45
|
+
from: 0,
|
|
46
|
+
to: prices.length
|
|
47
|
+
});
|
|
42
48
|
var reference_data_prices = pricesTable;
|
|
43
49
|
export default reference_data_prices;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
const allowAll = ()=>true;
|
|
2
|
+
const denyAll = ()=>false;
|
|
3
|
+
const AllowAllPermissionFilter = {
|
|
4
|
+
createPredicate: ()=>allowAll
|
|
5
|
+
};
|
|
6
|
+
const DenyAllPermissionFilter = {
|
|
7
|
+
createPredicate: ()=>denyAll
|
|
8
|
+
};
|
|
9
|
+
class RowPermissionFilter {
|
|
10
|
+
rowPredicate;
|
|
11
|
+
constructor(rowPredicate){
|
|
12
|
+
this.rowPredicate = rowPredicate;
|
|
13
|
+
}
|
|
14
|
+
createPredicate(columnMap) {
|
|
15
|
+
let currentRow = [];
|
|
16
|
+
const rowData = {
|
|
17
|
+
get: (columnName)=>{
|
|
18
|
+
const idx = columnMap[columnName];
|
|
19
|
+
return void 0 === idx ? void 0 : currentRow[idx];
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
return (row)=>{
|
|
23
|
+
currentRow = row;
|
|
24
|
+
return this.rowPredicate(rowData);
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
class ContainsPermissionFilter {
|
|
29
|
+
columnName;
|
|
30
|
+
allowedValues;
|
|
31
|
+
constructor(columnName, allowedValues){
|
|
32
|
+
this.columnName = columnName;
|
|
33
|
+
this.allowedValues = allowedValues;
|
|
34
|
+
}
|
|
35
|
+
createPredicate(columnMap) {
|
|
36
|
+
const idx = columnMap[this.columnName];
|
|
37
|
+
if (void 0 === idx || 0 === this.allowedValues.size) return denyAll;
|
|
38
|
+
const { allowedValues } = this;
|
|
39
|
+
return (row)=>{
|
|
40
|
+
const value = row[idx];
|
|
41
|
+
return null != value && allowedValues.has(String(value));
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
class PermissionFilterChain {
|
|
46
|
+
filters;
|
|
47
|
+
constructor(filters){
|
|
48
|
+
this.filters = filters;
|
|
49
|
+
}
|
|
50
|
+
createPredicate(columnMap) {
|
|
51
|
+
const predicates = this.filters.map((f)=>f.createPredicate(columnMap));
|
|
52
|
+
return (row)=>predicates.every((predicate)=>predicate(row));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function PermissionFilter(arg, allowedValues) {
|
|
56
|
+
if ("function" == typeof arg) return new RowPermissionFilter(arg);
|
|
57
|
+
if ("string" == typeof arg) return new ContainsPermissionFilter(arg, allowedValues ?? new Set());
|
|
58
|
+
return new PermissionFilterChain(Array.from(arg));
|
|
59
|
+
}
|
|
60
|
+
export { AllowAllPermissionFilter, DenyAllPermissionFilter, PermissionFilter };
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { Table } from "../../Table.js";
|
|
2
|
+
class PermissionFilteredTable extends Table {
|
|
3
|
+
#attached = false;
|
|
4
|
+
#indexOfKey;
|
|
5
|
+
#predicate;
|
|
6
|
+
#source;
|
|
7
|
+
constructor(source, predicate){
|
|
8
|
+
super(source.schema, source.data.filter(predicate), source.map);
|
|
9
|
+
this.#indexOfKey = source.map[source.schema.key];
|
|
10
|
+
this.#predicate = predicate;
|
|
11
|
+
this.#source = source;
|
|
12
|
+
this.attach();
|
|
13
|
+
}
|
|
14
|
+
get source() {
|
|
15
|
+
return this.#source;
|
|
16
|
+
}
|
|
17
|
+
attach() {
|
|
18
|
+
if (!this.#attached) {
|
|
19
|
+
this.#source.on("insert", this.handleSourceInsert);
|
|
20
|
+
this.#source.on("update", this.handleSourceUpdate);
|
|
21
|
+
this.#source.on("delete", this.handleSourceDelete);
|
|
22
|
+
this.#attached = true;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
dispose() {
|
|
26
|
+
if (this.#attached) {
|
|
27
|
+
this.#source.removeListener("insert", this.handleSourceInsert);
|
|
28
|
+
this.#source.removeListener("update", this.handleSourceUpdate);
|
|
29
|
+
this.#source.removeListener("delete", this.handleSourceDelete);
|
|
30
|
+
this.#attached = false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
contains(key) {
|
|
34
|
+
return void 0 !== this.findByKey(key);
|
|
35
|
+
}
|
|
36
|
+
handleSourceInsert = (row)=>{
|
|
37
|
+
if (this.#predicate(row)) this.insert(row);
|
|
38
|
+
};
|
|
39
|
+
handleSourceUpdate = (row)=>{
|
|
40
|
+
const key = row[this.#indexOfKey];
|
|
41
|
+
const isMember = this.contains(key);
|
|
42
|
+
const isPermitted = this.#predicate(row);
|
|
43
|
+
if (isMember && isPermitted) this.replaceRow(row);
|
|
44
|
+
else if (isMember) this.delete(key);
|
|
45
|
+
else if (isPermitted) this.insert(row);
|
|
46
|
+
};
|
|
47
|
+
handleSourceDelete = (key)=>{
|
|
48
|
+
if (this.contains(key)) this.delete(key);
|
|
49
|
+
};
|
|
50
|
+
replaceRow(row) {
|
|
51
|
+
const key = row[this.#indexOfKey];
|
|
52
|
+
const rowIndex = this.data.findIndex((r)=>r[this.#indexOfKey] === key);
|
|
53
|
+
if (-1 !== rowIndex) {
|
|
54
|
+
this.data[rowIndex] = row;
|
|
55
|
+
this.emit("update", row);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
export { PermissionFilteredTable };
|
|
@@ -4,6 +4,10 @@ import { TickingArrayDataSource } from "../../TickingArrayDataSource.js";
|
|
|
4
4
|
import { RuntimeVisualLink } from "../../RuntimeVisualLink.js";
|
|
5
5
|
import ModuleContainer from "./ModuleContainer.js";
|
|
6
6
|
import { sessionTableRow, sessionTableSchema } from "../../session-table-utils.js";
|
|
7
|
+
import { AllowAllPermissionFilter } from "../filter/PermissionFilter.js";
|
|
8
|
+
import { PermissionFilteredTable } from "../filter/PermissionFilteredTable.js";
|
|
9
|
+
import { getCurrentUser } from "../user/CurrentUser.js";
|
|
10
|
+
import TableContainer from "../table/TableContainer.js";
|
|
7
11
|
const assertUpdateIsValid = (schema, column, _data)=>{
|
|
8
12
|
const col = schema.columns.find((col)=>col.name === column);
|
|
9
13
|
if (col) ;
|
|
@@ -27,6 +31,7 @@ class VuuModule {
|
|
|
27
31
|
}
|
|
28
32
|
async beforeSessionSave(_sourceTable, _sessionTable) {}
|
|
29
33
|
async afterSessionSave(_sourceTable, _sessionTable) {}
|
|
34
|
+
permissionFunctions;
|
|
30
35
|
getTableSchema(tableName) {
|
|
31
36
|
return this.schemas[tableName] ?? this.#sessionTableMap[tableName]?.schema;
|
|
32
37
|
}
|
|
@@ -126,9 +131,17 @@ class VuuModule {
|
|
|
126
131
|
return void 0 === linksForTable ? void 0 : this.getLinks(this.#subscriptionMap, linksForTable);
|
|
127
132
|
};
|
|
128
133
|
createDataSource = (tableName, viewport, config)=>{
|
|
134
|
+
this.beforeCreateDataSource?.(tableName);
|
|
129
135
|
const columnDescriptors = this.getColumnDescriptors(tableName);
|
|
130
|
-
const table = this.tables[tableName];
|
|
131
136
|
const sessionTable = this.#sessionTableMap[tableName];
|
|
137
|
+
const user = getCurrentUser();
|
|
138
|
+
const permissionFunction = sessionTable ? void 0 : this.permissionFunctions?.[tableName];
|
|
139
|
+
const viewportId = permissionFunction ? viewport ?? uuid() : viewport;
|
|
140
|
+
const permissionFilteredTable = permissionFunction ? this.createPermissionFilteredTable(this.tables[tableName], permissionFunction, {
|
|
141
|
+
id: viewportId,
|
|
142
|
+
user
|
|
143
|
+
}) : void 0;
|
|
144
|
+
const table = permissionFilteredTable ?? this.tables[tableName];
|
|
132
145
|
const vuuModule = this;
|
|
133
146
|
const dataSource = new TickingArrayDataSource({
|
|
134
147
|
...config,
|
|
@@ -139,18 +152,24 @@ class VuuModule {
|
|
|
139
152
|
menu: this.menus?.[tableName],
|
|
140
153
|
rpcServices: this.getServices(tableName),
|
|
141
154
|
rpcMenuServices: this.getMenuServices(tableName),
|
|
142
|
-
viewport,
|
|
155
|
+
viewport: viewportId,
|
|
143
156
|
visualLinkService: this.visualLinkService,
|
|
144
157
|
vuuModule
|
|
145
158
|
});
|
|
146
159
|
dataSource.on("subscribed", this.handlePostSubscribeActivities);
|
|
147
160
|
dataSource.on("unsubscribed", this.unregisterViewport);
|
|
161
|
+
if (permissionFilteredTable) {
|
|
162
|
+
dataSource.on("subscribed", ()=>permissionFilteredTable.attach());
|
|
163
|
+
dataSource.on("unsubscribed", ()=>permissionFilteredTable.dispose());
|
|
164
|
+
}
|
|
148
165
|
const existingSubscriptions = this.#subscriptionMap.get(tableName);
|
|
149
166
|
const subscription = {
|
|
150
167
|
viewportId: dataSource.viewport,
|
|
151
168
|
dataSource,
|
|
152
169
|
sessionTableName: sessionTable ? tableName : void 0,
|
|
153
|
-
sourceTableName: this.#sessionSourceTableMap[tableName]
|
|
170
|
+
sourceTableName: this.#sessionSourceTableMap[tableName],
|
|
171
|
+
table: table || sessionTable,
|
|
172
|
+
user
|
|
154
173
|
};
|
|
155
174
|
if (existingSubscriptions) existingSubscriptions.push(subscription);
|
|
156
175
|
else this.#subscriptionMap.set(tableName, [
|
|
@@ -158,6 +177,11 @@ class VuuModule {
|
|
|
158
177
|
]);
|
|
159
178
|
return dataSource;
|
|
160
179
|
};
|
|
180
|
+
createPermissionFilteredTable(table, permissionFunction, viewport) {
|
|
181
|
+
const permissionFilter = permissionFunction(viewport, TableContainer);
|
|
182
|
+
if (permissionFilter === AllowAllPermissionFilter) return;
|
|
183
|
+
return new PermissionFilteredTable(table, permissionFilter.createPredicate(table.map));
|
|
184
|
+
}
|
|
161
185
|
getServices(tableName) {
|
|
162
186
|
const tableServices = this.services?.[tableName];
|
|
163
187
|
const defaultServices = this.includeDefaultServices ? this.#moduleServices : [];
|
|
@@ -477,7 +501,9 @@ class VuuModule {
|
|
|
477
501
|
sessionTable.insert(row);
|
|
478
502
|
return {
|
|
479
503
|
type: "SUCCESS_RESULT",
|
|
480
|
-
data:
|
|
504
|
+
data: {
|
|
505
|
+
key: rowKey
|
|
506
|
+
}
|
|
481
507
|
};
|
|
482
508
|
}
|
|
483
509
|
return {
|
|
@@ -15,9 +15,9 @@ class TableContainer {
|
|
|
15
15
|
this.addTable(table);
|
|
16
16
|
return table;
|
|
17
17
|
};
|
|
18
|
-
createJoinTable(joinTable,
|
|
19
|
-
const table1 = this.getTable(
|
|
20
|
-
const table2 = this.getTable(
|
|
18
|
+
createJoinTable(joinTable, source1, source2, joinColumn) {
|
|
19
|
+
const table1 = source1 instanceof Table ? source1 : this.getTable(source1.table);
|
|
20
|
+
const table2 = source2 instanceof Table ? source2 : this.getTable(source2.table);
|
|
21
21
|
const { map: m1, schema: schema1 } = table1;
|
|
22
22
|
const { map: m2, schema: schema2 } = table2;
|
|
23
23
|
const k1 = m1[joinColumn];
|
|
@@ -27,7 +27,7 @@ class TableContainer {
|
|
|
27
27
|
...schema2.columns
|
|
28
28
|
].map((col)=>col.name).sort());
|
|
29
29
|
const combinedSchema = {
|
|
30
|
-
key:
|
|
30
|
+
key: schema1.key,
|
|
31
31
|
table: joinTable,
|
|
32
32
|
rangeLimits: DEFAULT_RANGE_LIMITS,
|
|
33
33
|
columns: Array.from(combinedColumns).map((columnName)=>({
|
|
@@ -53,6 +53,18 @@ class TableContainer {
|
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
55
|
const newTable = new Table(combinedSchema, data, combinedColumnMap);
|
|
56
|
+
const joinedKeys = new Map();
|
|
57
|
+
const indexJoinedRow = (row)=>{
|
|
58
|
+
const value = String(row[combinedColumnMap[joinColumn]]);
|
|
59
|
+
const key = String(row[combinedColumnMap[schema1.key]]);
|
|
60
|
+
let keys = joinedKeys.get(value);
|
|
61
|
+
if (!keys) {
|
|
62
|
+
keys = new Set();
|
|
63
|
+
joinedKeys.set(value, keys);
|
|
64
|
+
}
|
|
65
|
+
keys.add(key);
|
|
66
|
+
};
|
|
67
|
+
data.forEach(indexJoinedRow);
|
|
56
68
|
table1.on("insert", (row)=>{
|
|
57
69
|
const row2 = table2.findByKey(String(row[k1]));
|
|
58
70
|
if (row2) {
|
|
@@ -65,18 +77,49 @@ class TableContainer {
|
|
|
65
77
|
const value = row2[m2[column.name]];
|
|
66
78
|
out[combinedColumnMap[column.name]] = value;
|
|
67
79
|
}
|
|
80
|
+
indexJoinedRow(out);
|
|
68
81
|
newTable.insert(out);
|
|
69
82
|
}
|
|
70
83
|
});
|
|
71
|
-
|
|
72
|
-
const
|
|
73
|
-
const targetRow = newTable.findByKey(
|
|
84
|
+
table1.on("update", (row)=>{
|
|
85
|
+
const key = String(row[m1[schema1.key]]);
|
|
86
|
+
const targetRow = newTable.findByKey(key);
|
|
74
87
|
if (targetRow) {
|
|
75
88
|
const updatedRow = targetRow.slice();
|
|
76
|
-
for (const { name } of
|
|
89
|
+
for (const { name } of schema1.columns)updatedRow[combinedColumnMap[name]] = row[m1[name]];
|
|
90
|
+
newTable.updateRow(updatedRow);
|
|
91
|
+
}
|
|
92
|
+
});
|
|
93
|
+
table1.on("delete", (key)=>{
|
|
94
|
+
const row = newTable.findByKey(key);
|
|
95
|
+
if (row) {
|
|
96
|
+
const value = String(row[combinedColumnMap[joinColumn]]);
|
|
97
|
+
const keys = joinedKeys.get(value);
|
|
98
|
+
keys?.delete(key);
|
|
99
|
+
if (keys?.size === 0) joinedKeys.delete(value);
|
|
100
|
+
newTable.delete(key);
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
table2.on("update", (row)=>{
|
|
104
|
+
const keyValue = String(row[k2]);
|
|
105
|
+
for (const key of joinedKeys.get(keyValue) ?? []){
|
|
106
|
+
const targetRow = newTable.findByKey(key);
|
|
107
|
+
if (!targetRow) continue;
|
|
108
|
+
const updatedRow = targetRow.slice();
|
|
109
|
+
for (const { name } of table2.schema.columns)if (!(name in m1)) {
|
|
110
|
+
if (row[m2[name]] !== updatedRow[combinedColumnMap[name]]) updatedRow[combinedColumnMap[name]] = row[m2[name]];
|
|
111
|
+
}
|
|
77
112
|
newTable.updateRow(updatedRow);
|
|
78
113
|
}
|
|
79
114
|
});
|
|
115
|
+
newTable.update = (key, columnName, value)=>{
|
|
116
|
+
const row = newTable.findByKey(key);
|
|
117
|
+
if (!row) throw Error(`[TableContainer] join row ${key} not found`);
|
|
118
|
+
if (columnName === schema1.key || columnName === joinColumn) throw Error(`[TableContainer] cannot edit join key ${columnName}`);
|
|
119
|
+
if (columnName in m1) table1.update(key, columnName, value);
|
|
120
|
+
else if (columnName in m2) table2.update(String(row[combinedColumnMap[schema2.key]]), columnName, value);
|
|
121
|
+
else throw Error(`[TableContainer] unknown join column ${columnName}`);
|
|
122
|
+
};
|
|
80
123
|
this.addTable(newTable);
|
|
81
124
|
return newTable;
|
|
82
125
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const DEFAULT_USER = {
|
|
2
|
+
name: "user",
|
|
3
|
+
authorizations: []
|
|
4
|
+
};
|
|
5
|
+
let currentUser = DEFAULT_USER;
|
|
6
|
+
const getCurrentUser = ()=>currentUser;
|
|
7
|
+
const setCurrentUser = (user)=>{
|
|
8
|
+
currentUser = void 0 === user ? DEFAULT_USER : "string" == typeof user ? {
|
|
9
|
+
name: user,
|
|
10
|
+
authorizations: []
|
|
11
|
+
} : user;
|
|
12
|
+
};
|
|
13
|
+
export { getCurrentUser, setCurrentUser };
|
package/src/index.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
export * from "./ArrayProxy.js";
|
|
2
|
+
export * from "./core/filter/PermissionFilter.js";
|
|
3
|
+
export * from "./core/filter/PermissionFilteredTable.js";
|
|
2
4
|
export * from "./core/module/VuuModule.js";
|
|
5
|
+
export * from "./core/user/CurrentUser.js";
|
|
3
6
|
export * from "./local-datasource-provider/LocalDatasourceProvider.js";
|
|
4
7
|
export * from "./makeSuggestions.js";
|
|
8
|
+
export * from "./notifications/index.js";
|
|
5
9
|
export * from "./schemas.js";
|
|
6
10
|
export * from "./simul/index.js";
|
|
7
11
|
export * from "./basket/index.js";
|
|
@@ -1,50 +1,70 @@
|
|
|
1
1
|
import { jsx } from "react/jsx-runtime";
|
|
2
2
|
import { DataProvider } from "@vuu-ui/core";
|
|
3
3
|
import { DataProvider as vuu_utils_DataProvider } from "@vuu-ui/vuu-utils";
|
|
4
|
-
import ModuleContainer from "../core/module/ModuleContainer.js";
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
return
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
4
|
+
import ModuleContainer, { ensureVuuModule } from "../core/module/ModuleContainer.js";
|
|
5
|
+
const createLocalDataSourceProvider = (modules)=>{
|
|
6
|
+
const ownModules = modules ? new Map(modules.map((module)=>[
|
|
7
|
+
module.name,
|
|
8
|
+
module
|
|
9
|
+
])) : void 0;
|
|
10
|
+
const getModule = (moduleName)=>{
|
|
11
|
+
if (ownModules) {
|
|
12
|
+
const module = ownModules.get(moduleName);
|
|
13
|
+
if (module) return module;
|
|
14
|
+
throw Error(`[LocalDataSourceProvider] module ${moduleName} is not available on this server`);
|
|
15
|
+
}
|
|
16
|
+
return ModuleContainer.get(moduleName);
|
|
17
|
+
};
|
|
18
|
+
const serverAPI = {
|
|
19
|
+
getTableList: async ()=>{
|
|
20
|
+
const tables = [];
|
|
21
|
+
for (const moduleName of ownModules?.keys() ?? ModuleContainer.moduleNames){
|
|
22
|
+
const module = getModule(moduleName);
|
|
23
|
+
for (const tableName of module.getTableList())tables.push(module.getTableSchema(tableName).table);
|
|
24
|
+
}
|
|
25
|
+
return {
|
|
26
|
+
tables
|
|
27
|
+
};
|
|
28
|
+
},
|
|
29
|
+
getTableSchema: async ({ module, table })=>getModule(module).getTableSchema(table),
|
|
30
|
+
rpcCall: async ()=>{
|
|
31
|
+
throw Error("RpcCall no longer supported on LocalDataSourceProvider ServerAPI");
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
const getServerAPI = async ()=>serverAPI;
|
|
35
|
+
class VuuDataSource {
|
|
36
|
+
constructor({ aggregations, baseFilterSpec, columns, filterSpec, groupBy, session, sort, table, viewport, visualLink }){
|
|
37
|
+
const config = {
|
|
38
|
+
aggregations,
|
|
39
|
+
baseFilterSpec,
|
|
40
|
+
columns,
|
|
41
|
+
filterSpec,
|
|
42
|
+
groupBy,
|
|
43
|
+
session,
|
|
44
|
+
sort,
|
|
45
|
+
visualLink
|
|
46
|
+
};
|
|
47
|
+
const module = getModule(table.module);
|
|
48
|
+
return module.createDataSource(table.table, viewport, config);
|
|
49
|
+
}
|
|
23
50
|
}
|
|
24
|
-
}
|
|
25
|
-
const getServerAPI = async ()=>serverAPI;
|
|
26
|
-
class VuuDataSource {
|
|
27
|
-
constructor({ aggregations, columns, filterSpec, groupBy, session, sort, table, viewport, visualLink }){
|
|
28
|
-
const config = {
|
|
29
|
-
aggregations,
|
|
30
|
-
columns,
|
|
31
|
-
filterSpec,
|
|
32
|
-
groupBy,
|
|
33
|
-
session,
|
|
34
|
-
sort,
|
|
35
|
-
visualLink
|
|
36
|
-
};
|
|
37
|
-
const module = ModuleContainer.get(table.module);
|
|
38
|
-
return module.createDataSource(table.table, viewport, config);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
const LocalDataSourceProvider = ({ children })=>/*#__PURE__*/ jsx(vuu_utils_DataProvider, {
|
|
42
|
-
VuuDataSource: VuuDataSource,
|
|
43
|
-
getServerAPI: getServerAPI,
|
|
44
|
-
children: /*#__PURE__*/ jsx(DataProvider, {
|
|
51
|
+
const DataSourceProvider = ({ children })=>/*#__PURE__*/ jsx(vuu_utils_DataProvider, {
|
|
45
52
|
VuuDataSource: VuuDataSource,
|
|
46
53
|
getServerAPI: getServerAPI,
|
|
47
|
-
children:
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
54
|
+
children: /*#__PURE__*/ jsx(DataProvider, {
|
|
55
|
+
VuuDataSource: VuuDataSource,
|
|
56
|
+
getServerAPI: getServerAPI,
|
|
57
|
+
children: children
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
return DataSourceProvider;
|
|
61
|
+
};
|
|
62
|
+
const LocalDataSourceProvider = createLocalDataSourceProvider();
|
|
63
|
+
const createLocalVuuServer = ({ connectionId, modules })=>{
|
|
64
|
+
modules.forEach(ensureVuuModule);
|
|
65
|
+
return {
|
|
66
|
+
connectionId,
|
|
67
|
+
DataSourceProvider: createLocalDataSourceProvider(modules)
|
|
68
|
+
};
|
|
69
|
+
};
|
|
70
|
+
export { LocalDataSourceProvider, createLocalVuuServer };
|