@things-factory/dataset 5.0.0-alpha.15 → 5.0.0-alpha.17

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.
@@ -56,9 +56,9 @@ export class DataOoc extends connect(store)(localize(i18next)(PageView)) {
56
56
  help: 'integration/ui/data-ooc',
57
57
  actions: [
58
58
  {
59
- title: i18next.t('button.delete'),
60
- action: this._deleteDataOoc.bind(this),
61
- ...CommonButtonStyles.delete
59
+ title: i18next.t('button.save'),
60
+ action: this._updateDataOoc.bind(this),
61
+ ...CommonButtonStyles.save
62
62
  }
63
63
  ],
64
64
  exportable: {
@@ -350,6 +350,38 @@ export class DataOoc extends connect(store)(localize(i18next)(PageView)) {
350
350
  }
351
351
  }
352
352
 
353
+ async _updateDataOoc() {
354
+ let patches = this.grist.dirtyRecords
355
+ if (patches && patches.length) {
356
+ patches = patches.map(patch => {
357
+ let patchField = patch.id ? { id: patch.id } : {}
358
+ const dirtyFields = patch.__dirtyfields__
359
+ for (let key in dirtyFields) {
360
+ patchField[key] = dirtyFields[key].after
361
+ }
362
+ this._setDefaultFieldsValue(patchField)
363
+ patchField.cuFlag = patch.__dirty__
364
+
365
+ return patchField
366
+ })
367
+
368
+ const response = await client.mutate({
369
+ mutation: gql`
370
+ mutation ($patches: [DataOocPatch!]!) {
371
+ updateMultipleDataOoc(patches: $patches) {
372
+ name
373
+ }
374
+ }
375
+ `,
376
+ variables: {
377
+ patches
378
+ }
379
+ })
380
+
381
+ if (!response.errors) this.grist.fetch()
382
+ }
383
+ }
384
+
353
385
  async _deleteDataOoc() {
354
386
  if (confirm(i18next.t('text.sure_to_x', { x: i18next.t('text.delete') }))) {
355
387
  const ids = this.grist.selected.map(record => record.id)
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createDataSample = void 0;
7
+ const data_ooc_1 = require("../service/data-ooc/data-ooc");
8
+ const shell_1 = require("@things-factory/shell");
9
+ const data_item_1 = require("../service/data-item/data-item");
10
+ const data_sample_1 = require("../service/data-sample/data-sample");
11
+ const data_set_1 = require("../service/data-set/data-set");
12
+ const data_use_case_1 = require("./data-use-case");
13
+ const moment_1 = __importDefault(require("moment"));
14
+ const debug = require('debug')('things-factory:dataset:controller/save-data-sample');
15
+ // parse variable javascript string pattern
16
+ const replaceVariables = (keys, dic) => {
17
+ for (const k in keys) {
18
+ const matches = keys[k].match(/\$\{\w*\}/g);
19
+ matches &&
20
+ matches.forEach(m => {
21
+ keys[k] = keys[k].replace(m, dic[m.slice(2, -1)]);
22
+ });
23
+ }
24
+ return keys;
25
+ };
26
+ // It is required UTC date for Partitioning File System like AWS S3 from Athena.
27
+ // ex) %YYYY, %MM, %DD
28
+ const formatDate = (keys, _moment) => {
29
+ for (const k in keys) {
30
+ const matches = keys[k].match(/%\w*/g);
31
+ matches &&
32
+ matches.forEach(m => {
33
+ keys[k] = keys[k].replace(m, _moment.format(m.substr(1)));
34
+ });
35
+ }
36
+ return keys;
37
+ };
38
+ async function createDataSample(dataSample, context) {
39
+ const { domain, user, tx } = context.state;
40
+ const dataSet = await tx.getRepository(data_set_1.DataSet).findOne({
41
+ where: { id: dataSample.dataSet.id }
42
+ });
43
+ const dataItems = await tx.getRepository(data_item_1.DataItem).find({
44
+ where: {
45
+ domain,
46
+ dataSet
47
+ },
48
+ order: {
49
+ sequence: 'DESC'
50
+ }
51
+ });
52
+ const spec = dataItems.reduce((spec, dataItem) => {
53
+ spec[dataItem.tag] = Object.assign(Object.assign({}, dataItem.spec), { name: dataItem.name /* do we need ? */ });
54
+ return spec;
55
+ }, {});
56
+ var partitionKeys = Object.assign({}, dataSet.partitionKeys);
57
+ const collectedAt = dataSample.collectedAt || new Date();
58
+ partitionKeys = formatDate(partitionKeys, (0, moment_1.default)(collectedAt).utc());
59
+ partitionKeys = replaceVariables(partitionKeys, Object.assign({ domain: domain.subdomain, dataSetId: dataSample.dataSet.id }, dataSample.data));
60
+ const { ooc, oos } = data_use_case_1.DataUseCase.evaluate(dataSet, dataItems, dataSample.data) || {};
61
+ const result = await tx.getRepository(data_sample_1.DataSample).save(Object.assign(Object.assign({ name: dataSet.name, description: dataSet.description }, dataSample), { domain,
62
+ partitionKeys,
63
+ spec,
64
+ ooc,
65
+ oos,
66
+ collectedAt, creator: user, updater: user }));
67
+ if (ooc || oos) {
68
+ const dataOoc = await tx.getRepository(data_ooc_1.DataOoc).save({
69
+ name: dataSet.name,
70
+ description: dataSet.description,
71
+ dataSet,
72
+ dataSample: result,
73
+ data: dataSample.data,
74
+ domain,
75
+ partitionKeys,
76
+ spec,
77
+ ooc,
78
+ oos,
79
+ state: data_ooc_1.DataOocStatus.CREATED,
80
+ collectedAt,
81
+ creator: user,
82
+ updater: user
83
+ });
84
+ shell_1.pubsub.publish('data-ooc', {
85
+ dataOoc,
86
+ supervisoryRoleId: dataSet.supervisoryRoleId
87
+ });
88
+ shell_1.pubsub.publish('notification', {
89
+ notification: {
90
+ domain,
91
+ type: 'error',
92
+ title: `Data OOC occurred on '${dataSet.name}'`,
93
+ body: `Data OOC occurred on '${dataSet.name}'`,
94
+ url: (0, shell_1.getRedirectSubdomainPath)(context, domain.subdomain, `/data-ooc/${dataOoc.id}`),
95
+ timestamp: collectedAt
96
+ }
97
+ });
98
+ }
99
+ return result;
100
+ }
101
+ exports.createDataSample = createDataSample;
102
+ //# sourceMappingURL=create-data-sample.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"create-data-sample.js","sourceRoot":"","sources":["../../server/controllers/create-data-sample.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,9 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const typeorm_1 = require("typeorm");
4
- const service_1 = require("./service");
5
3
  const data_item_1 = require("./service/data-item/data-item");
6
4
  const data_sensor_1 = require("./service/data-sensor/data-sensor");
5
+ const create_data_sample_1 = require("./controllers/create-data-sample");
6
+ const typeorm_1 = require("typeorm");
7
7
  const debug = require('debug')('things-factory:dataset:routes');
8
8
  process.on('bootstrap-module-global-public-route', (app, globalPublicRouter) => {
9
9
  /*
@@ -49,24 +49,13 @@ process.on('bootstrap-module-global-public-route', (app, globalPublicRouter) =>
49
49
  sequence: 'DESC'
50
50
  }
51
51
  });
52
- var spec = {};
53
- dataItems.forEach(dataItem => {
54
- spec[dataItem.name] = dataItem.spec;
55
- });
56
- await tx.getRepository(service_1.DataSample).save({
57
- domain,
58
- name: dataSet.name,
59
- description: dataSet.description,
60
- partitionKeys: dataSet.partitionKeys,
52
+ return await (0, create_data_sample_1.createDataSample)({
61
53
  dataSet,
62
54
  data,
63
55
  rawData,
64
- spec,
65
56
  source: deviceId,
66
- collectedAt: new Date(timestamp),
67
- creator: user,
68
- updater: user
69
- });
57
+ collectedAt: new Date(timestamp)
58
+ }, { state: { domain, user, tx } });
70
59
  });
71
60
  return 'OK';
72
61
  });
@@ -1 +1 @@
1
- {"version":3,"file":"routes.js","sourceRoot":"","sources":["../server/routes.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"routes.js","sourceRoot":"","sources":["../server/routes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.DataOocSubscription = void 0;
16
+ const type_graphql_1 = require("type-graphql");
17
+ const graphql_subscriptions_1 = require("graphql-subscriptions");
18
+ const shell_1 = require("@things-factory/shell");
19
+ const auth_base_1 = require("@things-factory/auth-base");
20
+ const data_ooc_1 = require("./data-ooc");
21
+ const typeorm_1 = require("typeorm");
22
+ const debug = require('debug')('things-factory:dataset:data-ooc-subscription');
23
+ let DataOocSubscription = class DataOocSubscription {
24
+ dataOoc(payload) {
25
+ return payload.dataOoc;
26
+ }
27
+ };
28
+ __decorate([
29
+ (0, type_graphql_1.Subscription)({
30
+ subscribe: (_, args, context, info) => {
31
+ var _a;
32
+ const { domain, user } = context.state;
33
+ const subdomain = domain === null || domain === void 0 ? void 0 : domain.subdomain;
34
+ debug('subscribe', subdomain);
35
+ if (!domain) {
36
+ throw new Error('domain required');
37
+ }
38
+ if (!((_a = user.domains) === null || _a === void 0 ? void 0 : _a.find(d => d.subdomain === subdomain))) {
39
+ throw new Error(`domain(${subdomain}) is not working for user(${user.email}).`);
40
+ }
41
+ return (0, graphql_subscriptions_1.withFilter)(() => shell_1.pubsub.asyncIterator('data-ooc'), async (payload, variables, context, info) => {
42
+ const { dataOoc, supervisoryRoleId } = payload;
43
+ const { domain } = dataOoc;
44
+ if (subdomain !== (domain === null || domain === void 0 ? void 0 : domain.subdomain)) {
45
+ return false;
46
+ }
47
+ // check if the user has that role
48
+ const userWithRoles = await (0, typeorm_1.getRepository)(auth_base_1.User).findOne({
49
+ where: { id: user.id },
50
+ relations: ['roles']
51
+ });
52
+ return userWithRoles.roles.find(role => role.id === supervisoryRoleId);
53
+ })(_, args, context, info);
54
+ }
55
+ }),
56
+ __param(0, (0, type_graphql_1.Root)()),
57
+ __metadata("design:type", Function),
58
+ __metadata("design:paramtypes", [Object]),
59
+ __metadata("design:returntype", data_ooc_1.DataOoc)
60
+ ], DataOocSubscription.prototype, "dataOoc", null);
61
+ DataOocSubscription = __decorate([
62
+ (0, type_graphql_1.Resolver)(data_ooc_1.DataOoc)
63
+ ], DataOocSubscription);
64
+ exports.DataOocSubscription = DataOocSubscription;
65
+ //# sourceMappingURL=data-ooc-subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-ooc-subscription.js","sourceRoot":"","sources":["../../../server/service/data-ooc/data-ooc-subscription.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,+CAA2D;AAC3D,iEAAkD;AAClD,iDAA8C;AAC9C,yDAAgD;AAChD,yCAAoC;AACpC,qCAAuC;AAEvC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,8CAA8C,CAAC,CAAA;AAG9E,IAAa,mBAAmB,GAAhC,MAAa,mBAAmB;IAqC9B,OAAO,CAAS,OAAwD;QACtE,OAAO,OAAO,CAAC,OAAO,CAAA;IACxB,CAAC;CACF,CAAA;AAHC;IApCC,IAAA,2BAAY,EAAC;QACZ,SAAS,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;;YACpC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,KAAK,CAAA;YACtC,MAAM,SAAS,GAAG,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,SAAS,CAAA;YAEnC,KAAK,CAAC,WAAW,EAAE,SAAS,CAAC,CAAA;YAE7B,IAAI,CAAC,MAAM,EAAE;gBACX,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;aACnC;YAED,IAAI,CAAC,CAAA,MAAA,IAAI,CAAC,OAAO,0CAAE,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAA,EAAE;gBACvD,MAAM,IAAI,KAAK,CAAC,UAAU,SAAS,6BAA6B,IAAI,CAAC,KAAK,IAAI,CAAC,CAAA;aAChF;YAED,OAAO,IAAA,kCAAU,EACf,GAAG,EAAE,CAAC,cAAM,CAAC,aAAa,CAAC,UAAU,CAAC,EACtC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE;gBAC1C,MAAM,EAAE,OAAO,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAA;gBAC9C,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;gBAE1B,IAAI,SAAS,MAAK,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,SAAS,CAAA,EAAE;oBACnC,OAAO,KAAK,CAAA;iBACb;gBAED,kCAAkC;gBAClC,MAAM,aAAa,GAAS,MAAM,IAAA,uBAAa,EAAC,gBAAI,CAAC,CAAC,OAAO,CAAC;oBAC5D,KAAK,EAAE,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE;oBACtB,SAAS,EAAE,CAAC,OAAO,CAAC;iBACrB,CAAC,CAAA;gBAEF,OAAO,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,iBAAiB,CAAC,CAAA;YACxE,CAAC,CACF,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,CAAA;QAC3B,CAAC;KACF,CAAC;IACO,WAAA,IAAA,mBAAI,GAAE,CAAA;;;oCAA4D,kBAAO;kDAEjF;AAvCU,mBAAmB;IAD/B,IAAA,uBAAQ,EAAC,kBAAO,CAAC;GACL,mBAAmB,CAwC/B;AAxCY,kDAAmB"}
@@ -4,6 +4,7 @@ exports.resolvers = exports.entities = void 0;
4
4
  const data_ooc_1 = require("./data-ooc");
5
5
  const data_ooc_mutation_1 = require("./data-ooc-mutation");
6
6
  const data_ooc_query_1 = require("./data-ooc-query");
7
+ const data_ooc_subscription_1 = require("./data-ooc-subscription");
7
8
  exports.entities = [data_ooc_1.DataOoc];
8
- exports.resolvers = [data_ooc_query_1.DataOocQuery, data_ooc_mutation_1.DataOocMutation];
9
+ exports.resolvers = [data_ooc_query_1.DataOocQuery, data_ooc_mutation_1.DataOocMutation, data_ooc_subscription_1.DataOocSubscription];
9
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/data-ooc/index.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,2DAAqD;AACrD,qDAA+C;AAElC,QAAA,QAAQ,GAAG,CAAC,kBAAO,CAAC,CAAA;AACpB,QAAA,SAAS,GAAG,CAAC,6BAAY,EAAE,mCAAe,CAAC,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/service/data-ooc/index.ts"],"names":[],"mappings":";;;AAAA,yCAAoC;AACpC,2DAAqD;AACrD,qDAA+C;AAC/C,mEAA6D;AAEhD,QAAA,QAAQ,GAAG,CAAC,kBAAO,CAAC,CAAA;AACpB,QAAA,SAAS,GAAG,CAAC,6BAAY,EAAE,mCAAe,EAAE,2CAAmB,CAAC,CAAA"}
@@ -11,94 +11,16 @@ var __metadata = (this && this.__metadata) || function (k, v) {
11
11
  var __param = (this && this.__param) || function (paramIndex, decorator) {
12
12
  return function (target, key) { decorator(target, key, paramIndex); }
13
13
  };
14
- var __importDefault = (this && this.__importDefault) || function (mod) {
15
- return (mod && mod.__esModule) ? mod : { "default": mod };
16
- };
17
14
  Object.defineProperty(exports, "__esModule", { value: true });
18
15
  exports.DataSampleMutation = void 0;
19
16
  const type_graphql_1 = require("type-graphql");
20
- const data_item_1 = require("../data-item/data-item");
21
- const data_set_1 = require("../data-set/data-set");
22
17
  const data_sample_1 = require("./data-sample");
23
18
  const data_sample_type_1 = require("./data-sample-type");
24
- const moment_1 = __importDefault(require("moment"));
25
- const controllers_1 = require("../../controllers");
26
- const data_ooc_1 = require("../data-ooc/data-ooc");
19
+ const create_data_sample_1 = require("../../controllers/create-data-sample");
27
20
  const debug = require('debug')('things-factory:dataset:data-sample:data-sample-mutation');
28
- // parse variable javascript string pattern
29
- const replaceVariables = (keys, dic) => {
30
- for (const k in keys) {
31
- const matches = keys[k].match(/\$\{\w*\}/g);
32
- matches &&
33
- matches.forEach(m => {
34
- keys[k] = keys[k].replace(m, dic[m.slice(2, -1)]);
35
- });
36
- }
37
- return keys;
38
- };
39
- // It is required UTC date for Partitioning File System like AWS S3 from Athena.
40
- // ex) %YYYY, %MM, %DD
41
- const formatDate = (keys, _moment) => {
42
- for (const k in keys) {
43
- const matches = keys[k].match(/%\w*/g);
44
- matches &&
45
- matches.forEach(m => {
46
- keys[k] = keys[k].replace(m, _moment.format(m.substr(1)));
47
- });
48
- }
49
- return keys;
50
- };
51
21
  let DataSampleMutation = class DataSampleMutation {
52
22
  async createDataSample(dataSample, context) {
53
- const { domain, user, tx } = context.state;
54
- const dataSet = await tx.getRepository(data_set_1.DataSet).findOne({
55
- where: { id: dataSample.dataSet.id }
56
- });
57
- const dataItems = await tx.getRepository(data_item_1.DataItem).find({
58
- where: {
59
- domain,
60
- dataSet
61
- },
62
- order: {
63
- sequence: 'DESC'
64
- }
65
- });
66
- const spec = dataItems.reduce((spec, dataItem) => {
67
- spec[dataItem.tag] = Object.assign(Object.assign({}, dataItem.spec), { name: dataItem.name /* do we need ? */ });
68
- return spec;
69
- }, {});
70
- // appending spec to data for reporting and optimizing AWS Athena search
71
- dataSample.data = Object.assign(Object.assign({}, dataSample.data), { _spec: JSON.stringify(spec) });
72
- var partitionKeys = Object.assign({}, dataSet.partitionKeys);
73
- const collectedAt = dataSample.collectedAt || new Date();
74
- partitionKeys = formatDate(partitionKeys, (0, moment_1.default)(collectedAt).utc());
75
- partitionKeys = replaceVariables(partitionKeys, Object.assign({ domain: domain.subdomain, dataSetId: dataSample.dataSet.id }, dataSample.data));
76
- const { ooc, oos } = controllers_1.DataUseCase.evaluate(dataSet, dataItems, dataSample.data) || {};
77
- const result = await tx.getRepository(data_sample_1.DataSample).save(Object.assign(Object.assign({ name: dataSet.name, description: dataSet.description }, dataSample), { domain,
78
- partitionKeys,
79
- spec,
80
- ooc,
81
- oos,
82
- collectedAt, creator: user, updater: user }));
83
- if (ooc || oos) {
84
- await tx.getRepository(data_ooc_1.DataOoc).save({
85
- name: dataSet.name,
86
- description: dataSet.description,
87
- dataSet,
88
- dataSample: result,
89
- data: dataSample.data,
90
- domain,
91
- partitionKeys,
92
- spec,
93
- ooc,
94
- oos,
95
- state: data_ooc_1.DataOocStatus.CREATED,
96
- collectedAt,
97
- creator: user,
98
- updater: user
99
- });
100
- }
101
- return result;
23
+ return await (0, create_data_sample_1.createDataSample)(dataSample, context);
102
24
  }
103
25
  };
104
26
  __decorate([
@@ -1 +1 @@
1
- {"version":3,"file":"data-sample-mutation.js","sourceRoot":"","sources":["../../../server/service/data-sample/data-sample-mutation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-sample-mutation.js","sourceRoot":"","sources":["../../../server/service/data-sample/data-sample-mutation.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;AAAA,+CAAsE;AAEtE,+CAA0C;AAC1C,yDAAkD;AAElD,6EAAuE;AAEvE,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,yDAAyD,CAAC,CAAA;AAGzF,IAAa,kBAAkB,GAA/B,MAAa,kBAAkB;IAI7B,KAAK,CAAC,gBAAgB,CAAoB,UAAyB,EAAS,OAAY;QACtF,OAAO,MAAM,IAAA,qCAAgB,EAAC,UAAU,EAAE,OAAO,CAAC,CAAA;IACpD,CAAC;CACF,CAAA;AAHC;IAHC,IAAA,wBAAS,EAAC,sFAAsF,CAAC;IACjG,IAAA,wBAAS,EAAC,cAAc,CAAC;IACzB,IAAA,uBAAQ,EAAC,OAAO,CAAC,EAAE,CAAC,wBAAU,EAAE,EAAE,WAAW,EAAE,2BAA2B,EAAE,CAAC;IACtD,WAAA,IAAA,kBAAG,EAAC,YAAY,CAAC,CAAA;IAA6B,WAAA,IAAA,kBAAG,GAAE,CAAA;;qCAArB,gCAAa;;0DAElE;AANU,kBAAkB;IAD9B,IAAA,uBAAQ,EAAC,wBAAU,CAAC;GACR,kBAAkB,CAO9B;AAPY,gDAAkB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/dataset",
3
- "version": "5.0.0-alpha.15",
3
+ "version": "5.0.0-alpha.17",
4
4
  "main": "dist-server/index.js",
5
5
  "browser": "client/index.js",
6
6
  "things-factory": true,
@@ -24,19 +24,19 @@
24
24
  "migration:create": "node ../../node_modules/typeorm/cli.js migration:create -d ./server/migrations"
25
25
  },
26
26
  "dependencies": {
27
- "@operato/app": "1.0.0-alpha.35",
28
- "@operato/data-grist": "1.0.0-alpha.35",
29
- "@operato/dataset": "1.0.0-alpha.35",
30
- "@operato/graphql": "1.0.0-alpha.35",
31
- "@operato/i18n": "1.0.0-alpha.35",
32
- "@operato/layout": "1.0.0-alpha.35",
33
- "@operato/shell": "1.0.0-alpha.35",
34
- "@operato/styles": "1.0.0-alpha.35",
35
- "@operato/utils": "1.0.0-alpha.35",
36
- "@things-factory/auth-base": "^5.0.0-alpha.15",
37
- "@things-factory/env": "^5.0.0-alpha.15",
38
- "@things-factory/shell": "^5.0.0-alpha.15",
27
+ "@operato/app": "1.0.0-alpha.36",
28
+ "@operato/data-grist": "1.0.0-alpha.36",
29
+ "@operato/dataset": "1.0.0-alpha.36",
30
+ "@operato/graphql": "1.0.0-alpha.36",
31
+ "@operato/i18n": "1.0.0-alpha.36",
32
+ "@operato/layout": "1.0.0-alpha.36",
33
+ "@operato/shell": "1.0.0-alpha.36",
34
+ "@operato/styles": "1.0.0-alpha.36",
35
+ "@operato/utils": "1.0.0-alpha.36",
36
+ "@things-factory/auth-base": "^5.0.0-alpha.17",
37
+ "@things-factory/env": "^5.0.0-alpha.17",
38
+ "@things-factory/shell": "^5.0.0-alpha.17",
39
39
  "moment": "^2.29.1"
40
40
  },
41
- "gitHead": "88072e1d32788fff7c2f06f2b21b62ba944786ab"
41
+ "gitHead": "258d2d2f3bfb96ebcc88525c1cc0dcd8ea8d8c64"
42
42
  }
@@ -0,0 +1,139 @@
1
+ import { DataOoc, DataOocStatus } from '../service/data-ooc/data-ooc'
2
+ import { Domain, getRedirectSubdomainPath, pubsub } from '@things-factory/shell'
3
+
4
+ import { DataItem } from '../service/data-item/data-item'
5
+ import { DataSample } from '../service/data-sample/data-sample'
6
+ import { DataSet } from '../service/data-set/data-set'
7
+ import { DataUseCase } from './data-use-case'
8
+ import { EntityManager } from 'typeorm'
9
+ import { NewDataSample } from '../service/data-sample/data-sample-type'
10
+ import { User } from '@things-factory/auth-base'
11
+ import moment from 'moment'
12
+
13
+ const debug = require('debug')('things-factory:dataset:controller/save-data-sample')
14
+
15
+ // parse variable javascript string pattern
16
+ const replaceVariables = (keys, dic) => {
17
+ for (const k in keys) {
18
+ const matches = keys[k].match(/\$\{\w*\}/g)
19
+ matches &&
20
+ matches.forEach(m => {
21
+ keys[k] = keys[k].replace(m, dic[m.slice(2, -1)])
22
+ })
23
+ }
24
+ return keys
25
+ }
26
+
27
+ // It is required UTC date for Partitioning File System like AWS S3 from Athena.
28
+ // ex) %YYYY, %MM, %DD
29
+ const formatDate = (keys, _moment) => {
30
+ for (const k in keys) {
31
+ const matches = keys[k].match(/%\w*/g)
32
+ matches &&
33
+ matches.forEach(m => {
34
+ keys[k] = keys[k].replace(m, _moment.format(m.substr(1)))
35
+ })
36
+ }
37
+ return keys
38
+ }
39
+
40
+ export async function createDataSample(
41
+ dataSample: NewDataSample,
42
+ context: {
43
+ state: {
44
+ domain: Domain
45
+ user: User
46
+ tx: EntityManager
47
+ }
48
+ }
49
+ ): Promise<DataSample> {
50
+ const { domain, user, tx } = context.state
51
+
52
+ const dataSet = await tx.getRepository(DataSet).findOne({
53
+ where: { id: dataSample.dataSet.id }
54
+ })
55
+
56
+ const dataItems = await tx.getRepository(DataItem).find({
57
+ where: {
58
+ domain,
59
+ dataSet
60
+ },
61
+ order: {
62
+ sequence: 'DESC'
63
+ }
64
+ })
65
+
66
+ const spec = dataItems.reduce((spec, dataItem) => {
67
+ spec[dataItem.tag] = {
68
+ ...dataItem.spec,
69
+ name: dataItem.name /* do we need ? */
70
+ }
71
+
72
+ return spec
73
+ }, {})
74
+
75
+ var partitionKeys = {
76
+ ...dataSet.partitionKeys
77
+ }
78
+
79
+ const collectedAt = dataSample.collectedAt || new Date()
80
+ partitionKeys = formatDate(partitionKeys, moment(collectedAt).utc())
81
+ partitionKeys = replaceVariables(partitionKeys, {
82
+ domain: domain.subdomain,
83
+ dataSetId: dataSample.dataSet.id,
84
+ ...dataSample.data
85
+ })
86
+
87
+ const { ooc, oos } = DataUseCase.evaluate(dataSet, dataItems, dataSample.data) || {}
88
+
89
+ const result = await tx.getRepository(DataSample).save({
90
+ name: dataSet.name,
91
+ description: dataSet.description,
92
+ ...dataSample,
93
+ domain,
94
+ partitionKeys,
95
+ spec,
96
+ ooc,
97
+ oos,
98
+ collectedAt,
99
+ creator: user,
100
+ updater: user
101
+ })
102
+
103
+ if (ooc || oos) {
104
+ const dataOoc = await tx.getRepository(DataOoc).save({
105
+ name: dataSet.name,
106
+ description: dataSet.description,
107
+ dataSet,
108
+ dataSample: result,
109
+ data: dataSample.data,
110
+ domain,
111
+ partitionKeys,
112
+ spec,
113
+ ooc,
114
+ oos,
115
+ state: DataOocStatus.CREATED,
116
+ collectedAt,
117
+ creator: user,
118
+ updater: user
119
+ })
120
+
121
+ pubsub.publish('data-ooc', {
122
+ dataOoc,
123
+ supervisoryRoleId: dataSet.supervisoryRoleId
124
+ })
125
+
126
+ pubsub.publish('notification', {
127
+ notification: {
128
+ domain,
129
+ type: 'error',
130
+ title: `Data OOC occurred on '${dataSet.name}'`,
131
+ body: `Data OOC occurred on '${dataSet.name}'`,
132
+ url: getRedirectSubdomainPath(context, domain.subdomain, `/data-ooc/${dataOoc.id}`),
133
+ timestamp: collectedAt
134
+ }
135
+ })
136
+ }
137
+
138
+ return result
139
+ }
package/server/routes.ts CHANGED
@@ -1,8 +1,7 @@
1
- import { getConnection } from 'typeorm'
2
-
3
- import { DataSample } from './service'
4
1
  import { DataItem } from './service/data-item/data-item'
5
2
  import { DataSensor } from './service/data-sensor/data-sensor'
3
+ import { createDataSample } from './controllers/create-data-sample'
4
+ import { getConnection } from 'typeorm'
6
5
 
7
6
  const debug = require('debug')('things-factory:dataset:routes')
8
7
 
@@ -59,26 +58,16 @@ process.on('bootstrap-module-global-public-route' as any, (app, globalPublicRout
59
58
  }
60
59
  })
61
60
 
62
- var spec = {} as any
63
-
64
- dataItems.forEach(dataItem => {
65
- spec[dataItem.name] = dataItem.spec
66
- })
67
-
68
- await tx.getRepository(DataSample).save({
69
- domain,
70
- name: dataSet.name,
71
- description: dataSet.description,
72
- partitionKeys: dataSet.partitionKeys,
73
- dataSet,
74
- data,
75
- rawData,
76
- spec,
77
- source: deviceId,
78
- collectedAt: new Date(timestamp),
79
- creator: user,
80
- updater: user
81
- })
61
+ return await createDataSample(
62
+ {
63
+ dataSet,
64
+ data,
65
+ rawData,
66
+ source: deviceId,
67
+ collectedAt: new Date(timestamp)
68
+ },
69
+ { state: { domain, user, tx } }
70
+ )
82
71
  })
83
72
 
84
73
  return 'OK'
@@ -0,0 +1,51 @@
1
+ import { Resolver, Subscription, Root } from 'type-graphql'
2
+ import { withFilter } from 'graphql-subscriptions'
3
+ import { pubsub } from '@things-factory/shell'
4
+ import { User } from '@things-factory/auth-base'
5
+ import { DataOoc } from './data-ooc'
6
+ import { getRepository } from 'typeorm'
7
+
8
+ const debug = require('debug')('things-factory:dataset:data-ooc-subscription')
9
+
10
+ @Resolver(DataOoc)
11
+ export class DataOocSubscription {
12
+ @Subscription({
13
+ subscribe: (_, args, context, info) => {
14
+ const { domain, user } = context.state
15
+ const subdomain = domain?.subdomain
16
+
17
+ debug('subscribe', subdomain)
18
+
19
+ if (!domain) {
20
+ throw new Error('domain required')
21
+ }
22
+
23
+ if (!user.domains?.find(d => d.subdomain === subdomain)) {
24
+ throw new Error(`domain(${subdomain}) is not working for user(${user.email}).`)
25
+ }
26
+
27
+ return withFilter(
28
+ () => pubsub.asyncIterator('data-ooc'),
29
+ async (payload, variables, context, info) => {
30
+ const { dataOoc, supervisoryRoleId } = payload
31
+ const { domain } = dataOoc
32
+
33
+ if (subdomain !== domain?.subdomain) {
34
+ return false
35
+ }
36
+
37
+ // check if the user has that role
38
+ const userWithRoles: User = await getRepository(User).findOne({
39
+ where: { id: user.id },
40
+ relations: ['roles']
41
+ })
42
+
43
+ return userWithRoles.roles.find(role => role.id === supervisoryRoleId)
44
+ }
45
+ )(_, args, context, info)
46
+ }
47
+ })
48
+ dataOoc(@Root() payload: { dataOoc: DataOoc; supervisoryRoleId: string }): DataOoc {
49
+ return payload.dataOoc
50
+ }
51
+ }
@@ -1,6 +1,7 @@
1
1
  import { DataOoc } from './data-ooc'
2
2
  import { DataOocMutation } from './data-ooc-mutation'
3
3
  import { DataOocQuery } from './data-ooc-query'
4
+ import { DataOocSubscription } from './data-ooc-subscription'
4
5
 
5
6
  export const entities = [DataOoc]
6
- export const resolvers = [DataOocQuery, DataOocMutation]
7
+ export const resolvers = [DataOocQuery, DataOocMutation, DataOocSubscription]
@@ -1,121 +1,18 @@
1
1
  import { Arg, Ctx, Directive, Mutation, Resolver } from 'type-graphql'
2
2
 
3
- import { DataItem } from '../data-item/data-item'
4
- import { DataSet } from '../data-set/data-set'
5
3
  import { DataSample } from './data-sample'
6
4
  import { NewDataSample } from './data-sample-type'
7
5
 
8
- import moment from 'moment'
9
- import { DataUseCase } from '../../controllers'
10
- import { DataOoc, DataOocStatus } from '../data-ooc/data-ooc'
6
+ import { createDataSample } from '../../controllers/create-data-sample'
11
7
 
12
8
  const debug = require('debug')('things-factory:dataset:data-sample:data-sample-mutation')
13
9
 
14
- // parse variable javascript string pattern
15
- const replaceVariables = (keys, dic) => {
16
- for (const k in keys) {
17
- const matches = keys[k].match(/\$\{\w*\}/g)
18
- matches &&
19
- matches.forEach(m => {
20
- keys[k] = keys[k].replace(m, dic[m.slice(2, -1)])
21
- })
22
- }
23
- return keys
24
- }
25
-
26
- // It is required UTC date for Partitioning File System like AWS S3 from Athena.
27
- // ex) %YYYY, %MM, %DD
28
- const formatDate = (keys, _moment) => {
29
- for (const k in keys) {
30
- const matches = keys[k].match(/%\w*/g)
31
- matches &&
32
- matches.forEach(m => {
33
- keys[k] = keys[k].replace(m, _moment.format(m.substr(1)))
34
- })
35
- }
36
- return keys
37
- }
38
-
39
10
  @Resolver(DataSample)
40
11
  export class DataSampleMutation {
41
12
  @Directive('@privilege(category: "data-sample", privilege: "mutation", domainOwnerGranted: true)')
42
13
  @Directive('@transaction')
43
14
  @Mutation(returns => DataSample, { description: 'To create new data sample' })
44
15
  async createDataSample(@Arg('dataSample') dataSample: NewDataSample, @Ctx() context: any): Promise<DataSample> {
45
- const { domain, user, tx } = context.state
46
-
47
- const dataSet = await tx.getRepository(DataSet).findOne({
48
- where: { id: dataSample.dataSet.id }
49
- })
50
- const dataItems = await tx.getRepository(DataItem).find({
51
- where: {
52
- domain,
53
- dataSet
54
- },
55
- order: {
56
- sequence: 'DESC'
57
- }
58
- })
59
-
60
- const spec = dataItems.reduce((spec, dataItem) => {
61
- spec[dataItem.tag] = {
62
- ...dataItem.spec,
63
- name: dataItem.name /* do we need ? */
64
- }
65
-
66
- return spec
67
- }, {})
68
-
69
- // appending spec to data for reporting and optimizing AWS Athena search
70
- dataSample.data = { ...dataSample.data, _spec: JSON.stringify(spec) }
71
-
72
- var partitionKeys = {
73
- ...dataSet.partitionKeys
74
- }
75
-
76
- const collectedAt = dataSample.collectedAt || new Date()
77
- partitionKeys = formatDate(partitionKeys, moment(collectedAt).utc())
78
- partitionKeys = replaceVariables(partitionKeys, {
79
- domain: domain.subdomain,
80
- dataSetId: dataSample.dataSet.id,
81
- ...dataSample.data
82
- })
83
-
84
- const { ooc, oos } = DataUseCase.evaluate(dataSet, dataItems, dataSample.data) || {}
85
-
86
- const result = await tx.getRepository(DataSample).save({
87
- name: dataSet.name,
88
- description: dataSet.description,
89
- ...dataSample,
90
- domain,
91
- partitionKeys,
92
- spec,
93
- ooc,
94
- oos,
95
- collectedAt,
96
- creator: user,
97
- updater: user
98
- })
99
-
100
- if (ooc || oos) {
101
- await tx.getRepository(DataOoc).save({
102
- name: dataSet.name,
103
- description: dataSet.description,
104
- dataSet,
105
- dataSample: result,
106
- data: dataSample.data,
107
- domain,
108
- partitionKeys,
109
- spec,
110
- ooc,
111
- oos,
112
- state: DataOocStatus.CREATED,
113
- collectedAt,
114
- creator: user,
115
- updater: user
116
- })
117
- }
118
-
119
- return result
16
+ return await createDataSample(dataSample, context)
120
17
  }
121
18
  }
@@ -18,7 +18,7 @@
18
18
  "field.ref-by": "ref. by",
19
19
  "field.serial-no": "serial #",
20
20
  "field.spec": "spec",
21
- "field.state": "state",
21
+ "field.state": "keadaan",
22
22
  "field.supervisory-role": "supervisory role",
23
23
  "field.tag": "tag name",
24
24
  "field.unit": "unit",
@@ -30,4 +30,4 @@
30
30
  "title.data-sample list": "data sample list",
31
31
  "title.data-sensor list": "data sensor list",
32
32
  "title.data-set list": "data set list"
33
- }
33
+ }
@@ -18,7 +18,7 @@
18
18
  "field.ref-by": "ref. by",
19
19
  "field.serial-no": "serial #",
20
20
  "field.spec": "spec",
21
- "field.state": "state",
21
+ "field.state": "状态",
22
22
  "field.supervisory-role": "supervisory role",
23
23
  "field.tag": "tag name",
24
24
  "field.unit": "unit",
@@ -30,4 +30,4 @@
30
30
  "title.data-sample list": "data sample list",
31
31
  "title.data-sensor list": "data sensor list",
32
32
  "title.data-set list": "data set list"
33
- }
33
+ }