Fix channel sync edit/list

* Edit -> prefer to use reactive forms for required inputs
 * List -> use chip class to fix the channel display
pull/6648/head
Chocobozzz 2024-09-27 16:34:58 +02:00
parent ae31ff79ac
commit 639feb2306
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
15 changed files with 72 additions and 87 deletions

View File

@ -54,21 +54,19 @@
</td> </td>
<td> <td>
<div class="actor"> <a [routerLink]="[ '/c', videoChannelSync.channel.name ]" i18n-title title="Channel page">
<my-actor-avatar <div class="chip two-lines">
class="channel" <my-actor-avatar
[actor]="videoChannelSync.channel" actorType="channel" [actor]="videoChannelSync.channel" actorType="channel"
[internalHref]="[ '/c', videoChannelSync.channel.name ]" [internalHref]="[ '/c', videoChannelSync.channel.name ]" size="32"
size="25" ></my-actor-avatar>
></my-actor-avatar>
<div class="actor-info"> <div>
<a [routerLink]="[ '/c', videoChannelSync.channel.name ]" class="actor-names" i18n-title title="Channel page"> <span class="fw-semibold">{{ videoChannelSync.channel.displayName }}</span>
<div class="actor-display-name">{{ videoChannelSync.channel.displayName }}</div> <span class="muted">{{ videoChannelSync.channel.name }}</span>
<div class="actor-name">{{ videoChannelSync.channel.name }}</div> </div>
</a>
</div> </div>
</div> </a>
</td> </td>
<td> <td>

View File

@ -1,11 +0,0 @@
@use '_variables' as *;
@use '_mixins' as *;
@use '_actor' as *;
.actor {
margin-bottom: 0;
padding-bottom: 0;
border: 0;
@include actor-row($min-height: auto, $separator: true);
}

View File

@ -16,7 +16,6 @@ import { ActionDropdownComponent, DropdownAction } from '../../shared/shared-mai
@Component({ @Component({
templateUrl: './my-video-channel-syncs.component.html', templateUrl: './my-video-channel-syncs.component.html',
styleUrls: [ './my-video-channel-syncs.component.scss' ],
standalone: true, standalone: true,
imports: [ imports: [
NgIf, NgIf,

View File

@ -30,8 +30,8 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label i18n for="videoChannel">Video Channel</label> <label i18n for="videoChannel">Video channel</label>
<my-select-channel required [items]="userVideoChannels" formControlName="videoChannel"></my-select-channel> <my-select-channel labelForId="videoChannel" [items]="userVideoChannels" formControlName="videoChannel"></my-select-channel>
<div *ngIf="formErrors['videoChannel']" class="form-error" role="alert"> <div *ngIf="formErrors['videoChannel']" class="form-error" role="alert">
{{ formErrors['videoChannel'] }} {{ formErrors['videoChannel'] }}
@ -42,12 +42,12 @@
<label for="existingVideoStrategy" i18n>Options for existing videos on remote channel:</label> <label for="existingVideoStrategy" i18n>Options for existing videos on remote channel:</label>
<div class="peertube-radio-container"> <div class="peertube-radio-container">
<input type="radio" name="existingVideoStrategy" id="import" value="import" formControlName="existingVideoStrategy" required /> <input type="radio" name="existingVideoStrategy" id="import" value="import" formControlName="existingVideoStrategy" />
<label for="import" i18n>Import all and watch for new publications</label> <label for="import" i18n>Import all and watch for new publications</label>
</div> </div>
<div class="peertube-radio-container"> <div class="peertube-radio-container">
<input type="radio" name="existingVideoStrategy" id="doNothing" value="nothing" formControlName="existingVideoStrategy" required /> <input type="radio" name="existingVideoStrategy" id="doNothing" value="nothing" formControlName="existingVideoStrategy" />
<label for="doNothing" i18n>Only watch for new publications</label> <label for="doNothing" i18n>Only watch for new publications</label>
</div> </div>
</div> </div>

View File

@ -14,6 +14,7 @@ import { VideoChannelSyncCreate } from '@peertube/peertube-models'
import { mergeMap } from 'rxjs' import { mergeMap } from 'rxjs'
import { SelectChannelItem } from 'src/types' import { SelectChannelItem } from 'src/types'
import { SelectChannelComponent } from '../../../shared/shared-forms/select/select-channel.component' import { SelectChannelComponent } from '../../../shared/shared-forms/select/select-channel.component'
import { REQUIRED_VALIDATOR } from '@app/shared/form-validators/common-validators'
@Component({ @Component({
selector: 'my-video-channel-sync-edit', selector: 'my-video-channel-sync-edit',
@ -41,8 +42,8 @@ export class VideoChannelSyncEditComponent extends FormReactive implements OnIni
ngOnInit () { ngOnInit () {
this.buildForm({ this.buildForm({
externalChannelUrl: VIDEO_CHANNEL_EXTERNAL_URL_VALIDATOR, externalChannelUrl: VIDEO_CHANNEL_EXTERNAL_URL_VALIDATOR,
videoChannel: null, videoChannel: REQUIRED_VALIDATOR,
existingVideoStrategy: null existingVideoStrategy: REQUIRED_VALIDATOR
}) })
listUserChannelsForSelect(this.authService) listUserChannelsForSelect(this.authService)

View File

@ -69,11 +69,9 @@
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="videoChannelIdl" i18n>Channel</label> <label for="videoChannelId" i18n>Channel</label>
<my-select-channel <my-select-channel labelForId="videoChannelId" [items]="userVideoChannels" formControlName="videoChannelId"></my-select-channel>
labelForId="videoChannelId" [items]="userVideoChannels" formControlName="videoChannelId"
></my-select-channel>
<div *ngIf="formErrors['videoChannelId']" class="form-error" role="alert">{{ formErrors['videoChannelId'] }}</div> <div *ngIf="formErrors['videoChannelId']" class="form-error" role="alert">{{ formErrors['videoChannelId'] }}</div>
</div> </div>

View File

@ -4,9 +4,7 @@
<div class="form-group"> <div class="form-group">
<label i18n for="first-step-channel">Channel</label> <label i18n for="first-step-channel">Channel</label>
<my-select-channel <my-select-channel labelForId="first-step-channel" [items]="userVideoChannels" [(ngModel)]="firstStepChannelId"></my-select-channel>
labelForId="first-step-channel" [items]="userVideoChannels" [(ngModel)]="firstStepChannelId"
></my-select-channel>
</div> </div>
<div class="form-group"> <div class="form-group">

View File

@ -28,9 +28,7 @@
<div class="form-group"> <div class="form-group">
<label i18n for="first-step-channel">Channel</label> <label i18n for="first-step-channel">Channel</label>
<my-select-channel <my-select-channel labelForId="first-step-channel" [items]="userVideoChannels" [(ngModel)]="firstStepChannelId"></my-select-channel>
labelForId="first-step-channel" [items]="userVideoChannels" [(ngModel)]="firstStepChannelId"
></my-select-channel>
</div> </div>
<div class="form-group"> <div class="form-group">

View File

@ -24,9 +24,7 @@
<div class="form-group"> <div class="form-group">
<label i18n for="first-step-channel">Channel</label> <label i18n for="first-step-channel">Channel</label>
<my-select-channel <my-select-channel labelForId="first-step-channel" [items]="userVideoChannels" [(ngModel)]="firstStepChannelId"></my-select-channel>
labelForId="first-step-channel" [items]="userVideoChannels" [(ngModel)]="firstStepChannelId"
></my-select-channel>
</div> </div>
<div class="form-group"> <div class="form-group">

View File

@ -17,9 +17,7 @@
<div class="form-group form-group-channel"> <div class="form-group form-group-channel">
<label i18n for="first-step-channel">Channel</label> <label i18n for="first-step-channel">Channel</label>
<my-select-channel <my-select-channel labelForId="first-step-channel" [items]="userVideoChannels" [(ngModel)]="firstStepChannelId"></my-select-channel>
labelForId="first-step-channel" [items]="userVideoChannels" [(ngModel)]="firstStepChannelId"
></my-select-channel>
</div> </div>
<div class="form-group"> <div class="form-group">

View File

@ -0,0 +1,9 @@
import { Validators } from '@angular/forms'
import { BuildFormValidator } from './form-validator.model'
export const REQUIRED_VALIDATOR: BuildFormValidator = {
VALIDATORS: [ Validators.required ],
MESSAGES: {
required: $localize`This field is required.`
}
}

View File

@ -5,6 +5,7 @@
[bindValue]="bindValue" [bindValue]="bindValue"
[clearable]="clearable" [clearable]="clearable"
[searchable]="searchable" [searchable]="searchable"
[labelForId]="labelForId"
> >
<ng-option *ngFor="let channel of channels" [value]="channel.id"> <ng-option *ngFor="let channel of channels" [value]="channel.id">
<img alt="" class="avatar me-1" [src]="channel.avatarPath" /> <img alt="" class="avatar me-1" [src]="channel.avatarPath" />

View File

@ -20,6 +20,7 @@ import { VideoChannel } from '@app/shared/shared-main/channel/video-channel.mode
imports: [ NgSelectModule, FormsModule, NgFor ] imports: [ NgSelectModule, FormsModule, NgFor ]
}) })
export class SelectChannelComponent implements ControlValueAccessor, OnChanges { export class SelectChannelComponent implements ControlValueAccessor, OnChanges {
@Input({ required: true }) labelForId: string
@Input() items: SelectChannelItem[] = [] @Input() items: SelectChannelItem[] = []
channels: SelectChannelItem[] = [] channels: SelectChannelItem[] = []

View File

@ -99,7 +99,43 @@
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
.chip { .chip {
@include chip; --avatarSize: 1.2rem;
display: inline-flex;
color: pvar(--mainForegroundColor);
height: var(--avatarSize);
max-width: 320px;
overflow: hidden;
text-decoration: none;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
align-items: center;
my-actor-avatar {
border-radius: 5rem;
width: var(--avatarSize);
height: var(--avatarSize);
@include margin-right(0.5rem);
}
&.two-lines {
--avatarSize: 2rem;
font-size: 14px;
line-height: 1rem;
my-actor-avatar {
display: inline-block;
}
> div {
display: flex;
flex-direction: column;
justify-content: center;
}
}
} }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------

View File

@ -620,45 +620,6 @@
} }
} }
@mixin chip {
--avatar-size: 1.2rem;
display: inline-flex;
color: pvar(--mainForegroundColor);
height: var(--avatar-size);
max-width: 320px;
overflow: hidden;
text-decoration: none;
text-overflow: ellipsis;
vertical-align: middle;
white-space: nowrap;
my-actor-avatar {
border-radius: 5rem;
width: var(--avatar-size);
height: var(--avatar-size);
@include margin-right(.2rem);
}
&.two-lines {
--avatar-size: 2rem;
font-size: 14px;
line-height: 1rem;
my-actor-avatar {
display: inline-block;
}
> div {
display: flex;
flex-direction: column;
justify-content: center;
}
}
}
// applies ratio (default to 16:9) to a child element (using $selector) only using // applies ratio (default to 16:9) to a child element (using $selector) only using
// an immediate's parent size. This allows to set a ratio without explicit // an immediate's parent size. This allows to set a ratio without explicit
// dimensions, as width/height cannot be computed from each other. // dimensions, as width/height cannot be computed from each other.