aboutsummaryrefslogtreecommitdiffhomepage
path: root/client/src/app
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/app')
-rw-r--r--client/src/app/+about/about-instance/about-instance.component.html53
-rw-r--r--client/src/app/+about/about-instance/about-instance.component.scss19
-rw-r--r--client/src/app/+about/about-instance/about-instance.component.ts27
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.html135
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss9
-rw-r--r--client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.ts68
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html2
-rw-r--r--client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts47
-rw-r--r--client/src/app/+my-account/my-account.module.ts4
-rw-r--r--client/src/app/shared/shared.module.ts7
10 files changed, 290 insertions, 81 deletions
diff --git a/client/src/app/+about/about-instance/about-instance.component.html b/client/src/app/+about/about-instance/about-instance.component.html
index 7c27ec760..0fd3626b7 100644
--- a/client/src/app/+about/about-instance/about-instance.component.html
+++ b/client/src/app/+about/about-instance/about-instance.component.html
@@ -1,7 +1,8 @@
1<div class="row"> 1<div class="row">
2 <div class="col-md-12 col-xl-6"> 2 <div class="col-md-12 col-xl-6">
3
3 <div class="about-instance-title"> 4 <div class="about-instance-title">
4 <div i18n>About {{ instanceName }} instance</div> 5 <div i18n class="title">About {{ instanceName }} instance</div>
5 6
6 <div *ngIf="isContactFormEnabled" (click)="openContactModal()" i18n role="button" class="contact-admin">Contact administrator</div> 7 <div *ngIf="isContactFormEnabled" (click)="openContactModal()" i18n role="button" class="contact-admin">Contact administrator</div>
7 </div> 8 </div>
@@ -12,16 +13,58 @@
12 <div *ngIf="isNSFW" class="dedicated-to-nsfw">This instance is dedicated to sensitive/NSFW content.</div> 13 <div *ngIf="isNSFW" class="dedicated-to-nsfw">This instance is dedicated to sensitive/NSFW content.</div>
13 </div> 14 </div>
14 15
15 <div class="description"> 16 <div class="middle-title" *ngIf="html.administrator || maintenanceLifetime || businessModel">
17 Administrators & sustainability
18 </div>
19
20 <div class="block administrator" *ngIf="html.administrator">
21 <div i18n class="section-title">Instance administrators</div>
22
23 <div [innerHTML]="html.administrator"></div>
24 </div>
25
26 <div class="block maintenance-lifetime" *ngIf="maintenanceLifetime">
27 <div i18n class="section-title">Maintenance lifetime</div>
28
29 <p>{{ maintenanceLifetime }}</p>
30 </div>
31
32 <div class="block business-model" *ngIf="businessModel">
33 <div i18n class="section-title">Business model</div>
34
35 <p>{{ businessModel }}</p>
36 </div>
37
38 <div class="middle-title" *ngIf="html.description">
39 Information
40 </div>
41
42 <div class="block description">
16 <div i18n class="section-title">Description</div> 43 <div i18n class="section-title">Description</div>
17 44
18 <div [innerHTML]="descriptionHTML"></div> 45 <div [innerHTML]="html.description"></div>
46 </div>
47
48 <div class="middle-title" *ngIf="html.moderationInformation || html.codeOfConduct || html.terms">
49 Moderation
50 </div>
51
52 <div class="block moderation-information" *ngIf="html.moderationInformation">
53 <div i18n class="section-title">Moderation information</div>
54
55 <div [innerHTML]="html.moderationInformation"></div>
56 </div>
57
58 <div class="block code-of-conduct" *ngIf="html.codeOfConduct">
59 <div i18n class="section-title">Code of conduct</div>
60
61 <div [innerHTML]="html.codeOfConduct"></div>
19 </div> 62 </div>
20 63
21 <div class="terms" id="terms-section"> 64 <div class="block terms" id="terms-section">
22 <div i18n class="section-title">Terms</div> 65 <div i18n class="section-title">Terms</div>
23 66
24 <div [innerHTML]="termsHTML"></div> 67 <div [innerHTML]="html.terms"></div>
25 </div> 68 </div>
26 </div> 69 </div>
27 70
diff --git a/client/src/app/+about/about-instance/about-instance.component.scss b/client/src/app/+about/about-instance/about-instance.component.scss
index 0296ae8e9..0585ad5f3 100644
--- a/client/src/app/+about/about-instance/about-instance.component.scss
+++ b/client/src/app/+about/about-instance/about-instance.component.scss
@@ -5,13 +5,13 @@
5 display: flex; 5 display: flex;
6 justify-content: space-between; 6 justify-content: space-between;
7 7
8 & > div { 8 .title {
9 font-size: 20px; 9 font-size: 20px;
10 font-weight: bold;
11 margin-bottom: 15px; 10 margin-bottom: 15px;
11 font-weight: $font-semibold;
12 } 12 }
13 13
14 & > .contact-admin { 14 .contact-admin {
15 @include peertube-button; 15 @include peertube-button;
16 @include orange-button; 16 @include orange-button;
17 17
@@ -21,11 +21,20 @@
21 21
22.section-title { 22.section-title {
23 font-weight: $font-semibold; 23 font-weight: $font-semibold;
24 font-size: 20px; 24 font-size: 16px;
25 margin-bottom: 5px; 25 margin-bottom: 5px;
26 display: flex;
27 align-items: center;
28}
29
30.middle-title {
31 @include in-content-small-title;
32
33 margin-top: 45px;
34 margin-bottom: 25px;
26} 35}
27 36
28.short-description, .description, .terms, .signup { 37.block {
29 margin-bottom: 30px; 38 margin-bottom: 30px;
30} 39}
31 40
diff --git a/client/src/app/+about/about-instance/about-instance.component.ts b/client/src/app/+about/about-instance/about-instance.component.ts
index a5204de27..b85a6be94 100644
--- a/client/src/app/+about/about-instance/about-instance.component.ts
+++ b/client/src/app/+about/about-instance/about-instance.component.ts
@@ -14,8 +14,20 @@ export class AboutInstanceComponent implements OnInit {
14 @ViewChild('contactAdminModal', { static: true }) contactAdminModal: ContactAdminModalComponent 14 @ViewChild('contactAdminModal', { static: true }) contactAdminModal: ContactAdminModalComponent
15 15
16 shortDescription = '' 16 shortDescription = ''
17 descriptionHTML = '' 17
18 termsHTML = '' 18 html = {
19 description: '',
20 terms: '',
21 codeOfConduct: '',
22 moderationInformation: '',
23 administrator: ''
24 }
25
26 maintenanceLifetime = ''
27 businessModel = ''
28
29 languages: string[] = []
30 categories: number[] = []
19 31
20 constructor ( 32 constructor (
21 private notifier: Notifier, 33 private notifier: Notifier,
@@ -43,8 +55,15 @@ export class AboutInstanceComponent implements OnInit {
43 async res => { 55 async res => {
44 this.shortDescription = res.instance.shortDescription 56 this.shortDescription = res.instance.shortDescription
45 57
46 this.descriptionHTML = await this.markdownService.textMarkdownToHTML(res.instance.description) 58 this.maintenanceLifetime = res.instance.maintenanceLifetime
47 this.termsHTML = await this.markdownService.textMarkdownToHTML(res.instance.terms) 59 this.businessModel = res.instance.businessModel
60
61 for (const key of [ 'description', 'terms', 'codeOfConduct', 'moderationInformation', 'administrator' ]) {
62 this.html[key] = await this.markdownService.textMarkdownToHTML(res.instance[key])
63 }
64
65 this.languages = res.instance.languages
66 this.categories = res.instance.categories
48 }, 67 },
49 68
50 () => this.notifier.error(this.i18n('Cannot get about information from server')) 69 () => this.notifier.error(this.i18n('Cannot get about information from server'))
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 ec6f879d7..50df8a8ac 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
@@ -2,12 +2,13 @@
2 2
3 <ngb-tabset class="root-tabset bootstrap"> 3 <ngb-tabset class="root-tabset bootstrap">
4 4
5 <ngb-tab i18n-title title="Basic configuration"> 5 <ngb-tab i18n-title title="Instance information">
6 <ng-template ngbTabContent> 6 <ng-template ngbTabContent>
7 7
8 <div i18n class="inner-form-title">Instance</div>
9
10 <ng-container formGroupName="instance"> 8 <ng-container formGroupName="instance">
9
10 <div i18n class="inner-form-title">Instance</div>
11
11 <div class="form-group"> 12 <div class="form-group">
12 <label i18n for="instanceName">Name</label> 13 <label i18n for="instanceName">Name</label>
13 <input 14 <input
@@ -36,37 +37,41 @@
36 </div> 37 </div>
37 38
38 <div class="form-group"> 39 <div class="form-group">
39 <label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help> 40 <label i18n for="instanceCategories">Main instance categories</label>
40 <my-markdown-textarea 41
41 id="instanceTerms" formControlName="terms" textareaWidth="500px" [previewColumn]="true" 42 <div>
42 [ngClass]="{ 'input-error': formErrors['instance.terms'] }" 43 <p-multiSelect
43 ></my-markdown-textarea> 44 inputId="instanceCategories" [options]="categoryItems" formControlName="categories" showToggleAll="false"
44 <div *ngIf="formErrors.instance.terms" class="form-error">{{ formErrors.instance.terms }}</div> 45 [defaultLabel]="getDefaultCategoryLabel()" [selectedItemsLabel]="getSelectedCategoryLabel()"
46 emptyFilterMessage="No results found" i18n-emptyFilterMessage
47 ></p-multiSelect>
48 </div>
45 </div> 49 </div>
46 50
47 <div class="form-group"> 51 <div class="form-group">
52 <label i18n for="instanceLanguages">Main languages you/your moderators speak</label>
53
54 <div>
55 <p-multiSelect
56 inputId="instanceLanguages" [options]="languageItems" formControlName="languages" showToggleAll="false"
57 [defaultLabel]="getDefaultLanguageLabel()" [selectedItemsLabel]="getSelectedLanguageLabel()"
58 emptyFilterMessage="No results found" i18n-emptyFilterMessage
59 ></p-multiSelect>
60 </div>
61 </div>
62
63 <div i18n class="inner-form-title">Moderation & NSFW</div>
64
65 <div class="form-group">
48 <my-peertube-checkbox 66 <my-peertube-checkbox
49 inputName="instanceIsNSFW" formControlName="isNSFW" 67 inputName="instanceIsNSFW" formControlName="isNSFW"
50 i18n-labelText labelText="Dedicated to sensitive or NSFW content" 68 i18n-labelText labelText="This instance is dedicated to sensitive or NSFW content"
51 i18n-helpHtml helpHtml="Enabling it will allow other administrators to know that you are mainly federating sensitive content.<br /><br /> 69 i18n-helpHtml helpHtml="Enabling it will allow other administrators to know that you are mainly federating sensitive content.<br /><br />
52 Moreover, the NSFW checkbox on video upload will be automatically checked by default." 70 Moreover, the NSFW checkbox on video upload will be automatically checked by default."
53 ></my-peertube-checkbox> 71 ></my-peertube-checkbox>
54 </div> 72 </div>
55 73
56 <div class="form-group"> 74 <div class="form-group">
57 <label i18n for="instanceDefaultClientRoute">Default client route</label>
58 <div class="peertube-select-container">
59 <select id="instanceDefaultClientRoute" formControlName="defaultClientRoute">
60 <option i18n value="/videos/overview">Videos Overview</option>
61 <option i18n value="/videos/trending">Videos Trending</option>
62 <option i18n value="/videos/recently-added">Videos Recently Added</option>
63 <option i18n value="/videos/local">Local videos</option>
64 </select>
65 </div>
66 <div *ngIf="formErrors.instance.defaultClientRoute" class="form-error">{{ formErrors.instance.defaultClientRoute }}</div>
67 </div>
68
69 <div class="form-group">
70 <label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label> 75 <label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label>
71 <my-help 76 <my-help
72 helpType="custom" i18n-customHtml 77 helpType="custom" i18n-customHtml
@@ -82,10 +87,79 @@
82 </div> 87 </div>
83 <div *ngIf="formErrors.instance.defaultNSFWPolicy" class="form-error">{{ formErrors.instance.defaultNSFWPolicy }}</div> 88 <div *ngIf="formErrors.instance.defaultNSFWPolicy" class="form-error">{{ formErrors.instance.defaultNSFWPolicy }}</div>
84 </div> 89 </div>
90
91 <div class="form-group">
92 <label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help>
93 <my-markdown-textarea
94 id="instanceTerms" formControlName="terms" textareaWidth="500px" [previewColumn]="true"
95 [ngClass]="{ 'input-error': formErrors['instance.terms'] }"
96 ></my-markdown-textarea>
97 <div *ngIf="formErrors.instance.terms" class="form-error">{{ formErrors.instance.terms }}</div>
98 </div>
99
100 <div class="form-group">
101 <label i18n for="instanceCodeOfConduct">Code of conduct</label><my-help helpType="markdownText"></my-help>
102 <my-markdown-textarea
103 id="instanceCodeOfConduct" formControlName="codeOfConduct" textareaWidth="500px" [previewColumn]="true"
104 [ngClass]="{ 'input-error': formErrors['instance.codeOfConduct'] }"
105 ></my-markdown-textarea>
106 <div *ngIf="formErrors.instance.codeOfConduct" class="form-error">{{ formErrors.instance.codeOfConduct }}</div>
107 </div>
108
109 <div class="form-group">
110 <label i18n for="instanceModerationInformation">Moderation information</label><my-help helpType="markdownText"></my-help>
111 <div class="label-small-info">Who moderates the instance? What is the policy regarding NSFW videos? Political videos? etc</div>
112
113 <my-markdown-textarea
114 id="instanceModerationInformation" formControlName="moderationInformation" textareaWidth="500px" [previewColumn]="true"
115 [ngClass]="{ 'input-error': formErrors['instance.moderationInformation'] }"
116 ></my-markdown-textarea>
117 <div *ngIf="formErrors.instance.moderationInformation" class="form-error">{{ formErrors.instance.moderationInformation }}</div>
118 </div>
119
120 <div i18n class="inner-form-title">You and your instance</div>
121
122 <div class="form-group">
123 <label i18n for="instanceAdministrator">Who is behind the instance? </label>
124 <div class="label-small-info">A single person? A non profit? A company?</div>
125
126 <textarea
127 id="instanceAdministrator" formControlName="administrator"
128 [ngClass]="{ 'input-error': formErrors['instance.administrator'] }"
129 ></textarea>
130 <div *ngIf="formErrors.instance.administrator" class="form-error">{{ formErrors.instance.administrator }}</div>
131 </div>
132
133 <div class="form-group">
134 <label i18n for="instanceMaintenanceLifetime">How long do you plan to maintain this instance?</label>
135 <div class="label-small-info">It's important to know for users who want to register on your instance</div>
136
137 <textarea
138 id="instanceMaintenanceLifetime" formControlName="maintenanceLifetime"
139 [ngClass]="{ 'input-error': formErrors['instance.maintenanceLifetime'] }"
140 ></textarea>
141 <div *ngIf="formErrors.instance.maintenanceLifetime" class="form-error">{{ formErrors.instance.maintenanceLifetime }}</div>
142 </div>
143
144 <div class="form-group">
145 <label i18n for="instanceBusinessModel">How will you pay the PeerTube instance server?</label>
146 <div class="label-small-info">With you own funds? With users donations? Advertising?</div>
147
148 <textarea
149 id="instanceBusinessModel" formControlName="businessModel"
150 [ngClass]="{ 'input-error': formErrors['instance.businessModel'] }"
151 ></textarea>
152 <div *ngIf="formErrors.instance.businessModel" class="form-error">{{ formErrors.instance.businessModel }}</div>
153 </div>
154
85 </ng-container> 155 </ng-container>
156 </ng-template>
157 </ngb-tab>
86 158
159 <ngb-tab i18n-title title="Basic configuration">
160 <ng-template ngbTabContent>
87 161
88 <div i18n class="inner-form-title">Theme</div> 162 <div i18n class="inner-form-title">Theme & Default route</div>
89 163
90 <ng-container formGroupName="theme"> 164 <ng-container formGroupName="theme">
91 <div class="form-group"> 165 <div class="form-group">
@@ -102,6 +176,19 @@
102 </ng-container> 176 </ng-container>
103 177
104 178
179 <div class="form-group" formGroupName="instance">
180 <label i18n for="instanceDefaultClientRoute">Default client route</label>
181 <div class="peertube-select-container">
182 <select id="instanceDefaultClientRoute" formControlName="defaultClientRoute">
183 <option i18n value="/videos/overview">Videos Discover</option>
184 <option i18n value="/videos/trending">Videos Trending</option>
185 <option i18n value="/videos/recently-added">Videos Recently Added</option>
186 <option i18n value="/videos/local">Local videos</option>
187 </select>
188 </div>
189 <div *ngIf="formErrors.instance.defaultClientRoute" class="form-error">{{ formErrors.instance.defaultClientRoute }}</div>
190 </div>
191
105 <div i18n class="inner-form-title">Signup</div> 192 <div i18n class="inner-form-title">Signup</div>
106 193
107 <ng-container formGroupName="signup"> 194 <ng-container formGroupName="signup">
diff --git a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
index c90bd5141..68f1b01b7 100644
--- a/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
+++ b/client/src/app/+admin/config/edit-custom-config/edit-custom-config.component.scss
@@ -1,6 +1,10 @@
1@import '_variables'; 1@import '_variables';
2@import '_mixins'; 2@import '_mixins';
3 3
4.form-group {
5 margin-bottom: 25px;
6}
7
4input[type=text] { 8input[type=text] {
5 @include peertube-input-text(340px); 9 @include peertube-input-text(340px);
6 display: block; 10 display: block;
@@ -44,3 +48,8 @@ textarea {
44 height: 100px; 48 height: 100px;
45 } 49 }
46} 50}
51
52.label-small-info {
53 font-style: italic;
54 margin-bottom: 10px;
55}
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 d51104569..3119ab040 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
@@ -6,6 +6,9 @@ import { Notifier } from '@app/core'
6import { CustomConfig } from '../../../../../../shared/models/server/custom-config.model' 6import { CustomConfig } from '../../../../../../shared/models/server/custom-config.model'
7import { I18n } from '@ngx-translate/i18n-polyfill' 7import { I18n } from '@ngx-translate/i18n-polyfill'
8import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' 8import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
9import { SelectItem } from 'primeng/api'
10import { forkJoin } from 'rxjs'
11import { first } from 'rxjs/operators'
9 12
10@Component({ 13@Component({
11 selector: 'my-edit-custom-config', 14 selector: 'my-edit-custom-config',
@@ -18,6 +21,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
18 resolutions: { id: string, label: string }[] = [] 21 resolutions: { id: string, label: string }[] = []
19 transcodingThreadOptions: { label: string, value: number }[] = [] 22 transcodingThreadOptions: { label: string, value: number }[] = []
20 23
24 languageItems: SelectItem[] = []
25 categoryItems: SelectItem[] = []
26
21 constructor ( 27 constructor (
22 protected formValidatorService: FormValidatorService, 28 protected formValidatorService: FormValidatorService,
23 private customConfigValidatorsService: CustomConfigValidatorsService, 29 private customConfigValidatorsService: CustomConfigValidatorsService,
@@ -88,10 +94,22 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
88 name: this.customConfigValidatorsService.INSTANCE_NAME, 94 name: this.customConfigValidatorsService.INSTANCE_NAME,
89 shortDescription: this.customConfigValidatorsService.INSTANCE_SHORT_DESCRIPTION, 95 shortDescription: this.customConfigValidatorsService.INSTANCE_SHORT_DESCRIPTION,
90 description: null, 96 description: null,
91 terms: null, 97
92 defaultClientRoute: null,
93 isNSFW: false, 98 isNSFW: false,
94 defaultNSFWPolicy: null, 99 defaultNSFWPolicy: null,
100
101 terms: null,
102 codeOfConduct: null,
103 moderationInformation: null,
104 administrator: null,
105 maintenanceLifetime: null,
106 businessModel: null,
107
108 categories: null,
109 languages: null,
110
111 defaultClientRoute: null,
112
95 customizations: { 113 customizations: {
96 javascript: null, 114 javascript: null,
97 css: null 115 css: null
@@ -184,18 +202,27 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
184 202
185 this.buildForm(formGroupData) 203 this.buildForm(formGroupData)
186 204
187 this.configService.getCustomConfig() 205 forkJoin([
188 .subscribe( 206 this.configService.getCustomConfig(),
189 res => { 207 this.serverService.videoLanguagesLoaded.pipe(first()), // First so the observable completes
190 this.customConfig = res 208 this.serverService.videoCategoriesLoaded.pipe(first())
209 ]).subscribe(
210 ([ config ]) => {
211 this.customConfig = config
191 212
192 this.updateForm() 213 const languages = this.serverService.getVideoLanguages()
193 // Force form validation 214 this.languageItems = languages.map(l => ({ label: l.label, value: l.id }))
194 this.forceCheck()
195 },
196 215
197 err => this.notifier.error(err.message) 216 const categories = this.serverService.getVideoCategories()
198 ) 217 this.categoryItems = categories.map(l => ({ label: l.label, value: l.id }))
218
219 this.updateForm()
220 // Force form validation
221 this.forceCheck()
222 },
223
224 err => this.notifier.error(err.message)
225 )
199 } 226 }
200 227
201 isTranscodingEnabled () { 228 isTranscodingEnabled () {
@@ -224,8 +251,23 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit {
224 ) 251 )
225 } 252 }
226 253
254 getSelectedLanguageLabel () {
255 return this.i18n('{{\'{0} languages selected')
256 }
257
258 getDefaultLanguageLabel () {
259 return this.i18n('No language')
260 }
261
262 getSelectedCategoryLabel () {
263 return this.i18n('{{\'{0} categories selected')
264 }
265
266 getDefaultCategoryLabel () {
267 return this.i18n('No category')
268 }
269
227 private updateForm () { 270 private updateForm () {
228 this.form.patchValue(this.customConfig) 271 this.form.patchValue(this.customConfig)
229 } 272 }
230
231} 273}
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
index 2796dd2db..caa032149 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
+++ b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
@@ -23,7 +23,7 @@
23 23
24 <div> 24 <div>
25 <p-multiSelect 25 <p-multiSelect
26 [options]="languageItems" formControlName="videoLanguages" showToggleAll="true" 26 inputId="videoLanguages" [options]="languageItems" formControlName="videoLanguages" showToggleAll="true"
27 [defaultLabel]="getDefaultVideoLanguageLabel()" [selectedItemsLabel]="getSelectedVideoLanguageLabel()" 27 [defaultLabel]="getDefaultVideoLanguageLabel()" [selectedItemsLabel]="getSelectedVideoLanguageLabel()"
28 emptyFilterMessage="No results found" i18n-emptyFilterMessage 28 emptyFilterMessage="No results found" i18n-emptyFilterMessage
29 ></p-multiSelect> 29 ></p-multiSelect>
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
index 77febf179..4fb828082 100644
--- a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
+++ b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
@@ -5,9 +5,9 @@ import { AuthService } from '../../../core'
5import { FormReactive, User, UserService } from '../../../shared' 5import { FormReactive, User, UserService } from '../../../shared'
6import { I18n } from '@ngx-translate/i18n-polyfill' 6import { I18n } from '@ngx-translate/i18n-polyfill'
7import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' 7import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
8import { Subject } from 'rxjs' 8import { forkJoin, Subject } from 'rxjs'
9import { SelectItem } from 'primeng/api' 9import { SelectItem } from 'primeng/api'
10import { switchMap } from 'rxjs/operators' 10import { first } from 'rxjs/operators'
11 11
12@Component({ 12@Component({
13 selector: 'my-account-video-settings', 13 selector: 'my-account-video-settings',
@@ -39,30 +39,31 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI
39 videoLanguages: null 39 videoLanguages: null
40 }) 40 })
41 41
42 this.serverService.videoLanguagesLoaded 42 forkJoin([
43 .pipe(switchMap(() => this.userInformationLoaded)) 43 this.serverService.videoLanguagesLoaded.pipe(first()),
44 .subscribe(() => { 44 this.userInformationLoaded.pipe(first())
45 const languages = this.serverService.getVideoLanguages() 45 ]).subscribe(() => {
46 46 const languages = this.serverService.getVideoLanguages()
47 this.languageItems = [ { label: this.i18n('Unknown language'), value: '_unknown' } ] 47
48 this.languageItems = this.languageItems 48 this.languageItems = [ { label: this.i18n('Unknown language'), value: '_unknown' } ]
49 .concat(languages.map(l => ({ label: l.label, value: l.id }))) 49 this.languageItems = this.languageItems
50 50 .concat(languages.map(l => ({ label: l.label, value: l.id })))
51 const videoLanguages = this.user.videoLanguages 51
52 ? this.user.videoLanguages 52 const videoLanguages = this.user.videoLanguages
53 : this.languageItems.map(l => l.value) 53 ? this.user.videoLanguages
54 54 : this.languageItems.map(l => l.value)
55 this.form.patchValue({ 55
56 nsfwPolicy: this.user.nsfwPolicy, 56 this.form.patchValue({
57 webTorrentEnabled: this.user.webTorrentEnabled, 57 nsfwPolicy: this.user.nsfwPolicy,
58 autoPlayVideo: this.user.autoPlayVideo === true, 58 webTorrentEnabled: this.user.webTorrentEnabled,
59 videoLanguages 59 autoPlayVideo: this.user.autoPlayVideo === true,
60 }) 60 videoLanguages
61 }) 61 })
62 })
62 } 63 }
63 64
64 updateDetails () { 65 updateDetails () {
65 const nsfwPolicy = this.form.value['nsfwPolicy'] 66 const nsfwPolicy = this.form.value[ 'nsfwPolicy' ]
66 const webTorrentEnabled = this.form.value['webTorrentEnabled'] 67 const webTorrentEnabled = this.form.value['webTorrentEnabled']
67 const autoPlayVideo = this.form.value['autoPlayVideo'] 68 const autoPlayVideo = this.form.value['autoPlayVideo']
68 69
diff --git a/client/src/app/+my-account/my-account.module.ts b/client/src/app/+my-account/my-account.module.ts
index 571f46de9..6cf1499d3 100644
--- a/client/src/app/+my-account/my-account.module.ts
+++ b/client/src/app/+my-account/my-account.module.ts
@@ -37,7 +37,6 @@ import {
37} from '@app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component' 37} from '@app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component'
38import { DragDropModule } from '@angular/cdk/drag-drop' 38import { DragDropModule } from '@angular/cdk/drag-drop'
39import { MyAccountChangeEmailComponent } from '@app/+my-account/my-account-settings/my-account-change-email' 39import { MyAccountChangeEmailComponent } from '@app/+my-account/my-account-settings/my-account-change-email'
40import { MultiSelectModule } from 'primeng/multiselect'
41import { MyAccountInterfaceSettingsComponent } from '@app/+my-account/my-account-settings/my-account-interface' 40import { MyAccountInterfaceSettingsComponent } from '@app/+my-account/my-account-settings/my-account-interface'
42 41
43@NgModule({ 42@NgModule({
@@ -48,8 +47,7 @@ import { MyAccountInterfaceSettingsComponent } from '@app/+my-account/my-account
48 SharedModule, 47 SharedModule,
49 TableModule, 48 TableModule,
50 InputSwitchModule, 49 InputSwitchModule,
51 DragDropModule, 50 DragDropModule
52 MultiSelectModule
53 ], 51 ],
54 52
55 declarations: [ 53 declarations: [
diff --git a/client/src/app/shared/shared.module.ts b/client/src/app/shared/shared.module.ts
index eb57a2fff..d71f6357b 100644
--- a/client/src/app/shared/shared.module.ts
+++ b/client/src/app/shared/shared.module.ts
@@ -6,10 +6,8 @@ import { RouterModule } from '@angular/router'
6import { MarkdownTextareaComponent } from '@app/shared/forms/markdown-textarea.component' 6import { MarkdownTextareaComponent } from '@app/shared/forms/markdown-textarea.component'
7import { HelpComponent } from '@app/shared/misc/help.component' 7import { HelpComponent } from '@app/shared/misc/help.component'
8import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive' 8import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive'
9
10import { BytesPipe, KeysPipe, NgPipesModule } from 'ngx-pipes' 9import { BytesPipe, KeysPipe, NgPipesModule } from 'ngx-pipes'
11import { SharedModule as PrimeSharedModule } from 'primeng/components/common/shared' 10import { SharedModule as PrimeSharedModule } from 'primeng/components/common/shared'
12
13import { AUTH_INTERCEPTOR_PROVIDER } from './auth' 11import { AUTH_INTERCEPTOR_PROVIDER } from './auth'
14import { ButtonComponent } from './buttons/button.component' 12import { ButtonComponent } from './buttons/button.component'
15import { DeleteButtonComponent } from './buttons/delete-button.component' 13import { DeleteButtonComponent } from './buttons/delete-button.component'
@@ -93,6 +91,7 @@ import { VideoDownloadComponent } from '@app/shared/video/modals/video-download.
93import { VideoReportComponent } from '@app/shared/video/modals/video-report.component' 91import { VideoReportComponent } from '@app/shared/video/modals/video-report.component'
94import { ClipboardModule } from 'ngx-clipboard' 92import { ClipboardModule } from 'ngx-clipboard'
95import { FollowService } from '@app/shared/instance/follow.service' 93import { FollowService } from '@app/shared/instance/follow.service'
94import { MultiSelectModule } from 'primeng/multiselect'
96 95
97@NgModule({ 96@NgModule({
98 imports: [ 97 imports: [
@@ -113,7 +112,8 @@ import { FollowService } from '@app/shared/instance/follow.service'
113 112
114 PrimeSharedModule, 113 PrimeSharedModule,
115 InputMaskModule, 114 InputMaskModule,
116 NgPipesModule 115 NgPipesModule,
116 MultiSelectModule
117 ], 117 ],
118 118
119 declarations: [ 119 declarations: [
@@ -186,6 +186,7 @@ import { FollowService } from '@app/shared/instance/follow.service'
186 InputMaskModule, 186 InputMaskModule,
187 BytesPipe, 187 BytesPipe,
188 KeysPipe, 188 KeysPipe,
189 MultiSelectModule,
189 190
190 LoaderComponent, 191 LoaderComponent,
191 SmallLoaderComponent, 192 SmallLoaderComponent,