Upload and OAUTH finished
This commit is contained in:
parent
66c1540d6c
commit
6eed5efedb
@ -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"
|
||||
|
||||
@ -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({
|
||||
|
||||
@ -7,4 +7,5 @@ import {Component} from '@angular/core';
|
||||
})
|
||||
export class AppComponent {
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -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: [ {
|
||||
|
||||
@ -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,
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
@ -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'
|
||||
)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@ -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] : []"
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@ -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>
|
||||
@ -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;
|
||||
}
|
||||
46
apps/red-ui/src/app/upload/file-drop/file-drop.component.ts
Normal file
46
apps/red-ui/src/app/upload/file-drop/file-drop.component.ts
Normal 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();
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
32
apps/red-ui/src/app/upload/file-upload.module.ts
Normal file
32
apps/red-ui/src/app/upload/file-upload.module.ts
Normal 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 {
|
||||
}
|
||||
47
apps/red-ui/src/app/upload/file-upload.service.ts
Normal file
47
apps/red-ui/src/app/upload/file-upload.service.ts
Normal 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() {
|
||||
|
||||
}
|
||||
}
|
||||
8
apps/red-ui/src/app/upload/model/file-upload.model.ts
Normal file
8
apps/red-ui/src/app/upload/model/file-upload.model.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export interface FileUploadModel {
|
||||
|
||||
file: File;
|
||||
progress: number;
|
||||
completed: boolean;
|
||||
error: any;
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -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>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
80
apps/red-ui/src/app/utils/dialog-helper.ts
Normal file
80
apps/red-ui/src/app/utils/dialog-helper.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
@ -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": ""
|
||||
}
|
||||
|
||||
@ -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": {
|
||||
|
||||
1
apps/red-ui/src/assets/icons/general/add.svg
Normal file
1
apps/red-ui/src/assets/icons/general/add.svg
Normal 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 |
10
apps/red-ui/src/assets/icons/general/arrow_down.svg
Executable file
10
apps/red-ui/src/assets/icons/general/arrow_down.svg
Executable 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 |
10
apps/red-ui/src/assets/icons/general/arrow_up.svg
Normal file
10
apps/red-ui/src/assets/icons/general/arrow_up.svg
Normal 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 |
10
apps/red-ui/src/assets/icons/general/check_icon.svg
Executable file
10
apps/red-ui/src/assets/icons/general/check_icon.svg
Executable 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 |
10
apps/red-ui/src/assets/icons/general/error_icon.svg
Executable file
10
apps/red-ui/src/assets/icons/general/error_icon.svg
Executable 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 |
@ -1,7 +0,0 @@
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
parent.postMessage(location.href, location.origin);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
7
apps/red-ui/src/assets/oauth/silent-refresh.html
Normal file
7
apps/red-ui/src/assets/oauth/silent-refresh.html
Normal file
@ -0,0 +1,7 @@
|
||||
<html>
|
||||
<body>
|
||||
<script>
|
||||
(window.opener || window.parent).postMessage(location.hash || ('#' + location.search), location.origin);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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",
|
||||
|
||||
15
yarn.lock
15
yarn.lock
@ -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"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user