@dhis2/analytics 21.0.11 → 21.2.0
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 +28 -0
- package/build/cjs/components/FileMenu/FileMenu.js +6 -16
- package/build/cjs/components/FileMenu/__tests__/FileMenu.spec.js +3 -3
- package/build/cjs/components/TranslationDialog/TranslationModal/LocalesSelect.js +69 -0
- package/build/cjs/components/TranslationDialog/TranslationModal/TranslationForm.js +149 -0
- package/build/cjs/components/TranslationDialog/TranslationModal/TranslationModal.js +76 -0
- package/build/cjs/components/TranslationDialog/TranslationModal/TranslationModalActions.js +39 -0
- package/build/cjs/components/TranslationDialog/TranslationModal/useTranslationsResults.js +46 -0
- package/build/cjs/components/TranslationDialog/index.js +13 -0
- package/build/cjs/index.js +8 -0
- package/build/cjs/locales/ar/translations.json +1 -1
- package/build/cjs/locales/en/translations.json +8 -0
- package/build/cjs/modules/pivotTable/PivotTableEngine.js +4 -3
- package/build/es/components/FileMenu/FileMenu.js +4 -14
- package/build/es/components/FileMenu/__tests__/FileMenu.spec.js +1 -1
- package/build/es/components/TranslationDialog/TranslationModal/LocalesSelect.js +52 -0
- package/build/es/components/TranslationDialog/TranslationModal/TranslationForm.js +126 -0
- package/build/es/components/TranslationDialog/TranslationModal/TranslationModal.js +54 -0
- package/build/es/components/TranslationDialog/TranslationModal/TranslationModalActions.js +24 -0
- package/build/es/components/TranslationDialog/TranslationModal/useTranslationsResults.js +32 -0
- package/build/es/components/TranslationDialog/index.js +2 -0
- package/build/es/index.js +3 -1
- package/build/es/locales/ar/translations.json +1 -1
- package/build/es/locales/en/translations.json +8 -0
- package/build/es/modules/pivotTable/PivotTableEngine.js +4 -3
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,31 @@
|
|
|
1
|
+
# [21.2.0](https://github.com/dhis2/analytics/compare/v21.1.1...v21.2.0) (2021-12-23)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Features
|
|
5
|
+
|
|
6
|
+
* use new translations dialog (TECH-873) ([#1105](https://github.com/dhis2/analytics/issues/1105)) ([1e1a984](https://github.com/dhis2/analytics/commit/1e1a98429663241487ad66c56d3aab3914b8cbc6))
|
|
7
|
+
|
|
8
|
+
## [21.1.1](https://github.com/dhis2/analytics/compare/v21.1.0...v21.1.1) (2021-12-22)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* do not fix headers if no dimension items are selected ([#1057](https://github.com/dhis2/analytics/issues/1057)) ([ae51967](https://github.com/dhis2/analytics/commit/ae51967ff35a17b8589f4959015b06c4913b7dae))
|
|
14
|
+
|
|
15
|
+
# [21.1.0](https://github.com/dhis2/analytics/compare/v21.0.12...v21.1.0) (2021-12-20)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* export formatValue function ([#1080](https://github.com/dhis2/analytics/issues/1080)) ([20d0f5a](https://github.com/dhis2/analytics/commit/20d0f5a1b2eda14879f03a4c6d37337c80bb15ff))
|
|
21
|
+
|
|
22
|
+
## [21.0.12](https://github.com/dhis2/analytics/compare/v21.0.11...v21.0.12) (2021-12-11)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
### Bug Fixes
|
|
26
|
+
|
|
27
|
+
* **translations:** sync translations from transifex (master) ([ac9ad8c](https://github.com/dhis2/analytics/commit/ac9ad8ca44fa56d976e11c554a894b6aafebb58c))
|
|
28
|
+
|
|
1
29
|
## [21.0.11](https://github.com/dhis2/analytics/compare/v21.0.10...v21.0.11) (2021-12-10)
|
|
2
30
|
|
|
3
31
|
|
|
@@ -7,8 +7,6 @@ exports.default = exports.FileMenu = void 0;
|
|
|
7
7
|
|
|
8
8
|
var _style = _interopRequireDefault(require("styled-jsx/style"));
|
|
9
9
|
|
|
10
|
-
var _d2UiTranslationDialog = _interopRequireDefault(require("@dhis2/d2-ui-translation-dialog"));
|
|
11
|
-
|
|
12
10
|
var _ui = require("@dhis2/ui");
|
|
13
11
|
|
|
14
12
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
@@ -19,6 +17,8 @@ var _index = _interopRequireDefault(require("../../locales/index.js"));
|
|
|
19
17
|
|
|
20
18
|
var _OpenFileDialog = require("../OpenFileDialog/OpenFileDialog.js");
|
|
21
19
|
|
|
20
|
+
var _index2 = require("../TranslationDialog/index.js");
|
|
21
|
+
|
|
22
22
|
var _DeleteDialog = require("./DeleteDialog.js");
|
|
23
23
|
|
|
24
24
|
var _FileMenuStyles = require("./FileMenu.styles.js");
|
|
@@ -95,21 +95,11 @@ const FileMenu = ({
|
|
|
95
95
|
});
|
|
96
96
|
|
|
97
97
|
case 'translate':
|
|
98
|
-
return /*#__PURE__*/_react.default.createElement(
|
|
99
|
-
|
|
100
|
-
d2: d2,
|
|
101
|
-
objectToTranslate: { ...fileObject,
|
|
102
|
-
// mock modelDefinition to avoid an error
|
|
103
|
-
// in the TranslationDialog component
|
|
104
|
-
modelDefinition: {
|
|
105
|
-
name: fileType
|
|
106
|
-
}
|
|
107
|
-
},
|
|
98
|
+
return /*#__PURE__*/_react.default.createElement(_index2.TranslationDialog, {
|
|
99
|
+
objectToTranslate: fileObject,
|
|
108
100
|
fieldsToTranslate: ['name', 'description'],
|
|
109
|
-
|
|
110
|
-
onTranslationSaved: onTranslate
|
|
111
|
-
onTranslationError: onError,
|
|
112
|
-
insertTheme: true
|
|
101
|
+
onClose: onDialogClose,
|
|
102
|
+
onTranslationSaved: onTranslate
|
|
113
103
|
});
|
|
114
104
|
|
|
115
105
|
case 'sharing':
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
var _d2UiTranslationDialog = _interopRequireDefault(require("@dhis2/d2-ui-translation-dialog"));
|
|
4
|
-
|
|
5
3
|
var _ui = require("@dhis2/ui");
|
|
6
4
|
|
|
7
5
|
var _enzyme = require("enzyme");
|
|
@@ -10,6 +8,8 @@ var _react = _interopRequireDefault(require("react"));
|
|
|
10
8
|
|
|
11
9
|
var _OpenFileDialog = require("../../OpenFileDialog/OpenFileDialog.js");
|
|
12
10
|
|
|
11
|
+
var _index = require("../../TranslationDialog/index.js");
|
|
12
|
+
|
|
13
13
|
var _DeleteDialog = require("../DeleteDialog.js");
|
|
14
14
|
|
|
15
15
|
var _FileMenu = require("../FileMenu.js");
|
|
@@ -152,7 +152,7 @@ describe('The FileMenu component ', () => {
|
|
|
152
152
|
const fileMenuComponent = getFileMenuComponent(props);
|
|
153
153
|
fileMenuComponent.find('button').simulate('click');
|
|
154
154
|
fileMenuComponent.findWhere(n => n.prop('label') === 'Translate…').simulate('click');
|
|
155
|
-
expect(fileMenuComponent.find(
|
|
155
|
+
expect(fileMenuComponent.find(_index.TranslationDialog)).toHaveLength(1);
|
|
156
156
|
});
|
|
157
157
|
it('renders the SharingDialog when the Share button is clicked', () => {
|
|
158
158
|
props.fileObject = {
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.LocalesSelect = void 0;
|
|
7
|
+
|
|
8
|
+
var _appRuntime = require("@dhis2/app-runtime");
|
|
9
|
+
|
|
10
|
+
var _d2I18n = _interopRequireDefault(require("@dhis2/d2-i18n"));
|
|
11
|
+
|
|
12
|
+
var _ui = require("@dhis2/ui");
|
|
13
|
+
|
|
14
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
15
|
+
|
|
16
|
+
var _react = _interopRequireDefault(require("react"));
|
|
17
|
+
|
|
18
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
19
|
+
|
|
20
|
+
const query = {
|
|
21
|
+
locales: {
|
|
22
|
+
resource: 'locales/db'
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
const LocalesSelect = ({
|
|
27
|
+
onChange,
|
|
28
|
+
selected
|
|
29
|
+
}) => {
|
|
30
|
+
const {
|
|
31
|
+
data,
|
|
32
|
+
fetching
|
|
33
|
+
} = (0, _appRuntime.useDataQuery)(query);
|
|
34
|
+
return /*#__PURE__*/_react.default.createElement(_ui.SingleSelect, {
|
|
35
|
+
prefix: selected ? _d2I18n.default.t('Translating to') : _d2I18n.default.t('Choose a locale'),
|
|
36
|
+
onChange: ({
|
|
37
|
+
selected
|
|
38
|
+
}) => onChange(selected),
|
|
39
|
+
loading: fetching,
|
|
40
|
+
selected: data ? selected : undefined,
|
|
41
|
+
dense: true
|
|
42
|
+
}, data && data.locales // XXX remove duplicates ?! fr_SN - French (Senegal)
|
|
43
|
+
.reduce((locales, {
|
|
44
|
+
locale,
|
|
45
|
+
name
|
|
46
|
+
}) => {
|
|
47
|
+
if (!locales.find(entry => entry.locale === locale)) {
|
|
48
|
+
locales.push({
|
|
49
|
+
locale,
|
|
50
|
+
name
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return locales;
|
|
55
|
+
}, []).map(({
|
|
56
|
+
locale,
|
|
57
|
+
name
|
|
58
|
+
}) => /*#__PURE__*/_react.default.createElement(_ui.SingleSelectOption, {
|
|
59
|
+
key: locale,
|
|
60
|
+
value: locale,
|
|
61
|
+
label: name
|
|
62
|
+
})));
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
exports.LocalesSelect = LocalesSelect;
|
|
66
|
+
LocalesSelect.propTypes = {
|
|
67
|
+
onChange: _propTypes.default.func.isRequired,
|
|
68
|
+
selected: _propTypes.default.string
|
|
69
|
+
};
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TranslationForm = void 0;
|
|
7
|
+
|
|
8
|
+
var _appRuntime = require("@dhis2/app-runtime");
|
|
9
|
+
|
|
10
|
+
var _d2I18n = _interopRequireDefault(require("@dhis2/d2-i18n"));
|
|
11
|
+
|
|
12
|
+
var _ui = require("@dhis2/ui");
|
|
13
|
+
|
|
14
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
15
|
+
|
|
16
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
17
|
+
|
|
18
|
+
var _LocalesSelect = require("./LocalesSelect.js");
|
|
19
|
+
|
|
20
|
+
var _TranslationModalActions = require("./TranslationModalActions.js");
|
|
21
|
+
|
|
22
|
+
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
23
|
+
|
|
24
|
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
25
|
+
|
|
26
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
27
|
+
|
|
28
|
+
const SESSION_STORAGE_TRANSLATION_LOCALE_KEY = 'translation-dialog-selected-locale';
|
|
29
|
+
|
|
30
|
+
const TranslationForm = ({
|
|
31
|
+
fieldsToTranslate,
|
|
32
|
+
objectToTranslate,
|
|
33
|
+
translations,
|
|
34
|
+
resource,
|
|
35
|
+
onTranslationSaved,
|
|
36
|
+
onClose
|
|
37
|
+
}) => {
|
|
38
|
+
const [newTranslations, setNewTranslations] = (0, _react.useState)();
|
|
39
|
+
const [translationLocale, setTranslationLocale] = (0, _react.useState)();
|
|
40
|
+
const {
|
|
41
|
+
show: showError
|
|
42
|
+
} = (0, _appRuntime.useAlert)(error => error, {
|
|
43
|
+
critical: true
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const formatFieldLabel = field => {
|
|
47
|
+
field.replace(/[a-z][A-Z]/g, match => [match.charAt(0), match.charAt(1)].join(' ')).toLowerCase();
|
|
48
|
+
return field.charAt(0).toUpperCase() + field.slice(1);
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const camelCaseToUnderscores = field => field.replace(/[a-z][A-Z]/g, match => [match.charAt(0), match.charAt(1)].join('_')).toLowerCase();
|
|
52
|
+
|
|
53
|
+
const getTranslationIndexForField = field => newTranslations.findIndex(element => element.locale === translationLocale && element.property.toLowerCase() === camelCaseToUnderscores(field));
|
|
54
|
+
|
|
55
|
+
const getTranslationForField = field => {
|
|
56
|
+
var _newTranslations$tran;
|
|
57
|
+
|
|
58
|
+
const translationIndex = getTranslationIndexForField(field);
|
|
59
|
+
return translationIndex !== -1 ? ((_newTranslations$tran = newTranslations[translationIndex]) === null || _newTranslations$tran === void 0 ? void 0 : _newTranslations$tran.value) || '' : '';
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
const setTranslationForField = (field, translation) => {
|
|
63
|
+
const newTranslation = {
|
|
64
|
+
locale: translationLocale,
|
|
65
|
+
property: camelCaseToUnderscores(field).toUpperCase(),
|
|
66
|
+
value: translation
|
|
67
|
+
};
|
|
68
|
+
const translationIndex = getTranslationIndexForField(field);
|
|
69
|
+
setNewTranslations(translationIndex === -1 ? [...newTranslations, newTranslation] : newTranslations.map((translation, index) => index === translationIndex ? newTranslation : translation));
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const translationsMutationRef = (0, _react.useRef)({
|
|
73
|
+
resource: "".concat(resource, "/translations"),
|
|
74
|
+
type: 'update',
|
|
75
|
+
data: ({
|
|
76
|
+
translations
|
|
77
|
+
}) => ({
|
|
78
|
+
translations
|
|
79
|
+
})
|
|
80
|
+
});
|
|
81
|
+
const [saveTranslations, {
|
|
82
|
+
loading: saveInProgress
|
|
83
|
+
}] = (0, _appRuntime.useDataMutation)(translationsMutationRef.current, {
|
|
84
|
+
onComplete: () => {
|
|
85
|
+
onTranslationSaved();
|
|
86
|
+
onClose();
|
|
87
|
+
},
|
|
88
|
+
onError: error => {
|
|
89
|
+
showError(error);
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
const onLocaleChange = locale => {
|
|
94
|
+
setTranslationLocale(locale);
|
|
95
|
+
window.sessionStorage.setItem(SESSION_STORAGE_TRANSLATION_LOCALE_KEY, locale);
|
|
96
|
+
};
|
|
97
|
+
|
|
98
|
+
const save = () => saveTranslations({
|
|
99
|
+
translations: newTranslations
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
(0, _react.useEffect)(() => setTranslationLocale(window.sessionStorage.getItem(SESSION_STORAGE_TRANSLATION_LOCALE_KEY)), []);
|
|
103
|
+
(0, _react.useEffect)(() => setNewTranslations(translations), [translations]);
|
|
104
|
+
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_ui.ModalContent, null, /*#__PURE__*/_react.default.createElement(_ui.DataTable, {
|
|
105
|
+
layout: "fixed"
|
|
106
|
+
}, /*#__PURE__*/_react.default.createElement(_ui.DataTableHead, null, /*#__PURE__*/_react.default.createElement(_ui.DataTableRow, null, /*#__PURE__*/_react.default.createElement(_ui.DataTableColumnHeader, {
|
|
107
|
+
fixed: true,
|
|
108
|
+
top: "0"
|
|
109
|
+
}, _d2I18n.default.t('Base locale reference')), /*#__PURE__*/_react.default.createElement(_ui.DataTableColumnHeader, {
|
|
110
|
+
fixed: true,
|
|
111
|
+
top: "0"
|
|
112
|
+
}, /*#__PURE__*/_react.default.createElement(_LocalesSelect.LocalesSelect, {
|
|
113
|
+
selected: translationLocale,
|
|
114
|
+
onChange: onLocaleChange
|
|
115
|
+
})))), /*#__PURE__*/_react.default.createElement(_ui.DataTableBody, null, fieldsToTranslate.map((field, index) => /*#__PURE__*/_react.default.createElement(_ui.DataTableRow, {
|
|
116
|
+
key: field
|
|
117
|
+
}, /*#__PURE__*/_react.default.createElement(_ui.DataTableCell, null, /*#__PURE__*/_react.default.createElement("div", {
|
|
118
|
+
className: ""
|
|
119
|
+
}, /*#__PURE__*/_react.default.createElement(_ui.InputField, {
|
|
120
|
+
label: formatFieldLabel(field),
|
|
121
|
+
value: objectToTranslate[field],
|
|
122
|
+
readOnly: true
|
|
123
|
+
}))), translationLocale && /*#__PURE__*/_react.default.createElement(_ui.DataTableCell, null, /*#__PURE__*/_react.default.createElement("div", {
|
|
124
|
+
className: ""
|
|
125
|
+
}, /*#__PURE__*/_react.default.createElement(_ui.InputField, {
|
|
126
|
+
label: formatFieldLabel(field),
|
|
127
|
+
value: getTranslationForField(field),
|
|
128
|
+
onChange: ({
|
|
129
|
+
value
|
|
130
|
+
}) => setTranslationForField(field, value)
|
|
131
|
+
}))), !translationLocale && index === 0 && /*#__PURE__*/_react.default.createElement(_ui.DataTableCell, {
|
|
132
|
+
rowSpan: String(fieldsToTranslate.length)
|
|
133
|
+
}, /*#__PURE__*/_react.default.createElement(_ui.CenteredContent, null, _d2I18n.default.t('Choose a locale to translate from the menu above')))))))), /*#__PURE__*/_react.default.createElement(_TranslationModalActions.TranslationModalActions, {
|
|
134
|
+
onClose: onClose,
|
|
135
|
+
onSave: save,
|
|
136
|
+
saveInProgress: saveInProgress,
|
|
137
|
+
saveButtonDisabled: !translationLocale
|
|
138
|
+
}));
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
exports.TranslationForm = TranslationForm;
|
|
142
|
+
TranslationForm.propTypes = {
|
|
143
|
+
fieldsToTranslate: _propTypes.default.array.isRequired,
|
|
144
|
+
objectToTranslate: _propTypes.default.object.isRequired,
|
|
145
|
+
resource: _propTypes.default.string.isRequired,
|
|
146
|
+
translations: _propTypes.default.array.isRequired,
|
|
147
|
+
onClose: _propTypes.default.func.isRequired,
|
|
148
|
+
onTranslationSaved: _propTypes.default.func.isRequired
|
|
149
|
+
};
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TranslationModal = void 0;
|
|
7
|
+
|
|
8
|
+
var _d2I18n = _interopRequireDefault(require("@dhis2/d2-i18n"));
|
|
9
|
+
|
|
10
|
+
var _ui = require("@dhis2/ui");
|
|
11
|
+
|
|
12
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
13
|
+
|
|
14
|
+
var _react = _interopRequireWildcard(require("react"));
|
|
15
|
+
|
|
16
|
+
var _TranslationForm = require("./TranslationForm.js");
|
|
17
|
+
|
|
18
|
+
var _TranslationModalActions = require("./TranslationModalActions.js");
|
|
19
|
+
|
|
20
|
+
var _useTranslationsResults = require("./useTranslationsResults.js");
|
|
21
|
+
|
|
22
|
+
function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function () { return cache; }; return cache; }
|
|
23
|
+
|
|
24
|
+
function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
25
|
+
|
|
26
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
27
|
+
|
|
28
|
+
const TranslationModal = ({
|
|
29
|
+
objectToTranslate,
|
|
30
|
+
fieldsToTranslate,
|
|
31
|
+
onClose,
|
|
32
|
+
onTranslationSaved
|
|
33
|
+
}) => {
|
|
34
|
+
const [translations, setTranslations] = (0, _react.useState)([]);
|
|
35
|
+
const endpointPath = new URL(objectToTranslate.href).pathname;
|
|
36
|
+
const endpointPathMatch = endpointPath.match(/api\/\d+\/(?<resource>.+)/);
|
|
37
|
+
const resource = endpointPathMatch !== null && endpointPathMatch !== void 0 && endpointPathMatch.groups ? endpointPathMatch.groups.resource : null;
|
|
38
|
+
const {
|
|
39
|
+
translationsData,
|
|
40
|
+
fetching
|
|
41
|
+
} = (0, _useTranslationsResults.useTranslationsResults)({
|
|
42
|
+
resource
|
|
43
|
+
});
|
|
44
|
+
(0, _react.useEffect)(() => {
|
|
45
|
+
if (translationsData) {
|
|
46
|
+
setTranslations(translationsData);
|
|
47
|
+
}
|
|
48
|
+
}, [translationsData]);
|
|
49
|
+
return /*#__PURE__*/_react.default.createElement(_ui.Modal, {
|
|
50
|
+
large: true,
|
|
51
|
+
position: "middle",
|
|
52
|
+
onClose: onClose
|
|
53
|
+
}, /*#__PURE__*/_react.default.createElement(_ui.ModalTitle, null, _d2I18n.default.t('Translate: {{objectName}}', {
|
|
54
|
+
objectName: objectToTranslate.name || 'TEXT',
|
|
55
|
+
// XXX
|
|
56
|
+
nsSeparator: '^^'
|
|
57
|
+
})), fetching ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_ui.ModalContent, null, /*#__PURE__*/_react.default.createElement(_ui.CenteredContent, null, /*#__PURE__*/_react.default.createElement(_ui.CircularLoader, null))), /*#__PURE__*/_react.default.createElement(_TranslationModalActions.TranslationModalActions, {
|
|
58
|
+
onClose: onClose,
|
|
59
|
+
saveButtonDisabled: true
|
|
60
|
+
})) : /*#__PURE__*/_react.default.createElement(_TranslationForm.TranslationForm, {
|
|
61
|
+
fieldsToTranslate: fieldsToTranslate,
|
|
62
|
+
objectToTranslate: objectToTranslate,
|
|
63
|
+
translations: translations,
|
|
64
|
+
onTranslationSaved: onTranslationSaved,
|
|
65
|
+
resource: resource,
|
|
66
|
+
onClose: onClose
|
|
67
|
+
}));
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
exports.TranslationModal = TranslationModal;
|
|
71
|
+
TranslationModal.propTypes = {
|
|
72
|
+
fieldsToTranslate: _propTypes.default.array.isRequired,
|
|
73
|
+
objectToTranslate: _propTypes.default.object.isRequired,
|
|
74
|
+
onClose: _propTypes.default.func.isRequired,
|
|
75
|
+
onTranslationSaved: _propTypes.default.func.isRequired
|
|
76
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TranslationModalActions = void 0;
|
|
7
|
+
|
|
8
|
+
var _d2I18n = _interopRequireDefault(require("@dhis2/d2-i18n"));
|
|
9
|
+
|
|
10
|
+
var _ui = require("@dhis2/ui");
|
|
11
|
+
|
|
12
|
+
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
13
|
+
|
|
14
|
+
var _react = _interopRequireDefault(require("react"));
|
|
15
|
+
|
|
16
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
17
|
+
|
|
18
|
+
const TranslationModalActions = ({
|
|
19
|
+
onClose,
|
|
20
|
+
onSave,
|
|
21
|
+
saveInProgress,
|
|
22
|
+
saveButtonDisabled
|
|
23
|
+
}) => /*#__PURE__*/_react.default.createElement(_ui.ModalActions, null, /*#__PURE__*/_react.default.createElement(_ui.ButtonStrip, null, /*#__PURE__*/_react.default.createElement(_ui.Button, {
|
|
24
|
+
secondary: true,
|
|
25
|
+
onClick: onClose
|
|
26
|
+
}, _d2I18n.default.t('Cancel')), /*#__PURE__*/_react.default.createElement(_ui.Button, {
|
|
27
|
+
primary: true,
|
|
28
|
+
onClick: onSave,
|
|
29
|
+
loading: saveInProgress,
|
|
30
|
+
disabled: saveButtonDisabled
|
|
31
|
+
}, _d2I18n.default.t('Save translations'))));
|
|
32
|
+
|
|
33
|
+
exports.TranslationModalActions = TranslationModalActions;
|
|
34
|
+
TranslationModalActions.propTypes = {
|
|
35
|
+
onClose: _propTypes.default.func.isRequired,
|
|
36
|
+
saveButtonDisabled: _propTypes.default.bool,
|
|
37
|
+
saveInProgress: _propTypes.default.bool,
|
|
38
|
+
onSave: _propTypes.default.func
|
|
39
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.useTranslationsResults = void 0;
|
|
7
|
+
|
|
8
|
+
var _appRuntime = require("@dhis2/app-runtime");
|
|
9
|
+
|
|
10
|
+
var _d2I18n = _interopRequireDefault(require("@dhis2/d2-i18n"));
|
|
11
|
+
|
|
12
|
+
var _react = require("react");
|
|
13
|
+
|
|
14
|
+
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
15
|
+
|
|
16
|
+
const useTranslationsResults = ({
|
|
17
|
+
resource
|
|
18
|
+
}) => {
|
|
19
|
+
const translationsQueryRef = (0, _react.useRef)({
|
|
20
|
+
translations: {
|
|
21
|
+
resource: "".concat(resource, "/translations")
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
const {
|
|
25
|
+
data,
|
|
26
|
+
fetching,
|
|
27
|
+
refetch
|
|
28
|
+
} = (0, _appRuntime.useDataQuery)(translationsQueryRef.current, {
|
|
29
|
+
onError: error => showError(error)
|
|
30
|
+
});
|
|
31
|
+
const {
|
|
32
|
+
show: showError
|
|
33
|
+
} = (0, _appRuntime.useAlert)(error => error.message || _d2I18n.default.t('Could not load translations'), {
|
|
34
|
+
critical: true,
|
|
35
|
+
actions: [{
|
|
36
|
+
label: _d2I18n.default.t('Retry'),
|
|
37
|
+
onClick: refetch
|
|
38
|
+
}]
|
|
39
|
+
});
|
|
40
|
+
return {
|
|
41
|
+
translationsData: fetching ? undefined : data.translations.translations,
|
|
42
|
+
fetching
|
|
43
|
+
};
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
exports.useTranslationsResults = useTranslationsResults;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "TranslationDialog", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _TranslationModal.TranslationModal;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
var _TranslationModal = require("./TranslationModal/TranslationModal.js");
|
package/build/cjs/index.js
CHANGED
|
@@ -969,6 +969,12 @@ Object.defineProperty(exports, "LEGEND_DISPLAY_STYLE_TEXT", {
|
|
|
969
969
|
return _legends.LEGEND_DISPLAY_STYLE_TEXT;
|
|
970
970
|
}
|
|
971
971
|
});
|
|
972
|
+
Object.defineProperty(exports, "formatValue", {
|
|
973
|
+
enumerable: true,
|
|
974
|
+
get: function () {
|
|
975
|
+
return _renderValue.renderValue;
|
|
976
|
+
}
|
|
977
|
+
});
|
|
972
978
|
Object.defineProperty(exports, "COLOR_SET_DEFAULT", {
|
|
973
979
|
enumerable: true,
|
|
974
980
|
get: function () {
|
|
@@ -1270,6 +1276,8 @@ var _fontStyle = require("./modules/fontStyle.js");
|
|
|
1270
1276
|
|
|
1271
1277
|
var _legends = require("./modules/legends.js");
|
|
1272
1278
|
|
|
1279
|
+
var _renderValue = require("./modules/pivotTable/renderValue.js");
|
|
1280
|
+
|
|
1273
1281
|
var _colorSets = require("./visualizations/util/colors/colorSets.js");
|
|
1274
1282
|
|
|
1275
1283
|
var _index7 = require("./components/PeriodDimension/utils/index.js");
|
|
@@ -222,6 +222,14 @@
|
|
|
222
222
|
"Six-months": "Six-months",
|
|
223
223
|
"Financial Years": "Financial Years",
|
|
224
224
|
"Years": "Years",
|
|
225
|
+
"Translating to": "Translating to",
|
|
226
|
+
"Choose a locale": "Choose a locale",
|
|
227
|
+
"Base locale reference": "Base locale reference",
|
|
228
|
+
"Choose a locale to translate from the menu above": "Choose a locale to translate from the menu above",
|
|
229
|
+
"Translate: {{objectName}}": "Translate: {{objectName}}",
|
|
230
|
+
"Save translations": "Save translations",
|
|
231
|
+
"Could not load translations": "Could not load translations",
|
|
232
|
+
"Retry": "Retry",
|
|
225
233
|
"Series": "Series",
|
|
226
234
|
"Category": "Category",
|
|
227
235
|
"Filter": "Filter",
|
|
@@ -226,6 +226,7 @@ class PivotTableEngine {
|
|
|
226
226
|
return sets;
|
|
227
227
|
}, {});
|
|
228
228
|
this.rawData = data;
|
|
229
|
+
this.dimensionLookup = buildDimensionLookup(this.visualization, this.rawData.metaData, this.rawData.headers);
|
|
229
230
|
this.options = { ...defaultOptions,
|
|
230
231
|
showColumnTotals: visualization.colTotals,
|
|
231
232
|
showRowTotals: visualization.rowTotals,
|
|
@@ -235,10 +236,10 @@ class PivotTableEngine {
|
|
|
235
236
|
hideEmptyRows: visualization.hideEmptyRows,
|
|
236
237
|
title: visualization.hideTitle ? undefined : visualization.title,
|
|
237
238
|
subtitle: visualization.hideSubtitle ? undefined : visualization.subtitle,
|
|
238
|
-
|
|
239
|
-
|
|
239
|
+
// turn on fixed headers only when there are dimensions
|
|
240
|
+
fixColumnHeaders: this.dimensionLookup.columns.length ? visualization.fixColumnHeaders : false,
|
|
241
|
+
fixRowHeaders: this.dimensionLookup.rows.length ? visualization.fixRowHeaders : false
|
|
240
242
|
};
|
|
241
|
-
this.dimensionLookup = buildDimensionLookup(this.visualization, this.rawData.metaData, this.rawData.headers);
|
|
242
243
|
this.adaptiveClippingController = new _AdaptiveClippingController.AdaptiveClippingController(this);
|
|
243
244
|
const doColumnSubtotals = this.options.showColumnSubtotals && this.dimensionLookup.rows.length > 1;
|
|
244
245
|
const singularRow = this.dimensionLookup.rows.length === 1 && this.dimensionLookup.rows[0].count === 1;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import _JSXStyle from "styled-jsx/style";
|
|
2
|
-
import TranslationDialog from '@dhis2/d2-ui-translation-dialog';
|
|
3
2
|
import { IconAdd24, IconLaunch24, IconSave24, IconEdit24, IconTranslate24, IconShare24, IconLink24, IconDelete24, SharingDialog, colors, FlyoutMenu, Layer, MenuItem, MenuDivider, Popper } from '@dhis2/ui';
|
|
4
3
|
import PropTypes from 'prop-types';
|
|
5
4
|
import React, { createRef, useState } from 'react';
|
|
6
5
|
import i18n from '../../locales/index.js';
|
|
7
6
|
import { OpenFileDialog } from '../OpenFileDialog/OpenFileDialog.js';
|
|
7
|
+
import { TranslationDialog } from '../TranslationDialog/index.js';
|
|
8
8
|
import { DeleteDialog } from './DeleteDialog.js';
|
|
9
9
|
import { fileMenuStyles } from './FileMenu.styles.js';
|
|
10
10
|
import { GetLinkDialog } from './GetLinkDialog.js';
|
|
@@ -70,20 +70,10 @@ export const FileMenu = ({
|
|
|
70
70
|
|
|
71
71
|
case 'translate':
|
|
72
72
|
return /*#__PURE__*/React.createElement(TranslationDialog, {
|
|
73
|
-
|
|
74
|
-
d2: d2,
|
|
75
|
-
objectToTranslate: { ...fileObject,
|
|
76
|
-
// mock modelDefinition to avoid an error
|
|
77
|
-
// in the TranslationDialog component
|
|
78
|
-
modelDefinition: {
|
|
79
|
-
name: fileType
|
|
80
|
-
}
|
|
81
|
-
},
|
|
73
|
+
objectToTranslate: fileObject,
|
|
82
74
|
fieldsToTranslate: ['name', 'description'],
|
|
83
|
-
|
|
84
|
-
onTranslationSaved: onTranslate
|
|
85
|
-
onTranslationError: onError,
|
|
86
|
-
insertTheme: true
|
|
75
|
+
onClose: onDialogClose,
|
|
76
|
+
onTranslationSaved: onTranslate
|
|
87
77
|
});
|
|
88
78
|
|
|
89
79
|
case 'sharing':
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import TranslationDialog from '@dhis2/d2-ui-translation-dialog';
|
|
2
1
|
import { SharingDialog } from '@dhis2/ui';
|
|
3
2
|
import { shallow } from 'enzyme';
|
|
4
3
|
import React from 'react';
|
|
5
4
|
import { OpenFileDialog } from '../../OpenFileDialog/OpenFileDialog.js';
|
|
5
|
+
import { TranslationDialog } from '../../TranslationDialog/index.js';
|
|
6
6
|
import { DeleteDialog } from '../DeleteDialog.js';
|
|
7
7
|
import { FileMenu } from '../FileMenu.js';
|
|
8
8
|
import { GetLinkDialog } from '../GetLinkDialog.js';
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { useDataQuery } from '@dhis2/app-runtime';
|
|
2
|
+
import i18n from '@dhis2/d2-i18n';
|
|
3
|
+
import { SingleSelect, SingleSelectOption } from '@dhis2/ui';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import React from 'react';
|
|
6
|
+
const query = {
|
|
7
|
+
locales: {
|
|
8
|
+
resource: 'locales/db'
|
|
9
|
+
}
|
|
10
|
+
};
|
|
11
|
+
export const LocalesSelect = ({
|
|
12
|
+
onChange,
|
|
13
|
+
selected
|
|
14
|
+
}) => {
|
|
15
|
+
const {
|
|
16
|
+
data,
|
|
17
|
+
fetching
|
|
18
|
+
} = useDataQuery(query);
|
|
19
|
+
return /*#__PURE__*/React.createElement(SingleSelect, {
|
|
20
|
+
prefix: selected ? i18n.t('Translating to') : i18n.t('Choose a locale'),
|
|
21
|
+
onChange: ({
|
|
22
|
+
selected
|
|
23
|
+
}) => onChange(selected),
|
|
24
|
+
loading: fetching,
|
|
25
|
+
selected: data ? selected : undefined,
|
|
26
|
+
dense: true
|
|
27
|
+
}, data && data.locales // XXX remove duplicates ?! fr_SN - French (Senegal)
|
|
28
|
+
.reduce((locales, {
|
|
29
|
+
locale,
|
|
30
|
+
name
|
|
31
|
+
}) => {
|
|
32
|
+
if (!locales.find(entry => entry.locale === locale)) {
|
|
33
|
+
locales.push({
|
|
34
|
+
locale,
|
|
35
|
+
name
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return locales;
|
|
40
|
+
}, []).map(({
|
|
41
|
+
locale,
|
|
42
|
+
name
|
|
43
|
+
}) => /*#__PURE__*/React.createElement(SingleSelectOption, {
|
|
44
|
+
key: locale,
|
|
45
|
+
value: locale,
|
|
46
|
+
label: name
|
|
47
|
+
})));
|
|
48
|
+
};
|
|
49
|
+
LocalesSelect.propTypes = {
|
|
50
|
+
onChange: PropTypes.func.isRequired,
|
|
51
|
+
selected: PropTypes.string
|
|
52
|
+
};
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { useAlert, useDataMutation } from '@dhis2/app-runtime';
|
|
2
|
+
import i18n from '@dhis2/d2-i18n';
|
|
3
|
+
import { CenteredContent, DataTable, DataTableBody, DataTableCell, DataTableColumnHeader, DataTableHead, DataTableRow, InputField, ModalContent } from '@dhis2/ui';
|
|
4
|
+
import PropTypes from 'prop-types';
|
|
5
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
6
|
+
import { LocalesSelect } from './LocalesSelect.js';
|
|
7
|
+
import { TranslationModalActions } from './TranslationModalActions.js';
|
|
8
|
+
const SESSION_STORAGE_TRANSLATION_LOCALE_KEY = 'translation-dialog-selected-locale';
|
|
9
|
+
export const TranslationForm = ({
|
|
10
|
+
fieldsToTranslate,
|
|
11
|
+
objectToTranslate,
|
|
12
|
+
translations,
|
|
13
|
+
resource,
|
|
14
|
+
onTranslationSaved,
|
|
15
|
+
onClose
|
|
16
|
+
}) => {
|
|
17
|
+
const [newTranslations, setNewTranslations] = useState();
|
|
18
|
+
const [translationLocale, setTranslationLocale] = useState();
|
|
19
|
+
const {
|
|
20
|
+
show: showError
|
|
21
|
+
} = useAlert(error => error, {
|
|
22
|
+
critical: true
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
const formatFieldLabel = field => {
|
|
26
|
+
field.replace(/[a-z][A-Z]/g, match => [match.charAt(0), match.charAt(1)].join(' ')).toLowerCase();
|
|
27
|
+
return field.charAt(0).toUpperCase() + field.slice(1);
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const camelCaseToUnderscores = field => field.replace(/[a-z][A-Z]/g, match => [match.charAt(0), match.charAt(1)].join('_')).toLowerCase();
|
|
31
|
+
|
|
32
|
+
const getTranslationIndexForField = field => newTranslations.findIndex(element => element.locale === translationLocale && element.property.toLowerCase() === camelCaseToUnderscores(field));
|
|
33
|
+
|
|
34
|
+
const getTranslationForField = field => {
|
|
35
|
+
var _newTranslations$tran;
|
|
36
|
+
|
|
37
|
+
const translationIndex = getTranslationIndexForField(field);
|
|
38
|
+
return translationIndex !== -1 ? ((_newTranslations$tran = newTranslations[translationIndex]) === null || _newTranslations$tran === void 0 ? void 0 : _newTranslations$tran.value) || '' : '';
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
const setTranslationForField = (field, translation) => {
|
|
42
|
+
const newTranslation = {
|
|
43
|
+
locale: translationLocale,
|
|
44
|
+
property: camelCaseToUnderscores(field).toUpperCase(),
|
|
45
|
+
value: translation
|
|
46
|
+
};
|
|
47
|
+
const translationIndex = getTranslationIndexForField(field);
|
|
48
|
+
setNewTranslations(translationIndex === -1 ? [...newTranslations, newTranslation] : newTranslations.map((translation, index) => index === translationIndex ? newTranslation : translation));
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const translationsMutationRef = useRef({
|
|
52
|
+
resource: "".concat(resource, "/translations"),
|
|
53
|
+
type: 'update',
|
|
54
|
+
data: ({
|
|
55
|
+
translations
|
|
56
|
+
}) => ({
|
|
57
|
+
translations
|
|
58
|
+
})
|
|
59
|
+
});
|
|
60
|
+
const [saveTranslations, {
|
|
61
|
+
loading: saveInProgress
|
|
62
|
+
}] = useDataMutation(translationsMutationRef.current, {
|
|
63
|
+
onComplete: () => {
|
|
64
|
+
onTranslationSaved();
|
|
65
|
+
onClose();
|
|
66
|
+
},
|
|
67
|
+
onError: error => {
|
|
68
|
+
showError(error);
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
const onLocaleChange = locale => {
|
|
73
|
+
setTranslationLocale(locale);
|
|
74
|
+
window.sessionStorage.setItem(SESSION_STORAGE_TRANSLATION_LOCALE_KEY, locale);
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
const save = () => saveTranslations({
|
|
78
|
+
translations: newTranslations
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
useEffect(() => setTranslationLocale(window.sessionStorage.getItem(SESSION_STORAGE_TRANSLATION_LOCALE_KEY)), []);
|
|
82
|
+
useEffect(() => setNewTranslations(translations), [translations]);
|
|
83
|
+
return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ModalContent, null, /*#__PURE__*/React.createElement(DataTable, {
|
|
84
|
+
layout: "fixed"
|
|
85
|
+
}, /*#__PURE__*/React.createElement(DataTableHead, null, /*#__PURE__*/React.createElement(DataTableRow, null, /*#__PURE__*/React.createElement(DataTableColumnHeader, {
|
|
86
|
+
fixed: true,
|
|
87
|
+
top: "0"
|
|
88
|
+
}, i18n.t('Base locale reference')), /*#__PURE__*/React.createElement(DataTableColumnHeader, {
|
|
89
|
+
fixed: true,
|
|
90
|
+
top: "0"
|
|
91
|
+
}, /*#__PURE__*/React.createElement(LocalesSelect, {
|
|
92
|
+
selected: translationLocale,
|
|
93
|
+
onChange: onLocaleChange
|
|
94
|
+
})))), /*#__PURE__*/React.createElement(DataTableBody, null, fieldsToTranslate.map((field, index) => /*#__PURE__*/React.createElement(DataTableRow, {
|
|
95
|
+
key: field
|
|
96
|
+
}, /*#__PURE__*/React.createElement(DataTableCell, null, /*#__PURE__*/React.createElement("div", {
|
|
97
|
+
className: ""
|
|
98
|
+
}, /*#__PURE__*/React.createElement(InputField, {
|
|
99
|
+
label: formatFieldLabel(field),
|
|
100
|
+
value: objectToTranslate[field],
|
|
101
|
+
readOnly: true
|
|
102
|
+
}))), translationLocale && /*#__PURE__*/React.createElement(DataTableCell, null, /*#__PURE__*/React.createElement("div", {
|
|
103
|
+
className: ""
|
|
104
|
+
}, /*#__PURE__*/React.createElement(InputField, {
|
|
105
|
+
label: formatFieldLabel(field),
|
|
106
|
+
value: getTranslationForField(field),
|
|
107
|
+
onChange: ({
|
|
108
|
+
value
|
|
109
|
+
}) => setTranslationForField(field, value)
|
|
110
|
+
}))), !translationLocale && index === 0 && /*#__PURE__*/React.createElement(DataTableCell, {
|
|
111
|
+
rowSpan: String(fieldsToTranslate.length)
|
|
112
|
+
}, /*#__PURE__*/React.createElement(CenteredContent, null, i18n.t('Choose a locale to translate from the menu above')))))))), /*#__PURE__*/React.createElement(TranslationModalActions, {
|
|
113
|
+
onClose: onClose,
|
|
114
|
+
onSave: save,
|
|
115
|
+
saveInProgress: saveInProgress,
|
|
116
|
+
saveButtonDisabled: !translationLocale
|
|
117
|
+
}));
|
|
118
|
+
};
|
|
119
|
+
TranslationForm.propTypes = {
|
|
120
|
+
fieldsToTranslate: PropTypes.array.isRequired,
|
|
121
|
+
objectToTranslate: PropTypes.object.isRequired,
|
|
122
|
+
resource: PropTypes.string.isRequired,
|
|
123
|
+
translations: PropTypes.array.isRequired,
|
|
124
|
+
onClose: PropTypes.func.isRequired,
|
|
125
|
+
onTranslationSaved: PropTypes.func.isRequired
|
|
126
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import i18n from '@dhis2/d2-i18n';
|
|
2
|
+
import { CenteredContent, CircularLoader, Modal, ModalContent, ModalTitle } from '@dhis2/ui';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import React, { useEffect, useState } from 'react';
|
|
5
|
+
import { TranslationForm } from './TranslationForm.js';
|
|
6
|
+
import { TranslationModalActions } from './TranslationModalActions.js';
|
|
7
|
+
import { useTranslationsResults } from './useTranslationsResults.js';
|
|
8
|
+
export const TranslationModal = ({
|
|
9
|
+
objectToTranslate,
|
|
10
|
+
fieldsToTranslate,
|
|
11
|
+
onClose,
|
|
12
|
+
onTranslationSaved
|
|
13
|
+
}) => {
|
|
14
|
+
const [translations, setTranslations] = useState([]);
|
|
15
|
+
const endpointPath = new URL(objectToTranslate.href).pathname;
|
|
16
|
+
const endpointPathMatch = endpointPath.match(/api\/\d+\/(?<resource>.+)/);
|
|
17
|
+
const resource = endpointPathMatch !== null && endpointPathMatch !== void 0 && endpointPathMatch.groups ? endpointPathMatch.groups.resource : null;
|
|
18
|
+
const {
|
|
19
|
+
translationsData,
|
|
20
|
+
fetching
|
|
21
|
+
} = useTranslationsResults({
|
|
22
|
+
resource
|
|
23
|
+
});
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (translationsData) {
|
|
26
|
+
setTranslations(translationsData);
|
|
27
|
+
}
|
|
28
|
+
}, [translationsData]);
|
|
29
|
+
return /*#__PURE__*/React.createElement(Modal, {
|
|
30
|
+
large: true,
|
|
31
|
+
position: "middle",
|
|
32
|
+
onClose: onClose
|
|
33
|
+
}, /*#__PURE__*/React.createElement(ModalTitle, null, i18n.t('Translate: {{objectName}}', {
|
|
34
|
+
objectName: objectToTranslate.name || 'TEXT',
|
|
35
|
+
// XXX
|
|
36
|
+
nsSeparator: '^^'
|
|
37
|
+
})), fetching ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ModalContent, null, /*#__PURE__*/React.createElement(CenteredContent, null, /*#__PURE__*/React.createElement(CircularLoader, null))), /*#__PURE__*/React.createElement(TranslationModalActions, {
|
|
38
|
+
onClose: onClose,
|
|
39
|
+
saveButtonDisabled: true
|
|
40
|
+
})) : /*#__PURE__*/React.createElement(TranslationForm, {
|
|
41
|
+
fieldsToTranslate: fieldsToTranslate,
|
|
42
|
+
objectToTranslate: objectToTranslate,
|
|
43
|
+
translations: translations,
|
|
44
|
+
onTranslationSaved: onTranslationSaved,
|
|
45
|
+
resource: resource,
|
|
46
|
+
onClose: onClose
|
|
47
|
+
}));
|
|
48
|
+
};
|
|
49
|
+
TranslationModal.propTypes = {
|
|
50
|
+
fieldsToTranslate: PropTypes.array.isRequired,
|
|
51
|
+
objectToTranslate: PropTypes.object.isRequired,
|
|
52
|
+
onClose: PropTypes.func.isRequired,
|
|
53
|
+
onTranslationSaved: PropTypes.func.isRequired
|
|
54
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import i18n from '@dhis2/d2-i18n';
|
|
2
|
+
import { Button, ButtonStrip, ModalActions } from '@dhis2/ui';
|
|
3
|
+
import PropTypes from 'prop-types';
|
|
4
|
+
import React from 'react';
|
|
5
|
+
export const TranslationModalActions = ({
|
|
6
|
+
onClose,
|
|
7
|
+
onSave,
|
|
8
|
+
saveInProgress,
|
|
9
|
+
saveButtonDisabled
|
|
10
|
+
}) => /*#__PURE__*/React.createElement(ModalActions, null, /*#__PURE__*/React.createElement(ButtonStrip, null, /*#__PURE__*/React.createElement(Button, {
|
|
11
|
+
secondary: true,
|
|
12
|
+
onClick: onClose
|
|
13
|
+
}, i18n.t('Cancel')), /*#__PURE__*/React.createElement(Button, {
|
|
14
|
+
primary: true,
|
|
15
|
+
onClick: onSave,
|
|
16
|
+
loading: saveInProgress,
|
|
17
|
+
disabled: saveButtonDisabled
|
|
18
|
+
}, i18n.t('Save translations'))));
|
|
19
|
+
TranslationModalActions.propTypes = {
|
|
20
|
+
onClose: PropTypes.func.isRequired,
|
|
21
|
+
saveButtonDisabled: PropTypes.bool,
|
|
22
|
+
saveInProgress: PropTypes.bool,
|
|
23
|
+
onSave: PropTypes.func
|
|
24
|
+
};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useAlert, useDataQuery } from '@dhis2/app-runtime';
|
|
2
|
+
import i18n from '@dhis2/d2-i18n';
|
|
3
|
+
import { useRef } from 'react';
|
|
4
|
+
export const useTranslationsResults = ({
|
|
5
|
+
resource
|
|
6
|
+
}) => {
|
|
7
|
+
const translationsQueryRef = useRef({
|
|
8
|
+
translations: {
|
|
9
|
+
resource: "".concat(resource, "/translations")
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
const {
|
|
13
|
+
data,
|
|
14
|
+
fetching,
|
|
15
|
+
refetch
|
|
16
|
+
} = useDataQuery(translationsQueryRef.current, {
|
|
17
|
+
onError: error => showError(error)
|
|
18
|
+
});
|
|
19
|
+
const {
|
|
20
|
+
show: showError
|
|
21
|
+
} = useAlert(error => error.message || i18n.t('Could not load translations'), {
|
|
22
|
+
critical: true,
|
|
23
|
+
actions: [{
|
|
24
|
+
label: i18n.t('Retry'),
|
|
25
|
+
onClick: refetch
|
|
26
|
+
}]
|
|
27
|
+
});
|
|
28
|
+
return {
|
|
29
|
+
translationsData: fetching ? undefined : data.translations.translations,
|
|
30
|
+
fetching
|
|
31
|
+
};
|
|
32
|
+
};
|
package/build/es/index.js
CHANGED
|
@@ -78,7 +78,9 @@ export { createVisualization } from './visualizations/index.js'; // Modules: fon
|
|
|
78
78
|
|
|
79
79
|
export { FONT_STYLE_VISUALIZATION_TITLE, FONT_STYLE_VISUALIZATION_SUBTITLE, FONT_STYLE_HORIZONTAL_AXIS_TITLE, FONT_STYLE_VERTICAL_AXIS_TITLE, FONT_STYLE_LEGEND, FONT_STYLE_AXIS_LABELS, FONT_STYLE_REGRESSION_LINE_LABEL, FONT_STYLE_OPTION_FONT, FONT_STYLE_OPTION_FONT_SIZE, FONT_STYLE_OPTION_BOLD, FONT_STYLE_OPTION_ITALIC, FONT_STYLE_OPTION_UNDERLINE, FONT_STYLE_OPTION_TEXT_COLOR, FONT_STYLE_OPTION_TEXT_ALIGN, TEXT_ALIGN_LEFT, TEXT_ALIGN_CENTER, TEXT_ALIGN_RIGHT, defaultFontStyle, getFontSizeOptions, getTextAlignOptions, deleteFontStyleOption } from './modules/fontStyle.js'; // Modules: legend
|
|
80
80
|
|
|
81
|
-
export { LEGEND_DISPLAY_STRATEGY_BY_DATA_ITEM, LEGEND_DISPLAY_STRATEGY_FIXED, LEGEND_DISPLAY_STYLE_FILL, LEGEND_DISPLAY_STYLE_TEXT } from './modules/legends.js'; //
|
|
81
|
+
export { LEGEND_DISPLAY_STRATEGY_BY_DATA_ITEM, LEGEND_DISPLAY_STRATEGY_FIXED, LEGEND_DISPLAY_STYLE_FILL, LEGEND_DISPLAY_STYLE_TEXT } from './modules/legends.js'; // Modules: pivotTable
|
|
82
|
+
|
|
83
|
+
export { renderValue as formatValue } from './modules/pivotTable/renderValue.js'; // Utils: colorSets
|
|
82
84
|
|
|
83
85
|
export { COLOR_SET_DEFAULT, COLOR_SET_BRIGHT, COLOR_SET_DARK, COLOR_SET_GRAY, COLOR_SET_COLOR_BLIND, COLOR_SET_PATTERNS, colorSets } from './visualizations/util/colors/colorSets.js'; // Utils: periods
|
|
84
86
|
|
|
@@ -222,6 +222,14 @@
|
|
|
222
222
|
"Six-months": "Six-months",
|
|
223
223
|
"Financial Years": "Financial Years",
|
|
224
224
|
"Years": "Years",
|
|
225
|
+
"Translating to": "Translating to",
|
|
226
|
+
"Choose a locale": "Choose a locale",
|
|
227
|
+
"Base locale reference": "Base locale reference",
|
|
228
|
+
"Choose a locale to translate from the menu above": "Choose a locale to translate from the menu above",
|
|
229
|
+
"Translate: {{objectName}}": "Translate: {{objectName}}",
|
|
230
|
+
"Save translations": "Save translations",
|
|
231
|
+
"Could not load translations": "Could not load translations",
|
|
232
|
+
"Retry": "Retry",
|
|
225
233
|
"Series": "Series",
|
|
226
234
|
"Category": "Category",
|
|
227
235
|
"Filter": "Filter",
|
|
@@ -211,6 +211,7 @@ export class PivotTableEngine {
|
|
|
211
211
|
return sets;
|
|
212
212
|
}, {});
|
|
213
213
|
this.rawData = data;
|
|
214
|
+
this.dimensionLookup = buildDimensionLookup(this.visualization, this.rawData.metaData, this.rawData.headers);
|
|
214
215
|
this.options = { ...defaultOptions,
|
|
215
216
|
showColumnTotals: visualization.colTotals,
|
|
216
217
|
showRowTotals: visualization.rowTotals,
|
|
@@ -220,10 +221,10 @@ export class PivotTableEngine {
|
|
|
220
221
|
hideEmptyRows: visualization.hideEmptyRows,
|
|
221
222
|
title: visualization.hideTitle ? undefined : visualization.title,
|
|
222
223
|
subtitle: visualization.hideSubtitle ? undefined : visualization.subtitle,
|
|
223
|
-
|
|
224
|
-
|
|
224
|
+
// turn on fixed headers only when there are dimensions
|
|
225
|
+
fixColumnHeaders: this.dimensionLookup.columns.length ? visualization.fixColumnHeaders : false,
|
|
226
|
+
fixRowHeaders: this.dimensionLookup.rows.length ? visualization.fixRowHeaders : false
|
|
225
227
|
};
|
|
226
|
-
this.dimensionLookup = buildDimensionLookup(this.visualization, this.rawData.metaData, this.rawData.headers);
|
|
227
228
|
this.adaptiveClippingController = new AdaptiveClippingController(this);
|
|
228
229
|
const doColumnSubtotals = this.options.showColumnSubtotals && this.dimensionLookup.rows.length > 1;
|
|
229
230
|
const singularRow = this.dimensionLookup.rows.length === 1 && this.dimensionLookup.rows[0].count === 1;
|