Skip to content

Commit

Permalink
Merge pull request #1029 from yaacov/refactor-provider-secret-store
Browse files Browse the repository at this point in the history
🧼 Refactor provider credentials store
  • Loading branch information
yaacov authored Mar 26, 2024
2 parents 9f439a8 + a99391a commit 860849b
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 57 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import React, { ReactNode, useReducer, useState } from 'react';
import React, { useReducer, useState } from 'react';
import { AlertMessageForModals } from 'src/modules/Providers/modals';
import { isSecretDataChanged, ValidationMsg } from 'src/modules/Providers/utils';
import { ValidationMsg } from 'src/modules/Providers/utils';
import { useForkliftTranslation } from 'src/utils/i18n';

import { IoK8sApiCoreV1Secret } from '@kubev2v/types';
Expand All @@ -18,6 +18,7 @@ import EyeSlashIcon from '@patternfly/react-icons/dist/esm/icons/eye-slash-icon'
import Pencil from '@patternfly/react-icons/dist/esm/icons/pencil-alt-icon';

import { patchSecretData } from './edit';
import { baseCredentialsSectionReducerFactory, BaseCredentialsSectionState } from './state';

import './BaseCredentialsSection.style.css';

Expand All @@ -31,26 +32,6 @@ export interface EditComponentProps {
onChange: (newValue: IoK8sApiCoreV1Secret) => void;
}

/**
* Represents the state of the secret edit form.
*
* @typedef {Object} BaseCredentialsSecretState
* @property {boolean} reveal - Determines whether the secret's values are visible.
* @property {boolean} edit - Determines whether the secret is currently being edited.
* @property {IoK8sApiCoreV1Secret} newSecret - The new version of the secret being edited.
* @property {boolean} dataChanged - Determines whether the secret's data has changed.
* @property {boolean} dataIsValid - Determines whether the new secret's data is valid.
* @property {ReactNode} alertMessage - The message to display when a validation error occurs.
*/
export interface BaseCredentialsSecretState {
reveal: boolean;
edit: boolean;
newSecret: IoK8sApiCoreV1Secret;
dataChanged: boolean;
dataError: ValidationMsg;
alertMessage: ReactNode;
}

export type BaseCredentialsSectionProps = {
secret: IoK8sApiCoreV1Secret;
validator: (secret: IoK8sApiCoreV1Secret) => ValidationMsg;
Expand All @@ -75,7 +56,7 @@ export const BaseCredentialsSection: React.FC<BaseCredentialsSectionProps> = ({
name: secret.metadata.name,
});

const initialState: BaseCredentialsSecretState = {
const initialState: BaseCredentialsSectionState = {
reveal: false,
edit: false,
newSecret: secret,
Expand All @@ -84,37 +65,10 @@ export const BaseCredentialsSection: React.FC<BaseCredentialsSectionProps> = ({
alertMessage: null,
};

function reducer(
state: BaseCredentialsSecretState,
action: { type: string; payload?: IoK8sApiCoreV1Secret },
): BaseCredentialsSecretState {
switch (action.type) {
case 'TOGGLE_REVEAL':
return { ...state, reveal: !state.reveal };
case 'TOGGLE_EDIT':
return { ...state, edit: !state.edit };
case 'RESET_DATA_CHANGED': {
return { ...state, dataChanged: false };
}
case 'SET_NEW_SECRET': {
const dataChanged = isSecretDataChanged(secret, action.payload);
const validationError = validator(action.payload);

return {
...state,
dataChanged,
dataError: validationError,
newSecret: action.payload,
alertMessage: null,
};
}
case 'SET_ALERT_MESSAGE':
return { ...state, alertMessage: action.payload };
default:
return state;
}
}
const [state, dispatch] = useReducer(reducer, initialState);
const [state, dispatch] = useReducer(
baseCredentialsSectionReducerFactory(secret, validator),
initialState,
);

if (!secret?.data) {
return <span className="text-muted">{t('No credentials found.')}</span>;
Expand Down Expand Up @@ -153,12 +107,12 @@ export const BaseCredentialsSection: React.FC<BaseCredentialsSectionProps> = ({
setIsLoading(true);

try {
// Patch provider secret, set clean to `true`
// to remove old values from the secret
// Patch provider secret, set clean to `true` to remove old values from the secret
// if successful reset data change
await patchSecretData(state.newSecret, true);
resetDataChanged();

setIsLoading(false);
resetDataChanged();
toggleEdit();
} catch (err) {
dispatch({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// @index(['./*', /style/g], f => `export * from '${f.path}';`)
export * from './reducer';
// @endindex
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { ReactNode } from 'react';
import { isSecretDataChanged, ValidationMsg } from 'src/modules/Providers/utils';

import { IoK8sApiCoreV1Secret } from '@kubev2v/types';

/**
* Represents the state of the secret edit form.
*
* @typedef {Object} BaseCredentialsSectionState
* @property {boolean} reveal - Determines whether the secret's values are visible.
* @property {boolean} edit - Determines whether the secret is currently being edited.
* @property {IoK8sApiCoreV1Secret} newSecret - The new version of the secret being edited.
* @property {boolean} dataChanged - Determines whether the secret's data has changed.
* @property {boolean} dataIsValid - Determines whether the new secret's data is valid.
* @property {ReactNode} alertMessage - The message to display when a validation error occurs.
*/
export interface BaseCredentialsSectionState {
reveal: boolean;
edit: boolean;
newSecret: IoK8sApiCoreV1Secret;
dataChanged: boolean;
dataError: ValidationMsg;
alertMessage: ReactNode;
}

export type BaseCredentialsAction =
| { type: 'TOGGLE_REVEAL' }
| { type: 'TOGGLE_EDIT' }
| { type: 'RESET_DATA_CHANGED' }
| { type: 'SET_NEW_SECRET'; payload: IoK8sApiCoreV1Secret }
| { type: 'SET_ALERT_MESSAGE'; payload: ReactNode };

export function baseCredentialsSectionReducerFactory(secret, validator) {
return function baseCredentialsSectionReducer(
state: BaseCredentialsSectionState,
action: BaseCredentialsAction,
): BaseCredentialsSectionState {
switch (action.type) {
case 'TOGGLE_REVEAL':
return { ...state, reveal: !state.reveal };
case 'TOGGLE_EDIT':
return { ...state, edit: !state.edit };
case 'RESET_DATA_CHANGED': {
return { ...state, dataChanged: false };
}
case 'SET_NEW_SECRET': {
const dataChanged = isSecretDataChanged(secret, action.payload);
const validationError = validator(action.payload);

return {
...state,
dataChanged,
dataError: validationError,
newSecret: action.payload,
alertMessage: null,
};
}
case 'SET_ALERT_MESSAGE':
return { ...state, alertMessage: action.payload };
default:
return state;
}
};
}

0 comments on commit 860849b

Please sign in to comment.