Skip to content

Commit

Permalink
Merge pull request #202 from visulate/pgoldtho/recent-history
Browse files Browse the repository at this point in the history
Pgoldtho/recent history
  • Loading branch information
pgoldtho authored Nov 6, 2020
2 parents 6a2cbdd + 2bed290 commit 9cb30e6
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 35 deletions.
2 changes: 2 additions & 0 deletions ui/src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatInputModule } from '@angular/material/input';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatCheckboxModule } from '@angular/material/checkbox';
import {MatGridListModule} from '@angular/material/grid-list';

import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
Expand Down Expand Up @@ -100,6 +101,7 @@ export function hljsLanguages() {
MatInputModule,
MatAutocompleteModule,
MatCheckboxModule,
MatGridListModule,
HighlightModule.forRoot({
languages: hljsLanguages
})
Expand Down
5 changes: 5 additions & 0 deletions ui/src/app/components/find-object/find-object.component.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
.search-box {
width: 300px;
}

.mat-card {
max-height: 400px;
overflow-y: auto;
}
75 changes: 50 additions & 25 deletions ui/src/app/components/find-object/find-object.component.html
Original file line number Diff line number Diff line change
@@ -1,25 +1,50 @@
<mat-card>
<form (keydown.enter)="processSearchRequest(searchTerm)">
<mat-form-field class="search-box" appearance="outline">
<input [(ngModel)]="searchTerm" [ngModelOptions]="{standalone: true}"
matInput placeholder="Enter a database object name" #searchBox>
</mat-form-field>
</form>
<ng-container *ngIf="searchResult">
<ng-container *ngFor="let res of searchResult.result">
<mat-nav-list>
<ng-container *ngFor="let object of res.objects">
<a mat-list-item
routerLink="/database/{{res.database}}/{{object.owner}}/{{object.object_type}}/{{object.object_name}}"
[queryParams]="{filter: object.object_name}">
{{res.database}}/{{object.owner}}/{{object.object_type}}/{{object.object_name}}
</a>
</ng-container>
<p *ngIf="res.objects?.length==0">Not found in {{res.database}}</p>
</mat-nav-list>
</ng-container>
</ng-container>

<button mat-icon-button aria-hidden="false" aria-label="cancel icon"
(click)="processCancel()"> <mat-icon>cancel</mat-icon> </button>
</mat-card>

<mat-grid-list [cols]="breakpoint" (window:resize)="onResize($event)" rowHeight=420>
<mat-grid-tile>
<mat-card>
<mat-card-title>Search
</mat-card-title>
<form (keydown.enter)="processSearchRequest(searchTerm)">
<mat-form-field class="search-box" appearance="outline">
<input [(ngModel)]="searchTerm" [ngModelOptions]="{standalone: true}" matInput
placeholder="Enter a database object name" #searchBox>
</mat-form-field>
</form>
<ng-container *ngIf="searchResult">
<ng-container *ngFor="let res of searchResult.result">
<mat-nav-list>
<ng-container *ngFor="let object of res.objects">
<a mat-list-item
routerLink="/database/{{res.database}}/{{object.owner}}/{{object.object_type}}/{{object.object_name}}"
[queryParams]="{filter: object.object_name}">
{{res.database}}/{{object.owner}}/{{object.object_type}}/{{object.object_name}}
</a>
</ng-container>
<p *ngIf="res.objects?.length==0">Not found in {{res.database}}</p>
</mat-nav-list>
</ng-container>
</ng-container>


</mat-card>

<button mat-icon-button aria-hidden="false" aria-label="cancel icon" (click)="processCancel()">
<mat-icon>cancel</mat-icon>
</button>
</mat-grid-tile>

<mat-grid-tile>

<mat-card>
<mat-card-title>Recent History
</mat-card-title>
<mat-nav-list *ngFor="let item of history">
<a mat-list-item routerLink="/database/{{item.endpoint}}/{{item.owner}}/{{item.objectType}}/{{item.objectName}}">
<!-- [queryParams]="{filter: item.filter}"> -->
/{{item.endpoint}}/{{item.owner}}/{{item.objectType}}/{{item.objectName}}</a>
</mat-nav-list>
</mat-card>


</mat-grid-tile>
</mat-grid-list>
32 changes: 27 additions & 5 deletions ui/src/app/components/find-object/find-object.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
*/
import { Component, Output, EventEmitter, ElementRef, ViewChild} from '@angular/core';
import { RestService } from 'src/app/services/rest.service';
import { FindObjectModel } from '../../models/find-object.model';
import { FindObjectModel, ObjectHistoryModel } from '../../models/find-object.model';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';

Expand All @@ -29,12 +29,14 @@ import { takeUntil } from 'rxjs/operators';
* Quick find feature tied to search icon in toolbar. Finds objects of
* a given name in each registered database
*/
export class FindObjectComponent {
export class FindObjectComponent {
public searchResult: FindObjectModel;
public history: ObjectHistoryModel[] = [];
private unsubscribe$ = new Subject<void>();
public searchTerm: string = '';
public breakpoint: number;

@ViewChild('searchBox') searchBox: ElementRef;
@ViewChild('searchBox') searchBox: ElementRef;
@Output() cancelSearchForm: EventEmitter<boolean> = new EventEmitter();

constructor(private restService: RestService) {
Expand All @@ -44,14 +46,34 @@ export class FindObjectComponent {
this.restService.getSearchResults$(searchTerm)
.pipe(takeUntil(this.unsubscribe$))
.subscribe(searchResult => {this.searchResult = searchResult;});
}
}

processCancel() {
this.cancelSearchForm.emit(false);
}

getHistory() {
let localStorageHistory = JSON.parse(localStorage.getItem('objectHistory') || '[]');
localStorageHistory.forEach((entry) => {
this.history.push(new ObjectHistoryModel
( entry.endpoint, entry.owner, entry.objectType, entry.objectName, entry.filter));
});
}

ngAfterViewInit(): void {

setTimeout(() => this.searchBox.nativeElement.focus());
this.getHistory();
}

/**
* Set the mat-grid-list cols value to 1 if screen width is less than 700px
*/
ngAfterContentInit(): void {
this.breakpoint = (window.innerWidth <= 700) ? 1 : 2;
}
onResize(event) {
this.breakpoint = (event.target.innerWidth <= 700) ? 1 : 2;
}

ngOnDestroy(): void {
Expand Down
20 changes: 18 additions & 2 deletions ui/src/app/models/find-object.model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ export class FindObjectModel implements Deserializable {
export class ResultModel implements Deserializable {
public database: string;
public objects: ObjectModel[];

deserialize(input: any): this {
Object.assign(this, input);
this.objects = input.objects.map(object => new ObjectModel().deserialize(object));
Expand All @@ -51,9 +51,25 @@ export class ObjectModel implements Deserializable {
object_name: string;
object_type: string;
status: string;

deserialize(input: any): this {
Object.assign(this, input);
return this;
}
}

export class ObjectHistoryModel {
endpoint: string;
owner: string;
objectType: string;
objectName: string;
filter: string;

constructor(endpoint: string, owner: string, objectType: string, objectName: string, filter: string){
this.endpoint = endpoint;
this.owner = owner;
this.objectType = objectType;
this.objectName = objectName;
this.filter = filter;
}
}
37 changes: 34 additions & 3 deletions ui/src/app/services/state.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export class StateService {
* `currentContext$` holds the menu selection.
* The currentContext$ observable records the current menu selection,
* the previous selection and a summary of what changed. Subscribers
* use the change summary and previous context to determine whether an API
* use the change summary and previous context to determine whether an API
* call is required.
*/
private _endpoint: string = '';
Expand All @@ -49,7 +49,7 @@ export class StateService {
new CurrentContextModel('', '', '', '', '', false, []),
new CurrentContextModel('', '', '', '', '', false, []),
[]));
private sqlEnabled = new BehaviorSubject<boolean>(false);
private sqlEnabled = new BehaviorSubject<boolean>(false);

endpoints$ = this.endpointList.asObservable();
currentContext$ = this.subjectContext.asObservable();
Expand Down Expand Up @@ -82,10 +82,14 @@ export class StateService {
this._filter = context.filter;
this._showInternal = context.showInternal;
this._objectList = context.objectList;

if (context.objectName){
this.saveContextInLocalStorage(context);
}
}

getStoredContext(){
return new CurrentContextModel(this._endpoint, this._owner, this._objectType,
return new CurrentContextModel(this._endpoint, this._owner, this._objectType,
this._objectName, this._filter, this._showInternal, this._objectList);
}

Expand All @@ -104,4 +108,31 @@ export class StateService {
this._sqlEnabled = sqlEnabled;
this.sqlEnabled.next(sqlEnabled);
}

saveContextInLocalStorage(context: CurrentContextModel) {
const maxHistoryLength = 5;
const contextObject = { "endpoint": context.endpoint,
"owner": context.owner,
"objectType": context.objectType,
"objectName": context.objectName,
"filter": context.filter
};

let history = JSON.parse(localStorage.getItem('objectHistory') || '[]');
let contextObjectPosn = history.findIndex( obj => obj.objectName === contextObject.objectName &&
obj.objectType === contextObject.objectType &&
obj.owner === contextObject.owner &&
obj.endpoint === contextObject.endpoint );

if (contextObjectPosn > -1) {
history.splice(contextObjectPosn, 1);
}
if (history.length > maxHistoryLength) {
history = history.slice(1);
}
history.push(contextObject);
localStorage.setItem('objectHistory', JSON.stringify(history));
}


}

0 comments on commit 9cb30e6

Please sign in to comment.