From ccc00cb2aac1360921b957f3ecb3be7eb55dfa1b Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Fri, 23 Aug 2019 15:23:27 +0200 Subject: [PATCH] Add more attributes to about page --- .../about-instance.component.html | 53 ++++++- .../about-instance.component.scss | 19 ++- .../about-instance.component.ts | 27 +++- .../edit-custom-config.component.html | 135 ++++++++++++++---- .../edit-custom-config.component.scss | 9 ++ .../edit-custom-config.component.ts | 68 +++++++-- .../my-account-video-settings.component.html | 2 +- .../my-account-video-settings.component.ts | 47 +++--- .../src/app/+my-account/my-account.module.ts | 4 +- client/src/app/shared/shared.module.ts | 7 +- config/default.yaml | 47 ++++++ server/controllers/api/config.ts | 21 ++- server/initializers/config.ts | 10 ++ server/tests/api/check-params/config.ts | 10 ++ server/tests/api/server/config.ts | 30 ++++ shared/extra-utils/server/config.ts | 10 ++ shared/models/server/about.model.ts | 10 ++ shared/models/server/custom-config.model.ts | 10 ++ 18 files changed, 437 insertions(+), 82 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 @@
+
-
About {{ instanceName }} instance
+
About {{ instanceName }} instance
Contact administrator
@@ -12,16 +13,58 @@
This instance is dedicated to sensitive/NSFW content.
-
+
+ Administrators & sustainability +
+ +
+
Instance administrators
+ +
+
+ +
+
Maintenance lifetime
+ +

{{ maintenanceLifetime }}

+
+ +
+
Business model
+ +

{{ businessModel }}

+
+ +
+ Information +
+ +
Description
-
+
+
+ +
+ Moderation +
+ +
+
Moderation information
+ +
+
+ +
+
Code of conduct
+ +
-
+
Terms
-
+
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 @@ display: flex; justify-content: space-between; - & > div { + .title { font-size: 20px; - font-weight: bold; margin-bottom: 15px; + font-weight: $font-semibold; } - & > .contact-admin { + .contact-admin { @include peertube-button; @include orange-button; @@ -21,11 +21,20 @@ .section-title { font-weight: $font-semibold; - font-size: 20px; + font-size: 16px; margin-bottom: 5px; + display: flex; + align-items: center; +} + +.middle-title { + @include in-content-small-title; + + margin-top: 45px; + margin-bottom: 25px; } -.short-description, .description, .terms, .signup { +.block { margin-bottom: 30px; } 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 { @ViewChild('contactAdminModal', { static: true }) contactAdminModal: ContactAdminModalComponent shortDescription = '' - descriptionHTML = '' - termsHTML = '' + + html = { + description: '', + terms: '', + codeOfConduct: '', + moderationInformation: '', + administrator: '' + } + + maintenanceLifetime = '' + businessModel = '' + + languages: string[] = [] + categories: number[] = [] constructor ( private notifier: Notifier, @@ -43,8 +55,15 @@ export class AboutInstanceComponent implements OnInit { async res => { this.shortDescription = res.instance.shortDescription - this.descriptionHTML = await this.markdownService.textMarkdownToHTML(res.instance.description) - this.termsHTML = await this.markdownService.textMarkdownToHTML(res.instance.terms) + this.maintenanceLifetime = res.instance.maintenanceLifetime + this.businessModel = res.instance.businessModel + + for (const key of [ 'description', 'terms', 'codeOfConduct', 'moderationInformation', 'administrator' ]) { + this.html[key] = await this.markdownService.textMarkdownToHTML(res.instance[key]) + } + + this.languages = res.instance.languages + this.categories = res.instance.categories }, () => 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 @@ - + -
Instance
- + +
Instance
+
- - -
{{ formErrors.instance.terms }}
+ + +
+ +
+
+ + +
+ +
+
+ +
Moderation & NSFW
+
-
- -
- -
-
{{ formErrors.instance.defaultClientRoute }}
-
-
{{ formErrors.instance.defaultNSFWPolicy }}
+ +
+ + +
{{ formErrors.instance.terms }}
+
+ +
+ + +
{{ formErrors.instance.codeOfConduct }}
+
+ +
+ +
Who moderates the instance? What is the policy regarding NSFW videos? Political videos? etc
+ + +
{{ formErrors.instance.moderationInformation }}
+
+ +
You and your instance
+ +
+ +
A single person? A non profit? A company?
+ + +
{{ formErrors.instance.administrator }}
+
+ +
+ +
It's important to know for users who want to register on your instance
+ + +
{{ formErrors.instance.maintenanceLifetime }}
+
+ +
+ +
With you own funds? With users donations? Advertising?
+ + +
{{ formErrors.instance.businessModel }}
+
+ + + + + -
Theme
+
Theme & Default route
@@ -102,6 +176,19 @@ +
+ +
+ +
+
{{ formErrors.instance.defaultClientRoute }}
+
+
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 @@ @import '_variables'; @import '_mixins'; +.form-group { + margin-bottom: 25px; +} + input[type=text] { @include peertube-input-text(340px); display: block; @@ -44,3 +48,8 @@ textarea { height: 100px; } } + +.label-small-info { + font-style: italic; + margin-bottom: 10px; +} 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' import { CustomConfig } from '../../../../../../shared/models/server/custom-config.model' import { I18n } from '@ngx-translate/i18n-polyfill' import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' +import { SelectItem } from 'primeng/api' +import { forkJoin } from 'rxjs' +import { first } from 'rxjs/operators' @Component({ selector: 'my-edit-custom-config', @@ -18,6 +21,9 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { resolutions: { id: string, label: string }[] = [] transcodingThreadOptions: { label: string, value: number }[] = [] + languageItems: SelectItem[] = [] + categoryItems: SelectItem[] = [] + constructor ( protected formValidatorService: FormValidatorService, private customConfigValidatorsService: CustomConfigValidatorsService, @@ -88,10 +94,22 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { name: this.customConfigValidatorsService.INSTANCE_NAME, shortDescription: this.customConfigValidatorsService.INSTANCE_SHORT_DESCRIPTION, description: null, - terms: null, - defaultClientRoute: null, + isNSFW: false, defaultNSFWPolicy: null, + + terms: null, + codeOfConduct: null, + moderationInformation: null, + administrator: null, + maintenanceLifetime: null, + businessModel: null, + + categories: null, + languages: null, + + defaultClientRoute: null, + customizations: { javascript: null, css: null @@ -184,18 +202,27 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { this.buildForm(formGroupData) - this.configService.getCustomConfig() - .subscribe( - res => { - this.customConfig = res + forkJoin([ + this.configService.getCustomConfig(), + this.serverService.videoLanguagesLoaded.pipe(first()), // First so the observable completes + this.serverService.videoCategoriesLoaded.pipe(first()) + ]).subscribe( + ([ config ]) => { + this.customConfig = config - this.updateForm() - // Force form validation - this.forceCheck() - }, + const languages = this.serverService.getVideoLanguages() + this.languageItems = languages.map(l => ({ label: l.label, value: l.id })) - err => this.notifier.error(err.message) - ) + const categories = this.serverService.getVideoCategories() + this.categoryItems = categories.map(l => ({ label: l.label, value: l.id })) + + this.updateForm() + // Force form validation + this.forceCheck() + }, + + err => this.notifier.error(err.message) + ) } isTranscodingEnabled () { @@ -224,8 +251,23 @@ export class EditCustomConfigComponent extends FormReactive implements OnInit { ) } + getSelectedLanguageLabel () { + return this.i18n('{{\'{0} languages selected') + } + + getDefaultLanguageLabel () { + return this.i18n('No language') + } + + getSelectedCategoryLabel () { + return this.i18n('{{\'{0} categories selected') + } + + getDefaultCategoryLabel () { + return this.i18n('No category') + } + private updateForm () { this.form.patchValue(this.customConfig) } - } 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 @@
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' import { FormReactive, User, UserService } from '../../../shared' import { I18n } from '@ngx-translate/i18n-polyfill' import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service' -import { Subject } from 'rxjs' +import { forkJoin, Subject } from 'rxjs' import { SelectItem } from 'primeng/api' -import { switchMap } from 'rxjs/operators' +import { first } from 'rxjs/operators' @Component({ selector: 'my-account-video-settings', @@ -39,30 +39,31 @@ export class MyAccountVideoSettingsComponent extends FormReactive implements OnI videoLanguages: null }) - this.serverService.videoLanguagesLoaded - .pipe(switchMap(() => this.userInformationLoaded)) - .subscribe(() => { - const languages = this.serverService.getVideoLanguages() - - this.languageItems = [ { label: this.i18n('Unknown language'), value: '_unknown' } ] - this.languageItems = this.languageItems - .concat(languages.map(l => ({ label: l.label, value: l.id }))) - - const videoLanguages = this.user.videoLanguages - ? this.user.videoLanguages - : this.languageItems.map(l => l.value) - - this.form.patchValue({ - nsfwPolicy: this.user.nsfwPolicy, - webTorrentEnabled: this.user.webTorrentEnabled, - autoPlayVideo: this.user.autoPlayVideo === true, - videoLanguages - }) - }) + forkJoin([ + this.serverService.videoLanguagesLoaded.pipe(first()), + this.userInformationLoaded.pipe(first()) + ]).subscribe(() => { + const languages = this.serverService.getVideoLanguages() + + this.languageItems = [ { label: this.i18n('Unknown language'), value: '_unknown' } ] + this.languageItems = this.languageItems + .concat(languages.map(l => ({ label: l.label, value: l.id }))) + + const videoLanguages = this.user.videoLanguages + ? this.user.videoLanguages + : this.languageItems.map(l => l.value) + + this.form.patchValue({ + nsfwPolicy: this.user.nsfwPolicy, + webTorrentEnabled: this.user.webTorrentEnabled, + autoPlayVideo: this.user.autoPlayVideo === true, + videoLanguages + }) + }) } updateDetails () { - const nsfwPolicy = this.form.value['nsfwPolicy'] + const nsfwPolicy = this.form.value[ 'nsfwPolicy' ] const webTorrentEnabled = this.form.value['webTorrentEnabled'] const autoPlayVideo = this.form.value['autoPlayVideo'] 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 { } from '@app/+my-account/my-account-video-playlists/my-account-video-playlist-elements.component' import { DragDropModule } from '@angular/cdk/drag-drop' import { MyAccountChangeEmailComponent } from '@app/+my-account/my-account-settings/my-account-change-email' -import { MultiSelectModule } from 'primeng/multiselect' import { MyAccountInterfaceSettingsComponent } from '@app/+my-account/my-account-settings/my-account-interface' @NgModule({ @@ -48,8 +47,7 @@ import { MyAccountInterfaceSettingsComponent } from '@app/+my-account/my-account SharedModule, TableModule, InputSwitchModule, - DragDropModule, - MultiSelectModule + DragDropModule ], 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' import { MarkdownTextareaComponent } from '@app/shared/forms/markdown-textarea.component' import { HelpComponent } from '@app/shared/misc/help.component' import { InfiniteScrollerDirective } from '@app/shared/video/infinite-scroller.directive' - import { BytesPipe, KeysPipe, NgPipesModule } from 'ngx-pipes' import { SharedModule as PrimeSharedModule } from 'primeng/components/common/shared' - import { AUTH_INTERCEPTOR_PROVIDER } from './auth' import { ButtonComponent } from './buttons/button.component' import { DeleteButtonComponent } from './buttons/delete-button.component' @@ -93,6 +91,7 @@ import { VideoDownloadComponent } from '@app/shared/video/modals/video-download. import { VideoReportComponent } from '@app/shared/video/modals/video-report.component' import { ClipboardModule } from 'ngx-clipboard' import { FollowService } from '@app/shared/instance/follow.service' +import { MultiSelectModule } from 'primeng/multiselect' @NgModule({ imports: [ @@ -113,7 +112,8 @@ import { FollowService } from '@app/shared/instance/follow.service' PrimeSharedModule, InputMaskModule, - NgPipesModule + NgPipesModule, + MultiSelectModule ], declarations: [ @@ -186,6 +186,7 @@ import { FollowService } from '@app/shared/instance/follow.service' InputMaskModule, BytesPipe, KeysPipe, + MultiSelectModule, LoaderComponent, SmallLoaderComponent, diff --git a/config/default.yaml b/config/default.yaml index 5a935fede..f84ecfcf9 100644 --- a/config/default.yaml +++ b/config/default.yaml @@ -238,7 +238,53 @@ instance: short_description: 'PeerTube, a federated (ActivityPub) video streaming platform using P2P (BitTorrent) directly in the web browser with WebTorrent and Angular.' description: 'Welcome to this PeerTube instance!' # Support markdown terms: 'No terms for now.' # Support markdown + code_of_conduct: '' # Supports markdown + + # Who moderates the instance? What is the policy regarding NSFW videos? Political videos? etc + moderation_information: '' # Supports markdown + + # Who is behind the instance? A single person? A non profit? + administrator: '' + + # How long do you plan to maintain this instance? + maintenance_lifetime: '' + + # How will you pay the PeerTube instance server? With you own funds? With users donations? Advertising? + business_model: '' + + # What are the main languages of your instance? To interact with your users for example + # Uncomment or add the languages you want + # List of supported languages: https://peertube.cpy.re/api/v1/videos/languages + languages: +# - en +# - es +# - fr + + # You can specify the main categories of your instance (dedicated to music, gaming or politics etc) + # Uncomment or add the category ids you want + # List of supported categories: https://peertube.cpy.re/api/v1/videos/categories + categories: +# - 1 # Music +# - 2 # Films +# - 3 # Vehicles +# - 4 # Art +# - 5 # Sports +# - 6 # Travels +# - 7 # Gaming +# - 8 # People +# - 9 # Comedy +# - 10 # Entertainment +# - 11 # News & Politics +# - 12 # How To +# - 13 # Education +# - 14 # Activism +# - 15 # Science & Technology +# - 16 # Animals +# - 17 # Kids +# - 18 # Food + default_client_route: '/videos/trending' + # Whether or not the instance is dedicated to NSFW content # Enabling it will allow other administrators to know that you are mainly federating sensitive content # Moreover, the NSFW checkbox on video upload will be automatically checked by default @@ -246,6 +292,7 @@ instance: # By default, "do_not_list" or "blur" or "display" NSFW videos # Could be overridden per user with a setting default_nsfw_policy: 'do_not_list' + customizations: javascript: '' # Directly your JavaScript code (without