@truedat/dd 4.40.13 → 4.41.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.
Files changed (29) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/package.json +6 -6
  3. package/src/api.js +3 -0
  4. package/src/components/DictionaryRoutes.js +17 -1
  5. package/src/components/EditDomainForm.js +37 -24
  6. package/src/components/PendingStructureNoteRow.js +45 -0
  7. package/src/components/PendingStructureNotes.js +149 -0
  8. package/src/components/PendingStructureNotesTable.js +73 -0
  9. package/src/components/StructuresDomainsUploadOption.js +54 -0
  10. package/src/components/StructuresOptions.js +4 -0
  11. package/src/components/__tests__/EditDomainForm.spec.js +2 -0
  12. package/src/components/__tests__/PendingStructureNoteRow.spec.js +48 -0
  13. package/src/components/__tests__/PendingStructureNotes.spec.js +102 -0
  14. package/src/components/__tests__/PendingStructureNotesTable.spec.js +83 -0
  15. package/src/components/__tests__/StructuresOptions.spec.js +6 -1
  16. package/src/components/__tests__/__snapshots__/DictionaryRoutes.spec.js.snap +4 -0
  17. package/src/components/__tests__/__snapshots__/EditDomainForm.spec.js.snap +66 -77
  18. package/src/components/__tests__/__snapshots__/PendingStructureNoteRow.spec.js.snap +35 -0
  19. package/src/components/__tests__/__snapshots__/PendingStructureNotes.spec.js.snap +126 -0
  20. package/src/components/__tests__/__snapshots__/PendingStructureNotesTable.spec.js.snap +123 -0
  21. package/src/components/__tests__/__snapshots__/StructuresOptions.spec.js.snap +14 -0
  22. package/src/messages/en.js +27 -0
  23. package/src/messages/es.js +30 -0
  24. package/src/reducers/__tests__/ddMessage.spec.js +73 -0
  25. package/src/reducers/ddMessage.js +51 -8
  26. package/src/routines.js +3 -0
  27. package/src/sagas/__tests__/uploadStructuresDomains.spec.js +81 -0
  28. package/src/sagas/index.js +3 -0
  29. package/src/sagas/uploadStructuresDomains.js +35 -0
@@ -150,6 +150,15 @@ export default {
150
150
  "navigation.lineage.view": "View in Data Catalog",
151
151
  "navigation.profile.executions": "Executions",
152
152
  "navigation.profile.executions.detail": "Detail",
153
+ "pendingStructureNotes.header": "Pending Notes",
154
+ "pendingStructureNotes.subheader": "Structure notes pending some action",
155
+ "pendingStructureNotes.props.structure": "Data Structure",
156
+ "pendingStructureNotes.props.status": "Status",
157
+ "pendingStructureNotes.props.system": "System",
158
+ "pendingStructureNotes.props.domains": "Domains",
159
+ "pendingStructureNotes.props.path": "Path",
160
+ "pendingStructureNotes.search.results.empty": "No structure notes found",
161
+ "pendingStructureNotes.filters": "Filters",
153
162
  "profile.completed.content": "{count} profiles completed.",
154
163
  "profile.completed.header": "Profiles completed.",
155
164
  "profile.pending.content":
@@ -362,9 +371,13 @@ export default {
362
371
  "structures.actions.new_system": "New system",
363
372
  "structures.actions.upload": "Upload file",
364
373
  "structures.actions.upload.confirmation.content": "Notes",
374
+ "structures.actions.uploadDomains.confirmation.content": "Structure domains",
365
375
  "structures.actions.upload.confirmation.header":
366
376
  "Upload notes file of structures",
377
+ "structures.actions.uploadDomains.confirmation.header":
378
+ "Upload structures domains file",
367
379
  "structures.actions.upload.tooltip": "Upload structure notes",
380
+ "structures.actions.uploadDomains.tooltip": "Update structure domains",
368
381
  "structures.bulkUpdate.crumbs.top": "Bulk update",
369
382
  "structures.bulkUpdate.success.content":
370
383
  "Updated {count} structures successfully",
@@ -382,12 +395,25 @@ export default {
382
395
  "Bulk update completed. Loaded {count_ids} errors {count_errors}",
383
396
  "structures.bulkUpdateStructures.success.errors":
384
397
  "Error in external id {externalId}, message: {message}",
398
+ "structures.bulkUploadStructuresDomains.success.errors.domain: not_exist":
399
+ "Error in line {row}, in external id {externalId}, domain does not exist",
400
+ "structures.bulkUploadStructuresDomains.success.errors.update_domain: forbbiden":
401
+ "Error in line {row}, in external id {externalId}, update forbbiden",
402
+ "structures.bulkUploadStructuresDomains.success.errors.domain_ids: must be a non-empty list":
403
+ "Error in line {row}, in external id {externalId}, domain_ids must be a non-empty list",
404
+ "structures.bulkUploadStructuresDomains.success.errors.structure: not_exist":
405
+ "Error in line {row}, in external id {externalId}, data structure does not exist",
385
406
  "structures.bulkUploadStructures.success.errors":
386
407
  "Error in line {row}, in external id {externalId}, message: {message}",
408
+ "structures.bulkUploadStructuresDomains.success.errors":
409
+ "Error in line {row}, in external id {externalId}, message: {message}",
387
410
  "structures.bulkUpdateStructures.success.unchanged":
388
411
  "{unchanged} structures remained unchanged.",
389
412
  "structures.bulkUpdateStructures.success.updated":
390
413
  "Updated {changed} structures successfully.",
414
+ "structures.bulkUploadStructuresDomains.success.header":
415
+ "Bulk update completed. Loaded {count_ids} errors {count_errors}",
416
+
391
417
  "structures.crumbs.top": "Structures",
392
418
  "structures.edit.bulk.confirmation.content":
393
419
  "{structures_count} structures will be updated. Are you sure?",
@@ -436,6 +462,7 @@ export default {
436
462
  "structures.uploadStructures.failed.external_id_not_exist":
437
463
  "Invalid External Id",
438
464
  "structures.uploadStructures.failed.header": "Upload Failed!",
465
+ "structures.uploadStructuresDomains.failed.header": "Upload Failed!",
439
466
  "structures.uploadStructures.failed.invalid_file_format":
440
467
  "Invalid file format",
441
468
  "structures.uploadStructures.failed.note.df_content.default":
@@ -153,6 +153,16 @@ export default {
153
153
  "navigation.lineage.view": "Ver detalle",
154
154
  "navigation.profile.executions": "Ejecuciones",
155
155
  "navigation.profile.executions.detail": "Detalle",
156
+ "pendingStructureNotes.header": "Notas pendientes",
157
+ "pendingStructureNotes.subheader":
158
+ "Notas de estructuras pendientes de acción",
159
+ "pendingStructureNotes.props.structure": "Estructura",
160
+ "pendingStructureNotes.props.status": "Estado",
161
+ "pendingStructureNotes.props.system": "Sistema",
162
+ "pendingStructureNotes.props.domains": "Dominios",
163
+ "pendingStructureNotes.props.path": "Ruta",
164
+ "pendingStructureNotes.search.results.empty": "Ninguna nota encontrada",
165
+ "pendingStructureNotes.filters": "Filtros",
156
166
  "profile.completed.content": "Se han ejecutado {count} perfilados.",
157
167
  "profile.completed.header": "Ejecuciones finalizadas",
158
168
  "profile.pending.content":
@@ -365,9 +375,15 @@ export default {
365
375
  "structures.actions.new_system": "Nuevo sistema",
366
376
  "structures.actions.upload": "Subir fichero",
367
377
  "structures.actions.upload.confirmation.content": "Notas",
378
+ "structures.actions.uploadDomains.confirmation.content":
379
+ "Dominios de estructuras",
368
380
  "structures.actions.upload.confirmation.header":
369
381
  "Subir fichero de notas de estructuras",
382
+ "structures.actions.uploadDomains.confirmation.header":
383
+ "Subir fichero de dominios de estructuras",
370
384
  "structures.actions.upload.tooltip": "Subir notas de estructuras",
385
+ "structures.actions.uploadDomains.tooltip":
386
+ "Actualizar dominios de estructuras",
371
387
  "structures.bulkUpdate.crumbs.top": "Actualización masiva",
372
388
  "structures.bulkUpdate.success.content":
373
389
  "Se han actualizado {count} estructuras",
@@ -385,12 +401,24 @@ export default {
385
401
  "¡Actualización finalizada! subidos {count_ids} errores {count_errors}",
386
402
  "structures.bulkUpdateStructures.success.errors":
387
403
  "Error en external id {externalId}, mensaje: {message}",
404
+ "structures.bulkUploadStructuresDomains.success.errors.domain: not_exist":
405
+ "Error en linea {row}, en external id {externalId}, el dominio no existe",
406
+ "structures.bulkUploadStructuresDomains.success.errors.structure: not_exist":
407
+ "Error en linea {row}, en external id {externalId}, la estructura no existe",
408
+ "structures.bulkUploadStructuresDomains.success.errors.update_domain: forbbiden":
409
+ "Error en linea {row}, en external id {externalId}, no tiene permisos para actualizar",
410
+ "structures.bulkUploadStructuresDomains.success.errors.domain_ids: must be a non-empty list":
411
+ "Error en linea {row}, en external id {externalId}, domain_ids no puede ser una lista vacia",
388
412
  "structures.bulkUploadStructures.success.errors":
389
413
  "Error en linea {row}, en external id {externalId} mensaje: {message}",
414
+ "structures.bulkUploadStructuresDomains.success.errors":
415
+ "Error en linea {row}, en external id {externalId} mensaje: {message}",
390
416
  "structures.bulkUpdateStructures.success.unchanged":
391
417
  "{unchanged} se han mantenido sin cambios.",
392
418
  "structures.bulkUpdateStructures.success.updated":
393
419
  "Se han actualizado {changed} estructuras.",
420
+ "structures.bulkUploadStructuresDomains.success.header":
421
+ "¡Actualización finalizada! subidos {count_ids} errores {count_errors}",
394
422
  "structures.crumbs.top": "Estructuras",
395
423
  "structures.edit.bulk.confirmation.content":
396
424
  "Se van a actualizar {structures_count} estructuras. ¿Estás seguro?",
@@ -443,6 +471,8 @@ export default {
443
471
  "External Id Inválido",
444
472
  "structures.uploadStructures.failed.header":
445
473
  "Error al subir el fichero. El contenido no se ha actualizado",
474
+ "structures.uploadStructuresDomains.failed.header":
475
+ "Error al subir el fichero. El contenido no se ha actualizado",
446
476
  "structures.uploadStructures.failed.invalid_file_format":
447
477
  "Formato de fichero inválido",
448
478
  "structures.uploadStructures.failed.note.df_content.default":
@@ -0,0 +1,73 @@
1
+ import { uploadStructuresDomains } from "../../routines";
2
+ import { ddMessage } from "..";
3
+
4
+ const fooState = { foo: "bar" };
5
+
6
+ describe("reducers: ddMessage", () => {
7
+ const initialState = null;
8
+
9
+ it("should provide the initial state", () => {
10
+ expect(ddMessage(undefined, {})).toEqual(initialState);
11
+ });
12
+
13
+ it("should handle the uploadStructuresDomains.SUCCESS action returning some errored rows", () => {
14
+ const ddMsg = ddMessage(fooState, {
15
+ type: uploadStructuresDomains.SUCCESS,
16
+ payload: {
17
+ data: {
18
+ errors: [
19
+ {
20
+ external_id:
21
+ "postgres://Postgres-Test/postgres/public/city/city_id",
22
+ message: {
23
+ external_domain_ids: ["must exist: UEUEUEU"],
24
+ },
25
+ row: 3,
26
+ },
27
+ {
28
+ external_id:
29
+ "postgres://Postgres-Test/postgres/public/city/city_name",
30
+ message: {
31
+ external_domain_ids: ["must exist: NANDAKA, JAJAJA"],
32
+ },
33
+ row: 4,
34
+ },
35
+ ],
36
+ ids: [5375339],
37
+ },
38
+ },
39
+ });
40
+
41
+ expect(ddMsg).toMatchObject({
42
+ error: false,
43
+ header: "structures.bulkUploadStructuresDomains.success.header",
44
+ icon: "check",
45
+ color: "orange",
46
+ fields: { count_errors: 2, count_ids: 1 },
47
+ });
48
+ const { messages: errors } = ddMsg;
49
+ expect(errors.length).toEqual(2);
50
+ });
51
+
52
+ it("should handle the uploadStructuresDomains.FAILURE action", () => {
53
+ const ddMsg = ddMessage(fooState, {
54
+ type: uploadStructuresDomains.FAILURE,
55
+ payload: {
56
+ status: 422,
57
+ data: {
58
+ error: {
59
+ message:
60
+ "invalid_headers, must be: external_id, domain_external_ids",
61
+ },
62
+ },
63
+ },
64
+ });
65
+
66
+ expect(ddMsg).toMatchObject({
67
+ error: true,
68
+ header: "structures.uploadStructuresDomains.failed.header",
69
+ icon: "attention",
70
+ content: "invalid_headers, must be: external_id, domain_external_ids",
71
+ });
72
+ });
73
+ });
@@ -4,6 +4,7 @@ import {
4
4
  bulkUpdateStructures,
5
5
  uploadStructures,
6
6
  updateStructureType,
7
+ uploadStructuresDomains,
7
8
  } from "../routines";
8
9
 
9
10
  const initialState = null;
@@ -18,10 +19,7 @@ const ddMessage = (state = initialState, { type, payload }) => {
18
19
  ? _.flow(
19
20
  _.propOr([], "errors"),
20
21
  _.map((error) => ({
21
- id:
22
- type == bulkUpdateStructures.SUCCESS
23
- ? `structures.bulkUpdateStructures.failed.note.${error.message}`
24
- : `structures.uploadStructures.failed.note.${error.message}`,
22
+ id: `structures.bulkUpdateStructures.failed.note.${error.message}`,
25
23
  fields: {
26
24
  row: error.row,
27
25
  id: error.id,
@@ -29,10 +27,7 @@ const ddMessage = (state = initialState, { type, payload }) => {
29
27
  externalId: error.external_id,
30
28
  message: error.message,
31
29
  },
32
- defaultMessage:
33
- type == bulkUpdateStructures.SUCCESS
34
- ? "structures.bulkUpdateStructures.success.errors"
35
- : "structures.bulkUploadStructures.success.errors",
30
+ defaultMessage: "structures.bulkUploadStructures.success.errors",
36
31
  }))
37
32
  )(payload.data)
38
33
  : "";
@@ -51,6 +46,54 @@ const ddMessage = (state = initialState, { type, payload }) => {
51
46
  initialMaxListItems: 5,
52
47
  };
53
48
  }
49
+
50
+ case uploadStructuresDomains.SUCCESS: {
51
+ const messagesImp = _.has("errors")(payload.data)
52
+ ? _.flow(
53
+ _.propOr([], "errors"),
54
+ _.map((error) => {
55
+ const errorMessage = Object.entries(error.message)
56
+ .map(([field, messages]) => `${field}: ${messages.join(", ")}`)
57
+ .join(" | ");
58
+ return {
59
+ id: `structures.bulkUploadStructuresDomains.success.errors.${errorMessage}`,
60
+ fields: {
61
+ row: error.row,
62
+ id: error.id,
63
+ field: error.field,
64
+ externalId: error.external_id,
65
+ message: errorMessage,
66
+ },
67
+ };
68
+ })
69
+ )(payload.data)
70
+ : "";
71
+ return {
72
+ error: false,
73
+ header: "structures.bulkUploadStructuresDomains.success.header",
74
+ icon: "check",
75
+ color: payload.data.errors.length >= 1 ? "orange" : "green",
76
+ text: "",
77
+ messages: messagesImp,
78
+ fields: {
79
+ count_ids: payload.data.ids.length,
80
+ count_errors: payload.data.errors.length,
81
+ },
82
+ downloadable: true,
83
+ initialMaxListItems: 5,
84
+ };
85
+ }
86
+
87
+ case uploadStructuresDomains.FAILURE:
88
+ return payload.status !== 422
89
+ ? state
90
+ : {
91
+ error: true,
92
+ header: "structures.uploadStructuresDomains.failed.header",
93
+ icon: "attention",
94
+ content: payload?.data?.error?.message,
95
+ };
96
+
54
97
  case updateStructureType.SUCCESS:
55
98
  return {
56
99
  error: false,
package/src/routines.js CHANGED
@@ -132,6 +132,9 @@ export const updateStructureTag = createRoutine("UPDATE_STRUCTURE_TAG");
132
132
  export const updateStructureType = createRoutine("UPDATE_STRUCTURE_TYPE");
133
133
  export const updateSystem = createRoutine("UPDATE_SYSTEM");
134
134
  export const uploadStructures = createRoutine("UPLOAD_STRUCTURES");
135
+ export const uploadStructuresDomains = createRoutine(
136
+ "UPLOAD_STRUCTURES_DOMAINS"
137
+ );
135
138
  export const addGrantRequestToCart = createRoutine("ADD_GRANT_REQUEST_TO_CART");
136
139
  export const removeGrantRequestFromCart = createRoutine(
137
140
  "REMOVE_GRANT_REQUEST_FROM_CART"
@@ -0,0 +1,81 @@
1
+ import { testSaga } from "redux-saga-test-plan";
2
+ import { apiJsonPost, UPLOAD_JSON_OPTS } from "@truedat/core/services/api";
3
+ import {
4
+ uploadStructuresDomainsRequestSaga,
5
+ uploadStructuresDomainsSaga,
6
+ } from "../uploadStructuresDomains";
7
+ import { uploadStructuresDomains } from "../../routines";
8
+ import { API_STRUCTURES_DOMAINS_UPLOAD } from "../../api";
9
+
10
+ describe("sagas: uploadStructuresDomainsRequestSaga", () => {
11
+ it("should invoke uploadStructuresDomainsSaga on trigger", () => {
12
+ expect(() => {
13
+ testSaga(uploadStructuresDomainsRequestSaga)
14
+ .next()
15
+ .takeLatest(
16
+ uploadStructuresDomains.TRIGGER,
17
+ uploadStructuresDomainsSaga
18
+ )
19
+ .finish()
20
+ .isDone();
21
+ }).not.toThrow();
22
+ });
23
+
24
+ it("should throw exception if an unhandled action is received", () => {
25
+ expect(() => {
26
+ testSaga(uploadStructuresDomainsRequestSaga)
27
+ .next()
28
+ .takeLatest("FOO", uploadStructuresDomainsSaga);
29
+ }).toThrow();
30
+ });
31
+ });
32
+
33
+ describe("sagas: uploadStructuresDomainsSaga", () => {
34
+ const body = { structures_domains: "content" };
35
+ const payload = { data: body };
36
+ const data = { message: [1, 2] };
37
+ it("should put a success action when a response is returned", () => {
38
+ expect(() => {
39
+ testSaga(uploadStructuresDomainsSaga, { payload })
40
+ .next()
41
+ .put(uploadStructuresDomains.request())
42
+ .next()
43
+ .call(
44
+ apiJsonPost,
45
+ API_STRUCTURES_DOMAINS_UPLOAD,
46
+ body,
47
+ UPLOAD_JSON_OPTS
48
+ )
49
+ .next({ data })
50
+ .put(uploadStructuresDomains.success({ data }))
51
+ .next()
52
+ .put(uploadStructuresDomains.fulfill())
53
+ .next()
54
+ .isDone();
55
+ }).not.toThrow();
56
+ });
57
+
58
+ it("should put a failure action when the call returns an error", () => {
59
+ const message = "Request failed";
60
+ const error = { message };
61
+
62
+ expect(() => {
63
+ testSaga(uploadStructuresDomainsSaga, { payload })
64
+ .next()
65
+ .put(uploadStructuresDomains.request())
66
+ .next()
67
+ .call(
68
+ apiJsonPost,
69
+ API_STRUCTURES_DOMAINS_UPLOAD,
70
+ body,
71
+ UPLOAD_JSON_OPTS
72
+ )
73
+ .throw(error)
74
+ .put(uploadStructuresDomains.failure(message))
75
+ .next()
76
+ .put(uploadStructuresDomains.fulfill())
77
+ .next()
78
+ .isDone();
79
+ }).not.toThrow();
80
+ });
81
+ });
@@ -46,6 +46,7 @@ import { updateStructureTagRequestSaga } from "./updateStructureTag";
46
46
  import { updateStructureTypeRequestSaga } from "./updateStructureType";
47
47
  import { updateSystemRequestSaga } from "./updateSystem";
48
48
  import { uploadStructuresRequestSaga } from "./uploadStructures";
49
+ import { uploadStructuresDomainsRequestSaga } from "./uploadStructuresDomains";
49
50
  import { operateGrantRequestToCartRequestSaga } from "./operateGrantRequestCart";
50
51
 
51
52
  export {
@@ -97,6 +98,7 @@ export {
97
98
  updateStructureTypeRequestSaga,
98
99
  updateSystemRequestSaga,
99
100
  uploadStructuresRequestSaga,
101
+ uploadStructuresDomainsRequestSaga,
100
102
  operateGrantRequestToCartRequestSaga,
101
103
  };
102
104
 
@@ -149,5 +151,6 @@ export default [
149
151
  updateStructureTypeRequestSaga(),
150
152
  updateSystemRequestSaga(),
151
153
  uploadStructuresRequestSaga(),
154
+ uploadStructuresDomainsRequestSaga(),
152
155
  operateGrantRequestToCartRequestSaga(),
153
156
  ];
@@ -0,0 +1,35 @@
1
+ import { call, put, takeLatest } from "redux-saga/effects";
2
+ import { apiJsonPost, UPLOAD_JSON_OPTS } from "@truedat/core/services/api";
3
+ import { uploadStructuresDomains } from "../routines";
4
+ import { API_STRUCTURES_DOMAINS_UPLOAD } from "../api";
5
+
6
+ export function* uploadStructuresDomainsSaga({ payload }) {
7
+ try {
8
+ const { data: body } = payload;
9
+ yield put(uploadStructuresDomains.request());
10
+ const { data } = yield call(
11
+ apiJsonPost,
12
+ API_STRUCTURES_DOMAINS_UPLOAD,
13
+ body,
14
+ UPLOAD_JSON_OPTS
15
+ );
16
+
17
+ yield put(uploadStructuresDomains.success({ data }));
18
+ } catch (error) {
19
+ if (error.response) {
20
+ const { status, data } = error.response;
21
+ yield put(uploadStructuresDomains.failure({ status, data }));
22
+ } else {
23
+ yield put(uploadStructuresDomains.failure(error.message));
24
+ }
25
+ } finally {
26
+ yield put(uploadStructuresDomains.fulfill());
27
+ }
28
+ }
29
+
30
+ export function* uploadStructuresDomainsRequestSaga() {
31
+ yield takeLatest(
32
+ uploadStructuresDomains.TRIGGER,
33
+ uploadStructuresDomainsSaga
34
+ );
35
+ }