@windward/core 0.9.1 → 0.10.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.
- package/CHANGELOG.md +3 -0
- package/components/Content/Blocks/Accordion.vue +14 -21
- package/components/Content/Blocks/ClickableIcons.vue +13 -2
- package/components/Content/Blocks/Video.vue +79 -25
- package/components/Settings/AccordionSettings.vue +10 -49
- package/components/Settings/ClickableIconsSettings.vue +13 -21
- package/components/Settings/TextEditorSettings.vue +6 -4
- package/components/Settings/VideoSettings/SourcePicker.vue +1 -1
- package/components/Settings/VideoSettings.vue +7 -2
- package/components/utils/TinyMCEWrapper.vue +17 -2
- package/components/utils/glossary/GlossaryToolTip.vue +6 -6
- package/i18n/en-US/components/content/blocks/video.ts +1 -1
- package/i18n/en-US/components/settings/video.ts +8 -4
- package/i18n/en-US/shared/settings.ts +1 -1
- package/i18n/es-ES/components/content/blocks/video.ts +1 -1
- package/i18n/es-ES/components/settings/video.ts +8 -4
- package/i18n/es-ES/shared/settings.ts +1 -1
- package/i18n/sv-SE/components/content/blocks/video.ts +1 -1
- package/i18n/sv-SE/components/settings/video.ts +8 -4
- package/i18n/sv-SE/shared/settings.ts +1 -1
- package/package.json +2 -2
- package/pages/glossary.vue +1 -1
- package/test/Components/Settings/AccordionSettings.spec.js +2 -6
- package/test/Components/Settings/ClickableIconsSettings.spec.js +45 -0
- package/test/__mocks__/modelMock.js +4 -0
package/CHANGELOG.md
CHANGED
|
@@ -59,26 +59,19 @@
|
|
|
59
59
|
"
|
|
60
60
|
></TextEditor>
|
|
61
61
|
</v-container>
|
|
62
|
-
<v-container
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
62
|
+
<v-container
|
|
63
|
+
v-if="
|
|
64
|
+
block.metadata.config.items[itemIndex].fileConfig
|
|
65
|
+
.asset
|
|
66
|
+
"
|
|
67
|
+
>
|
|
68
|
+
<ImageAssetViewer
|
|
69
|
+
v-model="
|
|
66
70
|
block.metadata.config.items[itemIndex]
|
|
67
|
-
.
|
|
68
|
-
"
|
|
69
|
-
:alt="
|
|
70
|
-
getImageAlt(
|
|
71
|
-
block.metadata.config.items[itemIndex].file,
|
|
72
|
-
block.metadata.config.items[itemIndex]
|
|
73
|
-
.altText
|
|
74
|
-
)
|
|
75
|
-
"
|
|
76
|
-
:src="
|
|
77
|
-
getImagePublicUrl(
|
|
78
|
-
block.metadata.config.items[itemIndex].file
|
|
79
|
-
)
|
|
71
|
+
.fileConfig
|
|
80
72
|
"
|
|
81
|
-
|
|
73
|
+
:assets="block.assets"
|
|
74
|
+
></ImageAssetViewer>
|
|
82
75
|
</v-container>
|
|
83
76
|
</v-expansion-panel-content>
|
|
84
77
|
</v-expansion-panel>
|
|
@@ -89,6 +82,7 @@
|
|
|
89
82
|
<script>
|
|
90
83
|
import _ from 'lodash'
|
|
91
84
|
import Crypto from '~/helpers/Crypto'
|
|
85
|
+
import ImageAssetViewer from '~/components/Content/ImageAssetViewer.vue'
|
|
92
86
|
import TextEditor from '~/components/Text/TextEditor'
|
|
93
87
|
import TextViewer from '~/components/Text/TextViewer'
|
|
94
88
|
import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
|
|
@@ -98,6 +92,7 @@ export default {
|
|
|
98
92
|
components: {
|
|
99
93
|
TextEditor,
|
|
100
94
|
TextViewer,
|
|
95
|
+
ImageAssetViewer,
|
|
101
96
|
},
|
|
102
97
|
extends: BaseContentBlock,
|
|
103
98
|
beforeMount() {
|
|
@@ -118,9 +113,7 @@ export default {
|
|
|
118
113
|
header: '',
|
|
119
114
|
expand: false,
|
|
120
115
|
content: '',
|
|
121
|
-
|
|
122
|
-
altText: '',
|
|
123
|
-
ariaDescribedBy: '',
|
|
116
|
+
fileConfig: {},
|
|
124
117
|
}
|
|
125
118
|
this.block.metadata.config.items = []
|
|
126
119
|
this.block.metadata.config.items.push(defaultObject)
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
@click="item.active = !item.active"
|
|
28
28
|
>
|
|
29
29
|
<v-avatar
|
|
30
|
-
v-if="item.iconImage && item.
|
|
30
|
+
v-if="item.iconImage && item.fileConfig"
|
|
31
31
|
class="clickable--image"
|
|
32
32
|
:rounded="
|
|
33
33
|
block.metadata.config.display.round_icon
|
|
@@ -36,7 +36,12 @@
|
|
|
36
36
|
"
|
|
37
37
|
size="100%"
|
|
38
38
|
>
|
|
39
|
-
<
|
|
39
|
+
<ImageAssetViewer
|
|
40
|
+
v-model="item.fileConfig"
|
|
41
|
+
:assets="block.assets"
|
|
42
|
+
class="image-asset-viewer"
|
|
43
|
+
:inherit-sizing="true"
|
|
44
|
+
></ImageAssetViewer>
|
|
40
45
|
</v-avatar>
|
|
41
46
|
<v-icon
|
|
42
47
|
v-else-if="isIcon(item.icon)"
|
|
@@ -77,11 +82,13 @@ import _ from 'lodash'
|
|
|
77
82
|
import he from 'he'
|
|
78
83
|
import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
|
|
79
84
|
import TextViewer from '~/components/Text/TextViewer'
|
|
85
|
+
import ImageAssetViewer from '~/components/Content/ImageAssetViewer.vue'
|
|
80
86
|
|
|
81
87
|
export default {
|
|
82
88
|
name: 'ClickableIcons',
|
|
83
89
|
components: {
|
|
84
90
|
TextViewer,
|
|
91
|
+
ImageAssetViewer,
|
|
85
92
|
},
|
|
86
93
|
extends: BaseContentBlock,
|
|
87
94
|
beforeMount() {
|
|
@@ -295,4 +302,8 @@ button.button-icon.button-icon--rounded {
|
|
|
295
302
|
font-size: 2.5rem;
|
|
296
303
|
}
|
|
297
304
|
}
|
|
305
|
+
.image-asset-viewer {
|
|
306
|
+
height: inherit;
|
|
307
|
+
width: inherit;
|
|
308
|
+
}
|
|
298
309
|
</style>
|
|
@@ -7,30 +7,9 @@
|
|
|
7
7
|
{{ block.metadata.config.description }}
|
|
8
8
|
</p>
|
|
9
9
|
|
|
10
|
-
<v-card v-if="render && !hasSource">
|
|
11
|
-
<v-card-title>
|
|
12
|
-
<v-icon class="mr-2">mdi-cloud-question</v-icon>
|
|
13
|
-
{{
|
|
14
|
-
$t(
|
|
15
|
-
'windward.core.components.content.blocks.video.not_configured_title'
|
|
16
|
-
)
|
|
17
|
-
}}
|
|
18
|
-
</v-card-title>
|
|
19
|
-
<v-card-text>{{
|
|
20
|
-
$t('windward.core.components.content.blocks.video.edit_prompt')
|
|
21
|
-
}}</v-card-text>
|
|
22
|
-
</v-card>
|
|
23
|
-
|
|
24
|
-
<v-skeleton-loader
|
|
25
|
-
v-if="!render && !hasSource"
|
|
26
|
-
type="image, image, list-item-avatar"
|
|
27
|
-
class="reload-skeleton"
|
|
28
|
-
></v-skeleton-loader>
|
|
29
|
-
|
|
30
10
|
<VuetifyPlayer
|
|
31
|
-
v-if="hasSource"
|
|
32
11
|
:language="$i18n && $i18n.locale ? $i18n.locale : 'en-US'"
|
|
33
|
-
|
|
12
|
+
type="auto"
|
|
34
13
|
:playlist="linkedPlaylist"
|
|
35
14
|
:autoplay="block.metadata.config.attributes.autoplay"
|
|
36
15
|
:autopictureinpicture="
|
|
@@ -59,9 +38,31 @@
|
|
|
59
38
|
block.metadata.config.attributes.playlistautoadvance
|
|
60
39
|
"
|
|
61
40
|
:playbackrates="block.metadata.config.attributes.playbackrates"
|
|
41
|
+
:captions-autoscroll.sync="captionsAutoscroll"
|
|
42
|
+
:captions-paragraph-view.sync="captionsParagraphView"
|
|
43
|
+
:captions-visible.sync="captionsVisible"
|
|
44
|
+
flat
|
|
62
45
|
@seeking="onSeeking"
|
|
63
46
|
@timeupdate="onTimeupdate"
|
|
64
|
-
|
|
47
|
+
>
|
|
48
|
+
<template #no-source>
|
|
49
|
+
<v-card>
|
|
50
|
+
<v-card-title class="justify-center">
|
|
51
|
+
<v-icon class="mr-2">mdi-cloud-question</v-icon>
|
|
52
|
+
{{
|
|
53
|
+
$t(
|
|
54
|
+
'windward.core.components.content.blocks.video.not_configured_title'
|
|
55
|
+
)
|
|
56
|
+
}}
|
|
57
|
+
</v-card-title>
|
|
58
|
+
<v-card-text>{{
|
|
59
|
+
$t(
|
|
60
|
+
'windward.core.components.content.blocks.video.edit_prompt'
|
|
61
|
+
)
|
|
62
|
+
}}</v-card-text>
|
|
63
|
+
</v-card>
|
|
64
|
+
</template>
|
|
65
|
+
</VuetifyPlayer>
|
|
65
66
|
<!-- display first note in the playlist for now -->
|
|
66
67
|
<v-alert
|
|
67
68
|
v-if="notes.length > 0"
|
|
@@ -78,10 +79,11 @@
|
|
|
78
79
|
|
|
79
80
|
<script>
|
|
80
81
|
import _ from 'lodash'
|
|
82
|
+
import he from 'he'
|
|
81
83
|
import VuetifyPlayer from '@mindedge/vuetify-player'
|
|
84
|
+
import AuthUserRepository from '~/models/repositories/AuthUserRepository'
|
|
82
85
|
import BaseContentBlock from '~/components/Content/Blocks/BaseContentBlock'
|
|
83
86
|
import TextViewer from '~/components/Text/TextViewer'
|
|
84
|
-
import he from 'he'
|
|
85
87
|
|
|
86
88
|
export default {
|
|
87
89
|
name: 'ContentBlockVideo',
|
|
@@ -214,6 +216,58 @@ export default {
|
|
|
214
216
|
})
|
|
215
217
|
return playlist
|
|
216
218
|
},
|
|
219
|
+
captionsAutoscroll: {
|
|
220
|
+
get() {
|
|
221
|
+
const user = new AuthUserRepository(this.$nuxt)
|
|
222
|
+
|
|
223
|
+
return user.getPreference('video.captions-autoscroll', true)
|
|
224
|
+
},
|
|
225
|
+
set(v) {
|
|
226
|
+
try {
|
|
227
|
+
const user = new AuthUserRepository(this.$nuxt)
|
|
228
|
+
user.setPreference('video.captions-autoscroll', v)
|
|
229
|
+
user.save()
|
|
230
|
+
} catch (e) {
|
|
231
|
+
console.error('Could not save user video preference!')
|
|
232
|
+
console.error(e)
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
},
|
|
236
|
+
captionsParagraphView: {
|
|
237
|
+
get() {
|
|
238
|
+
const user = new AuthUserRepository(this.$nuxt)
|
|
239
|
+
return user.getPreference(
|
|
240
|
+
'video.captions-paragraph-view',
|
|
241
|
+
false
|
|
242
|
+
)
|
|
243
|
+
},
|
|
244
|
+
set(v) {
|
|
245
|
+
try {
|
|
246
|
+
const user = new AuthUserRepository(this.$nuxt)
|
|
247
|
+
user.setPreference('video.captions-paragraph-view', v)
|
|
248
|
+
user.save()
|
|
249
|
+
} catch (e) {
|
|
250
|
+
console.error('Could not save user video preference!')
|
|
251
|
+
console.error(e)
|
|
252
|
+
}
|
|
253
|
+
},
|
|
254
|
+
},
|
|
255
|
+
captionsVisible: {
|
|
256
|
+
get() {
|
|
257
|
+
const user = new AuthUserRepository(this.$nuxt)
|
|
258
|
+
return user.getPreference('video.captions-visible', false)
|
|
259
|
+
},
|
|
260
|
+
set(v) {
|
|
261
|
+
try {
|
|
262
|
+
const user = new AuthUserRepository(this.$nuxt)
|
|
263
|
+
user.setPreference('video.captions-visible', v)
|
|
264
|
+
user.save()
|
|
265
|
+
} catch (e) {
|
|
266
|
+
console.error('Could not save user video preference!')
|
|
267
|
+
console.error(e)
|
|
268
|
+
}
|
|
269
|
+
},
|
|
270
|
+
},
|
|
217
271
|
},
|
|
218
272
|
data() {
|
|
219
273
|
return {
|
|
@@ -224,7 +278,7 @@ export default {
|
|
|
224
278
|
description: '',
|
|
225
279
|
// Default settings for new blocks
|
|
226
280
|
// This will be overridden in beforeMount()
|
|
227
|
-
type: '
|
|
281
|
+
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
|
|
228
282
|
attributes: {
|
|
229
283
|
autoplay: false, // Autoplay on load. It's in the spec but DON'T USE THIS
|
|
230
284
|
autopictureinpicture: false, // Start with picture in picture mode
|
|
@@ -98,53 +98,16 @@
|
|
|
98
98
|
)
|
|
99
99
|
}}
|
|
100
100
|
</h4>
|
|
101
|
-
<
|
|
102
|
-
v-model="
|
|
103
|
-
block.metadata.config.items[index].altText
|
|
104
|
-
"
|
|
105
|
-
class="pt-3 pb-3"
|
|
106
|
-
:hide-details="true"
|
|
107
|
-
dense
|
|
108
|
-
outlined
|
|
109
|
-
:label="
|
|
110
|
-
$t(
|
|
111
|
-
'windward.core.shared.settings.alt_image'
|
|
112
|
-
)
|
|
113
|
-
"
|
|
114
|
-
:disabled="render"
|
|
115
|
-
></v-text-field>
|
|
116
|
-
<v-text-field
|
|
101
|
+
<ImageAssetSettings
|
|
117
102
|
v-model="
|
|
118
103
|
block.metadata.config.items[index]
|
|
119
|
-
.
|
|
104
|
+
.fileConfig
|
|
120
105
|
"
|
|
121
|
-
class="pt-3 pb-3"
|
|
122
|
-
:hide-details="true"
|
|
123
|
-
dense
|
|
124
|
-
outlined
|
|
125
|
-
:label="
|
|
126
|
-
$t(
|
|
127
|
-
'windward.core.shared.settings.aria_described'
|
|
128
|
-
)
|
|
129
|
-
"
|
|
130
|
-
:disabled="render"
|
|
131
|
-
></v-text-field>
|
|
132
|
-
<ContentBlockAsset
|
|
133
|
-
v-model="
|
|
134
|
-
block.metadata.config.items[index].file
|
|
135
|
-
"
|
|
136
|
-
mimes="image/png,image/jpeg"
|
|
137
106
|
:assets.sync="block.assets"
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
$t(
|
|
143
|
-
'windward.core.components.settings.image.place_image'
|
|
144
|
-
)
|
|
145
|
-
}}
|
|
146
|
-
</template>
|
|
147
|
-
</ContentBlockAsset>
|
|
107
|
+
hide-background
|
|
108
|
+
hide-decorative
|
|
109
|
+
hide-modal
|
|
110
|
+
></ImageAssetSettings>
|
|
148
111
|
</v-container>
|
|
149
112
|
</v-container>
|
|
150
113
|
</template>
|
|
@@ -181,12 +144,14 @@ import BaseContentSettings from '~/components/Content/Settings/BaseContentSettin
|
|
|
181
144
|
import TextEditor from '~/components/Text/TextEditor'
|
|
182
145
|
import SortableExpansionPanel from '~/components/Core/SortableExpansionPanel.vue'
|
|
183
146
|
import Uuid from '~/helpers/Uuid'
|
|
147
|
+
import ImageAssetSettings from '~/components/Content/Settings/ImageAssetSettings.vue'
|
|
184
148
|
|
|
185
149
|
export default {
|
|
186
150
|
name: 'AccordionSettings',
|
|
187
151
|
components: {
|
|
188
152
|
TextEditor,
|
|
189
153
|
SortableExpansionPanel,
|
|
154
|
+
ImageAssetSettings,
|
|
190
155
|
},
|
|
191
156
|
extends: BaseContentSettings,
|
|
192
157
|
beforeMount() {
|
|
@@ -219,9 +184,7 @@ export default {
|
|
|
219
184
|
header: '',
|
|
220
185
|
expand: false,
|
|
221
186
|
content: '',
|
|
222
|
-
|
|
223
|
-
altText: '',
|
|
224
|
-
ariaDescribedBy: '',
|
|
187
|
+
fileConfig: {},
|
|
225
188
|
}
|
|
226
189
|
this.block.metadata.config.items = []
|
|
227
190
|
this.block.metadata.config.items.push(defaultObject)
|
|
@@ -260,9 +223,7 @@ export default {
|
|
|
260
223
|
header: '',
|
|
261
224
|
expand: false,
|
|
262
225
|
content: '',
|
|
263
|
-
|
|
264
|
-
altText: '',
|
|
265
|
-
ariaDescribedBy: '',
|
|
226
|
+
fileConfig: {},
|
|
266
227
|
}
|
|
267
228
|
this.block.metadata.config.items.push(default_item)
|
|
268
229
|
this.block.metadata.config.selectedPanels =
|
|
@@ -87,8 +87,8 @@
|
|
|
87
87
|
@click:close="onRemoveElement"
|
|
88
88
|
>
|
|
89
89
|
<template #header="{ item }">
|
|
90
|
-
<v-avatar v-if="item.iconImage && item.
|
|
91
|
-
<v-img :src="getImagePublicUrl(item.
|
|
90
|
+
<v-avatar v-if="item.iconImage && item.fileConfig">
|
|
91
|
+
<v-img :src="getImagePublicUrl(item.fileConfig.asset)" />
|
|
92
92
|
</v-avatar>
|
|
93
93
|
<v-icon
|
|
94
94
|
v-else-if="
|
|
@@ -146,29 +146,19 @@
|
|
|
146
146
|
:rules="validation.iconRules"
|
|
147
147
|
:disabled="render"
|
|
148
148
|
></TextIconPicker>
|
|
149
|
-
|
|
150
|
-
<ContentBlockAsset
|
|
149
|
+
<ImageAssetSettings
|
|
151
150
|
v-if="
|
|
152
151
|
block.metadata.config.items[index].iconImage
|
|
153
152
|
"
|
|
154
153
|
v-model="
|
|
155
|
-
block.metadata.config.items[index]
|
|
154
|
+
block.metadata.config.items[index]
|
|
155
|
+
.fileConfig
|
|
156
156
|
"
|
|
157
157
|
:assets.sync="block.assets"
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
@click:file="onFileSelect($event, index)"
|
|
163
|
-
>
|
|
164
|
-
<template #title>
|
|
165
|
-
{{
|
|
166
|
-
$t(
|
|
167
|
-
'windward.core.components.settings.image.place_image'
|
|
168
|
-
)
|
|
169
|
-
}}
|
|
170
|
-
</template>
|
|
171
|
-
</ContentBlockAsset>
|
|
158
|
+
hide-background
|
|
159
|
+
hide-decorative
|
|
160
|
+
hide-modal
|
|
161
|
+
></ImageAssetSettings>
|
|
172
162
|
<v-text-field
|
|
173
163
|
v-model="
|
|
174
164
|
block.metadata.config.items[index].title
|
|
@@ -234,6 +224,7 @@ import TextIconPicker from '~/components/Core/TextIconPicker.vue'
|
|
|
234
224
|
import ColorPicker from '~/components/Core/ColorPicker.vue'
|
|
235
225
|
import SortableExpansionPanel from '~/components/Core/SortableExpansionPanel.vue'
|
|
236
226
|
import ContentBlockAsset from '~/components/Content/ContentBlockAsset.vue'
|
|
227
|
+
import ImageAssetSettings from '~/components/Content/Settings/ImageAssetSettings.vue'
|
|
237
228
|
|
|
238
229
|
export default {
|
|
239
230
|
name: 'ClickableIconsSettings',
|
|
@@ -243,6 +234,7 @@ export default {
|
|
|
243
234
|
TextIconPicker,
|
|
244
235
|
ColorPicker,
|
|
245
236
|
ContentBlockAsset,
|
|
237
|
+
ImageAssetSettings,
|
|
246
238
|
},
|
|
247
239
|
extends: BaseContentSettings,
|
|
248
240
|
data() {
|
|
@@ -311,7 +303,7 @@ export default {
|
|
|
311
303
|
onAddElement() {
|
|
312
304
|
const defaultObject = {
|
|
313
305
|
icon: '',
|
|
314
|
-
|
|
306
|
+
fileConfig: {},
|
|
315
307
|
iconImage: false,
|
|
316
308
|
title: '',
|
|
317
309
|
body: '<p></p>',
|
|
@@ -336,7 +328,7 @@ export default {
|
|
|
336
328
|
onClickToggleIconImage(index) {
|
|
337
329
|
// We're switching between images / text. Clear the relevant fields
|
|
338
330
|
this.block.metadata.config.items[index].icon = ''
|
|
339
|
-
this.block.metadata.config.items[index].
|
|
331
|
+
this.block.metadata.config.items[index].fileConfig = null
|
|
340
332
|
},
|
|
341
333
|
onFileSelect(file, index) {
|
|
342
334
|
// file = null when you remove a file
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
:disabled="render"
|
|
114
114
|
@click:close="editTerm(verified)"
|
|
115
115
|
>
|
|
116
|
-
<
|
|
116
|
+
<ContentViewer v-model="verified.term"></ContentViewer>
|
|
117
117
|
</v-chip>
|
|
118
118
|
</v-card-text>
|
|
119
119
|
</v-card>
|
|
@@ -136,7 +136,9 @@
|
|
|
136
136
|
:disabled="render"
|
|
137
137
|
@click:close="addGlossaryTerm(unVerified)"
|
|
138
138
|
>
|
|
139
|
-
<
|
|
139
|
+
<ContentViewer
|
|
140
|
+
v-model="unVerified.term"
|
|
141
|
+
></ContentViewer>
|
|
140
142
|
</v-chip>
|
|
141
143
|
</v-card-text>
|
|
142
144
|
</v-card>
|
|
@@ -198,18 +200,18 @@
|
|
|
198
200
|
import { mapGetters, mapMutations } from 'vuex'
|
|
199
201
|
import GlossaryHelper from '../../helpers/GlossaryHelper'
|
|
200
202
|
import CourseGlossaryForm from '../utils/glossary/CourseGlossaryForm.vue'
|
|
203
|
+
import ContentViewer from '../utils/ContentViewer.vue'
|
|
201
204
|
import DialogBox from '~/components/Core/DialogBox.vue'
|
|
202
205
|
import Course from '~/models/Course'
|
|
203
206
|
import BaseContentSettings from '~/components/Content/Settings/BaseContentSettings.js'
|
|
204
207
|
import TextEditor from '~/components/Text/TextEditor'
|
|
205
|
-
import TextViewer from '~/components/Text/TextViewer.vue'
|
|
206
208
|
export default {
|
|
207
209
|
name: 'TextEditorSettings',
|
|
208
210
|
components: {
|
|
209
211
|
DialogBox,
|
|
210
212
|
TextEditor,
|
|
211
213
|
CourseGlossaryForm,
|
|
212
|
-
|
|
214
|
+
ContentViewer,
|
|
213
215
|
},
|
|
214
216
|
extends: BaseContentSettings,
|
|
215
217
|
data() {
|
|
@@ -146,9 +146,9 @@
|
|
|
146
146
|
:disabled="render"
|
|
147
147
|
@change:source="
|
|
148
148
|
(file, rawFile) =>
|
|
149
|
-
onAdSourceSelect(file, rawFile,
|
|
149
|
+
onAdSourceSelect(file, rawFile, 100)
|
|
150
150
|
"
|
|
151
|
-
@change:track="onAdTrackSelect($event,
|
|
151
|
+
@change:track="onAdTrackSelect($event, 100)"
|
|
152
152
|
></SourcePicker>
|
|
153
153
|
</v-tab-item>
|
|
154
154
|
</v-tabs-items>
|
|
@@ -575,6 +575,11 @@ export default {
|
|
|
575
575
|
return ads.length
|
|
576
576
|
},
|
|
577
577
|
onRemovePlaylistItem() {
|
|
578
|
+
// If there's still items in the playlist then decrement it down to the previous item
|
|
579
|
+
if (this.playlistIndex > 0) {
|
|
580
|
+
this.playlistPaginator--
|
|
581
|
+
}
|
|
582
|
+
|
|
578
583
|
if (this.block.metadata.config.playlist.length > 1) {
|
|
579
584
|
this.block.metadata.config.playlist.splice(
|
|
580
585
|
this.playlistIndex,
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
<label v-if="label" class="editor-label">{{ label }}</label>
|
|
12
12
|
</slot>
|
|
13
13
|
<Editor
|
|
14
|
-
:id="
|
|
14
|
+
:id="editorId"
|
|
15
15
|
:key="seed + (isDarkTheme ? '-theme-dark' : '-theme-light')"
|
|
16
16
|
v-model="text"
|
|
17
17
|
initial-value=""
|
|
@@ -121,6 +121,7 @@ export default {
|
|
|
121
121
|
props: {
|
|
122
122
|
value: { type: String, required: true, default: '' },
|
|
123
123
|
id: { type: String, required: false, default: '' },
|
|
124
|
+
dataKey: { type: String, required: false, default: '' }, // used as a unique key for testing
|
|
124
125
|
height: { type: Number, required: false, default: null },
|
|
125
126
|
menubar: {
|
|
126
127
|
type: String,
|
|
@@ -152,12 +153,26 @@ export default {
|
|
|
152
153
|
computed: {
|
|
153
154
|
dataCy() {
|
|
154
155
|
return (
|
|
156
|
+
this.dataKey ||
|
|
155
157
|
this.id ||
|
|
156
158
|
this.label.toLowerCase().replaceAll(/[^a-z0-9]/g, '-') ||
|
|
157
159
|
this.hint.toLowerCase().replaceAll(/[^a-z0-9]/g, '-') ||
|
|
158
160
|
_.get(this, '$parent.$parent.$options.name', '')
|
|
159
161
|
)
|
|
160
162
|
},
|
|
163
|
+
editorId() {
|
|
164
|
+
// If the id is not empty then make sure it's unique
|
|
165
|
+
// TinyMCE fails to load if an id is duplicated. Also duplicate ids are just bad in general
|
|
166
|
+
if (this.id) {
|
|
167
|
+
const duplicates = document.querySelectorAll(`#${this.id}`)
|
|
168
|
+
|
|
169
|
+
return duplicates.length === 0
|
|
170
|
+
? this.id
|
|
171
|
+
: this.id + '-' + this.seed
|
|
172
|
+
} else {
|
|
173
|
+
return ''
|
|
174
|
+
}
|
|
175
|
+
},
|
|
161
176
|
isDarkTheme() {
|
|
162
177
|
return this.$vuetify.theme.isDark
|
|
163
178
|
},
|
|
@@ -194,7 +209,7 @@ export default {
|
|
|
194
209
|
},
|
|
195
210
|
autoresize_min_height: 100,
|
|
196
211
|
autoresize_max_height: 1000,
|
|
197
|
-
autoresize_bottom_margin:
|
|
212
|
+
autoresize_bottom_margin: 1,
|
|
198
213
|
plugins: [
|
|
199
214
|
'autoresize',
|
|
200
215
|
'advlist',
|
|
@@ -1,25 +1,25 @@
|
|
|
1
1
|
<template>
|
|
2
2
|
<div
|
|
3
|
+
v-click-outside="onClickOutside"
|
|
3
4
|
class="glossary-word"
|
|
4
5
|
:class="{ active: show }"
|
|
5
|
-
v-click-outside="onClickOutside"
|
|
6
6
|
@click="show = !show"
|
|
7
7
|
>
|
|
8
8
|
<v-tooltip
|
|
9
|
-
top
|
|
10
9
|
v-model="show"
|
|
10
|
+
top
|
|
11
11
|
:open-on-hover="false"
|
|
12
12
|
color="primary"
|
|
13
13
|
max-width="768px"
|
|
14
14
|
z-index="10"
|
|
15
15
|
>
|
|
16
16
|
<template #activator="{ on }">
|
|
17
|
-
<span v-on="on">
|
|
17
|
+
<span tabindex="0" v-on="on">
|
|
18
18
|
<slot name="term"></slot>
|
|
19
19
|
</span>
|
|
20
20
|
</template>
|
|
21
21
|
<div>
|
|
22
|
-
<div v-if="
|
|
22
|
+
<div v-if="$slots['definition']">
|
|
23
23
|
<h6 class="text-capitalize">
|
|
24
24
|
<slot name="term"></slot>
|
|
25
25
|
{{
|
|
@@ -33,7 +33,7 @@
|
|
|
33
33
|
<slot name="definition"></slot>
|
|
34
34
|
</p>
|
|
35
35
|
</div>
|
|
36
|
-
<div v-if="
|
|
36
|
+
<div v-if="$slots['alternate_forms']">
|
|
37
37
|
<h4 class="text-capitalize">
|
|
38
38
|
<slot name="term"></slot>
|
|
39
39
|
{{
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
<p><slot name="alternate_forms"></slot></p>
|
|
47
47
|
</div>
|
|
48
48
|
|
|
49
|
-
<div v-if="
|
|
49
|
+
<div v-if="$slots['related_terms']">
|
|
50
50
|
<h4 class="text-capitalize">
|
|
51
51
|
{{
|
|
52
52
|
$t(
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export default {
|
|
2
|
-
title: '
|
|
2
|
+
title: 'Media Title',
|
|
3
3
|
sources: 'Sources',
|
|
4
4
|
place_source: 'Place Video or Audio',
|
|
5
5
|
playback: 'Playback',
|
|
6
6
|
no_sources: 'No Sources Configured',
|
|
7
|
-
default_filename: '
|
|
8
|
-
playlist: '
|
|
7
|
+
default_filename: 'Media',
|
|
8
|
+
playlist: 'Media in Playlist',
|
|
9
9
|
playlist_name: 'Name in Playlist',
|
|
10
10
|
playlist_name_source_required:
|
|
11
11
|
'Select a source before naming this playlist item',
|
|
@@ -16,6 +16,10 @@ export default {
|
|
|
16
16
|
'When enabled, the selected media will use captions linked on the file, managed in the file manager. When disabled, the selected media will have its own unique captions that is not shared globally on the file.',
|
|
17
17
|
inherit_missing_captions:
|
|
18
18
|
'No global captions are available for this source. Please set them in the file settings',
|
|
19
|
+
media: {
|
|
20
|
+
configure_blurb:
|
|
21
|
+
'Upload a media file (.mp4, .webm, .mp3, .ogg), pick one from the file manager, or add via the public URL',
|
|
22
|
+
},
|
|
19
23
|
video: {
|
|
20
24
|
title: 'Video File',
|
|
21
25
|
configure_blurb:
|
|
@@ -29,7 +33,7 @@ export default {
|
|
|
29
33
|
playback_rates: 'Playback Rates',
|
|
30
34
|
rewind: 'Allow 10 Second Rewind',
|
|
31
35
|
playsinline: 'Disable fullscreen and force inline viewing',
|
|
32
|
-
captionsmenu: 'Show the
|
|
36
|
+
captionsmenu: 'Show the transcript menu',
|
|
33
37
|
playlistmenu:
|
|
34
38
|
'Show playlist menu (Requires more than 1 video selected to show)',
|
|
35
39
|
playlistautoadvance: 'Auto-advance the playlist on media end',
|
|
@@ -11,7 +11,7 @@ export default {
|
|
|
11
11
|
clickable_icons: 'Clickable Icons Settings',
|
|
12
12
|
scenario_choice: 'Scenario Choice',
|
|
13
13
|
accordion: 'Accordion Settings',
|
|
14
|
-
video: 'Video Settings',
|
|
14
|
+
video: 'Video / Audio Settings',
|
|
15
15
|
table: 'Table Settings',
|
|
16
16
|
math: 'Math Settings',
|
|
17
17
|
feedback: 'Feedback Settings',
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export default {
|
|
2
|
-
title: 'Título del
|
|
2
|
+
title: 'Título del medio',
|
|
3
3
|
sources: 'Fuentes',
|
|
4
4
|
place_source: 'Colocar video o audio',
|
|
5
5
|
playback: 'Reproducción',
|
|
6
6
|
no_sources: 'No hay fuentes configuradas',
|
|
7
|
-
default_filename: '
|
|
8
|
-
playlist: '
|
|
7
|
+
default_filename: 'Medios de comunicación',
|
|
8
|
+
playlist: 'Medios en lista de reproducción',
|
|
9
9
|
playlist_name: 'Nombre en lista de reproducción',
|
|
10
10
|
playlist_name_source_required:
|
|
11
11
|
'Seleccione una fuente antes de nombrar este elemento de la lista de reproducción',
|
|
@@ -16,6 +16,10 @@ export default {
|
|
|
16
16
|
'Cuando está habilitado, el contenido multimedia seleccionado utilizará subtítulos vinculados al archivo, administrados en el administrador de archivos. Cuando está deshabilitado, el contenido multimedia seleccionado tendrá sus propios subtítulos exclusivos que no se comparten globalmente en el archivo.',
|
|
17
17
|
inherit_missing_captions:
|
|
18
18
|
'No hay subtítulos globales disponibles para esta fuente. Establézcalos en la configuración del archivo',
|
|
19
|
+
media: {
|
|
20
|
+
configure_blurb:
|
|
21
|
+
'Sube un archivo multimedia (.mp4, .webm, .mp3, .ogg), elige uno del administrador de archivos o agrégalo a través de la URL pública',
|
|
22
|
+
},
|
|
19
23
|
video: {
|
|
20
24
|
title: 'Archivo de vídeo',
|
|
21
25
|
configure_blurb:
|
|
@@ -30,7 +34,7 @@ export default {
|
|
|
30
34
|
rewind: 'Permitir rebobinado de 10 segundos',
|
|
31
35
|
playsinline:
|
|
32
36
|
'Deshabilitar pantalla completa y forzar visualización en línea',
|
|
33
|
-
captionsmenu: 'Mostrar el
|
|
37
|
+
captionsmenu: 'Mostrar el menú de transcripción',
|
|
34
38
|
playlistmenu:
|
|
35
39
|
'Mostrar menú de lista de reproducción (requiere más de 1 video seleccionado para mostrar)',
|
|
36
40
|
playlistautoadvance:
|
|
@@ -13,7 +13,7 @@ export default {
|
|
|
13
13
|
'Configuración de iconos en los que se puede hacer clic',
|
|
14
14
|
scenario_choice: 'Elección de escenario',
|
|
15
15
|
accordion: 'Configuración de acordeón',
|
|
16
|
-
video: 'Configuración de
|
|
16
|
+
video: 'Configuración de video/audio',
|
|
17
17
|
table: 'Configuración de la tabla',
|
|
18
18
|
math: 'Configuración matemática',
|
|
19
19
|
feedback: 'Configuración de comentarios',
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export default {
|
|
2
|
-
title: '
|
|
2
|
+
title: 'Media Titel',
|
|
3
3
|
sources: 'Källor',
|
|
4
4
|
place_source: 'Placera video eller ljud',
|
|
5
5
|
playback: 'Uppspelning',
|
|
6
6
|
no_sources: 'Inga källor konfigurerade',
|
|
7
|
-
default_filename: '
|
|
8
|
-
playlist: '
|
|
7
|
+
default_filename: 'Media',
|
|
8
|
+
playlist: 'Media i spellistan',
|
|
9
9
|
playlist_name: 'Namn i spellista',
|
|
10
10
|
playlist_name_source_required:
|
|
11
11
|
'Välj en källa innan du namnger detta spellistaobjekt',
|
|
@@ -16,6 +16,10 @@ export default {
|
|
|
16
16
|
'När det är aktiverat kommer det valda mediet att använda bildtexter länkade på filen, hanterade i filhanteraren. När det är inaktiverat kommer det valda mediet att ha sina egna unika bildtexter som inte delas globalt på filen.',
|
|
17
17
|
inherit_missing_captions:
|
|
18
18
|
'Inga globala bildtexter är tillgängliga för den här källan. Ange dem i filinställningarna',
|
|
19
|
+
media: {
|
|
20
|
+
configure_blurb:
|
|
21
|
+
'Ladda upp en mediefil (.mp4, .webm, .mp3, .ogg), välj en från filhanteraren eller lägg till via den offentliga webbadressen',
|
|
22
|
+
},
|
|
19
23
|
video: {
|
|
20
24
|
title: 'Videofil',
|
|
21
25
|
configure_blurb:
|
|
@@ -29,7 +33,7 @@ export default {
|
|
|
29
33
|
playback_rates: 'Uppspelningshastigheter',
|
|
30
34
|
rewind: 'Tillåt 10 sekunders spola tillbaka',
|
|
31
35
|
playsinline: 'Inaktivera helskärm och tvinga inline-visning',
|
|
32
|
-
captionsmenu: 'Visa
|
|
36
|
+
captionsmenu: 'Visa avskriftsmenyn',
|
|
33
37
|
playlistmenu:
|
|
34
38
|
'Visa spellistameny (kräver mer än 1 video vald för att visa)',
|
|
35
39
|
playlistautoadvance: 'Avancera spellistan automatiskt på mediaänden',
|
|
@@ -11,7 +11,7 @@ export default {
|
|
|
11
11
|
clickable_icons: 'Inställningar för klickbara ikoner',
|
|
12
12
|
scenario_choice: 'Scenarioval',
|
|
13
13
|
accordion: 'Accordion Settings',
|
|
14
|
-
video: '
|
|
14
|
+
video: 'Video/ljudinställningar',
|
|
15
15
|
table: 'Tabellinställningar',
|
|
16
16
|
math: 'Matematiska inställningar',
|
|
17
17
|
feedback: 'Feedback-inställningar',
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@windward/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Windward UI Core Plugins",
|
|
5
5
|
"main": "plugin.js",
|
|
6
6
|
"scripts": {
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
"license": "MIT",
|
|
22
22
|
"homepage": "https://bitbucket.org/mindedge/windward-ui-plugin-core#readme",
|
|
23
23
|
"dependencies": {
|
|
24
|
-
"@mindedge/vuetify-player": "^0.
|
|
24
|
+
"@mindedge/vuetify-player": "^0.4.1",
|
|
25
25
|
"@tinymce/tinymce-vue": "^3.2.8",
|
|
26
26
|
"accessibility-scanner": "^0.0.1",
|
|
27
27
|
"eslint": "^8.11.0",
|
package/pages/glossary.vue
CHANGED
|
@@ -31,17 +31,13 @@ describe('AccordionSettings', () => {
|
|
|
31
31
|
header: '',
|
|
32
32
|
expand: false,
|
|
33
33
|
content: '',
|
|
34
|
-
|
|
35
|
-
altText: '',
|
|
36
|
-
ariaDescribedBy: '',
|
|
34
|
+
fileConfig: {},
|
|
37
35
|
},
|
|
38
36
|
{
|
|
39
37
|
header: '',
|
|
40
38
|
expand: false,
|
|
41
39
|
content: '',
|
|
42
|
-
|
|
43
|
-
altText: '',
|
|
44
|
-
ariaDescribedBy: '',
|
|
40
|
+
fileConfig: {},
|
|
45
41
|
},
|
|
46
42
|
])
|
|
47
43
|
})
|
|
@@ -17,4 +17,49 @@ describe('ClickableIconsSettings', () => {
|
|
|
17
17
|
})
|
|
18
18
|
expect(wrapper.vm).toBeTruthy()
|
|
19
19
|
})
|
|
20
|
+
|
|
21
|
+
test('can add an clickable icon', () => {
|
|
22
|
+
const wrapper = shallowMount(ClickableIconsSettings, {
|
|
23
|
+
propsData: {
|
|
24
|
+
tag: 'core-clickable-icons-settings',
|
|
25
|
+
},
|
|
26
|
+
mocks: defaultMocks,
|
|
27
|
+
})
|
|
28
|
+
wrapper.vm.onAddElement()
|
|
29
|
+
expect(wrapper.vm.$data.block.metadata.config.items).toEqual([
|
|
30
|
+
{
|
|
31
|
+
icon: '',
|
|
32
|
+
fileConfig: {},
|
|
33
|
+
iconImage: false,
|
|
34
|
+
title: '',
|
|
35
|
+
body: '<p></p>',
|
|
36
|
+
color: {
|
|
37
|
+
class: '',
|
|
38
|
+
},
|
|
39
|
+
active: false,
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
icon: '',
|
|
43
|
+
fileConfig: {},
|
|
44
|
+
iconImage: false,
|
|
45
|
+
title: '',
|
|
46
|
+
body: '<p></p>',
|
|
47
|
+
color: {
|
|
48
|
+
class: '',
|
|
49
|
+
},
|
|
50
|
+
active: false,
|
|
51
|
+
},
|
|
52
|
+
])
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
test('can remove an clickable icon', () => {
|
|
56
|
+
const wrapper = shallowMount(ClickableIconsSettings, {
|
|
57
|
+
propsData: {
|
|
58
|
+
tag: 'core-clickable-icons-settings',
|
|
59
|
+
},
|
|
60
|
+
mocks: defaultMocks,
|
|
61
|
+
})
|
|
62
|
+
wrapper.vm.onRemoveElement(0)
|
|
63
|
+
expect(wrapper.vm.$data.block.metadata.config.items).toEqual([])
|
|
64
|
+
})
|
|
20
65
|
})
|