diff --git a/interactive-mining-angular-frontend/ng-package.json b/interactive-mining-angular-frontend/ng-package.json
index 18dc203..5bba2de 100755
--- a/interactive-mining-angular-frontend/ng-package.json
+++ b/interactive-mining-angular-frontend/ng-package.json
@@ -1,6 +1,4 @@
{
"$schema": "./node_modules/ng-packagr/ng-package.schema.json",
- "whitelistedNonPeerDependencies": [
- "."
- ]
+ "allowedNonPeerDependencies": ["."]
}
diff --git a/interactive-mining-angular-frontend/package.json b/interactive-mining-angular-frontend/package.json
index 9c0b890..2965777 100755
--- a/interactive-mining-angular-frontend/package.json
+++ b/interactive-mining-angular-frontend/package.json
@@ -25,7 +25,6 @@
"core-js": "^2.4.1",
"file-saver": "^2.0.2",
"jquery": "^3.4.1",
- "ng2-nouislider": "^1.8.2",
"ngx-pagination": "^3.2.1",
"nouislider": "^13.1.5",
"rxjs": "^6.5.1",
@@ -56,4 +55,4 @@
"ts-node": "~8.2.0",
"typescript": "~4.6.4"
}
-}
\ No newline at end of file
+}
diff --git a/interactive-mining-angular-frontend/src/app/configuration/configuration.module.ts b/interactive-mining-angular-frontend/src/app/configuration/configuration.module.ts
index e2f1444..f3ad894 100755
--- a/interactive-mining-angular-frontend/src/app/configuration/configuration.module.ts
+++ b/interactive-mining-angular-frontend/src/app/configuration/configuration.module.ts
@@ -6,7 +6,7 @@ import { SettingsComponent } from './settings/settings.component';
import { ResultspreviewComponent } from './resultspreview/resultspreview.component';
import {ConfigurationService} from './configuration.service';
import {StepsnavbarModule} from '../stepsnvabar/stepsnavbar.module';
-import { NouisliderModule } from 'ng2-nouislider';
+import {NouisliderModule} from '../ng2-nouislider/ng2-nouislider.module';
@NgModule({
imports: [
diff --git a/interactive-mining-angular-frontend/src/app/configuration/settings/settings.component.html b/interactive-mining-angular-frontend/src/app/configuration/settings/settings.component.html
index cc660e1..e0403b6 100755
--- a/interactive-mining-angular-frontend/src/app/configuration/settings/settings.component.html
+++ b/interactive-mining-angular-frontend/src/app/configuration/settings/settings.component.html
@@ -7,7 +7,7 @@
High
recall
-
+
High
precision
@@ -121,19 +121,19 @@
Select among the following text preprocessing steps.
@@ -173,13 +173,13 @@
diff --git a/interactive-mining-angular-frontend/src/app/configuration/settings/settings.component.ts b/interactive-mining-angular-frontend/src/app/configuration/settings/settings.component.ts
index e3f9a2e..922ce41 100755
--- a/interactive-mining-angular-frontend/src/app/configuration/settings/settings.component.ts
+++ b/interactive-mining-angular-frontend/src/app/configuration/settings/settings.component.ts
@@ -191,45 +191,47 @@ export class SettingsComponent implements OnInit {
}
}
- contextprevChange(value): void {
+ contextprevChange(eventTarget: EventTarget): void {
+ let value = +(eventTarget as HTMLInputElement).value;
if (value < 0 || value > 20) {
return;
}
- localStorage.setItem('contextprev', value);
+ localStorage.setItem('contextprev', value.toString());
this.getSettingsFromLocalStorage();
}
- contextnextChange(value): void {
+ contextnextChange(eventTarget: EventTarget): void {
+ let value = +(eventTarget as HTMLInputElement).value;
if (value < 0 || value > 20) {
return;
}
- localStorage.setItem('contextnext', value);
+ localStorage.setItem('contextnext', value.toString());
this.getSettingsFromLocalStorage();
}
- stopwordsCheckBoxChange(value: boolean): void {
- localStorage.setItem('stopwords', value ? '1' : '0');
- this.settings.stopwords = value ? 1 : 0;
+ stopwordsCheckBoxChange(eventTarget: EventTarget): void {
+ localStorage.setItem('stopwords', (eventTarget as HTMLInputElement).checked ? '1' : '0');
+ this.settings.stopwords = (eventTarget as HTMLInputElement).checked ? 1 : 0;
}
- punctuationCheckBoxChange(value: boolean): void {
- localStorage.setItem('punctuation', value ? '1' : '0');
- this.settings.punctuation = value ? 1 : 0;
+ punctuationCheckBoxChange(eventTarget: EventTarget): void {
+ localStorage.setItem('punctuation', (eventTarget as HTMLInputElement).checked ? '1' : '0');
+ this.settings.punctuation = (eventTarget as HTMLInputElement).checked ? 1 : 0;
}
- allLowercaseCheckBoxChange(value: boolean): void {
- localStorage.setItem('allLowercase', value ? '1' : '0');
- this.settings.allLowercase = value ? 1 : 0;
+ allLowercaseCheckBoxChange(eventTarget: EventTarget): void {
+ localStorage.setItem('allLowercase', (eventTarget as HTMLInputElement).checked ? '1' : '0');
+ this.settings.allLowercase = (eventTarget as HTMLInputElement).checked ? 1 : 0;
}
- lowercaseCheckBoxChange(value: boolean): void {
- localStorage.setItem('lowercase', value ? '1' : '0');
- this.settings.lowercase = value ? 1 : 0;
+ lowercaseCheckBoxChange(eventTarget: EventTarget): void {
+ localStorage.setItem('lowercase', (eventTarget as HTMLInputElement).checked ? '1' : '0');
+ this.settings.lowercase = (eventTarget as HTMLInputElement).checked ? 1 : 0;
}
- stemmingCheckBoxChange(value: boolean): void {
- localStorage.setItem('stemming', value ? '1' : '0');
- this.settings.stemming = value ? 1 : 0;
+ stemmingCheckBoxChange(eventTarget: EventTarget): void {
+ localStorage.setItem('stemming', (eventTarget as HTMLInputElement).checked ? '1' : '0');
+ this.settings.stemming = (eventTarget as HTMLInputElement).checked ? 1 : 0;
}
documentAreaChange(value: string): void {
diff --git a/interactive-mining-angular-frontend/src/app/contents/contents.component.html b/interactive-mining-angular-frontend/src/app/contents/contents.component.html
index e8d9aa5..d8ba1cf 100755
--- a/interactive-mining-angular-frontend/src/app/contents/contents.component.html
+++ b/interactive-mining-angular-frontend/src/app/contents/contents.component.html
@@ -59,7 +59,7 @@
-
+
diff --git a/interactive-mining-angular-frontend/src/app/contents/contents.component.ts b/interactive-mining-angular-frontend/src/app/contents/contents.component.ts
index 875cdb1..1b14129 100755
--- a/interactive-mining-angular-frontend/src/app/contents/contents.component.ts
+++ b/interactive-mining-angular-frontend/src/app/contents/contents.component.ts
@@ -87,7 +87,8 @@ export class ContentComponent implements OnInit {
});
}
- onFilesChange(file: File) {
+ onFilesChange(event: File | EventTarget) {
+ let file = (event instanceof File)?event:(event).files[0];
if (file !== null && file !== undefined) {
const ext = file.name.split('.')[file.name.split('.').length - 1];
const allowedExtensions = ['tsv', 'txt'];
diff --git a/interactive-mining-angular-frontend/src/app/ng2-nouislider/ng2-nouislider.component.ts b/interactive-mining-angular-frontend/src/app/ng2-nouislider/ng2-nouislider.component.ts
new file mode 100644
index 0000000..eac9e64
--- /dev/null
+++ b/interactive-mining-angular-frontend/src/app/ng2-nouislider/ng2-nouislider.component.ts
@@ -0,0 +1,304 @@
+import * as noUiSlider from 'nouislider';
+import {
+ Component,
+ ElementRef,
+ EventEmitter,
+ forwardRef,
+ Input,
+ OnInit,
+ OnChanges,
+ Output,
+ Renderer2,
+ NgZone,
+ OnDestroy
+} from '@angular/core';
+import {
+ ControlValueAccessor,
+ FormControl,
+ NG_VALUE_ACCESSOR
+} from '@angular/forms';
+
+export interface NouiFormatter {
+ to(value: number): string;
+ from(value: string): number;
+}
+
+export class DefaultFormatter implements NouiFormatter {
+ to(value: number): string {
+ // formatting with http://stackoverflow.com/a/26463364/478584
+ return String(parseFloat(parseFloat(String(value)).toFixed(2)));
+ };
+
+ from(value: string): number {
+ return parseFloat(value);
+ }
+}
+
+@Component({
+ selector: 'nouislider',
+ host: {
+ '[class.ng2-nouislider]': 'true'
+ },
+ template: '',
+ styles: [`
+ :host {
+ display: block;
+ margin-top: 1rem;
+ margin-bottom: 1rem;
+ }
+ `],
+ providers: [
+ {
+ provide: NG_VALUE_ACCESSOR,
+ useExisting: forwardRef(() => NouisliderComponent),
+ multi: true
+ }
+ ]
+})
+export class NouisliderComponent implements ControlValueAccessor, OnInit, OnChanges, OnDestroy {
+
+ public slider: any;
+ public handles: any[];
+ @Input() public disabled: boolean; // tslint:disable-line
+ @Input() public behaviour: string;
+ @Input() public connect: boolean[];
+ @Input() public limit: number;
+ @Input() public min: number;
+ @Input() public max: number;
+ @Input() public snap: boolean;
+ @Input() public animate: boolean | boolean[];
+ @Input() public range: any;
+ @Input() public step: number;
+ @Input() public format: NouiFormatter;
+ @Input() public pageSteps: number;
+ @Input() public config: any = {};
+ @Input() public ngModel: number | number[];
+ @Input() public keyboard: boolean;
+ @Input() public onKeydown: any;
+ @Input() public formControl: FormControl;
+ @Input() public tooltips: Array;
+ @Output() public change: EventEmitter = new EventEmitter(true);
+ @Output() public update: EventEmitter = new EventEmitter(true);
+ @Output() public slide: EventEmitter = new EventEmitter(true);
+ @Output() public set: EventEmitter = new EventEmitter(true);
+ @Output() public start: EventEmitter = new EventEmitter(true);
+ @Output() public end: EventEmitter = new EventEmitter(true);
+ private value: any;
+ private onChange: any = Function.prototype;
+ private cleanups: VoidFunction[] = [];
+
+ constructor(private ngZone: NgZone, private el: ElementRef, private renderer : Renderer2) { }
+
+ ngOnInit(): void {
+ let inputsConfig = JSON.parse(
+ JSON.stringify({
+ behaviour: this.behaviour,
+ connect: this.connect,
+ limit: this.limit,
+ start: this.formControl !== undefined ? this.formControl.value : this.ngModel,
+ step: this.step,
+ pageSteps: this.pageSteps,
+ keyboard: this.keyboard,
+ onKeydown: this.onKeydown,
+ range: this.range || this.config.range || { min: this.min, max: this.max },
+ tooltips: this.tooltips,
+ snap: this.snap,
+ animate: this.animate,
+ }),
+ );
+ inputsConfig.tooltips = this.tooltips || this.config.tooltips;
+ inputsConfig.format = this.format || this.config.format || new DefaultFormatter();
+
+ this.ngZone.runOutsideAngular(() => {
+ this.slider = noUiSlider.create(
+ this.el.nativeElement.querySelector('div'),
+ Object.assign(this.config, inputsConfig)
+ );
+ });
+
+ this.handles = [].slice.call(this.el.nativeElement.querySelectorAll('.noUi-handle'));
+
+ if (this.config.keyboard) {
+ if (this.config.pageSteps === undefined) {
+ this.config.pageSteps = 10;
+ }
+
+ for (const handle of this.handles) {
+ handle.setAttribute('tabindex', 0);
+
+ const onKeydown = this.config.onKeydown || this.defaultKeyHandler;
+
+ this.ngZone.runOutsideAngular(() => {
+ this.cleanups.push(
+ this.renderer.listen(handle, 'keydown', onKeydown),
+ this.renderer.listen(handle, 'click', () => {
+ handle.focus();
+ }),
+ );
+ });
+ }
+ }
+
+ this.slider.on('set', (values: string[], handle: number, unencoded: number[]) => {
+ this.eventHandler(this.set, values, handle, unencoded);
+ });
+
+ this.slider.on('update', (values: string[], handle: number, unencoded: number[]) => {
+ if (this.update.observers.length > 0) {
+ this.ngZone.run(() => {
+ this.update.emit(this.toValues(values));
+ });
+ }
+ });
+
+ this.slider.on('change', (values: string[], handle: number, unencoded: number[]) => {
+ if (this.change.observers.length > 0) {
+ this.ngZone.run(() => {
+ this.change.emit(this.toValues(values));
+ });
+ }
+ });
+
+ this.slider.on('slide', (values: string[], handle: number, unencoded: number[]) => {
+ this.eventHandler(this.slide, values, handle, unencoded);
+ });
+
+ this.slider.on('start', (values: string[], handle: number, unencoded: number[]) => {
+ if (this.start.observers.length > 0) {
+ this.ngZone.run(() => {
+ this.start.emit(this.toValues(values));
+ });
+ }
+ });
+
+ this.slider.on('end', (values: string[], handle: number, unencoded: number[]) => {
+ if (this.end.observers.length > 0) {
+ this.ngZone.run(() => {
+ this.end.emit(this.toValues(values));
+ });
+ }
+ });
+ }
+
+ ngOnChanges(changes: any) {
+ if (this.slider && (changes.min || changes.max || changes.step || changes.range)) {
+ this.ngZone.runOutsideAngular(() => {
+ setTimeout(() => {
+ this.slider.updateOptions({
+ range: Object.assign({}, {
+ min: this.min,
+ max: this.max
+ }, this.range || {}),
+ step: this.step
+ });
+ });
+ });
+ }
+ }
+
+ ngOnDestroy(): void {
+ this.slider.destroy();
+
+ while (this.cleanups.length) {
+ this.cleanups.pop()();
+ }
+ }
+
+ toValues(values: string[]): any | any[] {
+ let v = values.map(this.config.format.from);
+ return (v.length == 1 ? v[0] : v);
+ }
+
+ writeValue(value: any): void {
+ if (this.slider) {
+ this.ngZone.runOutsideAngular(() => {
+ setTimeout(() => {
+ this.slider.set(value);
+ });
+ });
+ }
+ }
+
+ registerOnChange(fn: (value: any) => void) {
+ this.onChange = fn;
+ }
+
+ registerOnTouched(fn: () => {}): void {}
+
+ setDisabledState(isDisabled: boolean): void {
+ isDisabled
+ ? this.renderer.setAttribute(this.el.nativeElement.childNodes[0], 'disabled', 'true')
+ : this.renderer.removeAttribute(this.el.nativeElement.childNodes[0], 'disabled');
+ }
+
+ private eventHandler = (emitter: EventEmitter, values: string[], handle: number, unencoded: number[]) => {
+ let v = this.toValues(values);
+ let emitEvents = false;
+ if(this.value === undefined) {
+ this.value = v;
+ return;
+ }
+ if(Array.isArray(v) && this.value[handle] != v[handle]) {
+ emitEvents = true;
+ }
+ if(!Array.isArray(v) && this.value != v) {
+ emitEvents = true;
+ }
+ if(emitEvents) {
+ this.ngZone.run(() => {
+ if (emitter.observers.length > 0) {
+ emitter.emit(v);
+ }
+ this.onChange(v);
+ });
+ }
+ if(Array.isArray(v)) {
+ this.value[handle] = v[handle];
+ } else {
+ this.value = v;
+ }
+ }
+
+ private defaultKeyHandler = (e: KeyboardEvent) => {
+ let stepSize: any[] = this.slider.steps();
+ let index = parseInt((e.target).getAttribute('data-handle'));
+ let sign = 1;
+ let multiplier: number = 1;
+ let step = 0;
+ let delta = 0;
+
+ switch ( e.which ) {
+ case 34: // PageDown
+ multiplier = this.config.pageSteps;
+ case 40: // ArrowDown
+ case 37: // ArrowLeft
+ sign = -1;
+ step = stepSize[index][0];
+ e.preventDefault();
+ break;
+
+ case 33: // PageUp
+ multiplier = this.config.pageSteps;
+ case 38: // ArrowUp
+ case 39: // ArrowRight
+ step = stepSize[index][1];
+ e.preventDefault();
+ break;
+
+ default:
+ break;
+ }
+
+ delta = sign * multiplier * step;
+ let newValue: number | number[];
+
+ if(Array.isArray(this.value)) {
+ newValue = [].concat(this.value);
+ newValue[index] = newValue[index] + delta;
+ } else {
+ newValue = this.value + delta;
+ }
+
+ this.slider.set(newValue);
+ }
+}
diff --git a/interactive-mining-angular-frontend/src/app/ng2-nouislider/ng2-nouislider.module.ts b/interactive-mining-angular-frontend/src/app/ng2-nouislider/ng2-nouislider.module.ts
new file mode 100644
index 0000000..f428077
--- /dev/null
+++ b/interactive-mining-angular-frontend/src/app/ng2-nouislider/ng2-nouislider.module.ts
@@ -0,0 +1,8 @@
+import {NgModule} from "@angular/core";
+import {NouisliderComponent} from "./ng2-nouislider.component";
+
+@NgModule({
+ exports: [NouisliderComponent],
+ declarations: [NouisliderComponent],
+})
+export class NouisliderModule { }