Merge branch 'release/2.1.0' into develop
[oweals/peertube.git] / client / src / app / +admin / config / edit-custom-config / edit-custom-config.component.html
1 <form role="form" [formGroup]="form">
2
3   <ngb-tabset class="root-tabset bootstrap">
4
5     <ngb-tab i18n-title title="Instance information">
6       <ng-template ngbTabContent>
7
8         <ng-container formGroupName="instance">
9
10           <div i18n class="inner-form-title">Instance</div>
11
12           <div class="form-group">
13             <label i18n for="instanceName">Name</label>
14             <input
15               type="text" id="instanceName"
16               formControlName="name" [ngClass]="{ 'input-error': formErrors.instance.name }"
17             >
18             <div *ngIf="formErrors.instance.name" class="form-error">{{ formErrors.instance.name }}</div>
19           </div>
20
21           <div class="form-group">
22             <label i18n for="instanceShortDescription">Short description</label>
23             <textarea
24               id="instanceShortDescription" formControlName="shortDescription" class="small"
25               [ngClass]="{ 'input-error': formErrors['instance.shortDescription'] }"
26             ></textarea>
27             <div *ngIf="formErrors.instance.shortDescription" class="form-error">{{ formErrors.instance.shortDescription }}</div>
28           </div>
29
30           <div class="form-group">
31             <label i18n for="instanceDescription">Description</label><my-help helpType="markdownText"></my-help>
32             <my-markdown-textarea
33               name="instanceDescription" formControlName="description" textareaWidth="500px" [previewColumn]="true"
34               [classes]="{ 'input-error': formErrors['instance.description'] }"
35             ></my-markdown-textarea>
36             <div *ngIf="formErrors.instance.description" class="form-error">{{ formErrors.instance.description }}</div>
37           </div>
38
39           <div class="form-group">
40             <label i18n for="instanceCategories">Main instance categories</label>
41
42             <div>
43               <p-multiSelect
44                 inputId="instanceCategories" [options]="categoryItems" formControlName="categories" [showToggleAll]="false"
45                 [defaultLabel]="getDefaultCategoryLabel()" [selectedItemsLabel]="getSelectedCategoryLabel()"
46                 emptyFilterMessage="No results found" i18n-emptyFilterMessage
47               ></p-multiSelect>
48             </div>
49           </div>
50
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">
66             <my-peertube-checkbox inputName="instanceIsNSFW" formControlName="isNSFW">
67               <ng-template ptTemplate="label">
68                 <ng-container i18n>This instance is dedicated to sensitive or NSFW content</ng-container>
69               </ng-template>
70
71               <ng-template ptTemplate="help">
72                 <ng-container i18n>
73                   Enabling it will allow other administrators to know that you are mainly federating sensitive content.<br /><br />
74                   Moreover, the NSFW checkbox on video upload will be automatically checked by default.
75                 </ng-container>
76               </ng-template>
77             </my-peertube-checkbox>
78           </div>
79
80           <div class="form-group">
81             <label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label>
82
83             <my-help>
84               <ng-template ptTemplate="customHtml">
85                 <ng-container i18n>
86                   With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video.
87                 </ng-container>
88               </ng-template>
89             </my-help>
90
91             <div class="peertube-select-container">
92               <select id="instanceDefaultNSFWPolicy" formControlName="defaultNSFWPolicy">
93                 <option i18n value="do_not_list">Do not list</option>
94                 <option i18n value="blur">Blur thumbnails</option>
95                 <option i18n value="display">Display</option>
96               </select>
97             </div>
98             <div *ngIf="formErrors.instance.defaultNSFWPolicy" class="form-error">{{ formErrors.instance.defaultNSFWPolicy }}</div>
99           </div>
100
101           <div class="form-group">
102             <label i18n for="instanceTerms">Terms</label><my-help helpType="markdownText"></my-help>
103             <my-markdown-textarea
104               name="instanceTerms" formControlName="terms" textareaWidth="500px" [previewColumn]="true"
105               [ngClass]="{ 'input-error': formErrors['instance.terms'] }"
106             ></my-markdown-textarea>
107             <div *ngIf="formErrors.instance.terms" class="form-error">{{ formErrors.instance.terms }}</div>
108           </div>
109
110           <div class="form-group">
111             <label i18n for="instanceCodeOfConduct">Code of conduct</label><my-help helpType="markdownText"></my-help>
112             <my-markdown-textarea
113               name="instanceCodeOfConduct" formControlName="codeOfConduct" textareaWidth="500px" [previewColumn]="true"
114               [ngClass]="{ 'input-error': formErrors['instance.codeOfConduct'] }"
115             ></my-markdown-textarea>
116             <div *ngIf="formErrors.instance.codeOfConduct" class="form-error">{{ formErrors.instance.codeOfConduct }}</div>
117           </div>
118
119           <div class="form-group">
120             <label i18n for="instanceModerationInformation">Moderation information</label><my-help helpType="markdownText"></my-help>
121             <div i18n class="label-small-info">Who moderates the instance? What is the policy regarding NSFW videos? Political videos? etc</div>
122
123             <my-markdown-textarea
124               name="instanceModerationInformation" formControlName="moderationInformation" textareaWidth="500px" [previewColumn]="true"
125               [ngClass]="{ 'input-error': formErrors['instance.moderationInformation'] }"
126             ></my-markdown-textarea>
127             <div *ngIf="formErrors.instance.moderationInformation" class="form-error">{{ formErrors.instance.moderationInformation }}</div>
128           </div>
129
130           <div i18n class="inner-form-title">You and your instance</div>
131
132           <div class="form-group">
133             <label i18n for="instanceAdministrator">Who is behind the instance?</label>
134             <div i18n class="label-small-info">A single person? A non-profit? A company?</div>
135
136             <my-markdown-textarea
137               name="instanceAdministrator" formControlName="administrator" textareaWidth="500px" textareaHeight="75px" [previewColumn]="true"
138               [classes]="{ 'input-error': formErrors['instance.administrator'] }"
139             ></my-markdown-textarea>
140
141             <div *ngIf="formErrors.instance.administrator" class="form-error">{{ formErrors.instance.administrator }}</div>
142           </div>
143
144           <div class="form-group">
145             <label i18n for="instanceCreationReason">Why did you create this instance?</label>
146             <div i18n class="label-small-info">To share your personal videos? To open registrations and allow people to upload what they want?</div>
147
148             <textarea
149               id="instanceCreationReason" formControlName="creationReason" class="small"
150               [ngClass]="{ 'input-error': formErrors['instance.creationReason'] }"
151             ></textarea>
152             <div *ngIf="formErrors.instance.creationReason" class="form-error">{{ formErrors.instance.creationReason }}</div>
153           </div>
154
155           <div class="form-group">
156             <label i18n for="instanceMaintenanceLifetime">How long do you plan to maintain this instance?</label>
157             <div i18n class="label-small-info">It's important to know for users who want to register on your instance</div>
158
159             <textarea
160               id="instanceMaintenanceLifetime" formControlName="maintenanceLifetime" class="small"
161               [ngClass]="{ 'input-error': formErrors['instance.maintenanceLifetime'] }"
162             ></textarea>
163             <div *ngIf="formErrors.instance.maintenanceLifetime" class="form-error">{{ formErrors.instance.maintenanceLifetime }}</div>
164           </div>
165
166           <div class="form-group">
167             <label i18n for="instanceBusinessModel">How will you finance the PeerTube server?</label>
168             <div i18n class="label-small-info">With your own funds? With users donations? Advertising?</div>
169
170             <textarea
171               id="instanceBusinessModel" formControlName="businessModel" class="small"
172               [ngClass]="{ 'input-error': formErrors['instance.businessModel'] }"
173             ></textarea>
174             <div *ngIf="formErrors.instance.businessModel" class="form-error">{{ formErrors.instance.businessModel }}</div>
175           </div>
176
177           <div i18n class="inner-form-title">Other information</div>
178
179           <div class="form-group">
180             <label i18n for="instanceHardwareInformation">What server/hardware does the instance run on?</label>
181             <div i18n class="label-small-info">2vCore 2GB RAM/or directly the link to the server you rent etc</div>
182
183             <my-markdown-textarea
184               name="instanceHardwareInformation" formControlName="hardwareInformation" textareaWidth="500px" textareaHeight="75px" [previewColumn]="true"
185               [classes]="{ 'input-error': formErrors['instance.hardwareInformation'] }"
186             ></my-markdown-textarea>
187
188             <div *ngIf="formErrors.instance.hardwareInformation" class="form-error">{{ formErrors.instance.hardwareInformation }}</div>
189           </div>
190
191         </ng-container>
192       </ng-template>
193     </ngb-tab>
194
195     <ngb-tab i18n-title title="Basic configuration">
196       <ng-template ngbTabContent>
197
198         <div i18n class="inner-form-title">Theme & Default route</div>
199
200         <ng-container formGroupName="theme">
201           <div class="form-group">
202             <label i18n for="themeDefault">Global theme</label>
203
204             <div class="peertube-select-container">
205               <select formControlName="default" id="themeDefault">
206                 <option i18n value="default">default</option>
207
208                 <option *ngFor="let theme of availableThemes" [value]="theme">{{ theme }}</option>
209               </select>
210             </div>
211           </div>
212         </ng-container>
213
214
215         <div class="form-group" formGroupName="instance">
216           <label i18n for="instanceDefaultClientRoute">Default client route</label>
217           <div class="peertube-select-container">
218             <select id="instanceDefaultClientRoute" formControlName="defaultClientRoute">
219               <option i18n value="/videos/overview">Discover videos</option>
220               <option i18n value="/videos/trending">Trending videos</option>
221               <option i18n value="/videos/most-liked">Most liked videos</option>
222               <option i18n value="/videos/recently-added">Recently added videos</option>
223               <option i18n value="/videos/local">Local videos</option>
224             </select>
225           </div>
226           <div *ngIf="formErrors.instance.defaultClientRoute" class="form-error">{{ formErrors.instance.defaultClientRoute }}</div>
227         </div>
228
229         <div i18n class="inner-form-title">Signup</div>
230
231         <ng-container formGroupName="signup">
232           <div class="form-group">
233             <my-peertube-checkbox
234               inputName="signupEnabled" formControlName="enabled"
235               i18n-labelText labelText="Signup enabled"
236             >
237               <ng-container ngProjectAs="description">
238                 <span i18n>⚠️ This functionality requires a lot of attention and extra moderation.</span>
239               </ng-container>
240               <ng-container ngProjectAs="extra">
241                 <my-peertube-checkbox [ngClass]="{ 'disabled-checkbox-extra': !isSignupEnabled() }"
242                   inputName="signupRequiresEmailVerification" formControlName="requiresEmailVerification"
243                   i18n-labelText labelText="Signup requires email verification"
244                 ></my-peertube-checkbox>
245
246                 <div [ngClass]="{ 'disabled-checkbox-extra': !isSignupEnabled() }" class="mt-3">
247                   <label i18n for="signupLimit">Signup limit</label>
248                   <input
249                     type="number" min="-1" id="signupLimit"
250                     formControlName="limit" [ngClass]="{ 'input-error': formErrors['signup.limit'] }"
251                   >
252                   <div *ngIf="formErrors.signup.limit" class="form-error">{{ formErrors.signup.limit }}</div>
253                   <small *ngIf="form.value['signup']['limit'] === -1" class="text-muted">Signup won't be limited to a fixed number of users.</small>
254                 </div>
255               </ng-container>
256             </my-peertube-checkbox>
257           </div>
258         </ng-container>
259
260
261         <div i18n class="inner-form-title">Users</div>
262
263         <ng-container formGroupName="user">
264           <div class="form-group">
265             <label i18n for="userVideoQuota">Default video quota per user</label>
266             <div class="peertube-select-container">
267               <select id="userVideoQuota" formControlName="videoQuota">
268                 <option *ngFor="let videoQuotaOption of videoQuotaOptions" [value]="videoQuotaOption.value">
269                   {{ videoQuotaOption.label }}
270                 </option>
271               </select>
272             </div>
273             <div *ngIf="formErrors.user.videoQuota" class="form-error">{{ formErrors.user.videoQuota }}</div>
274           </div>
275
276           <div class="form-group">
277             <label i18n for="userVideoQuotaDaily">Default daily upload limit per user</label>
278             <div class="peertube-select-container">
279               <select id="userVideoQuotaDaily" formControlName="videoQuotaDaily">
280                 <option *ngFor="let videoQuotaDailyOption of videoQuotaDailyOptions" [value]="videoQuotaDailyOption.value">
281                   {{ videoQuotaDailyOption.label }}
282                 </option>
283               </select>
284             </div>
285             <div *ngIf="formErrors.user.videoQuotaDaily" class="form-error">{{ formErrors.user.videoQuotaDaily }}</div>
286           </div>
287         </ng-container>
288
289
290         <div i18n class="inner-form-title">Import</div>
291
292         <ng-container formGroupName="import">
293           <ng-container formGroupName="videos">
294
295             <div class="form-group" formGroupName="http">
296               <my-peertube-checkbox
297                 inputName="importVideosHttpEnabled" formControlName="enabled"
298                 i18n-labelText labelText="Allow import with HTTP URL (i.e. YouTube)"
299               ></my-peertube-checkbox>
300             </div>
301
302             <div class="form-group" formGroupName="torrent">
303               <my-peertube-checkbox
304                 inputName="importVideosTorrentEnabled" formControlName="enabled"
305                 i18n-labelText labelText="Allow import with a torrent file or a magnet URI"
306               ></my-peertube-checkbox>
307             </div>
308
309           </ng-container>
310         </ng-container>
311
312
313         <div i18n class="inner-form-title">Auto-blacklist</div>
314
315         <ng-container formGroupName="autoBlacklist">
316           <ng-container formGroupName="videos">
317             <ng-container formGroupName="ofUsers">
318
319               <div class="form-group">
320                 <my-peertube-checkbox
321                   inputName="autoBlacklistVideosOfUsersEnabled" formControlName="enabled"
322                   i18n-labelText labelText="Blacklist new videos automatically"
323                 >
324                 <ng-container ngProjectAs="description">
325                   <span i18n>Unless a user is marked as trusted, their videos will stay private until a moderator reviews them.</span>
326                 </ng-container>
327               </my-peertube-checkbox>
328               </div>
329
330             </ng-container>
331           </ng-container>
332         </ng-container>
333
334
335         <div i18n class="inner-form-title">Instance followers</div>
336
337         <ng-container formGroupName="followers">
338           <ng-container formGroupName="instance">
339
340             <div class="form-group">
341               <my-peertube-checkbox
342                 inputName="followersInstanceEnabled" formControlName="enabled"
343                 i18n-labelText labelText="Other instances can follow your instance"
344               ></my-peertube-checkbox>
345             </div>
346
347             <div class="form-group">
348               <my-peertube-checkbox
349                 inputName="followersInstanceManualApproval" formControlName="manualApproval"
350                 i18n-labelText labelText="Manually approve new instance followers"
351               ></my-peertube-checkbox>
352             </div>
353           </ng-container>
354         </ng-container>
355
356         <div i18n class="inner-form-title">Instance followings</div>
357
358         <ng-container formGroupName="followings">
359           <ng-container formGroupName="instance">
360
361             <ng-container formGroupName="autoFollowBack">
362               <div class="form-group">
363                 <my-peertube-checkbox
364                   inputName="followingsInstanceAutoFollowBackEnabled" formControlName="enabled"
365                   i18n-labelText labelText="Automatically follow other instances that follow you"
366                 >
367                   <ng-container ngProjectAs="description">
368                     <span i18n>⚠️ This functionality requires a lot of attention and extra moderation.</span>
369                   </ng-container>
370                 </my-peertube-checkbox>
371               </div>
372             </ng-container>
373
374             <ng-container formGroupName="autoFollowIndex">
375               <div class="form-group">
376                 <my-peertube-checkbox
377                   inputName="followingsInstanceAutoFollowIndexEnabled" formControlName="enabled"
378                   i18n-labelText labelText="Automatically follow instances of the public index"
379                 >
380                   <ng-container ngProjectAs="description">
381                     <span i18n>⚠️ This functionality requires a lot of attention and extra moderation.</span>
382                   </ng-container>
383
384                   <ng-container ngProjectAs="extra">
385                     <div [ngClass]="{ 'disabled-checkbox-extra': !isAutoFollowIndexEnabled() }">
386                       <label i18n for="followingsInstanceAutoFollowIndexUrl">Index URL</label>
387                       <input
388                         type="text" id="followingsInstanceAutoFollowIndexUrl"
389                         formControlName="indexUrl" [ngClass]="{ 'input-error': formErrors['followings.instance.autoFollowIndex.indexUrl'] }"
390                       >
391                       <div *ngIf="formErrors.followings.instance.autoFollowIndex.indexUrl" class="form-error">{{ formErrors.followings.instance.autoFollowIndex.indexUrl }}</div>
392                     </div>
393                   </ng-container>
394                 </my-peertube-checkbox>
395               </div>
396
397             </ng-container>
398           </ng-container>
399         </ng-container>
400
401
402         <div i18n class="inner-form-title">Administrator</div>
403
404         <div class="form-group" formGroupName="admin">
405           <label i18n for="adminEmail">Admin email</label>
406           <input
407             type="text" id="adminEmail"
408             formControlName="email" [ngClass]="{ 'input-error': formErrors['admin.email'] }"
409           >
410           <div *ngIf="formErrors.admin.email" class="form-error">{{ formErrors.admin.email }}</div>
411         </div>
412
413         <div class="form-group" formGroupName="contactForm">
414           <my-peertube-checkbox
415             inputName="enableContactForm" formControlName="enabled"
416             i18n-labelText labelText="Enable contact form"
417           ></my-peertube-checkbox>
418         </div>
419
420       </ng-template>
421     </ngb-tab>
422
423     <ngb-tab i18n-title title="Services">
424       <ng-template ngbTabContent>
425         <div i18n class="inner-form-title">Twitter</div>
426
427         <ng-container formGroupName="services">
428           <ng-container formGroupName="twitter">
429
430             <div class="form-group">
431               <label i18n for="signupLimit">Your Twitter username</label>
432
433               <my-help>
434                 <ng-template ptTemplate="customHtml">
435                   <ng-container i18n>Indicates the Twitter account for the website or platform on which the content was published.</ng-container>
436                 </ng-template>
437               </my-help>
438
439               <input
440                 type="text" id="servicesTwitterUsername"
441                 formControlName="username" [ngClass]="{ 'input-error': formErrors['services.twitter.username'] }"
442               >
443               <div *ngIf="formErrors.services.twitter.username" class="form-error">{{ formErrors.services.twitter.username }}</div>
444             </div>
445
446             <div class="form-group">
447               <my-peertube-checkbox inputName="servicesTwitterWhitelisted" formControlName="whitelisted">
448                 <ng-template ptTemplate="label">
449                   <ng-container i18n>Instance whitelisted by Twitter</ng-container>
450                 </ng-template>
451
452                 <ng-template ptTemplate="help">
453                   <ng-container i18n>
454                     If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br />
455                     If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br />
456                     Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/videos/watch/blabla) on
457                     <a target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a>
458                     to see if you instance is whitelisted.
459                   </ng-container>
460                 </ng-template>
461               </my-peertube-checkbox>
462             </div>
463
464           </ng-container>
465         </ng-container>
466
467     </ng-template>
468     </ngb-tab>
469
470     <ngb-tab i18n-title title="Advanced configuration">
471       <ng-template ngbTabContent>
472
473         <div i18n class="inner-form-title">Transcoding</div>
474
475         <ng-container formGroupName="transcoding">
476           <div class="form-group">
477             <my-peertube-checkbox inputName="transcodingEnabled" formControlName="enabled">
478               <ng-template ptTemplate="label">
479                 <ng-container i18n>Transcoding enabled</ng-container>
480               </ng-template>
481
482               <ng-template ptTemplate="help">
483                 <ng-container i18n>If you disable transcoding, many videos from your users will not work!</ng-container>
484               </ng-template>
485             </my-peertube-checkbox>
486           </div>
487
488           <ng-container *ngIf="isTranscodingEnabled()">
489
490             <div class="form-group">
491               <my-peertube-checkbox
492                 inputName="transcodingAllowAdditionalExtensions" formControlName="allowAdditionalExtensions"
493                 i18n-labelText labelText="Allow additional extensions"
494               >
495                 <ng-template ptTemplate="help">
496                   <ng-container i18n>Allow your users to upload .mkv, .mov, .avi and .flv videos</ng-container>
497                 </ng-template>
498               </my-peertube-checkbox>
499             </div>
500
501             <div class="form-group">
502               <my-peertube-checkbox
503                 inputName="transcodingAllowAudioFiles" formControlName="allowAudioFiles"
504                 i18n-labelText labelText="Allow audio files upload"
505               >
506                 <ng-template ptTemplate="help">
507                   <ng-container i18n>Allow your users to upload audio files that will be merged with the preview file on upload</ng-container>
508                 </ng-template>
509               </my-peertube-checkbox>
510             </div>
511
512             <ng-container formGroupName="webtorrent">
513               <div class="form-group" >
514                 <my-peertube-checkbox
515                   inputName="transcodingWebTorrentEnabled" formControlName="enabled"
516                   i18n-labelText labelText="WebTorrent support enabled"
517                 >
518                   <ng-template ptTemplate="help">
519                     <ng-container i18n>
520                       <strong>Experimental, we suggest you to not disable webtorrent support for now</strong>
521
522                       <p>If you also enabled HLS support, it will multiply videos storage by 2</p>
523
524                       <br />
525
526                       <strong>If disabled, breaks federation with PeerTube instances < 2.1</strong>
527                     </ng-container>
528                   </ng-template>
529                 </my-peertube-checkbox>
530               </div>
531             </ng-container>
532
533             <ng-container formGroupName="hls">
534               <div class="form-group" >
535                 <my-peertube-checkbox
536                   inputName="transcodingHlsEnabled" formControlName="enabled"
537                   i18n-labelText labelText="HLS support enabled"
538                 >
539                   <ng-template ptTemplate="help">
540                     <ng-container i18n>
541                       <strong>Requires ffmpeg >= 4.1</strong>
542
543                       <p>Generate HLS playlists and fragmented MP4 files resulting in a better playback than with the current default player:</p>
544                       <ul>
545                         <li>Resolution change is smoother</li>
546                         <li>Faster playback in particular with long videos</li>
547                         <li>More stable playback (less bugs/infinite loading)</li>
548                       </ul>
549
550                       <p>If you also enabled WebTorrent support, it will multiply videos storage by 2</p>
551                     </ng-container>
552                   </ng-template>
553                 </my-peertube-checkbox>
554               </div>
555             </ng-container>
556
557             <div class="form-group">
558               <label i18n for="transcodingThreads">Transcoding threads</label>
559               <div class="peertube-select-container">
560                 <select id="transcodingThreads" formControlName="threads">
561                   <option *ngFor="let transcodingThreadOption of transcodingThreadOptions" [value]="transcodingThreadOption.value">
562                     {{ transcodingThreadOption.label }}
563                   </option>
564                 </select>
565               </div>
566               <div *ngIf="formErrors.transcoding.threads" class="form-error">{{ formErrors.transcoding.threads }}</div>
567             </div>
568
569             <ng-container formGroupName="resolutions">
570               <div class="form-group" *ngFor="let resolution of resolutions">
571                 <my-peertube-checkbox
572                   [inputName]="getResolutionKey(resolution.id)" [formControlName]="resolution.id"
573                   i18n-labelText labelText="Resolution {{resolution.label}} enabled"
574                 >
575                   <ng-template *ngIf="resolution.description" ptTemplate="help">
576                     <div [innerHTML]="resolution.description"></div>
577                   </ng-template>
578                 </my-peertube-checkbox>
579               </div>
580             </ng-container>
581
582           </ng-container>
583         </ng-container>
584
585         <div class="inner-form-title">
586           <ng-container i18n>Cache</ng-container>
587
588           <my-help>
589             <ng-template ptTemplate="customHtml">
590               <ng-container i18n>Some files are not federated (previews, captions). We fetch them directly from the origin instance and cache them.</ng-container>
591             </ng-template>
592           </my-help>
593         </div>
594
595         <ng-container formGroupName="cache">
596           <div class="form-group" formGroupName="previews">
597             <label i18n for="cachePreviewsSize">Previews cache size</label>
598             <input
599               type="text" id="cachePreviewsSize"
600               formControlName="size" [ngClass]="{ 'input-error': formErrors['cache.previews.size'] }"
601             >
602             <div *ngIf="formErrors.cache.previews.size" class="form-error">{{ formErrors.cache.previews.size }}</div>
603           </div>
604
605           <div class="form-group" formGroupName="captions">
606             <label i18n for="cacheCaptionsSize">Video captions cache size</label>
607             <input
608               type="text" id="cacheCaptionsSize"
609               formControlName="size" [ngClass]="{ 'input-error': formErrors['cache.captions.size'] }"
610             >
611             <div *ngIf="formErrors.cache.captions.size" class="form-error">{{ formErrors.cache.captions.size }}</div>
612           </div>
613         </ng-container>
614
615         <div i18n class="inner-form-title">Customizations</div>
616
617         <ng-container formGroupName="instance">
618           <ng-container formGroupName="customizations">
619             <div class="form-group">
620               <label i18n for="customizationJavascript">JavaScript</label>
621               <my-help>
622                 <ng-template ptTemplate="customHtml">
623                   <ng-container i18n>
624                     Write JavaScript code directly.<br />Example: <pre>console.log('my instance is amazing');</pre>
625                   </ng-container>
626                 </ng-template>
627               </my-help>
628
629               <textarea
630                 id="customizationJavascript" formControlName="javascript"
631                 [ngClass]="{ 'input-error': formErrors['instance.customizations.javascript'] }"
632               ></textarea>
633
634               <div *ngIf="formErrors.instance.customizations.javascript" class="form-error">{{ formErrors.instance.customizations.javascript }}</div>
635             </div>
636
637             <div class="form-group">
638               <label for="customizationCSS">CSS</label>
639
640               <my-help>
641                 <ng-template ptTemplate="customHtml">
642                   <ng-container i18n>
643                     Write CSS code directly. Example:<br /><br />
644 <pre>
645 #custom-css {{ '{' }}
646   color: red;
647 {{ '}' }}
648 </pre>
649
650                     Prepend with <em>#custom-css</em> to override styles. Example:<br /><br />
651 <pre>
652 #custom-css .logged-in-email {{ '{' }}
653   color: red;
654 {{ '}' }}
655 </pre>
656                   </ng-container>
657                 </ng-template>
658               </my-help>
659
660               <textarea
661                 id="customizationCSS" formControlName="css"
662                 [ngClass]="{ 'input-error': formErrors['instance.customizations.css'] }"
663               ></textarea>
664               <div *ngIf="formErrors.instance.customizations.css" class="form-error">{{ formErrors.instance.customizations.css }}</div>
665             </div>
666           </ng-container>
667         </ng-container>
668
669       </ng-template>
670     </ngb-tab>
671   </ngb-tabset>
672
673   <input (click)="formValidated()" type="submit" i18n-value value="Update configuration" [disabled]="!form.valid">
674   <span class="form-error" i18n *ngIf="!form.valid">It seems like the configuration is invalid. Please search for potential errors in the different tabs.</span>
675 </form>