Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

On Mediaupload, attach video to currently selected playlist #765 #780

Merged
merged 5 commits into from
Sep 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 9 additions & 8 deletions cronjobs/opencast_discover_videos.php
Original file line number Diff line number Diff line change
Expand Up @@ -72,15 +72,16 @@ public function execute($last_result, $parameters = array())
$video = Videos::findOneBySql("config_id = ? AND episode = ?", [$config['id'], $new_event_id]);
if (!$video) {
$video = new Videos;
$video->setData([
'episode' => $new_event_id,
'config_id' => $config['id'],
'title' => $events[$new_event_id]->title,
'description' => $events[$new_event_id]->description,
'duration' => $events[$new_event_id]->duration
]);
}
$video->setValue('available', true);
$video->setData([
'episode' => $new_event_id,
'config_id' => $config['id'],
'title' => $events[$new_event_id]->title,
'description' => $events[$new_event_id]->description,
'duration' => $events[$new_event_id]->duration,
'state' => 'running',
'available' => true
]);
$video->store();

// create task to update permissions and everything else
Expand Down
29 changes: 20 additions & 9 deletions lib/Models/Videos.php
Original file line number Diff line number Diff line change
Expand Up @@ -264,6 +264,7 @@ protected static function getFilteredVideos($query, $filters)
}

$where .= " AND trashed = " . $filters->getTrashed();
$where .= " AND oc_video.token IS NOT NULL";

$sql .= $where;

Expand Down Expand Up @@ -789,15 +790,25 @@ public static function addToCoursePlaylist($eventType, $episode, $video)
// get the courses this series belongs to
$series = SeminarSeries::findBySeries_id($episode->is_part_of);
foreach ($series as $s) {
$playlist = Helpers::checkCoursePlaylist($s['seminar_id']);

$pvideo = PlaylistVideos::findOneBySQL('video_id = ? AND playlist_id = ?', [$video->id, $playlist->id]);

if (empty($pvideo)) {
$pvideo = new PlaylistVideos();
$pvideo->video_id = $video->id;
$pvideo->playlist_id = $playlist->id;
$pvideo->store();
// Only add video to default playlist if it is not connected to a any playlist in this course
$stmt = \DBManager::get()->prepare($sql = 'SELECT count(*) FROM oc_playlist_seminar
INNER JOIN oc_playlist_video ON (oc_playlist_video.playlist_id = oc_playlist_seminar.playlist_id)
WHERE oc_playlist_seminar.seminar_id = ?
AND oc_playlist_video.video_id = ?
');
$stmt->execute([$video->id, $s['seminar_id']]);
if ($stmt->fetchColumn() == 0) {
// Add video to default playlist here
$playlist = Helpers::checkCoursePlaylist($s['seminar_id']);

$pvideo = PlaylistVideos::findOneBySQL('video_id = ? AND playlist_id = ?', [$video->id, $playlist->id]);

if (empty($pvideo)) {
$pvideo = new PlaylistVideos();
$pvideo->video_id = $video->id;
$pvideo->playlist_id = $playlist->id;
$pvideo->store();
}
}
}
}
Expand Down
1 change: 1 addition & 0 deletions lib/RouteMap.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ public function authenticatedRoutes()
$this->app->put('/videos/{token}', Routes\Video\VideoUpdate::class);
$this->app->put('/videos/{token}/restore', Routes\Video\VideoRestore::class);
$this->app->delete('/videos/{token}', Routes\Video\VideoDelete::class);
$this->app->post('/videos/{episode_id}', Routes\Video\VideoAdd::class);

$this->app->post('/videos/{token}/report', Routes\Video\VideoReport::class);
$this->app->post('/videos/{token}/playlists', Routes\Video\VideoAddToPlaylist::class);
Expand Down
62 changes: 62 additions & 0 deletions lib/Routes/Video/VideoAdd.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace Opencast\Routes\Video;

use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Opencast\Errors\AuthorizationFailedException;
use Opencast\Errors\Error;
use Opencast\OpencastTrait;
use Opencast\OpencastController;
use Opencast\Models\Videos;

class VideoAdd extends OpencastController
{
use OpencastTrait;

public function __invoke(Request $request, Response $response, $args)
{
$json = $this->getRequestData($request);
$event = $json['event'];

$episode_id = $args['episode_id'];

$ret = [];

$video = Videos::findByEpisode($episode_id);
if (!empty($video) || !isset($event['config_id'])) {
$message = [
'type' => 'error',
'text' => _('Beim Erstellen des Videos ist ein Fehler aufgetreten.')
];
}
else {
$video = new Videos;
$video->setData([
'episode' => $episode_id,
'config_id' => $event['config_id'],
'title' => $event['title'],
'description' => $event['description'],
'duration' => $event['duration'],
'state' => $event['state'],
'available' => false
]);
if (!$video->token) {
$video->token = bin2hex(random_bytes(8));
}
$video->store();

$ret = $video->toSanitizedArray();

$message = [
'type' => 'success',
'text' => _('Das Video wurde erfolgreich erstellt.')
];
}

return $this->createResponse([
'message' => $message,
'event' => $ret
], $response->withStatus(200));
}
}
2 changes: 1 addition & 1 deletion vueapp/common/upload.service.js
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ class UploadService {
const xmlDoc = $.parseXML(mediaPackage);
episode_id = xmlDoc.documentElement.id;
if (episode_id) {
uploadDone(episode_id, workflowId);
uploadDone(episode_id, terms, workflowId);
}
} catch (ex) {
console.log(ex);
Expand Down
2 changes: 1 addition & 1 deletion vueapp/components/Videos/VideoCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
</span>
</span>
</a>
<span v-else-if="!event.available" class="oc--unavailable">
<span v-else-if="!event.available && !event.state" class="oc--unavailable">
{{ $gettext("Video nicht verfügbar") }}
</span>
<a v-else-if="event.state == 'cutting'"
Expand Down
61 changes: 59 additions & 2 deletions vueapp/components/Videos/VideoUpload.vue
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,20 @@
name="title" id="titleField" v-model="upload.title" required>
</label>

<label>
<span v-translate>
Zu Wiedergabeliste hinzufügen
</span>

<select v-model="upload.playlist_token" required>
<option v-for="playlist in upload_playlists"
v-bind:key="playlist.token"
:value="playlist.token">
{{ playlist.title }}
</option>
</select>
</label>

<label>
<span class="required" v-translate>
Aufnahmezeitpunkt
Expand Down Expand Up @@ -229,6 +243,7 @@ export default {
creator: this.currentUser.username,
contributor: this.currentUser.fullname,
workflow: null,
playlist_token: null,
recordDate: format(new Date(), "yyyy-MM-dd'T'HH:ii", { locale: de}),
subject: this.$gettext('Medienupload, Stud.IP')
},
Expand All @@ -244,9 +259,22 @@ export default {
...mapGetters({
'config' : 'simple_config_list',
'course_config': 'course_config',
'cid' : 'cid'
'cid' : 'cid',
'playlist' : 'playlist',
'playlists' : 'playlists'
}),

upload_playlists() {
let upload_playlists = this.playlists
if (!this.playlist) {
upload_playlists.unshift({
token: null,
title: 'Keine Wiedergabeliste auswählen'
})
}
return upload_playlists;
},

upload_workflows() {
let upload_wfs = [];

Expand Down Expand Up @@ -368,15 +396,40 @@ export default {
progress: parseInt(Math.round((loaded / total) * 100 ))
}
},
uploadDone: (episode_id, workflow_id) => {
uploadDone: (episode_id, uploadData, workflow_id) => {
view.$emit('done');
view.$store.dispatch('createLogEvent', {
event: 'upload',
data: {
episode_id: episode_id,
workflow_id: workflow_id
}
});

// Add event to database
view.$store.dispatch('createVideo', {
'episode': episode_id,
'config_id': view.selectedServer.id,
'title': uploadData.title,
'description': uploadData.description
})
.then(({ data }) => {
this.$store.dispatch('addMessage', data.message);

// If a playlist is selected, connect event with playlist
if (data.event?.token && uploadData.playlist_token) {
let playlist = view.playlists.find(p => p.token === uploadData.playlist_token);
if (playlist) {
this.$store.dispatch('addVideoToPlaylists', {
token: data.event.token,
playlists: [playlist],
})
.then(({data}) => {
this.$store.dispatch('addMessage', data.message);
})
}
}
});
}
});
},
Expand All @@ -401,6 +454,10 @@ export default {
if (this.cid) {
this.$store.dispatch('loadCourseConfig', this.cid);
}

if (this.playlist) {
this.upload.playlist_token = this.playlist.token;
}
}
}
</script>
4 changes: 4 additions & 0 deletions vueapp/store/videos.module.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,10 @@ const actions = {
return ApiService.put('playlists/' + data.playlist_token + '/positions', data.sortedVideos)
},

async createVideo(context, event) {
return ApiService.post('videos/' + event.episode, {event: event});
},

async deleteVideo(context, token) {
return ApiService.delete('videos/' + token);
},
Expand Down