@windward/core 0.16.0 → 0.18.0

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 (32) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/components/Content/Blocks/Accordion.vue +49 -39
  3. package/components/Content/Blocks/BlockQuote.vue +10 -1
  4. package/components/Content/Blocks/ClickableIcons.vue +55 -39
  5. package/components/Content/Blocks/Email.vue +11 -2
  6. package/components/Content/Blocks/FileDownload.vue +9 -1
  7. package/components/Content/Blocks/OpenResponse.vue +25 -12
  8. package/components/Content/Blocks/ScenarioChoice.vue +14 -5
  9. package/components/Content/Blocks/Tab.vue +15 -2
  10. package/components/Content/Blocks/UserUpload.vue +10 -1
  11. package/components/Content/Blocks/Video.vue +13 -4
  12. package/components/Navigation/Items/UserUploadNav.vue +4 -0
  13. package/components/Settings/AccordionSettings.vue +16 -30
  14. package/components/Settings/BlockQuoteSettings.vue +35 -48
  15. package/components/Settings/ClickableIconsSettings.vue +14 -27
  16. package/components/Settings/EmailSettings.vue +18 -28
  17. package/components/Settings/FileDownloadSettings.vue +14 -21
  18. package/components/Settings/OpenResponseSettings.vue +13 -27
  19. package/components/Settings/ScenarioChoiceSettings.vue +19 -29
  20. package/components/Settings/TabSettings.vue +22 -30
  21. package/components/Settings/TextEditorSettings.vue +1 -0
  22. package/components/Settings/UserUploadSettings.vue +12 -22
  23. package/components/Settings/VideoSettings.vue +12 -19
  24. package/components/utils/ContentViewer.vue +3 -0
  25. package/components/utils/FillInBlank/FillInBlankInput.vue +32 -28
  26. package/components/{Content/Blocks → utils}/GenerateAIQuestionButton.vue +117 -25
  27. package/components/utils/TinyMCEWrapper.vue +14 -57
  28. package/helpers/tinymce/WindwardPlugins.ts +36 -3
  29. package/models/Activity.ts +9 -0
  30. package/package.json +1 -1
  31. package/test/__mocks__/componentsMock.js +1 -0
  32. package/utils/index.js +1 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # Changelog
2
2
 
3
+ ### Release [0.18.0] created - 2025-05-21
4
+
5
+
6
+ ### Release [0.17.0] created - 2025-05-13
7
+
8
+
3
9
  ### Release [0.16.0] created - 2025-04-29
4
10
 
5
11
 
@@ -1,13 +1,19 @@
1
1
  <template>
2
2
  <div>
3
3
  <v-container
4
- class="pa-0"
5
4
  v-if="
6
5
  block.metadata.config.title ||
7
6
  block.metadata.config.instructions
8
7
  "
8
+ class="pa-0"
9
9
  >
10
- <h2 v-if="block.metadata.config.title" tabindex="0">
10
+ <h2
11
+ v-if="
12
+ block.metadata.config.title &&
13
+ block.metadata.config.display_title
14
+ "
15
+ tabindex="0"
16
+ >
11
17
  {{ block.metadata.config.title }}
12
18
  </h2>
13
19
 
@@ -31,9 +37,10 @@
31
37
  :key="itemIndex"
32
38
  >
33
39
  <v-expansion-panel-header
40
+ :ref="'expansion-panel-' + itemIndex"
34
41
  class="expansion-panel-header"
35
42
  color="primary"
36
- :ref="'expansion-panel-' + itemIndex"
43
+ role="button"
37
44
  @click="onOpenAccordion(itemIndex)"
38
45
  >
39
46
  {{
@@ -43,8 +50,8 @@
43
50
  }}
44
51
  </v-expansion-panel-header>
45
52
  <v-expansion-panel-content
46
- class="expansion-panel-body"
47
53
  :key="expansionPanelKey"
54
+ class="expansion-panel-body"
48
55
  >
49
56
  <v-container
50
57
  class="px-0 d-flex"
@@ -87,9 +94,9 @@
87
94
  import _ from 'lodash'
88
95
  import Crypto from '~/helpers/Crypto'
89
96
  import ImageAssetViewer from '~/components/Content/ImageAssetViewer.vue'
97
+ import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
90
98
  import TextEditor from '~/components/Text/TextEditor'
91
99
  import TextViewer from '~/components/Text/TextViewer'
92
- import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
93
100
 
94
101
  export default {
95
102
  name: 'ContentBlockAccordion',
@@ -99,40 +106,6 @@ export default {
99
106
  ImageAssetViewer,
100
107
  },
101
108
  extends: BaseContentBlock,
102
- beforeMount() {
103
- if (_.isEmpty(this.block)) {
104
- this.block = {}
105
- }
106
- if (_.isEmpty(this.block.metadata)) {
107
- this.block.metadata = {}
108
- }
109
- if (_.isEmpty(this.block.metadata.config)) {
110
- this.block.metadata.config = {}
111
- }
112
- if (_.isEmpty(this.block.metadata.config.title)) {
113
- this.block.metadata.config.title = ''
114
- }
115
- if (_.isEmpty(this.block.metadata.config.items)) {
116
- const defaultObject = {
117
- header: '',
118
- expand: false,
119
- content: '',
120
- fileConfig: {
121
- display: {
122
- width: 100,
123
- margin: '',
124
- padding: '',
125
- },
126
- hideBackground: true,
127
- },
128
- }
129
- this.block.metadata.config.items = []
130
- this.block.metadata.config.items.push(defaultObject)
131
- }
132
- this.block.body = this.$t(
133
- 'windward.core.shared.content_blocks.title.accordion'
134
- )
135
- },
136
109
  data() {
137
110
  return {
138
111
  expansionPanelKey: '0',
@@ -184,6 +157,43 @@ export default {
184
157
  }
185
158
  },
186
159
  },
160
+ beforeMount() {
161
+ if (_.isEmpty(this.block)) {
162
+ this.block = {}
163
+ }
164
+ if (_.isEmpty(this.block.metadata)) {
165
+ this.block.metadata = {}
166
+ }
167
+ if (_.isEmpty(this.block.metadata.config)) {
168
+ this.block.metadata.config = {}
169
+ }
170
+ if (_.isEmpty(this.block.metadata.config.title)) {
171
+ this.block.metadata.config.title = ''
172
+ }
173
+ if (!_.isBoolean(this.block.metadata.config.display_title)) {
174
+ this.$set(this.block.metadata.config, 'display_title', true)
175
+ }
176
+ if (_.isEmpty(this.block.metadata.config.items)) {
177
+ const defaultObject = {
178
+ header: '',
179
+ expand: false,
180
+ content: '',
181
+ fileConfig: {
182
+ display: {
183
+ width: 100,
184
+ margin: '',
185
+ padding: '',
186
+ },
187
+ hideBackground: true,
188
+ },
189
+ }
190
+ this.block.metadata.config.items = []
191
+ this.block.metadata.config.items.push(defaultObject)
192
+ }
193
+ this.block.body = this.$t(
194
+ 'windward.core.shared.content_blocks.title.accordion'
195
+ )
196
+ },
187
197
  mounted() {
188
198
  if (this.render) {
189
199
  // ensure panels are always loaded closed
@@ -7,7 +7,13 @@
7
7
  "
8
8
  >
9
9
  <v-col cols="12" class="pb-0">
10
- <h2 v-if="block.metadata.config.title" tabindex="0">
10
+ <h2
11
+ v-if="
12
+ block.metadata.config.title &&
13
+ block.metadata.config.display_title
14
+ "
15
+ tabindex="0"
16
+ >
11
17
  {{ block.metadata.config.title }}
12
18
  </h2>
13
19
  <p
@@ -148,6 +154,9 @@ export default {
148
154
  if (_.isEmpty(this.block.metadata.config.title)) {
149
155
  this.block.metadata.config.title = ''
150
156
  }
157
+ if (!_.isBoolean(this.block.metadata.config.display_title)) {
158
+ this.$set(this.block.metadata.config, 'display_title', true)
159
+ }
151
160
  if (_.isEmpty(this.block.metadata.config.instructions)) {
152
161
  this.block.metadata.config.instructions = ''
153
162
  }
@@ -1,15 +1,21 @@
1
1
  <template>
2
2
  <div>
3
3
  <v-container class="pa-0">
4
- <h2 v-if="block.metadata.config.title" tabindex="0">
4
+ <h2
5
+ v-if="
6
+ block.metadata.config.title &&
7
+ block.metadata.config.display_title
8
+ "
9
+ tabindex="0"
10
+ >
5
11
  {{ block.metadata.config.title }}
6
12
  </h2>
7
13
  <p
8
- v-if="block.metadata.config.description"
14
+ v-if="block.metadata.config.instructions"
9
15
  tabindex="0"
10
16
  class="pt-3"
11
17
  >
12
- {{ block.metadata.config.description }}
18
+ {{ block.metadata.config.instructions }}
13
19
  </p>
14
20
  </v-container>
15
21
  <v-container class="pa-0">
@@ -20,7 +26,7 @@
20
26
  :class="rowClass(itemIndex)"
21
27
  class="pa-0"
22
28
  >
23
- <v-col cols="12" v-bind="iconColumnAttrs">
29
+ <v-col cols="8" v-bind="iconColumnAttrs">
24
30
  <button
25
31
  class="mr-1"
26
32
  :class="activatorButtonClass(itemIndex)"
@@ -85,8 +91,8 @@
85
91
  import _ from 'lodash'
86
92
  import he from 'he'
87
93
  import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
88
- import TextViewer from '~/components/Text/TextViewer'
89
94
  import ImageAssetViewer from '~/components/Content/ImageAssetViewer.vue'
95
+ import TextViewer from '~/components/Text/TextViewer'
90
96
 
91
97
  export default {
92
98
  name: 'ClickableIcons',
@@ -95,38 +101,6 @@ export default {
95
101
  ImageAssetViewer,
96
102
  },
97
103
  extends: BaseContentBlock,
98
- beforeMount() {
99
- // Apply the default config
100
- this.block.body = this.$t(
101
- 'windward.core.shared.content_blocks.title.clickable_icons'
102
- )
103
- if (_.isEmpty(this.block.metadata.config.items)) {
104
- this.block.metadata.config.items = []
105
- this.block.metadata.config.description = this.$t(
106
- 'windward.core.components.settings.clickable_icon.information'
107
- )
108
- }
109
- if (_.isEmpty(this.block.metadata.config.title)) {
110
- this.block.metadata.config.title = ''
111
- }
112
- if (_.isEmpty(this.block.metadata.config.description)) {
113
- this.block.metadata.config.description = ''
114
- }
115
- if (_.isEmpty(this.block.metadata.config.display)) {
116
- this.block.metadata.config.display = {
117
- show_title: false,
118
- show_background: false,
119
- round_icon: false,
120
- italic_icon: false,
121
- autocolor: true,
122
- }
123
- }
124
- if (this.block.metadata.config.items.length) {
125
- for (const index in this.block.metadata.config.items) {
126
- this.block.metadata.config.items[index].active = false
127
- }
128
- }
129
- },
130
104
  data() {
131
105
  return {
132
106
  saveState: false,
@@ -154,6 +128,9 @@ export default {
154
128
  ) {
155
129
  classes += ' ' + this.itemColor(itemIndex) + ' black--text'
156
130
  }
131
+ if (window.innerWidth <= 600) {
132
+ classes += 'd-flex justify-center '
133
+ }
157
134
  return classes
158
135
  }
159
136
  },
@@ -261,6 +238,41 @@ export default {
261
238
  }
262
239
  },
263
240
  },
241
+ beforeMount() {
242
+ // Apply the default config
243
+ this.block.body = this.$t(
244
+ 'windward.core.shared.content_blocks.title.clickable_icons'
245
+ )
246
+ if (_.isEmpty(this.block.metadata.config.items)) {
247
+ this.block.metadata.config.items = []
248
+ this.block.metadata.config.description = this.$t(
249
+ 'windward.core.components.settings.clickable_icon.information'
250
+ )
251
+ }
252
+ if (_.isEmpty(this.block.metadata.config.title)) {
253
+ this.block.metadata.config.title = ''
254
+ }
255
+ if (!_.isBoolean(this.block.metadata.config.display_title)) {
256
+ this.$set(this.block.metadata.config, 'display_title', true)
257
+ }
258
+ if (_.isEmpty(this.block.metadata.config.description)) {
259
+ this.block.metadata.config.description = ''
260
+ }
261
+ if (_.isEmpty(this.block.metadata.config.display)) {
262
+ this.block.metadata.config.display = {
263
+ show_title: false,
264
+ show_background: false,
265
+ round_icon: false,
266
+ italic_icon: false,
267
+ autocolor: true,
268
+ }
269
+ }
270
+ if (this.block.metadata.config.items.length) {
271
+ for (const index in this.block.metadata.config.items) {
272
+ this.block.metadata.config.items[index].active = false
273
+ }
274
+ }
275
+ },
264
276
  methods: {
265
277
  isIcon(str) {
266
278
  return str && _.isString(str) && str.indexOf('mdi-') === 0
@@ -295,13 +307,17 @@ button.button-icon.button-icon--rounded {
295
307
  }
296
308
 
297
309
  .button-icon--normal {
298
- .clickable--icon,
310
+ .clickable--icon {
311
+ font-size: 5rem;
312
+ }
299
313
  .clickable--text {
300
314
  font-size: 1.5rem;
301
315
  }
302
316
  }
303
317
  .button-icon--large {
304
- .clickable--icon,
318
+ .clickable--icon {
319
+ font-size: 9rem;
320
+ }
305
321
  .clickable--text {
306
322
  font-size: 2.5rem;
307
323
  }
@@ -7,7 +7,13 @@
7
7
  "
8
8
  >
9
9
  <v-col cols="12" class="pa-0">
10
- <h2 v-if="block.metadata.config.title" tabindex="0">
10
+ <h2
11
+ v-if="
12
+ block.metadata.config.title &&
13
+ block.metadata.config.display_title
14
+ "
15
+ tabindex="0"
16
+ >
11
17
  {{ block.metadata.config.title }}
12
18
  </h2>
13
19
  <p
@@ -21,8 +27,8 @@
21
27
  </v-row>
22
28
  <v-row>
23
29
  <v-expansion-panels
24
- v-model="selectedPanels"
25
30
  :key="expansionPanelKey"
31
+ v-model="selectedPanels"
26
32
  accordion
27
33
  >
28
34
  <v-container
@@ -248,6 +254,9 @@ export default {
248
254
  if (_.isEmpty(this.block.metadata.config.title)) {
249
255
  this.block.metadata.config.title = ''
250
256
  }
257
+ if (!_.isBoolean(this.block.metadata.config.display_title)) {
258
+ this.$set(this.block.metadata.config, 'display_title', true)
259
+ }
251
260
  if (_.isEmpty(this.block.metadata.config.instructions)) {
252
261
  this.block.metadata.config.instructions = ''
253
262
  }
@@ -1,6 +1,11 @@
1
1
  <template>
2
2
  <v-container class="pa-0">
3
- <h2>
3
+ <h2
4
+ v-if="
5
+ block.metadata.config.title &&
6
+ block.metadata.config.display_title
7
+ "
8
+ >
4
9
  {{
5
10
  block.metadata.config.title ||
6
11
  $t(
@@ -125,6 +130,9 @@ export default {
125
130
  'windward.core.components.content.blocks.file_download.default_title'
126
131
  )
127
132
  }
133
+ if (!_.isBoolean(this.block.metadata.config.display_title)) {
134
+ this.$set(this.block.metadata.config, 'display_title', true)
135
+ }
128
136
  if (_.isEmpty(this.block.metadata.config.instructions)) {
129
137
  this.block.metadata.config.instructions = this.$t(
130
138
  'windward.core.components.content.blocks.file_download.default_instructions'
@@ -1,13 +1,19 @@
1
1
  <template>
2
2
  <div>
3
3
  <v-container
4
- class="pa-0"
5
4
  v-if="
6
5
  block.metadata.config.title ||
7
6
  block.metadata.config.instructions
8
7
  "
8
+ class="pa-0"
9
9
  >
10
- <h2 v-if="block.metadata.config.title" tabindex="0">
10
+ <h2
11
+ v-if="
12
+ block.metadata.config.title &&
13
+ block.metadata.config.display_title
14
+ "
15
+ tabindex="0"
16
+ >
11
17
  {{ block.metadata.config.title }}
12
18
  </h2>
13
19
 
@@ -23,6 +29,7 @@
23
29
  <div v-if="block.body && !submitted">
24
30
  <TextViewer v-model="block.body" :height="200"></TextViewer>
25
31
  <TextEditor
32
+ :key="updateKey"
26
33
  v-model="response"
27
34
  :height="200"
28
35
  menubar=""
@@ -104,23 +111,25 @@
104
111
  <script>
105
112
  import _ from 'lodash'
106
113
  import { mapGetters } from 'vuex'
107
- import TextViewer from '~/components/Text/TextViewer'
108
- import TextEditor from '~/components/Text/TextEditor'
109
114
  import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
110
115
  import UserContentBlockState from '~/models/UserContentBlockState'
116
+ import Crypto from '~/helpers/Crypto'
117
+ import TextViewer from '~/components/Text/TextViewer'
118
+ import TextEditor from '~/components/Text/TextEditor'
111
119
 
112
120
  export default {
113
121
  name: 'ContentBlockOpenResponse',
114
- extends: BaseContentBlock,
115
122
  components: {
116
123
  TextViewer,
117
124
  TextEditor,
118
125
  },
126
+ extends: BaseContentBlock,
119
127
  data() {
120
128
  return {
121
129
  stateLoaded: false,
122
130
  response: '',
123
131
  submitted: false,
132
+ updateKey: Crypto.id(),
124
133
  }
125
134
  },
126
135
  computed: {
@@ -135,6 +144,13 @@ export default {
135
144
  )
136
145
  },
137
146
  },
147
+ watch: {
148
+ render(newVal) {
149
+ if (newVal) {
150
+ this.onAfterSetContentBlockState()
151
+ }
152
+ },
153
+ },
138
154
  beforeMount() {
139
155
  if (_.isEmpty(this.block.body)) {
140
156
  this.block.body = ''
@@ -145,6 +161,9 @@ export default {
145
161
  if (_.isEmpty(this.block.metadata.config.title)) {
146
162
  this.block.metadata.config.title = ''
147
163
  }
164
+ if (!_.isBoolean(this.block.metadata.config.display_title)) {
165
+ this.$set(this.block.metadata.config, 'display_title', true)
166
+ }
148
167
  if (_.isEmpty(this.block.metadata.config.instructions)) {
149
168
  this.block.metadata.config.instructions = ''
150
169
  }
@@ -155,13 +174,6 @@ export default {
155
174
  this.block.metadata.config.starting_text = ''
156
175
  }
157
176
  },
158
- watch: {
159
- render(newVal) {
160
- if (newVal) {
161
- this.onAfterSetContentBlockState()
162
- }
163
- },
164
- },
165
177
  mounted() {},
166
178
  methods: {
167
179
  async onAfterSetContentBlockState() {
@@ -194,6 +206,7 @@ export default {
194
206
  // If we don't have a block_id then we are in the initial setup state
195
207
  this.response = this.block.metadata.config.starting_text
196
208
  }
209
+ this.updateKey = Crypto.id()
197
210
  this.stateLoaded = true
198
211
  },
199
212
  onSubmit() {
@@ -1,15 +1,21 @@
1
1
  <template>
2
2
  <div>
3
3
  <v-container class="pa-0">
4
- <h2 v-if="block.metadata.config.title" tabindex="0">
4
+ <h2
5
+ v-if="
6
+ block.metadata.config.title &&
7
+ block.metadata.config.display_title
8
+ "
9
+ tabindex="0"
10
+ >
5
11
  {{ block.metadata.config.title }}
6
12
  </h2>
7
13
  <p
8
- v-if="block.metadata.config.description"
14
+ v-if="block.metadata.config.instructions"
9
15
  tabindex="0"
10
16
  class="pt-3"
11
17
  >
12
- {{ block.metadata.config.description }}
18
+ {{ block.metadata.config.instructions }}
13
19
  </p>
14
20
  <div
15
21
  v-if="choiceIndex !== null && block.metadata.config.show_reset"
@@ -244,8 +250,11 @@ export default {
244
250
  if (_.isEmpty(this.block.metadata.config.title)) {
245
251
  this.block.metadata.config.title = ''
246
252
  }
247
- if (_.isEmpty(this.block.metadata.config.description)) {
248
- this.block.metadata.config.description = ''
253
+ if (!_.isBoolean(this.block.metadata.config.display_title)) {
254
+ this.$set(this.block.metadata.config, 'display_title', true)
255
+ }
256
+ if (_.isEmpty(this.block.metadata.config.instructions)) {
257
+ this.block.metadata.config.instructions = ''
249
258
  }
250
259
  if (_.isEmpty(this.block.metadata.config.display_style)) {
251
260
  this.block.metadata.config.display_style = 'letter'
@@ -7,7 +7,13 @@
7
7
  "
8
8
  class="pa-0"
9
9
  >
10
- <h2 v-if="block.metadata.config.title" tabindex="0">
10
+ <h2
11
+ v-if="
12
+ block.metadata.config.title &&
13
+ block.metadata.config.display_title
14
+ "
15
+ tabindex="0"
16
+ >
11
17
  {{ block.metadata.config.title }}
12
18
  </h2>
13
19
 
@@ -116,6 +122,9 @@ export default {
116
122
  }
117
123
  })
118
124
  }
125
+ if (!_.isBoolean(this.block.metadata.config.display_title)) {
126
+ this.$set(this.block.metadata.config, 'display_title', true)
127
+ }
119
128
  if (_.isEmpty(this.block.metadata.config.currentTab)) {
120
129
  this.block.metadata.config.currentTab = 0
121
130
  }
@@ -185,4 +194,8 @@ export default {
185
194
  }
186
195
  </script>
187
196
 
188
- <style scoped></style>
197
+ <style scoped>
198
+ .text-viewer {
199
+ color: var(--v-primary-base);
200
+ }
201
+ </style>
@@ -1,7 +1,13 @@
1
1
  <template>
2
2
  <v-container class="pa-0">
3
3
  <div>
4
- <h2 v-if="block.metadata.config.title" tabindex="0">
4
+ <h2
5
+ v-if="
6
+ block.metadata.config.title &&
7
+ block.metadata.config.display_title
8
+ "
9
+ tabindex="0"
10
+ >
5
11
  {{ block.metadata.config.title }}
6
12
  </h2>
7
13
  <v-row>
@@ -110,6 +116,9 @@ export default {
110
116
  if (_.isEmpty(this.block.metadata.config)) {
111
117
  this.block.metadata.config = {}
112
118
  }
119
+ if (!_.isBoolean(this.block.metadata.config.display_title)) {
120
+ this.$set(this.block.metadata.config, 'display_title', true)
121
+ }
113
122
  if (_.isEmpty(this.block.metadata.config.instructions)) {
114
123
  this.block.metadata.config.instructions = ''
115
124
  }
@@ -1,10 +1,16 @@
1
1
  <template>
2
2
  <div>
3
- <h2 v-if="block.metadata.config.title" tabindex="0">
3
+ <h2
4
+ v-if="
5
+ block.metadata.config.title &&
6
+ block.metadata.config.display_title
7
+ "
8
+ tabindex="0"
9
+ >
4
10
  {{ block.metadata.config.title }}
5
11
  </h2>
6
- <p v-if="block.metadata.config.description" tabindex="0" class="pt-3">
7
- {{ block.metadata.config.description }}
12
+ <p v-if="block.metadata.config.instructions" tabindex="0" class="pt-3">
13
+ {{ block.metadata.config.instructions }}
8
14
  </p>
9
15
 
10
16
  <VuetifyPlayer
@@ -309,7 +315,7 @@ export default {
309
315
  // Default config settings
310
316
  defaultConfig: {
311
317
  title: '',
312
- description: '',
318
+ instructions: '',
313
319
  // Default settings for new blocks
314
320
  // This will be overridden in beforeMount()
315
321
  type: 'auto', // Allowed auto|video|audio. In audio mode the player has a max-height of 40px. Auto will switch between the other types when needed
@@ -393,6 +399,9 @@ export default {
393
399
  ) {
394
400
  this.block.metadata.config.attributes.playbackrates = [1]
395
401
  }
402
+ if (!_.isBoolean(this.block.metadata.config.display_title)) {
403
+ this.$set(this.block.metadata.config, 'display_title', true)
404
+ }
396
405
  if (_.isEmpty(this.block.assets)) {
397
406
  this.$set(this.block, 'assets', [])
398
407
  }
@@ -2,6 +2,7 @@
2
2
  <v-tooltip right>
3
3
  <template #activator="{ on, attrs }">
4
4
  <v-list-item
5
+ :class="color"
5
6
  :to="
6
7
  '/course/' +
7
8
  course.id +
@@ -38,6 +39,9 @@ import { mapGetters } from 'vuex'
38
39
  export default {
39
40
  components: {},
40
41
  middleware: ['auth'],
42
+ props: {
43
+ color: { type: String, required: false, default: '' },
44
+ },
41
45
  data() {
42
46
  return {}
43
47
  },