-import { Injectable } from '@angular/core'
import { HttpClient, HttpParams } from '@angular/common/http'
-import { Observable } from 'rxjs/Observable'
+import { Injectable } from '@angular/core'
+import { BytesPipe } from 'ngx-pipes'
+import { SortMeta } from 'primeng/components/common/sortmeta'
import 'rxjs/add/operator/catch'
import 'rxjs/add/operator/map'
-
-import { SortMeta } from 'primeng/components/common/sortmeta'
-import { BytesPipe } from 'angular-pipes/src/math/bytes.pipe'
-
-import { RestExtractor, User, RestPagination, RestService } from '../../../shared'
-import { UserCreate, UserUpdate, ResultList } from '../../../../../../shared'
+import { Observable } from 'rxjs/Observable'
+import { ResultList, UserCreate, UserUpdate } from '../../../../../../shared'
+import { RestExtractor, RestPagination, RestService, User } from '../../../shared'
@Injectable()
export class UserService {
+++ /dev/null
-<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
-
-<form role="form" (ngSubmit)="changePassword()" [formGroup]="form">
- <div class="form-group">
- <label for="new-password">New password</label>
- <input
- type="password" class="form-control" id="new-password"
- formControlName="new-password"
- >
- <div *ngIf="formErrors['new-password']" class="alert alert-danger">
- {{ formErrors['new-password'] }}
- </div>
- </div>
-
- <div class="form-group">
- <label for="name">Confirm new password</label>
- <input
- type="password" class="form-control" id="new-confirmed-password"
- formControlName="new-confirmed-password"
- >
- </div>
-
- <input type="submit" value="Change password" class="btn btn-default" [disabled]="!form.valid">
-</form>
+++ /dev/null
-import { Component, OnInit } from '@angular/core'
-import { FormBuilder, FormGroup } from '@angular/forms'
-import { Router } from '@angular/router'
-
-import { NotificationsService } from 'angular2-notifications'
-
-import { FormReactive, UserService, USER_PASSWORD } from '../../shared'
-
-@Component({
- selector: 'my-account-change-password',
- templateUrl: './account-change-password.component.html'
-})
-
-export class AccountChangePasswordComponent 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
- )
- }
-}
+++ /dev/null
-export * from './account-change-password.component'
+++ /dev/null
-<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
-
-<form role="form" (ngSubmit)="updateDetails()" [formGroup]="form">
- <div class="form-group">
- <input
- type="checkbox" id="displayNSFW"
- formControlName="displayNSFW"
- >
- <label for="displayNSFW">Display videos that contain mature or explicit content</label>
- <div *ngIf="formErrors['displayNSFW']" class="alert alert-danger">
- {{ formErrors['displayNSFW'] }}
- </div>
- </div>
-
- <input type="submit" value="Update" class="btn btn-default" [disabled]="!form.valid">
-</form>
+++ /dev/null
-import { Component, OnInit, Input } from '@angular/core'
-import { FormBuilder, FormGroup } from '@angular/forms'
-import { Router } from '@angular/router'
-
-import { NotificationsService } from 'angular2-notifications'
-
-import { AuthService } from '../../core'
-import {
- FormReactive,
- User,
- UserService,
- USER_PASSWORD
-} from '../../shared'
-import { UserUpdateMe } from '../../../../../shared'
-
-@Component({
- selector: 'my-account-details',
- templateUrl: './account-details.component.html'
-})
-
-export class AccountDetailsComponent extends FormReactive implements OnInit {
- @Input() user: User = null
-
- error: string = 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({
- displayNSFW: [ this.user.displayNSFW ]
- })
-
- this.form.valueChanges.subscribe(data => this.onValueChanged(data))
- }
-
- ngOnInit () {
- this.buildForm()
- }
-
- updateDetails () {
- const displayNSFW = this.form.value['displayNSFW']
- const details: UserUpdateMe = {
- displayNSFW
- }
-
- this.error = null
- this.userService.updateMyDetails(details).subscribe(
- () => {
- this.notificationsService.success('Success', 'Information updated.')
-
- this.authService.refreshUserInformation()
- },
-
- err => this.error = err.message
- )
- }
-}
+++ /dev/null
-export * from './account-details.component'
import { LoginGuard } from '../core'
import { AccountComponent } from './account.component'
+import { AccountSettingsComponent } from './account-settings/account-settings.component'
const accountRoutes: Routes = [
{
path: 'account',
component: AccountComponent,
- canActivate: [ MetaGuard, LoginGuard ],
- data: {
- meta: {
- title: 'My account'
- }
- }
+ canActivateChild: [ MetaGuard, LoginGuard ],
+ children: [
+ {
+ path: 'settings',
+ component: AccountSettingsComponent,
+ data: {
+ meta: {
+ title: 'Account settings'
+ }
+ }
+ },
+ // {
+ // path: 'videos',
+ // component: AccountVideosComponent,
+ // data: {
+ // meta: {
+ // title: 'Account videos'
+ // }
+ // }
+ // }
+ ]
}
]
--- /dev/null
+<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
+
+<form role="form" (ngSubmit)="changePassword()" [formGroup]="form">
+ <input
+ type="password" class="form-control" id="new-password" placeholder="Old password"
+ formControlName="new-password"
+ >
+ <div *ngIf="formErrors['new-password']" class="alert alert-danger">
+ {{ formErrors['new-password'] }}
+ </div>
+
+ <input
+ type="password" id="new-confirmed-password" placeholder="New password"
+ formControlName="new-confirmed-password"
+ >
+
+ <input type="submit" value="Change password" [disabled]="!form.valid">
+</form>
--- /dev/null
+input[type=password] {
+ @include peertube-input-text(340px);
+ display: block;
+ margin-bottom: 10px;
+}
+
+input[type=submit] {
+ @include peertube-button;
+}
--- /dev/null
+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: './account-change-password.component.html',
+ styleUrls: [ './account-change-password.component.scss' ]
+})
+export class AccountChangePasswordComponent 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
+ )
+ }
+}
--- /dev/null
+export * from './account-change-password.component'
--- /dev/null
+<div *ngIf="error" class="alert alert-danger">{{ error }}</div>
+
+<form role="form" (ngSubmit)="updateDetails()" [formGroup]="form">
+ <input
+ type="checkbox" id="displayNSFW"
+ formControlName="displayNSFW"
+ >
+ <label for="displayNSFW">Display videos that contain mature or explicit content</label>
+ <div *ngIf="formErrors['displayNSFW']" class="alert alert-danger">
+ {{ formErrors['displayNSFW'] }}
+ </div>
+
+ <input type="submit" value="Update" [disabled]="!form.valid">
+</form>
--- /dev/null
+label {
+ font-size: 15px;
+ font-weight: $font-regular;
+ margin-left: 5px;
+}
+
+input[type=submit] {
+ @include peertube-button;
+
+ display: block;
+}
--- /dev/null
+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-details',
+ templateUrl: './account-details.component.html',
+ styleUrls: [ './account-details.component.scss' ]
+})
+
+export class AccountDetailsComponent extends FormReactive implements OnInit {
+ @Input() user: User = null
+
+ error: string = 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({
+ displayNSFW: [ this.user.displayNSFW ]
+ })
+
+ this.form.valueChanges.subscribe(data => this.onValueChanged(data))
+ }
+
+ ngOnInit () {
+ this.buildForm()
+ }
+
+ updateDetails () {
+ const displayNSFW = this.form.value['displayNSFW']
+ const details: UserUpdateMe = {
+ displayNSFW
+ }
+
+ this.error = null
+ this.userService.updateMyDetails(details).subscribe(
+ () => {
+ this.notificationsService.success('Success', 'Information updated.')
+
+ this.authService.refreshUserInformation()
+ },
+
+ err => this.error = err.message
+ )
+ }
+}
--- /dev/null
+export * from './account-details.component'
--- /dev/null
+<div class="user-info">
+ {{ user.username }}
+</div>
+
+<div class="account-title">Account settings</div>
+<my-account-change-password></my-account-change-password>
+
+<div class="account-title">Filtering</div>
+<my-account-details [user]="user"></my-account-details>
--- /dev/null
+.user-info {
+ font-size: 20px;
+ font-weight: $font-bold;
+}
+
+.account-title {
+ text-transform: uppercase;
+ color: $orange-color;
+ font-weight: $font-bold;
+ font-size: 13px;
+ margin-top: 55px;
+ margin-bottom: 30px;
+}
--- /dev/null
+import { Component, OnInit } from '@angular/core'
+import { User } from '../../shared'
+import { AuthService } from '../../core'
+
+@Component({
+ selector: 'my-account-settings',
+ templateUrl: './account-settings.component.html',
+ styleUrls: [ './account-settings.component.scss' ]
+})
+export class AccountSettingsComponent implements OnInit {
+ user: User = null
+
+ constructor (private authService: AuthService) {}
+
+ ngOnInit () {
+ this.user = this.authService.getUser()
+ }
+}
<div class="row">
- <div class="content-padding">
- <h3>Account</h3>
+ <div class="sub-menu">
+ <a routerLink="/account/settings" routerLinkActive="active" class="title-page">My account</a>
- <div class="col-md-6 col-sm-12">
- <div class="panel panel-default">
- <div class="panel-heading">Change password</div>
-
- <div class="panel-body">
- <my-account-change-password></my-account-change-password>
- </div>
- </div>
- </div>
-
- <div class="col-md-6 col-sm-12">
- <div class="panel panel-default">
- <div class="panel-heading">Update my informations</div>
+ <a routerLink="/account/videos" routerLinkActive="active" class="title-page">My videos</a>
+ </div>
- <div class="panel-body">
- <my-account-details [user]="user"></my-account-details>
- </div>
- </div>
- </div>
+ <div class="margin-content">
+ <router-outlet></router-outlet>
</div>
</div>
-.panel {
- margin-top: 40px;
-}
-import { Component, OnInit } from '@angular/core'
-import { FormBuilder, FormGroup } from '@angular/forms'
-import { Router } from '@angular/router'
-
-import { NotificationsService } from 'angular2-notifications'
-
-import { AuthService } from '../core'
-import {
- FormReactive,
- User,
- UserService,
- USER_PASSWORD
-} from '../shared'
+import { Component } from '@angular/core'
@Component({
selector: 'my-account',
templateUrl: './account.component.html',
styleUrls: [ './account.component.scss' ]
})
-export class AccountComponent implements OnInit {
- user: User = null
-
- constructor (private authService: AuthService) {}
-
- ngOnInit () {
- this.user = this.authService.getUser()
- }
-}
+export class AccountComponent {}
import { NgModule } from '@angular/core'
-
+import { SharedModule } from '../shared'
import { AccountRoutingModule } from './account-routing.module'
+import { AccountChangePasswordComponent } from './account-settings/account-change-password/account-change-password.component'
+import { AccountDetailsComponent } from './account-settings/account-details/account-details.component'
+import { AccountSettingsComponent } from './account-settings/account-settings.component'
import { AccountComponent } from './account.component'
-import { AccountChangePasswordComponent } from './account-change-password'
-import { AccountDetailsComponent } from './account-details'
import { AccountService } from './account.service'
-import { SharedModule } from '../shared'
@NgModule({
imports: [
declarations: [
AccountComponent,
+ AccountSettingsComponent,
AccountChangePasswordComponent,
AccountDetailsComponent
],
min-height: calc(100vh - #{$header-height} - #{$footer-height} - #{$footer-margin});
}
-.main-col {
- margin-left: $menu-width;
-
- &.expanded {
- margin-left: 0;
- }
-}
-
.sub-header-container {
margin-top: $header-height;
}
<menu>
<div *ngIf="isLoggedIn" class="logged-in-block">
<div class="logged-in-info">
- <div class="logged-in-username">{{ user.username }}</div>
+ <a routerLink="/account/settings" class="logged-in-username">{{ user.username }}</a>
<div class="logged-in-email">{{ user.email }}</div>
</div>
.logged-in-username {
font-size: 16px;
font-weight: $font-semibold;
+ color: $menu-color;
+ cursor: pointer;
+
+ @include disable-default-a-behaviour;
}
.logged-in-email {
width: 190px;
border-radius: 3px;
text-align: center;
+ color: $menu-color;
+ display: block;
+ cursor: pointer;
+ margin-bottom: 15px;
+
+ @include disable-default-a-behaviour;
&.login-button {
background-color: $orange-color;
a {
display: flex;
+ color: $menu-color;
+ cursor: pointer;
+ height: 22px;
+ line-height: 22px;
+ font-size: 16px;
+ margin-bottom: 15px;
+ @include disable-default-a-behaviour;
.icon {
width: 22px;
}
}
}
-
- a {
- color: $menu-color;
- height: 22px;
- line-height: 22px;
- display: block;
- font-size: 16px;
- cursor: pointer;
- margin-bottom: 15px;
-
- @include disable-default-a-behaviour;
- }
}
#search-video {
- display: inline-block;
- height: $button-height;
- width: $search-input-width;
+ @include peertube-input-text($search-input-width);
margin-right: 15px;
padding-right: 25px; // For the search icon
- background: #fff;
- border: 1px solid #C6C6C6;
- border-radius: 3px;
- padding-left: 15px;
&::placeholder {
color: #000;
}
.upload-button {
- display: inline-block;
- color: #fff;
- font-weight: $font-semibold;
- font-size: 15px;
- height: $button-height;
- line-height: $button-height;
- border-radius: 3px;
- text-align: center;
- margin-right: 25px;
- background-color: $orange-color;
- padding: 0 17px 0 13px;
+ @include peertube-button-link;
- @include disable-default-a-behaviour;
+ margin-right: 25px;
.icon.icon-upload {
display: inline-block;
-export * from './my-videos.component'
export * from './video-recently-added.component'
export * from './video-trending.component'
export * from './shared'
+++ /dev/null
-import { Component, OnDestroy, OnInit } from '@angular/core'
-import { ActivatedRoute, Router } from '@angular/router'
-
-import { NotificationsService } from 'angular2-notifications'
-
-import { AbstractVideoList } from './shared'
-import { VideoService } from '../shared'
-
-@Component({
- selector: 'my-videos',
- styleUrls: [ './shared/abstract-video-list.scss' ],
- templateUrl: './shared/abstract-video-list.html'
-})
-export class MyVideosComponent extends AbstractVideoList implements OnInit, OnDestroy {
-
- constructor (
- protected router: Router,
- protected route: ActivatedRoute,
- protected notificationsService: NotificationsService,
- private videoService: VideoService
- ) {
- super()
- }
-
- ngOnInit () {
- super.ngOnInit()
- }
-
- ngOnDestroy () {
- super.ngOnDestroy()
- }
-
- getVideosObservable () {
- return this.videoService.getMyVideos(this.pagination, this.sort)
- }
-}
-<div class="title-page">
- {{ titlePage }}
-</div>
+<div class="margin-content">
+ <div class="title-page title-page-single">
+ {{ titlePage }}
+ </div>
-<div
- class="videos-miniatures"
- infiniteScroll
- [infiniteScrollUpDistance]="1.5"
- [infiniteScrollDistance]="0.5"
- (scrolled)="onNearOfBottom()"
- (scrolledUp)="onNearOfTop()"
->
- <my-video-miniature
- class="ng-animate"
- *ngFor="let video of videos" [video]="video" [user]="user" [currentSort]="sort"
+ <div
+ infiniteScroll
+ [infiniteScrollUpDistance]="1.5"
+ [infiniteScrollDistance]="0.5"
+ (scrolled)="onNearOfBottom()"
+ (scrolledUp)="onNearOfTop()"
>
- </my-video-miniature>
+ <my-video-miniature
+ class="ng-animate"
+ *ngFor="let video of videos" [video]="video" [user]="user" [currentSort]="sort"
+ >
+ </my-video-miniature>
+ </div>
</div>
-.videos-info {
- @media screen and (max-width: 400px) {
- margin-left: 0;
- }
-
- border-bottom: 1px solid #f1f1f1;
- height: 40px;
- line-height: 40px;
-
- .videos-total-results {
- font-size: 13px;
- }
-
- my-loader {
- display: inline-block;
- margin-left: 5px;
- }
-}
-
-pagination {
- display: block;
- text-align: center;
-}
}
ngOnDestroy () {
- this.subActivatedRoute.unsubscribe()
+ if (this.subActivatedRoute) {
+ this.subActivatedRoute.unsubscribe()
+ }
}
onNearOfTop () {
import { NgModule } from '@angular/core'
import { RouterModule, Routes } from '@angular/router'
import { MetaGuard } from '@ngx-meta/core'
-import { MyVideosComponent } from './video-list'
import { VideoRecentlyAddedComponent } from './video-list/video-recently-added.component'
import { VideoTrendingComponent } from './video-list/video-trending.component'
import { VideosComponent } from './videos.component'
pathMatch: 'full',
redirectTo: 'recently-added'
},
- {
- path: 'mine',
- component: MyVideosComponent,
- data: {
- meta: {
- title: 'My videos'
- }
- }
- },
{
path: 'trending',
component: VideoTrendingComponent,
import { InfiniteScrollModule } from 'ngx-infinite-scroll'
import { SharedModule } from '../shared'
import { VideoService } from './shared'
-import { MyVideosComponent, VideoMiniatureComponent } from './video-list'
+import { VideoMiniatureComponent } from './video-list'
import { VideoRecentlyAddedComponent } from './video-list/video-recently-added.component'
import { VideoTrendingComponent } from './video-list/video-trending.component'
import { VideosRoutingModule } from './videos-routing.module'
VideoTrendingComponent,
VideoRecentlyAddedComponent,
- MyVideosComponent,
VideoMiniatureComponent
],
outline: none !important;
}
}
+
+@mixin peertube-input-text($width) {
+ display: inline-block;
+ height: $button-height;
+ width: $width;
+ background: #fff;
+ border: 1px solid #C6C6C6;
+ border-radius: 3px;
+ padding-left: 15px;
+
+ &::placeholder {
+ color: #585858;
+ }
+}
+
+@mixin peertube-button {
+ border: none;
+ color: #fff;
+ font-weight: $font-semibold;
+ font-size: 15px;
+ height: $button-height;
+ line-height: $button-height;
+ border-radius: 3px;
+ text-align: center;
+ background-color: $orange-color;
+ padding: 0 17px 0 13px;
+ cursor: pointer;
+}
+
+@mixin peertube-button-link {
+ display: inline-block;
+
+ @include peertube-button;
+ @include disable-default-a-behaviour;
+}
$black-background: #000;
$grey-background: #f6f2f2;
+$expanded-horizontal-margins: 150px;
+
$button-height: 30px;
$header-height: 50px;
}
.main-col {
- padding: 30px;
+ margin-left: $menu-width;
.title-page {
+ color: #000;
font-size: 16px;
- font-weight: $font-bold;
display: inline-block;
- border-bottom: 2px solid $orange-color;
- margin-bottom: 25px;
+ margin-right: 55px;
+ font-weight: $font-semibold;
+ @include disable-default-a-behaviour;
+
+ &.active, &.title-page-single {
+ border-bottom: 2px solid $orange-color;
+ font-weight: $font-bold;
+ margin-top: 30px;
+ margin-bottom: 25px;
+ }
+ }
+
+ .margin-content {
+ margin-left: 10px;
+ margin-right: 10px;
+ }
+
+ .sub-menu {
+ background-color: #F7F7F7;
+ width: 100%;
+ height: 81px;
+ margin-bottom: 30px;
+ display: flex;
+ align-items: center;
+ }
+
+ // Override some properties if the main content is expanded (no menu on the left)
+ &.expanded {
+ margin-left: 0;
+
+ .margin-content {
+ margin-left: $expanded-horizontal-margins;
+ margin-right: $expanded-horizontal-margins;
+ }
+
+ .sub-menu {
+ padding-left: $expanded-horizontal-margins;
+ }
}
}
@import '_variables.scss';
+@import '_mixins.scss';
$bootstrap-sass-asset-helper: false !default;
//