mirror of
https://github.com/Kong/insomnia.git
synced 2026-10-11 08:37:59 -04:00
Track history, bug fixes, analytics
This commit is contained in:
1 parent
9bc4680a5f
commit
403b0024ce
13 files changed
+101
-50
No files matched your search
@@ -1,5 +1,5 @@
|
||||
import * as analytics from '../index';
|
||||
import {GA_HOST} from '../../common/constants';
|
||||
import {GA_HOST, getAppVersion, getAppPlatform} from '../../common/constants';
|
||||
import * as db from '../../common/database';
|
||||
import * as models from '../../models';
|
||||
|
||||
@@ -30,7 +30,7 @@ describe('init()', () => {
|
||||
await analytics.init('acct_123');
|
||||
|
||||
// Verify that Google Analytics works
|
||||
expect(window.ga.mock.calls.length).toBe(5);
|
||||
expect(window.ga.mock.calls.length).toBe(7);
|
||||
expect(window.ga.mock.calls[0][0]).toBe('create');
|
||||
expect(window.ga.mock.calls[0][1]).toBe('UA-86416787-1');
|
||||
expect(window.ga.mock.calls[0][2].storage).toBe('none');
|
||||
@@ -39,20 +39,22 @@ describe('init()', () => {
|
||||
expect(window.ga.mock.calls[1].slice(0, 2)).toEqual(['set', 'checkProtocolTask']);
|
||||
expect(window.ga.mock.calls[1][2]()).toBeNull();
|
||||
expect(window.ga.mock.calls[2]).toEqual(['set', 'location', `https://${GA_HOST}/`]);
|
||||
expect(window.ga.mock.calls[3]).toEqual(['send', 'pageview']);
|
||||
expect(window.ga.mock.calls[4]).toEqual(['set', 'userId', 'acct_123']);
|
||||
expect(window.ga.mock.calls[3]).toEqual(['set', 'userId', 'acct_123']);
|
||||
expect(window.ga.mock.calls[4]).toEqual(['set', 'dimension1', getAppPlatform()]);
|
||||
expect(window.ga.mock.calls[5]).toEqual(['set', 'dimension2', getAppVersion()]);
|
||||
expect(window.ga.mock.calls[6]).toEqual(['send', 'pageview']);
|
||||
|
||||
analytics.trackEvent('foo', 'bar', 'baz');
|
||||
expect(window.ga.mock.calls.length).toBe(6);
|
||||
expect(window.ga.mock.calls[5]).toEqual(['send', 'event', 'foo', 'bar', 'baz']);
|
||||
expect(window.ga.mock.calls.length).toBe(8);
|
||||
expect(window.ga.mock.calls[7]).toEqual(['send', 'event', 'foo', 'bar', 'baz']);
|
||||
|
||||
analytics.setAccountId('acct_456');
|
||||
expect(window.ga.mock.calls.length).toBe(7);
|
||||
expect(window.ga.mock.calls[6]).toEqual(['set', 'userId', 'acct_456']);
|
||||
expect(window.ga.mock.calls.length).toBe(9);
|
||||
expect(window.ga.mock.calls[8]).toEqual(['set', 'userId', 'acct_456']);
|
||||
|
||||
// Try reinitializing
|
||||
analytics.init();
|
||||
expect(window.ga.mock.calls.length).toBe(7);
|
||||
expect(window.ga.mock.calls.length).toBe(9);
|
||||
|
||||
// TODO: Verify that Segment works (although it's not that important)
|
||||
});
|
||||
|
||||
+31
-6
@@ -2,7 +2,10 @@ import * as constants from '../common/constants';
|
||||
|
||||
let _sessionId = null;
|
||||
|
||||
export function init (userId = null) {
|
||||
const DIMENSION_PLATFORM = 'dimension1';
|
||||
const DIMENSION_VERSION = 'dimension2';
|
||||
|
||||
export function init (userId, platform, version) {
|
||||
if (constants.isDevelopment()) {
|
||||
console.log(`[ga] Not initializing for dev`);
|
||||
return;
|
||||
@@ -29,18 +32,40 @@ export function init (userId = null) {
|
||||
// Set a fake location
|
||||
window.ga('set', 'location', `https://${constants.GA_HOST}/`);
|
||||
|
||||
setUserId(userId);
|
||||
setPlatform(platform);
|
||||
setVersion(version);
|
||||
|
||||
// Track the initial page view
|
||||
window.ga('send', 'pageview');
|
||||
|
||||
if (userId) {
|
||||
setUserId(userId);
|
||||
}
|
||||
|
||||
console.log(`[ga] Initialized for ${_sessionId}`);
|
||||
}
|
||||
|
||||
export function setPlatform (platform) {
|
||||
if (!window.ga || !platform) {
|
||||
return;
|
||||
}
|
||||
|
||||
ga('set', DIMENSION_PLATFORM, platform);
|
||||
console.log(`[ga] Set platform ${platform}`);
|
||||
}
|
||||
|
||||
export function setVersion (version) {
|
||||
if (!window.ga || !version) {
|
||||
return;
|
||||
}
|
||||
|
||||
ga('set', DIMENSION_VERSION, version);
|
||||
console.log(`[ga] Set version ${version}`);
|
||||
}
|
||||
|
||||
export function setUserId (userId) {
|
||||
window.ga && window.ga('set', 'userId', userId);
|
||||
if (!window.ga || !userId) {
|
||||
return;
|
||||
}
|
||||
|
||||
window.ga('set', 'userId', userId);
|
||||
console.log(`[ga] Set userId ${userId}`);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import * as segment from './segment';
|
||||
import * as google from './google';
|
||||
import {ipcRenderer} from 'electron';
|
||||
import {getAppVersion, getAppPlatform} from '../common/constants';
|
||||
|
||||
let initialized = false;
|
||||
export async function init (accountId) {
|
||||
@@ -10,7 +11,7 @@ export async function init (accountId) {
|
||||
|
||||
try {
|
||||
await segment.init();
|
||||
await google.init(accountId);
|
||||
await google.init(accountId, getAppPlatform(), getAppVersion());
|
||||
|
||||
initialized = true;
|
||||
} catch (e) {
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 7.2 KiB |
@@ -280,6 +280,7 @@ function createWindow () {
|
||||
minHeight: 500,
|
||||
minWidth: 500,
|
||||
acceptFirstMouse: true,
|
||||
icon: path.resolve(__dirname, 'icons/icon.png'),
|
||||
webPreferences: {
|
||||
zoomFactor: zoomFactor
|
||||
}
|
||||
@@ -302,7 +303,7 @@ function createWindow () {
|
||||
clearTimeout(_moveTimeout);
|
||||
_moveTimeout = setTimeout(() => {
|
||||
trackEvent('Window', 'Move');
|
||||
});
|
||||
}, 1000);
|
||||
});
|
||||
mainWindow.on('unresponsive', e => {
|
||||
showUnresponsiveModal();
|
||||
|
||||
+2
-2
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"private": true,
|
||||
"name": "insomnia",
|
||||
"version": "4.0.2",
|
||||
"version": "4.0.4",
|
||||
"productName": "Insomnia",
|
||||
"longName": "Insomnia REST Client",
|
||||
"description": "A simple and beautiful REST API client",
|
||||
@@ -16,7 +16,7 @@
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"hkdf": "0.0.2",
|
||||
"httpsnippet": "git@github.com:getinsomnia/httpsnippet.git#a3a2c0a0167fa844bf92df52a1442fa1d68a9053",
|
||||
"insomnia-importers": "^1.2.0",
|
||||
"insomnia-importers": "^1.2.5",
|
||||
"json-lint": "^0.1.0",
|
||||
"jsonpath-plus": "^0.15.0",
|
||||
"mime-types": "^2.1.12",
|
||||
|
||||
@@ -3,6 +3,7 @@ import classnames from 'classnames';
|
||||
import {DEBOUNCE_MILLIS} from '../../../common/constants';
|
||||
import FileInputButton from '../base/FileInputButton';
|
||||
import {Dropdown, DropdownItem, DropdownButton} from './dropdown/index';
|
||||
import PromptButton from '../base/PromptButton';
|
||||
|
||||
const NAME = 'name';
|
||||
const VALUE = 'value';
|
||||
@@ -202,7 +203,7 @@ class KeyValueEditor extends Component {
|
||||
const {maxPairs, className, valueInputType, multipart} = this.props;
|
||||
|
||||
return (
|
||||
<ul className={classnames('key-value-editor', 'wide', className)}>
|
||||
<ul key={pairs.length} className={classnames('key-value-editor', 'wide', className)}>
|
||||
{pairs.map((pair, i) => (
|
||||
<li key={`${i}.pair`}
|
||||
className={classnames(
|
||||
@@ -285,12 +286,14 @@ class KeyValueEditor extends Component {
|
||||
}
|
||||
</button>
|
||||
|
||||
<button key={Math.random()}
|
||||
tabIndex="-1"
|
||||
onClick={e => this._deletePair(i)}
|
||||
title="Delete item">
|
||||
<PromptButton key={Math.random()}
|
||||
tabIndex="-1"
|
||||
confirmMessage=" "
|
||||
addIcon={true}
|
||||
onClick={e => this._deletePair(i)}
|
||||
title="Delete item">
|
||||
<i className="fa fa-trash-o"></i>
|
||||
</button>
|
||||
</PromptButton>
|
||||
</li>
|
||||
))}
|
||||
{!maxPairs || pairs.length < maxPairs ? (
|
||||
|
||||
@@ -15,7 +15,7 @@ class Link extends Component {
|
||||
|
||||
if (href.match(/^http/i)) {
|
||||
const appName = isDevelopment() ? 'Insomnia Dev' : 'Insomnia';
|
||||
const qs = `utm_source=${appName}&utm_medium=App&utm_campaign=v${getAppVersion()}`;
|
||||
const qs = `utm_source=${appName}&utm_medium=app&utm_campaign=v${getAppVersion()}`;
|
||||
const attributedHref = querystring.joinUrl(href, qs);
|
||||
shell.openExternal(attributedHref);
|
||||
} else {
|
||||
|
||||
@@ -5,6 +5,7 @@ import StatusTag from '../tags/StatusTag';
|
||||
import TimeTag from '../tags/TimeTag';
|
||||
import * as models from '../../../models/index';
|
||||
import PromptButton from '../base/PromptButton';
|
||||
import {trackEvent} from '../../../analytics/index';
|
||||
|
||||
class ResponseHistoryDropdown extends Component {
|
||||
state = {
|
||||
@@ -12,9 +13,15 @@ class ResponseHistoryDropdown extends Component {
|
||||
};
|
||||
|
||||
_handleDeleteResponses = () => {
|
||||
trackEvent('History', 'Delete Responses');
|
||||
this.props.handleDeleteResponses(this.props.requestId);
|
||||
};
|
||||
|
||||
_handleSetActiveResponse = responseId => {
|
||||
trackEvent('History', 'Activate Response');
|
||||
this.props.handleSetActiveResponse(responseId);
|
||||
};
|
||||
|
||||
async _load (requestId) {
|
||||
const responses = await models.response.findRecentForRequest(requestId);
|
||||
|
||||
@@ -40,13 +47,13 @@ class ResponseHistoryDropdown extends Component {
|
||||
}
|
||||
|
||||
renderDropdownItem = (response, i) => {
|
||||
const {activeResponseId, handleSetActiveResponse} = this.props;
|
||||
const {activeResponseId} = this.props;
|
||||
const active = response._id === activeResponseId;
|
||||
return (
|
||||
<DropdownItem key={response._id}
|
||||
disabled={active}
|
||||
value={i === 0 ? null : response._id}
|
||||
onClick={handleSetActiveResponse}>
|
||||
onClick={this._handleSetActiveResponse}>
|
||||
{active ? <i className="fa fa-thumb-tack"/> : <i className="fa fa-empty"/>}
|
||||
{" "}
|
||||
<StatusTag statusCode={response.statusCode}
|
||||
@@ -60,9 +67,9 @@ class ResponseHistoryDropdown extends Component {
|
||||
|
||||
render () {
|
||||
const {
|
||||
activeResponseId,
|
||||
handleSetActiveResponse,
|
||||
handleDeleteResponses,
|
||||
activeResponseId, // Don't want this in ...extraProps
|
||||
handleSetActiveResponse, // Don't want this in ...extraProps
|
||||
handleDeleteResponses, // Don't want this in ...extraProps
|
||||
isLatestResponseActive,
|
||||
...extraProps
|
||||
} = this.props;
|
||||
|
||||
@@ -8,6 +8,7 @@ import ModalHeader from '../base/ModalHeader';
|
||||
import PromptButton from '../base/PromptButton';
|
||||
import * as models from '../../../models/index';
|
||||
import * as fs from 'fs';
|
||||
import {trackEvent} from '../../../analytics/index';
|
||||
|
||||
|
||||
class WorkspaceSettingsModal extends Component {
|
||||
@@ -57,12 +58,14 @@ class WorkspaceSettingsModal extends Component {
|
||||
|
||||
await models.workspace.update(workspace, {certificates});
|
||||
this._handleToggleCertificateForm();
|
||||
trackEvent('Certificates', 'Create');
|
||||
};
|
||||
|
||||
_handleDeleteCertificate = certificate => {
|
||||
const {workspace} = this.props;
|
||||
const certificates = workspace.certificates.filter(c => c.host !== certificate.host);
|
||||
models.workspace.update(workspace, {certificates});
|
||||
trackEvent('Certificates', 'Delete');
|
||||
};
|
||||
|
||||
_handleToggleCertificate = certificate => {
|
||||
@@ -71,6 +74,7 @@ class WorkspaceSettingsModal extends Component {
|
||||
c => c === certificate ? Object.assign({}, c, {disabled: !c.disabled}) : c
|
||||
);
|
||||
models.workspace.update(workspace, {certificates});
|
||||
trackEvent('Certificates', 'Toggle');
|
||||
};
|
||||
|
||||
toggle (workspace) {
|
||||
@@ -303,7 +307,7 @@ class WorkspaceSettingsModal extends Component {
|
||||
</button>
|
||||
{" "}
|
||||
<button className="btn btn--clicky" type="submit">
|
||||
Import Certificate
|
||||
Add Certificate
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
@@ -320,11 +324,6 @@ class WorkspaceSettingsModal extends Component {
|
||||
<Modal ref={this._handleSetModalRef} tall={true} freshState={true}>
|
||||
{workspace ? this.renderModalHeader() : null}
|
||||
{workspace ? this.renderModalBody() : null}
|
||||
{/*<ModalFooter>*/}
|
||||
{/*<button className="btn" onClick={this._handleClose}>*/}
|
||||
{/*Close*/}
|
||||
{/*</button>*/}
|
||||
{/*</ModalFooter>*/}
|
||||
</Modal>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -217,10 +217,21 @@ class App extends Component {
|
||||
};
|
||||
|
||||
_handleSendRequestWithEnvironment = async (requestId, environmentId) => {
|
||||
this.props.handleStartLoading(requestId);
|
||||
const request = await models.request.getById(requestId);
|
||||
if (!request) {
|
||||
return;
|
||||
}
|
||||
|
||||
trackEvent('Request', 'Send');
|
||||
trackLegacyEvent('Request Send');
|
||||
// NOTE: Since request is by far the most popular event, we will throttle
|
||||
// it so that we only track it if the request has changed since the last noe
|
||||
const key = `${request._id}::${request.modified}`;
|
||||
if (this._sendRequestTrackingKey !== key) {
|
||||
trackEvent('Request', 'Send');
|
||||
trackLegacyEvent('Request Send');
|
||||
this._sendRequestTrackingKey = key;
|
||||
}
|
||||
|
||||
this.props.handleStartLoading(requestId);
|
||||
|
||||
try {
|
||||
await network.send(requestId, environmentId);
|
||||
@@ -244,12 +255,12 @@ class App extends Component {
|
||||
};
|
||||
|
||||
_startDragSidebar = () => {
|
||||
trackEvent('Sidebar', 'Drag Start');
|
||||
trackEvent('Sidebar', 'Drag');
|
||||
this.setState({draggingSidebar: true})
|
||||
};
|
||||
|
||||
_resetDragSidebar = () => {
|
||||
trackEvent('Sidebar', 'Drag Reset');
|
||||
trackEvent('Sidebar', 'Drag');
|
||||
// TODO: Remove setTimeout need be not triggering drag on double click
|
||||
setTimeout(() => this._handleSetSidebarWidth(DEFAULT_SIDEBAR_WIDTH), 50);
|
||||
};
|
||||
@@ -260,7 +271,7 @@ class App extends Component {
|
||||
};
|
||||
|
||||
_resetDragPane = () => {
|
||||
trackEvent('App Pane', 'Reset');
|
||||
trackEvent('App Pane', 'Drag Reset');
|
||||
// TODO: Remove setTimeout need be not triggering drag on double click
|
||||
setTimeout(() => this._handleSetPaneWidth(DEFAULT_PANE_WIDTH), 50);
|
||||
};
|
||||
@@ -329,6 +340,8 @@ class App extends Component {
|
||||
} else if (lastVersion !== getAppVersion()) {
|
||||
trackEvent('General', 'Updated', getAppVersion());
|
||||
showModal(ChangelogModal);
|
||||
} else {
|
||||
trackEvent('General', 'Launched', getAppVersion());
|
||||
}
|
||||
|
||||
db.onChange(changes => {
|
||||
|
||||
@@ -6,8 +6,8 @@ export default function configureStore () {
|
||||
const middleware = [thunkMiddleware];
|
||||
|
||||
if (__DEV__) {
|
||||
const createLogger = require('redux-logger');
|
||||
middleware.push(createLogger({collapsed: true}));
|
||||
// const createLogger = require('redux-logger');
|
||||
// middleware.push(createLogger({collapsed: true}));
|
||||
}
|
||||
|
||||
const store = createStore(reducer, applyMiddleware(...middleware));
|
||||
|
||||
+5
-5
@@ -24,8 +24,8 @@
|
||||
"build:copy": "cp -r ./app/package.json ./app/static ./app/icons/* ./build/",
|
||||
"build:install": "cd build && npm install",
|
||||
"build": "npm run build:clean && npm run build:renderer && npm run build:main && npm run build:copy && npm run build:install",
|
||||
"package:mac": "rm -rf dist/mac && node node_modules/electron-builder/out/build-cli.js --publish=never --x64 --mac",
|
||||
"package:win": "rm -rf dist/win* && node node_modules/electron-builder/out/build-cli.js --publish=never --x64 --win",
|
||||
"package:mac": "rm -rf dist/mac && node node_modules/electron-builder/out/cli/build-cli.js --publish=never --x64 --mac",
|
||||
"package:win": "rm -rf dist/win* && node node_modules/electron-builder/out/cli/build-cli.js --publish=never --x64 --win",
|
||||
"package:linux": "rm -rf dist/linux && rm -f dist/*.AppImage && rm -f dist/*.deb && node node_modules/electron-builder/out/build-cli.js --publish=never --x64 --linux",
|
||||
"package": "npm test && rm -rf dist && npm run package:mac && npm run package:win && npm run package:linux",
|
||||
"build-n-package": "npm run build && npm run package",
|
||||
@@ -101,7 +101,7 @@
|
||||
"electron-squirrel-startup": "^1.0.0",
|
||||
"hkdf": "0.0.2",
|
||||
"httpsnippet": "git@github.com:getinsomnia/httpsnippet.git#a3a2c0a0167fa844bf92df52a1442fa1d68a9053",
|
||||
"insomnia-importers": "^1.2.0",
|
||||
"insomnia-importers": "^1.2.5",
|
||||
"json-lint": "^0.1.0",
|
||||
"jsonpath-plus": "^0.15.0",
|
||||
"mime-types": "^2.1.12",
|
||||
@@ -149,8 +149,8 @@
|
||||
"concurrently": "^2.0.0",
|
||||
"cross-env": "^2.0.0",
|
||||
"css-loader": "^0.23.1",
|
||||
"electron": "^1.4.7",
|
||||
"electron-builder": "^8.6.0",
|
||||
"electron": "^1.4.10",
|
||||
"electron-builder": "^10.5.0",
|
||||
"electron-devtools-installer": "^2.0.1",
|
||||
"express": "^4.14.0",
|
||||
"file-loader": "^0.9.0",
|
||||
|
||||
Reference in new issue
Block a user