Skip to content

Commit 6a87cbf

Browse files
committed
Merge branch 'main' into issue-1351
2 parents 39bc62e + 5fe8a1d commit 6a87cbf

File tree

9 files changed

+165
-14
lines changed

9 files changed

+165
-14
lines changed

assets/css/opencast.scss

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1322,3 +1322,12 @@ label.oc--file-upload {
13221322
position: sticky;
13231323
bottom: 0px;
13241324
}
1325+
1326+
/* * * * * * * * * * * * * * * * * */
1327+
/* E M B E D D I N G C O D E */
1328+
/* * * * * * * * * * * * * * * * * */
1329+
1330+
.oc--embedding-code-text {
1331+
width: 100%;
1332+
box-sizing: border-box;
1333+
}

bootstrap_migrations.php

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
<?php
2-
ini_set('display_errors', 1);
3-
42
StudipAutoloader::addAutoloadPath(__DIR__, 'ElanEv');
53
StudipAutoloader::addAutoloadPath(__DIR__ . '/lib', 'Opencast');
64

lib/Routes/Config/SimpleConfigList.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public function __invoke(Request $request, Response $response, $args)
3737
'id' => $conf->id,
3838
'name' => $conf->service_url,
3939
'version' => $conf->service_version,
40+
'play' => reset(Endpoints::findBySql("config_id = ? AND service_type = 'play'", [$conf->id]))->service_url,
4041
'ingest' => reset(Endpoints::findBySql("config_id = ? AND service_type = 'ingest'", [$conf->id]))->service_url,
4142
'apievents' => reset(Endpoints::findBySql("config_id = ? AND service_type = 'apievents'", [$conf->id]))->service_url,
4243
'apiplaylists' => reset(Endpoints::findBySql("config_id = ? AND service_type = 'apiplaylists'", [$conf->id]))->service_url,

migrations/107_migrate_previews.php

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,27 +16,26 @@ public function up()
1616

1717

1818
while ($data = $result->fetch()) {
19-
$new_preview = null;
19+
$new_preview_url = null;
2020
$previews = json_decode($data['preview'], true);
2121

2222
if (!empty($previews)) {
2323
if (!empty($previews['player'])) {
24-
$new_preview = $previews['player'];
24+
$new_preview_url = $previews['player'];
2525
} else if (!empty($previews['search'])) {
26-
$new_preview = $previews['search'];
26+
$new_preview_url = $previews['search'];
2727
}
2828
}
2929

30-
if (!empty($new_preview)) {
31-
$stmt->execute([
32-
':preview' => $new_preview,
33-
':id' => $data['id']
34-
]);
35-
}
30+
// Since we are migrating previews to preview URL, we update the preview regardless of the value of the new preview url, whether it is empty or not!
31+
$stmt->execute([
32+
':preview' => $new_preview_url,
33+
':id' => $data['id']
34+
]);
3635
}
3736
}
3837

3938
public function down()
4039
{
4140
}
42-
}
41+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
<?php
2+
3+
class FixOrphanedPreviews extends Migration
4+
{
5+
public function description()
6+
{
7+
return 'Fix for previews that could not get migrated in 107.';
8+
}
9+
10+
public function up()
11+
{
12+
$db = DBManager::get();
13+
14+
$stmt = $db->prepare('UPDATE oc_video SET preview = :preview WHERE id = :id');
15+
$result = $db->query('SELECT id, preview FROM oc_video WHERE preview IS NOT NULL');
16+
17+
18+
while ($data = $result->fetch()) {
19+
$new_preview_url = null;
20+
$previews = json_decode($data['preview'], true);
21+
22+
// We want to handle the case where the preview is still a json object.
23+
if (!empty($previews)) {
24+
// Last chance to present the preview URL.
25+
if (!empty($previews['player'])) {
26+
$new_preview_url = $previews['player'];
27+
} else if (!empty($previews['search'])) {
28+
$new_preview_url = $previews['search'];
29+
}
30+
31+
$stmt->execute([
32+
':preview' => $new_preview_url,
33+
':id' => $data['id']
34+
]);
35+
}
36+
}
37+
}
38+
39+
public function down()
40+
{
41+
}
42+
}

vueapp/components/Videos/Actions/VideoAccess.vue

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,11 @@
139139
{{ $gettext('Links zu den Mediendateien anzeigen.') }}
140140
<studip-icon shape="link-intern" role="clickable" />
141141
</a>
142+
<br>
143+
<a style="cursor: pointer" @click.stop="performAction('VideoEmbeddingCode')">
144+
{{ $gettext('Einbettungscode anzeigen.') }}
145+
<studip-icon shape="link-intern" role="clickable" />
146+
</a>
142147
<br><br>
143148

144149
<StudipButton icon="trash"
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<template>
2+
<div>
3+
<StudipDialog
4+
:title="$gettext('Einbettungscode')"
5+
:closeText="$gettext('Schließen')"
6+
:closeClass="'cancel'"
7+
height="400"
8+
width="550"
9+
@close="this.$emit('cancel')"
10+
>
11+
<template v-slot:dialogContent>
12+
<textarea v-model="embeddingCode" rows="5" class="oc--embedding-code-text" readonly></textarea>
13+
14+
<StudipButton
15+
:disabled="!embeddingCode"
16+
@click.prevent="copyEmbeddingCode()"
17+
>
18+
{{ $gettext('Einbettungscode kopieren') }}
19+
</StudipButton>
20+
21+
<MessageList :dialog="true" />
22+
</template>
23+
</StudipDialog>
24+
</div>
25+
</template>
26+
27+
<script>
28+
import { mapGetters } from 'vuex';
29+
import StudipDialog from '@studip/StudipDialog'
30+
import StudipButton from '@studip/StudipButton'
31+
import MessageList from '@/components/MessageList.vue';
32+
33+
export default {
34+
name: 'VideoEmbeddingCode',
35+
36+
components: {
37+
StudipDialog,
38+
StudipButton,
39+
MessageList,
40+
},
41+
42+
props: ['event'],
43+
44+
computed: {
45+
...mapGetters([
46+
'simple_config_list'
47+
]),
48+
url() {
49+
if (this.event.config_id === undefined) {
50+
return null;
51+
}
52+
53+
if (this.simple_config_list?.server?.[this.event.config_id]?.play === undefined) {
54+
return null;
55+
}
56+
57+
return this.simple_config_list.server[this.event.config_id].play + '/' + this.event.episode;
58+
},
59+
embeddingCode() {
60+
if (!this.url) {
61+
return null;
62+
}
63+
64+
return `<iframe allowfullscreen src="${this.url}" style="border: 0; margin 0;" name="Player"></iframe>`;
65+
},
66+
},
67+
68+
methods: {
69+
copyEmbeddingCode() {
70+
navigator.clipboard.writeText(this.embeddingCode).then(() => {
71+
this.$store.dispatch('addMessage', {
72+
type: 'success',
73+
text: this.$gettext('Der Einbettungscode wurde in die Zwischenablage kopiert.'),
74+
dialog: true
75+
});
76+
}).catch(() => {
77+
this.$store.dispatch('addMessage', {
78+
type: 'error',
79+
text: this.$gettext('Der Einbettungscode konnte nicht in die Zwischenablage kopiert werden.'),
80+
dialog: true
81+
});
82+
});
83+
},
84+
},
85+
}
86+
</script>

vueapp/components/Videos/VideoRow.vue

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -512,6 +512,16 @@ export default {
512512
});
513513
}
514514
515+
if (this.canShare && this.event.visibility === 'public') {
516+
menuItems.push({
517+
id: 4,
518+
label: this.$gettext('Einbettungscode anzeigen'),
519+
icon: 'code',
520+
emit: 'performAction',
521+
emitArguments: 'VideoEmbeddingCode'
522+
});
523+
}
524+
515525
// As we abandoned the preview object structure, we now have to only validate the preview URL!
516526
if ((this.event?.preview || this.event?.state == 'cutting') && !this.isLivestream) {
517527
menuItems.push({

vueapp/components/Videos/VideosTable.vue

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,7 @@ import VideoEdit from '@/components/Videos/Actions/VideoEdit.vue';
187187
import VideoCut from '@/components/Videos/Actions/VideoCut.vue';
188188
import VideoRestore from '@/components/Videos/Actions/VideoRestore.vue';
189189
import VideoRemoveFromPlaylist from '@/components/Videos/Actions/VideoRemoveFromPlaylist.vue';
190+
import VideoEmbeddingCode from '@/components/Videos/Actions/VideoEmbeddingCode.vue';
190191
191192
import BulkVideoDelete from '@/components/Videos/BulkActions/VideoDelete.vue';
192193
import BulkVideoDeletePermanent from '@/components/Videos/BulkActions/VideoDeletePermanent.vue';
@@ -209,8 +210,8 @@ export default {
209210
VideoEdit, VideoCut,
210211
VideoRestore, VideoDelete,
211212
VideoDeletePermanent, VideoRemoveFromPlaylist,
212-
BulkVideoDelete, BulkVideoDeletePermanent,
213-
BulkVideoRestore,
213+
VideoEmbeddingCode, BulkVideoDelete,
214+
BulkVideoDeletePermanent, BulkVideoRestore,
214215
draggable,
215216
},
216217

0 commit comments

Comments
 (0)