@windward/core 0.6.0 → 0.8.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 (176) hide show
  1. package/CHANGELOG.md +8 -1
  2. package/components/Content/Blocks/Accordion.vue +22 -0
  3. package/components/Content/Blocks/BlockQuote.vue +6 -2
  4. package/components/Content/Blocks/ClickableIcons.vue +19 -4
  5. package/components/Content/Blocks/Email.vue +12 -3
  6. package/components/Content/Blocks/GenerateAIQuestionButton.vue +14 -6
  7. package/components/Content/Blocks/HorizontalRule.vue +3 -4
  8. package/components/Content/Blocks/OpenResponse.vue +25 -0
  9. package/components/Content/Blocks/OpenResponseCollate.vue +13 -12
  10. package/components/Content/Blocks/ScenarioChoice.vue +66 -33
  11. package/components/Content/Blocks/Tab.vue +19 -0
  12. package/components/Content/Blocks/UserUpload.vue +5 -10
  13. package/components/Content/Blocks/Video.vue +129 -15
  14. package/components/Settings/AccordionSettings.vue +52 -13
  15. package/components/Settings/BlockQuoteSettings.vue +17 -33
  16. package/components/Settings/ClickableIconsSettings.vue +37 -23
  17. package/components/Settings/EmailSettings.vue +12 -30
  18. package/components/Settings/FileDownloadSettings.vue +12 -31
  19. package/components/Settings/HorizontalRuleSettings.vue +0 -3
  20. package/components/Settings/ImageSettings.vue +3 -9
  21. package/components/Settings/OpenResponseCollateSettings.vue +47 -55
  22. package/components/Settings/OpenResponseSettings.vue +62 -36
  23. package/components/Settings/ScenarioChoiceSettings.vue +22 -29
  24. package/components/Settings/TabSettings.vue +99 -81
  25. package/components/Settings/UserUploadSettings.vue +16 -42
  26. package/components/Settings/VideoSettings/SourcePicker.vue +223 -0
  27. package/components/Settings/VideoSettings.vue +115 -195
  28. package/components/utils/TinyMCEWrapper.vue +9 -5
  29. package/components/utils/assets/tinymce/content/global.scss +14 -0
  30. package/components/utils/glossary/CourseGlossary.vue +52 -27
  31. package/helpers/GlossaryHelper.ts +12 -2
  32. package/helpers/tinymce/WindwardPlugins.ts +59 -10
  33. package/i18n/en-US/components/content/blocks/generate_questions.ts +2 -1
  34. package/i18n/en-US/components/content/blocks/video.ts +2 -51
  35. package/i18n/en-US/components/settings/accordion.ts +1 -0
  36. package/i18n/en-US/components/settings/open_response_collate.ts +1 -1
  37. package/i18n/en-US/components/settings/scenario_choice.ts +3 -2
  38. package/i18n/en-US/components/settings/tab.ts +1 -0
  39. package/i18n/en-US/components/settings/user_upload.ts +1 -0
  40. package/i18n/en-US/components/settings/video.ts +51 -0
  41. package/i18n/en-US/components/utils/tiny_mce_wrapper.ts +9 -1
  42. package/i18n/en-US/shared/settings.ts +1 -1
  43. package/i18n/es-ES/components/content/blocks/generate_questions.ts +2 -1
  44. package/i18n/es-ES/components/content/blocks/video.ts +3 -53
  45. package/i18n/es-ES/components/settings/accordion.ts +1 -0
  46. package/i18n/es-ES/components/settings/open_response_collate.ts +1 -1
  47. package/i18n/es-ES/components/settings/scenario_choice.ts +3 -2
  48. package/i18n/es-ES/components/settings/tab.ts +2 -0
  49. package/i18n/es-ES/components/settings/user_upload.ts +1 -0
  50. package/i18n/es-ES/components/settings/video.ts +53 -0
  51. package/i18n/es-ES/components/utils/tiny_mce_wrapper.ts +9 -0
  52. package/i18n/es-ES/shared/settings.ts +1 -1
  53. package/i18n/sv-SE/components/content/blocks/generate_questions.ts +2 -1
  54. package/i18n/sv-SE/components/content/blocks/video.ts +2 -51
  55. package/i18n/sv-SE/components/settings/accordion.ts +2 -0
  56. package/i18n/sv-SE/components/settings/open_response_collate.ts +1 -1
  57. package/i18n/sv-SE/components/settings/scenario_choice.ts +3 -2
  58. package/i18n/sv-SE/components/settings/tab.ts +1 -0
  59. package/i18n/sv-SE/components/settings/user_upload.ts +1 -0
  60. package/i18n/sv-SE/components/settings/video.ts +51 -0
  61. package/i18n/sv-SE/components/utils/tiny_mce_wrapper.ts +8 -0
  62. package/package.json +3 -2
  63. package/plugin.js +1 -1
  64. package/test/__mocks__/modelMock.js +1 -1
  65. package/test/helpers/GlossaryHelper.spec.js +22 -3
  66. package/test/mocks.js +8 -0
  67. package/.idea/codeStyles/Project.xml +0 -58
  68. package/.idea/codeStyles/codeStyleConfig.xml +0 -5
  69. package/.idea/inspectionProfiles/Project_Default.xml +0 -6
  70. package/.idea/modules.xml +0 -8
  71. package/.idea/php-docker-settings.xml +0 -24
  72. package/.idea/php.xml +0 -19
  73. package/.idea/vcs.xml +0 -6
  74. package/.idea/watcherTasks.xml +0 -4
  75. package/.idea/windward-ui-plugin-core.iml +0 -8
  76. package/config/menu.config.json +0 -475
  77. package/coverage/clover.xml +0 -223
  78. package/coverage/coverage-final.json +0 -16
  79. package/coverage/lcov-report/base.css +0 -224
  80. package/coverage/lcov-report/block-navigation.js +0 -87
  81. package/coverage/lcov-report/components/Content/Blocks/Accordion.vue.html +0 -430
  82. package/coverage/lcov-report/components/Content/Blocks/Image.vue.html +0 -394
  83. package/coverage/lcov-report/components/Content/Blocks/Math.vue.html +0 -262
  84. package/coverage/lcov-report/components/Content/Blocks/RichText.vue.html +0 -295
  85. package/coverage/lcov-report/components/Content/Blocks/Tab.vue.html +0 -415
  86. package/coverage/lcov-report/components/Content/Blocks/Table.vue.html +0 -667
  87. package/coverage/lcov-report/components/Content/Blocks/Video.vue.html +0 -2275
  88. package/coverage/lcov-report/components/Content/Blocks/index.html +0 -206
  89. package/coverage/lcov-report/components/utils/ContentViewer.vue.html +0 -199
  90. package/coverage/lcov-report/components/utils/MathExpressionEditor.vue.html +0 -919
  91. package/coverage/lcov-report/components/utils/MathLiveWrapper.vue.html +0 -343
  92. package/coverage/lcov-report/components/utils/TinyMCEWrapper.vue.html +0 -271
  93. package/coverage/lcov-report/components/utils/index.html +0 -161
  94. package/coverage/lcov-report/config/index.html +0 -116
  95. package/coverage/lcov-report/config/tinymce.config.js.html +0 -493
  96. package/coverage/lcov-report/favicon.png +0 -0
  97. package/coverage/lcov-report/helpers/MathHelper.ts.html +0 -793
  98. package/coverage/lcov-report/helpers/index.html +0 -116
  99. package/coverage/lcov-report/helpers/tinymce/index.html +0 -116
  100. package/coverage/lcov-report/helpers/tinymce/plugin.ts.html +0 -334
  101. package/coverage/lcov-report/index.html +0 -191
  102. package/coverage/lcov-report/prettify.css +0 -1
  103. package/coverage/lcov-report/prettify.js +0 -2
  104. package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
  105. package/coverage/lcov-report/sorter.js +0 -196
  106. package/coverage/lcov-report/test/index.html +0 -116
  107. package/coverage/lcov-report/test/mocks.js.html +0 -457
  108. package/coverage/lcov.info +0 -403
  109. package/lib/helpers/GlossaryHelper.d.ts +0 -9
  110. package/lib/helpers/GlossaryHelper.js +0 -118
  111. package/lib/helpers/GlossaryTerm.d.ts +0 -10
  112. package/lib/helpers/GlossaryTerm.js +0 -22
  113. package/lib/helpers/MathHelper.d.ts +0 -99
  114. package/lib/helpers/MathHelper.js +0 -194
  115. package/lib/helpers/tinymce/plugin.d.ts +0 -2
  116. package/lib/helpers/tinymce/plugin.js +0 -86
  117. package/lib/i18n/en-US/components/content/blocks/image.d.ts +0 -6
  118. package/lib/i18n/en-US/components/content/blocks/image.js +0 -7
  119. package/lib/i18n/en-US/components/content/blocks/index.d.ts +0 -75
  120. package/lib/i18n/en-US/components/content/blocks/index.js +0 -14
  121. package/lib/i18n/en-US/components/content/blocks/tab.d.ts +0 -5
  122. package/lib/i18n/en-US/components/content/blocks/tab.js +0 -6
  123. package/lib/i18n/en-US/components/content/blocks/table.d.ts +0 -5
  124. package/lib/i18n/en-US/components/content/blocks/table.js +0 -6
  125. package/lib/i18n/en-US/components/content/blocks/user_upload.d.ts +0 -13
  126. package/lib/i18n/en-US/components/content/blocks/user_upload.js +0 -14
  127. package/lib/i18n/en-US/components/content/blocks/video.d.ts +0 -48
  128. package/lib/i18n/en-US/components/content/blocks/video.js +0 -49
  129. package/lib/i18n/en-US/components/content/index.d.ts +0 -77
  130. package/lib/i18n/en-US/components/content/index.js +0 -6
  131. package/lib/i18n/en-US/components/index.d.ts +0 -140
  132. package/lib/i18n/en-US/components/index.js +0 -12
  133. package/lib/i18n/en-US/components/navigation/image.d.ts +0 -5
  134. package/lib/i18n/en-US/components/navigation/image.js +0 -6
  135. package/lib/i18n/en-US/components/navigation/index.d.ts +0 -10
  136. package/lib/i18n/en-US/components/navigation/index.js +0 -8
  137. package/lib/i18n/en-US/components/navigation/user_upload.d.ts +0 -4
  138. package/lib/i18n/en-US/components/navigation/user_upload.js +0 -5
  139. package/lib/i18n/en-US/components/settings/clickable_icon.d.ts +0 -6
  140. package/lib/i18n/en-US/components/settings/clickable_icon.js +0 -7
  141. package/lib/i18n/en-US/components/settings/image.d.ts +0 -2
  142. package/lib/i18n/en-US/components/settings/image.js +0 -3
  143. package/lib/i18n/en-US/components/settings/index.d.ts +0 -39
  144. package/lib/i18n/en-US/components/settings/index.js +0 -14
  145. package/lib/i18n/en-US/components/settings/text_editor.d.ts +0 -8
  146. package/lib/i18n/en-US/components/settings/text_editor.js +0 -9
  147. package/lib/i18n/en-US/components/settings/user_upload.d.ts +0 -12
  148. package/lib/i18n/en-US/components/settings/user_upload.js +0 -13
  149. package/lib/i18n/en-US/components/settings/video.d.ts +0 -13
  150. package/lib/i18n/en-US/components/settings/video.js +0 -14
  151. package/lib/i18n/en-US/components/utils/index.d.ts +0 -15
  152. package/lib/i18n/en-US/components/utils/index.js +0 -6
  153. package/lib/i18n/en-US/components/utils/tiny_mce_wrapper.d.ts +0 -13
  154. package/lib/i18n/en-US/components/utils/tiny_mce_wrapper.js +0 -14
  155. package/lib/i18n/en-US/index.d.ts +0 -197
  156. package/lib/i18n/en-US/index.js +0 -16
  157. package/lib/i18n/en-US/modules/index.d.ts +0 -2
  158. package/lib/i18n/en-US/modules/index.js +0 -6
  159. package/lib/i18n/en-US/pages/glossary.d.ts +0 -8
  160. package/lib/i18n/en-US/pages/glossary.js +0 -9
  161. package/lib/i18n/en-US/pages/index.d.ts +0 -13
  162. package/lib/i18n/en-US/pages/index.js +0 -8
  163. package/lib/i18n/en-US/pages/user_upload.d.ts +0 -4
  164. package/lib/i18n/en-US/pages/user_upload.js +0 -5
  165. package/lib/i18n/en-US/shared/content_blocks.d.ts +0 -20
  166. package/lib/i18n/en-US/shared/content_blocks.js +0 -21
  167. package/lib/i18n/en-US/shared/index.d.ts +0 -39
  168. package/lib/i18n/en-US/shared/index.js +0 -10
  169. package/lib/i18n/en-US/shared/menu.d.ts +0 -4
  170. package/lib/i18n/en-US/shared/menu.js +0 -5
  171. package/lib/i18n/en-US/shared/settings.d.ts +0 -15
  172. package/lib/i18n/en-US/shared/settings.js +0 -16
  173. package/lib/i18n/en-US.d.ts +0 -197
  174. package/lib/i18n/en-US.js +0 -15
  175. package/lib/models/UserFileAsset.d.ts +0 -5
  176. package/lib/models/UserFileAsset.js +0 -37
@@ -1,18 +1,23 @@
1
1
  <template>
2
2
  <div>
3
+ <h2 v-if="block.metadata.config.title" tabindex="0">
4
+ {{ block.metadata.config.title }}
5
+ </h2>
6
+ <p v-if="block.metadata.config.description" tabindex="0" class="pt-3">
7
+ {{ block.metadata.config.description }}
8
+ </p>
9
+
3
10
  <v-card v-if="render && !hasSource">
4
11
  <v-card-title>
5
12
  <v-icon class="mr-2">mdi-cloud-question</v-icon>
6
13
  {{
7
14
  $t(
8
- 'windward.core.components.content.blocks.video.video.not_configured_title'
15
+ 'windward.core.components.content.blocks.video.not_configured_title'
9
16
  )
10
17
  }}
11
18
  </v-card-title>
12
19
  <v-card-text>{{
13
- $t(
14
- 'windward.core.components.content.blocks.video.video.edit_prompt'
15
- )
20
+ $t('windward.core.components.content.blocks.video.edit_prompt')
16
21
  }}</v-card-text>
17
22
  </v-card>
18
23
 
@@ -21,12 +26,7 @@
21
26
  type="image, image, list-item-avatar"
22
27
  class="reload-skeleton"
23
28
  ></v-skeleton-loader>
24
- <h2 v-if="block.metadata.config.title">
25
- {{ block.metadata.config.title }}
26
- </h2>
27
- <p v-if="block.metadata.config.description" class="pb-0 mb-0">
28
- {{ block.metadata.config.description }}
29
- </p>
29
+
30
30
  <VuetifyPlayer
31
31
  v-if="hasSource"
32
32
  :language="$i18n && $i18n.locale ? $i18n.locale : 'en-US'"
@@ -59,7 +59,20 @@
59
59
  block.metadata.config.attributes.playlistautoadvance
60
60
  "
61
61
  :playbackrates="block.metadata.config.attributes.playbackrates"
62
+ @seeking="onSeeking"
63
+ @timeupdate="onTimeupdate"
62
64
  />
65
+ <!-- display first note in the playlist for now -->
66
+ <v-alert
67
+ v-if="notes.length > 0"
68
+ :color="
69
+ $vuetify.theme.isDark
70
+ ? 'v-navigation-drawer'
71
+ : 'blue-grey lighten-5'
72
+ "
73
+ >
74
+ <TextViewer v-model="notes[0]"></TextViewer>
75
+ </v-alert>
63
76
  </div>
64
77
  </template>
65
78
 
@@ -67,10 +80,13 @@
67
80
  import _ from 'lodash'
68
81
  import VuetifyPlayer from '@mindedge/vuetify-player'
69
82
  import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
83
+ import TextViewer from '~/components/Text/TextViewer'
84
+ import he from 'he'
70
85
 
71
86
  export default {
72
87
  name: 'ContentBlockVideo',
73
88
  components: {
89
+ TextViewer,
74
90
  VuetifyPlayer,
75
91
  },
76
92
  extends: BaseContentBlock,
@@ -96,12 +112,30 @@ export default {
96
112
  )
97
113
  return _.get(file, 'asset.public_url')
98
114
  },
115
+ notes() {
116
+ const playlist = this.block.metadata.config.playlist
117
+ let result = []
118
+ for (const index in playlist) {
119
+ for (const sourceIndex in playlist[index].sources) {
120
+ let file = this.resolveAsset(
121
+ playlist[index].sources[sourceIndex]
122
+ )
123
+ if (
124
+ !_.isEmpty(_.get(file, 'asset.metadata.notes')) &&
125
+ //check the file notes are actually text and not an empty div
126
+ this.hasWords(_.get(file, 'asset.metadata.notes'))
127
+ ) {
128
+ result.push(_.get(file, 'asset.metadata.notes'))
129
+ }
130
+ }
131
+ }
132
+ return result
133
+ },
99
134
  /**
100
135
  * Resolve assets to their playlist items
101
136
  */
102
137
  linkedPlaylist() {
103
138
  const playlist = _.cloneDeep(this.block.metadata.config.playlist)
104
-
105
139
  for (const index in playlist) {
106
140
  for (const sourceIndex in playlist[index].sources) {
107
141
  let file = this.resolveAsset(
@@ -112,6 +146,13 @@ export default {
112
146
  src: _.get(file, 'asset.public_url', ''),
113
147
  type: _.get(file, 'asset.metadata.mime', ''),
114
148
  }
149
+
150
+ // If there's linked captions and there's no hard-set captions
151
+ // Fallback to the linked captions
152
+ const linkedCaptions = this.getLinkedCaptions(file)
153
+ if (playlist[index].tracks.length === 0 && linkedCaptions) {
154
+ playlist[index].tracks.push(linkedCaptions)
155
+ }
115
156
  }
116
157
 
117
158
  for (const trackIndex in playlist[index].tracks) {
@@ -126,7 +167,6 @@ export default {
126
167
  default: true,
127
168
  }
128
169
  }
129
-
130
170
  for (const adIndex in playlist[index].ads) {
131
171
  for (const adSourceIndex in playlist[index].ads[adIndex]
132
172
  .sources) {
@@ -138,7 +178,20 @@ export default {
138
178
  src: _.get(file, 'asset.public_url', ''),
139
179
  type: _.get(file, 'asset.metadata.mime', ''),
140
180
  }
181
+
182
+ // If there's linked captions and there's no hard-set captions
183
+ // Fallback to the linked captions
184
+ const linkedCaptions = this.getLinkedCaptions(file)
185
+ if (
186
+ playlist[index].ads[adIndex].tracks.length === 0 &&
187
+ linkedCaptions
188
+ ) {
189
+ playlist[index].ads[adIndex].tracks.push(
190
+ linkedCaptions
191
+ )
192
+ }
141
193
  }
194
+
142
195
  for (const adTrackIndex in playlist[index].ads[adIndex]
143
196
  .tracks) {
144
197
  let file = this.resolveAsset(
@@ -154,13 +207,16 @@ export default {
154
207
  }
155
208
  }
156
209
  }
157
-
210
+ // reset adds to empty array as we aren't using these right now
211
+ // left code above in case we want to implement later
212
+ playlist.forEach((element) => {
213
+ element.ads = []
214
+ })
158
215
  return playlist
159
216
  },
160
217
  },
161
218
  data() {
162
219
  return {
163
- saveState: false,
164
220
  fileTab: null,
165
221
  // Default config settings
166
222
  defaultConfig: {
@@ -230,6 +286,10 @@ export default {
230
286
  },*/
231
287
  ],
232
288
  },
289
+ tracking: {
290
+ hasSkipped: false,
291
+ percentComplete: 0,
292
+ },
233
293
  }
234
294
  },
235
295
  beforeMount() {
@@ -249,11 +309,65 @@ export default {
249
309
  this.$set(this.block, 'assets', [])
250
310
  }
251
311
  },
252
- mounted() {},
253
312
  methods: {
313
+ onSeeking(e) {
314
+ this.tracking.hasSkipped = true
315
+ },
316
+ onTimeupdate(e) {
317
+ // If you were seeking / skipped parts only "resume" if you start back from where you left off
318
+ if (e.current_percent <= this.tracking.percentComplete) {
319
+ this.tracking.hasSkipped = false
320
+ }
321
+
322
+ if (!this.tracking.hasSkipped) {
323
+ if (e.current_percent >= this.tracking.percentComplete) {
324
+ this.tracking.percentComplete = e.current_percent
325
+ }
326
+
327
+ if (!this.completed && this.tracking.percentComplete >= 90) {
328
+ this.emitCompleted()
329
+ }
330
+ }
331
+ },
254
332
  async onBeforeSave() {
255
333
  this.block.body = 'video'
256
334
  },
335
+ getLinkedCaptions(file) {
336
+ // Check to see if the video source has a linked asset and it's a vtt file
337
+ const linkedCaption = _.find(
338
+ _.get(file, 'asset.linked_assets', []),
339
+ function (f) {
340
+ return _.get(f, 'asset.metadata.extension', '') === 'vtt'
341
+ }
342
+ )
343
+
344
+ if (linkedCaption) {
345
+ const foundAsset = this.block.assets.find((a) => {
346
+ return a.file_asset_id === linkedCaption.file_asset_id
347
+ })
348
+
349
+ // The linked captions aren't part of the block.assets
350
+ // Add it so the block knows how to properly load it
351
+ if (!foundAsset) {
352
+ this.block.assets.push(_.cloneDeep(linkedCaption))
353
+ }
354
+ }
355
+
356
+ return linkedCaption || null
357
+ },
358
+
359
+ /**
360
+ * Check if the given text has words, omitting HTML tags and HTML entities
361
+ * @param {string} text - The text to check
362
+ * @returns {boolean} - True if the text has words, false otherwise
363
+ */
364
+ hasWords(text) {
365
+ const strippedText = he
366
+ .decode(text)
367
+ .replace(/<\/?[^>]+(>|$)/g, '') // Remove HTML tags
368
+ .trim()
369
+ return /\b\w+\b/.test(strippedText) // Check if there are any words
370
+ },
257
371
  },
258
372
  }
259
373
  </script>
@@ -1,6 +1,31 @@
1
1
  <template>
2
2
  <div>
3
3
  <v-container class="pa-0">
4
+ <v-row class="pl-3 pr-3">
5
+ <v-text-field
6
+ id="block-settings-title"
7
+ v-model="block.metadata.config.title"
8
+ :autofocus="true"
9
+ :rules="$Validation.getRule('block.title')"
10
+ :counter="$Validation.getLimit('block.title')"
11
+ outlined
12
+ :label="
13
+ $t(
14
+ 'windward.core.components.settings.clickable_icon.title'
15
+ )
16
+ "
17
+ :disabled="render"
18
+ ></v-text-field>
19
+ <v-textarea
20
+ id="block-settings-instructions"
21
+ v-model="block.metadata.config.instructions"
22
+ :rules="$Validation.getRule('block.instructions')"
23
+ :counter="$Validation.getLimit('block.instructions')"
24
+ outlined
25
+ :label="$t('components.content.settings.base.instructions')"
26
+ :disabled="render"
27
+ ></v-textarea>
28
+ </v-row>
4
29
  <v-divider class="my-4 primary"></v-divider>
5
30
  <p>
6
31
  {{ $t('windward.core.components.settings.accordion.items') }}
@@ -22,8 +47,8 @@
22
47
  <v-text-field
23
48
  v-model="block.metadata.config.items[index].header"
24
49
  :autofocus="true"
25
- :counter="50"
26
- :rules="validation.titleRule"
50
+ :rules="$Validation.getRule('shortInput')"
51
+ :counter="$Validation.getLimit('shortInput')"
27
52
  outlined
28
53
  :label="
29
54
  $t('components.content.settings.base.title')
@@ -86,6 +111,7 @@
86
111
  'windward.core.shared.settings.alt_image'
87
112
  )
88
113
  "
114
+ :disabled="render"
89
115
  ></v-text-field>
90
116
  <v-text-field
91
117
  v-model="
@@ -101,6 +127,7 @@
101
127
  'windward.core.shared.settings.aria_described'
102
128
  )
103
129
  "
130
+ :disabled="render"
104
131
  ></v-text-field>
105
132
  <ContentBlockAsset
106
133
  v-model="
@@ -108,7 +135,16 @@
108
135
  "
109
136
  mimes="image/png,image/jpeg"
110
137
  :assets.sync="block.assets"
111
- ></ContentBlockAsset>
138
+ outlined
139
+ >
140
+ <template #title>
141
+ {{
142
+ $t(
143
+ 'windward.core.components.settings.image.place_image'
144
+ )
145
+ }}
146
+ </template>
147
+ </ContentBlockAsset>
112
148
  </v-container>
113
149
  </v-container>
114
150
  </template>
@@ -144,6 +180,7 @@ import Crypto from '~/helpers/Crypto'
144
180
  import BaseContentSettings from '~/components/Content/Settings/BaseContentSettings.js'
145
181
  import TextEditor from '~/components/Text/TextEditor'
146
182
  import SortableExpansionPanel from '~/components/Core/SortableExpansionPanel.vue'
183
+ import Uuid from '~/helpers/Uuid'
147
184
 
148
185
  export default {
149
186
  name: 'AccordionSettings',
@@ -162,6 +199,18 @@ export default {
162
199
  if (_.isEmpty(this.block.metadata.config)) {
163
200
  this.block.metadata.config = {}
164
201
  }
202
+ if (_.isEmpty(this.block.metadata.config.title)) {
203
+ this.block.metadata.config.title = ''
204
+ }
205
+ if (
206
+ _.isEmpty(this.block.metadata.config.instructions) &&
207
+ this.block.id &&
208
+ !Uuid.test(this.block.id)
209
+ ) {
210
+ this.block.metadata.config.instructions = this.$t(
211
+ 'windward.core.components.settings.accordion.instructions'
212
+ )
213
+ }
165
214
  if (_.isEmpty(this.block.metadata.config.editOnContentItem)) {
166
215
  this.block.metadata.config.editOnContentItem = false
167
216
  }
@@ -185,16 +234,6 @@ export default {
185
234
  return {
186
235
  expansionPanelKey: '0',
187
236
  loading: false,
188
- validation: {
189
- titleRule: [
190
- (v) =>
191
- v.length <= 50 ||
192
- this.$t(
193
- 'windward.core.shared.settings.errors.input_limitations',
194
- [50]
195
- ),
196
- ],
197
- },
198
237
  }
199
238
  },
200
239
  beforeDestroy() {
@@ -2,21 +2,23 @@
2
2
  <div>
3
3
  <v-container class="pa-0">
4
4
  <v-text-field
5
+ id="block-settings-title"
6
+ ref="title"
5
7
  v-model="block.metadata.config.title"
6
8
  :autofocus="true"
7
9
  outlined
8
- :counter="50"
9
- :rules="validation.shortInputRules"
10
+ :counter="$Validation.getLimit('block.title')"
11
+ :rules="$Validation.getRule('block.title')"
10
12
  :label="$t('components.content.settings.base.title')"
11
- ref="title"
12
13
  :disabled="render"
13
14
  ></v-text-field>
14
15
  <v-textarea
16
+ id="block-settings-instructions"
15
17
  v-model="block.metadata.config.instructions"
16
18
  outlined
17
19
  auto-grow
18
- :rules="validation.longInputRules"
19
- :counter="255"
20
+ :rules="$Validation.getRule('block.instructions')"
21
+ :counter="$Validation.getLimit('block.instructions')"
20
22
  :label="$t('components.content.settings.base.instructions')"
21
23
  :disabled="render"
22
24
  ></v-textarea>
@@ -25,10 +27,10 @@
25
27
  <v-container class="pa-0">
26
28
  <TextEditor
27
29
  v-model="block.metadata.config.block_quote.quote"
28
- :rules="validation.longInputRules"
30
+ :rules="$Validation.getRule('longInput')"
31
+ :counter="$Validation.getLimit('longInput')"
29
32
  outlined
30
33
  auto-grow
31
- :counter="255"
32
34
  :height="200"
33
35
  :label="
34
36
  $t('windward.core.components.settings.block_quote.body')
@@ -40,8 +42,8 @@
40
42
  <v-container class="pa-0">
41
43
  <v-text-field
42
44
  v-model="block.metadata.config.block_quote.author"
43
- :rules="validation.shortInputRules"
44
- :counter="50"
45
+ :rules="$Validation.getRule('shortInput')"
46
+ :counter="$Validation.getLimit('shortInput')"
45
47
  outlined
46
48
  auto-grow
47
49
  :label="
@@ -52,8 +54,8 @@
52
54
  <v-text-field
53
55
  v-model="block.metadata.config.block_quote.author_title"
54
56
  outlined
55
- :rules="validation.shortInputRules"
56
- :counter="50"
57
+ :rules="$Validation.getRule('shortInput')"
58
+ :counter="$Validation.getLimit('shortInput')"
57
59
  auto-grow
58
60
  :label="
59
61
  $t('windward.core.components.settings.block_quote.title')
@@ -62,8 +64,8 @@
62
64
  ></v-text-field>
63
65
  <v-text-field
64
66
  v-model="block.metadata.config.block_quote.organization"
65
- :rules="validation.shortInputRules"
66
- :counter="50"
67
+ :rules="$Validation.getRule('shortInput')"
68
+ :counter="$Validation.getLimit('shortInput')"
67
69
  outlined
68
70
  auto-grow
69
71
  :label="$t('windward.core.components.settings.block_quote.org')"
@@ -72,8 +74,8 @@
72
74
  <v-text-field
73
75
  v-model="block.metadata.config.block_quote.source_title"
74
76
  outlined
75
- :rules="validation.shortInputRules"
76
- :counter="50"
77
+ :rules="$Validation.getRule('shortInput')"
78
+ :counter="$Validation.getLimit('shortInput')"
77
79
  auto-grow
78
80
  :label="
79
81
  $t(
@@ -182,24 +184,6 @@ export default {
182
184
  value: 'online_journal',
183
185
  },
184
186
  ],
185
- validation: {
186
- shortInputRules: [
187
- (v) =>
188
- v.length <= 50 ||
189
- this.$t(
190
- 'windward.core.shared.settings.errors.input_limitations',
191
- [50]
192
- ),
193
- ],
194
- longInputRules: [
195
- (v) =>
196
- v.length <= 255 ||
197
- this.$t(
198
- 'windward.core.shared.settings.errors.input_limitations',
199
- [255]
200
- ),
201
- ],
202
- },
203
187
  }
204
188
  },
205
189
  methods: {},
@@ -3,12 +3,12 @@
3
3
  <v-container class="pa-0">
4
4
  <v-col class="pa-0">
5
5
  <v-text-field
6
+ id="block-settings-title"
6
7
  v-model="block.metadata.config.title"
7
8
  :autofocus="true"
8
- :rules="validation.shortInputRules"
9
- :counter="50"
9
+ :rules="$Validation.getRule('block.title')"
10
+ :counter="$Validation.getLimit('block.title')"
10
11
  outlined
11
- id="title"
12
12
  :label="
13
13
  $t(
14
14
  'windward.core.components.settings.clickable_icon.title'
@@ -17,9 +17,10 @@
17
17
  :disabled="render"
18
18
  ></v-text-field>
19
19
  <v-textarea
20
+ id="block-settings-instructions"
20
21
  v-model="block.metadata.config.description"
21
- :rules="validation.instructionRule"
22
- :counter="255"
22
+ :rules="$Validation.getRule('block.instructions')"
23
+ :counter="$Validation.getLimit('block.instructions')"
23
24
  outlined
24
25
  :label="$t('components.content.settings.base.instructions')"
25
26
  :disabled="render"
@@ -142,6 +143,7 @@
142
143
  [index + 1]
143
144
  )
144
145
  "
146
+ :rules="validation.iconRules"
145
147
  :disabled="render"
146
148
  ></TextIconPicker>
147
149
 
@@ -156,16 +158,25 @@
156
158
  class="mb-4"
157
159
  mimes="image/jpeg,image/png,image/gif"
158
160
  :disabled="render"
161
+ outlined
159
162
  @click:file="onFileSelect($event, index)"
160
- ></ContentBlockAsset>
163
+ >
164
+ <template #title>
165
+ {{
166
+ $t(
167
+ 'windward.core.components.settings.image.place_image'
168
+ )
169
+ }}
170
+ </template>
171
+ </ContentBlockAsset>
161
172
  <v-text-field
162
173
  v-model="
163
174
  block.metadata.config.items[index].title
164
175
  "
165
176
  :id="'item-' + index + '-title'"
166
177
  outlined
167
- :counter="50"
168
- :rules="validation.shortInputRules"
178
+ :rules="$Validation.getRule('shortInput')"
179
+ :counter="$Validation.getLimit('shortInput')"
169
180
  :label="
170
181
  $t(
171
182
  'windward.core.components.settings.clickable_icon.item_title'
@@ -237,21 +248,24 @@ export default {
237
248
  data() {
238
249
  return {
239
250
  validation: {
240
- shortInputRules: [
241
- (v) =>
242
- v.length <= 50 ||
243
- this.$t(
244
- 'windward.core.shared.settings.errors.input_limitations',
245
- [50]
246
- ),
247
- ],
248
- instructionRule: [
249
- (v) =>
250
- v.length <= 255 ||
251
- this.$t(
252
- 'windward.core.shared.settings.errors.input_limitations',
253
- [255]
254
- ),
251
+ iconRules: [
252
+ (v) => {
253
+ if (v) {
254
+ const isMDI = v.startsWith('mdi')
255
+ if (isMDI) {
256
+ return true
257
+ } else if (v.length >= 5) {
258
+ return this.$t(
259
+ 'shared.forms.errors.number_lt',
260
+ [4]
261
+ )
262
+ } else {
263
+ return true
264
+ }
265
+ } else {
266
+ return true
267
+ }
268
+ },
255
269
  ],
256
270
  },
257
271
  }
@@ -6,17 +6,17 @@
6
6
  :autofocus="true"
7
7
  ref="title"
8
8
  outlined
9
- :counter="50"
10
- :rules="validation.shortInputRules"
9
+ :rules="$Validation.getRule('block.title')"
10
+ :counter="$Validation.getLimit('block.title')"
11
11
  :label="$t('components.content.settings.base.title')"
12
12
  :disabled="render"
13
13
  ></v-text-field>
14
14
  <v-textarea
15
15
  v-model="block.metadata.config.instructions"
16
16
  outlined
17
- :rules="validation.instructionRule"
17
+ :rules="$Validation.getRule('block.instructions')"
18
+ :counter="$Validation.getLimit('block.instructions')"
18
19
  auto-grow
19
- :counter="255"
20
20
  :label="$t('components.content.settings.base.instructions')"
21
21
  :disabled="render"
22
22
  ></v-textarea>
@@ -42,8 +42,8 @@
42
42
  <v-container :key="expansionPanelKey">
43
43
  <v-text-field
44
44
  v-model="block.metadata.config.emails[index].from"
45
- :rules="validation.shortInputRules"
46
- :counter="50"
45
+ :rules="$Validation.getRule('shortInput')"
46
+ :counter="$Validation.getLimit('shortInput')"
47
47
  outlined
48
48
  :label="
49
49
  $t(
@@ -54,8 +54,8 @@
54
54
  ></v-text-field>
55
55
  <v-text-field
56
56
  v-model="block.metadata.config.emails[index].to"
57
- :rules="validation.shortInputRules"
58
- :counter="50"
57
+ :rules="$Validation.getRule('shortInput')"
58
+ :counter="$Validation.getLimit('shortInput')"
59
59
  outlined
60
60
  :label="
61
61
  $t('windward.core.components.settings.email.to')
@@ -64,8 +64,8 @@
64
64
  ></v-text-field>
65
65
  <v-text-field
66
66
  v-model="block.metadata.config.emails[index].cc"
67
- :rules="validation.shortInputRules"
68
- :counter="50"
67
+ :rules="$Validation.getRule('shortInput')"
68
+ :counter="$Validation.getLimit('shortInput')"
69
69
  outlined
70
70
  :label="
71
71
  $t('windward.core.components.settings.email.cc')
@@ -76,8 +76,8 @@
76
76
  v-model="
77
77
  block.metadata.config.emails[index].subject
78
78
  "
79
- :rules="validation.shortInputRules"
80
- :counter="50"
79
+ :rules="$Validation.getRule('shortInput')"
80
+ :counter="$Validation.getLimit('shortInput')"
81
81
  outlined
82
82
  :label="
83
83
  $t(
@@ -213,24 +213,6 @@ export default {
213
213
  loading: false,
214
214
  expansionPanelKey: 0,
215
215
  editingPanel: 0,
216
- validation: {
217
- shortInputRules: [
218
- (v) =>
219
- v.length <= 50 ||
220
- this.$t(
221
- 'windward.core.shared.settings.errors.input_limitations',
222
- [50]
223
- ),
224
- ],
225
- instructionRule: [
226
- (v) =>
227
- v.length <= 255 ||
228
- this.$t(
229
- 'windward.core.shared.settings.errors.input_limitations',
230
- [255]
231
- ),
232
- ],
233
- },
234
216
  }
235
217
  },
236
218
  beforeDestroy() {