diff --git a/.gitignore b/.gitignore index 1d157739e0..e527c0d1fe 100644 --- a/.gitignore +++ b/.gitignore @@ -12,6 +12,7 @@ altair.zip /out /web-ext-artifacts +*.nex # dependencies /node_modules diff --git a/src/app/actions/layout/layout.ts b/src/app/actions/layout/layout.ts index fe53298ede..b74e27bc86 100644 --- a/src/app/actions/layout/layout.ts +++ b/src/app/actions/layout/layout.ts @@ -3,21 +3,28 @@ import { Action } from '@ngrx/store'; export const START_LOADING = 'START_LOADING'; export const STOP_LOADING = 'STOP_LOADING'; export const SET_WINDOW_NAME = 'SET_WINDOW_NAME'; +export const NOTIFY_EXPERIMENTAL = 'NOTIFY_EXPERIMENTAL'; export class StartLoadingAction implements Action { - readonly type = START_LOADING; + readonly type = START_LOADING; - constructor(public windowId: string) {} + constructor(public windowId: string) {} } export class StopLoadingAction implements Action { - readonly type = STOP_LOADING; + readonly type = STOP_LOADING; - constructor(public windowId: string) {} + constructor(public windowId: string) {} } export class SetWindowNameAction implements Action { - readonly type = SET_WINDOW_NAME; + readonly type = SET_WINDOW_NAME; - constructor(public windowId: string, public payload: string) {} + constructor(public windowId: string, public payload: string) {} +} + +export class NotifyExperimentalAction implements Action { + readonly type = NOTIFY_EXPERIMENTAL; + + constructor(public windowId: string) {} } diff --git a/src/app/containers/window/window.component.ts b/src/app/containers/window/window.component.ts index c012e43df4..8ee8bfe2c6 100644 --- a/src/app/containers/window/window.component.ts +++ b/src/app/containers/window/window.component.ts @@ -17,6 +17,7 @@ import * as headerActions from '../../actions/headers/headers'; import * as variableActions from '../../actions/variables/variables'; import * as dialogsActions from '../../actions/dialogs/dialogs'; import * as docsActions from '../../actions/docs/docs'; +import * as layoutActions from '../../actions/layout/layout'; import { QueryService, GqlService, NotifyService } from '../../services'; import { graphql } from 'graphql'; @@ -180,6 +181,7 @@ export class WindowComponent implements OnInit { addQueryToEditor(queryData: { query: String, meta: any }) { // Add the query to what is already in the editor this.store.dispatch(new queryActions.SetQueryAction(`${this.query}\n${queryData.query}`, this.windowId)); + this.store.dispatch(new layoutActions.NotifyExperimentalAction(this.windowId)); // If the query has args if (queryData.meta.hasArgs) { diff --git a/src/app/effects/query.ts b/src/app/effects/query.ts index c2b1becd4d..837526b5fb 100644 --- a/src/app/effects/query.ts +++ b/src/app/effects/query.ts @@ -135,72 +135,85 @@ export class QueryEffects { @Effect() saveIntrospectionToDb$: Observable = this.actions$ - .ofType(gqlSchemaActions.SET_INTROSPECTION) - .map((data: queryActions.Action) => { - this.queryService.storeIntrospection(data.payload, data.windowId); - return new dbActions.SaveIntrospectionSuccessAction(); - }); + .ofType(gqlSchemaActions.SET_INTROSPECTION) + .map((data: queryActions.Action) => { + this.queryService.storeIntrospection(data.payload, data.windowId); + return new dbActions.SaveIntrospectionSuccessAction(); + }); @Effect() getIntrospectionForUrl$: Observable = this.actions$ - .ofType(queryActions.SEND_INTROSPECTION_QUERY_REQUEST) - .withLatestFrom(this.store, (action: queryActions.Action, state) => { - return { data: state.windows[action.windowId], windowId: action.windowId, action }; - }) - .switchMap((res) => { - if (!res.data.query.url) { - return Observable.empty(); + .ofType(queryActions.SEND_INTROSPECTION_QUERY_REQUEST) + .withLatestFrom(this.store, (action: queryActions.Action, state) => { + return { data: state.windows[action.windowId], windowId: action.windowId, action }; + }) + .switchMap((res) => { + if (!res.data.query.url) { + return Observable.empty(); + } + + this.store.dispatch(new docsAction.StartLoadingDocsAction(res.windowId)); + return this.gqlService.getIntrospectionRequest(res.data.query.url) + .catch(err => { + const errorObj = err; + let allowsIntrospection = true; + + if (errorObj.errors) { + errorObj.errors.forEach(error => { + if (error.code === 'GRAPHQL_VALIDATION_ERROR') { + allowsIntrospection = false; + } + }); } - this.store.dispatch(new docsAction.StartLoadingDocsAction(res.windowId)); - return this.gqlService.getIntrospectionRequest(res.data.query.url) - .catch(err => { - const errorObj = err; - let allowsIntrospection = true; - - if (errorObj.errors) { - errorObj.errors.forEach(error => { - if (error.code === 'GRAPHQL_VALIDATION_ERROR') { - allowsIntrospection = false; - } - }); - } - - // If the server does not support introspection - if (!allowsIntrospection) { - this.store.dispatch(new gqlSchemaActions.SetAllowIntrospectionAction(false, res.windowId)); - } - this.store.dispatch(new docsAction.StopLoadingDocsAction(res.windowId)); - return Observable.empty(); - }) - .map(introspectionData => { - if (!introspectionData) { - return Observable.empty(); - } + // If the server does not support introspection + if (!allowsIntrospection) { + this.store.dispatch(new gqlSchemaActions.SetAllowIntrospectionAction(false, res.windowId)); + } + this.store.dispatch(new docsAction.StopLoadingDocsAction(res.windowId)); + return Observable.empty(); + }) + .map(introspectionData => { + if (!introspectionData) { + return Observable.empty(); + } - this.store.dispatch(new gqlSchemaActions.SetAllowIntrospectionAction(true, res.windowId)); - this.store.dispatch(new docsAction.StopLoadingDocsAction(res.windowId)); + this.store.dispatch(new gqlSchemaActions.SetAllowIntrospectionAction(true, res.windowId)); + this.store.dispatch(new docsAction.StopLoadingDocsAction(res.windowId)); - return new gqlSchemaActions.SetIntrospectionAction(introspectionData, res.windowId); - }); - }); + return new gqlSchemaActions.SetIntrospectionAction(introspectionData, res.windowId); + }); + }); @Effect() // Hides the editor set alert after it has been shown showEditorSetAlert$: Observable = this.actions$ - .ofType(queryActions.SHOW_EDITOR_ALERT) - .switchMap((data: queryActions.Action) => { - return Observable.timer(3000) - .switchMap(() => Observable.of(new queryActions.HideEditorAlertAction(data.windowId))); + .ofType(queryActions.SHOW_EDITOR_ALERT) + .switchMap((data: queryActions.Action) => { + return Observable.timer(3000) + .switchMap(() => Observable.of(new queryActions.HideEditorAlertAction(data.windowId))); + }); + + @Effect() + notifyExperimental$: Observable = this.actions$ + .ofType(layoutActions.NOTIFY_EXPERIMENTAL) + .switchMap(() => { + this.notifyService.info(` + This feature is experimental, and still in beta. + Click here to submit bugs, improvements, etc. + `, null, { + toastLife: 10000 }); + return Observable.empty(); + }); // Get the introspection after setting the URL constructor( - private actions$: Actions, - private gqlService: GqlService, - private queryService: QueryService, - private notifyService: NotifyService, - private store: Store + private actions$: Actions, + private gqlService: GqlService, + private queryService: QueryService, + private notifyService: NotifyService, + private store: Store ) {} getVariablesObj(variables) { diff --git a/src/app/reducers/windows.ts b/src/app/reducers/windows.ts index 440fabae87..2c99ed4845 100644 --- a/src/app/reducers/windows.ts +++ b/src/app/reducers/windows.ts @@ -60,7 +60,7 @@ export function windows(reducer: ActionReducer) { const _windowState = _state[action.windowId]; if (!_windowState) { // If the provided windowId is invalid, log the error and just return the state - console.error('Invalid window ID provided.'); + console.warn('Invalid window ID provided.'); return _state; } diff --git a/src/app/services/notify/notify.service.ts b/src/app/services/notify/notify.service.ts index 035732cd35..72671c58cd 100644 --- a/src/app/services/notify/notify.service.ts +++ b/src/app/services/notify/notify.service.ts @@ -9,17 +9,16 @@ export class NotifyService { ) { } - success(message, title = 'Altair') { - this.toastr.success(message, title); + success(message, title = 'Altair', opts = {}) { + this.toastr.success(message, title, opts); } - error(message, title = 'Altair') { - this.toastr.error(message, title); + error(message, title = 'Altair', opts = {}) { + this.toastr.error(message, title, opts); } - warning(message, title = 'Altair') { - this.toastr.warning(message, title); + warning(message, title = 'Altair', opts = {}) { + this.toastr.warning(message, title, opts); } - info(message, title = 'Altair') { - this.toastr.info(message, title); + info(message, title = 'Altair', opts = {}) { + this.toastr.info(message, title, opts); } - } diff --git a/src/app/services/notify/toastr-options.ts b/src/app/services/notify/toastr-options.ts index c5e36c39cf..c20e641761 100644 --- a/src/app/services/notify/toastr-options.ts +++ b/src/app/services/notify/toastr-options.ts @@ -4,4 +4,5 @@ export class CustomOption extends ToastOptions { newestOnTop = false; showCloseButton = true; positionClass = 'toast-top-center'; + enableHTML = true; } diff --git a/src/app/utils/ga.ts b/src/app/utils/ga.ts index 8d917d8d96..577b9ff1ef 100644 --- a/src/app/utils/ga.ts +++ b/src/app/utils/ga.ts @@ -24,6 +24,7 @@ export const initTracking = () => { window['_gaq'] = window['_gaq'] || []; window['_gaq'].push(['_setAccount', config.ga]); + window['_gaq'].push(['_setCustomVar', 4, 'User Device Protocol', window.location.protocol, 1]); window['_gaq'].push(['_trackPageview']); const ga = document.createElement('script');