Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#1341 setup sites screen #214

Merged
merged 4 commits into from
Aug 26, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3,279 changes: 1,831 additions & 1,448 deletions udmif/web/package-lock.json

Large diffs are not rendered by default.

20 changes: 10 additions & 10 deletions udmif/web/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,32 +17,32 @@
"src/**/*.{html,ts,json,scss}": "prettier --single-quote --arrow-parens always --trailing-comma es5 --print-width 120 --write"
},
"dependencies": {
"@abacritt/angularx-social-login": "^1.0.2",
"@abacritt/angularx-social-login": "~1.0.2",
"@angular/animations": "~13.3.3",
"@angular/cdk": "^13.3.3",
"@angular/cdk": "~13.3.3",
"@angular/common": "~13.3.3",
"@angular/compiler": "~13.3.3",
"@angular/core": "~13.3.3",
"@angular/forms": "~13.3.3",
"@angular/material": "^13.3.3",
"@angular/material": "~13.3.3",
"@angular/platform-browser": "~13.3.3",
"@angular/platform-browser-dynamic": "~13.3.3",
"@angular/router": "~13.3.3",
"@apollo/client": "^3.6.6",
"apollo-angular": "^3.0.1",
"graphql": "^16.5.0",
"lodash-es": "^4.17.21",
"@apollo/client": "~3.6.6",
"apollo-angular": "~3.0.1",
"graphql": "~16.5.0",
"lodash-es": "~4.17.21",
"rxjs": "~7.5.5",
"tslib": "^2.3.0",
"tslib": "~2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "~13.3.3",
"@angular/cli": "~13.3.3",
"@angular/compiler-cli": "~13.3.3",
"@types/jasmine": "~3.10.0",
"@types/lodash-es": "^4.17.6",
"@types/node": "^12.11.1",
"@types/lodash-es": "~4.17.6",
"@types/node": "~12.11.1",
"husky": "~7.0.4",
"jasmine-core": "~4.0.0",
"karma": "~6.3.0",
Expand Down
5 changes: 5 additions & 0 deletions udmif/web/src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ const routes: Routes = [
loadChildren: () => import('./login/login.module').then((m) => m.LoginModule),
canActivate: [LoginGuard],
},
{
path: 'sites',
loadChildren: () => import('./sites/sites.module').then((m) => m.SitesModule),
canActivate: [AuthGuard],
},
{
path: 'devices',
loadChildren: () => import('./devices/devices.module').then((m) => m.DevicesModule),
Expand Down
2 changes: 1 addition & 1 deletion udmif/web/src/app/devices/devices.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ export class DevicesComponent implements OnInit, OnDestroy {
});
}

ngOnDestroy() {
ngOnDestroy(): void {
this.devicesSubscription.unsubscribe(); // cleanup
}

Expand Down
2 changes: 1 addition & 1 deletion udmif/web/src/app/devices/devices.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ export type DeviceModelsQueryResponse = {
export interface DeviceModelsQueryVariables extends CommonSearchQueryVariables {}

export type DeviceSitesQueryResponse = {
sites: string[];
siteNames: string[];
};

export interface DeviceSitesQueryVariables extends CommonSearchQueryVariables {}
Expand Down
12 changes: 6 additions & 6 deletions udmif/web/src/app/devices/devices.gql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,31 +23,31 @@ export const GET_DEVICES = gql`
`;

export const GET_DEVICE_NAMES = gql`
query GetDeviceNames($searchOptions: DeviceNamesSearchOptions) {
query GetDeviceNames($searchOptions: DistinctSearchOptions) {
deviceNames(searchOptions: $searchOptions)
}
`;

export const GET_DEVICE_MAKES = gql`
query GetDeviceMakes($searchOptions: DeviceMakesSearchOptions) {
query GetDeviceMakes($searchOptions: DistinctSearchOptions) {
deviceMakes(searchOptions: $searchOptions)
}
`;

export const GET_DEVICE_MODELS = gql`
query GetDeviceModels($searchOptions: DeviceModelsSearchOptions) {
query GetDeviceModels($searchOptions: DistinctSearchOptions) {
deviceModels(searchOptions: $searchOptions)
}
`;

export const GET_DEVICE_SITES = gql`
query GetDeviceSites($searchOptions: SitesSearchOptions) {
sites(searchOptions: $searchOptions)
query GetDeviceSites($searchOptions: DistinctSearchOptions) {
siteNames(searchOptions: $searchOptions)
}
`;

export const GET_DEVICE_SECTIONS = gql`
query GetDeviceSections($searchOptions: SectionsSearchOptions) {
query GetDeviceSections($searchOptions: DistinctSearchOptions) {
sections(searchOptions: $searchOptions)
}
`;
2 changes: 1 addition & 1 deletion udmif/web/src/app/devices/devices.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export class DevicesService {
})
.valueChanges.pipe(
map(({ data }) => {
return { values: data.sites };
return { values: data.siteNames };
})
);
}
Expand Down
1 change: 1 addition & 0 deletions udmif/web/src/app/navigation/navigation.component.html
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<mat-toolbar color="primary" *ngIf="isLoggedIn | async">
<h1>UDMI</h1>
<nav role="navigation" aria-label="Main navigation">
<a mat-button routerLink="/sites" routerLinkActive="active">Sites</a>
<a mat-button routerLink="/devices" routerLinkActive="active">Devices</a>
</nav>
<span class="spacer"></span>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,7 @@ describe('SearchFilterComponent', () => {
imports: [SearchFilterModule, BrowserAnimationsModule],
providers: [{ provide: DevicesService, useValue: mockDevicesService }],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(SearchFilterComponent);
component = fixture.componentInstance;
component.fields = { name: 'getDeviceNames', make: 'getDeviceMakes' };
Expand Down
2 changes: 2 additions & 0 deletions udmif/web/src/app/search-filter/search-filter.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ import { map, startWith, switchMap } from 'rxjs/operators';
import { ChipItem, SearchFilterItem } from './search-filter';
import { MatChipInputEvent } from '@angular/material/chips';
import { DevicesService } from '../devices/devices.service';
import { SitesService } from '../sites/sites.service';

const services: any = {
DevicesService,
SitesService,
};

@Component({
Expand Down
6 changes: 6 additions & 0 deletions udmif/web/src/app/site/site.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
interface SiteModel {
id: string;
name: string;
}

export type Site = Partial<SiteModel>;
11 changes: 11 additions & 0 deletions udmif/web/src/app/sites/sites-routing.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { SitesComponent } from './sites.component';

const routes: Routes = [{ path: '', component: SitesComponent }];

@NgModule({
imports: [RouterModule.forChild(routes)],
exports: [RouterModule],
})
export class SitesRoutingModule {}
10 changes: 10 additions & 0 deletions udmif/web/src/app/sites/sites.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<div class="table-controls"></div>
<mat-table [dataSource]="sites" matSort (matSortChange)="sortData($event)" aria-label="List of sites">
<ng-container *ngFor="let columnName of displayedColumns" matColumnDef="{{ columnName }}">
<mat-header-cell *matHeaderCellDef>{{ columnName | capitalize }}</mat-header-cell>
<mat-cell *matCellDef="let element">{{ element[columnName] }}</mat-cell>
</ng-container>

<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
</mat-table>
32 changes: 32 additions & 0 deletions udmif/web/src/app/sites/sites.component.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
.table-controls {
display: flex;
align-items: center;

.grow {
flex: 1;
}
}

.mat-table {
width: 100%;
border: solid thin rgba(0, 0, 0, 0.12);
border-bottom: none;

.link {
display: block;
text-align: initial;
min-width: auto;
line-height: initial;
padding: 0;
border-radius: 0;
white-space: initial;
font-weight: initial;

::ng-deep.mat-button-ripple.mat-ripple,
::ng-deep.mat-button-focus-overlay {
top: -1px;
left: -1px;
right: -1px;
}
}
}
136 changes: 136 additions & 0 deletions udmif/web/src/app/sites/sites.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { SitesComponent } from './sites.component';
import { SitesModule } from './sites.module';
import { SitesService } from './sites.service';
import { of } from 'rxjs';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { PageEvent } from '@angular/material/paginator';
import { Sort } from '@angular/material/sort';
import { SitesQueryResponse, SitesQueryVariables, SortOptions } from './sites';
import { SearchFilterItem } from '../search-filter/search-filter';
import { Site } from '../site/site';
import { ApolloQueryResult } from '@apollo/client/core';
import { QueryRef } from 'apollo-angular';

describe('SitesComponent', () => {
let component: SitesComponent;
let fixture: ComponentFixture<SitesComponent>;
let mockSitesService: jasmine.SpyObj<SitesService>;
let refetch: jasmine.Spy;
let sites: Site[] = [
{
id: 'site-id-123',
name: 'site one',
},
];

beforeEach(async () => {
refetch = jasmine.createSpy().and.resolveTo(<ApolloQueryResult<SitesQueryResponse>>{
data: {},
});
mockSitesService = jasmine.createSpyObj(SitesService, ['getSites']);
mockSitesService.getSites.and.returnValue(<QueryRef<SitesQueryResponse, SitesQueryVariables>>(<unknown>{
valueChanges: of(<ApolloQueryResult<SitesQueryResponse>>{
data: {
sites: {
sites,
totalCount: 1,
totalFilteredCount: 1,
},
},
}),
refetch,
}));

await TestBed.configureTestingModule({
imports: [SitesModule, BrowserAnimationsModule],
providers: [{ provide: SitesService, useValue: mockSitesService }],
}).compileComponents();
});

beforeEach(() => {
fixture = TestBed.createComponent(SitesComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});

it('should create', () => {
expect(component).toBeTruthy();
});

it('should store the sites in memory', () => {
expect(mockSitesService.getSites).toHaveBeenCalledWith(0, 10);
expect(component.sites).toEqual(sites);
expect(component.totalCount).toEqual(1);
expect(component.totalFilteredCount).toEqual(1);
});

it('should change pages', () => {
const e: PageEvent = {
pageSize: 11,
pageIndex: 2,
length: 100,
};

component.pageChanged(e);

expect(component.pageSize).toEqual(11);
expect(component.currentPage).toEqual(2);
expect(refetch).toHaveBeenCalledWith({
searchOptions: {
offset: 22,
batchSize: 11,
sortOptions: undefined,
filter: undefined,
},
});
});

it('should sort', () => {
const e: Sort = {
active: 'site',
direction: 'asc',
};

component.sortData(e);

const sortOptions: SortOptions = {
direction: 'ASC',
field: 'site',
};

expect(component.sortOptions).toEqual(sortOptions);
expect(refetch).toHaveBeenCalledWith({
searchOptions: {
offset: 0,
batchSize: 10,
sortOptions,
filter: undefined,
},
});
});

it('should filter', () => {
const filters: SearchFilterItem[] = [
{
field: 'name',
operator: '=',
value: 'AHU1',
},
];

component.filterData(filters);

const filter: string = JSON.stringify(filters);

expect(component.filter).toEqual(filter);
expect(refetch).toHaveBeenCalledWith({
searchOptions: {
offset: 0,
batchSize: 10,
sortOptions: undefined,
filter,
},
});
});
});
Loading