mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 10:02:05 +00:00
feat(editor): Add telemetry for focus panel (no-changelog) (#17159)
Co-authored-by: Daria Staferova <daria.staferova@n8n.io>
This commit is contained in:
@@ -28,6 +28,7 @@ import { useDebounce } from '@/composables/useDebounce';
|
||||
import { htmlEditorEventBus } from '@/event-bus';
|
||||
import { hasFocusOnInput, isFocusableEl } from '@/utils/typesUtils';
|
||||
import type { ResizeData, TargetNodeParameterContext } from '@/Interface';
|
||||
import { useTelemetry } from '@/composables/useTelemetry';
|
||||
import { useThrottleFn } from '@vueuse/core';
|
||||
import { useStyles } from '@/composables/useStyles';
|
||||
import { useExecutionData } from '@/composables/useExecutionData';
|
||||
@@ -53,6 +54,7 @@ const nodeHelpers = useNodeHelpers();
|
||||
const focusPanelStore = useFocusPanelStore();
|
||||
const workflowsStore = useWorkflowsStore();
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const telemetry = useTelemetry();
|
||||
const nodeSettingsParameters = useNodeSettingsParameters();
|
||||
const environmentsStore = useEnvironmentsStore();
|
||||
const deviceSupport = useDeviceSupport();
|
||||
@@ -262,6 +264,22 @@ function optionSelected(command: string) {
|
||||
}
|
||||
}
|
||||
|
||||
function closeFocusPanel() {
|
||||
telemetry.track('User closed focus panel', {
|
||||
source: 'closeIcon',
|
||||
parameters: focusPanelStore.focusedNodeParametersInTelemetryFormat,
|
||||
});
|
||||
|
||||
focusPanelStore.closeFocusPanel();
|
||||
}
|
||||
|
||||
function onExecute() {
|
||||
telemetry.track(
|
||||
'User executed node from focus panel',
|
||||
focusPanelStore.focusedNodeParametersInTelemetryFormat[0],
|
||||
);
|
||||
}
|
||||
|
||||
const valueChangedDebounced = debounce(valueChanged, { debounceTime: 0 });
|
||||
|
||||
// Wait for editor to mount before focusing
|
||||
@@ -343,13 +361,14 @@ const onResizeThrottle = useThrottleFn(onResize, 10);
|
||||
:square="true"
|
||||
:hide-label="true"
|
||||
telemetry-source="focus"
|
||||
></NodeExecuteButton>
|
||||
@execute="onExecute"
|
||||
/>
|
||||
<N8nIcon
|
||||
:class="$style.closeButton"
|
||||
icon="x"
|
||||
color="text-base"
|
||||
size="xlarge"
|
||||
@click="focusPanelStore.closeFocusPanel"
|
||||
@click="closeFocusPanel"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -21,6 +21,7 @@ import { useActions } from './NodeCreator/composables/useActions';
|
||||
import KeyboardShortcutTooltip from '@/components/KeyboardShortcutTooltip.vue';
|
||||
import AssistantIcon from '@n8n/design-system/components/AskAssistantIcon/AssistantIcon.vue';
|
||||
import { useI18n } from '@n8n/i18n';
|
||||
import { useTelemetry } from '@/composables/useTelemetry';
|
||||
import { useAssistantStore } from '@/stores/assistant.store';
|
||||
|
||||
type Props = {
|
||||
@@ -46,6 +47,7 @@ const uiStore = useUIStore();
|
||||
const focusPanelStore = useFocusPanelStore();
|
||||
const posthogStore = usePostHog();
|
||||
const i18n = useI18n();
|
||||
const telemetry = useTelemetry();
|
||||
const assistantStore = useAssistantStore();
|
||||
|
||||
const { getAddedNodesAndConnections } = useActions();
|
||||
@@ -86,6 +88,15 @@ function nodeTypeSelected(value: NodeTypeSelectedPayload[]) {
|
||||
closeNodeCreator(true);
|
||||
}
|
||||
|
||||
function toggleFocusPanel() {
|
||||
focusPanelStore.toggleFocusPanel();
|
||||
|
||||
telemetry.track(`User ${focusPanelStore.focusPanelActive ? 'opened' : 'closed'} focus panel`, {
|
||||
source: 'canvasButton',
|
||||
parameters: focusPanelStore.focusedNodeParametersInTelemetryFormat,
|
||||
});
|
||||
}
|
||||
|
||||
function onAskAssistantButtonClick() {
|
||||
if (!assistantStore.chatWindowOpen)
|
||||
assistantStore.trackUserOpenedAssistant({
|
||||
@@ -132,12 +143,7 @@ function onAskAssistantButtonClick() {
|
||||
:shortcut="{ keys: ['f'], shiftKey: true }"
|
||||
placement="left"
|
||||
>
|
||||
<n8n-icon-button
|
||||
type="tertiary"
|
||||
size="large"
|
||||
icon="panel-right"
|
||||
@click="focusPanelStore.toggleFocusPanel"
|
||||
/>
|
||||
<n8n-icon-button type="tertiary" size="large" icon="panel-right" @click="toggleFocusPanel" />
|
||||
</KeyboardShortcutTooltip>
|
||||
<n8n-tooltip v-if="assistantStore.canShowAssistantButtonsOnCanvas" placement="left">
|
||||
<template #content> {{ i18n.baseText('aiAssistant.tooltip') }}</template>
|
||||
|
||||
@@ -78,6 +78,7 @@ import { isCredentialOnlyNodeType } from '@/utils/credentialOnlyNodes';
|
||||
import { hasFocusOnInput, isBlurrableEl, isFocusableEl, isSelectableEl } from '@/utils/typesUtils';
|
||||
import { completeExpressionSyntax, shouldConvertToExpression } from '@/utils/expressions';
|
||||
import CssEditor from './CssEditor/CssEditor.vue';
|
||||
import { useFocusPanelStore } from '@/stores/focusPanel.store';
|
||||
|
||||
type Picker = { $emit: (arg0: string, arg1: Date) => void };
|
||||
|
||||
@@ -141,6 +142,7 @@ const workflowsStore = useWorkflowsStore();
|
||||
const settingsStore = useSettingsStore();
|
||||
const nodeTypesStore = useNodeTypesStore();
|
||||
const uiStore = useUIStore();
|
||||
const focusPanelStore = useFocusPanelStore();
|
||||
|
||||
// ESLint: false positive
|
||||
// eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
|
||||
@@ -1000,6 +1002,10 @@ async function optionSelected(command: string) {
|
||||
|
||||
case 'focus':
|
||||
nodeSettingsParameters.handleFocus(node.value, props.path, props.parameter);
|
||||
telemetry.track('User opened focus panel', {
|
||||
source: 'parameterButton',
|
||||
parameters: focusPanelStore.focusedNodeParametersInTelemetryFormat,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -152,6 +152,16 @@ export const useFocusPanelStore = defineStore(STORES.FOCUS_PANEL, () => {
|
||||
return 'value' in p && 'node' in p;
|
||||
}
|
||||
|
||||
const focusedNodeParametersInTelemetryFormat = computed<
|
||||
Array<{ parameterPath: string; nodeType: string; nodeId: string }>
|
||||
>(() =>
|
||||
focusedNodeParameters.value.map((x) => ({
|
||||
parameterPath: x.parameterPath,
|
||||
nodeType: isRichParameter(x) ? x.node.type : 'unresolved',
|
||||
nodeId: x.nodeId,
|
||||
})),
|
||||
);
|
||||
|
||||
// Ensure lastFocusTimestamp is set on initial load if panel is already active (e.g. after reload)
|
||||
watchOnce(
|
||||
() => currentFocusPanelData.value,
|
||||
@@ -165,6 +175,7 @@ export const useFocusPanelStore = defineStore(STORES.FOCUS_PANEL, () => {
|
||||
return {
|
||||
focusPanelActive,
|
||||
focusedNodeParameters,
|
||||
focusedNodeParametersInTelemetryFormat,
|
||||
lastFocusTimestamp,
|
||||
focusPanelWidth,
|
||||
openWithFocusedNodeParameter,
|
||||
|
||||
@@ -1233,6 +1233,11 @@ function onToggleFocusPanel() {
|
||||
}
|
||||
|
||||
focusPanelStore.toggleFocusPanel();
|
||||
telemetry.track(`User ${focusPanelStore.focusPanelActive ? 'opened' : 'closed'} focus panel`, {
|
||||
source: 'canvasKeyboardShortcut',
|
||||
parameters: focusPanelStore.focusedNodeParametersInTelemetryFormat,
|
||||
parameterCount: focusPanelStore.focusedNodeParametersInTelemetryFormat.length,
|
||||
});
|
||||
}
|
||||
|
||||
function closeNodeCreator() {
|
||||
|
||||
Reference in New Issue
Block a user