min word length fixed to 2

This commit is contained in:
Timo 2020-12-02 19:22:16 +02:00
parent e0c26c14ba
commit 962b1d39af
10 changed files with 158 additions and 58 deletions

View File

@ -17,6 +17,8 @@ declare var ace;
styleUrls: ['./dictionary-overview-screen.component.scss'] styleUrls: ['./dictionary-overview-screen.component.scss']
}) })
export class DictionaryOverviewScreenComponent { export class DictionaryOverviewScreenComponent {
static readonly MIN_WORD_LENGTH: number = 2;
@ViewChild('editorComponent') @ViewChild('editorComponent')
editorComponent: AceEditorComponent; editorComponent: AceEditorComponent;
@ -136,12 +138,12 @@ export class DictionaryOverviewScreenComponent {
const Range = ace.acequire('ace/range').Range; const Range = ace.acequire('ace/range').Range;
for (const i of this.changedLines) { for (const i of this.changedLines) {
let entry = this.currentDictionaryEntries[i]; const entry = this.currentDictionaryEntries[i];
if (entry?.trim().length > 0) { if (entry?.trim().length > 0) {
// only mark non-empty lines // only mark non-empty lines
this.activeEditMarkers.push(this.editorComponent.getEditor().getSession().addMarker(new Range(i, 0, i, 1), 'changed-row-marker', 'fullLine')); this.activeEditMarkers.push(this.editorComponent.getEditor().getSession().addMarker(new Range(i, 0, i, 1), 'changed-row-marker', 'fullLine'));
} }
if (entry?.trim().length > 0 && entry.trim().length < 3) { if (entry?.trim().length > 0 && entry.trim().length < DictionaryOverviewScreenComponent.MIN_WORD_LENGTH) {
// show lines that are to short // show lines that are to short
this.activeEditMarkers.push(this.editorComponent.getEditor().getSession().addMarker(new Range(i, 0, i, 1), 'to-short-marker', 'fullLine')); this.activeEditMarkers.push(this.editorComponent.getEditor().getSession().addMarker(new Range(i, 0, i, 1), 'to-short-marker', 'fullLine'));
} }
@ -167,15 +169,21 @@ export class DictionaryOverviewScreenComponent {
}); });
// remove empty lines // remove empty lines
entriesToAdd = entriesToAdd.filter((e) => e && e.trim().length > 0); entriesToAdd = entriesToAdd.filter((e) => e && e.trim().length > 0).map((e) => e.trim());
if (entriesToAdd.length > 0) { const invalidRowsExist = entriesToAdd.filter((e) => e.length < DictionaryOverviewScreenComponent.MIN_WORD_LENGTH);
await this._dictionaryControllerService.addEntry(entriesToAdd, this.dictionary.type).toPromise();
if (invalidRowsExist.length === 0) {
if (entriesToAdd.length > 0) {
await this._dictionaryControllerService.addEntry(entriesToAdd, this.dictionary.type).toPromise();
}
if (entriesToDelete.length > 0) {
await this._dictionaryControllerService.deleteEntries(entriesToDelete, this.dictionary.type).toPromise();
}
this._initialize();
} else {
console.log('Invalid ROW', invalidRowsExist);
} }
if (entriesToDelete.length > 0) {
await this._dictionaryControllerService.deleteEntries(entriesToDelete, this.dictionary.type).toPromise();
}
this._initialize();
// .ace_marker-layer .search-marker // .ace_marker-layer .search-marker
} }

View File

@ -1,4 +1,4 @@
import { ChangeDetectorRef, Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { ChangeDetectorRef, Component, HostListener, OnDestroy, OnInit, ViewChild } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router'; import { ActivatedRoute, Router } from '@angular/router';
import { NotificationService, NotificationType } from '../../notification/notification.service'; import { NotificationService, NotificationType } from '../../notification/notification.service';
import { AppStateService } from '../../state/app-state.service'; import { AppStateService } from '../../state/app-state.service';
@ -38,6 +38,7 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
public needsWorkFilters: FilterModel[]; public needsWorkFilters: FilterModel[];
public collapsedDetails = false; public collapsedDetails = false;
public searchForm: FormGroup; public searchForm: FormGroup;
showFileDrop: boolean;
displayedFiles: FileStatusWrapper[] = []; displayedFiles: FileStatusWrapper[] = [];
@ -188,12 +189,14 @@ export class ProjectOverviewScreenComponent implements OnInit, OnDestroy {
file: file, file: file,
progress: 0, progress: 0,
completed: false, completed: false,
error: null error: null,
retryCount: 0
}); });
} }
this._fileUploadService.uploadFiles(uploadFiles); this._fileUploadService.uploadFiles(uploadFiles);
this._uploadStatusOverlayService.openStatusOverlay(); this._uploadStatusOverlayService.openStatusOverlay();
this._changeDetectorRef.detectChanges();
} }
private _computeAllFilters() { private _computeAllFilters() {

View File

@ -1,4 +1,4 @@
<section> <section (mouseout)="close()">
<ngx-dropzone (change)="handleFileInput($event.addedFiles)" class="file-drop-zone"> <ngx-dropzone (change)="handleFileInput($event.addedFiles)" class="file-drop-zone">
<ngx-dropzone-label>{{ 'project-overview.upload-files' | translate }}</ngx-dropzone-label> <ngx-dropzone-label>{{ 'project-overview.upload-files' | translate }}</ngx-dropzone-label>
</ngx-dropzone> </ngx-dropzone>

View File

@ -1,4 +1,4 @@
import { Component, HostListener, OnInit } from '@angular/core'; import { ChangeDetectorRef, Component, HostListener, OnInit } from '@angular/core';
import { FileUploadService } from '../file-upload.service'; import { FileUploadService } from '../file-upload.service';
import { FileUploadModel } from '../model/file-upload.model'; import { FileUploadModel } from '../model/file-upload.model';
import { OverlayRef } from '@angular/cdk/overlay'; import { OverlayRef } from '@angular/cdk/overlay';
@ -13,7 +13,8 @@ export class FileDropComponent implements OnInit {
constructor( constructor(
private readonly _dialogRef: OverlayRef, private readonly _dialogRef: OverlayRef,
private readonly _fileUploadService: FileUploadService, private readonly _fileUploadService: FileUploadService,
private _uploadStatusOverlayService: UploadStatusOverlayService private readonly _changeDetectorRef: ChangeDetectorRef,
private readonly _uploadStatusOverlayService: UploadStatusOverlayService
) {} ) {}
ngOnInit() {} ngOnInit() {}
@ -35,12 +36,14 @@ export class FileDropComponent implements OnInit {
file: file, file: file,
progress: 0, progress: 0,
completed: false, completed: false,
error: null error: null,
retryCount: 0
}); });
} }
this._fileUploadService.uploadFiles(uploadFiles); this._fileUploadService.uploadFiles(uploadFiles);
this._uploadStatusOverlayService.openStatusOverlay(); this._uploadStatusOverlayService.openStatusOverlay();
this._dialogRef.detach(); this._dialogRef.detach();
this._changeDetectorRef.detectChanges();
} }
} }

View File

@ -1,13 +1,13 @@
import { Injectable, Injector } from '@angular/core'; import { Injectable, Injector } from '@angular/core';
import { Overlay } from '@angular/cdk/overlay'; import { Overlay, OverlayRef } from '@angular/cdk/overlay';
import { FileDropComponent } from '../file-drop.component'; import { FileDropComponent } from '../file-drop.component';
import { ComponentPortal } from '@angular/cdk/portal'; import { ComponentPortal } from '@angular/cdk/portal';
import { OverlayRef } from '@angular/cdk/overlay';
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class FileDropOverlayService { export class FileDropOverlayService {
private _mouseIn: boolean = false;
private readonly _dropOverlayRef: OverlayRef; private readonly _dropOverlayRef: OverlayRef;
constructor(private overlay: Overlay, private readonly _injector: Injector) { constructor(private overlay: Overlay, private readonly _injector: Injector) {
@ -17,29 +17,40 @@ export class FileDropOverlayService {
}); });
} }
dragListener = () => { dragListener = (e) => {
this.openFileDropOverlay(); e.preventDefault();
e.stopPropagation();
if (this._mouseIn) {
this.openFileDropOverlay();
}
return false;
};
mouseIn = (e) => {
e.preventDefault();
e.stopPropagation();
this._mouseIn = true;
return false;
}; };
mouseOut = (e) => { mouseOut = (e) => {
e.preventDefault();
e.stopPropagation();
if (e.toElement == null && e.relatedTarget == null) { if (e.toElement == null && e.relatedTarget == null) {
this._mouseIn = false;
this.closeFileDropOverlay(); this.closeFileDropOverlay();
} }
return false;
}; };
initFileDropHandling() { initFileDropHandling() {
document document.getElementsByTagName('body')[0].addEventListener('dragenter', this.dragListener, false);
.getElementsByTagName('body')[0] document.getElementsByTagName('body')[0].addEventListener('mouseenter', this.mouseIn, false);
.addEventListener('dragenter', this.dragListener, false);
document.getElementsByTagName('body')[0].addEventListener('mouseout', this.mouseOut, false); document.getElementsByTagName('body')[0].addEventListener('mouseout', this.mouseOut, false);
} }
cleanupFileDropHandling() { cleanupFileDropHandling() {
document document.getElementsByTagName('body')[0].removeEventListener('dragenter', this.dragListener, false);
.getElementsByTagName('body')[0] document.getElementsByTagName('body')[0].removeEventListener('mouseenter', this.mouseIn, false);
.removeEventListener('dragenter', this.dragListener, false); document.getElementsByTagName('body')[0].removeEventListener('mouseout', this.mouseOut, false);
document
.getElementsByTagName('body')[0]
.removeEventListener('mouseout', this.mouseOut, false);
} }
private _createInjector() { private _createInjector() {

View File

@ -3,43 +3,108 @@ import { FileUploadModel } from './model/file-upload.model';
import { AppStateService } from '../state/app-state.service'; import { AppStateService } from '../state/app-state.service';
import { HttpEventType } from '@angular/common/http'; import { HttpEventType } from '@angular/common/http';
import { FileManagementControllerService } from '@redaction/red-ui-http'; import { FileManagementControllerService } from '@redaction/red-ui-http';
import { interval, Subscription } from 'rxjs';
export interface UploadFile {
fileUploadModel: FileUploadModel;
}
@Injectable({ @Injectable({
providedIn: 'root' providedIn: 'root'
}) })
export class FileUploadService { export class FileUploadService {
static readonly MAX_PARALLEL_UPLOADS = 5;
files: FileUploadModel[] = []; files: FileUploadModel[] = [];
constructor(private readonly _appStateService: AppStateService, private readonly _fileManagementControllerService: FileManagementControllerService) {} activeUploads: number = 0;
private _pendingUploads: UploadFile[] = [];
private _activeUploads: Subscription[] = [];
constructor(private readonly _appStateService: AppStateService, private readonly _fileManagementControllerService: FileManagementControllerService) {
interval(2500).subscribe((val) => {
this._handleUploads();
});
}
scheduleUpload(item: FileUploadModel) {
this._pendingUploads.push({
fileUploadModel: item
});
}
uploadFiles(files: FileUploadModel[]) { uploadFiles(files: FileUploadModel[]) {
this.files.push(...files); this.files.push(...files);
files.forEach((newFile) => { files.forEach((newFile) => {
this._fileManagementControllerService.uploadFileForm(newFile.file, this._appStateService.activeProject.project.projectId, 'events', true).subscribe( this.scheduleUpload(newFile);
async (event) => {
if (event.type === HttpEventType.UploadProgress) {
newFile.progress = Math.round((event.loaded / (event.total || event.loaded)) * 100);
}
if (event.type === HttpEventType.Response) {
if (event.status < 300) {
newFile.progress = 100;
newFile.completed = true;
} else {
newFile.completed = true;
newFile.error = event.body;
}
await this._appStateService.reloadActiveProjectFiles();
}
},
(error) => {
newFile.completed = true;
newFile.error = error;
}
);
}); });
} }
stopAllUploads() { stopAllUploads() {
this.files = []; this.files = [];
} }
private _handleUploads() {
if (this._activeUploads.length < FileUploadService.MAX_PARALLEL_UPLOADS && this._pendingUploads.length > 0) {
let cnt = FileUploadService.MAX_PARALLEL_UPLOADS - this._activeUploads.length;
while (cnt > 0) {
cnt--;
const popped = this._pendingUploads.pop();
if (popped) {
const sub = this._createSubscription(popped);
this._activeUploads.push(sub);
} else {
return;
}
}
}
}
private _createSubscription(uploadFile: UploadFile) {
this.activeUploads++;
const obs = this._fileManagementControllerService.uploadFileForm(
uploadFile.fileUploadModel.file,
this._appStateService.activeProject.project.projectId,
'events',
true
);
const subscription = obs.subscribe(
async (event) => {
if (event.type === HttpEventType.UploadProgress) {
uploadFile.fileUploadModel.progress = Math.round((event.loaded / (event.total || event.loaded)) * 100);
}
if (event.type === HttpEventType.Response) {
if (event.status < 300) {
uploadFile.fileUploadModel.progress = 100;
uploadFile.fileUploadModel.completed = true;
} else {
uploadFile.fileUploadModel.completed = true;
uploadFile.fileUploadModel.error = event.body;
}
this._removeUpload(subscription);
await this._appStateService.reloadActiveProjectFiles();
}
},
(error) => {
uploadFile.fileUploadModel.completed = true;
uploadFile.fileUploadModel.error = error;
this._removeUpload(subscription);
}
);
return subscription;
}
private _removeUpload(subscription: Subscription) {
const index = this._activeUploads.indexOf(subscription);
if (index > -1) {
this._activeUploads.splice(index, 1);
this.activeUploads--;
}
}
removeFile(item: FileUploadModel) {
const index = this.files.indexOf(item);
if (index > -1) {
this.files.splice(index, 1);
}
}
} }

View File

@ -3,4 +3,5 @@ export interface FileUploadModel {
progress: number; progress: number;
completed: boolean; completed: boolean;
error: any; error: any;
retryCount: number;
} }

View File

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core'; import { ChangeDetectorRef, Component, OnInit } from '@angular/core';
import { FileUploadModel } from '../model/file-upload.model'; import { FileUploadModel } from '../model/file-upload.model';
import { FileUploadService } from '../file-upload.service'; import { FileUploadService } from '../file-upload.service';
import { OverlayRef } from '@angular/cdk/overlay'; import { OverlayRef } from '@angular/cdk/overlay';
@ -13,7 +13,11 @@ export class UploadStatusOverlay implements OnInit {
uploadStatusInterval: number; uploadStatusInterval: number;
constructor(public readonly uploadService: FileUploadService, private readonly _overlayRef: OverlayRef) {} constructor(
public readonly uploadService: FileUploadService,
private readonly _overlayRef: OverlayRef,
private readonly _changeDetectorRef: ChangeDetectorRef
) {}
ngOnInit() { ngOnInit() {
this.uploadStatusInterval = setInterval(() => { this.uploadStatusInterval = setInterval(() => {
@ -27,11 +31,16 @@ export class UploadStatusOverlay implements OnInit {
}, 2500); }, 2500);
} }
cancelItem(item: FileUploadModel) {} cancelItem(item: FileUploadModel) {
this.uploadService.removeFile(item);
}
uploadItem(item: FileUploadModel) { uploadItem(item: FileUploadModel) {
item.progress = 0;
item.completed = false; item.completed = false;
item.error = null; item.error = null;
this._changeDetectorRef.detectChanges();
this.uploadService.scheduleUpload(item);
} }
closeDialog() { closeDialog() {

View File

@ -1,5 +1,5 @@
{ {
"OAUTH_URL": "https://redkc-staging.iqser.cloud/auth/realms/redaction", "OAUTH_URL": "https://redkc-staging.iqser.cloud/auth/realms/redaction",
"OAUTH_CLIENT_ID": "redaction", "OAUTH_CLIENT_ID": "redaction",
"API_URL": "https://timo-redaction-dev.iqser.cloud" "API_URL": "https://redapi-staging.iqser.cloud"
} }

View File

@ -8476,10 +8476,10 @@ ngx-color-picker@^10.1.0:
dependencies: dependencies:
tslib "^2.0.0" tslib "^2.0.0"
ngx-dropzone@^2.2.2: ngx-dropzone@^2.3.0:
version "2.2.2" version "2.3.0"
resolved "https://registry.yarnpkg.com/ngx-dropzone/-/ngx-dropzone-2.2.2.tgz#450609031efb909461181c6b693d7c5f793a278d" resolved "https://registry.yarnpkg.com/ngx-dropzone/-/ngx-dropzone-2.3.0.tgz#fb34bceb0d8ad3c00c314b957d095018d15c5fe9"
integrity sha512-REuBcPNTY33OtcZD6dw8Fq/jFqwviiYydYaCn74yig8TvDDYhtJ/BPjtvbw7uEgF4BJr/UEHbKMvkdZIyCgsww== integrity sha512-Mhsu6MW1yJRxLPRPbwal7y18trokU9josTD8GDb8wFRmaCd/N+dJeMDXn0XsxtDhlZ7vWqbpEr9k0ej4Na3v8Q==
dependencies: dependencies:
tslib "^1.9.0" tslib "^1.9.0"