Upload and OAUTH finished

This commit is contained in:
Timo Bejan 2020-10-04 20:46:47 +03:00
parent 66c1540d6c
commit 6eed5efedb
35 changed files with 745 additions and 86 deletions

View File

@ -1,36 +1,36 @@
{
"/project": {
"target": "http://ingress.redaction-timo-dev.178.63.47.73.xip.io",
"target": "http://ingress.redaction.178.63.47.73.xip.io",
"secure": false,
"changeOrigin": true,
"logLevel": "debug"
},
"/reanalyse": {
"target": "http://ingress.redaction-timo-dev.178.63.47.73.xip.io",
"target": "http://ingress.redaction.178.63.47.73.xip.io",
"secure": false,
"changeOrigin": true,
"logLevel": "debug"
},
"/upload": {
"target": "http://ingress.redaction-timo-dev.178.63.47.73.xip.io",
"target": "http://ingress.redaction.178.63.47.73.xip.io",
"secure": false,
"changeOrigin": true,
"logLevel": "debug"
},
"/download": {
"target": "http://ingress.redaction-timo-dev.178.63.47.73.xip.io",
"target": "http://ingress.redaction.178.63.47.73.xip.io",
"secure": false,
"changeOrigin": true,
"logLevel": "debug"
},
"/delete": {
"target": "http://ingress.redaction-timo-dev.178.63.47.73.xip.io",
"target": "http://ingress.redaction.178.63.47.73.xip.io",
"secure": false,
"changeOrigin": true,
"logLevel": "debug"
},
"/status": {
"target": "http://ingress.redaction-timo-dev.178.63.47.73.xip.io",
"target": "http://ingress.redaction.178.63.47.73.xip.io",
"secure": false,
"changeOrigin": true,
"logLevel": "debug"

View File

@ -8,6 +8,7 @@ export enum AppConfigKey {
OAUTH_URL = "OAUTH_URL",
OAUTH_CLIENT_ID = "OAUTH_CLIENT_ID",
API_URL = "API_URL",
PDFTRON_LICENSE ="PDFTRON_LICENSE"
}
@Injectable({

View File

@ -7,4 +7,5 @@ import {Component} from '@angular/core';
})
export class AppComponent {
}

View File

@ -41,6 +41,7 @@ import {environment} from '../environments/environment';
import {ProjectDetailsDialogComponent} from './screens/project-overview-screen/project-details-dialog/project-details-dialog.component';
import {AuthModule} from "./auth/auth.module";
import {AuthGuard} from "./auth/auth.guard";
import {FileUploadModule} from "./upload/file-upload.module";
export function HttpLoaderFactory(httpClient: HttpClient) {
return new TranslateHttpLoader(httpClient, '/assets/i18n/', '.json');
@ -105,8 +106,8 @@ export function HttpLoaderFactory(httpClient: HttpClient) {
MatFormFieldModule,
ToastrModule.forRoot(),
MatSelectModule,
NgxDropzoneModule,
MatSidenavModule,
FileUploadModule,
ServiceWorkerModule.register('ngsw-worker.js', {enabled: environment.production})
],
providers: [ {

View File

@ -4,6 +4,7 @@ import {Observable} from "rxjs";
import {AuthConfig, OAuthService} from "angular-oauth2-oidc";
import {AppConfigKey, AppConfigService} from "../app-config/app-config.service";
import {map} from "rxjs/operators";
import {JwksValidationHandler} from "angular-oauth2-oidc-jwks";
@Injectable()
@ -18,6 +19,8 @@ export class AuthGuard implements CanActivate {
this._configured = true;
const authConfig = await this._createConfiguration().toPromise();
this._oauthService.configure(authConfig);
this._oauthService.tokenValidationHandler = new JwksValidationHandler();
this._oauthService.setupAutomaticSilentRefresh();
return this._oauthService.loadDiscoveryDocumentAndTryLogin();
}
@ -25,11 +28,13 @@ export class AuthGuard implements CanActivate {
if (!this._configured) {
return this._configure().then(() => this._checkToken());
}
return this._checkToken();
}
private _checkToken() {
if (!this._oauthService.getAccessToken()) {
const expired = this._oauthService.getAccessTokenExpiration() - new Date().getTime() < 0;
if (!this._oauthService.getAccessToken() || expired) {
this._oauthService.initLoginFlow();
return false;
}
@ -42,8 +47,10 @@ export class AuthGuard implements CanActivate {
issuer: config[AppConfigKey.OAUTH_URL],
redirectUri: window.location.origin,
clientId: config[AppConfigKey.OAUTH_CLIENT_ID],
responseType: 'code',
scope: 'openid',
showDebugInformation: true,
silentRefreshRedirectUri: window.location.origin + '/assets/oauth/silent-refresh.html',
useSilentRefresh: true,
}
}));
}

View File

@ -74,6 +74,31 @@ export class IconsModule {
sanitizer.bypassSecurityTrustResourceUrl('/assets/icons/general/refresh.svg')
);
iconRegistry.addSvgIconInNamespace(
'red',
'arrow-down',
sanitizer.bypassSecurityTrustResourceUrl('/assets/icons/general/arrow_down.svg')
);
iconRegistry.addSvgIconInNamespace(
'red',
'arrow-up',
sanitizer.bypassSecurityTrustResourceUrl('/assets/icons/general/arrow_up.svg')
);
iconRegistry.addSvgIconInNamespace(
'red',
'error',
sanitizer.bypassSecurityTrustResourceUrl(
'/assets/icons/general/error_icon.svg'
)
);
iconRegistry.addSvgIconInNamespace(
'red',
'check',
sanitizer.bypassSecurityTrustResourceUrl(
'/assets/icons/general/check_icon.svg'
)
);
}

View File

@ -1,10 +1,10 @@
import {AfterViewInit, Component, ElementRef, Input, OnChanges, OnInit, SimpleChanges, ViewChild} from '@angular/core';
import {KeycloakService} from "keycloak-angular";
import {AppConfigService} from "../../../app-config/app-config.service";
import {AppConfigKey, AppConfigService} from "../../../app-config/app-config.service";
import {FileStatus, FileUploadControllerService} from "@redaction/red-ui-http";
import {Observable, of} from "rxjs";
import {tap} from "rxjs/operators";
import WebViewer, {WebViewerInstance} from "@pdftron/webviewer";
import {TranslateService} from "@ngx-translate/core";
export enum FileType {
@ -32,9 +32,10 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
_redactedFileData: Blob;
constructor(private readonly _keycloak: KeycloakService,
private readonly _fileUploadControllerService: FileUploadControllerService,
private readonly _appConfigService: AppConfigService) {
constructor(
private readonly _translateService: TranslateService,
private readonly _fileUploadControllerService: FileUploadControllerService,
private readonly _appConfigService: AppConfigService) {
}
ngOnInit() {
@ -43,7 +44,7 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
wvDocumentLoadedHandler(): void {
this.wvInstance.setFitMode('FitWidth');
if(this.fileType === FileType.ANNOTATED){
if (this.fileType === FileType.ANNOTATED) {
this.wvInstance.toggleElement('notesPanel')
}
}
@ -63,10 +64,13 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
}
private _loadViewer(pdfBlob: any) {
const license = this._appConfigService.getConfig(AppConfigKey.PDFTRON_LICENSE);
WebViewer({
licenseKey: license,
path: '/assets/wv-resources',
}, this.viewer.nativeElement).then(instance => {
this.wvInstance = instance;
this._configureTextPopup();
instance.docViewer.on('documentLoaded', this.wvDocumentLoadedHandler)
instance.loadDocument(pdfBlob, {filename: this.fileStatus.filename});
})
@ -95,4 +99,18 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnChanges {
}
return fileObs$;
}
private _configureTextPopup() {
this.wvInstance.textPopup.add(<any>{
type: 'actionButton',
img: '/assets/icons/general/add.svg',
title: this._translateService.instant('pdf-viewer.text-popup.actions.suggestion-redaction.label'),
onClick: () => {
const selectedQuads = this.wvInstance.docViewer.getSelectedTextQuads();
console.log(selectedQuads);
}
});
}
}

View File

@ -7,7 +7,7 @@
<div class="heading-xl clamp-1">{{appStateService.activeProject.projectName}}</div>
<button (click)="fileInput.click()" color="accent" mat-flat-button
translate="project-overview.upload-files.label"></button>
<input #fileInput (change)="handleFileInput($event.target.files)" class="file-upload-input" multiple="true"
<input #fileInput (change)="uploadFiles($event.target.files)" class="file-upload-input" multiple="true"
type="file">
</div>
<div class="flex-row">
@ -23,13 +23,7 @@
</mat-form-field>
</div>
<div class="break-20"></div>
<div (dragenter)="dragEnter($event)" (mouseout)="dragLeave($event)" class="listing">
<ngx-dropzone #dropzoneComponent (change)="handleFileInput($event.addedFiles)"
(dragleave)="dragLeave($event)"
[class.active]="dragActive || (appStateService.projectFiles && appStateService.projectFiles.length === 0)"
class="drop-zone">
<ngx-dropzone-label>{{"project-overview.upload-files.label"| translate}}</ngx-dropzone-label>
</ngx-dropzone>
<div class="listing">
<div *ngFor="let fileStatus of appStateService.projectFiles | sortBy: sorting.order:sorting.name; trackBy:fileId"
[class.clickable]="fileStatus.status === 'PROCESSED'"
[routerLink]="fileStatus.status === 'PROCESSED' ? ['/ui/projects/'+projectId+'/file/'+fileStatus.fileId] : []"

View File

@ -10,20 +10,3 @@
}
.drop-zone {
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
height: calc(100% - 4px);
width: calc(100% - 4px);
background: white;
z-index: 100;
display: none;
cursor: pointer;
&.active {
display: flex;
}
}

View File

@ -13,6 +13,8 @@ import {ConfirmationDialogComponent} from "../../common/confirmation-dialog/conf
import {MatDialog} from "@angular/material/dialog";
import {AppStateService} from "../../state/app-state.service";
import {ProjectDetailsDialogComponent} from "./project-details-dialog/project-details-dialog.component";
import {FileDropOverlayService} from "../../upload/file-drop/service/file-drop-overlay.service";
@Component({
selector: 'redaction-project-overview-screen',
@ -53,6 +55,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
private readonly _dialog: MatDialog,
private readonly _reanalysisControllerService: ReanalysisControllerService,
private readonly _router: Router,
private readonly _fileDropOverlayService: FileDropOverlayService,
private readonly _fileUploadControllerService: FileUploadControllerService,
private readonly _projectControllerService: ProjectControllerService) {
this._activatedRoute.params.subscribe(params => {
@ -62,23 +65,12 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
}
ngOnInit(): void {
this._fileDropOverlayService.initFileDropHandling();
this._fileStatusInterval = setInterval(() => {
this._getFileStatus();
}, 5000);
}
handleFileInput(files: FileList | File[]) {
this.dragActive = false;
for (let i = 0; i < files.length; i++) {
const file = files[i];
this._fileUploadControllerService.uploadFileForm(file, this.projectId, 'response').subscribe(() => {
this._getFileStatus();
}, () => {
this._notificationService.showToastNotification(this._translateService.instant('project-overview.upload-error.label', file), null, NotificationType.ERROR);
})
}
}
deleteFile($event: MouseEvent, fileStatus: FileStatus) {
$event.stopPropagation();
const dialogRef = this._dialog.open(ConfirmationDialogComponent, {
@ -102,13 +94,6 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
this.sorting = $event;
}
dragEnter($event: DragEvent) {
this.dragActive = true;
}
dragLeave($event: any) {
this.dragActive = false;
}
showDetailsDialog($event: MouseEvent) {
$event.stopPropagation();
@ -126,6 +111,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
}
ngOnDestroy(): void {
this._fileDropOverlayService.cleanupFileDropHandling();
if (this._fileStatusInterval) {
this._fileStatusInterval = null;
clearInterval(this._fileStatusInterval)
@ -152,4 +138,8 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
fileId(index, item){
return item.fileId;
}
uploadFiles(files: any) {
}
}

View File

@ -0,0 +1,11 @@
<section>
<ngx-dropzone (change)="handleFileInput($event.addedFiles)"
class="file-drop-zone">
<ngx-dropzone-label>{{"project-overview.upload-files.label"| translate}}</ngx-dropzone-label>
</ngx-dropzone>
<input type="file" multiple hidden/>
<button (click)="close()" class="close-icon" mat-icon-button>
<mat-icon svgIcon="red:close"></mat-icon>
</button>
</section>

View File

@ -0,0 +1,26 @@
section {
position: fixed;
top: 0;
bottom: 0;
right: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: 1000;
padding: 12px;
background: white;
}
.file-drop-zone {
background: white;
height: calc(100% - 26px);
width: calc(100% - 26px);
}
.close-icon {
position: absolute;
z-index: 1100;
top: 20px;
right: 40px;
}

View File

@ -0,0 +1,46 @@
import {Component, HostListener, OnInit} from '@angular/core';
import {FileUploadService} from "../file-upload.service";
import {FileUploadModel} from "../model/file-upload.model";
import {OverlayRef} from "@angular/cdk/overlay";
import {UploadStatusOverlayService} from "../upload-status-dialog/service/upload-status-overlay.service";
@Component({
selector: 'redaction-file-drop',
templateUrl: './file-drop.component.html',
styleUrls: ['./file-drop.component.scss']
})
export class FileDropComponent implements OnInit {
constructor(private readonly _dialogRef: OverlayRef, private readonly _fileUploadService: FileUploadService, private _uploadStatusOverlayService: UploadStatusOverlayService) {
}
ngOnInit() {
}
close() {
this._dialogRef.detach();
}
@HostListener('document:keydown.escape', ['$event'])
onKeydownHandler(evt: KeyboardEvent) {
this.close();
}
handleFileInput(files: FileList | File[]) {
const uploadFiles: FileUploadModel[] = [];
for (let i = 0; i < files.length; i++) {
const file = files[i];
uploadFiles.push({
file: file,
progress: 0,
completed: false,
error: null
})
}
this._fileUploadService.uploadFiles(uploadFiles);
this._uploadStatusOverlayService.openStatusOverlay();
this._dialogRef.detach();
}
}

View File

@ -0,0 +1,69 @@
import {Injectable, Injector} from "@angular/core";
import {Overlay} from "@angular/cdk/overlay";
import {FileDropComponent} from "../file-drop.component";
import {ComponentPortal} from "@angular/cdk/portal";
import {OverlayRef} from "@angular/cdk/overlay";
@Injectable({
providedIn: 'root'
})
export class FileDropOverlayService {
private readonly _dropOverlayRef: OverlayRef;
constructor(private overlay: Overlay, private readonly _injector: Injector) {
this._dropOverlayRef = this.overlay.create({
height: '100vh',
width: '100vw',
});
}
dragListener = () => {
this.openFileDropOverlay();
};
mouseOut = e => {
if (e.toElement == null && e.relatedTarget == null) {
this.closeFileDropOverlay();
}
};
initFileDropHandling() {
document
.getElementsByTagName('body')[0]
.addEventListener('dragenter', this.dragListener, false);
document.getElementsByTagName('body')[0].addEventListener('mouseout', this.mouseOut, false);
}
cleanupFileDropHandling() {
document
.getElementsByTagName('body')[0]
.removeEventListener('dragenter', this.dragListener, false);
document
.getElementsByTagName('body')[0]
.removeEventListener('mouseout', this.mouseOut, false);
}
private _createInjector() {
return Injector.create({
providers: [{provide: OverlayRef, useValue: this._dropOverlayRef}],
parent: this._injector,
})
}
openFileDropOverlay() {
const component = new ComponentPortal(FileDropComponent, null, this._createInjector());
if (!this._dropOverlayRef.hasAttached()) {
this._dropOverlayRef.attach(component);
}
}
closeFileDropOverlay() {
if (this._dropOverlayRef) {
this._dropOverlayRef.detach();
}
}
}

View File

@ -0,0 +1,32 @@
import {NgModule} from '@angular/core';
import {CommonModule} from '@angular/common';
import {MatIconModule} from '@angular/material/icon';
import {MatListModule} from '@angular/material/list';
import {MatProgressBarModule} from '@angular/material/progress-bar';
import {MatTooltipModule} from '@angular/material/tooltip';
import {FileDropComponent} from './file-drop/file-drop.component';
import {OverlayModule} from '@angular/cdk/overlay';
import {UploadStatusOverlay} from './upload-status-dialog/upload-status-overlay.component';
import {NgxDropzoneModule} from "ngx-dropzone";
import {TranslateModule} from "@ngx-translate/core";
import {MatButtonModule} from "@angular/material/button";
@NgModule({
imports: [
CommonModule,
MatIconModule,
MatTooltipModule,
TranslateModule,
MatListModule,
NgxDropzoneModule,
MatProgressBarModule,
OverlayModule,
MatButtonModule,
],
declarations: [FileDropComponent, UploadStatusOverlay],
providers: [],
entryComponents: [FileDropComponent, UploadStatusOverlay],
exports: [FileDropComponent, UploadStatusOverlay]
})
export class FileUploadModule {
}

View File

@ -0,0 +1,47 @@
import {Injectable} from "@angular/core";
import {FileUploadModel} from "./model/file-upload.model";
import {FileUploadControllerService} from "@redaction/red-ui-http";
import {AppStateService} from "../state/app-state.service";
import {HttpEventType} from "@angular/common/http";
@Injectable({
providedIn: 'root'
})
export class FileUploadService {
files: FileUploadModel[] = [];
constructor(
private readonly _appStateService: AppStateService,
private readonly _fileUploadControllerService: FileUploadControllerService,
) {
}
uploadFiles(files: FileUploadModel[]) {
this.files.push(...files);
files.forEach(newFile => {
this._fileUploadControllerService.uploadFileForm(newFile.file, this._appStateService.activeProject.projectId, 'events', true).subscribe((event) => {
if (event.type === HttpEventType.UploadProgress) {
newFile.progress = (event.loaded / (event.total || event.loaded) * 100) | 0;
}
if (event.type === HttpEventType.Response) {
if (event.status < 300) {
newFile.progress = 100;
newFile.completed = true;
} else {
newFile.completed = true;
newFile.error = event.body;
}
}
}, (error) => {
newFile.completed = true;
newFile.error = error;
});
});
}
stopAllUploads() {
}
}

View File

@ -0,0 +1,8 @@
export interface FileUploadModel {
file: File;
progress: number;
completed: boolean;
error: any;
}

View File

@ -0,0 +1,41 @@
import {Injectable, Injector} from "@angular/core";
import {Overlay, OverlayRef} from "@angular/cdk/overlay";
import {ComponentPortal} from "@angular/cdk/portal";
import {UploadStatusOverlay} from "../upload-status-overlay.component";
@Injectable({
providedIn: 'root'
})
export class UploadStatusOverlayService {
private readonly _statusOverlayRef: OverlayRef;
constructor(private overlay: Overlay, private readonly _injector: Injector) {
this._statusOverlayRef = this.overlay.create({
height: '500px',
width: '300px',
});
}
private _createInjector() {
return Injector.create({
providers: [{provide: OverlayRef, useValue: this._statusOverlayRef}],
parent: this._injector,
})
}
openStatusOverlay() {
const component = new ComponentPortal(UploadStatusOverlay, null, this._createInjector());
if (!this._statusOverlayRef.hasAttached()) {
this._statusOverlayRef.attach(component);
}
}
closeStatusOverlay() {
if (this._statusOverlayRef) {
this._statusOverlayRef.detach();
}
}
}

View File

@ -0,0 +1,77 @@
<section class="red-upload-overlay mat-elevation-z4">
<div class="red-upload-header" (click)="collapsed = !collapsed">
<div class="text">
{{ 'upload-status.dialog.title.label' | translate: {p1: uploadService.files.length} }}
</div>
<div class="collapse-icon" *ngIf="!collapsed">
<mat-icon svgIcon="red:arrow-down"></mat-icon>
</div>
<div class="collapse-icon" *ngIf="collapsed">
<mat-icon svgIcon="red:arrow-up"></mat-icon>
</div>
<div (click)="closeDialog()" class="close-icon">
<mat-icon svgIcon="red:close"></mat-icon>
</div>
</div>
<div [hidden]="collapsed">
<div class="upload-list">
<div
*ngFor="let model of uploadService.files"
class="upload-list-item"
>
<div mat-line class="upload-line">
<div
class="upload-file-name"
[matTooltip]="model.file?.name"
>
{{ model.file?.name }}
</div>
<div class="upload-progress" *ngIf="!model.completed && model.progress < 100">
{{ model.progress }}%
</div>
<div class="upload-progress error" *ngIf="model.completed && model.error">
<mat-icon svgIcon="red:error"></mat-icon>
</div>
<div class="upload-progress ok" *ngIf="model.completed && !model.error">
<mat-icon svgIcon="red:check"></mat-icon>
</div>
</div>
<div class="upload-line" *ngIf="model.completed && model.error">
<div
class="upload-file-name error"
[matTooltip]="model.error.message"
>
{{ model.error.message }}
</div>
<div class="upload-progress">
<div
class="error-action"
(click)="uploadItem(model)"
[matTooltip]="'upload-status.dialog.actions.re-upload.label' | translate"
>
<mat-icon svgIcon="red:refresh"></mat-icon>key
</div>
<div
class="error-action"
(click)="cancelItem(model)"
[matTooltip]="'upload-status.dialog.actions.cancel.label' | translate"
>
<mat-icon svgIcon="red:close"></mat-icon>
</div>
</div>
</div>
<div mat-line *ngIf="!model.completed" class="upload-progress">
<mat-progress-bar
mode="determinate"
color="primary"
[value]="model.progress"
*ngIf="model.progress !== 100"
></mat-progress-bar>
</div>
</div>
</div>
</div>
</section>

View File

@ -0,0 +1,91 @@
@import "../../../assets/styles/red-variables";
section {
background: white;
position: fixed;
bottom: 10px;
right: 10px;
border: 2px solid $grey-1;
}
.upload-list {
max-height: 400px;
max-width: 400px;
overflow: auto;
}
.red-upload-header {
display: flex;
flex-direction: row;
position: relative;
padding: 10px;
background: $grey-1;
color: $white;
width: 380px;
cursor: pointer;
mat-icon {
color: $white;
}
}
.collapse-icon {
padding-left: 8px;
mat-icon {
width: 16px;
}
}
.close-icon {
position: absolute;
right: 10px;
color: $white;
}
.upload-list-item {
padding: 8px;
mat-icon {
width: 16px;
height: 16px;
}
.upload-line {
display: flex !important;
height: 20px;
position: relative;
justify-content: flex-end;
.upload-file-name {
text-overflow: ellipsis;
overflow: hidden;
display: block;
white-space: nowrap;
padding-right: 50px;
&.error {
color: $red-1;
padding-right: 60px;
}
}
.upload-progress {
position: absolute;
right: 0;
width: 50px;
display: flex;
justify-content: space-evenly;
&.error {
color: $red-1;
}
&.ok {
color: $blue-1;
}
}
}
}

View File

@ -0,0 +1,39 @@
import {Component, OnInit} from '@angular/core';
import {FileUploadModel} from "../model/file-upload.model";
import {FileUploadService} from "../file-upload.service";
import {OverlayRef} from "@angular/cdk/overlay";
@Component({
selector: 'redaction-upload-status-overlay',
templateUrl: './upload-status-overlay.component.html',
styleUrls: ['./upload-status-overlay.component.scss']
})
export class UploadStatusOverlay implements OnInit {
collapsed: boolean = false;
constructor(public readonly uploadService: FileUploadService, private readonly _overlayRef: OverlayRef) {
}
ngOnInit() {
}
cancelItem(item: FileUploadModel) {
}
uploadItem(item: FileUploadModel) {
item.completed = false;
item.error = null;
}
closeDialog() {
this.uploadService.stopAllUploads();
this._overlayRef.detach();
}
}

View File

@ -0,0 +1,80 @@
import { MatDialogConfig } from '@angular/material/dialog';
import { Overlay, OverlayConfig } from '@angular/cdk/overlay';
export class DialogHelper {
public static _MARGIN = '16px';
public static generateDialogConfig(injectionData?: any | null): MatDialogConfig {
const viewPortWidth = window.innerWidth;
if (viewPortWidth < 600) {
return DialogHelper.generateFullScreenDialogConfig(injectionData);
}
const conf = new MatDialogConfig();
conf.position = { top: '100px' };
conf.maxWidth = '90vw';
conf.maxHeight = '88vh';
if (injectionData) {
conf.data = injectionData;
}
return conf;
}
public static generateMediumDialogConfig(injectionData?: any | null): MatDialogConfig {
const conf = new MatDialogConfig();
conf.width = '60vw';
conf.maxHeight = '88vh';
conf.maxWidth = '90vw';
if (injectionData) {
conf.data = injectionData;
}
return conf;
}
public static generateLargeDialogConfig(injectionData?: any | null): MatDialogConfig {
const conf = new MatDialogConfig();
conf.height = '90vh';
conf.width = '90vw';
conf.maxWidth = '90vw';
if (injectionData) {
conf.data = injectionData;
}
return conf;
}
public static generateFullScreenDialogConfig(injectionData?: any | null): MatDialogConfig {
const conf = new MatDialogConfig();
conf.height = '100vh';
conf.width = '100vw';
conf.maxWidth = '100vw';
if (injectionData) {
conf.data = injectionData;
}
return conf;
}
public static generateFileDropConfig(overlay: Overlay): OverlayConfig {
const config = new OverlayConfig();
config.hasBackdrop = true;
config.backdropClass = 'dark-backdrop';
config.panelClass = 'gin-file-upload-dialog-panel';
config.scrollStrategy = overlay.scrollStrategies.block();
config.positionStrategy = overlay
.position()
.global()
.centerHorizontally()
.centerVertically();
return config;
}
public static generateUploadStatusConfig(overlay: Overlay): OverlayConfig {
const config = new OverlayConfig();
config.hasBackdrop = false;
config.positionStrategy = overlay
.position()
.global()
.bottom(DialogHelper._MARGIN)
.right(DialogHelper._MARGIN);
return config;
}
}

View File

@ -1,5 +1,6 @@
{
"OAUTH_URL": "https://keycloak-dev.iqser.cloud/auth/realms/dev",
"OAUTH_CLIENT_ID": "gin-client",
"API_URL": ""
"API_URL": "",
"PDFTRON_LICENSE": ""
}

View File

@ -1,4 +1,28 @@
{
"upload-status": {
"dialog": {
"title": {
"label": "File Upload"
},
"actions": {
"re-upload": {
"label": "Retry Upload"
},
"cancel": {
"label": "Cancel Upload"
}
}
}
},
"pdf-viewer": {
"text-popup": {
"actions": {
"suggestion-redaction": {
"label": "Suggest Redaction"
}
}
}
},
"common": {
"dialog": {
"close": {

View File

@ -0,0 +1 @@
<svg id="Capa_1" enable-background="new 0 0 512 512" height="512" viewBox="0 0 512 512" width="512" xmlns="http://www.w3.org/2000/svg"><g><path d="m0 0h406.333v90.667h-406.333z"/><path d="m406.333 240.666v-44.999h-406.333v120.667h284.679c22.182-44.793 68.376-75.668 121.654-75.668z"/><path d="m278.347 421.333h-278.347v90.667h406.333c-59.039 0-109.382-37.912-127.986-90.667z"/><path d="m60 113.167c-16.569 0-30 13.431-30 30s13.431 30 30 30h286.333c16.569 0 30-13.431 30-30s-13.431-30-30-30z"/><path d="m275.941 338.833h-215.941c-16.569 0-30 13.431-30 30s13.431 30 30 30h212.542c-1.227-7.321-1.876-14.836-1.876-22.5 0-13.004 1.843-25.585 5.275-37.5z"/><path d="m406.333 270.666c-58.265 0-105.667 47.402-105.667 105.667s47.402 105.667 105.667 105.667 105.667-47.402 105.667-105.667-47.402-105.667-105.667-105.667zm60.334 120.667h-45.167v45.333h-30v-45.333h-45.167v-30h45.167v-45h30v45h45.167z"/></g></svg>

After

Width:  |  Height:  |  Size: 903 B

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="6px" height="4px" viewBox="0 0 6 4" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<defs></defs>
<g id="Artboard" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-156.000000, -921.000000)">
<g id="sorting-score" transform="translate(122.000000, 909.000000)" fill="currentColor">
<path d="M37.0001108,13.1581116 L34.8604385,15.1931756 C34.6640542,15.3799587 34.3452254,15.3793961 34.1482495,15.1920504 C33.9500907,15.0037201 33.9512737,14.7014634 34.147658,14.5146803 L36.6443121,12.1400873 C36.7425042,12.0466958 36.8713075,12 37.0001108,12 C37.1295056,12 37.2577173,12.0466958 37.3559095,12.1400873 L39.8525635,14.5146803 C40.0495394,14.702026 40.0489479,15.0047047 39.851972,15.1920504 C39.6538131,15.3805213 39.3361674,15.3799587 39.1397831,15.1931756 L37.0001108,13.1581116 Z" id="arrow_down" transform="translate(37.000000, 13.666667) scale(1, -1) translate(-37.000000, -13.666667) "></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="6px" height="4px" viewBox="0 0 6 4" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 48.2 (47327) - http://www.bohemiancoding.com/sketch -->
<defs></defs>
<g id="Global-Error-Expanded" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" transform="translate(-323.000000, -409.000000)">
<g id="Group" transform="translate(160.000000, 399.000000)" fill="currentColor">
<path d="M166.000111,11.1581116 L163.860438,13.1931756 C163.664054,13.3799587 163.345225,13.3793961 163.14825,13.1920504 C162.950091,13.0037201 162.951274,12.7014634 163.147658,12.5146803 L165.644312,10.1400873 C165.742504,10.0466958 165.871308,10 166.000111,10 C166.129506,10 166.257717,10.0466958 166.355909,10.1400873 L168.852564,12.5146803 C169.049539,12.702026 169.048948,13.0047047 168.851972,13.1920504 C168.653813,13.3805213 168.336167,13.3799587 168.139783,13.1931756 L166.000111,11.1581116 Z" id="arrow_up"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 49.1 (51147) - http://www.bohemiancoding.com/sketch -->
<defs></defs>
<g id="Upload" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Upload-05" transform="translate(-1388.000000, -675.000000)" fill="currentColor">
<path d="M1398.0001,675 C1393.95533,675 1390.3095,677.43651 1388.76152,681.172741 C1387.2138,684.910305 1388.06899,689.211331 1390.92923,692.07077 C1393.78867,694.93101 1398.08969,695.786201 1401.82726,694.238483 C1405.56349,692.690498 1408,689.044666 1408,684.999904 C1408,679.477024 1403.52298,675 1398.0001,675 Z M1402.8587,682.154871 L1396.49861,688.743106 C1396.30995,688.937483 1396.00579,688.937483 1395.81687,688.743106 L1392.58535,685.39701 C1392.39748,685.201551 1392.39748,684.886433 1392.58535,684.690703 L1392.768,684.50147 C1392.95692,684.306822 1393.26108,684.306822 1393.44974,684.50147 L1396.16388,687.305855 L1401.99405,681.256894 C1402.18297,681.062517 1402.48713,681.062517 1402.67605,681.256894 L1402.8587,681.446397 C1403.04762,681.641857 1403.04658,681.959141 1402.8587,682.154871 Z" id="check_icon"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg width="20px" height="20px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<!-- Generator: Sketch 49.1 (51147) - http://www.bohemiancoding.com/sketch -->
<defs></defs>
<g id="Upload" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Upload-Errors-01" transform="translate(-1388.000000, -622.000000)" fill="currentColor">
<path d="M1405.075,639.075 C1406.88516,637.26484 1408,634.761 1408,632 C1408,629.2398 1406.88516,626.7352 1405.075,624.925 C1403.26484,623.1148 1400.761,622 1398,622 C1395.2398,622 1392.7352,623.11484 1390.925,624.925 C1389.1148,626.73516 1388,629.239 1388,632 C1388,634.7602 1389.11484,637.2648 1390.925,639.075 C1392.73516,640.8852 1395.239,642 1398,642 C1400.7602,642 1403.2648,640.88516 1405.075,639.075 Z M1399.3532,635.8578 C1399.3532,635.10858 1398.75008,634.50468 1398.00008,634.50468 C1397.25086,634.50468 1396.62898,635.1078 1396.62898,635.8578 C1396.62898,636.60702 1397.25086,637.2289 1398.00008,637.2289 C1398.7493,637.2289 1399.3532,636.60702 1399.3532,635.8578 Z M1398.00008,633.1336 C1397.50632,633.1336 1397.1407,632.73126 1397.08602,632.21954 L1396.62898,628.14294 C1396.55554,627.42966 1397.30554,626.77184 1398.00008,626.77184 C1398.69462,626.77184 1399.44462,627.42966 1399.3532,628.14294 L1398.91414,632.21954 C1398.85945,632.73126 1398.49382,633.1336 1398.00008,633.1336 Z" id="error_icon"></path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

@ -1,7 +0,0 @@
<html>
<body>
<script>
parent.postMessage(location.href, location.origin);
</script>
</body>
</html>

View File

@ -0,0 +1,7 @@
<html>
<body>
<script>
(window.opener || window.parent).postMessage(location.hash || ('#' + location.search), location.origin);
</script>
</body>
</html>

View File

@ -5,8 +5,8 @@
$grey-1-palette: (
default: $grey-1,
lighter: lighten($grey-1, 15%),
darker: darken($grey-1, 15%),
lighter: lighten($grey-1, 30%),
darker: darken($grey-1, 30%),
text: $grey-1,
contrast: (
default: $white,
@ -17,8 +17,8 @@ $grey-1-palette: (
$grey-2-palette: (
default: $grey-2,
lighter: lighten($grey-2, 15%),
darker: darken($grey-2, 15%),
lighter: lighten($grey-2, 30%),
darker: darken($grey-2, 30%),
text: $grey-2,
contrast: (
default: $grey-1,
@ -29,8 +29,8 @@ $grey-2-palette: (
$red-palette: (
default: $red-1,
lighter: lighten($red-1, 15%),
darker: darken($red-1, 15%),
lighter: lighten($red-1, 30%),
darker: darken($red-1, 30%),
text: $red-1,
contrast: (
default: $white,

View File

@ -1,14 +1,14 @@
#!/bin/sh
API_CLIENT="${API_CLIENT:-gin-client}"
KEYCLOAK_URL="${KEYCLOAK_URL:-https://keycloak-dev.iqser.cloud/auth}"
KEYCLOAK_REALM="${KEYCLOAK_REALM:-dev}"
OAUTH_CLIENT_ID="${OAUTH_CLIENT_ID:-gin-client}"
OAUTH_URL="${OAUTH_URL:-https://keycloak-dev.iqser.cloud/auth/realms/dev}"
API_URL="${API_URL:-}"
PDFTRON_LICENSE="${API_URL:-}"
echo '{
"API_CLIENT":"'"$API_CLIENT"'",
"KEYCLOAK_URL":"'"$KEYCLOAK_URL"'",
"KEYCLOAK_REALM":"'"$KEYCLOAK_REALM"'",
"OAUTH_CLIENT_ID":"'"$OAUTH_CLIENT_ID"'",
"OAUTH_URL":"'"$OAUTH_URL"'",
"PDFTRON_LICENSE":"'"$PDFTRON_LICENSE"'",
"API_URL":"'"$API_URL"'"
}' > /usr/share/nginx/html/assets/config/config.json

View File

@ -29,7 +29,7 @@
"private": true,
"dependencies": {
"@angular/animations": "^10.0.0",
"@angular/cdk": "^10.2.1",
"@angular/cdk": "^10.2.3",
"@angular/common": "^10.0.0",
"@angular/core": "^10.0.0",
"@angular/forms": "^10.0.0",
@ -45,8 +45,7 @@
"angular-oauth2-oidc": "^10.0.3",
"angular-oauth2-oidc-jwks": "^9.0.0",
"file-saver": "^2.0.2",
"keycloak-angular": "^8.0.1",
"keycloak-js": "10.0.2",
"ng2-file-upload": "^1.4.0",
"ngp-sort-pipe": "^0.0.4",
"ngx-dropzone": "^2.2.2",
"ngx-toastr": "^13.0.0",

View File

@ -182,10 +182,10 @@
dependencies:
tslib "^2.0.0"
"@angular/cdk@^10.2.1":
version "10.2.1"
resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-10.2.1.tgz#7ca0fe7220ca97bdf8e73a40105212749427a88f"
integrity sha512-67nPfteerlGPlwBeKt+EEOgEo2zm3+U6FzwhXVqwEeBxCZ7PWelMDiartHC7zZnzIKkcNEO0Uptq7Bzl2gdU0w==
"@angular/cdk@^10.2.3":
version "10.2.3"
resolved "https://registry.yarnpkg.com/@angular/cdk/-/cdk-10.2.3.tgz#49eb09ae68f91f1ecec388592091a0f8f1dd5dce"
integrity sha512-ne3uSnWLQyUfYQ32zTvDauudyPONRPPBSbdOzFSsvFQuPxUcMQ3mFHJuq2OXei47TfSatmmyuKSuw9EtmTRbQw==
dependencies:
tslib "^2.0.0"
optionalDependencies:
@ -7714,6 +7714,13 @@ ng-packagr@^10.1.2:
stylus "^0.54.7"
terser "^5.0.0"
ng2-file-upload@^1.4.0:
version "1.4.0"
resolved "https://registry.yarnpkg.com/ng2-file-upload/-/ng2-file-upload-1.4.0.tgz#8dea28d573234c52af474ad2a4001b335271e5c4"
integrity sha512-3J/KPU/tyh/ad6TFeUbrxX+SihUj0iOEt2Zsg4EX7mB3GFiQscXOfcUOxCkBtPWWWaqt3azrYbVGzsYa3/7NzQ==
dependencies:
tslib "^1.9.0"
ngp-sort-pipe@^0.0.4:
version "0.0.4"
resolved "https://registry.yarnpkg.com/ngp-sort-pipe/-/ngp-sort-pipe-0.0.4.tgz#9d70caff0ee34f32f2ea1df16c7333b72df72b56"