Skip to content

Commit

Permalink
Handle importing .graphql files.
Browse files Browse the repository at this point in the history
  • Loading branch information
imolorhe committed Nov 10, 2019
1 parent d6cf071 commit c0c47d1
Show file tree
Hide file tree
Showing 8 changed files with 108 additions and 20 deletions.
3 changes: 2 additions & 1 deletion src/app/actions/gql-schema/gql-schema.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Action } from '@ngrx/store';
import { GraphQLSchema } from 'graphql';

export const SET_INTROSPECTION = 'SET_INTROSPECTION';
export const SET_INTROSPECTION_FROM_DB = 'SET_INTROSPECTION_FROM_DB';
Expand All @@ -25,7 +26,7 @@ export class SetIntrospectionFromDbAction implements Action {
export class SetSchemaAction implements Action {
readonly type = SET_SCHEMA;

constructor(public windowId: string, public payload: any) { }
constructor(public windowId: string, public payload: GraphQLSchema) { }
}

export class SetSchemaSDLAction implements Action {
Expand Down
19 changes: 16 additions & 3 deletions src/app/containers/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ import {
DonationService,
ElectronAppService,
KeybinderService,
PluginRegistryService
PluginRegistryService,
QueryCollectionService
} from '../../services';

import config from '../../config';
Expand Down Expand Up @@ -82,6 +83,7 @@ export class AppComponent implements OnDestroy {
private electronApp: ElectronAppService,
private keybinder: KeybinderService,
private pluginRegistry: PluginRegistryService,
private collectionService: QueryCollectionService,
) {
this.settings$ = this.store.pipe(select('settings')).pipe(distinctUntilChanged());
this.collection$ = this.store.select('collection');
Expand Down Expand Up @@ -420,10 +422,21 @@ export class AppComponent implements OnDestroy {
this.pluginRegistry.setPluginActive(plugin.name, !plugin.isActive);
}

fileDropped(event) {
async fileDropped(event) {
const dataTransfer: DataTransfer = event.mouseEvent.dataTransfer;
if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
this.windowService.handleImportedFile(dataTransfer.files);
try {
// Handle window import
await this.windowService.handleImportedFile(dataTransfer.files);
} catch (error) {
debug.log(error);
try {
// Handle collection import
await this.collectionService.handleImportedFile(dataTransfer.files)
} catch (collectionError) {
debug.log(collectionError);
}
}
}
}

Expand Down
10 changes: 5 additions & 5 deletions src/app/effects/query.ts
Original file line number Diff line number Diff line change
Expand Up @@ -633,11 +633,11 @@ export class QueryEffects {
switchMap(res => {

if (res.data.schema.schema) {
const sdl = this.gqlService.getSDL(res.data.schema.schema);

if (sdl) {
downloadData(sdl, 'sdl', { fileType: 'gql' });
}
this.gqlService.getSDL(res.data.schema.schema).then(sdl => {
if (sdl) {
downloadData(sdl, 'sdl', { fileType: 'gql' });
}
})
}
return observableEmpty();
}),
Expand Down
3 changes: 2 additions & 1 deletion src/app/reducers/gql-schema/gql-schema.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { Action } from '@ngrx/store';

import * as gqlSchema from '../../actions/gql-schema/gql-schema';
import { GraphQLSchema } from 'graphql';

export interface State {
// Adding undefined for backward compatibility
introspection?: object;
// Adding undefined for backward compatibility
schema?: object;
schema?: GraphQLSchema;
sdl: string;
allowIntrospection: boolean;
}
Expand Down
2 changes: 2 additions & 0 deletions src/app/reducers/windows.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { Action, ActionReducer } from '@ngrx/store';
import * as windowsActions from '../actions/windows/windows';
import * as fromRoot from './';
import { debug } from 'app/utils/logger';
import { GraphQLSchema } from 'graphql';

export interface State {
[id: string]: fromRoot.PerWindowState;
Expand Down Expand Up @@ -31,6 +32,7 @@ export interface ExportWindowState {
* ID for window in collection
*/
windowIdInCollection?: string;
gqlSchema?: GraphQLSchema;
}

/**
Expand Down
13 changes: 12 additions & 1 deletion src/app/services/query-collection/query-collection.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { StorageService } from '../storage/storage.service';
import * as uuid from 'uuid/v4';
import { debug } from 'app/utils/logger';
import { IQueryCollection, ExportCollectionState } from 'app/reducers/collection/collection';
import { getFileStr } from 'app/utils';

// Handling hierarchical data
// https://stackoverflow.com/questions/4048151/what-are-the-options-for-storing-hierarchical-data-in-a-relational-database
Expand Down Expand Up @@ -107,7 +108,7 @@ export class QueryCollectionService {
return this.importCollectionData(JSON.parse(data));
} catch (err) {
debug.log('The file is invalid.', err);
return throwError(new Error('String is empty.'));
return throwError(err);
}
}

Expand All @@ -133,6 +134,16 @@ export class QueryCollectionService {
}
}

handleImportedFile(files) {
return getFileStr(files).then((dataStr: string) => {
try {
this.importCollectionDataFromJson(dataStr);
} catch (error) {
debug.log('There was an issue importing the file.', error);
}
});
}

getAll() {
return observableFrom(this.storage.queryCollections.toArray());
}
Expand Down
72 changes: 66 additions & 6 deletions src/app/services/window.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,16 +20,19 @@ import * as windowsMetaActions from '../actions/windows-meta/windows-meta';
import * as preRequestActions from '../actions/pre-request/pre-request';
import * as streamActions from '../actions/stream/stream';
import * as localActions from '../actions/local/local';
import * as gqlSchemaActions from '../actions/gql-schema/gql-schema';

import { getFileStr } from '../utils';
import { parseCurlToObj } from '../utils/curl';
import { debug } from 'app/utils/logger';
import { GqlService } from './gql/gql.service';

@Injectable()
export class WindowService {

constructor(
private store: Store<fromRoot.State>
private store: Store<fromRoot.State>,
private gqlService: GqlService,
) { }

newWindow(opts: { title?, url?, collectionId?, windowIdInCollection? } = {}): Observable<any> {
Expand Down Expand Up @@ -90,6 +93,7 @@ export class WindowService {
windowName: `${window.layout.title} (Copy)`,
preRequestScript: window.preRequest.script,
preRequestScriptEnabled: window.preRequest.enabled,
gqlSchema: window.schema.schema,
};

return this.importWindowData(windowData);
Expand Down Expand Up @@ -224,6 +228,10 @@ export class WindowService {
this.store.dispatch(new preRequestActions.SetPreRequestScriptAction(windowId, { script: data.preRequestScript }));
}

if (data.gqlSchema) {
this.store.dispatch(new gqlSchemaActions.SetSchemaAction(windowId, data.gqlSchema));
}

this.store.dispatch(new windowsMetaActions.SetActiveWindowIdAction({ windowId }));
});
} catch (err) {
Expand All @@ -236,14 +244,62 @@ export class WindowService {
* @param dataStr data
*/
importStringData(dataStr) {
const invalidFileError = new Error('Invalid Altair window file.');
try {
const parsed = JSON.parse(dataStr);

if (parsed.type === 'window') {
this.importWindowData(parsed);
if (parsed.type === 'window' && parsed.version === 1) {
return this.importWindowData(parsed);
}
throw invalidFileError;
} catch (err) {
debug.log('There was an issue importing the file.');
debug.log('Invalid Altair window file.', err);
try {
// Check if sdl file
const schema = this.gqlService.sdlToSchema(dataStr);
if (schema) {
// Import only schema
return this.importWindowData({
version: 1,
type: 'window',
apiUrl: '',
headers: [],
preRequestScript: '',
preRequestScriptEnabled: false,
query: '',
subscriptionUrl: '',
variables: '{}',
windowName: '',
gqlSchema: schema,
});
}
throw invalidFileError;
} catch (sdlError) {
debug.log('Invalid SDL file.', sdlError);
try {
// Else check if graphql query
const operations = this.gqlService.getOperations(dataStr);
debug.log(operations);
if (operations && operations.length) {
// Import only query
return this.importWindowData({
version: 1,
type: 'window',
apiUrl: '',
headers: [],
preRequestScript: '',
preRequestScriptEnabled: false,
query: dataStr,
subscriptionUrl: '',
variables: '{}',
windowName: '',
});
}
throw invalidFileError;
} catch (queryError) {
throw queryError;
}
}
}
}

Expand All @@ -252,8 +308,12 @@ export class WindowService {
* @param files FilesList object
*/
handleImportedFile(files) {
getFileStr(files).then((dataStr: string) => {
this.importStringData(dataStr);
return getFileStr(files).then((dataStr: string) => {
try {
this.importStringData(dataStr);
} catch (error) {
debug.log('There was an issue importing the file.', error);
}
});
}

Expand Down
6 changes: 3 additions & 3 deletions src/app/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const fileDialog = require('file-dialog');
* @param fileName name of downloaded file
* @param opts configuration options
*/
export const downloadData = (data, fileName = 'data', opts: any = undefined) => {
export const downloadData = (data: string, fileName = 'data', opts: any = undefined) => {
let _opts = {
mimeType: 'text/plain',
dataUriAttr: 'text/plain;charset=utf-8',
Expand Down Expand Up @@ -53,7 +53,7 @@ export const downloadJson = (obj, fileName = 'response', opts: any = undefined)
* Get file data as string
* @param files FileList object
*/
export const getFileStr = files => {
export const getFileStr = (files: FileList) => {
return new Promise((resolve, reject) => {
const fileReader = new FileReader();
fileReader.onload = function (e: any) {
Expand Down Expand Up @@ -109,7 +109,7 @@ export const jsonc = (str: string) => {
return JSON.parse(str);
};

export const copyToClipboard = str => {
export const copyToClipboard = (str: string) => {
const el = document.createElement('textarea'); // Create a <textarea> element
el.value = str; // Set its value to the string that you want copied
el.setAttribute('readonly', ''); // Make it readonly to be tamper-proof
Expand Down

0 comments on commit c0c47d1

Please sign in to comment.