fixed chart

This commit is contained in:
Timo Bejan 2020-10-12 20:44:38 +03:00
parent 4ccf18be77
commit 72a9804637
8 changed files with 79 additions and 78 deletions

View File

@ -11,6 +11,8 @@ import { Annotations } from '@pdftron/webviewer';
import { PdfViewerComponent } from '../pdf-viewer/pdf-viewer.component';
import { AnnotationUtils } from '../../../utils/annotation-utils';
@Component({
selector: 'redaction-file-preview-screen',
templateUrl: './file-preview-screen.component.html',

View File

@ -16,9 +16,6 @@ import {tap} from "rxjs/operators";
import WebViewer, {Annotations, WebViewerInstance} from "@pdftron/webviewer";
import {TranslateService} from "@ngx-translate/core";
import {ViewerSyncService} from "../service/viwer-sync.service";
import { AnnotationUtils } from '../../../utils/annotation-utils';
export enum FileType {
ORIGINAL = 'ORIGINAL',
@ -84,7 +81,7 @@ export class PdfViewerComponent implements OnInit, AfterViewInit, OnDestroy {
this._configureTextPopup();
this._configureHeader();
instance.annotManager.on('annotationChanged', (annotations, action) => {
if(action === 'add'){
if (action === 'add') {
this.annotationsAdded.emit(annotations);
}
});

View File

@ -38,13 +38,20 @@
{{pw.project.projectName}}
</div>
<div class="subtitle stats-subtitle">
<div><mat-icon svgIcon="red:files"></mat-icon>{{documentCount(pw)}}</div>
<div><mat-icon svgIcon="red:user"></mat-icon>{{userCount(pw)}}</div>
<div><mat-icon svgIcon="red:calendar"></mat-icon>{{pw.project.date | date:'mediumDate'}}</div>
<div>
<mat-icon svgIcon="red:files"></mat-icon>
{{documentCount(pw)}}</div>
<div>
<mat-icon svgIcon="red:user"></mat-icon>
{{userCount(pw)}}</div>
<div>
<mat-icon svgIcon="red:calendar"></mat-icon>
{{pw.project.date | date:'mediumDate'}}</div>
</div>
</div>
<div class="flex-1">
<redaction-initials-avatar [username]="user.name"
color="gray-red"
withName="true"
></redaction-initials-avatar>
</div>
@ -72,9 +79,7 @@
</div>
<div class="right-fixed-container">
<!-- <redaction-simple-doughnut-chart [initialValues]="[120,26]">-->
<!-- </redaction-simple-doughnut-chart>-->
<redaction-simple-doughnut-chart [data]="projectsChartData" [strokeWidth]="15"></redaction-simple-doughnut-chart>
</div>
</div>

View File

@ -8,6 +8,7 @@ import {NotificationService} from "../../notification/notification.service";
import {AppStateService, ProjectWrapper} from "../../state/app-state.service";
import {UserService} from "../../user/user.service";
import {ProjectDetailsDialogComponent} from "../project-overview-screen/project-details-dialog/project-details-dialog.component";
import {DataSeries} from "../../simple-doughnut-chart/simple-doughnut-chart.component";
@Component({
selector: 'redaction-project-listing-screen',
@ -15,6 +16,7 @@ import {ProjectDetailsDialogComponent} from "../project-overview-screen/project-
styleUrls: ['./project-listing-screen.component.scss']
})
export class ProjectListingScreenComponent implements OnInit {
projectsChartData: DataSeries [] = [];
constructor(
public readonly appStateService: AppStateService,
@ -22,7 +24,7 @@ export class ProjectListingScreenComponent implements OnInit {
private readonly _projectControllerService: ProjectControllerService,
private readonly _translateService: TranslateService,
private readonly _notificationService: NotificationService,
private readonly _dialog: MatDialog) {
private readonly _dialog: MatDialog) {
}
get user() {
@ -31,6 +33,9 @@ export class ProjectListingScreenComponent implements OnInit {
ngOnInit(): void {
this.appStateService.reset();
this.projectsChartData = [
{value: this.activeProjects, color: '#DD4D50', label: 'active-projects'},
{value: this.inactiveProjects, color: '#f8eded', label: 'Archived'}];
}
openAddProjectDialog(project?: Project): void {
@ -77,4 +82,12 @@ export class ProjectListingScreenComponent implements OnInit {
userCount(project: ProjectWrapper) {
return 1;
}
get activeProjects() {
return this.appStateService.allProjects.reduce((i, p) => i+(p.project.status === Project.StatusEnum.ACTIVE ? 1 :0), 0)
}
get inactiveProjects() {
return this.appStateService.allProjects.length - this.activeProjects;
}
}

View File

@ -1,14 +1,16 @@
<svg height="160" width="160" viewBox="0 0 160 160" class="donut-chart">
<g *ngFor="let val of chartData; let i = index">
<svg attr.height="{{size}}" attr.width="{{size}}" attr.viewBox="0 0 {{size}} {{size}}" class="donut-chart">
<g *ngFor="let value of data; let i = index">
<circle attr.cx="{{cx}}"
attr.cy="{{cy}}"
attr.r="{{radius}}"
attr.stroke="{{colors[i]}}"
attr.stroke="{{data[i].color}}"
attr.stroke-width="{{strokeWidth}}"
attr.stroke-dasharray="{{adjustedCircumference}}"
attr.stroke-dashoffset="calculateStrokeDashOffset(value, circumference)"
attr.stroke-dashoffset="{{calculateStrokeDashOffset(value.value, circumference)}}"
fill="transparent"
attr.transform="{{returnCircleTransformValue(i)}}}"/>
attr.transform="{{returnCircleTransformValue(i)}}"/>
</g>
</svg>
<div *ngFor="let val of data">
{{val.value}} {{val.label}}
</div>

Before

Width:  |  Height:  |  Size: 561 B

After

Width:  |  Height:  |  Size: 673 B

View File

@ -1,6 +1,13 @@
import {Component, Input, OnInit} from '@angular/core';
export class DataSeries {
value: number;
color: string;
label: string;
}
@Component({
selector: 'redaction-simple-doughnut-chart',
templateUrl: './simple-doughnut-chart.component.html',
@ -8,101 +15,66 @@ import {Component, Input, OnInit} from '@angular/core';
})
export class SimpleDoughnutChartComponent implements OnInit {
@Input() initialValues: [];
@Input() title: string;
@Input() subtitle: number;
@Input() data: DataSeries[] = [];
@Input() angleOffset: number = -90;
@Input() colors: string[] = ["#6495ED", "goldenrod", "#cd5c5c", "thistle", "lightgray"];
@Input() cx: number = 80;
@Input() cy: number = 80;
@Input() radius: number = 60;
@Input() strokeWidth: 30;
@Input() radius: number = 80;
@Input() strokeWidth: number = 20;
chartData: any[] = [];
sortedValues: number[] = [];
perimeter: number;
data: any[] = [];
cx: number = 0;
cy: number = 0;
size: number = 0;
constructor() {
}
ngOnInit() {
this.sortInitialValues();
this.calculateChartData();
this.cx = this.radius + (this.strokeWidth / 2);
this.cy = this.radius + (this.strokeWidth / 2);
this.size = this.strokeWidth+(this.radius * 2) ;
}
get adjustedCircumference() {
return this.circumference - 2
return this.circumference;
};
get circumference() {
return 2 * Math.PI * this.radius
return 2 * Math.PI * this.radius;
};
get dataTotal() {
return this.sortedValues.reduce((acc, val) => acc + val)
return this.data.map(v => v.value).reduce((acc, val) => acc + val, 0);
};
calculateChartData() {
this.sortedValues.forEach((dataVal, index) => {
const {x, y} = this.calculateTextCoords(dataVal, this.angleOffset)
// start at -90deg so that the largest segment is perpendicular to top
this.data.forEach((dataVal) => {
const data = {
degrees: this.angleOffset,
textX: x,
textY: y
}
this.chartData.push(data)
this.angleOffset = this.dataPercentage(dataVal) * 360 + this.angleOffset
this.angleOffset = this.dataPercentage(dataVal.value) * 360 + this.angleOffset;
})
}
calculateStrokeDashOffset(dataVal, circumference) {
const strokeDiff = this.dataPercentage(dataVal) * circumference
return circumference - strokeDiff
return circumference - strokeDiff;
}
calculateTextCoords(dataVal, angleOffset) {
// t must be radians
// x(t) = r cos(t) + j
// y(t) = r sin(t) + j
const angle = (this.dataPercentage(dataVal) * 360) / 2 + angleOffset
const radians = this.degreesToRadians(angle)
const textCoords = {
x: this.radius * Math.cos(radians) + this.cx,
y: this.radius * Math.sin(radians) + this.cy
}
return textCoords
}
degreesToRadians(angle) {
return angle * (Math.PI / 180)
return angle * (Math.PI / 180);
}
dataPercentage(dataVal) {
return dataVal / this.dataTotal
}
percentageString(dataVal) {
return `${Math.round(this.dataPercentage(dataVal) * 100)}%`
return dataVal / this.dataTotal;
}
returnCircleTransformValue(index) {
return `rotate(${this.chartData[index].degrees}, ${this.cx}, ${this.cy})`
return `rotate(${this.chartData[index].degrees}, ${this.cx}, ${this.cy})`;
}
segmentBigEnough(dataVal) {
return Math.round(this.dataPercentage(dataVal) * 100) > 5
}
sortInitialValues() {
return this.sortedValues = this.initialValues.sort((a, b) => b - a)
}
}

View File

@ -58,13 +58,15 @@ export class AppStateService {
async loadAllProjects() {
const projects = await this._projectControllerService.getProjects().toPromise();
this._appState.projects = projects.map(p => {
return new ProjectWrapper(p, []);
});
for (let project of projects) {
await this.getFiles(project.projectId);
if(projects) {
this._appState.projects = projects.map(p => {
return new ProjectWrapper(p, []);
});
for (let project of projects) {
await this.getFiles(project.projectId);
}
this._computeStats();
}
this._computeStats();
}
async getFiles(projectId: string) {

View File

@ -30,6 +30,7 @@
&.gray-red {
background-color: $grey-4;
color: $red-1;
border: none;
}
@ -42,6 +43,13 @@
.stats-subtitle {
display: flex;
> div {
display: flex;
justify-content: center;
align-items: center;
}
> div:not(:last-child) {
margin-right: 12px;
}