Design modals

pull/177/head
Chocobozzz 2017-12-20 17:49:58 +01:00
parent cb9244de97
commit 5f0805d39b
No known key found for this signature in database
GPG Key ID: 583A612D890159BE
20 changed files with 247 additions and 110 deletions

View 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>

View 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;
}

View 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>
<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="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>
<!-- 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" />-->
<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>
<div class="form-group inputs">
<span class="action-button action-button-cancel" (click)="hide()">
Cancel
</span>
<input
type="submit" value="Download" class="action-button-submit"
(click)="download()"
>
</div>
</div>
</div>

View File

@ -1,26 +1,17 @@
@import '_variables';
@import '_mixins';
.resolution-block:not(:first-child) {
.peertube-select-container {
@include peertube-select-container(130px);
}
.download-type {
margin-top: 30px;
}
.orange-button-link {
margin-right: 10px;
}
.peertube-radio-container {
@include peertube-radio-container;
label {
display: block;
}
.icon {
@include icon(21px);
margin-right: 5px;
position: relative;
top: -1px;
&.icon-download {
background-image: url('../../../assets/images/video/download-white.svg');
display: inline-block;
margin-right: 30px;
}
}

View 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)
}
}

View 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>

View File

@ -0,0 +1,6 @@
@import '_variables';
@import '_mixins';
textarea {
@include peertube-textarea(100%, 60px);
}

View 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

View 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">
@ -37,6 +35,12 @@
<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>

View File

@ -0,0 +1,3 @@
.action-button-cancel {
margin-right: 0 !important;
}

View File

@ -101,27 +101,27 @@
.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-blacklist {
background-image: url('../../../assets/images/video/eye-closed.svg');
&.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/blacklist.svg');
}
}
}
}

View File

@ -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>

After

Width:  |  Height:  |  Size: 743 B

View 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>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -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>

After

Width:  |  Height:  |  Size: 785 B

View File

@ -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>

After

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -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>

Before

Width:  |  Height:  |  Size: 1.3 KiB

View 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;
}
}
}

View 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";

View File

@ -22,6 +22,14 @@
}
}
@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;
@ -101,6 +109,7 @@
overflow: hidden;
background: #fff;
position: relative;
font-size: 15px;
&:after {
top: 50%;
@ -149,6 +158,44 @@
}
}
// 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;

View 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.')