Design modals
authorChocobozzz <me@florianbigard.com>
Wed, 20 Dec 2017 16:49:58 +0000 (17:49 +0100)
committerChocobozzz <me@florianbigard.com>
Wed, 20 Dec 2017 16:49:58 +0000 (17:49 +0100)
20 files changed:
client/src/app/core/confirm/confirm.component.html
client/src/app/videos/+video-edit/shared/video-description.component.scss
client/src/app/videos/+video-watch/video-download.component.html
client/src/app/videos/+video-watch/video-download.component.scss
client/src/app/videos/+video-watch/video-download.component.ts
client/src/app/videos/+video-watch/video-report.component.html
client/src/app/videos/+video-watch/video-report.component.scss [new file with mode: 0644]
client/src/app/videos/+video-watch/video-report.component.ts
client/src/app/videos/+video-watch/video-share.component.html
client/src/app/videos/+video-watch/video-share.component.scss
client/src/app/videos/+video-watch/video-watch.component.scss
client/src/assets/images/global/cross.svg [new file with mode: 0644]
client/src/assets/images/video/alert.svg
client/src/assets/images/video/blacklist.svg [new file with mode: 0644]
client/src/assets/images/video/download-black.svg [new file with mode: 0644]
client/src/assets/images/video/eye-closed.svg [deleted file]
client/src/sass/application.scss
client/src/sass/include/_bootstrap.scss
client/src/sass/include/_mixins.scss
server/lib/cache/videos-preview-cache.ts

index 31b735f9734b95f9f8921b9331e8e636f7b48498..cc2c28de27c15b0f6825b7c29eec6e4c184d0410 100644 (file)
@@ -3,17 +3,23 @@
     <div class="modal-content">
 
       <div class="modal-header">
-        <button type="button" class="close" aria-label="Close" (click)="cancel()">
-          <span aria-hidden="true">&times;</span>
-        </button>
-        <h4 class="title-page title-page-single">{{ title }}</h4>
+        <span class="close" aria-hidden="true" (click)="cancel()"></span>
+        <h4 class="modal-title">{{ title }}</h4>
       </div>
 
-      <div class="modal-body" [innerHtml]="message"></div>
+      <div class="modal-body" >
+        <div [innerHtml]="message"></div>
 
-      <div class="modal-footer">
-        <button type="button" class="grey-button" data-dismiss="modal" (click)="cancel()">Cancel</button>
-        <button type="button" class="orange-button" (click)="confirm()">Confirm</button>
+        <div class="form-group inputs">
+          <span class="action-button action-button-cancel" (click)="cancel()">
+            Cancel
+          </span>
+
+          <input
+            type="submit" value="Confirm" class="action-button-submit"
+            (click)="confirm()"
+          >
+        </div>
       </div>
     </div>
   </div>
index d6a5190c594e767045934c9c5b8d1752feee14a9..2c731bee3b7bf463f740333a3c768210b5744c49 100644 (file)
@@ -2,11 +2,8 @@
 @import '_mixins';
 
 textarea {
-  @include peertube-input-text(100%);
+  @include peertube-textarea(100%, 150px);
 
-  padding: 5px 15px;
-  font-size: 15px;
-  height: 150px;
   margin-bottom: 15px;
 }
 
index 7efc79e93fd4a8f495357c10931a78d48f49199d..f8f17a47131e0b1b97b32f4a17851d595b2e641f 100644 (file)
@@ -1,29 +1,40 @@
 <div bsModal #modal="bs-modal" class="modal" tabindex="-1">
   <div class="modal-dialog">
-    <div class="modal-content modal-lg">
+    <div class="modal-content">
 
       <div class="modal-header">
-        <button type="button" class="close" aria-label="Close" (click)="hide()">
-          <span aria-hidden="true">&times;</span>
-        </button>
-        <h4 class="title-page title-page-single">Download</h4>
+        <span class="close" aria-hidden="true" (click)="hide()"></span>
+        <h4 class="modal-title">Download video</h4>
       </div>
 
       <div class="modal-body">
-        <div *ngFor="let file of video.files" class="resolution-block">
-          <label>{{ file.resolutionLabel }}</label>
+        <div class="peertube-select-container">
+          <select [(ngModel)]="resolution">
+            <option *ngFor="let file of video.files" [value]="file.resolution">{{ file.resolutionLabel }}</option>
+          </select>
+        </div>
+
+        <div class="download-type">
+          <div class="peertube-radio-container">
+            <input type="radio" name="download" id="download-torrent" [(ngModel)]="downloadType" value="torrent">
+            <label for="download-torrent">Torrent</label>
+          </div>
+
+          <div class="peertube-radio-container">
+            <input type="radio" name="download" id="download-direct" [(ngModel)]="downloadType" value="direct">
+            <label for="download-direct">Direct download</label>
+          </div>
+        </div>
 
-          <a class="orange-button-link " target="_blank" [href]="file.torrentUrl">
-            <span class="icon icon-download"></span>
-            Torrent file
-          </a>
-          <a class="orange-button-link" target="_blank" [href]="file.fileUrl">
-            <span class="icon icon-download"></span>
-            Download
-          </a>
+        <div class="form-group inputs">
+          <span class="action-button action-button-cancel" (click)="hide()">
+            Cancel
+          </span>
 
-          <!-- Don't display magnet URI for now, this is not compatible with most torrent clients -->
-          <!--<input #magnetUriInput (click)="magnetUriInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="file.magnetUri" />-->
+          <input
+            type="submit" value="Download" class="action-button-submit"
+            (click)="download()"
+          >
         </div>
       </div>
     </div>
index 7eac3d1c9f0506807b3833e99217a1b041bdc94d..5fca82135b0a36e3b31eda2dd49160394ee998d9 100644 (file)
@@ -1,26 +1,17 @@
 @import '_variables';
 @import '_mixins';
 
-.resolution-block:not(:first-child) {
-  margin-top: 30px;
-}
-
-.orange-button-link {
-  margin-right: 10px;
+.peertube-select-container {
+  @include peertube-select-container(130px);
 }
 
-label {
-  display: block;
-}
-
-.icon {
-  @include icon(21px);
+.download-type {
+  margin-top: 30px;
 
-  margin-right: 5px;
-  position: relative;
-  top: -1px;
+  .peertube-radio-container {
+    @include peertube-radio-container;
 
-  &.icon-download {
-    background-image: url('../../../assets/images/video/download-white.svg');
+    display: inline-block;
+    margin-right: 30px;
   }
 }
index 095df16989f4eaa57da851f7c97e2a484fd16a24..44ece986cfce96ecb95ddcd7c0a2dc400edec681 100644 (file)
@@ -1,4 +1,4 @@
-import { Component, Input, ViewChild } from '@angular/core'
+import { Component, Input, OnInit, ViewChild } from '@angular/core'
 import { ModalDirective } from 'ngx-bootstrap/modal'
 import { VideoDetails } from '../../shared/video/video-details.model'
 
@@ -7,15 +7,22 @@ import { VideoDetails } from '../../shared/video/video-details.model'
   templateUrl: './video-download.component.html',
   styleUrls: [ './video-download.component.scss' ]
 })
-export class VideoDownloadComponent {
+export class VideoDownloadComponent implements OnInit {
   @Input() video: VideoDetails = null
 
   @ViewChild('modal') modal: ModalDirective
 
+  downloadType: 'direct' | 'torrent' = 'torrent'
+  resolution = -1
+
   constructor () {
     // empty
   }
 
+  ngOnInit () {
+    this.resolution = this.video.files[0].resolution
+  }
+
   show () {
     this.modal.show()
   }
@@ -23,4 +30,15 @@ export class VideoDownloadComponent {
   hide () {
     this.modal.hide()
   }
+
+  download () {
+    const file = this.video.files.find(f => f.resolution === this.resolution)
+    if (!file) {
+      console.error('Could not find file with resolution %d.', this.resolution)
+      return
+    }
+
+    const link = this.downloadType === 'direct' ? file.fileUrl : file.torrentUrl
+    window.open(link)
+  }
 }
index 20474bab42f646569c24b7267b5e7305e6951a0c..a9a7beb481ca9b436d444c1945c4a32f2e6a8fd5 100644 (file)
@@ -1,32 +1,30 @@
 <div bsModal #modal="bs-modal" class="modal" tabindex="-1">
   <div class="modal-dialog">
-    <div class="modal-content modal-lg">
+    <div class="modal-content">
 
       <div class="modal-header">
-        <button type="button" class="close" aria-label="Close" (click)="hide()">
-          <span aria-hidden="true">&times;</span>
-        </button>
-        <h4 class="title-page title-page-single">Report video</h4>
+        <span class="close" aria-hidden="true" (click)="hide()"></span>
+        <h4 class="modal-title">Report video</h4>
       </div>
 
       <div class="modal-body">
 
         <form novalidate [formGroup]="form" (ngSubmit)="report()">
           <div class="form-group">
-            <label for="reason">Reason</label>
-            <textarea
-              id="reason" class="form-control" placeholder="Reason..."
-              formControlName="reason" [ngClass]="{ 'input-error': formErrors['reason'] }"
-            >
+            <textarea placeholder="Reason..." formControlName="reason" [ngClass]="{ 'input-error': formErrors['reason'] }">
             </textarea>
             <div *ngIf="formErrors.reason" class="form-error">
               {{ formErrors.reason }}
             </div>
           </div>
 
-          <div class="form-group">
+          <div class="form-group inputs">
+            <span class="action-button action-button-cancel" (click)="hide()">
+              Cancel
+            </span>
+
             <input
-              type="submit" value="Report" class="orange-button"
+              type="submit" value="Submit" class="action-button-submit"
               [disabled]="!form.valid"
             >
           </div>
diff --git a/client/src/app/videos/+video-watch/video-report.component.scss b/client/src/app/videos/+video-watch/video-report.component.scss
new file mode 100644 (file)
index 0000000..09d273b
--- /dev/null
@@ -0,0 +1,6 @@
+@import '_variables';
+@import '_mixins';
+
+textarea {
+  @include peertube-textarea(100%, 60px);
+}
index b94e4144e83d4417979d064695f447588659dcc0..ece14754a365d0be2172983bbc4e799a642280fe 100644 (file)
@@ -7,7 +7,8 @@ import { VideoDetails } from '../../shared/video/video-details.model'
 
 @Component({
   selector: 'my-video-report',
-  templateUrl: './video-report.component.html'
+  templateUrl: './video-report.component.html',
+  styleUrls: [ './video-report.component.scss' ]
 })
 export class VideoReportComponent extends FormReactive implements OnInit {
   @Input() video: VideoDetails = null
index e99eccbfe110c4fc1ef76ca382e86de0f96516d2..85cf10a6cfdddf5e8df0cafde6279323b7ca5bb1 100644 (file)
@@ -1,12 +1,10 @@
 <div bsModal #modal="bs-modal" class="modal" tabindex="-1">
-  <div class="modal-dialog modal-lg">
+  <div class="modal-dialog">
     <div class="modal-content">
 
       <div class="modal-header">
-        <button type="button" class="close" aria-label="Close" (click)="hide()">
-          <span aria-hidden="true">&times;</span>
-        </button>
-        <h4 class="title-page title-page-single">Share</h4>
+        <span class="close" aria-hidden="true" (click)="hide()"></span>
+        <h4 class="modal-title">Share</h4>
       </div>
 
       <div class="modal-body">
         <div *ngIf="notSecure()" class="alert alert-warning">
           The url is not secured (no HTTPS), so the embed video won't work on HTTPS websites (web browsers block non secured HTTP requests on HTTPS websites).
         </div>
+
+        <div class="form-group inputs">
+          <span class="action-button action-button-cancel" (click)="hide()">
+            Cancel
+          </span>
+        </div>
       </div>
     </div>
   </div>
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..184e09027b5ad4c09c5ecd5154e048043c6b1d6c 100644 (file)
@@ -0,0 +1,3 @@
+.action-button-cancel {
+  margin-right: 0 !important;
+}
index e742e1329518058b287e59713ae22587c112022c..205a4333c5fc79fc51d5a272538e99aad7863fa2 100644 (file)
         .action-more {
           display: inline-block;
 
-          .dropdown-menu .icon {
-            display: inline-block;
-            background-repeat: no-repeat;
-            background-size: contain;
-            width: 21px;
-            height: 21px;
-            vertical-align: middle;
-            margin-right: 5px;
-            position: relative;
-            top: -1px;
+          .dropdown-menu .dropdown-item {
+            padding: 6px 24px;
 
-            &.icon-download {
-              background-image: url('../../../assets/images/video/download-grey.svg');
-            }
+            .icon {
+              @include icon(24px);
 
-            &.icon-alert {
-              background-image: url('../../../assets/images/video/alert.svg');
-            }
+              margin-right: 10px;
+              position: relative;
+              top: -1px;
+
+              &.icon-download {
+                background-image: url('../../../assets/images/video/download-black.svg');
+              }
+
+              &.icon-alert {
+                background-image: url('../../../assets/images/video/alert.svg');
+              }
 
-            &.icon-blacklist {
-              background-image: url('../../../assets/images/video/eye-closed.svg');
+              &.icon-blacklist {
+                background-image: url('../../../assets/images/video/blacklist.svg');
+              }
             }
           }
         }
diff --git a/client/src/assets/images/global/cross.svg b/client/src/assets/images/global/cross.svg
new file mode 100644 (file)
index 0000000..d47a759
--- /dev/null
@@ -0,0 +1,12 @@
+<?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">
+    <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, -115.000000)" stroke="#585858" stroke-width="2">
+            <g id="7" transform="translate(312.000000, 115.000000)">
+                <path d="M19,5 L5,19" id="Path-14"></path>
+                <path d="M19,5 L5,19" id="Path-14" transform="translate(12.000000, 12.000000) scale(-1, 1) translate(-12.000000, -12.000000) "></path>
+            </g>
+        </g>
+    </g>
+</svg>
index 6d3af029f56c06ba5e1d10e3d9d99169d9579dd0..5b43534add5a6e55e98270a38d453ae876dd3be7 100644 (file)
@@ -7,9 +7,9 @@
     <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
         <g id="Artboard-4" transform="translate(-48.000000, -467.000000)">
             <g id="161" transform="translate(48.000000, 467.000000)">
-                <path d="M12.8715755,3.50973876 L12,1.96027114 L11.1284245,3.50973876 L2.12842446,19.5097388 L1.29015252,21 L3,21 L21,21 L22.7098475,21 L21.8715755,19.5097388 L12.8715755,3.50973876 Z" id="Triangle-2" stroke="#585858" stroke-width="2" stroke-linejoin="round"></path>
-                <path d="M12,17.75 C12.6903559,17.75 13.25,17.1903559 13.25,16.5 C13.25,15.8096441 12.6903559,15.25 12,15.25 C11.3096441,15.25 10.75,15.8096441 10.75,16.5 C10.75,17.1903559 11.3096441,17.75 12,17.75 Z" id="Oval-8" fill="#585858"></path>
-                <rect id="Rectangle-3" fill="#585858" x="11" y="9" width="2" height="5" rx="1"></rect>
+                <path d="M12.8715755,3.50973876 L12,1.96027114 L11.1284245,3.50973876 L2.12842446,19.5097388 L1.29015252,21 L3,21 L21,21 L22.7098475,21 L21.8715755,19.5097388 L12.8715755,3.50973876 Z" id="Triangle-2" stroke="#000000" stroke-width="2" stroke-linejoin="round"></path>
+                <path d="M12,17.75 C12.6903559,17.75 13.25,17.1903559 13.25,16.5 C13.25,15.8096441 12.6903559,15.25 12,15.25 C11.3096441,15.25 10.75,15.8096441 10.75,16.5 C10.75,17.1903559 11.3096441,17.75 12,17.75 Z" id="Oval-8" fill="#000000"></path>
+                <rect id="Rectangle-3" fill="#000000" x="11" y="9" width="2" height="5" rx="1"></rect>
             </g>
         </g>
     </g>
diff --git a/client/src/assets/images/video/blacklist.svg b/client/src/assets/images/video/blacklist.svg
new file mode 100644 (file)
index 0000000..431c738
--- /dev/null
@@ -0,0 +1,15 @@
+<?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>no</title>
+    <desc>Created with Sketch.</desc>
+    <defs></defs>
+    <g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
+        <g id="Artboard-4" transform="translate(-312.000000, -863.000000)" stroke="#000000" stroke-width="2">
+            <g id="347" transform="translate(312.000000, 863.000000)">
+                <circle id="Oval-196" cx="12" cy="12" r="9"></circle>
+                <path d="M18,18 L6,6" id="Path-275"></path>
+            </g>
+        </g>
+    </g>
+</svg>
diff --git a/client/src/assets/images/video/download-black.svg b/client/src/assets/images/video/download-black.svg
new file mode 100644 (file)
index 0000000..5018367
--- /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>download</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(-180.000000, -291.000000)" stroke="#000000" stroke-width="2">
+            <g id="84" transform="translate(180.000000, 291.000000)">
+                <path d="M12,3 L12,15" id="Path-58"></path>
+                <polyline id="Path-59" stroke-linejoin="round" transform="translate(12.000000, 14.000000) rotate(-270.000000) translate(-12.000000, -14.000000) " points="9 8 15 14 9 20"></polyline>
+                <path d="M3,18 L3,20.0590859 C3,20.6127331 3.44494889,21.0615528 3.99340349,21.0615528 L20.0067018,21.0615528 C20.5553434,21.0615528 21.0001052,20.6098102 21.0001051,20.0590859 L21.0001049,18" id="Path-12" stroke-linejoin="round"></path>
+            </g>
+        </g>
+    </g>
+</svg>
diff --git a/client/src/assets/images/video/eye-closed.svg b/client/src/assets/images/video/eye-closed.svg
deleted file mode 100644 (file)
index c5b7396..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-<?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">
-    <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(-796.000000, -1046.000000)" stroke="#585858" stroke-width="2">
-            <g id="Extras" transform="translate(48.000000, 1046.000000)">
-                <g id="eye-closed" transform="translate(760.000000, 12.000000) scale(1, -1) translate(-760.000000, -12.000000) translate(748.000000, 0.000000)">
-                    <path d="M2,14 C2,14 5,7 12,7 C19,7 22,14 22,14" id="Path-80" stroke-linejoin="round"></path>
-                    <path d="M12,7 L12,5" id="Path-81"></path>
-                    <path d="M18,8.5 L19,7" id="Path-81"></path>
-                    <path d="M21,12 L22.5,11" id="Path-81"></path>
-                    <path d="M1.5,12 L3,11" id="Path-81" transform="translate(2.250000, 11.500000) scale(1, -1) translate(-2.250000, -11.500000) "></path>
-                    <path d="M5,8.5 L6,7" id="Path-81" transform="translate(5.500000, 7.750000) scale(-1, 1) translate(-5.500000, -7.750000) "></path>
-                </g>
-            </g>
-        </g>
-    </g>
-</svg>
index a1c222c31d1b3ae034c94908611f4a66ca38dddc..0d96d5ec0bc2960d1bf671df49f1f33e53b74bff 100644 (file)
@@ -258,9 +258,39 @@ p-datatable {
 .modal {
   .modal-header {
     border-bottom: none;
+    margin-bottom: 5px;
 
-    .title-page-single {
-      margin: 0;
+    .modal-title {
+      font-size: 20px;
+      font-weight: $font-semibold;
+    }
+
+    .close {
+      @include icon(24px);
+
+      position: relative;
+      right: -1px;
+      float: right;
+      background-image: url('../assets/images/global/cross.svg');
+    }
+  }
+
+  .inputs {
+    margin-top: 40px;
+    margin-bottom: 0;
+    text-align: right;
+
+    .action-button-cancel {
+      @include peertube-button;
+      @include grey-button;
+
+      display: inline-block;
+      margin-right: 10px;
+    }
+
+    .action-button-submit {
+      @include peertube-button;
+      @include orange-button;
     }
   }
 }
index 3857bb521ffa9857569e267aa5195878ec7dd93a..4f0e2893e99eacedc9b5b62a46552399227906d6 100644 (file)
@@ -37,7 +37,7 @@
 //@import "~bootstrap-sass/assets/stylesheets/bootstrap/panels";
 //@import "~bootstrap-sass/assets/stylesheets/bootstrap/responsive-embed";
 //@import "~bootstrap-sass/assets/stylesheets/bootstrap/wells";
-@import "~bootstrap-sass/assets/stylesheets/bootstrap/close";
+//@import "~bootstrap-sass/assets/stylesheets/bootstrap/close";
 
 // Components w/ JavaScript
 @import "~bootstrap-sass/assets/stylesheets/bootstrap/modals";
index a07bd5d28b995b860c2d179f8819de734678c5e6..252cf2173b30301b3a462af0b09ddbf511a50e4b 100644 (file)
   }
 }
 
+@mixin peertube-textarea ($width, $height) {
+  @include peertube-input-text($width);
+
+  height: $height;
+  padding: 5px 15px;
+  font-size: 15px;
+}
+
 @mixin orange-button {
   &, &:active, &:focus {
     color: #fff;
   overflow: hidden;
   background: #fff;
   position: relative;
+  font-size: 15px;
 
   &:after {
     top: 50%;
   }
 }
 
+// Thanks: https://codepen.io/triss90/pen/XNEdRe/
+@mixin peertube-radio-container {
+  input[type="radio"] {
+    display: none;
+
+    & + label {
+      font-weight: $font-regular;
+      cursor: pointer;
+
+      &:before {
+        position: relative;
+        top: -2px;
+        content: '';
+        background: #fff;
+        border-radius: 100%;
+        border: 1px solid #000;
+        display: inline-block;
+        width: 15px;
+        height: 15px;
+        vertical-align: middle;
+        cursor: pointer;
+        text-align: center;
+        margin-right: 10px;
+      }
+    }
+
+    &:checked + label:before {
+      background-color: #000;
+      box-shadow: inset 0 0 0 4px #fff;
+    }
+
+    &:focus + label:before {
+      outline: none;
+      border-color: #000;
+    }
+  }
+}
+
 @mixin peertube-checkbox ($border-width) {
   display: none;
 
index 28908b186498ae104bef05f4d4e28e4508d992f9..0eb43efcc03dc10c7aab65a929b1e64bfa2f1734 100644 (file)
@@ -47,7 +47,7 @@ class VideosPreviewCache {
   }
 
   private async loadPreviews (key: string) {
-    const video = await VideoModel.loadByUUID(key)
+    const video = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(key)
     if (!video) return undefined
 
     if (video.isOwned()) throw new Error('Cannot load preview of owned video.')