1 <ng-container [formGroup]=
"form">
2 <div class=
"row mt-5"> <!-- appearance grid -->
3 <div class=
"col-12 col-lg-4 col-xl-3">
4 <div i18n
class=
"inner-form-title">APPEARANCE
</div>
5 <div i18n
class=
"inner-form-description">
6 Use
<a class=
"link-orange" routerLink=
"/admin/plugins">plugins & themes
</a> for more involved changes, or add slight
<a class=
"link-orange" routerLink=
"/admin/config/edit-custom" fragment=
"advanced-configuration">customizations
</a>.
10 <div class=
"col-12 col-lg-8 col-xl-9">
12 <ng-container formGroupName=
"theme">
13 <div class=
"form-group">
14 <label i18n
for=
"themeDefault">Theme
</label>
16 <div class=
"peertube-select-container">
17 <select formControlName=
"default" id=
"themeDefault" class=
"form-control">
18 <option i18n
value=
"default">{{ getDefaultThemeLabel() }}
</option>
20 <option *
ngFor=
"let theme of availableThemes" [value]=
"theme.id">{{ theme.label }}
</option>
26 <div class=
"form-group" formGroupName=
"instance">
27 <label i18n
for=
"instanceDefaultClientRoute">Landing page
</label>
29 <my-select-custom-value
30 id=
"instanceDefaultClientRoute"
31 [items]=
"defaultLandingPageOptions"
32 formControlName=
"defaultClientRoute"
35 ></my-select-custom-value>
37 <div *
ngIf=
"formErrors.instance.defaultClientRoute" class=
"form-error">{{ formErrors.instance.defaultClientRoute }}
</div>
40 <div class=
"form-group" formGroupName=
"trending">
41 <ng-container formGroupName=
"videos">
42 <ng-container formGroupName=
"algorithms">
43 <label i18n
for=
"trendingVideosAlgorithmsDefault">Default trending page
</label>
45 <div class=
"peertube-select-container">
46 <select id=
"trendingVideosAlgorithmsDefault" formControlName=
"default" class=
"form-control">
47 <option i18n
value=
"publishedAt">Recently added videos
</option>
48 <option i18n
value=
"originallyPublishedAt">Original publication date
</option>
49 <option i18n
value=
"name">Name
</option>
50 <option i18n
value=
"hot">Hot videos
</option>
51 <option i18n
value=
"most-viewed">Recent views
</option>
52 <option i18n
value=
"most-liked">Most liked videos
</option>
53 <option i18n
value=
"views">Global views
</option>
57 <div *
ngIf=
"formErrors.trending.videos.algorithms.default" class=
"form-error">{{ formErrors.trending.videos.algorithms.default }}
</div>
62 <ng-container formGroupName=
"client">
64 <ng-container formGroupName=
"videos">
65 <ng-container formGroupName=
"miniature">
66 <div class=
"form-group">
68 inputName=
"clientVideosMiniaturePreferAuthorDisplayName" formControlName=
"preferAuthorDisplayName"
69 i18n-labelText
labelText=
"Prefer author display name in video miniature"
70 ></my-peertube-checkbox>
75 <ng-container formGroupName=
"menu">
76 <ng-container formGroupName=
"login">
77 <div class=
"form-group">
79 inputName=
"clientMenuLoginRedirectOnSingleExternalAuth" formControlName=
"redirectOnSingleExternalAuth"
80 i18n-labelText
labelText=
"Redirect users on single external auth when users click on the login button in menu"
82 <ng-container ngProjectAs=
"description">
83 <span *
ngIf=
"countExternalAuth() === 0" i18n
>⚠️ You don't have any external auth plugin enabled.
</span>
84 <span *
ngIf=
"countExternalAuth() > 1" i18n
>⚠️ You have multiple external auth plugins enabled.
</span>
86 </my-peertube-checkbox>
95 <div class=
"row mt-4"> <!-- broadcast grid -->
96 <div class=
"col-12 col-lg-4 col-xl-3">
97 <div i18n
class=
"inner-form-title">BROADCAST MESSAGE
</div>
98 <div i18n
class=
"inner-form-description">
99 Display a message on your instance
103 <div class=
"col-12 col-lg-8 col-xl-9">
105 <ng-container formGroupName=
"broadcastMessage">
107 <div class=
"form-group">
108 <my-peertube-checkbox
109 inputName=
"broadcastMessageEnabled" formControlName=
"enabled"
110 i18n-labelText
labelText=
"Enable broadcast message"
111 ></my-peertube-checkbox>
114 <div class=
"form-group">
115 <my-peertube-checkbox
116 inputName=
"broadcastMessageDismissable" formControlName=
"dismissable"
117 i18n-labelText
labelText=
"Allow users to dismiss the broadcast message "
118 ></my-peertube-checkbox>
121 <div class=
"form-group">
122 <label i18n
for=
"broadcastMessageLevel">Broadcast message level
</label>
124 <div class=
"peertube-select-container">
125 <select id=
"broadcastMessageLevel" formControlName=
"level" class=
"form-control">
126 <option value=
"info">info
</option>
127 <option value=
"warning">warning
</option>
128 <option value=
"error">error
</option>
132 <div *
ngIf=
"formErrors.broadcastMessage.level" class=
"form-error">{{ formErrors.broadcastMessage.level }}
</div>
135 <div class=
"form-group">
136 <label i18n
for=
"broadcastMessageMessage">Message
</label><my-help helpType=
"markdownText"></my-help>
138 <my-markdown-textarea
139 name=
"broadcastMessageMessage" formControlName=
"message"
140 [formError]=
"formErrors['broadcastMessage.message']"
141 ></my-markdown-textarea>
143 <div *
ngIf=
"formErrors.broadcastMessage.message" class=
"form-error">{{ formErrors.broadcastMessage.message }}
</div>
151 <div class=
"row mt-4"> <!-- new users grid -->
152 <div class=
"col-12 col-lg-4 col-xl-3">
153 <div i18n
class=
"inner-form-title">NEW USERS
</div>
154 <div i18n
class=
"inner-form-description">
155 Manage
<a class=
"link-orange" routerLink=
"/admin/users">users
</a> to set their quota individually.
159 <div class=
"col-12 col-lg-8 col-xl-9">
161 <ng-container formGroupName=
"signup">
162 <div class=
"form-group">
163 <my-peertube-checkbox
164 inputName=
"signupEnabled" formControlName=
"enabled"
165 i18n-labelText
labelText=
"Enable Signup"
167 <ng-container ngProjectAs=
"description">
168 <span i18n
>⚠️ This functionality requires a lot of attention and extra moderation.
</span>
170 <div class=
"alert pt-alert-primary alert-signup" *
ngIf=
"signupAlertMessage">{{ signupAlertMessage }}
</div>
173 <ng-container ngProjectAs=
"extra">
174 <div class=
"form-group">
175 <my-peertube-checkbox [ngClass]=
"getDisabledSignupClass()"
176 inputName=
"signupRequiresApproval" formControlName=
"requiresApproval"
177 i18n-labelText
labelText=
"Signup requires approval by moderators"
178 ></my-peertube-checkbox>
181 <div class=
"form-group">
182 <my-peertube-checkbox [ngClass]=
"getDisabledSignupClass()"
183 inputName=
"signupRequiresEmailVerification" formControlName=
"requiresEmailVerification"
184 i18n-labelText
labelText=
"Signup requires email verification"
185 ></my-peertube-checkbox>
188 <div [ngClass]=
"getDisabledSignupClass()">
189 <label i18n
for=
"signupLimit">Signup limit
</label>
191 <div class=
"number-with-unit">
193 type=
"number" min=
"-1" id=
"signupLimit" class=
"form-control"
194 formControlName=
"limit" [ngClass]=
"{ 'input-error': formErrors['signup.limit'] }"
196 <span i18n
>{form.value['signup']['limit'], plural, =
1 {user} other {users}}
</span>
199 <div *
ngIf=
"formErrors.signup.limit" class=
"form-error">{{ formErrors.signup.limit }}
</div>
201 <small i18n *
ngIf=
"hasUnlimitedSignup()" class=
"muted small">Signup won't be limited to a fixed number of users.
</small>
204 <div [ngClass]=
"getDisabledSignupClass()" class=
"mt-3">
205 <label i18n
for=
"signupMinimumAge">Minimum required age to create an account
</label>
207 <div class=
"number-with-unit">
209 type=
"number" min=
"1" id=
"signupMinimumAge" class=
"form-control"
210 formControlName=
"minimumAge" [ngClass]=
"{ 'input-error': formErrors['signup.minimumAge'] }"
212 <span i18n
>{form.value['signup']['minimumAge'], plural, =
1 {year old} other {years old}}
</span>
215 <div *
ngIf=
"formErrors.signup.minimumAge" class=
"form-error">{{ formErrors.signup.minimumAge }}
</div>
218 </my-peertube-checkbox>
222 <ng-container formGroupName=
"user">
223 <div class=
"form-group">
224 <label i18n
for=
"userVideoQuota">Default video quota per user
</label>
226 <my-select-custom-value
228 [items]=
"getVideoQuotaOptions()"
229 formControlName=
"videoQuota"
230 i18n-inputSuffix
inputSuffix=
"bytes" inputType=
"number"
232 ></my-select-custom-value>
234 <my-user-real-quota-info [videoQuota]=
"getUserVideoQuota()"></my-user-real-quota-info>
236 <div *
ngIf=
"formErrors.user.videoQuota" class=
"form-error">{{ formErrors.user.videoQuota }}
</div>
239 <div class=
"form-group">
240 <label i18n
for=
"userVideoQuotaDaily">Default daily upload limit per user
</label>
242 <my-select-custom-value
243 id=
"userVideoQuotaDaily"
244 [items]=
"getVideoQuotaDailyOptions()"
245 formControlName=
"videoQuotaDaily"
246 i18n-inputSuffix
inputSuffix=
"bytes" inputType=
"number"
248 ></my-select-custom-value>
250 <div *
ngIf=
"formErrors.user.videoQuotaDaily" class=
"form-error">{{ formErrors.user.videoQuotaDaily }}
</div>
257 <div class=
"row mt-4"> <!-- videos grid -->
258 <div class=
"col-12 col-lg-4 col-xl-3">
259 <div i18n
class=
"inner-form-title">VIDEOS
</div>
262 <div class=
"col-12 col-lg-8 col-xl-9">
264 <ng-container formGroupName=
"import">
266 <ng-container formGroupName=
"videos">
268 <div class=
"form-group">
269 <label i18n
for=
"importConcurrency">Import jobs concurrency
</label>
270 <span i18n
class=
"small muted ms-1">allows to import multiple videos in parallel. ⚠️ Requires a PeerTube restart.
</span>
272 <div class=
"number-with-unit">
273 <input type=
"number" name=
"importConcurrency" formControlName=
"concurrency" />
274 <span i18n
>jobs in parallel
</span>
277 <div *
ngIf=
"formErrors.import.concurrency" class=
"form-error">{{ formErrors.import.concurrency }}
</div>
280 <div class=
"form-group" formGroupName=
"http">
281 <my-peertube-checkbox
282 inputName=
"importVideosHttpEnabled" formControlName=
"enabled"
283 i18n-labelText
labelText=
"Allow import with HTTP URL (e.g. YouTube)"
285 <ng-container ngProjectAs=
"description">
286 <span i18n
>⚠️ If enabled, we recommend to use
<a class=
"link-orange" href=
"https://docs.joinpeertube.org/maintain-configuration?id=security">a HTTP proxy
</a> to prevent private URL access from your PeerTube server
</span>
288 </my-peertube-checkbox>
291 <div class=
"form-group" formGroupName=
"torrent">
292 <my-peertube-checkbox
293 inputName=
"importVideosTorrentEnabled" formControlName=
"enabled"
294 i18n-labelText
labelText=
"Allow import with a torrent file or a magnet URI"
296 <ng-container ngProjectAs=
"description">
297 <span i18n
>⚠️ We don't recommend to enable this feature if you don't trust your users
</span>
299 </my-peertube-checkbox>
304 <ng-container formGroupName=
"videoChannelSynchronization">
305 <div class=
"form-group">
306 <my-peertube-checkbox
307 inputName=
"importSynchronizationEnabled" formControlName=
"enabled"
308 i18n-labelText
labelText=
"Allow channel synchronization with channel of other platforms like YouTube (requires allowing import with HTTP URL)"
310 <ng-container ngProjectAs=
"description">
311 <span i18n [hidden]=
"isImportVideosHttpEnabled()">
312 ⛔ You need to allow import with HTTP URL to be able to activate this feature.
315 </my-peertube-checkbox>
321 <ng-container formGroupName=
"autoBlacklist">
322 <ng-container formGroupName=
"videos">
323 <ng-container formGroupName=
"ofUsers">
325 <div class=
"form-group">
326 <my-peertube-checkbox
327 inputName=
"autoBlacklistVideosOfUsersEnabled" formControlName=
"enabled"
328 i18n-labelText
labelText=
"Block new videos automatically"
330 <ng-container ngProjectAs=
"description">
331 <span i18n
>Unless a user is marked as trusted, their videos will stay private until a moderator reviews them.
</span>
333 </my-peertube-checkbox>
343 <div class=
"row mt-4"> <!-- video channels grid -->
344 <div class=
"col-12 col-lg-4 col-xl-3">
345 <div i18n
class=
"inner-form-title">VIDEO CHANNELS
</div>
348 <div class=
"col-12 col-lg-8 col-xl-9">
349 <div class=
"form-group" formGroupName=
"videoChannels">
350 <label i18n
for=
"videoChannelsMaxPerUser">Max video channels per user
</label>
352 <div class=
"number-with-unit">
354 type=
"number" min=
"1" id=
"videoChannelsMaxPerUser" class=
"form-control"
355 formControlName=
"maxPerUser" [ngClass]=
"{ 'input-error': formErrors['videoChannels.maxPerUser'] }"
357 <span i18n
>{form.value['videoChannels']['maxPerUser'], plural, =
1 {channel} other {channels}}
</span>
360 <div *
ngIf=
"formErrors.videoChannels.maxPerUser" class=
"form-error">{{ formErrors.videoChannels.maxPerUser }}
</div>
365 <div class=
"row mt-4"> <!-- search grid -->
366 <div class=
"col-12 col-lg-4 col-xl-3">
367 <div i18n
class=
"inner-form-title">SEARCH
</div>
370 <div class=
"col-12 col-lg-8 col-xl-9">
372 <ng-container formGroupName=
"search">
373 <ng-container formGroupName=
"remoteUri">
375 <div class=
"form-group">
376 <my-peertube-checkbox
377 inputName=
"searchRemoteUriUsers" formControlName=
"users"
378 i18n-labelText
labelText=
"Allow users to do remote URI/handle search"
380 <ng-container ngProjectAs=
"description">
381 <span i18n
>Allow
<strong>your users
</strong> to look up remote videos/actors that may not be federated with your instance
</span>
383 </my-peertube-checkbox>
386 <div class=
"form-group">
387 <my-peertube-checkbox
388 inputName=
"searchRemoteUriAnonymous" formControlName=
"anonymous"
389 i18n-labelText
labelText=
"Allow anonymous to do remote URI/handle search"
391 <ng-container ngProjectAs=
"description">
392 <span i18n
>Allow
<strong>anonymous users
</strong> to look up remote videos/actors that may not be federated with your instance
</span>
394 </my-peertube-checkbox>
399 <ng-container formGroupName=
"searchIndex">
400 <div class=
"form-group">
401 <my-peertube-checkbox
402 inputName=
"searchIndexEnabled" formControlName=
"enabled"
403 i18n-labelText
labelText=
"Enable global search"
405 <ng-container ngProjectAs=
"description">
406 <div i18n
>⚠️ This functionality depends heavily on the moderation of instances followed by the search index you select.
</div>
409 You should only use moderated search indexes in production, or
<a class=
"link-orange" href=
"https://framagit.org/framasoft/peertube/search-index">host your own
</a>.
413 <ng-container ngProjectAs=
"extra">
414 <div [ngClass]=
"getDisabledSearchIndexClass()">
415 <label i18n
for=
"searchIndexUrl">Search index URL
</label>
418 type=
"text" id=
"searchIndexUrl" class=
"form-control"
419 formControlName=
"url" [ngClass]=
"{ 'input-error': formErrors['search.searchIndex.url'] }"
422 <div *
ngIf=
"formErrors.search.searchIndex.url" class=
"form-error">{{ formErrors.search.searchIndex.url }}
</div>
426 <my-peertube-checkbox [ngClass]=
"getDisabledSearchIndexClass()"
427 inputName=
"searchIndexDisableLocalSearch" formControlName=
"disableLocalSearch"
428 i18n-labelText
labelText=
"Disable local search in search bar"
429 ></my-peertube-checkbox>
433 <my-peertube-checkbox [ngClass]=
"getDisabledSearchIndexClass()"
434 inputName=
"searchIndexIsDefaultSearch" formControlName=
"isDefaultSearch"
435 i18n-labelText
labelText=
"Search bar uses the global search index by default"
437 <ng-container ngProjectAs=
"description">
438 <span i18n
>Otherwise the local search stays used by default
</span>
440 </my-peertube-checkbox>
444 </my-peertube-checkbox>
454 <div class=
"row mt-4"> <!-- federation grid -->
455 <div class=
"col-12 col-lg-4 col-xl-3">
456 <div i18n
class=
"inner-form-title">FEDERATION
</div>
457 <div i18n
class=
"inner-form-description">
458 Manage
<a class=
"link-orange" routerLink=
"/admin/follows">relations
</a> with other instances.
462 <div class=
"col-12 col-lg-8 col-xl-9">
464 <ng-container formGroupName=
"followers">
465 <ng-container formGroupName=
"instance">
467 <div class=
"form-group">
468 <my-peertube-checkbox
469 inputName=
"followersInstanceEnabled" formControlName=
"enabled"
470 i18n-labelText
labelText=
"Other instances can follow yours"
471 ></my-peertube-checkbox>
474 <div class=
"form-group">
475 <my-peertube-checkbox
476 inputName=
"followersInstanceManualApproval" formControlName=
"manualApproval"
477 i18n-labelText
labelText=
"Manually approve new instance followers"
478 ></my-peertube-checkbox>
483 <ng-container formGroupName=
"followings">
484 <ng-container formGroupName=
"instance">
486 <ng-container formGroupName=
"autoFollowBack">
487 <div class=
"form-group">
488 <my-peertube-checkbox
489 inputName=
"followingsInstanceAutoFollowBackEnabled" formControlName=
"enabled"
490 i18n-labelText
labelText=
"Automatically follow back instances"
492 <ng-container ngProjectAs=
"description">
493 <span i18n
>⚠️ This functionality requires a lot of attention and extra moderation.
</span>
495 </my-peertube-checkbox>
499 <ng-container formGroupName=
"autoFollowIndex">
500 <div class=
"form-group">
501 <my-peertube-checkbox
502 inputName=
"followingsInstanceAutoFollowIndexEnabled" formControlName=
"enabled"
503 i18n-labelText
labelText=
"Automatically follow instances of a public index"
505 <ng-container ngProjectAs=
"description">
506 <div i18n
>⚠️ This functionality requires a lot of attention and extra moderation.
</div>
509 See
<a class=
"link-orange" href=
"https://docs.joinpeertube.org/admin-following-instances?id=automatically-follow-other-instances" rel=
"noopener noreferrer" target=
"_blank">the documentation
</a> for more information about the expected URL
513 <ng-container ngProjectAs=
"extra">
514 <div [ngClass]=
"{ 'disabled-checkbox-extra': !isAutoFollowIndexEnabled() }">
515 <label i18n
for=
"followingsInstanceAutoFollowIndexUrl">Index URL
</label>
517 type=
"text" id=
"followingsInstanceAutoFollowIndexUrl" class=
"form-control"
518 formControlName=
"indexUrl" [ngClass]=
"{ 'input-error': formErrors['followings.instance.autoFollowIndex.indexUrl'] }"
520 <div *
ngIf=
"formErrors.followings.instance.autoFollowIndex.indexUrl" class=
"form-error">{{ formErrors.followings.instance.autoFollowIndex.indexUrl }}
</div>
523 </my-peertube-checkbox>
533 <div class=
"row mt-4"> <!-- administrators grid -->
534 <div class=
"col-12 col-lg-4 col-xl-3">
535 <div i18n
class=
"inner-form-title">ADMINISTRATORS
</div>
538 <div class=
"col-12 col-lg-8 col-xl-9">
540 <div class=
"form-group" formGroupName=
"admin">
541 <label i18n
for=
"adminEmail">Admin email
</label>
544 type=
"text" id=
"adminEmail" class=
"form-control"
545 formControlName=
"email" [ngClass]=
"{ 'input-error': formErrors['admin.email'] }"
548 <div *
ngIf=
"formErrors.admin.email" class=
"form-error">{{ formErrors.admin.email }}
</div>
551 <div class=
"form-group" formGroupName=
"contactForm">
552 <my-peertube-checkbox
553 inputName=
"enableContactForm" formControlName=
"enabled"
554 i18n-labelText
labelText=
"Enable contact form"
555 ></my-peertube-checkbox>
561 <div class=
"row mt-4"> <!-- Twitter grid -->
562 <div class=
"col-12 col-lg-4 col-xl-3">
563 <div i18n
class=
"inner-form-title">TWITTER
</div>
564 <div i18n
class=
"inner-form-description">
565 Provide the Twitter account representing your instance to improve link previews.
566 If you don't have a Twitter account, just leave the default value.
570 <div class=
"col-12 col-lg-8 col-xl-9">
572 <ng-container formGroupName=
"services">
573 <ng-container formGroupName=
"twitter">
575 <div class=
"form-group">
576 <label for=
"servicesTwitterUsername" i18n
>Your Twitter username
</label>
579 type=
"text" id=
"servicesTwitterUsername" class=
"form-control"
580 formControlName=
"username" [ngClass]=
"{ 'input-error': formErrors['services.twitter.username'] }"
583 <div *
ngIf=
"formErrors.services.twitter.username" class=
"form-error">{{ formErrors.services.twitter.username }}
</div>
586 <div class=
"form-group">
587 <my-peertube-checkbox inputName=
"servicesTwitterWhitelisted" formControlName=
"whitelisted">
588 <ng-template ptTemplate=
"label">
589 <ng-container i18n
>Instance allowed by Twitter
</ng-container>
592 <ng-template ptTemplate=
"help">
594 If your instance is explicitly allowed by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.
<br />
595 If the instance is not, we use an image link card that will redirect to your PeerTube instance.
<br /><br />
596 Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/w/blabla) on
597 <a class=
"link-orange" target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'
>https://cards-dev.twitter.com/validator
</a>
598 to see if you instance is allowed.
601 </my-peertube-checkbox>