Add about information in registration page

pull/2131/head
Chocobozzz 2019-08-27 17:09:43 +02:00 committed by Chocobozzz
parent 4402b54dce
commit 421d935d25
22 changed files with 466 additions and 171 deletions

View File

@ -6,7 +6,6 @@ import { InstanceService } from '@app/shared/instance/instance.service'
import { MarkdownService } from '@app/shared/renderer'
import { forkJoin } from 'rxjs'
import { first } from 'rxjs/operators'
import { peertubeTranslate } from '@shared/models'
@Component({
selector: 'my-about-instance',
@ -59,32 +58,16 @@ export class AboutInstanceComponent implements OnInit {
this.serverService.videoLanguagesLoaded.pipe(first()),
this.serverService.videoCategoriesLoaded.pipe(first())
]).subscribe(
async ([ res, translations ]) => {
this.shortDescription = res.instance.shortDescription
async ([ about, translations ]) => {
this.shortDescription = about.instance.shortDescription
this.maintenanceLifetime = res.instance.maintenanceLifetime
this.businessModel = res.instance.businessModel
this.maintenanceLifetime = about.instance.maintenanceLifetime
this.businessModel = about.instance.businessModel
for (const key of [ 'description', 'terms', 'codeOfConduct', 'moderationInformation', 'administrator' ]) {
this.html[ key ] = await this.markdownService.textMarkdownToHTML(res.instance[ key ])
}
this.html = await this.instanceService.buildHtml(about)
const languagesArray = this.serverService.getVideoLanguages()
const categoriesArray = this.serverService.getVideoCategories()
this.languages = res.instance.languages
.map(l => {
const languageObj = languagesArray.find(la => la.id === l)
return peertubeTranslate(languageObj.label, translations)
})
this.categories = res.instance.categories
.map(c => {
const categoryObj = categoriesArray.find(ca => ca.id === c)
return peertubeTranslate(categoryObj.label, translations)
})
this.languages = this.instanceService.buildTranslatedLanguages(about, translations)
this.categories = this.instanceService.buildTranslatedCategories(about, translations)
},
() => this.notifier.error(this.i18n('Cannot get about information from server'))

View File

@ -63,20 +63,30 @@
<div i18n class="inner-form-title">Moderation & NSFW</div>
<div class="form-group">
<my-peertube-checkbox
inputName="instanceIsNSFW" formControlName="isNSFW"
i18n-labelText labelText="This instance is dedicated to sensitive or NSFW content"
i18n-helpHtml helpHtml="Enabling it will allow other administrators to know that you are mainly federating sensitive content.<br /><br />
Moreover, the NSFW checkbox on video upload will be automatically checked by default."
></my-peertube-checkbox>
<my-peertube-checkbox inputName="instanceIsNSFW" formControlName="isNSFW">
<ng-template ptTemplate="label">
<ng-container i18n>This instance is dedicated to sensitive or NSFW content</ng-container>
</ng-template>
<ng-template ptTemplate="help">
<ng-container i18n>
Enabling it will allow other administrators to know that you are mainly federating sensitive content.<br /><br />
Moreover, the NSFW checkbox on video upload will be automatically checked by default.
</ng-container>
</ng-template>
</my-peertube-checkbox>
</div>
<div class="form-group">
<label i18n for="instanceDefaultNSFWPolicy">Policy on videos containing sensitive content</label>
<my-help
helpType="custom" i18n-customHtml
customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video."
></my-help>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>
With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video.
</ng-container>
</ng-template>
</my-help>
<div class="peertube-select-container">
<select id="instanceDefaultNSFWPolicy" formControlName="defaultNSFWPolicy">
@ -374,10 +384,13 @@
<div class="form-group">
<label i18n for="signupLimit">Your Twitter username</label>
<my-help
helpType="custom" i18n-customHtml
customHtml="Indicates the Twitter account for the website or platform on which the content was published."
></my-help>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>Indicates the Twitter account for the website or platform on which the content was published.</ng-container>
</ng-template>
</my-help>
<input
type="text" id="servicesTwitterUsername"
formControlName="username" [ngClass]="{ 'input-error': formErrors['services.twitter.username'] }"
@ -386,13 +399,21 @@
</div>
<div class="form-group">
<my-peertube-checkbox
inputName="servicesTwitterWhitelisted" formControlName="whitelisted"
i18n-labelText labelText="Instance whitelisted by Twitter"
i18n-helpHtml helpHtml="If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br />
If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br />
Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/videos/watch/blabla) on <a target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a> to see if you instance is whitelisted."
></my-peertube-checkbox>
<my-peertube-checkbox inputName="servicesTwitterWhitelisted" formControlName="whitelisted">
<ng-template ptTemplate="label">
<ng-container i18n>Instance whitelisted by Twitter</ng-container>
</ng-template>
<ng-template ptTemplate="help">
<ng-container i18n>
If your instance is whitelisted by Twitter, a video player will be embedded in the Twitter feed on PeerTube video share.<br />
If the instance is not whitelisted, we use an image link card that will redirect on your PeerTube instance.<br /><br />
Check this checkbox, save the configuration and test with a video URL of your instance (https://example.com/videos/watch/blabla) on
<a target='_blank' rel='noopener noreferrer' href='https://cards-dev.twitter.com/validator'>https://cards-dev.twitter.com/validator</a>
to see if you instance is whitelisted.
</ng-container>
</ng-template>
</my-peertube-checkbox>
</div>
</ng-container>
@ -408,11 +429,15 @@
<ng-container formGroupName="transcoding">
<div class="form-group">
<my-peertube-checkbox
inputName="transcodingEnabled" formControlName="enabled"
i18n-labelText labelText="Transcoding enabled"
i18n-helpHtml helpHtml="If you disable transcoding, many videos from your users will not work!"
></my-peertube-checkbox>
<my-peertube-checkbox inputName="transcodingEnabled" formControlName="enabled">
<ng-template ptTemplate="label">
<ng-container i18n>Transcoding enabled</ng-container>
</ng-template>
<ng-template ptTemplate="help">
<ng-container i18n>If you disable transcoding, many videos from your users will not work!</ng-container>
</ng-template>
</my-peertube-checkbox>
</div>
<ng-container *ngIf="isTranscodingEnabled()">
@ -421,16 +446,22 @@
<my-peertube-checkbox
inputName="transcodingAllowAdditionalExtensions" formControlName="allowAdditionalExtensions"
i18n-labelText labelText="Allow additional extensions"
i18n-helpHtml helpHtml="Allow your users to upload .mkv, .mov, .avi, .flv videos"
></my-peertube-checkbox>
>
<ng-template ptTemplate="help">
<ng-container i18n>Allow your users to upload .mkv, .mov, .avi, .flv videos</ng-container>
</ng-template>
</my-peertube-checkbox>
</div>
<div class="form-group">
<my-peertube-checkbox
inputName="transcodingAllowAudioFiles" formControlName="allowAudioFiles"
i18n-labelText labelText="Allow audio files upload"
i18n-helpHtml helpHtml="Allow your users to upload audio files that will be merged with the preview file on upload"
></my-peertube-checkbox>
>
<ng-template ptTemplate="help">
<ng-container i18n>Allow your users to upload audio files that will be merged with the preview file on upload</ng-container>
</ng-template>
</my-peertube-checkbox>
</div>
<div class="form-group">
@ -460,10 +491,11 @@
<div i18n class="inner-form-title">
Cache
<my-help
helpType="custom" i18n-customHtml
customHtml="Some files are not federated (previews, captions). We fetch them directly from the origin instance and cache them."
></my-help>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>Some files are not federated (previews, captions). We fetch them directly from the origin instance and cache them.</ng-container>
</ng-template>
</my-help>
</div>
<ng-container formGroupName="cache">
@ -492,38 +524,45 @@
<ng-container formGroupName="customizations">
<div class="form-group">
<label i18n for="customizationJavascript">JavaScript</label>
<my-help
helpType="custom" i18n-customHtml
customHtml="Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>"
></my-help>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>
Write directly JavaScript code.<br />Example: <pre>console.log('my instance is amazing');</pre>
</ng-container>
</ng-template>
</my-help>
<textarea
id="customizationJavascript" formControlName="javascript"
[ngClass]="{ 'input-error': formErrors['instance.customizations.javascript'] }"
></textarea>
<div *ngIf="formErrors.instance.customizations.javascript" class="form-error">{{ formErrors.instance.customizations.javascript }}</div>
</div>
<div class="form-group">
<label for="customizationCSS">CSS</label>
<my-help
helpType="custom"
i18n-customHtml
customHtml="
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>
Write directly CSS code. Example:<br /><br />
<pre>
#custom-css {{ '{' }}
color: red;
{{ '}' }}
</pre>
<pre>
#custom-css {{ '{' }}
color: red;
{{ '}' }}
</pre>
Prepend with <em>#custom-css</em> to override styles. Example:<br /><br />
<pre>
#custom-css .logged-in-email {{ '{' }}
color: red;
{{ '}' }}
</pre>
"
></my-help>
<pre>
#custom-css .logged-in-email {{ '{' }}
color: red;
{{ '}' }}
</pre>
</ng-container>
</ng-template>
</my-help>
<textarea
id="customizationCSS" formControlName="css"
[ngClass]="{ 'input-error': formErrors['instance.customizations.css'] }"

View File

@ -1,10 +1,13 @@
<form role="form" (ngSubmit)="updateDetails()" [formGroup]="form">
<div class="form-group">
<label i18n for="nsfwPolicy">Default policy on videos containing sensitive content</label>
<my-help
helpType="custom" i18n-customHtml
customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video."
></my-help>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>
With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video.
</ng-container>
</ng-template>
</my-help>
<div class="peertube-select-container">
<select id="nsfwPolicy" formControlName="nsfwPolicy">
@ -17,9 +20,11 @@
<div class="form-group">
<label i18n for="videoLanguages">Only display videos in the following languages</label>
<my-help i18n-customHtml
customHtml="In Recently added, Trending, Local and Search pages"
></my-help>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>In Recently added, Trending, Local and Search pages</ng-container>
</ng-template>
</my-help>
<div>
<p-multiSelect

View File

@ -60,11 +60,16 @@
</div>
<div class="form-group form-group-terms">
<my-peertube-checkbox
inputName="terms" formControlName="terms"
i18n-labelHtml
labelHtml="I am at least 16 years old and agree to the <a href='/about/instance#terms-section' target='_blank'rel='noopener noreferrer'>Terms</a> of this instance"
></my-peertube-checkbox>
<my-peertube-checkbox inputName="terms" formControlName="terms">
<ng-template ptTemplate="label">
<ng-container i18n>
I am at least 16 years old and agree
to the <a (click)="onTermsClick($event)" href='#'>Terms</a>
<ng-container *ngIf="hasCodeOfConduct"> and to the <a (click)="onCodeOfConductClick($event)" href='#'>Code of Conduct</a></ng-container>
of this instance
</ng-container>
</ng-template>
</my-peertube-checkbox>
<div *ngIf="formErrors.terms" class="form-error">
{{ formErrors.terms }}

View File

@ -1,4 +1,4 @@
import { Component, EventEmitter, OnInit, Output } from '@angular/core'
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
import { AuthService } from '@app/core'
import { FormReactive, UserService, UserValidatorsService } from '@app/shared'
import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
@ -12,7 +12,11 @@ import { concat, of } from 'rxjs'
styleUrls: [ './register.component.scss' ]
})
export class RegisterStepUserComponent extends FormReactive implements OnInit {
@Input() hasCodeOfConduct = false
@Output() formBuilt = new EventEmitter<FormGroup>()
@Output() termsClick = new EventEmitter<void>()
@Output() codeOfConductClick = new EventEmitter<void>()
constructor (
protected formValidatorService: FormValidatorService,
@ -45,6 +49,16 @@ export class RegisterStepUserComponent extends FormReactive implements OnInit {
.subscribe(([ oldValue, newValue ]) => this.onDisplayNameChange(oldValue, newValue))
}
onTermsClick (event: Event) {
event.preventDefault()
this.termsClick.emit()
}
onCodeOfConductClick (event: Event) {
event.preventDefault()
this.codeOfConductClick.emit()
}
private onDisplayNameChange (oldDisplayName: string, newDisplayName: string) {
const username = this.form.value['username'] || ''

View File

@ -7,11 +7,15 @@
<my-signup-success *ngIf="signupDone" [message]="success"></my-signup-success>
<div *ngIf="info" class="alert alert-info">{{ info }}</div>
<div class="wrapper" *ngIf="!signupDone">
<div>
<div class="wrapper" [hidden]="signupDone">
<div class="register-form">
<my-custom-stepper linear *ngIf="!signupDone">
<cdk-step [stepControl]="formStepUser" i18n-label label="User information">
<my-register-step-user (formBuilt)="onUserFormBuilt($event)"></my-register-step-user>
<my-register-step-user
[hasCodeOfConduct]="!!aboutHtml.codeOfConduct"
(formBuilt)="onUserFormBuilt($event)" (termsClick)="onTermsClick()" (codeOfConductClick)="onCodeOfConductClick()"
>
</my-register-step-user>
<button i18n cdkStepperNext [disabled]="!formStepUser || !formStepUser.valid">Next</button>
</cdk-step>
@ -38,9 +42,56 @@
</my-custom-stepper>
</div>
<div>
<label i18n>Features found on this instance</label>
<my-instance-features-table></my-instance-features-table>
<div class="instance-information">
<ngb-accordion [closeOthers]="true" #accordion="ngbAccordion">
<ngb-panel id="instance-features" i18n-title title="Features found on this instance">
<ng-template ngbPanelContent>
<my-instance-features-table></my-instance-features-table>
</ng-template>
</ngb-panel>
<ng-container *ngIf="about">
<ngb-panel
*ngIf="aboutHtml.administrator || about.instance.maintenanceLifetime || about.instance.businessModel"
id="admin-sustainability" i18n-title title="Administrators & Sustainability"
>
<ng-template ngbPanelContent>
<div class="block">
<strong i18n>Who are we?</strong>
<div [innerHTML]="aboutHtml.administrator"></div>
</div>
<div class="block">
<strong i18n>How long do we plan to maintain this instance?</strong>
<div [innerHTML]="about.instance.maintenanceLifetime"></div>
</div>
<div class="block">
<strong i18n>How will we pay this instance?</strong>
<div [innerHTML]="about.instance.businessModel"></div>
</div>
</ng-template>
</ngb-panel>
<ngb-panel *ngIf="aboutHtml.moderationInformation" id="moderation-information" i18n-title title="Moderation information">
<ng-template ngbPanelContent>
<div class="block" [innerHTML]="aboutHtml.moderationInformation"></div>
</ng-template>
</ngb-panel>
<ngb-panel *ngIf="aboutHtml.codeOfConduct" id="code-of-conduct" i18n-title title="Code of conduct">
<ng-template ngbPanelContent>
<div class="block" [innerHTML]="aboutHtml.codeOfConduct"></div>
</ng-template>
</ngb-panel>
<ngb-panel *ngIf="aboutHtml.terms" id="terms" i18n-title title="Terms">
<ng-template ngbPanelContent>
<div class="block" [innerHTML]="aboutHtml.terms"></div>
</ng-template>
</ngb-panel>
</ng-container>
</ngb-accordion>
</div>
</div>

View File

@ -1,5 +1,9 @@
@import '_variables';
@import '_mixins';
@import "./_bootstrap-variables";
@import '~bootstrap/scss/functions';
@import '~bootstrap/scss/variables';
.alert {
font-size: 15px;
@ -13,7 +17,32 @@
& > div {
margin-bottom: 40px;
width: 450px;
&.register-form {
width: 450px;
}
&.instance-information {
width: 600px;
margin-bottom: 40px;
.block {
font-size: 15px;
margin-bottom: 15px;
padding: 0 $btn-padding-x;
}
@media screen and (max-width: 1500px) {
width: 450px;
}
ngb-accordion ::ng-deep {
.btn {
font-weight: $font-semibold !important;
color: var(--mainForegroundColor) !important;
}
}
}
@media screen and (max-width: 500px) {
width: auto;
@ -21,12 +50,6 @@
}
}
my-instance-features-table {
display: block;
margin-bottom: 40px;
}
.form-group-terms {
margin: 30px 0;
}

View File

@ -1,21 +1,35 @@
import { Component } from '@angular/core'
import { Component, OnInit, ViewChild } from '@angular/core'
import { AuthService, Notifier, RedirectService, ServerService } from '@app/core'
import { UserService, UserValidatorsService } from '@app/shared'
import { I18n } from '@ngx-translate/i18n-polyfill'
import { UserRegister } from '@shared/models/users/user-register.model'
import { FormGroup } from '@angular/forms'
import { About } from '@shared/models/server'
import { InstanceService } from '@app/shared/instance/instance.service'
import { NgbAccordion } from '@ng-bootstrap/ng-bootstrap'
@Component({
selector: 'my-register',
templateUrl: './register.component.html',
styleUrls: [ './register.component.scss' ]
})
export class RegisterComponent {
export class RegisterComponent implements OnInit {
@ViewChild('accordion', { static: true }) accordion: NgbAccordion
info: string = null
error: string = null
success: string = null
signupDone = false
about: About
aboutHtml = {
description: '',
terms: '',
codeOfConduct: '',
moderationInformation: '',
administrator: ''
}
formStepUser: FormGroup
formStepChannel: FormGroup
@ -26,6 +40,7 @@ export class RegisterComponent {
private userService: UserService,
private serverService: ServerService,
private redirectService: RedirectService,
private instanceService: InstanceService,
private i18n: I18n
) {
}
@ -34,6 +49,19 @@ export class RegisterComponent {
return this.serverService.getConfig().signup.requiresEmailVerification
}
ngOnInit (): void {
this.instanceService.getAbout()
.subscribe(
async about => {
this.about = about
this.aboutHtml = await this.instanceService.buildHtml(about)
},
err => this.notifier.error(err.message)
)
}
hasSameChannelAndAccountNames () {
return this.getUsername() === this.getChannelName()
}
@ -58,6 +86,14 @@ export class RegisterComponent {
this.formStepChannel = form
}
onTermsClick () {
if (this.accordion) this.accordion.toggle('terms')
}
onCodeOfConductClick () {
if (this.accordion) this.accordion.toggle('code-of-conduct')
}
signup () {
this.error = null

View File

@ -7,13 +7,15 @@ import { RegisterStepChannelComponent } from './register-step-channel.component'
import { RegisterStepUserComponent } from './register-step-user.component'
import { CustomStepperComponent } from './custom-stepper.component'
import { SignupSharedModule } from '@app/+signup/shared/signup-shared.module'
import { NgbAccordionModule } from '@ng-bootstrap/ng-bootstrap'
@NgModule({
imports: [
RegisterRoutingModule,
SharedModule,
CdkStepperModule,
SignupSharedModule
SignupSharedModule,
NgbAccordionModule
],
declarations: [

View File

@ -23,10 +23,11 @@
or create an account on another instance
</a>
<my-help
*ngIf="signupAllowed === false" helpType="custom" i18n-customHtml
customHtml="User registration is not allowed on this instance, but you can register on many others!"
></my-help>
<my-help *ngIf="signupAllowed === false">
<ng-template ptTemplate="customHtml">
<ng-container i18n>User registration is not allowed on this instance, but you can register on many others!</ng-container>
</ng-template>
</my-help>
</div>
<div *ngIf="formErrors.username" class="form-error">

View File

@ -3,8 +3,8 @@ import { Directive, Input, TemplateRef } from '@angular/core'
@Directive({
selector: '[ptTemplate]'
})
export class PeerTubeTemplateDirective {
@Input('ptTemplate') name: string
export class PeerTubeTemplateDirective <T extends string> {
@Input('ptTemplate') name: T
constructor (public template: TemplateRef<any>) {
// empty

View File

@ -3,8 +3,15 @@
<input type="checkbox" [(ngModel)]="checked" (ngModelChange)="onModelChange()" [id]="inputName" [disabled]="disabled" />
<span role="checkbox" [attr.aria-checked]="checked"></span>
<span *ngIf="labelText">{{ labelText }}</span>
<span *ngIf="labelHtml" [innerHTML]="labelHtml"></span>
<span *ngIf="labelTemplate">
<ng-container *ngTemplateOutlet="labelTemplate"></ng-container>
</span>
</label>
<my-help *ngIf="helpHtml" [tooltipPlacement]="helpPlacement" helpType="custom" i18n-customHtml [customHtml]="helpHtml"></my-help>
<my-help *ngIf="helpTemplate" [tooltipPlacement]="helpPlacement" helpType="custom">
<ng-template ptTemplate="customHtml">
<ng-template *ngTemplateOutlet="helpTemplate"></ng-template>
</ng-template>
</my-help>
</div>

View File

@ -1,5 +1,6 @@
import { ChangeDetectorRef, Component, forwardRef, Input, OnChanges, SimpleChanges } from '@angular/core'
import { AfterContentInit, ChangeDetectorRef, Component, ContentChildren, forwardRef, Input, QueryList, TemplateRef } from '@angular/core'
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
import { PeerTubeTemplateDirective } from '@app/shared/angular/peertube-template.directive'
@Component({
selector: 'my-peertube-checkbox',
@ -13,20 +14,35 @@ import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms'
}
]
})
export class PeertubeCheckboxComponent implements ControlValueAccessor {
export class PeertubeCheckboxComponent implements ControlValueAccessor, AfterContentInit {
@Input() checked = false
@Input() inputName: string
@Input() labelText: string
@Input() labelHtml: string
@Input() helpHtml: string
@Input() helpPlacement = 'top'
@Input() disabled = false
@ContentChildren(PeerTubeTemplateDirective) templates: QueryList<PeerTubeTemplateDirective<'label' | 'help'>>
// FIXME: https://github.com/angular/angular/issues/10816#issuecomment-307567836
@Input() onPushWorkaround = false
labelTemplate: TemplateRef<any>
helpTemplate: TemplateRef<any>
constructor (private cdr: ChangeDetectorRef) { }
ngAfterContentInit () {
{
const t = this.templates.find(t => t.name === 'label')
if (t) this.labelTemplate = t.template
}
{
const t = this.templates.find(t => t.name === 'help')
if (t) this.helpTemplate = t.template
}
}
propagateChange = (_: any) => { /* empty */ }
writeValue (checked: boolean) {

View File

@ -43,7 +43,11 @@
<ng-container *ngIf="initialUserVideoQuota !== -1">
{{ initialUserVideoQuota | bytes: 0 }} <ng-container *ngIf="dailyUserVideoQuota !== -1">({{ dailyUserVideoQuota | bytes: 0 }} per day)</ng-container>
<my-help tooltipPlacement="auto" helpType="custom" [customHtml]="quotaHelpIndication"></my-help>
<my-help tooltipPlacement="auto" helpType="custom">
<ng-template ptTemplate="customHtml">
<div [innerHTML]="quotaHelpIndication"></div>
</ng-template>
</my-help>
</ng-container>
<ng-container i18n *ngIf="initialUserVideoQuota === -1">

View File

@ -4,6 +4,9 @@ import { Injectable } from '@angular/core'
import { environment } from '../../../environments/environment'
import { RestExtractor, RestService } from '../rest'
import { About } from '../../../../../shared/models/server'
import { MarkdownService } from '@app/shared/renderer'
import { peertubeTranslate } from '@shared/models'
import { ServerService } from '@app/core'
@Injectable()
export class InstanceService {
@ -13,7 +16,9 @@ export class InstanceService {
constructor (
private authHttp: HttpClient,
private restService: RestService,
private restExtractor: RestExtractor
private restExtractor: RestExtractor,
private markdownService: MarkdownService,
private serverService: ServerService
) {
}
@ -34,4 +39,42 @@ export class InstanceService {
.pipe(catchError(res => this.restExtractor.handleError(res)))
}
async buildHtml (about: About) {
const html = {
description: '',
terms: '',
codeOfConduct: '',
moderationInformation: '',
administrator: ''
}
for (const key of [ 'description', 'terms', 'codeOfConduct', 'moderationInformation', 'administrator' ]) {
html[ key ] = await this.markdownService.textMarkdownToHTML(about.instance[ key ])
}
return html
}
buildTranslatedLanguages (about: About, translations: any) {
const languagesArray = this.serverService.getVideoLanguages()
return about.instance.languages
.map(l => {
const languageObj = languagesArray.find(la => la.id === l)
return peertubeTranslate(languageObj.label, translations)
})
}
buildTranslatedCategories (about: About, translations: any) {
const categoriesArray = this.serverService.getVideoCategories()
return about.instance.categories
.map(c => {
const categoryObj = categoriesArray.find(ca => ca.id === c)
return peertubeTranslate(categoryObj.label, translations)
})
}
}

View File

@ -1,15 +1,25 @@
<ng-template #tooltipTemplate>
<ng-template [ngIf]="preHtml">
<p [innerHTML]="preHtml"></p>
<br />
</ng-template>
<p *ngIf="preHtmlTemplate">
<ng-template *ngTemplateOutlet="preHtmlTemplate"></ng-template>
</p>
<p [innerHTML]="mainHtml"></p>
<ng-container *ngIf="preHtmlTemplate && (customHtmlTemplate || mainHtml || postHtmlTemplate)">
<br /><br />
</ng-container>
<ng-template [ngIf]="postHtml">
<br />
<p [innerHTML]="postHtml"></p>
</ng-template>
<p *ngIf="customHtmlTemplate">
<ng-template *ngTemplateOutlet="customHtmlTemplate"></ng-template>
</p>
<p *ngIf="mainHtml" [innerHTML]="mainHtml"></p>
<ng-container *ngIf="(customHtmlTemplate || mainHtml) && postHtmlTemplate">
<br /><br />
</ng-container>
<p *ngIf="postHtmlTemplate">
<ng-template *ngTemplateOutlet="postHtmlTemplate"></ng-template>
</p>
</ng-template>
<span

View File

@ -1,6 +1,7 @@
import { Component, Input, OnChanges, OnInit } from '@angular/core'
import { AfterContentInit, Component, ContentChildren, Input, OnChanges, OnInit, QueryList, TemplateRef } from '@angular/core'
import { I18n } from '@ngx-translate/i18n-polyfill'
import { MarkdownService } from '@app/shared/renderer'
import { PeerTubeTemplateDirective } from '@app/shared/angular/peertube-template.directive'
@Component({
selector: 'my-help',
@ -8,22 +9,42 @@ import { MarkdownService } from '@app/shared/renderer'
templateUrl: './help.component.html'
})
export class HelpComponent implements OnInit, OnChanges {
@Input() preHtml = ''
@Input() postHtml = ''
@Input() customHtml = ''
export class HelpComponent implements OnInit, OnChanges, AfterContentInit {
@Input() helpType: 'custom' | 'markdownText' | 'markdownEnhanced' = 'custom'
@Input() tooltipPlacement = 'right'
@ContentChildren(PeerTubeTemplateDirective) templates: QueryList<PeerTubeTemplateDirective<'preHtml' | 'customHtml' | 'postHtml'>>
isPopoverOpened = false
mainHtml = ''
preHtmlTemplate: TemplateRef<any>
customHtmlTemplate: TemplateRef<any>
postHtmlTemplate: TemplateRef<any>
constructor (private i18n: I18n) { }
ngOnInit () {
this.init()
}
ngAfterContentInit () {
{
const t = this.templates.find(t => t.name === 'preHtml')
if (t) this.preHtmlTemplate = t.template
}
{
const t = this.templates.find(t => t.name === 'customHtml')
if (t) this.customHtmlTemplate = t.template
}
{
const t = this.templates.find(t => t.name === 'postHtml')
if (t) this.postHtmlTemplate = t.template
}
}
ngOnChanges () {
this.init()
}
@ -37,11 +58,6 @@ export class HelpComponent implements OnInit, OnChanges {
}
private init () {
if (this.helpType === 'custom') {
this.mainHtml = this.customHtml
return
}
if (this.helpType === 'markdownText') {
this.mainHtml = this.formatMarkdownSupport(MarkdownService.TEXT_RULES)
return

View File

@ -12,13 +12,21 @@
<span *ngIf="interact">Remote interact</span>
</button>
<my-help *ngIf="!interact && showHelp"
helpType="custom"
i18n-customHtml customHtml="You can subscribe to the channel via any ActivityPub-capable fediverse instance. For instance with Mastodon or Pleroma you can type the channel URL in the search box and subscribe there.">
<my-help *ngIf="!interact && showHelp">
<ng-template ptTemplate="customHtml">
<ng-container i18n>
You can subscribe to the channel via any ActivityPub-capable fediverse instance.<br /><br />
For instance with Mastodon or Pleroma you can type the channel URL in the search box and subscribe there.
</ng-container>
</ng-template>
</my-help>
<my-help *ngIf="showHelp && interact"
helpType="custom"
i18n-customHtml customHtml="You can interact with this via any ActivityPub-capable fediverse instance. For instance with Mastodon or Pleroma you can type the current URL in the search box and interact with it there.">
<my-help *ngIf="showHelp && interact">
<ng-template ptTemplate="customHtml">
<ng-container i18n>
You can interact with this via any ActivityPub-capable fediverse instance.<br /><br />
For instance with Mastodon or Pleroma you can type the current URL in the search box and interact with it there.
</ng-container>
</ng-template>
</my-help>
</form>
</form>

View File

@ -35,7 +35,7 @@ export class VideosSelectionComponent extends AbstractVideoList implements OnIni
@Input() titlePage: string
@Input() miniatureDisplayOptions: MiniatureDisplayOptions
@Input() getVideosObservableFunction: (page: number, sort?: VideoSortField) => Observable<ResultList<Video>>
@ContentChildren(PeerTubeTemplateDirective) templates: QueryList<PeerTubeTemplateDirective>
@ContentChildren(PeerTubeTemplateDirective) templates: QueryList<PeerTubeTemplateDirective<'rowButtons' | 'globalButtons'>>
@Output() selectionChange = new EventEmitter<SelectionType>()
@Output() videosModelChange = new EventEmitter<Video[]>()

View File

@ -15,7 +15,16 @@
<div class="form-group">
<label i18n class="label-tags">Tags</label>
<my-help i18n-preHtml preHtml="Tags could be used to suggest relevant recommendations.</br>Press Enter to add a new tag."></my-help>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>
Tags could be used to suggest relevant recommendations. <br />
Press Enter to add a new tag.
</ng-container>
</ng-template>
</my-help>
<tag-input
[validators]="tagValidators" [errorMessages]="tagValidatorsMessages"
i18n-placeholder placeholder="+ Tag" i18n-secondaryPlaceholder secondaryPlaceholder="Enter a new tag"
@ -25,7 +34,15 @@
<div class="form-group">
<label i18n for="description">Description</label>
<my-help helpType="markdownText" i18n-preHtml preHtml="Video descriptions are truncated by default and require manual action to expand them."></my-help>
<my-help helpType="markdownText">
<ng-template ptTemplate="preHtml">
<ng-container i18n>
Video descriptions are truncated by default and require manual action to expand them.
</ng-container>
</ng-template>
</my-help>
<my-markdown-textarea truncate="250" formControlName="description"></my-markdown-textarea>
<div *ngIf="formErrors.description" class="form-error">
@ -114,20 +131,25 @@
</div>
</div>
<my-peertube-checkbox
inputName="nsfw" formControlName="nsfw"
i18n-labelText labelText="This video contains mature or explicit content"
i18n-helpHtml helpHtml="Some instances do not list videos containing mature or explicit content by default."
helpPlacement="bottom-right"
></my-peertube-checkbox>
<my-peertube-checkbox inputName="nsfw" formControlName="nsfw" helpPlacement="bottom-right">
<ng-template ptTemplate="label">
<ng-container i18n>This video contains mature or explicit content</ng-container>
</ng-template>
<my-peertube-checkbox
*ngIf="waitTranscodingEnabled"
inputName="waitTranscoding" formControlName="waitTranscoding"
i18n-labelText labelText="Wait transcoding before publishing the video"
i18n-helpHtml helpHtml="If you decide not to wait for transcoding before publishing the video, it could be unplayable until transcoding ends."
helpPlacement="bottom-right"
></my-peertube-checkbox>
<ng-template ptTemplate="help">
<ng-container i18n>Some instances do not list videos containing mature or explicit content by default.</ng-container>
</ng-template>
</my-peertube-checkbox>
<my-peertube-checkbox *ngIf="waitTranscodingEnabled" inputName="waitTranscoding" formControlName="waitTranscoding" helpPlacement="bottom-right">
<ng-template ptTemplate="label">
<ng-container i18n>Wait transcoding before publishing the video</ng-container>
</ng-template>
<ng-template ptTemplate="help">
<ng-container i18n>If you decide not to wait for transcoding before publishing the video, it could be unplayable until transcoding ends.</ng-container>
</ng-template>
</my-peertube-checkbox>
</div>
</div>

View File

@ -12,10 +12,14 @@
<div class="form-group form-group-magnet-uri">
<label i18n for="magnetUri">Paste magnet URI</label>
<my-help
helpType="custom" i18n-customHtml
customHtml="You can import any torrent file that points to a mp4 file. You should make sure you have diffusion rights over the content it points to, otherwise it could cause legal trouble to yourself and your instance."
></my-help>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>
You can import any torrent file that points to a mp4 file.
You should make sure you have diffusion rights over the content it points to, otherwise it could cause legal trouble to yourself and your instance.
</ng-container>
</ng-template>
</my-help>
<input type="text" id="magnetUri" [(ngModel)]="magnetUri" />
</div>

View File

@ -4,10 +4,16 @@
<div class="form-group">
<label i18n for="targetUrl">URL</label>
<my-help
helpType="custom" i18n-customHtml
customHtml="You can import any URL <a href='https://rg3.github.io/youtube-dl/supportedsites.html' target='_blank' rel='noopener noreferrer'>supported by youtube-dl</a> or URL that points to a raw MP4 file. You should make sure you have diffusion rights over the content it points to, otherwise it could cause legal trouble to yourself and your instance."
></my-help>
<my-help>
<ng-template ptTemplate="customHtml">
<ng-container i18n>
You can import any URL <a href='https://rg3.github.io/youtube-dl/supportedsites.html' target='_blank' rel='noopener noreferrer'>supported by youtube-dl</a>
or URL that points to a raw MP4 file.
You should make sure you have diffusion rights over the content it points to, otherwise it could cause legal trouble to yourself and your instance.
</ng-container>
</ng-template>
</my-help>
<input type="text" id="targetUrl" [(ngModel)]="targetUrl" />
</div>