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