Skip to content

Commit

Permalink
feat(dh): load actors and add filters to Actors page (#1942)
Browse files Browse the repository at this point in the history
* refactor(dh): replace Actor interface with one from GraphQL

* feat(dh): add query for getting actors

* feat(dh): add filters to actors page

* feat(dh): generate GraphQL schema

* chore(dh): mock get actor query

* feat(dh): load actors

* chore: add license

* chore(dh): update feature flags date

* refactor(dh): replace destroy pattern with unsubscribe

---------

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
dzhavat and github-actions[bot] authored Aug 9, 2023
1 parent a289585 commit a7a6b58
Show file tree
Hide file tree
Showing 10 changed files with 301 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -559,6 +559,11 @@
"name": "Navn",
"marketRole": "Markedsrolle",
"status": "Status"
},
"filters": {
"marketRole": "Markedsrolle",
"status": "Status",
"reset": "Nulstil"
}
},
"marketRolesOverview": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,11 @@
"name": "Name",
"marketRole": "Market role",
"status": "Status"
},
"filters": {
"marketRole": "Market role",
"status": "Status",
"reset": "Reset"
}
},
"marketRolesOverview": {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
query GetActors {
actors {
id
glnOrEicNumber
name
marketRole
status
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "dh-market-participant-actors-data-access-graphql",
"$schema": "../../../../../node_modules/nx/schemas/project-schema.json",
"projectType": "library",
"sourceRoot": "libs/dh/market-participant/actors/data-access-graphql",
"prefix": "dh",
"tags": ["product:dh", "domain:market-participant", "type:data-access"]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* @license
* Copyright 2020 Energinet DataHub A/S
*
* Licensed under the Apache License, Version 2.0 (the "License2");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { MarketParticipantEicFunction } from '@energinet-datahub/dh/shared/domain';
import { ActorStatus } from '@energinet-datahub/dh/shared/domain/graphql';

export interface ActorsFilters {
actorStatus: ActorStatus[] | null;
marketRoles: MarketParticipantEicFunction[] | null;
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,15 +22,23 @@ <h3>
</h3>
</watt-card-title>

<dh-actors-filters
class="watt-space-stack-m"
[initial]="filters$.value"
(filter)="filters$.next($event)"
/>

<watt-table
[dataSource]="dataSource"
[columns]="columns"
sortBy="name"
sortDirection="asc"
[sortClear]="false"
>
<ng-container *wattTableCell="columns['glnOrEic']; header: t('columns.glnOrEic'); let actor">
{{ actor.glnOrEic }}
<ng-container
*wattTableCell="columns['glnOrEicNumber']; header: t('columns.glnOrEic'); let actor"
>
{{ actor.glnOrEicNumber }}
</ng-container>

<ng-container *wattTableCell="columns['name']; header: t('columns.name'); let actor">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,20 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Component } from '@angular/core';
import { Component, OnDestroy, OnInit, inject } from '@angular/core';
import { TranslocoModule } from '@ngneat/transloco';
import { BehaviorSubject, Subscription } from 'rxjs';
import { Apollo } from 'apollo-angular';
import type { ResultOf } from '@graphql-typed-document-node/core';

import { WATT_CARD } from '@energinet-datahub/watt/card';
import { WATT_TABLE, WattTableColumnDef, WattTableDataSource } from '@energinet-datahub/watt/table';
import { GetActorsDocument } from '@energinet-datahub/dh/shared/domain/graphql';

interface Actor {
glnOrEic: string;
name: string;
marketRole: string;
status: string;
}
import { DhActorsFiltersComponent } from './filters/dh-actors-filters.component';
import { ActorsFilters } from './actors-filters';

export type Actor = ResultOf<typeof GetActorsDocument>['actors'][0];

@Component({
standalone: true,
Expand All @@ -38,15 +40,41 @@ interface Actor {
}
`,
],
imports: [TranslocoModule, WATT_TABLE, WATT_CARD],
imports: [TranslocoModule, DhActorsFiltersComponent, WATT_TABLE, WATT_CARD],
})
export class DhActorsOverviewComponent {
export class DhActorsOverviewComponent implements OnInit, OnDestroy {
private apollo = inject(Apollo);
private getActorsSubscription?: Subscription;

getActorsQuery$ = this.apollo.watchQuery({
useInitialLoading: true,
notifyOnNetworkStatusChange: true,
query: GetActorsDocument,
});

dataSource = new WattTableDataSource<Actor>([]);

columns: WattTableColumnDef<Actor> = {
glnOrEic: { accessor: 'glnOrEic' },
glnOrEicNumber: { accessor: 'glnOrEicNumber' },
name: { accessor: 'name' },
marketRole: { accessor: 'marketRole' },
status: { accessor: 'status' },
};

filters$ = new BehaviorSubject<ActorsFilters>({
actorStatus: null,
marketRoles: null,
});

ngOnInit(): void {
this.getActorsSubscription = this.getActorsQuery$.valueChanges.subscribe({
next: (result) => {
this.dataSource.data = result.data?.actors;
},
});
}

ngOnDestroy(): void {
this.getActorsSubscription?.unsubscribe();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
/**
* @license
* Copyright 2020 Energinet DataHub A/S
*
* Licensed under the Apache License, Version 2.0 (the "License2");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import {
ChangeDetectionStrategy,
Component,
EventEmitter,
Input,
OnDestroy,
OnInit,
Output,
inject,
} from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { TranslocoModule, TranslocoService } from '@ngneat/transloco';
import { Observable, Subscription, debounceTime, map } from 'rxjs';
import { RxPush } from '@rx-angular/template/push';

import { WATT_FORM_FIELD } from '@energinet-datahub/watt/form-field';
import { WattButtonComponent } from '@energinet-datahub/watt/button';
import {
WattDropdownComponent,
WattDropdownOption,
WattDropdownOptions,
} from '@energinet-datahub/watt/dropdown';
import { MarketParticipantEicFunction } from '@energinet-datahub/dh/shared/domain';
import { ActorStatus } from '@energinet-datahub/dh/shared/domain/graphql';

import { ActorsFilters } from '../actors-filters';

/** Helper function for creating form control with `nonNullable` based on value. */
const makeFormControl = <T>(value: T | null = null) =>
new FormControl(value, { nonNullable: Boolean(value) });

@Component({
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
imports: [
ReactiveFormsModule,
TranslocoModule,
RxPush,
WATT_FORM_FIELD,
WattButtonComponent,
WattDropdownComponent,
],
selector: 'dh-actors-filters',
styles: [
`
:host {
display: block;
}
form {
display: flex;
gap: 1rem;
align-items: center;
overflow: auto;
overflow-y: hidden;
}
watt-button {
margin-left: auto;
}
`,
],
template: `
<form
[formGroup]="formGroup"
*transloco="let t; read: 'marketParticipant.actorsOverview.filters'"
>
<watt-form-field>
<watt-dropdown
formControlName="actorStatus"
[options]="actorStatusOptions"
[multiple]="true"
[chipMode]="true"
[placeholder]="t('status')"
/>
</watt-form-field>
<watt-form-field>
<watt-dropdown
formControlName="marketRole"
[options]="marketRolesOptions | push"
[multiple]="true"
[chipMode]="true"
[placeholder]="t('marketRole')"
/>
</watt-form-field>
<watt-button variant="text" icon="undo" type="reset">{{ t('reset') }}</watt-button>
</form>
`,
})
export class DhActorsFiltersComponent implements OnInit, OnDestroy {
private transloco = inject(TranslocoService);
private formGroupSubscription?: Subscription;

@Input({ required: true }) initial!: ActorsFilters;
@Output() filter = new EventEmitter<ActorsFilters>();

formGroup!: FormGroup;

actorStatusOptions: WattDropdownOptions = this.buildActorStatusOptions();
marketRolesOptions = this.buildMarketRolesOptions();

ngOnInit() {
this.formGroup = new FormGroup({
actorStatus: makeFormControl<ActorStatus[] | null>(this.initial.actorStatus),
marketRole: makeFormControl<MarketParticipantEicFunction[] | null>(this.initial.marketRoles),
});

this.formGroupSubscription = this.formGroup.valueChanges
.pipe(debounceTime(250))
.subscribe((value) => this.filter.emit(value));
}

ngOnDestroy() {
this.formGroupSubscription?.unsubscribe();
}

private buildActorStatusOptions(): WattDropdownOptions {
return Object.keys(ActorStatus).map((key) => ({
displayValue: key,
value: key,
}));
}

private buildMarketRolesOptions(): Observable<WattDropdownOptions> {
return this.transloco.selectTranslateObject('marketParticipant.marketRoles').pipe(
map((marketRolesTranslations) =>
Object.keys(MarketParticipantEicFunction).map(
(marketRole): WattDropdownOption => ({
value: marketRole,
displayValue: marketRolesTranslations[marketRole],
})
)
)
);
}
}
26 changes: 26 additions & 0 deletions libs/dh/shared/data-access-msw/src/lib/mocks/marketParticipant.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,13 @@
*/
import { rest } from 'msw';

import {
ActorStatus,
EicFunction,
mockGetActorsQuery,
GetActorsQuery,
} from '@energinet-datahub/dh/shared/domain/graphql';

import organizationsData from './data/marketParticipantOrganizations.json';
import { marketParticipantOrganizationsWithActors } from './data/marketParticipantOrganizationsWithActors';
import gridAreaData from './data/marketParticipantGridArea.json';
Expand All @@ -25,6 +32,18 @@ import actorContactsData from './data/marketPaticipantActorContacts.json';
import organizationData from './data/marketPaticipantOrganization.json';
import userRoleData from './data/marketParticipantUserRoleTemplates.json';

const actorsMockData: GetActorsQuery = {
actors: [
{
glnOrEicNumber: '5790000555555',
id: 'efad0fee-9d7c-49c6-7c17-08da5f28ddb1',
name: 'Test Actor',
marketRole: EicFunction.BalanceResponsibleParty,
status: ActorStatus.Active,
},
],
};

export function marketParticipantMocks(apiBase: string) {
return [
getOrganizations(apiBase),
Expand All @@ -35,6 +54,7 @@ export function marketParticipantMocks(apiBase: string) {
getActorContact(apiBase),
getOrganization(apiBase),
getUserRoles(apiBase),
getActors(),
];
}

Expand Down Expand Up @@ -107,3 +127,9 @@ function getUserRoles(apiBase: string) {
return res(ctx.json(userRoleData));
});
}

function getActors() {
return mockGetActorsQuery((req, res, ctx) => {
return res(ctx.delay(300), ctx.data(actorsMockData));
});
}
Loading

0 comments on commit a7a6b58

Please sign in to comment.