@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.
Files changed (26) hide show
  1. package/CHANGELOG.md +28 -0
  2. package/build/cjs/components/FileMenu/FileMenu.js +6 -16
  3. package/build/cjs/components/FileMenu/__tests__/FileMenu.spec.js +3 -3
  4. package/build/cjs/components/TranslationDialog/TranslationModal/LocalesSelect.js +69 -0
  5. package/build/cjs/components/TranslationDialog/TranslationModal/TranslationForm.js +149 -0
  6. package/build/cjs/components/TranslationDialog/TranslationModal/TranslationModal.js +76 -0
  7. package/build/cjs/components/TranslationDialog/TranslationModal/TranslationModalActions.js +39 -0
  8. package/build/cjs/components/TranslationDialog/TranslationModal/useTranslationsResults.js +46 -0
  9. package/build/cjs/components/TranslationDialog/index.js +13 -0
  10. package/build/cjs/index.js +8 -0
  11. package/build/cjs/locales/ar/translations.json +1 -1
  12. package/build/cjs/locales/en/translations.json +8 -0
  13. package/build/cjs/modules/pivotTable/PivotTableEngine.js +4 -3
  14. package/build/es/components/FileMenu/FileMenu.js +4 -14
  15. package/build/es/components/FileMenu/__tests__/FileMenu.spec.js +1 -1
  16. package/build/es/components/TranslationDialog/TranslationModal/LocalesSelect.js +52 -0
  17. package/build/es/components/TranslationDialog/TranslationModal/TranslationForm.js +126 -0
  18. package/build/es/components/TranslationDialog/TranslationModal/TranslationModal.js +54 -0
  19. package/build/es/components/TranslationDialog/TranslationModal/TranslationModalActions.js +24 -0
  20. package/build/es/components/TranslationDialog/TranslationModal/useTranslationsResults.js +32 -0
  21. package/build/es/components/TranslationDialog/index.js +2 -0
  22. package/build/es/index.js +3 -1
  23. package/build/es/locales/ar/translations.json +1 -1
  24. package/build/es/locales/en/translations.json +8 -0
  25. package/build/es/modules/pivotTable/PivotTableEngine.js +4 -3
  26. 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(_d2UiTranslationDialog.default, {
99
- open: true,
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
- onRequestClose: onDialogClose,
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(_d2UiTranslationDialog.default)).toHaveLength(1);
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");
@@ -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");
@@ -281,7 +281,7 @@
281
281
  "Left": "الأيسر",
282
282
  "Center": "المركز",
283
283
  "Right": "الأيمن",
284
- "Start": "بدء",
284
+ "Start": "البدء",
285
285
  "Middle": "الوسط",
286
286
  "End": "النهاية",
287
287
  "Top": "القمة",
@@ -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
- fixColumnHeaders: visualization.fixColumnHeaders,
239
- fixRowHeaders: visualization.fixRowHeaders
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
- open: true,
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
- onRequestClose: onDialogClose,
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
+ };
@@ -0,0 +1,2 @@
1
+ import { TranslationModal as TranslationDialog } from './TranslationModal/TranslationModal.js';
2
+ export { TranslationDialog };
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'; // Utils: colorSets
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
 
@@ -281,7 +281,7 @@
281
281
  "Left": "الأيسر",
282
282
  "Center": "المركز",
283
283
  "Right": "الأيمن",
284
- "Start": "بدء",
284
+ "Start": "البدء",
285
285
  "Middle": "الوسط",
286
286
  "End": "النهاية",
287
287
  "Top": "القمة",
@@ -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
- fixColumnHeaders: visualization.fixColumnHeaders,
224
- fixRowHeaders: visualization.fixRowHeaders
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;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dhis2/analytics",
3
- "version": "21.0.11",
3
+ "version": "21.2.0",
4
4
  "main": "./build/cjs/index.js",
5
5
  "module": "./build/es/index.js",
6
6
  "exports": {