├── .gitignore ├── README.md ├── __fixtures__ ├── old_style_datapackages │ ├── datastore_tabular.js │ └── map.js └── with_widgets │ ├── chart.js │ ├── data_explorer.js │ ├── data_explorer_2.js │ ├── geojson_simple.js │ ├── pdf.js │ ├── table.js │ ├── tabularmap.js │ ├── unsupported.js │ ├── web.js │ └── web_view_on_datastore_resource.js ├── cosmos.config.js ├── data-explorer-hello.png ├── dist ├── App.css ├── App.js ├── App.test.js ├── AppWithProvider.js ├── actions │ └── index.js ├── components │ ├── DataView │ │ ├── index.js │ │ └── index.test.js │ ├── DataViewBuilder │ │ ├── index.js │ │ └── index.test.js │ ├── Pagination │ │ └── index.js │ └── Share │ │ └── index.js ├── css │ └── index.css ├── i18n │ ├── i18n.js │ └── locales │ │ ├── da │ │ └── translation.json │ │ ├── en │ │ └── translation.json │ │ ├── fr │ │ └── translation.json │ │ └── pt_BR │ │ └── translation.json ├── index.js ├── reducers │ ├── datapackage.js │ ├── datastoreFilters.js │ ├── rootReducer.js │ ├── serializedState.js │ └── widgets.js ├── serviceWorker.js ├── store.js ├── testData │ ├── actes-criminels.json │ ├── inlinedData.json │ ├── montreal1.json │ ├── remoteData.json │ ├── testChartBuilder.json │ ├── testData.json │ ├── testDataInit.json │ └── testDataTableInit.json └── utils │ ├── index.js │ ├── loadDataset.js │ └── utils.test.js ├── package.json ├── postcss.config.js ├── public ├── README.md ├── app.css ├── example-with-geopoint.html ├── example-with-lots-of-columns.html ├── favicon.ico ├── index.html └── manifest.json ├── src ├── App.css ├── App.js ├── App.test.js ├── AppWithProvider.js ├── actions │ └── index.js ├── components │ ├── DataView │ │ ├── index.js │ │ └── index.test.js │ ├── DataViewBuilder │ │ ├── index.js │ │ └── index.test.js │ ├── Pagination │ │ └── index.js │ └── Share │ │ └── index.js ├── css │ └── index.css ├── i18n │ ├── i18n.js │ └── locales │ │ ├── da │ │ └── translation.json │ │ ├── en │ │ └── translation.json │ │ ├── fr │ │ └── translation.json │ │ └── pt_BR │ │ └── translation.json ├── index.js ├── reducers │ ├── datapackage.js │ ├── datastoreFilters.js │ ├── rootReducer.js │ ├── serializedState.js │ └── widgets.js ├── serviceWorker.js ├── store.js ├── testData │ ├── actes-criminels.json │ ├── inlinedData.json │ ├── montreal1.json │ ├── remoteData.json │ ├── testChartBuilder.json │ ├── testData.json │ ├── testDataInit.json │ └── testDataTableInit.json └── utils │ ├── index.js │ ├── loadDataset.js │ └── utils.test.js ├── tailwind.config.js └── yarn.lock /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # development 12 | __fixtures__/projects/ 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | *.sw* 26 | 27 | /build 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Docs at: http://tech.datopian.com/data-explorer/ 2 | -------------------------------------------------------------------------------- /__fixtures__/old_style_datapackages/datastore_tabular.js: -------------------------------------------------------------------------------- 1 | import 'react' 2 | import App from '../../src/AppWithProvider' 3 | 4 | const datapackage = {"resources":[{"mimetype":"text/csv","cache_url":null,"hash":"","description":"","created":"2019-08-19T20:37:50.141937","datastore_active":true,"format":"csv","package_id":"538da88b-b409-49bd-b5ac-b24cfc82dfb9","name":"test_resource","cache_last_updated":null,"state":"active","mimetype_inner":null,"archiver":{"is_broken_printable":"Downloaded OK","updated":"2019-08-19T20:37:58.237014","cache_filepath":"/tmp/archive/5e/5e18c734-3331-49b5-8df4-a5775d061ef4/interventionscitoyendo-1.csv","last_success":"2019-08-19T20:37:58.237014","size":13253667,"is_broken":false,"failure_count":0,"etag":"\"17415da26209536f1f43dfc6efc5e605\"","status":"Archived successfully","url_redirected_to":"https://cc-p-minio.ckan.io/ckan/montreal/resources/5e18c734-3331-49b5-8df4-a5775d061ef4/interventionscitoyendo-1.csv?AWSAccessKeyId=2effdd1004072cb9&Expires=1566247137&Signature=S43L%2FG%2F4HkXvpHY5PS%2FhcEP5XI0%3D","hash":"3bf10da9370c55491f9639a71c9991f9119b80e6","status_id":0,"reason":"","last_modified":"2019-08-19T20:37:51","resource_timestamp":"2019-08-19T20:37:53.680248","mimetype":"text/csv","cache_url":"https://montreal.l3.ckan.io/5e/5e18c734-3331-49b5-8df4-a5775d061ef4/interventionscitoyendo-1.csv","created":"2019-08-19T20:37:58.339970","first_failure":null},"last_modified":"2019-08-19T20:37:50.063748","position":0,"revision_id":"fcfa7f9a-0cf1-45d2-bfbc-bbed48af22bb","url_type":"upload","id":"5e18c734-3331-49b5-8df4-a5775d061ef4","resource_type":null,"size":null,"title":"test resource","path":"https://montreal.l3.ckan.io/en/dataset/538da88b-b409-49bd-b5ac-b24cfc82dfb9/resource/5e18c734-3331-49b5-8df4-a5775d061ef4/download/interventionscitoyendo-1.csv","shareLink":"http://0.0.0.0:4000/bixi/test-2019-09-19/5e18c734-3331-49b5-8df4-a5775d061ef4","iframeText":"","index":0}],"views":[{"id":0,"title":"test resource","format":"csv","resources":["test_resource"],"specType":"table"},{"id":0,"title":"test resource","format":"csv","resources":["test_resource"],"specType":"simple"},{"id":0,"title":"test resource","format":"csv","resources":["test_resource"],"specType":"tabularmap"}],"controls":{"showChartBuilder":true,"showMapBuilder":true}} 5 | 6 | export default { 7 | component: App, 8 | props: {datapackage: JSON.stringify(datapackage)} 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/old_style_datapackages/map.js: -------------------------------------------------------------------------------- 1 | import 'react' 2 | import App from '../../src/AppWithProvider' 3 | 4 | const datapackage = '{"name":"test","resources":[{"name":"geojson-test","format":"GeoJSON","path":"https://montreal.l3.ckan.io/en/dataset/587de1ea-817b-4e10-b387-83ec89f94e1b/resource/bc1e71e4-269a-4fa9-a278-ab6bfd80ec23/download/murales.geojson"}],"views":[{"specType":"map","resources":["geojson-test"]}]}' 5 | 6 | export default { 7 | component: App, 8 | props: {datapackage} 9 | } 10 | -------------------------------------------------------------------------------- /__fixtures__/with_widgets/chart.js: -------------------------------------------------------------------------------- 1 | import App from '../../src/AppWithProvider' 2 | 3 | const widgets = [ 4 | { 5 | active: true, 6 | name: 'Chart', 7 | datapackage: { 8 | views: [ 9 | { 10 | "resources": ["inspection_des_aliments_–_contrevenants"], 11 | "description": "", 12 | "title": "Graphe", 13 | "resource_id": "51026016-7d82-49dc-93e0-2176df8790c6", 14 | "view_type": "recline_graph_view", 15 | "id": "4b94afa6-2fbc-4d34-95b6-dbb63a2f3348", 16 | "package_id": "a5c1f0b9-261f-4247-99d8-f28da5000688", 17 | "specType": "simple", 18 | "spec": {} 19 | } 20 | ] 21 | } 22 | } 23 | ] 24 | 25 | const datapackage = { 26 | name: 'test', 27 | resources: [ 28 | { 29 | api: "https://montreal.l3.ckan.io/api/3/action/datastore_search?resource_id=54d7ffa0-04bf-442c-bacd-a84c6aab888d", 30 | path: 'https://montreal.l3.ckan.io/dataset/a5c1f0b9-261f-4247-99d8-f28da5000688/resource/54d7ffa0-04bf-442c-bacd-a84c6aab888d/download/inspection-aliments-contrevenants.csv', 31 | name: 'inspection_des_aliments_–_contrevenants', 32 | format: 'csv' 33 | } 34 | ] 35 | } 36 | 37 | export default { 38 | component: App, 39 | props: {widgets, datapackage: JSON.stringify(datapackage)} 40 | } 41 | -------------------------------------------------------------------------------- /__fixtures__/with_widgets/data_explorer.js: -------------------------------------------------------------------------------- 1 | import App from '../../src/AppWithProvider' 2 | 3 | const widgets = [ 4 | { 5 | active: true, 6 | name: 'Table', 7 | datapackage: { 8 | views: [ 9 | { 10 | "id": 1, 11 | "specType": "table" 12 | } 13 | ] 14 | } 15 | }, 16 | { 17 | active: false, 18 | name: 'Chart', 19 | datapackage: { 20 | views: [ 21 | { 22 | "id": 1, 23 | "specType": "simple", 24 | "spec": {} 25 | } 26 | ] 27 | } 28 | }, 29 | { 30 | active: false, 31 | name: 'Map', 32 | datapackage: { 33 | views: [ 34 | { 35 | "id": 1, 36 | "specType": "tabularmap", 37 | "spec": {} 38 | } 39 | ] 40 | } 41 | } 42 | ] 43 | 44 | const datapackage = { 45 | name: 'test', 46 | resources: [ 47 | { 48 | api: "https://montreal.l3.ckan.io/api/3/action/datastore_search?resource_id=54d7ffa0-04bf-442c-bacd-a84c6aab888d", 49 | path: 'https://montreal.l3.ckan.io/dataset/a5c1f0b9-261f-4247-99d8-f28da5000688/resource/54d7ffa0-04bf-442c-bacd-a84c6aab888d/download/inspection-aliments-contrevenants.csv', 50 | name: 'inspection_des_aliments_–_contrevenants', 51 | id: '54d7ffa0-04bf-442c-bacd-a84c6aab888d', 52 | format: 'csv', 53 | datastore_active: true 54 | } 55 | ] 56 | } 57 | 58 | export default { 59 | component: App, 60 | props: {widgets, datapackage: JSON.stringify(datapackage)} 61 | } 62 | -------------------------------------------------------------------------------- /__fixtures__/with_widgets/data_explorer_2.js: -------------------------------------------------------------------------------- 1 | import App from '../../src/AppWithProvider' 2 | 3 | 4 | const widgets = [ 5 | { 6 | "name": "Table", 7 | "active": true, 8 | "datapackage": { 9 | "views": [ 10 | { 11 | "id": "66632027-3d7d-4ca6-911f-bc4d003f3ddf", 12 | "specType": "table" 13 | } 14 | ] 15 | } 16 | }, 17 | { 18 | "name": "Chart", 19 | "active": false, 20 | "datapackage": { 21 | "views": [ 22 | { 23 | "id": "66632027-3d7d-4ca6-911f-bc4d003f3ddf", 24 | "specType": "simple" 25 | } 26 | ] 27 | } 28 | }, 29 | { 30 | "name": "Map", 31 | "active": false, 32 | "datapackage": { 33 | "views": [ 34 | { 35 | "id": "66632027-3d7d-4ca6-911f-bc4d003f3ddf", 36 | "specType": "tabularmap" 37 | } 38 | ] 39 | } 40 | } 41 | ] 42 | 43 | const datapackage = { 44 | "resources": [ 45 | { 46 | "mimetype": null, 47 | "cache_url": null, 48 | "hash": "", 49 | "description": "We publish embedded wind and solar forecast up to 14 days ahead at a daily resolution. ", 50 | "name": "embedded_solar_and_wind_forecast_daily", 51 | "format": "csv", 52 | "datastore_active": true, 53 | "cache_last_updated": null, 54 | "package_id": "91c0c70e-0ef5-4116-b6fa-7ad084b5e0e8", 55 | "created": "2019-11-07T21:25:27.215305", 56 | "state": "active", 57 | "mimetype_inner": null, 58 | "last_modified": "2020-02-18T04:34:45", 59 | "position": 0, 60 | "revision_id": "9adf3925-0f34-4235-984a-d1c536ecbe1a", 61 | "url_type": null, 62 | "id": "db6c038f-98af-4570-ab60-24d71ebd0ae5", 63 | "resource_type": null, 64 | "size": null, 65 | "title": "Embedded Solar and Wind Forecast DAILY", 66 | "path": "https://docs.google.com/spreadsheets/d/10suCRrhbljC1VX-9lVMGBncUZbvTJ4KVBV0wfVoVRUU/gviz/tq?tqx=out:csv", 67 | "views": [ 68 | { 69 | "description": "", 70 | "title": "Data Explorer", 71 | "resource_id": "db6c038f-98af-4570-ab60-24d71ebd0ae5", 72 | "view_type": "recline_view", 73 | "id": "66632027-3d7d-4ca6-911f-bc4d003f3ddf", 74 | "package_id": "91c0c70e-0ef5-4116-b6fa-7ad084b5e0e8", 75 | "specType": "dataExplorer", 76 | "spec": { 77 | "widgets": [ 78 | { 79 | "specType": "table" 80 | }, 81 | { 82 | "specType": "simple" 83 | }, 84 | { 85 | "specType": "tabularmap" 86 | } 87 | ] 88 | } 89 | } 90 | ], 91 | "descriptionHtml": "

We publish embedded wind and solar forecast up to 14 days ahead at a daily resolution.

\\n", 92 | "api": "https://national-grid-admin.ckan.io/api/3/action/datastore_search?resource_id=db6c038f-98af-4570-ab60-24d71ebd0ae5" 93 | } 94 | ] 95 | } 96 | 97 | export default { 98 | component: App, 99 | props: {widgets, datapackage: JSON.stringify(datapackage)} 100 | } 101 | -------------------------------------------------------------------------------- /__fixtures__/with_widgets/geojson_simple.js: -------------------------------------------------------------------------------- 1 | import App from '../../src/AppWithProvider' 2 | 3 | const widgets = [ 4 | { 5 | active: true, 6 | name: 'Map', 7 | datapackage: { 8 | views: [ 9 | { 10 | specType: 'map', 11 | resources: [ 12 | 'geojson-test' 13 | ] 14 | } 15 | ] 16 | } 17 | } 18 | ] 19 | 20 | const datapackage = { 21 | name: 'test', 22 | resources: [ 23 | { 24 | path: 'https://montreal.l3.ckan.io/en/dataset/587de1ea-817b-4e10-b387-83ec89f94e1b/resource/bc1e71e4-269a-4fa9-a278-ab6bfd80ec23/download/murales.geojson', 25 | pathType: 'remote', 26 | name: 'geojson-test', 27 | format: 'GeoJSON', 28 | mediatype: 'application/geo+json', 29 | encoding: 'utf-8', 30 | } 31 | ] 32 | } 33 | 34 | export default { 35 | component: App, 36 | props: {widgets, datapackage: JSON.stringify(datapackage)} 37 | } 38 | -------------------------------------------------------------------------------- /__fixtures__/with_widgets/pdf.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datopian/data-explorer/0dbb7cad13a3f2f96b80860adf97669e79a44d9f/__fixtures__/with_widgets/pdf.js -------------------------------------------------------------------------------- /__fixtures__/with_widgets/table.js: -------------------------------------------------------------------------------- 1 | import App from '../../src/AppWithProvider' 2 | 3 | const widgets = [ 4 | { 5 | active: true, 6 | name: 'Table', 7 | datapackage: { 8 | views: [ 9 | { 10 | "description": "", 11 | "title": "Table", 12 | "resource_id": "54d7ffa0-04bf-442c-bacd-a84c6aab888d", 13 | "view_type": "recline_grid_view", 14 | "id": "16ce7d84-0db1-4d39-aeab-d74e3dcf7d31", 15 | "package_id": "a5c1f0b9-261f-4247-99d8-f28da5000688", 16 | "specType": "table" 17 | } 18 | ] 19 | } 20 | } 21 | ] 22 | 23 | const datapackage = { 24 | name: 'test', 25 | resources: [ 26 | { 27 | api: "https://montreal.l3.ckan.io/api/3/action/datastore_search?resource_id=54d7ffa0-04bf-442c-bacd-a84c6aab888d", 28 | path: 'https://montreal.l3.ckan.io/dataset/a5c1f0b9-261f-4247-99d8-f28da5000688/resource/54d7ffa0-04bf-442c-bacd-a84c6aab888d/download/inspection-aliments-contrevenants.csv', 29 | name: 'inspection_des_aliments_–_contrevenants', 30 | format: 'csv' 31 | } 32 | ] 33 | } 34 | 35 | export default { 36 | component: App, 37 | props: {widgets, datapackage: JSON.stringify(datapackage)} 38 | } 39 | -------------------------------------------------------------------------------- /__fixtures__/with_widgets/tabularmap.js: -------------------------------------------------------------------------------- 1 | import App from '../../src/AppWithProvider' 2 | 3 | const widgets = [ 4 | { 5 | active: true, 6 | name: 'Map', 7 | datapackage: { 8 | views: [ 9 | { 10 | "resources": ["inspection_des_aliments_–_contrevenants"], 11 | "description": "", 12 | "title": "Map", 13 | "resource_id": "51026016-7d82-49dc-93e0-2176df8790c6", 14 | "view_type": "recline_map_view", 15 | "id": "4b94afa6-2fbc-4d34-95b6-dbb63a2f3348", 16 | "package_id": "a5c1f0b9-261f-4247-99d8-f28da5000688", 17 | "specType": "tabularmap", 18 | "spec": {} 19 | } 20 | ] 21 | } 22 | } 23 | ] 24 | 25 | const datapackage = { 26 | name: 'test', 27 | resources: [ 28 | { 29 | api: "https://montreal.l3.ckan.io/api/3/action/datastore_search?resource_id=54d7ffa0-04bf-442c-bacd-a84c6aab888d", 30 | path: 'https://montreal.l3.ckan.io/dataset/a5c1f0b9-261f-4247-99d8-f28da5000688/resource/54d7ffa0-04bf-442c-bacd-a84c6aab888d/download/inspection-aliments-contrevenants.csv', 31 | name: 'inspection_des_aliments_–_contrevenants', 32 | format: 'csv' 33 | } 34 | ] 35 | } 36 | 37 | export default { 38 | component: App, 39 | props: {widgets, datapackage: JSON.stringify(datapackage)} 40 | } 41 | -------------------------------------------------------------------------------- /__fixtures__/with_widgets/unsupported.js: -------------------------------------------------------------------------------- 1 | import App from '../../src/AppWithProvider' 2 | 3 | const widgets = [ 4 | { 5 | "name": "widget0", 6 | "active": true, 7 | "datapackage": { 8 | "views": [ 9 | { 10 | "id": "217d95ca-fbbe-4a28-b123-0ce3c6b8bfcb", 11 | "specType": "unsupported" 12 | } 13 | ] 14 | } 15 | } 16 | ] 17 | 18 | 19 | const datapackage = { 20 | "resources": [ 21 | { 22 | "name": "inspection_des_aliments_–_contrevenants", 23 | "format": "xml", 24 | "id": "54d7ffa0-04bf-442c-bacd-a84c6aab888d", 25 | "title": "Inspection des aliments – contrevenants", 26 | "path": "https://montreal.l3.ckan.io/dataset/a5c1f0b9-261f-4247-99d8-f28da5000688/resource/54d7ffa0-04bf-442c-bacd-a84c6aab888d/download/inspection-aliments-contrevenants.csv", 27 | } 28 | ] 29 | } 30 | 31 | 32 | export default { 33 | component: App, 34 | props: {widgets, datapackage: JSON.stringify(datapackage)} 35 | } 36 | -------------------------------------------------------------------------------- /__fixtures__/with_widgets/web.js: -------------------------------------------------------------------------------- 1 | import App from '../../src/AppWithProvider' 2 | 3 | const widgets = [ 4 | { 5 | "name": "widget0", 6 | "active": true, 7 | "datapackage": { 8 | "views": [ 9 | { 10 | "id": "217d95ca-fbbe-4a28-b123-0ce3c6b8bfcb", 11 | "specType": "web", 12 | "page_url": "https://datahub.io/core/co2-ppm/view/0" 13 | } 14 | ] 15 | } 16 | } 17 | ] 18 | 19 | 20 | const datapackage = { 21 | "resources": [ 22 | { 23 | "name": "inspection_des_aliments_–_contrevenants", 24 | "format": "xml", 25 | "id": "54d7ffa0-04bf-442c-bacd-a84c6aab888d", 26 | "title": "Inspection des aliments – contrevenants", 27 | "path": "http://example.com", 28 | } 29 | ] 30 | } 31 | 32 | 33 | export default { 34 | component: App, 35 | props: {widgets, datapackage: JSON.stringify(datapackage)} 36 | } 37 | -------------------------------------------------------------------------------- /__fixtures__/with_widgets/web_view_on_datastore_resource.js: -------------------------------------------------------------------------------- 1 | // Web view in a datastore resource. 2 | // This fixture is for testing that self contained web view shouldn't display 3 | // datastore specific components such as "total rows", "filters (aka rules)", 4 | // and pagination. 5 | 6 | import App from '../../src/AppWithProvider' 7 | 8 | const widgets = [ 9 | { 10 | "active": true, 11 | "datapackage": { 12 | "views": [ 13 | { 14 | "id": "217d95ca-fbbe-4a28-b123-0ce3c6b8bfcb", 15 | "specType": "web", 16 | "page_url": "https://datahub.io/core/co2-ppm/view/0" 17 | } 18 | ] 19 | } 20 | } 21 | ] 22 | 23 | 24 | const datapackage = { 25 | "resources": [ 26 | { 27 | "name": "inspection_des_aliments_–_contrevenants", 28 | "format": "xml", 29 | "id": "54d7ffa0-04bf-442c-bacd-a84c6aab888d", 30 | "title": "Inspection des aliments – contrevenants", 31 | "path": "https://national-grid-admin.ckan.io/", 32 | "api": "https://national-grid-admin.ckan.io/api/3/action/datastore_search?resource_id=db6c038f-98af-4570-ab60-24d71ebd0ae5", 33 | "datastore_active": true 34 | } 35 | ] 36 | } 37 | 38 | 39 | export default { 40 | component: App, 41 | props: {widgets, datapackage: JSON.stringify(datapackage)} 42 | } 43 | -------------------------------------------------------------------------------- /cosmos.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | containerQuerySelector: '#root', 3 | webpackConfigPath: './node_modules/react-scripts/config/webpack.config.js', 4 | publicPath: 'public', 5 | port: 9090 6 | } 7 | -------------------------------------------------------------------------------- /data-explorer-hello.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/datopian/data-explorer/0dbb7cad13a3f2f96b80860adf97669e79a44d9f/data-explorer-hello.png -------------------------------------------------------------------------------- /dist/App.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports.default = exports.App = void 0; 9 | 10 | var _react = _interopRequireWildcard(require("react")); 11 | 12 | var _reactRedux = require("react-redux"); 13 | 14 | require("./App.css"); 15 | 16 | var _datastoreQueryBuilder = require("@datopian/datastore-query-builder"); 17 | 18 | var _DataView = _interopRequireDefault(require("./components/DataView")); 19 | 20 | var _Share = _interopRequireDefault(require("./components/Share")); 21 | 22 | var _Pagination = _interopRequireDefault(require("./components/Pagination")); 23 | 24 | var _chartBuilder = require("@datopian/chart-builder"); 25 | 26 | var _mapBuilder = require("@datopian/map-builder"); 27 | 28 | var _reactTabsRedux = require("react-tabs-redux"); 29 | 30 | var _actions = require("./actions/"); 31 | 32 | var _utils = require("./utils"); 33 | 34 | require("./i18n/i18n"); 35 | 36 | var _reactI18next = require("react-i18next"); 37 | 38 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 39 | 40 | function _getRequireWildcardCache() { if (typeof WeakMap !== "function") return null; var cache = new WeakMap(); _getRequireWildcardCache = function _getRequireWildcardCache() { return cache; }; return cache; } 41 | 42 | 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; } 43 | 44 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } 45 | 46 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 47 | 48 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 49 | 50 | var App = function App(props) { 51 | (0, _react.useEffect)(function () { 52 | var payload = { 53 | datapackage: props.datapackage, 54 | widgets: props.widgets 55 | }; 56 | props.fetchDataAction(payload); 57 | }, []); 58 | var activeWidget = props.widgets.find(function (widget) { 59 | return widget.active; 60 | }); 61 | 62 | var _useTranslation = (0, _reactI18next.useTranslation)(), 63 | t = _useTranslation.t; // Check if any of widgets requires datastore specific components: 64 | 65 | 66 | var nonDataStoreViewTypes = ['web', 'document']; 67 | var datastoreComponents = props.widgets.find(function (widget) { 68 | return widget.datapackage.views.find(function (view) { 69 | return !nonDataStoreViewTypes.includes(view.specType); 70 | }); 71 | }); 72 | var totalRows = props.datapackage.resources[0].datastore_active ? props.datapackage.resources[0].totalrowcount ? props.datapackage.resources[0].totalrowcount.toLocaleString() : '' : ''; 73 | var distinguisher = '-' + Math.random().toString(36).slice(2, 5); 74 | var retrieveSelectedTab = activeWidget ? activeWidget.name : props.widgets[0].name; 75 | var selectedTab; 76 | 77 | if (retrieveSelectedTab.includes('-')) { 78 | selectedTab = retrieveSelectedTab; 79 | } else { 80 | selectedTab = retrieveSelectedTab + distinguisher; 81 | } 82 | 83 | var illegalCharacters = /\W+/gi; 84 | selectedTab = selectedTab.replace(illegalCharacters, "-"); 85 | var tabLinks = props.widgets.map(function (widget, index) { 86 | return _react.default.createElement(_reactTabsRedux.TabLink, { 87 | to: (widget.name + distinguisher).replace(illegalCharacters, "-"), 88 | className: "mr-4 tab-".concat(widget.name.toLowerCase()), 89 | key: "tabLink-".concat(index) 90 | }, t(widget.name)); 91 | }); 92 | var tabContents = props.widgets.map(function (widget, index) { 93 | return _react.default.createElement(_reactTabsRedux.TabContent, { 94 | for: (widget.name + distinguisher).replace(illegalCharacters, "-"), 95 | className: "mr-4 tabpanel-".concat(widget.name.toLowerCase()), 96 | key: "tabContent-".concat(index) 97 | }, ['table', 'web'].includes(widget.datapackage.views[0].specType) ? _react.default.createElement("div", { 98 | className: "container flex py-6" 99 | }, _react.default.createElement("div", { 100 | className: "w-full py-3" 101 | }, _react.default.createElement(_DataView.default, widget))) : _react.default.createElement("div", { 102 | className: "container flex py-6" 103 | }, _react.default.createElement("div", { 104 | className: "w-3/4 py-3 mr-4" 105 | }, _react.default.createElement(_DataView.default, widget)), _react.default.createElement("div", { 106 | className: "w-1/4" 107 | }, _react.default.createElement("div", { 108 | className: "w-full" 109 | }, _react.default.createElement("div", { 110 | className: "p-4 mr-4" 111 | }, widget.datapackage.views[0].specType === 'simple' ? _react.default.createElement(_chartBuilder.ChartBuilder, { 112 | view: widget.datapackage.views[0], 113 | dataViewBuilderAction: props.dataViewBuilderAction 114 | }) : '', widget.datapackage.views[0].specType === 'tabularmap' ? _react.default.createElement(_mapBuilder.MapBuilder, { 115 | view: widget.datapackage.views[0], 116 | dataViewBuilderAction: props.dataViewBuilderAction 117 | }) : ''))))); 118 | }); 119 | return _react.default.createElement("div", { 120 | className: "data-explorer" 121 | }, totalRows && datastoreComponents && _react.default.createElement("div", { 122 | className: "total-rows" 123 | }, _react.default.createElement("span", { 124 | className: "total-rows-label" 125 | }, t('Total rows')), ": ", _react.default.createElement("span", { 126 | className: "total-rows-value" 127 | }, totalRows)), _react.default.createElement("div", { 128 | className: "datastore-query-builder" 129 | }, (0, _utils.showQueryBuilder)(props) ? _react.default.createElement(_datastoreQueryBuilder.QueryBuilder, { 130 | resource: (0, _utils.getResourceForFiltering)(props.datapackage), 131 | filterBuilderAction: props.filterUIAction 132 | }) : ''), _react.default.createElement(_reactTabsRedux.Tabs, { 133 | renderActiveTabContentOnly: true, 134 | handleSelect: function handleSelect(selectedTab) { 135 | props.selectTabAction(selectedTab); 136 | }, 137 | className: "data-explorer-content", 138 | selectedTab: selectedTab 139 | }, tabLinks, tabContents), props.datapackage.resources[0].datastore_active && datastoreComponents ? _react.default.createElement(_Pagination.default, { 140 | datapackage: props.datapackage, 141 | updateAction: props.filterUIAction 142 | }) : _react.default.createElement("div", { 143 | className: "no-pagination not-datastore-resource" 144 | }), datastoreComponents ? _react.default.createElement(_Share.default, { 145 | serializedState: props.serializedState, 146 | apiUri: props.datapackage.resources[0].api 147 | }) : _react.default.createElement("div", { 148 | className: "no-share-feature" 149 | })); 150 | }; 151 | 152 | exports.App = App; 153 | 154 | var mapStateToProps = function mapStateToProps(state) { 155 | return _objectSpread({}, state); 156 | }; 157 | 158 | var mapDispatchToProps = function mapDispatchToProps(dispatch) { 159 | return { 160 | filterUIAction: function filterUIAction(payload) { 161 | return dispatch((0, _actions.filterUIAction)(payload)); 162 | }, 163 | fetchDataAction: function fetchDataAction(payload) { 164 | return dispatch((0, _actions.fetchDataAction)(payload)); 165 | }, 166 | dataViewBuilderAction: function dataViewBuilderAction(payload) { 167 | return dispatch((0, _actions.dataViewBuilderAction)(payload)); 168 | }, 169 | selectTabAction: function selectTabAction(payload) { 170 | return dispatch((0, _actions.selectTabAction)(payload)); 171 | } 172 | }; 173 | }; 174 | 175 | var _default = (0, _reactRedux.connect)(mapStateToProps, mapDispatchToProps)(App); 176 | 177 | exports.default = _default; -------------------------------------------------------------------------------- /dist/App.test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _react = _interopRequireDefault(require("react")); 4 | 5 | var _reactDom = _interopRequireDefault(require("react-dom")); 6 | 7 | var _App = require("./App"); 8 | 9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10 | 11 | it('renders without crashing', function () { 12 | var div = document.createElement('div'); 13 | 14 | _reactDom.default.render(_react.default.createElement(_App.App, null), div); 15 | 16 | _reactDom.default.unmountComponentAtNode(div); 17 | }); -------------------------------------------------------------------------------- /dist/AppWithProvider.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | var _react = _interopRequireDefault(require("react")); 9 | 10 | var _reactRedux = require("react-redux"); 11 | 12 | var _store = _interopRequireDefault(require("./store")); 13 | 14 | require("./App.css"); 15 | 16 | var _App2 = _interopRequireDefault(require("./App")); 17 | 18 | require("./i18n/i18n"); 19 | 20 | var _reactI18next = require("react-i18next"); 21 | 22 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 23 | 24 | function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } 25 | 26 | var _default = function _default(props) { 27 | var _useTranslation = (0, _reactI18next.useTranslation)(), 28 | t = _useTranslation.t; 29 | 30 | var datapackage; // Allow datapackage json or obj 31 | 32 | if (typeof props.datapackage === 'string') { 33 | try { 34 | datapackage = JSON.parse(props.datapackage); 35 | } catch (e) { 36 | // TODO -- would be nice for the app to still load in an empty state on fail case 37 | datapackage = {}; 38 | console.warn('Invalid datapackage', e); 39 | } 40 | } else if (_typeof(props.datapackage) === 'object') { 41 | datapackage = props.datapackage; 42 | } 43 | 44 | var views; 45 | 46 | try { 47 | views = JSON.parse(JSON.stringify(datapackage.views)); 48 | delete datapackage.views; 49 | } catch (_unused) { 50 | console.log('No views set on datapackage'); 51 | } 52 | 53 | var widgetsFromViews = function widgetsFromViews(views) { 54 | var widgetNames = { 55 | 'table': t('Table'), 56 | 'tabularmap': t('Map'), 57 | 'map': t('Map'), 58 | 'simple': t('Chart') 59 | }; 60 | return views.map(function (view, index) { 61 | return { 62 | active: index === 0 ? true : false, 63 | name: widgetNames[view.specType], 64 | datapackage: { 65 | views: [view] 66 | } 67 | }; 68 | }); 69 | }; 70 | 71 | var widgets = props.widgets ? props.widgets : widgetsFromViews(views); 72 | return _react.default.createElement(_reactRedux.Provider, { 73 | store: (0, _store.default)({ 74 | widgets: widgets, 75 | datapackage: datapackage 76 | }) 77 | }, _react.default.createElement(_App2.default, null)); 78 | }; 79 | 80 | exports.default = _default; -------------------------------------------------------------------------------- /dist/actions/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.fetchDataAction = exports.dataViewBuilderAction = exports.filterUIAction = exports.selectTabAction = void 0; 7 | 8 | var _loadDataset = _interopRequireDefault(require("../utils/loadDataset")); 9 | 10 | var _datapackageRender = require("datapackage-render"); 11 | 12 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 13 | 14 | function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; } 15 | 16 | function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } 17 | 18 | function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; } 19 | 20 | var selectTabAction = function selectTabAction(payload) { 21 | return function (dispatch, getState) { 22 | var widgets = JSON.parse(JSON.stringify(getState().widgets)); 23 | widgets.forEach(function (widget, index) { 24 | widgets[index].active = false; 25 | 26 | if (widget.name === payload || payload.includes('-') && payload.split('-')[0] === widget.name) { 27 | widgets[index].active = true; 28 | } 29 | }); 30 | dispatch(selectTab({ 31 | widgets: widgets 32 | })); 33 | }; 34 | }; 35 | 36 | exports.selectTabAction = selectTabAction; 37 | 38 | var filterUIAction = function filterUIAction(payload) { 39 | return function _callee(dispatch, getState) { 40 | var datapackage, newResource, updatedDatapackage, loadingWidgets, loadedDataset, widgets; 41 | return regeneratorRuntime.async(function _callee$(_context) { 42 | while (1) { 43 | switch (_context.prev = _context.next) { 44 | case 0: 45 | datapackage = JSON.parse(JSON.stringify(getState().datapackage)); // For datastore resources, we need to remove loaded `data` attribute to 46 | // trigger re-fetch of a resource. This is required since we initially fetch 47 | // only subset of data from datastore, eg, first 100 rows. When user applies 48 | // filters, we need to hit datastore api and update the data. 49 | 50 | newResource = JSON.parse(JSON.stringify(payload)); 51 | updatedDatapackage = Object.assign(datapackage, { 52 | resources: [newResource] 53 | }); 54 | 55 | if (updatedDatapackage.resources[0].datastore_active) { 56 | delete updatedDatapackage.resources[0].data; 57 | } // Update state.datapackage with new resource path that includes filters (datastore query) 58 | 59 | 60 | dispatch(datapackageLoad({ 61 | datapackage: updatedDatapackage 62 | })); // Set state of widgets as loading 63 | 64 | loadingWidgets = JSON.parse(JSON.stringify(getState().widgets)).map(function (widget) { 65 | widget.loading = true; 66 | return widget; 67 | }); 68 | dispatch(fetchDataBegin({ 69 | widgets: loadingWidgets 70 | })); // Load dataset using new path and update state 71 | 72 | datapackage = JSON.parse(JSON.stringify(getState().datapackage)); 73 | _context.next = 10; 74 | return regeneratorRuntime.awrap((0, _loadDataset.default)(datapackage)); 75 | 76 | case 10: 77 | loadedDataset = _context.sent; 78 | dispatch(datapackageLoad({ 79 | datapackage: loadedDataset 80 | })); // Compile new data into widget views 81 | 82 | widgets = JSON.parse(JSON.stringify(getState().widgets)).map(function (widget) { 83 | widget.datapackage.views = widget.datapackage.views.map(function (view) { 84 | return (0, _datapackageRender.compileView)(view, loadedDataset); 85 | }); 86 | widget.loading = false; 87 | return widget; 88 | }); 89 | dispatch(fetchDataSuccess({ 90 | widgets: widgets 91 | })); 92 | 93 | case 14: 94 | case "end": 95 | return _context.stop(); 96 | } 97 | } 98 | }); 99 | }; 100 | }; 101 | 102 | exports.filterUIAction = filterUIAction; 103 | 104 | var dataViewBuilderAction = function dataViewBuilderAction(payload) { 105 | return function (dispatch) { 106 | var actionType; 107 | 108 | if (payload.specType === 'simple') { 109 | actionType = 'DATA_VIEW_CHART_BUILDER_ACTION'; 110 | } else if (payload.specType === 'tabularmap') { 111 | actionType = 'DATA_VIEW_MAP_BUILDER_ACTION'; 112 | } 113 | 114 | dispatch({ 115 | type: actionType, 116 | payload: payload 117 | }); 118 | }; 119 | }; 120 | 121 | exports.dataViewBuilderAction = dataViewBuilderAction; 122 | 123 | var fetchDataAction = function fetchDataAction(payload) { 124 | return function _callee2(dispatch) { 125 | var loadingWidgets, datapackage, loadedDataset, widgets; 126 | return regeneratorRuntime.async(function _callee2$(_context2) { 127 | while (1) { 128 | switch (_context2.prev = _context2.next) { 129 | case 0: 130 | loadingWidgets = JSON.parse(JSON.stringify(payload.widgets)).map(function (widget) { 131 | widget.loading = true; 132 | return widget; 133 | }); 134 | dispatch(fetchDataBegin({ 135 | widgets: loadingWidgets 136 | })); 137 | datapackage = JSON.parse(JSON.stringify(payload.datapackage)); 138 | _context2.next = 5; 139 | return regeneratorRuntime.awrap((0, _loadDataset.default)(datapackage)); 140 | 141 | case 5: 142 | loadedDataset = _context2.sent; 143 | dispatch(datapackageLoad({ 144 | datapackage: loadedDataset 145 | })); 146 | widgets = JSON.parse(JSON.stringify(payload.widgets)).map(function (widget) { 147 | widget.datapackage.views = widget.datapackage.views.map(function (view) { 148 | return (0, _datapackageRender.compileView)(view, loadedDataset); 149 | }); 150 | return widget; 151 | }); 152 | dispatch(fetchDataSuccess({ 153 | widgets: widgets 154 | })); 155 | 156 | case 9: 157 | case "end": 158 | return _context2.stop(); 159 | } 160 | } 161 | }); 162 | }; 163 | }; 164 | 165 | exports.fetchDataAction = fetchDataAction; 166 | 167 | var selectTab = function selectTab(res) { 168 | return { 169 | type: 'SELECT_TAB', 170 | payload: _objectSpread({}, res) 171 | }; 172 | }; 173 | 174 | var datapackageLoad = function datapackageLoad(res) { 175 | return { 176 | type: 'DATAPACKAGE_LOAD', 177 | payload: _objectSpread({}, res) 178 | }; 179 | }; 180 | 181 | var fetchDataBegin = function fetchDataBegin(res) { 182 | return { 183 | type: 'FETCH_DATA_BEGIN', 184 | payload: _objectSpread({}, res) 185 | }; 186 | }; 187 | 188 | var fetchDataSuccess = function fetchDataSuccess(res) { 189 | return { 190 | type: 'FETCH_DATA_SUCCESS', 191 | payload: _objectSpread({}, res) 192 | }; 193 | }; 194 | 195 | var fetchDataFailure = function fetchDataFailure(err) { 196 | return { 197 | type: 'FETCH_DATA_FAILURE', 198 | payload: { 199 | err: err 200 | } 201 | }; 202 | }; -------------------------------------------------------------------------------- /dist/components/DataView/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | require("../../i18n/i18n"); 9 | 10 | var _react = _interopRequireDefault(require("react")); 11 | 12 | var _reactLoader = _interopRequireDefault(require("react-loader")); 13 | 14 | var _datapackageViewsJs = require("@datopian/datapackage-views-js"); 15 | 16 | var _reactI18next = require("react-i18next"); 17 | 18 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 19 | 20 | var _default = function _default(props) { 21 | var _useTranslation = (0, _reactI18next.useTranslation)(), 22 | t = _useTranslation.t; 23 | 24 | var views = props.datapackage.views; 25 | 26 | var showGuideText = function showGuideText(specType) { 27 | return _react.default.createElement("div", { 28 | className: "dx-guiding-text" 29 | }, specType === 'simple' ? _react.default.createElement("p", null, t('Select chart type, group column (abscissa x-axis) and series (ordinate y-axis) on the right hand side panel.')) : '', specType === 'tabularmap' ? _react.default.createElement("p", null, t('Select geo data column on the right hand side panel.')) : ''); 30 | }; 31 | 32 | var checkIfGuideIsNeeded = function checkIfGuideIsNeeded(view) { 33 | if (view.specType === 'simple' && !(view.spec && Object.keys(view.spec).length > 0)) { 34 | return true; 35 | } 36 | 37 | return false; 38 | }; 39 | 40 | return _react.default.createElement(_reactLoader.default, { 41 | loaded: !props.loading, 42 | style: { 43 | position: "relative" 44 | } 45 | }, _react.default.createElement("div", null, checkIfGuideIsNeeded(views[0]) ? showGuideText(views[0].specType) : views.map(function (view) { 46 | return _react.default.createElement(_datapackageViewsJs.DataView, { 47 | key: Math.random(), 48 | datapackage: { 49 | views: [view] 50 | } 51 | }); 52 | }))); 53 | }; 54 | 55 | exports.default = _default; -------------------------------------------------------------------------------- /dist/components/DataView/index.test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _react = _interopRequireDefault(require("react")); 4 | 5 | var _reactDom = _interopRequireDefault(require("react-dom")); 6 | 7 | var _ = _interopRequireDefault(require("./")); 8 | 9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10 | 11 | it('renders without crashing', function () { 12 | var div = document.createElement('div'); 13 | 14 | _reactDom.default.render(_react.default.createElement(_.default, null), div); 15 | 16 | _reactDom.default.unmountComponentAtNode(div); 17 | }); -------------------------------------------------------------------------------- /dist/components/DataViewBuilder/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | require("../../i18n/i18n"); 9 | 10 | var _react = _interopRequireDefault(require("react")); 11 | 12 | var _testChartBuilder = _interopRequireDefault(require("../../testData/testChartBuilder.json")); 13 | 14 | var _reactI18next = require("react-i18next"); 15 | 16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17 | 18 | var _default = function _default(props) { 19 | var _useTranslation = (0, _reactI18next.useTranslation)(), 20 | t = _useTranslation.t; 21 | 22 | return _react.default.createElement("div", null, _react.default.createElement("h2", { 23 | className: "text-2xl" 24 | }, "DataView Builder"), _react.default.createElement("button", { 25 | className: "bg-blue-600 hover:bg-gray-700 text-white font-bold py-2 px-4 rounded-full m-2", 26 | onClick: function onClick(e) { 27 | props.dataViewBuilderAction(_testChartBuilder.default); 28 | } 29 | }, t('UPDATE CHART'))); 30 | }; 31 | 32 | exports.default = _default; -------------------------------------------------------------------------------- /dist/components/DataViewBuilder/index.test.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _react = _interopRequireDefault(require("react")); 4 | 5 | var _reactDom = _interopRequireDefault(require("react-dom")); 6 | 7 | var _ = _interopRequireDefault(require("./")); 8 | 9 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 10 | 11 | it('renders without crashing', function () { 12 | var div = document.createElement('div'); 13 | 14 | _reactDom.default.render(_react.default.createElement(_.default, null), div); 15 | 16 | _reactDom.default.unmountComponentAtNode(div); 17 | }); -------------------------------------------------------------------------------- /dist/components/Pagination/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | require("../../i18n/i18n"); 9 | 10 | var _react = _interopRequireDefault(require("react")); 11 | 12 | var _reactPaginate = _interopRequireDefault(require("react-paginate")); 13 | 14 | var _reactI18next = require("react-i18next"); 15 | 16 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 17 | 18 | var _default = function _default(props) { 19 | var _useTranslation = (0, _reactI18next.useTranslation)(), 20 | t = _useTranslation.t; 21 | 22 | function handlePageClick(data) { 23 | var selected = data.selected; 24 | var offset = Math.ceil(selected * 100); 25 | var resource = JSON.parse(JSON.stringify(props.datapackage.resources[0])); 26 | var urlObj = new URL(resource.api); 27 | 28 | if (resource.api.includes('datastore_search?')) { 29 | urlObj.searchParams.set('offset', offset); 30 | } else if (resource.api.includes('datastore_search_sql?')) { 31 | var sql = urlObj.searchParams.get('sql'); 32 | var regex = /OFFSET(%20|\s)\d+/; 33 | 34 | if (regex.test(sql)) { 35 | urlObj.searchParams.set('sql', sql.replace(regex, "OFFSET ".concat(offset))); 36 | } else { 37 | urlObj.searchParams.set('sql', sql + " OFFSET ".concat(offset)); 38 | } 39 | 40 | resource.api = resource.api.includes('offset'); 41 | } 42 | 43 | resource.api = urlObj.href; 44 | props.updateAction(resource); 45 | } 46 | 47 | return _react.default.createElement(_reactPaginate.default, { 48 | previousLabel: t('Previous'), 49 | nextLabel: t('Next'), 50 | breakLabel: '...', 51 | breakClassName: 'break-me', 52 | pageCount: Math.ceil(props.datapackage.resources[0].totalrowcount / 100), 53 | marginPagesDisplayed: 2, 54 | pageRangeDisplayed: 5, 55 | onPageChange: handlePageClick, 56 | containerClassName: 'pagination', 57 | activeClassName: 'active' 58 | }); 59 | }; 60 | 61 | exports.default = _default; -------------------------------------------------------------------------------- /dist/components/Share/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | Object.defineProperty(exports, "__esModule", { 4 | value: true 5 | }); 6 | exports.default = void 0; 7 | 8 | require("../../i18n/i18n"); 9 | 10 | var _react = _interopRequireDefault(require("react")); 11 | 12 | var _reactI18next = require("react-i18next"); 13 | 14 | function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } 15 | 16 | var MAX_LEN = 1500; 17 | var slimProps = ['archiver', 'schema', 'shareLink', 'iframeText']; 18 | 19 | var slim = function slim(serializedState) { 20 | if (serializedState.length <= MAX_LEN) return serializedState; 21 | var state = JSON.parse(serializedState); 22 | state.datapackage.resources.forEach(function (resource) { 23 | for (var prop in slimProps) { 24 | if (resource[slimProps[prop]]) delete resource[slimProps[prop]]; 25 | } 26 | }); 27 | return JSON.stringify(state); 28 | }; 29 | 30 | var _default = function _default(props) { 31 | var _useTranslation = (0, _reactI18next.useTranslation)(), 32 | t = _useTranslation.t; 33 | 34 | var serializedState = slim(props.serializedState); 35 | var urlObj = new URL(window.location.href); 36 | urlObj.searchParams.set('explorer', serializedState); 37 | var shareLink = urlObj.href; 38 | var iframe = "