First step upload with new design
authorChocobozzz <florian.bigard@gmail.com>
Thu, 7 Dec 2017 15:32:06 +0000 (16:32 +0100)
committerChocobozzz <florian.bigard@gmail.com>
Thu, 7 Dec 2017 15:32:06 +0000 (16:32 +0100)
client/src/app/videos/+video-edit/shared/video-edit.component.html
client/src/app/videos/+video-edit/shared/video-edit.component.scss
client/src/app/videos/+video-edit/video-add.component.html
client/src/app/videos/+video-edit/video-add.component.scss [new file with mode: 0644]
client/src/app/videos/+video-edit/video-add.component.ts
client/src/assets/images/video/upload.svg [new file with mode: 0644]

index a6b753166fe128ecaa13f346d8272dc6fa9fb5aa..8c071ce125f68bd0846addf326f540f12b09287e 100644 (file)
@@ -67,6 +67,7 @@
     <div class="form-group">
       <label for="privacy">Privacy</label>
       <select id="privacy" formControlName="privacy">
+
         <option></option>
         <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
       </select>
index 0af48fabeeefaa8cc01c366864e2af5e500a3ab0..2d0bfc36e60b058baa370e629ef66888385aecf9 100644 (file)
   }
 }
 
-
-.btn-file {
-  position: relative;
-  overflow: hidden;
-  display: block;
-}
-
-.btn-file input[type=file] {
-  position: absolute;
-  top: 0;
-  right: 0;
-  min-width: 100%;
-  min-height: 100%;
-  font-size: 100px;
-  text-align: right;
-  filter: alpha(opacity=0);
-  opacity: 0;
-  outline: none;
-  background: white;
-  cursor: inherit;
-  display: block;
-}
-
-div.file-to-upload {
-  height: 40px;
-
-  .glyphicon-remove {
-    cursor: pointer;
-  }
-}
-
 .little-information {
   font-size: 0.8em;
   font-style: italic;
 }
-
-.label-tags {
-  margin-bottom: 0;
-}
index b4e0f9f7c3ae6c7ec8e43d54f31ba41e5bfe9fd1..f8355f3dba6aa04c15e30640e3f0588016c15ae8 100644 (file)
-<div class="row">
-  <div class="content-padding">
+<div class="margin-content">
+  <div class="title-page title-page-single">
+    Upload your video
+  </div>
 
-    <h3>Upload a video</h3>
+  <div *ngIf="error" class="alert alert-danger">{{ error }}</div>
 
-    <div *ngIf="error !== undefined" class="alert alert-danger">{{ error }}</div>
+  <div class="upload-video-container">
+    <div class="upload-video">
+      <div class="icon icon-upload"></div>
 
-    <form novalidate [formGroup]="form">
-      <div class="form-group">
-        <label for="name">Name</label>
-        <input
-          type="text" class="form-control" id="name"
-          formControlName="name"
-        >
-        <div *ngIf="formErrors.name" class="alert alert-danger">
-          {{ formErrors.name }}
-        </div>
+      <div class="button-file">
+        <span>Select the file to upload</span>
+        <input #videofileInput type="file" name="videofile" id="videofile" (change)="fileChange($event)" />
       </div>
 
       <div class="form-group">
-        <label for="privacy">Privacy</label>
-        <select class="form-control" id="privacy" formControlName="privacy">
-          <option></option>
+        <select [(ngModel)]="firstStepPrivacy">
           <option *ngFor="let privacy of videoPrivacies" [value]="privacy.id">{{ privacy.label }}</option>
         </select>
-
-        <div *ngIf="formErrors.privacy" class="alert alert-danger">
-          {{ formErrors.privacy }}
-        </div>
-      </div>
-
-      <div class="form-group">
-        <input
-          type="checkbox" id="nsfw"
-          formControlName="nsfw"
-        >
-        <label for="nsfw">This video contains mature or explicit content</label>
       </div>
 
       <div class="form-group">
-        <label for="category">Channel</label>
-        <select class="form-control" id="channelId" formControlName="channelId">
+        <select [(ngModel)]="firstStepChannel">
           <option *ngFor="let channel of userVideoChannels" [value]="channel.id">{{ channel.label }}</option>
         </select>
-
-        <div *ngIf="formErrors.channelId" class="alert alert-danger">
-          {{ formErrors.channelId }}
-        </div>
       </div>
+    </div>
 
-      <div class="form-group">
-        <label for="category">Category</label>
-        <select class="form-control" id="category" formControlName="category">
-          <option></option>
-          <option *ngFor="let category of videoCategories" [value]="category.id">{{ category.label }}</option>
-        </select>
 
-        <div *ngIf="formErrors.category" class="alert alert-danger">
-          {{ formErrors.category }}
-        </div>
-      </div>
-
-      <div class="form-group">
-        <label for="licence">Licence</label>
-        <select class="form-control" id="licence" formControlName="licence">
-          <option></option>
-          <option *ngFor="let licence of videoLicences" [value]="licence.id">{{ licence.label }}</option>
-        </select>
-
-        <div *ngIf="formErrors.licence" class="alert alert-danger">
-          {{ formErrors.licence }}
-        </div>
-      </div>
-
-      <div class="form-group">
-        <label for="language">Language</label>
-        <select class="form-control" id="language" formControlName="language">
-          <option></option>
-          <option *ngFor="let language of videoLanguages" [value]="language.id">{{ language.label }}</option>
-        </select>
+    <form *ngIf="isUploadingVideo" novalidate [formGroup]="form">
+      <my-video-edit
+          [form]="form" [formErrors]="formErrors"
+          [validationMessages]="validationMessages" [videoPrivacies]="videoPrivacies"
+      ></my-video-edit>
 
-        <div *ngIf="formErrors.language" class="alert alert-danger">
-          {{ formErrors.language }}
+      <div class="submit-container">
+        <div class="submit-button" [ngClass]="{ disabled: !form.valid }">
+          <span class="icon icon-validate"></span>
+          <input type="button" value="Publish" (click)="upload()" />
         </div>
       </div>
-
-      <div class="form-group">
-        <label class="label-tags">Tags</label> <span class="little-information">(press enter to add the tag)</span>
-        <tag-input
-          [ngModel]="tags" [validators]="tagValidators" [errorMessages]="tagValidatorsMessages"
-          formControlName="tags" maxItems="5" modelAsStrings="true"
-        ></tag-input>
-      </div>
-
-      <div class="form-group">
-        <label for="videofile">File</label>
-        <div class="btn btn-default btn-file">
-          <span>Select the video...</span>
-          <input #videofileInput type="file" name="videofile" id="videofile" (change)="fileChange($event)" />
-          <input type="hidden" name="videofileHidden" formControlName="videofile"/>
-        </div>
-      </div>
-
-      <div class="file-to-upload">
-        <div class="file" *ngIf="filename">
-          <span class="filename">{{ filename }}</span>
-          <span class="glyphicon glyphicon-remove" (click)="removeFile()"></span>
-        </div>
-      </div>
-
-      <div *ngIf="formErrors.videofile" class="alert alert-danger">
-        {{ formErrors.videofile }}
-      </div>
-
-      <div class="form-group">
-        <label for="description">Description</label>
-        <my-video-description formControlName="description"></my-video-description>
-
-        <div *ngIf="formErrors.description" class="alert alert-danger">
-          {{ formErrors.description }}
-        </div>
-      </div>
-
-      <div class="progress">
-        <progressbar [value]="progressPercent" max="100">
-          <ng-template [ngIf]="progressPercent === 100">
-            <span class="glyphicon glyphicon-refresh glyphicon-refresh-animate"></span>
-            Server is processing the video
-          </ng-template>
-        </progressbar>
-      </div>
-
-      <div class="form-group">
-        <input
-          type="button" value="Upload" class="btn btn-default form-control"
-          (click)="upload()"
-        >
-      </div>
     </form>
   </div>
 </div>
diff --git a/client/src/app/videos/+video-edit/video-add.component.scss b/client/src/app/videos/+video-edit/video-add.component.scss
new file mode 100644 (file)
index 0000000..25dfd40
--- /dev/null
@@ -0,0 +1,60 @@
+.upload-video-container {
+  border-radius: 3px;
+  background-color: #F7F7F7;
+  border: 3px solid #EAEAEA;
+  width: 100%;
+  height: 440px;
+  text-align: center;
+  margin-top: 40px;
+  display: flex;
+  justify-content: center;
+  align-items: center;
+
+  .upload-video {
+    display: flex;
+    flex-direction: column;
+    align-items: center;
+
+    .icon.icon-upload {
+      @include icon(90px);
+      margin-bottom: 25px;
+
+      background-image: url('../../../assets/images/video/upload.svg');
+    }
+
+    .button-file {
+      position: relative;
+      overflow: hidden;
+      display: inline-block;
+      margin-bottom: 70px;
+
+      @include peertube-button;
+      @include orange-button;
+
+      input[type=file] {
+        position: absolute;
+        top: 0;
+        right: 0;
+        min-width: 100%;
+        min-height: 100%;
+        font-size: 100px;
+        text-align: right;
+        filter: alpha(opacity=0);
+        opacity: 0;
+        outline: none;
+        background: white;
+        cursor: inherit;
+        display: block;
+      }
+    }
+
+    select {
+      @include peertube-select(auto);
+
+      display: inline-block;
+      font-size: 15px
+    }
+  }
+}
+
+
index 989addbd703b2f3e2f6f52fcb19c0a43ad4a76df..071f9a28bf6991219a5ce52901bb12ee2fe4bb75 100644 (file)
@@ -6,61 +6,33 @@ import { NotificationsService } from 'angular2-notifications'
 import { VideoService } from 'app/shared/video/video.service'
 import { VideoCreate } from '../../../../../shared'
 import { AuthService, ServerService } from '../../core'
-import {
-  FormReactive,
-  VIDEO_CATEGORY,
-  VIDEO_CHANNEL,
-  VIDEO_DESCRIPTION,
-  VIDEO_FILE,
-  VIDEO_LANGUAGE,
-  VIDEO_LICENCE,
-  VIDEO_NAME,
-  VIDEO_PRIVACY,
-  VIDEO_TAGS
-} from '../../shared'
+import { FormReactive } from '../../shared'
+import { ValidatorMessage } from '../../shared/forms/form-validators'
+import { VideoEdit } from '../../shared/video/video-edit.model'
 
 @Component({
   selector: 'my-videos-add',
-  styleUrls: [ './shared/video-edit.component.scss' ],
-  templateUrl: './video-add.component.html'
+  templateUrl: './video-add.component.html',
+  styleUrls: [
+    './shared/video-edit.component.scss',
+    './video-add.component.scss'
+  ]
 })
 
 export class VideoAddComponent extends FormReactive implements OnInit {
   @ViewChild('videofileInput') videofileInput
 
+  isUploadingVideo = false
   progressPercent = 0
-  tags: string[] = []
-  videoCategories = []
-  videoLicences = []
-  videoLanguages = []
-  videoPrivacies = []
-  userVideoChannels = []
-
-  tagValidators = VIDEO_TAGS.VALIDATORS
-  tagValidatorsMessages = VIDEO_TAGS.MESSAGES
 
-  error: string
+  error: string = null
   form: FormGroup
-  formErrors = {
-    name: '',
-    privacy: '',
-    category: '',
-    licence: '',
-    language: '',
-    channelId: '',
-    description: '',
-    videofile: ''
-  }
-  validationMessages = {
-    name: VIDEO_NAME.MESSAGES,
-    privacy: VIDEO_PRIVACY.MESSAGES,
-    category: VIDEO_CATEGORY.MESSAGES,
-    licence: VIDEO_LICENCE.MESSAGES,
-    language: VIDEO_LANGUAGE.MESSAGES,
-    channelId: VIDEO_CHANNEL.MESSAGES,
-    description: VIDEO_DESCRIPTION.MESSAGES,
-    videofile: VIDEO_FILE.MESSAGES
-  }
+  formErrors: { [ id: string ]: string } = {}
+  validationMessages: ValidatorMessage = {}
+  userVideoChannels = []
+  videoPrivacies = []
+  firstStepPrivacy = 0
+  firstStepChannel = 0
 
   constructor (
     private formBuilder: FormBuilder,
@@ -73,35 +45,17 @@ export class VideoAddComponent extends FormReactive implements OnInit {
     super()
   }
 
-  get filename () {
-    return this.form.value['videofile']
-  }
-
   buildForm () {
-    this.form = this.formBuilder.group({
-      name: [ '', VIDEO_NAME.VALIDATORS ],
-      nsfw: [ false ],
-      privacy: [ '', VIDEO_PRIVACY.VALIDATORS ],
-      category: [ '', VIDEO_CATEGORY.VALIDATORS ],
-      licence: [ '', VIDEO_LICENCE.VALIDATORS ],
-      language: [ '', VIDEO_LANGUAGE.VALIDATORS ],
-      channelId: [ '', VIDEO_CHANNEL.VALIDATORS ],
-      description: [ '', VIDEO_DESCRIPTION.VALIDATORS ],
-      videofile: [ '', VIDEO_FILE.VALIDATORS ],
-      tags: [ '' ]
-    })
-
+    this.form = this.formBuilder.group({})
     this.form.valueChanges.subscribe(data => this.onValueChanged(data))
   }
 
   ngOnInit () {
-    this.videoCategories = this.serverService.getVideoCategories()
-    this.videoLicences = this.serverService.getVideoLicences()
-    this.videoLanguages = this.serverService.getVideoLanguages()
-    this.videoPrivacies = this.serverService.getVideoPrivacies()
-
     this.buildForm()
 
+    this.videoPrivacies = this.serverService.getVideoPrivacies()
+    this.firstStepPrivacy = this.videoPrivacies[0].id
+
     this.authService.userInformationLoaded
       .subscribe(
         () => {
@@ -112,21 +66,13 @@ export class VideoAddComponent extends FormReactive implements OnInit {
           if (Array.isArray(videoChannels) === false) return
 
           this.userVideoChannels = videoChannels.map(v => ({ id: v.id, label: v.name }))
-
-          this.form.patchValue({ channelId: this.userVideoChannels[0].id })
+          this.firstStepChannel = this.userVideoChannels[0].id
         }
       )
   }
 
-  // The goal is to keep reactive form validation (required field)
-  // https://stackoverflow.com/a/44238894
   fileChange ($event) {
-    this.form.controls['videofile'].setValue($event.target.files[0].name)
-  }
-
-  removeFile () {
-    this.videofileInput.nativeElement.value = ''
-    this.form.controls['videofile'].setValue('')
+    console.log('uploading file ?')
   }
 
   checkForm () {
@@ -135,11 +81,7 @@ export class VideoAddComponent extends FormReactive implements OnInit {
     return this.form.valid
   }
 
-  upload () {
-    if (this.checkForm() === false) {
-      return
-    }
-
+  uploadFirstStep () {
     const formValue: VideoCreate = this.form.value
 
     const name = formValue.name
@@ -193,4 +135,26 @@ export class VideoAddComponent extends FormReactive implements OnInit {
       }
     )
   }
+
+  updateSecondStep () {
+    if (this.checkForm() === false) {
+      return
+    }
+
+    const video = new VideoEdit(this.form.value)
+
+    this.videoService.updateVideo(video)
+      .subscribe(
+        () => {
+          this.notificationsService.success('Success', 'Video published.')
+          this.router.navigate([ '/videos/watch', video.uuid ])
+        },
+
+        err => {
+          this.error = 'Cannot update the video.'
+          console.error(err)
+        }
+      )
+
+  }
 }
diff --git a/client/src/assets/images/video/upload.svg b/client/src/assets/images/video/upload.svg
new file mode 100644 (file)
index 0000000..c5b7cb4
--- /dev/null
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<svg width="24px" height="24px" viewBox="0 0 24 24" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
+    <!-- Generator: Sketch 43.2 (39069) - http://www.bohemiancoding.com/sketch -->
+    <title>cloud-upload</title>
+    <desc>Created with Sketch.</desc>
+    <defs></defs>
+    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round">
+        <g id="Artboard-4" transform="translate(-312.000000, -775.000000)" stroke="#C6C6C6" stroke-width="2">
+            <g id="307" transform="translate(312.000000, 775.000000)">
+                <path d="M8,18 L5,18 L5,18 C2.790861,18 1,16.209139 1,14 C1,11.790861 2.790861,10 5,10 C5.35840468,10 5.70579988,10.0471371 6.03632437,10.1355501 C6.01233106,9.92702603 6,9.71495305 6,9.5 C6,6.46243388 8.46243388,4 11.5,4 C14.0673313,4 16.2238156,5.7590449 16.8299648,8.1376465 C17.2052921,8.04765874 17.5970804,8 18,8 C20.7614237,8 23,10.2385763 23,13 C23,15.7614237 20.7614237,18 18,18 L16,18" id="Combined-Shape" stroke-linejoin="round"></path>
+                <path d="M12,13 L12,21" id="Path-58"></path>
+                <polyline id="Path-59" stroke-linejoin="round" transform="translate(12.000000, 12.500000) scale(1, -1) translate(-12.000000, -12.500000) " points="15 11 12 14 9 11"></polyline>
+            </g>
+        </g>
+    </g>
+</svg>