@windward/core 0.3.0 → 0.4.1

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 (63) hide show
  1. package/components/Content/Blocks/Accordion.vue +37 -0
  2. package/components/Content/Blocks/BlockQuote.vue +2 -2
  3. package/components/Content/Blocks/ClickableIcons.vue +108 -21
  4. package/components/Content/Blocks/Email.vue +19 -6
  5. package/components/Content/Blocks/Feedback.vue +12 -5
  6. package/components/Content/Blocks/Image.vue +47 -19
  7. package/components/Content/Blocks/OpenResponse.vue +7 -3
  8. package/components/Content/Blocks/OpenResponseCollate.vue +1 -1
  9. package/components/Content/Blocks/ScenarioChoice.vue +2 -2
  10. package/components/Content/Blocks/UserUpload/DisplayUserFilesTable.vue +2 -0
  11. package/components/Content/Blocks/UserUpload.vue +1 -0
  12. package/components/Content/Blocks/Video.vue +82 -11
  13. package/components/Navigation/Items/AskTheExpert.vue +1 -0
  14. package/components/Settings/AccordionSettings.vue +55 -0
  15. package/components/Settings/ClickableIconsSettings.vue +89 -8
  16. package/components/Settings/EmailSettings.vue +6 -10
  17. package/components/Settings/FeedbackSettings.vue +1 -0
  18. package/components/Settings/ImageSettings.vue +142 -39
  19. package/components/Settings/MathSettings.vue +1 -1
  20. package/components/Settings/OpenResponseSettings.vue +1 -2
  21. package/components/Settings/ScenarioChoiceSettings.vue +1 -0
  22. package/components/Settings/TabSettings.vue +7 -1
  23. package/components/Settings/TextEditorSettings.vue +3 -2
  24. package/components/Settings/UserUploadSettings.vue +1 -1
  25. package/components/Settings/VideoSettings.vue +102 -63
  26. package/components/utils/ContentViewer.vue +6 -1
  27. package/components/utils/FillInBlank/FillInBlankInput.vue +3 -0
  28. package/components/utils/MathExpressionEditor.vue +37 -11
  29. package/components/utils/MathLiveWrapper.vue +47 -25
  30. package/components/utils/TinyMCEWrapper.vue +214 -34
  31. package/components/utils/assets/tinymce/content/dark/content.scss +4 -0
  32. package/components/utils/assets/tinymce/{css/content.scss → content/global.scss} +38 -37
  33. package/components/utils/assets/tinymce/content/light/content.scss +4 -0
  34. package/components/utils/assets/tinymce/ui/dark/content.scss +803 -0
  35. package/components/utils/assets/tinymce/ui/dark/skin.scss +4727 -0
  36. package/components/utils/assets/tinymce/ui/global.scss +19 -0
  37. package/components/utils/assets/tinymce/ui/light/content.scss +822 -0
  38. package/components/utils/assets/tinymce/ui/light/skin.scss +4731 -0
  39. package/components/utils/glossary/CourseGlossary.vue +3 -1
  40. package/config/tinymce.config.ts +32 -20
  41. package/helpers/FillInBlankHelper.ts +34 -28
  42. package/helpers/GlossaryHelper.ts +90 -73
  43. package/helpers/MathHelper.ts +108 -28
  44. package/helpers/tinymce/WindwardPlugins.ts +335 -0
  45. package/i18n/en-US/components/settings/clickable_icon.ts +2 -0
  46. package/i18n/en-US/components/settings/image.ts +6 -1
  47. package/i18n/en-US/components/utils/tiny_mce_wrapper.ts +1 -0
  48. package/i18n/en-US/shared/settings.ts +3 -0
  49. package/i18n/es-ES/components/settings/clickable_icon.ts +2 -0
  50. package/i18n/es-ES/components/settings/image.ts +8 -1
  51. package/i18n/es-ES/components/utils/tiny_mce_wrapper.ts +1 -0
  52. package/i18n/es-ES/shared/settings.ts +3 -0
  53. package/i18n/sv-SE/components/settings/clickable_icon.ts +2 -0
  54. package/i18n/sv-SE/components/settings/image.ts +6 -1
  55. package/i18n/sv-SE/components/utils/tiny_mce_wrapper.ts +1 -0
  56. package/i18n/sv-SE/shared/settings.ts +3 -0
  57. package/package.json +6 -4
  58. package/test/Components/Settings/AccordionSettings.spec.js +16 -2
  59. package/test/__mocks__/contentBlockMock.js +6 -0
  60. package/test/__mocks__/contentSettingsMock.js +6 -0
  61. package/test/helpers/MathHelper.spec.js +36 -4
  62. package/tsconfig.json +4 -0
  63. package/helpers/tinymce/plugin.ts +0 -208
@@ -21,14 +21,14 @@
21
21
  type="image, image, list-item-avatar"
22
22
  class="reload-skeleton"
23
23
  ></v-skeleton-loader>
24
- <h3 v-if="block.metadata.config.title" class="pl-4">
24
+ <h2 v-if="block.metadata.config.title" class="pl-4">
25
25
  {{ block.metadata.config.title }}
26
- </h3>
26
+ </h2>
27
27
  <VuetifyPlayer
28
28
  v-if="hasSource"
29
29
  :language="$i18n && $i18n.locale ? $i18n.locale : 'en-US'"
30
30
  :type="block.metadata.config.type"
31
- :playlist="block.metadata.config.playlist"
31
+ :playlist="linkedPlaylist"
32
32
  :autoplay="block.metadata.config.attributes.autoplay"
33
33
  :autopictureinpicture="
34
34
  block.metadata.config.attributes.autopictureinpicture
@@ -48,7 +48,7 @@
48
48
  :loop="block.metadata.config.attributes.loop"
49
49
  :muted="block.metadata.config.attributes.muted"
50
50
  :playsinline="block.metadata.config.attributes.playsinline"
51
- :poster="block.metadata.config.attributes.poster"
51
+ :poster="linkedPosterPublicUrl"
52
52
  :preload="block.metadata.config.attributes.preload"
53
53
  :captionsmenu="block.metadata.config.attributes.captionsmenu"
54
54
  :playlistmenu="block.metadata.config.attributes.playlistmenu"
@@ -63,14 +63,12 @@
63
63
  <script>
64
64
  import _ from 'lodash'
65
65
  import VuetifyPlayer from '@mindedge/vuetify-player'
66
- import ContentBlockAsset from '~/components/Content/ContentBlockAsset.vue'
67
66
  import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
68
67
 
69
68
  export default {
70
69
  name: 'ContentBlockVideo',
71
70
  components: {
72
71
  VuetifyPlayer,
73
- ContentBlockAsset,
74
72
  },
75
73
  extends: BaseContentBlock,
76
74
  computed: {
@@ -89,6 +87,73 @@ export default {
89
87
  )
90
88
  )
91
89
  },
90
+ linkedPosterPublicUrl() {
91
+ const file = this.resolveAsset(
92
+ _.get(this.block, 'metadata.config.attributes.poster', null)
93
+ )
94
+ return _.get(file, 'asset.public_url')
95
+ },
96
+ /**
97
+ * Resolve assets to their playlist items
98
+ */
99
+ linkedPlaylist() {
100
+ const playlist = _.cloneDeep(this.block.metadata.config.playlist)
101
+
102
+ for (const index in playlist) {
103
+ for (const sourceIndex in playlist[index].sources) {
104
+ let file = this.resolveAsset(
105
+ playlist[index].sources[sourceIndex]
106
+ )
107
+
108
+ playlist[index].sources[sourceIndex] = {
109
+ src: _.get(file, 'asset.public_url', ''),
110
+ type: _.get(file, 'asset.metadata.mime', ''),
111
+ }
112
+ }
113
+
114
+ for (const trackIndex in playlist[index].tracks) {
115
+ let file = this.resolveAsset(
116
+ playlist[index].tracks[trackIndex]
117
+ )
118
+
119
+ playlist[index].tracks[trackIndex] = {
120
+ src: _.get(file, 'asset.public_url', ''),
121
+ kind: 'captions',
122
+ srclang: 'en-US',
123
+ default: true,
124
+ }
125
+ }
126
+
127
+ for (const adIndex in playlist[index].ads) {
128
+ for (const adSourceIndex in playlist[index].ads[adIndex]
129
+ .sources) {
130
+ let file = this.resolveAsset(
131
+ playlist[index].ads[adIndex].sources[adSourceIndex]
132
+ )
133
+
134
+ playlist[index].ads[adIndex].sources[adSourceIndex] = {
135
+ src: _.get(file, 'asset.public_url', ''),
136
+ type: _.get(file, 'asset.metadata.mime', ''),
137
+ }
138
+ }
139
+ for (const adTrackIndex in playlist[index].ads[adIndex]
140
+ .tracks) {
141
+ let file = this.resolveAsset(
142
+ playlist[index].ads[adIndex].tracks[adTrackIndex]
143
+ )
144
+
145
+ playlist[index].ads[adIndex].tracks[adTrackIndex] = {
146
+ src: _.get(file, 'asset.public_url', ''),
147
+ kind: 'captions',
148
+ srclang: 'en-US',
149
+ default: true,
150
+ }
151
+ }
152
+ }
153
+ }
154
+
155
+ return playlist
156
+ },
92
157
  },
93
158
  data() {
94
159
  return {
@@ -170,13 +235,19 @@ export default {
170
235
  if (_.isEmpty(this.block.metadata.config)) {
171
236
  this.block.metadata.config = this.defaultConfig
172
237
  }
238
+ // If no playback rates were set then re-init it as an array with the rate 1 or normal only
239
+ if (
240
+ _.isEmpty(
241
+ _.get(this.block, 'metadata.config.attributes.playbackrates')
242
+ )
243
+ ) {
244
+ this.block.metadata.config.attributes.playbackrates = [1]
245
+ }
246
+ if (_.isEmpty(this.block.assets)) {
247
+ this.$set(this.block, 'assets', [])
248
+ }
173
249
  },
174
250
  mounted() {
175
- // TODO Check privs
176
- //const hasPrivs = true
177
- //if (hasPrivs) {
178
- //this.blockSettings = this.initEditorSettings(this.settings)
179
- //}
180
251
  this.saveKey = this.settingsKey()
181
252
  },
182
253
  methods: {
@@ -92,6 +92,7 @@
92
92
  >
93
93
  <v-btn
94
94
  class="primary"
95
+ elevation="0"
95
96
  :disabled="valid"
96
97
  @click="onSubmit"
97
98
  >{{
@@ -40,6 +40,7 @@
40
40
  ></v-text-field>
41
41
  <v-btn
42
42
  text
43
+ elevation="0"
43
44
  :disabled="render"
44
45
  @click="
45
46
  onToggleExpand(
@@ -79,6 +80,53 @@
79
80
  "
80
81
  :disabled="render"
81
82
  ></TextEditor>
83
+ <v-container class="pa-0 pt-3">
84
+ <h4>
85
+ {{
86
+ $t(
87
+ 'windward.core.shared.settings.upload_file'
88
+ )
89
+ }}
90
+ </h4>
91
+ <v-text-field
92
+ v-model="
93
+ block.metadata.config.items[index]
94
+ .altText
95
+ "
96
+ class="pt-3 pb-3"
97
+ :hide-details="true"
98
+ dense
99
+ outlined
100
+ :autofocus="true"
101
+ :label="
102
+ $t(
103
+ 'windward.core.shared.settings.alt_image'
104
+ )
105
+ "
106
+ ></v-text-field>
107
+ <v-text-field
108
+ v-model="
109
+ block.metadata.config.items[index]
110
+ .ariaDescribedBy
111
+ "
112
+ class="pt-3 pb-3"
113
+ :hide-details="true"
114
+ dense
115
+ outlined
116
+ :label="
117
+ $t(
118
+ 'windward.core.shared.settings.aria_described'
119
+ )
120
+ "
121
+ ></v-text-field>
122
+ <ContentBlockAsset
123
+ v-model="
124
+ block.metadata.config.items[index].file
125
+ "
126
+ mimes="image/png,image/jpeg"
127
+ :assets.sync="block.assets"
128
+ ></ContentBlockAsset>
129
+ </v-container>
82
130
  </v-container>
83
131
  </template>
84
132
  </SortableExpansionPanel>
@@ -87,6 +135,7 @@
87
135
  <v-row justify="center" class="my-4">
88
136
  <v-btn
89
137
  color="primary"
138
+ elevation="0"
90
139
  :disabled="render"
91
140
  @click="onAddElement"
92
141
  ><v-icon>mdi-plus</v-icon
@@ -141,6 +190,9 @@ export default {
141
190
  header: '',
142
191
  expand: false,
143
192
  content: '',
193
+ file: null,
194
+ altText: '',
195
+ ariaDescribedBy: '',
144
196
  }
145
197
  this.block.metadata.config.items = []
146
198
  this.block.metadata.config.items.push(defaultObject)
@@ -180,6 +232,9 @@ export default {
180
232
  header: '',
181
233
  expand: false,
182
234
  content: '',
235
+ file: null,
236
+ altText: '',
237
+ ariaDescribedBy: '',
183
238
  }
184
239
  this.block.metadata.config.items.push(default_item)
185
240
  this.block.metadata.config.selectedPanels =
@@ -60,6 +60,15 @@
60
60
  "
61
61
  :disabled="render"
62
62
  ></v-switch>
63
+ <v-switch
64
+ v-model="block.metadata.config.display.large_icon"
65
+ :label="
66
+ $t(
67
+ 'windward.core.components.settings.clickable_icon.display.large_icon'
68
+ )
69
+ "
70
+ :disabled="render"
71
+ ></v-switch>
63
72
  <v-switch
64
73
  v-model="block.metadata.config.display.autocolor"
65
74
  :label="
@@ -77,12 +86,25 @@
77
86
  @click:close="onRemoveElement"
78
87
  >
79
88
  <template #header="{ item }">
80
- <v-icon v-if="item.icon && isIcon(item.icon)">{{
81
- item.icon
82
- }}</v-icon>
83
- <span v-else-if="item.icon && !isIcon(item.icon)">{{
84
- item.icon
85
- }}</span>
89
+ <v-avatar v-if="item.iconImage && item.iconAsset">
90
+ <v-img :src="getImagePublicUrl(item.iconAsset)" />
91
+ </v-avatar>
92
+ <v-icon
93
+ v-else-if="
94
+ !item.iconImage &&
95
+ item.icon &&
96
+ isIcon(item.icon)
97
+ "
98
+ >{{ item.icon }}</v-icon
99
+ >
100
+ <span
101
+ v-else-if="
102
+ !item.iconImage &&
103
+ item.icon &&
104
+ !isIcon(item.icon)
105
+ "
106
+ >{{ item.icon }}</span
107
+ >
86
108
  <span v-else class="font-italic">
87
109
  {{
88
110
  $t(
@@ -93,7 +115,24 @@
93
115
  </template>
94
116
  <template #body="{ index }">
95
117
  <v-container>
118
+ <v-switch
119
+ v-model="
120
+ block.metadata.config.items[index].iconImage
121
+ "
122
+ :label="
123
+ $t(
124
+ 'windward.core.components.settings.clickable_icon.icon_image'
125
+ )
126
+ "
127
+ @click="onClickToggleIconImage(index)"
128
+ :disabled="render"
129
+ ></v-switch>
130
+
96
131
  <TextIconPicker
132
+ v-if="
133
+ !block.metadata.config.items[index]
134
+ .iconImage
135
+ "
97
136
  v-model="
98
137
  block.metadata.config.items[index].icon
99
138
  "
@@ -105,6 +144,20 @@
105
144
  "
106
145
  :disabled="render"
107
146
  ></TextIconPicker>
147
+
148
+ <ContentBlockAsset
149
+ v-if="
150
+ block.metadata.config.items[index].iconImage
151
+ "
152
+ v-model="
153
+ block.metadata.config.items[index].iconAsset
154
+ "
155
+ :assets.sync="block.assets"
156
+ class="mb-4"
157
+ mimes="image/jpeg,image/png,image/gif"
158
+ :disabled="render"
159
+ @click:file="onFileSelect($event, index)"
160
+ ></ContentBlockAsset>
108
161
  <v-text-field
109
162
  v-model="
110
163
  block.metadata.config.items[index].title
@@ -118,7 +171,6 @@
118
171
  "
119
172
  :disabled="render"
120
173
  ></v-text-field>
121
-
122
174
  <ColorPicker
123
175
  v-if="!block.metadata.config.display.autocolor"
124
176
  v-model="
@@ -149,7 +201,11 @@
149
201
  </SortableExpansionPanel>
150
202
  </v-col>
151
203
  <v-row justify="center" class="my-4">
152
- <v-btn color="primary" :disabled="render" @click="onAddElement"
204
+ <v-btn
205
+ color="primary"
206
+ elevation="0"
207
+ :disabled="render"
208
+ @click="onAddElement"
153
209
  ><v-icon>mdi-plus</v-icon
154
210
  >{{ $t('shared.forms.add') }}</v-btn
155
211
  >
@@ -164,6 +220,7 @@ import TextEditor from '~/components/Text/TextEditor'
164
220
  import TextIconPicker from '~/components/Core/TextIconPicker.vue'
165
221
  import ColorPicker from '~/components/Core/ColorPicker.vue'
166
222
  import SortableExpansionPanel from '~/components/Core/SortableExpansionPanel.vue'
223
+ import ContentBlockAsset from '~/components/Content/ContentBlockAsset.vue'
167
224
 
168
225
  export default {
169
226
  name: 'ClickableIconsSettings',
@@ -172,6 +229,7 @@ export default {
172
229
  TextEditor,
173
230
  TextIconPicker,
174
231
  ColorPicker,
232
+ ContentBlockAsset,
175
233
  },
176
234
  extends: BaseContentSettings,
177
235
 
@@ -202,6 +260,7 @@ export default {
202
260
  show_background: false,
203
261
  round_icon: false,
204
262
  italic_icon: false,
263
+ large_icon: false,
205
264
  autocolor: true,
206
265
  }
207
266
  }
@@ -218,6 +277,8 @@ export default {
218
277
  onAddElement() {
219
278
  const defaultObject = {
220
279
  icon: '',
280
+ iconAsset: null,
281
+ iconImage: false,
221
282
  title: '',
222
283
  body: '<p></p>',
223
284
  color: {
@@ -233,6 +294,26 @@ export default {
233
294
  isIcon(str) {
234
295
  return str && _.isString(str) && str.indexOf('mdi-') === 0
235
296
  },
297
+ getImagePublicUrl(fileAssetId) {
298
+ const foundAsset = this.resolveAsset(fileAssetId)
299
+
300
+ return _.get(foundAsset, 'asset.public_url', null)
301
+ },
302
+ onClickToggleIconImage(index) {
303
+ // We're switching between images / text. Clear the relevant fields
304
+ this.block.metadata.config.items[index].icon = ''
305
+ this.block.metadata.config.items[index].iconAsset = null
306
+ },
307
+ onFileSelect(file, index) {
308
+ // file = null when you remove a file
309
+ if (_.isEmpty(file)) {
310
+ this.block.metadata.config.items[index].icon = null
311
+ } else {
312
+ this.block.assets.push(file)
313
+ this.block.metadata.config.items[index].icon =
314
+ file.file_asset_id
315
+ }
316
+ },
236
317
  },
237
318
  }
238
319
  </script>
@@ -85,6 +85,7 @@
85
85
  index
86
86
  )
87
87
  "
88
+ elevation="0"
88
89
  text
89
90
  :disabled="render"
90
91
  >
@@ -125,7 +126,11 @@
125
126
  </v-container>
126
127
  <v-container class="pa-0">
127
128
  <v-row justify="center" class="my-4">
128
- <v-btn color="primary" :disabled="render" @click="onAddElement"
129
+ <v-btn
130
+ color="primary"
131
+ elevation="0"
132
+ :disabled="render"
133
+ @click="onAddElement"
129
134
  ><v-icon>mdi-plus</v-icon
130
135
  >{{
131
136
  $t('windward.core.components.settings.email.add')
@@ -210,15 +215,6 @@ export default {
210
215
  this.block.metadata.config.selectedPanels = 0
211
216
  },
212
217
  methods: {
213
- onBeforeSave() {
214
- this.block.metadata.config.emails.forEach((element) => {
215
- if (element.from) {
216
- let matches = element.from.match(/\b(\w)/g)
217
- element.initials = matches.join('')
218
- }
219
- element.tinymce_expand = false
220
- })
221
- },
222
218
  onUpdatePanel($event) {
223
219
  if ($event !== this.block.metadata.config.selectedPanels) {
224
220
  //catch click event to open selected panel to edit
@@ -10,6 +10,7 @@
10
10
  <v-btn
11
11
  class="preset-btn text-sm-body-2 text-none"
12
12
  color="primary"
13
+ elevation="0"
13
14
  outlined
14
15
  v-bind="attrs"
15
16
  v-on="on"