@cdc/markup-include 4.25.8 → 4.25.11

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.
@@ -1,45 +1,26 @@
1
- import React, { useState, useEffect, memo, useContext, useRef, useMemo, useReducer } from 'react'
1
+ import React, { useState, useEffect, useContext, useRef } from 'react'
2
2
 
3
- // Third Party
4
- import _ from 'lodash'
3
+ import { cloneConfig } from '@cdc/core/helpers/cloneConfig'
5
4
 
6
5
  // Context
7
- import { Variable } from '../types/Variable'
8
6
  import ConfigContext from '../ConfigContext'
9
7
 
10
8
  // Helpers
11
9
  import { updateFieldFactory } from '@cdc/core/helpers/updateFieldFactory'
12
10
 
13
11
  // Components
14
- import InputCheckbox from '@cdc/core/components/inputs/InputCheckbox'
12
+ import { TextField, CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
15
13
  import ErrorBoundary from '@cdc/core/components/ErrorBoundary'
16
- import Icon from '@cdc/core/components/ui/Icon'
17
- import InputText from '@cdc/core/components/inputs/InputText'
18
14
  import Layout from '@cdc/core/components/Layout'
19
- import Tooltip from '@cdc/core/components/ui/Tooltip'
20
15
  import Accordion from '@cdc/core/components/ui/Accordion'
16
+ import MarkupVariablesEditor from '@cdc/core/components/EditorPanel/components/MarkupVariablesEditor'
17
+ import FootnotesEditor from '@cdc/core/components/EditorPanel/FootnotesEditor'
18
+ import { HeaderThemeSelector } from '@cdc/core/components/HeaderThemeSelector'
19
+ import { Datasets } from '@cdc/core/types/DataSet'
21
20
 
22
21
  // styles
23
22
  import '@cdc/core/styles/v2/components/editor.scss'
24
23
  import './editorPanel.style.css'
25
- import VariableSection from './Variables'
26
- import { CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
27
- import FootnotesEditor from '@cdc/core/components/EditorPanel/FootnotesEditor'
28
- import { Datasets } from '@cdc/core/types/DataSet'
29
-
30
- const headerColors = [
31
- 'theme-blue',
32
- 'theme-purple',
33
- 'theme-brown',
34
- 'theme-teal',
35
- 'theme-pink',
36
- 'theme-orange',
37
- 'theme-slate',
38
- 'theme-indigo',
39
- 'theme-cyan',
40
- 'theme-green',
41
- 'theme-amber'
42
- ]
43
24
 
44
25
  type MarkupIncludeEditorPanelProps = {
45
26
  datasets?: Datasets
@@ -48,13 +29,11 @@ type MarkupIncludeEditorPanelProps = {
48
29
  const EditorPanel: React.FC<MarkupIncludeEditorPanelProps> = ({ datasets }) => {
49
30
  const { config, data, isDashboard, loading, setParentConfig, updateConfig } = useContext(ConfigContext)
50
31
  const { contentEditor, theme, visual } = config
51
- const { inlineHTML, markupVariables, srcUrl, title, useInlineHTML, allowHideSection, shoNoDataMessage } =
52
- contentEditor
32
+ const { inlineHTML, srcUrl, title, useInlineHTML } = contentEditor
53
33
  const [displayPanel, setDisplayPanel] = useState(true)
54
34
  const updateField = updateFieldFactory(config, updateConfig, true)
55
- const hasData = data?.[0] !== undefined ?? false
56
35
 
57
- const openVariableControls = useState<boolean[]>([])
36
+ const textAreaInEditorContainer = useRef(null)
58
37
 
59
38
  useEffect(() => {
60
39
  // Pass up to Editor if needed
@@ -80,58 +59,31 @@ const EditorPanel: React.FC<MarkupIncludeEditorPanelProps> = ({ datasets }) => {
80
59
  }
81
60
 
82
61
  const convertStateToConfig = () => {
83
- const strippedState = _.cloneDeep(config)
62
+ const strippedState = cloneConfig(config)
84
63
  delete strippedState.newViz
85
64
  delete strippedState.runtime
86
65
 
87
66
  return strippedState
88
67
  }
89
68
 
90
- const [variableArray, setVariableArray] = useState<Variable[]>([...markupVariables])
91
- const [isCreatingVariable, setIsCreatingVariable] = useState(false)
92
-
93
- const textAreaInEditorContainer = useRef(null)
94
- const [controls, setControls] = openVariableControls
95
-
96
- const handleCreateNewVariableButtonClick = () => {
97
- const newVariableArray = [..._.cloneDeep(variableArray)]
98
- const newVariable = {
99
- columnName: '',
100
- conditions: [],
101
- name: '',
102
- tag: ''
103
- }
104
-
105
- setControls({ ...controls, [variableArray.length + 1]: true })
106
-
107
- newVariableArray.push(newVariable)
108
- setVariableArray(newVariableArray)
109
- setIsCreatingVariable(!isCreatingVariable)
110
- }
111
-
112
- const updateVariableArray = (newVariable: Variable, variableIndex: number) => {
113
- const newVariableArray = _.cloneDeep(variableArray)
114
- newVariableArray[variableIndex] = newVariable
115
- setVariableArray(newVariableArray)
116
- updateField('contentEditor', null, 'markupVariables', newVariableArray)
117
- return
69
+ const handleMarkupVariablesChange = (variables: any[]) => {
70
+ updateConfig({
71
+ ...config,
72
+ markupVariables: variables
73
+ })
118
74
  }
119
75
 
120
- const deleteVariable = (variableIndex: number) => {
121
- const newVariableArray = _.cloneDeep(variableArray)
122
- newVariableArray.splice(variableIndex, 1)
123
- setVariableArray(newVariableArray)
124
- updateField('contentEditor', null, 'markupVariables', newVariableArray)
125
-
126
- const newControls = _.cloneDeep(controls)
127
- delete newControls[variableIndex]
128
- setControls(newControls)
76
+ const handleToggleEnable = (enabled: boolean) => {
77
+ updateConfig({
78
+ ...config,
79
+ enableMarkupVariables: enabled
80
+ })
129
81
  }
130
82
 
131
83
  const editorContent = (
132
84
  <Accordion>
133
85
  <Accordion.Section title='General'>
134
- <InputText
86
+ <TextField
135
87
  value={title || ''}
136
88
  section='contentEditor'
137
89
  fieldName='title'
@@ -142,12 +94,11 @@ const EditorPanel: React.FC<MarkupIncludeEditorPanelProps> = ({ datasets }) => {
142
94
  </Accordion.Section>
143
95
  <Accordion.Section title='Content Editor'>
144
96
  <span className='divider-heading'>Enter Markup</span>
145
- <InputCheckbox
146
- inline
97
+ <CheckBox
147
98
  value={useInlineHTML}
148
99
  section='contentEditor'
149
100
  fieldName='useInlineHTML'
150
- label='Use Inline HTML&nbsp;'
101
+ label='Use Inline HTML'
151
102
  updateField={updateField}
152
103
  />
153
104
  <div className='column-edit'>
@@ -155,98 +106,19 @@ const EditorPanel: React.FC<MarkupIncludeEditorPanelProps> = ({ datasets }) => {
155
106
  <>
156
107
  {/* HTML Textbox */}
157
108
  <div ref={textAreaInEditorContainer}>
158
- <InputText
109
+ <TextField
159
110
  value={inlineHTML}
160
111
  section='contentEditor'
161
112
  fieldName='inlineHTML'
162
113
  label='HTML'
163
114
  placeholder='Add HTML here'
164
115
  type='textarea'
165
- rows={10}
166
116
  updateField={updateField}
167
117
  />
168
-
169
- <hr className='accordion__divider' />
170
118
  </div>
171
- {/* Create New Variable*/}
172
-
173
- {/* Variable Options List */}
174
- <fieldset>
175
- <label>
176
- <span className='edit-label'>
177
- Variables
178
- <Tooltip style={{ textTransform: 'none' }}>
179
- <Tooltip.Target>
180
- <Icon display='question' style={{ marginLeft: '0.5rem' }} />
181
- </Tooltip.Target>
182
- <Tooltip.Content>{`To use created variables wrap the variable name in curly brackets, e.g. {{some_variable}}, and place the variable directly in your Inline HTML`}</Tooltip.Content>
183
- </Tooltip>
184
- </span>
185
- </label>
186
- {hasData === false && (
187
- <span className='need-data-source-prompt'>To use variables, add data source.</span>
188
- )}
189
- {variableArray && variableArray.length > 0 && (
190
- <div className='section-border'>
191
- {variableArray?.map((variableObject, index) => {
192
- return (
193
- <VariableSection
194
- key={`${variableObject.name}-${index}`}
195
- controls={openVariableControls}
196
- data={data}
197
- deleteVariable={deleteVariable}
198
- updateVariableArray={updateVariableArray}
199
- variableConfig={variableObject}
200
- variableIndex={index}
201
- />
202
- )
203
- })}
204
- </div>
205
- )}
206
- <div className='pt-2'>
207
- <CheckBox
208
- value={allowHideSection}
209
- section='contentEditor'
210
- fieldName='allowHideSection'
211
- label='Hide Section on Null'
212
- updateField={updateField}
213
- tooltip={
214
- <Tooltip style={{ textTransform: 'none' }}>
215
- <Tooltip.Target>
216
- <Icon
217
- display='question'
218
- style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
219
- />
220
- </Tooltip.Target>
221
- <Tooltip.Content>
222
- <p>{`Hide this entire Markup Include section if any variable is null or blank.`}</p>
223
- </Tooltip.Content>
224
- </Tooltip>
225
- }
226
- />
227
-
228
- <CheckBox
229
- value={contentEditor.showNoDataMessage}
230
- section='contentEditor'
231
- fieldName='showNoDataMessage'
232
- label='Add No Data Message'
233
- updateField={updateField}
234
- />
235
- </div>
236
-
237
- <div className='mb-1 d-flex'>
238
- <button
239
- className={'btn btn-primary'}
240
- onClick={handleCreateNewVariableButtonClick}
241
- disabled={!hasData}
242
- >
243
- Create New Variable
244
- </button>
245
- </div>
246
- </fieldset>
247
119
  </>
248
120
  ) : (
249
- <InputText
121
+ <TextField
250
122
  value={srcUrl || ''}
251
123
  section='contentEditor'
252
124
  fieldName='srcUrl'
@@ -257,56 +129,46 @@ const EditorPanel: React.FC<MarkupIncludeEditorPanelProps> = ({ datasets }) => {
257
129
  )}
258
130
  </div>
259
131
  </Accordion.Section>
260
- <Accordion.Section title='Visual'>
261
- <div className='input-group'>
262
- <label>Theme</label>
263
- <ul className='color-palette'>
264
- {headerColors.map(palette => (
265
- <li
266
- title={palette}
267
- key={palette}
268
- onClick={() => {
269
- updateConfig({ ...config, theme: palette })
270
- }}
271
- className={theme === palette ? 'selected ' + palette : palette}
272
- ></li>
273
- ))}
274
- </ul>
275
- </div>
276
- <div className='cove-accordion__panel-section checkbox-group'>
277
- <InputCheckbox
132
+ <Accordion.Section title='Visual' className='panel-visual'>
133
+ <HeaderThemeSelector
134
+ selectedTheme={theme}
135
+ onThemeSelect={theme => updateConfig({ ...config, theme })}
136
+ label='Theme'
137
+ />
138
+ <div className='checkbox-group'>
139
+ <CheckBox
278
140
  value={visual.border}
279
141
  section='visual'
280
142
  fieldName='border'
281
- label='Display Border&nbsp;'
143
+ label='Display Border'
282
144
  updateField={updateField}
283
145
  />
284
- <InputCheckbox
146
+ <CheckBox
285
147
  value={visual.borderColorTheme}
286
148
  section='visual'
287
149
  fieldName='borderColorTheme'
288
- label='Use Border Color Theme&nbsp;'
150
+ label='Use Border Color Theme'
289
151
  updateField={updateField}
290
152
  />
291
- <InputCheckbox
153
+ <CheckBox
292
154
  value={visual.accent}
293
155
  section='visual'
294
156
  fieldName='accent'
295
- label='Use Accent Style&nbsp;'
157
+ label='Use Accent Style'
296
158
  updateField={updateField}
297
159
  />
298
- <InputCheckbox
160
+ <CheckBox
299
161
  value={visual.background}
300
162
  section='visual'
301
163
  fieldName='background'
302
- label='Use Theme Background Color&nbsp;'
164
+ label='Use Theme Background Color'
303
165
  updateField={updateField}
304
166
  />
305
- <InputCheckbox
167
+ <CheckBox
306
168
  value={visual.hideBackgroundColor}
307
169
  section='visual'
308
170
  fieldName='hideBackgroundColor'
309
- label='Hide Background Color&nbsp;'
171
+ label='Hide Background Color'
310
172
  updateField={updateField}
311
173
  />
312
174
  </div>
@@ -316,6 +178,17 @@ const EditorPanel: React.FC<MarkupIncludeEditorPanelProps> = ({ datasets }) => {
316
178
  <FootnotesEditor config={config} updateField={updateField} datasets={datasets} />
317
179
  </Accordion.Section>
318
180
  )}
181
+ <Accordion.Section title='Markup Variables'>
182
+ <MarkupVariablesEditor
183
+ markupVariables={config.markupVariables || []}
184
+ data={data || []}
185
+ datasets={datasets}
186
+ config={config}
187
+ onChange={handleMarkupVariablesChange}
188
+ enableMarkupVariables={config.enableMarkupVariables || false}
189
+ onToggleEnable={handleToggleEnable}
190
+ />
191
+ </Accordion.Section>
319
192
  </Accordion>
320
193
  )
321
194
 
@@ -1,7 +1,6 @@
1
1
  export default {
2
2
  contentEditor: {
3
3
  inlineHTML: '<h2>Inline HTML</h2>',
4
- markupVariables: [],
5
4
  showHeader: true,
6
5
  srcUrl: '#example',
7
6
  title: 'Markup Include',
@@ -21,5 +20,7 @@ export default {
21
20
  background: false,
22
21
  hideBackgroundColor: false,
23
22
  borderColorTheme: false
24
- }
23
+ },
24
+ markupVariables: [],
25
+ enableMarkupVariables: false
25
26
  }
@@ -4,7 +4,6 @@ import ReactDOM from 'react-dom/client'
4
4
  import { GlobalContextProvider } from '@cdc/core/components/GlobalContext'
5
5
 
6
6
  import '@cdc/core/styles/cove-main.scss'
7
- import './coreStyles_markupinclude.scss'
8
7
 
9
8
  import CdcMarkupInclude from './CdcMarkupInclude'
10
9
 
@@ -1,12 +1,4 @@
1
1
  .markup-include {
2
- .checkbox-group {
3
- padding: 16px;
4
- border: 1px solid #c4c4c4;
5
- border-radius: 8px;
6
- margin-top: 8px;
7
- margin-bottom: 24px;
8
- }
9
-
10
2
  .cove-component__content-wrap {
11
3
  padding: 1rem 0;
12
4
 
@@ -1,7 +1,7 @@
1
1
  import { MarkupIncludeConfig } from '@cdc/core/types/MarkupInclude'
2
2
  import MarkupIncludeActions from './markupInclude.actions'
3
3
 
4
- export type MarkupIncludeState = {
4
+ type MarkupIncludeState = {
5
5
  config?: MarkupIncludeConfig
6
6
  loading: boolean
7
7
  urlMarkup: string
@@ -1,6 +1,11 @@
1
- // Placeholder test until we add them in.
1
+ import path from 'path'
2
+ import { testStandaloneBuild } from '@cdc/core/helpers/tests/testStandaloneBuild.ts'
3
+ import { describe, it, expect } from 'vitest'
4
+
2
5
  describe('Markup Include', () => {
3
- it('has a test.', async () => {
4
- return true
6
+ it('Can be built in isolation', async () => {
7
+ const pkgDir = path.join(__dirname, '..')
8
+ const result = testStandaloneBuild(pkgDir)
9
+ expect(result).toBe(true)
5
10
  })
6
11
  })
@@ -1,5 +1,5 @@
1
1
  export type Condition = {
2
2
  columnName: string
3
- isOrIsNotEqualTo: string
3
+ isOrIsNotEqualTo: 'is' | 'is not'
4
4
  value: string
5
5
  }
package/vite.config.js CHANGED
@@ -1,4 +1,4 @@
1
- import GenerateViteConfig from '../../generateViteConfig.js'
1
+ import GenerateViteConfig from '@cdc/core/generateViteConfig.js'
2
2
  import { moduleName } from './package.json'
3
3
 
4
4
  export default GenerateViteConfig(moduleName)
@@ -1,118 +0,0 @@
1
- import _ from 'lodash'
2
- import { Condition } from '../types/Condition'
3
- import Icon from '@cdc/core/components/ui/Icon'
4
-
5
- type OpenControls = [boolean[], Function] // useState type
6
-
7
- type CondtionsProps = {
8
- conditionControls: OpenControls
9
- conditionLookup: Record<string, string[] | number[]>
10
- conditionSettings: Condition
11
- conditionIndex: number
12
- removeCondition: Function
13
- selectedColumn: string
14
- updateConditionsList: Function
15
- }
16
-
17
- const Conditions: React.FC<CondtionsProps> = ({
18
- conditionControls,
19
- conditionLookup,
20
- conditionSettings,
21
- conditionIndex,
22
- removeCondition,
23
- selectedColumn,
24
- updateConditionsList
25
- }) => {
26
- const [openConditionControls, setOpenConditionControls] = conditionControls
27
- const showCondition = openConditionControls[conditionIndex]
28
- const setShowCondition = (index, value) => {
29
- const newOpenConditionsControls = [...openConditionControls]
30
- newOpenConditionsControls[index] = value
31
- setOpenConditionControls(newOpenConditionsControls)
32
- }
33
-
34
- const columnNames = Object.keys(conditionLookup)
35
- const columnNameConditionOptions = columnNames.filter(optionName => optionName !== selectedColumn)
36
-
37
- const { columnName, isOrIsNotEqualTo, value } = conditionSettings
38
-
39
- const handleConditionChange = (selectionValue: string | number, conditionSetting: string) => {
40
- const conditionSettingUpdate = _.cloneDeep(conditionSettings)
41
- if (conditionSetting === 'columnName') {
42
- conditionSettingUpdate['value'] = ''
43
- }
44
- conditionSettingUpdate[conditionSetting] = selectionValue
45
- updateConditionsList(conditionSettingUpdate, conditionIndex)
46
- }
47
-
48
- return !showCondition ? (
49
- <>
50
- <div className='mb-1'>
51
- <button onClick={() => setShowCondition(conditionIndex, true)}>
52
- <Icon display='caretDown' />
53
- </button>
54
- <span>
55
- {' '}
56
- {value ? `${columnName} ${isOrIsNotEqualTo === 'is' ? 'is' : 'is not'} ${value}` : 'New Condition'}
57
- </span>
58
- </div>
59
- </>
60
- ) : (
61
- <>
62
- <div className='d-flex justify-content-between'>
63
- <button
64
- onClick={() => {
65
- const newOpenConditionsControls = [...openConditionControls]
66
- newOpenConditionsControls[conditionIndex] = false
67
- setOpenConditionControls(newOpenConditionsControls)
68
- }}
69
- >
70
- <Icon display='caretDown' />
71
- </button>
72
- <button className='btn btn-warn btn-sm mt-0 ms-2' onClick={() => removeCondition(conditionIndex)}>
73
- Remove
74
- </button>
75
- </div>
76
- <div id={`condition_${conditionIndex}`}>
77
- <label className='d-block'>
78
- <span>Condition : </span>
79
- <div className='pt-1'>
80
- <select
81
- className='ms-1'
82
- value={columnName}
83
- onChange={e => handleConditionChange(e.target.value, 'columnName')}
84
- >
85
- <option value=''>Select</option>
86
- {columnNameConditionOptions?.map(columnName => (
87
- <option key={columnName} value={columnName}>
88
- {columnName}
89
- </option>
90
- ))}
91
- </select>
92
- <select
93
- className='ms-1'
94
- value={isOrIsNotEqualTo}
95
- onChange={e => handleConditionChange(e.target.value, 'isOrIsNotEqualTo')}
96
- >
97
- <option value='is'>is</option>
98
- <option value='isNot'>is not</option>
99
- </select>
100
- <select className='ms-1' value={value} onChange={e => handleConditionChange(e.target.value, 'value')}>
101
- <option value=''>Select</option>
102
-
103
- {conditionLookup[columnName]?.map(valueItem => {
104
- return (
105
- <option key={valueItem} value={valueItem}>
106
- {valueItem}
107
- </option>
108
- )
109
- })}
110
- </select>
111
- </div>
112
- </label>
113
- </div>
114
- </>
115
- )
116
- }
117
-
118
- export default Conditions