Skip to content

Commit

Permalink
Added history functionality.
Browse files Browse the repository at this point in the history
Closes #166.
  • Loading branch information
imolorhe committed Dec 17, 2017
1 parent ffcdce4 commit 4adf3d8
Show file tree
Hide file tree
Showing 20 changed files with 256 additions and 14 deletions.
13 changes: 13 additions & 0 deletions src/app/actions/dialogs/dialogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Action } from '@ngrx/store';
export const TOGGLE_HEADER_DIALOG = 'TOGGLE_HEADER_DIALOG';
export const TOGGLE_VARIABLE_DIALOG = 'TOGGLE_VARIABLE_DIALOG';
export const TOGGLE_SUBSCRIPTION_URL_DIALOG = 'TOGGLE_SUBSCRIPTION_URL_DIALOG';
export const TOGGLE_HISTORY_DIALOG = 'TOGGLE_HISTORY_DIALOG';

export class ToggleHeaderDialogAction implements Action {
readonly type = TOGGLE_HEADER_DIALOG;
Expand All @@ -21,3 +22,15 @@ export class ToggleSubscriptionUrlDialogAction implements Action {

constructor(public windowId: string) { }
}

export class ToggleHistoryDialogAction implements Action {
readonly type = TOGGLE_HISTORY_DIALOG;

constructor(public windowId: string) { }
}

export type Action =
ToggleHeaderDialogAction |
ToggleVariableDialogAction |
ToggleSubscriptionUrlDialogAction |
ToggleHistoryDialogAction;
11 changes: 11 additions & 0 deletions src/app/actions/history/history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Action } from '@ngrx/store';

export const ADD_HISTORY = 'ADD_HISTORY';

export class AddHistoryAction implements Action {
readonly type = ADD_HISTORY;

constructor(public windowId: string, public payload: { query: string }) { }
}

export type Action = AddHistoryAction;
3 changes: 3 additions & 0 deletions src/app/components/action-bar/action-bar.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,10 @@ export class ActionBarComponent {
@Input() isSubscribed = false;
@Output() toggleHeaderDialog = new EventEmitter();
@Output() toggleVariableDialog = new EventEmitter();
@Output() toggleDocsChange = new EventEmitter();
@Output() reloadDocsChange = new EventEmitter();
@Output() prettifyCodeChange = new EventEmitter();
@Output() sendRequest = new EventEmitter();
@Output() clearEditorChange = new EventEmitter();
@Output() toggleSubscriptionUrlDialog = new EventEmitter();

Expand Down
22 changes: 22 additions & 0 deletions src/app/components/history-dialog/history-dialog.component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<clr-modal [clrModalOpen]="showDialog" (clrModalOpenChange)="toggleDialogChange.next()">
<h3 class="modal-title">
<div class="app-dialog-header">
<div class="app-dialog-title">{{ 'HISTORY_TEXT' | translate }}</div>
{{ 'HISTORY_SUB_TEXT' | translate }}
</div>
</h3>
<div class="modal-body">
<div class="app-dialog-body">
<div class="history-container">
<div class="history-item _track_me" *ngFor="let item of historyList; let index = index;" (click)="restoreHistory(index)">
{{item.query}}
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="app-dialog-footer">
<button class="app-button active-primary right" (click)="toggleDialogChange.next()">{{ 'DONE_BUTTON' | translate }}</button>
</div>
</div>
</clr-modal>
35 changes: 35 additions & 0 deletions src/app/components/history-dialog/history-dialog.component.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';

import { FormsModule } from '@angular/forms';
import { ClarityModule } from 'clarity-angular';
import { CodemirrorModule } from 'ng2-codemirror';
import { TranslateModule } from '@ngx-translate/core';
import { HistoryDialogComponent } from './history-dialog.component';

describe('HistoryDialogComponent', () => {
let component: HistoryDialogComponent;
let fixture: ComponentFixture<HistoryDialogComponent>;

beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ HistoryDialogComponent ],
imports: [
FormsModule,
CodemirrorModule,
ClarityModule.forRoot(),
TranslateModule.forRoot()
]
})
.compileComponents();
}));

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

it('should create', () => {
expect(component).toBeTruthy();
});
});
23 changes: 23 additions & 0 deletions src/app/components/history-dialog/history-dialog.component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';

@Component({
selector: 'app-history-dialog',
templateUrl: './history-dialog.component.html'
})
export class HistoryDialogComponent implements OnInit {

@Input() historyList = [];
@Input() showDialog = false;
@Output() toggleDialogChange = new EventEmitter();
@Output() restoreHistoryChange = new EventEmitter();

constructor() { }

ngOnInit() {
}

restoreHistory(index) {
this.restoreHistoryChange.next(index);
this.toggleDialogChange.next();
}
}
4 changes: 3 additions & 1 deletion src/app/components/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { ForkRepoComponent } from './fork-repo/fork-repo.component';
import { WindowSwitcherComponent } from './window-switcher/window-switcher.component';
import { SubscriptionUrlDialogComponent } from './subscription-url-dialog/subscription-url-dialog.component';
import { SubscriptionResultItemComponent } from './subscription-result-item/subscription-result-item.component';
import { HistoryDialogComponent } from './history-dialog/history-dialog.component';

const COMPONENTS = [
QueryEditorComponent,
Expand All @@ -28,7 +29,8 @@ const COMPONENTS = [
WindowSwitcherComponent,
SubscriptionUrlDialogComponent,
SubscriptionResultItemComponent,
UrlBoxComponent
UrlBoxComponent,
HistoryDialogComponent
];

@NgModule({
Expand Down
10 changes: 7 additions & 3 deletions src/app/components/query-result/query-result.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,17 @@
<span class="response-status-text response-stats__item">{{responseStatusText}}</span>
{{ 'QUERY_RESULT_STATUS_CODE_TEXT' | translate }}:
<span class="response-status-code response-stats__item">{{responseStatus}}</span>
{{ 'QUERY_RESULT_TIME_SPENT_TEXT' | translate }}:
<span class="response-time response-stats__item">{{responseTime}}ms</span>
<span class="response-time response-stats__item"><clr-icon shape="clock"></clr-icon> {{responseTime}}ms</span>
</div>
<div class="right">
<button class="response-stats__download-result-link" (click)="downloadResultChange.next()">{{ 'QUERY_RESULT_DOWNLOAD_RESULT_BUTTON' | translate }}</button>
</div>
</div>
<div class="query-result__bottom-actions">
<button class="btn btn-link btn-sm" (click)="downloadResultChange.next()">
<clr-icon shape="download"></clr-icon>
{{ 'QUERY_RESULT_DOWNLOAD_RESULT_BUTTON' | translate }}
</button>
</div>
<codemirror
#editor
class="app-query-result-textarea"
Expand Down
5 changes: 4 additions & 1 deletion src/app/config.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import isElectron from './utils/is_electron';

export default {
ga: 'UA-41432833-6',
add_query_depth_limit: 3,
max_windows: 10,
default_language: 'en',
languages: ['en']
languages: ['en'],
query_history_depth: isElectron ? 25 : 7
};
10 changes: 10 additions & 0 deletions src/app/containers/window/window.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ <h3 class="modal-title">
(toggleDialogChange)="toggleSubscriptionUrlDialog()"
(subscriptionUrlChange)="updateSubscriptionUrl($event)"
></app-subscription-url-dialog>
<app-history-dialog
[historyList]="historyList"
[showDialog]="showHistoryDialog"
(toggleDialogChange)="toggleHistoryDialog()"
(restoreHistoryChange)="restoreHistory($event)"
></app-history-dialog>
</div>
</div>
<!-- <nav class="sidenav">
Expand All @@ -132,5 +138,9 @@ <h3 class="modal-title">
<clr-icon clrVerticalNavIcon shape="trash"></clr-icon>
{{ 'CLEAR_BUTTON' | translate }}
</a>
<a clrVerticalNavLink (click)="toggleHistoryDialog()" title="{{ 'HISTORY_TEXT' | translate }}">
<clr-icon clrVerticalNavIcon shape="history"></clr-icon>
{{ 'HISTORY_TEXT' | translate }}
</a>
</clr-vertical-nav>
</div>
28 changes: 27 additions & 1 deletion src/app/containers/window/window.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ import {
import { Store } from '@ngrx/store';
import { ToastsManager } from 'ng2-toastr/ng2-toastr';

import * as fromRoot from '../../reducers';
import * as fromHeader from '../../reducers/headers/headers';
import * as fromHistory from '../../reducers/history/history';

import * as queryActions from '../../actions/query/query';
import * as headerActions from '../../actions/headers/headers';
Expand All @@ -17,6 +19,7 @@ import * as dialogsActions from '../../actions/dialogs/dialogs';
import * as docsActions from '../../actions/docs/docs';
import * as layoutActions from '../../actions/layout/layout';
import * as schemaActions from '../../actions/gql-schema/gql-schema';
import * as historyActions from '../../actions/history/history';

import { QueryService, GqlService, NotifyService } from '../../services';
import { graphql } from 'graphql';
Expand All @@ -35,9 +38,12 @@ export class WindowComponent implements OnInit {
initialQuery = '';
query = '';
queryResult = '';

showHeaderDialog = false;
showVariableDialog = false;
showSubscriptionUrlDialog = false;
showHistoryDialog = false;

showDocs = true;
docsIsLoading = false;
headers: fromHeader.State = [];
Expand Down Expand Up @@ -65,13 +71,15 @@ export class WindowComponent implements OnInit {
isSubscribed = false;
subscriptionResponses = [];

historyList: fromHistory.HistoryList = [];

collapsed = true;

constructor(
private queryService: QueryService,
private gql: GqlService,
private notifyService: NotifyService,
private store: Store<any>,
private store: Store<fromRoot.State>,
private toastr: ToastsManager,
private vRef: ViewContainerRef
) {
Expand All @@ -98,6 +106,7 @@ export class WindowComponent implements OnInit {
this.showHeaderDialog = data.dialogs.showHeaderDialog;
this.showVariableDialog = data.dialogs.showVariableDialog;
this.showSubscriptionUrlDialog = data.dialogs.showSubscriptionUrlDialog;
this.showHistoryDialog = data.dialogs.showHistoryDialog;
this.introspectionResult = data.schema.introspection;

this.variables = data.variables.variables;
Expand All @@ -114,6 +123,7 @@ export class WindowComponent implements OnInit {
this.subscriptionUrl = data.query.subscriptionUrl;
this.isSubscribed = data.query.isSubscribed;
this.subscriptionResponses = data.query.subscriptionResponseList;
this.historyList = data.history.list;

this.showEditorAlert = data.query.showEditorAlert;
this.editorAlertMessage = data.query.editorAlertMessage;
Expand Down Expand Up @@ -155,6 +165,11 @@ export class WindowComponent implements OnInit {
}

sendRequest() {
// Store the current query into the history if it does not already exist in the history
if (!this.historyList.filter(item => item.query.trim() === this.query.trim()).length) {
this.store.dispatch(new historyActions.AddHistoryAction(this.windowId, { query: this.query }));
}

// If the query is a subscription, subscribe to the subscription URL and send the query
if (this.gql.isSubscriptionQuery(this.query)) {
console.log('Your query is a SUBSCRIPTION!!!');
Expand Down Expand Up @@ -197,6 +212,10 @@ export class WindowComponent implements OnInit {
this.store.dispatch(new dialogsActions.ToggleSubscriptionUrlDialogAction(this.windowId));
}

toggleHistoryDialog() {
this.store.dispatch(new dialogsActions.ToggleHistoryDialogAction(this.windowId));
}

toggleDocs() {
this.store.dispatch(new docsActions.ToggleDocsViewAction(this.windowId));
}
Expand Down Expand Up @@ -253,6 +272,13 @@ export class WindowComponent implements OnInit {
this.store.dispatch(new queryActions.DownloadResultAction(this.windowId));
}

// Set the value of the item in the specified index of the history list
restoreHistory(index) {
if (this.historyList[index]) {
this.store.dispatch(new queryActions.SetQueryAction(this.historyList[index].query, this.windowId));
}
}

trackByFn(index, item) {
return index;
}
Expand Down
6 changes: 5 additions & 1 deletion src/app/reducers/dialogs/dialogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,14 @@ export interface State {
showHeaderDialog: boolean;
showVariableDialog: boolean;
showSubscriptionUrlDialog: boolean;
showHistoryDialog: boolean;
}

const initialState: State = {
showHeaderDialog: false,
showVariableDialog: false,
showSubscriptionUrlDialog: false
showSubscriptionUrlDialog: false,
showHistoryDialog: false,
};

export function dialogReducer(state = initialState, action: Action): State {
Expand All @@ -22,6 +24,8 @@ export function dialogReducer(state = initialState, action: Action): State {
return Object.assign({}, state, { showVariableDialog: !state.showVariableDialog });
case dialogs.TOGGLE_SUBSCRIPTION_URL_DIALOG:
return Object.assign({}, state, { showSubscriptionUrlDialog: !state.showSubscriptionUrlDialog });
case dialogs.TOGGLE_HISTORY_DIALOG:
return { ...state, showHistoryDialog: !state.showHistoryDialog };
default:
return state;
}
Expand Down
44 changes: 44 additions & 0 deletions src/app/reducers/history/history.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { Action } from '@ngrx/store';

import * as history from '../../actions/history/history';

import config from '../../config';

export interface History {
query: string;
}

export interface HistoryList extends Array<History> {
[index: number]: History;
}

export interface State {
list: HistoryList;
}

const initialState: State = {
list: []
};

export function historyReducer(state = initialState, action: history.Action): State {
switch (action.type) {
case history.ADD_HISTORY:
const _state = { ...state };

// If the items in the list is more than the allowed limit, remove the last item
if (state.list.length >= config.query_history_depth) {
// Remove the last item in the list
_state.list.pop();
}

return {
..._state,
list: [
{ query: action.payload.query }, // Add the new item to the top of the list
..._state.list
]
};
default:
return state;
}
}
Loading

0 comments on commit 4adf3d8

Please sign in to comment.