From 6f03f944c34f78b38a68128413b55186e0676949 Mon Sep 17 00:00:00 2001 From: Chocobozzz Date: Tue, 14 Jun 2022 13:54:54 +0200 Subject: [PATCH] Redesign register steps --- .../edit-vod-transcoding.component.html | 2 +- .../+register/custom-stepper.component.html | 37 +++-- .../+register/custom-stepper.component.scss | 139 +++++++++++------- .../+register/custom-stepper.component.ts | 9 +- .../register-step-channel.component.html | 52 ------- .../register-step-user.component.html | 64 -------- .../+signup/+register/register.component.html | 131 ++++++++++++----- .../+signup/+register/register.component.scss | 93 +++++++----- .../+signup/+register/register.component.ts | 53 ++++--- .../app/+signup/+register/register.module.ts | 9 +- .../src/app/+signup/+register/steps/index.ts | 4 + .../steps/register-step-about.component.html | 39 +++++ .../steps/register-step-about.component.scss | 53 +++++++ .../steps/register-step-about.component.ts | 19 +++ .../register-step-channel.component.html | 55 +++++++ .../register-step-channel.component.ts | 5 +- .../register-step-terms.component.html | 6 +- .../register-step-terms.component.ts | 2 +- .../steps/register-step-user.component.html | 73 +++++++++ .../register-step-user.component.ts | 7 +- .../+register/steps/step.component.scss | 27 ++++ .../verify-account-email.component.html | 2 +- .../+signup/shared/shared-signup.module.ts | 10 +- .../shared/signup-mascot.component.scss | 11 ++ .../+signup/shared/signup-mascot.component.ts | 29 ++++ .../shared/signup-step-title.component.html | 9 ++ .../shared/signup-step-title.component.scss | 23 +++ .../shared/signup-step-title.component.ts | 12 ++ .../shared/signup-success.component.html | 32 ++-- .../shared/signup-success.component.scss | 54 +------ .../shared/signup-success.component.ts | 11 +- .../shared/form-validators/user-validators.ts | 2 +- .../instance-about-accordion.component.html | 6 +- .../instance-about-accordion.component.scss | 3 +- .../instance-about-accordion.component.ts | 7 + .../assets/images/mascot/register/about.svg | 45 ++++++ .../assets/images/mascot/register/account.svg | 40 +++++ .../assets/images/mascot/register/channel.svg | 53 +++++++ .../assets/images/mascot/register/success.svg | 92 ++++++++++++ .../assets/images/mascot/register/terms.svg | 39 +++++ client/src/sass/application.scss | 1 + client/src/sass/class-helpers.scss | 43 +++++- .../sass/include/_bootstrap-variables.scss | 2 +- client/src/sass/include/_mixins.scss | 12 ++ client/src/sass/include/_variables.scss | 5 +- 45 files changed, 1049 insertions(+), 373 deletions(-) delete mode 100644 client/src/app/+signup/+register/register-step-channel.component.html delete mode 100644 client/src/app/+signup/+register/register-step-user.component.html create mode 100644 client/src/app/+signup/+register/steps/index.ts create mode 100644 client/src/app/+signup/+register/steps/register-step-about.component.html create mode 100644 client/src/app/+signup/+register/steps/register-step-about.component.scss create mode 100644 client/src/app/+signup/+register/steps/register-step-about.component.ts create mode 100644 client/src/app/+signup/+register/steps/register-step-channel.component.html rename client/src/app/+signup/+register/{ => steps}/register-step-channel.component.ts (94%) rename client/src/app/+signup/+register/{ => steps}/register-step-terms.component.html (74%) rename client/src/app/+signup/+register/{ => steps}/register-step-terms.component.ts (96%) create mode 100644 client/src/app/+signup/+register/steps/register-step-user.component.html rename client/src/app/+signup/+register/{ => steps}/register-step-user.component.ts (90%) create mode 100644 client/src/app/+signup/+register/steps/step.component.scss create mode 100644 client/src/app/+signup/shared/signup-mascot.component.scss create mode 100644 client/src/app/+signup/shared/signup-mascot.component.ts create mode 100644 client/src/app/+signup/shared/signup-step-title.component.html create mode 100644 client/src/app/+signup/shared/signup-step-title.component.scss create mode 100644 client/src/app/+signup/shared/signup-step-title.component.ts create mode 100644 client/src/assets/images/mascot/register/about.svg create mode 100644 client/src/assets/images/mascot/register/account.svg create mode 100644 client/src/assets/images/mascot/register/channel.svg create mode 100644 client/src/assets/images/mascot/register/success.svg create mode 100644 client/src/assets/images/mascot/register/terms.svg diff --git a/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html b/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html index 3d8ab094f..2a965ac97 100644 --- a/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html +++ b/client/src/app/+admin/config/edit-custom-config/edit-vod-transcoding.component.html @@ -4,7 +4,7 @@
-
+
Estimating a server's capacity to transcode and stream videos isn't easy and we can't tune PeerTube automatically. diff --git a/client/src/app/+signup/+register/custom-stepper.component.html b/client/src/app/+signup/+register/custom-stepper.component.html index a07e2fca3..f43a46842 100644 --- a/client/src/app/+signup/+register/custom-stepper.component.html +++ b/client/src/app/+signup/+register/custom-stepper.component.html @@ -1,24 +1,29 @@ -
+
- -
-
- Step {{ i + 1 }} - -
+
+ +
+
+ Step {{ i + 1 }} + +
+ +
+
-
{{ step.label }}
-
+
{{ step.label }}
+
- -
- + +
+ +
-
+
diff --git a/client/src/app/+signup/+register/custom-stepper.component.scss b/client/src/app/+signup/+register/custom-stepper.component.scss index 6a8815c77..4dda93489 100644 --- a/client/src/app/+signup/+register/custom-stepper.component.scss +++ b/client/src/app/+signup/+register/custom-stepper.component.scss @@ -2,76 +2,113 @@ @use '_variables' as *; @use '_mixins' as *; -$grey-color: #9CA3AB; -$index-block-height: 32px; +$index-block-height: 40px; -.container { - @include padding-left(0); - @include padding-right(0); - max-width: unset !important; +header { + margin-bottom: 40px; + padding-bottom: 60px; + width: 100%; + background-color: pvar(--mainColorVeryLight); } -header { +.header-steps { + max-width: 800px; display: flex; justify-content: space-between; - font-size: 15px; - margin-bottom: 30px; + margin: auto; + + // Useful on small screens + padding: 0 20px; +} - .step-info { - color: $grey-color; +.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; - flex-direction: column; + justify-content: center; align-items: center; - width: $index-block-height; + border: 1px solid pvar(--mainColor); + + my-global-icon { + @include apply-svg-color(pvar(--mainColor)); - &:not(.c-hand) { - cursor: default; + display: flex; + width: 12px; + height: 12px; } + } +} +.step-label { + width: max-content; + font-size: 18px; +} + +.step-info { + 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 { - display: flex; - justify-content: center; - align-items: center; - width: $index-block-height; - height: $index-block-height; - border-radius: 100px; - border: 2px solid $grey-color; - margin-bottom: 10px; - - my-global-icon { - @include apply-svg-color(pvar(--mainBackgroundColor)); - - width: 22px; - height: 22px; - } + background-color: pvar(--mainColor); + color: pvar(--mainBackgroundColor); } .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); - } - } + &.active { + opacity: 1; + } +} - &.completed { - cursor: pointer; - } +.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; } +} - .connector { - flex: auto; - margin: math.div($index-block-height, 2) 10px 0 10px; - height: 2px; - background-color: $grey-color; +@media screen and (max-width: $small-view) { + .step-label { + width: auto; + text-align: center; } } diff --git a/client/src/app/+signup/+register/custom-stepper.component.ts b/client/src/app/+signup/+register/custom-stepper.component.ts index 3b7ba40e8..4c308f7b6 100644 --- a/client/src/app/+signup/+register/custom-stepper.component.ts +++ b/client/src/app/+signup/+register/custom-stepper.component.ts @@ -14,13 +14,10 @@ export class CustomStepperComponent extends CdkStepper { } isCompleted (step: CdkStep) { - return step.stepControl?.dirty && step.stepControl.valid + return step.completed } - isAccessible (index: number) { - const stepsCompletedMap = this.steps.map(step => this.isCompleted(step)) - return index === 0 - ? true - : stepsCompletedMap[index - 1] + isAccessible (step: CdkStep) { + return step.editable && step.completed } } diff --git a/client/src/app/+signup/+register/register-step-channel.component.html b/client/src/app/+signup/+register/register-step-channel.component.html deleted file mode 100644 index 888e3245d..000000000 --- a/client/src/app/+signup/+register/register-step-channel.component.html +++ /dev/null @@ -1,52 +0,0 @@ -
- -
-

- A channel is an entity in which you upload your videos. Creating several of them helps you to organize and separate your content.
- 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. -

- -

- Other users can decide to subscribe any channel they want, to be notified when you publish a new video. -

-
- -
- - -
- -
- -
- {{ formErrors.displayName }} -
-
- -
- - -
- -
@{{ instanceHost }}
-
- -
- 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. -
- -
- {{ formErrors.name }} -
- -
- Channel name cannot be the same as your account name. You can click on the first step to update your account name. -
-
-
diff --git a/client/src/app/+signup/+register/register-step-user.component.html b/client/src/app/+signup/+register/register-step-user.component.html deleted file mode 100644 index 6e367b4c7..000000000 --- a/client/src/app/+signup/+register/register-step-user.component.html +++ /dev/null @@ -1,64 +0,0 @@ -
- -
- Video uploads are disabled on this instance, hence your account won't be able to upload videos. -
- -
- - -
- -
- -
- {{ formErrors.displayName }} -
-
- -
- - -
- - @{{ instanceHost }} -
- -
- 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. -
- -
- {{ formErrors.username }} -
-
- -
- - -
- {{ formErrors.email }} -
-
- -
- - -
- {{ formErrors.password }} -
-
- -
diff --git a/client/src/app/+signup/+register/register.component.html b/client/src/app/+signup/+register/register.component.html index 5c4fe5f0b..76b145604 100644 --- a/client/src/app/+signup/+register/register.component.html +++ b/client/src/app/+signup/+register/register.component.html @@ -1,64 +1,121 @@ -
+
-
+

+ {{ instanceName }} + > Create an account -

+ - -
{{ info }}
- -
-
- - -
- -
+
+ + + + + Create an account +
on {{ instanceName }}
+
+ + + +
+ + I already have an account, I log in + - + +
+
+ + + Terms +
of {{ instanceName }}
+
+ + + + + +
+ - +
+
+ + + + Setup +
your account
+
- - + +
- +
+
- - + + +
Create
+ your first channel +
+ + +
+ +
+ + I don't want to create a channel + + +
You will be able to create a channel later
+
+ - +
+
- -
- + +
+ -
PeerTube is creating your account...
-
+
PeerTube is creating your account...
+
+ +
{{ signupError }}
-
{{ error }}
-
-
-
+ + +
+ +
+
+
diff --git a/client/src/app/+signup/+register/register.component.scss b/client/src/app/+signup/+register/register.component.scss index 53093a81a..5d0df81bd 100644 --- a/client/src/app/+signup/+register/register.component.scss +++ b/client/src/app/+signup/+register/register.component.scss @@ -2,7 +2,7 @@ @use '_mixins' as *; .alert { - font-size: 15px; + font-size: 16px; text-align: center; } @@ -10,61 +10,75 @@ padding-top: 30vh; } -.wrapper { +.header-title { + font-weight: normal; + font-size: 15px; + background-color: pvar(--mainColorVeryLight); + padding: 35px 25px 15px 25px; + margin: 0; +} + +.register-content { + font-size: 16px; +} + +my-instance-about-accordion { + display: block; + margin-bottom: 25px; +} + +.step-buttons { display: flex; - flex-direction: column; + flex-wrap: wrap; + align-items: center; - .register-form { - max-width: 600px; - align-self: center; + .skip-step { + @include margin-right(30px); + + display: inline-block; } - .register-form, - .instance-information { - width: 100%; + .skip-step-description { + margin-top: 5px; + font-size: 14px; } - .instance-information { - margin-bottom: 15px; + .underline-orange { + color: pvar(--mainForegroundColor); + + &:hover { + opacity: 0.8; + } } -} -input:not([type=submit]) { - @include peertube-input-text(100%); - display: block; + button, + .skip-step { + margin-top: 20px; + margin-bottom: 20px; + } - &#username, - &#name { - width: auto !important; - flex-grow: 1; + .skip-step, + button[cdkStepperNext] { + @include margin-left(auto); + } + + .skip-step + button[cdkStepperNext] { + @include margin-left(0); } } -input[type=submit], button { - @include peertube-button; + @include peertube-button-big; &[cdkStepperNext] { @include orange-button; - - // Chrome does not support inline-end - float: right; - float: inline-end; } &[cdkStepperPrevious] { @include grey-button; - - // Chrome does not support inline-start - float: left; - float: inline-start; } } -.name-information { - margin-top: 10px; -} - .done-loader { display: flex; justify-content: center; @@ -73,13 +87,16 @@ button { my-loader { margin-bottom: 20px; + } +} - ::ng-deep .loader div { - border-color: pvar(--mainColor) transparent transparent transparent; - } +@media screen and (max-width: $small-view) { + .step-buttons { + justify-content: space-between; - + div { - font-size: 15px; + .skip-step, + button[cdkStepperNext] { + @include margin-left(0); } } } diff --git a/client/src/app/+signup/+register/register.component.ts b/client/src/app/+signup/+register/register.component.ts index b4a7c0d0e..396b27e5a 100644 --- a/client/src/app/+signup/+register/register.component.ts +++ b/client/src/app/+signup/+register/register.component.ts @@ -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 { ActivatedRoute } from '@angular/router' import { AuthService } from '@app/core' @@ -15,13 +16,15 @@ import { ServerConfig } from '@shared/models/server' styleUrls: [ './register.component.scss' ] }) export class RegisterComponent implements OnInit { + @ViewChild('lastStep') lastStep: CdkStep + accordion: NgbAccordion - info: string = null - error: string = null - success: string = null - signupDone = false + + signupError: string + signupSuccess = false videoUploadDisabled: boolean + videoQuota: number formStepTerms: FormGroup formStepUser: FormGroup @@ -39,8 +42,8 @@ export class RegisterComponent implements OnInit { moderation: false } - defaultPreviousStepButtonLabel = $localize`:Button on the registration form to go to the previous step:Back` - defaultNextStepButtonLabel = $localize`:Button on the registration form to go to the previous step:Next` + 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:Go to the next step` stepUserButtonLabel = this.defaultNextStepButtonLabel signupDisabled = false @@ -62,7 +65,11 @@ export class RegisterComponent implements OnInit { return this.serverConfig.signup.minimumAge } - ngOnInit (): void { + get instanceName () { + return this.serverConfig.instance.name + } + + ngOnInit () { this.serverConfig = this.route.snapshot.data.serverConfig if (this.serverConfig.signup.allowed === false || this.serverConfig.signup.allowedForCurrentIP === false) { @@ -70,7 +77,9 @@ export class RegisterComponent implements OnInit { return } - this.videoUploadDisabled = this.serverConfig.user.videoQuota === 0 + this.videoQuota = this.serverConfig.user.videoQuota + this.videoUploadDisabled = this.videoQuota === 0 + this.stepUserButtonLabel = this.videoUploadDisabled ? $localize`:Button on the registration form to finalize the account and channel creation:Signup` : this.defaultNextStepButtonLabel @@ -120,21 +129,31 @@ export class RegisterComponent implements OnInit { this.aboutHtml = instanceAboutAccordion.aboutHtml } + skipChannelCreation () { + this.formStepChannel.reset() + this.lastStep.select() + this.signup() + } + async signup () { - this.error = null + this.signupError = undefined 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', 'filter:api.signup.registration.create.params' ) this.userSignupService.signup(body).subscribe({ next: () => { - this.signupDone = true - if (this.requiresEmailVerification) { - this.info = $localize`Now please check your emails to verify your account and complete signup.` + this.signupSuccess = true return } @@ -142,17 +161,17 @@ export class RegisterComponent implements OnInit { this.authService.login(body.username, body.password) .subscribe({ next: () => { - this.success = $localize`You are now logged in as ${body.username}!` + this.signupSuccess = true }, error: err => { - this.error = err.message + this.signupError = err.message } }) }, error: err => { - this.error = err.message + this.signupError = err.message } }) } diff --git a/client/src/app/+signup/+register/register.module.ts b/client/src/app/+signup/+register/register.module.ts index 52cdb33bc..684aae2e9 100644 --- a/client/src/app/+signup/+register/register.module.ts +++ b/client/src/app/+signup/+register/register.module.ts @@ -2,15 +2,15 @@ import { CdkStepperModule } from '@angular/cdk/stepper' import { NgModule } from '@angular/core' import { SharedSignupModule } from '@app/+signup/shared/shared-signup.module' import { SharedInstanceModule } from '@app/shared/shared-instance' +import { SharedMainModule } from '@app/shared/shared-main' import { CustomStepperComponent } from './custom-stepper.component' 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 { RegisterStepAboutComponent, RegisterStepChannelComponent, RegisterStepTermsComponent, RegisterStepUserComponent } from './steps' @NgModule({ imports: [ + SharedMainModule, RegisterRoutingModule, CdkStepperModule, @@ -25,7 +25,8 @@ import { RegisterComponent } from './register.component' CustomStepperComponent, RegisterStepChannelComponent, RegisterStepTermsComponent, - RegisterStepUserComponent + RegisterStepUserComponent, + RegisterStepAboutComponent ], exports: [ diff --git a/client/src/app/+signup/+register/steps/index.ts b/client/src/app/+signup/+register/steps/index.ts new file mode 100644 index 000000000..b5eae7468 --- /dev/null +++ b/client/src/app/+signup/+register/steps/index.ts @@ -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' diff --git a/client/src/app/+signup/+register/steps/register-step-about.component.html b/client/src/app/+signup/+register/steps/register-step-about.component.html new file mode 100644 index 000000000..f93de8ce9 --- /dev/null +++ b/client/src/app/+signup/+register/steps/register-step-about.component.html @@ -0,0 +1,39 @@ +
+

Why creating an account?

+ +

+ As you probably noticed: creating an account is not necessary to watch video son {{ instanceName }}. +
+ However, creating an account on {{ instanceName }} will allow you to: +

+ +
    +
  • Comment videos
  • +
  • Subscribe to channels to be notified of new videos
  • +
  • Have access to your watch history
  • +
  • Create your channel to publish videos
  • +
+
+ +
+

You're using Mastodon, ActivityPub or a RSS feed aggregator?

+ +

+ You can already follow {{ instanceName }} using your favorite tool. +

+
+ +
+
+ mascot +
+ +
+

This website is a GAFAM alternative

+ +

+ {{ instanceName }} has been created using PeerTube, a video creation platform developed by Framasoft. + Framasoft is a french non-profit organization that offers alternatives to Big Tech's digital tools +

+
+
diff --git a/client/src/app/+signup/+register/steps/register-step-about.component.scss b/client/src/app/+signup/+register/steps/register-step-about.component.scss new file mode 100644 index 000000000..ab6d6dd4d --- /dev/null +++ b/client/src/app/+signup/+register/steps/register-step-about.component.scss @@ -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; + } + } +} diff --git a/client/src/app/+signup/+register/steps/register-step-about.component.ts b/client/src/app/+signup/+register/steps/register-step-about.component.ts new file mode 100644 index 000000000..9a0941016 --- /dev/null +++ b/client/src/app/+signup/+register/steps/register-step-about.component.ts @@ -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 + } +} diff --git a/client/src/app/+signup/+register/steps/register-step-channel.component.html b/client/src/app/+signup/+register/steps/register-step-channel.component.html new file mode 100644 index 000000000..c79256c68 --- /dev/null +++ b/client/src/app/+signup/+register/steps/register-step-channel.component.html @@ -0,0 +1,55 @@ +
+

+ You want to publish videos on {{ instanceName }}? Then you need to create your first channel. +

+ +

+ You might want to create a channel by theme: 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. +

+ +

+ {{ instanceName }} administrators allow you to publish up to {{ videoQuota | bytes: 0 }} of videos on their website. +

+
+ +
+ +
+ +
+ + +
This is the name that will be publicly visible by other users.
+ +
+ +
+ +
{{ formErrors.displayName }}
+
+ +
+ + +
This is the name that will be displayed in your profile URL.
+ +
+ +
@{{ instanceHost }}
+
+ +
{{ formErrors.name }}
+ +
+ Channel identifier cannot be the same as your account name. You can click on the first step to update your account name. +
+
+
+
diff --git a/client/src/app/+signup/+register/register-step-channel.component.ts b/client/src/app/+signup/+register/steps/register-step-channel.component.ts similarity index 94% rename from client/src/app/+signup/+register/register-step-channel.component.ts rename to client/src/app/+signup/+register/steps/register-step-channel.component.ts index 1bc0ccfd3..c10b568ba 100644 --- a/client/src/app/+signup/+register/register-step-channel.component.ts +++ b/client/src/app/+signup/+register/steps/register-step-channel.component.ts @@ -9,10 +9,13 @@ import { UserSignupService } from '@app/shared/shared-users' @Component({ selector: 'my-register-step-channel', templateUrl: './register-step-channel.component.html', - styleUrls: [ './register.component.scss' ] + styleUrls: [ './step.component.scss' ] }) export class RegisterStepChannelComponent extends FormReactive implements OnInit { @Input() username: string + @Input() instanceName: string + @Input() videoQuota: number + @Output() formBuilt = new EventEmitter() constructor ( diff --git a/client/src/app/+signup/+register/register-step-terms.component.html b/client/src/app/+signup/+register/steps/register-step-terms.component.html similarity index 74% rename from client/src/app/+signup/+register/register-step-terms.component.html rename to client/src/app/+signup/+register/steps/register-step-terms.component.html index 717a289e6..f54ca77e2 100644 --- a/client/src/app/+signup/+register/register-step-terms.component.html +++ b/client/src/app/+signup/+register/steps/register-step-terms.component.html @@ -4,15 +4,13 @@ I am at least {{ minimumAge }} years old and agree - to the Terms + to the Terms and to the Code of Conduct of this instance -
- {{ formErrors.terms }} -
+
{{ formErrors.terms }}
diff --git a/client/src/app/+signup/+register/register-step-terms.component.ts b/client/src/app/+signup/+register/steps/register-step-terms.component.ts similarity index 96% rename from client/src/app/+signup/+register/register-step-terms.component.ts rename to client/src/app/+signup/+register/steps/register-step-terms.component.ts index 20c1ae1c4..87d16696e 100644 --- a/client/src/app/+signup/+register/register-step-terms.component.ts +++ b/client/src/app/+signup/+register/steps/register-step-terms.component.ts @@ -8,7 +8,7 @@ import { FormReactive, FormValidatorService } from '@app/shared/shared-forms' @Component({ selector: 'my-register-step-terms', templateUrl: './register-step-terms.component.html', - styleUrls: [ './register.component.scss' ] + styleUrls: [ './step.component.scss' ] }) export class RegisterStepTermsComponent extends FormReactive implements OnInit { @Input() hasCodeOfConduct = false diff --git a/client/src/app/+signup/+register/steps/register-step-user.component.html b/client/src/app/+signup/+register/steps/register-step-user.component.html new file mode 100644 index 000000000..bffcf0346 --- /dev/null +++ b/client/src/app/+signup/+register/steps/register-step-user.component.html @@ -0,0 +1,73 @@ +
+ Video uploads are disabled on this instance, hence your account won't be able to upload videos. +
+ +
+
+ +
+ + +
+ This is the name that will be publicly visible by other users. +
+ +
+ +
+ +
{{ formErrors.displayName }}
+
+ +
+ + +
+ This is the name that will be displayed in your profile URL. +
+ +
+ + @{{ instanceHost }} +
+ +
{{ formErrors.username }}
+
+
+ +
+
+ + +
+ This email address will be used to validate your account. +
+ + + +
{{ formErrors.email }}
+
+ +
+ + +
{{ getMinPasswordLengthMessage() }}
+ + + +
{{ formErrors.password }}
+
+
+
diff --git a/client/src/app/+signup/+register/register-step-user.component.ts b/client/src/app/+signup/+register/steps/register-step-user.component.ts similarity index 90% rename from client/src/app/+signup/+register/register-step-user.component.ts rename to client/src/app/+signup/+register/steps/register-step-user.component.ts index 92ddfca2e..b89e38a28 100644 --- a/client/src/app/+signup/+register/register-step-user.component.ts +++ b/client/src/app/+signup/+register/steps/register-step-user.component.ts @@ -14,10 +14,11 @@ import { UserSignupService } from '@app/shared/shared-users' @Component({ selector: 'my-register-step-user', templateUrl: './register-step-user.component.html', - styleUrls: [ './register.component.scss' ] + styleUrls: [ './step.component.scss' ] }) export class RegisterStepUserComponent extends FormReactive implements OnInit { @Input() videoUploadDisabled = false + @Input() requiresEmailVerification = false @Output() formBuilt = new EventEmitter() @@ -49,6 +50,10 @@ export class RegisterStepUserComponent extends FormReactive implements OnInit { .subscribe(([ oldValue, newValue ]) => this.onDisplayNameChange(oldValue, newValue)) } + getMinPasswordLengthMessage () { + return USER_PASSWORD_VALIDATOR.MESSAGES.minlength + } + private onDisplayNameChange (oldDisplayName: string, newDisplayName: string) { const username = this.form.value['username'] || '' diff --git a/client/src/app/+signup/+register/steps/step.component.scss b/client/src/app/+signup/+register/steps/step.component.scss new file mode 100644 index 000000000..35cfdae91 --- /dev/null +++ b/client/src/app/+signup/+register/steps/step.component.scss @@ -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; +} diff --git a/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html b/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html index 47519c943..327e23f3f 100644 --- a/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html +++ b/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html @@ -3,7 +3,7 @@ Verify account email confirmation
- +
diff --git a/client/src/app/+signup/shared/shared-signup.module.ts b/client/src/app/+signup/shared/shared-signup.module.ts index f8b224c71..0aa08f3e2 100644 --- a/client/src/app/+signup/shared/shared-signup.module.ts +++ b/client/src/app/+signup/shared/shared-signup.module.ts @@ -3,6 +3,8 @@ import { SharedFormModule } from '@app/shared/shared-forms' import { SharedGlobalIconModule } from '@app/shared/shared-icons' import { SharedMainModule } from '@app/shared/shared-main' 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' @NgModule({ @@ -14,7 +16,9 @@ import { SignupSuccessComponent } from './signup-success.component' ], declarations: [ - SignupSuccessComponent + SignupSuccessComponent, + SignupStepTitleComponent, + SignupMascotComponent ], exports: [ @@ -22,7 +26,9 @@ import { SignupSuccessComponent } from './signup-success.component' SharedFormModule, SharedGlobalIconModule, - SignupSuccessComponent + SignupSuccessComponent, + SignupStepTitleComponent, + SignupMascotComponent ], providers: [ diff --git a/client/src/app/+signup/shared/signup-mascot.component.scss b/client/src/app/+signup/shared/signup-mascot.component.scss new file mode 100644 index 000000000..5eebfb014 --- /dev/null +++ b/client/src/app/+signup/shared/signup-mascot.component.scss @@ -0,0 +1,11 @@ +@use '_variables' as *; +@use '_mixins' as *; + +.root { + display: inline-block; + width: 270px; +} + +div ::ng-deep svg { + color: pvar(--mainColor); +} diff --git a/client/src/app/+signup/shared/signup-mascot.component.ts b/client/src/app/+signup/shared/signup-mascot.component.ts new file mode 100644 index 000000000..a96ccffee --- /dev/null +++ b/client/src/app/+signup/shared/signup-mascot.component.ts @@ -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: `
` +}) +export class SignupMascotComponent { + @Input() imageName: MascotImageName + + constructor (private sanitize: DomSanitizer) { + + } + + get html () { + return this.sanitize.bypassSecurityTrustHtml(images[this.imageName]) + } +} diff --git a/client/src/app/+signup/shared/signup-step-title.component.html b/client/src/app/+signup/shared/signup-step-title.component.html new file mode 100644 index 000000000..9cf4c4826 --- /dev/null +++ b/client/src/app/+signup/shared/signup-step-title.component.html @@ -0,0 +1,9 @@ +
+ + +

+ +

+ +
+
diff --git a/client/src/app/+signup/shared/signup-step-title.component.scss b/client/src/app/+signup/shared/signup-step-title.component.scss new file mode 100644 index 000000000..1e0cb2440 --- /dev/null +++ b/client/src/app/+signup/shared/signup-step-title.component.scss @@ -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; +} diff --git a/client/src/app/+signup/shared/signup-step-title.component.ts b/client/src/app/+signup/shared/signup-step-title.component.ts new file mode 100644 index 000000000..9664eb7f3 --- /dev/null +++ b/client/src/app/+signup/shared/signup-step-title.component.ts @@ -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 + +} diff --git a/client/src/app/+signup/shared/signup-success.component.html b/client/src/app/+signup/shared/signup-success.component.html index d66e8b568..c14889c72 100644 --- a/client/src/app/+signup/shared/signup-success.component.html +++ b/client/src/app/+signup/shared/signup-success.component.html @@ -1,20 +1,22 @@ - + + Welcome +
on {{ instanceName }}
+
- - - - +
+

Your account has been created!

-

Welcome to PeerTube!

- -
-

{{ message }}

- -

- If you need help to use PeerTube, you can have a look at the documentation. +

+ Check your emails to validate your account and complete your inscription.

-

- To help moderators and other users to know who you are, don't forget to set up your account profile by adding an avatar and a description. -

+ +

+ If you need help to use PeerTube, you can have a look at the documentation. +

+ +

+ To help moderators and other users to know who you are, don't forget to set up your account profile by adding an avatar and a description. +

+
diff --git a/client/src/app/+signup/shared/signup-success.component.scss b/client/src/app/+signup/shared/signup-success.component.scss index b302366e2..918349ba0 100644 --- a/client/src/app/+signup/shared/signup-success.component.scss +++ b/client/src/app/+signup/shared/signup-success.component.scss @@ -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 { - font-size: 15px; + font-size: 18px; + max-width: 900px; text-align: center; -} - -@keyframes dash { - 0% { - stroke-dashoffset: 1000; - } - 100% { - stroke-dashoffset: 0; - } -} - -@keyframes dash-check { - 0% { - stroke-dashoffset: -100; - } - 100% { - stroke-dashoffset: 900; - } + margin: auto; } diff --git a/client/src/app/+signup/shared/signup-success.component.ts b/client/src/app/+signup/shared/signup-success.component.ts index 19fb5922a..a03f3819d 100644 --- a/client/src/app/+signup/shared/signup-success.component.ts +++ b/client/src/app/+signup/shared/signup-success.component.ts @@ -1,4 +1,5 @@ import { Component, Input } from '@angular/core' +import { ServerService } from '@app/core' @Component({ selector: 'my-signup-success', @@ -6,5 +7,13 @@ import { Component, Input } from '@angular/core' styleUrls: [ './signup-success.component.scss' ] }) export class SignupSuccessComponent { - @Input() message: string + @Input() requiresEmailVerification: boolean + + constructor (private serverService: ServerService) { + + } + + get instanceName () { + return this.serverService.getHTMLConfig().instance.name + } } diff --git a/client/src/app/shared/form-validators/user-validators.ts b/client/src/app/shared/form-validators/user-validators.ts index 6d0dea64e..3262853d8 100644 --- a/client/src/app/shared/form-validators/user-validators.ts +++ b/client/src/app/shared/form-validators/user-validators.ts @@ -61,7 +61,7 @@ export const USER_EXISTING_PASSWORD_VALIDATOR: BuildFormValidator = { } } -export const USER_PASSWORD_VALIDATOR: BuildFormValidator = { +export const USER_PASSWORD_VALIDATOR = { VALIDATORS: [ Validators.required, Validators.minLength(6), diff --git a/client/src/app/shared/shared-instance/instance-about-accordion.component.html b/client/src/app/shared/shared-instance/instance-about-accordion.component.html index 73e511d1c..466d73ca4 100644 --- a/client/src/app/shared/shared-instance/instance-about-accordion.component.html +++ b/client/src/app/shared/shared-instance/instance-about-accordion.component.html @@ -1,6 +1,6 @@ -

{{ about?.instance.name }}

+

{{ about?.instance.name }}

-
{{ about?.instance.shortDescription }}
+
{{ about?.instance.shortDescription }}
@@ -32,7 +32,7 @@ - +
diff --git a/client/src/app/shared/shared-instance/instance-about-accordion.component.scss b/client/src/app/shared/shared-instance/instance-about-accordion.component.scss index 8e5dfb064..0da7aede9 100644 --- a/client/src/app/shared/shared-instance/instance-about-accordion.component.scss +++ b/client/src/app/shared/shared-instance/instance-about-accordion.component.scss @@ -8,8 +8,7 @@ .instance-short-description { @include ellipsis-multiline(1rem, 3); - margin-top: 20px; - margin-bottom: 20px; + margin: 25px 0; } .block { diff --git a/client/src/app/shared/shared-instance/instance-about-accordion.component.ts b/client/src/app/shared/shared-instance/instance-about-accordion.component.ts index b9f57e2a4..e13703c03 100644 --- a/client/src/app/shared/shared-instance/instance-about-accordion.component.ts +++ b/client/src/app/shared/shared-instance/instance-about-accordion.component.ts @@ -15,6 +15,9 @@ export class InstanceAboutAccordionComponent implements OnInit { @Output() init: EventEmitter = new EventEmitter() + @Input() displayInstanceName = true + @Input() displayInstanceShortDescription = true + @Input() pluginScope: PluginClientScope @Input() pluginHook: ClientFilterHookName @@ -66,6 +69,10 @@ export class InstanceAboutAccordionComponent implements OnInit { return !!(this.aboutHtml?.administrator || this.about?.instance.maintenanceLifetime || this.about?.instance.businessModel) } + getTermsTitle () { + return $localize`Terms of ${this.about.instance.name}` + } + get moderationPanel () { return this.panels.moderation && !!this.aboutHtml.moderationInformation } diff --git a/client/src/assets/images/mascot/register/about.svg b/client/src/assets/images/mascot/register/about.svg new file mode 100644 index 000000000..3c4c97a5d --- /dev/null +++ b/client/src/assets/images/mascot/register/about.svg @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/images/mascot/register/account.svg b/client/src/assets/images/mascot/register/account.svg new file mode 100644 index 000000000..e36177693 --- /dev/null +++ b/client/src/assets/images/mascot/register/account.svg @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/images/mascot/register/channel.svg b/client/src/assets/images/mascot/register/channel.svg new file mode 100644 index 000000000..20e5328db --- /dev/null +++ b/client/src/assets/images/mascot/register/channel.svg @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/images/mascot/register/success.svg b/client/src/assets/images/mascot/register/success.svg new file mode 100644 index 000000000..11166af38 --- /dev/null +++ b/client/src/assets/images/mascot/register/success.svg @@ -0,0 +1,92 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/assets/images/mascot/register/terms.svg b/client/src/assets/images/mascot/register/terms.svg new file mode 100644 index 000000000..09f420fbf --- /dev/null +++ b/client/src/assets/images/mascot/register/terms.svg @@ -0,0 +1,39 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/client/src/sass/application.scss b/client/src/sass/application.scss index 893afdd2b..2af456375 100644 --- a/client/src/sass/application.scss +++ b/client/src/sass/application.scss @@ -26,6 +26,7 @@ body { --mainColor: #{$main-color}; --mainColorLighter: #{$main-color-lighter}; --mainColorLightest: #{$main-color-lightest}; + --mainColorVeryLight: #{$main-color-very-light}; --mainHoverColor: #{$main-hover-color}; --mainBackgroundHoverColor: #{$main-background-hover-color}; diff --git a/client/src/sass/class-helpers.scss b/client/src/sass/class-helpers.scss index 45d45e0f8..0b2e6176a 100644 --- a/client/src/sass/class-helpers.scss +++ b/client/src/sass/class-helpers.scss @@ -3,6 +3,24 @@ @use '_badges' 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 { @include peertube-button; } @@ -70,6 +88,11 @@ margin-top: 10px; } +label + .form-group-description { + margin-bottom: 10px; + margin-top: 0; +} + // --------------------------------------------------------------------------- @@ -192,9 +215,12 @@ border-left-width: .25rem; } - &.callout-info { + &.callout-orange { 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)}; } } + +// --------------------------------------------------------------------------- + +.alert { + p:last-child { + margin-bottom: 0; + } + + &.pt-alert-primary { + background-color: pvar(--mainColorVeryLight); + border: 2px solid pvar(--mainColorLightest); + } +} diff --git a/client/src/sass/include/_bootstrap-variables.scss b/client/src/sass/include/_bootstrap-variables.scss index c103e485a..796850174 100644 --- a/client/src/sass/include/_bootstrap-variables.scss +++ b/client/src/sass/include/_bootstrap-variables.scss @@ -46,5 +46,5 @@ $dropdown-border-radius: 3px; $dropdown-link-active-color: pvar(--mainForegroundColor); $dropdown-link-active-bg: pvar(--mainBackgroundHoverColor); -$accordion-button-active-bg: pvar(--mainColorLightest); +$accordion-button-active-bg: pvar(--mainColorVeryLight); $accordion-button-active-color: pvar(--mainForegroundColor); diff --git a/client/src/sass/include/_mixins.scss b/client/src/sass/include/_mixins.scss index 22c3b2a2f..565012717 100644 --- a/client/src/sass/include/_mixins.scss +++ b/client/src/sass/include/_mixins.scss @@ -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 { @include disable-default-a-behaviour; @include peertube-button; diff --git a/client/src/sass/include/_variables.scss b/client/src/sass/include/_variables.scss index 6102e32f1..ef22fafe0 100644 --- a/client/src/sass/include/_variables.scss +++ b/client/src/sass/include/_variables.scss @@ -1,4 +1,5 @@ @use 'sass:math'; +@use 'sass:color'; @use '~bootstrap/scss/functions' as *; $small-view: 800px; @@ -14,11 +15,12 @@ $grey-background-color: #E5E5E5; $grey-background-hover-color: #EFEFEF; $grey-foreground-color: #585858; $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-lighter: lighten($main-color, 10%); $main-color-lightest: lighten($main-color, 40%); +$main-color-very-light: #fff5eb; $main-hover-color: lighten($main-color, 5%); $main-background-hover-color: #e9ecef; @@ -109,6 +111,7 @@ $variables: ( --mainColor: var(--mainColor), --mainColorLighter: var(--mainColorLighter), --mainColorLightest: var(--mainColorLightest), + --mainColorVeryLight: var(--mainColorVeryLight), --mainHoverColor: var(--mainHoverColor), --mainBackgroundHoverColor: var(--mainBackgroundHoverColor), -- 2.41.0