mirror of
https://github.com/Abdulazizzn/n8n-enterprise-unlocked.git
synced 2025-12-17 01:56:46 +00:00
Initial commit to release
This commit is contained in:
316
packages/editor-ui/src/components/NodeCredentials.vue
Normal file
316
packages/editor-ui/src/components/NodeCredentials.vue
Normal file
@@ -0,0 +1,316 @@
|
||||
<template>
|
||||
<div v-if="credentialTypesNodeDescriptionDisplayed.length" class="node-credentials">
|
||||
<credentials-edit :dialogVisible="credentialNewDialogVisible" :editCredentials="editCredentials" :setCredentialType="addType" :nodesInit="nodesInit" @closeDialog="closeCredentialNewDialog" @credentialsCreated="credentialsCreated" @credentialsUpdated="credentialsUpdated"></credentials-edit>
|
||||
|
||||
<div class="headline">
|
||||
Credentials
|
||||
</div>
|
||||
|
||||
<div v-for="credentialTypeDescription in credentialTypesNodeDescriptionDisplayed" :key="credentialTypeDescription.name" class="credential-data">
|
||||
<el-row v-if="displayCredentials(credentialTypeDescription)">
|
||||
|
||||
<el-col :span="10" class="parameter-name">
|
||||
{{credentialTypeNames[credentialTypeDescription.name]}}:
|
||||
</el-col>
|
||||
<el-col :span="12" class="parameter-value" :class="getIssues(credentialTypeDescription.name).length?'has-issues':''">
|
||||
<div class="credential-issues">
|
||||
<el-tooltip placement="top" effect="light">
|
||||
<div slot="content" v-html="'Issues:<br /> - ' + getIssues(credentialTypeDescription.name).join('<br /> - ')"></div>
|
||||
<font-awesome-icon icon="exclamation-triangle" />
|
||||
</el-tooltip>
|
||||
</div>
|
||||
<div :style="credentialInputWrapperStyle(credentialTypeDescription.name)">
|
||||
<el-select v-model="credentials[credentialTypeDescription.name]" :disabled="isReadOnly" @change="credentialSelected(credentialTypeDescription.name)" placeholder="Select Credential" size="small">
|
||||
<el-option
|
||||
v-for="(item, index) in credentialOptions[credentialTypeDescription.name]"
|
||||
:key="item.name + '_' + index"
|
||||
:label="item.name"
|
||||
:value="item.name">
|
||||
</el-option>
|
||||
</el-select>
|
||||
</div>
|
||||
</el-col>
|
||||
<el-col :span="2" class="parameter-value">
|
||||
<font-awesome-icon v-if="credentials[credentialTypeDescription.name]" icon="pen" @click="updateCredentials(credentialTypeDescription.name)" class="update-credentials clickable" title="Update Credentials" />
|
||||
</el-col>
|
||||
|
||||
</el-row>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
import { restApi } from '@/components/mixins/restApi';
|
||||
import {
|
||||
ICredentialsResponse,
|
||||
INodeUi,
|
||||
INodeUpdatePropertiesInformation,
|
||||
IUpdateInformation,
|
||||
} from '@/Interface';
|
||||
import {
|
||||
ICredentialType,
|
||||
INodeCredentialDescription,
|
||||
INodeTypeDescription,
|
||||
} from 'n8n-workflow';
|
||||
|
||||
import CredentialsEdit from '@/components/CredentialsEdit.vue';
|
||||
import ParameterInput from '@/components/ParameterInput.vue';
|
||||
|
||||
import { genericHelpers } from '@/components/mixins/genericHelpers';
|
||||
import { nodeHelpers } from '@/components/mixins/nodeHelpers';
|
||||
import { showMessage } from '@/components/mixins/showMessage';
|
||||
|
||||
import mixins from 'vue-typed-mixins';
|
||||
|
||||
export default mixins(
|
||||
genericHelpers,
|
||||
nodeHelpers,
|
||||
restApi,
|
||||
showMessage,
|
||||
).extend({
|
||||
name: 'NodeCredentials',
|
||||
props: [
|
||||
'node', // INodeUi
|
||||
],
|
||||
components: {
|
||||
CredentialsEdit,
|
||||
ParameterInput,
|
||||
},
|
||||
computed: {
|
||||
credentialTypesNode (): string[] {
|
||||
return this.credentialTypesNodeDescription
|
||||
.map((credentialTypeDescription) => credentialTypeDescription.name);
|
||||
},
|
||||
credentialTypesNodeDescriptionDisplayed (): INodeCredentialDescription[] {
|
||||
return this.credentialTypesNodeDescription
|
||||
.filter((credentialTypeDescription) => {
|
||||
return this.displayCredentials(credentialTypeDescription);
|
||||
});
|
||||
},
|
||||
credentialTypesNodeDescription (): INodeCredentialDescription[] {
|
||||
const node = this.node as INodeUi;
|
||||
|
||||
const activeNodeType = this.$store.getters.nodeType(node.type) as INodeTypeDescription;
|
||||
if (activeNodeType && activeNodeType.credentials) {
|
||||
return activeNodeType.credentials;
|
||||
}
|
||||
|
||||
return [];
|
||||
},
|
||||
credentialTypeNames () {
|
||||
const returnData: {
|
||||
[key: string]: string;
|
||||
} = {};
|
||||
let credentialType: ICredentialType | null;
|
||||
for (const credentialTypeName of this.credentialTypesNode) {
|
||||
credentialType = this.$store.getters.credentialType(credentialTypeName);
|
||||
returnData[credentialTypeName] = credentialType !== null ? credentialType.displayName : credentialTypeName;
|
||||
}
|
||||
return returnData;
|
||||
},
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
addType: undefined as string | undefined,
|
||||
credentialNewDialogVisible: false,
|
||||
credentialOptions: {} as { [key: string]: ICredentialsResponse[]; },
|
||||
credentials: {} as {
|
||||
[key: string]: string | undefined
|
||||
},
|
||||
editCredentials: null as object | null, // Credentials filter
|
||||
newCredentialText: '- Create New -',
|
||||
nodesInit: undefined as string[] | undefined,
|
||||
};
|
||||
},
|
||||
watch: {
|
||||
node () {
|
||||
this.init();
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
closeCredentialNewDialog () {
|
||||
this.credentialNewDialogVisible = false;
|
||||
},
|
||||
async credentialsCreated (data: ICredentialsResponse) {
|
||||
await this.credentialsUpdated(data);
|
||||
},
|
||||
credentialsUpdated (data: ICredentialsResponse) {
|
||||
if (!this.credentialTypesNode.includes(data.type)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.init();
|
||||
Vue.set(this.credentials, data.type, data.name);
|
||||
|
||||
// Makes sure that it does also get set correctly on the node not just the UI
|
||||
this.credentialSelected(data.type);
|
||||
|
||||
this.closeCredentialNewDialog();
|
||||
},
|
||||
credentialInputWrapperStyle (credentialType: string) {
|
||||
let deductWidth = 0;
|
||||
const styles = {
|
||||
width: '100%',
|
||||
};
|
||||
if (this.getIssues(credentialType).length) {
|
||||
deductWidth += 20;
|
||||
}
|
||||
|
||||
if (deductWidth !== 0) {
|
||||
styles.width = `calc(100% - ${deductWidth}px)`;
|
||||
}
|
||||
|
||||
return styles;
|
||||
},
|
||||
credentialSelected (credentialType: string) {
|
||||
const credential = this.credentials[credentialType];
|
||||
if (credential === this.newCredentialText) {
|
||||
// New credentials should be created
|
||||
this.addType = credentialType;
|
||||
this.editCredentials = null;
|
||||
this.nodesInit = [ (this.node as INodeUi).type ];
|
||||
this.credentialNewDialogVisible = true;
|
||||
|
||||
this.credentials[credentialType] = undefined;
|
||||
}
|
||||
|
||||
const node = this.node as INodeUi;
|
||||
|
||||
const updateInformation: INodeUpdatePropertiesInformation = {
|
||||
name: node.name,
|
||||
properties: {
|
||||
credentials: JSON.parse(JSON.stringify(this.credentials)),
|
||||
},
|
||||
};
|
||||
|
||||
this.$emit('credentialSelected', updateInformation);
|
||||
},
|
||||
displayCredentials (credentialTypeDescription: INodeCredentialDescription): boolean {
|
||||
if (credentialTypeDescription.displayOptions === undefined) {
|
||||
// If it is not defined no need to do a proper check
|
||||
return true;
|
||||
}
|
||||
return this.displayParameter(this.node.parameters, credentialTypeDescription, '');
|
||||
},
|
||||
getIssues (credentialTypeName: string): string[] {
|
||||
const node = this.node as INodeUi;
|
||||
|
||||
if (node.issues === undefined || node.issues.credentials === undefined) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (!node.issues.credentials.hasOwnProperty(credentialTypeName)) {
|
||||
return [];
|
||||
}
|
||||
|
||||
return node.issues.credentials[credentialTypeName];
|
||||
},
|
||||
updateCredentials (credentialType: string): void {
|
||||
const credentials = this.credentials[credentialType];
|
||||
|
||||
const name = this.credentials[credentialType];
|
||||
const credentialData = this.credentialOptions[credentialType].find((optionData: ICredentialsResponse) => optionData.name === name);
|
||||
if (credentialData === undefined) {
|
||||
this.$showMessage({
|
||||
title: 'Credentials not found',
|
||||
message: `The credentials named "${name}" of type "${credentialType}" could not be found!`,
|
||||
type: 'error',
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const editCredentials = {
|
||||
id: credentialData.id,
|
||||
name,
|
||||
type: credentialType,
|
||||
};
|
||||
|
||||
this.editCredentials = editCredentials;
|
||||
this.addType = credentialType;
|
||||
this.credentialNewDialogVisible = true;
|
||||
},
|
||||
|
||||
init () {
|
||||
const node = this.node as INodeUi;
|
||||
|
||||
const newOption = {
|
||||
name: this.newCredentialText,
|
||||
};
|
||||
|
||||
let options = [];
|
||||
|
||||
// Get the available credentials for each type
|
||||
for (const credentialType of this.credentialTypesNode) {
|
||||
options = this.$store.getters.credentialsByType(credentialType);
|
||||
options.push(newOption as ICredentialsResponse);
|
||||
Vue.set(this.credentialOptions, credentialType, options);
|
||||
}
|
||||
|
||||
// Set the current node credentials
|
||||
if (node.credentials) {
|
||||
Vue.set(this, 'credentials', JSON.parse(JSON.stringify(node.credentials)));
|
||||
} else {
|
||||
Vue.set(this, 'credentials', {});
|
||||
}
|
||||
},
|
||||
|
||||
},
|
||||
mounted () {
|
||||
this.init();
|
||||
},
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
.node-credentials {
|
||||
padding-bottom: 1em;
|
||||
margin: 0.5em;
|
||||
border-bottom: 1px solid #ccc;
|
||||
|
||||
.credential-issues {
|
||||
display: none;
|
||||
width: 20px;
|
||||
text-align: right;
|
||||
float: right;
|
||||
color: #ff8080;
|
||||
font-size: 1.2em;
|
||||
margin-top: 3px;
|
||||
}
|
||||
|
||||
.credential-data + .credential-data {
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
.has-issues {
|
||||
.credential-issues {
|
||||
display: inline-block;
|
||||
}
|
||||
.el-input input:hover {
|
||||
border-width: 1px;
|
||||
border-color: #ff8080;
|
||||
border-style: solid;
|
||||
}
|
||||
}
|
||||
|
||||
.headline {
|
||||
font-weight: bold;
|
||||
margin-bottom: 0.7em;
|
||||
}
|
||||
|
||||
.parameter-name {
|
||||
line-height: 2em;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
.update-credentials {
|
||||
position: absolute;
|
||||
top: 7px;
|
||||
right: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
Reference in New Issue
Block a user