@truedat/core 4.44.4 → 4.45.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/package.json +24 -18
- package/src/api/queries.js +2 -2
- package/src/components/TemplateSelector.js +15 -5
- package/src/components/__tests__/DateTime.spec.js +5 -3
- package/src/components/__tests__/TemplateSelector.spec.js +64 -35
- package/src/components/__tests__/__snapshots__/DateTime.spec.js.snap +7 -19
- package/src/components/__tests__/__snapshots__/TemplateSelector.spec.js.snap +134 -0
- package/src/messages/en.js +1 -0
- package/src/messages/es.js +1 -0
package/CHANGELOG.md
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.45.1",
|
|
4
4
|
"description": "Truedat Web Core",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -17,23 +17,26 @@
|
|
|
17
17
|
"scripts": {
|
|
18
18
|
"clean": "rimraf yarn-error.log",
|
|
19
19
|
"debug": "node --inspect-brk node_modules/.bin/jest --runInBand",
|
|
20
|
-
"test": "jest --coverage",
|
|
21
|
-
"test:watch": "jest --watch",
|
|
20
|
+
"test": "TZ=UTC jest --coverage",
|
|
21
|
+
"test:watch": "TZ=UTC jest --watch",
|
|
22
22
|
"eslint": "eslint src/**",
|
|
23
23
|
"eslint:fix": "eslint --fix src/**"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@babel/cli": "^7.
|
|
27
|
-
"@babel/core": "^7.
|
|
28
|
-
"@babel/plugin-proposal-class-properties": "^7.
|
|
29
|
-
"@babel/plugin-proposal-object-rest-spread": "^7.
|
|
30
|
-
"@babel/plugin-proposal-optional-chaining": "^7.
|
|
26
|
+
"@babel/cli": "^7.17.10",
|
|
27
|
+
"@babel/core": "^7.18.0",
|
|
28
|
+
"@babel/plugin-proposal-class-properties": "^7.17.12",
|
|
29
|
+
"@babel/plugin-proposal-object-rest-spread": "^7.18.0",
|
|
30
|
+
"@babel/plugin-proposal-optional-chaining": "^7.17.12",
|
|
31
31
|
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
|
|
32
|
-
"@babel/plugin-transform-modules-commonjs": "^7.
|
|
33
|
-
"@babel/preset-env": "^7.
|
|
34
|
-
"@babel/preset-react": "^7.
|
|
35
|
-
"@
|
|
36
|
-
"
|
|
32
|
+
"@babel/plugin-transform-modules-commonjs": "^7.18.0",
|
|
33
|
+
"@babel/preset-env": "^7.18.0",
|
|
34
|
+
"@babel/preset-react": "^7.17.12",
|
|
35
|
+
"@testing-library/jest-dom": "^5.16.4",
|
|
36
|
+
"@testing-library/react": "^12.0.0",
|
|
37
|
+
"@testing-library/user-event": "^13.2.1",
|
|
38
|
+
"@truedat/test": "4.45.1",
|
|
39
|
+
"babel-jest": "^28.1.0",
|
|
37
40
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
38
41
|
"babel-plugin-lodash": "^3.3.4",
|
|
39
42
|
"babel-plugin-react-intl": "^5.1.18",
|
|
@@ -41,7 +44,8 @@
|
|
|
41
44
|
"enzyme": "^3.11.0",
|
|
42
45
|
"enzyme-to-json": "^3.6.2",
|
|
43
46
|
"identity-obj-proxy": "^3.0.0",
|
|
44
|
-
"jest": "^
|
|
47
|
+
"jest": "^28.1.0",
|
|
48
|
+
"jest-environment-jsdom": "^28.1.0",
|
|
45
49
|
"jest-localstorage-mock": "^2.4.14",
|
|
46
50
|
"react": "^16.14.0",
|
|
47
51
|
"react-dom": "^16.14.0",
|
|
@@ -50,6 +54,8 @@
|
|
|
50
54
|
"semantic-ui-react": "^2.0.3"
|
|
51
55
|
},
|
|
52
56
|
"jest": {
|
|
57
|
+
"maxWorkers": "50%",
|
|
58
|
+
"testTimeout": 10000,
|
|
53
59
|
"moduleDirectories": [
|
|
54
60
|
"<rootDir>/src",
|
|
55
61
|
"../../node_modules"
|
|
@@ -82,16 +88,16 @@
|
|
|
82
88
|
}
|
|
83
89
|
},
|
|
84
90
|
"dependencies": {
|
|
85
|
-
"@apollo/client": "^3.4
|
|
91
|
+
"@apollo/client": "^3.6.4",
|
|
86
92
|
"axios": "^0.19.2",
|
|
87
93
|
"immutable": "^4.0.0-rc.12",
|
|
88
94
|
"is-hotkey": "^0.1.6",
|
|
89
95
|
"is-url": "^1.2.4",
|
|
90
|
-
"prop-types": "^15.
|
|
96
|
+
"prop-types": "^15.8.1",
|
|
91
97
|
"react-csv": "^2.2.2",
|
|
92
98
|
"react-dropzone": "^4.2.13",
|
|
93
99
|
"react-intl": "^5.20.10",
|
|
94
|
-
"react-moment": "^
|
|
100
|
+
"react-moment": "^1.1.2",
|
|
95
101
|
"react-redux": "^7.2.4",
|
|
96
102
|
"react-router-dom": "^5.2.0",
|
|
97
103
|
"redux": "^4.1.1",
|
|
@@ -106,5 +112,5 @@
|
|
|
106
112
|
"react-dom": ">= 16.8.6 < 17",
|
|
107
113
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
108
114
|
},
|
|
109
|
-
"gitHead": "
|
|
115
|
+
"gitHead": "c13f37ee357bf4a5e8c8c99eb6bd0c798f468c49"
|
|
110
116
|
}
|
package/src/api/queries.js
CHANGED
|
@@ -11,8 +11,8 @@ export const DOMAINS_QUERY = gql`
|
|
|
11
11
|
`;
|
|
12
12
|
|
|
13
13
|
export const TEMPLATES_QUERY = gql`
|
|
14
|
-
query Templates($scope: String
|
|
15
|
-
templates(scope: $scope) {
|
|
14
|
+
query Templates($scope: String, $domainIds: [ID]) {
|
|
15
|
+
templates(scope: $scope, domainIds: $domainIds) {
|
|
16
16
|
id
|
|
17
17
|
name
|
|
18
18
|
label
|
|
@@ -27,7 +27,7 @@ export const TemplateSelector = ({
|
|
|
27
27
|
}) => {
|
|
28
28
|
const { formatMessage } = useIntl();
|
|
29
29
|
const options = makeOptions(templates);
|
|
30
|
-
const hidden = _.size(templates) <= 1;
|
|
30
|
+
const hidden = loading ? false : _.size(templates) <= 1;
|
|
31
31
|
|
|
32
32
|
const handleChange = (e, { value, ...data }) => {
|
|
33
33
|
const template = _.find({ id: value })(templates);
|
|
@@ -50,7 +50,9 @@ export const TemplateSelector = ({
|
|
|
50
50
|
name={name}
|
|
51
51
|
onChange={handleChange}
|
|
52
52
|
options={options}
|
|
53
|
-
placeholder={formatMessage({
|
|
53
|
+
placeholder={formatMessage({
|
|
54
|
+
id: loading ? "loading" : "template.selector.placeholder",
|
|
55
|
+
})}
|
|
54
56
|
search
|
|
55
57
|
selection
|
|
56
58
|
value={_.toString(selectedValue)}
|
|
@@ -69,19 +71,27 @@ TemplateSelector.propTypes = {
|
|
|
69
71
|
templates: PropTypes.array,
|
|
70
72
|
};
|
|
71
73
|
|
|
72
|
-
|
|
74
|
+
const emptyTemplates = [];
|
|
75
|
+
export const TemplateSelectorLoader = ({
|
|
76
|
+
scope,
|
|
77
|
+
onLoad,
|
|
78
|
+
domainIds,
|
|
79
|
+
...props
|
|
80
|
+
}) => {
|
|
73
81
|
const { loading, error, data } = useQuery(TEMPLATES_QUERY, {
|
|
74
|
-
|
|
82
|
+
fetchPolicy: "cache-and-network",
|
|
83
|
+
variables: { scope, domainIds },
|
|
75
84
|
onCompleted: onLoad,
|
|
76
85
|
});
|
|
77
86
|
if (error) return null;
|
|
78
|
-
const templates = data?.templates ||
|
|
87
|
+
const templates = data?.templates || emptyTemplates;
|
|
79
88
|
return (
|
|
80
89
|
<TemplateSelector loading={loading} templates={templates} {...props} />
|
|
81
90
|
);
|
|
82
91
|
};
|
|
83
92
|
|
|
84
93
|
TemplateSelectorLoader.propTypes = {
|
|
94
|
+
domainIds: PropTypes.array,
|
|
85
95
|
scope: PropTypes.string.isRequired,
|
|
86
96
|
onLoad: PropTypes.func,
|
|
87
97
|
};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { render } from "@truedat/test/render";
|
|
3
3
|
import { DateTime } from "..";
|
|
4
4
|
|
|
5
5
|
describe("<DateTime />", () => {
|
|
6
6
|
it("matches the latest snapshot", () => {
|
|
7
|
-
const
|
|
8
|
-
|
|
7
|
+
const { container } = render(
|
|
8
|
+
<DateTime value="2018-06-27T07:32:53.154377Z" />
|
|
9
|
+
);
|
|
10
|
+
expect(container).toMatchSnapshot();
|
|
9
11
|
});
|
|
10
12
|
});
|
|
@@ -1,51 +1,80 @@
|
|
|
1
|
-
import React
|
|
2
|
-
import {
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { waitForElementToBeRemoved } from "@testing-library/react";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
3
4
|
import { render } from "@truedat/test/render";
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
errorTemplateMock,
|
|
7
|
+
multipleTemplatesMock,
|
|
8
|
+
singleTemplateMock,
|
|
9
|
+
} from "@truedat/test/mocks";
|
|
5
10
|
import TemplateSelector from "../TemplateSelector";
|
|
6
11
|
|
|
7
12
|
const scope = "foo";
|
|
8
|
-
const
|
|
9
|
-
|
|
10
|
-
id: "1",
|
|
11
|
-
name: "template1",
|
|
12
|
-
label: "template1",
|
|
13
|
-
content: [{ name: "g1", fields: [{ name: "field1", label: "field1" }] }],
|
|
14
|
-
scope,
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
id: "2",
|
|
18
|
-
name: "template2",
|
|
19
|
-
label: "template2",
|
|
20
|
-
content: {},
|
|
21
|
-
scope,
|
|
22
|
-
},
|
|
23
|
-
];
|
|
24
|
-
const templatesMock = {
|
|
25
|
-
request: { query: TEMPLATES_QUERY, variables: { scope } },
|
|
26
|
-
result: { data: { templates } },
|
|
27
|
-
};
|
|
28
|
-
|
|
29
|
-
const renderOpts = {
|
|
30
|
-
mocks: [templatesMock],
|
|
31
|
-
};
|
|
13
|
+
const domainIds = [1];
|
|
14
|
+
const variables = { scope, domainIds };
|
|
32
15
|
|
|
33
16
|
describe("<TemplateSelector />", () => {
|
|
34
17
|
const onChange = jest.fn();
|
|
35
|
-
const
|
|
36
|
-
|
|
18
|
+
const props = { onChange, domainIds, scope };
|
|
19
|
+
|
|
20
|
+
it("matches the latest snapshot (loading)", () => {
|
|
21
|
+
const renderOpts = { mocks: [multipleTemplatesMock(variables)] };
|
|
22
|
+
const { container, queryByText } = render(
|
|
23
|
+
<TemplateSelector {...props} />,
|
|
24
|
+
renderOpts
|
|
25
|
+
);
|
|
26
|
+
expect(queryByText(/loading/i)).toBeInTheDocument();
|
|
27
|
+
expect(container).toMatchSnapshot();
|
|
28
|
+
});
|
|
37
29
|
|
|
38
30
|
it("matches the latest snapshot", async () => {
|
|
31
|
+
const renderOpts = { mocks: [multipleTemplatesMock(variables)] };
|
|
32
|
+
const onLoad = jest.fn();
|
|
39
33
|
const { container, queryByText } = render(
|
|
40
|
-
<
|
|
41
|
-
<TemplateSelector {...props} />
|
|
42
|
-
</Suspense>,
|
|
34
|
+
<TemplateSelector {...props} onLoad={onLoad} />,
|
|
43
35
|
renderOpts
|
|
44
36
|
);
|
|
45
|
-
await
|
|
46
|
-
|
|
47
|
-
});
|
|
37
|
+
await waitForElementToBeRemoved(() => queryByText(/loading/i));
|
|
38
|
+
expect(queryByText("template1")).toBeInTheDocument();
|
|
48
39
|
expect(container).toMatchSnapshot();
|
|
49
40
|
expect(onLoad.mock.calls.length).toBe(1);
|
|
50
41
|
});
|
|
42
|
+
|
|
43
|
+
it("matches the latest snapshot when required", async () => {
|
|
44
|
+
const renderOpts = { mocks: [multipleTemplatesMock(variables)] };
|
|
45
|
+
const { container, queryByText } = render(
|
|
46
|
+
<TemplateSelector {...props} required />,
|
|
47
|
+
renderOpts
|
|
48
|
+
);
|
|
49
|
+
await waitForElementToBeRemoved(() => queryByText(/loading/i));
|
|
50
|
+
expect(queryByText("template1")).toBeInTheDocument();
|
|
51
|
+
expect(container).toMatchSnapshot();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("is empty if templates query returns an error", async () => {
|
|
55
|
+
const renderOpts = { mocks: [errorTemplateMock(variables)] };
|
|
56
|
+
const { queryByText } = render(
|
|
57
|
+
<TemplateSelector {...props} required />,
|
|
58
|
+
renderOpts
|
|
59
|
+
);
|
|
60
|
+
await waitForElementToBeRemoved(() => queryByText(/loading/i));
|
|
61
|
+
expect(queryByText("template1")).not.toBeInTheDocument();
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("calls onChange when template is selected", async () => {
|
|
65
|
+
const renderOpts = { mocks: [multipleTemplatesMock(variables)] };
|
|
66
|
+
const { findByRole } = render(<TemplateSelector {...props} />, renderOpts);
|
|
67
|
+
|
|
68
|
+
userEvent.click(await findByRole("option", { name: "template1" }));
|
|
69
|
+
expect(onChange.mock.calls[0][1]).toMatchObject({
|
|
70
|
+
template: { id: "1", label: "template1" },
|
|
71
|
+
});
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
it("is empty when query returns a single template", async () => {
|
|
75
|
+
const renderOpts = { mocks: [singleTemplateMock(variables)] };
|
|
76
|
+
const { queryByText } = render(<TemplateSelector {...props} />, renderOpts);
|
|
77
|
+
await waitForElementToBeRemoved(() => queryByText(/loading/i));
|
|
78
|
+
expect(queryByText("template1")).not.toBeInTheDocument();
|
|
79
|
+
});
|
|
51
80
|
});
|
|
@@ -1,23 +1,11 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`<DateTime /> matches the latest snapshot 1`] = `
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
format="YYYY-MM-DD HH:mm"
|
|
12
|
-
fromNow={false}
|
|
13
|
-
interval={60000}
|
|
14
|
-
local={false}
|
|
15
|
-
onChange={[Function]}
|
|
16
|
-
titleFormat=""
|
|
17
|
-
toNow={false}
|
|
18
|
-
unit={null}
|
|
19
|
-
unix={false}
|
|
20
|
-
utc={false}
|
|
21
|
-
withTitle={false}
|
|
22
|
-
/>
|
|
4
|
+
<div>
|
|
5
|
+
<time
|
|
6
|
+
datetime="1530084773154"
|
|
7
|
+
>
|
|
8
|
+
2018-06-27 07:32
|
|
9
|
+
</time>
|
|
10
|
+
</div>
|
|
23
11
|
`;
|
|
@@ -1,5 +1,59 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
|
+
exports[`<TemplateSelector /> matches the latest snapshot (loading) 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<div
|
|
6
|
+
class="field"
|
|
7
|
+
>
|
|
8
|
+
<label>
|
|
9
|
+
Template
|
|
10
|
+
</label>
|
|
11
|
+
<div
|
|
12
|
+
class="field"
|
|
13
|
+
>
|
|
14
|
+
<div
|
|
15
|
+
aria-busy="true"
|
|
16
|
+
aria-expanded="false"
|
|
17
|
+
class="ui loading search selection dropdown"
|
|
18
|
+
name="template"
|
|
19
|
+
role="combobox"
|
|
20
|
+
>
|
|
21
|
+
<input
|
|
22
|
+
aria-autocomplete="list"
|
|
23
|
+
autocomplete="off"
|
|
24
|
+
class="search"
|
|
25
|
+
tabindex="0"
|
|
26
|
+
type="text"
|
|
27
|
+
value=""
|
|
28
|
+
/>
|
|
29
|
+
<div
|
|
30
|
+
aria-atomic="true"
|
|
31
|
+
aria-live="polite"
|
|
32
|
+
class="divider default text"
|
|
33
|
+
role="alert"
|
|
34
|
+
>
|
|
35
|
+
loading...
|
|
36
|
+
</div>
|
|
37
|
+
<i
|
|
38
|
+
aria-hidden="true"
|
|
39
|
+
class="dropdown icon"
|
|
40
|
+
/>
|
|
41
|
+
<div
|
|
42
|
+
class="menu transition"
|
|
43
|
+
role="listbox"
|
|
44
|
+
>
|
|
45
|
+
<div
|
|
46
|
+
class="message"
|
|
47
|
+
>
|
|
48
|
+
No results found.
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
`;
|
|
56
|
+
|
|
3
57
|
exports[`<TemplateSelector /> matches the latest snapshot 1`] = `
|
|
4
58
|
<div>
|
|
5
59
|
<div
|
|
@@ -74,3 +128,83 @@ exports[`<TemplateSelector /> matches the latest snapshot 1`] = `
|
|
|
74
128
|
</div>
|
|
75
129
|
</div>
|
|
76
130
|
`;
|
|
131
|
+
|
|
132
|
+
exports[`<TemplateSelector /> matches the latest snapshot when required 1`] = `
|
|
133
|
+
<div>
|
|
134
|
+
<div
|
|
135
|
+
class="required field"
|
|
136
|
+
>
|
|
137
|
+
<label>
|
|
138
|
+
Template
|
|
139
|
+
<div
|
|
140
|
+
class="ui left pointing label"
|
|
141
|
+
>
|
|
142
|
+
Empty required field
|
|
143
|
+
</div>
|
|
144
|
+
</label>
|
|
145
|
+
<div
|
|
146
|
+
class="field"
|
|
147
|
+
>
|
|
148
|
+
<div
|
|
149
|
+
aria-busy="false"
|
|
150
|
+
aria-expanded="false"
|
|
151
|
+
class="ui search selection dropdown"
|
|
152
|
+
name="template"
|
|
153
|
+
role="combobox"
|
|
154
|
+
>
|
|
155
|
+
<input
|
|
156
|
+
aria-autocomplete="list"
|
|
157
|
+
autocomplete="off"
|
|
158
|
+
class="search"
|
|
159
|
+
tabindex="0"
|
|
160
|
+
type="text"
|
|
161
|
+
value=""
|
|
162
|
+
/>
|
|
163
|
+
<div
|
|
164
|
+
aria-atomic="true"
|
|
165
|
+
aria-live="polite"
|
|
166
|
+
class="divider default text"
|
|
167
|
+
role="alert"
|
|
168
|
+
>
|
|
169
|
+
Select a template...
|
|
170
|
+
</div>
|
|
171
|
+
<i
|
|
172
|
+
aria-hidden="true"
|
|
173
|
+
class="dropdown icon"
|
|
174
|
+
/>
|
|
175
|
+
<div
|
|
176
|
+
class="menu transition"
|
|
177
|
+
role="listbox"
|
|
178
|
+
>
|
|
179
|
+
<div
|
|
180
|
+
aria-checked="false"
|
|
181
|
+
aria-selected="true"
|
|
182
|
+
class="selected item"
|
|
183
|
+
role="option"
|
|
184
|
+
style="pointer-events: all;"
|
|
185
|
+
>
|
|
186
|
+
<span
|
|
187
|
+
class="text"
|
|
188
|
+
>
|
|
189
|
+
template1
|
|
190
|
+
</span>
|
|
191
|
+
</div>
|
|
192
|
+
<div
|
|
193
|
+
aria-checked="false"
|
|
194
|
+
aria-selected="false"
|
|
195
|
+
class="item"
|
|
196
|
+
role="option"
|
|
197
|
+
style="pointer-events: all;"
|
|
198
|
+
>
|
|
199
|
+
<span
|
|
200
|
+
class="text"
|
|
201
|
+
>
|
|
202
|
+
template2
|
|
203
|
+
</span>
|
|
204
|
+
</div>
|
|
205
|
+
</div>
|
|
206
|
+
</div>
|
|
207
|
+
</div>
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
`;
|
package/src/messages/en.js
CHANGED
|
@@ -45,6 +45,7 @@ export default {
|
|
|
45
45
|
filters: "Filters",
|
|
46
46
|
"filters.class.raw.field": "Field",
|
|
47
47
|
"filters.reset": "(reset all filters)",
|
|
48
|
+
loading: "loading...",
|
|
48
49
|
"form.validation.required": "{prop} is required",
|
|
49
50
|
"form.validation.minLength": "{prop} must have at least {value} characters",
|
|
50
51
|
"form.validation.email.invalid": "Invalid email address",
|
package/src/messages/es.js
CHANGED
|
@@ -49,6 +49,7 @@ export default {
|
|
|
49
49
|
"form.validation.required": "{prop} es un campo requerido",
|
|
50
50
|
"form.validation.minLength": "{prop} debe tener al menos {value} elementos",
|
|
51
51
|
"form.validation.email.invalid": "Dirección de email inválida",
|
|
52
|
+
loading: "cargando...",
|
|
52
53
|
"navigation.dashboard": "Dashboard",
|
|
53
54
|
"navigation.menu": "Menú",
|
|
54
55
|
"search.applied_filters": "Filtros aplicados:",
|