Load my-account module lazily
authorChocobozzz <me@florianbigard.com>
Wed, 9 May 2018 07:26:41 +0000 (09:26 +0200)
committerChocobozzz <me@florianbigard.com>
Wed, 9 May 2018 07:32:26 +0000 (09:32 +0200)
64 files changed:
client/src/app/+my-account/index.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-routing.module.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-change-password/index.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.html [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.scss [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-profile/index.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.scss [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-settings.component.html [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-settings.component.scss [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-settings.component.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-video-settings/index.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.scss [new file with mode: 0644]
client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.html [new file with mode: 0644]
client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.scss [new file with mode: 0644]
client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html [new file with mode: 0644]
client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss [new file with mode: 0644]
client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts [new file with mode: 0644]
client/src/app/+my-account/my-account-videos/my-account-videos.component.html [new file with mode: 0644]
client/src/app/+my-account/my-account-videos/my-account-videos.component.scss [new file with mode: 0644]
client/src/app/+my-account/my-account-videos/my-account-videos.component.ts [new file with mode: 0644]
client/src/app/+my-account/my-account.component.html [new file with mode: 0644]
client/src/app/+my-account/my-account.component.ts [new file with mode: 0644]
client/src/app/+my-account/my-account.module.ts [new file with mode: 0644]
client/src/app/app-routing.module.ts
client/src/app/app.module.ts
client/src/app/my-account/index.ts [deleted file]
client/src/app/my-account/my-account-routing.module.ts [deleted file]
client/src/app/my-account/my-account-settings/my-account-change-password/index.ts [deleted file]
client/src/app/my-account/my-account-settings/my-account-change-password/my-account-change-password.component.html [deleted file]
client/src/app/my-account/my-account-settings/my-account-change-password/my-account-change-password.component.scss [deleted file]
client/src/app/my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts [deleted file]
client/src/app/my-account/my-account-settings/my-account-profile/index.ts [deleted file]
client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.html [deleted file]
client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.scss [deleted file]
client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.ts [deleted file]
client/src/app/my-account/my-account-settings/my-account-settings.component.html [deleted file]
client/src/app/my-account/my-account-settings/my-account-settings.component.scss [deleted file]
client/src/app/my-account/my-account-settings/my-account-settings.component.ts [deleted file]
client/src/app/my-account/my-account-settings/my-account-video-settings/index.ts [deleted file]
client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html [deleted file]
client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.scss [deleted file]
client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts [deleted file]
client/src/app/my-account/my-account-video-channels/my-account-video-channel-create.component.ts [deleted file]
client/src/app/my-account/my-account-video-channels/my-account-video-channel-edit.component.html [deleted file]
client/src/app/my-account/my-account-video-channels/my-account-video-channel-edit.component.scss [deleted file]
client/src/app/my-account/my-account-video-channels/my-account-video-channel-edit.ts [deleted file]
client/src/app/my-account/my-account-video-channels/my-account-video-channel-update.component.ts [deleted file]
client/src/app/my-account/my-account-video-channels/my-account-video-channels.component.html [deleted file]
client/src/app/my-account/my-account-video-channels/my-account-video-channels.component.scss [deleted file]
client/src/app/my-account/my-account-video-channels/my-account-video-channels.component.ts [deleted file]
client/src/app/my-account/my-account-videos/my-account-videos.component.html [deleted file]
client/src/app/my-account/my-account-videos/my-account-videos.component.scss [deleted file]
client/src/app/my-account/my-account-videos/my-account-videos.component.ts [deleted file]
client/src/app/my-account/my-account.component.html [deleted file]
client/src/app/my-account/my-account.component.ts [deleted file]
client/src/app/my-account/my-account.module.ts [deleted file]

diff --git a/client/src/app/+my-account/index.ts b/client/src/app/+my-account/index.ts
new file mode 100644 (file)
index 0000000..3df96dd
--- /dev/null
@@ -0,0 +1,3 @@
+export * from './my-account-routing.module'
+export * from './my-account.component'
+export * from './my-account.module'
diff --git a/client/src/app/+my-account/my-account-routing.module.ts b/client/src/app/+my-account/my-account-routing.module.ts
new file mode 100644 (file)
index 0000000..7e19cd9
--- /dev/null
@@ -0,0 +1,71 @@
+import { NgModule } from '@angular/core'
+import { RouterModule, Routes } from '@angular/router'
+import { MetaGuard } from '@ngx-meta/core'
+import { LoginGuard } from '../core'
+import { MyAccountComponent } from './my-account.component'
+import { MyAccountSettingsComponent } from './my-account-settings/my-account-settings.component'
+import { MyAccountVideosComponent } from './my-account-videos/my-account-videos.component'
+import { MyAccountVideoChannelsComponent } from '@app/+my-account/my-account-video-channels/my-account-video-channels.component'
+import { MyAccountVideoChannelCreateComponent } from '@app/+my-account/my-account-video-channels/my-account-video-channel-create.component'
+import { MyAccountVideoChannelUpdateComponent } from '@app/+my-account/my-account-video-channels/my-account-video-channel-update.component'
+
+const myAccountRoutes: Routes = [
+  {
+    path: '',
+    component: MyAccountComponent,
+    canActivateChild: [ MetaGuard, LoginGuard ],
+    children: [
+      {
+        path: 'settings',
+        component: MyAccountSettingsComponent,
+        data: {
+          meta: {
+            title: 'Account settings'
+          }
+        }
+      },
+      {
+        path: 'video-channels',
+        component: MyAccountVideoChannelsComponent,
+        data: {
+          meta: {
+            title: 'Account video channels'
+          }
+        }
+      },
+      {
+        path: 'video-channels/create',
+        component: MyAccountVideoChannelCreateComponent,
+        data: {
+          meta: {
+            title: 'Create new video channel'
+          }
+        }
+      },
+      {
+        path: 'video-channels/update/:videoChannelId',
+        component: MyAccountVideoChannelUpdateComponent,
+        data: {
+          meta: {
+            title: 'Update video channel'
+          }
+        }
+      },
+      {
+        path: 'videos',
+        component: MyAccountVideosComponent,
+        data: {
+          meta: {
+            title: 'Account videos'
+          }
+        }
+      }
+    ]
+  }
+]
+
+@NgModule({
+  imports: [ RouterModule.forChild(myAccountRoutes) ],
+  exports: [ RouterModule ]
+})
+export class MyAccountRoutingModule {}
diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-password/index.ts b/client/src/app/+my-account/my-account-settings/my-account-change-password/index.ts
new file mode 100644 (file)
index 0000000..644047c
--- /dev/null
@@ -0,0 +1 @@
+export * from './my-account-change-password.component'
diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.html b/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.html
new file mode 100644 (file)
index 0000000..b0e3cad
--- /dev/null
@@ -0,0 +1,20 @@
+<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
+
+<form role="form" (ngSubmit)="changePassword()" [formGroup]="form">
+
+  <label for="new-password">Change password</label>
+  <input
+    type="password" id="new-password" placeholder="New password"
+    formControlName="new-password" [ngClass]="{ 'input-error': formErrors['new-password'] }"
+  >
+  <div *ngIf="formErrors['new-password']" class="form-error">
+    {{ formErrors['new-password'] }}
+  </div>
+
+  <input
+    type="password" id="new-confirmed-password" placeholder="Confirm new password"
+    formControlName="new-confirmed-password"
+  >
+
+  <input type="submit" value="Change password" [disabled]="!form.valid">
+</form>
diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.scss b/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.scss
new file mode 100644 (file)
index 0000000..f8279ff
--- /dev/null
@@ -0,0 +1,19 @@
+@import '_variables';
+@import '_mixins';
+
+input[type=password] {
+  @include peertube-input-text(340px);
+  display: block;
+
+  &#new-confirmed-password {
+    margin-top: 15px;
+  }
+}
+
+input[type=submit] {
+  @include peertube-button;
+  @include orange-button;
+
+  margin-top: 15px;
+}
+
diff --git a/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts b/client/src/app/+my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts
new file mode 100644 (file)
index 0000000..80af668
--- /dev/null
@@ -0,0 +1,62 @@
+import { Component, OnInit } from '@angular/core'
+import { FormBuilder, FormGroup } from '@angular/forms'
+import { NotificationsService } from 'angular2-notifications'
+import { FormReactive, USER_PASSWORD, UserService } from '../../../shared'
+
+@Component({
+  selector: 'my-account-change-password',
+  templateUrl: './my-account-change-password.component.html',
+  styleUrls: [ './my-account-change-password.component.scss' ]
+})
+export class MyAccountChangePasswordComponent extends FormReactive implements OnInit {
+  error: string = null
+
+  form: FormGroup
+  formErrors = {
+    'new-password': '',
+    'new-confirmed-password': ''
+  }
+  validationMessages = {
+    'new-password': USER_PASSWORD.MESSAGES,
+    'new-confirmed-password': USER_PASSWORD.MESSAGES
+  }
+
+  constructor (
+    private formBuilder: FormBuilder,
+    private notificationsService: NotificationsService,
+    private userService: UserService
+  ) {
+    super()
+  }
+
+  buildForm () {
+    this.form = this.formBuilder.group({
+      'new-password': [ '', USER_PASSWORD.VALIDATORS ],
+      'new-confirmed-password': [ '', USER_PASSWORD.VALIDATORS ]
+    })
+
+    this.form.valueChanges.subscribe(data => this.onValueChanged(data))
+  }
+
+  ngOnInit () {
+    this.buildForm()
+  }
+
+  changePassword () {
+    const newPassword = this.form.value['new-password']
+    const newConfirmedPassword = this.form.value['new-confirmed-password']
+
+    this.error = null
+
+    if (newPassword !== newConfirmedPassword) {
+      this.error = 'The new password and the confirmed password do not correspond.'
+      return
+    }
+
+    this.userService.changePassword(newPassword).subscribe(
+      () => this.notificationsService.success('Success', 'Password updated.'),
+
+      err => this.error = err.message
+    )
+  }
+}
diff --git a/client/src/app/+my-account/my-account-settings/my-account-profile/index.ts b/client/src/app/+my-account/my-account-settings/my-account-profile/index.ts
new file mode 100644 (file)
index 0000000..3cc049f
--- /dev/null
@@ -0,0 +1 @@
+export * from './my-account-profile.component'
diff --git a/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html b/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.html
new file mode 100644 (file)
index 0000000..306f3a1
--- /dev/null
@@ -0,0 +1,24 @@
+<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
+
+<form role="form" (ngSubmit)="updateMyProfile()" [formGroup]="form">
+
+  <label for="display-name">Display name</label>
+  <input
+    type="text" id="display-name"
+    formControlName="display-name" [ngClass]="{ 'input-error': formErrors['display-name'] }"
+  >
+  <div *ngIf="formErrors['display-name']" class="form-error">
+    {{ formErrors['display-name'] }}
+  </div>
+
+  <label for="description">Description</label>
+  <textarea
+    id="description" formControlName="description"
+    [ngClass]="{ 'input-error': formErrors['description'] }"
+  ></textarea>
+  <div *ngIf="formErrors.description" class="form-error">
+    {{ formErrors.description }}
+  </div>
+
+  <input type="submit" value="Update my profile" [disabled]="!form.valid">
+</form>
diff --git a/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.scss b/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.scss
new file mode 100644 (file)
index 0000000..fc2b92c
--- /dev/null
@@ -0,0 +1,23 @@
+@import '_variables';
+@import '_mixins';
+
+input[type=text] {
+  @include peertube-input-text(340px);
+
+  display: block;
+  margin-bottom: 15px;
+}
+
+textarea {
+  @include peertube-textarea(500px, 150px);
+
+  display: block;
+}
+
+input[type=submit] {
+  @include peertube-button;
+  @include orange-button;
+
+  margin-top: 15px;
+}
+
diff --git a/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts b/client/src/app/+my-account/my-account-settings/my-account-profile/my-account-profile.component.ts
new file mode 100644 (file)
index 0000000..2b7ba35
--- /dev/null
@@ -0,0 +1,65 @@
+import { Component, Input, OnInit } from '@angular/core'
+import { FormBuilder, FormGroup } from '@angular/forms'
+import { NotificationsService } from 'angular2-notifications'
+import { FormReactive, USER_DESCRIPTION, USER_DISPLAY_NAME, UserService } from '../../../shared'
+import { User } from '@app/shared'
+
+@Component({
+  selector: 'my-account-profile',
+  templateUrl: './my-account-profile.component.html',
+  styleUrls: [ './my-account-profile.component.scss' ]
+})
+export class MyAccountProfileComponent extends FormReactive implements OnInit {
+  @Input() user: User = null
+
+  error: string = null
+
+  form: FormGroup
+  formErrors = {
+    'display-name': '',
+    'description': ''
+  }
+  validationMessages = {
+    'display-name': USER_DISPLAY_NAME.MESSAGES,
+    'description': USER_DESCRIPTION.MESSAGES
+  }
+
+  constructor (
+    private formBuilder: FormBuilder,
+    private notificationsService: NotificationsService,
+    private userService: UserService
+  ) {
+    super()
+  }
+
+  buildForm () {
+    this.form = this.formBuilder.group({
+      'display-name': [ this.user.account.displayName, USER_DISPLAY_NAME.VALIDATORS ],
+      'description': [ this.user.account.description, USER_DESCRIPTION.VALIDATORS ]
+    })
+
+    this.form.valueChanges.subscribe(data => this.onValueChanged(data))
+  }
+
+  ngOnInit () {
+    this.buildForm()
+  }
+
+  updateMyProfile () {
+    const displayName = this.form.value['display-name']
+    const description = this.form.value['description']
+
+    this.error = null
+
+    this.userService.updateMyProfile({ displayName, description }).subscribe(
+      () => {
+        this.user.account.displayName = displayName
+        this.user.account.description = description
+
+        this.notificationsService.success('Success', 'Profile updated.')
+      },
+
+      err => this.error = err.message
+    )
+  }
+}
diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.html b/client/src/app/+my-account/my-account-settings/my-account-settings.component.html
new file mode 100644 (file)
index 0000000..0fcc778
--- /dev/null
@@ -0,0 +1,32 @@
+<div class="user">
+  <img [src]="user.accountAvatarUrl" alt="Avatar" />
+
+  <div class="user-info">
+    <div class="user-info-names">
+      <div class="user-info-display-name">{{ user.account.displayName }}</div>
+      <div class="user-info-username">{{ user.username }}</div>
+    </div>
+    <div class="user-info-followers">{{ user.account?.followersCount }} subscribers</div>
+  </div>
+</div>
+
+<div class="button-file">
+  <span>Change your avatar</span>
+  <input #avatarfileInput type="file" name="avatarfile" id="avatarfile" [accept]="avatarExtensions" (change)="changeAvatar()" />
+</div>
+<div class="file-max-size">(extensions: {{ avatarExtensions }}, max size: {{ maxAvatarSize | bytes }})</div>
+
+<div class="user-quota">
+  <span class="user-quota-label">Video quota:</span> {{ userVideoQuotaUsed | bytes: 0 }} / {{ userVideoQuota }}
+</div>
+
+<ng-template [ngIf]="user && user.account">
+  <div class="account-title">Profile</div>
+  <my-account-profile [user]="user"></my-account-profile>
+</ng-template>
+
+<div class="account-title">Password</div>
+<my-account-change-password></my-account-change-password>
+
+<div class="account-title">Video settings</div>
+<my-account-video-settings [user]="user"></my-account-video-settings>
diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.scss b/client/src/app/+my-account/my-account-settings/my-account-settings.component.scss
new file mode 100644 (file)
index 0000000..ec0d40b
--- /dev/null
@@ -0,0 +1,67 @@
+@import '_variables';
+@import '_mixins';
+
+.user {
+  display: flex;
+
+  img {
+    @include avatar(50px);
+
+    margin-right: 15px;
+  }
+
+  .user-info {
+    .user-info-names {
+      display: flex;
+      align-items: center;
+
+      .user-info-display-name {
+        font-size: 20px;
+        font-weight: $font-bold;
+      }
+
+      .user-info-username {
+        margin-left: 7px;
+        position: relative;
+        top: 2px;
+        font-size: 14px;
+        color: #777272;
+      }
+    }
+
+    .user-info-followers {
+      font-size: 15px;
+    }
+  }
+}
+
+.button-file {
+  @include peertube-button-file(160px);
+
+  margin-top: 10px;
+  margin-bottom: 5px;
+}
+
+.file-max-size {
+  display: inline-block;
+  font-size: 13px;
+
+  position: relative;
+  top: -10px;
+}
+
+.user-quota {
+  font-size: 15px;
+  margin-top: 20px;
+
+  .user-quota-label {
+    font-weight: $font-semibold;
+  }
+}
+
+.account-title {
+  @include in-content-small-title;
+
+  margin-top: 55px;
+  margin-bottom: 30px;
+}
diff --git a/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-settings.component.ts
new file mode 100644 (file)
index 0000000..06d1138
--- /dev/null
@@ -0,0 +1,70 @@
+import { Component, OnInit, ViewChild } from '@angular/core'
+import { NotificationsService } from 'angular2-notifications'
+import { BytesPipe } from 'ngx-pipes'
+import { AuthService } from '../../core'
+import { ServerService } from '../../core/server'
+import { User } from '../../shared'
+import { UserService } from '../../shared/users'
+
+@Component({
+  selector: 'my-account-settings',
+  templateUrl: './my-account-settings.component.html',
+  styleUrls: [ './my-account-settings.component.scss' ]
+})
+export class MyAccountSettingsComponent implements OnInit {
+  @ViewChild('avatarfileInput') avatarfileInput
+
+  user: User = null
+  userVideoQuota = '0'
+  userVideoQuotaUsed = 0
+
+  constructor (
+    private userService: UserService,
+    private authService: AuthService,
+    private serverService: ServerService,
+    private notificationsService: NotificationsService
+  ) {}
+
+  ngOnInit () {
+    this.user = this.authService.getUser()
+
+    this.authService.userInformationLoaded.subscribe(
+      () => {
+        if (this.user.videoQuota !== -1) {
+          this.userVideoQuota = new BytesPipe().transform(this.user.videoQuota, 0).toString()
+        } else {
+          this.userVideoQuota = 'Unlimited'
+        }
+      }
+    )
+
+    this.userService.getMyVideoQuotaUsed()
+      .subscribe(data => this.userVideoQuotaUsed = data.videoQuotaUsed)
+  }
+
+  changeAvatar () {
+    const avatarfile = this.avatarfileInput.nativeElement.files[ 0 ]
+
+    const formData = new FormData()
+    formData.append('avatarfile', avatarfile)
+
+    this.userService.changeAvatar(formData)
+      .subscribe(
+        data => {
+          this.notificationsService.success('Success', 'Avatar changed.')
+
+          this.user.account.avatar = data.avatar
+        },
+
+        err => this.notificationsService.error('Error', err.message)
+      )
+  }
+
+  get maxAvatarSize () {
+    return this.serverService.getConfig().avatar.file.size.max
+  }
+
+  get avatarExtensions () {
+    return this.serverService.getConfig().avatar.file.extensions.join(',')
+  }
+}
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/index.ts b/client/src/app/+my-account/my-account-settings/my-account-video-settings/index.ts
new file mode 100644 (file)
index 0000000..1253bd3
--- /dev/null
@@ -0,0 +1 @@
+export * from './my-account-video-settings.component'
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
new file mode 100644 (file)
index 0000000..0e8598e
--- /dev/null
@@ -0,0 +1,25 @@
+<form role="form" (ngSubmit)="updateDetails()" [formGroup]="form">
+  <div class="form-group">
+    <label for="nsfwPolicy">Default policy on videos containing sensitive content</label>
+    <my-help helpType="custom" customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video."></my-help>
+
+    <div class="peertube-select-container">
+      <select id="nsfwPolicy" formControlName="nsfwPolicy">
+        <option value="do_not_list">Do not list</option>
+        <option value="blur">Blur thumbnails</option>
+        <option value="display">Display</option>
+      </select>
+    </div>
+  </div>
+
+  <div class="form-group">
+    <input
+      type="checkbox" id="autoPlayVideo"
+      formControlName="autoPlayVideo"
+    >
+    <label for="autoPlayVideo"></label>
+    <label for="autoPlayVideo">Automatically plays video</label>
+  </div>
+
+  <input type="submit" value="Save" [disabled]="!form.valid">
+</form>
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.scss b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.scss
new file mode 100644 (file)
index 0000000..ed59e46
--- /dev/null
@@ -0,0 +1,20 @@
+@import '_variables';
+@import '_mixins';
+
+input[type=checkbox] {
+  @include peertube-checkbox(1px);
+}
+
+input[type=submit] {
+  @include peertube-button;
+  @include orange-button;
+
+  display: block;
+  margin-top: 15px;
+}
+
+.peertube-select-container {
+  @include peertube-select-container(340px);
+
+  margin-bottom: 30px;
+}
\ No newline at end of file
diff --git a/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts b/client/src/app/+my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
new file mode 100644 (file)
index 0000000..acc70c1
--- /dev/null
@@ -0,0 +1,60 @@
+import { Component, Input, OnInit } from '@angular/core'
+import { FormBuilder, FormGroup } from '@angular/forms'
+import { NotificationsService } from 'angular2-notifications'
+import { UserUpdateMe } from '../../../../../../shared'
+import { AuthService } from '../../../core'
+import { FormReactive, User, UserService } from '../../../shared'
+
+@Component({
+  selector: 'my-account-video-settings',
+  templateUrl: './my-account-video-settings.component.html',
+  styleUrls: [ './my-account-video-settings.component.scss' ]
+})
+export class MyAccountVideoSettingsComponent extends FormReactive implements OnInit {
+  @Input() user: User = null
+
+  form: FormGroup
+  formErrors = {}
+  validationMessages = {}
+
+  constructor (
+    private authService: AuthService,
+    private formBuilder: FormBuilder,
+    private notificationsService: NotificationsService,
+    private userService: UserService
+  ) {
+    super()
+  }
+
+  buildForm () {
+    this.form = this.formBuilder.group({
+      nsfwPolicy: [ this.user.nsfwPolicy ],
+      autoPlayVideo: [ this.user.autoPlayVideo ]
+    })
+
+    this.form.valueChanges.subscribe(data => this.onValueChanged(data))
+  }
+
+  ngOnInit () {
+    this.buildForm()
+  }
+
+  updateDetails () {
+    const nsfwPolicy = this.form.value['nsfwPolicy']
+    const autoPlayVideo = this.form.value['autoPlayVideo']
+    const details: UserUpdateMe = {
+      nsfwPolicy,
+      autoPlayVideo
+    }
+
+    this.userService.updateMyProfile(details).subscribe(
+      () => {
+        this.notificationsService.success('Success', 'Information updated.')
+
+        this.authService.refreshUserInformation()
+      },
+
+      err => this.notificationsService.error('Error', err.message)
+    )
+  }
+}
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-create.component.ts
new file mode 100644 (file)
index 0000000..0f03548
--- /dev/null
@@ -0,0 +1,89 @@
+import { Component, OnInit } from '@angular/core'
+import { Router } from '@angular/router'
+import { NotificationsService } from 'angular2-notifications'
+import 'rxjs/add/observable/from'
+import 'rxjs/add/operator/concatAll'
+import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit'
+import { FormBuilder, FormGroup } from '@angular/forms'
+import { VideoChannelCreate } from '../../../../../shared/models/videos'
+import {
+  VIDEO_CHANNEL_DESCRIPTION,
+  VIDEO_CHANNEL_DISPLAY_NAME,
+  VIDEO_CHANNEL_SUPPORT
+} from '@app/shared/forms/form-validators/video-channel'
+import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
+import { AuthService } from '@app/core'
+
+@Component({
+  selector: 'my-account-video-channel-create',
+  templateUrl: './my-account-video-channel-edit.component.html',
+  styleUrls: [ './my-account-video-channel-edit.component.scss' ]
+})
+export class MyAccountVideoChannelCreateComponent extends MyAccountVideoChannelEdit implements OnInit {
+  error: string
+
+  form: FormGroup
+  formErrors = {
+    'display-name': '',
+    'description': '',
+    'support': ''
+  }
+  validationMessages = {
+    'display-name': VIDEO_CHANNEL_DISPLAY_NAME.MESSAGES,
+    'description': VIDEO_CHANNEL_DESCRIPTION.MESSAGES,
+    'support': VIDEO_CHANNEL_SUPPORT.MESSAGES
+  }
+
+  constructor (
+    private authService: AuthService,
+    private notificationsService: NotificationsService,
+    private router: Router,
+    private formBuilder: FormBuilder,
+    private videoChannelService: VideoChannelService
+  ) {
+    super()
+  }
+
+  buildForm () {
+    this.form = this.formBuilder.group({
+      'display-name': [ '', VIDEO_CHANNEL_DISPLAY_NAME.VALIDATORS ],
+      description: [ '', VIDEO_CHANNEL_DESCRIPTION.VALIDATORS ],
+      support: [ '', VIDEO_CHANNEL_SUPPORT.VALIDATORS ]
+    })
+
+    this.form.valueChanges.subscribe(data => this.onValueChanged(data))
+  }
+
+  ngOnInit () {
+    this.buildForm()
+  }
+
+  formValidated () {
+    this.error = undefined
+
+    const body = this.form.value
+    const videoChannelCreate: VideoChannelCreate = {
+      displayName: body['display-name'],
+      description: body.description || undefined,
+      support: body.support || undefined
+    }
+
+    this.videoChannelService.createVideoChannel(videoChannelCreate).subscribe(
+      () => {
+        this.authService.refreshUserInformation()
+        this.notificationsService.success('Success', `Video channel ${videoChannelCreate.displayName} created.`)
+        this.router.navigate([ '/my-account', 'video-channels' ])
+      },
+
+      err => this.error = err.message
+    )
+  }
+
+  isCreation () {
+    return true
+  }
+
+  getFormButtonTitle () {
+    return 'Create'
+  }
+}
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.html b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.html
new file mode 100644 (file)
index 0000000..d5fb626
--- /dev/null
@@ -0,0 +1,42 @@
+<div class="form-sub-title" *ngIf="isCreation() === true">Create a video channel</div>
+<div class="form-sub-title" *ngIf="isCreation() === false">Update {{ videoChannel?.displayName }}</div>
+
+<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
+
+<form role="form" (ngSubmit)="formValidated()" [formGroup]="form">
+  <div class="form-group">
+    <label for="display-name">Display name</label>
+    <input
+      type="text" id="display-name"
+      formControlName="display-name" [ngClass]="{ 'input-error': formErrors['display-name'] }"
+    >
+    <div *ngIf="formErrors['display-name']" class="form-error">
+      {{ formErrors['display-name'] }}
+    </div>
+  </div>
+
+  <div class="form-group">
+    <label for="description">Description</label>
+    <textarea
+      id="description" formControlName="description"
+      [ngClass]="{ 'input-error': formErrors['description'] }"
+    ></textarea>
+    <div *ngIf="formErrors.description" class="form-error">
+      {{ formErrors.description }}
+    </div>
+  </div>
+
+  <div class="form-group">
+    <label for="support">Support</label>
+    <my-help helpType="markdownEnhanced" preHtml="Short text to tell people how they can support your channel (membership platform...)."></my-help>
+    <my-markdown-textarea
+        id="support" formControlName="support" textareaWidth="500px" [previewColumn]="true" markdownType="enhanced"
+        [classes]="{ 'input-error': formErrors['support'] }"
+    ></my-markdown-textarea>
+    <div *ngIf="formErrors.support" class="form-error">
+      {{ formErrors.support }}
+    </div>
+  </div>
+
+  <input type="submit" value="{{ getFormButtonTitle() }}" [disabled]="!form.valid">
+</form>
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.scss b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.component.scss
new file mode 100644 (file)
index 0000000..6fbb8ae
--- /dev/null
@@ -0,0 +1,27 @@
+@import '_variables';
+@import '_mixins';
+
+.form-sub-title {
+  margin-bottom: 20px;
+}
+
+input[type=text] {
+  @include peertube-input-text(340px);
+
+  display: block;
+}
+
+textarea {
+  @include peertube-textarea(500px, 150px);
+
+  display: block;
+}
+
+.peertube-select-container {
+  @include peertube-select-container(340px);
+}
+
+input[type=submit] {
+  @include peertube-button;
+  @include orange-button;
+}
\ No newline at end of file
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-edit.ts
new file mode 100644 (file)
index 0000000..e56f462
--- /dev/null
@@ -0,0 +1,6 @@
+import { FormReactive } from '@app/shared'
+
+export abstract class MyAccountVideoChannelEdit extends FormReactive {
+  abstract isCreation (): boolean
+  abstract getFormButtonTitle (): string
+}
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channel-update.component.ts
new file mode 100644 (file)
index 0000000..c0dc6a9
--- /dev/null
@@ -0,0 +1,117 @@
+import { Component, OnInit, OnDestroy } from '@angular/core'
+import { ActivatedRoute, Router } from '@angular/router'
+import { NotificationsService } from 'angular2-notifications'
+import 'rxjs/add/observable/from'
+import 'rxjs/add/operator/concatAll'
+import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit'
+import { FormBuilder, FormGroup } from '@angular/forms'
+import { VideoChannelUpdate } from '../../../../../shared/models/videos'
+import {
+  VIDEO_CHANNEL_DESCRIPTION,
+  VIDEO_CHANNEL_DISPLAY_NAME,
+  VIDEO_CHANNEL_SUPPORT
+} from '@app/shared/forms/form-validators/video-channel'
+import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
+import { Subscription } from 'rxjs/Subscription'
+import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
+import { AuthService } from '@app/core'
+
+@Component({
+  selector: 'my-account-video-channel-update',
+  templateUrl: './my-account-video-channel-edit.component.html',
+  styleUrls: [ './my-account-video-channel-edit.component.scss' ]
+})
+export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelEdit implements OnInit, OnDestroy {
+  error: string
+
+  form: FormGroup
+  formErrors = {
+    'display-name': '',
+    'description': '',
+    'support': ''
+  }
+  validationMessages = {
+    'display-name': VIDEO_CHANNEL_DISPLAY_NAME.MESSAGES,
+    'description': VIDEO_CHANNEL_DESCRIPTION.MESSAGES,
+    'support': VIDEO_CHANNEL_SUPPORT.MESSAGES
+  }
+
+  private videoChannelToUpdate: VideoChannel
+  private paramsSub: Subscription
+
+  constructor (
+    private authService: AuthService,
+    private notificationsService: NotificationsService,
+    private router: Router,
+    private route: ActivatedRoute,
+    private formBuilder: FormBuilder,
+    private videoChannelService: VideoChannelService
+  ) {
+    super()
+  }
+
+  buildForm () {
+    this.form = this.formBuilder.group({
+      'display-name': [ '', VIDEO_CHANNEL_DISPLAY_NAME.VALIDATORS ],
+      description: [ '', VIDEO_CHANNEL_DESCRIPTION.VALIDATORS ],
+      support: [ '', VIDEO_CHANNEL_SUPPORT.VALIDATORS ]
+    })
+
+    this.form.valueChanges.subscribe(data => this.onValueChanged(data))
+  }
+
+  ngOnInit () {
+    this.buildForm()
+
+    this.paramsSub = this.route.params.subscribe(routeParams => {
+      const videoChannelId = routeParams['videoChannelId']
+
+      this.videoChannelService.getVideoChannel(videoChannelId).subscribe(
+        videoChannelToUpdate => {
+          this.videoChannelToUpdate = videoChannelToUpdate
+
+          this.form.patchValue({
+            'display-name': videoChannelToUpdate.displayName,
+            description: videoChannelToUpdate.description,
+            support: videoChannelToUpdate.support
+          })
+        },
+
+        err => this.error = err.message
+      )
+    })
+  }
+
+  ngOnDestroy () {
+    if (this.paramsSub) this.paramsSub.unsubscribe()
+  }
+
+  formValidated () {
+    this.error = undefined
+
+    const body = this.form.value
+    const videoChannelUpdate: VideoChannelUpdate = {
+      displayName: body['display-name'],
+      description: body.description || undefined,
+      support: body.support || undefined
+    }
+
+    this.videoChannelService.updateVideoChannel(this.videoChannelToUpdate.uuid, videoChannelUpdate).subscribe(
+      () => {
+        this.authService.refreshUserInformation()
+        this.notificationsService.success('Success', `Video channel ${videoChannelUpdate.displayName} updated.`)
+        this.router.navigate([ '/my-account', 'video-channels' ])
+      },
+
+      err => this.error = err.message
+    )
+  }
+
+  isCreation () {
+    return false
+  }
+
+  getFormButtonTitle () {
+    return 'Update'
+  }
+}
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.html
new file mode 100644 (file)
index 0000000..90c401b
--- /dev/null
@@ -0,0 +1,30 @@
+<div class="video-channels-header">
+  <a class="create-button" routerLink="create">
+    <span class="icon icon-add"></span>
+    Create another video channel
+  </a>
+</div>
+
+<div class="video-channels">
+  <div *ngFor="let videoChannel of videoChannels" class="video-channel">
+    <a [routerLink]="[ '/video-channels', videoChannel.uuid ]">
+      <img [src]="videoChannel.avatarUrl" alt="Avatar" />
+    </a>
+
+    <div class="video-channel-info">
+      <a [routerLink]="[ '/video-channels', videoChannel.uuid ]" class="video-channel-names" title="Go to the channel">
+        <div class="video-channel-display-name">{{ videoChannel.displayName }}</div>
+        <!-- Hide the name for now, because it's an UUID not very friendly -->
+        <!--<div class="video-channel-name">{{ videoChannel.name }}</div>-->
+      </a>
+
+      <div class="video-channel-followers">{{ videoChannel.followersCount }} subscribers</div>
+    </div>
+
+    <div class="video-channel-buttons">
+      <my-delete-button (click)="deleteVideoChannel(videoChannel)"></my-delete-button>
+
+      <my-edit-button [routerLink]="[ 'update', videoChannel.uuid ]"></my-edit-button>
+    </div>
+  </div>
+</div>
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.scss
new file mode 100644 (file)
index 0000000..bcb58ea
--- /dev/null
@@ -0,0 +1,72 @@
+@import '_variables';
+@import '_mixins';
+
+.create-button {
+  @include create-button;
+}
+
+/deep/ .action-button {
+  &.action-button-delete {
+    margin-right: 10px;
+  }
+}
+
+.video-channel {
+  display: flex;
+  min-height: 130px;
+  padding-bottom: 20px;
+  margin-bottom: 20px;
+  border-bottom: 1px solid #C6C6C6;
+
+  img {
+    @include avatar(80px);
+
+    margin-right: 10px;
+  }
+
+  .video-channel-info {
+    flex-grow: 1;
+
+    a.video-channel-names {
+      @include disable-default-a-behaviour;
+
+      display: flex;
+      color: #000;
+
+      .video-channel-display-name {
+        font-weight: $font-semibold;
+        font-size: 18px;
+      }
+
+      .video-channel-name {
+        font-size: 14px;
+        color: #777272;
+      }
+    }
+  }
+
+  .video-channel-buttons {
+    min-width: 190px;
+  }
+}
+
+.video-channels-header {
+  text-align: right;
+  margin: 20px 0 50px;
+}
+
+@media screen and (max-width: 800px) {
+  .video-channel {
+    flex-direction: column;
+    height: auto;
+    text-align: center;
+
+    img {
+      margin-right: 0;
+    }
+
+    .video-channel-buttons {
+      margin-top: 10px;
+    }
+  }
+}
diff --git a/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts b/client/src/app/+my-account/my-account-video-channels/my-account-video-channels.component.ts
new file mode 100644 (file)
index 0000000..eeaca11
--- /dev/null
@@ -0,0 +1,59 @@
+import { Component, OnInit } from '@angular/core'
+import { NotificationsService } from 'angular2-notifications'
+import 'rxjs/add/observable/from'
+import 'rxjs/add/operator/concatAll'
+import { AuthService } from '../../core/auth'
+import { ConfirmService } from '../../core/confirm'
+import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
+import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
+import { User } from '@app/shared'
+
+@Component({
+  selector: 'my-account-video-channels',
+  templateUrl: './my-account-video-channels.component.html',
+  styleUrls: [ './my-account-video-channels.component.scss' ]
+})
+export class MyAccountVideoChannelsComponent implements OnInit {
+  videoChannels: VideoChannel[] = []
+
+  private user: User
+
+  constructor (
+    private authService: AuthService,
+    private notificationsService: NotificationsService,
+    private confirmService: ConfirmService,
+    private videoChannelService: VideoChannelService
+  ) {}
+
+  ngOnInit () {
+    this.user = this.authService.getUser()
+
+    this.loadVideoChannels()
+  }
+
+  async deleteVideoChannel (videoChannel: VideoChannel) {
+    const res = await this.confirmService.confirmWithInput(
+      `Do you really want to delete ${videoChannel.displayName}? It will delete all videos uploaded in this channel too.`,
+      'Please type the name of the video channel to confirm',
+      videoChannel.displayName,
+      'Delete'
+    )
+    if (res === false) return
+
+    this.videoChannelService.removeVideoChannel(videoChannel)
+      .subscribe(
+        status => {
+          this.loadVideoChannels()
+          this.notificationsService.success('Success', `Video channel ${videoChannel.name} deleted.`)
+        },
+
+        error => this.notificationsService.error('Error', error.message)
+      )
+  }
+
+  private loadVideoChannels () {
+    this.authService.userInformationLoaded
+        .flatMap(() => this.videoChannelService.listAccountVideoChannels(this.user.account.id))
+        .subscribe(res => this.videoChannels = res.data)
+  }
+}
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.html b/client/src/app/+my-account/my-account-videos/my-account-videos.component.html
new file mode 100644 (file)
index 0000000..66ce3a7
--- /dev/null
@@ -0,0 +1,45 @@
+<div *ngIf="pagination.totalItems === 0">No results.</div>
+
+<div
+  myInfiniteScroller
+  [pageHeight]="pageHeight"
+  (nearOfTop)="onNearOfTop()" (nearOfBottom)="onNearOfBottom()" (pageChanged)="onPageChanged($event)"
+  class="videos" #videosElement
+>
+  <div *ngFor="let videos of videoPages; let i = index" class="videos-page">
+    <div class="video" *ngFor="let video of videos; let j = index">
+      <div class="checkbox-container">
+        <input [id]="'video-check-' + video.id" type="checkbox" [(ngModel)]="checkedVideos[video.id]" />
+        <label [for]="'video-check-' + video.id"></label>
+      </div>
+
+      <my-video-thumbnail [video]="video"></my-video-thumbnail>
+
+      <div class="video-info">
+        <a class="video-info-name" [routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name">{{ video.name }}</a>
+        <span class="video-info-date-views">{{ video.createdAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span>
+        <div class="video-info-private">{{ video.privacy.label }}</div>
+      </div>
+
+      <!-- Display only once -->
+      <div class="action-selection-mode" *ngIf="isInSelectionMode() === true && i === 0 && j === 0">
+        <div class="action-selection-mode-child">
+          <span class="action-button action-button-cancel-selection" (click)="abortSelectionMode()">
+            Cancel
+          </span>
+
+          <span class="action-button action-button-delete-selection" (click)="deleteSelectedVideos()">
+            <span class="icon icon-delete-white"></span>
+            Delete
+          </span>
+        </div>
+      </div>
+
+      <div class="video-buttons" *ngIf="isInSelectionMode() === false">
+        <my-delete-button (click)="deleteVideo(video)"></my-delete-button>
+
+        <my-edit-button [routerLink]="[ '/videos', 'edit', video.uuid ]"></my-edit-button>
+      </div>
+    </div>
+  </div>
+</div>
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss b/client/src/app/+my-account/my-account-videos/my-account-videos.component.scss
new file mode 100644 (file)
index 0000000..f276ea3
--- /dev/null
@@ -0,0 +1,114 @@
+@import '_variables';
+@import '_mixins';
+
+.action-selection-mode {
+  width: 174px;
+  display: flex;
+  justify-content: flex-end;
+
+  .action-selection-mode-child {
+    position: fixed;
+
+    .action-button {
+      display: inline-block;
+    }
+
+    .action-button-cancel-selection {
+      @include peertube-button;
+      @include grey-button;
+
+      margin-right: 10px;
+    }
+
+    .action-button-delete-selection {
+      @include peertube-button;
+      @include orange-button;
+    }
+
+    .icon.icon-delete-white {
+      @include icon(21px);
+
+      position: relative;
+      top: -2px;
+      background-image: url('../../../assets/images/global/delete-white.svg');
+    }
+  }
+}
+
+/deep/ .action-button {
+  &.action-button-delete {
+    margin-right: 10px;
+  }
+}
+
+.video {
+  display: flex;
+  min-height: 130px;
+  padding-bottom: 20px;
+  margin-bottom: 20px;
+  border-bottom: 1px solid #C6C6C6;
+
+  &:first-child {
+    margin-top: 47px;
+  }
+
+  .checkbox-container {
+    display: flex;
+    align-items: center;
+    margin-right: 20px;
+    margin-left: 12px;
+
+    input[type=checkbox] {
+      @include peertube-checkbox(2px);
+    }
+  }
+
+  my-video-thumbnail {
+    margin-right: 10px;
+  }
+
+  .video-info {
+    flex-grow: 1;
+
+    .video-info-name {
+      @include disable-default-a-behaviour;
+
+      color: #000;
+      display: block;
+      font-size: 16px;
+      font-weight: $font-semibold;
+    }
+
+    .video-info-date-views, .video-info-private {
+      font-size: 13px;
+
+      &.video-info-private {
+        font-weight: $font-semibold;
+      }
+    }
+  }
+
+  .video-buttons {
+    min-width: 190px;
+  }
+}
+
+@media screen and (max-width: 800px) {
+  .video {
+    flex-direction: column;
+    height: auto;
+    text-align: center;
+
+    input[type=checkbox] {
+      display: none;
+    }
+
+    my-video-thumbnail {
+      margin-right: 0;
+    }
+
+    .video-buttons {
+      margin-top: 10px;
+    }
+  }
+}
diff --git a/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts b/client/src/app/+my-account/my-account-videos/my-account-videos.component.ts
new file mode 100644 (file)
index 0000000..c1b53bc
--- /dev/null
@@ -0,0 +1,131 @@
+import { Component, OnInit, OnDestroy } from '@angular/core'
+import { ActivatedRoute, Router } from '@angular/router'
+import { Location } from '@angular/common'
+import { immutableAssign } from '@app/shared/misc/utils'
+import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
+import { NotificationsService } from 'angular2-notifications'
+import 'rxjs/add/observable/from'
+import 'rxjs/add/operator/concatAll'
+import { Observable } from 'rxjs/Observable'
+import { AuthService } from '../../core/auth'
+import { ConfirmService } from '../../core/confirm'
+import { AbstractVideoList } from '../../shared/video/abstract-video-list'
+import { Video } from '../../shared/video/video.model'
+import { VideoService } from '../../shared/video/video.service'
+
+@Component({
+  selector: 'my-account-videos',
+  templateUrl: './my-account-videos.component.html',
+  styleUrls: [ './my-account-videos.component.scss' ]
+})
+export class MyAccountVideosComponent extends AbstractVideoList implements OnInit, OnDestroy {
+  titlePage = 'My videos'
+  currentRoute = '/my-account/videos'
+  checkedVideos: { [ id: number ]: boolean } = {}
+  pagination: ComponentPagination = {
+    currentPage: 1,
+    itemsPerPage: 5,
+    totalItems: null
+  }
+
+  protected baseVideoWidth = -1
+  protected baseVideoHeight = 155
+
+  constructor (protected router: Router,
+               protected route: ActivatedRoute,
+               protected authService: AuthService,
+               protected notificationsService: NotificationsService,
+               protected confirmService: ConfirmService,
+               protected location: Location,
+               private videoService: VideoService) {
+    super()
+  }
+
+  ngOnInit () {
+    super.ngOnInit()
+  }
+
+  ngOnDestroy () {
+    super.ngOnDestroy()
+  }
+
+  abortSelectionMode () {
+    this.checkedVideos = {}
+  }
+
+  isInSelectionMode () {
+    return Object.keys(this.checkedVideos).some(k => this.checkedVideos[k] === true)
+  }
+
+  getVideosObservable (page: number) {
+    const newPagination = immutableAssign(this.pagination, { currentPage: page })
+
+    return this.videoService.getMyVideos(newPagination, this.sort)
+  }
+
+  generateSyndicationList () {
+    throw new Error('Method not implemented.')
+  }
+
+  async deleteSelectedVideos () {
+    const toDeleteVideosIds = Object.keys(this.checkedVideos)
+      .filter(k => this.checkedVideos[k] === true)
+      .map(k => parseInt(k, 10))
+
+    const res = await this.confirmService.confirm(`Do you really want to delete ${toDeleteVideosIds.length} videos?`, 'Delete')
+    if (res === false) return
+
+    const observables: Observable<any>[] = []
+    for (const videoId of toDeleteVideosIds) {
+      const o = this.videoService
+        .removeVideo(videoId)
+        .do(() => this.spliceVideosById(videoId))
+
+      observables.push(o)
+    }
+
+    Observable.from(observables)
+      .concatAll()
+      .subscribe(
+        res => {
+          this.notificationsService.success('Success', `${toDeleteVideosIds.length} videos deleted.`)
+          this.buildVideoPages()
+        },
+
+        err => this.notificationsService.error('Error', err.message)
+      )
+  }
+
+  async deleteVideo (video: Video) {
+    const res = await this.confirmService.confirm(`Do you really want to delete ${video.name}?`, 'Delete')
+    if (res === false) return
+
+    this.videoService.removeVideo(video.id)
+      .subscribe(
+        status => {
+          this.notificationsService.success('Success', `Video ${video.name} deleted.`)
+          this.spliceVideosById(video.id)
+          this.buildVideoPages()
+        },
+
+        error => this.notificationsService.error('Error', error.message)
+      )
+  }
+
+  protected buildVideoHeight () {
+    // In account videos, the video height is fixed
+    return this.baseVideoHeight
+  }
+
+  private spliceVideosById (id: number) {
+    for (const key of Object.keys(this.loadedPages)) {
+      const videos = this.loadedPages[key]
+      const index = videos.findIndex(v => v.id === id)
+
+      if (index !== -1) {
+        videos.splice(index, 1)
+        return
+      }
+    }
+  }
+}
diff --git a/client/src/app/+my-account/my-account.component.html b/client/src/app/+my-account/my-account.component.html
new file mode 100644 (file)
index 0000000..591d58c
--- /dev/null
@@ -0,0 +1,13 @@
+<div class="row">
+  <div class="sub-menu">
+    <a routerLink="/my-account/settings" routerLinkActive="active" class="title-page">My settings</a>
+
+    <a routerLink="/my-account/video-channels" routerLinkActive="active" class="title-page">My video channels</a>
+
+    <a routerLink="/my-account/videos" routerLinkActive="active" class="title-page">My videos</a>
+  </div>
+
+  <div class="margin-content">
+    <router-outlet></router-outlet>
+  </div>
+</div>
diff --git a/client/src/app/+my-account/my-account.component.ts b/client/src/app/+my-account/my-account.component.ts
new file mode 100644 (file)
index 0000000..7bb461d
--- /dev/null
@@ -0,0 +1,7 @@
+import { Component } from '@angular/core'
+
+@Component({
+  selector: 'my-my-account',
+  templateUrl: './my-account.component.html'
+})
+export class MyAccountComponent {}
diff --git a/client/src/app/+my-account/my-account.module.ts b/client/src/app/+my-account/my-account.module.ts
new file mode 100644 (file)
index 0000000..7e6b8c0
--- /dev/null
@@ -0,0 +1,38 @@
+import { NgModule } from '@angular/core'
+import { SharedModule } from '../shared'
+import { MyAccountRoutingModule } from './my-account-routing.module'
+import { MyAccountChangePasswordComponent } from './my-account-settings/my-account-change-password/my-account-change-password.component'
+import { MyAccountVideoSettingsComponent } from './my-account-settings/my-account-video-settings/my-account-video-settings.component'
+import { MyAccountSettingsComponent } from './my-account-settings/my-account-settings.component'
+import { MyAccountComponent } from './my-account.component'
+import { MyAccountVideosComponent } from './my-account-videos/my-account-videos.component'
+import { MyAccountProfileComponent } from '@app/+my-account/my-account-settings/my-account-profile/my-account-profile.component'
+import { MyAccountVideoChannelsComponent } from '@app/+my-account/my-account-video-channels/my-account-video-channels.component'
+import { MyAccountVideoChannelCreateComponent } from '@app/+my-account/my-account-video-channels/my-account-video-channel-create.component'
+import { MyAccountVideoChannelUpdateComponent } from '@app/+my-account/my-account-video-channels/my-account-video-channel-update.component'
+
+@NgModule({
+  imports: [
+    MyAccountRoutingModule,
+    SharedModule
+  ],
+
+  declarations: [
+    MyAccountComponent,
+    MyAccountSettingsComponent,
+    MyAccountChangePasswordComponent,
+    MyAccountVideoSettingsComponent,
+    MyAccountProfileComponent,
+    MyAccountVideosComponent,
+    MyAccountVideoChannelsComponent,
+    MyAccountVideoChannelCreateComponent,
+    MyAccountVideoChannelUpdateComponent
+  ],
+
+  exports: [
+    MyAccountComponent
+  ],
+
+  providers: []
+})
+export class MyAccountModule { }
index 799748cfabde0408a9822f805f0c840cdfa4d933..936912d282fedddb07d171c6ccf593804da68729 100644 (file)
@@ -8,6 +8,10 @@ const routes: Routes = [
     path: 'admin',
     loadChildren: './+admin/admin.module#AdminModule'
   },
+  {
+    path: 'my-account',
+    loadChildren: './+my-account/my-account.module#MyAccountModule'
+  },
   {
     path: 'accounts',
     loadChildren: './+accounts/accounts.module#AccountsModule'
index c22632fb85d1714608e49be6232ac0db1fdc55d4..f0d2be27925747e521e66c039e56186596fdcd62 100644 (file)
@@ -6,8 +6,6 @@ import { ResetPasswordModule } from '@app/reset-password'
 
 import { MetaLoader, MetaModule, MetaStaticLoader, PageTitlePositioning } from '@ngx-meta/core'
 
-import { MyAccountModule } from './my-account'
-
 import { AppRoutingModule } from './app-routing.module'
 import { AppComponent } from './app.component'
 import { CoreModule } from './core'
@@ -46,7 +44,6 @@ export function metaFactory (serverService: ServerService): MetaLoader {
 
     AppRoutingModule,
 
-    MyAccountModule,
     CoreModule,
     LoginModule,
     ResetPasswordModule,
diff --git a/client/src/app/my-account/index.ts b/client/src/app/my-account/index.ts
deleted file mode 100644 (file)
index 3df96dd..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-export * from './my-account-routing.module'
-export * from './my-account.component'
-export * from './my-account.module'
diff --git a/client/src/app/my-account/my-account-routing.module.ts b/client/src/app/my-account/my-account-routing.module.ts
deleted file mode 100644 (file)
index 96f52c1..0000000
+++ /dev/null
@@ -1,71 +0,0 @@
-import { NgModule } from '@angular/core'
-import { RouterModule, Routes } from '@angular/router'
-import { MetaGuard } from '@ngx-meta/core'
-import { LoginGuard } from '../core'
-import { MyAccountComponent } from './my-account.component'
-import { MyAccountSettingsComponent } from './my-account-settings/my-account-settings.component'
-import { MyAccountVideosComponent } from './my-account-videos/my-account-videos.component'
-import { MyAccountVideoChannelsComponent } from '@app/my-account/my-account-video-channels/my-account-video-channels.component'
-import { MyAccountVideoChannelCreateComponent } from '@app/my-account/my-account-video-channels/my-account-video-channel-create.component'
-import { MyAccountVideoChannelUpdateComponent } from '@app/my-account/my-account-video-channels/my-account-video-channel-update.component'
-
-const myAccountRoutes: Routes = [
-  {
-    path: 'my-account',
-    component: MyAccountComponent,
-    canActivateChild: [ MetaGuard, LoginGuard ],
-    children: [
-      {
-        path: 'settings',
-        component: MyAccountSettingsComponent,
-        data: {
-          meta: {
-            title: 'Account settings'
-          }
-        }
-      },
-      {
-        path: 'video-channels',
-        component: MyAccountVideoChannelsComponent,
-        data: {
-          meta: {
-            title: 'Account video channels'
-          }
-        }
-      },
-      {
-        path: 'video-channels/create',
-        component: MyAccountVideoChannelCreateComponent,
-        data: {
-          meta: {
-            title: 'Create new video channel'
-          }
-        }
-      },
-      {
-        path: 'video-channels/update/:videoChannelId',
-        component: MyAccountVideoChannelUpdateComponent,
-        data: {
-          meta: {
-            title: 'Update video channel'
-          }
-        }
-      },
-      {
-        path: 'videos',
-        component: MyAccountVideosComponent,
-        data: {
-          meta: {
-            title: 'Account videos'
-          }
-        }
-      }
-    ]
-  }
-]
-
-@NgModule({
-  imports: [ RouterModule.forChild(myAccountRoutes) ],
-  exports: [ RouterModule ]
-})
-export class MyAccountRoutingModule {}
diff --git a/client/src/app/my-account/my-account-settings/my-account-change-password/index.ts b/client/src/app/my-account/my-account-settings/my-account-change-password/index.ts
deleted file mode 100644 (file)
index 644047c..0000000
+++ /dev/null
@@ -1 +0,0 @@
-export * from './my-account-change-password.component'
diff --git a/client/src/app/my-account/my-account-settings/my-account-change-password/my-account-change-password.component.html b/client/src/app/my-account/my-account-settings/my-account-change-password/my-account-change-password.component.html
deleted file mode 100644 (file)
index b0e3cad..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
-
-<form role="form" (ngSubmit)="changePassword()" [formGroup]="form">
-
-  <label for="new-password">Change password</label>
-  <input
-    type="password" id="new-password" placeholder="New password"
-    formControlName="new-password" [ngClass]="{ 'input-error': formErrors['new-password'] }"
-  >
-  <div *ngIf="formErrors['new-password']" class="form-error">
-    {{ formErrors['new-password'] }}
-  </div>
-
-  <input
-    type="password" id="new-confirmed-password" placeholder="Confirm new password"
-    formControlName="new-confirmed-password"
-  >
-
-  <input type="submit" value="Change password" [disabled]="!form.valid">
-</form>
diff --git a/client/src/app/my-account/my-account-settings/my-account-change-password/my-account-change-password.component.scss b/client/src/app/my-account/my-account-settings/my-account-change-password/my-account-change-password.component.scss
deleted file mode 100644 (file)
index f8279ff..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-@import '_variables';
-@import '_mixins';
-
-input[type=password] {
-  @include peertube-input-text(340px);
-  display: block;
-
-  &#new-confirmed-password {
-    margin-top: 15px;
-  }
-}
-
-input[type=submit] {
-  @include peertube-button;
-  @include orange-button;
-
-  margin-top: 15px;
-}
-
diff --git a/client/src/app/my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts b/client/src/app/my-account/my-account-settings/my-account-change-password/my-account-change-password.component.ts
deleted file mode 100644 (file)
index 80af668..0000000
+++ /dev/null
@@ -1,62 +0,0 @@
-import { Component, OnInit } from '@angular/core'
-import { FormBuilder, FormGroup } from '@angular/forms'
-import { NotificationsService } from 'angular2-notifications'
-import { FormReactive, USER_PASSWORD, UserService } from '../../../shared'
-
-@Component({
-  selector: 'my-account-change-password',
-  templateUrl: './my-account-change-password.component.html',
-  styleUrls: [ './my-account-change-password.component.scss' ]
-})
-export class MyAccountChangePasswordComponent extends FormReactive implements OnInit {
-  error: string = null
-
-  form: FormGroup
-  formErrors = {
-    'new-password': '',
-    'new-confirmed-password': ''
-  }
-  validationMessages = {
-    'new-password': USER_PASSWORD.MESSAGES,
-    'new-confirmed-password': USER_PASSWORD.MESSAGES
-  }
-
-  constructor (
-    private formBuilder: FormBuilder,
-    private notificationsService: NotificationsService,
-    private userService: UserService
-  ) {
-    super()
-  }
-
-  buildForm () {
-    this.form = this.formBuilder.group({
-      'new-password': [ '', USER_PASSWORD.VALIDATORS ],
-      'new-confirmed-password': [ '', USER_PASSWORD.VALIDATORS ]
-    })
-
-    this.form.valueChanges.subscribe(data => this.onValueChanged(data))
-  }
-
-  ngOnInit () {
-    this.buildForm()
-  }
-
-  changePassword () {
-    const newPassword = this.form.value['new-password']
-    const newConfirmedPassword = this.form.value['new-confirmed-password']
-
-    this.error = null
-
-    if (newPassword !== newConfirmedPassword) {
-      this.error = 'The new password and the confirmed password do not correspond.'
-      return
-    }
-
-    this.userService.changePassword(newPassword).subscribe(
-      () => this.notificationsService.success('Success', 'Password updated.'),
-
-      err => this.error = err.message
-    )
-  }
-}
diff --git a/client/src/app/my-account/my-account-settings/my-account-profile/index.ts b/client/src/app/my-account/my-account-settings/my-account-profile/index.ts
deleted file mode 100644 (file)
index 3cc049f..0000000
+++ /dev/null
@@ -1 +0,0 @@
-export * from './my-account-profile.component'
diff --git a/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.html b/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.html
deleted file mode 100644 (file)
index 306f3a1..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
-
-<form role="form" (ngSubmit)="updateMyProfile()" [formGroup]="form">
-
-  <label for="display-name">Display name</label>
-  <input
-    type="text" id="display-name"
-    formControlName="display-name" [ngClass]="{ 'input-error': formErrors['display-name'] }"
-  >
-  <div *ngIf="formErrors['display-name']" class="form-error">
-    {{ formErrors['display-name'] }}
-  </div>
-
-  <label for="description">Description</label>
-  <textarea
-    id="description" formControlName="description"
-    [ngClass]="{ 'input-error': formErrors['description'] }"
-  ></textarea>
-  <div *ngIf="formErrors.description" class="form-error">
-    {{ formErrors.description }}
-  </div>
-
-  <input type="submit" value="Update my profile" [disabled]="!form.valid">
-</form>
diff --git a/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.scss b/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.scss
deleted file mode 100644 (file)
index fc2b92c..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-@import '_variables';
-@import '_mixins';
-
-input[type=text] {
-  @include peertube-input-text(340px);
-
-  display: block;
-  margin-bottom: 15px;
-}
-
-textarea {
-  @include peertube-textarea(500px, 150px);
-
-  display: block;
-}
-
-input[type=submit] {
-  @include peertube-button;
-  @include orange-button;
-
-  margin-top: 15px;
-}
-
diff --git a/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.ts b/client/src/app/my-account/my-account-settings/my-account-profile/my-account-profile.component.ts
deleted file mode 100644 (file)
index 2b7ba35..0000000
+++ /dev/null
@@ -1,65 +0,0 @@
-import { Component, Input, OnInit } from '@angular/core'
-import { FormBuilder, FormGroup } from '@angular/forms'
-import { NotificationsService } from 'angular2-notifications'
-import { FormReactive, USER_DESCRIPTION, USER_DISPLAY_NAME, UserService } from '../../../shared'
-import { User } from '@app/shared'
-
-@Component({
-  selector: 'my-account-profile',
-  templateUrl: './my-account-profile.component.html',
-  styleUrls: [ './my-account-profile.component.scss' ]
-})
-export class MyAccountProfileComponent extends FormReactive implements OnInit {
-  @Input() user: User = null
-
-  error: string = null
-
-  form: FormGroup
-  formErrors = {
-    'display-name': '',
-    'description': ''
-  }
-  validationMessages = {
-    'display-name': USER_DISPLAY_NAME.MESSAGES,
-    'description': USER_DESCRIPTION.MESSAGES
-  }
-
-  constructor (
-    private formBuilder: FormBuilder,
-    private notificationsService: NotificationsService,
-    private userService: UserService
-  ) {
-    super()
-  }
-
-  buildForm () {
-    this.form = this.formBuilder.group({
-      'display-name': [ this.user.account.displayName, USER_DISPLAY_NAME.VALIDATORS ],
-      'description': [ this.user.account.description, USER_DESCRIPTION.VALIDATORS ]
-    })
-
-    this.form.valueChanges.subscribe(data => this.onValueChanged(data))
-  }
-
-  ngOnInit () {
-    this.buildForm()
-  }
-
-  updateMyProfile () {
-    const displayName = this.form.value['display-name']
-    const description = this.form.value['description']
-
-    this.error = null
-
-    this.userService.updateMyProfile({ displayName, description }).subscribe(
-      () => {
-        this.user.account.displayName = displayName
-        this.user.account.description = description
-
-        this.notificationsService.success('Success', 'Profile updated.')
-      },
-
-      err => this.error = err.message
-    )
-  }
-}
diff --git a/client/src/app/my-account/my-account-settings/my-account-settings.component.html b/client/src/app/my-account/my-account-settings/my-account-settings.component.html
deleted file mode 100644 (file)
index 0fcc778..0000000
+++ /dev/null
@@ -1,32 +0,0 @@
-<div class="user">
-  <img [src]="user.accountAvatarUrl" alt="Avatar" />
-
-  <div class="user-info">
-    <div class="user-info-names">
-      <div class="user-info-display-name">{{ user.account.displayName }}</div>
-      <div class="user-info-username">{{ user.username }}</div>
-    </div>
-    <div class="user-info-followers">{{ user.account?.followersCount }} subscribers</div>
-  </div>
-</div>
-
-<div class="button-file">
-  <span>Change your avatar</span>
-  <input #avatarfileInput type="file" name="avatarfile" id="avatarfile" [accept]="avatarExtensions" (change)="changeAvatar()" />
-</div>
-<div class="file-max-size">(extensions: {{ avatarExtensions }}, max size: {{ maxAvatarSize | bytes }})</div>
-
-<div class="user-quota">
-  <span class="user-quota-label">Video quota:</span> {{ userVideoQuotaUsed | bytes: 0 }} / {{ userVideoQuota }}
-</div>
-
-<ng-template [ngIf]="user && user.account">
-  <div class="account-title">Profile</div>
-  <my-account-profile [user]="user"></my-account-profile>
-</ng-template>
-
-<div class="account-title">Password</div>
-<my-account-change-password></my-account-change-password>
-
-<div class="account-title">Video settings</div>
-<my-account-video-settings [user]="user"></my-account-video-settings>
diff --git a/client/src/app/my-account/my-account-settings/my-account-settings.component.scss b/client/src/app/my-account/my-account-settings/my-account-settings.component.scss
deleted file mode 100644 (file)
index ec0d40b..0000000
+++ /dev/null
@@ -1,67 +0,0 @@
-@import '_variables';
-@import '_mixins';
-
-.user {
-  display: flex;
-
-  img {
-    @include avatar(50px);
-
-    margin-right: 15px;
-  }
-
-  .user-info {
-    .user-info-names {
-      display: flex;
-      align-items: center;
-
-      .user-info-display-name {
-        font-size: 20px;
-        font-weight: $font-bold;
-      }
-
-      .user-info-username {
-        margin-left: 7px;
-        position: relative;
-        top: 2px;
-        font-size: 14px;
-        color: #777272;
-      }
-    }
-
-    .user-info-followers {
-      font-size: 15px;
-    }
-  }
-}
-
-.button-file {
-  @include peertube-button-file(160px);
-
-  margin-top: 10px;
-  margin-bottom: 5px;
-}
-
-.file-max-size {
-  display: inline-block;
-  font-size: 13px;
-
-  position: relative;
-  top: -10px;
-}
-
-.user-quota {
-  font-size: 15px;
-  margin-top: 20px;
-
-  .user-quota-label {
-    font-weight: $font-semibold;
-  }
-}
-
-.account-title {
-  @include in-content-small-title;
-
-  margin-top: 55px;
-  margin-bottom: 30px;
-}
diff --git a/client/src/app/my-account/my-account-settings/my-account-settings.component.ts b/client/src/app/my-account/my-account-settings/my-account-settings.component.ts
deleted file mode 100644 (file)
index 06d1138..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-import { Component, OnInit, ViewChild } from '@angular/core'
-import { NotificationsService } from 'angular2-notifications'
-import { BytesPipe } from 'ngx-pipes'
-import { AuthService } from '../../core'
-import { ServerService } from '../../core/server'
-import { User } from '../../shared'
-import { UserService } from '../../shared/users'
-
-@Component({
-  selector: 'my-account-settings',
-  templateUrl: './my-account-settings.component.html',
-  styleUrls: [ './my-account-settings.component.scss' ]
-})
-export class MyAccountSettingsComponent implements OnInit {
-  @ViewChild('avatarfileInput') avatarfileInput
-
-  user: User = null
-  userVideoQuota = '0'
-  userVideoQuotaUsed = 0
-
-  constructor (
-    private userService: UserService,
-    private authService: AuthService,
-    private serverService: ServerService,
-    private notificationsService: NotificationsService
-  ) {}
-
-  ngOnInit () {
-    this.user = this.authService.getUser()
-
-    this.authService.userInformationLoaded.subscribe(
-      () => {
-        if (this.user.videoQuota !== -1) {
-          this.userVideoQuota = new BytesPipe().transform(this.user.videoQuota, 0).toString()
-        } else {
-          this.userVideoQuota = 'Unlimited'
-        }
-      }
-    )
-
-    this.userService.getMyVideoQuotaUsed()
-      .subscribe(data => this.userVideoQuotaUsed = data.videoQuotaUsed)
-  }
-
-  changeAvatar () {
-    const avatarfile = this.avatarfileInput.nativeElement.files[ 0 ]
-
-    const formData = new FormData()
-    formData.append('avatarfile', avatarfile)
-
-    this.userService.changeAvatar(formData)
-      .subscribe(
-        data => {
-          this.notificationsService.success('Success', 'Avatar changed.')
-
-          this.user.account.avatar = data.avatar
-        },
-
-        err => this.notificationsService.error('Error', err.message)
-      )
-  }
-
-  get maxAvatarSize () {
-    return this.serverService.getConfig().avatar.file.size.max
-  }
-
-  get avatarExtensions () {
-    return this.serverService.getConfig().avatar.file.extensions.join(',')
-  }
-}
diff --git a/client/src/app/my-account/my-account-settings/my-account-video-settings/index.ts b/client/src/app/my-account/my-account-settings/my-account-video-settings/index.ts
deleted file mode 100644 (file)
index 1253bd3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-export * from './my-account-video-settings.component'
diff --git a/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html b/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.html
deleted file mode 100644 (file)
index 0e8598e..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
-<form role="form" (ngSubmit)="updateDetails()" [formGroup]="form">
-  <div class="form-group">
-    <label for="nsfwPolicy">Default policy on videos containing sensitive content</label>
-    <my-help helpType="custom" customHtml="With <strong>Do not list</strong> or <strong>Blur thumbnails</strong>, a confirmation will be requested to watch the video."></my-help>
-
-    <div class="peertube-select-container">
-      <select id="nsfwPolicy" formControlName="nsfwPolicy">
-        <option value="do_not_list">Do not list</option>
-        <option value="blur">Blur thumbnails</option>
-        <option value="display">Display</option>
-      </select>
-    </div>
-  </div>
-
-  <div class="form-group">
-    <input
-      type="checkbox" id="autoPlayVideo"
-      formControlName="autoPlayVideo"
-    >
-    <label for="autoPlayVideo"></label>
-    <label for="autoPlayVideo">Automatically plays video</label>
-  </div>
-
-  <input type="submit" value="Save" [disabled]="!form.valid">
-</form>
diff --git a/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.scss b/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.scss
deleted file mode 100644 (file)
index ed59e46..0000000
+++ /dev/null
@@ -1,20 +0,0 @@
-@import '_variables';
-@import '_mixins';
-
-input[type=checkbox] {
-  @include peertube-checkbox(1px);
-}
-
-input[type=submit] {
-  @include peertube-button;
-  @include orange-button;
-
-  display: block;
-  margin-top: 15px;
-}
-
-.peertube-select-container {
-  @include peertube-select-container(340px);
-
-  margin-bottom: 30px;
-}
\ No newline at end of file
diff --git a/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts b/client/src/app/my-account/my-account-settings/my-account-video-settings/my-account-video-settings.component.ts
deleted file mode 100644 (file)
index acc70c1..0000000
+++ /dev/null
@@ -1,60 +0,0 @@
-import { Component, Input, OnInit } from '@angular/core'
-import { FormBuilder, FormGroup } from '@angular/forms'
-import { NotificationsService } from 'angular2-notifications'
-import { UserUpdateMe } from '../../../../../../shared'
-import { AuthService } from '../../../core'
-import { FormReactive, User, UserService } from '../../../shared'
-
-@Component({
-  selector: 'my-account-video-settings',
-  templateUrl: './my-account-video-settings.component.html',
-  styleUrls: [ './my-account-video-settings.component.scss' ]
-})
-export class MyAccountVideoSettingsComponent extends FormReactive implements OnInit {
-  @Input() user: User = null
-
-  form: FormGroup
-  formErrors = {}
-  validationMessages = {}
-
-  constructor (
-    private authService: AuthService,
-    private formBuilder: FormBuilder,
-    private notificationsService: NotificationsService,
-    private userService: UserService
-  ) {
-    super()
-  }
-
-  buildForm () {
-    this.form = this.formBuilder.group({
-      nsfwPolicy: [ this.user.nsfwPolicy ],
-      autoPlayVideo: [ this.user.autoPlayVideo ]
-    })
-
-    this.form.valueChanges.subscribe(data => this.onValueChanged(data))
-  }
-
-  ngOnInit () {
-    this.buildForm()
-  }
-
-  updateDetails () {
-    const nsfwPolicy = this.form.value['nsfwPolicy']
-    const autoPlayVideo = this.form.value['autoPlayVideo']
-    const details: UserUpdateMe = {
-      nsfwPolicy,
-      autoPlayVideo
-    }
-
-    this.userService.updateMyProfile(details).subscribe(
-      () => {
-        this.notificationsService.success('Success', 'Information updated.')
-
-        this.authService.refreshUserInformation()
-      },
-
-      err => this.notificationsService.error('Error', err.message)
-    )
-  }
-}
diff --git a/client/src/app/my-account/my-account-video-channels/my-account-video-channel-create.component.ts b/client/src/app/my-account/my-account-video-channels/my-account-video-channel-create.component.ts
deleted file mode 100644 (file)
index 0f03548..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-import { Component, OnInit } from '@angular/core'
-import { Router } from '@angular/router'
-import { NotificationsService } from 'angular2-notifications'
-import 'rxjs/add/observable/from'
-import 'rxjs/add/operator/concatAll'
-import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit'
-import { FormBuilder, FormGroup } from '@angular/forms'
-import { VideoChannelCreate } from '../../../../../shared/models/videos'
-import {
-  VIDEO_CHANNEL_DESCRIPTION,
-  VIDEO_CHANNEL_DISPLAY_NAME,
-  VIDEO_CHANNEL_SUPPORT
-} from '@app/shared/forms/form-validators/video-channel'
-import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
-import { AuthService } from '@app/core'
-
-@Component({
-  selector: 'my-account-video-channel-create',
-  templateUrl: './my-account-video-channel-edit.component.html',
-  styleUrls: [ './my-account-video-channel-edit.component.scss' ]
-})
-export class MyAccountVideoChannelCreateComponent extends MyAccountVideoChannelEdit implements OnInit {
-  error: string
-
-  form: FormGroup
-  formErrors = {
-    'display-name': '',
-    'description': '',
-    'support': ''
-  }
-  validationMessages = {
-    'display-name': VIDEO_CHANNEL_DISPLAY_NAME.MESSAGES,
-    'description': VIDEO_CHANNEL_DESCRIPTION.MESSAGES,
-    'support': VIDEO_CHANNEL_SUPPORT.MESSAGES
-  }
-
-  constructor (
-    private authService: AuthService,
-    private notificationsService: NotificationsService,
-    private router: Router,
-    private formBuilder: FormBuilder,
-    private videoChannelService: VideoChannelService
-  ) {
-    super()
-  }
-
-  buildForm () {
-    this.form = this.formBuilder.group({
-      'display-name': [ '', VIDEO_CHANNEL_DISPLAY_NAME.VALIDATORS ],
-      description: [ '', VIDEO_CHANNEL_DESCRIPTION.VALIDATORS ],
-      support: [ '', VIDEO_CHANNEL_SUPPORT.VALIDATORS ]
-    })
-
-    this.form.valueChanges.subscribe(data => this.onValueChanged(data))
-  }
-
-  ngOnInit () {
-    this.buildForm()
-  }
-
-  formValidated () {
-    this.error = undefined
-
-    const body = this.form.value
-    const videoChannelCreate: VideoChannelCreate = {
-      displayName: body['display-name'],
-      description: body.description || undefined,
-      support: body.support || undefined
-    }
-
-    this.videoChannelService.createVideoChannel(videoChannelCreate).subscribe(
-      () => {
-        this.authService.refreshUserInformation()
-        this.notificationsService.success('Success', `Video channel ${videoChannelCreate.displayName} created.`)
-        this.router.navigate([ '/my-account', 'video-channels' ])
-      },
-
-      err => this.error = err.message
-    )
-  }
-
-  isCreation () {
-    return true
-  }
-
-  getFormButtonTitle () {
-    return 'Create'
-  }
-}
diff --git a/client/src/app/my-account/my-account-video-channels/my-account-video-channel-edit.component.html b/client/src/app/my-account/my-account-video-channels/my-account-video-channel-edit.component.html
deleted file mode 100644 (file)
index d5fb626..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-<div class="form-sub-title" *ngIf="isCreation() === true">Create a video channel</div>
-<div class="form-sub-title" *ngIf="isCreation() === false">Update {{ videoChannel?.displayName }}</div>
-
-<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
-
-<form role="form" (ngSubmit)="formValidated()" [formGroup]="form">
-  <div class="form-group">
-    <label for="display-name">Display name</label>
-    <input
-      type="text" id="display-name"
-      formControlName="display-name" [ngClass]="{ 'input-error': formErrors['display-name'] }"
-    >
-    <div *ngIf="formErrors['display-name']" class="form-error">
-      {{ formErrors['display-name'] }}
-    </div>
-  </div>
-
-  <div class="form-group">
-    <label for="description">Description</label>
-    <textarea
-      id="description" formControlName="description"
-      [ngClass]="{ 'input-error': formErrors['description'] }"
-    ></textarea>
-    <div *ngIf="formErrors.description" class="form-error">
-      {{ formErrors.description }}
-    </div>
-  </div>
-
-  <div class="form-group">
-    <label for="support">Support</label>
-    <my-help helpType="markdownEnhanced" preHtml="Short text to tell people how they can support your channel (membership platform...)."></my-help>
-    <my-markdown-textarea
-        id="support" formControlName="support" textareaWidth="500px" [previewColumn]="true" markdownType="enhanced"
-        [classes]="{ 'input-error': formErrors['support'] }"
-    ></my-markdown-textarea>
-    <div *ngIf="formErrors.support" class="form-error">
-      {{ formErrors.support }}
-    </div>
-  </div>
-
-  <input type="submit" value="{{ getFormButtonTitle() }}" [disabled]="!form.valid">
-</form>
diff --git a/client/src/app/my-account/my-account-video-channels/my-account-video-channel-edit.component.scss b/client/src/app/my-account/my-account-video-channels/my-account-video-channel-edit.component.scss
deleted file mode 100644 (file)
index 6fbb8ae..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-@import '_variables';
-@import '_mixins';
-
-.form-sub-title {
-  margin-bottom: 20px;
-}
-
-input[type=text] {
-  @include peertube-input-text(340px);
-
-  display: block;
-}
-
-textarea {
-  @include peertube-textarea(500px, 150px);
-
-  display: block;
-}
-
-.peertube-select-container {
-  @include peertube-select-container(340px);
-}
-
-input[type=submit] {
-  @include peertube-button;
-  @include orange-button;
-}
\ No newline at end of file
diff --git a/client/src/app/my-account/my-account-video-channels/my-account-video-channel-edit.ts b/client/src/app/my-account/my-account-video-channels/my-account-video-channel-edit.ts
deleted file mode 100644 (file)
index e56f462..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-import { FormReactive } from '@app/shared'
-
-export abstract class MyAccountVideoChannelEdit extends FormReactive {
-  abstract isCreation (): boolean
-  abstract getFormButtonTitle (): string
-}
diff --git a/client/src/app/my-account/my-account-video-channels/my-account-video-channel-update.component.ts b/client/src/app/my-account/my-account-video-channels/my-account-video-channel-update.component.ts
deleted file mode 100644 (file)
index c0dc6a9..0000000
+++ /dev/null
@@ -1,117 +0,0 @@
-import { Component, OnInit, OnDestroy } from '@angular/core'
-import { ActivatedRoute, Router } from '@angular/router'
-import { NotificationsService } from 'angular2-notifications'
-import 'rxjs/add/observable/from'
-import 'rxjs/add/operator/concatAll'
-import { MyAccountVideoChannelEdit } from './my-account-video-channel-edit'
-import { FormBuilder, FormGroup } from '@angular/forms'
-import { VideoChannelUpdate } from '../../../../../shared/models/videos'
-import {
-  VIDEO_CHANNEL_DESCRIPTION,
-  VIDEO_CHANNEL_DISPLAY_NAME,
-  VIDEO_CHANNEL_SUPPORT
-} from '@app/shared/forms/form-validators/video-channel'
-import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
-import { Subscription } from 'rxjs/Subscription'
-import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
-import { AuthService } from '@app/core'
-
-@Component({
-  selector: 'my-account-video-channel-update',
-  templateUrl: './my-account-video-channel-edit.component.html',
-  styleUrls: [ './my-account-video-channel-edit.component.scss' ]
-})
-export class MyAccountVideoChannelUpdateComponent extends MyAccountVideoChannelEdit implements OnInit, OnDestroy {
-  error: string
-
-  form: FormGroup
-  formErrors = {
-    'display-name': '',
-    'description': '',
-    'support': ''
-  }
-  validationMessages = {
-    'display-name': VIDEO_CHANNEL_DISPLAY_NAME.MESSAGES,
-    'description': VIDEO_CHANNEL_DESCRIPTION.MESSAGES,
-    'support': VIDEO_CHANNEL_SUPPORT.MESSAGES
-  }
-
-  private videoChannelToUpdate: VideoChannel
-  private paramsSub: Subscription
-
-  constructor (
-    private authService: AuthService,
-    private notificationsService: NotificationsService,
-    private router: Router,
-    private route: ActivatedRoute,
-    private formBuilder: FormBuilder,
-    private videoChannelService: VideoChannelService
-  ) {
-    super()
-  }
-
-  buildForm () {
-    this.form = this.formBuilder.group({
-      'display-name': [ '', VIDEO_CHANNEL_DISPLAY_NAME.VALIDATORS ],
-      description: [ '', VIDEO_CHANNEL_DESCRIPTION.VALIDATORS ],
-      support: [ '', VIDEO_CHANNEL_SUPPORT.VALIDATORS ]
-    })
-
-    this.form.valueChanges.subscribe(data => this.onValueChanged(data))
-  }
-
-  ngOnInit () {
-    this.buildForm()
-
-    this.paramsSub = this.route.params.subscribe(routeParams => {
-      const videoChannelId = routeParams['videoChannelId']
-
-      this.videoChannelService.getVideoChannel(videoChannelId).subscribe(
-        videoChannelToUpdate => {
-          this.videoChannelToUpdate = videoChannelToUpdate
-
-          this.form.patchValue({
-            'display-name': videoChannelToUpdate.displayName,
-            description: videoChannelToUpdate.description,
-            support: videoChannelToUpdate.support
-          })
-        },
-
-        err => this.error = err.message
-      )
-    })
-  }
-
-  ngOnDestroy () {
-    if (this.paramsSub) this.paramsSub.unsubscribe()
-  }
-
-  formValidated () {
-    this.error = undefined
-
-    const body = this.form.value
-    const videoChannelUpdate: VideoChannelUpdate = {
-      displayName: body['display-name'],
-      description: body.description || undefined,
-      support: body.support || undefined
-    }
-
-    this.videoChannelService.updateVideoChannel(this.videoChannelToUpdate.uuid, videoChannelUpdate).subscribe(
-      () => {
-        this.authService.refreshUserInformation()
-        this.notificationsService.success('Success', `Video channel ${videoChannelUpdate.displayName} updated.`)
-        this.router.navigate([ '/my-account', 'video-channels' ])
-      },
-
-      err => this.error = err.message
-    )
-  }
-
-  isCreation () {
-    return false
-  }
-
-  getFormButtonTitle () {
-    return 'Update'
-  }
-}
diff --git a/client/src/app/my-account/my-account-video-channels/my-account-video-channels.component.html b/client/src/app/my-account/my-account-video-channels/my-account-video-channels.component.html
deleted file mode 100644 (file)
index 90c401b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-<div class="video-channels-header">
-  <a class="create-button" routerLink="create">
-    <span class="icon icon-add"></span>
-    Create another video channel
-  </a>
-</div>
-
-<div class="video-channels">
-  <div *ngFor="let videoChannel of videoChannels" class="video-channel">
-    <a [routerLink]="[ '/video-channels', videoChannel.uuid ]">
-      <img [src]="videoChannel.avatarUrl" alt="Avatar" />
-    </a>
-
-    <div class="video-channel-info">
-      <a [routerLink]="[ '/video-channels', videoChannel.uuid ]" class="video-channel-names" title="Go to the channel">
-        <div class="video-channel-display-name">{{ videoChannel.displayName }}</div>
-        <!-- Hide the name for now, because it's an UUID not very friendly -->
-        <!--<div class="video-channel-name">{{ videoChannel.name }}</div>-->
-      </a>
-
-      <div class="video-channel-followers">{{ videoChannel.followersCount }} subscribers</div>
-    </div>
-
-    <div class="video-channel-buttons">
-      <my-delete-button (click)="deleteVideoChannel(videoChannel)"></my-delete-button>
-
-      <my-edit-button [routerLink]="[ 'update', videoChannel.uuid ]"></my-edit-button>
-    </div>
-  </div>
-</div>
diff --git a/client/src/app/my-account/my-account-video-channels/my-account-video-channels.component.scss b/client/src/app/my-account/my-account-video-channels/my-account-video-channels.component.scss
deleted file mode 100644 (file)
index bcb58ea..0000000
+++ /dev/null
@@ -1,72 +0,0 @@
-@import '_variables';
-@import '_mixins';
-
-.create-button {
-  @include create-button;
-}
-
-/deep/ .action-button {
-  &.action-button-delete {
-    margin-right: 10px;
-  }
-}
-
-.video-channel {
-  display: flex;
-  min-height: 130px;
-  padding-bottom: 20px;
-  margin-bottom: 20px;
-  border-bottom: 1px solid #C6C6C6;
-
-  img {
-    @include avatar(80px);
-
-    margin-right: 10px;
-  }
-
-  .video-channel-info {
-    flex-grow: 1;
-
-    a.video-channel-names {
-      @include disable-default-a-behaviour;
-
-      display: flex;
-      color: #000;
-
-      .video-channel-display-name {
-        font-weight: $font-semibold;
-        font-size: 18px;
-      }
-
-      .video-channel-name {
-        font-size: 14px;
-        color: #777272;
-      }
-    }
-  }
-
-  .video-channel-buttons {
-    min-width: 190px;
-  }
-}
-
-.video-channels-header {
-  text-align: right;
-  margin: 20px 0 50px;
-}
-
-@media screen and (max-width: 800px) {
-  .video-channel {
-    flex-direction: column;
-    height: auto;
-    text-align: center;
-
-    img {
-      margin-right: 0;
-    }
-
-    .video-channel-buttons {
-      margin-top: 10px;
-    }
-  }
-}
diff --git a/client/src/app/my-account/my-account-video-channels/my-account-video-channels.component.ts b/client/src/app/my-account/my-account-video-channels/my-account-video-channels.component.ts
deleted file mode 100644 (file)
index eeaca11..0000000
+++ /dev/null
@@ -1,59 +0,0 @@
-import { Component, OnInit } from '@angular/core'
-import { NotificationsService } from 'angular2-notifications'
-import 'rxjs/add/observable/from'
-import 'rxjs/add/operator/concatAll'
-import { AuthService } from '../../core/auth'
-import { ConfirmService } from '../../core/confirm'
-import { VideoChannel } from '@app/shared/video-channel/video-channel.model'
-import { VideoChannelService } from '@app/shared/video-channel/video-channel.service'
-import { User } from '@app/shared'
-
-@Component({
-  selector: 'my-account-video-channels',
-  templateUrl: './my-account-video-channels.component.html',
-  styleUrls: [ './my-account-video-channels.component.scss' ]
-})
-export class MyAccountVideoChannelsComponent implements OnInit {
-  videoChannels: VideoChannel[] = []
-
-  private user: User
-
-  constructor (
-    private authService: AuthService,
-    private notificationsService: NotificationsService,
-    private confirmService: ConfirmService,
-    private videoChannelService: VideoChannelService
-  ) {}
-
-  ngOnInit () {
-    this.user = this.authService.getUser()
-
-    this.loadVideoChannels()
-  }
-
-  async deleteVideoChannel (videoChannel: VideoChannel) {
-    const res = await this.confirmService.confirmWithInput(
-      `Do you really want to delete ${videoChannel.displayName}? It will delete all videos uploaded in this channel too.`,
-      'Please type the name of the video channel to confirm',
-      videoChannel.displayName,
-      'Delete'
-    )
-    if (res === false) return
-
-    this.videoChannelService.removeVideoChannel(videoChannel)
-      .subscribe(
-        status => {
-          this.loadVideoChannels()
-          this.notificationsService.success('Success', `Video channel ${videoChannel.name} deleted.`)
-        },
-
-        error => this.notificationsService.error('Error', error.message)
-      )
-  }
-
-  private loadVideoChannels () {
-    this.authService.userInformationLoaded
-        .flatMap(() => this.videoChannelService.listAccountVideoChannels(this.user.account.id))
-        .subscribe(res => this.videoChannels = res.data)
-  }
-}
diff --git a/client/src/app/my-account/my-account-videos/my-account-videos.component.html b/client/src/app/my-account/my-account-videos/my-account-videos.component.html
deleted file mode 100644 (file)
index 66ce3a7..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<div *ngIf="pagination.totalItems === 0">No results.</div>
-
-<div
-  myInfiniteScroller
-  [pageHeight]="pageHeight"
-  (nearOfTop)="onNearOfTop()" (nearOfBottom)="onNearOfBottom()" (pageChanged)="onPageChanged($event)"
-  class="videos" #videosElement
->
-  <div *ngFor="let videos of videoPages; let i = index" class="videos-page">
-    <div class="video" *ngFor="let video of videos; let j = index">
-      <div class="checkbox-container">
-        <input [id]="'video-check-' + video.id" type="checkbox" [(ngModel)]="checkedVideos[video.id]" />
-        <label [for]="'video-check-' + video.id"></label>
-      </div>
-
-      <my-video-thumbnail [video]="video"></my-video-thumbnail>
-
-      <div class="video-info">
-        <a class="video-info-name" [routerLink]="['/videos/watch', video.uuid]" [attr.title]="video.name">{{ video.name }}</a>
-        <span class="video-info-date-views">{{ video.createdAt | myFromNow }} - {{ video.views | myNumberFormatter }} views</span>
-        <div class="video-info-private">{{ video.privacy.label }}</div>
-      </div>
-
-      <!-- Display only once -->
-      <div class="action-selection-mode" *ngIf="isInSelectionMode() === true && i === 0 && j === 0">
-        <div class="action-selection-mode-child">
-          <span class="action-button action-button-cancel-selection" (click)="abortSelectionMode()">
-            Cancel
-          </span>
-
-          <span class="action-button action-button-delete-selection" (click)="deleteSelectedVideos()">
-            <span class="icon icon-delete-white"></span>
-            Delete
-          </span>
-        </div>
-      </div>
-
-      <div class="video-buttons" *ngIf="isInSelectionMode() === false">
-        <my-delete-button (click)="deleteVideo(video)"></my-delete-button>
-
-        <my-edit-button [routerLink]="[ '/videos', 'edit', video.uuid ]"></my-edit-button>
-      </div>
-    </div>
-  </div>
-</div>
diff --git a/client/src/app/my-account/my-account-videos/my-account-videos.component.scss b/client/src/app/my-account/my-account-videos/my-account-videos.component.scss
deleted file mode 100644 (file)
index f276ea3..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-@import '_variables';
-@import '_mixins';
-
-.action-selection-mode {
-  width: 174px;
-  display: flex;
-  justify-content: flex-end;
-
-  .action-selection-mode-child {
-    position: fixed;
-
-    .action-button {
-      display: inline-block;
-    }
-
-    .action-button-cancel-selection {
-      @include peertube-button;
-      @include grey-button;
-
-      margin-right: 10px;
-    }
-
-    .action-button-delete-selection {
-      @include peertube-button;
-      @include orange-button;
-    }
-
-    .icon.icon-delete-white {
-      @include icon(21px);
-
-      position: relative;
-      top: -2px;
-      background-image: url('../../../assets/images/global/delete-white.svg');
-    }
-  }
-}
-
-/deep/ .action-button {
-  &.action-button-delete {
-    margin-right: 10px;
-  }
-}
-
-.video {
-  display: flex;
-  min-height: 130px;
-  padding-bottom: 20px;
-  margin-bottom: 20px;
-  border-bottom: 1px solid #C6C6C6;
-
-  &:first-child {
-    margin-top: 47px;
-  }
-
-  .checkbox-container {
-    display: flex;
-    align-items: center;
-    margin-right: 20px;
-    margin-left: 12px;
-
-    input[type=checkbox] {
-      @include peertube-checkbox(2px);
-    }
-  }
-
-  my-video-thumbnail {
-    margin-right: 10px;
-  }
-
-  .video-info {
-    flex-grow: 1;
-
-    .video-info-name {
-      @include disable-default-a-behaviour;
-
-      color: #000;
-      display: block;
-      font-size: 16px;
-      font-weight: $font-semibold;
-    }
-
-    .video-info-date-views, .video-info-private {
-      font-size: 13px;
-
-      &.video-info-private {
-        font-weight: $font-semibold;
-      }
-    }
-  }
-
-  .video-buttons {
-    min-width: 190px;
-  }
-}
-
-@media screen and (max-width: 800px) {
-  .video {
-    flex-direction: column;
-    height: auto;
-    text-align: center;
-
-    input[type=checkbox] {
-      display: none;
-    }
-
-    my-video-thumbnail {
-      margin-right: 0;
-    }
-
-    .video-buttons {
-      margin-top: 10px;
-    }
-  }
-}
diff --git a/client/src/app/my-account/my-account-videos/my-account-videos.component.ts b/client/src/app/my-account/my-account-videos/my-account-videos.component.ts
deleted file mode 100644 (file)
index c1b53bc..0000000
+++ /dev/null
@@ -1,131 +0,0 @@
-import { Component, OnInit, OnDestroy } from '@angular/core'
-import { ActivatedRoute, Router } from '@angular/router'
-import { Location } from '@angular/common'
-import { immutableAssign } from '@app/shared/misc/utils'
-import { ComponentPagination } from '@app/shared/rest/component-pagination.model'
-import { NotificationsService } from 'angular2-notifications'
-import 'rxjs/add/observable/from'
-import 'rxjs/add/operator/concatAll'
-import { Observable } from 'rxjs/Observable'
-import { AuthService } from '../../core/auth'
-import { ConfirmService } from '../../core/confirm'
-import { AbstractVideoList } from '../../shared/video/abstract-video-list'
-import { Video } from '../../shared/video/video.model'
-import { VideoService } from '../../shared/video/video.service'
-
-@Component({
-  selector: 'my-account-videos',
-  templateUrl: './my-account-videos.component.html',
-  styleUrls: [ './my-account-videos.component.scss' ]
-})
-export class MyAccountVideosComponent extends AbstractVideoList implements OnInit, OnDestroy {
-  titlePage = 'My videos'
-  currentRoute = '/my-account/videos'
-  checkedVideos: { [ id: number ]: boolean } = {}
-  pagination: ComponentPagination = {
-    currentPage: 1,
-    itemsPerPage: 5,
-    totalItems: null
-  }
-
-  protected baseVideoWidth = -1
-  protected baseVideoHeight = 155
-
-  constructor (protected router: Router,
-               protected route: ActivatedRoute,
-               protected authService: AuthService,
-               protected notificationsService: NotificationsService,
-               protected confirmService: ConfirmService,
-               protected location: Location,
-               private videoService: VideoService) {
-    super()
-  }
-
-  ngOnInit () {
-    super.ngOnInit()
-  }
-
-  ngOnDestroy () {
-    super.ngOnDestroy()
-  }
-
-  abortSelectionMode () {
-    this.checkedVideos = {}
-  }
-
-  isInSelectionMode () {
-    return Object.keys(this.checkedVideos).some(k => this.checkedVideos[k] === true)
-  }
-
-  getVideosObservable (page: number) {
-    const newPagination = immutableAssign(this.pagination, { currentPage: page })
-
-    return this.videoService.getMyVideos(newPagination, this.sort)
-  }
-
-  generateSyndicationList () {
-    throw new Error('Method not implemented.')
-  }
-
-  async deleteSelectedVideos () {
-    const toDeleteVideosIds = Object.keys(this.checkedVideos)
-      .filter(k => this.checkedVideos[k] === true)
-      .map(k => parseInt(k, 10))
-
-    const res = await this.confirmService.confirm(`Do you really want to delete ${toDeleteVideosIds.length} videos?`, 'Delete')
-    if (res === false) return
-
-    const observables: Observable<any>[] = []
-    for (const videoId of toDeleteVideosIds) {
-      const o = this.videoService
-        .removeVideo(videoId)
-        .do(() => this.spliceVideosById(videoId))
-
-      observables.push(o)
-    }
-
-    Observable.from(observables)
-      .concatAll()
-      .subscribe(
-        res => {
-          this.notificationsService.success('Success', `${toDeleteVideosIds.length} videos deleted.`)
-          this.buildVideoPages()
-        },
-
-        err => this.notificationsService.error('Error', err.message)
-      )
-  }
-
-  async deleteVideo (video: Video) {
-    const res = await this.confirmService.confirm(`Do you really want to delete ${video.name}?`, 'Delete')
-    if (res === false) return
-
-    this.videoService.removeVideo(video.id)
-      .subscribe(
-        status => {
-          this.notificationsService.success('Success', `Video ${video.name} deleted.`)
-          this.spliceVideosById(video.id)
-          this.buildVideoPages()
-        },
-
-        error => this.notificationsService.error('Error', error.message)
-      )
-  }
-
-  protected buildVideoHeight () {
-    // In account videos, the video height is fixed
-    return this.baseVideoHeight
-  }
-
-  private spliceVideosById (id: number) {
-    for (const key of Object.keys(this.loadedPages)) {
-      const videos = this.loadedPages[key]
-      const index = videos.findIndex(v => v.id === id)
-
-      if (index !== -1) {
-        videos.splice(index, 1)
-        return
-      }
-    }
-  }
-}
diff --git a/client/src/app/my-account/my-account.component.html b/client/src/app/my-account/my-account.component.html
deleted file mode 100644 (file)
index 591d58c..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-<div class="row">
-  <div class="sub-menu">
-    <a routerLink="/my-account/settings" routerLinkActive="active" class="title-page">My settings</a>
-
-    <a routerLink="/my-account/video-channels" routerLinkActive="active" class="title-page">My video channels</a>
-
-    <a routerLink="/my-account/videos" routerLinkActive="active" class="title-page">My videos</a>
-  </div>
-
-  <div class="margin-content">
-    <router-outlet></router-outlet>
-  </div>
-</div>
diff --git a/client/src/app/my-account/my-account.component.ts b/client/src/app/my-account/my-account.component.ts
deleted file mode 100644 (file)
index 7bb461d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-import { Component } from '@angular/core'
-
-@Component({
-  selector: 'my-my-account',
-  templateUrl: './my-account.component.html'
-})
-export class MyAccountComponent {}
diff --git a/client/src/app/my-account/my-account.module.ts b/client/src/app/my-account/my-account.module.ts
deleted file mode 100644 (file)
index ba9dea7..0000000
+++ /dev/null
@@ -1,38 +0,0 @@
-import { NgModule } from '@angular/core'
-import { SharedModule } from '../shared'
-import { MyAccountRoutingModule } from './my-account-routing.module'
-import { MyAccountChangePasswordComponent } from './my-account-settings/my-account-change-password/my-account-change-password.component'
-import { MyAccountVideoSettingsComponent } from './my-account-settings/my-account-video-settings/my-account-video-settings.component'
-import { MyAccountSettingsComponent } from './my-account-settings/my-account-settings.component'
-import { MyAccountComponent } from './my-account.component'
-import { MyAccountVideosComponent } from './my-account-videos/my-account-videos.component'
-import { MyAccountProfileComponent } from '@app/my-account/my-account-settings/my-account-profile/my-account-profile.component'
-import { MyAccountVideoChannelsComponent } from '@app/my-account/my-account-video-channels/my-account-video-channels.component'
-import { MyAccountVideoChannelCreateComponent } from '@app/my-account/my-account-video-channels/my-account-video-channel-create.component'
-import { MyAccountVideoChannelUpdateComponent } from '@app/my-account/my-account-video-channels/my-account-video-channel-update.component'
-
-@NgModule({
-  imports: [
-    MyAccountRoutingModule,
-    SharedModule
-  ],
-
-  declarations: [
-    MyAccountComponent,
-    MyAccountSettingsComponent,
-    MyAccountChangePasswordComponent,
-    MyAccountVideoSettingsComponent,
-    MyAccountProfileComponent,
-    MyAccountVideosComponent,
-    MyAccountVideoChannelsComponent,
-    MyAccountVideoChannelCreateComponent,
-    MyAccountVideoChannelUpdateComponent
-  ],
-
-  exports: [
-    MyAccountComponent
-  ],
-
-  providers: []
-})
-export class MyAccountModule { }