fixed chart
This commit is contained in:
parent
4ccf18be77
commit
72a9804637
@ -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',
|
||||
|
||||
@ -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);
|
||||
}
|
||||
});
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 |
@ -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)
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user