some more updates for group forms w/ burnettk

This commit is contained in:
jasquat 2022-11-03 15:55:50 -04:00
parent bba9ed27f1
commit 999134fc8f
7 changed files with 237 additions and 147 deletions

View File

@ -41,23 +41,35 @@ export default function ButtonWithConfirmation({
const confirmationDialog = () => {
return (
<Modal
show={showConfirmationPrompt}
onHide={handleConfirmationPromptCancel}
>
<Modal.Header closeButton>
<Modal.Title>{title}</Modal.Title>
</Modal.Header>
{modalBodyElement()}
<Modal.Footer>
<Button variant="secondary" onClick={handleConfirmationPromptCancel}>
Cancel
</Button>
<Button variant="primary" onClick={handleConfirmation}>
{confirmButtonLabel}
</Button>
</Modal.Footer>
</Modal>
open={showConfirmationPrompt}
danger
modalHeading={description}
modalLabel={title}
primaryButtonText={confirmButtonLabel}
secondaryButtonText="Cancel"
onSecondarySubmit={handleConfirmationPromptCancel}
onRequestSubmit={handleConfirmation}
/>
);
// return (
// <Modal
// show={showConfirmationPrompt}
// onHide={handleConfirmationPromptCancel}
// >
// <Modal.Header closeButton>
// <Modal.Title>{title}</Modal.Title>
// </Modal.Header>
// {modalBodyElement()}
// <Modal.Footer>
// <Button variant="secondary" onClick={handleConfirmationPromptCancel}>
// Cancel
// </Button>
// <Button variant="primary" onClick={handleConfirmation}>
// {confirmButtonLabel}
// </Button>
// </Modal.Footer>
// </Modal>
// );
};
return (

View File

@ -0,0 +1,178 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
// @ts-ignore
import { Button, ButtonSet, Form, Stack, TextInput } from '@carbon/react';
import { slugifyString } from '../helpers';
import HttpService from '../services/HttpService';
import { ProcessGroup } from '../interfaces';
import ButtonWithConfirmation from './ButtonWithConfirmation';
type OwnProps = {
mode: string;
processGroup: ProcessGroup;
setProcessGroup: (..._args: any[]) => any;
};
export default function ProcessGroupForm({
mode,
processGroup,
setProcessGroup,
}: OwnProps) {
const [identifierInvalid, setIdentifierInvalid] = useState<boolean>(false);
const [idHasBeenUpdatedByUser, setIdHasBeenUpdatedByUser] =
useState<boolean>(false);
const [displayNameInvalid, setDisplayNameInvalid] = useState<boolean>(false);
const navigate = useNavigate();
const navigateToProcessGroup = (_result: any) => {
if (processGroup) {
navigate(`/admin/process-groups/${processGroup.id}`);
}
};
const navigateToProcessGroups = (_result: any) => {
navigate(`/admin/process-groups`);
};
const hasValidIdentifier = (identifierToCheck: string) => {
return identifierToCheck.match(/^[a-z0-9][0-9a-z-]+[a-z0-9]$/);
};
const deleteProcessGroup = () => {
HttpService.makeCallToBackend({
path: `/process-groups/${processGroup.id}`,
successCallback: navigateToProcessGroups,
httpMethod: 'DELETE',
});
};
const handleFormSubmission = (event: any) => {
event.preventDefault();
let hasErrors = false;
if (!hasValidIdentifier(processGroup.id)) {
setIdentifierInvalid(true);
hasErrors = true;
}
if (processGroup.display_name === '') {
setDisplayNameInvalid(true);
hasErrors = true;
}
if (hasErrors) {
return;
}
let path = '/process-groups';
if (mode === 'edit') {
path = `/process-groups/${processGroup.id}`;
}
let httpMethod = 'POST';
if (mode === 'edit') {
httpMethod = 'PUT';
}
const postBody = {
display_name: processGroup.display_name,
description: processGroup.description,
};
if (mode === 'new') {
Object.assign(postBody, { id: processGroup.id });
}
HttpService.makeCallToBackend({
path,
successCallback: navigateToProcessGroup,
httpMethod,
postBody,
});
};
const updateProcessGroup = (newValues: any) => {
const processGroupToCopy = {
...processGroup,
};
Object.assign(processGroupToCopy, newValues);
setProcessGroup(processGroupToCopy);
};
const onDisplayNameChanged = (newDisplayName: any) => {
setDisplayNameInvalid(false);
const updateDict = { display_name: newDisplayName };
if (!idHasBeenUpdatedByUser) {
Object.assign(updateDict, { id: slugifyString(newDisplayName) });
}
updateProcessGroup(updateDict);
};
const formElements = () => {
const textInputs = [
<TextInput
id="process-group-display-name"
invalidText="Display Name is required."
invalid={displayNameInvalid}
labelText="Display Name*"
value={processGroup.display_name}
onChange={(event: any) => onDisplayNameChanged(event.target.value)}
onBlur={(event: any) => console.log('event', event)}
/>,
];
if (mode === 'new') {
textInputs.push(
<TextInput
id="process-group-identifier"
invalidText="Identifier is required and must be all lowercase characters and hyphens."
invalid={identifierInvalid}
labelText="Identifier*"
value={processGroup.id}
onChange={(event: any) => {
updateProcessGroup({ id: event.target.value });
// was invalid, and now valid
if (identifierInvalid && hasValidIdentifier(event.target.value)) {
setIdentifierInvalid(false);
}
setIdHasBeenUpdatedByUser(true);
}}
/>
);
}
textInputs.push(
<TextInput
id="process-group-description"
labelText="Description"
value={processGroup.description}
onChange={(event: any) =>
updateProcessGroup({ description: event.target.value })
}
/>
);
return textInputs;
};
const formButtons = () => {
const buttons = [
<Button kind="secondary" type="submit">
Submit
</Button>,
];
if (mode === 'edit') {
buttons.push(
<ButtonWithConfirmation
description={`Delete Process Group ${processGroup.id}?`}
onConfirmation={deleteProcessGroup}
buttonLabel="Delete"
confirmButtonLabel="Delete"
/>
);
}
return <ButtonSet>{buttons}</ButtonSet>;
};
return (
<Form onSubmit={handleFormSubmission}>
<Stack gap={5}>
{formElements()}
{formButtons()}
</Stack>
</Form>
);
}

View File

@ -9,12 +9,14 @@ type OwnProps = {
onChange: (..._args: any[]) => any;
processModels: ProcessModel[];
selectedItem?: ProcessModel | null;
titleText?: string;
};
export default function ProcessModelSearch({
processModels,
selectedItem,
onChange,
titleText = 'Process model',
}: OwnProps) {
const shouldFilterProcessModel = (options: any) => {
const processModel: ProcessModel = options.item;
@ -38,7 +40,7 @@ export default function ProcessModelSearch({
}}
shouldFilterItem={shouldFilterProcessModel}
placeholder="Choose a process model"
titleText="Process model"
titleText={titleText}
selectedItem={selectedItem}
/>
);

View File

@ -14,6 +14,7 @@ export interface RecentProcessModel {
export interface ProcessGroup {
id: string;
display_name: string;
description?: string | null;
}
export interface ProcessModel {

View File

@ -1,21 +1,18 @@
import { useState, useEffect } from 'react';
import { useParams, useNavigate } from 'react-router-dom';
import { useParams } from 'react-router-dom';
// @ts-ignore
import { Button, Stack } from '@carbon/react';
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
import HttpService from '../services/HttpService';
import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
import ProcessGroupForm from '../components/ProcessGroupForm';
import { ProcessGroup } from '../interfaces';
export default function ProcessGroupEdit() {
const [displayName, setDisplayName] = useState('');
const params = useParams();
const navigate = useNavigate();
const [processGroup, setProcessGroup] = useState(null);
const [processGroup, setProcessGroup] = useState<ProcessGroup | null>(null);
useEffect(() => {
const setProcessGroupsFromResult = (result: any) => {
setProcessGroup(result);
setDisplayName(result.display_name);
};
HttpService.makeCallToBackend({
@ -24,69 +21,16 @@ export default function ProcessGroupEdit() {
});
}, [params]);
const navigateToProcessGroup = (_result: any) => {
navigate(`/admin/process-groups/${(processGroup as any).id}`);
};
const navigateToProcessGroups = (_result: any) => {
navigate(`/admin/process-groups`);
};
const updateProcessGroup = (event: any) => {
event.preventDefault();
HttpService.makeCallToBackend({
path: `/process-groups/${(processGroup as any).id}`,
successCallback: navigateToProcessGroup,
httpMethod: 'PUT',
postBody: {
display_name: displayName,
id: (processGroup as any).id,
},
});
};
const deleteProcessGroup = () => {
HttpService.makeCallToBackend({
path: `/process-groups/${(processGroup as any).id}`,
successCallback: navigateToProcessGroups,
httpMethod: 'DELETE',
});
};
const onDisplayNameChanged = (newDisplayName: any) => {
setDisplayName(newDisplayName);
};
if (processGroup) {
return (
<>
<ProcessBreadcrumb processGroupId={(processGroup as any).id} />
<h2>Edit Process Group: {(processGroup as any).id}</h2>
<form onSubmit={updateProcessGroup}>
<label>Display Name:</label>
<input
name="display_name"
type="text"
value={displayName}
onChange={(e) => onDisplayNameChanged(e.target.value)}
/>
<br />
<br />
<Stack direction="horizontal" gap={3}>
<Button type="submit">Submit</Button>
<Button
variant="secondary"
href={`/admin/process-groups/${(processGroup as any).id}`}
>
Cancel
</Button>
<ButtonWithConfirmation
description={`Delete Process Group ${(processGroup as any).id}?`}
onConfirmation={deleteProcessGroup}
buttonLabel="Delete"
/>
</Stack>
</form>
<ProcessGroupForm
mode="edit"
processGroup={processGroup}
setProcessGroup={setProcessGroup}
/>
</>
);
}

View File

@ -1,15 +1,12 @@
import { useEffect, useState } from 'react';
import { Link, useNavigate, useSearchParams } from 'react-router-dom';
// @ts-ignore
import { Button, Form, Table } from '@carbon/react';
import { InputGroup } from 'react-bootstrap';
import { Typeahead } from 'react-bootstrap-typeahead';
import { Option } from 'react-bootstrap-typeahead/types/types';
import { Button, Table } from '@carbon/react';
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
import PaginationForTable from '../components/PaginationForTable';
import HttpService from '../services/HttpService';
import { getPageInfoFromSearchParams } from '../helpers';
import { CarbonComboBoxSelection, ProcessModel } from '../interfaces';
import { CarbonComboBoxSelection } from '../interfaces';
import ProcessModelSearch from '../components/ProcessModelSearch';
// Example process group json
@ -111,6 +108,7 @@ export default function ProcessGroupList() {
<ProcessModelSearch
onChange={processModelSearchOnChange}
processModels={processModelAvailableItems}
titleText="Process model search"
/>
);
};
@ -119,7 +117,9 @@ export default function ProcessGroupList() {
return (
<>
<ProcessBreadcrumb hotCrumbs={[['Process Groups']]} />
<Button href="/admin/process-groups/new">Add a process group</Button>
<Button kind="secondary" href="/admin/process-groups/new">
Add a process group
</Button>
<br />
<br />
{processModelSearchArea()}

View File

@ -1,71 +1,24 @@
import { useState } from 'react';
import { useNavigate } from 'react-router-dom';
import Button from 'react-bootstrap/Button';
import Form from 'react-bootstrap/Form';
import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
import { slugifyString } from '../helpers';
import HttpService from '../services/HttpService';
import ProcessGroupForm from '../components/ProcessGroupForm';
import { ProcessGroup } from '../interfaces';
export default function ProcessGroupNew() {
const [identifier, setIdentifier] = useState('');
const [idHasBeenUpdatedByUser, setIdHasBeenUpdatedByUser] = useState(false);
const [displayName, setDisplayName] = useState('');
const navigate = useNavigate();
const navigateToProcessGroup = (_result: any) => {
navigate(`/admin/process-groups/${identifier}`);
};
const addProcessGroup = (event: any) => {
event.preventDefault();
HttpService.makeCallToBackend({
path: `/process-groups`,
successCallback: navigateToProcessGroup,
httpMethod: 'POST',
postBody: {
id: identifier,
display_name: displayName,
},
});
};
const onDisplayNameChanged = (newDisplayName: any) => {
setDisplayName(newDisplayName);
if (!idHasBeenUpdatedByUser) {
setIdentifier(slugifyString(newDisplayName));
}
};
const [processGroup, setProcessGroup] = useState<ProcessGroup>({
id: '',
display_name: '',
description: '',
});
return (
<>
<ProcessBreadcrumb />
<h2>Add Process Group</h2>
<Form onSubmit={addProcessGroup}>
<Form.Group className="mb-3" controlId="display_name">
<Form.Label>Display Name:</Form.Label>
<Form.Control
type="text"
name="display_name"
value={displayName}
onChange={(e) => onDisplayNameChanged(e.target.value)}
/>
</Form.Group>
<Form.Group className="mb-3" controlId="identifier">
<Form.Label>ID:</Form.Label>
<Form.Control
type="text"
name="id"
value={identifier}
onChange={(e) => {
setIdentifier(e.target.value);
setIdHasBeenUpdatedByUser(true);
}}
/>
</Form.Group>
<Button variant="primary" type="submit">
Submit
</Button>
</Form>
<ProcessGroupForm
mode="new"
processGroup={processGroup}
setProcessGroup={setProcessGroup}
/>
</>
);
}