mirror of
https://github.com/n8n-io/n8n.git
synced 2025-03-05 20:50:17 -08:00
fix(editor): Fix most ts errors in credential components (no-changelog) (#9576)
This commit is contained in:
parent
379e2da547
commit
0e10c84efd
|
@ -118,6 +118,9 @@ declare global {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** String that represents a timestamp in the ISO8601 format, i.e. YYYY-MM-DDTHH:MM:SS.sssZ */
|
||||||
|
export type Iso8601String = string;
|
||||||
|
|
||||||
export type EndpointStyle = {
|
export type EndpointStyle = {
|
||||||
width?: number;
|
width?: number;
|
||||||
height?: number;
|
height?: number;
|
||||||
|
@ -351,8 +354,8 @@ export interface IShareWorkflowsPayload {
|
||||||
|
|
||||||
export interface ICredentialsResponse extends ICredentialsEncrypted {
|
export interface ICredentialsResponse extends ICredentialsEncrypted {
|
||||||
id: string;
|
id: string;
|
||||||
createdAt: number | string;
|
createdAt: Iso8601String;
|
||||||
updatedAt: number | string;
|
updatedAt: Iso8601String;
|
||||||
sharedWithProjects?: ProjectSharingData[];
|
sharedWithProjects?: ProjectSharingData[];
|
||||||
homeProject?: ProjectSharingData;
|
homeProject?: ProjectSharingData;
|
||||||
currentUserHasAccess?: boolean;
|
currentUserHasAccess?: boolean;
|
||||||
|
@ -361,8 +364,8 @@ export interface ICredentialsResponse extends ICredentialsEncrypted {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICredentialsBase {
|
export interface ICredentialsBase {
|
||||||
createdAt: number | string;
|
createdAt: Iso8601String;
|
||||||
updatedAt: number | string;
|
updatedAt: Iso8601String;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ICredentialsDecryptedResponse extends ICredentialsBase, ICredentialsDecrypted {
|
export interface ICredentialsDecryptedResponse extends ICredentialsBase, ICredentialsDecrypted {
|
||||||
|
|
|
@ -70,7 +70,6 @@ export default defineComponent({
|
||||||
updatedAt: '',
|
updatedAt: '',
|
||||||
type: '',
|
type: '',
|
||||||
name: '',
|
name: '',
|
||||||
nodesAccess: [],
|
|
||||||
sharedWithProjects: [],
|
sharedWithProjects: [],
|
||||||
homeProject: {} as ProjectSharingData,
|
homeProject: {} as ProjectSharingData,
|
||||||
}),
|
}),
|
||||||
|
@ -118,7 +117,7 @@ export default defineComponent({
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
formattedCreatedAtDate(): string {
|
formattedCreatedAtDate(): string {
|
||||||
const currentYear = new Date().getFullYear();
|
const currentYear = new Date().getFullYear().toString();
|
||||||
|
|
||||||
return dateformat(
|
return dateformat(
|
||||||
this.data.createdAt,
|
this.data.createdAt,
|
||||||
|
@ -128,10 +127,9 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
async onClick(event: Event) {
|
async onClick(event: Event) {
|
||||||
if (
|
const cardActionsEl = this.$refs.cardActions as HTMLDivElement | undefined;
|
||||||
this.$refs.cardActions === event.target ||
|
const clickTarget = event.target as HTMLElement | null;
|
||||||
this.$refs.cardActions?.contains(event.target)
|
if (cardActionsEl === clickTarget || (clickTarget && cardActionsEl?.contains(clickTarget))) {
|
||||||
) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -115,8 +115,8 @@
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
|
import { defineComponent, type PropType } from 'vue';
|
||||||
|
|
||||||
import type { ICredentialsResponse, IUser } from '@/Interface';
|
import type { ICredentialsResponse, IUser } from '@/Interface';
|
||||||
|
|
||||||
|
@ -158,6 +158,7 @@ import { useNDVStore } from '@/stores/ndv.store';
|
||||||
import { useCredentialsStore } from '@/stores/credentials.store';
|
import { useCredentialsStore } from '@/stores/credentials.store';
|
||||||
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
import { useNodeTypesStore } from '@/stores/nodeTypes.store';
|
||||||
import type { ProjectSharingData } from '@/features/projects/projects.types';
|
import type { ProjectSharingData } from '@/features/projects/projects.types';
|
||||||
|
import { assert } from '@/utils/assert';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getNodeAuthOptions,
|
getNodeAuthOptions,
|
||||||
|
@ -190,9 +191,11 @@ export default defineComponent({
|
||||||
activeId: {
|
activeId: {
|
||||||
type: [String, Number],
|
type: [String, Number],
|
||||||
required: false,
|
required: false,
|
||||||
|
default: undefined,
|
||||||
},
|
},
|
||||||
mode: {
|
mode: {
|
||||||
type: String,
|
type: String as PropType<'new' | 'edit'>,
|
||||||
|
default: 'new',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
|
@ -380,13 +383,14 @@ export default defineComponent({
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const properties = this.credentialType.properties.filter((propertyData: INodeProperties) => {
|
const credentialType = this.credentialType;
|
||||||
|
const properties = credentialType.properties.filter((propertyData: INodeProperties) => {
|
||||||
if (!this.displayCredentialParameter(propertyData)) {
|
if (!this.displayCredentialParameter(propertyData)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
!this.credentialType!.__overwrittenProperties ||
|
!credentialType.__overwrittenProperties ||
|
||||||
!this.credentialType!.__overwrittenProperties.includes(propertyData.name)
|
!credentialType.__overwrittenProperties.includes(propertyData.name)
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -407,16 +411,17 @@ export default defineComponent({
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property.type === 'string' && !this.credentialData[property.name]) {
|
const credentialProperty = this.credentialData[property.name];
|
||||||
|
|
||||||
|
if (property.type === 'string' && !credentialProperty) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property.type === 'number') {
|
if (property.type === 'number') {
|
||||||
const isExpression =
|
const containsExpression =
|
||||||
typeof this.credentialData[property.name] === 'string' &&
|
typeof credentialProperty === 'string' && credentialProperty.startsWith('=');
|
||||||
this.credentialData[property.name].startsWith('=');
|
|
||||||
|
|
||||||
if (typeof this.credentialData[property.name] !== 'number' && !isExpression) {
|
if (typeof credentialProperty !== 'number' && !containsExpression) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -463,7 +468,7 @@ export default defineComponent({
|
||||||
credentialTypeName = this.activeNodeType.credentials[0].name;
|
credentialTypeName = this.activeNodeType.credentials[0].name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return credentialTypeName || '';
|
return credentialTypeName ?? '';
|
||||||
},
|
},
|
||||||
showSaveButton(): boolean {
|
showSaveButton(): boolean {
|
||||||
return (
|
return (
|
||||||
|
@ -757,7 +762,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
async retestCredential() {
|
async retestCredential() {
|
||||||
if (!this.isCredentialTestable) {
|
if (!this.isCredentialTestable || !this.credentialTypeName) {
|
||||||
this.authError = '';
|
this.authError = '';
|
||||||
this.testedSuccessfully = false;
|
this.testedSuccessfully = false;
|
||||||
|
|
||||||
|
@ -768,7 +773,7 @@ export default defineComponent({
|
||||||
const details: ICredentialsDecrypted = {
|
const details: ICredentialsDecrypted = {
|
||||||
id: this.credentialId,
|
id: this.credentialId,
|
||||||
name: this.credentialName,
|
name: this.credentialName,
|
||||||
type: this.credentialTypeName!,
|
type: this.credentialTypeName,
|
||||||
data: credentialData,
|
data: credentialData,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -801,20 +806,21 @@ export default defineComponent({
|
||||||
this.isSaving = true;
|
this.isSaving = true;
|
||||||
|
|
||||||
// Save only the none default data
|
// Save only the none default data
|
||||||
|
assert(this.credentialType);
|
||||||
const data = NodeHelpers.getNodeParameters(
|
const data = NodeHelpers.getNodeParameters(
|
||||||
this.credentialType!.properties,
|
this.credentialType.properties,
|
||||||
this.credentialData as INodeParameters,
|
this.credentialData as INodeParameters,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
assert(this.credentialTypeName);
|
||||||
const credentialDetails: ICredentialsDecrypted = {
|
const credentialDetails: ICredentialsDecrypted = {
|
||||||
id: this.credentialId,
|
id: this.credentialId,
|
||||||
name: this.credentialName,
|
name: this.credentialName,
|
||||||
type: this.credentialTypeName!,
|
type: this.credentialTypeName,
|
||||||
data: data as unknown as ICredentialDataDecryptedObject,
|
data: data as unknown as ICredentialDataDecryptedObject,
|
||||||
nodesAccess: [],
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (
|
if (
|
||||||
|
@ -825,7 +831,7 @@ export default defineComponent({
|
||||||
.sharedWithProjects as ProjectSharingData[];
|
.sharedWithProjects as ProjectSharingData[];
|
||||||
}
|
}
|
||||||
|
|
||||||
let credential;
|
let credential: ICredentialsResponse | null = null;
|
||||||
|
|
||||||
const isNewCredential = this.mode === 'new' && !this.credentialId;
|
const isNewCredential = this.mode === 'new' && !this.credentialId;
|
||||||
|
|
||||||
|
@ -954,7 +960,7 @@ export default defineComponent({
|
||||||
async updateCredential(
|
async updateCredential(
|
||||||
credentialDetails: ICredentialsDecrypted,
|
credentialDetails: ICredentialsDecrypted,
|
||||||
): Promise<ICredentialsResponse | null> {
|
): Promise<ICredentialsResponse | null> {
|
||||||
let credential;
|
let credential: ICredentialsResponse | null = null;
|
||||||
try {
|
try {
|
||||||
if (this.credentialPermissions.update) {
|
if (this.credentialPermissions.update) {
|
||||||
credential = await this.credentialsStore.updateCredential({
|
credential = await this.credentialsStore.updateCredential({
|
||||||
|
@ -974,6 +980,14 @@ export default defineComponent({
|
||||||
this.isSharedWithChanged = false;
|
this.isSharedWithChanged = false;
|
||||||
}
|
}
|
||||||
this.hasUnsavedChanges = false;
|
this.hasUnsavedChanges = false;
|
||||||
|
|
||||||
|
if (credential) {
|
||||||
|
await this.externalHooks.run('credential.saved', {
|
||||||
|
credential_type: credentialDetails.type,
|
||||||
|
credential_id: credential.id,
|
||||||
|
is_new: false,
|
||||||
|
});
|
||||||
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
this.showError(
|
this.showError(
|
||||||
error,
|
error,
|
||||||
|
@ -983,12 +997,6 @@ export default defineComponent({
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
await this.externalHooks.run('credential.saved', {
|
|
||||||
credential_type: credentialDetails.type,
|
|
||||||
credential_id: credential.id,
|
|
||||||
is_new: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
// Now that the credentials changed check if any nodes use credentials
|
// Now that the credentials changed check if any nodes use credentials
|
||||||
// which have now a different name
|
// which have now a different name
|
||||||
this.nodeHelpers.updateNodesCredentialsIssues();
|
this.nodeHelpers.updateNodesCredentialsIssues();
|
||||||
|
|
|
@ -105,8 +105,8 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
credential: {
|
credential: {
|
||||||
type: Object as PropType<ICredentialsResponse>,
|
type: Object as PropType<ICredentialsResponse | null>,
|
||||||
required: true,
|
default: null,
|
||||||
},
|
},
|
||||||
credentialId: {
|
credentialId: {
|
||||||
type: String,
|
type: String,
|
||||||
|
@ -162,7 +162,7 @@ export default defineComponent({
|
||||||
return this.credentialsStore.getCredentialOwnerNameById(`${this.credentialId}`);
|
return this.credentialsStore.getCredentialOwnerNameById(`${this.credentialId}`);
|
||||||
},
|
},
|
||||||
isCredentialSharedWithCurrentUser(): boolean {
|
isCredentialSharedWithCurrentUser(): boolean {
|
||||||
return (this.credentialData.sharedWithProjects || []).some((sharee: IUser) => {
|
return (this.credentialData.sharedWithProjects ?? []).some((sharee: IUser) => {
|
||||||
return sharee.id === this.usersStore.currentUser?.id;
|
return sharee.id === this.usersStore.currentUser?.id;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,7 +11,7 @@ describe('OauthButton', () => {
|
||||||
test.each([
|
test.each([
|
||||||
['GoogleAuthButton', true],
|
['GoogleAuthButton', true],
|
||||||
['n8n-button', false],
|
['n8n-button', false],
|
||||||
])('should emit click event only once when %s is clicked', async (name, isGoogleOAuthType) => {
|
])('should emit click event only once when %s is clicked', async (_, isGoogleOAuthType) => {
|
||||||
const { emitted, getByRole } = renderComponent({
|
const { emitted, getByRole } = renderComponent({
|
||||||
props: { isGoogleOAuthType },
|
props: { isGoogleOAuthType },
|
||||||
});
|
});
|
||||||
|
|
|
@ -6,13 +6,11 @@
|
||||||
:size="inputSize"
|
:size="inputSize"
|
||||||
filterable
|
filterable
|
||||||
:model-value="displayValue"
|
:model-value="displayValue"
|
||||||
:placeholder="
|
:placeholder="$locale.baseText('parameterInput.select')"
|
||||||
parameter.placeholder ? getPlaceholder() : $locale.baseText('parameterInput.select')
|
|
||||||
"
|
|
||||||
:title="displayTitle"
|
:title="displayTitle"
|
||||||
:disabled="isReadOnly"
|
:disabled="isReadOnly"
|
||||||
data-test-id="credential-select"
|
data-test-id="credential-select"
|
||||||
@update:model-value="(value) => $emit('update:modelValue', value)"
|
@update:model-value="(value: string) => $emit('update:modelValue', value)"
|
||||||
@keydown.stop
|
@keydown.stop
|
||||||
@focus="$emit('setFocus')"
|
@focus="$emit('setFocus')"
|
||||||
@blur="$emit('onBlur')"
|
@blur="$emit('onBlur')"
|
||||||
|
@ -28,11 +26,6 @@
|
||||||
<div class="option-headline">
|
<div class="option-headline">
|
||||||
{{ credType.displayName }}
|
{{ credType.displayName }}
|
||||||
</div>
|
</div>
|
||||||
<div
|
|
||||||
v-if="credType.description"
|
|
||||||
class="option-description"
|
|
||||||
v-html="credType.description"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</n8n-option>
|
</n8n-option>
|
||||||
</n8n-select>
|
</n8n-select>
|
||||||
|
@ -62,9 +55,6 @@ import ScopesNotice from '@/components/ScopesNotice.vue';
|
||||||
import NodeCredentials from '@/components/NodeCredentials.vue';
|
import NodeCredentials from '@/components/NodeCredentials.vue';
|
||||||
import { mapStores } from 'pinia';
|
import { mapStores } from 'pinia';
|
||||||
import { useCredentialsStore } from '@/stores/credentials.store';
|
import { useCredentialsStore } from '@/stores/credentials.store';
|
||||||
import type { N8nSelect } from 'n8n-design-system';
|
|
||||||
|
|
||||||
type N8nSelectRef = InstanceType<typeof N8nSelect>;
|
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'CredentialsSelect',
|
name: 'CredentialsSelect',
|
||||||
|
@ -81,6 +71,7 @@ export default defineComponent({
|
||||||
'isReadOnly',
|
'isReadOnly',
|
||||||
'displayTitle',
|
'displayTitle',
|
||||||
],
|
],
|
||||||
|
emits: ['update:modelValue', 'setFocus', 'onBlur', 'credentialSelected'],
|
||||||
computed: {
|
computed: {
|
||||||
...mapStores(useCredentialsStore),
|
...mapStores(useCredentialsStore),
|
||||||
allCredentialTypes(): ICredentialType[] {
|
allCredentialTypes(): ICredentialType[] {
|
||||||
|
@ -97,7 +88,7 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
focus() {
|
focus() {
|
||||||
const selectRef = this.$refs.innerSelect as N8nSelectRef | undefined;
|
const selectRef = this.$refs.innerSelect as HTMLElement | undefined;
|
||||||
if (selectRef) {
|
if (selectRef) {
|
||||||
selectRef.focus();
|
selectRef.focus();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue