Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { Provider } from "react-redux";
import { createStore } from "../../test-utils";

export default {
title: "SealedSecretDialog",
title: "APPLICATION/SealedSecretDialog",
component: SealedSecretDialog,
};

Expand Down
115 changes: 78 additions & 37 deletions pkg/app/web/src/components/sealed-secret-dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,31 +1,33 @@
import {
Button,
Checkbox,
Dialog,
DialogActions,
DialogContent,
DialogTitle,
FormControlLabel,
IconButton,
makeStyles,
TextField,
Typography,
} from "@material-ui/core";
import CopyIcon from "@material-ui/icons/FileCopyOutlined";
import React, { FC, useRef, useState } from "react";
import React, { FC, memo, useCallback, useRef } from "react";
import { useDispatch, useSelector } from "react-redux";
import { AppState } from "../modules";
import { Application, selectById } from "../modules/applications";
import {
generateSealedSecret,
SealedSecret,
clearSealedSecret,
} from "../modules/sealed-secret";
import copy from "copy-to-clipboard";
import { addToast } from "../modules/toasts";
import { useFormik } from "formik";
import * as Yup from "yup";
import { AppDispatch } from "../store";
import { UI_TEXT_CANCEL, UI_TEXT_CLOSE } from "../constants/ui-text";

const useStyles = makeStyles((theme) => ({
description: {
marginBottom: theme.spacing(2),
},
targetApp: {
color: theme.palette.text.primary,
fontWeight: theme.typography.fontWeightMedium,
Expand All @@ -42,35 +44,56 @@ interface Props {
}

const DIALOG_TITLE = "Encrypting secret data for application";
const BASE64_CHECKBOX_LABEL =
"Use base64 encoding before encrypting the secret";

const validationSchema = Yup.object({
secretData: Yup.string().required(),
base64: Yup.bool(),
});

export const SealedSecretDialog: FC<Props> = ({
export const SealedSecretDialog: FC<Props> = memo(function SealedSecretDialog({
open,
applicationId,
onClose,
}) => {
}) {
const classes = useStyles();
const dispatch = useDispatch();
const [data, setData] = useState("");
const dispatch = useDispatch<AppDispatch>();
const secretRef = useRef<HTMLDivElement>(null);

const [application, sealedSecret] = useSelector<
const [application, isLoading, sealedSecret] = useSelector<
AppState,
[Application | undefined, SealedSecret]
[Application | undefined, boolean, string | null]
>((state) => [
applicationId ? selectById(state.applications, applicationId) : undefined,
state.sealedSecret,
state.sealedSecret.isLoading,
state.sealedSecret.data,
]);

const handleGenerate = (e: React.FormEvent<HTMLFormElement>): void => {
e.preventDefault();
if (application) {
dispatch(generateSealedSecret({ data, pipedId: application.pipedId, base64Encoding: false }));
}
};
const formik = useFormik({
initialValues: {
secretData: "",
base64: false,
},
validationSchema,
validateOnMount: true,
async onSubmit(values) {
if (!application) {
return;
}
await dispatch(
generateSealedSecret({
data: values.secretData,
pipedId: application.pipedId,
base64Encoding: values.base64,
})
);
},
});

const handleOnEnter = (): void => {
setData("");
};
const handleOnEnter = useCallback(() => {
formik.resetForm();
}, [formik]);

const handleOnExited = (): void => {
// Clear state after closed dialog
Expand All @@ -79,12 +102,12 @@ export const SealedSecretDialog: FC<Props> = ({
}, 200);
};

const handleOnClickCopy = (): void => {
if (sealedSecret.data) {
copy(sealedSecret.data);
const handleOnClickCopy = useCallback(() => {
if (sealedSecret) {
copy(sealedSecret);
dispatch(addToast({ message: "Secret copied to clipboard" }));
}
};
}, [dispatch, sealedSecret]);

if (!application) {
return null;
Expand All @@ -97,17 +120,19 @@ export const SealedSecretDialog: FC<Props> = ({
onExit={handleOnExited}
onClose={onClose}
>
{sealedSecret.data ? (
{sealedSecret ? (
<>
<DialogTitle>{DIALOG_TITLE}</DialogTitle>
<DialogContent>
<Typography variant="caption">Encrypted secret data</Typography>
<Typography variant="caption" color="textSecondary">
Encrypted secret data
</Typography>
<Typography
variant="body2"
className={classes.encryptedSecret}
ref={secretRef}
>
{sealedSecret.data}
{sealedSecret}
<IconButton
size="small"
style={{ marginLeft: 8 }}
Expand All @@ -119,19 +144,23 @@ export const SealedSecretDialog: FC<Props> = ({
</Typography>
</DialogContent>
<DialogActions>
<Button onClick={onClose}>Close</Button>
<Button onClick={onClose}>{UI_TEXT_CLOSE}</Button>
</DialogActions>
</>
) : (
<form onSubmit={handleGenerate}>
<form onSubmit={formik.handleSubmit}>
<DialogTitle>{DIALOG_TITLE}</DialogTitle>
<DialogContent>
<Typography variant="caption">Application</Typography>
<Typography variant="caption" color="textSecondary">
Application
</Typography>
<Typography variant="body1" className={classes.targetApp}>
{application.name}
</Typography>
<TextField
value={data}
id="secretData"
name="secretData"
value={formik.values.secretData}
variant="outlined"
margin="dense"
label="Secret Data"
Expand All @@ -140,17 +169,29 @@ export const SealedSecretDialog: FC<Props> = ({
rows={4}
required
autoFocus
onChange={(e) => setData(e.currentTarget.value)}
onChange={formik.handleChange}
/>
<FormControlLabel
control={
<Checkbox
color="primary"
checked={formik.values.base64}
onChange={formik.handleChange}
name="base64"
/>
}
disabled={formik.isSubmitting}
label={BASE64_CHECKBOX_LABEL}
/>
</DialogContent>
<DialogActions>
<Button onClick={onClose} disabled={sealedSecret.isLoading}>
Cancel
<Button onClick={onClose} disabled={isLoading}>
{UI_TEXT_CANCEL}
</Button>
<Button
color="primary"
type="submit"
disabled={sealedSecret.isLoading}
disabled={isLoading || formik.isValid === false}
>
Encrypt
</Button>
Expand All @@ -159,4 +200,4 @@ export const SealedSecretDialog: FC<Props> = ({
)}
</Dialog>
);
};
});
1 change: 1 addition & 0 deletions pkg/app/web/src/constants/ui-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export const UI_TEXT_CANCEL = "Cancel";
export const UI_TEXT_ADD = "Add";
export const UI_TEXT_EDIT = "Edit";
export const UI_TEXT_REFRESH = "REFRESH";
export const UI_TEXT_CLOSE = "Close";