@truedat/core 8.14.3 → 8.14.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 +3 -3
- package/src/components/FilterDropdown.js +21 -1
- package/src/components/FilterItem.js +6 -0
- package/src/components/ScrollToTop.js +17 -4
- package/src/components/__tests__/FilterDropdown.spec.js +18 -1
- package/src/components/__tests__/FilterItem.spec.js +21 -0
- package/src/components/__tests__/ScrollToTop.spec.js +54 -0
- package/src/components/__tests__/__snapshots__/FilterDropdown.spec.js.snap +7 -1
- package/src/components/__tests__/__snapshots__/FilterItem.spec.js.snap +1 -0
- package/src/components/__tests__/__snapshots__/SelectedFilters.spec.js.snap +24 -4
- package/src/i18n/components/LangProvider.js +1 -1
- package/src/i18n/components/Languages.js +1 -1
- package/src/i18n/components/__tests__/LangProvider.spec.js +44 -0
- package/src/i18n/components/__tests__/__snapshots__/Messages.spec.js.snap +1 -1
- package/src/messages/en.js +1 -0
- package/src/messages/es.js +1 -0
- package/src/styles/Card.less +160 -0
- package/src/styles/IconTextControls.less +6 -0
- package/src/styles/Modal.less +28 -0
- package/src/styles/ModalAppearance.less +52 -0
- package/src/styles/TrueModal.less +3 -38
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/core",
|
|
3
|
-
"version": "8.14.
|
|
3
|
+
"version": "8.14.5",
|
|
4
4
|
"description": "Truedat Web Core",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"**/*.css",
|
|
@@ -57,7 +57,7 @@
|
|
|
57
57
|
"@testing-library/jest-dom": "^6.6.3",
|
|
58
58
|
"@testing-library/react": "^16.3.0",
|
|
59
59
|
"@testing-library/user-event": "^14.6.1",
|
|
60
|
-
"@truedat/test": "8.14.
|
|
60
|
+
"@truedat/test": "8.14.5",
|
|
61
61
|
"identity-obj-proxy": "^3.0.0",
|
|
62
62
|
"jest": "^29.7.0",
|
|
63
63
|
"redux-saga-test-plan": "^4.0.6"
|
|
@@ -99,5 +99,5 @@
|
|
|
99
99
|
"swr": "^2.3.3",
|
|
100
100
|
"turndown": "^7.2.2"
|
|
101
101
|
},
|
|
102
|
-
"gitHead": "
|
|
102
|
+
"gitHead": "a792103a77b3b2392be5777a8dc6675ac3882ffd"
|
|
103
103
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
2
|
import { useState, useEffect } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
|
-
import { FormattedMessage } from "react-intl";
|
|
4
|
+
import { FormattedMessage, useIntl } from "react-intl";
|
|
5
5
|
import {
|
|
6
6
|
Label,
|
|
7
7
|
Icon,
|
|
@@ -25,6 +25,7 @@ export const FilterDropdown = ({
|
|
|
25
25
|
removeFilter,
|
|
26
26
|
toggleFilterValue,
|
|
27
27
|
}) => {
|
|
28
|
+
const { formatMessage } = useIntl();
|
|
28
29
|
const [selected, setSelected] = useState();
|
|
29
30
|
const [query, setQuery] = useState();
|
|
30
31
|
|
|
@@ -64,6 +65,10 @@ export const FilterDropdown = ({
|
|
|
64
65
|
return (
|
|
65
66
|
<Dropdown
|
|
66
67
|
item
|
|
68
|
+
aria-label={formatMessage({
|
|
69
|
+
id: `filters.${filter}`,
|
|
70
|
+
defaultMessage: removePrefix(filter),
|
|
71
|
+
})}
|
|
67
72
|
floating
|
|
68
73
|
scrolling
|
|
69
74
|
icon={false}
|
|
@@ -76,6 +81,21 @@ export const FilterDropdown = ({
|
|
|
76
81
|
/>
|
|
77
82
|
<Icon
|
|
78
83
|
name="delete"
|
|
84
|
+
role="button"
|
|
85
|
+
tabIndex={0}
|
|
86
|
+
onFocus={(event) => event.stopPropagation()}
|
|
87
|
+
aria-hidden={false}
|
|
88
|
+
aria-label={formatMessage({
|
|
89
|
+
id: "actions.delete",
|
|
90
|
+
defaultMessage: "Delete",
|
|
91
|
+
})}
|
|
92
|
+
onKeyDown={(event) => {
|
|
93
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
94
|
+
event.preventDefault();
|
|
95
|
+
event.stopPropagation();
|
|
96
|
+
removeFilter({ filter });
|
|
97
|
+
}
|
|
98
|
+
}}
|
|
79
99
|
onClick={(e) => {
|
|
80
100
|
e.preventDefault();
|
|
81
101
|
e.stopPropagation();
|
|
@@ -33,6 +33,12 @@ export const FilterItem = ({
|
|
|
33
33
|
option: { text, value },
|
|
34
34
|
}) => (
|
|
35
35
|
<Dropdown.Item
|
|
36
|
+
tabIndex={0}
|
|
37
|
+
onKeyDown={(event) => {
|
|
38
|
+
if (event.key === "Enter" || event.key === " ") {
|
|
39
|
+
preventDefault(event, () => toggleFilterValue({ filter, value }));
|
|
40
|
+
}
|
|
41
|
+
}}
|
|
36
42
|
onClick={(e) =>
|
|
37
43
|
preventDefault(e, () => toggleFilterValue({ filter, value }))
|
|
38
44
|
}
|
|
@@ -1,19 +1,32 @@
|
|
|
1
|
-
import { useEffect } from "react";
|
|
1
|
+
import { useEffect, useRef } from "react";
|
|
2
2
|
import PropTypes from "prop-types";
|
|
3
3
|
import { useLocation } from "react-router";
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
const NO_PRESERVED_ROUTES = [];
|
|
6
|
+
const withinRoute = (pathname, route) =>
|
|
7
|
+
pathname === route || pathname.startsWith(`${route}/`);
|
|
8
|
+
|
|
9
|
+
function ScrollToTop({ children, preserveWithin = NO_PRESERVED_ROUTES }) {
|
|
6
10
|
const location = useLocation();
|
|
11
|
+
const previousLocation = useRef(null);
|
|
7
12
|
|
|
8
13
|
useEffect(() => {
|
|
9
|
-
|
|
10
|
-
|
|
14
|
+
const preserveScroll = preserveWithin.some(
|
|
15
|
+
(route) =>
|
|
16
|
+
previousLocation.current &&
|
|
17
|
+
withinRoute(previousLocation.current.pathname, route) &&
|
|
18
|
+
withinRoute(location.pathname, route),
|
|
19
|
+
);
|
|
20
|
+
if (!preserveScroll) window.scrollTo(0, 0);
|
|
21
|
+
previousLocation.current = location;
|
|
22
|
+
}, [location, preserveWithin]);
|
|
11
23
|
|
|
12
24
|
return children;
|
|
13
25
|
}
|
|
14
26
|
|
|
15
27
|
ScrollToTop.propTypes = {
|
|
16
28
|
children: PropTypes.node,
|
|
29
|
+
preserveWithin: PropTypes.arrayOf(PropTypes.string),
|
|
17
30
|
};
|
|
18
31
|
|
|
19
32
|
export default ScrollToTop;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
2
|
import { renderWithIntl as render } from "@truedat/test/renderWithIntl";
|
|
3
|
-
import { waitFor, within } from "@testing-library/react";
|
|
3
|
+
import { act, waitFor, within } from "@testing-library/react";
|
|
4
4
|
import userEvent from "@testing-library/user-event";
|
|
5
5
|
|
|
6
6
|
import { FilterDropdown } from "../FilterDropdown";
|
|
@@ -181,3 +181,20 @@ describe("<FilterDropdown/>", () => {
|
|
|
181
181
|
});
|
|
182
182
|
});
|
|
183
183
|
});
|
|
184
|
+
|
|
185
|
+
it("removes the filter with the keyboard without opening it", async () => {
|
|
186
|
+
const removeFilter = jest.fn();
|
|
187
|
+
const openFilter = jest.fn();
|
|
188
|
+
const rendered = render(
|
|
189
|
+
<FilterDropdown
|
|
190
|
+
{...props}
|
|
191
|
+
options={null}
|
|
192
|
+
removeFilter={removeFilter}
|
|
193
|
+
openFilter={openFilter}
|
|
194
|
+
/>,
|
|
195
|
+
);
|
|
196
|
+
act(() => rendered.getByRole("button", { name: "Delete" }).focus());
|
|
197
|
+
await user.keyboard("{Enter}");
|
|
198
|
+
expect(removeFilter).toHaveBeenCalledWith({ filter: "foo" });
|
|
199
|
+
expect(openFilter).not.toHaveBeenCalled();
|
|
200
|
+
});
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { renderWithIntl as render } from "@truedat/test/renderWithIntl";
|
|
2
2
|
import { waitForLoad } from "@truedat/test/waitForLoad";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
3
4
|
import { FilterItem } from "../FilterItem";
|
|
4
5
|
|
|
5
6
|
describe("<FilterItem/>", () => {
|
|
@@ -25,3 +26,23 @@ describe("<FilterItem/>", () => {
|
|
|
25
26
|
expect(props.toggleFilterValue).toHaveBeenCalledTimes(1);
|
|
26
27
|
});
|
|
27
28
|
});
|
|
29
|
+
|
|
30
|
+
it("toggles an option with the keyboard", async () => {
|
|
31
|
+
const toggleFilterValue = jest.fn();
|
|
32
|
+
const rendered = render(
|
|
33
|
+
<FilterItem
|
|
34
|
+
filter="foo"
|
|
35
|
+
active={false}
|
|
36
|
+
option={{ value: "bar", text: "Bar" }}
|
|
37
|
+
toggleFilterValue={toggleFilterValue}
|
|
38
|
+
/>,
|
|
39
|
+
);
|
|
40
|
+
const user = userEvent.setup({ delay: null });
|
|
41
|
+
rendered.getByRole("option").focus();
|
|
42
|
+
await user.keyboard("{Enter} ");
|
|
43
|
+
expect(toggleFilterValue).toHaveBeenCalledTimes(2);
|
|
44
|
+
expect(toggleFilterValue).toHaveBeenCalledWith({
|
|
45
|
+
filter: "foo",
|
|
46
|
+
value: "bar",
|
|
47
|
+
});
|
|
48
|
+
});
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { fireEvent, render, screen } from "@testing-library/react";
|
|
2
|
+
import { Link, MemoryRouter, useNavigate } from "react-router";
|
|
3
|
+
import ScrollToTop from "../ScrollToTop";
|
|
4
|
+
|
|
5
|
+
const Navigation = () => {
|
|
6
|
+
const navigate = useNavigate();
|
|
7
|
+
return (
|
|
8
|
+
<>
|
|
9
|
+
<Link to="/users/1">User</Link>
|
|
10
|
+
<Link to="/users/1/edit_password">Password</Link>
|
|
11
|
+
<Link to="/users">Close</Link>
|
|
12
|
+
<Link to="/groups">Groups</Link>
|
|
13
|
+
<Link to="/users-other">Other</Link>
|
|
14
|
+
<button onClick={() => navigate(-1)}>Back</button>
|
|
15
|
+
</>
|
|
16
|
+
);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
it("preserves scroll between users and their modals, including browser back", () => {
|
|
20
|
+
const scroll = jest.spyOn(window, "scrollTo").mockImplementation(() => {});
|
|
21
|
+
render(
|
|
22
|
+
<MemoryRouter initialEntries={["/users"]}>
|
|
23
|
+
<ScrollToTop preserveWithin={["/users"]}>
|
|
24
|
+
<Navigation />
|
|
25
|
+
</ScrollToTop>
|
|
26
|
+
</MemoryRouter>,
|
|
27
|
+
);
|
|
28
|
+
expect(scroll).toHaveBeenCalledTimes(1);
|
|
29
|
+
["User", "Password", "Close", "Back"].forEach((name) =>
|
|
30
|
+
fireEvent.click(screen.getByText(name)),
|
|
31
|
+
);
|
|
32
|
+
expect(scroll).toHaveBeenCalledTimes(1);
|
|
33
|
+
fireEvent.click(screen.getByText("Groups"));
|
|
34
|
+
expect(scroll).toHaveBeenCalledTimes(2);
|
|
35
|
+
fireEvent.click(screen.getByText("Close"));
|
|
36
|
+
expect(scroll).toHaveBeenCalledTimes(3);
|
|
37
|
+
fireEvent.click(screen.getByText("Other"));
|
|
38
|
+
expect(scroll).toHaveBeenCalledTimes(4);
|
|
39
|
+
scroll.mockRestore();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("retains the default scroll reset behavior without preserved routes", () => {
|
|
43
|
+
const scroll = jest.spyOn(window, "scrollTo").mockImplementation(() => {});
|
|
44
|
+
render(
|
|
45
|
+
<MemoryRouter initialEntries={["/users"]}>
|
|
46
|
+
<ScrollToTop>
|
|
47
|
+
<Navigation />
|
|
48
|
+
</ScrollToTop>
|
|
49
|
+
</MemoryRouter>,
|
|
50
|
+
);
|
|
51
|
+
fireEvent.click(screen.getByText("User"));
|
|
52
|
+
expect(scroll).toHaveBeenCalledTimes(2);
|
|
53
|
+
scroll.mockRestore();
|
|
54
|
+
});
|
|
@@ -4,6 +4,7 @@ exports[`<FilterDropdown/> matches the latest snapshot 1`] = `
|
|
|
4
4
|
<div>
|
|
5
5
|
<div
|
|
6
6
|
aria-expanded="true"
|
|
7
|
+
aria-label="foo"
|
|
7
8
|
class="ui active visible floating item scrolling dropdown"
|
|
8
9
|
role="listbox"
|
|
9
10
|
tabindex="0"
|
|
@@ -13,8 +14,11 @@ exports[`<FilterDropdown/> matches the latest snapshot 1`] = `
|
|
|
13
14
|
>
|
|
14
15
|
foo
|
|
15
16
|
<i
|
|
16
|
-
aria-hidden="
|
|
17
|
+
aria-hidden="false"
|
|
18
|
+
aria-label="Delete"
|
|
17
19
|
class="delete icon"
|
|
20
|
+
role="button"
|
|
21
|
+
tabindex="0"
|
|
18
22
|
/>
|
|
19
23
|
</div>
|
|
20
24
|
<div
|
|
@@ -24,6 +28,7 @@ exports[`<FilterDropdown/> matches the latest snapshot 1`] = `
|
|
|
24
28
|
aria-checked="false"
|
|
25
29
|
class="item"
|
|
26
30
|
role="option"
|
|
31
|
+
tabindex="0"
|
|
27
32
|
>
|
|
28
33
|
<i
|
|
29
34
|
aria-hidden="true"
|
|
@@ -35,6 +40,7 @@ exports[`<FilterDropdown/> matches the latest snapshot 1`] = `
|
|
|
35
40
|
aria-checked="false"
|
|
36
41
|
class="item"
|
|
37
42
|
role="option"
|
|
43
|
+
tabindex="0"
|
|
38
44
|
>
|
|
39
45
|
<i
|
|
40
46
|
aria-hidden="true"
|
|
@@ -38,6 +38,7 @@ exports[`<SelectedFilters/> matches the latest snapshot 1`] = `
|
|
|
38
38
|
</div>
|
|
39
39
|
<div
|
|
40
40
|
aria-expanded="true"
|
|
41
|
+
aria-label="foo"
|
|
41
42
|
class="ui active visible floating item scrolling dropdown"
|
|
42
43
|
role="listbox"
|
|
43
44
|
tabindex="0"
|
|
@@ -47,8 +48,11 @@ exports[`<SelectedFilters/> matches the latest snapshot 1`] = `
|
|
|
47
48
|
>
|
|
48
49
|
foo
|
|
49
50
|
<i
|
|
50
|
-
aria-hidden="
|
|
51
|
+
aria-hidden="false"
|
|
52
|
+
aria-label="Delete"
|
|
51
53
|
class="delete icon"
|
|
54
|
+
role="button"
|
|
55
|
+
tabindex="0"
|
|
52
56
|
/>
|
|
53
57
|
</div>
|
|
54
58
|
<div
|
|
@@ -58,6 +62,7 @@ exports[`<SelectedFilters/> matches the latest snapshot 1`] = `
|
|
|
58
62
|
aria-checked="false"
|
|
59
63
|
class="item"
|
|
60
64
|
role="option"
|
|
65
|
+
tabindex="0"
|
|
61
66
|
>
|
|
62
67
|
<i
|
|
63
68
|
aria-hidden="true"
|
|
@@ -71,6 +76,7 @@ exports[`<SelectedFilters/> matches the latest snapshot 1`] = `
|
|
|
71
76
|
aria-checked="false"
|
|
72
77
|
class="item"
|
|
73
78
|
role="option"
|
|
79
|
+
tabindex="0"
|
|
74
80
|
>
|
|
75
81
|
<i
|
|
76
82
|
aria-hidden="true"
|
|
@@ -84,6 +90,7 @@ exports[`<SelectedFilters/> matches the latest snapshot 1`] = `
|
|
|
84
90
|
</div>
|
|
85
91
|
<div
|
|
86
92
|
aria-expanded="false"
|
|
93
|
+
aria-label="bar"
|
|
87
94
|
class="ui floating item scrolling dropdown"
|
|
88
95
|
role="listbox"
|
|
89
96
|
tabindex="0"
|
|
@@ -93,8 +100,11 @@ exports[`<SelectedFilters/> matches the latest snapshot 1`] = `
|
|
|
93
100
|
>
|
|
94
101
|
bar
|
|
95
102
|
<i
|
|
96
|
-
aria-hidden="
|
|
103
|
+
aria-hidden="false"
|
|
104
|
+
aria-label="Delete"
|
|
97
105
|
class="delete icon"
|
|
106
|
+
role="button"
|
|
107
|
+
tabindex="0"
|
|
98
108
|
/>
|
|
99
109
|
</div>
|
|
100
110
|
<div
|
|
@@ -144,6 +154,7 @@ exports[`<SelectedFilters/> taxonomy screens matches the latest snapshot 1`] = `
|
|
|
144
154
|
</div>
|
|
145
155
|
<div
|
|
146
156
|
aria-expanded="true"
|
|
157
|
+
aria-label="foo"
|
|
147
158
|
class="ui active visible floating item scrolling dropdown"
|
|
148
159
|
role="listbox"
|
|
149
160
|
tabindex="0"
|
|
@@ -153,8 +164,11 @@ exports[`<SelectedFilters/> taxonomy screens matches the latest snapshot 1`] = `
|
|
|
153
164
|
>
|
|
154
165
|
foo
|
|
155
166
|
<i
|
|
156
|
-
aria-hidden="
|
|
167
|
+
aria-hidden="false"
|
|
168
|
+
aria-label="Delete"
|
|
157
169
|
class="delete icon"
|
|
170
|
+
role="button"
|
|
171
|
+
tabindex="0"
|
|
158
172
|
/>
|
|
159
173
|
</div>
|
|
160
174
|
<div
|
|
@@ -164,6 +178,7 @@ exports[`<SelectedFilters/> taxonomy screens matches the latest snapshot 1`] = `
|
|
|
164
178
|
aria-checked="false"
|
|
165
179
|
class="item"
|
|
166
180
|
role="option"
|
|
181
|
+
tabindex="0"
|
|
167
182
|
>
|
|
168
183
|
<i
|
|
169
184
|
aria-hidden="true"
|
|
@@ -177,6 +192,7 @@ exports[`<SelectedFilters/> taxonomy screens matches the latest snapshot 1`] = `
|
|
|
177
192
|
aria-checked="false"
|
|
178
193
|
class="item"
|
|
179
194
|
role="option"
|
|
195
|
+
tabindex="0"
|
|
180
196
|
>
|
|
181
197
|
<i
|
|
182
198
|
aria-hidden="true"
|
|
@@ -190,6 +206,7 @@ exports[`<SelectedFilters/> taxonomy screens matches the latest snapshot 1`] = `
|
|
|
190
206
|
</div>
|
|
191
207
|
<div
|
|
192
208
|
aria-expanded="false"
|
|
209
|
+
aria-label="bar"
|
|
193
210
|
class="ui floating item scrolling dropdown"
|
|
194
211
|
role="listbox"
|
|
195
212
|
tabindex="0"
|
|
@@ -199,8 +216,11 @@ exports[`<SelectedFilters/> taxonomy screens matches the latest snapshot 1`] = `
|
|
|
199
216
|
>
|
|
200
217
|
bar
|
|
201
218
|
<i
|
|
202
|
-
aria-hidden="
|
|
219
|
+
aria-hidden="false"
|
|
220
|
+
aria-label="Delete"
|
|
203
221
|
class="delete icon"
|
|
222
|
+
role="button"
|
|
223
|
+
tabindex="0"
|
|
204
224
|
/>
|
|
205
225
|
</div>
|
|
206
226
|
<div
|
|
@@ -82,7 +82,7 @@ const LanguageContextProvider = ({ children, defaultMessages }) => {
|
|
|
82
82
|
|
|
83
83
|
const getMessagesForLang = (requestedLang) => {
|
|
84
84
|
if (loading || !requestedLang) return null;
|
|
85
|
-
return
|
|
85
|
+
return { ...defaultMessages[requestedLang], ...messages[requestedLang] };
|
|
86
86
|
};
|
|
87
87
|
|
|
88
88
|
const context = {
|
|
@@ -162,7 +162,7 @@ const Languages = () => {
|
|
|
162
162
|
className="lang-manager-dropdown"
|
|
163
163
|
placeholder={formatMessage({
|
|
164
164
|
id: "i18n.messages.locale.lang_select",
|
|
165
|
-
defaultMessage: "Select
|
|
165
|
+
defaultMessage: "Select language",
|
|
166
166
|
})}
|
|
167
167
|
name="add-locales"
|
|
168
168
|
multiple={false}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { render, screen } from "@testing-library/react";
|
|
2
|
+
import { FormattedMessage } from "react-intl";
|
|
3
|
+
import { useLocales } from "../../../hooks/useLocales";
|
|
4
|
+
import { LangProvider, useLanguage } from "../LangProvider";
|
|
5
|
+
|
|
6
|
+
jest.mock("../../../hooks/useLocales", () => ({ useLocales: jest.fn() }));
|
|
7
|
+
|
|
8
|
+
const defaults = {
|
|
9
|
+
en: { existing: "Local", added: "New local message" },
|
|
10
|
+
es: { added: "Mensaje local" },
|
|
11
|
+
};
|
|
12
|
+
const Catalogs = () => {
|
|
13
|
+
const { getMessagesForLang } = useLanguage();
|
|
14
|
+
return (
|
|
15
|
+
<>
|
|
16
|
+
<FormattedMessage id="existing" />
|
|
17
|
+
<FormattedMessage id="added" />
|
|
18
|
+
<output>{JSON.stringify(getMessagesForLang("es"))}</output>
|
|
19
|
+
</>
|
|
20
|
+
);
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
it("fills missing keys locally while preserving remote translations", () => {
|
|
24
|
+
useLocales.mockReturnValue({
|
|
25
|
+
locales: [
|
|
26
|
+
{
|
|
27
|
+
lang: "en",
|
|
28
|
+
is_default: true,
|
|
29
|
+
is_enabled: true,
|
|
30
|
+
messages: [{ message_id: "existing", definition: "Remote" }],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
loading: false,
|
|
34
|
+
});
|
|
35
|
+
render(
|
|
36
|
+
<LangProvider defaultMessages={defaults}>
|
|
37
|
+
<Catalogs />
|
|
38
|
+
</LangProvider>,
|
|
39
|
+
);
|
|
40
|
+
expect(screen.getByText(/Remote/)).toHaveTextContent("New local message");
|
|
41
|
+
expect(screen.getByRole("status")).toHaveTextContent(
|
|
42
|
+
'{"added":"Mensaje local"}',
|
|
43
|
+
);
|
|
44
|
+
});
|
package/src/messages/en.js
CHANGED
package/src/messages/es.js
CHANGED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
:root {
|
|
2
|
+
--card-groups-popup-background: var(--td-card-accent, #002057);
|
|
3
|
+
--card-groups-popup-text-color: #ffffff;
|
|
4
|
+
--card-groups-popup-muted-text-color: rgba(255, 255, 255, 0.86);
|
|
5
|
+
--card-groups-popup-border-color: rgba(255, 255, 255, 0.24);
|
|
6
|
+
--card-groups-popup-header-background: rgba(255, 255, 255, 0.12);
|
|
7
|
+
--card-groups-popup-item-background: rgba(255, 255, 255, 0.14);
|
|
8
|
+
--card-groups-popup-item-border-color: rgba(255, 255, 255, 0.18);
|
|
9
|
+
--card-groups-popup-marker-background: rgba(255, 255, 255, 0.24);
|
|
10
|
+
--card-groups-popup-marker-color: #ffffff;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
.ui.card {
|
|
14
|
+
--card-accent-color: var(--td-card-accent, #002057);
|
|
15
|
+
--card-accent-70: var(--td-card-accent-70, rgba(0, 32, 87, 0.7));
|
|
16
|
+
--card-border-color: #edf2f7;
|
|
17
|
+
--card-elevation-shadow: 0 12px 28px -10px rgba(15, 23, 42, 0.28);
|
|
18
|
+
--card-motion-duration: 300ms;
|
|
19
|
+
--card-motion-easing: cubic-bezier(0.22, 1, 0.36, 1);
|
|
20
|
+
border: 1px solid var(--card-border-color);
|
|
21
|
+
border-radius: 1.5rem;
|
|
22
|
+
transition:
|
|
23
|
+
transform var(--card-motion-duration) var(--card-motion-easing),
|
|
24
|
+
box-shadow var(--card-motion-duration) var(--card-motion-easing);
|
|
25
|
+
overflow: hidden;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
.ui.cards > .card {
|
|
29
|
+
--card-border-color: #edf2f7;
|
|
30
|
+
--card-elevation-shadow: 0 12px 28px -10px rgba(15, 23, 42, 0.28);
|
|
31
|
+
--card-motion-duration: 300ms;
|
|
32
|
+
--card-motion-easing: cubic-bezier(0.22, 1, 0.36, 1);
|
|
33
|
+
border: 1px solid var(--card-border-color);
|
|
34
|
+
margin: 0.875em 0.5em;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/*******************************
|
|
38
|
+
Unified Card Base
|
|
39
|
+
*******************************/
|
|
40
|
+
|
|
41
|
+
.ui.card.td-card-base {
|
|
42
|
+
--card-accent-color: var(--td-card-accent, #002057);
|
|
43
|
+
--card-accent-shadow: var(--td-card-accent-shadow, rgba(0, 32, 87, 0.18));
|
|
44
|
+
--card-accent-soft: var(--td-card-accent-soft, rgba(0, 32, 87, 0.12));
|
|
45
|
+
--card-accent-70: var(--td-card-accent-70, rgba(0, 32, 87, 0.7));
|
|
46
|
+
--card-secondary-color: var(--td-card-secondary, #ed5c17);
|
|
47
|
+
--card-motion-duration: 300ms;
|
|
48
|
+
--card-motion-easing: cubic-bezier(0.22, 1, 0.36, 1);
|
|
49
|
+
|
|
50
|
+
position: relative;
|
|
51
|
+
overflow: hidden;
|
|
52
|
+
background: #ffffff;
|
|
53
|
+
border: 1px solid var(--card-border-color);
|
|
54
|
+
border-radius: var(--uc-top-left-radius, 1.5rem)
|
|
55
|
+
var(--uc-top-right-radius, 1.5rem) var(--uc-bottom-right-radius, 1.5rem)
|
|
56
|
+
var(--uc-bottom-left-radius, 1.5rem);
|
|
57
|
+
box-shadow: 0 2px 8px rgba(15, 23, 42, 0.08);
|
|
58
|
+
transition:
|
|
59
|
+
transform var(--card-motion-duration) var(--card-motion-easing),
|
|
60
|
+
box-shadow var(--card-motion-duration) var(--card-motion-easing),
|
|
61
|
+
border-color var(--card-motion-duration) var(--card-motion-easing);
|
|
62
|
+
will-change: transform;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.ui.card.td-card-base:hover,
|
|
66
|
+
.ui.card.td-card-base:focus-within {
|
|
67
|
+
border: 1px solid var(--card-border-color);
|
|
68
|
+
box-shadow: var(--card-elevation-shadow);
|
|
69
|
+
transform: translateY(-4px);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.ui.card.td-card-base:active {
|
|
73
|
+
transform: translateY(-1px);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.ui.card.td-card-base:focus-within {
|
|
77
|
+
outline: 2px solid var(--card-accent-soft);
|
|
78
|
+
outline-offset: 2px;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
.ui.card.td-card-base > .hover-indicator {
|
|
82
|
+
display: none;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.ui.card.td-card-base.td-card--structure,
|
|
86
|
+
.ui.card.td-card-base.td-card--user-role {
|
|
87
|
+
width: 100%;
|
|
88
|
+
max-width: 300px;
|
|
89
|
+
height: auto;
|
|
90
|
+
min-height: 130px;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
.ui.card.td-card-base.td-card--user {
|
|
94
|
+
width: 100%;
|
|
95
|
+
max-width: 330px;
|
|
96
|
+
height: auto;
|
|
97
|
+
min-height: 128px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.ui.card.td-card-base.td-card--group {
|
|
101
|
+
width: 100%;
|
|
102
|
+
max-width: 300px;
|
|
103
|
+
height: auto;
|
|
104
|
+
min-height: 112px;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
.ui.card.td-card-base.td-card--taxonomy {
|
|
108
|
+
width: 100%;
|
|
109
|
+
max-width: 290px;
|
|
110
|
+
height: auto;
|
|
111
|
+
min-height: 310px;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.ui.card.td-card-base.td-card--domain {
|
|
115
|
+
width: 100%;
|
|
116
|
+
max-width: 290px;
|
|
117
|
+
height: auto;
|
|
118
|
+
min-height: 240px;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
@media (min-width: 768px) {
|
|
122
|
+
.ui.card.td-card-base.td-card--structure,
|
|
123
|
+
.ui.card.td-card-base.td-card--user-role {
|
|
124
|
+
width: 300px;
|
|
125
|
+
height: 130px;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.ui.card.td-card-base.td-card--user {
|
|
129
|
+
width: 330px;
|
|
130
|
+
height: auto;
|
|
131
|
+
min-height: 128px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.ui.card.td-card-base.td-card--group {
|
|
135
|
+
width: 300px;
|
|
136
|
+
height: auto;
|
|
137
|
+
min-height: 112px;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
.ui.card.td-card-base.td-card--taxonomy {
|
|
141
|
+
width: 290px;
|
|
142
|
+
height: 310px;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.ui.card.td-card-base.td-card--domain {
|
|
146
|
+
width: 290px;
|
|
147
|
+
height: 240px;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
.ui.card:hover,
|
|
152
|
+
.ui.card:focus-within,
|
|
153
|
+
.ui.cards > .card:hover,
|
|
154
|
+
.ui.cards > .card:focus-within,
|
|
155
|
+
.ui.cards > .card.create.link:hover,
|
|
156
|
+
.ui.cards > .card.create.link:focus-within {
|
|
157
|
+
border: 1px solid var(--card-border-color);
|
|
158
|
+
box-shadow: var(--card-elevation-shadow);
|
|
159
|
+
transform: translateY(-4px);
|
|
160
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
@import "./ModalAppearance.less";
|
|
2
|
+
|
|
3
|
+
:root {
|
|
4
|
+
--td-danger: #e42135;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
.ui.small.modal:not(.user-modal):not(.execution-popup-modal):not(.true-modal),
|
|
8
|
+
.ui.mini.modal:not(.user-modal):not(.execution-popup-modal):not(.true-modal) {
|
|
9
|
+
.modal-appearance();
|
|
10
|
+
|
|
11
|
+
> .close.icon {
|
|
12
|
+
.modal-close-appearance();
|
|
13
|
+
width: auto;
|
|
14
|
+
height: auto;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
> .actions {
|
|
18
|
+
display: flex;
|
|
19
|
+
flex-wrap: wrap;
|
|
20
|
+
justify-content: flex-end;
|
|
21
|
+
align-items: center;
|
|
22
|
+
gap: 0.75rem;
|
|
23
|
+
|
|
24
|
+
.button {
|
|
25
|
+
margin: 0;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
.modal-appearance() {
|
|
2
|
+
padding: 0;
|
|
3
|
+
border: 0;
|
|
4
|
+
border-radius: 1rem;
|
|
5
|
+
box-shadow:
|
|
6
|
+
0 20px 25px -5px rgba(0, 0, 0, 0.2),
|
|
7
|
+
0 8px 10px -6px rgba(0, 0, 0, 0.15);
|
|
8
|
+
|
|
9
|
+
> .header {
|
|
10
|
+
padding: 1.5rem 3.5rem 1rem 1.5rem;
|
|
11
|
+
border-radius: 1rem 1rem 0 0;
|
|
12
|
+
border-bottom: 0;
|
|
13
|
+
background: @primaryColor;
|
|
14
|
+
color: #f8fafc;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
> .content {
|
|
18
|
+
padding: 1.625rem 1.5rem 2rem;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
> .actions {
|
|
22
|
+
padding: 1rem 1.5rem;
|
|
23
|
+
padding-bottom: 1rem !important;
|
|
24
|
+
border-radius: 0 0 1rem 1rem;
|
|
25
|
+
border-top: 1px solid #e2e8f0;
|
|
26
|
+
background: #f8fafc;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
.modal-close-appearance() {
|
|
31
|
+
position: absolute;
|
|
32
|
+
top: 1.25rem;
|
|
33
|
+
right: 1rem;
|
|
34
|
+
padding: 6px;
|
|
35
|
+
border: none;
|
|
36
|
+
border-radius: 0.5rem;
|
|
37
|
+
background: none;
|
|
38
|
+
color: #f8fafc;
|
|
39
|
+
cursor: pointer;
|
|
40
|
+
font-size: 1.25rem;
|
|
41
|
+
line-height: 1;
|
|
42
|
+
opacity: 0.8;
|
|
43
|
+
|
|
44
|
+
&:hover {
|
|
45
|
+
opacity: 1;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
&:focus-visible {
|
|
49
|
+
outline: 2px solid currentColor;
|
|
50
|
+
outline-offset: 2px;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
@import "./ModalEffects.less";
|
|
2
|
+
@import "./ModalAppearance.less";
|
|
2
3
|
|
|
3
4
|
.ui.modal.true-modal {
|
|
5
|
+
.modal-appearance();
|
|
4
6
|
display: flex !important;
|
|
5
7
|
flex-direction: column;
|
|
6
8
|
max-width: calc(100vw - 2rem);
|
|
7
9
|
max-height: calc(100vh - 2rem);
|
|
8
10
|
max-height: calc(100dvh - 2rem);
|
|
9
|
-
padding: 0;
|
|
10
|
-
border: 0;
|
|
11
|
-
border-radius: 1rem;
|
|
12
|
-
box-shadow:
|
|
13
|
-
0 20px 25px -5px rgba(0, 0, 0, 0.2),
|
|
14
|
-
0 8px 10px -6px rgba(0, 0, 0, 0.15);
|
|
15
11
|
|
|
16
12
|
> .header {
|
|
17
13
|
display: flex;
|
|
18
14
|
align-items: center;
|
|
19
15
|
gap: 0.75rem;
|
|
20
16
|
flex-shrink: 0;
|
|
21
|
-
padding: 1.5rem 3.5rem 1rem 1.5rem;
|
|
22
|
-
border-radius: 1rem 1rem 0 0;
|
|
23
|
-
border-bottom: 0;
|
|
24
|
-
background: @primaryColor;
|
|
25
|
-
color: #f8fafc;
|
|
26
17
|
|
|
27
18
|
> .icon {
|
|
28
19
|
margin: 0;
|
|
@@ -43,34 +34,13 @@
|
|
|
43
34
|
}
|
|
44
35
|
|
|
45
36
|
> .true-modal-close {
|
|
46
|
-
|
|
47
|
-
top: 1.25rem;
|
|
48
|
-
right: 1rem;
|
|
49
|
-
padding: 6px;
|
|
50
|
-
border: none;
|
|
51
|
-
border-radius: 0.5rem;
|
|
52
|
-
background: none;
|
|
53
|
-
color: #f8fafc;
|
|
54
|
-
cursor: pointer;
|
|
55
|
-
font-size: 1.25rem;
|
|
56
|
-
line-height: 1;
|
|
57
|
-
opacity: 0.8;
|
|
58
|
-
|
|
59
|
-
&:hover {
|
|
60
|
-
opacity: 1;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
&:focus-visible {
|
|
64
|
-
outline: 2px solid currentColor;
|
|
65
|
-
outline-offset: 2px;
|
|
66
|
-
}
|
|
37
|
+
.modal-close-appearance();
|
|
67
38
|
}
|
|
68
39
|
|
|
69
40
|
> .content {
|
|
70
41
|
flex: 1 1 auto;
|
|
71
42
|
min-height: 0;
|
|
72
43
|
overflow-y: auto;
|
|
73
|
-
padding: 1.625rem 1.5rem 2rem;
|
|
74
44
|
}
|
|
75
45
|
|
|
76
46
|
> .actions {
|
|
@@ -80,11 +50,6 @@
|
|
|
80
50
|
justify-content: flex-end;
|
|
81
51
|
align-items: center;
|
|
82
52
|
gap: 0.75rem;
|
|
83
|
-
padding: 1rem 1.5rem;
|
|
84
|
-
padding-bottom: 1rem !important;
|
|
85
|
-
border-radius: 0 0 1rem 1rem;
|
|
86
|
-
border-top: 1px solid #e2e8f0;
|
|
87
|
-
background: #f8fafc;
|
|
88
53
|
|
|
89
54
|
.button {
|
|
90
55
|
margin: 0;
|