aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlutangar <johan.dufour@gmail.com>2022-08-30 17:13:26 +0200
committerChocobozzz <chocobozzz@cpy.re>2022-09-08 08:41:36 +0200
commit2873a53efd8913b6b5fbf305320f88731cd07771 (patch)
tree5063f5b38f222ce27f6923dc4bb8765f713ac4c7
parent5f016383a4fabf2f296cda6d5e383719ee9d5e27 (diff)
downloadPeerTube-2873a53efd8913b6b5fbf305320f88731cd07771.tar.gz
PeerTube-2873a53efd8913b6b5fbf305320f88731cd07771.tar.zst
PeerTube-2873a53efd8913b6b5fbf305320f88731cd07771.zip
Set scroll position at top of the textarea when opening the subtitle editor.
## Description This set the position of the scrollbar at the top of the textarea when opening the __subtitle editor__. Previously the textarea scroll position was at the bottom of the textarea which doesn't make much sense when you want to edit a subtitle : you most likely want to edit the beginning of the subtitle first. This also set the caret position on the first character. ## Design decision I had to use a *component approach* instead of an `<ng-template>` for the edition modal because the `@viewChild` directive doesn't work for elements __inside__ an `<ng-template>`. I needed the `viewChild` directive to get an `ElementRef` of the `textarea`. > See the following issue and its workaround : > - https://github.com/valor-software/ngx-bootstrap/issues/3825 > - https://stackblitz.com/edit/angular-t5dfp7 > - https://medium.com/@izzatnadiri/how-to-pass-data-to-and-receive-from-ng-bootstrap-modals-916f2ad5d66e ## Related issues Closes [peertube-plugin-transcription/#39](https://gitlab.com/apps_education/peertube/plugin-transcription/-/issues/39)
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-caption-edit-modal-content/video-caption-edit-modal-content.component.html34
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-caption-edit-modal-content/video-caption-edit-modal-content.component.scss (renamed from client/src/app/+videos/+video-edit/shared/video-caption-edit-modal/video-caption-edit-modal.component.scss)0
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-caption-edit-modal-content/video-caption-edit-modal-content.component.ts (renamed from client/src/app/+videos/+video-edit/shared/video-caption-edit-modal/video-caption-edit-modal.component.ts)26
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-caption-edit-modal/video-caption-edit-modal.component.html36
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-edit.component.html9
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-edit.component.ts14
-rw-r--r--client/src/app/+videos/+video-edit/shared/video-edit.module.ts4
7 files changed, 65 insertions, 58 deletions
diff --git a/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal-content/video-caption-edit-modal-content.component.html b/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal-content/video-caption-edit-modal-content.component.html
new file mode 100644
index 000000000..e8079c74e
--- /dev/null
+++ b/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal-content/video-caption-edit-modal-content.component.html
@@ -0,0 +1,34 @@
1<ng-container [formGroup]="form">
2 <div class="modal-header">
3 <h4 i18n class="modal-title">Edit caption</h4>
4 <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
5 </div>
6
7 <div class="modal-body">
8 <label i18n for="captionFileContent">Caption</label>
9 <textarea
10 id="captionFileContent"
11 formControlName="captionFileContent"
12 class="form-control caption-textarea"
13 [ngClass]="{ 'input-error': formErrors['captionFileContent'] }"
14 #textarea
15 >
16 </textarea>
17
18 <div *ngIf="formErrors.captionFileContent" class="form-error">
19 {{ formErrors.captionFileContent }}
20 </div>
21 </div>
22
23 <div class="modal-footer inputs">
24 <input
25 type="button" role="button" i18n-value value="Cancel" class="peertube-button grey-button"
26 (click)="cancel()" (key.enter)="cancel()"
27 >
28
29 <input
30 type="submit" i18n-value value="Edit this caption" class="peertube-button orange-button"
31 [disabled]="!form.valid" (click)="updateCaption()"
32 >
33 </div>
34</ng-container>
diff --git a/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal/video-caption-edit-modal.component.scss b/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal-content/video-caption-edit-modal-content.component.scss
index bd96f2b7a..bd96f2b7a 100644
--- a/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal/video-caption-edit-modal.component.scss
+++ b/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal-content/video-caption-edit-modal-content.component.scss
diff --git a/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal/video-caption-edit-modal.component.ts b/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal-content/video-caption-edit-modal-content.component.ts
index f74f3c5ea..f33353d36 100644
--- a/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal/video-caption-edit-modal.component.ts
+++ b/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal-content/video-caption-edit-modal-content.component.ts
@@ -2,28 +2,33 @@ import { Component, ElementRef, EventEmitter, Input, OnInit, Output, ViewChild }
2import { VIDEO_CAPTION_FILE_CONTENT_VALIDATOR } from '@app/shared/form-validators/video-captions-validators' 2import { VIDEO_CAPTION_FILE_CONTENT_VALIDATOR } from '@app/shared/form-validators/video-captions-validators'
3import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' 3import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
4import { VideoCaptionEdit, VideoCaptionService, VideoCaptionWithPathEdit } from '@app/shared/shared-main' 4import { VideoCaptionEdit, VideoCaptionService, VideoCaptionWithPathEdit } from '@app/shared/shared-main'
5import { NgbModal, NgbModalRef } from '@ng-bootstrap/ng-bootstrap' 5import { NgbModal, NgbActiveModal } from '@ng-bootstrap/ng-bootstrap'
6import { HTMLServerConfig, VideoConstant } from '@shared/models' 6import { HTMLServerConfig, VideoConstant } from '@shared/models'
7import { ServerService } from '../../../../core' 7import { ServerService } from '../../../../core'
8 8
9/**
10 * https://github.com/valor-software/ngx-bootstrap/issues/3825
11 * https://stackblitz.com/edit/angular-t5dfp7
12 * https://medium.com/@izzatnadiri/how-to-pass-data-to-and-receive-from-ng-bootstrap-modals-916f2ad5d66e
13 */
9@Component({ 14@Component({
10 selector: 'my-video-caption-edit-modal', 15 selector: 'my-video-caption-edit-modal-content',
11 styleUrls: [ './video-caption-edit-modal.component.scss' ], 16 styleUrls: [ './video-caption-edit-modal-content.component.scss' ],
12 templateUrl: './video-caption-edit-modal.component.html' 17 templateUrl: './video-caption-edit-modal-content.component.html'
13}) 18})
14 19
15export class VideoCaptionEditModalComponent extends FormReactive implements OnInit { 20export class VideoCaptionEditModalContentComponent extends FormReactive implements OnInit {
16 @Input() videoCaption: VideoCaptionWithPathEdit 21 @Input() videoCaption: VideoCaptionWithPathEdit
17 @Input() serverConfig: HTMLServerConfig 22 @Input() serverConfig: HTMLServerConfig
18 23
19 @Output() captionEdited = new EventEmitter<VideoCaptionEdit>() 24 @Output() captionEdited = new EventEmitter<VideoCaptionEdit>()
20 25
21 @ViewChild('modal', { static: true }) modal: ElementRef 26 @ViewChild('textarea', { static: true }) textarea!: ElementRef
22 27
23 videoCaptionLanguages: VideoConstant<string>[] = [] 28 videoCaptionLanguages: VideoConstant<string>[] = []
24 private openedModal: NgbModalRef
25 29
26 constructor ( 30 constructor (
31 protected openedModal: NgbActiveModal,
27 protected formValidatorService: FormValidatorService, 32 protected formValidatorService: FormValidatorService,
28 private modalService: NgbModal, 33 private modalService: NgbModal,
29 private videoCaptionService: VideoCaptionService, 34 private videoCaptionService: VideoCaptionService,
@@ -49,11 +54,14 @@ export class VideoCaptionEditModalComponent extends FormReactive implements OnIn
49 this.form.patchValue({ 54 this.form.patchValue({
50 captionFileContent: res 55 captionFileContent: res
51 }) 56 })
57 this.resetTextarea()
52 }) 58 })
53 } 59 }
54 60
55 show () { 61 resetTextarea () {
56 this.openedModal = this.modalService.open(this.modal, { centered: true, keyboard: false }) 62 this.textarea.nativeElement.scrollTop = 0
63 this.textarea.nativeElement.selectionStart = 0
64 this.textarea.nativeElement.selectionEnd = 0
57 } 65 }
58 66
59 hide () { 67 hide () {
diff --git a/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal/video-caption-edit-modal.component.html b/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal/video-caption-edit-modal.component.html
deleted file mode 100644
index be6f676c2..000000000
--- a/client/src/app/+videos/+video-edit/shared/video-caption-edit-modal/video-caption-edit-modal.component.html
+++ /dev/null
@@ -1,36 +0,0 @@
1<ng-template #modal>
2 <ng-container [formGroup]="form">
3
4 <div class="modal-header">
5 <h4 i18n class="modal-title">Edit caption</h4>
6 <my-global-icon iconName="cross" aria-label="Close" role="button" (click)="hide()"></my-global-icon>
7 </div>
8
9 <div class="modal-body">
10 <label i18n for="captionFileContent">Caption</label>
11 <textarea
12 id="captionFileContent"
13 formControlName="captionFileContent"
14 class="form-control caption-textarea"
15 [ngClass]="{ 'input-error': formErrors['captionFileContent'] }"
16 >
17 </textarea>
18
19 <div *ngIf="formErrors.captionFileContent" class="form-error">
20 {{ formErrors.captionFileContent }}
21 </div>
22 </div>
23
24 <div class="modal-footer inputs">
25 <input
26 type="button" role="button" i18n-value value="Cancel" class="peertube-button grey-button"
27 (click)="cancel()" (key.enter)="cancel()"
28 >
29
30 <input
31 type="submit" i18n-value value="Edit this caption" class="peertube-button orange-button"
32 [disabled]="!form.valid" (click)="updateCaption()"
33 >
34 </div>
35 </ng-container>
36</ng-template>
diff --git a/client/src/app/+videos/+video-edit/shared/video-edit.component.html b/client/src/app/+videos/+video-edit/shared/video-edit.component.html
index de126bdf7..7be5a3736 100644
--- a/client/src/app/+videos/+video-edit/shared/video-edit.component.html
+++ b/client/src/app/+videos/+video-edit/shared/video-edit.component.html
@@ -185,7 +185,7 @@
185 185
186 <div i18n class="caption-entry-state">Already uploaded on {{ videoCaption.updatedAt | date }} &#10004;</div> 186 <div i18n class="caption-entry-state">Already uploaded on {{ videoCaption.updatedAt | date }} &#10004;</div>
187 187
188 <span i18n class="caption-entry-edit" (click)="videoCaptionEditModal.show()">Edit</span> 188 <span i18n class="caption-entry-edit" (click)="openEditCaptionModal(videoCaption)">Edit</span>
189 <span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Delete</span> 189 <span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Delete</span>
190 </ng-container> 190 </ng-container>
191 191
@@ -212,13 +212,6 @@
212 212
213 <span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Cancel deletion</span> 213 <span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Cancel deletion</span>
214 </ng-container> 214 </ng-container>
215
216 <my-video-caption-edit-modal
217 #videoCaptionEditModal
218 [videoCaption]="videoCaption"
219 [serverConfig]="serverConfig"
220 (captionEdited)="onCaptionEdited($event)"
221 ></my-video-caption-edit-modal>
222 </div> 215 </div>
223 </div> 216 </div>
224 217
diff --git a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts
index 99f8c9034..0275f66f5 100644
--- a/client/src/app/+videos/+video-edit/shared/video-edit.component.ts
+++ b/client/src/app/+videos/+video-edit/shared/video-edit.component.ts
@@ -35,10 +35,11 @@ import {
35} from '@shared/models' 35} from '@shared/models'
36import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service' 36import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service'
37import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component' 37import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component'
38import { VideoCaptionEditModalComponent } from './video-caption-edit-modal/video-caption-edit-modal.component' 38import { VideoCaptionEditModalContentComponent } from './video-caption-edit-modal-content/video-caption-edit-modal-content.component'
39import { VideoEditType } from './video-edit.type' 39import { VideoEditType } from './video-edit.type'
40import { VideoSource } from '@shared/models/videos/video-source' 40import { VideoSource } from '@shared/models/videos/video-source'
41import { logger } from '@root-helpers/logger' 41import { logger } from '@root-helpers/logger'
42import { NgbModal } from '@ng-bootstrap/ng-bootstrap'
42 43
43type VideoLanguages = VideoConstant<string> & { group?: string } 44type VideoLanguages = VideoConstant<string> & { group?: string }
44type PluginField = { 45type PluginField = {
@@ -70,7 +71,6 @@ export class VideoEditComponent implements OnInit, OnDestroy {
70 @Input() liveVideo: LiveVideo 71 @Input() liveVideo: LiveVideo
71 72
72 @ViewChild('videoCaptionAddModal', { static: true }) videoCaptionAddModal: VideoCaptionAddModalComponent 73 @ViewChild('videoCaptionAddModal', { static: true }) videoCaptionAddModal: VideoCaptionAddModalComponent
73 @ViewChild('videoCaptionEditModal', { static: true }) editCaptionModal: VideoCaptionEditModalComponent
74 74
75 @Output() formBuilt = new EventEmitter<void>() 75 @Output() formBuilt = new EventEmitter<void>()
76 @Output() pluginFieldsAdded = new EventEmitter<void>() 76 @Output() pluginFieldsAdded = new EventEmitter<void>()
@@ -128,7 +128,8 @@ export class VideoEditComponent implements OnInit, OnDestroy {
128 private i18nPrimengCalendarService: I18nPrimengCalendarService, 128 private i18nPrimengCalendarService: I18nPrimengCalendarService,
129 private ngZone: NgZone, 129 private ngZone: NgZone,
130 private hooks: HooksService, 130 private hooks: HooksService,
131 private cd: ChangeDetectorRef 131 private cd: ChangeDetectorRef,
132 private modalService: NgbModal
132 ) { 133 ) {
133 this.calendarTimezone = this.i18nPrimengCalendarService.getTimezone() 134 this.calendarTimezone = this.i18nPrimengCalendarService.getTimezone()
134 this.calendarDateFormat = this.i18nPrimengCalendarService.getDateFormat() 135 this.calendarDateFormat = this.i18nPrimengCalendarService.getDateFormat()
@@ -286,6 +287,13 @@ export class VideoEditComponent implements OnInit, OnDestroy {
286 this.videoCaptionAddModal.show() 287 this.videoCaptionAddModal.show()
287 } 288 }
288 289
290 openEditCaptionModal (videoCaption: VideoCaptionWithPathEdit) {
291 const modalRef = this.modalService.open(VideoCaptionEditModalContentComponent, { centered: true, keyboard: false })
292 modalRef.componentInstance.videoCaption = videoCaption
293 modalRef.componentInstance.serverConfig = this.serverConfig
294 modalRef.componentInstance.captionEdited.subscribe(this.onCaptionEdited.bind(this))
295 }
296
289 isSaveReplayEnabled () { 297 isSaveReplayEnabled () {
290 return this.serverConfig.live.allowReplay 298 return this.serverConfig.live.allowReplay
291 } 299 }
diff --git a/client/src/app/+videos/+video-edit/shared/video-edit.module.ts b/client/src/app/+videos/+video-edit/shared/video-edit.module.ts
index 4e8767364..d463bf633 100644
--- a/client/src/app/+videos/+video-edit/shared/video-edit.module.ts
+++ b/client/src/app/+videos/+video-edit/shared/video-edit.module.ts
@@ -6,7 +6,7 @@ import { SharedMainModule } from '@app/shared/shared-main'
6import { SharedVideoLiveModule } from '@app/shared/shared-video-live' 6import { SharedVideoLiveModule } from '@app/shared/shared-video-live'
7import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service' 7import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service'
8import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component' 8import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component'
9import { VideoCaptionEditModalComponent } from './video-caption-edit-modal/video-caption-edit-modal.component' 9import { VideoCaptionEditModalContentComponent } from './video-caption-edit-modal-content/video-caption-edit-modal-content.component'
10import { VideoEditComponent } from './video-edit.component' 10import { VideoEditComponent } from './video-edit.component'
11 11
12@NgModule({ 12@NgModule({
@@ -22,7 +22,7 @@ import { VideoEditComponent } from './video-edit.component'
22 declarations: [ 22 declarations: [
23 VideoEditComponent, 23 VideoEditComponent,
24 VideoCaptionAddModalComponent, 24 VideoCaptionAddModalComponent,
25 VideoCaptionEditModalComponent 25 VideoCaptionEditModalContentComponent
26 ], 26 ],
27 27
28 exports: [ 28 exports: [