mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-25 12:44:07 -08:00
fix(editor): Add sticky note readonly state in new canvas (#10678)
This commit is contained in:
parent
aa98c18cd7
commit
c5bc8e6eb9
|
@ -91,21 +91,24 @@ export function createCanvasNodeProvide({
|
||||||
id = 'node',
|
id = 'node',
|
||||||
label = 'Test Node',
|
label = 'Test Node',
|
||||||
selected = false,
|
selected = false,
|
||||||
|
readOnly = false,
|
||||||
data = {},
|
data = {},
|
||||||
eventBus = createEventBus<CanvasNodeEventBusEvents>(),
|
eventBus = createEventBus<CanvasNodeEventBusEvents>(),
|
||||||
}: {
|
}: {
|
||||||
id?: string;
|
id?: string;
|
||||||
label?: string;
|
label?: string;
|
||||||
selected?: boolean;
|
selected?: boolean;
|
||||||
|
readOnly?: boolean;
|
||||||
data?: Partial<CanvasNodeData>;
|
data?: Partial<CanvasNodeData>;
|
||||||
eventBus?: EventBus<CanvasNodeEventBusEvents>;
|
eventBus?: EventBus<CanvasNodeEventBusEvents>;
|
||||||
} = {}) {
|
} = {}) {
|
||||||
const props = createCanvasNodeProps({ id, label, selected, data });
|
const props = createCanvasNodeProps({ id, label, selected, readOnly, data });
|
||||||
return {
|
return {
|
||||||
[`${CanvasNodeKey}`]: {
|
[`${CanvasNodeKey}`]: {
|
||||||
id: ref(props.id),
|
id: ref(props.id),
|
||||||
label: ref(props.label),
|
label: ref(props.label),
|
||||||
selected: ref(props.selected),
|
selected: ref(props.selected),
|
||||||
|
readOnly: ref(props.readOnly),
|
||||||
data: ref(props.data),
|
data: ref(props.data),
|
||||||
eventBus: ref(eventBus),
|
eventBus: ref(eventBus),
|
||||||
} satisfies CanvasNodeInjectionData,
|
} satisfies CanvasNodeInjectionData,
|
||||||
|
|
|
@ -219,12 +219,14 @@ const id = toRef(props, 'id');
|
||||||
const data = toRef(props, 'data');
|
const data = toRef(props, 'data');
|
||||||
const label = toRef(props, 'label');
|
const label = toRef(props, 'label');
|
||||||
const selected = toRef(props, 'selected');
|
const selected = toRef(props, 'selected');
|
||||||
|
const readOnly = toRef(props, 'readOnly');
|
||||||
|
|
||||||
provide(CanvasNodeKey, {
|
provide(CanvasNodeKey, {
|
||||||
id,
|
id,
|
||||||
data,
|
data,
|
||||||
label,
|
label,
|
||||||
selected,
|
selected,
|
||||||
|
readOnly,
|
||||||
eventBus: canvasNodeEventBus,
|
eventBus: canvasNodeEventBus,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -93,4 +93,26 @@ describe('CanvasNodeToolbar', () => {
|
||||||
|
|
||||||
expect(emitted('open:contextmenu')[0]).toEqual([expect.any(MouseEvent)]);
|
expect(emitted('open:contextmenu')[0]).toEqual([expect.any(MouseEvent)]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should emit "update" when sticky note color is changed', async () => {
|
||||||
|
const { getAllByTestId, getByTestId, emitted } = renderComponent({
|
||||||
|
global: {
|
||||||
|
provide: {
|
||||||
|
...createCanvasNodeProvide({
|
||||||
|
data: {
|
||||||
|
render: {
|
||||||
|
type: CanvasNodeRenderType.StickyNote,
|
||||||
|
options: { color: 3 },
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
await fireEvent.click(getByTestId('change-sticky-color'));
|
||||||
|
await fireEvent.click(getAllByTestId('color')[0]);
|
||||||
|
|
||||||
|
expect(emitted('update')[0]).toEqual([{ color: 1 }]);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -47,7 +47,9 @@ const isDisableNodeVisible = computed(() => {
|
||||||
|
|
||||||
const isDeleteNodeVisible = computed(() => !props.readOnly);
|
const isDeleteNodeVisible = computed(() => !props.readOnly);
|
||||||
|
|
||||||
const isStickyNoteNodeType = computed(() => render.value.type === CanvasNodeRenderType.StickyNote);
|
const isStickyNoteChangeColorVisible = computed(
|
||||||
|
() => !props.readOnly && render.value.type === CanvasNodeRenderType.StickyNote,
|
||||||
|
);
|
||||||
|
|
||||||
function executeNode() {
|
function executeNode() {
|
||||||
emit('run');
|
emit('run');
|
||||||
|
@ -106,7 +108,10 @@ function onOpenContextMenu(event: MouseEvent) {
|
||||||
:title="i18n.baseText('node.delete')"
|
:title="i18n.baseText('node.delete')"
|
||||||
@click="onDeleteNode"
|
@click="onDeleteNode"
|
||||||
/>
|
/>
|
||||||
<CanvasNodeStickyColorSelector v-if="isStickyNoteNodeType" @update="onChangeStickyColor" />
|
<CanvasNodeStickyColorSelector
|
||||||
|
v-if="isStickyNoteChangeColorVisible"
|
||||||
|
@update="onChangeStickyColor"
|
||||||
|
/>
|
||||||
<N8nIconButton
|
<N8nIconButton
|
||||||
data-test-id="overflow-node-button"
|
data-test-id="overflow-node-button"
|
||||||
type="tertiary"
|
type="tertiary"
|
||||||
|
|
|
@ -13,7 +13,7 @@ beforeEach(() => {
|
||||||
|
|
||||||
describe('CanvasNodeStickyNote', () => {
|
describe('CanvasNodeStickyNote', () => {
|
||||||
it('should render node correctly', () => {
|
it('should render node correctly', () => {
|
||||||
const { getByTestId } = renderComponent({
|
const { html } = renderComponent({
|
||||||
global: {
|
global: {
|
||||||
provide: {
|
provide: {
|
||||||
...createCanvasNodeProvide({
|
...createCanvasNodeProvide({
|
||||||
|
@ -23,6 +23,23 @@ describe('CanvasNodeStickyNote', () => {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(getByTestId('canvas-sticky-note-node')).toMatchSnapshot();
|
expect(html()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable resizing when node is readonly', () => {
|
||||||
|
const { container } = renderComponent({
|
||||||
|
global: {
|
||||||
|
provide: {
|
||||||
|
...createCanvasNodeProvide({
|
||||||
|
id: 'sticky',
|
||||||
|
readOnly: true,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const resizeControls = container.querySelectorAll('.vue-flow__resize-control');
|
||||||
|
|
||||||
|
expect(resizeControls).toHaveLength(0);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -20,7 +20,7 @@ const emit = defineEmits<{
|
||||||
|
|
||||||
const $style = useCssModule();
|
const $style = useCssModule();
|
||||||
|
|
||||||
const { id, isSelected, render, eventBus } = useCanvasNode();
|
const { id, isSelected, isReadOnly, render, eventBus } = useCanvasNode();
|
||||||
|
|
||||||
const renderOptions = computed(() => render.value.options as CanvasNodeStickyNoteRender['options']);
|
const renderOptions = computed(() => render.value.options as CanvasNodeStickyNoteRender['options']);
|
||||||
|
|
||||||
|
@ -95,6 +95,7 @@ onBeforeUnmount(() => {
|
||||||
:min-width="150"
|
:min-width="150"
|
||||||
:height="renderOptions.height"
|
:height="renderOptions.height"
|
||||||
:width="renderOptions.width"
|
:width="renderOptions.width"
|
||||||
|
:is-visible="!isReadOnly"
|
||||||
@resize="onResize"
|
@resize="onResize"
|
||||||
/>
|
/>
|
||||||
<N8nSticky
|
<N8nSticky
|
||||||
|
|
|
@ -1,45 +1,27 @@
|
||||||
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
exports[`CanvasNodeStickyNote > should render node correctly 1`] = `
|
exports[`CanvasNodeStickyNote > should render node correctly 1`] = `
|
||||||
<div
|
"<div class="vue-flow__resize-control nodrag top line"></div>
|
||||||
class="n8n-sticky sticky clickable color-1 sticky"
|
<div class="vue-flow__resize-control nodrag right line"></div>
|
||||||
data-test-id="canvas-sticky-note-node"
|
<div class="vue-flow__resize-control nodrag bottom line"></div>
|
||||||
style="height: 180px; width: 240px;"
|
<div class="vue-flow__resize-control nodrag left line"></div>
|
||||||
>
|
<div class="vue-flow__resize-control nodrag top left handle"></div>
|
||||||
<div
|
<div class="vue-flow__resize-control nodrag top right handle"></div>
|
||||||
class="wrapper"
|
<div class="vue-flow__resize-control nodrag bottom left handle"></div>
|
||||||
>
|
<div class="vue-flow__resize-control nodrag bottom right handle"></div>
|
||||||
<div
|
<div class="n8n-sticky sticky clickable color-1 sticky" style="height: 180px; width: 240px;" data-test-id="canvas-sticky-note-node">
|
||||||
class="n8n-markdown"
|
<div class="wrapper">
|
||||||
>
|
<div class="n8n-markdown">
|
||||||
<div
|
<div class="sticky"></div>
|
||||||
class="sticky"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div class="sticky-textarea" style="display: none;">
|
||||||
class="sticky-textarea"
|
<div class="el-textarea el-input--large n8n-input">
|
||||||
style="display: none;"
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="el-textarea el-input--large n8n-input"
|
|
||||||
>
|
|
||||||
<!-- input -->
|
<!-- input -->
|
||||||
|
<!-- textarea --><textarea class="el-textarea__inner" name="sticky-input" rows="5" title="" tabindex="0" autocomplete="off" placeholder=""></textarea>
|
||||||
<!-- textarea -->
|
|
||||||
<textarea
|
|
||||||
autocomplete="off"
|
|
||||||
class="el-textarea__inner"
|
|
||||||
name="sticky-input"
|
|
||||||
placeholder=""
|
|
||||||
rows="5"
|
|
||||||
tabindex="0"
|
|
||||||
title=""
|
|
||||||
/>
|
|
||||||
<!--v-if-->
|
<!--v-if-->
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!--v-if-->
|
<!--v-if-->
|
||||||
</div>
|
</div>"
|
||||||
`;
|
`;
|
||||||
|
|
|
@ -45,7 +45,7 @@ export function useCanvasNode() {
|
||||||
const connections = computed(() => data.value.connections);
|
const connections = computed(() => data.value.connections);
|
||||||
|
|
||||||
const isDisabled = computed(() => data.value.disabled);
|
const isDisabled = computed(() => data.value.disabled);
|
||||||
|
const isReadOnly = computed(() => node?.readOnly.value);
|
||||||
const isSelected = computed(() => node?.selected.value);
|
const isSelected = computed(() => node?.selected.value);
|
||||||
|
|
||||||
const pinnedDataCount = computed(() => data.value.pinnedData.count);
|
const pinnedDataCount = computed(() => data.value.pinnedData.count);
|
||||||
|
@ -75,6 +75,7 @@ export function useCanvasNode() {
|
||||||
outputs,
|
outputs,
|
||||||
connections,
|
connections,
|
||||||
isDisabled,
|
isDisabled,
|
||||||
|
isReadOnly,
|
||||||
isSelected,
|
isSelected,
|
||||||
pinnedDataCount,
|
pinnedDataCount,
|
||||||
hasPinnedData,
|
hasPinnedData,
|
||||||
|
|
|
@ -155,6 +155,7 @@ export interface CanvasNodeInjectionData {
|
||||||
data: Ref<CanvasNodeData>;
|
data: Ref<CanvasNodeData>;
|
||||||
label: Ref<NodeProps['label']>;
|
label: Ref<NodeProps['label']>;
|
||||||
selected: Ref<NodeProps['selected']>;
|
selected: Ref<NodeProps['selected']>;
|
||||||
|
readOnly: Ref<boolean>;
|
||||||
eventBus: Ref<EventBus<CanvasNodeEventBusEvents>>;
|
eventBus: Ref<EventBus<CanvasNodeEventBusEvents>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue