@truedat/dd 7.2.3 → 7.2.5
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/package.json +6 -6
- package/src/api.js +4 -2
- package/src/components/StructuresDownloadOption.js +23 -20
- package/src/components/StructuresEditableDownloadOption.js +23 -21
- package/src/components/StructuresOptions.js +27 -24
- package/src/components/StructuresUploadEventsTable.js +3 -2
- package/src/components/StructuresUploadOption.js +18 -23
- package/src/components/StructuresView.js +1 -1
- package/src/components/__tests__/StructuresDownloadOption.spec.js +12 -12
- package/src/components/__tests__/StructuresEditableDownloadOption.spec.js +8 -8
- package/src/components/__tests__/StructuresUploadEventsTable.spec.js +2 -2
- package/src/components/__tests__/StructuresUploadOption.spec.js +2 -5
- package/src/components/__tests__/__snapshots__/StructuresDownloadOption.spec.js.snap +2 -1
- package/src/components/__tests__/__snapshots__/StructuresEditableDownloadOption.spec.js.snap +2 -7
- package/src/components/__tests__/__snapshots__/StructuresOptions.spec.js.snap +3 -0
- package/src/components/__tests__/__snapshots__/StructuresUploadOption.spec.js.snap +2 -0
- package/src/hooks/useStructures.js +34 -1
- package/src/reducers/__tests__/structuresUploadEvents.spec.js +2 -2
- package/src/reducers/index.js +0 -6
- package/src/routines.js +0 -4
- package/src/sagas/__tests__/fetchStructuresUploadEvents.spec.js +2 -2
- package/src/sagas/index.js +0 -9
- package/src/reducers/__tests__/structuresDownloading.spec.js +0 -26
- package/src/reducers/__tests__/structuresEditableDownloading.spec.js +0 -32
- package/src/reducers/__tests__/uploadingStructuresFile.spec.js +0 -40
- package/src/reducers/structuresDownloading.js +0 -14
- package/src/reducers/structuresEditableDownloading.js +0 -14
- package/src/reducers/uploadingStructuresFile.js +0 -18
- package/src/sagas/__tests__/downloadEditableStructures.spec.js +0 -81
- package/src/sagas/__tests__/downloadStructures.spec.js +0 -82
- package/src/sagas/__tests__/uploadStructures.spec.js +0 -70
- package/src/sagas/downloadEditableStructures.js +0 -51
- package/src/sagas/downloadStructures.js +0 -51
- package/src/sagas/uploadStructures.js +0 -33
|
@@ -2,11 +2,19 @@ import _ from "lodash/fp";
|
|
|
2
2
|
import { compile } from "path-to-regexp";
|
|
3
3
|
import useSWR from "swr";
|
|
4
4
|
import useSWRMutations from "swr/mutation";
|
|
5
|
-
import
|
|
5
|
+
import FileSaver from "file-saver";
|
|
6
|
+
import {
|
|
7
|
+
apiJson,
|
|
8
|
+
apiJsonPost,
|
|
9
|
+
JSON_OPTS,
|
|
10
|
+
UPLOAD_JSON_OPTS,
|
|
11
|
+
} from "@truedat/core/services/api";
|
|
6
12
|
import {
|
|
7
13
|
API_SYSTEM_STRUCTURES,
|
|
8
14
|
API_DATA_STRUCTURES_SEARCH,
|
|
9
15
|
API_DATA_STRUCTURE_FILTERS_SEARCH,
|
|
16
|
+
API_DATA_STRUCTURES_XLSX_DOWNLOAD,
|
|
17
|
+
API_DATA_STRUCTURES_XLSX_UPLOAD,
|
|
10
18
|
} from "../api";
|
|
11
19
|
|
|
12
20
|
const toApiPath = compile(API_SYSTEM_STRUCTURES);
|
|
@@ -25,6 +33,15 @@ const asQueryParams = (queryParams) => {
|
|
|
25
33
|
return _.isEmpty(stringifyQueryParams) ? "" : `?${stringifyQueryParams}`;
|
|
26
34
|
};
|
|
27
35
|
|
|
36
|
+
function saveFile({ data, headers }) {
|
|
37
|
+
const contentDisposition = headers["content-disposition"];
|
|
38
|
+
const regex = /filename=(.+)$/;
|
|
39
|
+
const match = regex.exec(contentDisposition);
|
|
40
|
+
const fileName = match ? match[1] : "structures.xlsx";
|
|
41
|
+
|
|
42
|
+
FileSaver.saveAs(data, fileName);
|
|
43
|
+
}
|
|
44
|
+
|
|
28
45
|
export const useStructures = (args) => {
|
|
29
46
|
const url = toApiPath({ id: args.systemId });
|
|
30
47
|
const requestData = () => apiJson(`${url}${asQueryParams(args)}`);
|
|
@@ -55,3 +72,19 @@ export const useDataStructureSearch = () => {
|
|
|
55
72
|
return apiJsonPost(url, arg);
|
|
56
73
|
});
|
|
57
74
|
};
|
|
75
|
+
|
|
76
|
+
export const useDataStructureDownload = () => {
|
|
77
|
+
return useSWRMutations(API_DATA_STRUCTURES_XLSX_DOWNLOAD, (url, { arg }) => {
|
|
78
|
+
return apiJsonPost(url, arg, { ...JSON_OPTS, responseType: "blob" }).then(
|
|
79
|
+
({ data, headers }) => {
|
|
80
|
+
saveFile({ data, headers });
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
});
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const useDataStructureUpload = () => {
|
|
87
|
+
return useSWRMutations(API_DATA_STRUCTURES_XLSX_UPLOAD, (url, { arg }) => {
|
|
88
|
+
return apiJsonPost(url, arg, UPLOAD_JSON_OPTS);
|
|
89
|
+
});
|
|
90
|
+
};
|
|
@@ -13,7 +13,7 @@ describe("reducers: structuresUploadEvents", () => {
|
|
|
13
13
|
it("should handle the fetchStructuresUploadEvents.SUCCESS action", () => {
|
|
14
14
|
const someEvents = [
|
|
15
15
|
{
|
|
16
|
-
|
|
16
|
+
hash: "99E400B91D164F8F0A39F400CA323C8F",
|
|
17
17
|
inserted_at: "2022-04-23T15:53:24.638484Z",
|
|
18
18
|
message: null,
|
|
19
19
|
response: {},
|
|
@@ -22,7 +22,7 @@ describe("reducers: structuresUploadEvents", () => {
|
|
|
22
22
|
user_id: 467,
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
|
-
|
|
25
|
+
hash: "47D90FDF1AD967BD7DBBDAE28664278E",
|
|
26
26
|
inserted_at: "2022-04-23T15:14:48.770275Z",
|
|
27
27
|
message: null,
|
|
28
28
|
response: {},
|
package/src/reducers/index.js
CHANGED
|
@@ -58,8 +58,6 @@ import { structureQuery } from "./structureQuery";
|
|
|
58
58
|
import { structureRedirect } from "./structureRedirect";
|
|
59
59
|
import { structures } from "./structures";
|
|
60
60
|
import { structuresAliasNameMode } from "./structuresAliasNameMode";
|
|
61
|
-
import { structuresDownloading } from "./structuresDownloading";
|
|
62
|
-
import { structuresEditableDownloading } from "./structuresEditableDownloading";
|
|
63
61
|
import { structureSiblings } from "./structureSiblings";
|
|
64
62
|
import { structuresSiblings } from "./structureSiblings";
|
|
65
63
|
import { structuresUploadEvents } from "./structuresUploadEvents";
|
|
@@ -80,7 +78,6 @@ import { systemsLoading } from "./systemsLoading";
|
|
|
80
78
|
import { systemStructures } from "./systemStructures";
|
|
81
79
|
import { systemStructuresLoading } from "./systemStructuresLoading";
|
|
82
80
|
import { tagSaving } from "./tagSaving";
|
|
83
|
-
import { uploadingStructuresFile } from "./uploadingStructuresFile";
|
|
84
81
|
import { userPermissions } from "./userPermissions";
|
|
85
82
|
import { userSearchFilters } from "./userSearchFilters";
|
|
86
83
|
|
|
@@ -145,8 +142,6 @@ export {
|
|
|
145
142
|
structureRedirect,
|
|
146
143
|
structures,
|
|
147
144
|
structuresAliasNameMode,
|
|
148
|
-
structuresDownloading,
|
|
149
|
-
structuresEditableDownloading,
|
|
150
145
|
structuresFields,
|
|
151
146
|
structureSiblings,
|
|
152
147
|
structuresSiblings,
|
|
@@ -169,7 +164,6 @@ export {
|
|
|
169
164
|
systemStructures,
|
|
170
165
|
systemStructuresLoading,
|
|
171
166
|
tagSaving,
|
|
172
|
-
uploadingStructuresFile,
|
|
173
167
|
userPermissions,
|
|
174
168
|
userSearchFilters,
|
|
175
169
|
};
|
package/src/routines.js
CHANGED
|
@@ -72,14 +72,10 @@ export const deleteUserSearchFilter = createRoutine(
|
|
|
72
72
|
);
|
|
73
73
|
export const doStructureNoteAction = createRoutine("DO_STRUCTURE_NOTE_ACTION");
|
|
74
74
|
export const downloadCsvGraph = createRoutine("DOWNLOAD_CSV_GRAPH");
|
|
75
|
-
export const downloadEditableStructures = createRoutine(
|
|
76
|
-
"DOWNLOAD_EDITABLE_STRUCTURES"
|
|
77
|
-
);
|
|
78
75
|
export const downloadGrants = createRoutine("DOWNLOAD_GRANTS");
|
|
79
76
|
export const downloadReferenceDataset = createRoutine(
|
|
80
77
|
"DOWNLOAD_REFERENCE_DATASET"
|
|
81
78
|
);
|
|
82
|
-
export const downloadStructures = createRoutine("DOWNLOAD_STRUCTURES");
|
|
83
79
|
export const excludeNode = createRoutine("EXCLUDE_NODE");
|
|
84
80
|
export const fetchGrant = createRoutine("FETCH_GRANT");
|
|
85
81
|
export const fetchGrantFilters = createRoutine("FETCH_GRANT_FILTERS");
|
|
@@ -35,10 +35,10 @@ describe("sagas: fetchStructuresUploadEventsSaga", () => {
|
|
|
35
35
|
const url = API_STRUCTURES_UPLOAD_EVENTS;
|
|
36
36
|
const data = [
|
|
37
37
|
{
|
|
38
|
-
|
|
38
|
+
hash: "99E400B91D164F8F0A39F400CA323C8F",
|
|
39
39
|
},
|
|
40
40
|
{
|
|
41
|
-
|
|
41
|
+
hash: "47D90FDF1AD967BD7DBBDAE28664278E",
|
|
42
42
|
},
|
|
43
43
|
];
|
|
44
44
|
|
package/src/sagas/index.js
CHANGED
|
@@ -18,10 +18,8 @@ import { deleteTagRequestSaga } from "./deleteTag";
|
|
|
18
18
|
import { deleteUserSearchFilterRequestSaga } from "./deleteUserSearchFilter";
|
|
19
19
|
import { doStructureNoteActionRequestSaga } from "./doStructureNoteAction";
|
|
20
20
|
import { downloadCsvGraphRequestSaga } from "./downloadCsvGraph";
|
|
21
|
-
import { downloadEditableStructuresRequestSaga } from "./downloadEditableStructures";
|
|
22
21
|
import { downloadGrantsRequestSaga } from "./downloadGrants";
|
|
23
22
|
import { downloadReferenceDatasetRequestSaga } from "./downloadReferenceDataset";
|
|
24
|
-
import { downloadStructuresRequestSaga } from "./downloadStructures";
|
|
25
23
|
import { fetchGrantFiltersRequestSaga } from "./fetchGrantFilters";
|
|
26
24
|
import { fetchGrantRequestsFiltersRequestSaga } from "./fetchGrantRequestsFilters";
|
|
27
25
|
import { fetchGrantRequestRequestSaga } from "./fetchGrantRequest";
|
|
@@ -54,7 +52,6 @@ import { updateStructureRequestSaga } from "./updateStructure";
|
|
|
54
52
|
import { updateStructureTypeRequestSaga } from "./updateStructureType";
|
|
55
53
|
import { updateSystemRequestSaga } from "./updateSystem";
|
|
56
54
|
import { uploadStructuresDomainsRequestSaga } from "./uploadStructuresDomains";
|
|
57
|
-
import { uploadStructuresRequestSaga } from "./uploadStructures";
|
|
58
55
|
import { updateTagRequestSaga } from "./updateTag";
|
|
59
56
|
import { upsertCatalogViewConfigRequestSaga } from "./upsertCatalogViewConfig";
|
|
60
57
|
|
|
@@ -79,10 +76,8 @@ export {
|
|
|
79
76
|
deleteUserSearchFilterRequestSaga,
|
|
80
77
|
doStructureNoteActionRequestSaga,
|
|
81
78
|
downloadCsvGraphRequestSaga,
|
|
82
|
-
downloadEditableStructuresRequestSaga,
|
|
83
79
|
downloadGrantsRequestSaga,
|
|
84
80
|
downloadReferenceDatasetRequestSaga,
|
|
85
|
-
downloadStructuresRequestSaga,
|
|
86
81
|
fetchGrantFiltersRequestSaga,
|
|
87
82
|
fetchGrantRequestRequestSaga,
|
|
88
83
|
fetchGrantRequestsFiltersRequestSaga,
|
|
@@ -115,7 +110,6 @@ export {
|
|
|
115
110
|
updateStructureTypeRequestSaga,
|
|
116
111
|
updateSystemRequestSaga,
|
|
117
112
|
uploadStructuresDomainsRequestSaga,
|
|
118
|
-
uploadStructuresRequestSaga,
|
|
119
113
|
updateTagRequestSaga,
|
|
120
114
|
upsertCatalogViewConfigRequestSaga,
|
|
121
115
|
};
|
|
@@ -141,10 +135,8 @@ export default [
|
|
|
141
135
|
deleteUserSearchFilterRequestSaga(),
|
|
142
136
|
doStructureNoteActionRequestSaga(),
|
|
143
137
|
downloadCsvGraphRequestSaga(),
|
|
144
|
-
downloadEditableStructuresRequestSaga(),
|
|
145
138
|
downloadGrantsRequestSaga(),
|
|
146
139
|
downloadReferenceDatasetRequestSaga(),
|
|
147
|
-
downloadStructuresRequestSaga(),
|
|
148
140
|
fetchGrantFiltersRequestSaga(),
|
|
149
141
|
fetchGrantRequestRequestSaga(),
|
|
150
142
|
fetchGrantRequestsRequestSaga(),
|
|
@@ -178,6 +170,5 @@ export default [
|
|
|
178
170
|
updateStructureTypeRequestSaga(),
|
|
179
171
|
updateSystemRequestSaga(),
|
|
180
172
|
uploadStructuresDomainsRequestSaga(),
|
|
181
|
-
uploadStructuresRequestSaga(),
|
|
182
173
|
upsertCatalogViewConfigRequestSaga(),
|
|
183
174
|
];
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { downloadStructures } from "../../routines";
|
|
2
|
-
import { structuresDownloading } from "..";
|
|
3
|
-
|
|
4
|
-
const fooState = { foo: "bar" };
|
|
5
|
-
|
|
6
|
-
describe("reducers: structuresDownloading", () => {
|
|
7
|
-
it("should provide the initial state", () => {
|
|
8
|
-
expect(structuresDownloading(undefined, {})).toBe(false);
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it("should be true after receiving the downloadStructures.TRIGGER action", () => {
|
|
12
|
-
expect(
|
|
13
|
-
structuresDownloading(fooState, { type: downloadStructures.TRIGGER })
|
|
14
|
-
).toBe(true);
|
|
15
|
-
});
|
|
16
|
-
|
|
17
|
-
it("should be false after receiving the downloadStructures.FULFILL action", () => {
|
|
18
|
-
expect(
|
|
19
|
-
structuresDownloading(fooState, { type: downloadStructures.FULFILL })
|
|
20
|
-
).toBe(false);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("should ignore unhandled actions", () => {
|
|
24
|
-
expect(structuresDownloading(fooState, { type: "FOO" })).toBe(fooState);
|
|
25
|
-
});
|
|
26
|
-
});
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { downloadEditableStructures } from "../../routines";
|
|
2
|
-
import { structuresEditableDownloading } from "..";
|
|
3
|
-
|
|
4
|
-
const fooState = { foo: "bar" };
|
|
5
|
-
|
|
6
|
-
describe("reducers: structuresEditableDownloading", () => {
|
|
7
|
-
it("should provide the initial state", () => {
|
|
8
|
-
expect(structuresEditableDownloading(undefined, {})).toBe(false);
|
|
9
|
-
});
|
|
10
|
-
|
|
11
|
-
it("should be true after receiving the downloadEditableStructures.TRIGGER action", () => {
|
|
12
|
-
expect(
|
|
13
|
-
structuresEditableDownloading(fooState, {
|
|
14
|
-
type: downloadEditableStructures.TRIGGER,
|
|
15
|
-
})
|
|
16
|
-
).toBe(true);
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
it("should be false after receiving the downloadEditableStructures.FULFILL action", () => {
|
|
20
|
-
expect(
|
|
21
|
-
structuresEditableDownloading(fooState, {
|
|
22
|
-
type: downloadEditableStructures.FULFILL,
|
|
23
|
-
})
|
|
24
|
-
).toBe(false);
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
it("should ignore unhandled actions", () => {
|
|
28
|
-
expect(structuresEditableDownloading(fooState, { type: "FOO" })).toBe(
|
|
29
|
-
fooState
|
|
30
|
-
);
|
|
31
|
-
});
|
|
32
|
-
});
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import { uploadStructures } from "../../routines";
|
|
2
|
-
import { uploadingStructuresFile } from "..";
|
|
3
|
-
|
|
4
|
-
const fooState = { foo: "bar" };
|
|
5
|
-
|
|
6
|
-
describe("reducers: system", () => {
|
|
7
|
-
const initialState = false;
|
|
8
|
-
|
|
9
|
-
it("should provide the initial state", () => {
|
|
10
|
-
expect(uploadingStructuresFile(undefined, {})).toEqual(initialState);
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
it("should handle the uploadStructures.TRIGGER action", () => {
|
|
14
|
-
expect(
|
|
15
|
-
uploadingStructuresFile(fooState, {
|
|
16
|
-
type: uploadStructures.TRIGGER
|
|
17
|
-
})
|
|
18
|
-
).toBe(true);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("should handle the uploadStructures.TRIGGER action", () => {
|
|
22
|
-
expect(
|
|
23
|
-
uploadingStructuresFile(fooState, {
|
|
24
|
-
type: uploadStructures.REQUEST
|
|
25
|
-
})
|
|
26
|
-
).toBe(true);
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
it("should handle the uploadStructures.TRIGGER action", () => {
|
|
30
|
-
expect(
|
|
31
|
-
uploadingStructuresFile(fooState, {
|
|
32
|
-
type: uploadStructures.FULFILL
|
|
33
|
-
})
|
|
34
|
-
).toBe(false);
|
|
35
|
-
});
|
|
36
|
-
|
|
37
|
-
it("should ignore unknown actions", () => {
|
|
38
|
-
expect(uploadingStructuresFile(fooState, { type: "FOO" })).toBe(fooState);
|
|
39
|
-
});
|
|
40
|
-
});
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { downloadStructures } from "../routines";
|
|
2
|
-
|
|
3
|
-
const structuresDownloading = (state = false, { type }) => {
|
|
4
|
-
switch (type) {
|
|
5
|
-
case downloadStructures.TRIGGER:
|
|
6
|
-
return true;
|
|
7
|
-
case downloadStructures.FULFILL:
|
|
8
|
-
return false;
|
|
9
|
-
default:
|
|
10
|
-
return state;
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export { structuresDownloading };
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import { downloadEditableStructures } from "../routines";
|
|
2
|
-
|
|
3
|
-
const structuresEditableDownloading = (state = false, { type }) => {
|
|
4
|
-
switch (type) {
|
|
5
|
-
case downloadEditableStructures.TRIGGER:
|
|
6
|
-
return true;
|
|
7
|
-
case downloadEditableStructures.FULFILL:
|
|
8
|
-
return false;
|
|
9
|
-
default:
|
|
10
|
-
return state;
|
|
11
|
-
}
|
|
12
|
-
};
|
|
13
|
-
|
|
14
|
-
export { structuresEditableDownloading };
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { uploadStructures } from "../routines";
|
|
2
|
-
|
|
3
|
-
const initialState = false;
|
|
4
|
-
|
|
5
|
-
export const uploadingStructuresFile = (state = initialState, { type }) => {
|
|
6
|
-
switch (type) {
|
|
7
|
-
case uploadStructures.TRIGGER:
|
|
8
|
-
return true;
|
|
9
|
-
case uploadStructures.REQUEST:
|
|
10
|
-
return true;
|
|
11
|
-
case uploadStructures.FULFILL:
|
|
12
|
-
return false;
|
|
13
|
-
default:
|
|
14
|
-
return state;
|
|
15
|
-
}
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export default uploadingStructuresFile;
|
|
@@ -1,81 +0,0 @@
|
|
|
1
|
-
import { testSaga } from "redux-saga-test-plan";
|
|
2
|
-
import { apiJsonPost, JSON_OPTS } from "@truedat/core/services/api";
|
|
3
|
-
import {
|
|
4
|
-
downloadEditableStructuresRequestSaga,
|
|
5
|
-
downloadEditableStructuresSaga,
|
|
6
|
-
saveFile,
|
|
7
|
-
} from "../downloadEditableStructures";
|
|
8
|
-
import { downloadEditableStructures } from "../../routines";
|
|
9
|
-
import { API_DATA_STRUCTURES_EDITABLE_CSV } from "../../api";
|
|
10
|
-
|
|
11
|
-
describe("sagas: downloadEditableStructuresRequestSaga", () => {
|
|
12
|
-
it("should invoke downloadEditableStructuresSaga on downloadEditableStructures.TRIGGER", () => {
|
|
13
|
-
expect(() => {
|
|
14
|
-
testSaga(downloadEditableStructuresRequestSaga)
|
|
15
|
-
.next()
|
|
16
|
-
.takeLatest(
|
|
17
|
-
downloadEditableStructures.TRIGGER,
|
|
18
|
-
downloadEditableStructuresSaga
|
|
19
|
-
)
|
|
20
|
-
.finish()
|
|
21
|
-
.isDone();
|
|
22
|
-
}).not.toThrow();
|
|
23
|
-
});
|
|
24
|
-
|
|
25
|
-
it("should throw exception if an unhandled action is received", () => {
|
|
26
|
-
expect(() => {
|
|
27
|
-
testSaga(downloadEditableStructuresRequestSaga)
|
|
28
|
-
.next()
|
|
29
|
-
.takeLatest("FOO", downloadEditableStructuresRequestSaga);
|
|
30
|
-
}).toThrow();
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
describe("sagas: downloadEditableStructuresSaga", () => {
|
|
35
|
-
const lang = "es";
|
|
36
|
-
const query = { filters: {} };
|
|
37
|
-
const payload = { lang, searchParams: query };
|
|
38
|
-
const body = {
|
|
39
|
-
structure_url_schema: "http://localhost/structures/:id",
|
|
40
|
-
...query,
|
|
41
|
-
lang,
|
|
42
|
-
};
|
|
43
|
-
const data = "SOME CSV DATA";
|
|
44
|
-
|
|
45
|
-
it("should put a success action when a response is returned", () => {
|
|
46
|
-
expect(() => {
|
|
47
|
-
testSaga(downloadEditableStructuresSaga, { payload })
|
|
48
|
-
.next()
|
|
49
|
-
.put(downloadEditableStructures.request(body))
|
|
50
|
-
.next()
|
|
51
|
-
.call(apiJsonPost, API_DATA_STRUCTURES_EDITABLE_CSV, body, JSON_OPTS)
|
|
52
|
-
.next({ data })
|
|
53
|
-
.call(saveFile, data)
|
|
54
|
-
.next()
|
|
55
|
-
.put(downloadEditableStructures.success(data))
|
|
56
|
-
.next()
|
|
57
|
-
.put(downloadEditableStructures.fulfill())
|
|
58
|
-
.next()
|
|
59
|
-
.isDone();
|
|
60
|
-
}).not.toThrow();
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
it("should put a failure action when the call returns an error", () => {
|
|
64
|
-
const message = "Request failed";
|
|
65
|
-
const error = { message };
|
|
66
|
-
|
|
67
|
-
expect(() => {
|
|
68
|
-
testSaga(downloadEditableStructuresSaga, { payload })
|
|
69
|
-
.next()
|
|
70
|
-
.put(downloadEditableStructures.request(body))
|
|
71
|
-
.next()
|
|
72
|
-
.call(apiJsonPost, API_DATA_STRUCTURES_EDITABLE_CSV, body, JSON_OPTS)
|
|
73
|
-
.throw(error)
|
|
74
|
-
.put(downloadEditableStructures.failure(message))
|
|
75
|
-
.next()
|
|
76
|
-
.put(downloadEditableStructures.fulfill())
|
|
77
|
-
.next()
|
|
78
|
-
.isDone();
|
|
79
|
-
}).not.toThrow();
|
|
80
|
-
});
|
|
81
|
-
});
|
|
@@ -1,82 +0,0 @@
|
|
|
1
|
-
import { testSaga } from "redux-saga-test-plan";
|
|
2
|
-
import { apiJsonPost, JSON_OPTS } from "@truedat/core/services/api";
|
|
3
|
-
import {
|
|
4
|
-
downloadStructuresRequestSaga,
|
|
5
|
-
downloadStructuresSaga,
|
|
6
|
-
saveFile,
|
|
7
|
-
} from "../downloadStructures";
|
|
8
|
-
import { downloadStructures } from "../../routines";
|
|
9
|
-
import { API_DATA_STRUCTURES_CSV } from "../../api";
|
|
10
|
-
|
|
11
|
-
describe("sagas: downloadStructuresRequestSaga", () => {
|
|
12
|
-
it("should invoke downloadStructuresSaga on downloadStructures.TRIGGER", () => {
|
|
13
|
-
expect(() => {
|
|
14
|
-
testSaga(downloadStructuresRequestSaga)
|
|
15
|
-
.next()
|
|
16
|
-
.takeLatest(downloadStructures.TRIGGER, downloadStructuresSaga)
|
|
17
|
-
.finish()
|
|
18
|
-
.isDone();
|
|
19
|
-
}).not.toThrow();
|
|
20
|
-
});
|
|
21
|
-
|
|
22
|
-
it("should throw exception if an unhandled action is received", () => {
|
|
23
|
-
expect(() => {
|
|
24
|
-
testSaga(downloadStructuresRequestSaga)
|
|
25
|
-
.next()
|
|
26
|
-
.takeLatest("FOO", downloadStructuresRequestSaga);
|
|
27
|
-
}).toThrow();
|
|
28
|
-
});
|
|
29
|
-
});
|
|
30
|
-
|
|
31
|
-
describe("sagas: downloadStructuresSaga", () => {
|
|
32
|
-
const headerLabels = { name: "Name" };
|
|
33
|
-
const lang = "es";
|
|
34
|
-
const query = { filters: {} };
|
|
35
|
-
const payload = { headerLabels, lang: lang, searchParams: query };
|
|
36
|
-
|
|
37
|
-
const data = "SOME CSV DATA";
|
|
38
|
-
|
|
39
|
-
const body = {
|
|
40
|
-
header_labels: headerLabels,
|
|
41
|
-
lang: lang,
|
|
42
|
-
structure_url_schema: "http://localhost/structures/:id",
|
|
43
|
-
...query,
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
it("should put a success action when a response is returned", () => {
|
|
47
|
-
expect(() => {
|
|
48
|
-
testSaga(downloadStructuresSaga, { payload })
|
|
49
|
-
.next()
|
|
50
|
-
.put(downloadStructures.request(body))
|
|
51
|
-
.next()
|
|
52
|
-
.call(apiJsonPost, API_DATA_STRUCTURES_CSV, body, JSON_OPTS)
|
|
53
|
-
.next({ data })
|
|
54
|
-
.call(saveFile, data)
|
|
55
|
-
.next()
|
|
56
|
-
.put(downloadStructures.success(data))
|
|
57
|
-
.next()
|
|
58
|
-
.put(downloadStructures.fulfill())
|
|
59
|
-
.next()
|
|
60
|
-
.isDone();
|
|
61
|
-
}).not.toThrow();
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
it("should put a failure action when the call returns an error", () => {
|
|
65
|
-
const message = "Request failed";
|
|
66
|
-
const error = { message };
|
|
67
|
-
|
|
68
|
-
expect(() => {
|
|
69
|
-
testSaga(downloadStructuresSaga, { payload })
|
|
70
|
-
.next()
|
|
71
|
-
.put(downloadStructures.request(body))
|
|
72
|
-
.next()
|
|
73
|
-
.call(apiJsonPost, API_DATA_STRUCTURES_CSV, body, JSON_OPTS)
|
|
74
|
-
.throw(error)
|
|
75
|
-
.put(downloadStructures.failure(message))
|
|
76
|
-
.next()
|
|
77
|
-
.put(downloadStructures.fulfill())
|
|
78
|
-
.next()
|
|
79
|
-
.isDone();
|
|
80
|
-
}).not.toThrow();
|
|
81
|
-
});
|
|
82
|
-
});
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { testSaga } from "redux-saga-test-plan";
|
|
2
|
-
import { apiJsonPost, UPLOAD_JSON_OPTS } from "@truedat/core/services/api";
|
|
3
|
-
import {
|
|
4
|
-
uploadStructuresRequestSaga,
|
|
5
|
-
uploadStructuresSaga,
|
|
6
|
-
} from "../uploadStructures";
|
|
7
|
-
import { uploadStructures } from "../../routines";
|
|
8
|
-
import { API_STRUCTURES_UPLOAD } from "../../api";
|
|
9
|
-
|
|
10
|
-
describe("sagas: uploadStructuresRequestSaga", () => {
|
|
11
|
-
it("should invoke uploadStructuresSaga on trigger", () => {
|
|
12
|
-
expect(() => {
|
|
13
|
-
testSaga(uploadStructuresRequestSaga)
|
|
14
|
-
.next()
|
|
15
|
-
.takeLatest(uploadStructures.TRIGGER, uploadStructuresSaga)
|
|
16
|
-
.finish()
|
|
17
|
-
.isDone();
|
|
18
|
-
}).not.toThrow();
|
|
19
|
-
});
|
|
20
|
-
|
|
21
|
-
it("should throw exception if an unhandled action is received", () => {
|
|
22
|
-
expect(() => {
|
|
23
|
-
testSaga(uploadStructuresRequestSaga)
|
|
24
|
-
.next()
|
|
25
|
-
.takeLatest("FOO", uploadStructuresSaga);
|
|
26
|
-
}).toThrow();
|
|
27
|
-
});
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
describe("sagas: uploadStructuresSaga", () => {
|
|
31
|
-
const lang = "es";
|
|
32
|
-
const body = new FormData();
|
|
33
|
-
const payload = { data: body, lang };
|
|
34
|
-
const status = "JUST_STARTED";
|
|
35
|
-
const data = { message: [1, 2] };
|
|
36
|
-
it("should put a success action when a response is returned", () => {
|
|
37
|
-
expect(() => {
|
|
38
|
-
testSaga(uploadStructuresSaga, { payload })
|
|
39
|
-
.next()
|
|
40
|
-
.put(uploadStructures.request())
|
|
41
|
-
.next()
|
|
42
|
-
.call(apiJsonPost, API_STRUCTURES_UPLOAD, body, UPLOAD_JSON_OPTS)
|
|
43
|
-
.next({ status, data })
|
|
44
|
-
.put(uploadStructures.success({ status, data }))
|
|
45
|
-
.next()
|
|
46
|
-
.put(uploadStructures.fulfill())
|
|
47
|
-
.next()
|
|
48
|
-
.isDone();
|
|
49
|
-
}).not.toThrow();
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
it("should put a failure action when the call returns an error", () => {
|
|
53
|
-
const message = "Request failed";
|
|
54
|
-
const error = { message };
|
|
55
|
-
|
|
56
|
-
expect(() => {
|
|
57
|
-
testSaga(uploadStructuresSaga, { payload })
|
|
58
|
-
.next()
|
|
59
|
-
.put(uploadStructures.request())
|
|
60
|
-
.next()
|
|
61
|
-
.call(apiJsonPost, API_STRUCTURES_UPLOAD, body, UPLOAD_JSON_OPTS)
|
|
62
|
-
.throw(error)
|
|
63
|
-
.put(uploadStructures.failure(message))
|
|
64
|
-
.next()
|
|
65
|
-
.put(uploadStructures.fulfill())
|
|
66
|
-
.next()
|
|
67
|
-
.isDone();
|
|
68
|
-
}).not.toThrow();
|
|
69
|
-
});
|
|
70
|
-
});
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import _ from "lodash/fp";
|
|
2
|
-
import FileSaver from "file-saver";
|
|
3
|
-
import { call, put, takeLatest } from "redux-saga/effects";
|
|
4
|
-
import { apiJsonPost, JSON_OPTS } from "@truedat/core/services/api";
|
|
5
|
-
import { STRUCTURE } from "@truedat/core/routes";
|
|
6
|
-
import { downloadEditableStructures } from "../routines";
|
|
7
|
-
import { API_DATA_STRUCTURES_EDITABLE_CSV } from "../api";
|
|
8
|
-
|
|
9
|
-
export function saveFile(data) {
|
|
10
|
-
if (!_.isEmpty(data)) {
|
|
11
|
-
const blob = new Blob([String.fromCharCode(0xfeff), data], {
|
|
12
|
-
type: "text/csv;charset=utf-8",
|
|
13
|
-
});
|
|
14
|
-
FileSaver.saveAs(blob, "structures.csv");
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function* downloadEditableStructuresSaga({ payload }) {
|
|
19
|
-
const lang = _.propOr("en", "lang")(payload);
|
|
20
|
-
try {
|
|
21
|
-
const query = _.prop("searchParams")(payload);
|
|
22
|
-
const body = {
|
|
23
|
-
structure_url_schema: getStructureUrlSchema(),
|
|
24
|
-
lang,
|
|
25
|
-
...query,
|
|
26
|
-
};
|
|
27
|
-
const url = API_DATA_STRUCTURES_EDITABLE_CSV;
|
|
28
|
-
yield put(downloadEditableStructures.request(body));
|
|
29
|
-
const { data } = yield call(apiJsonPost, url, body, JSON_OPTS);
|
|
30
|
-
yield call(saveFile, data);
|
|
31
|
-
yield put(downloadEditableStructures.success(data));
|
|
32
|
-
} catch (error) {
|
|
33
|
-
if (error.response) {
|
|
34
|
-
const { status, data } = error.response;
|
|
35
|
-
yield put(downloadEditableStructures.failure({ status, data }));
|
|
36
|
-
} else {
|
|
37
|
-
yield put(downloadEditableStructures.failure(error.message));
|
|
38
|
-
}
|
|
39
|
-
} finally {
|
|
40
|
-
yield put(downloadEditableStructures.fulfill());
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export function* downloadEditableStructuresRequestSaga() {
|
|
45
|
-
yield takeLatest(
|
|
46
|
-
downloadEditableStructures.TRIGGER,
|
|
47
|
-
downloadEditableStructuresSaga
|
|
48
|
-
);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const getStructureUrlSchema = () => window.location.origin + STRUCTURE;
|
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import _ from "lodash/fp";
|
|
2
|
-
import FileSaver from "file-saver";
|
|
3
|
-
import { call, put, takeLatest } from "redux-saga/effects";
|
|
4
|
-
import { apiJsonPost, JSON_OPTS } from "@truedat/core/services/api";
|
|
5
|
-
import { STRUCTURE } from "@truedat/core/routes";
|
|
6
|
-
import { downloadStructures } from "../routines";
|
|
7
|
-
import { API_DATA_STRUCTURES_CSV } from "../api";
|
|
8
|
-
|
|
9
|
-
export function saveFile(data) {
|
|
10
|
-
if (!_.isEmpty(data)) {
|
|
11
|
-
const blob = new Blob([String.fromCharCode(0xfeff), data], {
|
|
12
|
-
type: "text/csv;charset=utf-8",
|
|
13
|
-
});
|
|
14
|
-
FileSaver.saveAs(blob, "structures.csv");
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export function* downloadStructuresSaga({ payload }) {
|
|
19
|
-
try {
|
|
20
|
-
const headerLabels = _.propOr({}, "headerLabels")(payload);
|
|
21
|
-
const lang = _.propOr("en", "lang")(payload);
|
|
22
|
-
const query = _.prop("searchParams")(payload);
|
|
23
|
-
|
|
24
|
-
const body = {
|
|
25
|
-
header_labels: headerLabels,
|
|
26
|
-
structure_url_schema: getStructureUrlSchema(),
|
|
27
|
-
lang,
|
|
28
|
-
...query,
|
|
29
|
-
};
|
|
30
|
-
const url = API_DATA_STRUCTURES_CSV;
|
|
31
|
-
yield put(downloadStructures.request(body));
|
|
32
|
-
const { data } = yield call(apiJsonPost, url, body, JSON_OPTS);
|
|
33
|
-
yield call(saveFile, data);
|
|
34
|
-
yield put(downloadStructures.success(data));
|
|
35
|
-
} catch (error) {
|
|
36
|
-
if (error.response) {
|
|
37
|
-
const { status, data } = error.response;
|
|
38
|
-
yield put(downloadStructures.failure({ status, data }));
|
|
39
|
-
} else {
|
|
40
|
-
yield put(downloadStructures.failure(error.message));
|
|
41
|
-
}
|
|
42
|
-
} finally {
|
|
43
|
-
yield put(downloadStructures.fulfill());
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export function* downloadStructuresRequestSaga() {
|
|
48
|
-
yield takeLatest(downloadStructures.TRIGGER, downloadStructuresSaga);
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
const getStructureUrlSchema = () => window.location.origin + STRUCTURE;
|