Skip to content

Commit

Permalink
Merged in feature/SHIBUI-1311 (pull request #333)
Browse files Browse the repository at this point in the history
SHIBUI-1311 Updated dashboard provider list

Approved-by: Ryan Mathis <rmathis@unicon.net>
  • Loading branch information
rmathis committed Jul 8, 2019
2 parents b149f7f + 22ebb8d commit 70f59e3
Show file tree
Hide file tree
Showing 21 changed files with 305 additions and 180 deletions.
2 changes: 2 additions & 0 deletions backend/src/main/resources/i18n/messages.properties
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,8 @@ label.title=Title
label.enabled=Enabled
label.author=Author
label.creation-date=Creation Date
label.order=Order
label.provider-type=Provider Type

label.metadata-resolver-history=Metadata resolver history
label.metadata-version-history=Metadata Version History
Expand Down
3 changes: 1 addition & 2 deletions ui/src/app/admin/component/enable-metadata.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@
aria-label="Provider Item Accordion. Press Spacebar to open">
<resolver-item
[entity]="resolver"
[isOpen]="(entitiesOpen$ | async)[resolver.getId()]"
[isOpen]="true"
(select)="edit(resolver)"
(toggle)="toggleEntity(resolver)"
(preview)="openPreviewDialog(resolver)"
(delete)="deleteResolver(resolver)"
(toggleEnabled)="toggleResolverEnabled(resolver, !resolver.enabled)"
Expand Down
6 changes: 0 additions & 6 deletions ui/src/app/admin/component/enable-metadata.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { map } from 'rxjs/operators';
import { MetadataEntity, MetadataResolver } from '../../metadata/domain/model';
import * as fromDashboard from '../../metadata/manager/reducer';
import * as fromMetadata from '../reducer';
import { ToggleEntityDisplay } from '../../metadata/manager/action/manager.action';
import { DeleteDialogComponent } from '../../metadata/manager/component/delete-dialog.component';
import { PreviewEntity } from '../../metadata/domain/action/entity.action';
import { FileBackedHttpMetadataResolver } from '../../metadata/domain/entity';
Expand Down Expand Up @@ -40,7 +39,6 @@ export class EnableMetadataComponent implements OnInit {
map(resolvers => resolvers.map(r => new FileBackedHttpMetadataResolver(r)))
);
this.loading$ = this.store.select(fromDashboard.getSearchLoading);
this.entitiesOpen$ = this.store.select(fromDashboard.getOpenProviders);

this.total$ = this.resolvers$.pipe(map(list => list.length));
}
Expand All @@ -51,10 +49,6 @@ export class EnableMetadataComponent implements OnInit {
this.router.navigate(['metadata', 'resolver', entity.getId(), 'edit']);
}

toggleEntity(entity: MetadataEntity): void {
this.store.dispatch(new ToggleEntityDisplay(entity.getId()));
}

openPreviewDialog(entity: MetadataEntity): void {
this.store.dispatch(new PreviewEntity({ id: entity.getId(), entity }));
}
Expand Down
2 changes: 1 addition & 1 deletion ui/src/app/core/model/action.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
export interface NavigationAction {
action: ($event: Event) => void;
category: string;
category?: string;
label: string;
content: string;
icon?: string;
Expand Down
50 changes: 50 additions & 0 deletions ui/src/app/core/service/navigation.service.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { TestBed, async } from '@angular/core/testing';

import { NavigationService } from './navigation.service';

describe('Navigation Service', () => {
let service: NavigationService;

beforeEach(() => {
TestBed.configureTestingModule({
imports: [],
providers: [
NavigationService
]
});
service = TestBed.get(NavigationService);
});

it('should instantiate', () => {
expect(service).toBeDefined();
});

describe('addAction method', () => {
it('should add a navigation option to the list of actions', () => {
service.addAction('foo', {
action: () => {},
category: 'bar',
label: 'baz',
content: 'something'
});

expect(service.actionList.length).toBe(1);
});

it('should emit the value from an observable when an action is added', (done: DoneFn) => {
const action = {
action: () => { },
category: 'bar',
label: 'baz',
content: 'something'
};
const actionName = 'foo';
service.addAction(actionName, action);

service.emitter.subscribe((actions) => {
expect(actions.length).toBe(1);
done();
});
});
});
});
1 change: 0 additions & 1 deletion ui/src/app/core/service/navigation.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ export class NavigationService {
}

addAction(name: string, action: NavigationAction): NavigationAction[] {
console.log(this.actions);
this.actions[name] = action;
this.subj.next(this.actionList);
return this.actionList;
Expand Down
12 changes: 0 additions & 12 deletions ui/src/app/metadata/manager/action/manager.action.ts

This file was deleted.

24 changes: 13 additions & 11 deletions ui/src/app/metadata/manager/action/search.action.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,34 @@
import { Action } from '@ngrx/store';
import { MetadataEntity } from '../../domain/model';
import { Action, MemoizedSelector } from '@ngrx/store';
import { Metadata } from '../../domain/domain.type';

export const ENTITY_SEARCH = '[Metadata Entity Search] Entity Search';
export const ENTITY_FILTER = '[Metadata Entity Filter] Entity Filter';
export const ENTITY_SEARCH_COMPLETE = '[Metadata Entity Search] Entity Search COMPLETE';
export enum DashboardSearchActionTypes {
ENTITY_SEARCH_COMPLETE = '[Metadata Entity Search] Entity Search COMPLETE',
ENTITY_FILTER = '[Metadata Entity Filter] Entity Filter',
ENTITY_SEARCH = '[Metadata Entity Search] Entity Search',
}

/**
* Add Resolver to Collection Actions
*/
export class SearchAction implements Action {
readonly type = ENTITY_SEARCH;
readonly type = DashboardSearchActionTypes.ENTITY_SEARCH;

constructor(public payload: string) { }
constructor(public payload: { query: string, selector: MemoizedSelector<object, any[]> }) { }
}

export class FilterAction implements Action {
readonly type = ENTITY_FILTER;
readonly type = DashboardSearchActionTypes.ENTITY_FILTER;

constructor(public payload: string) { }
}

export class SearchCompleteAction implements Action {
readonly type = ENTITY_SEARCH_COMPLETE;
readonly type = DashboardSearchActionTypes.ENTITY_SEARCH_COMPLETE;

constructor(public payload: Array<MetadataEntity>) { }
constructor(public payload: Array<Metadata>) { }
}

export type Actions =
export type DashboardSearchActionsUnion =
| SearchAction
| FilterAction
| SearchCompleteAction;
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,62 @@
</div>
</div>
<div class="p-3">
<provider-search
class="w-50 d-block"
[query]="searchQuery$ | async"
[searching]="loading$ | async"
(search)="search($event)">
</provider-search>
<div class="table-responsive mt-3" *ngIf="limited$ | async;">
<table class="table table-striped w-100 table-hover table-providers">
<thead>
<th translate="label.order">Order</th>
<th class="w-25" translate="label.title">Title</th>
<th class="w-15" translate="label.provider-type">Provider Type</th>
<th class="w-15" translate="label.author">Author</th>
<th class="w-15" translate="label.creation-date">Created Date</th>
<th class="text-right w-15" translate="label.enabled">Enabled</th>
</thead>
<tbody infiniteScroll [infiniteScrollDistance]="2" [infiniteScrollThrottle]="50" (scrolled)="onScroll($event)">
<tr *ngFor="let provider of limited$ | async; index as i; first as isFirst; last as isLast;">
<td>
<div class="d-flex align-items-center">
<div *ngIf="!(isSearching$ | async)" class="provider-index text-center text-primary font-weight-bold">{{ i }}</div>
<div *ngIf="(isSearching$ | async)" class="provider-index text-center text-primary font-weight-bold">&mdash;</div>
&nbsp;
<button class="btn btn-link px-1"
(click)="updateOrderDown(provider); $event.stopPropagation();"
[disabled]="isLast || (isSearching$ | async)"
aria-label="Decrease reorder by 1">
<i class="fa text-info fa-lg fa-chevron-circle-down" aria-hidden="true"></i>
</button>
<button class="btn btn-link px-1"
(click)="updateOrderUp(provider); $event.stopPropagation();"
[disabled]="isFirst || (isSearching$ | async)"
aria-label="Increase reorder by 1">
<i class="fa text-info fa-lg fa-chevron-circle-up" aria-hidden="true"></i>
</button>
</div>
</td>
<td>
<a [routerLink]="['/', 'metadata', 'provider', provider.id, 'configuration', 'options']">{{ provider.name }}</a>
</td>
<td>{{ provider['@type'] }}</td>
<td>{{ provider.createdBy }}</td>
<td>{{ provider.createdDate | customDate : '&mdash;' }}</td>
<td class="text-right">
<span class="badge"
[class.badge-danger]="!provider.enabled"
[class.badge-success]="provider.enabled">
<span *ngIf="provider.enabled" translate="value.enabled">Enabled</span>
<span *ngIf="!provider.enabled" translate="value.disabled">Enabled</span>
</span>
</td>
</tr>
</tbody>
</table>
</div>
<!--
<ul class="list-unstyled m-0">
<li *ngFor="let provider of providers$ | async; index as i; first as isFirst; last as isLast;"
[class.mt-2]="i > 0">
Expand All @@ -25,6 +81,7 @@
</provider-item>
</li>
</ul>
-->
</div>
</div>
</section>
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
@import '../../../../theme/palette';
.provider-index {
font-size: 1.8rem;
line-height: 1.8rem;
font-weight: lighter;
font-family: monospace;
width: 45px;
}

.table-providers {
tr > td {
vertical-align: middle;
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TestBed, ComponentFixture } from '@angular/core/testing';
import { ReactiveFormsModule } from '@angular/forms';
import { Router } from '@angular/router';
import { Router, RouterModule } from '@angular/router';
import { NoopAnimationsModule } from '@angular/platform-browser/animations';
import { StoreModule, Store, combineReducers } from '@ngrx/store';
import { NgbPaginationModule, NgbModal, NgbModalModule } from '@ng-bootstrap/ng-bootstrap';
Expand All @@ -12,10 +12,10 @@ import { NgbModalStub } from '../../../../testing/modal.stub';
import { DashboardProvidersListComponent } from './dashboard-providers-list.component';
import { MetadataProvider } from '../../domain/model';
import { ProviderItemComponent } from '../component/provider-item.component';
import { FileBackedHttpMetadataResolver } from '../../domain/entity';
import { MockI18nModule } from '../../../../testing/i18n.stub';
import { CustomDatePipe } from '../../../shared/pipe/date.pipe';
import { Observable, of } from 'rxjs';
import { of } from 'rxjs';
import { InfiniteScrollModule } from 'ngx-infinite-scroll';


describe('Dashboard Providers List Page', () => {
Expand All @@ -30,6 +30,8 @@ describe('Dashboard Providers List Page', () => {
name: 'bar'
};

let dispatchSpy, selectSpy;

beforeEach(() => {
TestBed.configureTestingModule({
providers: [
Expand All @@ -44,7 +46,9 @@ describe('Dashboard Providers List Page', () => {
ReactiveFormsModule,
NgbPaginationModule,
NgbModalModule,
MockI18nModule
MockI18nModule,
InfiniteScrollModule,
RouterModule
],
declarations: [
DashboardProvidersListComponent,
Expand All @@ -61,8 +65,8 @@ describe('Dashboard Providers List Page', () => {
router = TestBed.get(Router);
modal = TestBed.get(NgbModal);

spyOn(store, 'dispatch').and.callThrough();
spyOn(store, 'select').and.returnValues(of([]), of({'foo': true}));
dispatchSpy = spyOn(store, 'dispatch').and.callThrough();
selectSpy = spyOn(store, 'select').and.returnValues(of([]), of({'foo': true}));
});

it('should compile', () => {
Expand All @@ -71,10 +75,19 @@ describe('Dashboard Providers List Page', () => {
expect(fixture).toBeDefined();
});

describe('toggleProvider method', () => {
it('should fire a redux action', () => {
instance.toggleEntity(provider);
describe('search method', () => {
it('should default to an empty string', () => {
instance.search();
expect(store.dispatch).toHaveBeenCalled();
const action = dispatchSpy.calls.mostRecent().args[0];
expect(action.payload.query).toBe('');
});

it('should search with the provided query string', () => {
instance.search('foo');
expect(store.dispatch).toHaveBeenCalled();
const action = dispatchSpy.calls.mostRecent().args[0];
expect(action.payload.query).toBe('foo');
});
});

Expand All @@ -85,4 +98,23 @@ describe('Dashboard Providers List Page', () => {
expect(router.navigate).toHaveBeenCalledWith(['metadata', 'provider', provider.resourceId, 'edit']);
});
});

describe('loadMore method', () => {
it('should call the page observable to emit the next value', (done: DoneFn) => {
instance.loadMore(5);
instance.page$.subscribe(val => {
expect(val).toBe(5);
expect(instance.page).toBe(5);
done();
});
});
});

describe('onScroll method', () => {
it('should call the loadMore method', () => {
spyOn(instance, 'loadMore');
instance.onScroll(new Event('scrolled'));
expect(instance.loadMore).toHaveBeenCalledWith(instance.page + 1);
});
});
});
Loading

0 comments on commit 70f59e3

Please sign in to comment.