Skip to content

Commit

Permalink
Merge pull request #1014 from ToukL/video-info-view
Browse files Browse the repository at this point in the history
Add video info view
  • Loading branch information
mzur authored Jan 23, 2025
2 parents 82087b9 + d87b877 commit 3d9979f
Show file tree
Hide file tree
Showing 13 changed files with 329 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ public function show($id)
$annotation = VideoAnnotation::findOrFail($id);
$this->authorize('access', $annotation);

return redirect()->route('video', [
return redirect()->route('video-annotate', [
'id' => $annotation->video_id,
'annotation' => $annotation->id,
]);
Expand Down
36 changes: 36 additions & 0 deletions app/Http/Controllers/Views/Volumes/VideoController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

namespace Biigle\Http\Controllers\Views\Volumes;

use Arr;
use Biigle\Http\Controllers\Views\Controller;
use Biigle\Video;

class VideoController extends Controller
{
/**
* Shows the video index page.
*
* @param int $id volume ID
*/
public function index($id)
{
$video = Video::with('volume')->findOrFail($id);

$this->authorize('access', $video);

$metadataMap = [
'gps_altitude' => 'GPS Altitude',
'distance_to_ground' => 'Distance to ground',
'yaw' => 'Yaw/Heading',
'area' => 'Area',
];

return view('volumes.videos.index', [
'video' => $video,
'volume' => $video->volume,
'metadata' => Arr::only($video->metadata, array_keys($metadataMap)),
'metadataMap' => $metadataMap,
]);
}
}
81 changes: 81 additions & 0 deletions resources/assets/js/volumes/components/metadataModal.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
<template>
<modal
ref="modal"
v-model="show"
size="md"
:title="name"
:footer="false"
>
<div class="panel panel-default">
<table class="table">
<thead>
<tr>
<th class="text-center" v-if="times">{{ "Time" }}</th>
<th class="text-center" v-if="name !== 'Times'">{{ name }}</th>
</tr>
</thead>
<tbody v-if="name === 'Times'">
<tr v-for="time in times">
<td class="text-center">{{ time }}</td>
</tr>
</tbody>
<tbody v-else-if="times.length === items.length">
<tr v-for="(item, index) in items">
<td class="text-center">{{ times[index] }}</td>
<td class="text-center">{{ item }}</td>
</tr>
</tbody>
</table>
</div>
</modal>
</template>

<script>
import { Modal } from 'uiv';
export default {
components: {
modal: Modal,
},
props: {
showModal: {
required: true,
type: Boolean,
},
times: {
required: true,
type: Array,
},
items: {
required: true,
type: Array,
},
name: {
required: true,
type: String,
},
},
data() {
return {
show: false,
};
},
watch: {
// if volume-metadata-button pressed, trigger modal
showModal: function () {
if (this.showModal) {
this.show = true;
}
},
// if modal is closed, trigger the close-modal-event, which sets 'showModal' in parent container to false again
show: function() {
if (this.show === false) {
this.$emit('close-modal');
}
}
},
created() {
this.show = false;
}
}
</script>
2 changes: 2 additions & 0 deletions resources/assets/js/volumes/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import MetadataUpload from './metadataUpload';
import ProjectsBreadcrumb from './projectsBreadcrumb';
import SearchResults from './searchResults';
import VolumeContainer from './volumeContainer';
import VideoMetadata from './videoMetadata.vue';

biigle.$mount('annotation-session-panel', AnnotationSessionPanel);
biigle.$mount('create-volume-form-step-1', CreateFormStep1);
Expand All @@ -30,3 +31,4 @@ biigle.$mount('search-results', SearchResults);
biigle.$mount('volume-container', VolumeContainer);
biigle.$mount('volume-file-count', FileCount);
biigle.$mount('volume-metadata-upload', MetadataUpload);
biigle.$mount('video-metadata-modal', VideoMetadata);
62 changes: 62 additions & 0 deletions resources/assets/js/volumes/videoMetadata.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<script>
import LoaderMixin from '../core/mixins/loader';
import Messages from '../core/messages/store';
import metadataModal from './components/metadataModal';
/**
* The video container for metadata.
*/
export default {
mixins: [
LoaderMixin,
],
components: {
metadataModal: metadataModal,
},
data() {
return {
showModal: false,
metadata: null,
metadataMap: {},
times: [],
items: [],
name: "",
};
},
methods: {
getTimes(values) {
// If modal has been opened before, use cached data
if (this.times.length === 0) {
let dateStrings = [];
const options = { year: "numeric", month: "numeric", day: "numeric", hour: '2-digit', minute:'2-digit', second:'2-digit'}
values.forEach(element => {
dateStrings.push(new Date(element).toLocaleDateString(undefined, options));
});
this.times = dateStrings;
}
},
showTimes() {
if (this.times.length === 0)
this.handleError("No times data found.");
this.name = "Times";
this.showModal = true;
},
showMetadata(field) {
this.name = this.metadataMap[field];
this.items = this.metadata[field];
this.showModal = true;
},
hideMetadataModal() {
this.showModal = false;
},
handleError(message) {
Messages.danger(message);
},
},
created() {
this.getTimes(biigle.$require('videos.times'));
this.metadata = biigle.$require('videos.metadata');
this.metadataMap = biigle.$require('videos.metadataMap');
}
};
</script>
2 changes: 1 addition & 1 deletion resources/views/search/videos-content.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<ul id="search-results" class="row volume-search-results">
@foreach ($results as $video)
<li class="col-xs-4">
<a href="{{route('video', $video->id)}}" title="Show video {{$video->filename}}">
<a href="{{route('video-annotate', $video->id)}}" title="Show video {{$video->filename}}">
<preview-thumbnail class="preview-thumbnail" :id="{{$video->id}}" thumb-uris="{{$video->thumbnailsUrl->implode(',')}}">
<img src="{{ $video->thumbnailUrl }}" onerror="this.src='{{ asset(config('thumbnails.empty_url')) }}'">
<figcaption slot="caption">{{$video->filename}}</figcaption>
Expand Down
2 changes: 1 addition & 1 deletion resources/views/videos/dashboardActivityItem.blade.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<a class="activity-item" href="{{route('video', $item->id)}}" title="Show video {{$item->name}}">
<a class="activity-item" href="{{route('video-annotate', $item->id)}}" title="Show video {{$item->name}}">
<figure class="activity-item-image">
<i class="icon fas fa-film fa-lg"></i>
<img src="{{ $item->thumbnailUrl }}" onerror="this.src='{{ asset(config('thumbnails.empty_url')) }}'">
Expand Down
4 changes: 2 additions & 2 deletions resources/views/volumes/show.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@
biigle.$declare('volumes.infoUri', '{{ route('image', ':id') }}');
@else
biigle.$declare('volumes.thumbCount', {{ config('videos.thumbnail_count') }});
biigle.$declare('volumes.annotateUri', '{{ route('video', ':id') }}');
biigle.$declare('volumes.infoUri', undefined);
biigle.$declare('volumes.annotateUri', '{{ route('video-annotate', ':id') }}');
biigle.$declare('volumes.infoUri', '{{ route('video', ':id') }}');
@endif
biigle.$declare('volumes.userId', {!! $user->id !!});
Expand Down
33 changes: 33 additions & 0 deletions resources/views/volumes/videos/index.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
@extends('app')
@section('title', $video->filename)

@section('content')
<div class="container">
<div class="row">
<h2 class="col-lg-12 clearfix file-info-title" title="{{ $video->filename }}">
{{ $video->filename }}
<span class="pull-right">
<a href="{{route('volume', $volume->id)}}" title="Back to {{ $volume->name }}" class="btn btn-default">back</a>
@mixin('imagesIndexButtons')
</span>
</h2>
</div>
<div class="row">
<div class="col-sm-6 col-lg-4">
<div class="panel panel-default panel-image">
<img src="{{ $video->thumbnail_url }}" onerror="this.src='{{ asset(config('thumbnails.empty_url')) }}'">
</div>
@include('volumes.videos.index.meta')
</div>
</div>
</div>
@endsection

@section('navbar')
<div class="navbar-text navbar-volumes-breadcrumbs">
@include('volumes.partials.projectsBreadcrumb', ['projects' => $volume->projects]) /
<a href="{{route('volume', $volume->id)}}" class="navbar-link" title="Show volume {{$volume->name}}">{{$volume->name}}</a> /
<strong title="{{$video->filename}}">{{$video->filename}}</strong>
@include('volumes.partials.annotationSessionIndicator')
</div>
@endsection
68 changes: 68 additions & 0 deletions resources/views/volumes/videos/index/meta.blade.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
@push('scripts')
<script type="text/javascript">
biigle.$declare('videos.times', {!! collect($video->taken_at) !!});
biigle.$declare('videos.metadata', {!! collect($video->metadata) !!});
biigle.$declare('videos.metadataMap', {!! collect($metadataMap) !!});
</script>
@endpush

<div id="video-metadata-modal" class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Video information</h3>
</div>
<table class="table">
@if ($video->width && $video->height)
<tr>
<th>Dimensions</th>
<td>{{ $video->width }} &times; {{ $video->height }} px </td>
</tr>
@endif
@if ($video->size)
<tr>
<th>Size</th>
<td>{{ round($video->size / 1E+6, 2) }} MBytes </td>
</tr>
@endif
@if ($video->mimetype)
<tr>
<th>MIME</th>
<td><code>{{ $video->mimetype }}</code></td>
</tr>
@endif
@if ($video->taken_at)
@if (is_array($video->taken_at))
<metadata-modal v-bind:show-modal="showModal" v-bind:times="times" v-bind:items="items" v-bind:name="name" v-on:close-modal="hideMetadataModal"></metadata-modal>
<tr>
<th>
<a href="#" v-on:click.prevent="showTimes()">Created</a>
</th>
<td></td>
</tr>
@foreach ($metadata as $field => $value)
<tr>
@if (is_array($value))
<th>
<a href="#" v-on:click.prevent="showMetadata({{ json_encode($field) }})">{{ $metadataMap[$field] }}</a>
</th>
<td></td>
@else
<th>{{ $metadataMap[$field] }}</th>
<td>{{ $value }}</td>
@endif
</tr>
@endforeach
@else
<tr>
<th>Created</th>
<td>{{ $video->taken_at }}</td>
</tr>
@foreach ($metadata as $field => $value)
<tr>
<th>{{ $metadataMap[$field] }}</th>
<td>{{ $value }}</td>
</tr>
@endforeach
@endif
@endif
</table>
</div>
10 changes: 6 additions & 4 deletions routes/web.php
Original file line number Diff line number Diff line change
Expand Up @@ -353,19 +353,21 @@
$router->redirect('annotations/{id}', '/image-annotations/{id}');
});

$router->get('videos/{id}', [
'as' => 'video',
'uses' => 'Volumes\VideoController@index',
]);

$router->group(['namespace' => 'Videos'], function ($router) {
$router->get('videos/{id}/annotations', [
'as' => 'video',
'as' => 'video-annotate',
'uses' => 'VideoController@show',
]);

$router->get('video-annotations/{id}', [
'as' => 'show-video-annotation',
'uses' => 'VideoAnnotationController@show',
]);

// Legacy support.
$router->redirect('videos/{id}', '/videos/{id}/annotations');
});

});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,4 @@ public function testShow()
$this->beGuest();
$this->get("videos/{$video->id}/annotations")->assertStatus(200);
}

public function testShowRedirect()
{
$this->beUser();
$this->get('videos/999')->assertRedirect('/videos/999/annotations');
}
}
Loading

0 comments on commit 3d9979f

Please sign in to comment.