reworked dev features

This commit is contained in:
Timo 2020-11-25 12:24:19 +02:00
parent 630a624104
commit b164ebec01
17 changed files with 214 additions and 74 deletions

View File

@ -84,6 +84,7 @@ import { UserButtonComponent } from './components/buttons/user-button/user-butto
import { CircleButtonComponent } from './components/buttons/circle-button/circle-button.component';
import { ChevronButtonComponent } from './components/buttons/chevron-button/chevron-button.component';
import { DictionaryListingScreenComponent } from './screens/admin/dictionary-listing-screen/dictionary-listing-screen.component';
import { CustomTooltipModule } from './common/red-tooltip/custom-tooltip.module';
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
@ -148,6 +149,7 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
ApiModule,
MatDialogModule,
MatNativeDateModule,
CustomTooltipModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,

View File

@ -2,16 +2,15 @@ import { ComponentRef, Directive, ElementRef, HostListener, Input, OnChanges, On
import { Overlay, OverlayPositionBuilder, OverlayRef } from '@angular/cdk/overlay';
import { ComponentPortal } from '@angular/cdk/portal';
import { TooltipContentComponent } from './tooltip-content/tooltip-content.component';
import { TooltipModel } from './tooltip-content/tooltip.model';
import { ArOverlayPosition, Placement } from '../../common/model/ar-overlay-position';
import { NavigationStart, Router } from '@angular/router';
import { OverlayPosition, Placement } from './overlay-position';
@Directive({
selector: '[redTooltip]',
exportAs: 'redTooltip'
selector: '[redactionTooltip]',
exportAs: 'redactionTooltip'
})
export class CustomTooltipDirective implements OnInit, OnChanges, OnDestroy {
@Input() redTooltip: string;
@Input() redactionTooltip: string;
@Input() placement: Placement = 'top';
@ -37,8 +36,8 @@ export class CustomTooltipDirective implements OnInit, OnChanges, OnDestroy {
}
ngOnChanges(changes: SimpleChanges): void {
if (this.tooltipRef && this.redTooltip) {
this.tooltipRef.instance.tooltip = new TooltipModel(this.redTooltip);
if (this.tooltipRef && this.redactionTooltip) {
this.tooltipRef.instance.tooltip = this.redactionTooltip;
}
}
@ -55,19 +54,19 @@ export class CustomTooltipDirective implements OnInit, OnChanges, OnDestroy {
}
}
open(model?: TooltipModel) {
open(model?: string) {
if (!this.overlayRef) {
this.createOverlay();
}
if (model) {
this.redTooltip = model;
this.redactionTooltip = model;
}
if (this.redTooltip) {
if (this.redactionTooltip) {
this.overlayRef.detach();
const tooltipPortal = new ComponentPortal(TooltipContentComponent);
this.tooltipRef = this.overlayRef.attach(tooltipPortal);
this.tooltipRef.instance.tooltip = new TooltipModel(this.redTooltip);
this.tooltipRef.instance.tooltip = this.redactionTooltip;
}
}
@ -94,7 +93,7 @@ export class CustomTooltipDirective implements OnInit, OnChanges, OnDestroy {
private createOverlay() {
const positionStrategy = this.overlayPositionBuilder
.flexibleConnectedTo(this.elementRef)
.withPositions(ArOverlayPosition.getConnectedPosition(this.placement));
.withPositions(OverlayPosition.getConnectedPosition(this.placement));
this.overlayRef = this.overlay.create({
positionStrategy,
scrollStrategy: this.overlay.scrollStrategies.close()

View File

@ -1,8 +1,8 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { OverlayModule } from '@angular/cdk/overlay';
import { CustomTooltipDirective } from './ar-tooltip.directive';
import { TooltipContentComponent } from './tooltip-content/tooltip-content.component';
import { CustomTooltipDirective } from './custom-tooltip.directive';
@NgModule({
imports: [CommonModule, OverlayModule],

View File

@ -0,0 +1,138 @@
import { ConnectedPosition } from '@angular/cdk/overlay';
import { isArray } from 'rxjs/internal-compatibility';
export declare type Placement =
| 'auto'
| 'top'
| 'bottom'
| 'left'
| 'right'
| 'top-left'
| 'top-right'
| 'bottom-left'
| 'bottom-right'
| 'left-top'
| 'left-bottom'
| 'right-top'
| 'right-bottom';
export declare type PlacementArray = Placement | Array<Placement>;
export class OverlayPosition {
private static readonly _offsetYVal = 7;
public static TOP_LEFT: ConnectedPosition = {
originX: 'end',
originY: 'top',
overlayX: 'end',
overlayY: 'bottom',
offsetY: -OverlayPosition._offsetYVal
};
public static TOP_RIGHT: ConnectedPosition = {
originX: 'start',
originY: 'top',
overlayX: 'start',
overlayY: 'bottom',
offsetY: -OverlayPosition._offsetYVal
};
public static BOTTOM_LEFT: ConnectedPosition = {
originX: 'end',
originY: 'bottom',
overlayX: 'end',
overlayY: 'top',
offsetY: OverlayPosition._offsetYVal
};
public static BOTTOM_RIGHT: ConnectedPosition = {
originX: 'start',
originY: 'bottom',
overlayX: 'start',
overlayY: 'top',
offsetY: OverlayPosition._offsetYVal
};
public static LEFT_TOP: ConnectedPosition = {
originX: 'start',
originY: 'top',
overlayX: 'end',
overlayY: 'top',
offsetX: -OverlayPosition._offsetYVal
};
public static LEFT_BOTTOM: ConnectedPosition = {
originX: 'start',
originY: 'bottom',
overlayX: 'end',
overlayY: 'bottom',
offsetX: -OverlayPosition._offsetYVal
};
public static RIGHT_TOP: ConnectedPosition = {
originX: 'end',
originY: 'top',
overlayX: 'start',
overlayY: 'top',
offsetX: OverlayPosition._offsetYVal
};
public static RIGHT_BOTTOM: ConnectedPosition = {
originX: 'end',
originY: 'bottom',
overlayX: 'start',
overlayY: 'bottom',
offsetX: OverlayPosition._offsetYVal
};
public static getConnectedPosition(position: PlacementArray): ConnectedPosition[] {
if (isArray(position)) {
return Array.from(position).map((pos) => this.getPosition(pos as Placement));
} else if (position === 'auto') {
return this.getAutoPosition();
} else {
return [this.getPosition(position as Placement)];
}
}
private static getPosition(position: Placement) {
switch (position) {
case 'top':
return OverlayPosition.TOP_RIGHT;
case 'bottom':
return OverlayPosition.BOTTOM_RIGHT;
case 'left':
return OverlayPosition.LEFT_TOP;
case 'right':
return OverlayPosition.RIGHT_TOP;
case 'top-left':
return OverlayPosition.TOP_LEFT;
case 'top-right':
return OverlayPosition.TOP_RIGHT;
case 'bottom-left':
return OverlayPosition.BOTTOM_LEFT;
case 'bottom-right':
return OverlayPosition.BOTTOM_RIGHT;
case 'left-top':
return OverlayPosition.LEFT_TOP;
case 'left-bottom':
return OverlayPosition.LEFT_BOTTOM;
case 'right-top':
return OverlayPosition.RIGHT_TOP;
case 'right-bottom':
return OverlayPosition.RIGHT_BOTTOM;
}
}
private static getAutoPosition(): ConnectedPosition[] {
return [
OverlayPosition.TOP_LEFT,
OverlayPosition.TOP_RIGHT,
OverlayPosition.BOTTOM_LEFT,
OverlayPosition.BOTTOM_RIGHT,
OverlayPosition.LEFT_TOP,
OverlayPosition.LEFT_BOTTOM,
OverlayPosition.RIGHT_TOP,
OverlayPosition.RIGHT_BOTTOM
];
}
}

View File

@ -1,10 +1,3 @@
<div class="tooltip-wrapper">
<div *ngIf="tooltip.title && tooltip.body; else onlyBodyOrTile">
<div class="tooltip-title">{{ tooltip.title }}</div>
<div class="tooltip-body">{{ tooltip.body }}</div>
</div>
<ng-template #onlyBodyOrTile>
<div *ngIf="tooltip.title" class="tooltip-body">{{ tooltip.title }}</div>
<div *ngIf="tooltip.body" class="tooltip-body">{{ tooltip.body }}</div>
</ng-template>
{{ tooltip }}
</div>

View File

@ -1,19 +1,14 @@
@import '../../../../../../../assets/styles/ar-typography';
@import '../../../../assets/styles/red-variables';
.tooltip-wrapper {
background-color: $aci-white;
box-shadow: 2px 3px 20px 0 rgba(0, 0, 0, 0.1);
padding: 12px 16px;
max-width: 300px;
font-size: 13px;
opacity: 0.95;
.tooltip-title {
@extend .aci-font-style-f8, .aci-grey-1;
padding-bottom: 4px;
}
.tooltip-body {
@extend .aci-font-style-f9, .aci-grey-1;
}
background-color: $accent;
border-radius: 3px;
padding: 10px;
font-family: Inter, sans-serif;
font-size: 11px;
line-height: 14px;
color: white;
position: relative;
overflow: visible !important;
text-align: center;
}

View File

@ -1,13 +1,12 @@
import { Component, Input, OnInit } from '@angular/core';
import { TooltipModel } from './tooltip.model';
@Component({
selector: 'up-ext-tooltip-content',
selector: 'redaction-tooltip-content',
templateUrl: './tooltip-content.component.html',
styleUrls: ['./tooltip-content.component.scss']
})
export class TooltipContentComponent implements OnInit {
@Input() tooltip: TooltipModel;
@Input() tooltip: string;
constructor() {}

View File

@ -1,3 +0,0 @@
export class TooltipModel {
constructor(public body: string) {}
}

View File

@ -4,16 +4,16 @@ import { Injectable } from '@angular/core';
providedIn: 'root'
})
export class UserPreferenceService {
get areIgnoredAnnotationsEnabled() {
const value = sessionStorage.getItem('redaction.enable-ignore-annotations');
get areDevFeaturesEnabled() {
const value = sessionStorage.getItem('redaction.enable-dev-features');
if (value) {
return value === 'true';
}
return false;
}
public toggleIgnoredAnnotationsEnabled() {
sessionStorage.setItem('redaction.enable-ignore-annotations', `${!this.areIgnoredAnnotationsEnabled}`);
public toggleDevFeatures() {
sessionStorage.setItem('redaction.enable-dev-features', `${!this.areDevFeaturesEnabled}`);
window.location.reload();
}
}

View File

@ -38,8 +38,11 @@
</a>
</div>
<div class="center flex-1">
<redaction-logo></redaction-logo>
<redaction-hidden-action (action)="userPreferenceService.toggleDevFeatures()">
<redaction-logo></redaction-logo>
</redaction-hidden-action>
<div class="app-name" translate="app-name"></div>
<span class="dev-mode" *ngIf="userPreferenceService.areDevFeaturesEnabled" translate="dev-mode"></span>
</div>
<div class="menu right flex-2">
<redaction-user-button [user]="user" [matMenuTriggerFor]="menu"></redaction-user-button>
@ -57,7 +60,7 @@
<button (click)="changeLanguage('de')" mat-menu-item translate="top-bar.navigation-items.my-account.children.language.german"></button>
</mat-menu>
<button (click)="logout()" mat-menu-item>
<mat-icon svgIcon="red:logout"> </mat-icon>
<mat-icon svgIcon="red:logout"></mat-icon>
<span translate="top-bar.navigation-items.my-account.children.logout"> </span>
</button>
</mat-menu>

View File

@ -23,3 +23,15 @@
}
}
}
.dev-mode {
margin: 0 10px;
padding: 2px 5px;
background-color: $primary;
color: $white;
font-size: 14px;
font-weight: 600;
line-height: 16px;
height: 16px;
text-align: center;
}

View File

@ -3,6 +3,7 @@ import { UserService } from '../../user/user.service';
import { AppStateService } from '../../state/app-state.service';
import { LanguageService } from '../../i18n/language.service';
import { PermissionsService } from '../../common/service/permissions.service';
import { UserPreferenceService } from '../../common/service/user-preference.service';
@Component({
selector: 'redaction-base-screen',
@ -13,6 +14,7 @@ export class BaseScreenComponent {
constructor(
public readonly appStateService: AppStateService,
public readonly permissionsService: PermissionsService,
public readonly userPreferenceService: UserPreferenceService,
private readonly _languageService: LanguageService,
private readonly _userService: UserService
) {}

View File

@ -85,20 +85,14 @@
</div>
<div class="right-fixed-container">
<redaction-hidden-action (action)="userPreferenceService.toggleIgnoredAnnotationsEnabled()">
<div
class="right-title heading"
translate="file-preview.tabs.annotations.label"
[class.primary]="userPreferenceService.areIgnoredAnnotationsEnabled"
>
<redaction-filter
(filtersChanged)="filtersChanged($event)"
[filterTemplate]="annotationFilterTemplate"
[filters]="annotationFilters"
[chevron]="true"
></redaction-filter>
</div>
</redaction-hidden-action>
<div class="right-title heading" translate="file-preview.tabs.annotations.label">
<redaction-filter
(filtersChanged)="filtersChanged($event)"
[filterTemplate]="annotationFilterTemplate"
[filters]="annotationFilters"
[chevron]="true"
></redaction-filter>
</div>
<div class="right-content">
<div

View File

@ -170,7 +170,7 @@ export class FilePreviewScreenComponent implements OnInit, OnDestroy {
this.annotations = this.fileData.getAnnotations(
this.appStateService.dictionaryData,
this.permissionsService.currentUser,
this.userPreferenceService.areIgnoredAnnotationsEnabled
this.userPreferenceService.areDevFeaturesEnabled
);
const annotationFilters = this._annotationProcessingService.getAnnotationFilter(this.annotations);
this.annotationFilters = processFilters(this.annotationFilters, annotationFilters);

View File

@ -25,7 +25,7 @@ export class FileDataModel {
return this.redactionLog.redactionLogEntry;
}
getAnnotations(dictionaryData: { [p: string]: TypeValue }, currentUser: UserWrapper, areIgnoreAnnotationsEnabled: boolean): AnnotationWrapper[] {
getAnnotations(dictionaryData: { [p: string]: TypeValue }, currentUser: UserWrapper, areDevFeaturesEnabled: boolean): AnnotationWrapper[] {
const annotations = [];
const pairs: AnnotationPair[] = this._createPairs();
@ -41,7 +41,7 @@ export class FileDataModel {
pair.comments
);
if (annotation) {
if (annotation.isIgnored && !areIgnoreAnnotationsEnabled) {
if (annotation.isIgnored && !areDevFeaturesEnabled) {
return;
}

View File

@ -26,9 +26,11 @@ export class AnnotationDrawService {
annotationManager.addAnnotations(annotations, true);
annotationManager.drawAnnotationsFromList(annotations);
this._redactionLogControllerService.getSectionGrid(this._appStateService.activeFileId).subscribe((sectionGrid) => {
this.drawSections(activeViewer, sectionGrid);
});
if (this._userPreferenceService.areDevFeaturesEnabled) {
this._redactionLogControllerService.getSectionGrid(this._appStateService.activeFileId).subscribe((sectionGrid) => {
this.drawSections(activeViewer, sectionGrid);
});
}
}
public drawSections(activeViewer: WebViewerInstance, sectionGrid: SectionGrid) {
@ -37,6 +39,9 @@ export class AnnotationDrawService {
const sectionRectangles: SectionRectangle[] = sectionGrid.rectanglesPerPage[page];
sectionRectangles.forEach((sectionRectangle) => {
sections.push(this.computeSection(activeViewer, parseInt(page, 10), sectionRectangle));
// sectionRectangle.tableCells?.forEach(cell =>{
// sections.push(this.computeSection(activeViewer, parseInt(page, 10), cell));
// })
});
}
const annotationManager = activeViewer.annotManager;
@ -49,13 +54,13 @@ export class AnnotationDrawService {
const pageHeight = activeViewer.docViewer.getPageHeight(pageNumber);
const rectangle = { topLeft: sectionRectangle.topLeft, page: pageNumber, height: sectionRectangle.height, width: sectionRectangle.width };
rectangleAnnot.PageNumber = pageNumber;
rectangleAnnot.X = rectangle.topLeft.x - 2;
rectangleAnnot.Y = pageHeight - (rectangle.topLeft.y + rectangle.height) - 2;
rectangleAnnot.Width = rectangle.width + 4;
rectangleAnnot.Height = rectangle.height + 4;
rectangleAnnot.X = rectangle.topLeft.x - 1;
rectangleAnnot.Y = pageHeight - (rectangle.topLeft.y + rectangle.height) - 1;
rectangleAnnot.Width = rectangle.width + 2;
rectangleAnnot.Height = rectangle.height + 2;
rectangleAnnot.ReadOnly = true;
rectangleAnnot.StrokeColor = this.getColor(activeViewer, 'analysis', 'analysis');
rectangleAnnot.StrokeThickness = 2;
rectangleAnnot.StrokeThickness = 1;
return rectangleAnnot;
}

View File

@ -7,6 +7,7 @@
"logout": "Logout"
},
"app-name": "DDA-R",
"dev-mode": "[ DEV MODE ]",
"upload-status": {
"dialog": {
"title": "File Upload",