@devgateway/dvz-wp-commons 1.0.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 (50) hide show
  1. package/LICENSE +7 -0
  2. package/README.md +0 -0
  3. package/build/APIConfig.d.ts +49 -0
  4. package/build/APIConfig.js +302 -0
  5. package/build/APIutils.d.ts +4 -0
  6. package/build/APIutils.js +30 -0
  7. package/build/Blocks.d.ts +90 -0
  8. package/build/Blocks.js +374 -0
  9. package/build/CSVSourceConfig.d.ts +11 -0
  10. package/build/CSVSourceConfig.js +48 -0
  11. package/build/ChartColors.d.ts +55 -0
  12. package/build/ChartColors.js +401 -0
  13. package/build/ChartLegends.d.ts +33 -0
  14. package/build/ChartLegends.js +71 -0
  15. package/build/ChartMeasures.d.ts +23 -0
  16. package/build/ChartMeasures.js +117 -0
  17. package/build/Constants.d.ts +15 -0
  18. package/build/Constants.js +15 -0
  19. package/build/DataFilters.d.ts +13 -0
  20. package/build/DataFilters.js +98 -0
  21. package/build/Format.d.ts +12 -0
  22. package/build/Format.js +385 -0
  23. package/build/MapCSVSourceConfig.d.ts +12 -0
  24. package/build/MapCSVSourceConfig.js +12 -0
  25. package/build/Measures.d.ts +25 -0
  26. package/build/Measures.js +126 -0
  27. package/build/MobileConfigUtils.d.ts +6 -0
  28. package/build/MobileConfigUtils.js +88 -0
  29. package/build/Tooltip.d.ts +3 -0
  30. package/build/Tooltip.js +53 -0
  31. package/build/Util.d.ts +7 -0
  32. package/build/Util.js +11 -0
  33. package/build/hooks/index.d.ts +0 -0
  34. package/build/hooks/index.js +3 -0
  35. package/build/hooks/useSetting.d.ts +2 -0
  36. package/build/hooks/useSetting.js +11 -0
  37. package/build/icons/Chart.d.ts +3 -0
  38. package/build/icons/Chart.js +14 -0
  39. package/build/icons/Generic.d.ts +3 -0
  40. package/build/icons/Generic.js +5 -0
  41. package/build/icons/index.d.ts +2 -0
  42. package/build/icons/index.js +2 -0
  43. package/build/index.d.ts +18 -0
  44. package/build/index.js +19 -0
  45. package/build/post-type.d.ts +193 -0
  46. package/build/post-type.js +12 -0
  47. package/build/tsconfig.tsbuildinfo +1 -0
  48. package/build/types.d.ts +349 -0
  49. package/build/types.js +33 -0
  50. package/package.json +74 -0
@@ -0,0 +1,374 @@
1
+ import React from 'react';
2
+ import { __ } from '@wordpress/i18n';
3
+ import { CheckboxControl, PanelBody, PanelRow, SelectControl, TextControl } from '@wordpress/components';
4
+ import { Component } from '@wordpress/element';
5
+ import apiFetch from '@wordpress/api-fetch';
6
+ import { togglePanel } from './Util';
7
+ import { getTranslatedOptions, isSupersetAPI } from './APIutils';
8
+ import { subscribe, select } from '@wordpress/data';
9
+ export const SizeConfig = ({ height, setAttributes, panelStatus, initialOpen = false }) => {
10
+ return (React.createElement(PanelBody, { initialOpen: panelStatus ? panelStatus["SIZE"] : initialOpen, onToggle: () => togglePanel("SIZE", panelStatus, setAttributes), title: __("Size") },
11
+ React.createElement(PanelRow, null,
12
+ React.createElement(TextControl, { size: 10, label: "Height", value: height, onChange: (height) => setAttributes({ height: height ? parseInt(height) : 0 }) }))));
13
+ };
14
+ export class ComponentWithSettings extends Component {
15
+ iframe;
16
+ unsubscribe;
17
+ constructor(props) {
18
+ super(props);
19
+ this.state = {
20
+ react_ui_url: '',
21
+ react_api_url: null,
22
+ apache_superset_url: null,
23
+ site_language: '',
24
+ current_language: '',
25
+ };
26
+ window.addEventListener("message", (event) => {
27
+ if (event.data.type === 'componentReady' && event.data.value === true) {
28
+ if (this.iframe.current) {
29
+ console.log("-----------Sending message -----------");
30
+ this.iframe.current.contentWindow?.postMessage(({ messageType: 'component-attributes', ...this.props.attributes }), "*");
31
+ }
32
+ }
33
+ }, false);
34
+ this.iframe = React.createRef();
35
+ this.unsubscribe = subscribe(() => {
36
+ const newPreviewMode = select("core/editor").getDeviceType();
37
+ if (newPreviewMode !== this.state.previewMode) {
38
+ this.setState({ previewMode: newPreviewMode });
39
+ }
40
+ });
41
+ }
42
+ componentDidUpdate(prevProps, prevState, snapshot) {
43
+ if (this.iframe.current?.contentWindow) {
44
+ this.iframe.current.contentWindow.postMessage(({ messageType: 'component-attributes', ...this.props.attributes }), "*");
45
+ }
46
+ }
47
+ componentDidMount() {
48
+ apiFetch({ path: '/dg/v1/settings' }).then((data) => {
49
+ this.setState({
50
+ react_ui_url: data["react_ui_url"] + '/' + window._page_locale,
51
+ react_api_url: data["react_api_url"],
52
+ apache_superset_url: data["apache_superset_url"],
53
+ site_language: data["site_language"],
54
+ current_language: new URLSearchParams(document.location.search).get("edit_lang") || ''
55
+ });
56
+ });
57
+ }
58
+ componentWillUnmount() {
59
+ if (this.unsubscribe) {
60
+ this.unsubscribe();
61
+ }
62
+ }
63
+ }
64
+ export class BlockEditWithFilters extends ComponentWithSettings {
65
+ constructor(props) {
66
+ super(props);
67
+ this.state = {
68
+ react_ui_url: '',
69
+ react_api_url: null,
70
+ apache_superset_url: null,
71
+ site_language: '',
72
+ current_language: '',
73
+ taxonomyValues: [],
74
+ types: null,
75
+ taxonomies: null,
76
+ loading: true
77
+ };
78
+ this.onTypeChanged = this.onTypeChanged.bind(this);
79
+ this.onTaxonomyChanged = this.onTaxonomyChanged.bind(this);
80
+ this.getTaxonomyValues = this.getTaxonomyValues.bind(this);
81
+ this.onCategoryChanged = this.onCategoryChanged.bind(this);
82
+ }
83
+ componentDidUpdate(prevProps, prevState, snapshot) {
84
+ const { attributes: { type, taxonomy }, } = this.props;
85
+ super.componentDidUpdate(prevProps, prevState, snapshot);
86
+ if (prevProps.attributes) {
87
+ if (type != prevProps.attributes.type) {
88
+ }
89
+ if (taxonomy != prevProps.attributes.taxonomy) {
90
+ this.getTaxonomyValues();
91
+ }
92
+ }
93
+ }
94
+ componentDidMount() {
95
+ super.componentDidMount();
96
+ this.getTypes();
97
+ this.getTaxonomies();
98
+ const { attributes: { taxonomy }, } = this.props;
99
+ if (taxonomy != 'none') {
100
+ this.getTaxonomyValues();
101
+ }
102
+ }
103
+ onTypeChanged(value) {
104
+ const { setAttributes } = this.props;
105
+ setAttributes({ categories: [] });
106
+ setAttributes({ taxonomy: 'none' });
107
+ setAttributes({ type: value });
108
+ }
109
+ onTaxonomyChanged(value) {
110
+ const { setAttributes } = this.props;
111
+ setAttributes({ categories: [] });
112
+ setAttributes({ taxonomy: value });
113
+ }
114
+ onCategoryChanged(checked, value) {
115
+ const { setAttributes, attributes: { categories } } = this.props;
116
+ if (!checked) {
117
+ setAttributes({ categories: categories.filter(i => i != value) });
118
+ }
119
+ else {
120
+ let newCate = [...categories];
121
+ newCate.push(value);
122
+ setAttributes({ categories: newCate });
123
+ }
124
+ }
125
+ getTaxonomyValues() {
126
+ const { attributes: { taxonomy }, } = this.props;
127
+ apiFetch({
128
+ path: '/wp/v2/taxonomies/' + taxonomy + '?per_page=100',
129
+ }).then(data => {
130
+ this.setState({ taxonomyValues: data });
131
+ });
132
+ }
133
+ getTaxonomies() {
134
+ apiFetch({
135
+ path: '/wp/v2/taxonomies?per_page=100',
136
+ }).then(data => {
137
+ this.setState({
138
+ taxonomies: data,
139
+ });
140
+ });
141
+ }
142
+ getTypes() {
143
+ apiFetch({
144
+ path: '/wp/v2/types?per_page=100',
145
+ }).then(data => {
146
+ this.setState({
147
+ types: data, loading: false
148
+ });
149
+ });
150
+ }
151
+ typeOptions() {
152
+ const { types } = this.state;
153
+ const typeOptions = types ? Object.keys(types)
154
+ .filter(k => ['page', 'attachment', 'wp_block']
155
+ .indexOf(k) == -1).map(k => ({
156
+ slug: types[k].slug, label: types[k].name, value: types[k].rest_base
157
+ })) : [];
158
+ return typeOptions;
159
+ }
160
+ taxonomyOptions() {
161
+ const { attributes: { type, }, } = this.props;
162
+ const { types, taxonomies } = this.state;
163
+ let slug;
164
+ if (types) {
165
+ slug = this.typeOptions().filter(t => t.value == type)[0].slug;
166
+ const taxonomyOptions = types && taxonomies ? Object.keys(taxonomies)
167
+ .filter(i => taxonomies[i].types.indexOf(slug) > -1).map(k => ({
168
+ label: types[slug].name + ' -> ' + taxonomies[k].name, value: taxonomies[k].rest_base
169
+ })) : [];
170
+ return [{ label: 'None', value: 'none' }, ...taxonomyOptions];
171
+ }
172
+ else {
173
+ return [];
174
+ }
175
+ }
176
+ categoriesOptions() {
177
+ const { taxonomyValues } = this.state;
178
+ const taxonomyValuesOptions = taxonomyValues && taxonomyValues.map(t => ({ label: t.name, value: t.id }));
179
+ return taxonomyValuesOptions || [];
180
+ }
181
+ renderFilters() {
182
+ const { attributes: { type, taxonomy, categories, } } = this.props;
183
+ return (React.createElement(PanelBody, { title: __("Filter") },
184
+ React.createElement(PanelRow, null,
185
+ React.createElement(SelectControl, { label: __("Post Type"), options: this.typeOptions(), value: type, onChange: this.onTypeChanged })),
186
+ React.createElement(PanelRow, null,
187
+ React.createElement(SelectControl, { label: __("Use a taxonomy filter "), options: this.taxonomyOptions(), value: taxonomy, onChange: this.onTaxonomyChanged })),
188
+ (taxonomy != 'none' && this.categoriesOptions().length > 0) && this.categoriesOptions().map(o => {
189
+ return React.createElement(PanelRow, null,
190
+ React.createElement(CheckboxControl, { label: o.label, onChange: (checked) => this.onCategoryChanged(checked, o.value), checked: categories.indexOf(o.value) > -1 }));
191
+ })));
192
+ }
193
+ }
194
+ export class BlockEditWithAPIMetadata extends ComponentWithSettings {
195
+ constructor(props) {
196
+ super(props);
197
+ }
198
+ componentDidMount() {
199
+ apiFetch({
200
+ path: '/dg/v1/settings'
201
+ }).then((settingsData) => {
202
+ fetch(`/api/registry/eureka/apps`, {
203
+ headers: {
204
+ 'Accept': 'application/json',
205
+ },
206
+ })
207
+ .then((response) => response.json())
208
+ .then(data => {
209
+ const apps = data.applications ? [...data.applications.application
210
+ .filter(a => a.instance[0].metadata.type === 'data')
211
+ .map(a => ({
212
+ label: a.name, value: a.instance[0].vipAddress, settings: a.instance[0]
213
+ })), {
214
+ label: 'CSV', value: 'csv'
215
+ }] : [{
216
+ label: 'CSV', value: 'csv'
217
+ }];
218
+ this.setState({
219
+ react_ui_url: settingsData["react_ui_url"] + '/' + window._page_locale,
220
+ react_api_url: settingsData["react_api_url"],
221
+ apache_superset_url: settingsData["apache_superset_url"],
222
+ site_language: settingsData["site_language"],
223
+ current_language: new URLSearchParams(document.location.search).get("edit_lang") || "",
224
+ apps
225
+ }, () => {
226
+ const { app, dvzProxyDatasetId } = this.props.attributes;
227
+ if (isSupersetAPI(app, this.state.apps)) {
228
+ this.loadDatasets(app);
229
+ }
230
+ if (app && app != 'none') {
231
+ this.loadMetadata(app, dvzProxyDatasetId);
232
+ }
233
+ });
234
+ })
235
+ .catch(() => {
236
+ console.log("Error when loading apps");
237
+ });
238
+ });
239
+ }
240
+ componentDidUpdate(prevProps, prevState, snapshot) {
241
+ super.componentDidUpdate(prevProps, prevState, snapshot);
242
+ const { attributes: { app, dvzProxyDatasetId } } = this.props;
243
+ const { attributes: { dvzProxyDatasetId: prevDvzProxyDatasetId, app: prevAPP } } = prevProps;
244
+ if (app != prevAPP) { //if app changes we shoudl reload metadta
245
+ if (isSupersetAPI(app, this.state.apps)) { //if app is superset proxy an additional step is added
246
+ this.loadDatasets(app);
247
+ if (dvzProxyDatasetId) {
248
+ this.loadMetadata(app, dvzProxyDatasetId);
249
+ }
250
+ }
251
+ else {
252
+ this.loadMetadata(app, dvzProxyDatasetId);
253
+ }
254
+ }
255
+ else { //app wasn't changed
256
+ if (dvzProxyDatasetId != prevDvzProxyDatasetId) {
257
+ this.loadMetadata(app, dvzProxyDatasetId);
258
+ }
259
+ }
260
+ }
261
+ evictSuperSetCache() {
262
+ const { app, dvzProxyDatasetId } = this.props.attributes;
263
+ fetch(`/api/${app}/cacheEvict?dvzProxyDatasetId=${dvzProxyDatasetId}`).then(() => {
264
+ this.loadMetadata(app, dvzProxyDatasetId);
265
+ });
266
+ }
267
+ loadDatasets(app) {
268
+ fetch(`/api/${app}/datasets`)
269
+ .then(response => {
270
+ if (!response.ok) {
271
+ throw new Error("HTTP status " + response.status);
272
+ }
273
+ return response.json();
274
+ })
275
+ .then(data => {
276
+ this.setState({
277
+ datasets: data
278
+ });
279
+ })
280
+ .catch(() => {
281
+ console.log("Error when loading datasets");
282
+ });
283
+ }
284
+ loadMetadata(app, dvzProxyDatasetId) {
285
+ if (app == 'csv') {
286
+ return;
287
+ }
288
+ const dimensionsUrl = `/api/${app}/dimensions${dvzProxyDatasetId ? `?dvzProxyDatasetId=${dvzProxyDatasetId}` : ''}`;
289
+ const measuresUrl = `/api/${app}/measures${dvzProxyDatasetId ? `?dvzProxyDatasetId=${dvzProxyDatasetId}` : ''}`;
290
+ const filtersUrl = `/api/${app}/filters${dvzProxyDatasetId ? `?dvzProxyDatasetId=${dvzProxyDatasetId}` : ''}`;
291
+ const categoriesUrl = `/api/${app}/categories${dvzProxyDatasetId ? `?dvzProxyDatasetId=${dvzProxyDatasetId}` : ''}`;
292
+ if (app != "csv") {
293
+ fetch(dimensionsUrl)
294
+ .then(response => {
295
+ if (!response.ok) {
296
+ throw new Error("HTTP status " + response.status);
297
+ }
298
+ else {
299
+ return response.json();
300
+ }
301
+ })
302
+ .then(data => {
303
+ this.setState({
304
+ dimensions: [{ "label": __("None"), "value": "none" }, ...getTranslatedOptions(data)]
305
+ });
306
+ })
307
+ .catch(function () {
308
+ console.log("Error when loading dimensions");
309
+ });
310
+ fetch(filtersUrl)
311
+ .then(response => {
312
+ if (!response.ok) {
313
+ throw new Error("HTTP status " + response.status);
314
+ }
315
+ return response.json();
316
+ })
317
+ .then(data => {
318
+ const options = data.map(f => ({ ...f, value: f.param }));
319
+ this.setState({ filters: options });
320
+ })
321
+ .catch(function (response) {
322
+ console.log("Error when loading filters", response);
323
+ });
324
+ fetch(measuresUrl)
325
+ .then(response => {
326
+ if (!response.ok) {
327
+ throw new Error("HTTP status " + response.status);
328
+ }
329
+ return response.json();
330
+ })
331
+ .then(data => {
332
+ sessionStorage.setItem(`measures_${app}`, JSON.stringify(getTranslatedOptions(data)));
333
+ this.setState({ measures: getTranslatedOptions(data) });
334
+ })
335
+ .catch(function () {
336
+ console.log("Error when loading measures");
337
+ });
338
+ fetch(categoriesUrl)
339
+ .then(response => {
340
+ if (!response.ok) {
341
+ throw new Error("HTTP status " + response.status);
342
+ }
343
+ return response.json();
344
+ })
345
+ .then(data => {
346
+ sessionStorage.setItem(`categories_${app}`, JSON.stringify(data));
347
+ this.setState({ categories: getTranslatedOptions(data) });
348
+ })
349
+ .catch(function (response) {
350
+ console.log("Error when getting categories", response);
351
+ });
352
+ }
353
+ }
354
+ fetchData(url, stateKey, transformData) {
355
+ fetch(url)
356
+ .then(response => {
357
+ if (!response.ok) {
358
+ throw new Error("HTTP status " + response.status);
359
+ }
360
+ return response.json();
361
+ })
362
+ .then(data => {
363
+ // TODO: Check if the data is an array
364
+ // @ts-ignore
365
+ this.setState({
366
+ [stateKey]: transformData(data)
367
+ });
368
+ })
369
+ .catch(() => {
370
+ console.log(`Error when loading ${stateKey}`);
371
+ });
372
+ }
373
+ }
374
+ export default SizeConfig;
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ export declare const CSVConfig: ({ attributes: { csv, panelStatus, measures, type }, setAttributes }: {
3
+ attributes: {
4
+ csv: any;
5
+ panelStatus: any;
6
+ measures: any;
7
+ type: any;
8
+ };
9
+ setAttributes: any;
10
+ }) => React.JSX.Element[];
11
+ export default CSVConfig;
@@ -0,0 +1,48 @@
1
+ import React from 'react';
2
+ import { PanelBody, PanelRow, TextareaControl } from '@wordpress/components';
3
+ import { __ } from '@wordpress/i18n';
4
+ import Format from "./Format";
5
+ import { togglePanel } from "./Util";
6
+ const defaultFormat = {
7
+ "style": "percent",
8
+ "minimumFractionDigits": 1,
9
+ "maximumFractionDigits": 1,
10
+ "currency": "USD"
11
+ };
12
+ export const CSVConfig = ({ attributes: { csv, panelStatus, measures, type }, setAttributes }) => {
13
+ const onFormatChange = (format, field) => {
14
+ const app = "csv";
15
+ const uMs = measures ? JSON.parse(JSON.stringify(measures)) : {};
16
+ if (!uMs[app]) {
17
+ uMs[app] = { allowSelection: false, format: Object.assign({}, defaultFormat), customFormat: Object.assign({}, { ...defaultFormat }), selected: false };
18
+ }
19
+ uMs[app][field] = format;
20
+ setAttributes({ measures: uMs });
21
+ };
22
+ const onUseCustomAxisFormatChange = (value) => {
23
+ const app = "csv";
24
+ const uMs = measures ? JSON.parse(JSON.stringify(measures)) : {};
25
+ if (uMs[app]) {
26
+ uMs[app].useCustomAxisFormat = value;
27
+ if (!uMs[app].customFormat) {
28
+ uMs[app].customFormat = Object.assign({}, { ...defaultFormat });
29
+ }
30
+ setAttributes({ measures: uMs });
31
+ }
32
+ else {
33
+ uMs[app] = { allowSelection: false, format: Object.assign({}, { ...defaultFormat }), customFormat: Object.assign({}, { ...defaultFormat }), selected: false };
34
+ uMs[app].useCustomAxisFormat = value;
35
+ setAttributes({ measures: uMs });
36
+ }
37
+ };
38
+ return ([React.createElement(PanelBody, { initialOpen: false, title: __("CSV Configuration"), onToggle: e => togglePanel("csv_cfg", panelStatus, setAttributes) },
39
+ React.createElement(PanelRow, null,
40
+ React.createElement(TextareaControl, { label: __("CSV Data"), value: csv, onChange: (csv) => setAttributes({ csv }) })),
41
+ React.createElement(Format, { hiddenCustomAxisFormat: type == 'radar' || type == 'big-number', format: measures["csv"] && measures["csv"].format ? measures["csv"].format : {}, customFormat: measures["csv"] && measures["csv"].customFormat ? measures["csv"].customFormat : {}, useCustomAxisFormat: measures["csv"] ? measures["csv"].useCustomAxisFormat : false, onFormatChange: (newFormat, field) => {
42
+ onFormatChange(newFormat, field);
43
+ }, onUseCustomAxisFormatChange: value => {
44
+ onUseCustomAxisFormatChange(value);
45
+ } }))
46
+ ]);
47
+ };
48
+ export default CSVConfig;
@@ -0,0 +1,55 @@
1
+ import React from "react";
2
+ import { Categories, Dimension, Filter, Measure } from "./types";
3
+ export declare const categorical: {
4
+ value: string;
5
+ label: string;
6
+ }[];
7
+ export declare const sequential: {
8
+ value: string;
9
+ label: string;
10
+ }[];
11
+ export declare const diverging: {
12
+ value: string;
13
+ label: string;
14
+ }[];
15
+ export type ChartColorsProps = {
16
+ allDimensions?: Dimension[];
17
+ allFilters?: Filter[];
18
+ allMeasures?: Measure[];
19
+ allCategories?: Categories;
20
+ allApps?: any[];
21
+ setAttributes: (attributes: {
22
+ swap: boolean;
23
+ measures: Record<string, {
24
+ selected: boolean;
25
+ }>;
26
+ manualColors?: Record<string, Record<string, string>>;
27
+ scheme: string;
28
+ colorBy: string;
29
+ dimension1: string;
30
+ dimension2: string;
31
+ barColor: string | null;
32
+ type: string;
33
+ app: string;
34
+ csv: string;
35
+ includeOverall: boolean;
36
+ }) => void;
37
+ attributes: {
38
+ swap: boolean;
39
+ measures: Record<string, {
40
+ selected: boolean;
41
+ }>;
42
+ manualColors: Record<string, Record<string, string>>;
43
+ scheme: string;
44
+ colorBy: string;
45
+ dimension1: string;
46
+ dimension2: string;
47
+ barColor: string;
48
+ type: string;
49
+ app: string;
50
+ csv: string;
51
+ includeOverall: boolean;
52
+ };
53
+ };
54
+ export declare const ChartColors: (props: ChartColorsProps) => (string | number | boolean | React.JSX.Element | Iterable<React.ReactNode> | null | undefined)[] | null;
55
+ export default ChartColors;