@worksafevictoria/wcl7.5 1.1.0-beta.1 → 1.1.0-beta.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.
Files changed (35) hide show
  1. package/.storybook/main.js +4 -2
  2. package/.storybook/preview.js +5 -0
  3. package/ci/build/build_validation.yml +2 -0
  4. package/package.json +3 -1
  5. package/src/components/Common/CardGridItem/card-grid-item-icon.vue +1 -1
  6. package/src/components/Common/CardGridItem/index.vue +9 -3
  7. package/src/components/Global/AppHeader/ModalSearch/index.vue +6 -1
  8. package/src/components/Global/AppHeader/index.stories.js +16 -24
  9. package/src/components/Global/AppHeader/index.vue +9 -8
  10. package/src/components/Paragraphs/Chart/Constants.js +4790 -0
  11. package/src/components/Paragraphs/Chart/index.mdx +61 -0
  12. package/src/components/Paragraphs/Chart/index.stories.js +31 -0
  13. package/src/components/Paragraphs/Chart/index.vue +331 -0
  14. package/src/components/Paragraphs/ListGroup/Link/list-link.stories.js +34 -39
  15. package/src/components/Paragraphs/ListGroup/list-group.stories.js +34 -31
  16. package/src/components/Paragraphs/ListGroup/navigation-card.stories.js +33 -30
  17. package/src/components/Paragraphs/RelatedInformation/index.stories.js +5 -23
  18. package/src/components/Paragraphs/RelatedInformation/index.vue +12 -6
  19. package/src/components/Paragraphs/RelatedInformation/styles.scss +1 -3
  20. package/src/components/Paragraphs/ScrollSpy/index.stories.js +18 -26
  21. package/src/components/Paragraphs/ScrollSpy/index.vue +2 -1
  22. package/src/components/Paragraphs/TaskFinder/index.stories.js +10 -33
  23. package/src/components/Paragraphs/TaskFinder/pdf/index.vue +1 -1
  24. package/src/components/Paragraphs/TextMedia/index.stories.js +12 -61
  25. package/src/components/Paragraphs/VideoGrid/index.stories.js +16 -32
  26. package/src/components/SubComponents/FormInstance/index.vue +3 -1
  27. package/src/components/SubComponents/Search/GoogleREST/index.stories.js +50 -0
  28. package/src/components/SubComponents/Search/GoogleSearch/index.stories.js +23 -0
  29. package/src/components/SubComponents/Search/SearchListing/index.vue +69 -9
  30. package/src/components/SubComponents/Search/index.stories.js +19 -16
  31. package/src/components/SubComponents/Search/index.vue +563 -59
  32. package/src/includes/scss/vars/src/colors.scss +29 -1
  33. package/src/index.js +42 -40
  34. package/src/components/SubComponents/GoogleSearch/index.stories.js +0 -8
  35. package/src/components/SubComponents/GoogleSearch/index.vue +0 -405
@@ -0,0 +1,61 @@
1
+ import { Canvas, Meta } from '@storybook/blocks';
2
+
3
+ import * as ChartStories from './index.stories';
4
+
5
+ <Meta of={ChartStories} />
6
+ # Charts
7
+
8
+ Charts support links
9
+
10
+ * [vue-google-charts](https://github.com/devstark-com/vue-google-charts "Package") (package documentation)
11
+ * [Google-chart](https://developers.google.com/chart/ "Google charts") (customisation documentation)
12
+
13
+ <Canvas of={ChartStories.Default} />
14
+
15
+ ## Chart options
16
+
17
+ Visit Google-chart documentation for chart options.
18
+
19
+ ```tsx
20
+ options: {
21
+ title: 'graph',
22
+ pieSliceText: 'value',
23
+ is3D: true,
24
+ height: 600,
25
+ chartArea: { top: 20, bottom: 20 },
26
+ vAxis: { minValue: 0 },
27
+ animation: {
28
+ duration: 1000,
29
+ easing: 'out'
30
+ },
31
+ colors: [
32
+ '#3d3c36',
33
+ colors.orange100,
34
+ ]
35
+ }
36
+ ```
37
+
38
+ ## Chart filters
39
+
40
+ Filtering options. These are passed to 'directory-filters' component.
41
+
42
+ ```tsx
43
+ [
44
+ { record_id: 'DEATH_DATE', name: 'Year', date: true }, // Primary
45
+ { record_id: 'GENDER', name: 'Gender' }, // Secondary
46
+ { record_id: 'AGE_RANGE', name: 'Age range' },
47
+ { record_id: 'CATEGORY', name: 'Category' },
48
+ { record_id: 'INDUSTRY', name: 'Industry' },
49
+ { record_id: 'SIZE_', name: 'Size of Organisation' }
50
+ ]
51
+ ```
52
+
53
+ ## Filtering
54
+
55
+ Currently three filters are available for generating charts
56
+
57
+ **'primary':** Compare by Primary field (first in array)
58
+
59
+ **'months':** Incremental view (Requires date as Primary filter)
60
+
61
+ **'compare':** Compare Primary field with chosen field (default secondary)
@@ -0,0 +1,31 @@
1
+ import Chart from './index.vue'
2
+ import {
3
+ chart, filterFields, statsData
4
+ } from './Constants'
5
+ export default {
6
+ title: 'Paragraphs/Chart',
7
+ component: Chart,
8
+ }
9
+ export const Default = {
10
+ argTypes: {
11
+ "chart.type": {
12
+ control: "radio",
13
+ options: ["BarChart", "PieChart", "ColumnChart", "Table", "LineChart", "AreaChart", "BubbleChart", "ScatterChart"],
14
+ },
15
+ "chart.filter": {
16
+ control: "radio",
17
+ options: ["primary", "months", "compare"],
18
+ },
19
+ },
20
+ args: {
21
+ filterFields: filterFields,
22
+ chart: chart,
23
+ statsData: statsData
24
+ },
25
+ parameters: {
26
+ deepControls: { enabled: true },
27
+ },
28
+ }
29
+
30
+
31
+
@@ -0,0 +1,331 @@
1
+ <template>
2
+ <container>
3
+ <row>
4
+ <column class="pb-5">
5
+ <single-taxonomy
6
+ v-for="(t, i) in computedPropFilters"
7
+ :key="i"
8
+ :ref="`${t.record_id}`"
9
+ :data="t"
10
+ :results="filteredList.length"
11
+ :loading="isFiltering"
12
+ class="wcl-directory-filters__filterButton"
13
+ @onFilter="onFilter"
14
+ />
15
+ <filter-button
16
+ v-if="!hideReset"
17
+ :is-reset="true"
18
+ class="wcl-directory-filters__filterButton"
19
+ @clicked="reset"
20
+ />
21
+ </column>
22
+ </row>
23
+ <row>
24
+ <column>
25
+ <div>
26
+ <b-form-group
27
+ v-show="chart.filter === 'compare'"
28
+ label="Compare by:"
29
+ label-for="compare"
30
+ >
31
+ <b-form-select
32
+ id="compare"
33
+ v-model="graphSelected"
34
+ class="mb-1 mt-1"
35
+ :options="graphOptions"
36
+ ></b-form-select>
37
+ </b-form-group>
38
+ <g-chart
39
+ :type="filteredList.length > 0 ? chart.type : 'ColumnChart'"
40
+ :data="
41
+ filteredList.length > 0
42
+ ? chart.filter === 'primary'
43
+ ? by_primary()
44
+ : chart.filter === 'months'
45
+ ? by_months()
46
+ : compare()
47
+ : noData()
48
+ "
49
+ :options="chart.options"
50
+ />
51
+ </div>
52
+ </column>
53
+ </row>
54
+ </container>
55
+ </template>
56
+
57
+ <script>
58
+ import { GChart } from 'vue-google-charts'
59
+ import Container from '../../Containers/Container/index.vue'
60
+ import Column from '../../Containers/Column/index.vue'
61
+ import Row from '../../Containers/Row/index.vue'
62
+ import FilterButton from '../../Common/FilterButton/index.vue' // Reset
63
+ import SingleTaxonomy from '../../Global/DirectoryFilters/SingleTaxonomy/index.vue'
64
+ import { BFormGroup, BFormSelect } from 'bootstrap-vue-next'
65
+
66
+ export default {
67
+ name: 'Chart',
68
+ components: {
69
+ Row,
70
+ Column,
71
+ Container,
72
+ GChart,
73
+ FilterButton,
74
+ SingleTaxonomy,
75
+ BFormGroup,
76
+ BFormSelect
77
+ },
78
+ props: {
79
+ statsData: { type: Array, default: () => [] },
80
+ filterFields: { type: Array, default: () => [] },
81
+ chart: { type: Object, default: () => {} }
82
+ },
83
+ data() {
84
+ return {
85
+ hideReset: true,
86
+ isFiltering: false,
87
+ filters: {
88
+ taxonomies: [],
89
+ selected: {},
90
+ availableBundles: []
91
+ },
92
+ graphSelected: null,
93
+ chartHeight: this.chart.options.height ? this.chart.options.height : 600
94
+ }
95
+ },
96
+ computed: {
97
+ graphOptions: function() {
98
+ return this.filterFields.slice(1).map((field) => {
99
+ if (!this.graphSelected) {
100
+ this.graphSelected = field.record_id
101
+ }
102
+ return { value: field.record_id, text: field.name }
103
+ })
104
+ },
105
+ computedPropFilters: function() {
106
+ let fields = this.filterFields.map((field) => {
107
+ let terms = null
108
+ if (field.date) {
109
+ terms = this.statsData
110
+ .map((item) => item[field.record_id].split('/')[2]) // Date field get year
111
+ .filter((value, index, self) => self.indexOf(value) === index)
112
+ .map((value) => {
113
+ return { tid: value, name: value, preselected: false }
114
+ })
115
+ .sort((a, b) => a.name.localeCompare(b.name))
116
+ } else {
117
+ terms = this.statsData
118
+ .map((item) => item[field.record_id])
119
+ .filter((value, index, self) => self.indexOf(value) === index)
120
+ .map((value) => {
121
+ return { tid: value, name: value, preselected: false }
122
+ })
123
+ .sort((a, b) => a.name.localeCompare(b.name))
124
+ }
125
+ return {
126
+ name: field.name,
127
+ record_id: field.record_id,
128
+ terms
129
+ }
130
+ })
131
+ return fields
132
+ },
133
+ filteredList: function() {
134
+ let filterKeys = Object.keys(this.filters.selected).map((key) => key)
135
+ let list = this.statsData.filter((element) => {
136
+ let include = true
137
+ for (var i = 0, n = filterKeys.length; i < n; ++i) {
138
+ if (this.filters.selected[filterKeys[i]].length > 0) {
139
+ let filterType = this.filterFields.find(
140
+ (item) => item.record_id === filterKeys[i]
141
+ )
142
+ if (filterType.date) {
143
+ // Filter by year
144
+ if (
145
+ this.filters.selected[filterKeys[i]].indexOf(
146
+ element[filterKeys[i]].split('/')[2]
147
+ ) === -1
148
+ ) {
149
+ include = false
150
+ }
151
+ } else {
152
+ if (
153
+ this.filters.selected[filterKeys[i]].indexOf(
154
+ element[filterKeys[i]]
155
+ ) === -1
156
+ ) {
157
+ include = false
158
+ }
159
+ }
160
+ }
161
+ }
162
+ if (include) {
163
+ return element
164
+ }
165
+ })
166
+ return list
167
+ }
168
+ },
169
+ methods: {
170
+ onFilter(filters) {
171
+ this.hideReset = false
172
+ const allFiltersUnselected = Object.values(this.$refs).every(
173
+ (taxonomy) => {
174
+ return Object.values(taxonomy[0].selectedFilters).every(
175
+ (filter) => filter.filter((item) => !item.preselected).length === 0
176
+ )
177
+ }
178
+ )
179
+ if (allFiltersUnselected) {
180
+ this.hideReset = true
181
+ }
182
+ Object.keys(filters).forEach((filter) => {
183
+ this.filters.selected[filter] = filters[filter].map((obj) => obj.tid)
184
+ })
185
+ },
186
+ reset() {
187
+ this.hideReset = true
188
+ Object.keys(this.$refs).forEach((key) => {
189
+ this.$refs[key][0].reset()
190
+ })
191
+ this.filters.selected = {}
192
+ },
193
+ by_primary() {
194
+ let primaryFilter = this.filterFields[0]
195
+ let data = [[primaryFilter.name, this.chart.header]]
196
+ let keys = {}
197
+
198
+ this.filteredList.forEach((element) => {
199
+ // Work off primary field
200
+ let group = null
201
+ if (primaryFilter.date) {
202
+ group = `${element[primaryFilter.record_id].split('/')[2]} `
203
+ } else {
204
+ group = element[primaryFilter.record_id]
205
+ }
206
+
207
+ if (group in keys) {
208
+ keys[group]++
209
+ } else {
210
+ keys[group] = 1
211
+ }
212
+ })
213
+ Object.keys(keys).forEach((item) => {
214
+ data.push([item, keys[item]])
215
+ })
216
+ if (this.chart.type === 'BarChart') {
217
+ this.chart.options.height = data[0].length * 200
218
+ } else {
219
+ this.chart.options.height = this.chartHeight
220
+ }
221
+ return data
222
+ },
223
+ by_months() {
224
+ let primaryFilter = this.filterFields[0]
225
+ if (!primaryFilter.date) {
226
+ return ['Requires date in primary field']
227
+ }
228
+ let data = [
229
+ ['Month'],
230
+ ['Jan'],
231
+ ['Feb'],
232
+ ['Mar'],
233
+ ['Apr'],
234
+ ['May'],
235
+ ['Jun'],
236
+ ['Jul'],
237
+ ['Aug'],
238
+ ['Sep'],
239
+ ['Oct'],
240
+ ['Nov'],
241
+ ['Dec']
242
+ ]
243
+ let years = this.filteredList
244
+ .map((item) => item[primaryFilter.record_id].split('/')[2])
245
+ .filter((value, index, self) => self.indexOf(value) === index)
246
+ data[0].push(...years)
247
+ for (var i = 1, n = data.length; i < n; ++i) {
248
+ for (var j = 0, m = years.length; j < m; ++j) {
249
+ data[i].push(0)
250
+ }
251
+ }
252
+ this.filteredList.forEach((element) => {
253
+ let year = element[primaryFilter.record_id].split('/')[2]
254
+ let month = element[primaryFilter.record_id].split('/')[1]
255
+ data[month][data[0].indexOf(year)]++
256
+ })
257
+ for (var i = 2; i < data.length; i++) {
258
+ for (var j = 1; j < data[i].length; j++) {
259
+ data[i][j] = data[i][j] + data[i - 1][j]
260
+ }
261
+ }
262
+ if (this.chart.type === 'BarChart') {
263
+ this.chart.options.height = data[0].length * 200
264
+ } else {
265
+ this.chart.options.height = this.chartHeight
266
+ }
267
+ return data
268
+ },
269
+ compare() {
270
+ let primaryFilter = this.filterFields[0]
271
+ let comparison = this.filteredList
272
+ .map((item) => item[this.graphSelected])
273
+ .filter((value, index, self) => self.indexOf(value) === index)
274
+ .sort((a, b) => a.localeCompare(b))
275
+ let data = [['Year', ...comparison]]
276
+ let keys = {}
277
+ this.filteredList.forEach((element) => {
278
+ let group = null
279
+ if (primaryFilter.date) {
280
+ group = `${element[primaryFilter.record_id].split('/')[2]} `
281
+ } else {
282
+ group = element[primaryFilter.record_id]
283
+ }
284
+ if (group in keys) {
285
+ } else {
286
+ keys[group] = {}
287
+ comparison.forEach((co) => {
288
+ keys[group][co] = 0
289
+ })
290
+ }
291
+ keys[group][element[this.graphSelected]]++
292
+ })
293
+ Object.keys(keys).forEach((key) => {
294
+ data.push([key, ...Object.entries(keys[key]).map(([k, v]) => v)])
295
+ })
296
+ if (this.chart.type === 'BarChart') {
297
+ this.chart.options.height = data[0].length * 200
298
+ } else {
299
+ this.chart.options.height = this.chartHeight
300
+ }
301
+ return data
302
+ },
303
+ noData() {
304
+ return [
305
+ [
306
+ { label: 'Results', type: 'string' },
307
+ { label: 'Results', type: 'number' },
308
+ { role: 'style', type: 'string' },
309
+ { role: 'annotation', type: 'string' }
310
+ ],
311
+ ['', 0, null, 'No results found']
312
+ ]
313
+ }
314
+ }
315
+ }
316
+ </script>
317
+
318
+ <style lang="scss" scoped>
319
+ @import '../../../includes/scss/all';
320
+
321
+ .wcl-directory-filters {
322
+ &__filterButton {
323
+ display: inline-block;
324
+ padding-right: 16px;
325
+ line-height: 3;
326
+ &:last-child {
327
+ padding-right: 0px;
328
+ }
329
+ }
330
+ }
331
+ </style>
@@ -5,67 +5,62 @@ export default {
5
5
  title: 'Paragraphs/ListGroup',
6
6
  component: ListGroup,
7
7
  argTypes: {
8
- darkBackground: {
9
- control: 'boolean',
10
- defaultValue: false
11
- },
12
- items: {
13
- control: 'object',
14
- defaultValue: storyData.links
15
- },
16
- rtlItems: {
17
- control: 'object',
18
- defaultValue: storyDataAr.links
19
- },
20
- rtl: {
21
- control: 'boolean',
22
- defaultValue: false
23
- },
24
- titleTag: {
25
- control: 'text',
26
- defaultValue: 'h3'
27
- },
28
- showListItemNavigationArrow: {
29
- control: 'boolean',
30
- defaultValue: true
8
+ list: {
9
+ table: {
10
+ disable: true
11
+ }
31
12
  },
32
- showLargeSpacing: {
33
- control: 'boolean',
34
- defaultValue: false
13
+ title: {
14
+ table: {
15
+ disable: true
16
+ }
35
17
  },
36
- list: {
18
+ role: {
37
19
  table: {
38
20
  disable: true
39
21
  }
40
22
  },
41
- showListLink: {
42
- control: 'boolean',
43
- defaultValue: true
23
+ subHeading: {
24
+ table: {
25
+ disable: true
26
+ }
44
27
  },
45
- title: {
28
+ footerHeading: {
46
29
  table: {
47
30
  disable: true
48
31
  }
49
32
  }
33
+ },
34
+ args: {
35
+ darkBackground: false,
36
+ items: storyData.links,
37
+ rtlItems: storyDataAr.links,
38
+ rtl: false,
39
+ titleTag: 'h3',
40
+ showListItemNavigationArrow: true,
41
+ showLargeSpacing: false,
42
+ showListLink: true
50
43
  }
51
44
  }
52
45
 
53
- const Template = (args, { argTypes }) => ({
46
+ const Template = (args) => ({
54
47
  components: { ListGroup },
48
+ setup() {
49
+ return { args };
50
+ },
55
51
  data() {
56
52
  return {
57
53
  storyData,
58
54
  storyDataAr
59
55
  }
60
56
  },
61
- props: Object.keys(argTypes),
62
57
  template: `<list-group
63
- v-bind="$props"
64
- :list="rtl ? rtlItems : items"
65
- :title="(rtl ? storyDataAr.title : storyData.title)"
66
- :sub-heading="(rtl ? storyDataAr.subHeading : storyData.subHeading)"
67
- :footer-heading="(rtl ? storyDataAr.footer : storyDataAr.footer)"
68
- :show-list-link="showListLink" />`
58
+ v-bind="args"
59
+ :list="args.rtl ? args.rtlItems : args.items"
60
+ :title="(args.rtl ? storyDataAr.title : storyData.title)"
61
+ :sub-heading="(args.rtl ? storyDataAr.subHeading : storyData.subHeading)"
62
+ :footer-heading="(args.rtl ? storyDataAr.footer : storyDataAr.footer)"
63
+ :show-list-link="args.showListLink" />`
69
64
  })
70
65
 
71
66
  export const Link = Template.bind({})
@@ -5,60 +5,63 @@ export default {
5
5
  title: 'Paragraphs/ListGroup',
6
6
  component: ListGroup,
7
7
  argTypes: {
8
- darkBackground: {
9
- control: 'boolean',
10
- defaultValue: false
11
- },
12
- items: {
13
- control: 'object',
14
- defaultValue: storyData.links
15
- },
16
- rtlItems: {
17
- control: 'object',
18
- defaultValue: storyDataAr.links
19
- },
20
- rtl: {
21
- control: 'boolean',
22
- defaultValue: false
8
+ list: {
9
+ table: {
10
+ disable: true
11
+ }
23
12
  },
24
- titleTag: {
25
- control: 'text',
26
- defaultValue: 'h3'
13
+ title: {
14
+ table: {
15
+ disable: true
16
+ }
27
17
  },
28
- showListItemNavigationArrow: {
29
- control: 'boolean',
30
- defaultValue: true
18
+ role: {
19
+ table: {
20
+ disable: true
21
+ }
31
22
  },
32
- showLargeSpacing: {
33
- control: 'boolean',
34
- defaultValue: false
23
+ subHeading: {
24
+ table: {
25
+ disable: true
26
+ }
35
27
  },
36
- list: {
28
+ footerHeading: {
37
29
  table: {
38
30
  disable: true
39
31
  }
40
32
  },
41
- title: {
33
+ showListLink: {
42
34
  table: {
43
35
  disable: true
44
36
  }
45
37
  }
38
+ },
39
+ args: {
40
+ darkBackground: false,
41
+ items: storyData.links,
42
+ rtlItems: storyDataAr.links,
43
+ rtl: false,
44
+ titleTag: 'h3',
45
+ showListItemNavigationArrow: true,
46
+ showLargeSpacing: false
46
47
  }
47
48
  }
48
49
 
49
- const Template = (args, { argTypes }) => ({
50
+ const Template = (args) => ({
50
51
  components: { ListGroup },
52
+ setup() {
53
+ return { args }
54
+ },
51
55
  data() {
52
56
  return {
53
57
  storyData,
54
58
  storyDataAr
55
59
  }
56
60
  },
57
- props: Object.keys(argTypes),
58
61
  template: `<list-group
59
- v-bind="$props"
60
- :list="rtl ? rtlItems : items"
61
- :title="(rtl ? storyDataAr.title : storyData.title)" />`
62
+ v-bind="args"
63
+ :list="args.rtl ? args.rtlItems : args.items"
64
+ :title="(args.rtl ? storyDataAr.title : storyData.title)" />`
62
65
  })
63
66
 
64
67
  export const Default = Template.bind({})