@enso-ui/how-to 4.0.10 → 4.0.14
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enso-ui/how-to",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.14",
|
|
4
4
|
"description": "Basic how-to package",
|
|
5
5
|
"main": "src/bulma/pages/howTo/Index.vue",
|
|
6
6
|
"scripts": {
|
|
@@ -32,8 +32,7 @@
|
|
|
32
32
|
"@fortawesome/vue-fontawesome": "3.0.0-5",
|
|
33
33
|
"v-tooltip": "4.0.0-beta.2",
|
|
34
34
|
"video.js": "^7.0",
|
|
35
|
-
"vue": "^3.0"
|
|
36
|
-
"vue-video-player": "^5.0"
|
|
35
|
+
"vue": "^3.0"
|
|
37
36
|
},
|
|
38
37
|
"devDependencies": {
|
|
39
38
|
"@vue/cli-plugin-babel": "5.0.0-beta.6",
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
<div class="columns is-multiline">
|
|
73
73
|
<div class="column is-half"
|
|
74
74
|
v-for="(vid, index) in filteredVideos"
|
|
75
|
-
:key="
|
|
75
|
+
:key="vid.id">
|
|
76
76
|
<how-to-video class="is-rounded raises-on-hover"
|
|
77
77
|
:video="vid"
|
|
78
78
|
:tags="tags"
|
|
@@ -201,7 +201,7 @@ export default {
|
|
|
201
201
|
|
|
202
202
|
components: { Fa, Fade, HowToVideo, Uploader, },
|
|
203
203
|
|
|
204
|
-
inject: ['canAccess', 'errorHandler', 'i18n', 'route', 'toastr'],
|
|
204
|
+
inject: ['canAccess', 'errorHandler', 'http', 'i18n', 'route', 'toastr'],
|
|
205
205
|
|
|
206
206
|
data: () => ({
|
|
207
207
|
videos: [],
|
|
@@ -265,12 +265,12 @@ export default {
|
|
|
265
265
|
|
|
266
266
|
methods: {
|
|
267
267
|
getVideos() {
|
|
268
|
-
|
|
268
|
+
this.http.get(this.route('howTo.videos.index'))
|
|
269
269
|
.then(({ data }) => (this.videos = data))
|
|
270
270
|
.catch(this.errorHandler);
|
|
271
271
|
},
|
|
272
272
|
getTags() {
|
|
273
|
-
|
|
273
|
+
this.http.get(this.route('howTo.tags.index'))
|
|
274
274
|
.then(({ data }) => (this.tags = data))
|
|
275
275
|
.catch(this.errorHandler);
|
|
276
276
|
},
|
|
@@ -305,26 +305,26 @@ export default {
|
|
|
305
305
|
return;
|
|
306
306
|
}
|
|
307
307
|
|
|
308
|
-
|
|
308
|
+
this.http.post(this.route('howTo.tags.store'), { name: this.query })
|
|
309
309
|
.then(({ data }) => {
|
|
310
310
|
this.tags.push(data);
|
|
311
311
|
this.query = '';
|
|
312
312
|
}).catch(this.errorHandler);
|
|
313
313
|
},
|
|
314
314
|
updateTag() {
|
|
315
|
-
|
|
315
|
+
this.http.patch(this.route('howTo.tags.update', this.selectedTag.id), {
|
|
316
316
|
name: this.selectedTag.name,
|
|
317
317
|
}).catch(this.errorHandler);
|
|
318
318
|
},
|
|
319
319
|
deleteTag(tagId) {
|
|
320
|
-
|
|
320
|
+
this.http.delete(this.route('howTo.tags.destroy', tagId))
|
|
321
321
|
.then(() => {
|
|
322
322
|
const index = this.tags.findIndex(({ id }) => id === tagId);
|
|
323
323
|
this.tags.splice(index, 1);
|
|
324
324
|
}).catch(this.errorHandler);
|
|
325
325
|
},
|
|
326
326
|
update() {
|
|
327
|
-
|
|
327
|
+
this.http.patch(this.route('howTo.videos.update', this.video.id), this.video)
|
|
328
328
|
.then(({ data }) => {
|
|
329
329
|
this.toastr.success(data.message);
|
|
330
330
|
this.reset();
|
|
@@ -40,16 +40,14 @@
|
|
|
40
40
|
</span>
|
|
41
41
|
</card-control>
|
|
42
42
|
<card-control v-if="canAccess('howTo.posters.destroy') && video.poster">
|
|
43
|
-
<confirmation @confirm="destroyPoster"
|
|
44
|
-
v-tooltip="i18n('Remove poster')">
|
|
43
|
+
<confirmation @confirm="destroyPoster">
|
|
45
44
|
<span class="icon is-small">
|
|
46
45
|
<fa :icon="['far', 'trash-alt']"/>
|
|
47
46
|
</span>
|
|
48
47
|
</confirmation>
|
|
49
48
|
</card-control>
|
|
50
49
|
<card-control v-else-if="canAccess('howTo.videos.destroy')">
|
|
51
|
-
<confirmation @confirm="destroyVideo"
|
|
52
|
-
v-tooltip="i18n('Delete video')">
|
|
50
|
+
<confirmation @confirm="destroyVideo">
|
|
53
51
|
<span class="icon is-small">
|
|
54
52
|
<fa :icon="['far', 'trash-alt']"/>
|
|
55
53
|
</span>
|
|
@@ -90,13 +88,13 @@
|
|
|
90
88
|
</template>
|
|
91
89
|
|
|
92
90
|
<script>
|
|
91
|
+
import 'v-tooltip/dist/v-tooltip.css';
|
|
93
92
|
import { VTooltip } from 'v-tooltip';
|
|
94
93
|
import { FontAwesomeIcon as Fa } from '@fortawesome/vue-fontawesome';
|
|
95
94
|
import { library } from '@fortawesome/fontawesome-svg-core';
|
|
96
95
|
import { faInfo, faTags, faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
|
97
96
|
import { faTrashAlt, faEdit, faImage } from '@fortawesome/free-regular-svg-icons';
|
|
98
|
-
import
|
|
99
|
-
import 'vue-video-player/src/custom-theme.css';
|
|
97
|
+
import VideoPlayer from './VideoPlayer.vue';
|
|
100
98
|
import {
|
|
101
99
|
Card, CardHeader, CardCollapse, CardControl, CardContent,
|
|
102
100
|
CardFooter, CardFooterItem,
|
|
@@ -123,10 +121,10 @@ export default {
|
|
|
123
121
|
CardContent,
|
|
124
122
|
Fa,
|
|
125
123
|
Uploader,
|
|
126
|
-
|
|
124
|
+
VideoPlayer,
|
|
127
125
|
},
|
|
128
126
|
|
|
129
|
-
inject: ['canAccess', 'errorHandler', 'i18n', 'route', 'toastr'],
|
|
127
|
+
inject: ['canAccess', 'errorHandler', 'http', 'i18n', 'route', 'toastr'],
|
|
130
128
|
|
|
131
129
|
props: {
|
|
132
130
|
video: {
|
|
@@ -139,6 +137,8 @@ export default {
|
|
|
139
137
|
},
|
|
140
138
|
},
|
|
141
139
|
|
|
140
|
+
emits: ['delete', 'edit', 'start-tagging', 'stop-tagging'],
|
|
141
|
+
|
|
142
142
|
data: () => ({
|
|
143
143
|
tagging: false,
|
|
144
144
|
}),
|
|
@@ -166,14 +166,14 @@ export default {
|
|
|
166
166
|
};
|
|
167
167
|
},
|
|
168
168
|
destroyPoster() {
|
|
169
|
-
|
|
169
|
+
this.http.delete(this.route('howTo.posters.destroy', this.video.poster.id))
|
|
170
170
|
.then(({ data }) => {
|
|
171
171
|
this.toastr.success(data.message);
|
|
172
172
|
this.video.poster = null;
|
|
173
173
|
}).catch(this.errorHandler);
|
|
174
174
|
},
|
|
175
175
|
destroyVideo() {
|
|
176
|
-
|
|
176
|
+
this.http.delete(this.route('howTo.videos.destroy', this.video.id))
|
|
177
177
|
.then(({ data }) => {
|
|
178
178
|
this.toastr.success(data.message);
|
|
179
179
|
this.$emit('delete');
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
<template>
|
|
2
|
+
<div class="video-player" v-if="reseted">
|
|
3
|
+
<video class="video-js" ref="video">
|
|
4
|
+
<track v-for="crtTrack in trackList"
|
|
5
|
+
:kind="crtTrack.kind"
|
|
6
|
+
:label="crtTrack.label"
|
|
7
|
+
:src="crtTrack.src"
|
|
8
|
+
:srcLang="crtTrack.srcLang"
|
|
9
|
+
:default="crtTrack.default"/>
|
|
10
|
+
</video>
|
|
11
|
+
</div>
|
|
12
|
+
</template>
|
|
13
|
+
|
|
14
|
+
<script>
|
|
15
|
+
// lib
|
|
16
|
+
import _videojs from 'video.js';
|
|
17
|
+
const videojs = window.videojs || _videojs;
|
|
18
|
+
|
|
19
|
+
// as of videojs 6.6.0
|
|
20
|
+
const DEFAULT_EVENTS = [
|
|
21
|
+
'loadeddata',
|
|
22
|
+
'canplay',
|
|
23
|
+
'canplaythrough',
|
|
24
|
+
'play',
|
|
25
|
+
'pause',
|
|
26
|
+
'waiting',
|
|
27
|
+
'playing',
|
|
28
|
+
'ended',
|
|
29
|
+
'error'
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
// export
|
|
33
|
+
export default {
|
|
34
|
+
name: 'VideoPlayer',
|
|
35
|
+
props: {
|
|
36
|
+
start: {
|
|
37
|
+
type: Number,
|
|
38
|
+
default: 0,
|
|
39
|
+
},
|
|
40
|
+
crossOrigin: {
|
|
41
|
+
type: String,
|
|
42
|
+
default: '',
|
|
43
|
+
},
|
|
44
|
+
playsinline: {
|
|
45
|
+
type: Boolean,
|
|
46
|
+
default: false,
|
|
47
|
+
},
|
|
48
|
+
customEventName: {
|
|
49
|
+
type: String,
|
|
50
|
+
default: 'statechanged',
|
|
51
|
+
},
|
|
52
|
+
options: {
|
|
53
|
+
type: Object,
|
|
54
|
+
required: true,
|
|
55
|
+
},
|
|
56
|
+
events: {
|
|
57
|
+
type: Array,
|
|
58
|
+
default: () => [],
|
|
59
|
+
},
|
|
60
|
+
globalOptions: {
|
|
61
|
+
type: Object,
|
|
62
|
+
default: () => ({
|
|
63
|
+
// autoplay: false,
|
|
64
|
+
controls: true,
|
|
65
|
+
// preload: 'auto',
|
|
66
|
+
// fluid: false,
|
|
67
|
+
// muted: false,
|
|
68
|
+
controlBar: {
|
|
69
|
+
remainingTimeDisplay: false,
|
|
70
|
+
playToggle: {},
|
|
71
|
+
progressControl: {},
|
|
72
|
+
fullscreenToggle: {},
|
|
73
|
+
volumeMenuButton: {
|
|
74
|
+
inline: false,
|
|
75
|
+
vertical: true,
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
techOrder: ['html5'],
|
|
79
|
+
plugins: {},
|
|
80
|
+
})
|
|
81
|
+
},
|
|
82
|
+
globalEvents: {
|
|
83
|
+
type: Array,
|
|
84
|
+
default: () => [],
|
|
85
|
+
},
|
|
86
|
+
trackList: {
|
|
87
|
+
type: Array,
|
|
88
|
+
default: () => [],
|
|
89
|
+
}
|
|
90
|
+
},
|
|
91
|
+
data() {
|
|
92
|
+
return {
|
|
93
|
+
player: null,
|
|
94
|
+
reseted: true,
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
mounted() {
|
|
98
|
+
if (!this.player) {
|
|
99
|
+
this.initialize();
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
beforeUnmount() {
|
|
103
|
+
if (this.player) {
|
|
104
|
+
this.dispose();
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
methods: {
|
|
108
|
+
initialize() {
|
|
109
|
+
|
|
110
|
+
// videojs options
|
|
111
|
+
const videoOptions = Object.assign({}, this.globalOptions, this.options)
|
|
112
|
+
|
|
113
|
+
// ios fullscreen
|
|
114
|
+
if (this.playsinline) {
|
|
115
|
+
this.$refs.video.setAttribute('playsinline', this.playsinline)
|
|
116
|
+
this.$refs.video.setAttribute('webkit-playsinline', this.playsinline)
|
|
117
|
+
this.$refs.video.setAttribute('x5-playsinline', this.playsinline)
|
|
118
|
+
this.$refs.video.setAttribute('x5-video-player-type', 'h5')
|
|
119
|
+
this.$refs.video.setAttribute('x5-video-player-fullscreen', false)
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// cross origin
|
|
123
|
+
if (this.crossOrigin !== '') {
|
|
124
|
+
this.$refs.video.crossOrigin = this.crossOrigin
|
|
125
|
+
this.$refs.video.setAttribute('crossOrigin', this.crossOrigin)
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// emit event
|
|
129
|
+
const emitPlayerState = (event, value) => {
|
|
130
|
+
if (event) {
|
|
131
|
+
this.$emit(event, this.player)
|
|
132
|
+
}
|
|
133
|
+
if (value) {
|
|
134
|
+
this.$emit(this.customEventName, { [event]: value })
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// avoid error "VIDEOJS: ERROR: Unable to find plugin: __ob__"
|
|
139
|
+
if (videoOptions.plugins) {
|
|
140
|
+
delete videoOptions.plugins.__ob__
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// videoOptions
|
|
144
|
+
// console.log('videoOptions', videoOptions)
|
|
145
|
+
|
|
146
|
+
// player
|
|
147
|
+
const self = this
|
|
148
|
+
this.player = videojs(this.$refs.video, videoOptions, function() {
|
|
149
|
+
|
|
150
|
+
// events
|
|
151
|
+
const events = DEFAULT_EVENTS.concat(self.events).concat(self.globalEvents)
|
|
152
|
+
|
|
153
|
+
// watch events
|
|
154
|
+
const onEdEvents = {}
|
|
155
|
+
for (let i = 0; i < events.length; i++) {
|
|
156
|
+
if (typeof events[i] === 'string' && onEdEvents[events[i]] === undefined) {
|
|
157
|
+
(event => {
|
|
158
|
+
onEdEvents[event] = null
|
|
159
|
+
this.on(event, () => {
|
|
160
|
+
emitPlayerState(event, true)
|
|
161
|
+
})
|
|
162
|
+
})(events[i])
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// watch timeupdate
|
|
167
|
+
this.on('timeupdate', function() {
|
|
168
|
+
emitPlayerState('timeupdate', this.currentTime())
|
|
169
|
+
})
|
|
170
|
+
|
|
171
|
+
// player readied
|
|
172
|
+
self.$emit('ready', this)
|
|
173
|
+
})
|
|
174
|
+
},
|
|
175
|
+
dispose(callback) {
|
|
176
|
+
if (this.player && this.player.dispose) {
|
|
177
|
+
if (this.player.techName_ !== 'Flash') {
|
|
178
|
+
this.player.pause && this.player.pause();
|
|
179
|
+
}
|
|
180
|
+
this.player.dispose();
|
|
181
|
+
this.player = null;
|
|
182
|
+
this.$nextTick(() => {
|
|
183
|
+
this.reseted = false;
|
|
184
|
+
this.$nextTick(() => {
|
|
185
|
+
this.reseted = true;
|
|
186
|
+
this.$nextTick(() => {
|
|
187
|
+
callback && callback();
|
|
188
|
+
});
|
|
189
|
+
});
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
},
|
|
194
|
+
watch: {
|
|
195
|
+
options: {
|
|
196
|
+
deep: true,
|
|
197
|
+
handler(options, oldOptions) {
|
|
198
|
+
this.dispose(() => {
|
|
199
|
+
if (options && options.sources && options.sources.length) {
|
|
200
|
+
this.initialize();
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
},
|
|
204
|
+
},
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
</script>
|
|
208
|
+
|
|
209
|
+
<style>
|
|
210
|
+
.vjs-custom-skin > .video-js .vjs-big-play-button {
|
|
211
|
+
top: 50%;
|
|
212
|
+
left: 50%;
|
|
213
|
+
margin-left: -1.5em;
|
|
214
|
+
margin-top: -1em
|
|
215
|
+
}
|
|
216
|
+
</style>
|