Skip to content

Commit

Permalink
adding icons and updated dashboard.
Browse files Browse the repository at this point in the history
Added new way to register widgets with Gridstack (comes from widgetModule directly)
  • Loading branch information
AnalogJ committed Oct 14, 2023
1 parent 90b08b8 commit d427f79
Show file tree
Hide file tree
Showing 24 changed files with 803 additions and 22 deletions.
17 changes: 17 additions & 0 deletions backend/pkg/web/handler/dashboard/testing.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"id": "updated",
"schema_version": "1.0",
"title": "Updated Dashboard",
"description": "An example dashboard to show-off the power of Fasten widgets",
"widgets": [
{
"title_text": "Records Summary",
"description_text": "Track key metrics for your chronic disease (eg. Diabetes). The data within this widget is not reflective of your health record, and is only present for demonstrational purposes.",
"x": 0,
"y": 0,
"width": 8,
"height": 6,
"item_type": "records-summary-widget"
}
]
}
21 changes: 2 additions & 19 deletions frontend/src/app/components/gridstack/gridstack.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,7 @@ import { GridHTMLElement, GridItemHTMLElement, GridStack, GridStackNode, GridSta

import { GridItemCompHTMLElement, GridstackItemComponent } from './gridstack-item.component';
import {CommonModule} from '@angular/common';
import {WidgetsModule} from '../../widgets/widgets.module';
import {ComplexLineWidgetComponent} from '../../widgets/complex-line-widget/complex-line-widget.component';
import {DashboardWidgetComponent} from '../../widgets/dashboard-widget/dashboard-widget.component';
import {DonutChartWidgetComponent} from '../../widgets/donut-chart-widget/donut-chart-widget.component';
import {DualGaugesWidgetComponent} from '../../widgets/dual-gauges-widget/dual-gauges-widget.component';
import {GroupedBarChartWidgetComponent} from '../../widgets/grouped-bar-chart-widget/grouped-bar-chart-widget.component';
import {PatientVitalsWidgetComponent} from '../../widgets/patient-vitals-widget/patient-vitals-widget.component';
import {SimpleLineChartWidgetComponent} from '../../widgets/simple-line-chart-widget/simple-line-chart-widget.component';
import {TableWidgetComponent} from '../../widgets/table-widget/table-widget.component';
import {WidgetsModule, WidgetComponents} from '../../widgets/widgets.module';
import {DashboardWidgetComponentInterface} from '../../widgets/dashboard-widget-component-interface';

/** events handlers emitters signature for different events */
Expand Down Expand Up @@ -137,16 +129,7 @@ export class GridstackComponent implements OnInit, AfterContentInit, OnDestroy {
) {

// register all our dynamic components created in the grid
GridstackComponent.addComponentToSelectorType([
ComplexLineWidgetComponent,
DashboardWidgetComponent,
DonutChartWidgetComponent,
DualGaugesWidgetComponent,
GroupedBarChartWidgetComponent,
PatientVitalsWidgetComponent,
SimpleLineChartWidgetComponent,
TableWidgetComponent,
]);
GridstackComponent.addComponentToSelectorType(WidgetComponents());
// set globally our method to create the right widget type
GridStack.addRemoveCB = gsCreateNgComponents;
GridStack.saveCB = gsSaveAdditionalNgInfo;
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/app/models/widget/dashboard-widget-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import * as _ from 'lodash';

export class DashboardWidgetConfig {
id?: string
item_type: "complex-line-widget" | "donut-chart-widget" | "dual-gauges-widget" | "grouped-bar-chart-widget" | "patient-vitals-widget" | "simple-line-chart-widget" | "table-widget"
item_type: "complex-line-widget" | "donut-chart-widget" | "dual-gauges-widget" | "grouped-bar-chart-widget" | "patient-vitals-widget" | "simple-line-chart-widget" | "table-widget" | "records-summary-widget"

title_text: string
description_text: string
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,185 @@
<ng-container [ngTemplateOutlet]="loading ? showLoading : (!loading && isEmpty) ? showEmpty : showChart"></ng-container>

<ng-template #showLoading>
<loading-widget></loading-widget>
</ng-template>

<ng-template #showEmpty>
<empty-widget></empty-widget>
</ng-template>

<ng-template #showChart>
<div class="card card-dashboard-sixteen">
<div class="card-header">
<h6 class="card-title">Medical Records</h6>
</div><!-- card-header -->
<div class="card-body">

<div class="row">
<div class="col-6">
<div class="table-responsive">
<table class="table mg-b-0">
<tbody>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/allergies.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Allergies</h6>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">7</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/clinicalnotes.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Clinical Notes</h6>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">85</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/careplans.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Care Plans</h6>
<small class="tx-11 tx-gray-500">Appointments<br/>Medical Conditions<br/>Health Goals<br/>Orders</small>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">83</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/careteam.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Care Team</h6>
<small class="tx-11 tx-gray-500">Primary Care Provider<br/>Provider Details</small>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">8</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/demographics.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Demographic Information</h6>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">3</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/labresults.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Lab Results</h6>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">3</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col-6">
<div class="table-responsive">
<table class="table mg-b-0">
<tbody>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/healthgoals.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Health Goals</h6>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">2</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/conditions.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Health Issues</h6>
<small class="tx-11 tx-gray-500">Conditions</small>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">6</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/immunizations.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Immunizations</h6>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">9</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/implants.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Implants</h6>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">22</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/medications.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Medications</h6>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">22</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
<tr>
<td>
<div class="az-img-user"><img src="assets/icons/procedures.svg" alt=""></div>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">Procedures</h6>
</td>
<td>
<h6 class="mg-b-0 tx-inverse">22</h6>
<small class="tx-11 tx-gray-500">Records</small>
</td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
</div><!-- card-body -->
</div>
</ng-template><!-- card -->
Empty file.
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';

import { RecordsSummaryWidgetComponent } from './records-summary-widget.component';

describe('RecordsSummaryWidgetComponent', () => {
let component: RecordsSummaryWidgetComponent;
let fixture: ComponentFixture<RecordsSummaryWidgetComponent>;

beforeEach(async () => {
await TestBed.configureTestingModule({
declarations: [ RecordsSummaryWidgetComponent ]
})
.compileComponents();

fixture = TestBed.createComponent(RecordsSummaryWidgetComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { Component, OnInit } from '@angular/core';
import {NgChartsModule} from 'ng2-charts';
import {CommonModule} from '@angular/common';
import {MomentModule} from 'ngx-moment';
import {LoadingWidgetComponent} from '../loading-widget/loading-widget.component';
import {EmptyWidgetComponent} from '../empty-widget/empty-widget.component';
import {DashboardWidgetComponent} from '../dashboard-widget/dashboard-widget.component';
import {DashboardWidgetConfig} from '../../models/widget/dashboard-widget-config';

@Component({
standalone: true,
imports: [CommonModule, LoadingWidgetComponent, EmptyWidgetComponent],
selector: 'records-summary-widget',
templateUrl: './records-summary-widget.component.html',
styleUrls: ['./records-summary-widget.component.scss']
})
export class RecordsSummaryWidgetComponent extends DashboardWidgetComponent implements OnInit {

// constructor() { }

ngOnInit(): void {
//manually define the widget config, rather than pull from the configuration file
this.widgetConfig = {
id: 'records-summary-widget',
item_type: 'records-summary-widget',
description_text: 'Displays a summary of patient records',
width: 4,
height: 5,
title_text: 'Medical Records',
queries: []

} as DashboardWidgetConfig
super.ngOnInit();
this.loading = false
this.isEmpty = false
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import type { Meta, StoryObj } from '@storybook/angular';
import {RecordsSummaryWidgetComponent} from './records-summary-widget.component';
import {applicationConfig, moduleMetadata} from '@storybook/angular';
import {HttpClient, HttpClientModule} from '@angular/common/http';
import {HTTP_CLIENT_TOKEN} from '../../dependency-injection';
import {importProvidersFrom} from '@angular/core';
import {CommonModule} from '@angular/common';

// More on how to set up stories at: https://storybook.js.org/docs/angular/writing-stories/introduction
const meta: Meta<RecordsSummaryWidgetComponent> = {
title: 'Widget/RecordsSummaryWidget',
component: RecordsSummaryWidgetComponent,
decorators: [
applicationConfig({
providers: [
{
provide: HttpClient,
useClass: HttpClient
},
{
provide: HTTP_CLIENT_TOKEN,
useClass: HttpClient,
},
importProvidersFrom(HttpClientModule)
]
}),
moduleMetadata({
imports: [CommonModule, HttpClientModule],
})
],
tags: ['autodocs'],
render: (args: RecordsSummaryWidgetComponent) => ({
props: {
backgroundColor: null,
...args,
},
}),
argTypes: {
},
};

export default meta;
type Story = StoryObj<RecordsSummaryWidgetComponent>;

// More on writing stories with args: https://storybook.js.org/docs/angular/writing-stories/args
export const Example: Story = {
args: {
}
};

Loading

0 comments on commit d427f79

Please # to comment.