fix: Hide cred setup button from canvas (no-changelog) (#8255)

This commit is contained in:
Tomi Turtiainen
2024-01-08 13:59:04 +02:00
committed by GitHub
parent 7899f7aca5
commit 8affdf680d
6 changed files with 88 additions and 8 deletions

View File

@@ -202,6 +202,8 @@ describe('Template credentials setup', () => {
});
});
getSetupWorkflowCredentialsButton().should('not.exist');
// We need to save the workflow or otherwise a browser native popup
// will block cypress from continuing
workflowPage.actions.saveWorkflowOnButtonClick();

View File

@@ -206,6 +206,7 @@ export class WorkflowService {
'active',
'nodes',
'connections',
'meta',
'settings',
'staticData',
'pinData',

View File

@@ -609,6 +609,25 @@ describe('PATCH /workflows/:id', () => {
expect(versionId).toBe(workflow.versionId);
expect(active).toBe(false);
});
test('should update workflow meta', async () => {
const workflow = await createWorkflow({}, owner);
const payload = {
...workflow,
meta: {
templateCredsSetupCompleted: true,
},
};
const response = await authOwnerAgent.patch(`/workflows/${workflow.id}`).send(payload);
const { data: updatedWorkflow } = response.body;
expect(response.statusCode).toBe(200);
expect(updatedWorkflow.id).toBe(workflow.id);
expect(updatedWorkflow.meta).toEqual(payload.meta);
});
});
describe('POST /workflows/run', () => {

View File

@@ -274,6 +274,7 @@ export interface WorkflowMetadata {
onboardingId?: string;
templateId?: string;
instanceId?: string;
templateCredsSetupCompleted?: boolean;
}
// Almost identical to cli.Interfaces.ts

View File

@@ -1,12 +1,12 @@
<script lang="ts" setup>
import { computed, onBeforeUnmount, watch } from 'vue';
import { useI18n } from '@/composables/useI18n';
import { SETUP_CREDENTIALS_MODAL_KEY, TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT } from '@/constants';
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
import { usePostHog } from '@/stores/posthog.store';
import { useUIStore } from '@/stores/ui.store';
import { useWorkflowsStore } from '@/stores/workflows.store';
import { doesNodeHaveCredentialsToFill } from '@/utils/nodes/nodeTransforms';
import { computed, onBeforeUnmount } from 'vue';
import { doesNodeHaveAllCredentialsFilled } from '@/utils/nodes/nodeTransforms';
const workflowsStore = useWorkflowsStore();
const nodeTypesStore = useNodeTypesStore();
@@ -14,15 +14,41 @@ const uiStore = useUIStore();
const posthogStore = usePostHog();
const i18n = useI18n();
const showButton = computed(() => {
const isFeatureEnabled = posthogStore.isFeatureEnabled(TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT);
const isCreatedFromTemplate = !!workflowsStore.workflow?.meta?.templateId;
if (!isFeatureEnabled || !isCreatedFromTemplate) {
const isTemplateSetupCompleted = computed(() => {
return !!workflowsStore.workflow?.meta?.templateCredsSetupCompleted;
});
const allCredentialsFilled = computed(() => {
if (isTemplateSetupCompleted.value) {
return true;
}
const nodes = workflowsStore.getNodes();
if (!nodes.length) {
return false;
}
const nodes = workflowsStore.workflow?.nodes ?? [];
return nodes.some((node) => doesNodeHaveCredentialsToFill(nodeTypesStore, node));
return nodes.every((node) => doesNodeHaveAllCredentialsFilled(nodeTypesStore, node));
});
const showButton = computed(() => {
const isFeatureEnabled = posthogStore.isFeatureEnabled(TEMPLATE_CREDENTIAL_SETUP_EXPERIMENT);
const isCreatedFromTemplate = !!workflowsStore.workflow?.meta?.templateId;
if (!isFeatureEnabled || !isCreatedFromTemplate || isTemplateSetupCompleted.value) {
return false;
}
return !allCredentialsFilled.value;
});
const unsubscribe = watch(allCredentialsFilled, (newValue) => {
if (newValue) {
workflowsStore.addToWorkflowMetadata({
templateCredsSetupCompleted: true,
});
unsubscribe();
}
});
const handleClick = () => {

View File

@@ -32,6 +32,9 @@ export function getNodeTypeDisplayableCredentials(
return displayableCredentials;
}
/**
* Checks if the given node has credentials that can be filled.
*/
export function doesNodeHaveCredentialsToFill(
nodeTypeProvider: NodeTypeProvider,
node: Pick<INodeUi, 'parameters' | 'type' | 'typeVersion'>,
@@ -40,3 +43,31 @@ export function doesNodeHaveCredentialsToFill(
return requiredCredentials.length > 0;
}
/**
* Does node has the given credential filled
*
* @param credentialName E.g. "telegramApi"
*/
export function hasNodeCredentialFilled(
node: Pick<INodeUi, 'credentials'>,
credentialName: string,
): boolean {
if (!node.credentials) {
return false;
}
return !!node.credentials[credentialName];
}
/**
* Checks if the given node has all credentials filled.
*/
export function doesNodeHaveAllCredentialsFilled(
nodeTypeProvider: NodeTypeProvider,
node: Pick<INodeUi, 'parameters' | 'type' | 'typeVersion' | 'credentials'>,
): boolean {
const requiredCredentials = getNodeTypeDisplayableCredentials(nodeTypeProvider, node);
return requiredCredentials.every((cred) => hasNodeCredentialFilled(node, cred.name));
}