Merge commit 'a087961fab0d73cc54f9cae658e9eb50ab060f96'

This commit is contained in:
Jon Herron 2022-10-13 20:45:09 -04:00
commit 3803b835c2
8 changed files with 133 additions and 25 deletions

View File

@ -43,6 +43,7 @@
"react-bootstrap-typeahead": "^6.0.0",
"react-datepicker": "^4.8.0",
"react-dom": "^18.2.0",
"react-icons": "^4.4.0",
"react-jsonschema-form": "^1.8.1",
"react-markdown": "^8.0.3",
"react-router-dom": "^6.3.0",
@ -22404,6 +22405,14 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
},
"node_modules/react-icons": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz",
"integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg==",
"peerDependencies": {
"react": "*"
}
},
"node_modules/react-is": {
"version": "16.9.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz",
@ -44975,7 +44984,7 @@
"@csstools/postcss-text-decoration-shorthand": "^1.0.0",
"@csstools/postcss-trigonometric-functions": "^1.0.2",
"@csstools/postcss-unset-value": "^1.0.2",
"autoprefixer": "10.4.8",
"autoprefixer": "10.4.5",
"browserslist": "^4.21.3",
"css-blank-pseudo": "^3.0.3",
"css-has-pseudo": "^3.0.4",
@ -45013,7 +45022,8 @@
},
"dependencies": {
"autoprefixer": {
"version": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.5.tgz",
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.5.tgz",
"integrity": "sha512-Fvd8yCoA7lNX/OUllvS+aS1I7WRBclGXsepbvT8ZaPgrH24rgXpZzF0/6Hh3ZEkwg+0AES/Osd196VZmYoEFtw==",
"requires": {
"browserslist": "^4.20.2",
@ -45721,6 +45731,12 @@
"resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz",
"integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA=="
},
"react-icons": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/react-icons/-/react-icons-4.4.0.tgz",
"integrity": "sha512-fSbvHeVYo/B5/L4VhB7sBA1i2tS8MkT0Hb9t2H1AVPkwGfVHLJCqyr2Py9dKMxsyM63Eng1GkdZfbWj+Fmv8Rg==",
"requires": {}
},
"react-is": {
"version": "16.9.0",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.9.0.tgz",

View File

@ -38,6 +38,7 @@
"react-bootstrap-typeahead": "^6.0.0",
"react-datepicker": "^4.8.0",
"react-dom": "^18.2.0",
"react-icons": "^4.4.0",
"react-jsonschema-form": "^1.8.1",
"react-markdown": "^8.0.3",
"react-router-dom": "^6.3.0",

View File

@ -1,7 +1,8 @@
export interface Secret {
id: number;
key: string;
value: string;
username: string;
creator_user_id: string;
}
export interface RecentProcessModel {

View File

@ -1,6 +1,7 @@
import { useEffect, useState } from 'react';
import { Link, useSearchParams } from 'react-router-dom';
import { Button, Table } from 'react-bootstrap';
import { MdDelete } from 'react-icons/md';
import PaginationForTable from '../components/PaginationForTable';
import HttpService from '../services/HttpService';
import { getPageInfoFromSearchParams } from '../helpers';
@ -23,17 +24,36 @@ export default function SecretList() {
});
}, [searchParams]);
const reloadSecrets = (_result: any) => {
window.location.reload();
};
const handleDeleteSecret = (key: any) => {
HttpService.makeCallToBackend({
path: `/secrets/${key}`,
successCallback: reloadSecrets,
httpMethod: 'DELETE',
});
};
const buildTable = () => {
const rows = secrets.map((row) => {
return (
<tr key={(row as any).key}>
<td>
<Link to={`/admin/secrets/${(row as any).key}`}>
{(row as any).id}
</Link>
</td>
<td>
<Link to={`/admin/secrets/${(row as any).key}`}>
{(row as any).key}
</Link>
</td>
<td>{(row as any).value}</td>
<td>{(row as any).username}</td>
<td>
<MdDelete onClick={() => handleDeleteSecret((row as any).key)} />
</td>
</tr>
);
});
@ -41,9 +61,10 @@ export default function SecretList() {
<Table striped bordered>
<thead>
<tr>
<th>ID</th>
<th>Secret Key</th>
<th>Secret Value</th>
<th>Creator</th>
<th>Delete</th>
</tr>
</thead>
<tbody>{rows}</tbody>
@ -72,12 +93,11 @@ export default function SecretList() {
if (pagination) {
return (
<>
<Button href="/admin/secrets/new">Add a secret</Button>
<br />
<br />
<div>
<h2>Secrets</h2>
{SecretsDisplayArea()}
</>
<Button href="/admin/secrets/new">Add a secret</Button>
</div>
);
}
return null;

View File

@ -1,5 +1,6 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import { Stack } from 'react-bootstrap';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import HttpService from '../services/HttpService';
@ -13,6 +14,18 @@ export default function SecretNew() {
navigate(`/admin/secrets/${key}`);
};
const navigateToSecrets = () => {
navigate(`/admin/secrets`);
};
const changeSpacesToDash = (someString: string) => {
// change spaces to `-`
let s1 = someString.replace(' ', '-');
// remove any trailing `-`
s1 = s1.replace(/-$/, '');
return s1;
};
const addSecret = (event: any) => {
event.preventDefault();
HttpService.makeCallToBackend({
@ -26,16 +39,22 @@ export default function SecretNew() {
});
};
const warningStyle = {
color: 'red',
};
return (
<main style={{ padding: '1rem 0' }}>
<h2>Add Secret</h2>
<Form onSubmit={addSecret}>
<Form.Group className="mb-3" controlId="formDisplayName">
<Form.Label>Key:</Form.Label>
<Form.Label>
Key: <span style={warningStyle}>No Spaces</span>
</Form.Label>
<Form.Control
type="text"
value={key}
onChange={(e) => setKey(e.target.value)}
onChange={(e) => setKey(changeSpacesToDash(e.target.value))}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="formIdentifier">
@ -48,9 +67,14 @@ export default function SecretNew() {
}}
/>
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
<Stack direction="horizontal" gap={3}>
<Button variant="primary" type="submit">
Submit
</Button>
<Button variant="danger" type="button" onClick={navigateToSecrets}>
Cancel
</Button>
</Stack>
</Form>
</main>
);

View File

@ -1,6 +1,6 @@
import { useEffect, useState } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { Stack, Table } from 'react-bootstrap';
import { Stack, Table, Button } from 'react-bootstrap';
import HttpService from '../services/HttpService';
import { Secret } from '../interfaces';
import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
@ -10,10 +10,7 @@ export default function SecretShow() {
const params = useParams();
const [secret, setSecret] = useState<Secret | null>(null);
const navigateToSecrets = (_result: any) => {
navigate(`/admin/secrets`);
};
const [secretValue, setSecretValue] = useState(secret?.value);
useEffect(() => {
HttpService.makeCallToBackend({
@ -22,6 +19,37 @@ export default function SecretShow() {
});
}, [params]);
const handleSecretValueChange = (event: any) => {
if (secret) {
setSecretValue(event.target.value);
}
};
// const reloadSecret = (_result: any) => {
// window.location.reload();
// };
const updateSecretValue = () => {
if (secret && secretValue) {
secret.value = secretValue;
HttpService.makeCallToBackend({
path: `/secrets/${secret.key}`,
successCallback: () => {
setSecret(secret);
},
httpMethod: 'PUT',
postBody: {
value: secretValue,
creator_user_id: secret.creator_user_id,
},
});
}
};
const navigateToSecrets = (_result: any) => {
navigate(`/admin/secrets`);
};
const deleteSecret = () => {
if (secret === null) {
return;
@ -34,17 +62,18 @@ export default function SecretShow() {
};
if (secret) {
const secretToUse = secret as any;
return (
<>
<Stack direction="horizontal" gap={3}>
<h2>Secret Key: {secretToUse.key}</h2>
<h2>Secret Key: {secret.key}</h2>
<ButtonWithConfirmation
description="Delete Secret?"
onConfirmation={deleteSecret}
buttonLabel="Delete"
/>
<Button variant="warning" onClick={updateSecretValue}>
Update Value
</Button>
</Stack>
<div>
<Table striped bordered>
@ -57,7 +86,15 @@ export default function SecretShow() {
<tbody>
<tr>
<td>{params.key}</td>
<td>{secretToUse.value}</td>
<td>
<input
id="secret_value"
name="secret_value"
type="text"
value={secretValue || secret.value}
onChange={handleSecretValueChange}
/>
</td>
</tr>
</tbody>
</Table>

View File

@ -17,7 +17,6 @@ export default function TaskShow() {
const setErrorMessage = (useContext as any)(ErrorContext)[1];
useEffect(() => {
setErrorMessage('');
HttpService.makeCallToBackend({
path: `/tasks/${params.process_instance_id}/${params.task_id}`,
successCallback: setTask,

View File

@ -67,11 +67,15 @@ backendCallProps) => {
});
let isSuccessful = true;
let is403 = false;
fetch(`${BACKEND_BASE_URL}${path}`, httpArgs)
.then((response) => {
if (response.status === 401) {
UserService.doLogin();
throw new UnauthenticatedError('You must be authenticated to do this.');
} else if (response.status === 403) {
is403 = true;
isSuccessful = false;
} else if (!response.ok) {
isSuccessful = false;
}
@ -80,6 +84,10 @@ backendCallProps) => {
.then((result: any) => {
if (isSuccessful) {
successCallback(result);
} else if (is403) {
// Hopefully we can make this service a hook and use the error message context directly
// eslint-disable-next-line no-alert
alert(result.message);
} else {
let message = 'A server error occurred.';
if (result.message) {
@ -89,6 +97,8 @@ backendCallProps) => {
failureCallback(message);
} else {
console.error(message);
// eslint-disable-next-line no-alert
alert(message);
}
}
})