mirror of
https://github.com/Kong/insomnia.git
synced 2026-04-20 22:27:24 -04:00
feat: Add segment events [INS-5807] (#8802)
* fix: update segment event tracking for export completion * fix: include platform information in segment event tracking properties * feat: track segment events for import and export actions in workspace dropdown * feat: track segment events for import and export actions in workspace dropdown * feat: track segment event for export requests selection in modal * feat: track segment event for import completion with workspace and request counts * feat: include selected role in invitation tracking properties * feat: track segment events for invite resent and revoked actions * feat: track segment event for import action in project empty view * feat: track segment event for scanned import source * feat: track segment events for VCS pull and push actions with error handling * feat: track segment event for import action initiation * feat: track segment events for project creation and update actions with storage details * feat: track segment event for import action initiation in project route * fix: standardize storage property values to lowercase in project actions * fix: remove unnecessary console log in ExportRequestsModal * fix: replace alias import of database with direct import in actions file * fix: update segment event source for import and export actions to include 'scratchpad' * fix: restore import of showAlert in InviteModal component
This commit is contained in:
@@ -6,8 +6,8 @@ import React from 'react';
|
||||
|
||||
import { type Environment } from '../models/environment';
|
||||
import * as requestOperations from '../models/helpers/request-operations';
|
||||
import { type BaseModel, environment } from '../models/index';
|
||||
import * as models from '../models/index';
|
||||
import { type BaseModel, environment } from '../models/index';
|
||||
import { isRequest } from '../models/request';
|
||||
import { isWorkspace, type Workspace } from '../models/workspace';
|
||||
import { SegmentEvent } from '../ui/analytics';
|
||||
@@ -268,7 +268,7 @@ export const exportProjectToFile = (activeProjectName: string, workspacesForActi
|
||||
throw new Error(`selected export format "${selectedFormat}" is invalid`);
|
||||
}
|
||||
}
|
||||
window.main.trackSegmentEvent({ event: SegmentEvent.dataExport, properties: { type: selectedFormat } });
|
||||
window.main.trackSegmentEvent({ event: SegmentEvent.exportCompleted });
|
||||
} catch (err) {
|
||||
showError({
|
||||
title: 'Export Failed',
|
||||
|
||||
@@ -83,7 +83,10 @@ export async function trackSegmentEvent(event: SegmentEvent, properties?: Record
|
||||
analytics.track(
|
||||
{
|
||||
event,
|
||||
properties,
|
||||
properties: {
|
||||
...properties,
|
||||
platform: 'app',
|
||||
},
|
||||
context,
|
||||
anonymousId,
|
||||
userId: userSession?.hashedAccountId || '',
|
||||
|
||||
@@ -3,7 +3,11 @@ export enum SegmentEvent {
|
||||
analyticsDisabled = 'Analytics Disabled',
|
||||
collectionCreate = 'Collection Created',
|
||||
dataExport = 'Data Exported',
|
||||
exportCompleted = 'Export Completed',
|
||||
dataImport = 'Data Imported',
|
||||
importStarted = 'Import Started',
|
||||
importScanned = 'Import Scanned',
|
||||
importCompleted = 'Import Completed',
|
||||
documentCreate = 'Document Created',
|
||||
mockCreate = 'Mock Created',
|
||||
environmentWorkspaceCreate = 'Environment Workspace Created',
|
||||
@@ -33,6 +37,12 @@ export enum SegmentEvent {
|
||||
vcsAction = 'VCS Action Executed',
|
||||
buttonClick = 'Button Clicked',
|
||||
inviteMember = 'Invite Member',
|
||||
inviteResent = 'Invite Resent',
|
||||
inviteRevoked = 'Invite Revoked',
|
||||
projectCreated = 'Project Created',
|
||||
projectUpdated = 'Project Updated',
|
||||
exportStarted = 'Export Started',
|
||||
exportRequestsChosen = 'Export Requests Chosen',
|
||||
}
|
||||
|
||||
type PushPull = 'push' | 'pull';
|
||||
|
||||
@@ -14,6 +14,7 @@ import { WorkspaceScopeKeys } from '../../../models/workspace';
|
||||
import type { DocumentAction } from '../../../plugins';
|
||||
import { getDocumentActions } from '../../../plugins';
|
||||
import * as pluginContexts from '../../../plugins/context';
|
||||
import { SegmentEvent } from '../../analytics';
|
||||
import { useLoadingRecord } from '../../hooks/use-loading-record';
|
||||
import { Dropdown, DropdownItem, DropdownSection, ItemContent } from '../base/dropdown';
|
||||
import { Icon } from '../icon';
|
||||
@@ -143,13 +144,33 @@ export const WorkspaceCardDropdown: FC<Props> = props => {
|
||||
</DropdownItem>
|
||||
<DropdownSection aria-label="Meta section">
|
||||
<DropdownItem aria-label="Import">
|
||||
<ItemContent label="Import" icon="file-import" onClick={() => setIsImportModalOpen(true)} />
|
||||
<ItemContent
|
||||
label="Import"
|
||||
icon="file-import"
|
||||
onClick={() => {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.importStarted,
|
||||
properties: {
|
||||
source: `${workspace.scope}-list`,
|
||||
},
|
||||
});
|
||||
|
||||
setIsImportModalOpen(true);
|
||||
}}
|
||||
/>
|
||||
</DropdownItem>
|
||||
<DropdownItem aria-label="Export">
|
||||
<ItemContent
|
||||
label="Export"
|
||||
icon="file-export"
|
||||
onClick={() => {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.exportStarted,
|
||||
properties: {
|
||||
source: `${workspace.scope}-list`,
|
||||
},
|
||||
});
|
||||
|
||||
if (workspace.scope === 'mock-server') {
|
||||
return exportMockServerToFile(workspace);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import type { WorkspaceAction } from '../../../plugins';
|
||||
import { getWorkspaceActions } from '../../../plugins';
|
||||
import * as pluginContexts from '../../../plugins/context';
|
||||
import { invariant } from '../../../utils/invariant';
|
||||
import { SegmentEvent } from '../../analytics';
|
||||
import { useAIContext } from '../../context/app/ai-context';
|
||||
import { useRootLoaderData } from '../../routes/root';
|
||||
import type { WorkspaceLoaderData } from '../../routes/workspace';
|
||||
@@ -133,13 +134,28 @@ export const WorkspaceDropdown: FC<{}> = () => {
|
||||
id: 'Import',
|
||||
name: 'Import',
|
||||
icon: <Icon icon="file-import" />,
|
||||
action: () => setIsImportModalOpen(true),
|
||||
action: () => {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.importStarted,
|
||||
properties: {
|
||||
source: `scratchpad-${activeWorkspace.scope}-menu`,
|
||||
},
|
||||
});
|
||||
|
||||
setIsImportModalOpen(true);
|
||||
},
|
||||
},
|
||||
{
|
||||
id: 'Export',
|
||||
name: 'Export',
|
||||
icon: <Icon icon="file-export" />,
|
||||
action: () => {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.exportStarted,
|
||||
properties: {
|
||||
source: `scratchpad-${activeWorkspace.scope}-menu`,
|
||||
},
|
||||
});
|
||||
if (activeWorkspace.scope === 'mock-server') {
|
||||
return exportMockServerToFile(activeWorkspace);
|
||||
}
|
||||
@@ -176,7 +192,15 @@ export const WorkspaceDropdown: FC<{}> = () => {
|
||||
id: 'from-file',
|
||||
name: 'From File',
|
||||
icon: <Icon icon="file-import" />,
|
||||
action: () => setIsImportModalOpen(true),
|
||||
action: () => {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.importStarted,
|
||||
properties: {
|
||||
source: `${activeWorkspace.scope}-menu`,
|
||||
},
|
||||
});
|
||||
setIsImportModalOpen(true);
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
@@ -235,6 +259,13 @@ export const WorkspaceDropdown: FC<{}> = () => {
|
||||
name: 'Export',
|
||||
icon: <Icon icon="file-export" />,
|
||||
action: () => {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.exportStarted,
|
||||
properties: {
|
||||
source: `${activeWorkspace.scope}-menu`,
|
||||
},
|
||||
});
|
||||
|
||||
if (activeWorkspace.scope === 'mock-server') {
|
||||
return exportMockServerToFile(activeWorkspace);
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ import { type GrpcRequest, isGrpcRequest } from '../../../models/grpc-request';
|
||||
import { isRequest, type Request } from '../../../models/request';
|
||||
import type { RequestGroup } from '../../../models/request-group';
|
||||
import { isWebSocketRequest, type WebSocketRequest } from '../../../models/websocket-request';
|
||||
import { SegmentEvent } from '../../analytics';
|
||||
import type { Child, WorkspaceLoaderData } from '../../routes/workspace';
|
||||
import { Icon } from '../icon';
|
||||
import { getMethodShortHand } from '../tags/method-tag';
|
||||
@@ -330,6 +331,15 @@ export const ExportRequestsModal = ({
|
||||
</Button>
|
||||
<Button
|
||||
onPress={() => {
|
||||
if (state?.treeRoot) {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.exportRequestsChosen,
|
||||
properties: {
|
||||
totalRequests: state.treeRoot.totalRequests,
|
||||
exported_requests: state.treeRoot.selectedRequests,
|
||||
},
|
||||
});
|
||||
}
|
||||
state?.treeRoot && exportRequestsToFile(workspaceIdToExport, getSelectedRequestIds(state.treeRoot));
|
||||
close();
|
||||
}}
|
||||
|
||||
@@ -333,9 +333,20 @@ export const ImportModal: FC<ImportModalProps> = ({
|
||||
|
||||
useEffect(() => {
|
||||
if (importFetcher?.data?.done === true) {
|
||||
// Track the import completion event
|
||||
if (scanResourcesFetcherData?.length) {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.importCompleted,
|
||||
properties: {
|
||||
workspaces: scanResourcesFetcherData.map(scanResult => scanResult.workspaces?.length || 0),
|
||||
requests: scanResourcesFetcherData.map(scanResult => scanResult.requests?.length || 0),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
modalRef.current?.hide();
|
||||
}
|
||||
}, [importFetcher.data]);
|
||||
}, [importFetcher.data, scanResourcesFetcherData]);
|
||||
// allow workspace import if there is only one workspace
|
||||
const totalWorkspacesCount = useMemo(() => {
|
||||
return (
|
||||
|
||||
@@ -259,6 +259,7 @@ export const InviteForm = ({ allRoles, onInviteCompleted }: EmailsInputProps) =>
|
||||
properties: {
|
||||
numberOfInvites: emailsToInvite.length,
|
||||
numberOfTeams: groupsToInvite.length,
|
||||
role: selectedRoleRef.current.name,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ import { insomniaFetch } from '../../../insomniaFetch';
|
||||
import type { Collaborator, CollaboratorsListLoaderResult } from '../../../routes/invite';
|
||||
import { PromptButton } from '../../base/prompt-button';
|
||||
import { Icon } from '../../icon';
|
||||
import { showAlert } from '..';
|
||||
import { showAlert } from '../index';
|
||||
import { InviteForm } from './invite-form';
|
||||
import { OrganizationMemberRolesSelector, type Role, SELECTOR_TYPE } from './organization-member-roles-selector';
|
||||
|
||||
@@ -373,6 +373,7 @@ const MemberListItem: FC<{
|
||||
method: 'POST',
|
||||
},
|
||||
);
|
||||
window.main.trackSegmentEvent({ event: SegmentEvent.inviteResent });
|
||||
}
|
||||
}}
|
||||
className="flex min-w-[75px] items-center gap-2 px-2 py-1 text-sm font-semibold text-[--color-font] transition-all aria-pressed:bg-[--hl-sm]"
|
||||
@@ -476,6 +477,7 @@ const MemberListItem: FC<{
|
||||
revokeOrganizationInvite(organizationId, member.metadata.invitationId)
|
||||
.then(() => {
|
||||
onResetCurrentPage();
|
||||
window.main.trackSegmentEvent({ event: SegmentEvent.inviteRevoked });
|
||||
})
|
||||
.catch(error => {
|
||||
onError(error.message);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { type FC } from 'react';
|
||||
import { Button } from 'react-aria-components';
|
||||
|
||||
import { SegmentEvent } from '../../analytics';
|
||||
import { Icon } from '../icon';
|
||||
|
||||
interface Props {
|
||||
@@ -38,7 +39,16 @@ export const ProjectEmptyView: FC<Props> = ({
|
||||
<Button
|
||||
aria-label="Import"
|
||||
className="flex w-full max-w-[180px] flex-col items-center justify-center gap-[var(--padding-xs)] rounded-md border border-solid border-[--hl-sm] px-12 py-8 text-[var(--font-size-sm)] shadow-sm transition-all duration-100 hover:bg-[--color-bg] sm:gap-[var(--padding-sm)]"
|
||||
onPress={onImportFrom}
|
||||
onPress={() => {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.importStarted,
|
||||
properties: {
|
||||
source: 'home-page',
|
||||
},
|
||||
});
|
||||
|
||||
onImportFrom();
|
||||
}}
|
||||
>
|
||||
<Icon icon="file-import" className="text-[var(--font-size-xl)]" />
|
||||
Import
|
||||
|
||||
@@ -9,7 +9,6 @@ import { version } from '../../../package.json';
|
||||
import { parseApiSpec, resolveComponentSchemaRefs } from '../../common/api-specs';
|
||||
import { ACTIVITY_DEBUG, getAIServiceURL, METHOD_GET } from '../../common/constants';
|
||||
import { database } from '../../common/database';
|
||||
import { database as db } from '../../common/database';
|
||||
import { importResourcesToWorkspace, scanResources, type ScanResult } from '../../common/import';
|
||||
import { generateId } from '../../common/misc';
|
||||
import * as models from '../../models';
|
||||
@@ -39,6 +38,7 @@ import { SpectralRunner } from '../worker/spectral-handler';
|
||||
// Project
|
||||
export const createNewProjectAction: ActionFunction = async ({ request, params }) => {
|
||||
const { organizationId } = params;
|
||||
|
||||
invariant(organizationId, 'Organization ID is required');
|
||||
const newProjectData = (await request.json()) as {
|
||||
name: string;
|
||||
@@ -62,6 +62,13 @@ export const createNewProjectAction: ActionFunction = async ({ request, params }
|
||||
parentId: organizationId,
|
||||
});
|
||||
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.projectCreated,
|
||||
properties: {
|
||||
storage: 'local',
|
||||
},
|
||||
});
|
||||
|
||||
return redirect(`/organization/${organizationId}/project/${project._id}`);
|
||||
}
|
||||
|
||||
@@ -77,6 +84,13 @@ export const createNewProjectAction: ActionFunction = async ({ request, params }
|
||||
};
|
||||
}
|
||||
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.projectCreated,
|
||||
properties: {
|
||||
storage: 'git',
|
||||
},
|
||||
});
|
||||
|
||||
return redirect(`/organization/${organizationId}/project/${projectId}`);
|
||||
}
|
||||
|
||||
@@ -99,6 +113,15 @@ export const createNewProjectAction: ActionFunction = async ({ request, params }
|
||||
sessionId,
|
||||
});
|
||||
|
||||
if (newCloudProject && !('error' in newCloudProject)) {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.projectCreated,
|
||||
properties: {
|
||||
storage: 'remote',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!newCloudProject || 'error' in newCloudProject) {
|
||||
let error = 'An unexpected error occurred while creating the project. Please try again.';
|
||||
if (newCloudProject.error === 'FORBIDDEN') {
|
||||
@@ -209,6 +232,15 @@ export const updateProjectAction: ActionFunction = async ({ request, params }) =
|
||||
sessionId,
|
||||
});
|
||||
|
||||
if (response && !response.error) {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.projectUpdated,
|
||||
properties: {
|
||||
storage: 'local',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (response && 'error' in response) {
|
||||
let error = 'An unexpected error occurred while updating your project. Please try again.';
|
||||
|
||||
@@ -250,6 +282,15 @@ export const updateProjectAction: ActionFunction = async ({ request, params }) =
|
||||
sessionId,
|
||||
});
|
||||
|
||||
if (newCloudProject && !('error' in newCloudProject)) {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.projectUpdated,
|
||||
properties: {
|
||||
storage: 'remote',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (!newCloudProject || 'error' in newCloudProject) {
|
||||
let error = 'An unexpected error occurred while updating your project. Please try again.';
|
||||
if (newCloudProject.error === 'FORBIDDEN') {
|
||||
@@ -293,6 +334,15 @@ export const updateProjectAction: ActionFunction = async ({ request, params }) =
|
||||
sessionId,
|
||||
});
|
||||
|
||||
if (response && !response.error) {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.projectUpdated,
|
||||
properties: {
|
||||
storage: 'git',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (response && 'error' in response) {
|
||||
let error = 'An unexpected error occurred while updating your project. Please try again.';
|
||||
|
||||
@@ -358,6 +408,13 @@ export const updateProjectAction: ActionFunction = async ({ request, params }) =
|
||||
// local project rename
|
||||
await models.project.update(project, { name });
|
||||
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.projectUpdated,
|
||||
properties: {
|
||||
storage: 'local',
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
success: true,
|
||||
};
|
||||
@@ -683,7 +740,7 @@ async function duplicateWorkspace(
|
||||
invariant(workspace, 'Workspace not found');
|
||||
invariant(duplicateToProject, 'Project not found');
|
||||
async function duplicate(workspace: Workspace, { name, parentId }: Pick<Workspace, 'name' | 'parentId'>) {
|
||||
const newWorkspace = await db.duplicate(workspace, {
|
||||
const newWorkspace = await database.duplicate(workspace, {
|
||||
name,
|
||||
parentId,
|
||||
});
|
||||
|
||||
@@ -21,6 +21,7 @@ import {
|
||||
import { VCSInstance } from '../../sync/vcs/insomnia-sync';
|
||||
import type { ImportEntry } from '../../utils/importers/entities';
|
||||
import { invariant } from '../../utils/invariant';
|
||||
import { SegmentEvent } from '../analytics';
|
||||
import { fetchAndCacheOrganizationStorageRule } from './organization';
|
||||
|
||||
export const scanForResourcesAction: ActionFunction = async ({ request }): Promise<ScanResult[]> => {
|
||||
@@ -31,6 +32,13 @@ export const scanForResourcesAction: ActionFunction = async ({ request }): Promi
|
||||
invariant(typeof source === 'string', 'Source is required.');
|
||||
invariant(['file', 'uri', 'clipboard'].includes(source), 'Unsupported import type');
|
||||
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.importScanned,
|
||||
properties: {
|
||||
source,
|
||||
},
|
||||
});
|
||||
|
||||
const contentList: ImportEntry[] = [];
|
||||
if (source === 'uri') {
|
||||
const uri = formData.get('uri');
|
||||
@@ -150,6 +158,7 @@ export const importResourcesAction: ActionFunction = async ({ request }): Promis
|
||||
await importResourcesToWorkspace({
|
||||
workspaceId: workspaceId,
|
||||
});
|
||||
|
||||
// TODO: find more elegant way to wait for import to finish
|
||||
return { done: true };
|
||||
}
|
||||
|
||||
@@ -66,6 +66,7 @@ import { VCSInstance } from '../../sync/vcs/insomnia-sync';
|
||||
import { insomniaFetch } from '../../ui/insomniaFetch';
|
||||
import { invariant } from '../../utils/invariant';
|
||||
import { getInitialRouteForOrganization } from '../../utils/router';
|
||||
import { SegmentEvent } from '../analytics';
|
||||
import { AvatarGroup } from '../components/avatar';
|
||||
import { GitProjectSyncDropdown } from '../components/dropdowns/git-project-sync-dropdown';
|
||||
import { ProjectDropdown } from '../components/dropdowns/project-dropdown';
|
||||
@@ -1308,6 +1309,12 @@ const ProjectRoute: FC = () => {
|
||||
|
||||
<Button
|
||||
onPress={() => {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.importStarted,
|
||||
properties: {
|
||||
source: 'project',
|
||||
},
|
||||
});
|
||||
setImportModalType('file');
|
||||
}}
|
||||
aria-label="Import"
|
||||
|
||||
@@ -19,6 +19,30 @@ import type { BackendProject, Compare, Snapshot, Status, StatusCandidate } from
|
||||
import { UserAbortResolveMergeConflictError, VCSInstance } from '../../sync/vcs/insomnia-sync';
|
||||
import { pullBackendProject } from '../../sync/vcs/pull-backend-project';
|
||||
import { invariant } from '../../utils/invariant';
|
||||
import { SegmentEvent } from '../analytics';
|
||||
|
||||
type PushPull = 'push' | 'pull';
|
||||
type VCSAction =
|
||||
| PushPull
|
||||
| `force_${PushPull}`
|
||||
| 'create_branch'
|
||||
| 'merge_branch'
|
||||
| 'delete_branch'
|
||||
| 'checkout_branch'
|
||||
| 'commit'
|
||||
| 'stage_all'
|
||||
| 'stage'
|
||||
| 'unstage_all'
|
||||
| 'unstage'
|
||||
| 'rollback'
|
||||
| 'rollback_all'
|
||||
| 'update'
|
||||
| 'setup'
|
||||
| 'clone';
|
||||
|
||||
export function vcsSegmentEventProperties(type: 'remote', action: VCSAction, error?: string) {
|
||||
return { type, action, error };
|
||||
}
|
||||
|
||||
async function getSyncItems({ workspaceId }: { workspaceId: string }) {
|
||||
const syncItemsList: (
|
||||
@@ -457,10 +481,21 @@ export const pullFromRemoteAction: ActionFunction = async ({ params }) => {
|
||||
projectId: project._id,
|
||||
});
|
||||
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.vcsAction,
|
||||
properties: vcsSegmentEventProperties('remote', 'pull'),
|
||||
});
|
||||
|
||||
await database.batchModifyDocs(delta);
|
||||
delete remoteCompareCache[workspaceId];
|
||||
} catch (err) {
|
||||
const errorMessage = err instanceof Error ? err.message : 'Unknown error while pulling from remote.';
|
||||
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.vcsAction,
|
||||
properties: vcsSegmentEventProperties('remote', 'pull', errorMessage),
|
||||
});
|
||||
|
||||
return {
|
||||
error: errorMessage,
|
||||
};
|
||||
@@ -519,9 +554,21 @@ export const pushToRemoteAction: ActionFunction = async ({ params }) => {
|
||||
teamId: project.parentId,
|
||||
teamProjectId: project.remoteId,
|
||||
});
|
||||
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.vcsAction,
|
||||
properties: vcsSegmentEventProperties('remote', 'push'),
|
||||
});
|
||||
|
||||
delete remoteCompareCache[workspaceId];
|
||||
} catch (err) {
|
||||
const errorMessage = err instanceof Error ? err.message : 'Unknown error while pushing to remote.';
|
||||
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.vcsAction,
|
||||
properties: vcsSegmentEventProperties('remote', 'push', errorMessage),
|
||||
});
|
||||
|
||||
return {
|
||||
error: errorMessage,
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ import type { UserSession } from '../../models/user-session';
|
||||
import { reloadPlugins } from '../../plugins';
|
||||
import { createPlugin } from '../../plugins/create';
|
||||
import { setTheme } from '../../plugins/misc';
|
||||
import { SegmentEvent } from '../analytics';
|
||||
import { getLoginUrl } from '../auth-session-provider';
|
||||
import { ErrorBoundary } from '../components/error-boundary';
|
||||
import { showError, showModal } from '../components/modals';
|
||||
@@ -90,6 +91,13 @@ const Root = () => {
|
||||
);
|
||||
}
|
||||
if (urlWithoutParams === 'insomnia://app/import') {
|
||||
window.main.trackSegmentEvent({
|
||||
event: SegmentEvent.importStarted,
|
||||
properties: {
|
||||
source: 'import-url',
|
||||
},
|
||||
});
|
||||
|
||||
return setImportUri(params.uri);
|
||||
}
|
||||
if (urlWithoutParams === 'insomnia://plugins/install') {
|
||||
|
||||
Reference in New Issue
Block a user