Commit 3c7546b5 authored by Gert Paimla's avatar Gert Paimla

article analyzer highlight text, dashboard real data

parent abeb5032
......@@ -26,11 +26,12 @@ import {DashboardComponent} from './dashboard/dashboard.component';
import {NzSpaceModule} from 'ng-zorro-antd/space';
import {NzMenuModule, NzProgressModule} from 'ng-zorro-antd';
import {BarChartModule} from '@swimlane/ngx-charts';
import {NzSwitchModule} from 'ng-zorro-antd/switch';
import { NzRadioModule } from 'ng-zorro-antd/radio';
import { NzDatePickerModule } from 'ng-zorro-antd/date-picker';
import { HealthComponent } from './health/health.component';
import { NzCardModule } from 'ng-zorro-antd/card';
import { NzSkeletonModule } from 'ng-zorro-antd/skeleton';
import { HighlightComponent } from './shared/components/highlight/highlight.component';
registerLocaleData(en);
@NgModule({
......@@ -40,7 +41,8 @@ registerLocaleData(en);
ArticleAnalyzerComponent,
ArticleGenerationComponent,
DashboardComponent,
HealthComponent
HealthComponent,
HighlightComponent
],
imports: [
BrowserModule,
......@@ -62,7 +64,7 @@ registerLocaleData(en);
NzSpinModule,
NzSpaceModule,
NzProgressModule,
NzSwitchModule,
NzRadioModule,
BarChartModule,
NzCardModule,
NzSkeletonModule,
......
......@@ -28,21 +28,31 @@
</div>
</div>
<div class="container">
<div *ngFor="let key of resultSource" class="flex-col align-center">
<h1>{{key}}</h1>
<div class="tag-wrapper flex-row">
<ng-container *ngFor="let item of results[key]">
<nz-tag *ngIf="item.tag" nz-tooltip nzColor="{{COLORS['KEYWORD']}}"
nzTooltipTitle="KEYWORD">{{item.tag}}
</nz-tag>
<nz-tag *ngIf="item.type && item.entity" [nzColor]="COLORS[item.type]" [nzTooltipTitle]="item.type"
nz-tooltip>{{item.entity}}
</nz-tag>
</ng-container>
<div class="flex-col">
<nz-radio-group [(ngModel)]="radioValue" nzButtonStyle="solid">
<label nz-radio-button nzValue="Tags">Tags</label>
<label nz-radio-button nzValue="Text">Text</label>
</nz-radio-group>
<span class="lang">Language: {{language}}</span>
</div>
<div [hidden]="radioValue !== 'Tags'">
<div *ngFor="let key of resultSource" class="flex-col">
<h1>{{key}}</h1>
<div class="tag-wrapper flex-row">
<ng-container *ngFor="let item of results[key]">
<nz-tag *ngIf="item.tag" nz-tooltip nzColor="{{COLORS['KEYWORD']}}"
nzTooltipTitle="KEYWORD">{{item.tag}}
</nz-tag>
<nz-tag *ngIf="item.type && item.entity" [nzColor]="COLORS[item.type]" [nzTooltipTitle]="item.type"
nz-tooltip>{{item.entity}}
</nz-tag>
</ng-container>
</div>
</div>
</div>
<div>
<span>Language: {{language}}</span>
<div [hidden]="radioValue !== 'Text'">
<app-highlight
[highlightConfig]="{currentColumn: 'text', searcherHighlight: resultTextData.highlight, highlightTextaFacts: true, data: resultTextData}"></app-highlight>
</div>
</div>
</ng-container>
......
......@@ -4,7 +4,7 @@
flex-wrap: wrap;
nz-tag {
margin: 5px;
margin: 5px 5px 5px 0px;
}
}
......@@ -14,16 +14,26 @@
justify-content: space-between;
flex-wrap: wrap;
align-items: center;
margin-left: auto;
nz-tag {
margin: 5px;
margin: 5px 5px 5px 0px;
}
}
.container > div {
margin-top: 5%;
.container{
align-items: flex-start;
.lang{
margin-top: 5px;
}
}
.container > div > div {
margin-top: 4%;
}
h1 {
font-size: @font-size;
}
}
app-highlight{
color: white;
font-size: 16px;
}
......@@ -5,6 +5,14 @@ import {HttpErrorResponse} from '@angular/common/http';
import {UtilityFunctions} from '../shared/UtilityFunctions';
import {Subject} from 'rxjs';
import {takeUntil} from 'rxjs/operators';
import {HighlightSpan} from '../shared/components/highlight/highlight.component';
import {KeywordExtractionResponse} from '../shared/types/KeywordExtractionResponse';
interface HighlightDataFormat {
text: string;
texta_facts: HighlightSpan[];
highlight: { text: string[] };
}
@Component({
selector: 'app-entity-extraction',
......@@ -20,6 +28,9 @@ export class ArticleAnalyzerComponent implements OnInit, OnDestroy {
isLoading = false;
language: string;
destroyed$: Subject<boolean> = new Subject<boolean>();
radioValue: 'Text' | 'Tags' = 'Tags';
resultTextData: HighlightDataFormat;
constructor(private analyzersService: AnalyzersService,
private logService: LogService) {
......@@ -45,7 +56,7 @@ export class ArticleAnalyzerComponent implements OnInit, OnDestroy {
this.populateResultData(UtilityFunctions.getDistinctByProperty(x.tags, (y) => y.tag));
}
this.language = x.language;
console.log(this.results);
this.resultTextData = this.toHighlightData(x);
} else if (x instanceof HttpErrorResponse) {
this.logService.messageHttpError(x);
}
......@@ -57,8 +68,43 @@ export class ArticleAnalyzerComponent implements OnInit, OnDestroy {
this.results[item.source].push(item);
}
}
ngOnDestroy(): void {
this.destroyed$.next(true);
this.destroyed$.complete();
}
private toHighlightData(val: KeywordExtractionResponse): HighlightDataFormat {
const temp: HighlightDataFormat = {text: val.text, texta_facts: [], highlight: {text: ['']}};
for (const entity of val.entities) {
const regexp = new RegExp(entity.entity, 'ig');
const matches = val.text.matchAll(regexp);
for (const match of matches) {
if (match.index && entity.entity) {
temp.texta_facts.push({
doc_path: 'text',
spans: JSON.stringify([[match.index, match.index + entity.entity.length]]),
fact: entity.type,
str_val: entity.entity
});
}
}
}
const tags = UtilityFunctions.getDistinctByProperty(val.tags, (x => x.tag.toLowerCase()));
for (const tag of tags) {
const regexp = new RegExp(tag.tag, 'ig');
const matches = val.text.matchAll(regexp);
for (const match of matches) {
if (match.index && tag.tag) {
temp.texta_facts.push({
doc_path: 'text',
spans: JSON.stringify([[match.index, match.index + tag.tag.length]]),
fact: 'KEYWORD',
str_val: tag.tag
});
}
}
}
return temp;
}
}
......@@ -19,10 +19,10 @@ export class DashboardComponent implements OnInit {
strokeWidth = 9; // %
blockedByModelProgressWidth = 0;
commentsOkProgressWidth = 0;
tags: { PER: GraphData[], LOC: GraphData[], KEYWORD: GraphData[] } = {
tags: { PER: GraphData[], LOC: GraphData[], ORG: GraphData[] } = {
PER: [],
LOC: [],
KEYWORD: []
ORG: []
};
tagsKeys = Object.keys(this.tags);
......@@ -42,7 +42,130 @@ export class DashboardComponent implements OnInit {
selectedRange;
dataset = [{value: 'test', display_name: 'test2'}];
customColors: { name: string, value: string }[] = [];
PERVALS = [
{
key: 'Bengals',
doc_count: 278
},
{
key: 'Kalju',
doc_count: 121
},
{
key: 'Kalev',
doc_count: 118
},
{
key: 'Levadia',
doc_count: 111
},
{
key: 'Savisaar',
doc_count: 92
},
{
key: 'Koit',
doc_count: 83
},
{
key: 'Vettel',
doc_count: 82
},
{
key: 'Rüütel',
doc_count: 78
},
{
key: 'Edgar Savisaar',
doc_count: 75
},
{
key: 'Anu',
doc_count: 73
}
];
LOCVALS = [
{
key: 'Eesti',
doc_count: 2524
},
{
key: 'Tallinn',
doc_count: 541
},
{
key: 'Euroopa',
doc_count: 389
},
{
key: 'Venemaa',
doc_count: 372
},
{
key: 'Soome',
doc_count: 323
},
{
key: 'USA',
doc_count: 317
},
{
key: 'Itaalia',
doc_count: 285
},
{
key: 'Saksamaa',
doc_count: 281
},
{
key: 'Türgi',
doc_count: 223
},
{
key: 'Hispaania',
doc_count: 216
}];
ORGVALS = [
{
key: 'Keskerakond',
doc_count: 196
},
{
key: 'IRL',
doc_count: 166
},
{
key: 'Reformierakond',
doc_count: 145
},
{
key: 'ERR',
doc_count: 137
},
{
key: 'õhtuleht',
doc_count: 135
},
{
key: 'NBA',
doc_count: 128
},
{
key: 'ETV',
doc_count: 119
},
{
key: 'Ferrari',
doc_count: 101
},
{
key: 'TV3',
doc_count: 99
},
{
key: 'MM',
doc_count: 83
}];
constructor(private changeDetectorRef: ChangeDetectorRef) {
}
......@@ -52,21 +175,20 @@ export class DashboardComponent implements OnInit {
}
ngOnInit(): void {
for (let f = 0; f <= 10; f++) {
const perName = Math.random().toString(36).substring(Math.random() * 10);
for (let f = 0; f < 10; f++) {
this.tags.PER.push({
name: perName, value: Math.floor(Math.random() * 100), extra: {date: this.randomDate(new Date(2012, 0, 1), new Date())}
name: this.PERVALS[f].key, value: this.PERVALS[f].doc_count, extra: {date: this.randomDate(new Date(2012, 0, 1), new Date())}
});
this.customColors.push({name: perName, value: this.COLORS.PER});
const keyName = Math.random().toString(36).substring(Math.random() * 10);
this.tags.KEYWORD.push({
name: keyName, value: Math.floor(Math.random() * 100), extra: {date: this.randomDate(new Date(2012, 0, 1), new Date())}
this.customColors.push({name: this.PERVALS[f].key, value: this.COLORS.PER});
const keyName = this.ORGVALS[f].key;
this.tags.ORG.push({
name: keyName, value: this.ORGVALS[f].doc_count, extra: {date: this.randomDate(new Date(2012, 0, 1), new Date())}
});
this.customColors.push({name: keyName, value: this.COLORS.KEYWORD});
const locName = Math.random().toString(36).substring(Math.random() * 10);
this.customColors.push({name: keyName, value: this.COLORS.ORG});
const locName = this.LOCVALS[f].key;
this.tags.LOC.push({
name: locName,
value: Math.floor(Math.random() * 100), extra: {date: this.randomDate(new Date(2012, 0, 1), new Date())}
value: this.LOCVALS[f].doc_count, extra: {date: this.randomDate(new Date(2012, 0, 1), new Date())}
});
this.customColors.push({name: locName, value: this.COLORS.LOC});
}
......@@ -94,8 +216,6 @@ export class DashboardComponent implements OnInit {
}
getSelectedFacts(facts, dateRange: [Date, Date], data): GraphData[] {
console.log(facts);
console.log(data);
const temp: GraphData[] = [];
for (const key of facts) {
if (data[key]) {
......@@ -112,7 +232,7 @@ export class DashboardComponent implements OnInit {
submitForm() {
this.isLoading = true;
this.selectedFact = ['PER', 'LOC', 'KEYWORD'];
this.selectedFact = ['PER', 'LOC', 'ORG'];
this.graphData = this.getSelectedFacts(this.selectedFact, this.selectedRange, this.tags);
this.isLoading = false;
}
......
......@@ -20,13 +20,13 @@
<label class="fw-medium">DISK SPACE</label>
<nz-progress [nzPercent]="disk" nzStatus="normal" nzStrokeLinecap="square" nzStrokeWidth="9"
nzType="dashboard"></nz-progress>
<label class="margin-10">{{diskObj.used | number: '1.0-2'}} / {{diskObj.total | number: '1.0-2'}} {{diskObj.unit}}</label>
<label class="margin-10" *ngIf="diskObj">{{diskObj.used | number: '1.0-2'}} / {{diskObj.total | number: '1.0-2'}} {{diskObj.unit}}</label>
</div>
<div class="flex-col align-center">
<label class="fw-medium">MEMORY</label>
<nz-progress [nzPercent]="memory" nzStatus="normal" nzStrokeLinecap="square" nzStrokeWidth="9"
nzType="dashboard"></nz-progress>
<label class="margin-10">{{memoryObj.used | number: '1.0-2'}} / {{memoryObj.total | number: '1.0-2'}} {{memoryObj.unit}}</label>
<label class="margin-10" *ngIf="memoryObj">{{memoryObj.used | number: '1.0-2'}} / {{memoryObj.total | number: '1.0-2'}} {{memoryObj.unit}}</label>
</div>
</div>
</nz-card>
......
export class UtilityFunctions {
static readonly COLORS = {
ORG: '#b71c1c',
ORG: '#9c019c',
PER: '#880e4f',
GPE: '#4a148c',
LOC: '#311b92',
......@@ -8,7 +8,7 @@ export class UtilityFunctions {
COMPANY: '#006064',
PHO: '#1b5e20',
EMAIL: '#3e2723',
KEYWORD: '#263238'
KEYWORD: '#8a7a00'
};
static typeGuard<T>(o, className: { new(...args: any[]): T }): o is T {
......
<div [title]="isTextLimited !== undefined ? isTextLimited ? 'Expand' : 'Collapse': ''">
<ng-container *ngFor="let highlight of highlightArray">
<ng-template [ngIf]="highlight.highlighted && !highlight.span?.searcherHighlight && !highlight.span?.urlSpan">
<span style="cursor: pointer;" style.background-color="{{highlight.color}}"
title="{{highlight.span?.fact}}: {{highlight.span?.str_val}}">{{highlight.text}}</span>
</ng-template>
<ng-template [ngIf]="highlight.highlighted && highlight.span?.searcherHighlight">
<span style="cursor: pointer;" style.background-color="{{highlight.color}}">{{highlight.text}}</span>
</ng-template>
<ng-template [ngIf]="highlight.highlighted && highlight.span?.urlSpan">
<a href="{{highlight.span?.str_val}}" target="_blank">{{highlight.text}}</a>
</ng-template>
<ng-template [ngIf]="highlight.nested">
<ng-container [ngTemplateOutletContext]={highlight:highlight.nested} [ngTemplateOutlet]="factTemplate">
</ng-container>
</ng-template>
<ng-template [ngIf]="!highlight.highlighted">{{highlight.text}}</ng-template>
</ng-container>
</div>
<ng-template #factTemplate let-highlight="highlight">
<ng-template [ngIf]="highlight.span?.urlSpan">
<a href="{{highlight.span?.str_val}}" target="_blank">{{highlight.text}}</a>
</ng-template>
<ng-template [ngIf]="!highlight.span?.urlSpan">
<span style="cursor: pointer;" style.background-color="{{highlight.color}}"
title="{{highlight.span?.fact}}: {{highlight.span?.str_val}}">{{highlight.text}}</span>
</ng-template>
<ng-template [ngIf]="highlight.nested">
<ng-container [ngTemplateOutletContext]={highlight:highlight.nested} [ngTemplateOutlet]="factTemplate">
</ng-container>
</ng-template>
</ng-template>
span{
color: inherit;
font-size: inherit;
}
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { HighlightComponent } from './highlight.component';
describe('HighlightComponent', () => {
let component: HighlightComponent;
let fixture: ComponentFixture<HighlightComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HighlightComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(HighlightComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});
This diff is collapsed.
......@@ -4,6 +4,5 @@
font-size: @font-size;
padding: 0.4em;
margin: 0;
min-width: 100px;
text-align: center;
}
......@@ -26,7 +26,7 @@
nz-spin {
padding: 10%;
padding: 5%;
width: 100%;
display: flex;
align-items: center;
......
......@@ -12,7 +12,7 @@
"importHelpers": true,
"target": "es2015",
"lib": [
"es2019",
"es2020",
"dom"
],
"strictNullChecks": true
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment