-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge remote-tracking branch 'origin/members'
- Loading branch information
Showing
12 changed files
with
387 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import { ActivatedRouteSnapshot, ResolveFn, RouterStateSnapshot, Routes } from '@angular/router' | ||
import { AuthGuard } from '../account/auth.guard' | ||
import { Observable, filter, of, take } from 'rxjs' | ||
import { inject } from '@angular/core' | ||
import { IMember, Member } from './model/member.model' | ||
import { MemberService } from './service/member.service' | ||
import { MembersComponent } from './members.component' | ||
|
||
export const MemberResolver: ResolveFn<Member | null> = ( | ||
route: ActivatedRouteSnapshot, | ||
state: RouterStateSnapshot, | ||
memberService: MemberService = inject(MemberService) | ||
): Observable<IMember | null> => { | ||
if (route.paramMap.get('id')) { | ||
return memberService.find(route.paramMap.get('id')!).pipe( | ||
filter<IMember>((member: IMember) => !!member), | ||
take(1) | ||
) | ||
} else { | ||
return of(null) | ||
} | ||
} | ||
|
||
export const memberRoutes: Routes = [ | ||
{ | ||
path: 'members', | ||
component: MembersComponent, | ||
data: { | ||
authorities: ['ROLE_ADMIN'], | ||
defaultSort: 'id,asc', | ||
pageTitle: 'gatewayApp.msUserServiceMSMember.home.title.string', | ||
}, | ||
canActivate: [AuthGuard], | ||
}, | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
<div> | ||
<h1 id="page-heading" class="mt-3" i18n="@@gatewayApp.msUserServiceMSMember.home.title.string">Manage members</h1> | ||
<div class="row justify-content-end"> | ||
<div class="col-md-12 mb-2"> | ||
<button id="jh-create-entity" class="btn btn-primary float-right jh-create-entity create-ms-member ml-1" [routerLink]="['/member/new']"> | ||
<fa-icon [icon]="'plus'"></fa-icon> | ||
<span i18n="@@gatewayApp.msUserServiceMSMember.home.createLabel.string"> | ||
Add member | ||
</span> | ||
</button> | ||
<button id="jh-upload-ms-member" class="btn btn-primary float-right jh-create-entity create-ms-member ml-1" [routerLink]="['/', 'member', { outlets: { popup: 'import'} }]"> | ||
<fa-icon [icon]="'plus'"></fa-icon> | ||
<span i18n="@@gatewayApp.msUserServiceMSMember.home.uploadLabel.string"> | ||
Import members from CSV | ||
</span> | ||
</button> | ||
</div> | ||
</div> | ||
<div class="row"> | ||
<div class="col-md-12"> | ||
<div class="input-group filter-group justify-content-end"> | ||
<div class="filter-input"> | ||
<input type="text" (keyup.enter)="submitSearch()" [(ngModel)]="searchTerm" i18n-placeholder="@@global.form.search.string" placeholder="Search..." ng-model="selected" class="form-control"> | ||
<button *ngIf="submittedSearchTerm" class="reset" (click)="resetSearch()"><fa-icon aria-hidden="true" [icon]="faTimes" [styles]="{'color': '#2e7f9f'}"></fa-icon></button> | ||
</div> | ||
<button class="search" (click)="submitSearch()"><fa-icon aria-hidden="true" [icon]="faSearch" [styles]="{'color': '#2e7f9f'}"></fa-icon></button> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="row"> | ||
<div class="col-md-12"> | ||
<app-alert></app-alert> | ||
<div class="alert alert-warning" *ngIf="members?.length === 0"> | ||
<span i18n="@@gatewayApp.msUserServiceMSMember.home.notFound.string">No members to show</span> | ||
</div> | ||
</div> | ||
</div> | ||
<div class="table-responsive" *ngIf="members!.length > 0"> | ||
<table class="table table-striped"> | ||
<thead> | ||
<tr> | ||
<th (click)="updateSort('salesforceId')"><span i18n="@@gatewayApp.msUserServiceMSMember.salesforceId.string">Salesforce Id</span> <fa-icon class="ml-2" *ngIf="sortColumn === 'salesforceId'" [icon]="ascending ? faSortDown : faSortUp"></fa-icon></th> | ||
<th (click)="updateSort('clientName')"><span i18n="@@gatewayApp.msUserServiceMSMember.clientName.string">Member Name</span> <fa-icon class="ml-2" *ngIf="sortColumn === 'clientName'" [icon]="ascending ? faSortDown : faSortUp"></fa-icon></th> | ||
<th (click)="updateSort('isConsortiumLead')"><span i18n="@@gatewayApp.msUserServiceMSMember.isConsortiumLead.string">Consortium Lead</span> <fa-icon class="ml-2" *ngIf="sortColumn === 'isConsortiumLead'" [icon]="ascending ? faSortDown : faSortUp"></fa-icon></th> | ||
<th (click)="updateSort('parentSalesforceId')"><span i18n="@@gatewayApp.msUserServiceMSMember.parentSalesforceId.string">Parent Salesforce Id</span> <fa-icon class="ml-2" *ngIf="sortColumn === 'parentSalesforceId'" [icon]="ascending ? faSortDown : faSortUp"></fa-icon></th> | ||
<th (click)="updateSort('assertionServiceEnabled')"><span i18n="@@gatewayApp.msUserServiceMSMember.assertionServiceEnabled.string">Assertions Enabled</span> <fa-icon class="ml-2" *ngIf="sortColumn === 'assertionServiceEnabled'" [icon]="ascending ? faSortDown : faSortUp"></fa-icon></th> | ||
<th (click)="updateSort('lastModifiedDate')"><span i18n="@@gatewayApp.msUserServiceMSMember.lastModifiedDate.string">Last Modified</span> <fa-icon class="ml-2" *ngIf="sortColumn === 'lastModifiedDate'" [icon]="ascending ? faSortDown : faSortUp"></fa-icon></th> | ||
<th></th> | ||
</tr> | ||
</thead> | ||
<tbody> | ||
<tr *ngFor="let member of members ;trackBy: trackId"> | ||
<td><a [routerLink]="['/members', member.id, 'view' ]">{{member.salesforceId}}</a></td> | ||
<td>{{member.clientName}}</td> | ||
<td class="text-center"> | ||
<span class="sr-only">{{member.isConsortiumLead}}</span> | ||
<fa-icon aria-hidden="true" *ngIf="member.isConsortiumLead" [icon]="faCheckCircle" [styles]="{'color': '#28a745'}"></fa-icon> | ||
<fa-icon aria-hidden="true" *ngIf="!member.isConsortiumLead" [icon]="faTimesCircle" [styles]="{'color': '#f22112'}"></fa-icon> | ||
</td> | ||
<td>{{member.parentSalesforceId}}</td> | ||
<td class="text-center"> | ||
<span class="sr-only">{{member.assertionServiceEnabled}}</span> | ||
<fa-icon aria-hidden="true" *ngIf="member.assertionServiceEnabled" [icon]="faCheckCircle" [styles]="{'color': '#28a745'}"></fa-icon> | ||
<fa-icon aria-hidden="true" *ngIf="!member.assertionServiceEnabled" [icon]="faTimesCircle" [styles]="{'color': '#f22112'}"></fa-icon> | ||
</td> | ||
<td>{{member.lastModifiedDate?.toString() | date:'medium'}}</td> | ||
<td class="text-right"> | ||
<div class="btn-group"> | ||
<button type="submit" | ||
[routerLink]="['/members', member.id, 'edit']" | ||
class="btn btn-primary btn-sm ml-1"> | ||
<fa-icon [icon]="'pencil-alt'"></fa-icon> | ||
<span class="d-none d-md-inline" i18n="@@entity.action.edit.string">Edit</span> | ||
</button> | ||
</div> | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
</div> | ||
<div [hidden]="members?.length === 0"> | ||
<div class="row justify-content-center"> | ||
<p>{{ itemCount }}</p> | ||
</div> | ||
<div class="row justify-content-center"> | ||
<ngb-pagination [collectionSize]="totalItems" [(page)]="page" [pageSize]="itemsPerPage" [maxSize]="5" [rotate]="true" [boundaryLinks]="true" (pageChange)="loadPage()"></ngb-pagination> | ||
</div> | ||
</div> | ||
</div> |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
import { ComponentFixture, TestBed } from '@angular/core/testing'; | ||
|
||
import { MembersComponent } from './members.component'; | ||
|
||
describe('MembersComponent', () => { | ||
let component: MembersComponent; | ||
let fixture: ComponentFixture<MembersComponent>; | ||
|
||
beforeEach(() => { | ||
TestBed.configureTestingModule({ | ||
declarations: [MembersComponent] | ||
}); | ||
fixture = TestBed.createComponent(MembersComponent); | ||
component = fixture.componentInstance; | ||
fixture.detectChanges(); | ||
}); | ||
|
||
it('should create', () => { | ||
expect(component).toBeTruthy(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,176 @@ | ||
import { Component, OnDestroy, OnInit } from '@angular/core' | ||
import { IMember } from './model/member.model' | ||
import { Subscription } from 'rxjs' | ||
import { | ||
faCheckCircle, | ||
faSearch, | ||
faSortDown, | ||
faSortUp, | ||
faTimes, | ||
faTimesCircle, | ||
} from '@fortawesome/free-solid-svg-icons' | ||
import { MemberService } from './service/member.service' | ||
import { ActivatedRoute, Router } from '@angular/router' | ||
import { EventType, ITEMS_PER_PAGE } from '../app.constants' | ||
import { AccountService } from '../account/service/account.service' | ||
import { EventService } from '../shared/service/event.service' | ||
import { AlertService } from '../shared/service/alert.service' | ||
import { IMemberPage } from './model/member-page.model' | ||
|
||
@Component({ | ||
selector: 'app-members', | ||
templateUrl: './members.component.html', | ||
styleUrls: ['./members.component.scss'], | ||
}) | ||
export class MembersComponent implements OnInit { | ||
currentAccount: any | ||
members: IMember[] | undefined | null | ||
error: any | ||
eventSubscriber: Subscription | undefined | ||
routeData: any | ||
links: any | ||
totalItems: any | ||
itemsPerPage: any | ||
page: any | ||
predicate: any | ||
reverse: any | ||
faTimesCircle = faTimesCircle | ||
faCheckCircle = faCheckCircle | ||
faTimes = faTimes | ||
faSearch = faSearch | ||
faSortDown = faSortDown | ||
faSortUp = faSortUp | ||
itemCount: string | undefined | ||
searchTerm: string | undefined | ||
submittedSearchTerm: string | undefined | ||
paginationHeaderSubscription: Subscription | undefined | ||
sortColumn = 'salesforceId' | ||
ascending: any | ||
|
||
constructor( | ||
protected memberService: MemberService, | ||
protected alertService: AlertService, | ||
protected accountService: AccountService, | ||
protected activatedRoute: ActivatedRoute, | ||
protected router: Router, | ||
protected eventService: EventService | ||
) { | ||
this.itemsPerPage = ITEMS_PER_PAGE | ||
this.routeData = this.activatedRoute.data.subscribe((data: any) => { | ||
this.page = data.pagingParams.page | ||
this.reverse = data.pagingParams.ascending | ||
this.predicate = data.pagingParams.predicate | ||
}) | ||
} | ||
|
||
ngOnInit() { | ||
this.loadAll() | ||
this.accountService.getAccountData().subscribe((account) => { | ||
this.currentAccount = account | ||
}) | ||
|
||
this.eventSubscriber = this.eventService.on(EventType.MEMBER_LIST_MODIFICATION).subscribe(() => { | ||
this.searchTerm = '' | ||
this.submittedSearchTerm = '' | ||
this.loadAll() | ||
}) | ||
} | ||
|
||
loadAll() { | ||
if (this.submittedSearchTerm) { | ||
this.searchTerm = this.submittedSearchTerm | ||
} else { | ||
this.searchTerm = '' | ||
} | ||
|
||
this.memberService | ||
.query({ | ||
page: this.page - 1, | ||
size: this.itemsPerPage, | ||
sort: this.sort(), | ||
filter: this.submittedSearchTerm ? encodeURIComponent(this.submittedSearchTerm) : '', | ||
}) | ||
.subscribe({ | ||
next: (res) => { | ||
if (res) { | ||
this.paginate(res) | ||
} | ||
}, | ||
}) | ||
} | ||
|
||
loadPage() { | ||
this.transition() | ||
} | ||
|
||
transition() { | ||
this.router.navigate(['/members'], { | ||
queryParams: { | ||
page: this.page, | ||
size: this.itemsPerPage, | ||
sort: this.predicate + ',' + (this.reverse ? 'asc' : 'desc'), | ||
filter: this.submittedSearchTerm ? this.submittedSearchTerm : '', | ||
}, | ||
}) | ||
this.loadAll() | ||
} | ||
|
||
clear() { | ||
this.page = 0 | ||
this.router.navigate([ | ||
'/members', | ||
{ | ||
page: this.page, | ||
sort: this.predicate + ',' + (this.reverse ? 'asc' : 'desc'), | ||
filter: this.submittedSearchTerm ? this.submittedSearchTerm : '', | ||
}, | ||
]) | ||
this.loadAll() | ||
} | ||
|
||
trackId(index: number, item: IMember) { | ||
return item.id | ||
} | ||
|
||
sort() { | ||
const result = [this.predicate + ',' + (this.reverse ? 'asc' : 'desc')] | ||
if (this.predicate !== 'id') { | ||
result.push('id') | ||
} | ||
return result | ||
} | ||
|
||
resetSearch() { | ||
this.page = 1 | ||
this.searchTerm = '' | ||
this.submittedSearchTerm = '' | ||
this.loadAll() | ||
} | ||
|
||
submitSearch() { | ||
this.page = 1 | ||
this.submittedSearchTerm = this.searchTerm | ||
this.loadAll() | ||
} | ||
|
||
protected paginate(res: IMemberPage) { | ||
this.totalItems = res.totalItems | ||
this.members = res.members | ||
const first = (this.page - 1) * this.itemsPerPage === 0 ? 1 : (this.page - 1) * this.itemsPerPage + 1 | ||
const second = this.page * this.itemsPerPage < this.totalItems ? this.page * this.itemsPerPage : this.totalItems | ||
this.itemCount = $localize`:@@global.item-count.string:Showing ${first} - ${second} of ${this.totalItems} items.` | ||
} | ||
|
||
protected onError(errorMessage: string) { | ||
this.alertService.broadcast(errorMessage) | ||
} | ||
|
||
updateSort(columnName: string) { | ||
if (this.sortColumn && this.sortColumn == columnName) { | ||
this.ascending = !this.ascending | ||
} else { | ||
this.sortColumn = columnName | ||
} | ||
this.loadPage() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import { Member } from './member.model' | ||
|
||
export interface IMemberPage { | ||
members: Member[] | null | undefined | ||
totalItems: number | null | undefined | ||
} | ||
|
||
export class MemberPage implements IMemberPage { | ||
constructor( | ||
public members: Member[], | ||
public totalItems: number | ||
) { | ||
this.members = members | ||
this.totalItems = totalItems | ||
} | ||
} |
Oops, something went wrong.