insomnia/app/ui/redux/modules/global.js

266 lines
7.5 KiB
JavaScript
Raw Normal View History

import electron from 'electron';
import React from 'react';
Sync Proof of Concept (#33) * Maybe working POC * Change to use remote url * Other URL too * Some logic * Got the push part working * Made some updates * Fix * Update * Add status code check * Stuff * Implemented new sync api * A bit more robust * Debounce changes * Change timeout * Some fixes * Remove .less * Better error handling * Fix base url * Support for created vs updated docs * Try silent * Silence removal too * Small fix after merge * Fix test * Stuff * Implement key generation algorithm * Tidy * stuff * A bunch of stuff for the new API * Integrated the session stuff * Stuff * Just started on encryption * Lots of updates to encryption * Finished createResourceGroup function * Full encryption/decryption working (I think) * Encrypt localstorage with sessionID * Some more * Some extra checks * Now uses separate DB. Still needs to be simplified a LOT * Fix deletion bug * Fixed unicode bug with encryption * Simplified and working * A bunch of polish * Some stuff * Removed some workspace meta properties * Migrated a few more meta properties * Small changes * Fix body scrolling and url cursor jumping * Removed duplication of webpack port * Remove workspaces reduces * Some small fixes * Added sync modal and opt-in setting * Good start to sync flow * Refactored modal footer css * Update sync status * Sync logger * A bit better logging * Fixed a bunch of sync-related bugs * Fixed signup form button * Gravatar component * Split sync modal into tabs * Tidying * Some more error handling * start sending 'user agent * Login/signup error handling * Use real UUIDs * Fixed tests * Remove unused function * Some extra checks * Moved cloud sync setting to about page * Some small changes * Some things
2016-10-21 17:20:36 +00:00
import {combineReducers} from 'redux';
import fs from 'fs';
import path from 'path';
import AskModal from '../../../ui/components/modals/ask-modal';
import * as moment from 'moment';
2016-07-07 20:10:55 +00:00
import * as importUtils from '../../../common/import';
import {trackEvent} from '../../../analytics';
import AlertModal from '../../components/modals/alert-modal';
import {showModal} from '../../components/modals';
import PaymentNotificationModal from '../../components/modals/payment-notification-modal';
import LoginModal from '../../components/modals/login-modal';
import * as models from '../../../models';
const LOCALSTORAGE_PREFIX = `insomnia::meta`;
2016-07-07 20:10:55 +00:00
const LOAD_START = 'global/load-start';
const LOAD_STOP = 'global/load-stop';
const LOAD_REQUEST_START = 'global/load-request-start';
const LOAD_REQUEST_STOP = 'global/load-request-stop';
const REQUEST_GROUP_TOGGLE_COLLAPSE = 'global/request-group-toggle';
const SET_ACTIVE_WORKSPACE = 'global/activate-workspace';
const COMMAND_ALERT = 'app/alert';
const COMMAND_LOGIN = 'app/auth/login';
const COMMAND_TRIAL_END = 'app/billing/trial-end';
const COMMAND_IMPORT_URI = 'app/import';
2016-04-23 06:08:52 +00:00
// ~~~~~~~~ //
// REDUCERS //
// ~~~~~~~~ //
function activeWorkspaceReducer (state = null, action) {
Sync Proof of Concept (#33) * Maybe working POC * Change to use remote url * Other URL too * Some logic * Got the push part working * Made some updates * Fix * Update * Add status code check * Stuff * Implemented new sync api * A bit more robust * Debounce changes * Change timeout * Some fixes * Remove .less * Better error handling * Fix base url * Support for created vs updated docs * Try silent * Silence removal too * Small fix after merge * Fix test * Stuff * Implement key generation algorithm * Tidy * stuff * A bunch of stuff for the new API * Integrated the session stuff * Stuff * Just started on encryption * Lots of updates to encryption * Finished createResourceGroup function * Full encryption/decryption working (I think) * Encrypt localstorage with sessionID * Some more * Some extra checks * Now uses separate DB. Still needs to be simplified a LOT * Fix deletion bug * Fixed unicode bug with encryption * Simplified and working * A bunch of polish * Some stuff * Removed some workspace meta properties * Migrated a few more meta properties * Small changes * Fix body scrolling and url cursor jumping * Removed duplication of webpack port * Remove workspaces reduces * Some small fixes * Added sync modal and opt-in setting * Good start to sync flow * Refactored modal footer css * Update sync status * Sync logger * A bit better logging * Fixed a bunch of sync-related bugs * Fixed signup form button * Gravatar component * Split sync modal into tabs * Tidying * Some more error handling * start sending 'user agent * Login/signup error handling * Use real UUIDs * Fixed tests * Remove unused function * Some extra checks * Moved cloud sync setting to about page * Some small changes * Some things
2016-10-21 17:20:36 +00:00
switch (action.type) {
case SET_ACTIVE_WORKSPACE:
return action.workspaceId;
Sync Proof of Concept (#33) * Maybe working POC * Change to use remote url * Other URL too * Some logic * Got the push part working * Made some updates * Fix * Update * Add status code check * Stuff * Implemented new sync api * A bit more robust * Debounce changes * Change timeout * Some fixes * Remove .less * Better error handling * Fix base url * Support for created vs updated docs * Try silent * Silence removal too * Small fix after merge * Fix test * Stuff * Implement key generation algorithm * Tidy * stuff * A bunch of stuff for the new API * Integrated the session stuff * Stuff * Just started on encryption * Lots of updates to encryption * Finished createResourceGroup function * Full encryption/decryption working (I think) * Encrypt localstorage with sessionID * Some more * Some extra checks * Now uses separate DB. Still needs to be simplified a LOT * Fix deletion bug * Fixed unicode bug with encryption * Simplified and working * A bunch of polish * Some stuff * Removed some workspace meta properties * Migrated a few more meta properties * Small changes * Fix body scrolling and url cursor jumping * Removed duplication of webpack port * Remove workspaces reduces * Some small fixes * Added sync modal and opt-in setting * Good start to sync flow * Refactored modal footer css * Update sync status * Sync logger * A bit better logging * Fixed a bunch of sync-related bugs * Fixed signup form button * Gravatar component * Split sync modal into tabs * Tidying * Some more error handling * start sending 'user agent * Login/signup error handling * Use real UUIDs * Fixed tests * Remove unused function * Some extra checks * Moved cloud sync setting to about page * Some small changes * Some things
2016-10-21 17:20:36 +00:00
default:
return state;
}
}
function loadingReducer (state = false, action) {
2016-04-23 06:08:52 +00:00
switch (action.type) {
case LOAD_START:
Sync Proof of Concept (#33) * Maybe working POC * Change to use remote url * Other URL too * Some logic * Got the push part working * Made some updates * Fix * Update * Add status code check * Stuff * Implemented new sync api * A bit more robust * Debounce changes * Change timeout * Some fixes * Remove .less * Better error handling * Fix base url * Support for created vs updated docs * Try silent * Silence removal too * Small fix after merge * Fix test * Stuff * Implement key generation algorithm * Tidy * stuff * A bunch of stuff for the new API * Integrated the session stuff * Stuff * Just started on encryption * Lots of updates to encryption * Finished createResourceGroup function * Full encryption/decryption working (I think) * Encrypt localstorage with sessionID * Some more * Some extra checks * Now uses separate DB. Still needs to be simplified a LOT * Fix deletion bug * Fixed unicode bug with encryption * Simplified and working * A bunch of polish * Some stuff * Removed some workspace meta properties * Migrated a few more meta properties * Small changes * Fix body scrolling and url cursor jumping * Removed duplication of webpack port * Remove workspaces reduces * Some small fixes * Added sync modal and opt-in setting * Good start to sync flow * Refactored modal footer css * Update sync status * Sync logger * A bit better logging * Fixed a bunch of sync-related bugs * Fixed signup form button * Gravatar component * Split sync modal into tabs * Tidying * Some more error handling * start sending 'user agent * Login/signup error handling * Use real UUIDs * Fixed tests * Remove unused function * Some extra checks * Moved cloud sync setting to about page * Some small changes * Some things
2016-10-21 17:20:36 +00:00
return true;
case LOAD_STOP:
Sync Proof of Concept (#33) * Maybe working POC * Change to use remote url * Other URL too * Some logic * Got the push part working * Made some updates * Fix * Update * Add status code check * Stuff * Implemented new sync api * A bit more robust * Debounce changes * Change timeout * Some fixes * Remove .less * Better error handling * Fix base url * Support for created vs updated docs * Try silent * Silence removal too * Small fix after merge * Fix test * Stuff * Implement key generation algorithm * Tidy * stuff * A bunch of stuff for the new API * Integrated the session stuff * Stuff * Just started on encryption * Lots of updates to encryption * Finished createResourceGroup function * Full encryption/decryption working (I think) * Encrypt localstorage with sessionID * Some more * Some extra checks * Now uses separate DB. Still needs to be simplified a LOT * Fix deletion bug * Fixed unicode bug with encryption * Simplified and working * A bunch of polish * Some stuff * Removed some workspace meta properties * Migrated a few more meta properties * Small changes * Fix body scrolling and url cursor jumping * Removed duplication of webpack port * Remove workspaces reduces * Some small fixes * Added sync modal and opt-in setting * Good start to sync flow * Refactored modal footer css * Update sync status * Sync logger * A bit better logging * Fixed a bunch of sync-related bugs * Fixed signup form button * Gravatar component * Split sync modal into tabs * Tidying * Some more error handling * start sending 'user agent * Login/signup error handling * Use real UUIDs * Fixed tests * Remove unused function * Some extra checks * Moved cloud sync setting to about page * Some small changes * Some things
2016-10-21 17:20:36 +00:00
return false;
default:
return state;
}
}
2016-04-23 06:08:52 +00:00
function loadingRequestsReducer (state = {}, action) {
switch (action.type) {
case LOAD_REQUEST_START:
return Object.assign({}, state, {[action.requestId]: action.time});
case LOAD_REQUEST_STOP:
return Object.assign({}, state, {[action.requestId]: -1});
default:
return state;
}
}
export const reducer = combineReducers({
isLoading: loadingReducer,
loadingRequestIds: loadingRequestsReducer,
activeWorkspaceId: activeWorkspaceReducer
Sync Proof of Concept (#33) * Maybe working POC * Change to use remote url * Other URL too * Some logic * Got the push part working * Made some updates * Fix * Update * Add status code check * Stuff * Implemented new sync api * A bit more robust * Debounce changes * Change timeout * Some fixes * Remove .less * Better error handling * Fix base url * Support for created vs updated docs * Try silent * Silence removal too * Small fix after merge * Fix test * Stuff * Implement key generation algorithm * Tidy * stuff * A bunch of stuff for the new API * Integrated the session stuff * Stuff * Just started on encryption * Lots of updates to encryption * Finished createResourceGroup function * Full encryption/decryption working (I think) * Encrypt localstorage with sessionID * Some more * Some extra checks * Now uses separate DB. Still needs to be simplified a LOT * Fix deletion bug * Fixed unicode bug with encryption * Simplified and working * A bunch of polish * Some stuff * Removed some workspace meta properties * Migrated a few more meta properties * Small changes * Fix body scrolling and url cursor jumping * Removed duplication of webpack port * Remove workspaces reduces * Some small fixes * Added sync modal and opt-in setting * Good start to sync flow * Refactored modal footer css * Update sync status * Sync logger * A bit better logging * Fixed a bunch of sync-related bugs * Fixed signup form button * Gravatar component * Split sync modal into tabs * Tidying * Some more error handling * start sending 'user agent * Login/signup error handling * Use real UUIDs * Fixed tests * Remove unused function * Some extra checks * Moved cloud sync setting to about page * Some small changes * Some things
2016-10-21 17:20:36 +00:00
});
2016-04-23 06:08:52 +00:00
// ~~~~~~~ //
// ACTIONS //
// ~~~~~~~ //
export function newCommand (command, args) {
return async dispatch => {
// TODO: Make this use reducer when Modals ported to Redux
if (command === COMMAND_ALERT) {
const {message, title} = args;
showModal(AlertModal, {title, message});
} else if (command === COMMAND_LOGIN) {
const {title, message} = args;
showModal(LoginModal, {title, message});
} else if (command === COMMAND_TRIAL_END) {
showModal(PaymentNotificationModal);
} else if (command === COMMAND_IMPORT_URI) {
await showModal(AlertModal, {
title: 'Confirm Data Import',
message: <span>Do you really want to import <code>{args.uri}</code>?</span>,
addCancel: true
});
dispatch(importUri(args.workspaceId, args.uri));
}
};
}
2016-04-23 06:08:52 +00:00
export function loadStart () {
return {type: LOAD_START};
2016-04-23 06:08:52 +00:00
}
export function loadStop () {
return {type: LOAD_STOP};
2016-04-23 06:08:52 +00:00
}
2016-07-07 20:10:55 +00:00
export function loadRequestStart (requestId) {
return {type: LOAD_REQUEST_START, requestId, time: Date.now()};
}
export function loadRequestStop (requestId) {
return {type: LOAD_REQUEST_STOP, requestId};
}
export function setActiveWorkspace (workspaceId) {
window.localStorage.setItem(`${LOCALSTORAGE_PREFIX}::activeWorkspaceId`, JSON.stringify(workspaceId));
return {type: SET_ACTIVE_WORKSPACE, workspaceId};
Sync Proof of Concept (#33) * Maybe working POC * Change to use remote url * Other URL too * Some logic * Got the push part working * Made some updates * Fix * Update * Add status code check * Stuff * Implemented new sync api * A bit more robust * Debounce changes * Change timeout * Some fixes * Remove .less * Better error handling * Fix base url * Support for created vs updated docs * Try silent * Silence removal too * Small fix after merge * Fix test * Stuff * Implement key generation algorithm * Tidy * stuff * A bunch of stuff for the new API * Integrated the session stuff * Stuff * Just started on encryption * Lots of updates to encryption * Finished createResourceGroup function * Full encryption/decryption working (I think) * Encrypt localstorage with sessionID * Some more * Some extra checks * Now uses separate DB. Still needs to be simplified a LOT * Fix deletion bug * Fixed unicode bug with encryption * Simplified and working * A bunch of polish * Some stuff * Removed some workspace meta properties * Migrated a few more meta properties * Small changes * Fix body scrolling and url cursor jumping * Removed duplication of webpack port * Remove workspaces reduces * Some small fixes * Added sync modal and opt-in setting * Good start to sync flow * Refactored modal footer css * Update sync status * Sync logger * A bit better logging * Fixed a bunch of sync-related bugs * Fixed signup form button * Gravatar component * Split sync modal into tabs * Tidying * Some more error handling * start sending 'user agent * Login/signup error handling * Use real UUIDs * Fixed tests * Remove unused function * Some extra checks * Moved cloud sync setting to about page * Some small changes * Some things
2016-10-21 17:20:36 +00:00
}
export function toggleRequestGroup (requestGroup) {
return {
type: REQUEST_GROUP_TOGGLE_COLLAPSE,
requestGroupId: requestGroup._id
};
}
export function importFile (workspaceId) {
return async dispatch => {
2016-07-07 20:10:55 +00:00
dispatch(loadStart());
const options = {
title: 'Import Insomnia Data',
buttonLabel: 'Import',
2016-07-07 20:10:55 +00:00
properties: ['openFile'],
filters: [{
// Allow empty extension and JSON
name: 'Insomnia Import',
extensions: [
'', 'sh', 'txt', 'json', 'har', 'curl', 'bash', 'shell'
]
2016-07-07 20:10:55 +00:00
}]
};
2016-11-20 07:43:22 +00:00
electron.remote.dialog.showOpenDialog(options, async paths => {
2016-07-07 20:10:55 +00:00
if (!paths) {
// It was cancelled, so let's bail out
dispatch(loadStop());
trackEvent('Import File', 'Cancel');
2016-07-07 20:10:55 +00:00
return;
}
// Let's import all the paths!
for (const p of paths) {
2016-11-20 07:43:22 +00:00
try {
const uri = `file://${p}`;
await importUtils.importUri(workspaceId, uri);
trackEvent('Import File', 'Success');
} catch (err) {
showModal(AlertModal, {title: 'Import Failed', message: err + ''});
trackEvent('Import File', 'Failure');
} finally {
dispatch(loadStop());
2016-11-20 07:43:22 +00:00
}
}
2016-07-07 20:10:55 +00:00
});
};
2016-07-07 20:10:55 +00:00
}
export function importUri (workspaceId, uri) {
return async dispatch => {
dispatch(loadStart());
try {
await importUtils.importUri(workspaceId, uri);
trackEvent('Import URI', 'Success');
} catch (err) {
trackEvent('Import URI', 'Failure');
showModal(AlertModal, {title: 'Import Failed', message: err + ''});
} finally {
dispatch(loadStop());
}
};
}
export function exportFile (workspaceId = null) {
return async dispatch => {
dispatch(loadStart());
const workspace = await models.workspace.getById(workspaceId);
// Check if we want to export private environments
let environments;
if (workspace) {
const parentEnv = await models.environment.getOrCreateForWorkspace(workspace);
environments = [
parentEnv,
...await models.environment.findByParentId(parentEnv._id)
];
} else {
environments = await models.environment.all();
}
let exportPrivateEnvironments = false;
const privateEnvironments = environments.filter(e => e.isPrivate);
if (privateEnvironments.length) {
const names = privateEnvironments.map(e => e.name).join(', ');
exportPrivateEnvironments = await showModal(AskModal, {
title: 'Export Private Environments?',
message: `Do you want to include private environments (${names}) in your export?`
});
}
const json = await importUtils.exportJSON(workspace, exportPrivateEnvironments);
const date = moment().format('YYYY-MM-DD');
const name = (workspace ? workspace.name : 'Insomnia All').replace(/ /g, '-');
const lastDir = window.localStorage.getItem('insomnia.lastExportPath');
const dir = lastDir || electron.remote.app.getPath('desktop');
const options = {
title: 'Export Insomnia Data',
buttonLabel: 'Export',
defaultPath: path.join(dir, `${name}_${date}`),
filters: [{
name: 'Insomnia Export', extensions: ['json']
}]
};
electron.remote.dialog.showSaveDialog(options, filename => {
if (!filename) {
trackEvent('Export', 'Cancel');
// It was cancelled, so let's bail out
dispatch(loadStop());
return;
}
// Remember last exported path
window.localStorage.setItem(
'insomnia.lastExportPath',
path.dirname(filename)
);
fs.writeFile(filename, json, {}, err => {
if (err) {
console.warn('Export failed', err);
2016-10-27 03:41:30 +00:00
trackEvent('Export', 'Failure');
return;
}
2016-10-27 03:41:30 +00:00
trackEvent('Export', 'Success');
dispatch(loadStop());
});
});
};
}
export function init () {
let workspaceId = null;
try {
const key = `${LOCALSTORAGE_PREFIX}::activeWorkspaceId`;
const item = window.localStorage.getItem(key);
workspaceId = JSON.parse(item);
} catch (e) {
// Nothing here...
}
return setActiveWorkspace(workspaceId);
}