Design modals

This commit is contained in:
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-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="cancel()"> <span class="close" aria-hidden="true" (click)="cancel()"></span>
<span aria-hidden="true">&times;</span> <h4 class="modal-title">{{ title }}</h4>
</button>
<h4 class="title-page title-page-single">{{ title }}</h4>
</div> </div>
<div class="modal-body" [innerHtml]="message"></div> <div class="modal-body" >
<div [innerHtml]="message"></div>
<div class="modal-footer"> <div class="form-group inputs">
<button type="button" class="grey-button" data-dismiss="modal" (click)="cancel()">Cancel</button> <span class="action-button action-button-cancel" (click)="cancel()">
<button type="button" class="orange-button" (click)="confirm()">Confirm</button> Cancel
</span>
<input
type="submit" value="Confirm" class="action-button-submit"
(click)="confirm()"
>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -2,11 +2,8 @@
@import '_mixins'; @import '_mixins';
textarea { textarea {
@include peertube-input-text(100%); @include peertube-textarea(100%, 150px);
padding: 5px 15px;
font-size: 15px;
height: 150px;
margin-bottom: 15px; margin-bottom: 15px;
} }

View File

@ -1,29 +1,40 @@
<div bsModal #modal="bs-modal" class="modal" tabindex="-1"> <div bsModal #modal="bs-modal" class="modal" tabindex="-1">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content modal-lg"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="hide()"> <span class="close" aria-hidden="true" (click)="hide()"></span>
<span aria-hidden="true">&times;</span> <h4 class="modal-title">Download video</h4>
</button>
<h4 class="title-page title-page-single">Download</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<div *ngFor="let file of video.files" class="resolution-block"> <div class="peertube-select-container">
<label>{{ file.resolutionLabel }}</label> <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"> <div class="download-type">
<span class="icon icon-download"></span> <div class="peertube-radio-container">
Torrent file <input type="radio" name="download" id="download-torrent" [(ngModel)]="downloadType" value="torrent">
</a> <label for="download-torrent">Torrent</label>
<a class="orange-button-link" target="_blank" [href]="file.fileUrl"> </div>
<span class="icon icon-download"></span>
Download
</a>
<!-- Don't display magnet URI for now, this is not compatible with most torrent clients --> <div class="peertube-radio-container">
<!--<input #magnetUriInput (click)="magnetUriInput.select()" type="text" class="form-control input-sm readonly" readonly [value]="file.magnetUri" />--> <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> </div>
</div> </div>

View File

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

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 { ModalDirective } from 'ngx-bootstrap/modal'
import { VideoDetails } from '../../shared/video/video-details.model' 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', templateUrl: './video-download.component.html',
styleUrls: [ './video-download.component.scss' ] styleUrls: [ './video-download.component.scss' ]
}) })
export class VideoDownloadComponent { export class VideoDownloadComponent implements OnInit {
@Input() video: VideoDetails = null @Input() video: VideoDetails = null
@ViewChild('modal') modal: ModalDirective @ViewChild('modal') modal: ModalDirective
downloadType: 'direct' | 'torrent' = 'torrent'
resolution = -1
constructor () { constructor () {
// empty // empty
} }
ngOnInit () {
this.resolution = this.video.files[0].resolution
}
show () { show () {
this.modal.show() this.modal.show()
} }
@ -23,4 +30,15 @@ export class VideoDownloadComponent {
hide () { hide () {
this.modal.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 bsModal #modal="bs-modal" class="modal" tabindex="-1">
<div class="modal-dialog"> <div class="modal-dialog">
<div class="modal-content modal-lg"> <div class="modal-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="hide()"> <span class="close" aria-hidden="true" (click)="hide()"></span>
<span aria-hidden="true">&times;</span> <h4 class="modal-title">Report video</h4>
</button>
<h4 class="title-page title-page-single">Report video</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form novalidate [formGroup]="form" (ngSubmit)="report()"> <form novalidate [formGroup]="form" (ngSubmit)="report()">
<div class="form-group"> <div class="form-group">
<label for="reason">Reason</label> <textarea placeholder="Reason..." formControlName="reason" [ngClass]="{ 'input-error': formErrors['reason'] }">
<textarea
id="reason" class="form-control" placeholder="Reason..."
formControlName="reason" [ngClass]="{ 'input-error': formErrors['reason'] }"
>
</textarea> </textarea>
<div *ngIf="formErrors.reason" class="form-error"> <div *ngIf="formErrors.reason" class="form-error">
{{ formErrors.reason }} {{ formErrors.reason }}
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group inputs">
<span class="action-button action-button-cancel" (click)="hide()">
Cancel
</span>
<input <input
type="submit" value="Report" class="orange-button" type="submit" value="Submit" class="action-button-submit"
[disabled]="!form.valid" [disabled]="!form.valid"
> >
</div> </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({ @Component({
selector: 'my-video-report', 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 { export class VideoReportComponent extends FormReactive implements OnInit {
@Input() video: VideoDetails = null @Input() video: VideoDetails = null

View File

@ -1,12 +1,10 @@
<div bsModal #modal="bs-modal" class="modal" tabindex="-1"> <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-content">
<div class="modal-header"> <div class="modal-header">
<button type="button" class="close" aria-label="Close" (click)="hide()"> <span class="close" aria-hidden="true" (click)="hide()"></span>
<span aria-hidden="true">&times;</span> <h4 class="modal-title">Share</h4>
</button>
<h4 class="title-page title-page-single">Share</h4>
</div> </div>
<div class="modal-body"> <div class="modal-body">
@ -37,6 +35,12 @@
<div *ngIf="notSecure()" class="alert alert-warning"> <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). 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>
<div class="form-group inputs">
<span class="action-button action-button-cancel" (click)="hide()">
Cancel
</span>
</div>
</div> </div>
</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 { .action-more {
display: inline-block; display: inline-block;
.dropdown-menu .icon { .dropdown-menu .dropdown-item {
display: inline-block; padding: 6px 24px;
background-repeat: no-repeat;
background-size: contain;
width: 21px;
height: 21px;
vertical-align: middle;
margin-right: 5px;
position: relative;
top: -1px;
&.icon-download { .icon {
background-image: url('../../../assets/images/video/download-grey.svg'); @include icon(24px);
}
&.icon-alert { margin-right: 10px;
background-image: url('../../../assets/images/video/alert.svg'); position: relative;
} top: -1px;
&.icon-blacklist { &.icon-download {
background-image: url('../../../assets/images/video/eye-closed.svg'); 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="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Artboard-4" transform="translate(-48.000000, -467.000000)"> <g id="Artboard-4" transform="translate(-48.000000, -467.000000)">
<g id="161" 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.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="#585858"></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="#585858" x="11" y="9" width="2" height="5" rx="1"></rect> <rect id="Rectangle-3" fill="#000000" x="11" y="9" width="2" height="5" rx="1"></rect>
</g> </g>
</g> </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 {
.modal-header { .modal-header {
border-bottom: none; border-bottom: none;
margin-bottom: 5px;
.title-page-single { .modal-title {
margin: 0; 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/panels";
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/responsive-embed"; //@import "~bootstrap-sass/assets/stylesheets/bootstrap/responsive-embed";
//@import "~bootstrap-sass/assets/stylesheets/bootstrap/wells"; //@import "~bootstrap-sass/assets/stylesheets/bootstrap/wells";
@import "~bootstrap-sass/assets/stylesheets/bootstrap/close"; //@import "~bootstrap-sass/assets/stylesheets/bootstrap/close";
// Components w/ JavaScript // Components w/ JavaScript
@import "~bootstrap-sass/assets/stylesheets/bootstrap/modals"; @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 { @mixin orange-button {
&, &:active, &:focus { &, &:active, &:focus {
color: #fff; color: #fff;
@ -101,6 +109,7 @@
overflow: hidden; overflow: hidden;
background: #fff; background: #fff;
position: relative; position: relative;
font-size: 15px;
&:after { &:after {
top: 50%; 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) { @mixin peertube-checkbox ($border-width) {
display: none; display: none;

View File

@ -47,7 +47,7 @@ class VideosPreviewCache {
} }
private async loadPreviews (key: string) { private async loadPreviews (key: string) {
const video = await VideoModel.loadByUUID(key) const video = await VideoModel.loadByUUIDAndPopulateAccountAndServerAndTags(key)
if (!video) return undefined if (!video) return undefined
if (video.isOwned()) throw new Error('Cannot load preview of owned video.') if (video.isOwned()) throw new Error('Cannot load preview of owned video.')