mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
feat(editor): Make focus panel resizable (no-changelog) (#17289)
This commit is contained in:
@@ -14,13 +14,21 @@ function closestNumber(value: number, divisor: number): number {
|
|||||||
return n2;
|
return n2;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getSize(min: number, virtual: number, gridSize: number): number {
|
function getSize(min: number, virtual: number, gridSize: number, max: number): number {
|
||||||
const target = closestNumber(virtual, gridSize);
|
if (virtual <= 0) {
|
||||||
if (target >= min && virtual > 0) {
|
return min;
|
||||||
return target;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return min;
|
const target = closestNumber(virtual, gridSize);
|
||||||
|
|
||||||
|
if (target <= min) {
|
||||||
|
return min;
|
||||||
|
}
|
||||||
|
if (target >= max) {
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
|
||||||
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ResizeProps {
|
interface ResizeProps {
|
||||||
@@ -28,7 +36,9 @@ interface ResizeProps {
|
|||||||
height?: number;
|
height?: number;
|
||||||
width?: number;
|
width?: number;
|
||||||
minHeight?: number;
|
minHeight?: number;
|
||||||
|
maxHeight?: number;
|
||||||
minWidth?: number;
|
minWidth?: number;
|
||||||
|
maxWidth?: number;
|
||||||
scale?: number;
|
scale?: number;
|
||||||
gridSize?: number;
|
gridSize?: number;
|
||||||
supportedDirections?: Direction[];
|
supportedDirections?: Direction[];
|
||||||
@@ -41,7 +51,9 @@ const props = withDefaults(defineProps<ResizeProps>(), {
|
|||||||
height: 0,
|
height: 0,
|
||||||
width: 0,
|
width: 0,
|
||||||
minHeight: 0,
|
minHeight: 0,
|
||||||
|
maxHeight: Number.POSITIVE_INFINITY,
|
||||||
minWidth: 0,
|
minWidth: 0,
|
||||||
|
maxWidth: Number.POSITIVE_INFINITY,
|
||||||
scale: 1,
|
scale: 1,
|
||||||
gridSize: 20,
|
gridSize: 20,
|
||||||
outset: false,
|
outset: false,
|
||||||
@@ -109,8 +121,8 @@ const mouseMove = (event: MouseEvent) => {
|
|||||||
|
|
||||||
state.vHeight.value = state.vHeight.value + deltaHeight;
|
state.vHeight.value = state.vHeight.value + deltaHeight;
|
||||||
state.vWidth.value = state.vWidth.value + deltaWidth;
|
state.vWidth.value = state.vWidth.value + deltaWidth;
|
||||||
const height = getSize(props.minHeight, state.vHeight.value, props.gridSize);
|
const height = getSize(props.minHeight, state.vHeight.value, props.gridSize, props.maxHeight);
|
||||||
const width = getSize(props.minWidth, state.vWidth.value, props.gridSize);
|
const width = getSize(props.minWidth, state.vWidth.value, props.gridSize, props.maxWidth);
|
||||||
|
|
||||||
const dX = left && width !== props.width ? -1 * (width - props.width) : 0;
|
const dX = left && width !== props.width ? -1 * (width - props.width) : 0;
|
||||||
const dY = top && height !== props.height ? -1 * (height - props.height) : 0;
|
const dY = top && height !== props.height ? -1 * (height - props.height) : 0;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import { useFocusPanelStore } from '@/stores/focusPanel.store';
|
import { useFocusPanelStore } from '@/stores/focusPanel.store';
|
||||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||||
import { N8nText, N8nInput } from '@n8n/design-system';
|
import { N8nText, N8nInput, N8nResizeWrapper } from '@n8n/design-system';
|
||||||
import { computed, nextTick, ref } from 'vue';
|
import { computed, nextTick, ref } from 'vue';
|
||||||
import { useI18n } from '@n8n/i18n';
|
import { useI18n } from '@n8n/i18n';
|
||||||
import {
|
import {
|
||||||
@@ -26,7 +26,8 @@ import { useEnvironmentsStore } from '@/stores/environments.ee.store';
|
|||||||
import { useDebounce } from '@/composables/useDebounce';
|
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 { TargetNodeParameterContext } from '@/Interface';
|
import type { ResizeData, TargetNodeParameterContext } from '@/Interface';
|
||||||
|
import { useThrottleFn } from '@vueuse/core';
|
||||||
|
|
||||||
defineOptions({ name: 'FocusPanel' });
|
defineOptions({ name: 'FocusPanel' });
|
||||||
|
|
||||||
@@ -58,6 +59,7 @@ const resolvedParameter = computed(() =>
|
|||||||
);
|
);
|
||||||
|
|
||||||
const focusPanelActive = computed(() => focusPanelStore.focusPanelActive);
|
const focusPanelActive = computed(() => focusPanelStore.focusPanelActive);
|
||||||
|
const focusPanelWidth = computed(() => focusPanelStore.focusPanelWidth);
|
||||||
|
|
||||||
const isDisabled = computed(() => {
|
const isDisabled = computed(() => {
|
||||||
if (!resolvedParameter.value) return false;
|
if (!resolvedParameter.value) return false;
|
||||||
@@ -244,153 +246,177 @@ function optionSelected(command: string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const valueChangedDebounced = debounce(valueChanged, { debounceTime: 0 });
|
const valueChangedDebounced = debounce(valueChanged, { debounceTime: 0 });
|
||||||
|
|
||||||
|
function onResize(event: ResizeData) {
|
||||||
|
focusPanelStore.updateWidth(event.width);
|
||||||
|
}
|
||||||
|
|
||||||
|
const onResizeThrottle = useThrottleFn(onResize, 10);
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div v-if="focusPanelActive" :class="$style.container" @keydown.stop>
|
<div v-if="focusPanelActive" :class="$style.wrapper" @keydown.stop>
|
||||||
<div :class="$style.header">
|
<N8nResizeWrapper
|
||||||
<N8nText size="small" :bold="true">
|
:width="focusPanelWidth"
|
||||||
{{ locale.baseText('nodeView.focusPanel.title') }}
|
:supported-directions="['left']"
|
||||||
</N8nText>
|
:min-width="300"
|
||||||
<div :class="$style.closeButton" @click="focusPanelStore.closeFocusPanel">
|
:max-width="1000"
|
||||||
<n8n-icon icon="arrow-right" color="text-base" />
|
:grid-size="8"
|
||||||
</div>
|
:style="{ width: `${focusPanelWidth}px` }"
|
||||||
</div>
|
@resize="onResizeThrottle"
|
||||||
<div v-if="resolvedParameter" :class="$style.content">
|
>
|
||||||
<div :class="$style.tabHeader">
|
<div :class="$style.container">
|
||||||
<div :class="$style.tabHeaderText">
|
<div :class="$style.header">
|
||||||
<N8nText color="text-dark" size="small">
|
<N8nText size="small" :bold="true">
|
||||||
{{ resolvedParameter.parameter.displayName }}
|
{{ locale.baseText('nodeView.focusPanel.title') }}
|
||||||
</N8nText>
|
</N8nText>
|
||||||
<N8nText color="text-base" size="xsmall">{{ resolvedParameter.node.name }}</N8nText>
|
<div :class="$style.closeButton" @click="focusPanelStore.closeFocusPanel">
|
||||||
|
<n8n-icon icon="arrow-right" color="text-base" />
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<NodeExecuteButton
|
<div v-if="resolvedParameter" :class="$style.content">
|
||||||
data-test-id="node-execute-button"
|
<div :class="$style.tabHeader">
|
||||||
:node-name="resolvedParameter.node.name"
|
<div :class="$style.tabHeaderText">
|
||||||
:tooltip="`Execute ${resolvedParameter.node.name}`"
|
<N8nText color="text-dark" size="small">
|
||||||
:disabled="!isExecutable"
|
{{ resolvedParameter.parameter.displayName }}
|
||||||
size="small"
|
|
||||||
icon="play"
|
|
||||||
:square="true"
|
|
||||||
:hide-label="true"
|
|
||||||
telemetry-source="focus"
|
|
||||||
></NodeExecuteButton>
|
|
||||||
</div>
|
|
||||||
<div :class="$style.parameterDetailsWrapper">
|
|
||||||
<div :class="$style.parameterOptionsWrapper">
|
|
||||||
<div></div>
|
|
||||||
<ParameterOptions
|
|
||||||
v-if="isDisplayed"
|
|
||||||
:parameter="resolvedParameter.parameter"
|
|
||||||
:value="resolvedParameter.value"
|
|
||||||
:is-read-only="isReadOnly"
|
|
||||||
@update:model-value="optionSelected"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div v-if="typeof resolvedParameter.value === 'string'" :class="$style.editorContainer">
|
|
||||||
<div v-if="!isDisplayed" :class="[$style.content, $style.emptyContent]">
|
|
||||||
<div :class="$style.emptyText">
|
|
||||||
<N8nText color="text-base">
|
|
||||||
{{ locale.baseText('nodeView.focusPanel.missingParameter') }}
|
|
||||||
</N8nText>
|
</N8nText>
|
||||||
|
<N8nText color="text-base" size="xsmall">{{ resolvedParameter.node.name }}</N8nText>
|
||||||
|
</div>
|
||||||
|
<NodeExecuteButton
|
||||||
|
data-test-id="node-execute-button"
|
||||||
|
:node-name="resolvedParameter.node.name"
|
||||||
|
:tooltip="`Execute ${resolvedParameter.node.name}`"
|
||||||
|
:disabled="!isExecutable"
|
||||||
|
size="small"
|
||||||
|
icon="play"
|
||||||
|
:square="true"
|
||||||
|
:hide-label="true"
|
||||||
|
telemetry-source="focus"
|
||||||
|
></NodeExecuteButton>
|
||||||
|
</div>
|
||||||
|
<div :class="$style.parameterDetailsWrapper">
|
||||||
|
<div :class="$style.parameterOptionsWrapper">
|
||||||
|
<div></div>
|
||||||
|
<ParameterOptions
|
||||||
|
v-if="isDisplayed"
|
||||||
|
:parameter="resolvedParameter.parameter"
|
||||||
|
:value="resolvedParameter.value"
|
||||||
|
:is-read-only="isReadOnly"
|
||||||
|
@update:model-value="optionSelected"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div v-if="typeof resolvedParameter.value === 'string'" :class="$style.editorContainer">
|
||||||
|
<div v-if="!isDisplayed" :class="[$style.content, $style.emptyContent]">
|
||||||
|
<div :class="$style.emptyText">
|
||||||
|
<N8nText color="text-base">
|
||||||
|
{{ locale.baseText('nodeView.focusPanel.missingParameter') }}
|
||||||
|
</N8nText>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<ExpressionEditorModalInput
|
||||||
|
v-else-if="expressionModeEnabled"
|
||||||
|
ref="inputField"
|
||||||
|
:model-value="resolvedParameter.value"
|
||||||
|
:class="$style.editor"
|
||||||
|
:is-read-only="isReadOnly"
|
||||||
|
:path="resolvedParameter.parameterPath"
|
||||||
|
data-test-id="expression-modal-input"
|
||||||
|
:target-node-parameter-context="targetNodeParameterContext"
|
||||||
|
@change="valueChangedDebounced($event.value)"
|
||||||
|
/>
|
||||||
|
<template v-else-if="['json', 'string'].includes(resolvedParameter.parameter.type)">
|
||||||
|
<CodeNodeEditor
|
||||||
|
v-if="editorType === 'codeNodeEditor'"
|
||||||
|
:id="resolvedParameter.parameterPath"
|
||||||
|
:mode="codeEditorMode"
|
||||||
|
:model-value="resolvedParameter.value"
|
||||||
|
:default-value="resolvedParameter.parameter.default"
|
||||||
|
:language="editorLanguage"
|
||||||
|
:is-read-only="isReadOnly"
|
||||||
|
:target-node-parameter-context="targetNodeParameterContext"
|
||||||
|
fill-parent
|
||||||
|
:disable-ask-ai="true"
|
||||||
|
@update:model-value="valueChangedDebounced" />
|
||||||
|
<HtmlEditor
|
||||||
|
v-else-if="editorType === 'htmlEditor'"
|
||||||
|
:model-value="resolvedParameter.value"
|
||||||
|
:is-read-only="isReadOnly"
|
||||||
|
:rows="editorRows"
|
||||||
|
:disable-expression-coloring="!isHtmlNode"
|
||||||
|
:disable-expression-completions="!isHtmlNode"
|
||||||
|
fullscreen
|
||||||
|
@update:model-value="valueChangedDebounced" />
|
||||||
|
<CssEditor
|
||||||
|
v-else-if="editorType === 'cssEditor'"
|
||||||
|
:model-value="resolvedParameter.value"
|
||||||
|
:is-read-only="isReadOnly"
|
||||||
|
:rows="editorRows"
|
||||||
|
fullscreen
|
||||||
|
@update:model-value="valueChangedDebounced" />
|
||||||
|
<SqlEditor
|
||||||
|
v-else-if="editorType === 'sqlEditor'"
|
||||||
|
:model-value="resolvedParameter.value"
|
||||||
|
:dialect="getTypeOption('sqlDialect')"
|
||||||
|
:is-read-only="isReadOnly"
|
||||||
|
:rows="editorRows"
|
||||||
|
fullscreen
|
||||||
|
@update:model-value="valueChangedDebounced" />
|
||||||
|
<JsEditor
|
||||||
|
v-else-if="editorType === 'jsEditor'"
|
||||||
|
:model-value="resolvedParameter.value"
|
||||||
|
:is-read-only="isReadOnly"
|
||||||
|
:rows="editorRows"
|
||||||
|
:posthog-capture="shouldCaptureForPosthog"
|
||||||
|
fill-parent
|
||||||
|
@update:model-value="valueChangedDebounced" />
|
||||||
|
<JsonEditor
|
||||||
|
v-else-if="resolvedParameter.parameter.type === 'json'"
|
||||||
|
:model-value="resolvedParameter.value"
|
||||||
|
:is-read-only="isReadOnly"
|
||||||
|
:rows="editorRows"
|
||||||
|
fullscreen
|
||||||
|
fill-parent
|
||||||
|
@update:model-value="valueChangedDebounced" />
|
||||||
|
<N8nInput
|
||||||
|
v-else
|
||||||
|
ref="inputField"
|
||||||
|
:model-value="resolvedParameter.value"
|
||||||
|
:class="$style.editor"
|
||||||
|
:readonly="isReadOnly"
|
||||||
|
type="textarea"
|
||||||
|
resize="none"
|
||||||
|
@update:model-value="valueChangedDebounced"
|
||||||
|
></N8nInput
|
||||||
|
></template>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<ExpressionEditorModalInput
|
</div>
|
||||||
v-else-if="expressionModeEnabled"
|
<div v-else :class="[$style.content, $style.emptyContent]">
|
||||||
ref="inputField"
|
<div :class="$style.emptyText">
|
||||||
:model-value="resolvedParameter.value"
|
<N8nText color="text-base">
|
||||||
:class="$style.editor"
|
{{ locale.baseText('nodeView.focusPanel.noParameters') }}
|
||||||
:is-read-only="isReadOnly"
|
</N8nText>
|
||||||
:path="resolvedParameter.parameterPath"
|
</div>
|
||||||
data-test-id="expression-modal-input"
|
|
||||||
:target-node-parameter-context="targetNodeParameterContext"
|
|
||||||
@change="valueChangedDebounced($event.value)"
|
|
||||||
/>
|
|
||||||
<template v-else-if="['json', 'string'].includes(resolvedParameter.parameter.type)">
|
|
||||||
<CodeNodeEditor
|
|
||||||
v-if="editorType === 'codeNodeEditor'"
|
|
||||||
:id="resolvedParameter.parameterPath"
|
|
||||||
:mode="codeEditorMode"
|
|
||||||
:model-value="resolvedParameter.value"
|
|
||||||
:default-value="resolvedParameter.parameter.default"
|
|
||||||
:language="editorLanguage"
|
|
||||||
:is-read-only="isReadOnly"
|
|
||||||
:target-node-parameter-context="targetNodeParameterContext"
|
|
||||||
fill-parent
|
|
||||||
:disable-ask-ai="true"
|
|
||||||
@update:model-value="valueChangedDebounced" />
|
|
||||||
<HtmlEditor
|
|
||||||
v-else-if="editorType === 'htmlEditor'"
|
|
||||||
:model-value="resolvedParameter.value"
|
|
||||||
:is-read-only="isReadOnly"
|
|
||||||
:rows="editorRows"
|
|
||||||
:disable-expression-coloring="!isHtmlNode"
|
|
||||||
:disable-expression-completions="!isHtmlNode"
|
|
||||||
fullscreen
|
|
||||||
@update:model-value="valueChangedDebounced" />
|
|
||||||
<CssEditor
|
|
||||||
v-else-if="editorType === 'cssEditor'"
|
|
||||||
:model-value="resolvedParameter.value"
|
|
||||||
:is-read-only="isReadOnly"
|
|
||||||
:rows="editorRows"
|
|
||||||
fullscreen
|
|
||||||
@update:model-value="valueChangedDebounced" />
|
|
||||||
<SqlEditor
|
|
||||||
v-else-if="editorType === 'sqlEditor'"
|
|
||||||
:model-value="resolvedParameter.value"
|
|
||||||
:dialect="getTypeOption('sqlDialect')"
|
|
||||||
:is-read-only="isReadOnly"
|
|
||||||
:rows="editorRows"
|
|
||||||
fullscreen
|
|
||||||
@update:model-value="valueChangedDebounced" />
|
|
||||||
<JsEditor
|
|
||||||
v-else-if="editorType === 'jsEditor'"
|
|
||||||
:model-value="resolvedParameter.value"
|
|
||||||
:is-read-only="isReadOnly"
|
|
||||||
:rows="editorRows"
|
|
||||||
:posthog-capture="shouldCaptureForPosthog"
|
|
||||||
fill-parent
|
|
||||||
@update:model-value="valueChangedDebounced" />
|
|
||||||
<JsonEditor
|
|
||||||
v-else-if="resolvedParameter.parameter.type === 'json'"
|
|
||||||
:model-value="resolvedParameter.value"
|
|
||||||
:is-read-only="isReadOnly"
|
|
||||||
:rows="editorRows"
|
|
||||||
fullscreen
|
|
||||||
fill-parent
|
|
||||||
@update:model-value="valueChangedDebounced" />
|
|
||||||
<N8nInput
|
|
||||||
v-else
|
|
||||||
ref="inputField"
|
|
||||||
:model-value="resolvedParameter.value"
|
|
||||||
:class="$style.editor"
|
|
||||||
:readonly="isReadOnly"
|
|
||||||
type="textarea"
|
|
||||||
resize="none"
|
|
||||||
@update:model-value="valueChangedDebounced"
|
|
||||||
></N8nInput
|
|
||||||
></template>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</N8nResizeWrapper>
|
||||||
<div v-else :class="[$style.content, $style.emptyContent]">
|
|
||||||
<div :class="$style.emptyText">
|
|
||||||
<N8nText color="text-base">
|
|
||||||
{{ locale.baseText('nodeView.focusPanel.noParameters') }}
|
|
||||||
</N8nText>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" module>
|
<style lang="scss" module>
|
||||||
.container {
|
.wrapper {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: row nowrap;
|
||||||
width: 528px;
|
|
||||||
border-left: 1px solid var(--color-foreground-base);
|
border-left: 1px solid var(--color-foreground-base);
|
||||||
background: var(--color-foreground-light);
|
background: var(--color-foreground-light);
|
||||||
overflow-y: hidden;
|
overflow-y: hidden;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.closeButton:hover {
|
.closeButton:hover {
|
||||||
|
|||||||
@@ -13,6 +13,8 @@ import { useWorkflowsStore } from './workflows.store';
|
|||||||
import { LOCAL_STORAGE_FOCUS_PANEL, PLACEHOLDER_EMPTY_WORKFLOW_ID } from '@/constants';
|
import { LOCAL_STORAGE_FOCUS_PANEL, PLACEHOLDER_EMPTY_WORKFLOW_ID } from '@/constants';
|
||||||
import { useStorage } from '@/composables/useStorage';
|
import { useStorage } from '@/composables/useStorage';
|
||||||
|
|
||||||
|
const DEFAULT_PANEL_WIDTH = 528;
|
||||||
|
|
||||||
type FocusedNodeParameter = {
|
type FocusedNodeParameter = {
|
||||||
nodeId: string;
|
nodeId: string;
|
||||||
parameter: INodeProperties;
|
parameter: INodeProperties;
|
||||||
@@ -27,6 +29,7 @@ export type RichFocusedNodeParameter = FocusedNodeParameter & {
|
|||||||
type FocusPanelData = {
|
type FocusPanelData = {
|
||||||
isActive: boolean;
|
isActive: boolean;
|
||||||
parameters: FocusedNodeParameter[];
|
parameters: FocusedNodeParameter[];
|
||||||
|
width?: number;
|
||||||
};
|
};
|
||||||
|
|
||||||
type FocusPanelDataByWid = Record<string, FocusPanelData>;
|
type FocusPanelDataByWid = Record<string, FocusPanelData>;
|
||||||
@@ -53,6 +56,7 @@ export const useFocusPanelStore = defineStore(STORES.FOCUS_PANEL, () => {
|
|||||||
);
|
);
|
||||||
|
|
||||||
const focusPanelActive = computed(() => currentFocusPanelData.value.isActive);
|
const focusPanelActive = computed(() => currentFocusPanelData.value.isActive);
|
||||||
|
const focusPanelWidth = computed(() => currentFocusPanelData.value.width ?? DEFAULT_PANEL_WIDTH);
|
||||||
const _focusedNodeParameters = computed(() => currentFocusPanelData.value.parameters);
|
const _focusedNodeParameters = computed(() => currentFocusPanelData.value.parameters);
|
||||||
|
|
||||||
// An unenriched parameter indicates a missing nodeId
|
// An unenriched parameter indicates a missing nodeId
|
||||||
@@ -74,11 +78,13 @@ export const useFocusPanelStore = defineStore(STORES.FOCUS_PANEL, () => {
|
|||||||
parameters,
|
parameters,
|
||||||
isActive,
|
isActive,
|
||||||
wid = workflowsStore.workflowId,
|
wid = workflowsStore.workflowId,
|
||||||
|
width = undefined,
|
||||||
removeEmpty = false,
|
removeEmpty = false,
|
||||||
}: {
|
}: {
|
||||||
isActive?: boolean;
|
isActive?: boolean;
|
||||||
parameters?: FocusedNodeParameter[];
|
parameters?: FocusedNodeParameter[];
|
||||||
wid?: string;
|
wid?: string;
|
||||||
|
width?: number;
|
||||||
removeEmpty?: boolean;
|
removeEmpty?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const focusPanelDataCurrent = focusPanelData.value;
|
const focusPanelDataCurrent = focusPanelData.value;
|
||||||
@@ -92,6 +98,7 @@ export const useFocusPanelStore = defineStore(STORES.FOCUS_PANEL, () => {
|
|||||||
[wid]: {
|
[wid]: {
|
||||||
isActive: isActive ?? focusPanelActive.value,
|
isActive: isActive ?? focusPanelActive.value,
|
||||||
parameters: parameters ?? _focusedNodeParameters.value,
|
parameters: parameters ?? _focusedNodeParameters.value,
|
||||||
|
width,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -127,6 +134,10 @@ export const useFocusPanelStore = defineStore(STORES.FOCUS_PANEL, () => {
|
|||||||
_setOptions({ isActive: !focusPanelActive.value });
|
_setOptions({ isActive: !focusPanelActive.value });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function updateWidth(width: number) {
|
||||||
|
_setOptions({ width });
|
||||||
|
}
|
||||||
|
|
||||||
function isRichParameter(
|
function isRichParameter(
|
||||||
p: RichFocusedNodeParameter | FocusedNodeParameter,
|
p: RichFocusedNodeParameter | FocusedNodeParameter,
|
||||||
): p is RichFocusedNodeParameter {
|
): p is RichFocusedNodeParameter {
|
||||||
@@ -141,5 +152,7 @@ export const useFocusPanelStore = defineStore(STORES.FOCUS_PANEL, () => {
|
|||||||
closeFocusPanel,
|
closeFocusPanel,
|
||||||
toggleFocusPanel,
|
toggleFocusPanel,
|
||||||
onNewWorkflowSave,
|
onNewWorkflowSave,
|
||||||
|
updateWidth,
|
||||||
|
focusPanelWidth,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user