mirror of
https://github.com/n8n-io/n8n.git
synced 2024-12-24 20:24:05 -08:00
fix(editor): Improve error messages around pinned data (#9632)
This commit is contained in:
parent
37531cdb7d
commit
a8bb53f4e3
|
@ -144,6 +144,19 @@ describe('Data pinning', () => {
|
|||
.should('contain', 'Workflow has reached the maximum allowed pinned data size');
|
||||
});
|
||||
|
||||
it('Should show an error when pin data JSON in invalid', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas('Schedule Trigger');
|
||||
workflowPage.actions.addNodeToCanvas(EDIT_FIELDS_SET_NODE_NAME, true, true);
|
||||
ndv.getters.container().should('be.visible');
|
||||
ndv.getters.pinDataButton().should('not.exist');
|
||||
ndv.getters.editPinnedDataButton().should('be.visible');
|
||||
|
||||
ndv.actions.setPinnedData('[ { "name": "First item", "code": 2dsa }]')
|
||||
workflowPage.getters
|
||||
.errorToast()
|
||||
.should('contain', 'Unable to save due to invalid JSON');
|
||||
});
|
||||
|
||||
it('Should be able to reference paired items in a node located before pinned data', () => {
|
||||
workflowPage.actions.addInitialNodeToCanvas(MANUAL_TRIGGER_NODE_NAME);
|
||||
workflowPage.actions.addNodeToCanvas(HTTP_REQUEST_NODE_NAME, true, true);
|
||||
|
|
|
@ -151,14 +151,15 @@ export class NDV extends BasePage {
|
|||
cy.contains('Expression').invoke('show').click();
|
||||
this.getters.inlineExpressionEditorInput().click();
|
||||
},
|
||||
setPinnedData: (data: object) => {
|
||||
setPinnedData: (data: object | string) => {
|
||||
const pinnedData = typeof data === 'string' ? data : JSON.stringify(data);
|
||||
this.getters.editPinnedDataButton().click();
|
||||
|
||||
this.getters.pinnedDataEditor().click();
|
||||
this.getters
|
||||
.pinnedDataEditor()
|
||||
.type(
|
||||
`{selectall}{backspace}${JSON.stringify(data).replace(new RegExp('{', 'g'), '{{}')}`,
|
||||
`{selectall}{backspace}${pinnedData.replace(new RegExp('{', 'g'), '{{}')}`,
|
||||
{
|
||||
delay: 0,
|
||||
},
|
||||
|
|
|
@ -1294,9 +1294,15 @@ export default defineComponent({
|
|||
this.clearAllStickyNotifications();
|
||||
|
||||
try {
|
||||
this.pinnedData.setData(clearJsonKey(value) as INodeExecutionData[], 'save-edit');
|
||||
const clearedValue = clearJsonKey(value) as INodeExecutionData[];
|
||||
try {
|
||||
this.pinnedData.setData(clearedValue, 'save-edit');
|
||||
} catch (error) {
|
||||
// setData function already shows toasts on error, so just return here
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
this.showError(error, this.$locale.baseText('ndv.pinData.error.syntaxError.title'));
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import {
|
|||
MAX_WORKFLOW_SIZE,
|
||||
PIN_DATA_NODE_TYPES_DENYLIST,
|
||||
} from '@/constants';
|
||||
import { stringSizeInBytes } from '@/utils/typesUtils';
|
||||
import { stringSizeInBytes, toMegaBytes } from '@/utils/typesUtils';
|
||||
import { useWorkflowsStore } from '@/stores/workflows.store';
|
||||
import type { INodeUi, IRunDataDisplayMode } from '@/Interface';
|
||||
import { useExternalHooks } from '@/composables/useExternalHooks';
|
||||
|
@ -158,19 +158,29 @@ export function usePinnedData(
|
|||
|
||||
if (newPinDataSize > MAX_PINNED_DATA_SIZE) {
|
||||
toast.showError(
|
||||
new Error(i18n.baseText('ndv.pinData.error.tooLarge.description')),
|
||||
new Error(
|
||||
i18n.baseText('ndv.pinData.error.tooLarge.description', {
|
||||
interpolate: {
|
||||
size: toMegaBytes(newPinDataSize),
|
||||
limit: toMegaBytes(MAX_PINNED_DATA_SIZE),
|
||||
},
|
||||
}),
|
||||
),
|
||||
i18n.baseText('ndv.pinData.error.tooLarge.title'),
|
||||
);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
if (
|
||||
stringSizeInBytes(workflowJson) + newPinDataSize >
|
||||
MAX_WORKFLOW_SIZE - MAX_EXPECTED_REQUEST_SIZE
|
||||
) {
|
||||
const workflowSize = stringSizeInBytes(workflowJson) + newPinDataSize;
|
||||
const limit = MAX_WORKFLOW_SIZE - MAX_EXPECTED_REQUEST_SIZE;
|
||||
if (workflowSize > limit) {
|
||||
toast.showError(
|
||||
new Error(i18n.baseText('ndv.pinData.error.tooLargeWorkflow.description')),
|
||||
new Error(
|
||||
i18n.baseText('ndv.pinData.error.tooLargeWorkflow.description', {
|
||||
interpolate: { size: toMegaBytes(workflowSize), limit: toMegaBytes(limit) },
|
||||
}),
|
||||
),
|
||||
i18n.baseText('ndv.pinData.error.tooLargeWorkflow.title'),
|
||||
);
|
||||
|
||||
|
|
|
@ -945,10 +945,11 @@
|
|||
"ndv.pinData.beforeClosing.title": "Save output changes before closing?",
|
||||
"ndv.pinData.beforeClosing.cancel": "Discard",
|
||||
"ndv.pinData.beforeClosing.confirm": "Save",
|
||||
"ndv.pinData.error.tooLarge.title": "Pinned data too big",
|
||||
"ndv.pinData.error.tooLarge.description": "Workflow has reached the maximum allowed pinned data size",
|
||||
"ndv.pinData.error.tooLargeWorkflow.title": "Pinned data too big",
|
||||
"ndv.pinData.error.tooLargeWorkflow.description": "Workflow has reached the maximum allowed size",
|
||||
"ndv.pinData.error.syntaxError.title": "Unable to save due to invalid JSON",
|
||||
"ndv.pinData.error.tooLarge.title": "Unable to pin data due to size limit",
|
||||
"ndv.pinData.error.tooLarge.description": "Workflow has reached the maximum allowed pinned data size ({size} mb / {limit} mb)",
|
||||
"ndv.pinData.error.tooLargeWorkflow.title": "Unable to pin data due to size limit",
|
||||
"ndv.pinData.error.tooLargeWorkflow.description": "Workflow has reached the maximum allowed size ({size} mb / {limit} mb)",
|
||||
"ndv.httpRequest.credentialOnly.docsNotice": "Use the <a target=\"_blank\" href=\"{docsUrl}\">{nodeName} docs</a> to construct your request. We'll take care of the authentication part if you add a {nodeName} credential below.",
|
||||
"noTagsView.readyToOrganizeYourWorkflows": "Ready to organize your workflows?",
|
||||
"noTagsView.withWorkflowTagsYouReFree": "With workflow tags, you're free to create the perfect tagging system for your flows",
|
||||
|
|
|
@ -63,6 +63,11 @@ export function stringSizeInBytes(input: string | IDataObject | IDataObject[] |
|
|||
return new Blob([typeof input === 'string' ? input : JSON.stringify(input)]).size;
|
||||
}
|
||||
|
||||
export function toMegaBytes(bytes: number, decimalPlaces: number = 2): number {
|
||||
const megabytes = bytes / 1024 / 1024;
|
||||
return parseFloat(megabytes.toFixed(decimalPlaces));
|
||||
}
|
||||
|
||||
export function shorten(s: string, limit: number, keep: number) {
|
||||
if (s.length <= limit) {
|
||||
return s;
|
||||
|
|
Loading…
Reference in a new issue