Skip to content

Commit c259288

Browse files
Added progress chart
1 parent 6ec3522 commit c259288

10 files changed

+264
-1
lines changed

README.md

+7
Original file line numberDiff line numberDiff line change
@@ -218,3 +218,10 @@ For Example:
218218
| Line Chart | `line-chart` | [Line Chart Docs](docs/line-chart.md) |
219219
| Bar Chart | `bar-chart` | [Bar Chart Docs](docs/bar-chart.md) |
220220
| Doughnut/Pie Chart | `doughnut-pie-chart` | [Doughnut/Pie Chart Docs](docs/doughnut-pie-chart.md) |
221+
| Progress Chart | `progress-chart` | [Progress Chart Docs](docs/progress-chart.md) |
222+
223+
---
224+
225+
### Example Screenshot
226+
227+
![](docs/assets/example.png)

demo/index.js

+41-1
Original file line numberDiff line numberDiff line change
@@ -692,7 +692,7 @@ widgetContainer.jsonInput = {
692692
display: true,
693693
backgroundColor: {
694694
arguments: "context",
695-
body: "console.log(context.chart.config.options.backgroundColor);return context.chart.config.options.backgroundColor;",
695+
body: "return context.chart.config.options.backgroundColor;",
696696
},
697697
borderColor: "darkbrown",
698698
borderRadius: 25,
@@ -923,6 +923,46 @@ widgetContainer.jsonInput = {
923923
},
924924
],
925925
},
926+
{
927+
classes: ["justify-content-center"],
928+
widgets: [
929+
{
930+
widget: "progress-chart",
931+
classes: ["col-12"],
932+
clickable: true,
933+
datasets: [
934+
{
935+
title: "Category A",
936+
classes: ["col-md-6"],
937+
max: 50,
938+
value: 30,
939+
customId: 1,
940+
},
941+
{
942+
title: "Category B",
943+
classes: ["col-md-6"],
944+
max: 50,
945+
value: 40,
946+
customId: 1,
947+
},
948+
{
949+
title: "Category C",
950+
classes: ["col-md-6"],
951+
max: 50,
952+
value: 10,
953+
customId: 1,
954+
},
955+
{
956+
title: "Category D",
957+
classes: ["col-md-6"],
958+
max: 50,
959+
value: 50,
960+
customId: 1,
961+
},
962+
],
963+
},
964+
],
965+
},
926966
],
927967
};
928968

docs/assets/example.png

516 KB
Loading

docs/assets/progressChart1.png

15.3 KB
Loading

docs/progress-chart.md

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
## Bar Chart Widget
2+
3+
![](assets/progressChart1.png)
4+
5+
6+
| Option Name | Description | Structure | Default |
7+
| -------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | -------------------------------------- |
8+
| datasets | This will be an array of objects. | Object[] | [] |
9+
| datasets[index].title | Progress chart title | String | null |
10+
| datasets[index].classes | Progress chart bootstrap grid classes.<br />Eg.`col-md-6` will allocate half of total widget width for this progress chart for medium size screen and above | String[] | [] |
11+
| datasets[index].max | Max value for progress bar | Number | 100 |
12+
| datasets[index].value | The achieved value for progress bar | Number | 0 |
13+
| datasets[index].progress | The progress percentage for progress bar.<br />Note: If progress is provided, max and value will not be used to calculate progress percentage. Skip this value if providing max and value. | Number | Calculated based on`max` and `value` |
14+
| color | Color of progress bar. | String | `#488aff` |
15+
| disablePercentage | If True, will not show percentage symbol in the progress bar | Bool | False |
16+
| clickable | If True, the progress bar and title will be clickable. An output event will be emitted when clicked.<br />Event Structure:<br />*{"action":"clicked","widget":"progress-chart","data":`dataset`}* | Bool | False |
17+
18+
### Examples:
19+
20+
#### Example 1
21+
22+
##### JSON Input:
23+
24+
```js
25+
{
26+
widget: "progress-chart",
27+
classes: ["col-12"],
28+
clickable: true,
29+
datasets: [
30+
{
31+
title: "Category A",
32+
classes: ["col-md-6"],
33+
max: 50,
34+
value: 30,
35+
customId: 1,
36+
},
37+
{
38+
title: "Category B",
39+
classes: ["col-md-6"],
40+
max: 50,
41+
value: 40,
42+
customId: 1,
43+
},
44+
{
45+
title: "Category C",
46+
classes: ["col-md-6"],
47+
max: 50,
48+
value: 10,
49+
customId: 1,
50+
},
51+
{
52+
title: "Category D",
53+
classes: ["col-md-6"],
54+
max: 50,
55+
value: 50,
56+
customId: 1,
57+
},
58+
],
59+
}
60+
```
61+
62+
##### Widget Output
63+
64+
![](assets/progressChart1.png)
65+
66+
---
67+
68+
[Go Back to Main Page](../README.md)

src/app/app.module.ts

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import { AppComponent } from './app.component';
1414
import { BarChartComponent } from './bar-chart/bar-chart.component';
1515
import { DoughnutChartComponent } from './doughnut-chart/doughnut-chart.component';
1616
import { LineChartComponent } from './line-chart/line-chart.component';
17+
import { ProgressChartComponent } from './progress-chart/progress-chart.component';
1718
import { SmallStatComponent } from './small-stat/small-stat.component';
1819
import { StatGraphCardComponent } from './stat-graph-card/stat-graph-card.component';
1920
import { WidgetsContainerComponent } from './widgets-container/widgets-container.component';
@@ -22,6 +23,7 @@ const WidgetComponentMap = {
2223
'small-stat': SmallStatComponent,
2324
'line-chart': LineChartComponent,
2425
'bar-chart': BarChartComponent,
26+
'progress-chart': ProgressChartComponent,
2527
'doughnut-pie-chart': DoughnutChartComponent,
2628
'stat-graph-card': StatGraphCardComponent,
2729
};
@@ -42,6 +44,7 @@ const MaterialModules = [
4244
LineChartComponent,
4345
BarChartComponent,
4446
DoughnutChartComponent,
47+
ProgressChartComponent,
4548
],
4649
imports: [
4750
BrowserModule,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<div class="row progress-container" *ngIf="!loading">
2+
<div *ngFor="let item of chartData.datasets" [ngClass]="item.classes">
3+
<div class="d-flex justify-content-between">
4+
<span
5+
class="mat-h4 fw-bold mb-0"
6+
[ngClass]="{ clickable: chartData.clickable }"
7+
(click)="itemClicked(item)"
8+
>
9+
{{ item.title }}
10+
</span>
11+
<span class="value mat-small" *ngIf="item.value">
12+
{{ item.value }} <span *ngIf="item.max">/{{ item.max }}</span>
13+
</span>
14+
</div>
15+
<div
16+
class="progress-outer"
17+
[ngClass]="{ clickable: chartData.clickable }"
18+
(click)="itemClicked(item)"
19+
>
20+
<div [style.width]="whichWidth(item.progress)">
21+
<div class="progress-inner" [style.background-color]="color">
22+
{{ item.progress
23+
}}<ng-container *ngIf="!disablePercentage">% </ng-container>
24+
</div>
25+
</div>
26+
</div>
27+
</div>
28+
</div>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
.progress-outer {
2+
width: 96%;
3+
margin: 10px 2%;
4+
padding: 3px;
5+
background-color: #f4f4f4;
6+
border: 1px solid #dcdcdc;
7+
color: #fff;
8+
border-radius: 20px;
9+
text-align: center;
10+
}
11+
12+
.progress-inner {
13+
min-height: 18px;
14+
white-space: nowrap;
15+
overflow: hidden;
16+
padding: 0px;
17+
border-radius: 20px;
18+
animation: progress 2s;
19+
}
20+
21+
.value{
22+
color: rgba(0,0,0,0.54);
23+
margin-bottom: -7px;
24+
}
25+
26+
@keyframes progress {
27+
0% {
28+
width: 0%;
29+
}
30+
100% {
31+
width: 100%;
32+
}
33+
}
34+
35+
.progress-container > div {
36+
padding: 10px;
37+
}
38+
39+
.clickable{
40+
cursor: pointer;
41+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { ComponentFixture, TestBed } from '@angular/core/testing';
2+
3+
import { ProgressChartComponent } from './progress-chart.component';
4+
5+
describe('ProgressChartComponent', () => {
6+
let component: ProgressChartComponent;
7+
let fixture: ComponentFixture<ProgressChartComponent>;
8+
9+
beforeEach(() => {
10+
TestBed.configureTestingModule({
11+
declarations: [ProgressChartComponent]
12+
});
13+
fixture = TestBed.createComponent(ProgressChartComponent);
14+
component = fixture.componentInstance;
15+
fixture.detectChanges();
16+
});
17+
18+
it('should create', () => {
19+
expect(component).toBeTruthy();
20+
});
21+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
2+
import { isArray } from 'lodash-es';
3+
4+
@Component({
5+
selector: 'app-progress-chart',
6+
templateUrl: './progress-chart.component.html',
7+
styleUrls: ['./progress-chart.component.scss'],
8+
})
9+
export class ProgressChartComponent implements OnInit {
10+
@Input() chartData = {
11+
datasets: [],
12+
color: '',
13+
disablePercentage: false,
14+
clickable: false,
15+
};
16+
@Output() widgetOutput: EventEmitter<any> = new EventEmitter();
17+
18+
loading = true;
19+
color: string;
20+
disablePercentage: boolean;
21+
22+
ngOnInit(): void {
23+
if (!isArray(this.chartData?.datasets)) {
24+
this.chartData.datasets = [this.chartData.datasets];
25+
}
26+
27+
this.chartData.datasets.forEach((data) => {
28+
if (data.hasOwnProperty('progress')) {
29+
data.progress = +data.progress;
30+
} else {
31+
let val = +data.value || 0;
32+
let max = +data.max || 100;
33+
data.progress = Math.round((val / max) * 10000) / 100;
34+
}
35+
});
36+
37+
this.color = this.chartData.color || '#488aff';
38+
this.disablePercentage = this.chartData.disablePercentage || false;
39+
this.loading = false;
40+
}
41+
42+
whichWidth(progress) {
43+
return progress > 0 ? Math.max(progress, 15) + '%' : 0;
44+
}
45+
46+
itemClicked = (item) => {
47+
if (this.chartData.clickable) {
48+
this.widgetOutput.emit({
49+
action: 'clicked',
50+
data: item,
51+
widget: 'progress-chart',
52+
});
53+
}
54+
};
55+
}

0 commit comments

Comments
 (0)