mirror of
https://github.com/sartography/spiff-arena.git
synced 2025-01-27 09:45:12 +00:00
some more updates for group forms w/ burnettk
This commit is contained in:
parent
f0cc086e09
commit
7fffa650b0
@ -153,7 +153,6 @@ paths:
|
||||
description: The number of groups to show per page. Defaults to page 10.
|
||||
schema:
|
||||
type: integer
|
||||
# process_groups_list
|
||||
get:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_groups_list
|
||||
summary: get list
|
||||
@ -168,7 +167,6 @@ paths:
|
||||
type: array
|
||||
items:
|
||||
$ref: "#/components/schemas/ProcessModelCategory"
|
||||
# process_group_add
|
||||
post:
|
||||
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_group_add
|
||||
summary: Add process group
|
||||
|
@ -1,5 +1,6 @@
|
||||
"""Process_group."""
|
||||
from __future__ import annotations
|
||||
import dataclasses
|
||||
|
||||
from dataclasses import dataclass
|
||||
from dataclasses import field
|
||||
@ -20,6 +21,7 @@ class ProcessGroup:
|
||||
|
||||
id: str # A unique string name, lower case, under scores (ie, 'my_group')
|
||||
display_name: str
|
||||
description: str | None = None
|
||||
display_order: int | None = 0
|
||||
admin: bool | None = False
|
||||
process_models: list[ProcessModelInfo] = field(
|
||||
@ -38,6 +40,11 @@ class ProcessGroup:
|
||||
return True
|
||||
return False
|
||||
|
||||
@property
|
||||
def serialized(self) -> dict:
|
||||
original_dict = dataclasses.asdict(self)
|
||||
return {x: original_dict[x] for x in original_dict if x not in ["sort_index"]}
|
||||
|
||||
|
||||
class ProcessGroupSchema(Schema):
|
||||
"""ProcessGroupSchema."""
|
||||
|
@ -43,7 +43,7 @@ from spiffworkflow_backend.models.message_triggerable_process_model import (
|
||||
MessageTriggerableProcessModel,
|
||||
)
|
||||
from spiffworkflow_backend.models.principal import PrincipalModel
|
||||
from spiffworkflow_backend.models.process_group import ProcessGroupSchema
|
||||
from spiffworkflow_backend.models.process_group import ProcessGroup, ProcessGroupSchema
|
||||
from spiffworkflow_backend.models.process_instance import ProcessInstanceApiSchema
|
||||
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
|
||||
from spiffworkflow_backend.models.process_instance import ProcessInstanceModelSchema
|
||||
@ -135,17 +135,13 @@ def permissions_check(body: Dict[str, Dict[str, list[str]]]) -> flask.wrappers.R
|
||||
|
||||
|
||||
def process_group_add(
|
||||
body: Dict[str, Union[str, bool, int]]
|
||||
body: dict
|
||||
) -> flask.wrappers.Response:
|
||||
"""Add_process_group."""
|
||||
process_model_service = ProcessModelService()
|
||||
process_group = ProcessGroupSchema().load(body)
|
||||
process_group = ProcessGroup(**body)
|
||||
process_model_service.add_process_group(process_group)
|
||||
return Response(
|
||||
json.dumps(ProcessGroupSchema().dump(process_group)),
|
||||
status=201,
|
||||
mimetype="application/json",
|
||||
)
|
||||
return make_response(jsonify(process_group), 201)
|
||||
|
||||
|
||||
def process_group_delete(process_group_id: str) -> flask.wrappers.Response:
|
||||
@ -155,12 +151,12 @@ def process_group_delete(process_group_id: str) -> flask.wrappers.Response:
|
||||
|
||||
|
||||
def process_group_update(
|
||||
process_group_id: str, body: Dict[str, Union[str, bool, int]]
|
||||
) -> Dict[str, Union[str, bool, int]]:
|
||||
process_group_id: str, body: dict
|
||||
) -> flask.wrappers.Response:
|
||||
"""Process Group Update."""
|
||||
process_group = ProcessGroupSchema().load(body)
|
||||
process_group = ProcessGroup(id=process_group_id, **body)
|
||||
ProcessModelService().update_process_group(process_group)
|
||||
return ProcessGroupSchema().dump(process_group) # type: ignore
|
||||
return make_response(jsonify(process_group), 200)
|
||||
|
||||
|
||||
def process_groups_list(page: int = 1, per_page: int = 100) -> flask.wrappers.Response:
|
||||
@ -173,6 +169,7 @@ def process_groups_list(page: int = 1, per_page: int = 100) -> flask.wrappers.Re
|
||||
remainder = len(process_groups) % per_page
|
||||
if remainder > 0:
|
||||
pages += 1
|
||||
|
||||
response_json = {
|
||||
"results": ProcessGroupSchema(many=True).dump(batch),
|
||||
"pagination": {
|
||||
@ -198,7 +195,7 @@ def process_group_show(
|
||||
status_code=400,
|
||||
)
|
||||
) from exception
|
||||
return ProcessGroupSchema().dump(process_group)
|
||||
return make_response(jsonify(process_group), 200)
|
||||
|
||||
|
||||
def process_model_add(
|
||||
|
@ -1,4 +1,5 @@
|
||||
"""Process_model_service."""
|
||||
import dataclasses
|
||||
import json
|
||||
import os
|
||||
import shutil
|
||||
@ -170,7 +171,7 @@ class ProcessModelService(FileSystemService):
|
||||
json_path = os.path.join(cat_path, self.CAT_JSON_FILE)
|
||||
with open(json_path, "w") as cat_json:
|
||||
json.dump(
|
||||
self.GROUP_SCHEMA.dump(process_group),
|
||||
process_group.serialized,
|
||||
cat_json,
|
||||
indent=4,
|
||||
sort_keys=True,
|
||||
|
@ -1,4 +1,5 @@
|
||||
"""Test Process Api Blueprint."""
|
||||
import dataclasses
|
||||
import io
|
||||
import json
|
||||
import time
|
||||
@ -8,6 +9,7 @@ import pytest
|
||||
from flask.app import Flask
|
||||
from flask.testing import FlaskClient
|
||||
from flask_bpmn.models.db import db
|
||||
from spiffworkflow_backend import MyJSONEncoder
|
||||
from tests.spiffworkflow_backend.helpers.base_test import BaseTest
|
||||
from tests.spiffworkflow_backend.helpers.test_data import load_test_spec
|
||||
|
||||
@ -17,7 +19,7 @@ from spiffworkflow_backend.exceptions.process_entity_not_found_error import (
|
||||
from spiffworkflow_backend.models.active_task import ActiveTaskModel
|
||||
from spiffworkflow_backend.models.group import GroupModel
|
||||
from spiffworkflow_backend.models.process_group import ProcessGroup
|
||||
from spiffworkflow_backend.models.process_group import ProcessGroupSchema
|
||||
# from spiffworkflow_backend.models.process_group import ProcessGroupSchema
|
||||
from spiffworkflow_backend.models.process_instance import ProcessInstanceModel
|
||||
from spiffworkflow_backend.models.process_instance import ProcessInstanceStatus
|
||||
from spiffworkflow_backend.models.process_instance_report import (
|
||||
@ -388,25 +390,30 @@ class TestProcessApi(BaseTest):
|
||||
display_name="Another Test Category",
|
||||
display_order=0,
|
||||
admin=False,
|
||||
description="Test Description"
|
||||
)
|
||||
response = client.post(
|
||||
"/v1.0/process-groups",
|
||||
headers=self.logged_in_headers(with_super_admin_user),
|
||||
content_type="application/json",
|
||||
data=json.dumps(ProcessGroupSchema().dump(process_group)),
|
||||
data=json.dumps(process_group.serialized),
|
||||
|
||||
)
|
||||
assert response.status_code == 201
|
||||
assert response.json
|
||||
|
||||
# Check what is returned
|
||||
result = ProcessGroupSchema().loads(response.get_data(as_text=True))
|
||||
result = ProcessGroup(**response.json)
|
||||
assert result is not None
|
||||
assert result.display_name == "Another Test Category"
|
||||
assert result.id == "test"
|
||||
assert result.description == "Test Description"
|
||||
|
||||
# Check what is persisted
|
||||
persisted = ProcessModelService().get_process_group("test")
|
||||
assert persisted.display_name == "Another Test Category"
|
||||
assert persisted.id == "test"
|
||||
assert persisted.description == "Test Description"
|
||||
|
||||
def test_process_group_delete(
|
||||
self,
|
||||
|
@ -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 (
|
||||
|
178
spiffworkflow-frontend/src/components/ProcessGroupForm.tsx
Normal file
178
spiffworkflow-frontend/src/components/ProcessGroupForm.tsx
Normal 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>
|
||||
);
|
||||
}
|
@ -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}
|
||||
/>
|
||||
);
|
||||
|
@ -14,6 +14,7 @@ export interface RecentProcessModel {
|
||||
export interface ProcessGroup {
|
||||
id: string;
|
||||
display_name: string;
|
||||
description?: string | null;
|
||||
}
|
||||
|
||||
export interface ProcessModel {
|
||||
|
@ -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}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -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()}
|
||||
|
@ -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}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user