@truedat/core 5.20.0 → 5.20.2
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 +2 -2
- package/src/api.js +2 -0
- package/src/components/__tests__/SelectedFilters.spec.js +2 -0
- package/src/hooks/useAllLocales.js +9 -0
- package/src/hooks/useLocales.js +47 -5
- package/src/hooks/useMessages.js +1 -2
- package/src/i18n/components/Languages.js +231 -0
- package/src/i18n/components/MessageForm.js +11 -9
- package/src/i18n/components/Messages.js +58 -25
- package/src/i18n/components/__tests__/MessageForm.spec.js +0 -1
- package/src/i18n/components/__tests__/Messages.spec.js +4 -2
- package/src/i18n/components/__tests__/__snapshots__/Messages.spec.js.snap +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/core",
|
|
3
|
-
"version": "5.20.
|
|
3
|
+
"version": "5.20.2",
|
|
4
4
|
"description": "Truedat Web Core",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -117,5 +117,5 @@
|
|
|
117
117
|
"react-dom": ">= 16.8.6 < 17",
|
|
118
118
|
"semantic-ui-react": ">= 2.0.3 < 2.2"
|
|
119
119
|
},
|
|
120
|
-
"gitHead": "
|
|
120
|
+
"gitHead": "4f02a44805ab1746f026b3fb53e8a3b31ec86765"
|
|
121
121
|
}
|
package/src/api.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
export const API_COMMENTS = "/api/business_concepts/comments";
|
|
2
|
+
export const API_LOCALE = "/api/locales/:id";
|
|
2
3
|
export const API_LOCALE_MESSAGES = "/api/locales/:lang/messages";
|
|
3
4
|
export const API_LOCALES = "/api/locales";
|
|
5
|
+
export const API_ALL_LOCALES = "/api/locales/all_locales";
|
|
4
6
|
export const API_MESSAGE = "/api/messages/:id";
|
|
5
7
|
export const API_MESSAGES = "/api/messages";
|
|
6
8
|
export const API_REINDEX_GRANTS = "/api/grants/search/reindex_all";
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import useSWR from "swr";
|
|
2
|
+
import { API_ALL_LOCALES } from "../api";
|
|
3
|
+
import { apiJson } from "../services/api";
|
|
4
|
+
|
|
5
|
+
export const useAllLocales = () => {
|
|
6
|
+
const { data, loading, error, mutate } = useSWR(API_ALL_LOCALES, apiJson);
|
|
7
|
+
const all_locales = data?.data?.data;
|
|
8
|
+
return { all_locales, error, loading, mutate };
|
|
9
|
+
};
|
package/src/hooks/useLocales.js
CHANGED
|
@@ -1,9 +1,51 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import { compile } from "path-to-regexp";
|
|
1
3
|
import useSWR from "swr";
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
+
import useSWRMutations from "swr/mutation";
|
|
5
|
+
import { API_LOCALES, API_LOCALE } from "../api";
|
|
6
|
+
import {
|
|
7
|
+
apiJson,
|
|
8
|
+
apiJsonDelete,
|
|
9
|
+
apiJsonPatch,
|
|
10
|
+
apiJsonPost,
|
|
11
|
+
} from "../services/api";
|
|
12
|
+
|
|
13
|
+
const toApiLocalesPath = compile(API_LOCALES);
|
|
14
|
+
|
|
15
|
+
export const useLocales = (includeMessages = true) => {
|
|
16
|
+
const url = toApiLocalesPath() + "?includeMessages=" + includeMessages;
|
|
17
|
+
const { data, error, mutate, isValidating } = useSWR(url, apiJson);
|
|
4
18
|
|
|
5
|
-
export const useLocales = () => {
|
|
6
|
-
const { data, error, mutate } = useSWR(API_LOCALES, apiJson);
|
|
7
19
|
const locales = data?.data?.data;
|
|
8
|
-
return { locales, error, loading: !error && !data, mutate };
|
|
20
|
+
return { locales, error, loading: !error && !data, mutate, isValidating };
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export const useLocalesUpdate = (id) => {
|
|
24
|
+
const toApiPath = compile(API_LOCALE);
|
|
25
|
+
const url = toApiPath({ id });
|
|
26
|
+
return useSWRMutations(url, (url, { arg }) => {
|
|
27
|
+
const { mutateData, handleDimmer } = arg;
|
|
28
|
+
const payload = { id: arg.id, locale: arg };
|
|
29
|
+
apiJsonPatch(url, payload).then(() => {
|
|
30
|
+
mutateData();
|
|
31
|
+
handleDimmer(false);
|
|
32
|
+
});
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export const useLocalesCreate = () => {
|
|
37
|
+
const url = API_LOCALES;
|
|
38
|
+
|
|
39
|
+
return useSWRMutations(url, (url, { arg }) => {
|
|
40
|
+
apiJsonPost(url, arg);
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
export const useLocalesDelete = (id) => {
|
|
45
|
+
const toApiPath = compile(API_LOCALE);
|
|
46
|
+
const url = toApiPath({ id });
|
|
47
|
+
return useSWRMutations(url, (url, { arg }) => {
|
|
48
|
+
const payload = { id: arg.id };
|
|
49
|
+
apiJsonDelete(url, payload);
|
|
50
|
+
});
|
|
9
51
|
};
|
package/src/hooks/useMessages.js
CHANGED
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React, { useState } from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { useIntl } from "react-intl";
|
|
5
|
+
import {
|
|
6
|
+
Button,
|
|
7
|
+
Dimmer,
|
|
8
|
+
Dropdown,
|
|
9
|
+
Form,
|
|
10
|
+
Icon,
|
|
11
|
+
Input,
|
|
12
|
+
Loader,
|
|
13
|
+
Table,
|
|
14
|
+
TableBody,
|
|
15
|
+
TableCell,
|
|
16
|
+
TableHeader,
|
|
17
|
+
TableRow,
|
|
18
|
+
} from "semantic-ui-react";
|
|
19
|
+
import { ConfirmModal } from "@truedat/core/components";
|
|
20
|
+
import { useAllLocales } from "../../hooks/useAllLocales";
|
|
21
|
+
import {
|
|
22
|
+
useLocalesCreate,
|
|
23
|
+
useLocalesDelete,
|
|
24
|
+
useLocalesUpdate,
|
|
25
|
+
useLocales,
|
|
26
|
+
} from "../../hooks/useLocales";
|
|
27
|
+
|
|
28
|
+
const LanguajeRow = ({ code, local, name, config, mutate, handleDimmer }) => {
|
|
29
|
+
const { formatMessage } = useIntl();
|
|
30
|
+
const { trigger } = useLocalesUpdate(config.id);
|
|
31
|
+
const { trigger: triggerDelete } = useLocalesDelete(config.id);
|
|
32
|
+
|
|
33
|
+
const handleChange = (data) => {
|
|
34
|
+
const { name, checked } = data;
|
|
35
|
+
const newConfig = {
|
|
36
|
+
...config,
|
|
37
|
+
[name]: !checked,
|
|
38
|
+
};
|
|
39
|
+
handleDimmer(true);
|
|
40
|
+
trigger({ ...newConfig, mutateData: mutate, handleDimmer: handleDimmer });
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const handleDelete = () => {
|
|
44
|
+
triggerDelete(config).then(() => {
|
|
45
|
+
mutate();
|
|
46
|
+
});
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<TableRow>
|
|
51
|
+
<TableCell>
|
|
52
|
+
{_.upperCase(code)} | {local} ( {name} )
|
|
53
|
+
</TableCell>
|
|
54
|
+
<TableCell textAlign="center">
|
|
55
|
+
<Input
|
|
56
|
+
type="checkbox"
|
|
57
|
+
name="is_required"
|
|
58
|
+
checked={config.is_required}
|
|
59
|
+
disabled={config.is_default}
|
|
60
|
+
onChange={(_e, data) => handleChange(data)}
|
|
61
|
+
/>
|
|
62
|
+
</TableCell>
|
|
63
|
+
<TableCell textAlign="center">
|
|
64
|
+
<Input
|
|
65
|
+
id={`radio-${code}`}
|
|
66
|
+
type="radio"
|
|
67
|
+
name="is_default"
|
|
68
|
+
checked={config.is_default}
|
|
69
|
+
onChange={(_e, data) => handleChange(data)}
|
|
70
|
+
/>
|
|
71
|
+
</TableCell>
|
|
72
|
+
<TableCell>
|
|
73
|
+
<ConfirmModal
|
|
74
|
+
icon="trash"
|
|
75
|
+
trigger={
|
|
76
|
+
<Icon
|
|
77
|
+
className="lang-manager-delete"
|
|
78
|
+
name="trash alternate outline"
|
|
79
|
+
color="red"
|
|
80
|
+
disabled={config.is_default || ["es", "en"].includes(code)}
|
|
81
|
+
/>
|
|
82
|
+
}
|
|
83
|
+
header={formatMessage({
|
|
84
|
+
id: "i18n.messages.locale.delete.confirmation.header",
|
|
85
|
+
})}
|
|
86
|
+
content={formatMessage({
|
|
87
|
+
id: "i18n.messages.locale.delete.confirmation.content",
|
|
88
|
+
})}
|
|
89
|
+
onConfirm={() => handleDelete()}
|
|
90
|
+
/>
|
|
91
|
+
</TableCell>
|
|
92
|
+
</TableRow>
|
|
93
|
+
);
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
LanguajeRow.propTypes = {
|
|
97
|
+
code: PropTypes.string,
|
|
98
|
+
local: PropTypes.string,
|
|
99
|
+
name: PropTypes.string,
|
|
100
|
+
config: PropTypes.object,
|
|
101
|
+
mutate: PropTypes.func,
|
|
102
|
+
handleDimmer: PropTypes.func,
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
const Languages = () => {
|
|
106
|
+
const includeMessages = false;
|
|
107
|
+
const {
|
|
108
|
+
locales,
|
|
109
|
+
loading: loadingUseLocales,
|
|
110
|
+
mutate,
|
|
111
|
+
isValidating,
|
|
112
|
+
} = useLocales(includeMessages);
|
|
113
|
+
const langs = _.map("lang")(locales);
|
|
114
|
+
|
|
115
|
+
const { formatMessage } = useIntl();
|
|
116
|
+
const { all_locales, loading, error } = useAllLocales();
|
|
117
|
+
const [newLocales, setNewLocales] = useState([]);
|
|
118
|
+
const { trigger } = useLocalesCreate();
|
|
119
|
+
const [dimmerState, setDimmerState] = useState(false);
|
|
120
|
+
|
|
121
|
+
const handleDimmer = (isMutating) => {
|
|
122
|
+
setDimmerState(isMutating);
|
|
123
|
+
};
|
|
124
|
+
|
|
125
|
+
const langsConfig = _.flow(
|
|
126
|
+
_.map((locale) => _.omit("messages")(locale)),
|
|
127
|
+
_.groupBy("lang"),
|
|
128
|
+
_.mapValues(_.first)
|
|
129
|
+
)(locales);
|
|
130
|
+
|
|
131
|
+
const options = _.flow(
|
|
132
|
+
_.filter(({ code }) => {
|
|
133
|
+
return !langs.includes(code);
|
|
134
|
+
}),
|
|
135
|
+
_.map(({ code, name, local }) => {
|
|
136
|
+
return { text: `${local} (${name} | ${code})`, value: code };
|
|
137
|
+
})
|
|
138
|
+
)(all_locales);
|
|
139
|
+
|
|
140
|
+
const handleOnChange = ({ value }) => {
|
|
141
|
+
setNewLocales(value);
|
|
142
|
+
};
|
|
143
|
+
|
|
144
|
+
const handleSubmit = () => {
|
|
145
|
+
setNewLocales([]);
|
|
146
|
+
trigger({ locales: newLocales }).then(() => {
|
|
147
|
+
mutate();
|
|
148
|
+
});
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
return (
|
|
152
|
+
<>
|
|
153
|
+
<Form
|
|
154
|
+
onSubmit={() => {
|
|
155
|
+
handleSubmit();
|
|
156
|
+
}}
|
|
157
|
+
>
|
|
158
|
+
<Dropdown
|
|
159
|
+
className="lang-manager-dropdown"
|
|
160
|
+
placeholder={formatMessage({
|
|
161
|
+
id: "i18n.messages.locale.lang_select",
|
|
162
|
+
defaultMessage: "Select languaje",
|
|
163
|
+
})}
|
|
164
|
+
name="add-locales"
|
|
165
|
+
multiple={true}
|
|
166
|
+
search={true}
|
|
167
|
+
selection={true}
|
|
168
|
+
options={options}
|
|
169
|
+
clearable={true}
|
|
170
|
+
value={newLocales}
|
|
171
|
+
onChange={(_e, data) => {
|
|
172
|
+
handleOnChange(data);
|
|
173
|
+
}}
|
|
174
|
+
/>
|
|
175
|
+
<Button
|
|
176
|
+
type="submit"
|
|
177
|
+
className="lang-manager-button"
|
|
178
|
+
disabled={_.isEmpty(newLocales)}
|
|
179
|
+
>
|
|
180
|
+
{formatMessage({
|
|
181
|
+
id: "i18n.messages.locale.add_lang",
|
|
182
|
+
})}
|
|
183
|
+
</Button>
|
|
184
|
+
</Form>
|
|
185
|
+
|
|
186
|
+
<Dimmer.Dimmable dimmed={isValidating || dimmerState}>
|
|
187
|
+
<Dimmer active={isValidating || dimmerState} inverted>
|
|
188
|
+
<Loader />
|
|
189
|
+
</Dimmer>
|
|
190
|
+
<Table collapsing striped>
|
|
191
|
+
<TableHeader>
|
|
192
|
+
<TableRow>
|
|
193
|
+
<TableCell></TableCell>
|
|
194
|
+
<TableCell textAlign="center">
|
|
195
|
+
{formatMessage({
|
|
196
|
+
id: "i18n.messages.locale.required",
|
|
197
|
+
})}
|
|
198
|
+
</TableCell>
|
|
199
|
+
<TableCell textAlign="center">
|
|
200
|
+
{formatMessage({
|
|
201
|
+
id: "i18n.messages.locale.default",
|
|
202
|
+
})}
|
|
203
|
+
</TableCell>
|
|
204
|
+
<TableCell></TableCell>
|
|
205
|
+
</TableRow>
|
|
206
|
+
</TableHeader>
|
|
207
|
+
<TableBody>
|
|
208
|
+
{_.flow(
|
|
209
|
+
_.filter((locale) => _.includes(locale.code)(langs)),
|
|
210
|
+
_.map(({ code, local, name }) => {
|
|
211
|
+
return (
|
|
212
|
+
<LanguajeRow
|
|
213
|
+
key={code}
|
|
214
|
+
code={code}
|
|
215
|
+
local={local}
|
|
216
|
+
name={name}
|
|
217
|
+
config={langsConfig[code]}
|
|
218
|
+
mutate={mutate}
|
|
219
|
+
handleDimmer={handleDimmer}
|
|
220
|
+
/>
|
|
221
|
+
);
|
|
222
|
+
})
|
|
223
|
+
)(all_locales)}
|
|
224
|
+
</TableBody>
|
|
225
|
+
</Table>
|
|
226
|
+
</Dimmer.Dimmable>
|
|
227
|
+
</>
|
|
228
|
+
);
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
export default Languages;
|
|
@@ -104,15 +104,17 @@ export const MessageForm = ({ onSubmit, isSubmitting }) => {
|
|
|
104
104
|
)}
|
|
105
105
|
/>
|
|
106
106
|
|
|
107
|
-
{locales
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
{locales
|
|
108
|
+
.filter(({ lang }) => lang === "en" || lang === "es")
|
|
109
|
+
.map((lang, i) => (
|
|
110
|
+
<LangForm
|
|
111
|
+
key={i}
|
|
112
|
+
control={control}
|
|
113
|
+
lang={lang}
|
|
114
|
+
errors={errors}
|
|
115
|
+
formatMessage={formatMessage}
|
|
116
|
+
/>
|
|
117
|
+
))}
|
|
116
118
|
|
|
117
119
|
<div className="actions">
|
|
118
120
|
<Button
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
2
|
import React, { useState } from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
3
4
|
import { useIntl, FormattedMessage } from "react-intl";
|
|
4
5
|
import {
|
|
5
6
|
Button,
|
|
@@ -18,12 +19,18 @@ import { useLocales } from "@truedat/core/hooks";
|
|
|
18
19
|
import { I18N_MESSAGES_NEW } from "@truedat/core/routes";
|
|
19
20
|
import { Pagination } from "@truedat/core/components";
|
|
20
21
|
import MessagesTable from "./MessagesTable";
|
|
22
|
+
import Languages from "./Languages";
|
|
21
23
|
|
|
22
24
|
const ITEMS_PER_PAGE = 30;
|
|
23
25
|
|
|
24
26
|
export function MessagesContent({ locales, loading }) {
|
|
25
27
|
const langs = _.map("lang")(locales);
|
|
26
|
-
|
|
28
|
+
|
|
29
|
+
const [selectedLang, setSelectedLang] = useState(
|
|
30
|
+
_.head(_.filter((lang) => lang === "en" || lang === "es")(langs))
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
const [selectedManageView, setSelectedManageView] = useState(false);
|
|
27
34
|
const [page, setPage] = useState(1);
|
|
28
35
|
const [filter, setFilter] = useState("");
|
|
29
36
|
const { formatMessage } = useIntl();
|
|
@@ -56,38 +63,64 @@ export function MessagesContent({ locales, loading }) {
|
|
|
56
63
|
return (
|
|
57
64
|
<>
|
|
58
65
|
<Menu attached="top" secondary pointing tabular>
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
66
|
+
<Menu.Item
|
|
67
|
+
key={0}
|
|
68
|
+
active={selectedManageView}
|
|
69
|
+
onClick={() => setSelectedManageView(true)}
|
|
70
|
+
>
|
|
71
|
+
<FormattedMessage id="i18n.messages.locale.manage" />
|
|
72
|
+
</Menu.Item>
|
|
73
|
+
{langs
|
|
74
|
+
.filter((lang) => lang === "en" || lang === "es")
|
|
75
|
+
.map((lang, i) => (
|
|
76
|
+
<Menu.Item
|
|
77
|
+
key={i}
|
|
78
|
+
active={lang === selectedLang && !selectedManageView}
|
|
79
|
+
onClick={() => {
|
|
80
|
+
setSelectedLang(lang);
|
|
81
|
+
setSelectedManageView(false);
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
<FormattedMessage id={`i18n.messages.locale.${lang}`} />
|
|
85
|
+
</Menu.Item>
|
|
86
|
+
))}
|
|
68
87
|
</Menu>
|
|
69
88
|
<Divider hidden />
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
{!selectedManageView ? (
|
|
90
|
+
<>
|
|
91
|
+
<SearchInput
|
|
92
|
+
onChange={handleSearch}
|
|
93
|
+
placeholder={formatMessage({
|
|
94
|
+
id: "i18n.messages.search.placeholder",
|
|
95
|
+
})}
|
|
96
|
+
value={filter}
|
|
97
|
+
/>
|
|
98
|
+
<MessagesTable
|
|
99
|
+
messages={paginatedMessages}
|
|
100
|
+
locales={locales}
|
|
101
|
+
loading={loading}
|
|
102
|
+
/>
|
|
103
|
+
<Pagination
|
|
104
|
+
totalPages={totalPages}
|
|
105
|
+
activePage={page}
|
|
106
|
+
selectPage={({ activePage }) => setPage(activePage)}
|
|
107
|
+
/>
|
|
108
|
+
</>
|
|
109
|
+
) : (
|
|
110
|
+
<Languages />
|
|
111
|
+
)}
|
|
85
112
|
</>
|
|
86
113
|
);
|
|
87
114
|
}
|
|
88
115
|
|
|
116
|
+
MessagesContent.propTypes = {
|
|
117
|
+
locales: PropTypes.array,
|
|
118
|
+
loading: PropTypes.bool,
|
|
119
|
+
};
|
|
120
|
+
|
|
89
121
|
export default function Messages() {
|
|
90
122
|
const { formatMessage } = useIntl();
|
|
123
|
+
|
|
91
124
|
const { locales, loading } = useLocales();
|
|
92
125
|
|
|
93
126
|
return (
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { render } from "@truedat/test/render";
|
|
3
|
-
import
|
|
3
|
+
import en from "@truedat/core/messages/en";
|
|
4
4
|
import Messages from "../Messages";
|
|
5
5
|
|
|
6
|
-
const renderOpts = {
|
|
6
|
+
const renderOpts = {
|
|
7
|
+
messages: { en: { ...en, "i18n.messages.locale.manage": "manage" } },
|
|
8
|
+
};
|
|
7
9
|
|
|
8
10
|
jest.mock("@truedat/core/hooks", () => ({
|
|
9
11
|
useLocales: jest.fn(() => ({
|