diff options
21 files changed, 141 insertions, 105 deletions
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html index 844620ca2..637203b96 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html | |||
@@ -402,25 +402,29 @@ | |||
402 | <ng-container formGroupName="user"> | 402 | <ng-container formGroupName="user"> |
403 | <div class="form-group"> | 403 | <div class="form-group"> |
404 | <label i18n for="userVideoQuota">Default video quota per user</label> | 404 | <label i18n for="userVideoQuota">Default video quota per user</label> |
405 | <div class="peertube-select-container"> | 405 | |
406 | <select id="userVideoQuota" formControlName="videoQuota" class="form-control"> | 406 | <my-select-custom-value |
407 | <option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value" [disabled]="videoQuotaOption.disabled"> | 407 | id="userVideoQuota" |
408 | {{ videoQuotaOption.label }} | 408 | [items]="videoQuotaOptions" |
409 | </option> | 409 | formControlName="videoQuota" |
410 | </select> | 410 | i18n-inputSuffix inputSuffix="bytes" inputType="number" |
411 | </div> | 411 | [clearable]="false" |
412 | ></my-select-custom-value> | ||
413 | |||
412 | <div *ngIf="formErrors.user.videoQuota" class="form-error">{{ formErrors.user.videoQuota }}</div> | 414 | <div *ngIf="formErrors.user.videoQuota" class="form-error">{{ formErrors.user.videoQuota }}</div> |
413 | </div> | 415 | </div> |
414 | 416 | ||
415 | <div class="form-group"> | 417 | <div class="form-group"> |
416 | <label i18n for="userVideoQuotaDaily">Default daily upload limit per user</label> | 418 | <label i18n for="userVideoQuotaDaily">Default daily upload limit per user</label> |
417 | <div class="peertube-select-container"> | 419 | |
418 | <select id="userVideoQuotaDaily" formControlName="videoQuotaDaily" class="form-control"> | 420 | <my-select-custom-value |
419 | <option *ngFor="let videoQuotaDailyOption of videoQuotaDailyOptions" [value]="videoQuotaDailyOption.value" [disabled]="videoQuotaDailyOption.disabled"> | 421 | id="userVideoQuotaDaily" |
420 | {{ videoQuotaDailyOption.label }} | 422 | [items]="videoQuotaDailyOptions" |
421 | </option> | 423 | formControlName="videoQuotaDaily" |
422 | </select> | 424 | i18n-inputSuffix inputSuffix="bytes" inputType="number" |
423 | </div> | 425 | [clearable]="false" |
426 | ></my-select-custom-value> | ||
427 | |||
424 | <div *ngIf="formErrors.user.videoQuotaDaily" class="form-error">{{ formErrors.user.videoQuotaDaily }}</div> | 428 | <div *ngIf="formErrors.user.videoQuotaDaily" class="form-error">{{ formErrors.user.videoQuotaDaily }}</div> |
425 | </div> | 429 | </div> |
426 | </ng-container> | 430 | </ng-container> |
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts index a9f72d7db..56be97e84 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts +++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts | |||
@@ -19,9 +19,10 @@ import { | |||
19 | TRANSCODING_THREADS_VALIDATOR | 19 | TRANSCODING_THREADS_VALIDATOR |
20 | } from '@app/shared/form-validators/custom-config-validators' | 20 | } from '@app/shared/form-validators/custom-config-validators' |
21 | import { USER_VIDEO_QUOTA_DAILY_VALIDATOR, USER_VIDEO_QUOTA_VALIDATOR } from '@app/shared/form-validators/user-validators' | 21 | import { USER_VIDEO_QUOTA_DAILY_VALIDATOR, USER_VIDEO_QUOTA_VALIDATOR } from '@app/shared/form-validators/user-validators' |
22 | import { FormReactive, FormValidatorService, SelectOptionsItem } from '@app/shared/shared-forms' | 22 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' |
23 | import { NgbNav } from '@ng-bootstrap/ng-bootstrap' | 23 | import { NgbNav } from '@ng-bootstrap/ng-bootstrap' |
24 | import { CustomConfig, ServerConfig } from '@shared/models' | 24 | import { CustomConfig, ServerConfig } from '@shared/models' |
25 | import { SelectOptionsItem } from 'src/types/select-options-item.model' | ||
25 | 26 | ||
26 | @Component({ | 27 | @Component({ |
27 | selector: 'my-edit-custom-config', | 28 | selector: 'my-edit-custom-config', |
diff --git a/client/src/app/+admin/config/shared/config.service.ts b/client/src/app/+admin/config/shared/config.service.ts index 5f98aa545..d29b752f7 100644 --- a/client/src/app/+admin/config/shared/config.service.ts +++ b/client/src/app/+admin/config/shared/config.service.ts | |||
@@ -3,43 +3,46 @@ import { HttpClient } from '@angular/common/http' | |||
3 | import { Injectable } from '@angular/core' | 3 | import { Injectable } from '@angular/core' |
4 | import { RestExtractor } from '@app/core' | 4 | import { RestExtractor } from '@app/core' |
5 | import { CustomConfig } from '@shared/models' | 5 | import { CustomConfig } from '@shared/models' |
6 | import { SelectOptionsItem } from '../../../../types/select-options-item.model' | ||
6 | import { environment } from '../../../../environments/environment' | 7 | import { environment } from '../../../../environments/environment' |
7 | 8 | ||
8 | @Injectable() | 9 | @Injectable() |
9 | export class ConfigService { | 10 | export class ConfigService { |
10 | private static BASE_APPLICATION_URL = environment.apiUrl + '/api/v1/config' | 11 | private static BASE_APPLICATION_URL = environment.apiUrl + '/api/v1/config' |
11 | 12 | ||
12 | videoQuotaOptions: { value: number, label: string, disabled?: boolean }[] = [] | 13 | videoQuotaOptions: SelectOptionsItem[] = [] |
13 | videoQuotaDailyOptions: { value: number, label: string, disabled?: boolean }[] = [] | 14 | videoQuotaDailyOptions: SelectOptionsItem[] = [] |
14 | 15 | ||
15 | constructor ( | 16 | constructor ( |
16 | private authHttp: HttpClient, | 17 | private authHttp: HttpClient, |
17 | private restExtractor: RestExtractor | 18 | private restExtractor: RestExtractor |
18 | ) { | 19 | ) { |
19 | this.videoQuotaOptions = [ | 20 | this.videoQuotaOptions = [ |
20 | { value: undefined, label: 'Default quota', disabled: true }, | 21 | { id: -1, label: $localize`Unlimited` }, |
21 | { value: -1, label: $localize`Unlimited` }, | 22 | { id: 0, label: $localize`None - no upload possible` }, |
22 | { value: undefined, label: '─────', disabled: true }, | 23 | { id: 100 * 1024 * 1024, label: $localize`100MB` }, |
23 | { value: 0, label: $localize`None - no upload possible` }, | 24 | { id: 500 * 1024 * 1024, label: $localize`500MB` }, |
24 | { value: 100 * 1024 * 1024, label: $localize`100MB` }, | 25 | { id: 1024 * 1024 * 1024, label: $localize`1GB` }, |
25 | { value: 500 * 1024 * 1024, label: $localize`500MB` }, | 26 | { id: 5 * 1024 * 1024 * 1024, label: $localize`5GB` }, |
26 | { value: 1024 * 1024 * 1024, label: $localize`1GB` }, | 27 | { id: 20 * 1024 * 1024 * 1024, label: $localize`20GB` }, |
27 | { value: 5 * 1024 * 1024 * 1024, label: $localize`5GB` }, | 28 | { id: 50 * 1024 * 1024 * 1024, label: $localize`50GB` }, |
28 | { value: 20 * 1024 * 1024 * 1024, label: $localize`20GB` }, | 29 | { id: 100 * 1024 * 1024 * 1024, label: $localize`100GB` }, |
29 | { value: 50 * 1024 * 1024 * 1024, label: $localize`50GB` } | 30 | { id: 200 * 1024 * 1024 * 1024, label: $localize`200GB` }, |
31 | { id: 500 * 1024 * 1024 * 1024, label: $localize`500GB` } | ||
30 | ] | 32 | ] |
31 | 33 | ||
32 | this.videoQuotaDailyOptions = [ | 34 | this.videoQuotaDailyOptions = [ |
33 | { value: undefined, label: 'Default daily upload limit', disabled: true }, | 35 | { id: -1, label: $localize`Unlimited` }, |
34 | { value: -1, label: $localize`Unlimited` }, | 36 | { id: 0, label: $localize`None - no upload possible` }, |
35 | { value: undefined, label: '─────', disabled: true }, | 37 | { id: 10 * 1024 * 1024, label: $localize`10MB` }, |
36 | { value: 0, label: $localize`None - no upload possible` }, | 38 | { id: 50 * 1024 * 1024, label: $localize`50MB` }, |
37 | { value: 10 * 1024 * 1024, label: $localize`10MB` }, | 39 | { id: 100 * 1024 * 1024, label: $localize`100MB` }, |
38 | { value: 50 * 1024 * 1024, label: $localize`50MB` }, | 40 | { id: 500 * 1024 * 1024, label: $localize`500MB` }, |
39 | { value: 100 * 1024 * 1024, label: $localize`100MB` }, | 41 | { id: 2 * 1024 * 1024 * 1024, label: $localize`2GB` }, |
40 | { value: 500 * 1024 * 1024, label: $localize`500MB` }, | 42 | { id: 5 * 1024 * 1024 * 1024, label: $localize`5GB` }, |
41 | { value: 2 * 1024 * 1024 * 1024, label: $localize`2GB` }, | 43 | { id: 10 * 1024 * 1024 * 1024, label: $localize`10GB` }, |
42 | { value: 5 * 1024 * 1024 * 1024, label: $localize`5GB` } | 44 | { id: 20 * 1024 * 1024 * 1024, label: $localize`20GB` }, |
45 | { id: 50 * 1024 * 1024 * 1024, label: $localize`50GB` } | ||
43 | ] | 46 | ] |
44 | } | 47 | } |
45 | 48 | ||
diff --git a/client/src/app/+admin/users/user-edit/user-create.component.ts b/client/src/app/+admin/users/user-edit/user-create.component.ts index d0aac1cb9..da333240c 100644 --- a/client/src/app/+admin/users/user-edit/user-create.component.ts +++ b/client/src/app/+admin/users/user-edit/user-create.component.ts | |||
@@ -45,8 +45,8 @@ export class UserCreateComponent extends UserEdit implements OnInit { | |||
45 | 45 | ||
46 | const defaultValues = { | 46 | const defaultValues = { |
47 | role: UserRole.USER.toString(), | 47 | role: UserRole.USER.toString(), |
48 | videoQuota: '-1', | 48 | videoQuota: -1, |
49 | videoQuotaDaily: '-1' | 49 | videoQuotaDaily: -1 |
50 | } | 50 | } |
51 | 51 | ||
52 | this.buildForm({ | 52 | this.buildForm({ |
diff --git a/client/src/app/+admin/users/user-edit/user-edit.component.html b/client/src/app/+admin/users/user-edit/user-edit.component.html index fb34d6b22..243c6556a 100644 --- a/client/src/app/+admin/users/user-edit/user-edit.component.html +++ b/client/src/app/+admin/users/user-edit/user-edit.component.html | |||
@@ -149,28 +149,38 @@ | |||
149 | 149 | ||
150 | <div class="form-group"> | 150 | <div class="form-group"> |
151 | <label i18n for="videoQuota">Video quota</label> | 151 | <label i18n for="videoQuota">Video quota</label> |
152 | <div class="peertube-select-container"> | 152 | |
153 | <select id="videoQuota" formControlName="videoQuota" class="form-control"> | 153 | <my-select-custom-value |
154 | <option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value" [disabled]="videoQuotaOption.disabled"> | 154 | id="videoQuota" |
155 | {{ videoQuotaOption.label }} | 155 | [items]="videoQuotaOptions" |
156 | </option> | 156 | formControlName="videoQuota" |
157 | </select> | 157 | i18n-inputSuffix inputSuffix="bytes" inputType="number" |
158 | </div> | 158 | [clearable]="false" |
159 | ></my-select-custom-value> | ||
159 | 160 | ||
160 | <div i18n class="transcoding-information" *ngIf="isTranscodingInformationDisplayed()"> | 161 | <div i18n class="transcoding-information" *ngIf="isTranscodingInformationDisplayed()"> |
161 | Transcoding is enabled. The video quota only takes into account <strong>original</strong> video size. <br /> | 162 | Transcoding is enabled. The video quota only takes into account <strong>original</strong> video size. <br /> |
162 | At most, this user could upload ~ {{ computeQuotaWithTranscoding() | bytes: 0 }}. | 163 | At most, this user could upload ~ {{ computeQuotaWithTranscoding() | bytes: 0 }}. |
163 | </div> | 164 | </div> |
165 | |||
166 | <div *ngIf="formErrors.videoQuota" class="form-error"> | ||
167 | {{ formErrors.videoQuota }} | ||
168 | </div> | ||
164 | </div> | 169 | </div> |
165 | 170 | ||
166 | <div class="form-group"> | 171 | <div class="form-group"> |
167 | <label i18n for="videoQuotaDaily">Daily video quota</label> | 172 | <label i18n for="videoQuotaDaily">Daily video quota</label> |
168 | <div class="peertube-select-container"> | 173 | |
169 | <select id="videoQuotaDaily" formControlName="videoQuotaDaily" class="form-control"> | 174 | <my-select-custom-value |
170 | <option *ngFor="let videoQuotaDailyOption of videoQuotaDailyOptions" [value]="videoQuotaDailyOption.value" [disabled]="videoQuotaDailyOption.disabled"> | 175 | id="videoQuotaDaily" |
171 | {{ videoQuotaDailyOption.label }} | 176 | [items]="videoQuotaDailyOptions" |
172 | </option> | 177 | formControlName="videoQuotaDaily" |
173 | </select> | 178 | i18n-inputSuffix inputSuffix="bytes" inputType="number" |
179 | [clearable]="false" | ||
180 | ></my-select-custom-value> | ||
181 | |||
182 | <div *ngIf="formErrors.videoQuotaDaily" class="form-error"> | ||
183 | {{ formErrors.videoQuotaDaily }} | ||
174 | </div> | 184 | </div> |
175 | </div> | 185 | </div> |
176 | 186 | ||
diff --git a/client/src/app/+admin/users/user-edit/user-edit.component.scss b/client/src/app/+admin/users/user-edit/user-edit.component.scss index 3b7715062..aa87b8d6d 100644 --- a/client/src/app/+admin/users/user-edit/user-edit.component.scss +++ b/client/src/app/+admin/users/user-edit/user-edit.component.scss | |||
@@ -1,6 +1,8 @@ | |||
1 | @import '_variables'; | 1 | @import '_variables'; |
2 | @import '_mixins'; | 2 | @import '_mixins'; |
3 | 3 | ||
4 | $form-base-input-width: 340px; | ||
5 | |||
4 | label { | 6 | label { |
5 | font-weight: $font-regular; | 7 | font-weight: $font-regular; |
6 | font-size: 100%; | 8 | font-size: 100%; |
@@ -15,18 +17,24 @@ label { | |||
15 | } | 17 | } |
16 | 18 | ||
17 | input:not([type=submit]) { | 19 | input:not([type=submit]) { |
18 | @include peertube-input-text(340px); | 20 | @include peertube-input-text($form-base-input-width); |
19 | display: block; | 21 | display: block; |
20 | } | 22 | } |
21 | 23 | ||
22 | my-input-toggle-hidden { | 24 | my-input-toggle-hidden { |
23 | @include responsive-width(340px); | 25 | @include responsive-width($form-base-input-width); |
24 | 26 | ||
25 | display: block; | 27 | display: block; |
26 | } | 28 | } |
27 | 29 | ||
28 | .peertube-select-container { | 30 | .peertube-select-container { |
29 | @include peertube-select-container(340px); | 31 | @include peertube-select-container($form-base-input-width); |
32 | } | ||
33 | |||
34 | my-select-custom-value { | ||
35 | @include responsive-width($form-base-input-width); | ||
36 | |||
37 | display: block; | ||
30 | } | 38 | } |
31 | 39 | ||
32 | input[type=submit], button { | 40 | input[type=submit], button { |
diff --git a/client/src/app/+admin/users/user-edit/user-edit.ts b/client/src/app/+admin/users/user-edit/user-edit.ts index faa2f5ad8..2fc3c5d3b 100644 --- a/client/src/app/+admin/users/user-edit/user-edit.ts +++ b/client/src/app/+admin/users/user-edit/user-edit.ts | |||
@@ -4,12 +4,13 @@ import { AuthService, ScreenService, ServerService, User } from '@app/core' | |||
4 | import { FormReactive } from '@app/shared/shared-forms' | 4 | import { FormReactive } from '@app/shared/shared-forms' |
5 | import { USER_ROLE_LABELS } from '@shared/core-utils/users' | 5 | import { USER_ROLE_LABELS } from '@shared/core-utils/users' |
6 | import { ServerConfig, UserAdminFlag, UserRole, VideoResolution } from '@shared/models' | 6 | import { ServerConfig, UserAdminFlag, UserRole, VideoResolution } from '@shared/models' |
7 | import { SelectOptionsItem } from '../../../../types/select-options-item.model' | ||
7 | 8 | ||
8 | @Directive() | 9 | @Directive() |
9 | // tslint:disable-next-line: directive-class-suffix | 10 | // tslint:disable-next-line: directive-class-suffix |
10 | export abstract class UserEdit extends FormReactive implements OnInit { | 11 | export abstract class UserEdit extends FormReactive implements OnInit { |
11 | videoQuotaOptions: { value: string, label: string, disabled?: boolean }[] = [] | 12 | videoQuotaOptions: SelectOptionsItem[] = [] |
12 | videoQuotaDailyOptions: { value: string, label: string, disabled?: boolean }[] = [] | 13 | videoQuotaDailyOptions: SelectOptionsItem[] = [] |
13 | username: string | 14 | username: string |
14 | user: User | 15 | user: User |
15 | 16 | ||
@@ -97,19 +98,7 @@ export abstract class UserEdit extends FormReactive implements OnInit { | |||
97 | } | 98 | } |
98 | 99 | ||
99 | protected buildQuotaOptions () { | 100 | protected buildQuotaOptions () { |
100 | // These are used by a HTML select, so convert key into strings | 101 | this.videoQuotaOptions = this.configService.videoQuotaOptions |
101 | this.videoQuotaOptions = this.configService | 102 | this.videoQuotaDailyOptions = this.configService.videoQuotaDailyOptions |
102 | .videoQuotaOptions.map(q => ({ | ||
103 | value: q.value?.toString(), | ||
104 | label: q.label, | ||
105 | disabled: q.disabled | ||
106 | })) | ||
107 | |||
108 | this.videoQuotaDailyOptions = this.configService | ||
109 | .videoQuotaDailyOptions.map(q => ({ | ||
110 | value: q.value?.toString(), | ||
111 | label: q.label, | ||
112 | disabled: q.disabled | ||
113 | })) | ||
114 | } | 103 | } |
115 | } | 104 | } |
diff --git a/client/src/app/+my-library/my-video-playlists/my-video-playlist-edit.ts b/client/src/app/+my-library/my-video-playlists/my-video-playlist-edit.ts index 40ba23e75..71db0592a 100644 --- a/client/src/app/+my-library/my-video-playlists/my-video-playlist-edit.ts +++ b/client/src/app/+my-library/my-video-playlists/my-video-playlist-edit.ts | |||
@@ -1,6 +1,7 @@ | |||
1 | import { FormReactive, SelectChannelItem } from '@app/shared/shared-forms' | 1 | import { FormReactive } from '@app/shared/shared-forms' |
2 | import { VideoConstant, VideoPlaylistPrivacy } from '@shared/models' | 2 | import { VideoConstant, VideoPlaylistPrivacy } from '@shared/models' |
3 | import { VideoPlaylist } from '@shared/models/videos/playlist/video-playlist.model' | 3 | import { VideoPlaylist } from '@shared/models/videos/playlist/video-playlist.model' |
4 | import { SelectChannelItem } from '../../../types/select-options-item.model' | ||
4 | 5 | ||
5 | export abstract class MyVideoPlaylistEdit extends FormReactive { | 6 | export abstract class MyVideoPlaylistEdit extends FormReactive { |
6 | // Declare it here to avoid errors in create template | 7 | // Declare it here to avoid errors in create template |
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 80b5dce46..f51f52160 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 | |||
@@ -1,5 +1,6 @@ | |||
1 | import { forkJoin } from 'rxjs' | 1 | import { forkJoin } from 'rxjs' |
2 | import { map } from 'rxjs/operators' | 2 | import { map } from 'rxjs/operators' |
3 | import { SelectChannelItem } from 'src/types/select-options-item.model' | ||
3 | import { Component, EventEmitter, Input, NgZone, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' | 4 | import { Component, EventEmitter, Input, NgZone, OnDestroy, OnInit, Output, ViewChild } from '@angular/core' |
4 | import { FormArray, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms' | 5 | import { FormArray, FormControl, FormGroup, ValidatorFn, Validators } from '@angular/forms' |
5 | import { HooksService, PluginService, ServerService } from '@app/core' | 6 | import { HooksService, PluginService, ServerService } from '@app/core' |
@@ -17,10 +18,10 @@ import { | |||
17 | VIDEO_SUPPORT_VALIDATOR, | 18 | VIDEO_SUPPORT_VALIDATOR, |
18 | VIDEO_TAGS_ARRAY_VALIDATOR | 19 | VIDEO_TAGS_ARRAY_VALIDATOR |
19 | } from '@app/shared/form-validators/video-validators' | 20 | } from '@app/shared/form-validators/video-validators' |
20 | import { FormReactiveValidationMessages, FormValidatorService, SelectChannelItem } from '@app/shared/shared-forms' | 21 | import { FormReactiveValidationMessages, FormValidatorService } from '@app/shared/shared-forms' |
21 | import { InstanceService } from '@app/shared/shared-instance' | 22 | import { InstanceService } from '@app/shared/shared-instance' |
22 | import { VideoCaptionEdit, VideoEdit, VideoService } from '@app/shared/shared-main' | 23 | import { VideoCaptionEdit, VideoEdit, VideoService } from '@app/shared/shared-main' |
23 | import { ServerConfig, VideoConstant, LiveVideo, VideoPrivacy } from '@shared/models' | 24 | import { LiveVideo, ServerConfig, VideoConstant, VideoPrivacy } from '@shared/models' |
24 | import { RegisterClientFormFieldOptions, RegisterClientVideoFieldOptions } from '@shared/models/plugins/register-client-form-field.model' | 25 | import { RegisterClientFormFieldOptions, RegisterClientVideoFieldOptions } from '@shared/models/plugins/register-client-form-field.model' |
25 | import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service' | 26 | import { I18nPrimengCalendarService } from './i18n-primeng-calendar.service' |
26 | import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component' | 27 | import { VideoCaptionAddModalComponent } from './video-caption-add-modal.component' |
diff --git a/client/src/app/+videos/+video-edit/video-add-components/video-send.ts b/client/src/app/+videos/+video-edit/video-add-components/video-send.ts index 812936d7a..9a22024e5 100644 --- a/client/src/app/+videos/+video-edit/video-add-components/video-send.ts +++ b/client/src/app/+videos/+video-edit/video-add-components/video-send.ts | |||
@@ -1,8 +1,9 @@ | |||
1 | import { catchError, switchMap, tap } from 'rxjs/operators' | 1 | import { catchError, switchMap, tap } from 'rxjs/operators' |
2 | import { SelectChannelItem } from 'src/types/select-options-item.model' | ||
2 | import { Directive, EventEmitter, OnInit } from '@angular/core' | 3 | import { Directive, EventEmitter, OnInit } from '@angular/core' |
3 | import { AuthService, CanComponentDeactivateResult, Notifier, ServerService } from '@app/core' | 4 | import { AuthService, CanComponentDeactivateResult, Notifier, ServerService } from '@app/core' |
4 | import { populateAsyncUserVideoChannels } from '@app/helpers' | 5 | import { populateAsyncUserVideoChannels } from '@app/helpers' |
5 | import { FormReactive, SelectChannelItem } from '@app/shared/shared-forms' | 6 | import { FormReactive } from '@app/shared/shared-forms' |
6 | import { VideoCaptionEdit, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' | 7 | import { VideoCaptionEdit, VideoCaptionService, VideoEdit, VideoService } from '@app/shared/shared-main' |
7 | import { LoadingBarService } from '@ngx-loading-bar/core' | 8 | import { LoadingBarService } from '@ngx-loading-bar/core' |
8 | import { ServerConfig, VideoConstant, VideoPrivacy } from '@shared/models' | 9 | import { ServerConfig, VideoConstant, VideoPrivacy } from '@shared/models' |
diff --git a/client/src/app/+videos/+video-edit/video-update.component.ts b/client/src/app/+videos/+video-edit/video-update.component.ts index 654901798..2973c6840 100644 --- a/client/src/app/+videos/+video-edit/video-update.component.ts +++ b/client/src/app/+videos/+video-edit/video-update.component.ts | |||
@@ -1,9 +1,10 @@ | |||
1 | import { of } from 'rxjs' | 1 | import { of } from 'rxjs' |
2 | import { map, switchMap } from 'rxjs/operators' | 2 | import { map, switchMap } from 'rxjs/operators' |
3 | import { SelectChannelItem } from 'src/types/select-options-item.model' | ||
3 | import { Component, HostListener, OnInit } from '@angular/core' | 4 | import { Component, HostListener, OnInit } from '@angular/core' |
4 | import { ActivatedRoute, Router } from '@angular/router' | 5 | import { ActivatedRoute, Router } from '@angular/router' |
5 | import { Notifier } from '@app/core' | 6 | import { Notifier } from '@app/core' |
6 | import { FormReactive, FormValidatorService, SelectChannelItem } from '@app/shared/shared-forms' | 7 | import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' |
7 | import { VideoCaptionEdit, VideoCaptionService, VideoDetails, VideoEdit, VideoService } from '@app/shared/shared-main' | 8 | import { VideoCaptionEdit, VideoCaptionService, VideoDetails, VideoEdit, VideoService } from '@app/shared/shared-main' |
8 | import { LiveVideoService } from '@app/shared/shared-video-live' | 9 | import { LiveVideoService } from '@app/shared/shared-video-live' |
9 | import { LoadingBarService } from '@ngx-loading-bar/core' | 10 | import { LoadingBarService } from '@ngx-loading-bar/core' |
diff --git a/client/src/app/helpers/utils.ts b/client/src/app/helpers/utils.ts index b4e26d792..6d7e76b11 100644 --- a/client/src/app/helpers/utils.ts +++ b/client/src/app/helpers/utils.ts | |||
@@ -1,10 +1,10 @@ | |||
1 | import { SelectChannelItem } from 'src/types/select-options-item.model' | ||
1 | import { DatePipe } from '@angular/common' | 2 | import { DatePipe } from '@angular/common' |
2 | import { HttpErrorResponse } from '@angular/common/http' | 3 | import { HttpErrorResponse } from '@angular/common/http' |
3 | import { Notifier } from '@app/core' | 4 | import { Notifier } from '@app/core' |
4 | import { SelectChannelItem } from '@app/shared/shared-forms' | 5 | import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' |
5 | import { environment } from '../../environments/environment' | 6 | import { environment } from '../../environments/environment' |
6 | import { AuthService } from '../core/auth' | 7 | import { AuthService } from '../core/auth' |
7 | import { HttpStatusCode } from '@shared/core-utils/miscs/http-error-codes' | ||
8 | 8 | ||
9 | // Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript | 9 | // Thanks: https://stackoverflow.com/questions/901115/how-can-i-get-query-string-values-in-javascript |
10 | function getParameterByName (name: string, url: string) { | 10 | function getParameterByName (name: string, url: string) { |
diff --git a/client/src/app/shared/form-validators/form-validator.model.ts b/client/src/app/shared/form-validators/form-validator.model.ts index 248a3b1d3..07b1ea075 100644 --- a/client/src/app/shared/form-validators/form-validator.model.ts +++ b/client/src/app/shared/form-validators/form-validator.model.ts | |||
@@ -10,5 +10,5 @@ export type BuildFormArgument = { | |||
10 | } | 10 | } |
11 | 11 | ||
12 | export type BuildFormDefaultValues = { | 12 | export type BuildFormDefaultValues = { |
13 | [ name: string ]: string | string[] | BuildFormDefaultValues | 13 | [ name: string ]: number | string | string[] | BuildFormDefaultValues |
14 | } | 14 | } |
diff --git a/client/src/app/shared/shared-forms/select/select-channel.component.ts b/client/src/app/shared/shared-forms/select/select-channel.component.ts index 1d91d59bc..40a7c53bb 100644 --- a/client/src/app/shared/shared-forms/select/select-channel.component.ts +++ b/client/src/app/shared/shared-forms/select/select-channel.component.ts | |||
@@ -1,13 +1,7 @@ | |||
1 | import { Component, forwardRef, Input } from '@angular/core' | 1 | import { Component, forwardRef, Input, OnChanges } from '@angular/core' |
2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' | 2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' |
3 | import { VideoChannel } from '@app/shared/shared-main' | 3 | import { VideoChannel } from '@app/shared/shared-main' |
4 | 4 | import { SelectChannelItem } from '../../../../types/select-options-item.model' | |
5 | export type SelectChannelItem = { | ||
6 | id: number | ||
7 | label: string | ||
8 | support: string | ||
9 | avatarPath?: string | ||
10 | } | ||
11 | 5 | ||
12 | @Component({ | 6 | @Component({ |
13 | selector: 'my-select-channel', | 7 | selector: 'my-select-channel', |
@@ -21,9 +15,10 @@ export type SelectChannelItem = { | |||
21 | } | 15 | } |
22 | ] | 16 | ] |
23 | }) | 17 | }) |
24 | export class SelectChannelComponent implements ControlValueAccessor { | 18 | export class SelectChannelComponent implements ControlValueAccessor, OnChanges { |
25 | @Input() items: SelectChannelItem[] = [] | 19 | @Input() items: SelectChannelItem[] = [] |
26 | 20 | ||
21 | channels: SelectChannelItem[] = [] | ||
27 | selectedId: number | 22 | selectedId: number |
28 | 23 | ||
29 | // ng-select options | 24 | // ng-select options |
@@ -32,10 +27,14 @@ export class SelectChannelComponent implements ControlValueAccessor { | |||
32 | clearable = false | 27 | clearable = false |
33 | searchable = false | 28 | searchable = false |
34 | 29 | ||
35 | get channels () { | 30 | ngOnChanges () { |
36 | return this.items.map(c => Object.assign(c, { | 31 | this.channels = this.items.map(c => { |
37 | avatarPath: c.avatarPath ? c.avatarPath : VideoChannel.GET_DEFAULT_AVATAR_URL() | 32 | const avatarPath = c.avatarPath |
38 | })) | 33 | ? c.avatarPath |
34 | : VideoChannel.GET_DEFAULT_AVATAR_URL() | ||
35 | |||
36 | return Object.assign({}, c, { avatarPath }) | ||
37 | }) | ||
39 | } | 38 | } |
40 | 39 | ||
41 | propagateChange = (_: any) => { /* empty */ } | 40 | propagateChange = (_: any) => { /* empty */ } |
diff --git a/client/src/app/shared/shared-forms/select/select-checkbox.component.ts b/client/src/app/shared/shared-forms/select/select-checkbox.component.ts index eb0c49034..c2523f15c 100644 --- a/client/src/app/shared/shared-forms/select/select-checkbox.component.ts +++ b/client/src/app/shared/shared-forms/select/select-checkbox.component.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { Component, forwardRef, Input, OnInit } from '@angular/core' | 1 | import { Component, forwardRef, Input, OnInit } from '@angular/core' |
2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' | 2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' |
3 | import { SelectOptionsItem } from './select-options.component' | 3 | import { SelectOptionsItem } from '../../../../types/select-options-item.model' |
4 | 4 | ||
5 | export type ItemSelectCheckboxValue = { id?: string | number, group?: string } | string | 5 | export type ItemSelectCheckboxValue = { id?: string | number, group?: string } | string |
6 | 6 | ||
diff --git a/client/src/app/shared/shared-forms/select/select-custom-value.component.html b/client/src/app/shared/shared-forms/select/select-custom-value.component.html index 5fdf432ff..9dc8c2ec2 100644 --- a/client/src/app/shared/shared-forms/select/select-custom-value.component.html +++ b/client/src/app/shared/shared-forms/select/select-custom-value.component.html | |||
@@ -10,5 +10,9 @@ | |||
10 | (ngModelChange)="onModelChange()" | 10 | (ngModelChange)="onModelChange()" |
11 | ></my-select-options> | 11 | ></my-select-options> |
12 | 12 | ||
13 | <input *ngIf="isCustomValue()" [(ngModel)]="customValue" (ngModelChange)="onModelChange()" type="text" class="form-control" /> | 13 | <ng-container *ngIf="isCustomValue()"> |
14 | <input [(ngModel)]="customValue" (ngModelChange)="onModelChange()" [type]="inputType" class="form-control" /> | ||
15 | |||
16 | <span *ngIf="inputSuffix" class="input-suffix">{{ inputSuffix }}</span> | ||
17 | </ng-container> | ||
14 | </div> | 18 | </div> |
diff --git a/client/src/app/shared/shared-forms/select/select-custom-value.component.ts b/client/src/app/shared/shared-forms/select/select-custom-value.component.ts index a8e5ad0d3..bc6b863c7 100644 --- a/client/src/app/shared/shared-forms/select/select-custom-value.component.ts +++ b/client/src/app/shared/shared-forms/select/select-custom-value.component.ts | |||
@@ -1,6 +1,6 @@ | |||
1 | import { Component, forwardRef, Input, OnChanges } from '@angular/core' | 1 | import { Component, forwardRef, Input, OnChanges } from '@angular/core' |
2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' | 2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' |
3 | import { SelectOptionsItem } from './select-options.component' | 3 | import { SelectOptionsItem } from '../../../../types/select-options-item.model' |
4 | 4 | ||
5 | @Component({ | 5 | @Component({ |
6 | selector: 'my-select-custom-value', | 6 | selector: 'my-select-custom-value', |
@@ -20,6 +20,8 @@ export class SelectCustomValueComponent implements ControlValueAccessor, OnChang | |||
20 | @Input() searchable = false | 20 | @Input() searchable = false |
21 | @Input() groupBy: string | 21 | @Input() groupBy: string |
22 | @Input() labelForId: string | 22 | @Input() labelForId: string |
23 | @Input() inputSuffix: string | ||
24 | @Input() inputType = 'text' | ||
23 | 25 | ||
24 | customValue: number | string = '' | 26 | customValue: number | string = '' |
25 | selectedId: number | string | 27 | selectedId: number | string |
diff --git a/client/src/app/shared/shared-forms/select/select-options.component.ts b/client/src/app/shared/shared-forms/select/select-options.component.ts index 51a3f515d..2890670e5 100644 --- a/client/src/app/shared/shared-forms/select/select-options.component.ts +++ b/client/src/app/shared/shared-forms/select/select-options.component.ts | |||
@@ -1,13 +1,6 @@ | |||
1 | import { Component, forwardRef, Input } from '@angular/core' | 1 | import { Component, forwardRef, Input } from '@angular/core' |
2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' | 2 | import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms' |
3 | 3 | import { SelectOptionsItem } from '../../../../types/select-options-item.model' | |
4 | export type SelectOptionsItem = { | ||
5 | id: string | number | ||
6 | label: string | ||
7 | description?: string | ||
8 | group?: string | ||
9 | groupLabel?: string | ||
10 | } | ||
11 | 4 | ||
12 | @Component({ | 5 | @Component({ |
13 | selector: 'my-select-options', | 6 | selector: 'my-select-options', |
diff --git a/client/src/app/shared/shared-forms/select/select-shared.component.scss b/client/src/app/shared/shared-forms/select/select-shared.component.scss index 1a4192b55..80196b8df 100644 --- a/client/src/app/shared/shared-forms/select/select-shared.component.scss +++ b/client/src/app/shared/shared-forms/select/select-shared.component.scss | |||
@@ -33,15 +33,20 @@ ng-select ::ng-deep { | |||
33 | 33 | ||
34 | .root { | 34 | .root { |
35 | display:flex; | 35 | display:flex; |
36 | align-items: center; | ||
36 | 37 | ||
37 | > my-select-options { | 38 | > my-select-options { |
38 | flex-grow: 1; | 39 | flex-grow: 1; |
39 | } | 40 | } |
40 | } | 41 | } |
41 | 42 | ||
42 | input[type=text] { | 43 | my-select-options + input { |
43 | margin-left: 5px; | 44 | margin-left: 5px; |
44 | 45 | ||
45 | @include peertube-input-text($form-base-input-width); | 46 | @include peertube-input-text($form-base-input-width); |
46 | display: block; | 47 | display: block; |
47 | } | 48 | } |
49 | |||
50 | .input-suffix { | ||
51 | margin-left: 5px; | ||
52 | } | ||
diff --git a/client/src/app/shared/shared-user-settings/user-video-settings.component.ts b/client/src/app/shared/shared-user-settings/user-video-settings.component.ts index 2497e001c..d74c2b2d8 100644 --- a/client/src/app/shared/shared-user-settings/user-video-settings.component.ts +++ b/client/src/app/shared/shared-user-settings/user-video-settings.component.ts | |||
@@ -3,9 +3,10 @@ import { forkJoin, Subject, Subscription } from 'rxjs' | |||
3 | import { first } from 'rxjs/operators' | 3 | import { first } from 'rxjs/operators' |
4 | import { Component, Input, OnDestroy, OnInit } from '@angular/core' | 4 | import { Component, Input, OnDestroy, OnInit } from '@angular/core' |
5 | import { AuthService, Notifier, ServerService, User, UserService } from '@app/core' | 5 | import { AuthService, Notifier, ServerService, User, UserService } from '@app/core' |
6 | import { FormReactive, FormValidatorService, ItemSelectCheckboxValue, SelectOptionsItem } from '@app/shared/shared-forms' | 6 | import { FormReactive, FormValidatorService, ItemSelectCheckboxValue } from '@app/shared/shared-forms' |
7 | import { UserUpdateMe } from '@shared/models' | 7 | import { UserUpdateMe } from '@shared/models' |
8 | import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' | 8 | import { NSFWPolicyType } from '@shared/models/videos/nsfw-policy.type' |
9 | import { SelectOptionsItem } from '../../../types/select-options-item.model' | ||
9 | 10 | ||
10 | @Component({ | 11 | @Component({ |
11 | selector: 'my-user-video-settings', | 12 | selector: 'my-user-video-settings', |
diff --git a/client/src/types/select-options-item.model.ts b/client/src/types/select-options-item.model.ts new file mode 100644 index 000000000..895965a74 --- /dev/null +++ b/client/src/types/select-options-item.model.ts | |||
@@ -0,0 +1,13 @@ | |||
1 | export interface SelectOptionsItem { | ||
2 | id: string | number | ||
3 | label: string | ||
4 | description?: string | ||
5 | group?: string | ||
6 | groupLabel?: string | ||
7 | } | ||
8 | |||
9 | export interface SelectChannelItem extends SelectOptionsItem { | ||
10 | id: number | ||
11 | support: string | ||
12 | avatarPath?: string | ||
13 | } | ||