From d87b45e4218d60e6931f298fc7518dd1066c249d Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Fri, 11 Oct 2024 16:58:25 +0200 Subject: [PATCH 01/16] Add controller method to get last created annotation --- app/Http/Controllers/Api/ImageController.php | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/ImageController.php b/app/Http/Controllers/Api/ImageController.php index fe9ccee14..a0362b7ec 100644 --- a/app/Http/Controllers/Api/ImageController.php +++ b/app/Http/Controllers/Api/ImageController.php @@ -2,8 +2,8 @@ namespace Biigle\Http\Controllers\Api; -use Biigle\Http\Requests\DestroyImage; use Biigle\Image; +use Biigle\Http\Requests\DestroyImage; class ImageController extends Controller { @@ -83,4 +83,11 @@ public function destroy(DestroyImage $request) { $request->file->delete(); } + + public function getLastAnnotationId($id){ + $image = Image::findOrFail($id); + $this->authorize('access',$image); + + return $image->annotations()->max('id'); + } } From dfb8c508cd1110b9e3a5eab517f6753952a82fc6 Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Fri, 11 Oct 2024 16:59:39 +0200 Subject: [PATCH 02/16] Add new routes for getting last annotation --- resources/assets/js/annotations/api/volumes.js | 11 ++++++++++- routes/api.php | 2 ++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/resources/assets/js/annotations/api/volumes.js b/resources/assets/js/annotations/api/volumes.js index a6f8a2021..b0c78a24c 100644 --- a/resources/assets/js/annotations/api/volumes.js +++ b/resources/assets/js/annotations/api/volumes.js @@ -8,4 +8,13 @@ * * @type {Vue.resource} */ -export default Vue.resource('api/v1/volumes{/id}/images/area'); +export default Vue.resource('api/v1/volumes', {}, { + getArea: { + method: 'GET', + url: 'api/v1/volumes{/id}/images/area', + }, + getLastAnnotationId: { + method: 'GET', + url: 'api/v1/volumes/images{/id}' + } +}); diff --git a/routes/api.php b/routes/api.php index 148d6b58a..9fac563ea 100644 --- a/routes/api.php +++ b/routes/api.php @@ -406,6 +406,8 @@ ]); }); +$router->get('volumes/images/{id}','ImageController@getLastAnnotationId'); + $router->get('users/find/{pattern}', 'UserController@find'); $router->get('users/my', 'UserController@showOwn'); From c4f786c5554208901197119f43bc07a7a55e8cf5 Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Fri, 11 Oct 2024 17:00:27 +0200 Subject: [PATCH 03/16] Select last created annotation by using shortcut --- app/Http/Controllers/Api/ImageController.php | 5 +++-- .../js/annotations/annotatorContainer.vue | 17 +++++++++++++++-- .../annotations/components/annotationCanvas.vue | 4 ++++ resources/views/annotations/show.blade.php | 1 + 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/Api/ImageController.php b/app/Http/Controllers/Api/ImageController.php index a0362b7ec..fcccd6846 100644 --- a/app/Http/Controllers/Api/ImageController.php +++ b/app/Http/Controllers/Api/ImageController.php @@ -84,9 +84,10 @@ public function destroy(DestroyImage $request) $request->file->delete(); } - public function getLastAnnotationId($id){ + public function getLastAnnotationId($id) + { $image = Image::findOrFail($id); - $this->authorize('access',$image); + $this->authorize('access', $image); return $image->annotations()->max('id'); } diff --git a/resources/assets/js/annotations/annotatorContainer.vue b/resources/assets/js/annotations/annotatorContainer.vue index a19df869b..9c3512c44 100644 --- a/resources/assets/js/annotations/annotatorContainer.vue +++ b/resources/assets/js/annotations/annotatorContainer.vue @@ -19,7 +19,7 @@ import ShapeFilter from './models/ShapeAnnotationFilter'; import Sidebar from '../core/components/sidebar'; import SidebarTab from '../core/components/sidebarTab'; import UserFilter from './models/UserAnnotationFilter'; -import VolumeImageAreaApi from './api/volumes'; +import VolumeImageApi from './api/volumes'; import {CrossOriginError} from './stores/images'; import {debounce} from './../core/utils'; import {handleErrorResponse} from '../core/messages/store'; @@ -551,7 +551,7 @@ export default { fetchImagesArea() { if (!this.imagesArea) { this.imagesArea = {}; - VolumeImageAreaApi.get({id: this.volumeId}) + VolumeImageApi.getArea({id: this.volumeId}) .then(this.setImagesArea, handleErrorResponse); } }, @@ -592,6 +592,19 @@ export default { } Messages.danger(`Invalid shape. ${shape} needs ${count} different points.`); }, + fetchLastAnnotationId() { + VolumeImageApi.getLastAnnotationId({ id: this.image.id }) + .then((res) => { + let id = parseInt(res.body); + this.annotations.map((a) => { + if (a.id === id) { + a.selected = true; + } else { + a.selected = false; + } + }) + }); + } }, watch: { async imageId(id) { diff --git a/resources/assets/js/annotations/components/annotationCanvas.vue b/resources/assets/js/annotations/components/annotationCanvas.vue index 4484b7d98..9f4e3a667 100644 --- a/resources/assets/js/annotations/components/annotationCanvas.vue +++ b/resources/assets/js/annotations/components/annotationCanvas.vue @@ -679,6 +679,9 @@ export default { Keyboard.on('Backspace', this.deleteLastCreatedAnnotation, 0, this.listenerSet); } }, + emitFetchLastAnnotation() { + this.$emit('fetch-last-annotation'); + } }, watch: { image(image, oldImage) { @@ -826,6 +829,7 @@ export default { Keyboard.on('ArrowRight', this.handleNext, 0, this.listenerSet); Keyboard.on('ArrowLeft', this.handlePrevious, 0, this.listenerSet); Keyboard.on('Escape', this.resetInteractionMode, 0, this.listenerSet); + Keyboard.on('Control+l', this.emitFetchLastAnnotation, 0, this.listenerSet); this.modifyInteraction.on('modifystart', this.handleFeatureModifyStart); this.modifyInteraction.on('modifyend', this.handleFeatureModifyEnd); diff --git a/resources/views/annotations/show.blade.php b/resources/views/annotations/show.blade.php index cca57c664..893b0e785 100644 --- a/resources/views/annotations/show.blade.php +++ b/resources/views/annotations/show.blade.php @@ -96,6 +96,7 @@ v-on:measuring="fetchImagesArea" v-on:requires-selected-label="handleRequiresSelectedLabel" v-on:is-invalid-shape="handleInvalidShape" + v-on:fetch-last-annotation="fetchLastAnnotationId" ref="canvas" inline-template> @include('annotations.show.annotationCanvas') From e218c3144f1fefa1e97205a2c74e80fecbb9bd2f Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Mon, 14 Oct 2024 14:39:11 +0200 Subject: [PATCH 04/16] Revert "Select last created annotation by using shortcut" This reverts commit c4f786c5554208901197119f43bc07a7a55e8cf5. --- app/Http/Controllers/Api/ImageController.php | 5 ++--- .../js/annotations/annotatorContainer.vue | 17 ++--------------- .../annotations/components/annotationCanvas.vue | 4 ---- resources/views/annotations/show.blade.php | 1 - 4 files changed, 4 insertions(+), 23 deletions(-) diff --git a/app/Http/Controllers/Api/ImageController.php b/app/Http/Controllers/Api/ImageController.php index fcccd6846..a0362b7ec 100644 --- a/app/Http/Controllers/Api/ImageController.php +++ b/app/Http/Controllers/Api/ImageController.php @@ -84,10 +84,9 @@ public function destroy(DestroyImage $request) $request->file->delete(); } - public function getLastAnnotationId($id) - { + public function getLastAnnotationId($id){ $image = Image::findOrFail($id); - $this->authorize('access', $image); + $this->authorize('access',$image); return $image->annotations()->max('id'); } diff --git a/resources/assets/js/annotations/annotatorContainer.vue b/resources/assets/js/annotations/annotatorContainer.vue index 9c3512c44..a19df869b 100644 --- a/resources/assets/js/annotations/annotatorContainer.vue +++ b/resources/assets/js/annotations/annotatorContainer.vue @@ -19,7 +19,7 @@ import ShapeFilter from './models/ShapeAnnotationFilter'; import Sidebar from '../core/components/sidebar'; import SidebarTab from '../core/components/sidebarTab'; import UserFilter from './models/UserAnnotationFilter'; -import VolumeImageApi from './api/volumes'; +import VolumeImageAreaApi from './api/volumes'; import {CrossOriginError} from './stores/images'; import {debounce} from './../core/utils'; import {handleErrorResponse} from '../core/messages/store'; @@ -551,7 +551,7 @@ export default { fetchImagesArea() { if (!this.imagesArea) { this.imagesArea = {}; - VolumeImageApi.getArea({id: this.volumeId}) + VolumeImageAreaApi.get({id: this.volumeId}) .then(this.setImagesArea, handleErrorResponse); } }, @@ -592,19 +592,6 @@ export default { } Messages.danger(`Invalid shape. ${shape} needs ${count} different points.`); }, - fetchLastAnnotationId() { - VolumeImageApi.getLastAnnotationId({ id: this.image.id }) - .then((res) => { - let id = parseInt(res.body); - this.annotations.map((a) => { - if (a.id === id) { - a.selected = true; - } else { - a.selected = false; - } - }) - }); - } }, watch: { async imageId(id) { diff --git a/resources/assets/js/annotations/components/annotationCanvas.vue b/resources/assets/js/annotations/components/annotationCanvas.vue index 9f4e3a667..4484b7d98 100644 --- a/resources/assets/js/annotations/components/annotationCanvas.vue +++ b/resources/assets/js/annotations/components/annotationCanvas.vue @@ -679,9 +679,6 @@ export default { Keyboard.on('Backspace', this.deleteLastCreatedAnnotation, 0, this.listenerSet); } }, - emitFetchLastAnnotation() { - this.$emit('fetch-last-annotation'); - } }, watch: { image(image, oldImage) { @@ -829,7 +826,6 @@ export default { Keyboard.on('ArrowRight', this.handleNext, 0, this.listenerSet); Keyboard.on('ArrowLeft', this.handlePrevious, 0, this.listenerSet); Keyboard.on('Escape', this.resetInteractionMode, 0, this.listenerSet); - Keyboard.on('Control+l', this.emitFetchLastAnnotation, 0, this.listenerSet); this.modifyInteraction.on('modifystart', this.handleFeatureModifyStart); this.modifyInteraction.on('modifyend', this.handleFeatureModifyEnd); diff --git a/resources/views/annotations/show.blade.php b/resources/views/annotations/show.blade.php index 893b0e785..cca57c664 100644 --- a/resources/views/annotations/show.blade.php +++ b/resources/views/annotations/show.blade.php @@ -96,7 +96,6 @@ v-on:measuring="fetchImagesArea" v-on:requires-selected-label="handleRequiresSelectedLabel" v-on:is-invalid-shape="handleInvalidShape" - v-on:fetch-last-annotation="fetchLastAnnotationId" ref="canvas" inline-template> @include('annotations.show.annotationCanvas') From 177509b8f6694c21ee59740574166619d8f231c7 Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Mon, 14 Oct 2024 14:39:42 +0200 Subject: [PATCH 05/16] Revert "Add new routes for getting last annotation" This reverts commit dfb8c508cd1110b9e3a5eab517f6753952a82fc6. --- resources/assets/js/annotations/api/volumes.js | 11 +---------- routes/api.php | 2 -- 2 files changed, 1 insertion(+), 12 deletions(-) diff --git a/resources/assets/js/annotations/api/volumes.js b/resources/assets/js/annotations/api/volumes.js index b0c78a24c..a6f8a2021 100644 --- a/resources/assets/js/annotations/api/volumes.js +++ b/resources/assets/js/annotations/api/volumes.js @@ -8,13 +8,4 @@ * * @type {Vue.resource} */ -export default Vue.resource('api/v1/volumes', {}, { - getArea: { - method: 'GET', - url: 'api/v1/volumes{/id}/images/area', - }, - getLastAnnotationId: { - method: 'GET', - url: 'api/v1/volumes/images{/id}' - } -}); +export default Vue.resource('api/v1/volumes{/id}/images/area'); diff --git a/routes/api.php b/routes/api.php index 9fac563ea..148d6b58a 100644 --- a/routes/api.php +++ b/routes/api.php @@ -406,8 +406,6 @@ ]); }); -$router->get('volumes/images/{id}','ImageController@getLastAnnotationId'); - $router->get('users/find/{pattern}', 'UserController@find'); $router->get('users/my', 'UserController@showOwn'); From ef89f9d058209a9ca823905a31447cb52d5295b5 Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Mon, 14 Oct 2024 14:39:54 +0200 Subject: [PATCH 06/16] Revert "Add controller method to get last created annotation" This reverts commit d87b45e4218d60e6931f298fc7518dd1066c249d. --- app/Http/Controllers/Api/ImageController.php | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/app/Http/Controllers/Api/ImageController.php b/app/Http/Controllers/Api/ImageController.php index a0362b7ec..fe9ccee14 100644 --- a/app/Http/Controllers/Api/ImageController.php +++ b/app/Http/Controllers/Api/ImageController.php @@ -2,8 +2,8 @@ namespace Biigle\Http\Controllers\Api; -use Biigle\Image; use Biigle\Http\Requests\DestroyImage; +use Biigle\Image; class ImageController extends Controller { @@ -83,11 +83,4 @@ public function destroy(DestroyImage $request) { $request->file->delete(); } - - public function getLastAnnotationId($id){ - $image = Image::findOrFail($id); - $this->authorize('access',$image); - - return $image->annotations()->max('id'); - } } From 6c195b9064401fe25076867d600519991afbc379 Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Mon, 14 Oct 2024 15:23:40 +0200 Subject: [PATCH 07/16] Add shortcut to select last annotation --- resources/assets/js/annotations/annotatorContainer.vue | 6 ++++++ .../assets/js/annotations/components/annotationCanvas.vue | 4 ++++ resources/assets/js/videos/components/videoScreen.vue | 4 ++++ resources/assets/js/videos/videoContainer.vue | 6 ++++++ resources/views/annotations/show.blade.php | 1 + resources/views/videos/show/content.blade.php | 1 + 6 files changed, 22 insertions(+) diff --git a/resources/assets/js/annotations/annotatorContainer.vue b/resources/assets/js/annotations/annotatorContainer.vue index a19df869b..7f2b8ad91 100644 --- a/resources/assets/js/annotations/annotatorContainer.vue +++ b/resources/assets/js/annotations/annotatorContainer.vue @@ -592,6 +592,12 @@ export default { } Messages.danger(`Invalid shape. ${shape} needs ${count} different points.`); }, + selectLastAnnotation() { + let lastAnnotation = this.annotations.reduce((lastAnnotated, a) => a.id > lastAnnotated.id ? a : lastAnnotated, { id: 0 }); + let remainingAnnotations = this.annotations.filter(a => a.id != lastAnnotation.id); + lastAnnotation.selected = true; + remainingAnnotations.map(a => a.selected = false); + } }, watch: { async imageId(id) { diff --git a/resources/assets/js/annotations/components/annotationCanvas.vue b/resources/assets/js/annotations/components/annotationCanvas.vue index 4484b7d98..4cf061078 100644 --- a/resources/assets/js/annotations/components/annotationCanvas.vue +++ b/resources/assets/js/annotations/components/annotationCanvas.vue @@ -679,6 +679,9 @@ export default { Keyboard.on('Backspace', this.deleteLastCreatedAnnotation, 0, this.listenerSet); } }, + emitSelectLastAnnotation() { + this.$emit('select-last-annotation'); + } }, watch: { image(image, oldImage) { @@ -826,6 +829,7 @@ export default { Keyboard.on('ArrowRight', this.handleNext, 0, this.listenerSet); Keyboard.on('ArrowLeft', this.handlePrevious, 0, this.listenerSet); Keyboard.on('Escape', this.resetInteractionMode, 0, this.listenerSet); + Keyboard.on('Control+l', this.emitSelectLastAnnotation, 0, this.listenerSet); this.modifyInteraction.on('modifystart', this.handleFeatureModifyStart); this.modifyInteraction.on('modifyend', this.handleFeatureModifyEnd); diff --git a/resources/assets/js/videos/components/videoScreen.vue b/resources/assets/js/videos/components/videoScreen.vue index fb287ecbe..3e1b73802 100644 --- a/resources/assets/js/videos/components/videoScreen.vue +++ b/resources/assets/js/videos/components/videoScreen.vue @@ -571,6 +571,9 @@ export default { Keyboard.on('ArrowRight', this.emitNext, 0, this.listenerSet); Keyboard.on('ArrowLeft', this.emitPrevious, 0, this.listenerSet); } + }, + emitSelectLastAnnotation() { + this.$emit('select-last-annotation'); } }, watch: { @@ -637,6 +640,7 @@ export default { Keyboard.on('Escape', this.resetInteractionMode, 0, this.listenerSet); Keyboard.on('Control+ArrowRight', this.jumpForward, 0, this.listenerSet); Keyboard.on('Control+ArrowLeft', this.jumpBackward, 0, this.listenerSet); + Keyboard.on('Control+l', this.emitSelectLastAnnotation, 0, this.listenerSet); }, mounted() { this.map.setTarget(this.$el); diff --git a/resources/assets/js/videos/videoContainer.vue b/resources/assets/js/videos/videoContainer.vue index b45c7cc44..dca61372e 100644 --- a/resources/assets/js/videos/videoContainer.vue +++ b/resources/assets/js/videos/videoContainer.vue @@ -673,6 +673,12 @@ export default { } Messages.danger(`Invalid shape. ${shape} needs ${count} different points.`); }, + selectLastAnnotation() { + let lastAnnotation = this.annotations.reduce((lastAnnotated, a) => a.id > lastAnnotated.id ? a : lastAnnotated, { id: 0 }); + let remainingAnnotations = this.annotations.filter(a => a.id != lastAnnotation.id); + lastAnnotation.selected = true; + remainingAnnotations.map(a => a.selected = false); + } }, watch: { 'settings.playbackRate'(rate) { diff --git a/resources/views/annotations/show.blade.php b/resources/views/annotations/show.blade.php index cca57c664..0831b50ba 100644 --- a/resources/views/annotations/show.blade.php +++ b/resources/views/annotations/show.blade.php @@ -96,6 +96,7 @@ v-on:measuring="fetchImagesArea" v-on:requires-selected-label="handleRequiresSelectedLabel" v-on:is-invalid-shape="handleInvalidShape" + v-on:select-last-annotation="selectLastAnnotation" ref="canvas" inline-template> @include('annotations.show.annotationCanvas') diff --git a/resources/views/videos/show/content.blade.php b/resources/views/videos/show/content.blade.php index faf6bf059..54de21f37 100644 --- a/resources/views/videos/show/content.blade.php +++ b/resources/views/videos/show/content.blade.php @@ -65,6 +65,7 @@ v-on:seek="seek" v-on:start-seeking="startSeeking" v-on:is-invalid-shape="handleInvalidShape" + v-on:select-last-annotation="selectLastAnnotation" > Date: Tue, 15 Oct 2024 11:04:20 +0200 Subject: [PATCH 08/16] Use selection methods to select last annotation --- resources/assets/js/annotations/annotatorContainer.vue | 4 +--- resources/assets/js/videos/videoContainer.vue | 4 +--- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/resources/assets/js/annotations/annotatorContainer.vue b/resources/assets/js/annotations/annotatorContainer.vue index 7f2b8ad91..59e427ba6 100644 --- a/resources/assets/js/annotations/annotatorContainer.vue +++ b/resources/assets/js/annotations/annotatorContainer.vue @@ -594,9 +594,7 @@ export default { }, selectLastAnnotation() { let lastAnnotation = this.annotations.reduce((lastAnnotated, a) => a.id > lastAnnotated.id ? a : lastAnnotated, { id: 0 }); - let remainingAnnotations = this.annotations.filter(a => a.id != lastAnnotation.id); - lastAnnotation.selected = true; - remainingAnnotations.map(a => a.selected = false); + this.handleSelectAnnotation(lastAnnotation); } }, watch: { diff --git a/resources/assets/js/videos/videoContainer.vue b/resources/assets/js/videos/videoContainer.vue index dca61372e..dee0dd040 100644 --- a/resources/assets/js/videos/videoContainer.vue +++ b/resources/assets/js/videos/videoContainer.vue @@ -675,9 +675,7 @@ export default { }, selectLastAnnotation() { let lastAnnotation = this.annotations.reduce((lastAnnotated, a) => a.id > lastAnnotated.id ? a : lastAnnotated, { id: 0 }); - let remainingAnnotations = this.annotations.filter(a => a.id != lastAnnotation.id); - lastAnnotation.selected = true; - remainingAnnotations.map(a => a.selected = false); + this.selectAnnotations([lastAnnotation], [], lastAnnotation.startFrame); } }, watch: { From cd791a3e7b13b396c5b00956565fd3df0fe16e61 Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Tue, 15 Oct 2024 11:07:47 +0200 Subject: [PATCH 09/16] Change last annotation shortcut to ctrl --- resources/assets/js/annotations/components/annotationCanvas.vue | 2 +- resources/assets/js/videos/components/videoScreen.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/assets/js/annotations/components/annotationCanvas.vue b/resources/assets/js/annotations/components/annotationCanvas.vue index 4cf061078..27922f66c 100644 --- a/resources/assets/js/annotations/components/annotationCanvas.vue +++ b/resources/assets/js/annotations/components/annotationCanvas.vue @@ -829,7 +829,7 @@ export default { Keyboard.on('ArrowRight', this.handleNext, 0, this.listenerSet); Keyboard.on('ArrowLeft', this.handlePrevious, 0, this.listenerSet); Keyboard.on('Escape', this.resetInteractionMode, 0, this.listenerSet); - Keyboard.on('Control+l', this.emitSelectLastAnnotation, 0, this.listenerSet); + Keyboard.on('Control', this.emitSelectLastAnnotation, 0, this.listenerSet); this.modifyInteraction.on('modifystart', this.handleFeatureModifyStart); this.modifyInteraction.on('modifyend', this.handleFeatureModifyEnd); diff --git a/resources/assets/js/videos/components/videoScreen.vue b/resources/assets/js/videos/components/videoScreen.vue index 3e1b73802..5690b5fc2 100644 --- a/resources/assets/js/videos/components/videoScreen.vue +++ b/resources/assets/js/videos/components/videoScreen.vue @@ -640,7 +640,7 @@ export default { Keyboard.on('Escape', this.resetInteractionMode, 0, this.listenerSet); Keyboard.on('Control+ArrowRight', this.jumpForward, 0, this.listenerSet); Keyboard.on('Control+ArrowLeft', this.jumpBackward, 0, this.listenerSet); - Keyboard.on('Control+l', this.emitSelectLastAnnotation, 0, this.listenerSet); + Keyboard.on('Control', this.emitSelectLastAnnotation, 0, this.listenerSet); }, mounted() { this.map.setTarget(this.$el); From 580efaced8e8a793b7b7d45e510fb412f5911e1e Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Tue, 15 Oct 2024 11:17:01 +0200 Subject: [PATCH 10/16] Fix problem with seeking last annoation Deselect all other annotations to enable seeking again, if another annotation was already selected. --- resources/assets/js/videos/videoContainer.vue | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/resources/assets/js/videos/videoContainer.vue b/resources/assets/js/videos/videoContainer.vue index dee0dd040..91f6c2ea1 100644 --- a/resources/assets/js/videos/videoContainer.vue +++ b/resources/assets/js/videos/videoContainer.vue @@ -675,7 +675,8 @@ export default { }, selectLastAnnotation() { let lastAnnotation = this.annotations.reduce((lastAnnotated, a) => a.id > lastAnnotated.id ? a : lastAnnotated, { id: 0 }); - this.selectAnnotations([lastAnnotation], [], lastAnnotation.startFrame); + let remainingAnnotations = this.annotations.filter(a => a.id != lastAnnotation.id); + this.selectAnnotations([lastAnnotation], remainingAnnotations, lastAnnotation.startFrame); } }, watch: { From da02baa8c78294fe39a062f76157be002966463c Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Tue, 15 Oct 2024 11:21:58 +0200 Subject: [PATCH 11/16] Add shortcut to manuals --- .../views/manual/tutorials/annotations/shortcuts.blade.php | 4 ++++ resources/views/manual/tutorials/videos/shortcuts.blade.php | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/resources/views/manual/tutorials/annotations/shortcuts.blade.php b/resources/views/manual/tutorials/annotations/shortcuts.blade.php index 881868cfb..7f3db3125 100644 --- a/resources/views/manual/tutorials/annotations/shortcuts.blade.php +++ b/resources/views/manual/tutorials/annotations/shortcuts.blade.php @@ -123,6 +123,10 @@ p Capture a screenshot + + Ctrl + Select last created annotation + diff --git a/resources/views/manual/tutorials/videos/shortcuts.blade.php b/resources/views/manual/tutorials/videos/shortcuts.blade.php index 770d627b1..fb365eeed 100644 --- a/resources/views/manual/tutorials/videos/shortcuts.blade.php +++ b/resources/views/manual/tutorials/videos/shortcuts.blade.php @@ -115,6 +115,10 @@ Esc Cancel current action
e.g. drawing or moving an annotation + + Ctrl + Select last created annotation + From fefcebab7cac4a475afb5974340d0736c6129277 Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Thu, 17 Oct 2024 07:41:42 +0200 Subject: [PATCH 12/16] Use computed property to get selected annotations --- resources/assets/js/videos/videoContainer.vue | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/resources/assets/js/videos/videoContainer.vue b/resources/assets/js/videos/videoContainer.vue index 91f6c2ea1..4d7f2bf09 100644 --- a/resources/assets/js/videos/videoContainer.vue +++ b/resources/assets/js/videos/videoContainer.vue @@ -675,8 +675,7 @@ export default { }, selectLastAnnotation() { let lastAnnotation = this.annotations.reduce((lastAnnotated, a) => a.id > lastAnnotated.id ? a : lastAnnotated, { id: 0 }); - let remainingAnnotations = this.annotations.filter(a => a.id != lastAnnotation.id); - this.selectAnnotations([lastAnnotation], remainingAnnotations, lastAnnotation.startFrame); + this.selectAnnotations([lastAnnotation], this.selectedAnnotations, lastAnnotation.startFrame); } }, watch: { From 17ce78393828161d8c0d63300d7dee3899896af2 Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Mon, 4 Nov 2024 07:58:28 +0100 Subject: [PATCH 13/16] Listen to last annotation event in annotatorContainer --- resources/assets/js/annotations/annotatorContainer.vue | 3 +++ .../assets/js/annotations/components/annotationCanvas.vue | 4 ---- resources/views/annotations/show.blade.php | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/resources/assets/js/annotations/annotatorContainer.vue b/resources/assets/js/annotations/annotatorContainer.vue index 59e427ba6..6e5678917 100644 --- a/resources/assets/js/annotations/annotatorContainer.vue +++ b/resources/assets/js/annotations/annotatorContainer.vue @@ -24,6 +24,7 @@ import {CrossOriginError} from './stores/images'; import {debounce} from './../core/utils'; import {handleErrorResponse} from '../core/messages/store'; import {urlParams as UrlParams} from '../core/utils'; +import Keyboard from '../core/keyboard'; /** * View model for the annotator container @@ -746,6 +747,8 @@ export default { this.openTab = openTab; } } + + Keyboard.on('Control', this.selectLastAnnotation, 0, this.listenerSet); }, mounted() { Events.$emit('annotations.map.init', this.$refs.canvas.map); diff --git a/resources/assets/js/annotations/components/annotationCanvas.vue b/resources/assets/js/annotations/components/annotationCanvas.vue index 27922f66c..4484b7d98 100644 --- a/resources/assets/js/annotations/components/annotationCanvas.vue +++ b/resources/assets/js/annotations/components/annotationCanvas.vue @@ -679,9 +679,6 @@ export default { Keyboard.on('Backspace', this.deleteLastCreatedAnnotation, 0, this.listenerSet); } }, - emitSelectLastAnnotation() { - this.$emit('select-last-annotation'); - } }, watch: { image(image, oldImage) { @@ -829,7 +826,6 @@ export default { Keyboard.on('ArrowRight', this.handleNext, 0, this.listenerSet); Keyboard.on('ArrowLeft', this.handlePrevious, 0, this.listenerSet); Keyboard.on('Escape', this.resetInteractionMode, 0, this.listenerSet); - Keyboard.on('Control', this.emitSelectLastAnnotation, 0, this.listenerSet); this.modifyInteraction.on('modifystart', this.handleFeatureModifyStart); this.modifyInteraction.on('modifyend', this.handleFeatureModifyEnd); diff --git a/resources/views/annotations/show.blade.php b/resources/views/annotations/show.blade.php index 0831b50ba..cca57c664 100644 --- a/resources/views/annotations/show.blade.php +++ b/resources/views/annotations/show.blade.php @@ -96,7 +96,6 @@ v-on:measuring="fetchImagesArea" v-on:requires-selected-label="handleRequiresSelectedLabel" v-on:is-invalid-shape="handleInvalidShape" - v-on:select-last-annotation="selectLastAnnotation" ref="canvas" inline-template> @include('annotations.show.annotationCanvas') From cd2b8b950d6bc917bf8a69c34c847640a0746224 Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Mon, 4 Nov 2024 08:02:55 +0100 Subject: [PATCH 14/16] Listen to last annotation event in videoContainer --- resources/assets/js/videos/components/videoScreen.vue | 4 ---- resources/assets/js/videos/videoContainer.vue | 3 +++ resources/views/videos/show/content.blade.php | 1 - 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/resources/assets/js/videos/components/videoScreen.vue b/resources/assets/js/videos/components/videoScreen.vue index 5690b5fc2..fb287ecbe 100644 --- a/resources/assets/js/videos/components/videoScreen.vue +++ b/resources/assets/js/videos/components/videoScreen.vue @@ -571,9 +571,6 @@ export default { Keyboard.on('ArrowRight', this.emitNext, 0, this.listenerSet); Keyboard.on('ArrowLeft', this.emitPrevious, 0, this.listenerSet); } - }, - emitSelectLastAnnotation() { - this.$emit('select-last-annotation'); } }, watch: { @@ -640,7 +637,6 @@ export default { Keyboard.on('Escape', this.resetInteractionMode, 0, this.listenerSet); Keyboard.on('Control+ArrowRight', this.jumpForward, 0, this.listenerSet); Keyboard.on('Control+ArrowLeft', this.jumpBackward, 0, this.listenerSet); - Keyboard.on('Control', this.emitSelectLastAnnotation, 0, this.listenerSet); }, mounted() { this.map.setTarget(this.$el); diff --git a/resources/assets/js/videos/videoContainer.vue b/resources/assets/js/videos/videoContainer.vue index 4d7f2bf09..7fa0087c6 100644 --- a/resources/assets/js/videos/videoContainer.vue +++ b/resources/assets/js/videos/videoContainer.vue @@ -18,6 +18,7 @@ import VideoApi from './api/videos'; import VideoLabelsTab from './components/videoLabelsTab'; import VideoScreen from './components/videoScreen'; import VideoTimeline from './components/videoTimeline'; +import Keyboard from '../core/keyboard'; import {handleErrorResponse} from '../core/messages/store'; import {urlParams as UrlParams} from '../core/utils'; @@ -728,6 +729,8 @@ export default { this.video.addEventListener('pause', this.updateVideoUrlParams); this.video.addEventListener('seeked', this.updateVideoUrlParams); + Keyboard.on('Control', this.selectLastAnnotation, 0, this.listenerSet); + if (Settings.has('openTab')) { this.openTab = Settings.get('openTab'); } diff --git a/resources/views/videos/show/content.blade.php b/resources/views/videos/show/content.blade.php index 54de21f37..faf6bf059 100644 --- a/resources/views/videos/show/content.blade.php +++ b/resources/views/videos/show/content.blade.php @@ -65,7 +65,6 @@ v-on:seek="seek" v-on:start-seeking="startSeeking" v-on:is-invalid-shape="handleInvalidShape" - v-on:select-last-annotation="selectLastAnnotation" > Date: Tue, 5 Nov 2024 07:40:47 +0100 Subject: [PATCH 15/16] Use 'c' to highlight last annotation --- resources/assets/js/annotations/annotatorContainer.vue | 2 +- resources/assets/js/videos/videoContainer.vue | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/assets/js/annotations/annotatorContainer.vue b/resources/assets/js/annotations/annotatorContainer.vue index 6e5678917..880baa939 100644 --- a/resources/assets/js/annotations/annotatorContainer.vue +++ b/resources/assets/js/annotations/annotatorContainer.vue @@ -748,7 +748,7 @@ export default { } } - Keyboard.on('Control', this.selectLastAnnotation, 0, this.listenerSet); + Keyboard.on('C', this.selectLastAnnotation, 0, this.listenerSet); }, mounted() { Events.$emit('annotations.map.init', this.$refs.canvas.map); diff --git a/resources/assets/js/videos/videoContainer.vue b/resources/assets/js/videos/videoContainer.vue index 7fa0087c6..3fed5dcbe 100644 --- a/resources/assets/js/videos/videoContainer.vue +++ b/resources/assets/js/videos/videoContainer.vue @@ -729,7 +729,7 @@ export default { this.video.addEventListener('pause', this.updateVideoUrlParams); this.video.addEventListener('seeked', this.updateVideoUrlParams); - Keyboard.on('Control', this.selectLastAnnotation, 0, this.listenerSet); + Keyboard.on('C', this.selectLastAnnotation, 0, this.listenerSet); if (Settings.has('openTab')) { this.openTab = Settings.get('openTab'); From 94e99132ae4d00752ca449ccf2271220ef666908 Mon Sep 17 00:00:00 2001 From: Leane Schlundt Date: Tue, 5 Nov 2024 07:42:54 +0100 Subject: [PATCH 16/16] Update manuals --- .../views/manual/tutorials/annotations/shortcuts.blade.php | 2 +- resources/views/manual/tutorials/videos/shortcuts.blade.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/resources/views/manual/tutorials/annotations/shortcuts.blade.php b/resources/views/manual/tutorials/annotations/shortcuts.blade.php index 7f3db3125..97c916c85 100644 --- a/resources/views/manual/tutorials/annotations/shortcuts.blade.php +++ b/resources/views/manual/tutorials/annotations/shortcuts.blade.php @@ -124,7 +124,7 @@ Capture a screenshot - Ctrl + c Select last created annotation diff --git a/resources/views/manual/tutorials/videos/shortcuts.blade.php b/resources/views/manual/tutorials/videos/shortcuts.blade.php index fb365eeed..6a443ad81 100644 --- a/resources/views/manual/tutorials/videos/shortcuts.blade.php +++ b/resources/views/manual/tutorials/videos/shortcuts.blade.php @@ -116,7 +116,7 @@ Cancel current action
e.g. drawing or moving an annotation - Ctrl + c Select last created annotation