@cdc/editor 4.24.10 → 4.24.12-2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cdceditor.js +58311 -56056
- package/package.json +9 -9
- package/src/_stories/Editor.stories.tsx +19 -0
- package/src/components/ChooseTab.tsx +349 -381
- package/src/components/ConfigureTab.tsx +1 -1
- package/src/components/DataImport.tsx +134 -38
- package/src/components/PreviewDataTable.tsx +63 -45
- package/src/scss/choose-vis-tab.scss +12 -6
- package/src/scss/data-import.scss +14 -9
- package/src/scss/main.scss +1 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import React, { useContext } from 'react'
|
|
2
2
|
|
|
3
3
|
import CdcMap from '@cdc/map/src/CdcMap' // TODO: Lazy load this
|
|
4
|
-
import CdcChart from '
|
|
4
|
+
import CdcChart from '../../../chart/src/CdcChart' // TODO: Lazy load this
|
|
5
5
|
import CdcDataBite from '@cdc/data-bite/src/CdcDataBite'
|
|
6
6
|
import CdcWaffleChart from '@cdc/waffle-chart/src/CdcWaffleChart'
|
|
7
7
|
import CdcMarkupInclude from '@cdc/markup-include/src/CdcMarkupInclude'
|
|
@@ -40,7 +40,9 @@ export default function DataImport() {
|
|
|
40
40
|
}
|
|
41
41
|
const transform = new DataTransform()
|
|
42
42
|
|
|
43
|
-
const [externalURL, setExternalURL] = useState(
|
|
43
|
+
const [externalURL, setExternalURL] = useState(
|
|
44
|
+
config.dataFileSourceType === 'url' ? config.dataFileName : config.dataUrl || ''
|
|
45
|
+
)
|
|
44
46
|
|
|
45
47
|
const [keepURL, setKeepURL] = useState(!!config.dataUrl)
|
|
46
48
|
|
|
@@ -59,13 +61,13 @@ export default function DataImport() {
|
|
|
59
61
|
if (size === undefined) return ''
|
|
60
62
|
|
|
61
63
|
if (size > Math.pow(1024, 3)) {
|
|
62
|
-
return Math.round((size / Math.pow(1024, 3)) * 100) / 100 + '
|
|
64
|
+
return Math.round((size / Math.pow(1024, 3)) * 100) / 100 + 'GB'
|
|
63
65
|
} else if (size > Math.pow(1024, 2)) {
|
|
64
|
-
return Math.round((size / Math.pow(1024, 2)) * 100) / 100 + '
|
|
66
|
+
return Math.round((size / Math.pow(1024, 2)) * 100) / 100 + 'MB'
|
|
65
67
|
} else if (size > 1024) {
|
|
66
|
-
return Math.round((size / 1024) * 100) / 100 + '
|
|
68
|
+
return Math.round((size / 1024) * 100) / 100 + 'KB'
|
|
67
69
|
} else {
|
|
68
|
-
return size + '
|
|
70
|
+
return size + 'B'
|
|
69
71
|
}
|
|
70
72
|
}
|
|
71
73
|
|
|
@@ -88,7 +90,11 @@ export default function DataImport() {
|
|
|
88
90
|
}
|
|
89
91
|
|
|
90
92
|
const getFileExtension = (url: URL) => {
|
|
91
|
-
return isSolrCsv(externalURL)
|
|
93
|
+
return isSolrCsv(externalURL)
|
|
94
|
+
? '.csv'
|
|
95
|
+
: isSolrJson(externalURL)
|
|
96
|
+
? '.json'
|
|
97
|
+
: Object.keys(supportedDataTypes).find(extension => url.pathname.endsWith(extension))
|
|
92
98
|
}
|
|
93
99
|
|
|
94
100
|
const loadExternal = async () => {
|
|
@@ -96,7 +102,8 @@ export default function DataImport() {
|
|
|
96
102
|
// Is URL valid?
|
|
97
103
|
|
|
98
104
|
try {
|
|
99
|
-
dataURL =
|
|
105
|
+
dataURL =
|
|
106
|
+
isSolrCsv(externalURL) || isSolrJson(externalURL) ? externalURL : new URL(externalURL, window.location.origin)
|
|
100
107
|
} catch {
|
|
101
108
|
throw errorMessages.urlInvalid
|
|
102
109
|
}
|
|
@@ -116,7 +123,11 @@ export default function DataImport() {
|
|
|
116
123
|
const csvTypes = ['text/csv', 'text/plain']
|
|
117
124
|
if ((fileExtension === '.csv' && csvTypes.includes(responseBlob.type)) || isSolrCsv(externalURL)) {
|
|
118
125
|
responseBlob = responseBlob.slice(0, responseBlob.size, 'text/csv')
|
|
119
|
-
} else if (
|
|
126
|
+
} else if (
|
|
127
|
+
responseBlob.type === 'application/json' ||
|
|
128
|
+
(fileExtension === '.json' && responseBlob.type === 'text/plain') ||
|
|
129
|
+
isSolrJson(externalURL)
|
|
130
|
+
) {
|
|
120
131
|
responseBlob = responseBlob.slice(0, responseBlob.size, 'application/json')
|
|
121
132
|
}
|
|
122
133
|
})
|
|
@@ -146,7 +157,8 @@ export default function DataImport() {
|
|
|
146
157
|
*/
|
|
147
158
|
const loadData = async (fileBlob = null, fileName, editingDatasetKey) => {
|
|
148
159
|
let fileData = fileBlob
|
|
149
|
-
|
|
160
|
+
let fileSource = fileData?.path ?? fileName ?? externalURL
|
|
161
|
+
if (fileSource && typeof fileSource === 'string') fileSource = fileSource.trim()
|
|
150
162
|
const fileSourceType = fileBlob ? 'file' : 'url'
|
|
151
163
|
|
|
152
164
|
// Get the raw data as text from the file
|
|
@@ -332,19 +344,43 @@ export default function DataImport() {
|
|
|
332
344
|
}
|
|
333
345
|
|
|
334
346
|
const { getRootProps, getInputProps, isDragActive } = useDropzone({ onDrop })
|
|
335
|
-
const {
|
|
347
|
+
const {
|
|
348
|
+
getRootProps: getRootProps2,
|
|
349
|
+
getInputProps: getInputProps2,
|
|
350
|
+
isDragActive: isDragActive2
|
|
351
|
+
} = useDropzone({ onDrop })
|
|
336
352
|
|
|
337
353
|
const loadDataFromUrl = () => {
|
|
338
354
|
return (
|
|
339
355
|
<>
|
|
340
356
|
<form className='input-group d-flex' onSubmit={e => e.preventDefault()}>
|
|
341
|
-
<input
|
|
342
|
-
|
|
357
|
+
<input
|
|
358
|
+
id='external-data'
|
|
359
|
+
type='text'
|
|
360
|
+
className='form-control flex-grow-1 border-right-0'
|
|
361
|
+
placeholder='e.g., https://data.cdc.gov/resources/file.json'
|
|
362
|
+
aria-label='Load data from external URL'
|
|
363
|
+
aria-describedby='load-data'
|
|
364
|
+
value={externalURL}
|
|
365
|
+
onChange={e => setExternalURL(e.target.value)}
|
|
366
|
+
/>
|
|
367
|
+
<button
|
|
368
|
+
className='rounded-0 border-0 btn btn-primary px-4'
|
|
369
|
+
type='submit'
|
|
370
|
+
id='load-data'
|
|
371
|
+
onClick={() => loadData(null, externalURL, editingDataset)}
|
|
372
|
+
>
|
|
343
373
|
Load
|
|
344
374
|
</button>
|
|
345
375
|
</form>
|
|
346
376
|
<label htmlFor='keep-url' className='mt-1 d-flex keep-url'>
|
|
347
|
-
<input
|
|
377
|
+
<input
|
|
378
|
+
type='checkbox'
|
|
379
|
+
id='keep-url'
|
|
380
|
+
checked={keepURL}
|
|
381
|
+
onChange={() => changeKeepURL(!keepURL, editingDataset)}
|
|
382
|
+
/>{' '}
|
|
383
|
+
Always load from URL (normally will only pull once)
|
|
348
384
|
</label>
|
|
349
385
|
</>
|
|
350
386
|
)
|
|
@@ -365,7 +401,15 @@ export default function DataImport() {
|
|
|
365
401
|
return (
|
|
366
402
|
//todo convert to modal
|
|
367
403
|
<>
|
|
368
|
-
<button
|
|
404
|
+
<button
|
|
405
|
+
className='btn danger'
|
|
406
|
+
onClick={() =>
|
|
407
|
+
resetEditor(
|
|
408
|
+
{ type: config.type, visualizationType: config.visualizationType } as Visualization,
|
|
409
|
+
'Resetting will remove your data and settings. Do you want to continue?'
|
|
410
|
+
)
|
|
411
|
+
}
|
|
412
|
+
>
|
|
369
413
|
Clear
|
|
370
414
|
<CloseIcon />
|
|
371
415
|
</button>
|
|
@@ -444,7 +488,8 @@ export default function DataImport() {
|
|
|
444
488
|
readyToConfigure = Object.keys(config.datasets).length > 0
|
|
445
489
|
} else {
|
|
446
490
|
configureData = config
|
|
447
|
-
readyToConfigure =
|
|
491
|
+
readyToConfigure =
|
|
492
|
+
!!config.formattedData || (config.data && config.dataDescription && transform.autoStandardize(config.data))
|
|
448
493
|
}
|
|
449
494
|
|
|
450
495
|
if (config.visualizationType === 'Sankey' && config.data) {
|
|
@@ -504,7 +549,10 @@ export default function DataImport() {
|
|
|
504
549
|
<Icon display='question' />
|
|
505
550
|
</Tooltip.Target>
|
|
506
551
|
<Tooltip.Content>
|
|
507
|
-
<p style={{ padding: '0.5rem' }}>
|
|
552
|
+
<p style={{ padding: '0.5rem' }}>
|
|
553
|
+
Name of the query string parameter that will be appended to the URL above with the values
|
|
554
|
+
provided below.
|
|
555
|
+
</p>
|
|
508
556
|
</Tooltip.Content>
|
|
509
557
|
</Tooltip>
|
|
510
558
|
</span>{' '}
|
|
@@ -560,7 +608,10 @@ export default function DataImport() {
|
|
|
560
608
|
<form
|
|
561
609
|
onSubmit={e => {
|
|
562
610
|
e.preventDefault()
|
|
563
|
-
if (
|
|
611
|
+
if (
|
|
612
|
+
!config.filters[i].orderedValues ||
|
|
613
|
+
config.filters[i].orderedValues.indexOf(e.target[0].value) === -1
|
|
614
|
+
) {
|
|
564
615
|
let newFilters = [...config.filters]
|
|
565
616
|
newFilters[i].orderedValues = newFilters[i].orderedValues || []
|
|
566
617
|
newFilters[i].orderedValues.push(e.target[0].value)
|
|
@@ -582,7 +633,12 @@ export default function DataImport() {
|
|
|
582
633
|
<button
|
|
583
634
|
className='btn full-width'
|
|
584
635
|
onClick={() => {
|
|
585
|
-
setConfig({
|
|
636
|
+
setConfig({
|
|
637
|
+
...config,
|
|
638
|
+
filters: config.filters
|
|
639
|
+
? [...config.filters, { type: 'url', key: Date.now() }]
|
|
640
|
+
: [{ type: 'url', key: Date.now() }]
|
|
641
|
+
})
|
|
586
642
|
}}
|
|
587
643
|
>
|
|
588
644
|
Add New URL Filter
|
|
@@ -604,7 +660,7 @@ export default function DataImport() {
|
|
|
604
660
|
<th>Name</th>
|
|
605
661
|
<th>Size</th>
|
|
606
662
|
<th>Type</th>
|
|
607
|
-
<th colSpan={
|
|
663
|
+
<th colSpan={3}>Actions</th>
|
|
608
664
|
</tr>
|
|
609
665
|
</thead>
|
|
610
666
|
<tbody>
|
|
@@ -613,18 +669,26 @@ export default function DataImport() {
|
|
|
613
669
|
config.datasets[datasetKey].dataFileName && (
|
|
614
670
|
<tr key={`tr-${datasetKey}`}>
|
|
615
671
|
<td>
|
|
616
|
-
<input
|
|
672
|
+
<input
|
|
673
|
+
className='dataset-name-input'
|
|
674
|
+
type='text'
|
|
675
|
+
defaultValue={datasetKey}
|
|
676
|
+
onBlur={e => renameDataset(datasetKey, e.target.value)}
|
|
677
|
+
/>
|
|
617
678
|
</td>
|
|
618
|
-
<td>{displaySize(config.datasets[datasetKey].dataFileSize)}</td>
|
|
619
|
-
<td>{config.datasets[datasetKey].dataFileFormat}</td>
|
|
679
|
+
<td className='p-1'>{displaySize(config.datasets[datasetKey].dataFileSize)}</td>
|
|
680
|
+
<td className='p-1'>{config.datasets[datasetKey].dataFileFormat}</td>
|
|
620
681
|
<td>
|
|
621
|
-
<button
|
|
622
|
-
|
|
682
|
+
<button
|
|
683
|
+
className='btn btn-link p-1'
|
|
684
|
+
onClick={() => setGlobalDatasetProp(datasetKey, 'preview', true)}
|
|
685
|
+
>
|
|
686
|
+
Preview
|
|
623
687
|
</button>
|
|
624
688
|
</td>
|
|
625
689
|
<td>
|
|
626
690
|
<button
|
|
627
|
-
className='btn btn-
|
|
691
|
+
className='btn btn-link p-1'
|
|
628
692
|
onClick={() => {
|
|
629
693
|
if (editingDataset === datasetKey) {
|
|
630
694
|
setEditingDataset(undefined)
|
|
@@ -632,16 +696,18 @@ export default function DataImport() {
|
|
|
632
696
|
setKeepURL(false)
|
|
633
697
|
} else {
|
|
634
698
|
setEditingDataset(datasetKey)
|
|
635
|
-
setExternalURL(
|
|
699
|
+
setExternalURL(
|
|
700
|
+
config.datasets[datasetKey].dataUrl || config.datasets[datasetKey].dataFileName
|
|
701
|
+
)
|
|
636
702
|
setKeepURL(!!config.datasets[datasetKey].dataUrl)
|
|
637
703
|
}
|
|
638
704
|
}}
|
|
639
705
|
>
|
|
640
|
-
Edit
|
|
706
|
+
Edit
|
|
641
707
|
</button>
|
|
642
708
|
</td>
|
|
643
709
|
<td>
|
|
644
|
-
<button className='btn btn-
|
|
710
|
+
<button className='btn btn-danger' onClick={() => removeDataset(datasetKey)}>
|
|
645
711
|
X
|
|
646
712
|
</button>
|
|
647
713
|
</td>
|
|
@@ -661,7 +727,14 @@ export default function DataImport() {
|
|
|
661
727
|
<div className='file-loaded-area'>
|
|
662
728
|
{(config.dataFileSourceType === 'file' || !config.dataFileSourceType) && (
|
|
663
729
|
<div className='data-source-options'>
|
|
664
|
-
<div
|
|
730
|
+
<div
|
|
731
|
+
className={
|
|
732
|
+
isDragActive2
|
|
733
|
+
? 'drag-active cdcdataviz-file-selector loaded-file'
|
|
734
|
+
: 'cdcdataviz-file-selector loaded-file'
|
|
735
|
+
}
|
|
736
|
+
{...getRootProps2()}
|
|
737
|
+
>
|
|
665
738
|
<input {...getInputProps2()} />
|
|
666
739
|
{isDragActive2 ? (
|
|
667
740
|
<p>Drop file here</p>
|
|
@@ -688,7 +761,15 @@ export default function DataImport() {
|
|
|
688
761
|
</>
|
|
689
762
|
)}
|
|
690
763
|
|
|
691
|
-
{showDataDesigner &&
|
|
764
|
+
{showDataDesigner && (
|
|
765
|
+
<DataDesigner
|
|
766
|
+
visualizationKey={null}
|
|
767
|
+
configureData={configureData}
|
|
768
|
+
updateDescriptionProp={(key, value) => updateDescriptionProp(configureData.dataFileName, key, value)}
|
|
769
|
+
config={config}
|
|
770
|
+
setConfig={setConfig}
|
|
771
|
+
/>
|
|
772
|
+
)}
|
|
692
773
|
</>
|
|
693
774
|
)}
|
|
694
775
|
|
|
@@ -698,7 +779,10 @@ export default function DataImport() {
|
|
|
698
779
|
<Tabs startingTab={editingDataset && config.datasets[editingDataset].dataFileSourceType === 'url' ? 1 : 0}>
|
|
699
780
|
<TabPane title='Upload File' icon={<FileUploadIcon className='inline-icon' />}>
|
|
700
781
|
{sharepath && <p className='alert--info'>The share path set for this website is: {sharepath}</p>}
|
|
701
|
-
<div
|
|
782
|
+
<div
|
|
783
|
+
className={isDragActive ? 'drag-active cdcdataviz-file-selector' : 'cdcdataviz-file-selector'}
|
|
784
|
+
{...getRootProps()}
|
|
785
|
+
>
|
|
702
786
|
<input {...getInputProps()} />
|
|
703
787
|
{isDragActive ? (
|
|
704
788
|
<p>Drop file here</p>
|
|
@@ -720,7 +804,11 @@ export default function DataImport() {
|
|
|
720
804
|
(Array.isArray(errors)
|
|
721
805
|
? errors.map((message, index) => (
|
|
722
806
|
<div className='error-box slim mt-2' key={`error-${message}`}>
|
|
723
|
-
<span>{message}</span>
|
|
807
|
+
<span>{message}</span>{' '}
|
|
808
|
+
<CloseIcon
|
|
809
|
+
className='inline-icon dismiss-error'
|
|
810
|
+
onClick={() => setErrors(errors.filter((val, i) => i !== index))}
|
|
811
|
+
/>
|
|
724
812
|
</div>
|
|
725
813
|
))
|
|
726
814
|
: errors.message)}
|
|
@@ -733,22 +821,30 @@ export default function DataImport() {
|
|
|
733
821
|
)}
|
|
734
822
|
|
|
735
823
|
{config.type === 'dashboard' && !addingDataset && (
|
|
736
|
-
<
|
|
824
|
+
<div className='mt-2'>
|
|
737
825
|
<button className='btn btn-primary' onClick={() => setAddingDataset(true)}>
|
|
738
826
|
+ Add More Files
|
|
739
827
|
</button>
|
|
740
|
-
</
|
|
828
|
+
</div>
|
|
741
829
|
)}
|
|
742
830
|
|
|
743
831
|
{readyToConfigure && (
|
|
744
|
-
<
|
|
745
|
-
<button
|
|
832
|
+
<div className='mt-2'>
|
|
833
|
+
<button
|
|
834
|
+
className='btn btn-primary'
|
|
835
|
+
onClick={() => dispatch({ type: 'EDITOR_SET_GLOBALACTIVE', payload: 2 })}
|
|
836
|
+
>
|
|
746
837
|
Configure your visualization
|
|
747
838
|
</button>
|
|
748
|
-
</
|
|
839
|
+
</div>
|
|
749
840
|
)}
|
|
750
841
|
|
|
751
|
-
<a
|
|
842
|
+
<a
|
|
843
|
+
href='https://www.cdc.gov/wcms/4.0/cdc-wp/data-presentation/data-map.html'
|
|
844
|
+
target='_blank'
|
|
845
|
+
rel='noopener noreferrer'
|
|
846
|
+
className='guidance-link'
|
|
847
|
+
>
|
|
752
848
|
<div>
|
|
753
849
|
<h3>Get Help</h3>
|
|
754
850
|
<p>Documentation and examples on formatting data and configuring visualizations.</p>
|
|
@@ -1,13 +1,24 @@
|
|
|
1
1
|
import React, { useState, useContext, useMemo, useCallback, useEffect, memo } from 'react'
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
useTable,
|
|
4
|
+
useBlockLayout,
|
|
5
|
+
useFlexLayout,
|
|
6
|
+
useGlobalFilter,
|
|
7
|
+
useSortBy,
|
|
8
|
+
useResizeColumns,
|
|
9
|
+
usePagination
|
|
10
|
+
} from 'react-table'
|
|
3
11
|
import ConfigContext, { EditorDispatchContext } from '../ConfigContext'
|
|
4
12
|
import { useDebounce } from 'use-debounce'
|
|
5
13
|
import fetchRemoteData from '@cdc/core/helpers/fetchRemoteData'
|
|
14
|
+
import { MdNavigateNext } from 'react-icons/md'
|
|
15
|
+
import { GrFormPrevious } from 'react-icons/gr'
|
|
6
16
|
|
|
7
17
|
// Core
|
|
8
18
|
import validateFipsCodeLength from '@cdc/core/helpers/validateFipsCodeLength'
|
|
9
19
|
import { errorMessages } from '../helpers/errorMessages'
|
|
10
20
|
import { DataSet } from '@cdc/dashboard/src/types/DataSet'
|
|
21
|
+
import Icon from '@cdc/core/components/ui/Icon'
|
|
11
22
|
|
|
12
23
|
const TableFilter = memo(({ globalFilter, setGlobalFilter, disabled = false }: any) => {
|
|
13
24
|
const [filterValue, setFilterValue] = useState(globalFilter)
|
|
@@ -44,18 +55,28 @@ const Header = memo(({ globalFilter, data, setGlobalFilter }: any) => (
|
|
|
44
55
|
))
|
|
45
56
|
|
|
46
57
|
const Footer = memo(({ previousPage, nextPage, canPreviousPage, canNextPage, pageNumber, totalPages }: any) => (
|
|
47
|
-
<footer className='data-table-pagination'>
|
|
58
|
+
<footer className='data-table-pagination mt-2'>
|
|
48
59
|
<ul>
|
|
49
60
|
<li>
|
|
50
61
|
<button
|
|
51
62
|
onClick={() => previousPage()}
|
|
52
|
-
className='btn btn-prev'
|
|
63
|
+
className='btn btn-prev display-flex align-items-center justify-content-center'
|
|
53
64
|
disabled={!canPreviousPage}
|
|
54
65
|
title='Previous Page'
|
|
55
|
-
|
|
66
|
+
>
|
|
67
|
+
{' '}
|
|
68
|
+
<GrFormPrevious />
|
|
69
|
+
</button>
|
|
56
70
|
</li>
|
|
57
|
-
<li>
|
|
58
|
-
<button
|
|
71
|
+
<li className='mr-2'>
|
|
72
|
+
<button
|
|
73
|
+
onClick={() => nextPage()}
|
|
74
|
+
className='btn btn-next display-flex align-items-center justify-content-center'
|
|
75
|
+
disabled={!canNextPage}
|
|
76
|
+
title='Next Page'
|
|
77
|
+
>
|
|
78
|
+
<MdNavigateNext />
|
|
79
|
+
</button>
|
|
59
80
|
</li>
|
|
60
81
|
</ul>
|
|
61
82
|
<span>
|
|
@@ -138,8 +159,7 @@ const PreviewDataTable = () => {
|
|
|
138
159
|
const columnConfig = {
|
|
139
160
|
id: `column-${columnName}`,
|
|
140
161
|
accessor: row => row[columnName],
|
|
141
|
-
Header: columnName
|
|
142
|
-
width: 250
|
|
162
|
+
Header: columnName
|
|
143
163
|
}
|
|
144
164
|
|
|
145
165
|
return columnConfig
|
|
@@ -183,7 +203,7 @@ const PreviewDataTable = () => {
|
|
|
183
203
|
previousPage
|
|
184
204
|
} = useTable(
|
|
185
205
|
{ columns: tableColumns, data: tableData, initialState: { pageSize: 25 } },
|
|
186
|
-
|
|
206
|
+
useFlexLayout,
|
|
187
207
|
useGlobalFilter,
|
|
188
208
|
useSortBy,
|
|
189
209
|
useResizeColumns,
|
|
@@ -199,7 +219,7 @@ const PreviewDataTable = () => {
|
|
|
199
219
|
<p>Import data to preview</p>
|
|
200
220
|
</section>
|
|
201
221
|
</section>
|
|
202
|
-
<div className='table-container'>
|
|
222
|
+
<div className='table-container mt-2'>
|
|
203
223
|
<table className='editor data-table' role='table'>
|
|
204
224
|
<thead>
|
|
205
225
|
<tr>
|
|
@@ -237,44 +257,42 @@ const PreviewDataTable = () => {
|
|
|
237
257
|
}
|
|
238
258
|
|
|
239
259
|
const Table = () => (
|
|
240
|
-
|
|
241
|
-
<
|
|
242
|
-
<
|
|
243
|
-
|
|
244
|
-
{
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
260
|
+
<div className='table-responsive'>
|
|
261
|
+
<table className='mt-2 w-100 table table-striped data-table table-sm ' aria-hidden='true' {...getTableProps}>
|
|
262
|
+
<thead>
|
|
263
|
+
{headerGroups.map(headerGroup => (
|
|
264
|
+
<tr {...headerGroup.getHeaderGroupProps()}>
|
|
265
|
+
{headerGroup.headers.map(column => (
|
|
266
|
+
<th
|
|
267
|
+
scope='col'
|
|
268
|
+
{...column.getHeaderProps(column.getSortByToggleProps())}
|
|
269
|
+
className={column.isSorted ? (column.isSortedDesc ? 'sort sort-desc' : 'sort sort-asc') : ''}
|
|
270
|
+
title={column.Header}
|
|
271
|
+
>
|
|
272
|
+
{column.render('Header')}
|
|
273
|
+
<div {...column.getResizerProps()} className='resizer' />
|
|
274
|
+
</th>
|
|
275
|
+
))}
|
|
276
|
+
</tr>
|
|
277
|
+
))}
|
|
278
|
+
</thead>
|
|
279
|
+
<tbody {...getTableBodyProps()}>
|
|
280
|
+
{page.map(row => {
|
|
281
|
+
prepareRow(row)
|
|
282
|
+
return (
|
|
283
|
+
<tr {...row.getRowProps()}>
|
|
284
|
+
{row.cells.map(cell => (
|
|
285
|
+
<td {...cell.getCellProps()} title={cell.value}>
|
|
286
|
+
{cell.render('Cell')}
|
|
287
|
+
</td>
|
|
256
288
|
))}
|
|
257
289
|
</tr>
|
|
258
|
-
)
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
prepareRow(row)
|
|
263
|
-
return (
|
|
264
|
-
<tr {...row.getRowProps()}>
|
|
265
|
-
{row.cells.map(cell => (
|
|
266
|
-
<td {...cell.getCellProps()} title={cell.value}>
|
|
267
|
-
{cell.render('Cell')}
|
|
268
|
-
</td>
|
|
269
|
-
))}
|
|
270
|
-
</tr>
|
|
271
|
-
)
|
|
272
|
-
})}
|
|
273
|
-
</tbody>
|
|
274
|
-
</table>
|
|
275
|
-
</section>
|
|
290
|
+
)
|
|
291
|
+
})}
|
|
292
|
+
</tbody>
|
|
293
|
+
</table>
|
|
276
294
|
<Footer {...footerProps} />
|
|
277
|
-
|
|
295
|
+
</div>
|
|
278
296
|
)
|
|
279
297
|
|
|
280
298
|
return [
|
|
@@ -8,15 +8,21 @@
|
|
|
8
8
|
ul + .heading-2 {
|
|
9
9
|
margin-top: 1em;
|
|
10
10
|
}
|
|
11
|
-
.grid {
|
|
11
|
+
.visualization-grid {
|
|
12
12
|
margin-top: 1em;
|
|
13
13
|
list-style: none;
|
|
14
|
-
display:
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
margin-bottom: 1rem;
|
|
18
|
-
width: 165px;
|
|
14
|
+
display: grid;
|
|
15
|
+
&.category_general {
|
|
16
|
+
grid-template-columns: repeat(4, 180px);
|
|
19
17
|
}
|
|
18
|
+
&.category_charts {
|
|
19
|
+
grid-template-columns: repeat(7, 180px);
|
|
20
|
+
grid-row-gap: 50px;
|
|
21
|
+
}
|
|
22
|
+
&.category_maps {
|
|
23
|
+
grid-template-columns: repeat(5, 180px);
|
|
24
|
+
}
|
|
25
|
+
|
|
20
26
|
button {
|
|
21
27
|
background-color: #fff;
|
|
22
28
|
color: var(--baseColor);
|
|
@@ -69,15 +69,11 @@
|
|
|
69
69
|
white-space: nowrap;
|
|
70
70
|
text-overflow: ellipsis;
|
|
71
71
|
overflow: hidden;
|
|
72
|
-
max-width: 40px;
|
|
73
72
|
|
|
74
73
|
button {
|
|
75
74
|
font-size: 11pt;
|
|
76
75
|
}
|
|
77
76
|
}
|
|
78
|
-
td:last-child {
|
|
79
|
-
max-width: 10px;
|
|
80
|
-
}
|
|
81
77
|
}
|
|
82
78
|
.cdcdataviz-file-selector {
|
|
83
79
|
padding: 1rem 3rem;
|
|
@@ -116,10 +112,6 @@
|
|
|
116
112
|
margin: 1em 0 2em 0;
|
|
117
113
|
color: var(--mediumGray);
|
|
118
114
|
}
|
|
119
|
-
.btn {
|
|
120
|
-
display: inline-block;
|
|
121
|
-
margin: 1em 0;
|
|
122
|
-
}
|
|
123
115
|
.btn.active {
|
|
124
116
|
$primary: #005eaa;
|
|
125
117
|
background: darken($primary, 15%);
|
|
@@ -238,8 +230,21 @@
|
|
|
238
230
|
}
|
|
239
231
|
.right-col {
|
|
240
232
|
position: relative;
|
|
241
|
-
background-color:
|
|
233
|
+
background-color: var(--gray2);
|
|
242
234
|
padding: $gbl-padding;
|
|
243
235
|
width: 50% !important;
|
|
236
|
+
|
|
237
|
+
table {
|
|
238
|
+
width: 100%;
|
|
239
|
+
table-layout: unset;
|
|
240
|
+
border-collapse: collapse;
|
|
241
|
+
|
|
242
|
+
th,
|
|
243
|
+
td {
|
|
244
|
+
white-space: nowrap;
|
|
245
|
+
text-overflow: ellipsis;
|
|
246
|
+
overflow: hidden;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
244
249
|
}
|
|
245
250
|
}
|
package/src/scss/main.scss
CHANGED
|
@@ -93,7 +93,6 @@
|
|
|
93
93
|
|
|
94
94
|
.link.link-upload {
|
|
95
95
|
display: block;
|
|
96
|
-
color: #005eaa;
|
|
97
96
|
background: unset;
|
|
98
97
|
padding-left: unset;
|
|
99
98
|
margin-top: 0.3rem;
|
|
@@ -101,6 +100,7 @@
|
|
|
101
100
|
text-decoration: underline;
|
|
102
101
|
cursor: pointer;
|
|
103
102
|
font-size: 12px;
|
|
103
|
+
border: none;
|
|
104
104
|
}
|
|
105
105
|
|
|
106
106
|
.link.link-replace {
|