Add success icon on registration
authorChocobozzz <me@florianbigard.com>
Wed, 29 May 2019 12:39:49 +0000 (14:39 +0200)
committerChocobozzz <me@florianbigard.com>
Wed, 29 May 2019 12:39:49 +0000 (14:39 +0200)
52 files changed:
client/src/app/+signup/+register/custom-stepper.component.html [new file with mode: 0644]
client/src/app/+signup/+register/custom-stepper.component.scss [new file with mode: 0644]
client/src/app/+signup/+register/custom-stepper.component.ts [new file with mode: 0644]
client/src/app/+signup/+register/register-routing.module.ts [new file with mode: 0644]
client/src/app/+signup/+register/register-step-channel.component.html [new file with mode: 0644]
client/src/app/+signup/+register/register-step-channel.component.ts [new file with mode: 0644]
client/src/app/+signup/+register/register-step-user.component.html [new file with mode: 0644]
client/src/app/+signup/+register/register-step-user.component.ts [new file with mode: 0644]
client/src/app/+signup/+register/register.component.html [new file with mode: 0644]
client/src/app/+signup/+register/register.component.scss [new file with mode: 0644]
client/src/app/+signup/+register/register.component.ts [new file with mode: 0644]
client/src/app/+signup/+register/register.module.ts [new file with mode: 0644]
client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html [new file with mode: 0644]
client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.scss [new file with mode: 0644]
client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts [new file with mode: 0644]
client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.html [new file with mode: 0644]
client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts [new file with mode: 0644]
client/src/app/+signup/+verify-account/verify-account-routing.module.ts [new file with mode: 0644]
client/src/app/+signup/+verify-account/verify-account.module.ts [new file with mode: 0644]
client/src/app/+signup/shared/signup-shared.module.ts [new file with mode: 0644]
client/src/app/+signup/shared/signup-success.component.html [new file with mode: 0644]
client/src/app/+signup/shared/signup-success.component.scss [new file with mode: 0644]
client/src/app/+signup/shared/signup-success.component.ts [new file with mode: 0644]
client/src/app/+verify-account/index.ts [deleted file]
client/src/app/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html [deleted file]
client/src/app/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.scss [deleted file]
client/src/app/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts [deleted file]
client/src/app/+verify-account/verify-account-email/verify-account-email.component.html [deleted file]
client/src/app/+verify-account/verify-account-email/verify-account-email.component.ts [deleted file]
client/src/app/+verify-account/verify-account-routing.module.ts [deleted file]
client/src/app/+verify-account/verify-account.module.ts [deleted file]
client/src/app/app-routing.module.ts
client/src/app/app.module.ts
client/src/app/core/core.module.ts
client/src/app/core/routing/redirect.service.ts
client/src/app/core/routing/unlogged-guard.service.ts [new file with mode: 0644]
client/src/app/signup/custom-stepper.component.html [deleted file]
client/src/app/signup/custom-stepper.component.scss [deleted file]
client/src/app/signup/custom-stepper.component.ts [deleted file]
client/src/app/signup/index.ts [deleted file]
client/src/app/signup/signup-routing.module.ts [deleted file]
client/src/app/signup/signup-step-channel.component.html [deleted file]
client/src/app/signup/signup-step-channel.component.ts [deleted file]
client/src/app/signup/signup-step-user.component.html [deleted file]
client/src/app/signup/signup-step-user.component.ts [deleted file]
client/src/app/signup/signup.component.html [deleted file]
client/src/app/signup/signup.component.scss [deleted file]
client/src/app/signup/signup.component.ts [deleted file]
client/src/app/signup/signup.module.ts [deleted file]
client/src/app/signup/success.component.html [deleted file]
client/src/app/signup/success.component.scss [deleted file]
client/src/app/signup/success.component.ts [deleted file]

diff --git a/client/src/app/+signup/+register/custom-stepper.component.html b/client/src/app/+signup/+register/custom-stepper.component.html
new file mode 100644 (file)
index 0000000..bf507fc
--- /dev/null
@@ -0,0 +1,25 @@
+<section class="container">
+  <header>
+    <ng-container *ngFor="let step of steps; let i = index; let isLast = last;">
+      <div
+        class="step-info" [ngClass]="{ active: selectedIndex === i, completed: isCompleted(step) }"
+        (click)="onClick(i)"
+      >
+        <div class="step-index">
+          <ng-container *ngIf="!isCompleted(step)">{{ i + 1 }}</ng-container>
+          <my-global-icon *ngIf="isCompleted(step)" iconName="tick"></my-global-icon>
+        </div>
+
+        <div class="step-label">{{ step.label }}</div>
+      </div>
+
+      <!-- Do no display if this is the last child -->
+      <div *ngIf="!isLast" class="connector"></div>
+    </ng-container>
+  </header>
+
+  <div [style.display]="selected ? 'block' : 'none'">
+    <ng-container [ngTemplateOutlet]="selected.content"></ng-container>
+  </div>
+
+</section>
diff --git a/client/src/app/+signup/+register/custom-stepper.component.scss b/client/src/app/+signup/+register/custom-stepper.component.scss
new file mode 100644 (file)
index 0000000..2371c8a
--- /dev/null
@@ -0,0 +1,66 @@
+@import '_variables';
+@import '_mixins';
+
+$grey-color: #9CA3AB;
+$index-block-height: 32px;
+
+header {
+  display: flex;
+  justify-content: space-between;
+  font-size: 15px;
+  margin-bottom: 30px;
+
+  .step-info {
+    color: $grey-color;
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+    width: $index-block-height;
+
+    .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(var(--mainBackgroundColor));
+
+        width: 22px;
+        height: 22px;
+      }
+    }
+
+    .step-label {
+      width: max-content;
+    }
+
+    &.active,
+    &.completed {
+      .step-index {
+        border-color: var(--mainColor);
+        background-color: var(--mainColor);
+        color: var(--mainBackgroundColor);
+      }
+
+      .step-label {
+        color: var(--mainColor);
+      }
+    }
+
+    &.completed {
+      cursor: pointer;
+    }
+  }
+
+  .connector {
+    flex: auto;
+    margin: $index-block-height/2 10px 0 10px;
+    height: 2px;
+    background-color: $grey-color;
+  }
+}
diff --git a/client/src/app/+signup/+register/custom-stepper.component.ts b/client/src/app/+signup/+register/custom-stepper.component.ts
new file mode 100644 (file)
index 0000000..2ae40f3
--- /dev/null
@@ -0,0 +1,19 @@
+import { Component } from '@angular/core'
+import { CdkStep, CdkStepper } from '@angular/cdk/stepper'
+
+@Component({
+  selector: 'my-custom-stepper',
+  templateUrl: './custom-stepper.component.html',
+  styleUrls: [ './custom-stepper.component.scss' ],
+  providers: [ { provide: CdkStepper, useExisting: CustomStepperComponent } ]
+})
+export class CustomStepperComponent extends CdkStepper {
+
+  onClick (index: number): void {
+    this.selectedIndex = index
+  }
+
+  isCompleted (step: CdkStep) {
+    return step.stepControl && step.stepControl.dirty && step.stepControl.valid
+  }
+}
diff --git a/client/src/app/+signup/+register/register-routing.module.ts b/client/src/app/+signup/+register/register-routing.module.ts
new file mode 100644 (file)
index 0000000..e3a5001
--- /dev/null
@@ -0,0 +1,28 @@
+import { NgModule } from '@angular/core'
+import { RouterModule, Routes } from '@angular/router'
+import { MetaGuard } from '@ngx-meta/core'
+import { RegisterComponent } from './register.component'
+import { ServerConfigResolver } from '@app/core/routing/server-config-resolver.service'
+import { UnloggedGuard } from '@app/core/routing/unlogged-guard.service'
+
+const registerRoutes: Routes = [
+  {
+    path: '',
+    component: RegisterComponent,
+    canActivate: [ MetaGuard, UnloggedGuard ],
+    data: {
+      meta: {
+        title: 'Register'
+      }
+    },
+    resolve: {
+      serverConfigLoaded: ServerConfigResolver
+    }
+  }
+]
+
+@NgModule({
+  imports: [ RouterModule.forChild(registerRoutes) ],
+  exports: [ RouterModule ]
+})
+export class RegisterRoutingModule {}
diff --git a/client/src/app/+signup/+register/register-step-channel.component.html b/client/src/app/+signup/+register/register-step-channel.component.html
new file mode 100644 (file)
index 0000000..68ea447
--- /dev/null
@@ -0,0 +1,50 @@
+<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>
+      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="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-append">
+        <span class="input-group-text">@{{ instanceHost }}</span>
+      </div>
+    </div>
+
+    <div *ngIf="formErrors.name" class="form-error">
+      {{ formErrors.name }}
+    </div>
+
+    <div *ngIf="isSameThanUsername()" class="form-error" i18n>
+      Channel name cannot be the same than your account name. You can click on the first step to update your account name.
+    </div>
+  </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>
+</form>
diff --git a/client/src/app/+signup/+register/register-step-channel.component.ts b/client/src/app/+signup/+register/register-step-channel.component.ts
new file mode 100644 (file)
index 0000000..9e13f75
--- /dev/null
@@ -0,0 +1,40 @@
+import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
+import { AuthService } from '@app/core'
+import { FormReactive, VideoChannelValidatorsService } from '@app/shared'
+import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { FormGroup } from '@angular/forms'
+
+@Component({
+  selector: 'my-register-step-channel',
+  templateUrl: './register-step-channel.component.html',
+  styleUrls: [ './register.component.scss' ]
+})
+export class RegisterStepChannelComponent extends FormReactive implements OnInit {
+  @Input() username: string
+  @Output() formBuilt = new EventEmitter<FormGroup>()
+
+  constructor (
+    protected formValidatorService: FormValidatorService,
+    private authService: AuthService,
+    private videoChannelValidatorsService: VideoChannelValidatorsService
+  ) {
+    super()
+  }
+
+  get instanceHost () {
+    return window.location.host
+  }
+
+  isSameThanUsername () {
+    return this.username && this.username === this.form.value['name']
+  }
+
+  ngOnInit () {
+    this.buildForm({
+      name: this.videoChannelValidatorsService.VIDEO_CHANNEL_NAME,
+      displayName: this.videoChannelValidatorsService.VIDEO_CHANNEL_DISPLAY_NAME
+    })
+
+    setTimeout(() => this.formBuilt.emit(this.form))
+  }
+}
diff --git a/client/src/app/+signup/+register/register-step-user.component.html b/client/src/app/+signup/+register/register-step-user.component.html
new file mode 100644 (file)
index 0000000..cd0c78b
--- /dev/null
@@ -0,0 +1,54 @@
+<form role="form" [formGroup]="form">
+
+  <div class="form-group">
+    <label for="username" i18n>Username</label>
+
+    <div class="input-group">
+      <input
+        type="text" id="username" i18n-placeholder placeholder="Example: jane_doe"
+        formControlName="username" [ngClass]="{ 'input-error': formErrors['username'] }"
+      >
+      <div class="input-group-append">
+        <span class="input-group-text">@{{ instanceHost }}</span>
+      </div>
+    </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" [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>
+    <input
+      type="password" id="password" i18n-placeholder placeholder="Password"
+      formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
+    >
+    <div *ngIf="formErrors.password" class="form-error">
+      {{ formErrors.password }}
+    </div>
+  </div>
+
+  <div class="form-group form-group-terms">
+    <my-peertube-checkbox
+      inputName="terms" formControlName="terms"
+      i18n-labelHtml
+      labelHtml="I am at least 16 years old and agree to the <a href='/about/instance#terms-section' target='_blank'rel='noopener noreferrer'>Terms</a> of this instance"
+    ></my-peertube-checkbox>
+
+    <div *ngIf="formErrors.terms" class="form-error">
+      {{ formErrors.terms }}
+    </div>
+  </div>
+</form>
diff --git a/client/src/app/+signup/+register/register-step-user.component.ts b/client/src/app/+signup/+register/register-step-user.component.ts
new file mode 100644 (file)
index 0000000..3825ae3
--- /dev/null
@@ -0,0 +1,37 @@
+import { Component, EventEmitter, OnInit, Output } from '@angular/core'
+import { AuthService } from '@app/core'
+import { FormReactive, UserValidatorsService } from '@app/shared'
+import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { FormGroup } from '@angular/forms'
+
+@Component({
+  selector: 'my-register-step-user',
+  templateUrl: './register-step-user.component.html',
+  styleUrls: [ './register.component.scss' ]
+})
+export class RegisterStepUserComponent extends FormReactive implements OnInit {
+  @Output() formBuilt = new EventEmitter<FormGroup>()
+
+  constructor (
+    protected formValidatorService: FormValidatorService,
+    private authService: AuthService,
+    private userValidatorsService: UserValidatorsService
+  ) {
+    super()
+  }
+
+  get instanceHost () {
+    return window.location.host
+  }
+
+  ngOnInit () {
+    this.buildForm({
+      username: this.userValidatorsService.USER_USERNAME,
+      password: this.userValidatorsService.USER_PASSWORD,
+      email: this.userValidatorsService.USER_EMAIL,
+      terms: this.userValidatorsService.USER_TERMS
+    })
+
+    setTimeout(() => this.formBuilt.emit(this.form))
+  }
+}
diff --git a/client/src/app/+signup/+register/register.component.html b/client/src/app/+signup/+register/register.component.html
new file mode 100644 (file)
index 0000000..24def68
--- /dev/null
@@ -0,0 +1,41 @@
+<div class="margin-content">
+
+  <div i18n class="title-page title-page-single">
+    Create an account
+  </div>
+
+  <my-signup-success *ngIf="signupDone" [message]="success"></my-signup-success>
+  <div *ngIf="info" class="alert alert-info">{{ info }}</div>
+
+  <div class="wrapper" *ngIf="!signupDone">
+    <div>
+      <my-custom-stepper linear *ngIf="!signupDone">
+        <cdk-step [stepControl]="formStepUser" i18n-label label="User information">
+          <my-register-step-user (formBuilt)="onUserFormBuilt($event)"></my-register-step-user>
+
+          <button i18n cdkStepperNext [disabled]="!formStepUser || !formStepUser.valid">Next</button>
+        </cdk-step>
+
+        <cdk-step [stepControl]="formStepChannel" i18n-label label="Channel information">
+          <my-register-step-channel (formBuilt)="onChannelFormBuilt($event)" [username]="getUsername()"></my-register-step-channel>
+
+          <button i18n cdkStepperNext (click)="signup()"
+                  [disabled]="!formStepChannel || !formStepChannel.valid || hasSameChannelAndAccountNames()"
+          >
+            Create my account
+          </button>
+        </cdk-step>
+
+        <cdk-step i18n-label label="Done" editable="false">
+          <div *ngIf="error" class="alert alert-danger">{{ error }}</div>
+        </cdk-step>
+      </my-custom-stepper>
+    </div>
+
+    <div>
+      <label i18n>Features found on this instance</label>
+      <my-instance-features-table></my-instance-features-table>
+    </div>
+  </div>
+
+</div>
diff --git a/client/src/app/+signup/+register/register.component.scss b/client/src/app/+signup/+register/register.component.scss
new file mode 100644 (file)
index 0000000..6f61b78
--- /dev/null
@@ -0,0 +1,58 @@
+@import '_variables';
+@import '_mixins';
+
+.alert {
+  font-size: 15px;
+  text-align: center;
+}
+
+.wrapper {
+  display: flex;
+  justify-content: space-between;
+  flex-wrap: wrap;
+
+  & > div {
+    margin-bottom: 40px;
+    width: 450px;
+
+    @media screen and (max-width: 500px) {
+      width: auto;
+    }
+  }
+}
+
+my-instance-features-table {
+  display: block;
+
+  margin-bottom: 40px;
+}
+
+.form-group-terms {
+  margin: 30px 0;
+}
+
+.input-group {
+  @include peertube-input-group(400px);
+}
+
+.input-group-append {
+  height: 30px;
+}
+
+input:not([type=submit]) {
+  @include peertube-input-text(400px);
+
+  display: block;
+
+  &#username,
+  &#name {
+    width: auto !important;
+    flex-grow: 1;
+  }
+}
+
+input[type=submit],
+button {
+  @include peertube-button;
+  @include orange-button;
+}
diff --git a/client/src/app/+signup/+register/register.component.ts b/client/src/app/+signup/+register/register.component.ts
new file mode 100644 (file)
index 0000000..cd60597
--- /dev/null
@@ -0,0 +1,89 @@
+import { Component } from '@angular/core'
+import { AuthService, Notifier, RedirectService, ServerService } from '@app/core'
+import { UserService, UserValidatorsService } from '@app/shared'
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { UserRegister } from '@shared/models/users/user-register.model'
+import { FormGroup } from '@angular/forms'
+
+@Component({
+  selector: 'my-register',
+  templateUrl: './register.component.html',
+  styleUrls: [ './register.component.scss' ]
+})
+export class RegisterComponent {
+  info: string = null
+  error: string = null
+  success: string = null
+  signupDone = false
+
+  formStepUser: FormGroup
+  formStepChannel: FormGroup
+
+  constructor (
+    private authService: AuthService,
+    private userValidatorsService: UserValidatorsService,
+    private notifier: Notifier,
+    private userService: UserService,
+    private serverService: ServerService,
+    private redirectService: RedirectService,
+    private i18n: I18n
+  ) {
+  }
+
+  get requiresEmailVerification () {
+    return this.serverService.getConfig().signup.requiresEmailVerification
+  }
+
+  hasSameChannelAndAccountNames () {
+    return this.getUsername() === this.getChannelName()
+  }
+
+  getUsername () {
+    if (!this.formStepUser) return undefined
+
+    return this.formStepUser.value['username']
+  }
+
+  getChannelName () {
+    if (!this.formStepChannel) return undefined
+
+    return this.formStepChannel.value['name']
+  }
+
+  onUserFormBuilt (form: FormGroup) {
+    this.formStepUser = form
+  }
+
+  onChannelFormBuilt (form: FormGroup) {
+    this.formStepChannel = form
+  }
+
+  signup () {
+    this.error = null
+
+    const body: UserRegister = Object.assign(this.formStepUser.value, { channel: this.formStepChannel.value })
+
+    this.userService.signup(body).subscribe(
+      () => {
+        this.signupDone = true
+
+        if (this.requiresEmailVerification) {
+          this.info = this.i18n('Now please check your emails to verify your account and complete signup.')
+          return
+        }
+
+        // Auto login
+        this.authService.login(body.username, body.password)
+            .subscribe(
+              () => {
+                this.success = this.i18n('You are now logged in as {{username}}!', { username: body.username })
+              },
+
+              err => this.error = err.message
+            )
+      },
+
+      err => this.error = err.message
+    )
+  }
+}
diff --git a/client/src/app/+signup/+register/register.module.ts b/client/src/app/+signup/+register/register.module.ts
new file mode 100644 (file)
index 0000000..46336cb
--- /dev/null
@@ -0,0 +1,33 @@
+import { NgModule } from '@angular/core'
+import { RegisterRoutingModule } from './register-routing.module'
+import { RegisterComponent } from './register.component'
+import { SharedModule } from '@app/shared'
+import { CdkStepperModule } from '@angular/cdk/stepper'
+import { RegisterStepChannelComponent } from './register-step-channel.component'
+import { RegisterStepUserComponent } from './register-step-user.component'
+import { CustomStepperComponent } from './custom-stepper.component'
+import { SignupSharedModule } from '@app/+signup/shared/signup-shared.module'
+
+@NgModule({
+  imports: [
+    RegisterRoutingModule,
+    SharedModule,
+    CdkStepperModule,
+    SignupSharedModule
+  ],
+
+  declarations: [
+    RegisterComponent,
+    CustomStepperComponent,
+    RegisterStepChannelComponent,
+    RegisterStepUserComponent
+  ],
+
+  exports: [
+    RegisterComponent
+  ],
+
+  providers: [
+  ]
+})
+export class RegisterModule { }
diff --git a/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html b/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html
new file mode 100644 (file)
index 0000000..2e41806
--- /dev/null
@@ -0,0 +1,22 @@
+<div class="margin-content">
+  <div i18n class="title-page title-page-single">
+    Request email for account verification
+  </div>
+
+  <form *ngIf="requiresEmailVerification; else emailVerificationNotRequired" role="form" (ngSubmit)="askSendVerifyEmail()" [formGroup]="form">
+    <div class="form-group">
+      <label i18n for="verify-email-email">Email</label>
+      <input
+        type="email" id="verify-email-email" i18n-placeholder placeholder="Email address" required
+        formControlName="verify-email-email" [ngClass]="{ 'input-error': formErrors['verify-email-email'] }"
+      >
+      <div *ngIf="formErrors['verify-email-email']" class="form-error">
+          {{ formErrors['verify-email-email'] }}
+      </div>
+    </div>
+    <input type="submit" i18n-value value="Send verification email" [disabled]="!form.valid">
+  </form>
+  <ng-template #emailVerificationNotRequired>
+    <div i18n>This instance does not require email verification.</div>
+  </ng-template>
+</div>
diff --git a/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.scss b/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.scss
new file mode 100644 (file)
index 0000000..efec6b7
--- /dev/null
@@ -0,0 +1,12 @@
+@import '_variables';
+@import '_mixins';
+
+input:not([type=submit]) {
+  @include peertube-input-text(340px);
+  display: block;
+}
+
+input[type=submit] {
+  @include peertube-button;
+  @include orange-button;
+}
diff --git a/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts b/client/src/app/+signup/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts
new file mode 100644 (file)
index 0000000..cfd471f
--- /dev/null
@@ -0,0 +1,57 @@
+import { Component, OnInit } from '@angular/core'
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { Notifier, RedirectService } from '@app/core'
+import { ServerService } from '@app/core/server'
+import { FormReactive, UserService } from '@app/shared'
+import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
+import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
+
+@Component({
+  selector: 'my-verify-account-ask-send-email',
+  templateUrl: './verify-account-ask-send-email.component.html',
+  styleUrls: [ './verify-account-ask-send-email.component.scss' ]
+})
+
+export class VerifyAccountAskSendEmailComponent extends FormReactive implements OnInit {
+
+  constructor (
+    protected formValidatorService: FormValidatorService,
+    private userValidatorsService: UserValidatorsService,
+    private userService: UserService,
+    private serverService: ServerService,
+    private notifier: Notifier,
+    private redirectService: RedirectService,
+    private i18n: I18n
+  ) {
+    super()
+  }
+
+  get requiresEmailVerification () {
+    return this.serverService.getConfig().signup.requiresEmailVerification
+  }
+
+  ngOnInit () {
+    this.buildForm({
+      'verify-email-email': this.userValidatorsService.USER_EMAIL
+    })
+  }
+
+  askSendVerifyEmail () {
+    const email = this.form.value['verify-email-email']
+    this.userService.askSendVerifyEmail(email)
+      .subscribe(
+        () => {
+          const message = this.i18n(
+            'An email with verification link will be sent to {{email}}.',
+            { email }
+          )
+          this.notifier.success(message)
+          this.redirectService.redirectToHomepage()
+        },
+
+        err => {
+          this.notifier.error(err.message)
+        }
+      )
+  }
+}
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
new file mode 100644 (file)
index 0000000..728709c
--- /dev/null
@@ -0,0 +1,15 @@
+<div class="margin-content">
+  <div i18n class="title-page title-page-single">
+    Verify account email confirmation
+  </div>
+
+  <my-signup-success i18n *ngIf="success; else verificationError" message="Your email has been verified and you may now login.">
+  </my-signup-success>
+
+  <ng-template #verificationError>
+    <div>
+      <span i18n>An error occurred. </span>
+      <a i18n routerLink="/verify-account/ask-send-email">Request new verification email.</a>
+    </div>
+  </ng-template>
+</div>
diff --git a/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts b/client/src/app/+signup/+verify-account/verify-account-email/verify-account-email.component.ts
new file mode 100644 (file)
index 0000000..3fb2d1c
--- /dev/null
@@ -0,0 +1,50 @@
+import { Component, OnInit } from '@angular/core'
+import { ActivatedRoute, Router } from '@angular/router'
+import { I18n } from '@ngx-translate/i18n-polyfill'
+import { Notifier } from '@app/core'
+import { UserService } from '@app/shared'
+
+@Component({
+  selector: 'my-verify-account-email',
+  templateUrl: './verify-account-email.component.html'
+})
+
+export class VerifyAccountEmailComponent implements OnInit {
+  success = false
+
+  private userId: number
+  private verificationString: string
+
+  constructor (
+    private userService: UserService,
+    private notifier: Notifier,
+    private router: Router,
+    private route: ActivatedRoute,
+    private i18n: I18n
+  ) {
+  }
+
+  ngOnInit () {
+    this.userId = this.route.snapshot.queryParams['userId']
+    this.verificationString = this.route.snapshot.queryParams['verificationString']
+
+    if (!this.userId || !this.verificationString) {
+      this.notifier.error(this.i18n('Unable to find user id or verification string.'))
+    } else {
+      this.verifyEmail()
+    }
+  }
+
+  verifyEmail () {
+    this.userService.verifyEmail(this.userId, this.verificationString)
+      .subscribe(
+        () => {
+          this.success = true
+        },
+
+        err => {
+          this.notifier.error(err.message)
+        }
+      )
+  }
+}
diff --git a/client/src/app/+signup/+verify-account/verify-account-routing.module.ts b/client/src/app/+signup/+verify-account/verify-account-routing.module.ts
new file mode 100644 (file)
index 0000000..16d5fe0
--- /dev/null
@@ -0,0 +1,38 @@
+import { NgModule } from '@angular/core'
+import { RouterModule, Routes } from '@angular/router'
+import { MetaGuard } from '@ngx-meta/core'
+import { VerifyAccountEmailComponent } from './verify-account-email/verify-account-email.component'
+import { VerifyAccountAskSendEmailComponent } from './verify-account-ask-send-email/verify-account-ask-send-email.component'
+
+const verifyAccountRoutes: Routes = [
+  {
+    path: '',
+    canActivateChild: [ MetaGuard ],
+    children: [
+      {
+        path: 'email',
+        component: VerifyAccountEmailComponent,
+        data: {
+          meta: {
+            title: 'Verify account email'
+          }
+        }
+      },
+      {
+        path: 'ask-send-email',
+        component: VerifyAccountAskSendEmailComponent,
+        data: {
+          meta: {
+            title: 'Verify account ask send email'
+          }
+        }
+      }
+    ]
+  }
+]
+
+@NgModule({
+  imports: [ RouterModule.forChild(verifyAccountRoutes) ],
+  exports: [ RouterModule ]
+})
+export class VerifyAccountRoutingModule {}
diff --git a/client/src/app/+signup/+verify-account/verify-account.module.ts b/client/src/app/+signup/+verify-account/verify-account.module.ts
new file mode 100644 (file)
index 0000000..9fe14e8
--- /dev/null
@@ -0,0 +1,25 @@
+import { NgModule } from '@angular/core'
+import { VerifyAccountRoutingModule } from './verify-account-routing.module'
+import { VerifyAccountEmailComponent } from './verify-account-email/verify-account-email.component'
+import { VerifyAccountAskSendEmailComponent } from './verify-account-ask-send-email/verify-account-ask-send-email.component'
+import { SharedModule } from '@app/shared'
+import { SignupSharedModule } from '@app/+signup/shared/signup-shared.module'
+
+@NgModule({
+  imports: [
+    VerifyAccountRoutingModule,
+    SharedModule,
+    SignupSharedModule
+  ],
+
+  declarations: [
+    VerifyAccountEmailComponent,
+    VerifyAccountAskSendEmailComponent
+  ],
+
+  exports: [],
+
+  providers: []
+})
+export class VerifyAccountModule {
+}
diff --git a/client/src/app/+signup/shared/signup-shared.module.ts b/client/src/app/+signup/shared/signup-shared.module.ts
new file mode 100644 (file)
index 0000000..cd21fde
--- /dev/null
@@ -0,0 +1,21 @@
+import { NgModule } from '@angular/core'
+import { SignupSuccessComponent } from '../shared/signup-success.component'
+import { SharedModule } from '@app/shared'
+
+@NgModule({
+  imports: [
+    SharedModule
+  ],
+
+  declarations: [
+    SignupSuccessComponent
+  ],
+
+  exports: [
+    SignupSuccessComponent
+  ],
+
+  providers: [
+  ]
+})
+export class SignupSharedModule { }
diff --git a/client/src/app/+signup/shared/signup-success.component.html b/client/src/app/+signup/shared/signup-success.component.html
new file mode 100644 (file)
index 0000000..e35f858
--- /dev/null
@@ -0,0 +1,16 @@
+<!-- Thanks: Amit Singh Sansoya from https://codepen.io/amit3200/pen/zWMJOO -->
+
+<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 130.2 130.2">
+  <circle class="path circle" fill="none" stroke="#73AF55" stroke-width="6" stroke-miterlimit="10" cx="65.1" cy="65.1" r="62.1"/>
+  <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 class="bottom-message">Welcome on PeerTube!</p>
+
+<div *ngIf="message" class="alert alert-success">
+  <p>{{ message }}</p>
+
+  <p i18n>
+    If you need help to use PeerTube, you can take a look to the <a href="https://docs.joinpeertube.org/#/use-setup-account" target="_blank" rel="noopener noreferrer">documentation</a>.
+  </p>
+</div>
diff --git a/client/src/app/+signup/shared/signup-success.component.scss b/client/src/app/+signup/shared/signup-success.component.scss
new file mode 100644 (file)
index 0000000..fbc27c8
--- /dev/null
@@ -0,0 +1,76 @@
+svg {
+  width: 100px;
+  display: block;
+  margin: 40px auto 0;
+}
+
+.path {
+  stroke-dasharray: 1000;
+  stroke-dashoffset: 0;
+
+  &.circle {
+    -webkit-animation: dash .9s ease-in-out;
+    animation: dash .9s ease-in-out;
+  }
+
+  &.line {
+    stroke-dashoffset: 1000;
+    -webkit-animation: dash .9s .35s ease-in-out forwards;
+    animation: dash .9s .35s ease-in-out forwards;
+  }
+
+  &.check {
+    stroke-dashoffset: -100;
+    -webkit-animation: dash-check .9s .35s ease-in-out forwards;
+    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;
+  text-align: center;
+}
+
+
+@-webkit-keyframes dash {
+  0% {
+    stroke-dashoffset: 1000;
+  }
+  100% {
+    stroke-dashoffset: 0;
+  }
+}
+
+@keyframes dash {
+  0% {
+    stroke-dashoffset: 1000;
+  }
+  100% {
+    stroke-dashoffset: 0;
+  }
+}
+
+@-webkit-keyframes dash-check {
+  0% {
+    stroke-dashoffset: -100;
+  }
+  100% {
+    stroke-dashoffset: 900;
+  }
+}
+
+@keyframes dash-check {
+  0% {
+    stroke-dashoffset: -100;
+  }
+  100% {
+    stroke-dashoffset: 900;
+  }
+}
diff --git a/client/src/app/+signup/shared/signup-success.component.ts b/client/src/app/+signup/shared/signup-success.component.ts
new file mode 100644 (file)
index 0000000..19fb592
--- /dev/null
@@ -0,0 +1,10 @@
+import { Component, Input } from '@angular/core'
+
+@Component({
+  selector: 'my-signup-success',
+  templateUrl: './signup-success.component.html',
+  styleUrls: [ './signup-success.component.scss' ]
+})
+export class SignupSuccessComponent {
+  @Input() message: string
+}
diff --git a/client/src/app/+verify-account/index.ts b/client/src/app/+verify-account/index.ts
deleted file mode 100644 (file)
index 733f5ba..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-export * from '@app/+verify-account/verify-account-routing.module'
-export * from '@app/+verify-account/verify-account.module'
diff --git a/client/src/app/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html b/client/src/app/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.html
deleted file mode 100644 (file)
index 2e41806..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-<div class="margin-content">
-  <div i18n class="title-page title-page-single">
-    Request email for account verification
-  </div>
-
-  <form *ngIf="requiresEmailVerification; else emailVerificationNotRequired" role="form" (ngSubmit)="askSendVerifyEmail()" [formGroup]="form">
-    <div class="form-group">
-      <label i18n for="verify-email-email">Email</label>
-      <input
-        type="email" id="verify-email-email" i18n-placeholder placeholder="Email address" required
-        formControlName="verify-email-email" [ngClass]="{ 'input-error': formErrors['verify-email-email'] }"
-      >
-      <div *ngIf="formErrors['verify-email-email']" class="form-error">
-          {{ formErrors['verify-email-email'] }}
-      </div>
-    </div>
-    <input type="submit" i18n-value value="Send verification email" [disabled]="!form.valid">
-  </form>
-  <ng-template #emailVerificationNotRequired>
-    <div i18n>This instance does not require email verification.</div>
-  </ng-template>
-</div>
diff --git a/client/src/app/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.scss b/client/src/app/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.scss
deleted file mode 100644 (file)
index efec6b7..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-@import '_variables';
-@import '_mixins';
-
-input:not([type=submit]) {
-  @include peertube-input-text(340px);
-  display: block;
-}
-
-input[type=submit] {
-  @include peertube-button;
-  @include orange-button;
-}
diff --git a/client/src/app/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts b/client/src/app/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component.ts
deleted file mode 100644 (file)
index cfd471f..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-import { Component, OnInit } from '@angular/core'
-import { I18n } from '@ngx-translate/i18n-polyfill'
-import { Notifier, RedirectService } from '@app/core'
-import { ServerService } from '@app/core/server'
-import { FormReactive, UserService } from '@app/shared'
-import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
-import { UserValidatorsService } from '@app/shared/forms/form-validators/user-validators.service'
-
-@Component({
-  selector: 'my-verify-account-ask-send-email',
-  templateUrl: './verify-account-ask-send-email.component.html',
-  styleUrls: [ './verify-account-ask-send-email.component.scss' ]
-})
-
-export class VerifyAccountAskSendEmailComponent extends FormReactive implements OnInit {
-
-  constructor (
-    protected formValidatorService: FormValidatorService,
-    private userValidatorsService: UserValidatorsService,
-    private userService: UserService,
-    private serverService: ServerService,
-    private notifier: Notifier,
-    private redirectService: RedirectService,
-    private i18n: I18n
-  ) {
-    super()
-  }
-
-  get requiresEmailVerification () {
-    return this.serverService.getConfig().signup.requiresEmailVerification
-  }
-
-  ngOnInit () {
-    this.buildForm({
-      'verify-email-email': this.userValidatorsService.USER_EMAIL
-    })
-  }
-
-  askSendVerifyEmail () {
-    const email = this.form.value['verify-email-email']
-    this.userService.askSendVerifyEmail(email)
-      .subscribe(
-        () => {
-          const message = this.i18n(
-            'An email with verification link will be sent to {{email}}.',
-            { email }
-          )
-          this.notifier.success(message)
-          this.redirectService.redirectToHomepage()
-        },
-
-        err => {
-          this.notifier.error(err.message)
-        }
-      )
-  }
-}
diff --git a/client/src/app/+verify-account/verify-account-email/verify-account-email.component.html b/client/src/app/+verify-account/verify-account-email/verify-account-email.component.html
deleted file mode 100644 (file)
index a83d4a3..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-<div class="margin-content">
-  <div i18n class="title-page title-page-single">
-    Verify account email confirmation
-  </div>
-
-  <div i18n *ngIf="success; else verificationError">
-    Your email has been verified and you may now login. Redirecting...
-  </div>
-  <ng-template #verificationError>
-    <div>
-      <span i18n>An error occurred. </span>
-      <a i18n routerLink="/verify-account/ask-send-email">Request new verification email.</a>
-    </div>
-  </ng-template>
-</div>
diff --git a/client/src/app/+verify-account/verify-account-email/verify-account-email.component.ts b/client/src/app/+verify-account/verify-account-email/verify-account-email.component.ts
deleted file mode 100644 (file)
index f9ecf66..0000000
+++ /dev/null
@@ -1,53 +0,0 @@
-import { Component, OnInit } from '@angular/core'
-import { ActivatedRoute, Router } from '@angular/router'
-import { I18n } from '@ngx-translate/i18n-polyfill'
-import { Notifier } from '@app/core'
-import { UserService } from '@app/shared'
-
-@Component({
-  selector: 'my-verify-account-email',
-  templateUrl: './verify-account-email.component.html'
-})
-
-export class VerifyAccountEmailComponent implements OnInit {
-  success = false
-
-  private userId: number
-  private verificationString: string
-
-  constructor (
-    private userService: UserService,
-    private notifier: Notifier,
-    private router: Router,
-    private route: ActivatedRoute,
-    private i18n: I18n
-  ) {
-  }
-
-  ngOnInit () {
-    this.userId = this.route.snapshot.queryParams['userId']
-    this.verificationString = this.route.snapshot.queryParams['verificationString']
-
-    if (!this.userId || !this.verificationString) {
-      this.notifier.error(this.i18n('Unable to find user id or verification string.'))
-    } else {
-      this.verifyEmail()
-    }
-  }
-
-  verifyEmail () {
-    this.userService.verifyEmail(this.userId, this.verificationString)
-      .subscribe(
-        () => {
-          this.success = true
-          setTimeout(() => {
-            this.router.navigate([ '/login' ])
-          }, 2000)
-        },
-
-        err => {
-          this.notifier.error(err.message)
-        }
-      )
-  }
-}
diff --git a/client/src/app/+verify-account/verify-account-routing.module.ts b/client/src/app/+verify-account/verify-account-routing.module.ts
deleted file mode 100644 (file)
index a038f03..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-import { NgModule } from '@angular/core'
-import { RouterModule, Routes } from '@angular/router'
-
-import { MetaGuard } from '@ngx-meta/core'
-
-import { VerifyAccountEmailComponent } from '@app/+verify-account/verify-account-email/verify-account-email.component'
-import {
-  VerifyAccountAskSendEmailComponent
-} from '@app/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component'
-
-const verifyAccountRoutes: Routes = [
-  {
-    path: '',
-    canActivateChild: [ MetaGuard ],
-    children: [
-      {
-        path: 'email',
-        component: VerifyAccountEmailComponent,
-        data: {
-          meta: {
-            title: 'Verify account email'
-          }
-        }
-      },
-      {
-        path: 'ask-send-email',
-        component: VerifyAccountAskSendEmailComponent,
-        data: {
-          meta: {
-            title: 'Verify account ask send email'
-          }
-        }
-      }
-    ]
-  }
-]
-
-@NgModule({
-  imports: [ RouterModule.forChild(verifyAccountRoutes) ],
-  exports: [ RouterModule ]
-})
-export class VerifyAccountRoutingModule {}
diff --git a/client/src/app/+verify-account/verify-account.module.ts b/client/src/app/+verify-account/verify-account.module.ts
deleted file mode 100644 (file)
index 9092c6b..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-import { NgModule } from '@angular/core'
-
-import { VerifyAccountRoutingModule } from '@app/+verify-account/verify-account-routing.module'
-import { VerifyAccountEmailComponent } from '@app/+verify-account/verify-account-email/verify-account-email.component'
-import {
-  VerifyAccountAskSendEmailComponent
-} from '@app/+verify-account/verify-account-ask-send-email/verify-account-ask-send-email.component'
-import { SharedModule } from '@app/shared'
-
-@NgModule({
-  imports: [
-    VerifyAccountRoutingModule,
-    SharedModule
-  ],
-
-  declarations: [
-    VerifyAccountEmailComponent,
-    VerifyAccountAskSendEmailComponent
-  ],
-
-  exports: [
-  ],
-
-  providers: [
-  ]
-})
-export class VerifyAccountModule { }
index db8888dbae2a316faa80fde0d47aad1196513f7c..7ca51f226df24bf37c0055e85743ce3b5b5498de 100644 (file)
@@ -16,7 +16,7 @@ const routes: Routes = [
   },
   {
     path: 'verify-account',
-    loadChildren: './+verify-account/verify-account.module#VerifyAccountModule'
+    loadChildren: './+signup/+verify-account/verify-account.module#VerifyAccountModule'
   },
   {
     path: 'accounts',
@@ -30,6 +30,10 @@ const routes: Routes = [
     path: 'about',
     loadChildren: './+about/about.module#AboutModule'
   },
+  {
+    path: 'signup',
+    loadChildren: './+signup/+register/register.module#RegisterModule'
+  },
   {
     path: '',
     component: AppComponent // Avoid 404, app component will redirect dynamically
index 0bbc2e08b18ead9f25c12ea0a1554c79b4362d9a..1e2936a37bf6cdd7841db53a52fbe574c5be1d12 100644 (file)
@@ -14,7 +14,6 @@ import { HeaderComponent } from './header'
 import { LoginModule } from './login'
 import { AvatarNotificationComponent, LanguageChooserComponent, MenuComponent } from './menu'
 import { SharedModule } from './shared'
-import { SignupModule } from './signup'
 import { VideosModule } from './videos'
 import { buildFileLocale, getCompleteLocale, isDefaultLocale } from '../../../shared/models/i18n'
 import { getDevLocale, isOnDevLocale } from '@app/shared/i18n/i18n-utils'
@@ -53,7 +52,6 @@ export function metaFactory (serverService: ServerService): MetaLoader {
     CoreModule,
     LoginModule,
     ResetPasswordModule,
-    SignupModule,
     SearchModule,
     SharedModule,
     VideosModule,
index d3e72afb4d2ce6f71d19af408022e5e46b96c808..06fa8fcf1fd86c66e90b80a0a22d74cf7387e5d1 100644 (file)
@@ -20,6 +20,7 @@ import { Notifier } from './notification'
 import { MessageService } from 'primeng/api'
 import { UserNotificationSocket } from '@app/core/notification/user-notification-socket.service'
 import { ServerConfigResolver } from './routing/server-config-resolver.service'
+import { UnloggedGuard } from '@app/core/routing/unlogged-guard.service'
 
 @NgModule({
   imports: [
@@ -58,6 +59,8 @@ import { ServerConfigResolver } from './routing/server-config-resolver.service'
     ThemeService,
     LoginGuard,
     UserRightGuard,
+    UnloggedGuard,
+
     RedirectService,
     Notifier,
     MessageService,
index e1db4097b87ff35934529538a2c86487ae22e9a8..571822b767a3dd85b8ec749fb19853dc29f0a517 100644 (file)
@@ -42,7 +42,14 @@ export class RedirectService {
   }
 
   redirectToPreviousRoute () {
-    if (this.previousUrl) return this.router.navigateByUrl(this.previousUrl)
+    const exceptions = [
+      '/verify-account'
+    ]
+
+    if (this.previousUrl) {
+      const isException = exceptions.find(e => this.previousUrl.startsWith(e))
+      if (!isException) return this.router.navigateByUrl(this.previousUrl)
+    }
 
     return this.redirectToHomepage()
   }
diff --git a/client/src/app/core/routing/unlogged-guard.service.ts b/client/src/app/core/routing/unlogged-guard.service.ts
new file mode 100644 (file)
index 0000000..3132a1a
--- /dev/null
@@ -0,0 +1,25 @@
+import { Injectable } from '@angular/core'
+import { ActivatedRouteSnapshot, CanActivate, CanActivateChild, Router, RouterStateSnapshot } from '@angular/router'
+import { AuthService } from '../auth/auth.service'
+import { RedirectService } from './redirect.service'
+
+@Injectable()
+export class UnloggedGuard implements CanActivate, CanActivateChild {
+
+  constructor (
+    private router: Router,
+    private auth: AuthService,
+    private redirectService: RedirectService
+  ) {}
+
+  canActivate (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
+    if (this.auth.isLoggedIn() === false) return true
+
+    this.redirectService.redirectToHomepage()
+    return false
+  }
+
+  canActivateChild (route: ActivatedRouteSnapshot, state: RouterStateSnapshot) {
+    return this.canActivate(route, state)
+  }
+}
diff --git a/client/src/app/signup/custom-stepper.component.html b/client/src/app/signup/custom-stepper.component.html
deleted file mode 100644 (file)
index bf507fc..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<section class="container">
-  <header>
-    <ng-container *ngFor="let step of steps; let i = index; let isLast = last;">
-      <div
-        class="step-info" [ngClass]="{ active: selectedIndex === i, completed: isCompleted(step) }"
-        (click)="onClick(i)"
-      >
-        <div class="step-index">
-          <ng-container *ngIf="!isCompleted(step)">{{ i + 1 }}</ng-container>
-          <my-global-icon *ngIf="isCompleted(step)" iconName="tick"></my-global-icon>
-        </div>
-
-        <div class="step-label">{{ step.label }}</div>
-      </div>
-
-      <!-- Do no display if this is the last child -->
-      <div *ngIf="!isLast" class="connector"></div>
-    </ng-container>
-  </header>
-
-  <div [style.display]="selected ? 'block' : 'none'">
-    <ng-container [ngTemplateOutlet]="selected.content"></ng-container>
-  </div>
-
-</section>
diff --git a/client/src/app/signup/custom-stepper.component.scss b/client/src/app/signup/custom-stepper.component.scss
deleted file mode 100644 (file)
index 2371c8a..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-@import '_variables';
-@import '_mixins';
-
-$grey-color: #9CA3AB;
-$index-block-height: 32px;
-
-header {
-  display: flex;
-  justify-content: space-between;
-  font-size: 15px;
-  margin-bottom: 30px;
-
-  .step-info {
-    color: $grey-color;
-    display: flex;
-    flex-direction: column;
-    align-items: center;
-    width: $index-block-height;
-
-    .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(var(--mainBackgroundColor));
-
-        width: 22px;
-        height: 22px;
-      }
-    }
-
-    .step-label {
-      width: max-content;
-    }
-
-    &.active,
-    &.completed {
-      .step-index {
-        border-color: var(--mainColor);
-        background-color: var(--mainColor);
-        color: var(--mainBackgroundColor);
-      }
-
-      .step-label {
-        color: var(--mainColor);
-      }
-    }
-
-    &.completed {
-      cursor: pointer;
-    }
-  }
-
-  .connector {
-    flex: auto;
-    margin: $index-block-height/2 10px 0 10px;
-    height: 2px;
-    background-color: $grey-color;
-  }
-}
diff --git a/client/src/app/signup/custom-stepper.component.ts b/client/src/app/signup/custom-stepper.component.ts
deleted file mode 100644 (file)
index 2ae40f3..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-import { Component } from '@angular/core'
-import { CdkStep, CdkStepper } from '@angular/cdk/stepper'
-
-@Component({
-  selector: 'my-custom-stepper',
-  templateUrl: './custom-stepper.component.html',
-  styleUrls: [ './custom-stepper.component.scss' ],
-  providers: [ { provide: CdkStepper, useExisting: CustomStepperComponent } ]
-})
-export class CustomStepperComponent extends CdkStepper {
-
-  onClick (index: number): void {
-    this.selectedIndex = index
-  }
-
-  isCompleted (step: CdkStep) {
-    return step.stepControl && step.stepControl.dirty && step.stepControl.valid
-  }
-}
diff --git a/client/src/app/signup/index.ts b/client/src/app/signup/index.ts
deleted file mode 100644 (file)
index b0aca97..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './signup-routing.module'
-export * from './signup.component'
-export * from './signup.module'
diff --git a/client/src/app/signup/signup-routing.module.ts b/client/src/app/signup/signup-routing.module.ts
deleted file mode 100644 (file)
index 820d16d..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-import { NgModule } from '@angular/core'
-import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
-import { SignupComponent } from './signup.component'
-import { ServerConfigResolver } from '@app/core/routing/server-config-resolver.service'
-
-const signupRoutes: Routes = [
-  {
-    path: 'signup',
-    component: SignupComponent,
-    canActivate: [ MetaGuard ],
-    data: {
-      meta: {
-        title: 'Signup'
-      }
-    },
-    resolve: {
-      serverConfigLoaded: ServerConfigResolver
-    }
-  }
-]
-
-@NgModule({
-  imports: [ RouterModule.forChild(signupRoutes) ],
-  exports: [ RouterModule ]
-})
-export class SignupRoutingModule {}
diff --git a/client/src/app/signup/signup-step-channel.component.html b/client/src/app/signup/signup-step-channel.component.html
deleted file mode 100644 (file)
index 68ea447..0000000
+++ /dev/null
@@ -1,50 +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>
-      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="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-append">
-        <span class="input-group-text">@{{ instanceHost }}</span>
-      </div>
-    </div>
-
-    <div *ngIf="formErrors.name" class="form-error">
-      {{ formErrors.name }}
-    </div>
-
-    <div *ngIf="isSameThanUsername()" class="form-error" i18n>
-      Channel name cannot be the same than your account name. You can click on the first step to update your account name.
-    </div>
-  </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>
-</form>
diff --git a/client/src/app/signup/signup-step-channel.component.ts b/client/src/app/signup/signup-step-channel.component.ts
deleted file mode 100644 (file)
index a49b7f3..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core'
-import { AuthService } from '@app/core'
-import { FormReactive, VideoChannelValidatorsService } from '../shared'
-import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
-import { FormGroup } from '@angular/forms'
-
-@Component({
-  selector: 'my-signup-step-channel',
-  templateUrl: './signup-step-channel.component.html',
-  styleUrls: [ './signup.component.scss' ]
-})
-export class SignupStepChannelComponent extends FormReactive implements OnInit {
-  @Input() username: string
-  @Output() formBuilt = new EventEmitter<FormGroup>()
-
-  constructor (
-    protected formValidatorService: FormValidatorService,
-    private authService: AuthService,
-    private videoChannelValidatorsService: VideoChannelValidatorsService
-  ) {
-    super()
-  }
-
-  get instanceHost () {
-    return window.location.host
-  }
-
-  isSameThanUsername () {
-    return this.username && this.username === this.form.value['name']
-  }
-
-  ngOnInit () {
-    this.buildForm({
-      name: this.videoChannelValidatorsService.VIDEO_CHANNEL_NAME,
-      displayName: this.videoChannelValidatorsService.VIDEO_CHANNEL_DISPLAY_NAME
-    })
-
-    setTimeout(() => this.formBuilt.emit(this.form))
-  }
-}
diff --git a/client/src/app/signup/signup-step-user.component.html b/client/src/app/signup/signup-step-user.component.html
deleted file mode 100644 (file)
index cd0c78b..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-<form role="form" [formGroup]="form">
-
-  <div class="form-group">
-    <label for="username" i18n>Username</label>
-
-    <div class="input-group">
-      <input
-        type="text" id="username" i18n-placeholder placeholder="Example: jane_doe"
-        formControlName="username" [ngClass]="{ 'input-error': formErrors['username'] }"
-      >
-      <div class="input-group-append">
-        <span class="input-group-text">@{{ instanceHost }}</span>
-      </div>
-    </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" [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>
-    <input
-      type="password" id="password" i18n-placeholder placeholder="Password"
-      formControlName="password" [ngClass]="{ 'input-error': formErrors['password'] }"
-    >
-    <div *ngIf="formErrors.password" class="form-error">
-      {{ formErrors.password }}
-    </div>
-  </div>
-
-  <div class="form-group form-group-terms">
-    <my-peertube-checkbox
-      inputName="terms" formControlName="terms"
-      i18n-labelHtml
-      labelHtml="I am at least 16 years old and agree to the <a href='/about/instance#terms-section' target='_blank'rel='noopener noreferrer'>Terms</a> of this instance"
-    ></my-peertube-checkbox>
-
-    <div *ngIf="formErrors.terms" class="form-error">
-      {{ formErrors.terms }}
-    </div>
-  </div>
-</form>
diff --git a/client/src/app/signup/signup-step-user.component.ts b/client/src/app/signup/signup-step-user.component.ts
deleted file mode 100644 (file)
index 54855d8..0000000
+++ /dev/null
@@ -1,37 +0,0 @@
-import { Component, EventEmitter, OnInit, Output } from '@angular/core'
-import { AuthService } from '@app/core'
-import { FormReactive, UserValidatorsService } from '../shared'
-import { FormValidatorService } from '@app/shared/forms/form-validators/form-validator.service'
-import { FormGroup } from '@angular/forms'
-
-@Component({
-  selector: 'my-signup-step-user',
-  templateUrl: './signup-step-user.component.html',
-  styleUrls: [ './signup.component.scss' ]
-})
-export class SignupStepUserComponent extends FormReactive implements OnInit {
-  @Output() formBuilt = new EventEmitter<FormGroup>()
-
-  constructor (
-    protected formValidatorService: FormValidatorService,
-    private authService: AuthService,
-    private userValidatorsService: UserValidatorsService
-  ) {
-    super()
-  }
-
-  get instanceHost () {
-    return window.location.host
-  }
-
-  ngOnInit () {
-    this.buildForm({
-      username: this.userValidatorsService.USER_USERNAME,
-      password: this.userValidatorsService.USER_PASSWORD,
-      email: this.userValidatorsService.USER_EMAIL,
-      terms: this.userValidatorsService.USER_TERMS
-    })
-
-    setTimeout(() => this.formBuilt.emit(this.form))
-  }
-}
diff --git a/client/src/app/signup/signup.component.html b/client/src/app/signup/signup.component.html
deleted file mode 100644 (file)
index ae3a595..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<div class="margin-content">
-
-  <div i18n class="title-page title-page-single">
-    Create an account
-  </div>
-
-
-  <my-success *ngIf="signupDone"></my-success>
-  <div *ngIf="info" class="alert alert-info">{{ info }}</div>
-  <div *ngIf="success" class="alert alert-success">{{ success }}</div>
-
-  <div class="wrapper" *ngIf="!signupDone">
-    <div>
-      <my-custom-stepper linear *ngIf="!signupDone">
-        <cdk-step [stepControl]="formStepUser" i18n-label label="User information">
-          <my-signup-step-user (formBuilt)="onUserFormBuilt($event)"></my-signup-step-user>
-
-          <button i18n cdkStepperNext [disabled]="!formStepUser || !formStepUser.valid">Next</button>
-        </cdk-step>
-
-        <cdk-step [stepControl]="formStepChannel" i18n-label label="Channel information">
-          <my-signup-step-channel (formBuilt)="onChannelFormBuilt($event)" [username]="getUsername()"></my-signup-step-channel>
-
-          <button i18n cdkStepperNext (click)="signup()"
-                  [disabled]="!formStepChannel || !formStepChannel.valid || hasSameChannelAndAccountNames()"
-          >
-            Create my account
-          </button>
-        </cdk-step>
-
-        <cdk-step i18n-label label="Done" editable="false">
-          <div *ngIf="error" class="alert alert-danger">{{ error }}</div>
-        </cdk-step>
-      </my-custom-stepper>
-    </div>
-
-    <div>
-      <label i18n>Features found on this instance</label>
-      <my-instance-features-table></my-instance-features-table>
-    </div>
-  </div>
-
-</div>
diff --git a/client/src/app/signup/signup.component.scss b/client/src/app/signup/signup.component.scss
deleted file mode 100644 (file)
index 6f61b78..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-@import '_variables';
-@import '_mixins';
-
-.alert {
-  font-size: 15px;
-  text-align: center;
-}
-
-.wrapper {
-  display: flex;
-  justify-content: space-between;
-  flex-wrap: wrap;
-
-  & > div {
-    margin-bottom: 40px;
-    width: 450px;
-
-    @media screen and (max-width: 500px) {
-      width: auto;
-    }
-  }
-}
-
-my-instance-features-table {
-  display: block;
-
-  margin-bottom: 40px;
-}
-
-.form-group-terms {
-  margin: 30px 0;
-}
-
-.input-group {
-  @include peertube-input-group(400px);
-}
-
-.input-group-append {
-  height: 30px;
-}
-
-input:not([type=submit]) {
-  @include peertube-input-text(400px);
-
-  display: block;
-
-  &#username,
-  &#name {
-    width: auto !important;
-    flex-grow: 1;
-  }
-}
-
-input[type=submit],
-button {
-  @include peertube-button;
-  @include orange-button;
-}
diff --git a/client/src/app/signup/signup.component.ts b/client/src/app/signup/signup.component.ts
deleted file mode 100644 (file)
index 11eaa85..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-import { Component } from '@angular/core'
-import { AuthService, Notifier, RedirectService, ServerService } from '@app/core'
-import { UserService, UserValidatorsService } from '../shared'
-import { I18n } from '@ngx-translate/i18n-polyfill'
-import { UserRegister } from '@shared/models/users/user-register.model'
-import { FormGroup } from '@angular/forms'
-
-@Component({
-  selector: 'my-signup',
-  templateUrl: './signup.component.html',
-  styleUrls: [ './signup.component.scss' ]
-})
-export class SignupComponent {
-  info: string = null
-  error: string = null
-  success: string = null
-  signupDone = false
-
-  formStepUser: FormGroup
-  formStepChannel: FormGroup
-
-  constructor (
-    private authService: AuthService,
-    private userValidatorsService: UserValidatorsService,
-    private notifier: Notifier,
-    private userService: UserService,
-    private serverService: ServerService,
-    private redirectService: RedirectService,
-    private i18n: I18n
-  ) {
-  }
-
-  get requiresEmailVerification () {
-    return this.serverService.getConfig().signup.requiresEmailVerification
-  }
-
-  hasSameChannelAndAccountNames () {
-    return this.getUsername() === this.getChannelName()
-  }
-
-  getUsername () {
-    if (!this.formStepUser) return undefined
-
-    return this.formStepUser.value['username']
-  }
-
-  getChannelName () {
-    if (!this.formStepChannel) return undefined
-
-    return this.formStepChannel.value['name']
-  }
-
-  onUserFormBuilt (form: FormGroup) {
-    this.formStepUser = form
-  }
-
-  onChannelFormBuilt (form: FormGroup) {
-    this.formStepChannel = form
-  }
-
-  signup () {
-    this.error = null
-
-    const body: UserRegister = Object.assign(this.formStepUser.value, this.formStepChannel.value)
-
-    this.userService.signup(body).subscribe(
-      () => {
-        this.signupDone = true
-
-        if (this.requiresEmailVerification) {
-          this.info = this.i18n('Now please check your emails to verify your account and complete signup.')
-          return
-        }
-
-        // Auto login
-        this.authService.login(body.username, body.password)
-            .subscribe(
-              () => {
-                this.success = this.i18n('You are now logged in as {{username}}!', { username: body.username })
-              },
-
-              err => this.error = err.message
-            )
-      },
-
-      err => this.error = err.message
-    )
-  }
-}
diff --git a/client/src/app/signup/signup.module.ts b/client/src/app/signup/signup.module.ts
deleted file mode 100644 (file)
index fccaf7c..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-import { NgModule } from '@angular/core'
-import { SignupRoutingModule } from './signup-routing.module'
-import { SignupComponent } from './signup.component'
-import { SharedModule } from '../shared'
-import { CdkStepperModule } from '@angular/cdk/stepper'
-import { SignupStepChannelComponent } from '@app/signup/signup-step-channel.component'
-import { SignupStepUserComponent } from '@app/signup/signup-step-user.component'
-import { CustomStepperComponent } from '@app/signup/custom-stepper.component'
-import { SuccessComponent } from '@app/signup/success.component'
-
-@NgModule({
-  imports: [
-    SignupRoutingModule,
-    SharedModule,
-    CdkStepperModule
-  ],
-
-  declarations: [
-    SignupComponent,
-    CustomStepperComponent,
-    SuccessComponent,
-    SignupStepChannelComponent,
-    SignupStepUserComponent
-  ],
-
-  exports: [
-    SignupComponent
-  ],
-
-  providers: [
-  ]
-})
-export class SignupModule { }
diff --git a/client/src/app/signup/success.component.html b/client/src/app/signup/success.component.html
deleted file mode 100644 (file)
index 68eb72b..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<!-- Thanks: Amit Singh Sansoya from https://codepen.io/amit3200/pen/zWMJOO -->
-
-<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 130.2 130.2">
-  <circle class="path circle" fill="none" stroke="#73AF55" stroke-width="6" stroke-miterlimit="10" cx="65.1" cy="65.1" r="62.1"/>
-  <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 class="success">Welcome on PeerTube!</p>
diff --git a/client/src/app/signup/success.component.scss b/client/src/app/signup/success.component.scss
deleted file mode 100644 (file)
index 7c66e08..0000000
+++ /dev/null
@@ -1,74 +0,0 @@
-svg {
-  width: 100px;
-  display: block;
-  margin: 40px auto 0;
-}
-
-.path {
-  stroke-dasharray: 1000;
-  stroke-dashoffset: 0;
-
-  &.circle {
-    -webkit-animation: dash .9s ease-in-out;
-    animation: dash .9s ease-in-out;
-  }
-
-  &.line {
-    stroke-dashoffset: 1000;
-    -webkit-animation: dash .9s .35s ease-in-out forwards;
-    animation: dash .9s .35s ease-in-out forwards;
-  }
-
-  &.check {
-    stroke-dashoffset: -100;
-    -webkit-animation: dash-check .9s .35s ease-in-out forwards;
-    animation: dash-check .9s .35s ease-in-out forwards;
-  }
-}
-
-p {
-  text-align: center;
-  margin: 20px 0 60px;
-  font-size: 1.25em;
-
-  &.success {
-    color: #73AF55;
-  }
-}
-
-
-@-webkit-keyframes dash {
-  0% {
-    stroke-dashoffset: 1000;
-  }
-  100% {
-    stroke-dashoffset: 0;
-  }
-}
-
-@keyframes dash {
-  0% {
-    stroke-dashoffset: 1000;
-  }
-  100% {
-    stroke-dashoffset: 0;
-  }
-}
-
-@-webkit-keyframes dash-check {
-  0% {
-    stroke-dashoffset: -100;
-  }
-  100% {
-    stroke-dashoffset: 900;
-  }
-}
-
-@keyframes dash-check {
-  0% {
-    stroke-dashoffset: -100;
-  }
-  100% {
-    stroke-dashoffset: 900;
-  }
-}
diff --git a/client/src/app/signup/success.component.ts b/client/src/app/signup/success.component.ts
deleted file mode 100644 (file)
index 2674e1e..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-import { Component } from '@angular/core'
-
-@Component({
-  selector: 'my-success',
-  templateUrl: './success.component.html',
-  styleUrls: [ './success.component.scss' ]
-})
-export class SuccessComponent {
-
-}