Improve captions UX (at least I've tried)
This commit is contained in:
parent
d73c98884e
commit
772d5642ba
|
@ -10,6 +10,7 @@ export type FormReactiveValidationMessages = {
|
|||
|
||||
export abstract class FormReactive {
|
||||
protected abstract formValidatorService: FormValidatorService
|
||||
protected formChanged = false
|
||||
|
||||
form: FormGroup
|
||||
formErrors: FormReactiveErrors
|
||||
|
@ -31,6 +32,8 @@ export abstract class FormReactive {
|
|||
this.formErrors[ field ] = ''
|
||||
const control = this.form.get(field)
|
||||
|
||||
if (control.dirty) this.formChanged = true
|
||||
|
||||
// Don't care if dirty on force check
|
||||
const isDirty = control.dirty || forceCheck === true
|
||||
if (control && isDirty && !control.valid) {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<input
|
||||
type="file"
|
||||
[name]="inputName" [id]="inputName" [accept]="extensions"
|
||||
(change)="fileChange($event)"
|
||||
(change)="fileChange($event)" [(ngModel)]="fileInputValue"
|
||||
/>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -25,6 +25,7 @@ export class ReactiveFileComponent implements OnInit, ControlValueAccessor {
|
|||
@Output() fileChanged = new EventEmitter<Blob>()
|
||||
|
||||
allowedExtensionsMessage = ''
|
||||
fileInputValue: any
|
||||
|
||||
private file: File
|
||||
|
||||
|
@ -63,6 +64,8 @@ export class ReactiveFileComponent implements OnInit, ControlValueAccessor {
|
|||
|
||||
writeValue (file: any) {
|
||||
this.file = file
|
||||
|
||||
if (!this.file) this.fileInputValue = null
|
||||
}
|
||||
|
||||
registerOnChange (fn: (_: any) => void) {
|
||||
|
|
|
@ -142,10 +142,33 @@
|
|||
|
||||
<div class="form-group" *ngFor="let videoCaption of videoCaptions">
|
||||
|
||||
<div *ngIf="videoCaption.action !== 'REMOVE'" class="caption-entry">
|
||||
<div class="caption-entry-label">{{ videoCaption.language.label }}</div>
|
||||
<div class="caption-entry">
|
||||
<ng-container *ngIf="!videoCaption.action">
|
||||
<a
|
||||
i18n-title title="See the subtitle file" class="caption-entry-label" target="_blank" rel="noopener noreferrer"
|
||||
[href]="videoCaption.captionPath"
|
||||
>{{ videoCaption.language.label }}</a>
|
||||
|
||||
<span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Delete</span>
|
||||
<div class="caption-entry-state">Already uploaded ✔</div>
|
||||
|
||||
<span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Delete</span>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="videoCaption.action === 'CREATE'">
|
||||
<span class="caption-entry-label">{{ videoCaption.language.label }}</span>
|
||||
|
||||
<div class="caption-entry-state caption-entry-state-create">Will be created on update</div>
|
||||
|
||||
<span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Cancel create</span>
|
||||
</ng-container>
|
||||
|
||||
<ng-container *ngIf="videoCaption.action === 'REMOVE'">
|
||||
<span class="caption-entry-label">{{ videoCaption.language.label }}</span>
|
||||
|
||||
<div class="caption-entry-state caption-entry-state-delete">Will be deleted on update</div>
|
||||
|
||||
<span i18n class="caption-entry-delete" (click)="deleteCaption(videoCaption)">Cancel deletion</span>
|
||||
</ng-container>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -46,11 +46,34 @@
|
|||
height: 40px;
|
||||
align-items: center;
|
||||
|
||||
a.caption-entry-label {
|
||||
@include disable-default-a-behaviour;
|
||||
|
||||
color: #000;
|
||||
|
||||
&:hover {
|
||||
opacity: 0.8;
|
||||
}
|
||||
}
|
||||
|
||||
.caption-entry-label {
|
||||
font-size: 15px;
|
||||
font-weight: bold;
|
||||
|
||||
margin-right: 20px;
|
||||
width: 150px;
|
||||
}
|
||||
|
||||
.caption-entry-state {
|
||||
width: 200px;
|
||||
|
||||
&.caption-entry-state-create {
|
||||
color: #39CC0B;
|
||||
}
|
||||
|
||||
&.caption-entry-state-delete {
|
||||
color: #FF0000;
|
||||
}
|
||||
}
|
||||
|
||||
.caption-entry-delete {
|
||||
|
|
|
@ -50,6 +50,7 @@ export class VideoEditComponent implements OnInit, OnDestroy {
|
|||
|
||||
private schedulerInterval
|
||||
private firstPatchDone = false
|
||||
private initialVideoCaptions: string[] = []
|
||||
|
||||
constructor (
|
||||
private formValidatorService: FormValidatorService,
|
||||
|
@ -127,6 +128,8 @@ export class VideoEditComponent implements OnInit, OnDestroy {
|
|||
this.videoLanguages = this.serverService.getVideoLanguages()
|
||||
|
||||
this.schedulerInterval = setInterval(() => this.minScheduledDate = new Date(), 1000 * 60) // Update every minute
|
||||
|
||||
this.initialVideoCaptions = this.videoCaptions.map(c => c.language.id)
|
||||
}
|
||||
|
||||
ngOnDestroy () {
|
||||
|
@ -147,7 +150,13 @@ export class VideoEditComponent implements OnInit, OnDestroy {
|
|||
)
|
||||
}
|
||||
|
||||
deleteCaption (caption: VideoCaptionEdit) {
|
||||
async deleteCaption (caption: VideoCaptionEdit) {
|
||||
// Caption recovers his former state
|
||||
if (caption.action && this.initialVideoCaptions.indexOf(caption.language.id) !== -1) {
|
||||
caption.action = undefined
|
||||
return
|
||||
}
|
||||
|
||||
// This caption is not on the server, just remove it from our array
|
||||
if (caption.action === 'CREATE') {
|
||||
removeElementFromArray(this.videoCaptions, caption)
|
||||
|
|
|
@ -6,12 +6,14 @@ import { MetaGuard } from '@ngx-meta/core'
|
|||
import { LoginGuard } from '../../core'
|
||||
import { VideoUpdateComponent } from './video-update.component'
|
||||
import { VideoUpdateResolver } from '@app/videos/+video-edit/video-update.resolver'
|
||||
import { CanDeactivateGuard } from '@app/shared/guards/can-deactivate-guard.service'
|
||||
|
||||
const videoUpdateRoutes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: VideoUpdateComponent,
|
||||
canActivate: [ MetaGuard, LoginGuard ],
|
||||
canDeactivate: [ CanDeactivateGuard ],
|
||||
resolve: {
|
||||
videoData: VideoUpdateResolver
|
||||
}
|
||||
|
|
|
@ -29,6 +29,8 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
|
|||
schedulePublicationPossible = false
|
||||
videoCaptions: VideoCaptionEdit[] = []
|
||||
|
||||
private updateDone = false
|
||||
|
||||
constructor (
|
||||
protected formValidatorService: FormValidatorService,
|
||||
private route: ActivatedRoute,
|
||||
|
@ -65,7 +67,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
|
|||
this.schedulePublicationPossible = this.video.privacy === VideoPrivacy.PRIVATE
|
||||
}
|
||||
|
||||
// FIXME: Angular does not detec
|
||||
// FIXME: Angular does not detect the change inside this subscription, so use the patched setTimeout
|
||||
setTimeout(() => this.hydrateFormFromVideo())
|
||||
},
|
||||
|
||||
|
@ -76,6 +78,16 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
|
|||
)
|
||||
}
|
||||
|
||||
canDeactivate () {
|
||||
if (this.updateDone === true) return { canDeactivate: true }
|
||||
|
||||
for (const caption of this.videoCaptions) {
|
||||
if (caption.action) return { canDeactivate: false }
|
||||
}
|
||||
|
||||
return { canDeactivate: this.formChanged === false }
|
||||
}
|
||||
|
||||
checkForm () {
|
||||
this.forceCheck()
|
||||
|
||||
|
@ -100,6 +112,7 @@ export class VideoUpdateComponent extends FormReactive implements OnInit {
|
|||
)
|
||||
.subscribe(
|
||||
() => {
|
||||
this.updateDone = true
|
||||
this.isUpdatingVideo = false
|
||||
this.loadingBar.complete()
|
||||
this.notificationsService.success(this.i18n('Success'), this.i18n('Video updated.'))
|
||||
|
|
|
@ -4,6 +4,7 @@ import { VideoEditModule } from './shared/video-edit.module'
|
|||
import { VideoUpdateRoutingModule } from './video-update-routing.module'
|
||||
import { VideoUpdateComponent } from './video-update.component'
|
||||
import { VideoUpdateResolver } from '@app/videos/+video-edit/video-update.resolver'
|
||||
import { CanDeactivateGuard } from '@app/shared/guards/can-deactivate-guard.service'
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
|
@ -21,7 +22,8 @@ import { VideoUpdateResolver } from '@app/videos/+video-edit/video-update.resolv
|
|||
],
|
||||
|
||||
providers: [
|
||||
VideoUpdateResolver
|
||||
VideoUpdateResolver,
|
||||
CanDeactivateGuard
|
||||
]
|
||||
})
|
||||
export class VideoUpdateModule { }
|
||||
|
|
Loading…
Reference in New Issue