diff --git a/packages/backend/src/controllers/api/v1/steps/update-step.js b/packages/backend/src/controllers/api/v1/steps/update-step.js index c707726d..70f0b98f 100644 --- a/packages/backend/src/controllers/api/v1/steps/update-step.js +++ b/packages/backend/src/controllers/api/v1/steps/update-step.js @@ -11,12 +11,13 @@ export default async (request, response) => { }; const stepParams = (request) => { - const { connectionId, appKey, key, parameters } = request.body; + const { connectionId, appKey, key, name, parameters } = request.body; return { connectionId, appKey, key, + name, parameters, }; }; diff --git a/packages/backend/src/controllers/api/v1/steps/update-step.test.js b/packages/backend/src/controllers/api/v1/steps/update-step.test.js index 1a5ae1b9..c219dee0 100644 --- a/packages/backend/src/controllers/api/v1/steps/update-step.test.js +++ b/packages/backend/src/controllers/api/v1/steps/update-step.test.js @@ -35,6 +35,7 @@ describe('PATCH /api/v1/steps/:stepId', () => { connectionId: currentUserConnection.id, appKey: 'deepl', key: 'translateText', + name: 'Translate text', }); await createPermission({ @@ -58,6 +59,7 @@ describe('PATCH /api/v1/steps/:stepId', () => { parameters: { text: 'Hello world!', targetLanguage: 'de', + name: 'Translate text - Updated step name', }, }) .expect(200); diff --git a/packages/backend/src/db/migrations/20250106114602_add_name_column_to_steps.js b/packages/backend/src/db/migrations/20250106114602_add_name_column_to_steps.js new file mode 100644 index 00000000..bde4d6c5 --- /dev/null +++ b/packages/backend/src/db/migrations/20250106114602_add_name_column_to_steps.js @@ -0,0 +1,26 @@ +import toLower from 'lodash/toLower.js'; +import startCase from 'lodash/startCase.js'; +import upperFirst from 'lodash/upperFirst.js'; + +export async function up(knex) { + await knex.schema.table('steps', function (table) { + table.string('name'); + }); + + const rows = await knex('steps').select('id', 'key'); + + const updates = rows.map((row) => { + if (!row.key) return; + + const humanizedKey = upperFirst(toLower(startCase(row.key))); + return knex('steps').where({ id: row.id }).update({ name: humanizedKey }); + }); + + return await Promise.all(updates); +} + +export async function down(knex) { + return knex.schema.table('steps', function (table) { + table.dropColumn('name'); + }); +} diff --git a/packages/backend/src/models/__snapshots__/step.test.js.snap b/packages/backend/src/models/__snapshots__/step.test.js.snap index aa78645e..d9a45102 100644 --- a/packages/backend/src/models/__snapshots__/step.test.js.snap +++ b/packages/backend/src/models/__snapshots__/step.test.js.snap @@ -38,6 +38,14 @@ exports[`Step model > jsonSchema should have correct validations 1`] = ` "null", ], }, + "name": { + "maxLength": 255, + "minLength": 1, + "type": [ + "string", + "null", + ], + }, "parameters": { "type": "object", }, diff --git a/packages/backend/src/models/step.js b/packages/backend/src/models/step.js index 9f5f3f70..7c31e0a6 100644 --- a/packages/backend/src/models/step.js +++ b/packages/backend/src/models/step.js @@ -22,6 +22,7 @@ class Step extends Base { id: { type: 'string', format: 'uuid' }, flowId: { type: 'string', format: 'uuid' }, key: { type: ['string', 'null'] }, + name: { type: ['string', 'null'], minLength: 1, maxLength: 255 }, appKey: { type: ['string', 'null'], minLength: 1, maxLength: 255 }, type: { type: 'string', enum: ['action', 'trigger'] }, connectionId: { type: ['string', 'null'], format: 'uuid' }, @@ -314,7 +315,13 @@ class Step extends Base { } async updateFor(user, newStepData) { - const { appKey = this.appKey, connectionId, key, parameters } = newStepData; + const { + appKey = this.appKey, + name, + connectionId, + key, + parameters, + } = newStepData; if (connectionId && appKey) { await user.authorizedConnections @@ -335,6 +342,7 @@ class Step extends Base { const updatedStep = await this.$query().patchAndFetch({ key, + name, appKey, connectionId: connectionId, parameters: parameters, diff --git a/packages/backend/src/serializers/step.js b/packages/backend/src/serializers/step.js index f5ae1c26..5c1e0d38 100644 --- a/packages/backend/src/serializers/step.js +++ b/packages/backend/src/serializers/step.js @@ -5,6 +5,7 @@ const stepSerializer = (step) => { id: step.id, type: step.type, key: step.key, + name: step.name, appKey: step.appKey, iconUrl: step.iconUrl, webhookUrl: step.webhookUrl, diff --git a/packages/backend/src/serializers/step.test.js b/packages/backend/src/serializers/step.test.js index dfeffbeb..2b26cfcf 100644 --- a/packages/backend/src/serializers/step.test.js +++ b/packages/backend/src/serializers/step.test.js @@ -16,6 +16,7 @@ describe('stepSerializer', () => { id: step.id, type: step.type, key: step.key, + name: step.name, appKey: step.appKey, iconUrl: step.iconUrl, webhookUrl: step.webhookUrl, diff --git a/packages/backend/test/mocks/rest/api/v1/executions/get-execution-steps.js b/packages/backend/test/mocks/rest/api/v1/executions/get-execution-steps.js index f7b50194..f694f70a 100644 --- a/packages/backend/test/mocks/rest/api/v1/executions/get-execution-steps.js +++ b/packages/backend/test/mocks/rest/api/v1/executions/get-execution-steps.js @@ -14,6 +14,7 @@ const getExecutionStepsMock = async (executionSteps, steps) => { id: step.id, type: step.type, key: step.key, + name: step.name, appKey: step.appKey, iconUrl: step.iconUrl, webhookUrl: step.webhookUrl, diff --git a/packages/backend/test/mocks/rest/api/v1/executions/get-execution.js b/packages/backend/test/mocks/rest/api/v1/executions/get-execution.js index 3957e9d8..61feddd8 100644 --- a/packages/backend/test/mocks/rest/api/v1/executions/get-execution.js +++ b/packages/backend/test/mocks/rest/api/v1/executions/get-execution.js @@ -15,6 +15,7 @@ const getExecutionMock = async (execution, flow, steps) => { id: step.id, type: step.type, key: step.key, + name: step.name, appKey: step.appKey, iconUrl: step.iconUrl, webhookUrl: step.webhookUrl, diff --git a/packages/backend/test/mocks/rest/api/v1/executions/get-executions.js b/packages/backend/test/mocks/rest/api/v1/executions/get-executions.js index 21d36376..b194bee2 100644 --- a/packages/backend/test/mocks/rest/api/v1/executions/get-executions.js +++ b/packages/backend/test/mocks/rest/api/v1/executions/get-executions.js @@ -16,6 +16,7 @@ const getExecutionsMock = async (executions, flow, steps) => { id: step.id, type: step.type, key: step.key, + name: step.name, appKey: step.appKey, iconUrl: step.iconUrl, webhookUrl: step.webhookUrl, diff --git a/packages/backend/test/mocks/rest/api/v1/flows/duplicate-flow.js b/packages/backend/test/mocks/rest/api/v1/flows/duplicate-flow.js index 67684191..36426774 100644 --- a/packages/backend/test/mocks/rest/api/v1/flows/duplicate-flow.js +++ b/packages/backend/test/mocks/rest/api/v1/flows/duplicate-flow.js @@ -14,6 +14,7 @@ const duplicateFlowMock = async (flow, steps = []) => { iconUrl: step.iconUrl, id: step.id, key: step.key, + name: step.name, parameters: step.parameters, position: step.position, status: step.status, diff --git a/packages/backend/test/mocks/rest/api/v1/flows/get-flow.js b/packages/backend/test/mocks/rest/api/v1/flows/get-flow.js index db1e4a47..49efe83c 100644 --- a/packages/backend/test/mocks/rest/api/v1/flows/get-flow.js +++ b/packages/backend/test/mocks/rest/api/v1/flows/get-flow.js @@ -14,6 +14,7 @@ const getFlowMock = async (flow, steps = []) => { iconUrl: step.iconUrl, id: step.id, key: step.key, + name: step.name, parameters: step.parameters, position: step.position, status: step.status, diff --git a/packages/backend/test/mocks/rest/api/v1/flows/get-flows.js b/packages/backend/test/mocks/rest/api/v1/flows/get-flows.js index 0509aec3..6012a6f6 100644 --- a/packages/backend/test/mocks/rest/api/v1/flows/get-flows.js +++ b/packages/backend/test/mocks/rest/api/v1/flows/get-flows.js @@ -14,6 +14,7 @@ const getFlowsMock = async (flows, steps) => { iconUrl: step.iconUrl, id: step.id, key: step.key, + name: step.name, parameters: step.parameters, position: step.position, status: step.status, diff --git a/packages/backend/test/mocks/rest/api/v1/flows/update-flow-status.js b/packages/backend/test/mocks/rest/api/v1/flows/update-flow-status.js index f303f295..f7c32b3b 100644 --- a/packages/backend/test/mocks/rest/api/v1/flows/update-flow-status.js +++ b/packages/backend/test/mocks/rest/api/v1/flows/update-flow-status.js @@ -14,6 +14,7 @@ const updateFlowStatusMock = async (flow, steps = []) => { iconUrl: step.iconUrl, id: step.id, key: step.key, + name: step.name, parameters: step.parameters, position: step.position, status: step.status, diff --git a/packages/backend/test/mocks/rest/api/v1/steps/get-previous-steps.js b/packages/backend/test/mocks/rest/api/v1/steps/get-previous-steps.js index 7b5515ed..4ae477d6 100644 --- a/packages/backend/test/mocks/rest/api/v1/steps/get-previous-steps.js +++ b/packages/backend/test/mocks/rest/api/v1/steps/get-previous-steps.js @@ -8,6 +8,7 @@ const getPreviousStepsMock = async (steps, executionSteps) => { id: step.id, type: step.type, key: step.key, + name: step.name, appKey: step.appKey, iconUrl: step.iconUrl, webhookUrl: step.webhookUrl, diff --git a/packages/backend/test/mocks/rest/api/v1/steps/update-step.js b/packages/backend/test/mocks/rest/api/v1/steps/update-step.js index 87514ef9..a7ad0dea 100644 --- a/packages/backend/test/mocks/rest/api/v1/steps/update-step.js +++ b/packages/backend/test/mocks/rest/api/v1/steps/update-step.js @@ -3,6 +3,7 @@ const updateStepMock = (step) => { id: step.id, type: step.type || 'action', key: step.key || null, + name: step.name || null, appKey: step.appKey || null, iconUrl: step.iconUrl || null, webhookUrl: step.webhookUrl || null,