@cdc/markup-include 4.24.10 → 4.24.12

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cdc/markup-include",
3
- "version": "4.24.10",
3
+ "version": "4.24.12",
4
4
  "description": "React component for displaying HTML content from an outside link",
5
5
  "moduleName": "CdcMarkupInclude",
6
6
  "main": "dist/cdcmarkupinclude",
@@ -27,7 +27,7 @@
27
27
  "license": "Apache-2.0",
28
28
  "homepage": "https://github.com/CDCgov/cdc-open-viz#readme",
29
29
  "dependencies": {
30
- "@cdc/core": "^4.24.10",
30
+ "@cdc/core": "^4.24.12",
31
31
  "axios": "^1.6.0",
32
32
  "chroma": "0.0.1",
33
33
  "chroma-js": "^2.1.0",
@@ -39,5 +39,5 @@
39
39
  "react": "^18.2.0",
40
40
  "react-dom": "^18.2.0"
41
41
  },
42
- "gitHead": "a4d88d1bc91f596e1b0307d8e25c57ad8c668b75"
42
+ "gitHead": "347414f1da4b0e9bf2f22a7b59335deccf0b2d9c"
43
43
  }
@@ -1,4 +1,4 @@
1
- import { useEffect, useCallback, useRef, useReducer, useState } from 'react'
1
+ import { useEffect, useCallback, useRef, useReducer, useMemo } from 'react'
2
2
  import _ from 'lodash'
3
3
  // external
4
4
  import { Markup } from 'interweave'
@@ -154,17 +154,20 @@ const CdcMarkupInclude: React.FC<CdcMarkupIncludeProps> = ({
154
154
 
155
155
  const newWorkingData =
156
156
  isOrIsNotEqualTo === 'is'
157
- ? workingData.filter(dataObject => dataObject[columnName] === value)
158
- : workingData.filter(dataObject => dataObject[columnName] !== value)
157
+ ? workingData?.filter(dataObject => dataObject[columnName] === value)
158
+ : workingData?.filter(dataObject => dataObject[columnName] !== value)
159
159
 
160
160
  conditionList.shift()
161
161
  return conditionList.length === 0 ? newWorkingData : filterOutConditions(newWorkingData, conditionList)
162
162
  }
163
163
 
164
+ const emptyVariableChecker = []
165
+
164
166
  const convertVariablesInMarkup = inlineMarkup => {
165
167
  if (_.isEmpty(markupVariables)) return inlineMarkup
166
168
  const variableRegexPattern = /{{(.*?)}}/g
167
169
  const convertedInlineMarkup = inlineMarkup.replace(variableRegexPattern, variableTag => {
170
+ if (emptyVariableChecker.length > 0) return
168
171
  const workingVariable = markupVariables.filter(variable => variable.tag === variableTag)[0]
169
172
  if (workingVariable === undefined) return [variableTag]
170
173
  const workingData =
@@ -173,28 +176,33 @@ const CdcMarkupInclude: React.FC<CdcMarkupIncludeProps> = ({
173
176
  : filterOutConditions(data, [...workingVariable.conditions])
174
177
 
175
178
  const variableValues: string[] = _.uniq(
176
- (workingData || []).map(dataObject => dataObject[workingVariable.columnName])
179
+ (workingData || []).map(dataObject => {
180
+ const dataObjectValue = dataObject[workingVariable.columnName]
181
+ return workingVariable.addCommas && !isNaN(parseFloat(dataObjectValue))
182
+ ? parseFloat(dataObjectValue).toLocaleString('en-US', { useGrouping: true })
183
+ : dataObjectValue
184
+ })
177
185
  )
186
+
178
187
  const variableDisplay = []
179
188
 
180
189
  const listConjunction = !isEditor ? 'and' : 'or'
181
190
 
182
191
  const length = variableValues.length
183
192
  if (length === 2) {
184
- variableValues.push(variableValues.join(` ${listConjunction} `))
193
+ const newVariableValues = variableValues.join(` ${listConjunction} `)
194
+ variableValues.splice(0, 2, newVariableValues)
185
195
  }
186
196
  if (length > 2) {
187
197
  variableValues[length - 1] = `${listConjunction} ${variableValues[length - 1]}`
188
198
  }
189
199
  variableDisplay.push(variableValues.join(', '))
190
200
 
191
- let finalDisplay = variableDisplay[0]
201
+ const finalDisplay = variableDisplay[0]
192
202
 
193
- if (workingVariable.addCommas && !isNaN(parseFloat(finalDisplay))) {
194
- finalDisplay = parseFloat(finalDisplay)
195
- finalDisplay = finalDisplay.toLocaleString('en-US', { useGrouping: true })
203
+ if (finalDisplay === '' && contentEditor.allowHideSection) {
204
+ emptyVariableChecker.push(true)
196
205
  }
197
-
198
206
  return finalDisplay
199
207
  })
200
208
  return convertedInlineMarkup
@@ -237,23 +245,27 @@ const CdcMarkupInclude: React.FC<CdcMarkupIncludeProps> = ({
237
245
 
238
246
  const markup = useInlineHTML ? convertVariablesInMarkup(inlineHTML) : parseBodyMarkup(urlMarkup)
239
247
 
248
+ const hideMarkupInclude = contentEditor?.allowHideSection && emptyVariableChecker.length > 0 && !isEditor
249
+
240
250
  if (loading === false) {
241
251
  content = (
242
252
  <>
243
253
  {isEditor && <EditorPanel />}
244
- <Layout.Responsive isEditor={isEditor}>
245
- <div className='markup-include-content-container cove-component__content no-borders'>
246
- <div className={`markup-include-component ${contentClasses.join(' ')}`}>
247
- <Title title={title} isDashboard={isDashboard} classes={[`${theme}`, 'mb-0']} />
248
- <div className={`${innerContainerClasses.join(' ')}`}>
249
- <div className='cove-component__content-wrap'>
250
- {!markupError && <Markup allowElements={!!urlMarkup} content={markup} />}
251
- {markupError && srcUrl && <div className='warning'>{errorMessage}</div>}
254
+ {!hideMarkupInclude && (
255
+ <Layout.Responsive isEditor={isEditor}>
256
+ <div className='markup-include-content-container cove-component__content no-borders'>
257
+ <div className={`markup-include-component ${contentClasses.join(' ')}`}>
258
+ <Title title={title} isDashboard={isDashboard} classes={[`${theme}`, 'mb-0']} />
259
+ <div className={`${innerContainerClasses.join(' ')}`}>
260
+ <div className='cove-component__content-wrap'>
261
+ {!markupError && <Markup allowElements={!!urlMarkup} content={markup} />}
262
+ {markupError && srcUrl && <div className='warning'>{errorMessage}</div>}
263
+ </div>
252
264
  </div>
253
265
  </div>
254
266
  </div>
255
- </div>
256
- </Layout.Responsive>
267
+ </Layout.Responsive>
268
+ )}
257
269
  </>
258
270
  )
259
271
  }
@@ -14,7 +14,15 @@ type CondtionsProps = {
14
14
  updateConditionsList: Function
15
15
  }
16
16
 
17
- const Conditions: React.FC<CondtionsProps> = ({ conditionControls, conditionLookup, conditionSettings, conditionIndex, removeCondition, selectedColumn, updateConditionsList }) => {
17
+ const Conditions: React.FC<CondtionsProps> = ({
18
+ conditionControls,
19
+ conditionLookup,
20
+ conditionSettings,
21
+ conditionIndex,
22
+ removeCondition,
23
+ selectedColumn,
24
+ updateConditionsList
25
+ }) => {
18
26
  const [openConditionControls, setOpenConditionControls] = conditionControls
19
27
  const showCondition = openConditionControls[conditionIndex]
20
28
  const setShowCondition = (index, value) => {
@@ -43,7 +51,10 @@ const Conditions: React.FC<CondtionsProps> = ({ conditionControls, conditionLook
43
51
  <button onClick={() => setShowCondition(conditionIndex, true)}>
44
52
  <Icon display='caretDown' />
45
53
  </button>
46
- <span> {value ? `${columnName} ${isOrIsNotEqualTo === 'is' ? 'is' : 'is not'} ${value}` : 'New Condition'}</span>
54
+ <span>
55
+ {' '}
56
+ {value ? `${columnName} ${isOrIsNotEqualTo === 'is' ? 'is' : 'is not'} ${value}` : 'New Condition'}
57
+ </span>
47
58
  </div>
48
59
  </>
49
60
  ) : (
@@ -58,7 +69,7 @@ const Conditions: React.FC<CondtionsProps> = ({ conditionControls, conditionLook
58
69
  >
59
70
  <Icon display='caretDown' />
60
71
  </button>
61
- <button className='btn btn-danger btn-sm mt-0 ml-2' onClick={() => removeCondition(conditionIndex)}>
72
+ <button className='btn btn-warn btn-sm mt-0 ml-2' onClick={() => removeCondition(conditionIndex)}>
62
73
  Remove
63
74
  </button>
64
75
  </div>
@@ -66,7 +77,11 @@ const Conditions: React.FC<CondtionsProps> = ({ conditionControls, conditionLook
66
77
  <label className='d-block'>
67
78
  <span>Condition : </span>
68
79
  <div className='pt-1'>
69
- <select className='ml-1' value={columnName} onChange={e => handleConditionChange(e.target.value, 'columnName')}>
80
+ <select
81
+ className='ml-1'
82
+ value={columnName}
83
+ onChange={e => handleConditionChange(e.target.value, 'columnName')}
84
+ >
70
85
  <option value=''>Select</option>
71
86
  {columnNameConditionOptions?.map(columnName => (
72
87
  <option key={columnName} value={columnName}>
@@ -74,7 +89,11 @@ const Conditions: React.FC<CondtionsProps> = ({ conditionControls, conditionLook
74
89
  </option>
75
90
  ))}
76
91
  </select>
77
- <select className='ml-1' value={isOrIsNotEqualTo} onChange={e => handleConditionChange(e.target.value, 'isOrIsNotEqualTo')}>
92
+ <select
93
+ className='ml-1'
94
+ value={isOrIsNotEqualTo}
95
+ onChange={e => handleConditionChange(e.target.value, 'isOrIsNotEqualTo')}
96
+ >
78
97
  <option value='is'>is</option>
79
98
  <option value='isNot'>is not</option>
80
99
  </select>
@@ -23,13 +23,26 @@ import Accordion from '@cdc/core/components/ui/Accordion'
23
23
  import '@cdc/core/styles/v2/components/editor.scss'
24
24
  import './editorPanel.style.css'
25
25
  import VariableSection from './Variables'
26
+ import { CheckBox } from '@cdc/core/components/EditorPanel/Inputs'
26
27
 
27
- const headerColors = ['theme-blue', 'theme-purple', 'theme-brown', 'theme-teal', 'theme-pink', 'theme-orange', 'theme-slate', 'theme-indigo', 'theme-cyan', 'theme-green', 'theme-amber']
28
+ const headerColors = [
29
+ 'theme-blue',
30
+ 'theme-purple',
31
+ 'theme-brown',
32
+ 'theme-teal',
33
+ 'theme-pink',
34
+ 'theme-orange',
35
+ 'theme-slate',
36
+ 'theme-indigo',
37
+ 'theme-cyan',
38
+ 'theme-green',
39
+ 'theme-amber'
40
+ ]
28
41
 
29
42
  const EditorPanel: React.FC = () => {
30
43
  const { config, data, isDashboard, loading, setParentConfig, updateConfig } = useContext(ConfigContext)
31
44
  const { contentEditor, theme, visual } = config
32
- const { inlineHTML, markupVariables, srcUrl, title, useInlineHTML } = contentEditor
45
+ const { inlineHTML, markupVariables, srcUrl, title, useInlineHTML, allowHideSection } = contentEditor
33
46
  const [displayPanel, setDisplayPanel] = useState(true)
34
47
  const updateField = updateFieldFactory(config, updateConfig, true)
35
48
  const hasData = data?.[0] !== undefined ?? false
@@ -111,17 +124,40 @@ const EditorPanel: React.FC = () => {
111
124
  const editorContent = (
112
125
  <Accordion>
113
126
  <Accordion.Section title='General'>
114
- <InputText value={title || ''} section='contentEditor' fieldName='title' label='Title' placeholder='Markup Include Title' updateField={updateField} />
127
+ <InputText
128
+ value={title || ''}
129
+ section='contentEditor'
130
+ fieldName='title'
131
+ label='Title'
132
+ placeholder='Markup Include Title'
133
+ updateField={updateField}
134
+ />
115
135
  </Accordion.Section>
116
136
  <Accordion.Section title='Content Editor'>
117
137
  <span className='divider-heading'>Enter Markup</span>
118
- <InputCheckbox inline value={useInlineHTML} section='contentEditor' fieldName='useInlineHTML' label='Use Inline HTML&nbsp;' updateField={updateField} />
138
+ <InputCheckbox
139
+ inline
140
+ value={useInlineHTML}
141
+ section='contentEditor'
142
+ fieldName='useInlineHTML'
143
+ label='Use Inline HTML&nbsp;'
144
+ updateField={updateField}
145
+ />
119
146
  <div className='column-edit'>
120
147
  {useInlineHTML ? (
121
148
  <>
122
149
  {/* HTML Textbox */}
123
150
  <div ref={textAreaInEditorContainer}>
124
- <InputText value={inlineHTML} section='contentEditor' fieldName='inlineHTML' label='HTML' placeholder='Add HTML here' type='textarea' rows={10} updateField={updateField} />
151
+ <InputText
152
+ value={inlineHTML}
153
+ section='contentEditor'
154
+ fieldName='inlineHTML'
155
+ label='HTML'
156
+ placeholder='Add HTML here'
157
+ type='textarea'
158
+ rows={10}
159
+ updateField={updateField}
160
+ />
125
161
 
126
162
  <hr className='accordion__divider' />
127
163
  </div>
@@ -140,23 +176,69 @@ const EditorPanel: React.FC = () => {
140
176
  </Tooltip>
141
177
  </span>
142
178
  </label>
143
- {hasData === false && <span className='need-data-source-prompt'>To use variables, add data source.</span>}
179
+ {hasData === false && (
180
+ <span className='need-data-source-prompt'>To use variables, add data source.</span>
181
+ )}
144
182
  {variableArray && variableArray.length > 0 && (
145
183
  <div className='section-border'>
146
184
  {variableArray?.map((variableObject, index) => {
147
- return <VariableSection key={`${variableObject.name}-${index}`} controls={openVariableControls} data={data} deleteVariable={deleteVariable} updateVariableArray={updateVariableArray} variableConfig={variableObject} variableIndex={index} />
185
+ return (
186
+ <VariableSection
187
+ key={`${variableObject.name}-${index}`}
188
+ controls={openVariableControls}
189
+ data={data}
190
+ deleteVariable={deleteVariable}
191
+ updateVariableArray={updateVariableArray}
192
+ variableConfig={variableObject}
193
+ variableIndex={index}
194
+ />
195
+ )
148
196
  })}
149
197
  </div>
150
198
  )}
199
+ <div className='pt-2'>
200
+ <CheckBox
201
+ value={allowHideSection}
202
+ section='contentEditor'
203
+ fieldName='allowHideSection'
204
+ label='Hide Section on Null'
205
+ updateField={updateField}
206
+ tooltip={
207
+ <Tooltip style={{ textTransform: 'none' }}>
208
+ <Tooltip.Target>
209
+ <Icon
210
+ display='question'
211
+ style={{ marginLeft: '0.5rem', display: 'inline-block', whiteSpace: 'nowrap' }}
212
+ />
213
+ </Tooltip.Target>
214
+ <Tooltip.Content>
215
+ <p>{`Hide this entire Markup Include section if any variable is null or blank.`}</p>
216
+ </Tooltip.Content>
217
+ </Tooltip>
218
+ }
219
+ />
220
+ </div>
221
+
151
222
  <div className='mb-1 d-flex'>
152
- <button className={'btn btn-primary'} onClick={handleCreateNewVariableButtonClick} disabled={!hasData}>
223
+ <button
224
+ className={'btn btn-primary'}
225
+ onClick={handleCreateNewVariableButtonClick}
226
+ disabled={!hasData}
227
+ >
153
228
  Create New Variable
154
229
  </button>
155
230
  </div>
156
231
  </fieldset>
157
232
  </>
158
233
  ) : (
159
- <InputText value={srcUrl || ''} section='contentEditor' fieldName='srcUrl' label='Source URL;' placeholder='https://www.example.com/file.html' updateField={updateField} />
234
+ <InputText
235
+ value={srcUrl || ''}
236
+ section='contentEditor'
237
+ fieldName='srcUrl'
238
+ label='Source URL;'
239
+ placeholder='https://www.example.com/file.html'
240
+ updateField={updateField}
241
+ />
160
242
  )}
161
243
  </div>
162
244
  </Accordion.Section>
@@ -177,11 +259,41 @@ const EditorPanel: React.FC = () => {
177
259
  </ul>
178
260
  </div>
179
261
  <div className='cove-accordion__panel-section checkbox-group'>
180
- <InputCheckbox value={visual.border} section='visual' fieldName='border' label='Display Border&nbsp;' updateField={updateField} />
181
- <InputCheckbox value={visual.borderColorTheme} section='visual' fieldName='borderColorTheme' label='Use Border Color Theme&nbsp;' updateField={updateField} />
182
- <InputCheckbox value={visual.accent} section='visual' fieldName='accent' label='Use Accent Style&nbsp;' updateField={updateField} />
183
- <InputCheckbox value={visual.background} section='visual' fieldName='background' label='Use Theme Background Color&nbsp;' updateField={updateField} />
184
- <InputCheckbox value={visual.hideBackgroundColor} section='visual' fieldName='hideBackgroundColor' label='Hide Background Color&nbsp;' updateField={updateField} />
262
+ <InputCheckbox
263
+ value={visual.border}
264
+ section='visual'
265
+ fieldName='border'
266
+ label='Display Border&nbsp;'
267
+ updateField={updateField}
268
+ />
269
+ <InputCheckbox
270
+ value={visual.borderColorTheme}
271
+ section='visual'
272
+ fieldName='borderColorTheme'
273
+ label='Use Border Color Theme&nbsp;'
274
+ updateField={updateField}
275
+ />
276
+ <InputCheckbox
277
+ value={visual.accent}
278
+ section='visual'
279
+ fieldName='accent'
280
+ label='Use Accent Style&nbsp;'
281
+ updateField={updateField}
282
+ />
283
+ <InputCheckbox
284
+ value={visual.background}
285
+ section='visual'
286
+ fieldName='background'
287
+ label='Use Theme Background Color&nbsp;'
288
+ updateField={updateField}
289
+ />
290
+ <InputCheckbox
291
+ value={visual.hideBackgroundColor}
292
+ section='visual'
293
+ fieldName='hideBackgroundColor'
294
+ label='Hide Background Color&nbsp;'
295
+ updateField={updateField}
296
+ />
185
297
  </div>
186
298
  </Accordion.Section>
187
299
  </Accordion>
@@ -191,7 +303,12 @@ const EditorPanel: React.FC = () => {
191
303
 
192
304
  return (
193
305
  <ErrorBoundary component='EditorPanel'>
194
- <Layout.Sidebar displayPanel={displayPanel} isDashboard={isDashboard} title={'Configure Markup Include'} onBackClick={onBackClick}>
306
+ <Layout.Sidebar
307
+ displayPanel={displayPanel}
308
+ isDashboard={isDashboard}
309
+ title={'Configure Markup Include'}
310
+ onBackClick={onBackClick}
311
+ >
195
312
  {editorContent}
196
313
  </Layout.Sidebar>
197
314
  </ErrorBoundary>