@worksafevictoria/wcl7.5 1.17.0-beta.10 → 1.17.0-beta.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.
Files changed (31) hide show
  1. package/package.json +1 -1
  2. package/src/components/Containers/SectionGroup/index.vue +0 -1
  3. package/src/components/Paragraphs/RTWPlanner/Injuries/index.vue +7 -1
  4. package/src/components/Paragraphs/RTWPlanner/Planners/PlannerNameModal.vue +56 -0
  5. package/src/components/SubComponents/FormInstance/models/base-form-element.js +4 -3
  6. package/src/components/SubComponents/FormInstance/services/form-render-parser.js +51 -16
  7. package/src/components/SubComponents/FormInstance/services/logic-parser.js +81 -9
  8. package/src/components/SubComponents/FormInstance/services/registry-factory.js +52 -50
  9. package/src/components/SubComponents/FormInstance/stories/mocks/checkboxesother.json +1 -10
  10. package/src/components/SubComponents/FormInstance/stories/mocks/emailconfirm.json +1 -10
  11. package/src/components/SubComponents/FormInstance/stories/mocks/jahd.json +1 -5
  12. package/src/components/SubComponents/FormInstance/stories/mocks/quad.json +1 -5
  13. package/src/components/SubComponents/FormInstance/stories/mocks/radiosother.json +1 -9
  14. package/src/components/SubComponents/FormInstance/stories/mocks/sameas.json +1 -5
  15. package/src/components/SubComponents/FormInstance/stories/mocks/selectother.json +1 -10
  16. package/src/components/SubComponents/FormInstance/stories/mocks/styles.json +1 -5
  17. package/src/components/SubComponents/FormInstance/stories/mocks/table-select.json +1 -15
  18. package/src/components/SubComponents/FormInstance/stories/mocks/token.json +1 -5
  19. package/src/components/SubComponents/FormInstance/stories/mocks/twig.json +1 -13
  20. package/src/components/SubComponents/FormInstance/stories/mocks/wizard.json +1 -13
  21. package/src/components/SubComponents/FormInstance/tests/form-test-utils.js +3 -0
  22. package/src/components/SubComponents/FormInstance/tests/form.test.js +2 -1
  23. package/src/components/SubComponents/FormInstance/tests/radiosother.test.js +12 -11
  24. package/src/components/SubComponents/FormInstance/tests/rule-disabled.test.js +13 -45
  25. package/src/components/SubComponents/FormInstance/tests/rule-enabled-value.test.js +8 -24
  26. package/src/components/SubComponents/FormInstance/tests/rule-hidden.test.js +13 -45
  27. package/src/components/SubComponents/FormInstance/tests/rule-required-value.test.js +15 -55
  28. package/src/components/SubComponents/FormInstance/tests/rule-visible.test.js +0 -413
  29. package/src/components/SubComponents/FormInstance/tests/sameas.test.js +9 -25
  30. package/src/components/SubComponents/FormInstance/tests/twig.test.js +7 -5
  31. package/src/index.js +6 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@worksafevictoria/wcl7.5",
3
- "version": "1.17.0-beta.10",
3
+ "version": "1.17.0-beta.12",
4
4
  "description": "WorkSafe Victoria Component Library - GitHub Actions Migration Test",
5
5
  "main": "src/index.js",
6
6
  "license": "MIT",
@@ -181,7 +181,6 @@ export default {
181
181
  }
182
182
  if (this.backgroundVariant) {
183
183
  let bgColour
184
- console.log('this.backgroundVariant:-', this.backgroundVariant)
185
184
  switch (this.backgroundVariant) {
186
185
  case 'grey':
187
186
  case 'light':
@@ -8,6 +8,7 @@ import CardGroup from './../../../SubComponents/CardGroup/index.vue'
8
8
  import Breadcrumb from './../../../SubComponents/Breadcrumb/index.vue'
9
9
  import RichText from './../../RichText/index.vue'
10
10
  import SelectableCards from './../../SelectableCards/index.vue'
11
+ import PlannerNameModal from './../Planners/PlannerNameModal.vue'
11
12
 
12
13
  const props = defineProps({
13
14
  injuryPage: {
@@ -46,6 +47,7 @@ const props = defineProps({
46
47
 
47
48
  const screen = ref(1)
48
49
  const selectedCard = ref(null)
50
+ const showModal = ref(false)
49
51
 
50
52
  // local copy of breadcrumb items allowed to mutate
51
53
  const breadcrumbItemsLocal = ref([...props.breadcrumbItems])
@@ -87,7 +89,9 @@ function onCrumbClick({ index }) {
87
89
  // you can add logic for index === 1 here, or just leave it as no-op.
88
90
  }
89
91
 
90
- function nextScreenAgent() {}
92
+ function nextScreenAgent(card) {
93
+ showModal.value = true
94
+ }
91
95
  </script>
92
96
 
93
97
  <template>
@@ -172,6 +176,8 @@ function nextScreenAgent() {}
172
176
  @nextScreen="nextScreenAgent"
173
177
  />
174
178
  </div>
179
+
180
+ <PlannerNameModal class="injuries-app__new-planner" v-model="showModal" />
175
181
  </div>
176
182
  </template>
177
183
 
@@ -0,0 +1,56 @@
1
+ <script setup>
2
+ import { computed, ref } from 'vue'
3
+ import { BModal, BFormInput } from 'bootstrap-vue-next'
4
+ import CtaButton from './../../../SubComponents/CtaButton/index.vue'
5
+
6
+ const inputValue = ref('')
7
+
8
+ function handleSubmit() {
9
+ console.log('handle Submit', inputValue.value)
10
+ if (!inputValue.value.trim()) return
11
+ }
12
+ </script>
13
+
14
+ <template>
15
+ <b-modal
16
+ aria-labelledby="injuries-app__modal"
17
+ no-close-on-backdrop
18
+ centered
19
+ no-footer
20
+ size="lg"
21
+ >
22
+ <template #default="{ close }">
23
+ <div class="p-3">
24
+ <h3 class="fw-bold mb-3 modal-title__new-planner">Name your planner</h3>
25
+ <p class="mb-2 modal-description__new-planner">
26
+ Give your planner a name so you can easily find it and pick up where
27
+ you left off.
28
+ </p>
29
+
30
+ <label for="modal2CB" class="fw-bold mb-4">
31
+ Injured workers first name
32
+ </label>
33
+
34
+ <BFormInput
35
+ id="modal2CB"
36
+ name="modal2CB"
37
+ placeholder=""
38
+ v-model="inputValue"
39
+ class="mb-4 input__new-planner"
40
+ />
41
+
42
+ <CtaButton ref="calNextBtn" @click="handleSubmit">Next</CtaButton>
43
+ </div>
44
+ </template>
45
+ </b-modal>
46
+ </template>
47
+
48
+ <style lang="scss" scoped>
49
+ :deep(.modal-description__new-planner) {
50
+ width: 65%;
51
+ }
52
+
53
+ :deep(.input__new-planner) {
54
+ width: 60%;
55
+ }
56
+ </style>
@@ -54,7 +54,7 @@ export class BaseFormElement {
54
54
  getLabelPosition() {
55
55
  return this.getPosition(
56
56
  this.webformElement['#_title_display'] ??
57
- this.webformElement['#title_display']
57
+ this.webformElement['#title_display'],
58
58
  )
59
59
  }
60
60
 
@@ -160,7 +160,7 @@ export class BaseFormElement {
160
160
  label: getStyle(this.webformElement['#label_attributes']),
161
161
  wrapper: getStyle(this.webformElement['#wrapper_attributes']),
162
162
  element: getStyle(this.webformElement['#attributes']),
163
- additional: this.getAdditionalStyles(this.getCustomClass())
163
+ additional: this.getAdditionalStyles(this.getCustomClass()),
164
164
  }
165
165
  const hasOverride = Object.values(style).some((attr) => !this.isEmpty(attr))
166
166
  return hasOverride ? style : undefined
@@ -251,7 +251,8 @@ export class BaseFormElement {
251
251
  if (this.isEmpty(this.webformElement['#states'])) {
252
252
  return undefined
253
253
  } else {
254
- return parseElementStates(this.webformElement)
254
+ // NEW: Pass the current instance (`this`) to the parser.
255
+ return parseElementStates(this.webformElement, this)
255
256
  }
256
257
  }
257
258
 
@@ -3,6 +3,39 @@ import { converFormIOElementToJSON } from './convert-form-element'
3
3
  import { updateConditionWithFormReferences } from './logic-linker'
4
4
  import { RegisterFactory } from './registry-factory'
5
5
 
6
+ function extractWebformKeys(webformObject) {
7
+ const result = []
8
+
9
+ const isElement = (obj) => obj && typeof obj === 'object' && obj['#type']
10
+
11
+ const extract = (obj) => {
12
+ if (!obj || typeof obj !== 'object') return null
13
+
14
+ const type = obj['#type']
15
+
16
+ const key = obj['#webform_key'] || null
17
+ const node = key ? { key, children: [], type } : null
18
+
19
+ for (const [childKey, val] of Object.entries(obj)) {
20
+ if (childKey.startsWith('#')) continue
21
+ if (isElement(val)) {
22
+ const childNode = extract(val)
23
+ if (childNode && node) node.children.push(childNode)
24
+ else if (childNode) return childNode
25
+ }
26
+ }
27
+
28
+ return node
29
+ }
30
+
31
+ for (const [topKey, val] of Object.entries(webformObject)) {
32
+ if (typeof val === 'object' && val['#type']) {
33
+ const topNode = extract(val)
34
+ if (topNode) result.push(topNode)
35
+ }
36
+ }
37
+ return result
38
+ }
6
39
  export class FormRenderParser {
7
40
  initialise(contentApiUrl, isPreview) {
8
41
  this.formSettingsMeta = { contentApiUrl }
@@ -17,14 +50,16 @@ export class FormRenderParser {
17
50
  const formlogicList = []
18
51
  try {
19
52
  webform = this.preProcessWebForm(webform)
53
+ const pathTree = extractWebformKeys(webform)
20
54
  const formiodefinition = {
21
55
  id: webform['#id'],
22
56
  components: this.parseFormContainerComponents(
23
57
  webform,
24
58
  webFormElementTree,
25
59
  null,
26
- formlogicList
27
- )
60
+ formlogicList,
61
+ pathTree,
62
+ ),
28
63
  }
29
64
 
30
65
  options.breadcrumbSettings = { clickable: false }
@@ -35,14 +70,12 @@ export class FormRenderParser {
35
70
 
36
71
  formiodefinition.display = this.getDisplay(webFormElementTree)
37
72
  if (this.isPreview) {
38
- console.log('drupal webform', webform)
39
- console.log('formio definition', formiodefinition)
40
73
  }
41
74
  return {
42
75
  definition: formiodefinition,
43
76
  tree: webFormElementTree,
44
77
  options,
45
- css
78
+ css,
46
79
  }
47
80
  } catch (e) {
48
81
  console.error(e)
@@ -54,7 +87,8 @@ export class FormRenderParser {
54
87
  container,
55
88
  webFormElementTree,
56
89
  parent,
57
- formlogicList
90
+ formlogicList,
91
+ tree,
58
92
  ) => {
59
93
  return Object.keys(container)
60
94
  .filter((i) => !i.startsWith('#'))
@@ -63,11 +97,12 @@ export class FormRenderParser {
63
97
  return RegisterFactory.getFormIOElement(
64
98
  webFormElement,
65
99
  this.formSettingsMeta,
66
- parent
100
+ parent,
101
+ tree,
67
102
  )
68
103
  })
69
104
  .filter(
70
- (formIOElement) => !!formIOElement && formIOElement.isRenderable()
105
+ (formIOElement) => !!formIOElement && formIOElement.isRenderable(),
71
106
  )
72
107
  .map((formIOElement) => {
73
108
  // nested form logic
@@ -78,11 +113,11 @@ export class FormRenderParser {
78
113
  subContainer,
79
114
  webFormElementTree,
80
115
  formIOElement,
81
- formlogicList
82
- )
116
+ formlogicList,
117
+ tree,
118
+ ),
83
119
  )
84
120
  }
85
-
86
121
  return formIOElement
87
122
  })
88
123
  .map((formIOElement) => {
@@ -90,7 +125,7 @@ export class FormRenderParser {
90
125
  webFormElementTree[formIOElement.getKey()] = formIOElement
91
126
  const formioElementJSON = converFormIOElementToJSON(
92
127
  formIOElement,
93
- formlogicList
128
+ formlogicList,
94
129
  ).json
95
130
  formIOElement.setFormIOdefinitionForElement(formioElementJSON)
96
131
  return formioElementJSON
@@ -103,7 +138,7 @@ export class FormRenderParser {
103
138
  webform.actions = {
104
139
  '#type': 'webform_actions',
105
140
  '#webform_id': 'form--actions',
106
- '#webform_key': 'actions'
141
+ '#webform_key': 'actions',
107
142
  }
108
143
  }
109
144
  return webform
@@ -115,8 +150,8 @@ export class FormRenderParser {
115
150
  updateConditionWithFormReferences(
116
151
  logic,
117
152
  sourceElement,
118
- webFormElementTree
119
- )
153
+ webFormElementTree,
154
+ ),
120
155
  )
121
156
  })
122
157
  }
@@ -146,7 +181,7 @@ export class FormRenderParser {
146
181
 
147
182
  getDisplay(webFormElementTree) {
148
183
  const pageKeys = Object.keys(webFormElementTree).filter((elementKey) =>
149
- webFormElementTree[elementKey].isPageComponent()
184
+ webFormElementTree[elementKey].isPageComponent(),
150
185
  )
151
186
  if (pageKeys.length > 0) {
152
187
  return 'wizard'
@@ -4,7 +4,7 @@ import {
4
4
  isEmpty,
5
5
  } from '../models/form-utils'
6
6
 
7
- export function parseElementStates(webformElement) {
7
+ export function parseElementStates(webformElement, elementInstance) {
8
8
  const states = webformElement['#states'] || {}
9
9
  let logicList = []
10
10
  Object.keys(states)
@@ -21,9 +21,13 @@ export function parseElementStates(webformElement) {
21
21
  const state = states[sourceKey]
22
22
  let conditonal = `result = (`
23
23
  if (Array.isArray(state)) {
24
- state.forEach((rule) => (conditonal += ruleToString(rule, conditonal)))
24
+ // Pass instance to ruleToString
25
+ state.forEach((rule) => {
26
+ return (conditonal += ruleToString(rule, elementInstance, conditonal))
27
+ })
25
28
  } else {
26
- conditonal += ruleToString(state, conditonal)
29
+ // Pass instance to ruleToString
30
+ conditonal += ruleToString(state, elementInstance, conditonal)
27
31
  }
28
32
  conditonal += ')'
29
33
  logic.trigger.javascript = conditonal
@@ -54,10 +58,14 @@ function getLogicBasedOnCondition(elementCondition) {
54
58
  return null
55
59
  }
56
60
 
57
- function ruleToString(rule) {
61
+ function ruleToString(rule, elementInstance) {
58
62
  if (typeof rule === 'object') {
59
63
  const conditions = Object.keys(rule).reduce((items, ruleKey) => {
60
- const condition = ruleItemToString(rule[ruleKey], ruleKey)
64
+ const condition = ruleItemToString(
65
+ rule[ruleKey],
66
+ ruleKey,
67
+ elementInstance,
68
+ )
61
69
  if (!isEmpty(condition)) {
62
70
  items.push(condition)
63
71
  }
@@ -74,7 +82,7 @@ function ruleToString(rule) {
74
82
  return ''
75
83
  }
76
84
 
77
- function ruleItemToString(ruleItem, itemKey) {
85
+ function ruleItemToString(ruleItem, itemKey, elementInstance) {
78
86
  // Regex 1: Matches standard selectors (name="foo"). Captures 'foo'.
79
87
  const standardMatch = itemKey.match(/name="([^"]+)"/)
80
88
  // Regex 2: Matches array selectors (name="foo[bar]"). Captures 'foo' and 'bar'.
@@ -98,7 +106,13 @@ function ruleItemToString(ruleItem, itemKey) {
98
106
  const conditions = Object.keys(ruleItem)
99
107
  .map((elementProp) =>
100
108
  formComponentID
101
- ? getTrigger(formComponentID, ruleItem, elementProp, checkboxOptionKey)
109
+ ? getTrigger(
110
+ formComponentID,
111
+ ruleItem,
112
+ elementProp,
113
+ checkboxOptionKey,
114
+ elementInstance,
115
+ )
102
116
  : null,
103
117
  )
104
118
  .filter((trigger) => !!trigger)
@@ -143,12 +157,29 @@ function createNewLogic(actionName, actionValue) {
143
157
  }
144
158
  }
145
159
 
146
- function getTrigger(formComponentID, ruleItem, prop, checkboxOptionKey = null) {
160
+ function getTrigger(
161
+ formComponentID,
162
+ ruleItem,
163
+ prop,
164
+ checkboxOptionKey = null,
165
+ elementInstance,
166
+ ) {
147
167
  if (ruleItem.hasOwnProperty(prop)) {
148
168
  const value = ruleItem[prop] ?? ''
149
169
 
150
170
  let variable = `data.{${formComponentID}}`
151
- console.log('🚀 ~ getTrigger ~ variable:', variable)
171
+
172
+ try {
173
+ if (elementInstance && Array.isArray(elementInstance.tree)) {
174
+ const path = findPathInTree(elementInstance.tree, formComponentID)
175
+ if (path && path.length > 0) {
176
+ variable = buildDataAccessor(path, 'data')
177
+ }
178
+ }
179
+ } catch (e) {
180
+ let variable = `data.{${formComponentID}}`
181
+ }
182
+
152
183
  let valueDelimeter = typeof value === 'string' ? "'" : ''
153
184
  let expression = `${valueDelimeter}${value}${valueDelimeter}`
154
185
 
@@ -203,3 +234,44 @@ function getTrigger(formComponentID, ruleItem, prop, checkboxOptionKey = null) {
203
234
  }
204
235
  return null
205
236
  }
237
+
238
+ function findPathInTree(tree, targetKey) {
239
+ if (!Array.isArray(tree) || !targetKey) return null
240
+
241
+ function dfs(nodes, path) {
242
+ for (const node of nodes) {
243
+ if (!node) continue
244
+ const nodeKey = node.key
245
+ const newPath =
246
+ nodeKey && node.type !== 'webform_wizard_page'
247
+ ? path.concat(nodeKey)
248
+ : path
249
+ if (nodeKey === targetKey) return newPath
250
+ if (Array.isArray(node.children) && node.children.length > 0) {
251
+ const found = dfs(node.children, newPath)
252
+ if (found) return found
253
+ }
254
+ }
255
+ return null
256
+ }
257
+
258
+ return dfs(tree, [])
259
+ }
260
+
261
+ function isIdentifier(key) {
262
+ return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(String(key))
263
+ }
264
+
265
+ function buildDataAccessor(pathArray, rootName = 'data') {
266
+ if (!Array.isArray(pathArray) || pathArray.length === 0) return rootName
267
+ const parts = []
268
+ for (const key of pathArray) {
269
+ if (isIdentifier(key)) {
270
+ parts.push('.' + key)
271
+ } else {
272
+ const escaped = String(key).replace(/'/g, "\\'")
273
+ parts.push(`['${escaped}']`)
274
+ }
275
+ }
276
+ return rootName + parts.join('')
277
+ }