Pull request #115: Upload overlay UI

Merge in RED/ui from upload-overlay to master

* commit '21dae27c0e9592e5e1e20151dad8afa5a28d5412':
  Upload overlay UI
This commit is contained in:
Timo Bejan 2021-02-23 07:24:59 +01:00
commit f8160375f4
13 changed files with 302 additions and 169 deletions

View File

@ -3,15 +3,15 @@
<div class="dialog-content">
<p [innerHTML]="'overwrite-files-dialog.question' | translate: { filename: filename }"></p>
</div>
<div class="dialog-actions">
<mat-checkbox [checked]="remember" (change)="remember = !remember" color="primary" class="flex-1">
{{ 'overwrite-files-dialog.options.remember' | translate }}
</mat-checkbox>
</div>
<div class="all-caps-label primary pointer" (click)="selectOption('overwrite')" translate="overwrite-files-dialog.options.overwrite"></div>
<div class="all-caps-label primary pointer" (click)="selectOption('skip')" translate="overwrite-files-dialog.options.skip"></div>
<div class="dialog-actions">
<button (click)="selectOption('overwrite')" color="primary" mat-flat-button translate="overwrite-files-dialog.options.overwrite"></button>
<button (click)="selectOption('skip')" mat-flat-button translate="overwrite-files-dialog.options.skip"></button>
<div class="all-caps-label cancel" (click)="cancel()" translate="overwrite-files-dialog.options.cancel"></div>
</div>
</section>

View File

@ -1,3 +1,12 @@
.dialog-actions > div:not(:last-child) {
margin-right: 32px;
mat-checkbox {
margin-top: 11px;
font-weight: 600;
}
.dialog-actions > *:not(:last-child) {
margin-right: 16px;
}
.cancel {
margin-left: 8px;
}

View File

@ -61,6 +61,8 @@ export class IconsModule {
'sort-asc',
'sort-desc',
'status',
'status-expand',
'status-collapse',
'template',
'thumb-down',
'trash',

View File

@ -1,66 +1,56 @@
<section class="red-upload-download-overlay mat-elevation-z4">
<div (click)="collapsed = !collapsed" class="red-upload-download-header">
<div class="title">
<section class="red-upload-download-overlay">
<div (click)="collapsed = !collapsed" [class.expanded]="!collapsed" class="red-upload-download-header">
<div class="title flex-1">
{{ 'upload-status.dialog.title' | translate: { len: uploadService.files.length } }}
</div>
<div *ngIf="!collapsed" class="collapse-icon">
<mat-icon svgIcon="red:arrow-down"></mat-icon>
</div>
<div *ngIf="collapsed" class="collapse-icon">
<mat-icon svgIcon="red:arrow-up"></mat-icon>
</div>
<div (click)="closeDialog()" class="close-icon">
<mat-icon svgIcon="red:close"></mat-icon>
</div>
<mat-icon *ngIf="!collapsed" class="collapse-icon" svgIcon="red:status-collapse"></mat-icon>
<mat-icon *ngIf="collapsed" class="collapse-icon" svgIcon="red:status-expand"></mat-icon>
<mat-icon (click)="closeDialog()" svgIcon="red:close"></mat-icon>
</div>
<div [hidden]="collapsed">
<div class="upload-download-list">
<div *ngFor="let projectId of uploadService.activeProjectKeys">
<div class="project-name-wrapper">
<span class="project-name">{{ uploadService.groupedFiles[projectId][0].projectName }}</span> ({{
uploadService.groupedFiles[projectId].length
}})
</div>
<div *ngFor="let model of uploadService.groupedFiles[projectId]" class="upload-download-list-item">
<div [hidden]="collapsed" class="upload-download-list">
<div *ngFor="let projectId of uploadService.activeProjectKeys">
<div class="project-name-wrapper all-caps-label">
<span>{{ uploadService.groupedFiles[projectId][0].projectName }}</span>
</div>
<div *ngFor="let model of uploadService.groupedFiles[projectId]" class="upload-download-list-item" [class.error]="model.error">
<div>
<div class="upload-download-line">
<div matTooltipPosition="above" [matTooltip]="model.file?.name" class="upload-download-item-name">
<div
[matTooltip]="model.file?.name"
class="upload-download-item-name flex-1"
[class.complete]="model.completed && !model.error"
matTooltipPosition="above"
>
{{ model.file?.name }}
</div>
<div *ngIf="!model.completed && model.progress < 100" class="upload-download-progress">{{ model.progress }}%</div>
<div *ngIf="model.completed && model.error" class="upload-download-progress error">
<mat-icon svgIcon="red:error"></mat-icon>
</div>
<div *ngIf="model.completed && !model.error" class="upload-download-progress ok">
<mat-icon svgIcon="red:check"></mat-icon>
</div>
<div class="progress" *ngIf="!model.error">{{ model.progress }}%</div>
</div>
<div *ngIf="model.completed && model.error" class="upload-download-line">
<div matTooltipPosition="above" [matTooltip]="model.error.message" class="upload-download-item-name error">
{{ model.error.message }}
</div>
<div class="error-message" *ngIf="model.error">
{{ model.error?.message }}
</div>
</div>
<div class="upload-download-progress">
<div
*ngIf="!model.sizeError"
(click)="uploadItem(model)"
[matTooltip]="'upload-status.dialog.actions.re-upload' | translate"
matTooltipPosition="above"
class="error-action pointer"
>
<mat-icon svgIcon="red:refresh"></mat-icon>
</div>
<div
(click)="cancelItem(model)"
[matTooltip]="'upload-status.dialog.actions.cancel' | translate"
matTooltipPosition="above"
class="error-action pointer"
>
<mat-icon svgIcon="red:close"></mat-icon>
</div>
</div>
<div class="upload-download-progress" *ngIf="!model.error" mat-line>
<mat-progress-bar [value]="model.progress" color="primary" mode="determinate" [class.green]="model.completed"></mat-progress-bar>
</div>
<div class="actions" [class.error]="model.error" *ngIf="model.error || !model.completed">
<div
(click)="uploadItem(model)"
*ngIf="model.error && !model.sizeError"
[matTooltip]="'upload-status.dialog.actions.re-upload' | translate"
class="pointer"
matTooltipPosition="before"
>
<mat-icon svgIcon="red:refresh"></mat-icon>
</div>
<div *ngIf="!model.completed" class="upload-download-progress" mat-line>
<mat-progress-bar *ngIf="model.progress !== 100" [value]="model.progress" color="primary" mode="determinate"></mat-progress-bar>
<div
(click)="cancelItem(model)"
[matTooltip]="'upload-status.dialog.actions.cancel' | translate"
class="pointer"
matTooltipPosition="before"
>
<mat-icon svgIcon="red:close"></mat-icon>
</div>
</div>
</div>

View File

@ -2,16 +2,132 @@
@import '../../../assets/styles/red-mixins';
.red-upload-download-overlay {
right: 10px;
}
background: $white;
position: fixed;
bottom: 20px;
right: 20px;
box-shadow: 0 3px 12px 5px rgba(40, 50, 65, 0.14);
border-radius: 8px;
overflow: hidden;
width: 400px;
.project-name-wrapper {
display: flex;
padding: 8px 20px 8px 8px;
background-color: $grey-4;
font-weight: 600;
.red-upload-download-header {
display: flex;
flex-direction: row;
align-items: center;
position: relative;
padding: 16px 14px 16px 16px;
cursor: pointer;
.project-name {
@include line-clamp(1);
color: $grey-1;
font-size: 13px;
font-weight: 600;
line-height: 16px;
mat-icon {
height: 13px;
color: $grey-1;
&.collapse-icon {
height: 15px;
}
}
&.expanded {
border-bottom: 1px solid $separator;
}
}
.upload-download-list {
overflow: auto;
@include scroll-bar;
max-height: 260px;
> div:not(:first-child) {
.project-name-wrapper {
border-top: 1px solid $separator;
}
}
.project-name-wrapper {
display: flex;
padding: 4px 16px;
background-color: $grey-2;
> span {
@include line-clamp(1);
}
}
.upload-download-list-item {
padding: 10px 16px 12px 16px;
font-size: 11px;
line-height: 14px;
border-top: 1px solid $separator;
position: relative;
.upload-download-line {
display: flex;
justify-content: flex-start;
align-items: center;
.upload-download-item-name {
@include line-clamp(1);
&.complete {
text-decoration: underline;
}
}
.progress {
margin-left: 10px;
font-weight: 600;
}
}
.upload-download-progress {
margin-top: 8px;
}
&.error {
background-color: rgba($primary, 0.1);
padding-right: 100px;
.error-message {
margin-top: 2px;
color: $primary;
}
}
.actions {
display: none;
position: absolute;
align-items: center;
top: 0;
right: 0;
height: 100%;
&.error {
display: flex;
}
&:not(.error) {
background: linear-gradient(to right, rgba(244, 245, 247, 0) 0%, $grey-2 35%);
padding-left: 60px;
}
mat-icon {
height: 13px;
margin-right: 20px;
}
}
&:not(.error):hover {
background-color: $grey-2;
.actions {
display: flex;
}
}
}
}
}

View File

@ -736,13 +736,13 @@
"pending-changes-guard": "WARNING: You have unsaved changes. Press Cancel to go back and save these changes, or OK to lose these changes.",
"reset-filters": "Reset Filters",
"overwrite-files-dialog": {
"title": "File already exists!",
"question": "<b>{{filename}}</b> already exists. What do you want to do?",
"title": "Document already exists!",
"question": "<b>{{filename}}</b> already exists. Choose how to proceed:",
"options": {
"overwrite": "Overwrite",
"skip": "Skip",
"cancel": "Cancel",
"remember": "Apply for all uploads"
"overwrite": "Replace existing document",
"skip": "Keep existing document",
"cancel": "Cancel all uploads",
"remember": "Remember choice and don't ask me again"
}
},
"license-info-screen": {

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="15px" height="15px" viewBox="0 0 15 15" version="1.1" xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink">
<title>B14B1060-4D9C-4EEC-845D-CFA8258D2E16</title>
<defs>
<path
d="M1028,576 L1412,576 C1416.41828,576 1420,579.581722 1420,584 L1420,873 C1420,877.418278 1416.41828,881 1412,881 L1028,881 C1023.58172,881 1020,877.418278 1020,873 L1020,584 C1020,579.581722 1023.58172,576 1028,576 Z"
id="path-1"></path>
<filter x="-6.8%" y="-7.9%" width="113.5%" height="117.7%" filterUnits="objectBoundingBox" id="filter-3">
<feMorphology radius="2.5" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1"></feMorphology>
<feOffset dx="0" dy="3" in="shadowSpreadOuter1" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="6" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0.156862745 0 0 0 0 0.196078431 0 0 0 0 0.254901961 0 0 0 0.1428069 0"
type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="File-Upload-&amp;-Download-Overlays" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Document-Upload---Hover" transform="translate(-1360.000000, -592.000000)">
<rect x="0" y="0" width="1440" height="900"></rect>
<g id="Project-details" transform="translate(1111.000000, 127.000000)">
<g id="Group-4" transform="translate(0.000000, 145.000000)"></g>
</g>
<g id="Rectangle">
<use fill-opacity="1" filter="url(#filter-3)" xlink:href="#path-1"></use>
<use fill-rule="evenodd" xlink:href="#path-1"></use>
</g>
<g id="Group-6-Copy">
<g transform="translate(1352.000000, 584.000000)" id="status">
<g transform="translate(15.500000, 15.500000) rotate(90.000000) translate(-15.500000, -15.500000) translate(8.000000, 8.000000)">
<polygon id="Path" fill="currentColor" fill-rule="nonzero"
points="9.825 3.75 8.775 4.8 10.65 6.75 1.5 6.75 1.5 8.25 10.65 8.25 8.775 10.2 9.825 11.25 13.5 7.5"></polygon>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -0,0 +1,43 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="15px" height="15px" viewBox="0 0 15 15" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>98CDF1EA-D4BC-4B4A-A707-D85244677FBB</title>
<defs>
<path d="M8,0 L392,0 C396.418278,-8.11624501e-16 400,3.581722 400,8 L400,40 C400,44.418278 396.418278,48 392,48 L8,48 C3.581722,48 5.41083001e-16,44.418278 0,40 L0,8 C-5.41083001e-16,3.581722 3.581722,8.11624501e-16 8,0 Z" id="path-1"></path>
<filter x="-6.8%" y="-50.0%" width="113.5%" height="212.5%" filterUnits="objectBoundingBox" id="filter-3">
<feMorphology radius="2.5" operator="dilate" in="SourceAlpha" result="shadowSpreadOuter1"></feMorphology>
<feOffset dx="0" dy="3" in="shadowSpreadOuter1" result="shadowOffsetOuter1"></feOffset>
<feGaussianBlur stdDeviation="6" in="shadowOffsetOuter1" result="shadowBlurOuter1"></feGaussianBlur>
<feColorMatrix values="0 0 0 0 0.156862745 0 0 0 0 0.196078431 0 0 0 0 0.254901961 0 0 0 0.1428069 0" type="matrix" in="shadowBlurOuter1"></feColorMatrix>
</filter>
</defs>
<g id="File-Upload-&amp;-Download-Overlays" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Document-Upload---Collapsed" transform="translate(-1359.000000, -847.000000)">
<rect x="0" y="0" width="1440" height="900"></rect>
<g id="Project-details" transform="translate(1111.000000, 127.000000)" fill="currentColor" font-family="Inter-Regular, Inter" font-size="16" font-weight="normal">
<g id="Group-4" transform="translate(0.000000, 145.000000)">
<g id="Group-11" transform="translate(0.000000, 566.000000)">
<text id="Description">
<tspan x="0" y="16">Description</tspan>
</text>
</g>
</g>
</g>
<g id="Group-10" transform="translate(1020.000000, 832.000000)">
<g id="Group-8">
<mask id="mask-2">
<use xlink:href="#path-1"></use>
</mask>
<g id="Rectangle">
<use fill-opacity="1" filter="url(#filter-3)" xlink:href="#path-1"></use>
<use fill-rule="evenodd" xlink:href="#path-1"></use>
</g>
</g>
<g id="Group-6-Copy" transform="translate(347.000000, 23.000000) rotate(180.000000) translate(-347.000000, -23.000000) translate(332.000000, 8.000000)" fill="currentColor" fill-rule="nonzero">
<g id="status" transform="translate(15.500000, 15.500000) rotate(90.000000) translate(-15.500000, -15.500000) translate(8.000000, 8.000000)">
<polygon id="Path" points="9.825 3.75 8.775 4.8 10.65 6.75 1.5 6.75 1.5 8.25 10.65 8.25 8.775 10.2 9.825 11.25 13.5 7.5"></polygon>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -31,10 +31,20 @@
opacity: 0 !important;
}
.mat-flat-button.mat-primary,
.mat-button.primary {
.mat-flat-button,
.mat-button {
padding: 0 14px;
transition: background-color 0.2s, color 0.2s;
background-color: $grey-6;
&:not(.mat-button-disabled):hover {
background-color: $grey-4;
}
}
.mat-flat-button.mat-primary,
.mat-button.primary {
background-color: $red-1;
&.mat-button-disabled {

View File

@ -0,0 +1,16 @@
@import 'red-variables';
.mat-progress-bar {
height: 6px;
border-radius: 3px;
.mat-progress-bar-buffer {
background-color: $grey-4;
}
&.green {
.mat-progress-bar-fill::after {
background-color: $green-2;
}
}
}

View File

@ -63,7 +63,7 @@ cdk-virtual-scroll-viewport {
padding-left: 100px;
padding-right: 24px;
z-index: 1;
background: linear-gradient(to right, rgba(244, 245, 247, 0) 0%, #f4f5f7 35%);
background: linear-gradient(to right, rgba(244, 245, 247, 0) 0%, $grey-2 35%);
mat-icon {
width: 14px;

View File

@ -24,5 +24,5 @@
@import 'red-breadcrumbs';
@import 'red-editor';
@import 'red-slider';
@import 'red-upload-download-overlay';
@import 'red-loading';
@import 'red-progress-bar';

View File

@ -1,90 +0,0 @@
@import 'red-variables';
.red-upload-download-overlay {
background: white;
position: fixed;
bottom: 10px;
border: 2px solid $grey-1;
.upload-download-list {
max-height: 216px;
max-width: 400px;
overflow: auto;
}
.red-upload-download-header {
display: flex;
flex-direction: row;
align-items: center;
position: relative;
padding: 10px;
background: $grey-1;
color: $white;
width: 380px;
cursor: pointer;
mat-icon {
color: $white;
}
}
.collapse-icon {
transform: translate(0, 2px);
mat-icon {
width: 20px;
}
}
.close-icon {
position: absolute;
right: 10px;
color: $white;
}
.upload-download-list-item {
padding: 8px;
mat-icon {
width: 16px;
}
.upload-download-line {
display: flex !important;
height: 20px;
position: relative;
justify-content: flex-start;
align-items: center;
.upload-download-item-name {
text-overflow: ellipsis;
overflow: hidden;
display: block;
white-space: nowrap;
padding-right: 50px;
&.error {
color: $red-1;
padding-right: 60px;
padding-top: 4px;
}
}
.upload-download-progress {
position: absolute;
right: 0;
width: 50px;
display: flex;
justify-content: space-evenly;
&.error {
color: $red-1;
}
&.ok {
color: $blue-1;
}
}
}
}
}