Redesign register steps
|
@ -4,7 +4,7 @@
|
||||||
<div class="col-12 col-lg-4 col-xl-3"></div>
|
<div class="col-12 col-lg-4 col-xl-3"></div>
|
||||||
<div class="col-12 col-lg-8">
|
<div class="col-12 col-lg-8">
|
||||||
|
|
||||||
<div class="callout callout-info">
|
<div class="callout callout-orange">
|
||||||
<span i18n>
|
<span i18n>
|
||||||
Estimating a server's capacity to transcode and stream videos isn't easy and we can't tune PeerTube automatically.
|
Estimating a server's capacity to transcode and stream videos isn't easy and we can't tune PeerTube automatically.
|
||||||
</span>
|
</span>
|
||||||
|
|
|
@ -1,24 +1,29 @@
|
||||||
<section class="container">
|
<section>
|
||||||
<header *ngIf="steps.length > 2">
|
<header *ngIf="steps.length > 2">
|
||||||
<ng-container *ngFor="let step of steps; let i = index; let isLast = last;">
|
<div class="header-steps">
|
||||||
<div
|
<ng-container *ngFor="let step of steps; let i = index; let isLast = last;">
|
||||||
class="step-info" [ngClass]="{ active: selectedIndex === i, completed: isCompleted(step), 'c-hand': isAccessible(i) }" [attr.aria-current]="selectedIndex === i"
|
<div
|
||||||
(click)="onClick(i)"
|
class="step-info" [ngClass]="{ active: selectedIndex === i, completed: isCompleted(step), 'c-hand': isAccessible(step) }" [attr.aria-current]="selectedIndex === i"
|
||||||
>
|
(click)="onClick(i)"
|
||||||
<div class="step-index">
|
>
|
||||||
<ng-container *ngIf="!isCompleted(step)"><span class="visually-hidden" i18n>Step</span> {{ i + 1 }}</ng-container>
|
<div class="step-index">
|
||||||
<my-global-icon *ngIf="isCompleted(step)" iconName="tick"></my-global-icon>
|
<span class="visually-hidden" i18n>Step</span> {{ i + 1 }}
|
||||||
|
|
||||||
|
<div class="completed-icon" *ngIf="isCompleted(step)">
|
||||||
|
<my-global-icon iconName="tick"></my-global-icon>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="step-label">{{ step.label }}</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="step-label">{{ step.label }}</div>
|
<!-- Do no display if this is the last child -->
|
||||||
</div>
|
<div *ngIf="!isLast" class="connector"></div>
|
||||||
|
</ng-container>
|
||||||
<!-- Do no display if this is the last child -->
|
</div>
|
||||||
<div *ngIf="!isLast" class="connector"></div>
|
|
||||||
</ng-container>
|
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<div [style.display]="selected ? 'block' : 'none'">
|
<div class="margin-content" [style.display]="selected ? 'block' : 'none'">
|
||||||
<ng-container [ngTemplateOutlet]="selected.content"></ng-container>
|
<ng-container [ngTemplateOutlet]="selected.content"></ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
|
@ -2,76 +2,113 @@
|
||||||
@use '_variables' as *;
|
@use '_variables' as *;
|
||||||
@use '_mixins' as *;
|
@use '_mixins' as *;
|
||||||
|
|
||||||
$grey-color: #9CA3AB;
|
$index-block-height: 40px;
|
||||||
$index-block-height: 32px;
|
|
||||||
|
|
||||||
.container {
|
|
||||||
@include padding-left(0);
|
|
||||||
@include padding-right(0);
|
|
||||||
max-width: unset !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
header {
|
header {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
padding-bottom: 60px;
|
||||||
|
width: 100%;
|
||||||
|
background-color: pvar(--mainColorVeryLight);
|
||||||
|
}
|
||||||
|
|
||||||
|
.header-steps {
|
||||||
|
max-width: 800px;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
font-size: 15px;
|
margin: auto;
|
||||||
margin-bottom: 30px;
|
|
||||||
|
|
||||||
.step-info {
|
// Useful on small screens
|
||||||
color: $grey-color;
|
padding: 0 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-index {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: $index-block-height;
|
||||||
|
height: $index-block-height;
|
||||||
|
border-radius: $index-block-height;
|
||||||
|
border: 1px solid pvar(--mainColor);
|
||||||
|
margin-bottom: 10px;
|
||||||
|
font-size: 24px;
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.completed-icon {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
border-radius: 16px;
|
||||||
|
background-color: pvar(--mainBackgroundColor);
|
||||||
|
position: absolute;
|
||||||
|
bottom: 0;
|
||||||
|
right: 0;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
width: $index-block-height;
|
border: 1px solid pvar(--mainColor);
|
||||||
|
|
||||||
&:not(.c-hand) {
|
my-global-icon {
|
||||||
cursor: default;
|
@include apply-svg-color(pvar(--mainColor));
|
||||||
}
|
|
||||||
|
|
||||||
.step-index {
|
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
width: 12px;
|
||||||
align-items: center;
|
height: 12px;
|
||||||
width: $index-block-height;
|
}
|
||||||
height: $index-block-height;
|
}
|
||||||
border-radius: 100px;
|
}
|
||||||
border: 2px solid $grey-color;
|
|
||||||
margin-bottom: 10px;
|
|
||||||
|
|
||||||
my-global-icon {
|
.step-label {
|
||||||
@include apply-svg-color(pvar(--mainBackgroundColor));
|
width: max-content;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
width: 22px;
|
.step-info {
|
||||||
height: 22px;
|
color: pvar(--mainColor);
|
||||||
}
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
width: $index-block-height;
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: default;
|
||||||
|
|
||||||
|
&.c-hand {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.active,
|
||||||
|
&.completed {
|
||||||
|
.step-index {
|
||||||
|
background-color: pvar(--mainColor);
|
||||||
|
color: pvar(--mainBackgroundColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
.step-label {
|
.step-label {
|
||||||
width: max-content;
|
color: pvar(--mainColor);
|
||||||
}
|
|
||||||
|
|
||||||
&.active,
|
|
||||||
&.completed {
|
|
||||||
.step-index {
|
|
||||||
border-color: pvar(--mainColor);
|
|
||||||
background-color: pvar(--mainColor);
|
|
||||||
color: pvar(--mainBackgroundColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
.step-label {
|
|
||||||
color: pvar(--mainColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
&.completed {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.connector {
|
&.active {
|
||||||
flex: auto;
|
opacity: 1;
|
||||||
margin: math.div($index-block-height, 2) 10px 0 10px;
|
}
|
||||||
height: 2px;
|
}
|
||||||
background-color: $grey-color;
|
|
||||||
|
.connector {
|
||||||
|
flex: auto;
|
||||||
|
margin: math.div($index-block-height, 2) 10px 0 10px;
|
||||||
|
height: 2px;
|
||||||
|
background-color: pvar(--mainColor);
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: $small-view) {
|
||||||
|
.margin-content {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin:auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: $small-view) {
|
||||||
|
.step-label {
|
||||||
|
width: auto;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -14,13 +14,10 @@ export class CustomStepperComponent extends CdkStepper {
|
||||||
}
|
}
|
||||||
|
|
||||||
isCompleted (step: CdkStep) {
|
isCompleted (step: CdkStep) {
|
||||||
return step.stepControl?.dirty && step.stepControl.valid
|
return step.completed
|
||||||
}
|
}
|
||||||
|
|
||||||
isAccessible (index: number) {
|
isAccessible (step: CdkStep) {
|
||||||
const stepsCompletedMap = this.steps.map(step => this.isCompleted(step))
|
return step.editable && step.completed
|
||||||
return index === 0
|
|
||||||
? true
|
|
||||||
: stepsCompletedMap[index - 1]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
<form role="form" [formGroup]="form">
|
|
||||||
|
|
||||||
<div class="channel-explanations">
|
|
||||||
<p i18n>
|
|
||||||
A channel is an entity in which you upload your videos. Creating several of them helps you to organize and separate your content.<br />
|
|
||||||
For example, you could decide to have a channel to publish your piano concerts, and another channel in which you publish your videos talking about ecology.
|
|
||||||
</p>
|
|
||||||
|
|
||||||
<p i18n>
|
|
||||||
Other users can decide to subscribe any channel they want, to be notified when you publish a new video.
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="displayName" i18n>Channel display name</label>
|
|
||||||
|
|
||||||
<div class="input-group">
|
|
||||||
<input
|
|
||||||
type="text" id="displayName"
|
|
||||||
formControlName="displayName" [ngClass]="{ 'input-error': formErrors['displayName'] }"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="formErrors.displayName" class="form-error">
|
|
||||||
{{ formErrors.displayName }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="name" i18n>Channel name</label>
|
|
||||||
|
|
||||||
<div class="input-group">
|
|
||||||
<input
|
|
||||||
type="text" id="name" i18n-placeholder placeholder="Example: my_super_channel"
|
|
||||||
formControlName="name" [ngClass]="{ 'input-error': formErrors['name'] }"
|
|
||||||
>
|
|
||||||
<div class="input-group-text">@{{ instanceHost }}</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="name-information" i18n>
|
|
||||||
The channel name is a unique identifier of your channel on this and all the other instances. It's as unique as an email address, which makes it easy for other people to interact with it.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="formErrors.name" class="form-error">
|
|
||||||
{{ formErrors.name }}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="isSameThanUsername()" class="form-error" i18n>
|
|
||||||
Channel name cannot be the same as your account name. You can click on the first step to update your account name.
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
|
@ -1,64 +0,0 @@
|
||||||
<form role="form" [formGroup]="form">
|
|
||||||
|
|
||||||
<div class="capability-information alert alert-info" i18n *ngIf="videoUploadDisabled">
|
|
||||||
Video uploads are disabled on this instance, hence your account won't be able to upload videos.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="displayName" i18n>Display name</label>
|
|
||||||
|
|
||||||
<div class="input-group">
|
|
||||||
<input
|
|
||||||
type="text" id="displayName" placeholder="John Doe"
|
|
||||||
formControlName="displayName" [ngClass]="{ 'input-error': formErrors['displayName'] }"
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="formErrors.displayName" class="form-error">
|
|
||||||
{{ formErrors.displayName }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="username" i18n>Username</label>
|
|
||||||
|
|
||||||
<div class="input-group">
|
|
||||||
<input
|
|
||||||
type="text" id="username" i18n-placeholder="Username choice placeholder in the registration form" placeholder="e.g. jane_doe"
|
|
||||||
formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }"
|
|
||||||
>
|
|
||||||
<span class="input-group-text">@{{ instanceHost }}</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="name-information" i18n>
|
|
||||||
The username is a unique identifier of your account on this and all the other instances. It's as unique as an email address, which makes it easy for other people to interact with it.
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div *ngIf="formErrors.username" class="form-error">
|
|
||||||
{{ formErrors.username }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="email" i18n>Email</label>
|
|
||||||
<input
|
|
||||||
type="text" id="email" i18n-placeholder placeholder="Email"
|
|
||||||
formControlName="email" class="form-control" [ngClass]="{ 'input-error': formErrors['email'] }"
|
|
||||||
>
|
|
||||||
<div *ngIf="formErrors.email" class="form-error">
|
|
||||||
{{ formErrors.email }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="password" i18n>Password</label>
|
|
||||||
<my-input-text formControlName="password" inputId="password"
|
|
||||||
i18n-placeholder placeholder="Password"
|
|
||||||
[ngClass]="{ 'input-error': formErrors['password'] }"
|
|
||||||
autocomplete="new-password"></my-input-text>
|
|
||||||
<div *ngIf="formErrors.password" class="form-error">
|
|
||||||
{{ formErrors.password }}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</form>
|
|
|
@ -1,64 +1,121 @@
|
||||||
<div class="margin-content">
|
<div>
|
||||||
|
|
||||||
<div class="signup-disabled" *ngIf="signupDisabled">
|
<div class="signup-disabled" *ngIf="signupDisabled">
|
||||||
<div class="alert alert-warning" i18n>Signup is not enabled on this instance.</div>
|
<div class="alert alert-warning" i18n>Signup is not enabled on this instance.</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ng-container *ngIf="!signupDisabled">
|
<ng-container *ngIf="!signupDisabled">
|
||||||
<div i18n class="title-page title-page-single">
|
<h1 i18n class="header-title">
|
||||||
|
<strong class="underline-orange">{{ instanceName }}</strong>
|
||||||
|
>
|
||||||
Create an account
|
Create an account
|
||||||
</div>
|
</h1>
|
||||||
|
|
||||||
<my-signup-success *ngIf="signupDone" [message]="success"></my-signup-success>
|
<div class="register-content">
|
||||||
<div *ngIf="info" class="alert alert-info">{{ info }}</div>
|
<my-custom-stepper linear>
|
||||||
|
|
||||||
<div class="wrapper" [hidden]="signupDone">
|
<cdk-step i18n-label label="About" [editable]="!signupSuccess">
|
||||||
<div class="register-form">
|
<my-signup-step-title mascotImageName="about" i18n>
|
||||||
<my-custom-stepper linear *ngIf="!signupDone">
|
<strong>Create an account</strong>
|
||||||
<cdk-step [stepControl]="formStepTerms" i18n-label="Stepper label for the registration page describing terms of service" label="Terms">
|
<div>on {{ instanceName }}</div>
|
||||||
<div class="instance-information">
|
</my-signup-step-title>
|
||||||
<my-instance-about-accordion
|
|
||||||
(init)="onInstanceAboutAccordionInit($event)" [panels]="instanceInformationPanels"
|
|
||||||
pluginScope="signup" pluginHook="filter:signup.instance-about-plugin-panels.create.result"
|
|
||||||
></my-instance-about-accordion>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<my-register-step-terms
|
<my-register-step-about [videoUploadDisabled]="videoUploadDisabled"></my-register-step-about>
|
||||||
[hasCodeOfConduct]="!!aboutHtml.codeOfConduct"
|
|
||||||
[minimumAge]="minimumAge"
|
|
||||||
(formBuilt)="onTermsFormBuilt($event)" (termsClick)="onTermsClick()" (codeOfConductClick)="onCodeOfConductClick()"
|
|
||||||
></my-register-step-terms>
|
|
||||||
|
|
||||||
|
<div class="step-buttons">
|
||||||
|
<a i18n class="skip-step underline-orange" routerLink="/login">
|
||||||
|
<strong>I already have an account</strong>, I log in
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<button i18n cdkStepperNext>I create an account</button>
|
||||||
|
</div>
|
||||||
|
</cdk-step>
|
||||||
|
|
||||||
|
<cdk-step [stepControl]="formStepTerms" i18n-label label="Terms" [editable]="!signupSuccess">
|
||||||
|
<my-signup-step-title mascotImageName="terms" i18n>
|
||||||
|
<strong>Terms</strong>
|
||||||
|
<div>of {{ instanceName }}</div>
|
||||||
|
</my-signup-step-title>
|
||||||
|
|
||||||
|
<my-instance-about-accordion
|
||||||
|
[displayInstanceName]="false"
|
||||||
|
(init)="onInstanceAboutAccordionInit($event)" [panels]="instanceInformationPanels"
|
||||||
|
pluginScope="signup" pluginHook="filter:signup.instance-about-plugin-panels.create.result"
|
||||||
|
></my-instance-about-accordion>
|
||||||
|
|
||||||
|
<my-register-step-terms
|
||||||
|
[hasCodeOfConduct]="!!aboutHtml.codeOfConduct"
|
||||||
|
[minimumAge]="minimumAge"
|
||||||
|
(formBuilt)="onTermsFormBuilt($event)" (termsClick)="onTermsClick()" (codeOfConductClick)="onCodeOfConductClick()"
|
||||||
|
></my-register-step-terms>
|
||||||
|
|
||||||
|
<div class="step-buttons">
|
||||||
|
<button cdkStepperPrevious>{{ defaultPreviousStepButtonLabel }}</button>
|
||||||
<button cdkStepperNext [disabled]="!formStepTerms || !formStepTerms.valid">{{ defaultNextStepButtonLabel }}</button>
|
<button cdkStepperNext [disabled]="!formStepTerms || !formStepTerms.valid">{{ defaultNextStepButtonLabel }}</button>
|
||||||
</cdk-step>
|
</div>
|
||||||
|
</cdk-step>
|
||||||
|
|
||||||
<cdk-step [stepControl]="formStepUser" i18n-label="Stepper label for the registration page asking user information" label="User">
|
<cdk-step [stepControl]="formStepUser" label="My account" [editable]="!signupSuccess">
|
||||||
<my-register-step-user (formBuilt)="onUserFormBuilt($event)" [videoUploadDisabled]="videoUploadDisabled"></my-register-step-user>
|
<my-signup-step-title mascotImageName="account" i18n>
|
||||||
|
<strong>Setup</strong>
|
||||||
|
<div>your account</div>
|
||||||
|
</my-signup-step-title>
|
||||||
|
|
||||||
|
<my-register-step-user
|
||||||
|
(formBuilt)="onUserFormBuilt($event)"
|
||||||
|
[videoUploadDisabled]="videoUploadDisabled" [requiresEmailVerification]="requiresEmailVerification"
|
||||||
|
></my-register-step-user>
|
||||||
|
|
||||||
|
<div class="step-buttons">
|
||||||
<button cdkStepperPrevious>{{ defaultPreviousStepButtonLabel }}</button>
|
<button cdkStepperPrevious>{{ defaultPreviousStepButtonLabel }}</button>
|
||||||
<button cdkStepperNext [disabled]="!formStepUser || !formStepUser.valid" (click)="videoUploadDisabled && signup()">{{ stepUserButtonLabel }}</button>
|
<button cdkStepperNext [disabled]="!formStepUser || !formStepUser.valid" (click)="videoUploadDisabled && signup()">{{ stepUserButtonLabel }}</button>
|
||||||
</cdk-step>
|
</div>
|
||||||
|
</cdk-step>
|
||||||
|
|
||||||
<cdk-step [stepControl]="formStepChannel" i18n-label="Stepper label for the registration page asking information about the default channel" label="Channel" *ngIf="!videoUploadDisabled">
|
<cdk-step *ngIf="!videoUploadDisabled" [optional]="true" [stepControl]="formStepChannel" i18n-label label="My channel" [editable]="!signupSuccess">
|
||||||
<my-register-step-channel (formBuilt)="onChannelFormBuilt($event)" [username]="getUsername()"></my-register-step-channel>
|
<my-signup-step-title mascotImageName="channel" i18n>
|
||||||
|
<div>Create</div>
|
||||||
|
<strong>your first channel</strong>
|
||||||
|
</my-signup-step-title>
|
||||||
|
|
||||||
|
<my-register-step-channel
|
||||||
|
(formBuilt)="onChannelFormBuilt($event)"
|
||||||
|
[videoQuota]="videoQuota" [instanceName]="instanceName" [username]="getUsername()"
|
||||||
|
></my-register-step-channel>
|
||||||
|
|
||||||
|
<div class="step-buttons">
|
||||||
<button cdkStepperPrevious>{{ defaultPreviousStepButtonLabel }}</button>
|
<button cdkStepperPrevious>{{ defaultPreviousStepButtonLabel }}</button>
|
||||||
|
|
||||||
|
<div class="skip-step">
|
||||||
|
<span class="underline-orange" role="button" (click)="skipChannelCreation()">
|
||||||
|
<strong i18n>I don't want to create a channel</strong>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<div class="skip-step-description" i18n>You will be able to create a channel later</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<button cdkStepperNext [disabled]="!formStepChannel || !formStepChannel.valid || hasSameChannelAndAccountNames()" (click)="signup()" i18n>
|
<button cdkStepperNext [disabled]="!formStepChannel || !formStepChannel.valid || hasSameChannelAndAccountNames()" (click)="signup()" i18n>
|
||||||
Create my account
|
Create my account
|
||||||
</button>
|
</button>
|
||||||
</cdk-step>
|
</div>
|
||||||
|
</cdk-step>
|
||||||
|
|
||||||
<cdk-step i18n-label label="Done" editable="false">
|
<cdk-step #lastStep i18n-label label="Done!" [editable]="false">
|
||||||
<div *ngIf="!signupDone && !error" class="done-loader">
|
<div *ngIf="!signupSuccess && !signupError" class="done-loader">
|
||||||
<my-loader [loading]="true"></my-loader>
|
<my-loader [loading]="true"></my-loader>
|
||||||
|
|
||||||
<div i18n>PeerTube is creating your account...</div>
|
<div i18n>PeerTube is creating your account...</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
|
<div *ngIf="signupError" class="alert alert-danger">{{ signupError }}</div>
|
||||||
</cdk-step>
|
|
||||||
</my-custom-stepper>
|
<my-signup-success *ngIf="signupSuccess" [requiresEmailVerification]="requiresEmailVerification"></my-signup-success>
|
||||||
</div>
|
|
||||||
|
<div *ngIf="signupError" class="steps-button">
|
||||||
|
<button cdkStepperPrevious>{{ defaultPreviousStepButtonLabel }}</button>
|
||||||
|
</div>
|
||||||
|
</cdk-step>
|
||||||
|
</my-custom-stepper>
|
||||||
</div>
|
</div>
|
||||||
</ng-container>
|
</ng-container>
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
@use '_mixins' as *;
|
@use '_mixins' as *;
|
||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
font-size: 15px;
|
font-size: 16px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,61 +10,75 @@
|
||||||
padding-top: 30vh;
|
padding-top: 30vh;
|
||||||
}
|
}
|
||||||
|
|
||||||
.wrapper {
|
.header-title {
|
||||||
display: flex;
|
font-weight: normal;
|
||||||
flex-direction: column;
|
font-size: 15px;
|
||||||
|
background-color: pvar(--mainColorVeryLight);
|
||||||
.register-form {
|
padding: 35px 25px 15px 25px;
|
||||||
max-width: 600px;
|
margin: 0;
|
||||||
align-self: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.register-form,
|
|
||||||
.instance-information {
|
|
||||||
width: 100%;
|
|
||||||
}
|
|
||||||
|
|
||||||
.instance-information {
|
|
||||||
margin-bottom: 15px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input:not([type=submit]) {
|
.register-content {
|
||||||
@include peertube-input-text(100%);
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
|
||||||
|
my-instance-about-accordion {
|
||||||
display: block;
|
display: block;
|
||||||
|
margin-bottom: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
&#username,
|
.step-buttons {
|
||||||
&#name {
|
display: flex;
|
||||||
width: auto !important;
|
flex-wrap: wrap;
|
||||||
flex-grow: 1;
|
align-items: center;
|
||||||
|
|
||||||
|
.skip-step {
|
||||||
|
@include margin-right(30px);
|
||||||
|
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-step-description {
|
||||||
|
margin-top: 5px;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline-orange {
|
||||||
|
color: pvar(--mainForegroundColor);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
button,
|
||||||
|
.skip-step {
|
||||||
|
margin-top: 20px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-step,
|
||||||
|
button[cdkStepperNext] {
|
||||||
|
@include margin-left(auto);
|
||||||
|
}
|
||||||
|
|
||||||
|
.skip-step + button[cdkStepperNext] {
|
||||||
|
@include margin-left(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type=submit],
|
|
||||||
button {
|
button {
|
||||||
@include peertube-button;
|
@include peertube-button-big;
|
||||||
|
|
||||||
&[cdkStepperNext] {
|
&[cdkStepperNext] {
|
||||||
@include orange-button;
|
@include orange-button;
|
||||||
|
|
||||||
// Chrome does not support inline-end
|
|
||||||
float: right;
|
|
||||||
float: inline-end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&[cdkStepperPrevious] {
|
&[cdkStepperPrevious] {
|
||||||
@include grey-button;
|
@include grey-button;
|
||||||
|
|
||||||
// Chrome does not support inline-start
|
|
||||||
float: left;
|
|
||||||
float: inline-start;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.name-information {
|
|
||||||
margin-top: 10px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.done-loader {
|
.done-loader {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
|
@ -73,13 +87,16 @@ button {
|
||||||
|
|
||||||
my-loader {
|
my-loader {
|
||||||
margin-bottom: 20px;
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
::ng-deep .loader div {
|
@media screen and (max-width: $small-view) {
|
||||||
border-color: pvar(--mainColor) transparent transparent transparent;
|
.step-buttons {
|
||||||
}
|
justify-content: space-between;
|
||||||
|
|
||||||
+ div {
|
.skip-step,
|
||||||
font-size: 15px;
|
button[cdkStepperNext] {
|
||||||
|
@include margin-left(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Component, OnInit } from '@angular/core'
|
import { CdkStep } from '@angular/cdk/stepper'
|
||||||
|
import { Component, OnInit, ViewChild } from '@angular/core'
|
||||||
import { FormGroup } from '@angular/forms'
|
import { FormGroup } from '@angular/forms'
|
||||||
import { ActivatedRoute } from '@angular/router'
|
import { ActivatedRoute } from '@angular/router'
|
||||||
import { AuthService } from '@app/core'
|
import { AuthService } from '@app/core'
|
||||||
|
@ -15,13 +16,15 @@ import { ServerConfig } from '@shared/models/server'
|
||||||
styleUrls: [ './register.component.scss' ]
|
styleUrls: [ './register.component.scss' ]
|
||||||
})
|
})
|
||||||
export class RegisterComponent implements OnInit {
|
export class RegisterComponent implements OnInit {
|
||||||
|
@ViewChild('lastStep') lastStep: CdkStep
|
||||||
|
|
||||||
accordion: NgbAccordion
|
accordion: NgbAccordion
|
||||||
info: string = null
|
|
||||||
error: string = null
|
signupError: string
|
||||||
success: string = null
|
signupSuccess = false
|
||||||
signupDone = false
|
|
||||||
|
|
||||||
videoUploadDisabled: boolean
|
videoUploadDisabled: boolean
|
||||||
|
videoQuota: number
|
||||||
|
|
||||||
formStepTerms: FormGroup
|
formStepTerms: FormGroup
|
||||||
formStepUser: FormGroup
|
formStepUser: FormGroup
|
||||||
|
@ -39,8 +42,8 @@ export class RegisterComponent implements OnInit {
|
||||||
moderation: false
|
moderation: false
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultPreviousStepButtonLabel = $localize`:Button on the registration form to go to the previous step:Back`
|
defaultPreviousStepButtonLabel = $localize`:Button on the registration form to go to the previous step:Go to the previous step`
|
||||||
defaultNextStepButtonLabel = $localize`:Button on the registration form to go to the previous step:Next`
|
defaultNextStepButtonLabel = $localize`:Button on the registration form to go to the previous step:Go to the next step`
|
||||||
stepUserButtonLabel = this.defaultNextStepButtonLabel
|
stepUserButtonLabel = this.defaultNextStepButtonLabel
|
||||||
|
|
||||||
signupDisabled = false
|
signupDisabled = false
|
||||||
|
@ -62,7 +65,11 @@ export class RegisterComponent implements OnInit {
|
||||||
return this.serverConfig.signup.minimumAge
|
return this.serverConfig.signup.minimumAge
|
||||||
}
|
}
|
||||||
|
|
||||||
ngOnInit (): void {
|
get instanceName () {
|
||||||
|
return this.serverConfig.instance.name
|
||||||
|
}
|
||||||
|
|
||||||
|
ngOnInit () {
|
||||||
this.serverConfig = this.route.snapshot.data.serverConfig
|
this.serverConfig = this.route.snapshot.data.serverConfig
|
||||||
|
|
||||||
if (this.serverConfig.signup.allowed === false || this.serverConfig.signup.allowedForCurrentIP === false) {
|
if (this.serverConfig.signup.allowed === false || this.serverConfig.signup.allowedForCurrentIP === false) {
|
||||||
|
@ -70,7 +77,9 @@ export class RegisterComponent implements OnInit {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.videoUploadDisabled = this.serverConfig.user.videoQuota === 0
|
this.videoQuota = this.serverConfig.user.videoQuota
|
||||||
|
this.videoUploadDisabled = this.videoQuota === 0
|
||||||
|
|
||||||
this.stepUserButtonLabel = this.videoUploadDisabled
|
this.stepUserButtonLabel = this.videoUploadDisabled
|
||||||
? $localize`:Button on the registration form to finalize the account and channel creation:Signup`
|
? $localize`:Button on the registration form to finalize the account and channel creation:Signup`
|
||||||
: this.defaultNextStepButtonLabel
|
: this.defaultNextStepButtonLabel
|
||||||
|
@ -120,21 +129,31 @@ export class RegisterComponent implements OnInit {
|
||||||
this.aboutHtml = instanceAboutAccordion.aboutHtml
|
this.aboutHtml = instanceAboutAccordion.aboutHtml
|
||||||
}
|
}
|
||||||
|
|
||||||
|
skipChannelCreation () {
|
||||||
|
this.formStepChannel.reset()
|
||||||
|
this.lastStep.select()
|
||||||
|
this.signup()
|
||||||
|
}
|
||||||
|
|
||||||
async signup () {
|
async signup () {
|
||||||
this.error = null
|
this.signupError = undefined
|
||||||
|
|
||||||
const body: UserRegister = await this.hooks.wrapObject(
|
const body: UserRegister = await this.hooks.wrapObject(
|
||||||
Object.assign(this.formStepUser.value, { channel: this.videoUploadDisabled ? undefined : this.formStepChannel.value }),
|
{
|
||||||
|
...this.formStepUser.value,
|
||||||
|
|
||||||
|
channel: this.formStepChannel?.value?.name
|
||||||
|
? this.formStepChannel.value
|
||||||
|
: undefined
|
||||||
|
},
|
||||||
'signup',
|
'signup',
|
||||||
'filter:api.signup.registration.create.params'
|
'filter:api.signup.registration.create.params'
|
||||||
)
|
)
|
||||||
|
|
||||||
this.userSignupService.signup(body).subscribe({
|
this.userSignupService.signup(body).subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
this.signupDone = true
|
|
||||||
|
|
||||||
if (this.requiresEmailVerification) {
|
if (this.requiresEmailVerification) {
|
||||||
this.info = $localize`Now please check your emails to verify your account and complete signup.`
|
this.signupSuccess = true
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,17 +161,17 @@ export class RegisterComponent implements OnInit {
|
||||||
this.authService.login(body.username, body.password)
|
this.authService.login(body.username, body.password)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
next: () => {
|
next: () => {
|
||||||
this.success = $localize`You are now logged in as ${body.username}!`
|
this.signupSuccess = true
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => {
|
error: err => {
|
||||||
this.error = err.message
|
this.signupError = err.message
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
error: err => {
|
error: err => {
|
||||||
this.error = err.message
|
this.signupError = err.message
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,15 +2,15 @@ import { CdkStepperModule } from '@angular/cdk/stepper'
|
||||||
import { NgModule } from '@angular/core'
|
import { NgModule } from '@angular/core'
|
||||||
import { SharedSignupModule } from '@app/+signup/shared/shared-signup.module'
|
import { SharedSignupModule } from '@app/+signup/shared/shared-signup.module'
|
||||||
import { SharedInstanceModule } from '@app/shared/shared-instance'
|
import { SharedInstanceModule } from '@app/shared/shared-instance'
|
||||||
|
import { SharedMainModule } from '@app/shared/shared-main'
|
||||||
import { CustomStepperComponent } from './custom-stepper.component'
|
import { CustomStepperComponent } from './custom-stepper.component'
|
||||||
import { RegisterRoutingModule } from './register-routing.module'
|
import { RegisterRoutingModule } from './register-routing.module'
|
||||||
import { RegisterStepChannelComponent } from './register-step-channel.component'
|
|
||||||
import { RegisterStepTermsComponent } from './register-step-terms.component'
|
|
||||||
import { RegisterStepUserComponent } from './register-step-user.component'
|
|
||||||
import { RegisterComponent } from './register.component'
|
import { RegisterComponent } from './register.component'
|
||||||
|
import { RegisterStepAboutComponent, RegisterStepChannelComponent, RegisterStepTermsComponent, RegisterStepUserComponent } from './steps'
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
imports: [
|
imports: [
|
||||||
|
SharedMainModule,
|
||||||
RegisterRoutingModule,
|
RegisterRoutingModule,
|
||||||
|
|
||||||
CdkStepperModule,
|
CdkStepperModule,
|
||||||
|
@ -25,7 +25,8 @@ import { RegisterComponent } from './register.component'
|
||||||
CustomStepperComponent,
|
CustomStepperComponent,
|
||||||
RegisterStepChannelComponent,
|
RegisterStepChannelComponent,
|
||||||
RegisterStepTermsComponent,
|
RegisterStepTermsComponent,
|
||||||
RegisterStepUserComponent
|
RegisterStepUserComponent,
|
||||||
|
RegisterStepAboutComponent
|
||||||
],
|
],
|
||||||
|
|
||||||
exports: [
|
exports: [
|
||||||
|
|
4
client/src/app/+signup/+register/steps/index.ts
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
export * from './register-step-about.component'
|
||||||
|
export * from './register-step-channel.component'
|
||||||
|
export * from './register-step-terms.component'
|
||||||
|
export * from './register-step-user.component'
|
|
@ -0,0 +1,39 @@
|
||||||
|
<div class="why">
|
||||||
|
<h3 i18n>Why creating an account?</h3>
|
||||||
|
|
||||||
|
<p i18n>
|
||||||
|
As you probably noticed: creating an account is not necessary to watch video son {{ instanceName }}.
|
||||||
|
<br />
|
||||||
|
However, creating an account on {{ instanceName }} will allow you to:
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li i18n><strong>Comment</strong> videos</li>
|
||||||
|
<li i18n><strong>Subscribe</strong> to channels to be notified of new videos</li>
|
||||||
|
<li i18n>Have access to your <strong>watch history</strong></li>
|
||||||
|
<li *ngIf="!videoUploadDisabled" i18n>Create your channel to <strong>publish videos</strong></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<h4 i18n>You're using Mastodon, ActivityPub or a RSS feed aggregator?</h4>
|
||||||
|
|
||||||
|
<p i18n>
|
||||||
|
You can already follow {{ instanceName }} using your favorite tool.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="callout callout-orange callout-light">
|
||||||
|
<div class="mascot-container" style="min-width: 140px">
|
||||||
|
<img class="mascot" width="140px" height="160px" src="/client/assets/images/mascot/happy.svg" alt="mascot"/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="callout-content">
|
||||||
|
<h4 i18>This website is a GAFAM alternative</h4>
|
||||||
|
|
||||||
|
<p i18n>
|
||||||
|
{{ instanceName }} has been created using <a class="link-orange" target="_blank" rel="noopener noreferrer" href="https://joinpeertube.org">PeerTube</a>, a video creation platform developed by Framasoft.
|
||||||
|
<a class="link-orange" target="_blank" rel="noopener noreferrer" href="https://framasoft.org">Framasoft</a> is a french non-profit organization that offers alternatives to Big Tech's digital tools
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
|
@ -0,0 +1,53 @@
|
||||||
|
@use '_variables' as *;
|
||||||
|
@use '_mixins' as *;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
font-weight: $font-bold;
|
||||||
|
font-size: 24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h4 {
|
||||||
|
font-size: 18px;
|
||||||
|
font-weight: $font-bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.why {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.callout {
|
||||||
|
margin: 75px auto 25px;
|
||||||
|
border-width: 2px;
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
.mascot-container {
|
||||||
|
position: relative;
|
||||||
|
|
||||||
|
.mascot {
|
||||||
|
position: absolute;
|
||||||
|
top: -65px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.callout-content {
|
||||||
|
margin-left: 30px;
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: $small-view) {
|
||||||
|
.callout {
|
||||||
|
margin-top: 20px;
|
||||||
|
|
||||||
|
.mascot-container {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.callout-content {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
import { ServerService } from '@app/core'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-register-step-about',
|
||||||
|
templateUrl: './register-step-about.component.html',
|
||||||
|
styleUrls: [ './register-step-about.component.scss' ]
|
||||||
|
})
|
||||||
|
export class RegisterStepAboutComponent {
|
||||||
|
@Input() videoUploadDisabled: boolean
|
||||||
|
|
||||||
|
constructor (private serverService: ServerService) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get instanceName () {
|
||||||
|
return this.serverService.getHTMLConfig().instance.name
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
<div class="mb-5">
|
||||||
|
<p i18n>
|
||||||
|
You want to <strong>publish videos</strong> on {{ instanceName }}? Then you need to create your first <strong>channel</strong>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p i18n>
|
||||||
|
You might want to <strong>create a channel by theme:</strong> for example, you can create a channel named "SweetMelodies"
|
||||||
|
to publish your piano concerts and another one "Ecology" in which you publish your videos talking about ecology.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p i18n *ngIf="videoQuota !== -1">
|
||||||
|
{{ instanceName }} administrators allow you to publish up to <strong>{{ videoQuota | bytes: 0 }} of videos</strong> on their website.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form role="form" [formGroup]="form">
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-md-12 col-xl-6 form-group">
|
||||||
|
<label for="displayName" i18n>Channel display name</label>
|
||||||
|
|
||||||
|
<div i18n class="form-group-description">This is the name that will be publicly visible by other users.</div>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<input
|
||||||
|
type="text" id="displayName" i18n-placeholder placeholder="Example: Sweet Melodies"
|
||||||
|
formControlName="displayName" [ngClass]="{ 'input-error': formErrors['displayName'] }"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="formErrors.displayName" class="form-error">{{ formErrors.displayName }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12 col-xl-6 form-group">
|
||||||
|
<label for="name" i18n>Channel identifier</label>
|
||||||
|
|
||||||
|
<div i18n class="form-group-description">This is the name that will be displayed in your profile URL.</div>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<input
|
||||||
|
type="text" id="name" i18n-placeholder placeholder="Example: sweetmelodies24"
|
||||||
|
formControlName="name" [ngClass]="{ 'input-error': formErrors['name'] }"
|
||||||
|
>
|
||||||
|
<div class="input-group-text">@{{ instanceHost }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="formErrors.name" class="form-error">{{ formErrors.name }}</div>
|
||||||
|
|
||||||
|
<div *ngIf="isSameThanUsername()" class="form-error" i18n>
|
||||||
|
Channel identifier cannot be the same as your account name. You can click on the first step to update your account name.
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -9,10 +9,13 @@ import { UserSignupService } from '@app/shared/shared-users'
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-register-step-channel',
|
selector: 'my-register-step-channel',
|
||||||
templateUrl: './register-step-channel.component.html',
|
templateUrl: './register-step-channel.component.html',
|
||||||
styleUrls: [ './register.component.scss' ]
|
styleUrls: [ './step.component.scss' ]
|
||||||
})
|
})
|
||||||
export class RegisterStepChannelComponent extends FormReactive implements OnInit {
|
export class RegisterStepChannelComponent extends FormReactive implements OnInit {
|
||||||
@Input() username: string
|
@Input() username: string
|
||||||
|
@Input() instanceName: string
|
||||||
|
@Input() videoQuota: number
|
||||||
|
|
||||||
@Output() formBuilt = new EventEmitter<FormGroup>()
|
@Output() formBuilt = new EventEmitter<FormGroup>()
|
||||||
|
|
||||||
constructor (
|
constructor (
|
|
@ -4,15 +4,13 @@
|
||||||
<ng-template ptTemplate="label">
|
<ng-template ptTemplate="label">
|
||||||
<ng-container i18n>
|
<ng-container i18n>
|
||||||
I am at least {{ minimumAge }} years old and agree
|
I am at least {{ minimumAge }} years old and agree
|
||||||
to the <a class="terms-anchor" (click)="onTermsClick($event)" href='#'>Terms</a>
|
to the <a class="link-orange" (click)="onTermsClick($event)" href='#'>Terms</a>
|
||||||
<ng-container *ngIf="hasCodeOfConduct"> and to the <a (click)="onCodeOfConductClick($event)" href='#'>Code of Conduct</a></ng-container>
|
<ng-container *ngIf="hasCodeOfConduct"> and to the <a (click)="onCodeOfConductClick($event)" href='#'>Code of Conduct</a></ng-container>
|
||||||
of this instance
|
of this instance
|
||||||
</ng-container>
|
</ng-container>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</my-peertube-checkbox>
|
</my-peertube-checkbox>
|
||||||
|
|
||||||
<div *ngIf="formErrors.terms" class="form-error">
|
<div *ngIf="formErrors.terms" class="form-error">{{ formErrors.terms }}</div>
|
||||||
{{ formErrors.terms }}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
|
@ -8,7 +8,7 @@ import { FormReactive, FormValidatorService } from '@app/shared/shared-forms'
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-register-step-terms',
|
selector: 'my-register-step-terms',
|
||||||
templateUrl: './register-step-terms.component.html',
|
templateUrl: './register-step-terms.component.html',
|
||||||
styleUrls: [ './register.component.scss' ]
|
styleUrls: [ './step.component.scss' ]
|
||||||
})
|
})
|
||||||
export class RegisterStepTermsComponent extends FormReactive implements OnInit {
|
export class RegisterStepTermsComponent extends FormReactive implements OnInit {
|
||||||
@Input() hasCodeOfConduct = false
|
@Input() hasCodeOfConduct = false
|
|
@ -0,0 +1,73 @@
|
||||||
|
<div class="alert pt-alert-primary" i18n *ngIf="videoUploadDisabled">
|
||||||
|
Video uploads are disabled on this instance, hence your account won't be able to upload videos.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<form role="form" [formGroup]="form">
|
||||||
|
<div class="row">
|
||||||
|
|
||||||
|
<div class="col-md-12 col-xl-6 form-group">
|
||||||
|
<label for="displayName" i18n>Public name</label>
|
||||||
|
|
||||||
|
<div class="form-group-description" i18n>
|
||||||
|
This is the name that will be publicly visible by other users.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<input
|
||||||
|
type="text" id="displayName" i18n-placeholder placeholder="Example: John Doe"
|
||||||
|
formControlName="displayName" [ngClass]="{ 'input-error': formErrors['displayName'] }"
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="formErrors.displayName" class="form-error">{{ formErrors.displayName }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12 col-xl-6 form-group">
|
||||||
|
<label for="username" i18n>Username</label>
|
||||||
|
|
||||||
|
<div class="form-group-description" i18n>
|
||||||
|
This is the name that will be displayed in your profile URL.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="input-group">
|
||||||
|
<input
|
||||||
|
type="text" id="username" i18n-placeholder placeholder="Example: john_doe58"
|
||||||
|
formControlName="username" class="form-control" [ngClass]="{ 'input-error': formErrors['username'] }"
|
||||||
|
>
|
||||||
|
<span class="input-group-text">@{{ instanceHost }}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div *ngIf="formErrors.username" class="form-error">{{ formErrors.username }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-md-12 col-xl-6 form-group">
|
||||||
|
<label for="email" i18n>Email</label>
|
||||||
|
|
||||||
|
<div *ngIf="requiresEmailVerification" class="form-group-description" i18n>
|
||||||
|
This email address will be used to validate your account.
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<input
|
||||||
|
type="text" id="email" i18n-placeholder placeholder="Example: john@example.com"
|
||||||
|
formControlName="email" class="form-control" [ngClass]="{ 'input-error': formErrors['email'] }"
|
||||||
|
>
|
||||||
|
|
||||||
|
<div *ngIf="formErrors.email" class="form-error">{{ formErrors.email }}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-md-12 col-xl-6 form-group">
|
||||||
|
<label for="password" i18n>Password</label>
|
||||||
|
|
||||||
|
<div class="form-group-description">{{ getMinPasswordLengthMessage() }}</div>
|
||||||
|
|
||||||
|
<my-input-text
|
||||||
|
formControlName="password" inputId="password"
|
||||||
|
[ngClass]="{ 'input-error': formErrors['password'] }" autocomplete="new-password"
|
||||||
|
></my-input-text>
|
||||||
|
|
||||||
|
<div *ngIf="formErrors.password" class="form-error">{{ formErrors.password }}</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
|
@ -14,10 +14,11 @@ import { UserSignupService } from '@app/shared/shared-users'
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-register-step-user',
|
selector: 'my-register-step-user',
|
||||||
templateUrl: './register-step-user.component.html',
|
templateUrl: './register-step-user.component.html',
|
||||||
styleUrls: [ './register.component.scss' ]
|
styleUrls: [ './step.component.scss' ]
|
||||||
})
|
})
|
||||||
export class RegisterStepUserComponent extends FormReactive implements OnInit {
|
export class RegisterStepUserComponent extends FormReactive implements OnInit {
|
||||||
@Input() videoUploadDisabled = false
|
@Input() videoUploadDisabled = false
|
||||||
|
@Input() requiresEmailVerification = false
|
||||||
|
|
||||||
@Output() formBuilt = new EventEmitter<FormGroup>()
|
@Output() formBuilt = new EventEmitter<FormGroup>()
|
||||||
|
|
||||||
|
@ -49,6 +50,10 @@ export class RegisterStepUserComponent extends FormReactive implements OnInit {
|
||||||
.subscribe(([ oldValue, newValue ]) => this.onDisplayNameChange(oldValue, newValue))
|
.subscribe(([ oldValue, newValue ]) => this.onDisplayNameChange(oldValue, newValue))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMinPasswordLengthMessage () {
|
||||||
|
return USER_PASSWORD_VALIDATOR.MESSAGES.minlength
|
||||||
|
}
|
||||||
|
|
||||||
private onDisplayNameChange (oldDisplayName: string, newDisplayName: string) {
|
private onDisplayNameChange (oldDisplayName: string, newDisplayName: string) {
|
||||||
const username = this.form.value['username'] || ''
|
const username = this.form.value['username'] || ''
|
||||||
|
|
27
client/src/app/+signup/+register/steps/step.component.scss
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
@use '_variables' as *;
|
||||||
|
@use '_mixins' as *;
|
||||||
|
|
||||||
|
input:not([type=submit]) {
|
||||||
|
@include peertube-input-text(100%);
|
||||||
|
display: block;
|
||||||
|
|
||||||
|
&#username,
|
||||||
|
&#name {
|
||||||
|
width: auto !important;
|
||||||
|
flex-grow: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type=submit],
|
||||||
|
button {
|
||||||
|
@include peertube-button;
|
||||||
|
}
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: 18px;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.row {
|
||||||
|
margin-bottom: 30px;
|
||||||
|
}
|
|
@ -3,7 +3,7 @@
|
||||||
Verify account email confirmation
|
Verify account email confirmation
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<my-signup-success i18n *ngIf="!isPendingEmail && success" message="Your email has been verified and you may now login.">
|
<my-signup-success i18n *ngIf="!isPendingEmail && success" [requiresEmailVerification]="false">
|
||||||
</my-signup-success>
|
</my-signup-success>
|
||||||
|
|
||||||
<div i18n class="alert alert-success" *ngIf="isPendingEmail && success">
|
<div i18n class="alert alert-success" *ngIf="isPendingEmail && success">
|
||||||
|
|
|
@ -3,6 +3,8 @@ import { SharedFormModule } from '@app/shared/shared-forms'
|
||||||
import { SharedGlobalIconModule } from '@app/shared/shared-icons'
|
import { SharedGlobalIconModule } from '@app/shared/shared-icons'
|
||||||
import { SharedMainModule } from '@app/shared/shared-main'
|
import { SharedMainModule } from '@app/shared/shared-main'
|
||||||
import { SharedUsersModule } from '@app/shared/shared-users'
|
import { SharedUsersModule } from '@app/shared/shared-users'
|
||||||
|
import { SignupMascotComponent } from './signup-mascot.component'
|
||||||
|
import { SignupStepTitleComponent } from './signup-step-title.component'
|
||||||
import { SignupSuccessComponent } from './signup-success.component'
|
import { SignupSuccessComponent } from './signup-success.component'
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
|
@ -14,7 +16,9 @@ import { SignupSuccessComponent } from './signup-success.component'
|
||||||
],
|
],
|
||||||
|
|
||||||
declarations: [
|
declarations: [
|
||||||
SignupSuccessComponent
|
SignupSuccessComponent,
|
||||||
|
SignupStepTitleComponent,
|
||||||
|
SignupMascotComponent
|
||||||
],
|
],
|
||||||
|
|
||||||
exports: [
|
exports: [
|
||||||
|
@ -22,7 +26,9 @@ import { SignupSuccessComponent } from './signup-success.component'
|
||||||
SharedFormModule,
|
SharedFormModule,
|
||||||
SharedGlobalIconModule,
|
SharedGlobalIconModule,
|
||||||
|
|
||||||
SignupSuccessComponent
|
SignupSuccessComponent,
|
||||||
|
SignupStepTitleComponent,
|
||||||
|
SignupMascotComponent
|
||||||
],
|
],
|
||||||
|
|
||||||
providers: [
|
providers: [
|
||||||
|
|
11
client/src/app/+signup/shared/signup-mascot.component.scss
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
@use '_variables' as *;
|
||||||
|
@use '_mixins' as *;
|
||||||
|
|
||||||
|
.root {
|
||||||
|
display: inline-block;
|
||||||
|
width: 270px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div ::ng-deep svg {
|
||||||
|
color: pvar(--mainColor);
|
||||||
|
}
|
29
client/src/app/+signup/shared/signup-mascot.component.ts
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
import { DomSanitizer } from '@angular/platform-browser'
|
||||||
|
|
||||||
|
const images = {
|
||||||
|
about: require('!!raw-loader?!../../../assets/images/mascot/register/about.svg').default,
|
||||||
|
terms: require('!!raw-loader?!../../../assets/images/mascot/register/terms.svg').default,
|
||||||
|
success: require('!!raw-loader?!../../../assets/images/mascot/register/success.svg').default,
|
||||||
|
channel: require('!!raw-loader?!../../../assets/images/mascot/register/channel.svg').default,
|
||||||
|
account: require('!!raw-loader?!../../../assets/images/mascot/register/account.svg').default
|
||||||
|
}
|
||||||
|
|
||||||
|
export type MascotImageName = keyof typeof images
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-signup-mascot',
|
||||||
|
styleUrls: [ './signup-mascot.component.scss' ],
|
||||||
|
template: `<div class="root" [innerHTML]="html"></div>`
|
||||||
|
})
|
||||||
|
export class SignupMascotComponent {
|
||||||
|
@Input() imageName: MascotImageName
|
||||||
|
|
||||||
|
constructor (private sanitize: DomSanitizer) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get html () {
|
||||||
|
return this.sanitize.bypassSecurityTrustHtml(images[this.imageName])
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
<div class="step-content-title">
|
||||||
|
<my-signup-mascot [imageName]="mascotImageName"></my-signup-mascot>
|
||||||
|
|
||||||
|
<h2>
|
||||||
|
<ng-content></ng-content>
|
||||||
|
</h2>
|
||||||
|
|
||||||
|
<div class="step-content-title-separator"></div>
|
||||||
|
</div>
|
|
@ -0,0 +1,23 @@
|
||||||
|
@use '_variables' as *;
|
||||||
|
@use '_mixins' as *;
|
||||||
|
|
||||||
|
.step-content-title {
|
||||||
|
text-align: center;
|
||||||
|
margin: auto;
|
||||||
|
margin-bottom: 45px;
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 32px;
|
||||||
|
font-weight: normal;
|
||||||
|
max-width: 300px;
|
||||||
|
margin: 15px auto 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.step-content-title-separator {
|
||||||
|
height: 6px;
|
||||||
|
width: 60px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background-color: pvar(--mainColor);
|
||||||
|
margin: 5px auto 0;
|
||||||
|
}
|
12
client/src/app/+signup/shared/signup-step-title.component.ts
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
import { Component, Input } from '@angular/core'
|
||||||
|
import { MascotImageName } from './signup-mascot.component'
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'my-signup-step-title',
|
||||||
|
templateUrl: './signup-step-title.component.html',
|
||||||
|
styleUrls: [ './signup-step-title.component.scss' ]
|
||||||
|
})
|
||||||
|
export class SignupStepTitleComponent {
|
||||||
|
@Input() mascotImageName: MascotImageName
|
||||||
|
|
||||||
|
}
|
|
@ -1,20 +1,22 @@
|
||||||
<!-- Thanks: Amit Singh Sansoya from https://codepen.io/amit3200/pen/zWMJOO -->
|
<my-signup-step-title mascotImageName="success" i18n>
|
||||||
|
<strong>Welcome</strong>
|
||||||
|
<div>on {{ instanceName }}</div>
|
||||||
|
</my-signup-step-title>
|
||||||
|
|
||||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 130.2 130.2">
|
<div class="alert pt-alert-primary">
|
||||||
<circle class="path circle" fill="none" stroke="#73AF55" stroke-width="6" stroke-miterlimit="10" cx="65.1" cy="65.1" r="62.1"/>
|
<p i18n>Your account has been created!</p>
|
||||||
<polyline class="path check" fill="none" stroke="#73AF55" stroke-width="6" stroke-linecap="round" stroke-miterlimit="10" points="100.2,40.2 51.5,88.8 29.8,67.5 "/>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
<p i18n class="bottom-message">Welcome to PeerTube!</p>
|
<p i18n *ngIf="requiresEmailVerification">
|
||||||
|
<strong>Check your emails</strong> to validate your account and complete your inscription.
|
||||||
<div *ngIf="message" class="alert alert-success">
|
|
||||||
<p>{{ message }}</p>
|
|
||||||
|
|
||||||
<p i18n>
|
|
||||||
If you need help to use PeerTube, you can have a look at the <a href="https://docs.joinpeertube.org/use-setup-account" target="_blank" rel="noopener noreferrer">documentation</a>.
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<p i18n>
|
<ng-container *ngIf="!requiresEmailVerification">
|
||||||
To help moderators and other users to know <strong>who you are</strong>, don't forget to <a routerLink="/my-account/settings">set up your account profile</a> by adding an <strong>avatar</strong> and a <strong>description</strong>.
|
<p i18n>
|
||||||
</p>
|
If you need help to use PeerTube, you can have a look at the <a class="link-orange" href="https://docs.joinpeertube.org/use-setup-account" target="_blank" rel="noopener noreferrer">documentation</a>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p i18n>
|
||||||
|
To help moderators and other users to know <strong>who you are</strong>, don't forget to <a class="link-orange" routerLink="/my-account/settings">set up your account profile</a> by adding an <strong>avatar</strong> and a <strong>description</strong>.
|
||||||
|
</p>
|
||||||
|
</ng-container>
|
||||||
</div>
|
</div>
|
||||||
|
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 957 B |
|
@ -1,54 +1,6 @@
|
||||||
svg {
|
|
||||||
width: 100px;
|
|
||||||
display: block;
|
|
||||||
margin: 40px auto 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.path {
|
|
||||||
stroke-dasharray: 1000;
|
|
||||||
stroke-dashoffset: 0;
|
|
||||||
|
|
||||||
&.circle {
|
|
||||||
animation: dash .9s ease-in-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.line {
|
|
||||||
stroke-dashoffset: 1000;
|
|
||||||
animation: dash .9s .35s ease-in-out forwards;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.check {
|
|
||||||
stroke-dashoffset: -100;
|
|
||||||
animation: dash-check .9s .35s ease-in-out forwards;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.bottom-message {
|
|
||||||
text-align: center;
|
|
||||||
margin: 20px 0 60px;
|
|
||||||
font-size: 1.25em;
|
|
||||||
color: #73AF55;
|
|
||||||
}
|
|
||||||
|
|
||||||
.alert {
|
.alert {
|
||||||
font-size: 15px;
|
font-size: 18px;
|
||||||
|
max-width: 900px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
margin: auto;
|
||||||
|
|
||||||
@keyframes dash {
|
|
||||||
0% {
|
|
||||||
stroke-dashoffset: 1000;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
stroke-dashoffset: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes dash-check {
|
|
||||||
0% {
|
|
||||||
stroke-dashoffset: -100;
|
|
||||||
}
|
|
||||||
100% {
|
|
||||||
stroke-dashoffset: 900;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
import { Component, Input } from '@angular/core'
|
import { Component, Input } from '@angular/core'
|
||||||
|
import { ServerService } from '@app/core'
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
selector: 'my-signup-success',
|
selector: 'my-signup-success',
|
||||||
|
@ -6,5 +7,13 @@ import { Component, Input } from '@angular/core'
|
||||||
styleUrls: [ './signup-success.component.scss' ]
|
styleUrls: [ './signup-success.component.scss' ]
|
||||||
})
|
})
|
||||||
export class SignupSuccessComponent {
|
export class SignupSuccessComponent {
|
||||||
@Input() message: string
|
@Input() requiresEmailVerification: boolean
|
||||||
|
|
||||||
|
constructor (private serverService: ServerService) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
get instanceName () {
|
||||||
|
return this.serverService.getHTMLConfig().instance.name
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -61,7 +61,7 @@ export const USER_EXISTING_PASSWORD_VALIDATOR: BuildFormValidator = {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
export const USER_PASSWORD_VALIDATOR: BuildFormValidator = {
|
export const USER_PASSWORD_VALIDATOR = {
|
||||||
VALIDATORS: [
|
VALIDATORS: [
|
||||||
Validators.required,
|
Validators.required,
|
||||||
Validators.minLength(6),
|
Validators.minLength(6),
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<h2 class="instance-name">{{ about?.instance.name }}</h2>
|
<h2 *ngIf="displayInstanceName" class="instance-name">{{ about?.instance.name }}</h2>
|
||||||
|
|
||||||
<div class="instance-short-description">{{ about?.instance.shortDescription }}</div>
|
<div *ngIf="displayInstanceShortDescription" class="instance-short-description">{{ about?.instance.shortDescription }}</div>
|
||||||
|
|
||||||
<ngb-accordion #accordion="ngbAccordion" [closeOthers]="true">
|
<ngb-accordion #accordion="ngbAccordion" [closeOthers]="true">
|
||||||
<ngb-panel *ngIf="panels.features" id="instance-features" i18n-title title="Features found on this instance">
|
<ngb-panel *ngIf="panels.features" id="instance-features" i18n-title title="Features found on this instance">
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
</ng-template>
|
</ng-template>
|
||||||
</ngb-panel>
|
</ngb-panel>
|
||||||
|
|
||||||
<ngb-panel *ngIf="termsPanel" id="terms" i18n-title title="Terms">
|
<ngb-panel *ngIf="termsPanel" id="terms" [title]="getTermsTitle()">
|
||||||
<ng-template ngbPanelContent>
|
<ng-template ngbPanelContent>
|
||||||
<div class="block" [innerHTML]="aboutHtml.terms"></div>
|
<div class="block" [innerHTML]="aboutHtml.terms"></div>
|
||||||
</ng-template>
|
</ng-template>
|
||||||
|
|
|
@ -8,8 +8,7 @@
|
||||||
.instance-short-description {
|
.instance-short-description {
|
||||||
@include ellipsis-multiline(1rem, 3);
|
@include ellipsis-multiline(1rem, 3);
|
||||||
|
|
||||||
margin-top: 20px;
|
margin: 25px 0;
|
||||||
margin-bottom: 20px;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.block {
|
.block {
|
||||||
|
|
|
@ -15,6 +15,9 @@ export class InstanceAboutAccordionComponent implements OnInit {
|
||||||
|
|
||||||
@Output() init: EventEmitter<InstanceAboutAccordionComponent> = new EventEmitter<InstanceAboutAccordionComponent>()
|
@Output() init: EventEmitter<InstanceAboutAccordionComponent> = new EventEmitter<InstanceAboutAccordionComponent>()
|
||||||
|
|
||||||
|
@Input() displayInstanceName = true
|
||||||
|
@Input() displayInstanceShortDescription = true
|
||||||
|
|
||||||
@Input() pluginScope: PluginClientScope
|
@Input() pluginScope: PluginClientScope
|
||||||
@Input() pluginHook: ClientFilterHookName
|
@Input() pluginHook: ClientFilterHookName
|
||||||
|
|
||||||
|
@ -66,6 +69,10 @@ export class InstanceAboutAccordionComponent implements OnInit {
|
||||||
return !!(this.aboutHtml?.administrator || this.about?.instance.maintenanceLifetime || this.about?.instance.businessModel)
|
return !!(this.aboutHtml?.administrator || this.about?.instance.maintenanceLifetime || this.about?.instance.businessModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTermsTitle () {
|
||||||
|
return $localize`Terms of ${this.about.instance.name}`
|
||||||
|
}
|
||||||
|
|
||||||
get moderationPanel () {
|
get moderationPanel () {
|
||||||
return this.panels.moderation && !!this.aboutHtml.moderationInformation
|
return this.panels.moderation && !!this.aboutHtml.moderationInformation
|
||||||
}
|
}
|
||||||
|
|
45
client/src/assets/images/mascot/register/about.svg
Normal file
After Width: | Height: | Size: 56 KiB |
40
client/src/assets/images/mascot/register/account.svg
Normal file
After Width: | Height: | Size: 42 KiB |
53
client/src/assets/images/mascot/register/channel.svg
Normal file
After Width: | Height: | Size: 48 KiB |
92
client/src/assets/images/mascot/register/success.svg
Normal file
After Width: | Height: | Size: 51 KiB |
39
client/src/assets/images/mascot/register/terms.svg
Normal file
After Width: | Height: | Size: 40 KiB |
|
@ -26,6 +26,7 @@ body {
|
||||||
--mainColor: #{$main-color};
|
--mainColor: #{$main-color};
|
||||||
--mainColorLighter: #{$main-color-lighter};
|
--mainColorLighter: #{$main-color-lighter};
|
||||||
--mainColorLightest: #{$main-color-lightest};
|
--mainColorLightest: #{$main-color-lightest};
|
||||||
|
--mainColorVeryLight: #{$main-color-very-light};
|
||||||
|
|
||||||
--mainHoverColor: #{$main-hover-color};
|
--mainHoverColor: #{$main-hover-color};
|
||||||
--mainBackgroundHoverColor: #{$main-background-hover-color};
|
--mainBackgroundHoverColor: #{$main-background-hover-color};
|
||||||
|
|
|
@ -3,6 +3,24 @@
|
||||||
@use '_badges' as *;
|
@use '_badges' as *;
|
||||||
@use '_icons' as *;
|
@use '_icons' as *;
|
||||||
|
|
||||||
|
.link-orange {
|
||||||
|
color: pvar(--mainForegroundColor);
|
||||||
|
font-weight: $font-bold;
|
||||||
|
border-bottom: 3px solid pvar(--mainColor);
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: pvar(--mainForegroundColor);
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.underline-orange {
|
||||||
|
display: inline-block;
|
||||||
|
border-bottom: 3px solid pvar(--mainColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
.peertube-button {
|
.peertube-button {
|
||||||
@include peertube-button;
|
@include peertube-button;
|
||||||
}
|
}
|
||||||
|
@ -70,6 +88,11 @@
|
||||||
margin-top: 10px;
|
margin-top: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label + .form-group-description {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
margin-top: 0;
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------------------------------------------
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
@ -192,9 +215,12 @@
|
||||||
border-left-width: .25rem;
|
border-left-width: .25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.callout-info {
|
&.callout-orange {
|
||||||
border-color: pvar(--mainColorLightest);
|
border-color: pvar(--mainColorLightest);
|
||||||
border-left-color: pvar(--mainColor);
|
|
||||||
|
&:not(.callout-light) {
|
||||||
|
border-left-color: pvar(--mainColor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,3 +236,16 @@
|
||||||
top: #{-($header-height + $sub-menu-height + 20px)};
|
top: #{-($header-height + $sub-menu-height + 20px)};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.pt-alert-primary {
|
||||||
|
background-color: pvar(--mainColorVeryLight);
|
||||||
|
border: 2px solid pvar(--mainColorLightest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -46,5 +46,5 @@ $dropdown-border-radius: 3px;
|
||||||
$dropdown-link-active-color: pvar(--mainForegroundColor);
|
$dropdown-link-active-color: pvar(--mainForegroundColor);
|
||||||
$dropdown-link-active-bg: pvar(--mainBackgroundHoverColor);
|
$dropdown-link-active-bg: pvar(--mainBackgroundHoverColor);
|
||||||
|
|
||||||
$accordion-button-active-bg: pvar(--mainColorLightest);
|
$accordion-button-active-bg: pvar(--mainColorVeryLight);
|
||||||
$accordion-button-active-color: pvar(--mainForegroundColor);
|
$accordion-button-active-color: pvar(--mainForegroundColor);
|
||||||
|
|
|
@ -264,6 +264,18 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@mixin peertube-button-big {
|
||||||
|
height: auto;
|
||||||
|
padding: 10px 25px;
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1.2;
|
||||||
|
border: 0;
|
||||||
|
font-weight: $font-semibold;
|
||||||
|
|
||||||
|
// Because of primeng that redefines border-radius of all input[type="..."]
|
||||||
|
border-radius: 3px !important;
|
||||||
|
}
|
||||||
|
|
||||||
@mixin peertube-button-link {
|
@mixin peertube-button-link {
|
||||||
@include disable-default-a-behaviour;
|
@include disable-default-a-behaviour;
|
||||||
@include peertube-button;
|
@include peertube-button;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
@use 'sass:math';
|
@use 'sass:math';
|
||||||
|
@use 'sass:color';
|
||||||
@use '~bootstrap/scss/functions' as *;
|
@use '~bootstrap/scss/functions' as *;
|
||||||
|
|
||||||
$small-view: 800px;
|
$small-view: 800px;
|
||||||
|
@ -14,11 +15,12 @@ $grey-background-color: #E5E5E5;
|
||||||
$grey-background-hover-color: #EFEFEF;
|
$grey-background-hover-color: #EFEFEF;
|
||||||
$grey-foreground-color: #585858;
|
$grey-foreground-color: #585858;
|
||||||
$grey-foreground-hover-color: #303030;
|
$grey-foreground-hover-color: #303030;
|
||||||
$grey-button-outline-color: scale-color($grey-foreground-color, $alpha: -95%);
|
$grey-button-outline-color: color.scale($grey-foreground-color, $alpha: -95%);
|
||||||
|
|
||||||
$main-color: hsl(24, 90%, 50%);
|
$main-color: hsl(24, 90%, 50%);
|
||||||
$main-color-lighter: lighten($main-color, 10%);
|
$main-color-lighter: lighten($main-color, 10%);
|
||||||
$main-color-lightest: lighten($main-color, 40%);
|
$main-color-lightest: lighten($main-color, 40%);
|
||||||
|
$main-color-very-light: #fff5eb;
|
||||||
|
|
||||||
$main-hover-color: lighten($main-color, 5%);
|
$main-hover-color: lighten($main-color, 5%);
|
||||||
$main-background-hover-color: #e9ecef;
|
$main-background-hover-color: #e9ecef;
|
||||||
|
@ -109,6 +111,7 @@ $variables: (
|
||||||
--mainColor: var(--mainColor),
|
--mainColor: var(--mainColor),
|
||||||
--mainColorLighter: var(--mainColorLighter),
|
--mainColorLighter: var(--mainColorLighter),
|
||||||
--mainColorLightest: var(--mainColorLightest),
|
--mainColorLightest: var(--mainColorLightest),
|
||||||
|
--mainColorVeryLight: var(--mainColorVeryLight),
|
||||||
|
|
||||||
--mainHoverColor: var(--mainHoverColor),
|
--mainHoverColor: var(--mainHoverColor),
|
||||||
--mainBackgroundHoverColor: var(--mainBackgroundHoverColor),
|
--mainBackgroundHoverColor: var(--mainBackgroundHoverColor),
|
||||||
|
|