Pull request #72: Ui updates
Merge in RED/ui from ui-updates to master * commit '470c89e0fd3f3525d296f83bf320e16a2e4630b9': UI updates Scroll fixes UI updates UI updates
This commit is contained in:
commit
9741f7dfae
@ -97,6 +97,7 @@ import { PdfViewerScreenComponent } from './screens/pdf-viewer-screen/pdf-viewer
|
||||
import { HtmlDebugScreenComponent } from './screens/html-debug-screen/html-debug-screen.component';
|
||||
import { ReportDownloadBtnComponent } from './components/buttons/report-download-btn/report-download-btn.component';
|
||||
import { ProjectListingActionsComponent } from './screens/project-listing-screen/project-listing-actions/project-listing-actions.component';
|
||||
import { HasScrollbarDirective } from './utils/has-scrollbar.directive';
|
||||
|
||||
export function HttpLoaderFactory(httpClient: HttpClient) {
|
||||
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
|
||||
@ -280,6 +281,7 @@ const matImports = [
|
||||
ChevronButtonComponent,
|
||||
DictionaryListingScreenComponent,
|
||||
SyncWidthDirective,
|
||||
HasScrollbarDirective,
|
||||
AddEditDictionaryDialogComponent,
|
||||
DictionaryOverviewScreenComponent,
|
||||
TeamMembersComponent,
|
||||
|
||||
@ -5,6 +5,10 @@ button {
|
||||
|
||||
&.show-bg {
|
||||
background-color: $grey-6;
|
||||
|
||||
&:not(.mat-button-disabled):hover {
|
||||
background-color: $grey-4;
|
||||
}
|
||||
}
|
||||
|
||||
mat-icon {
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
<form (submit)="addComment()" *ngIf="addingComment" [formGroup]="commentForm">
|
||||
<div class="red-input-group">
|
||||
<input [placeholder]="translateService.instant('comments.add-comment')" formControlName="comment" name="comment" type="text" />
|
||||
<input [placeholder]="translateService.instant('comments.add-comment')" formControlName="comment" name="comment" type="text" class="w-full" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@ -30,8 +30,7 @@
|
||||
<div class="red-input-group">
|
||||
<label translate="project-listing.add-edit-dialog.form.description.label"></label>
|
||||
<textarea
|
||||
#textarea
|
||||
[class.has-scrollbar]="hasScrollbar"
|
||||
redactionHasScrollbar
|
||||
formControlName="description"
|
||||
name="description"
|
||||
type="text"
|
||||
@ -56,13 +55,9 @@
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button
|
||||
[disabled]="disabled || !changed"
|
||||
color="primary"
|
||||
mat-flat-button
|
||||
translate="project-listing.add-edit-dialog.actions.save"
|
||||
type="submit"
|
||||
></button>
|
||||
<button [disabled]="disabled || !changed" color="primary" mat-flat-button type="submit">
|
||||
{{ 'project-listing.add-edit-dialog.actions.save' | translate }}
|
||||
</button>
|
||||
|
||||
<redaction-icon-button
|
||||
[disabled]="disabled || !changed"
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { Component, ElementRef, Inject, ViewChild } from '@angular/core';
|
||||
import { Component, Inject } from '@angular/core';
|
||||
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
|
||||
import { Project } from '@redaction/red-ui-http';
|
||||
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
|
||||
@ -14,7 +14,6 @@ import * as moment from 'moment';
|
||||
export class AddEditProjectDialogComponent {
|
||||
public projectForm: FormGroup;
|
||||
public hasDueDate = true;
|
||||
@ViewChild('textarea') private _textarea: ElementRef;
|
||||
|
||||
constructor(
|
||||
private readonly _appStateService: AppStateService,
|
||||
@ -30,10 +29,6 @@ export class AddEditProjectDialogComponent {
|
||||
this.hasDueDate = !!this.project?.dueDate;
|
||||
}
|
||||
|
||||
public get hasScrollbar() {
|
||||
return this._textarea?.nativeElement.clientHeight < this._textarea?.nativeElement.scrollHeight;
|
||||
}
|
||||
|
||||
public get changed() {
|
||||
if (!this.project) {
|
||||
return true;
|
||||
|
||||
@ -48,7 +48,7 @@
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button color="primary" mat-flat-button type="submit" [disabled]="!usersForm.valid || !changed" class="red-button">
|
||||
<button [disabled]="!usersForm.valid || !changed" color="primary" mat-flat-button type="submit">
|
||||
{{ 'assign-' + data.type + '-owner.dialog.save' | translate }}
|
||||
</button>
|
||||
|
||||
|
||||
@ -8,10 +8,10 @@
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button (click)="confirm()" color="primary" mat-flat-button class="red-button">
|
||||
<button (click)="confirm()" color="primary" mat-flat-button>
|
||||
{{ confirmationDialogInput.confirmationText | translate: confirmationDialogInput.translateParams }}
|
||||
</button>
|
||||
<button (click)="deny()" color="primary" mat-flat-button class="red-button">
|
||||
<button (click)="deny()" color="primary" mat-flat-button>
|
||||
{{ confirmationDialogInput.denyText | translate: confirmationDialogInput.translateParams }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@ -32,7 +32,7 @@
|
||||
|
||||
<div class="red-input-group" [class.required]="!isDocumentAdmin">
|
||||
<label translate="manual-annotation.dialog.content.comment"></label>
|
||||
<textarea #textarea [class.has-scrollbar]="hasScrollbar" class="w-300" formControlName="comment" name="comment" type="text" rows="4"></textarea>
|
||||
<textarea redactionHasScrollbar class="w-300" formControlName="comment" name="comment" type="text" rows="4"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="red-input-group required" *ngIf="isDictionaryRequest && !isFalsePositiveRequest">
|
||||
@ -47,7 +47,9 @@
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button color="primary" mat-flat-button [disabled]="!redactionForm.valid" translate="manual-annotation.dialog.actions.save" type="submit"></button>
|
||||
<button color="primary" mat-flat-button [disabled]="!redactionForm.valid" type="submit">
|
||||
{{ 'manual-annotation.dialog.actions.save' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@ -31,8 +31,6 @@ export class ManualAnnotationDialogComponent implements OnInit {
|
||||
redactionDictionaries: TypeValue[] = [];
|
||||
legalOptions: LegalBasisOption[] = [];
|
||||
|
||||
@ViewChild('textarea') private _textarea: ElementRef;
|
||||
|
||||
get title() {
|
||||
return this._manualAnnotationService.getTitle(this.manualRedactionEntryWrapper.type);
|
||||
}
|
||||
@ -85,10 +83,6 @@ export class ManualAnnotationDialogComponent implements OnInit {
|
||||
this.redactionDictionaries.sort((a, b) => a.label.localeCompare(b.label));
|
||||
}
|
||||
|
||||
public get hasScrollbar() {
|
||||
return this._textarea?.nativeElement.clientHeight < this._textarea?.nativeElement.scrollHeight;
|
||||
}
|
||||
|
||||
handleAddRedaction() {
|
||||
this._enhanceManualRedaction(this.manualRedactionEntryWrapper.manualRedactionEntry);
|
||||
this._manualAnnotationService.addAnnotation(this.manualRedactionEntryWrapper.manualRedactionEntry).subscribe(
|
||||
|
||||
@ -5,15 +5,28 @@
|
||||
</div>
|
||||
|
||||
<div class="dialog-content">
|
||||
<div class="first-row">
|
||||
<div class="red-input-group required">
|
||||
<ng-container *ngIf="!!dictionary">
|
||||
<div class="red-input-group mb-14">
|
||||
<label translate="add-edit-dictionary.form.name"></label>
|
||||
{{ dictionary.label }}
|
||||
</div>
|
||||
</ng-container>
|
||||
|
||||
<div class="first-row">
|
||||
<div class="red-input-group required" *ngIf="!dictionary">
|
||||
<label translate="add-edit-dictionary.form.name"></label>
|
||||
<input formControlName="type" name="type" type="text" placeholder="{{ 'add-edit-dictionary.form.name-placeholder' | translate }}" />
|
||||
<span class="hint" translate="add-edit-dictionary.form.name-hint"></span>
|
||||
</div>
|
||||
|
||||
<div class="red-input-group required">
|
||||
<label translate="add-edit-dictionary.form.rank"></label>
|
||||
<input
|
||||
formControlName="type"
|
||||
name="type"
|
||||
type="text"
|
||||
[attr.disabled]="!!dictionary || null"
|
||||
placeholder="{{ 'add-edit-dictionary.form.name-placeholder' | translate }}"
|
||||
formControlName="rank"
|
||||
class="w-75"
|
||||
name="rank"
|
||||
type="number"
|
||||
placeholder="{{ 'add-edit-dictionary.form.rank-placeholder' | translate }}"
|
||||
/>
|
||||
</div>
|
||||
|
||||
@ -41,11 +54,6 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="red-input-group required">
|
||||
<label translate="add-edit-dictionary.form.rank"></label>
|
||||
<input formControlName="rank" name="rank" type="number" placeholder="{{ 'add-edit-dictionary.form.rank-placeholder' | translate }}" />
|
||||
</div>
|
||||
|
||||
<div class="red-input-group slider-row">
|
||||
<mat-button-toggle-group name="hint" formControlName="hint" appearance="legacy">
|
||||
<mat-button-toggle [value]="false"> {{ 'add-edit-dictionary.form.redaction' | translate }}</mat-button-toggle>
|
||||
@ -61,7 +69,9 @@
|
||||
</div>
|
||||
|
||||
<div class="dialog-actions">
|
||||
<button [disabled]="dictionaryForm.invalid || !changed" color="primary" mat-flat-button translate="add-edit-dictionary.save" type="submit"></button>
|
||||
<button [disabled]="dictionaryForm.invalid || !changed" color="primary" mat-flat-button type="submit">
|
||||
{{ 'add-edit-dictionary.save' | translate }}
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
display: flex;
|
||||
|
||||
> *:not(last-child) {
|
||||
margin-right: 24px;
|
||||
margin-right: 16px;
|
||||
}
|
||||
|
||||
.red-input-group {
|
||||
@ -23,3 +23,7 @@
|
||||
transition: background-color 0.25s ease;
|
||||
color: $white;
|
||||
}
|
||||
|
||||
.mb-14 {
|
||||
margin-bottom: 14px;
|
||||
}
|
||||
|
||||
@ -68,7 +68,7 @@
|
||||
<div class="placeholder-bottom-border scrollbar-placeholder"></div>
|
||||
</div>
|
||||
|
||||
<div class="grid-container">
|
||||
<div class="grid-container" redactionHasScrollbar>
|
||||
<!-- Table lines -->
|
||||
<div
|
||||
class="table-item pointer"
|
||||
|
||||
@ -17,7 +17,7 @@ redaction-table-col-name::ng-deep {
|
||||
.grid-container {
|
||||
grid-template-columns: auto 1fr 1fr 2fr 11px;
|
||||
|
||||
&:hover {
|
||||
&.has-scrollbar:hover {
|
||||
grid-template-columns: auto 1fr 1fr 2fr;
|
||||
}
|
||||
|
||||
|
||||
@ -70,7 +70,7 @@
|
||||
<div class="search-match-text">
|
||||
{{ currentMatch + '/' + searchPositions.length }}
|
||||
</div>
|
||||
<mat-icon svgIcon="red:arrow-down" class="transform-180 pointer" (click)="previousSearchMatch()"></mat-icon>
|
||||
<mat-icon svgIcon="red:arrow-up" class="pointer" (click)="previousSearchMatch()"></mat-icon>
|
||||
<mat-icon svgIcon="red:arrow-down" class="pointer" (click)="nextSearchMatch()"></mat-icon>
|
||||
<mat-icon svgIcon="red:close" (click)="searchChanged(''); inputElement.focus()" class="pointer"></mat-icon>
|
||||
</div>
|
||||
|
||||
@ -45,7 +45,7 @@
|
||||
|
||||
.red-input-group {
|
||||
margin-bottom: 16px;
|
||||
max-width: 450px;
|
||||
max-width: 300px;
|
||||
|
||||
input {
|
||||
padding-right: 32px;
|
||||
|
||||
@ -37,7 +37,7 @@
|
||||
<div class="placeholder-bottom-border scrollbar-placeholder"></div>
|
||||
</div>
|
||||
|
||||
<div class="grid-container">
|
||||
<div class="grid-container" redactionHasScrollbar>
|
||||
<!-- Table lines -->
|
||||
<div class="table-item" *ngFor="let user of displayedUsers">
|
||||
<div>
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
.grid-container {
|
||||
grid-template-columns: 1fr 1fr 11px;
|
||||
|
||||
&:hover {
|
||||
&.has-scrollbar:hover {
|
||||
grid-template-columns: 1fr 1fr;
|
||||
}
|
||||
|
||||
|
||||
@ -26,9 +26,8 @@
|
||||
<div class="red-input-group required">
|
||||
<label translate="watermark-screen.form.text"></label>
|
||||
<textarea
|
||||
#textarea
|
||||
redactionHasScrollbar
|
||||
formControlName="text"
|
||||
[class.has-scrollbar]="hasScrollbar"
|
||||
(mousemove)="triggerChanges()"
|
||||
class="w-full"
|
||||
name="text"
|
||||
@ -71,11 +70,11 @@
|
||||
</form>
|
||||
|
||||
<div class="actions-container">
|
||||
<button color="primary" mat-flat-button (click)="save()" [disabled]="configForm.invalid || !changed" class="red-button">
|
||||
<button color="primary" mat-flat-button (click)="save()" [disabled]="configForm.invalid || !changed">
|
||||
{{ 'watermark-screen.action.save' | translate }}
|
||||
</button>
|
||||
|
||||
<div class="all-caps-label pointer cancel" [class.disabled]="!changed" (click)="revert()" [translate]="'watermark-screen.action.revert'"></div>
|
||||
<div class="all-caps-label pointer cancel" [class.disabled]="!changed" (click)="revert()" translate="watermark-screen.action.revert"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -36,8 +36,6 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
@ViewChild('viewer', { static: true })
|
||||
private _viewer: ElementRef;
|
||||
|
||||
@ViewChild('textarea') private _textarea: ElementRef;
|
||||
|
||||
public viewReady = false;
|
||||
public configForm: FormGroup;
|
||||
|
||||
@ -104,10 +102,6 @@ export class WatermarkScreenComponent implements OnInit {
|
||||
|
||||
public triggerChanges() {}
|
||||
|
||||
public get hasScrollbar() {
|
||||
return this._textarea?.nativeElement.clientHeight < this._textarea?.nativeElement.scrollHeight;
|
||||
}
|
||||
|
||||
private _loadViewer() {
|
||||
WebViewer(
|
||||
{
|
||||
|
||||
@ -157,14 +157,7 @@
|
||||
</redaction-page-indicator>
|
||||
</div>
|
||||
|
||||
<div
|
||||
#annotationsElement
|
||||
(keydown)="preventKeyDefault($event)"
|
||||
(keyup)="preventKeyDefault($event)"
|
||||
[class.active-panel]="!pagesPanelActive"
|
||||
class="annotations"
|
||||
tabindex="1"
|
||||
>
|
||||
<div style="overflow: hidden;">
|
||||
<div attr.anotation-page-header="{{ activeViewerPage }}" class="page-separator">
|
||||
<span *ngIf="!!activeViewerPage" class="all-caps-label"
|
||||
><span translate="page"></span> {{ activeViewerPage }} - {{ displayedAnnotations[activeViewerPage]?.annotations?.length || 0 }}
|
||||
@ -172,38 +165,48 @@
|
||||
></span>
|
||||
</div>
|
||||
|
||||
<div *ngIf="!displayedAnnotations[activeViewerPage]" class="heading-l no-annotations">
|
||||
{{ 'file-preview.no-annotations-for-page' | translate }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
(click)="annotationClicked(annotation)"
|
||||
*ngFor="let annotation of displayedAnnotations[activeViewerPage]?.annotations"
|
||||
[ngClass]="{ active: selectedAnnotation?.id === annotation.id }"
|
||||
attr.annotation-id="{{ annotation.id }}"
|
||||
attr.annotation-page="{{ activeViewerPage }}"
|
||||
class="annotation"
|
||||
#annotationsElement
|
||||
(keydown)="preventKeyDefault($event)"
|
||||
(keyup)="preventKeyDefault($event)"
|
||||
[class.active-panel]="!pagesPanelActive"
|
||||
redactionHasScrollbar
|
||||
class="annotations"
|
||||
tabindex="1"
|
||||
>
|
||||
<div class="details">
|
||||
<redaction-type-annotation-icon [annotation]="annotation"></redaction-type-annotation-icon>
|
||||
<div class="flex-1">
|
||||
<div>
|
||||
<strong>{{ annotation.typeLabel | translate }}</strong>
|
||||
</div>
|
||||
<div *ngIf="annotation.dictionary && annotation.dictionary !== 'manual'">
|
||||
<strong><span translate="dictionary"></span>: </strong>{{ annotation.dictionary | humanize: false }}
|
||||
</div>
|
||||
<div *ngIf="annotation.content">
|
||||
<strong><span translate="content"></span>: </strong>{{ annotation.content }}
|
||||
</div>
|
||||
</div>
|
||||
<div *ngIf="!displayedAnnotations[activeViewerPage]" class="heading-l no-annotations">
|
||||
{{ 'file-preview.no-annotations-for-page' | translate }}
|
||||
</div>
|
||||
|
||||
<div
|
||||
(click)="annotationClicked(annotation)"
|
||||
*ngFor="let annotation of displayedAnnotations[activeViewerPage]?.annotations"
|
||||
[ngClass]="{ active: selectedAnnotation?.id === annotation.id }"
|
||||
attr.annotation-id="{{ annotation.id }}"
|
||||
attr.annotation-page="{{ activeViewerPage }}"
|
||||
class="annotation"
|
||||
>
|
||||
<div class="details">
|
||||
<redaction-type-annotation-icon [annotation]="annotation"></redaction-type-annotation-icon>
|
||||
<div class="flex-1">
|
||||
<div>
|
||||
<strong>{{ annotation.typeLabel | translate }}</strong>
|
||||
</div>
|
||||
<div *ngIf="annotation.dictionary && annotation.dictionary !== 'manual'">
|
||||
<strong><span translate="dictionary"></span>: </strong>{{ annotation.dictionary | humanize: false }}
|
||||
</div>
|
||||
<div *ngIf="annotation.content">
|
||||
<strong><span translate="content"></span>: </strong>{{ annotation.content }}
|
||||
</div>
|
||||
</div>
|
||||
<redaction-annotation-actions
|
||||
(annotationsChanged)="annotationsChangedByReviewAction(true, annotation)"
|
||||
[annotation]="annotation"
|
||||
[canPerformAnnotationActions]="canPerformAnnotationActions"
|
||||
></redaction-annotation-actions>
|
||||
</div>
|
||||
<redaction-comments [annotation]="annotation"></redaction-comments>
|
||||
</div>
|
||||
<redaction-comments [annotation]="annotation"></redaction-comments>
|
||||
<redaction-annotation-actions
|
||||
(annotationsChanged)="annotationsChangedByReviewAction(true, annotation)"
|
||||
[annotation]="annotation"
|
||||
[canPerformAnnotationActions]="canPerformAnnotationActions"
|
||||
></redaction-annotation-actions>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -60,7 +60,6 @@
|
||||
.pages,
|
||||
.annotations {
|
||||
overflow-y: scroll;
|
||||
@include no-scroll-bar();
|
||||
outline: none;
|
||||
|
||||
&.active-panel {
|
||||
@ -71,34 +70,37 @@
|
||||
.pages {
|
||||
border-right: 1px solid $separator;
|
||||
min-width: 61px;
|
||||
@include no-scroll-bar();
|
||||
}
|
||||
|
||||
.page-separator {
|
||||
border-bottom: 1px solid $separator;
|
||||
height: 32px;
|
||||
box-sizing: border-box;
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: $grey-6;
|
||||
}
|
||||
|
||||
.annotations {
|
||||
overflow: hidden;
|
||||
width: 100%;
|
||||
|
||||
.page-separator {
|
||||
border-bottom: 1px solid $separator;
|
||||
height: 32px;
|
||||
box-sizing: border-box;
|
||||
padding: 0 10px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background-color: $grey-6;
|
||||
}
|
||||
height: 100%;
|
||||
|
||||
.annotation {
|
||||
border-bottom: 1px solid $separator;
|
||||
padding: 10px 10px 10px 6px;
|
||||
padding: 10px 21px 10px 6px;
|
||||
font-size: 11px;
|
||||
line-height: 14px;
|
||||
cursor: pointer;
|
||||
position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
border-left: 4px solid transparent;
|
||||
|
||||
.details {
|
||||
display: flex;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
redaction-type-annotation-icon {
|
||||
@ -118,6 +120,17 @@
|
||||
border-left: 4px solid $primary;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
overflow-y: auto;
|
||||
@include scroll-bar;
|
||||
}
|
||||
|
||||
&.has-scrollbar:hover {
|
||||
.annotation {
|
||||
padding-right: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,19 +4,14 @@
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
justify-content: space-evenly;
|
||||
|
||||
> div {
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding-top: 50px;
|
||||
|
||||
//&:first-child {
|
||||
// border-right: 1px solid $separator;
|
||||
//}
|
||||
|
||||
.project-stats-container {
|
||||
.project-stats-item {
|
||||
display: flex;
|
||||
|
||||
@ -3,16 +3,16 @@
|
||||
<div class="filters">
|
||||
<div translate="filters.filter-by"></div>
|
||||
<redaction-filter
|
||||
[filters]="statusFilters"
|
||||
[filterLabel]="'filters.status'"
|
||||
[icon]="'red:status'"
|
||||
(filtersChanged)="filtersChanged()"
|
||||
[filterLabel]="'filters.status'"
|
||||
[filters]="statusFilters"
|
||||
[icon]="'red:status'"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
[filters]="peopleFilters"
|
||||
[filterLabel]="'filters.people'"
|
||||
[icon]="'red:user'"
|
||||
(filtersChanged)="filtersChanged()"
|
||||
[filterLabel]="'filters.people'"
|
||||
[filters]="peopleFilters"
|
||||
[icon]="'red:user'"
|
||||
></redaction-filter>
|
||||
<redaction-filter
|
||||
(filtersChanged)="filtersChanged()"
|
||||
@ -23,15 +23,15 @@
|
||||
></redaction-filter>
|
||||
<form [formGroup]="searchForm">
|
||||
<div class="red-input-group">
|
||||
<input [placeholder]="'project-listing.search' | translate" formControlName="query" name="query" type="text" class="w-250 with-icon mt-0" />
|
||||
<input [placeholder]="'project-listing.search' | translate" class="w-250 with-icon mt-0" formControlName="query" name="query" type="text" />
|
||||
<mat-icon class="icon-right" svgIcon="red:search"></mat-icon>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
<redaction-icon-button
|
||||
(action)="openAddProjectDialog()"
|
||||
*ngIf="permissionsService.isManager()"
|
||||
icon="red:plus"
|
||||
(action)="openAddProjectDialog()"
|
||||
text="project-listing.add-new"
|
||||
type="primary"
|
||||
></redaction-icon-button>
|
||||
@ -45,31 +45,31 @@
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="table-header" redactionSyncWidth="table-item" [class.no-data]="noData">
|
||||
<div [class.no-data]="noData" class="table-header" redactionSyncWidth="table-item">
|
||||
<redaction-table-col-name
|
||||
label="project-listing.table-col-names.name"
|
||||
column="project.projectName"
|
||||
(toggleSort)="sortingService.toggleSort('project-listing', $event)"
|
||||
[activeSortingOption]="sortingOption"
|
||||
[withSort]="true"
|
||||
(toggleSort)="sortingService.toggleSort('project-listing', $event)"
|
||||
column="project.projectName"
|
||||
label="project-listing.table-col-names.name"
|
||||
></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name label="project-listing.table-col-names.needs-work"></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name label="project-listing.table-col-names.owner"></redaction-table-col-name>
|
||||
|
||||
<redaction-table-col-name label="project-listing.table-col-names.status" class="flex-end"></redaction-table-col-name>
|
||||
<redaction-table-col-name class="flex-end" label="project-listing.table-col-names.status"></redaction-table-col-name>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
|
||||
<div *ngIf="noData" class="no-data heading-l" translate="project-listing.no-projects-match"></div>
|
||||
|
||||
<div class="grid-container">
|
||||
<div class="grid-container" redactionHasScrollbar>
|
||||
<div
|
||||
*ngFor="let pw of displayedProjects | sortBy: sortingOption.order:sortingOption.column"
|
||||
[class.pointer]="canOpenProject(pw)"
|
||||
[routerLink]="[canOpenProject(pw) ? '/ui/projects/' + pw.project.projectId : []]"
|
||||
class="table-item"
|
||||
[class.pointer]="canOpenProject(pw)"
|
||||
>
|
||||
<div class="filename">
|
||||
<div class="table-item-title heading">
|
||||
@ -105,7 +105,7 @@
|
||||
<redaction-initials-avatar [userId]="pw.project.ownerId" [withName]="true"></redaction-initials-avatar>
|
||||
</div>
|
||||
<div class="status-container">
|
||||
<redaction-project-listing-actions [project]="pw" (actionPerformed)="actionPerformed(pw)"></redaction-project-listing-actions>
|
||||
<redaction-project-listing-actions (actionPerformed)="actionPerformed(pw)" [project]="pw"></redaction-project-listing-actions>
|
||||
</div>
|
||||
<div class="scrollbar-placeholder"></div>
|
||||
</div>
|
||||
@ -114,16 +114,16 @@
|
||||
|
||||
<div class="right-container">
|
||||
<redaction-project-listing-details
|
||||
[projectsChartData]="projectsChartData"
|
||||
(filtersChanged)="filtersChanged($event)"
|
||||
[documentsChartData]="documentsChartData"
|
||||
[filters]="detailsContainerFilters"
|
||||
(filtersChanged)="filtersChanged($event)"
|
||||
[projectsChartData]="projectsChartData"
|
||||
></redaction-project-listing-details>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<redaction-project-listing-empty *ngIf="!appStateService.hasProjects" (addProjectRequest)="openAddProjectDialog()"></redaction-project-listing-empty>
|
||||
<redaction-project-listing-empty (addProjectRequest)="openAddProjectDialog()" *ngIf="!appStateService.hasProjects"></redaction-project-listing-empty>
|
||||
|
||||
<ng-template #needsWorkTemplate let-filter="filter">
|
||||
<redaction-type-filter [filter]="filter"></redaction-type-filter>
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
.grid-container {
|
||||
grid-template-columns: 2fr 1fr 1fr auto 11px;
|
||||
|
||||
&:hover {
|
||||
&.has-scrollbar:hover {
|
||||
grid-template-columns: 2fr 1fr 1fr auto;
|
||||
}
|
||||
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
|
||||
import { ChangeDetectorRef, Component, ElementRef, OnDestroy, OnInit, ViewChild } from '@angular/core';
|
||||
import { FileManagementControllerService, Project } from '@redaction/red-ui-http';
|
||||
import { AppStateService } from '../../state/app-state.service';
|
||||
import { UserService } from '../../user/user.service';
|
||||
|
||||
@ -47,13 +47,13 @@
|
||||
></redaction-simple-doughnut-chart>
|
||||
</div>
|
||||
|
||||
<div *ngIf="hasFiles" class="mt-24 legend">
|
||||
<div *ngIf="hasFiles" class="mt-24 legend pb-32">
|
||||
<div (click)="toggleFilter('needsWorkFilters', filter.key)" *ngFor="let filter of filters.needsWorkFilters" [class.active]="filter.checked">
|
||||
<redaction-type-filter [filter]="filter"></redaction-type-filter>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-32 small-label stats-subtitle">
|
||||
<div class="pb-32 small-label stats-subtitle">
|
||||
<div>
|
||||
<mat-icon svgIcon="red:document"></mat-icon>
|
||||
<span>{{ 'project-overview.project-details.stats.documents' | translate: { count: appStateService.activeProject.files.length } }}</span>
|
||||
@ -86,7 +86,7 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-32" *ngIf="!!appStateService.activeProject.project.description">
|
||||
<div class="pb-32" *ngIf="!!appStateService.activeProject.project.description">
|
||||
<div class="heading" translate="project-overview.project-details.description"></div>
|
||||
<div class="mt-8">{{ appStateService.activeProject.project.description }}</div>
|
||||
</div>
|
||||
|
||||
@ -63,6 +63,6 @@
|
||||
margin-top: 24px;
|
||||
}
|
||||
|
||||
.mt-32 {
|
||||
margin-top: 32px;
|
||||
.pb-32 {
|
||||
padding-bottom: 32px;
|
||||
}
|
||||
|
||||
@ -95,7 +95,7 @@
|
||||
</div>
|
||||
<div class="red-content-inner">
|
||||
<div class="left-container" [class.extended]="collapsedDetails">
|
||||
<div *ngIf="!appStateService.activeProject?.hasFiles" class="no-data">
|
||||
<div *ngIf="!appStateService.activeProject?.hasFiles" class="empty-state">
|
||||
<mat-icon svgIcon="red:document"></mat-icon>
|
||||
<div class="heading-l" translate="project-overview.no-data.title"></div>
|
||||
<redaction-icon-button (action)="fileInput.click()" icon="red:upload" text="project-overview.no-data.action" type="primary">
|
||||
@ -178,7 +178,7 @@
|
||||
|
||||
<div *ngIf="noData" class="no-data heading-l" translate="project-overview.no-files-match"></div>
|
||||
|
||||
<div class="grid-container">
|
||||
<div redactionHasScrollbar class="grid-container">
|
||||
<div
|
||||
*ngFor="let fileStatus of displayedFiles | sortBy: sortingOption.order:sortingOption.column"
|
||||
[class.pointer]="permissionsService.canOpenFile(fileStatus)"
|
||||
|
||||
@ -18,7 +18,7 @@ redaction-table-col-name::ng-deep {
|
||||
.grid-container {
|
||||
grid-template-columns: auto 3fr 2fr 1fr 2fr 1fr auto 11px;
|
||||
|
||||
&:hover {
|
||||
&.has-scrollbar:hover {
|
||||
grid-template-columns: auto 3fr 2fr 1fr 2fr 1fr auto;
|
||||
}
|
||||
|
||||
@ -80,6 +80,14 @@ redaction-table-col-name::ng-deep {
|
||||
|
||||
redaction-project-details {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
padding-right: 11px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
redaction-project-details {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -3,8 +3,8 @@
|
||||
<div class="title">
|
||||
{{ 'upload-status.dialog.title' | translate: { p1: uploadService.files.length } }}
|
||||
</div>
|
||||
<div *ngIf="!collapsed" class="collapse-icon transform-180">
|
||||
<mat-icon svgIcon="red:arrow-up"></mat-icon>
|
||||
<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>
|
||||
|
||||
18
apps/red-ui/src/app/utils/has-scrollbar.directive.ts
Normal file
18
apps/red-ui/src/app/utils/has-scrollbar.directive.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { AfterContentChecked, AfterContentInit, AfterViewChecked, Directive, ElementRef, HostBinding } from '@angular/core';
|
||||
|
||||
@Directive({
|
||||
selector: '[redactionHasScrollbar]',
|
||||
exportAs: 'redactionHasScrollbar'
|
||||
})
|
||||
export class HasScrollbarDirective implements AfterContentChecked {
|
||||
constructor(private el: ElementRef) {}
|
||||
|
||||
@HostBinding('class') class = '';
|
||||
ngAfterContentChecked() {
|
||||
this.class = this.hasScrollbar ? 'has-scrollbar' : '';
|
||||
}
|
||||
|
||||
public get hasScrollbar() {
|
||||
return this.el?.nativeElement.clientHeight < this.el?.nativeElement.scrollHeight;
|
||||
}
|
||||
}
|
||||
@ -528,6 +528,7 @@
|
||||
"form": {
|
||||
"name": "Dictionary Name",
|
||||
"name-placeholder": "Enter Name",
|
||||
"name-hint": "Cannot be edited after saving.",
|
||||
"rank": "Rank",
|
||||
"rank-placeholder": "1000",
|
||||
"color": "Hex Color",
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="14px" height="14px" viewBox="0 0 14 14" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>9A0E7FCD-AD02-40D9-BEF9-48F61351C288</title>
|
||||
<title>arrow-down</title>
|
||||
<g id="Styleguide" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Styleguide-Buttons" transform="translate(-469.000000, -757.000000)">
|
||||
<rect x="0" y="0" width="904" height="906"></rect>
|
||||
|
||||
|
Before Width: | Height: | Size: 772 B After Width: | Height: | Size: 746 B |
@ -1,7 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg width="6px" height="6px" viewBox="0 0 6 6" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<title>sort-up</title>
|
||||
<g id="sort-up" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<polygon id="Fill-1" fill="currentColor" transform="translate(3.000000, 3.000000) rotate(-180.000000) translate(-3.000000, -3.000000) " points="3 5 6 1 -1.33216355e-14 1"></polygon>
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="14px"
|
||||
height="14px"
|
||||
viewBox="0 0 14 14"
|
||||
version="1.1"
|
||||
id="svg101">
|
||||
<defs
|
||||
id="defs105" />
|
||||
<title
|
||||
id="title92">arrow-up</title>
|
||||
<g
|
||||
id="Styleguide"
|
||||
stroke="none"
|
||||
stroke-width="1"
|
||||
fill="none"
|
||||
fill-rule="evenodd">
|
||||
<g
|
||||
id="Styleguide-Buttons"
|
||||
transform="translate(-469.000000, -757.000000)">
|
||||
<rect
|
||||
x="0"
|
||||
y="0"
|
||||
width="904"
|
||||
height="906"
|
||||
id="rect94" />
|
||||
<rect
|
||||
id="Rectangle"
|
||||
x="359"
|
||||
y="747"
|
||||
width="134"
|
||||
height="34"
|
||||
rx="17" />
|
||||
<g
|
||||
id="right"
|
||||
transform="rotate(180,241.5,385.5)"
|
||||
fill="currentColor">
|
||||
<polygon
|
||||
id="Fill-1"
|
||||
points="4,5 7,9 10,5 " />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 497 B After Width: | Height: | Size: 962 B |
@ -13,6 +13,7 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
line-height: 34px;
|
||||
transition: opacity 0.2s;
|
||||
|
||||
> *:not(last-child) {
|
||||
margin-right: 6px;
|
||||
@ -20,17 +21,29 @@
|
||||
}
|
||||
|
||||
&.mat-button-disabled {
|
||||
background-color: $grey-6 !important;
|
||||
.mat-button-wrapper {
|
||||
opacity: 0.3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.cdk-program-focused .mat-button-focus-overlay {
|
||||
.mat-button-focus-overlay {
|
||||
opacity: 0 !important;
|
||||
}
|
||||
|
||||
.mat-flat-button.mat-primary.red-button {
|
||||
.mat-flat-button.mat-primary {
|
||||
padding: 0 14px;
|
||||
transition: background-color 0.2s;
|
||||
transition: background-color 0.2s, color 0.2s;
|
||||
background-color: $red-1;
|
||||
|
||||
&.mat-button-disabled {
|
||||
background-color: $red-1;
|
||||
color: $white;
|
||||
|
||||
> * {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.mat-button-disabled):hover {
|
||||
background-color: $red-2;
|
||||
@ -42,10 +55,10 @@ redaction-chevron-button,
|
||||
redaction-circle-button {
|
||||
position: relative;
|
||||
display: flex;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
button {
|
||||
font-weight: 400 !important;
|
||||
transition: background-color 0.2s;
|
||||
|
||||
&.overlay {
|
||||
background: rgba($primary, 0.1);
|
||||
|
||||
@ -6,6 +6,14 @@
|
||||
flex-direction: column;
|
||||
margin-top: 24px;
|
||||
position: relative;
|
||||
height: fit-content;
|
||||
|
||||
.hint {
|
||||
margin-top: 5px;
|
||||
font-size: 11px;
|
||||
line-height: 14px;
|
||||
opacity: 0.7;
|
||||
}
|
||||
|
||||
.input-icon {
|
||||
position: absolute;
|
||||
@ -173,6 +181,7 @@
|
||||
|
||||
.mat-datepicker-input {
|
||||
margin-top: 0;
|
||||
width: 120px;
|
||||
}
|
||||
|
||||
.mat-datepicker-toggle {
|
||||
|
||||
@ -82,7 +82,7 @@ body {
|
||||
height: 4px;
|
||||
}
|
||||
|
||||
.no-data {
|
||||
.empty-state {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
|
||||
@ -26,21 +26,6 @@
|
||||
max-height: calc(100vh - 50px - 30px - 111px);
|
||||
overflow-y: hidden;
|
||||
|
||||
&:hover {
|
||||
overflow-y: scroll;
|
||||
@include scroll-bar;
|
||||
|
||||
.table-item {
|
||||
.action-buttons {
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.table-item > .scrollbar-placeholder {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.table-item {
|
||||
display: contents;
|
||||
|
||||
@ -74,7 +59,7 @@
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
padding-left: 100px;
|
||||
padding-right: 13px;
|
||||
padding-right: 24px;
|
||||
z-index: 1;
|
||||
background: linear-gradient(to right, rgba(244, 245, 247, 0) 0%, #f4f5f7 35%);
|
||||
|
||||
@ -103,6 +88,24 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
overflow-y: auto;
|
||||
@include scroll-bar;
|
||||
|
||||
&.has-scrollbar {
|
||||
.table-item {
|
||||
.action-buttons {
|
||||
right: 0;
|
||||
padding-right: 13px;
|
||||
}
|
||||
|
||||
.scrollbar-placeholder {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.scrollbar-placeholder {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user