mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
145 lines
3.6 KiB
Vue
145 lines
3.6 KiB
Vue
<script setup lang="ts">
|
|
import { computed, ref } from 'vue';
|
|
import { listenForModalChanges, useUIStore } from '@/stores/ui.store';
|
|
import { listenForCredentialChanges, useCredentialsStore } from '@/stores/credentials.store';
|
|
import { assert } from '@/utils/assert';
|
|
import CredentialsDropdown from './CredentialsDropdown.vue';
|
|
import { useI18n } from '@/composables/useI18n';
|
|
import { CREDENTIAL_EDIT_MODAL_KEY } from '@/constants';
|
|
|
|
const props = defineProps<{
|
|
appName: string;
|
|
credentialType: string;
|
|
selectedCredentialId: string | null;
|
|
}>();
|
|
|
|
const $emit = defineEmits({
|
|
credentialSelected: (_credentialId: string) => true,
|
|
credentialDeselected: () => true,
|
|
credentialModalOpened: () => true,
|
|
});
|
|
|
|
const uiStore = useUIStore();
|
|
const credentialsStore = useCredentialsStore();
|
|
const i18n = useI18n();
|
|
|
|
const wasModalOpenedFromHere = ref(false);
|
|
|
|
const availableCredentials = computed(() => {
|
|
return credentialsStore.getCredentialsByType(props.credentialType);
|
|
});
|
|
|
|
const credentialOptions = computed(() => {
|
|
return availableCredentials.value.map((credential) => ({
|
|
id: credential.id,
|
|
name: credential.name,
|
|
typeDisplayName: credentialsStore.getCredentialTypeByName(credential.type)?.displayName,
|
|
}));
|
|
});
|
|
|
|
const onCredentialSelected = (credentialId: string) => {
|
|
$emit('credentialSelected', credentialId);
|
|
};
|
|
const createNewCredential = () => {
|
|
uiStore.openNewCredential(props.credentialType, true);
|
|
wasModalOpenedFromHere.value = true;
|
|
$emit('credentialModalOpened');
|
|
};
|
|
const editCredential = () => {
|
|
assert(props.selectedCredentialId);
|
|
uiStore.openExistingCredential(props.selectedCredentialId);
|
|
wasModalOpenedFromHere.value = true;
|
|
$emit('credentialModalOpened');
|
|
};
|
|
|
|
listenForCredentialChanges({
|
|
store: credentialsStore,
|
|
onCredentialCreated: (credential) => {
|
|
if (!wasModalOpenedFromHere.value) {
|
|
return;
|
|
}
|
|
|
|
$emit('credentialSelected', credential.id);
|
|
},
|
|
onCredentialDeleted: (deletedCredentialId) => {
|
|
if (!wasModalOpenedFromHere.value) {
|
|
return;
|
|
}
|
|
|
|
if (deletedCredentialId !== props.selectedCredentialId) {
|
|
return;
|
|
}
|
|
|
|
const optionsWoDeleted = credentialOptions.value
|
|
.map((credential) => credential.id)
|
|
.filter((id) => id !== deletedCredentialId);
|
|
if (optionsWoDeleted.length > 0) {
|
|
$emit('credentialSelected', optionsWoDeleted[0]);
|
|
} else {
|
|
$emit('credentialDeselected');
|
|
}
|
|
},
|
|
});
|
|
|
|
listenForModalChanges({
|
|
store: uiStore,
|
|
onModalClosed(modalName) {
|
|
if (modalName === CREDENTIAL_EDIT_MODAL_KEY && wasModalOpenedFromHere.value) {
|
|
wasModalOpenedFromHere.value = false;
|
|
}
|
|
},
|
|
});
|
|
</script>
|
|
|
|
<template>
|
|
<div>
|
|
<div v-if="credentialOptions.length > 0" :class="$style.dropdown">
|
|
<CredentialsDropdown
|
|
:credential-type="props.credentialType"
|
|
:credential-options="credentialOptions"
|
|
:selected-credential-id="props.selectedCredentialId"
|
|
@credential-selected="onCredentialSelected"
|
|
@new-credential="createNewCredential"
|
|
/>
|
|
|
|
<n8n-icon-button
|
|
icon="pen"
|
|
type="secondary"
|
|
:class="{
|
|
[$style.edit]: true,
|
|
[$style.invisible]: !props.selectedCredentialId,
|
|
}"
|
|
:title="i18n.baseText('nodeCredentials.updateCredential')"
|
|
data-test-id="credential-edit-button"
|
|
@click="editCredential()"
|
|
/>
|
|
</div>
|
|
|
|
<n8n-button
|
|
v-else
|
|
:label="`Create new ${props.appName} credential`"
|
|
data-test-id="create-credential"
|
|
@click="createNewCredential"
|
|
/>
|
|
</div>
|
|
</template>
|
|
|
|
<style lang="scss" module>
|
|
.dropdown {
|
|
display: flex;
|
|
}
|
|
|
|
.edit {
|
|
display: flex;
|
|
justify-content: center;
|
|
align-items: center;
|
|
min-width: 20px;
|
|
margin-left: var(--spacing-2xs);
|
|
font-size: var(--font-size-s);
|
|
}
|
|
|
|
.invisible {
|
|
visibility: hidden;
|
|
}
|
|
</style>
|