added new notification component that allows links based on carbons w/ burnettk cullerton

This commit is contained in:
jasquat 2022-12-08 12:28:23 -05:00
parent 1ccdd7887b
commit 675c776a5a
8 changed files with 105 additions and 44 deletions

View File

@ -459,7 +459,7 @@ paths:
description: the name of the branch we want to merge into description: the name of the branch we want to merge into
schema: schema:
type: string type: string
put: post:
operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_publish operationId: spiffworkflow_backend.routes.process_api_blueprint.process_model_publish
summary: Merge changes from this model to another branch. summary: Merge changes from this model to another branch.
tags: tags:

View File

@ -96,8 +96,8 @@ class GitService:
os.system("git push") os.system("git push")
# build url for github page to open PR # build url for github page to open PR
output = os.popen("git remote -v").read() output = os.popen("git config --get remote.origin.url").read()
remote_url = output.strip().split("\n")[0].split("\t")[1].split(" ")[0].replace(".git", "") remote_url = output.strip().replace(".git", "")
pr_url = f"{remote_url}/compare/{publish_branch}?expand=1" pr_url = f"{remote_url}/compare/{publish_branch}?expand=1"
# try to clean up # try to clean up

View File

@ -2665,7 +2665,7 @@ class TestProcessApi(BaseTest):
assert "new_file.txt" in listing assert "new_file.txt" in listing
modified_process_model_id = process_model_identifier.replace("/", ":") modified_process_model_id = process_model_identifier.replace("/", ":")
# response = client.put( # response = client.post(
# f"/v1.0/process-models/{modified_process_model_id}/publish?branch_to_update=staging", # f"/v1.0/process-models/{modified_process_model_id}/publish?branch_to_update=staging",
# headers=self.logged_in_headers(with_super_admin_user), # headers=self.logged_in_headers(with_super_admin_user),
# ) # )

View File

@ -0,0 +1,48 @@
import React, { useState } from 'react';
// @ts-ignore
import { Close, CheckmarkFilled } from '@carbon/icons-react';
// @ts-ignore
import { Button } from '@carbon/react';
type OwnProps = {
title: string;
children: React.ReactNode;
onClose: (..._args: any[]) => any;
type?: string;
};
export function Notification({
title,
children,
onClose,
type = 'success',
}: OwnProps) {
let iconClassName = 'green-icon';
if (type === 'error') {
iconClassName = 'red-icon';
}
return (
<div
role="status"
className={`with-bottom-margin cds--inline-notification cds--inline-notification--low-contrast cds--inline-notification--${type}`}
>
<div className="cds--inline-notification__details">
<div className="cds--inline-notification__text-wrapper">
<CheckmarkFilled className={`${iconClassName} notification-icon`} />
<div className="cds--inline-notification__title">{title}</div>
<div className="cds--inline-notification__subtitle">{children}</div>
</div>
</div>
<Button
data-qa="close-publish-notification"
renderIcon={Close}
iconDescription="Close Notification"
className="cds--inline-notification__close-button"
hasIconOnly
size="sm"
kind=""
onClick={onClose}
/>
</div>
);
}

View File

@ -7,7 +7,7 @@ import {
} from 'react-router-dom'; } from 'react-router-dom';
// @ts-ignore // @ts-ignore
import { Filter, Close, AddAlt } from '@carbon/icons-react'; import { Filter, Close, AddAlt, CheckmarkFilled } from '@carbon/icons-react';
import { import {
Button, Button,
ButtonSet, ButtonSet,
@ -65,6 +65,7 @@ import ProcessModelSearch from './ProcessModelSearch';
import ProcessInstanceReportSearch from './ProcessInstanceReportSearch'; import ProcessInstanceReportSearch from './ProcessInstanceReportSearch';
import ProcessInstanceListSaveAsReport from './ProcessInstanceListSaveAsReport'; import ProcessInstanceListSaveAsReport from './ProcessInstanceListSaveAsReport';
import { FormatProcessModelDisplayName } from './MiniComponents'; import { FormatProcessModelDisplayName } from './MiniComponents';
import { Notification } from './Notification';
const REFRESH_INTERVAL = 5; const REFRESH_INTERVAL = 5;
const REFRESH_TIMEOUT = 600; const REFRESH_TIMEOUT = 600;
@ -372,18 +373,13 @@ export default function ProcessInstanceListTable({
titleOperation = 'Created'; titleOperation = 'Created';
} }
return ( return (
<> <Notification title={`Perspective: ${titleOperation}`} onClose={() => setProcessInstanceReportJustSaved(null)}>
<InlineNotification <span>{`'${
title={`Perspective ${titleOperation}:`}
subtitle={`'${
processInstanceReportSelection processInstanceReportSelection
? processInstanceReportSelection.identifier ? processInstanceReportSelection.identifier
: '' : ''
}'`} }'`}</span>
kind="success" </Notification>
/>
<br />
</>
); );
} }
return null; return null;

View File

@ -18,6 +18,7 @@ export const useUriListForPermissions = () => {
processModelCreatePath: `/v1.0/process-models/${params.process_group_id}`, processModelCreatePath: `/v1.0/process-models/${params.process_group_id}`,
processModelFileCreatePath: `/v1.0/process-models/${params.process_model_id}/files`, processModelFileCreatePath: `/v1.0/process-models/${params.process_model_id}/files`,
processModelFileShowPath: `/v1.0/process-models/${params.process_model_id}/files/${params.file_name}`, processModelFileShowPath: `/v1.0/process-models/${params.process_model_id}/files/${params.file_name}`,
processModelPublishPath: `/v1.0/process-models/${params.process_model_id}/publish`,
processModelShowPath: `/v1.0/process-models/${params.process_model_id}`, processModelShowPath: `/v1.0/process-models/${params.process_model_id}`,
secretListPath: `/v1.0/secrets`, secretListPath: `/v1.0/secrets`,
}; };

View File

@ -332,6 +332,14 @@ td.actions-cell {
fill: red; fill: red;
} }
svg.green-icon {
fill: #198038;
}
svg.notification-icon {
margin-right: 1rem;
}
.failure-string { .failure-string {
color: red; color: red;
} }
@ -358,7 +366,8 @@ td.actions-cell {
} }
/* lime green */
.tag-type-green:hover { .tag-type-green:hover {
background-color: #00FF00; background-color: #80ee90;
} }

View File

@ -49,6 +49,7 @@ import ProcessInstanceListTable from '../components/ProcessInstanceListTable';
import { usePermissionFetcher } from '../hooks/PermissionService'; import { usePermissionFetcher } from '../hooks/PermissionService';
import { useUriListForPermissions } from '../hooks/UriListForPermissions'; import { useUriListForPermissions } from '../hooks/UriListForPermissions';
import ProcessInstanceRun from '../components/ProcessInstanceRun'; import ProcessInstanceRun from '../components/ProcessInstanceRun';
import { Notification } from '../components/Notification';
export default function ProcessModelShow() { export default function ProcessModelShow() {
const params = useParams(); const params = useParams();
@ -62,11 +63,13 @@ export default function ProcessModelShow() {
const [showFileUploadModal, setShowFileUploadModal] = const [showFileUploadModal, setShowFileUploadModal] =
useState<boolean>(false); useState<boolean>(false);
const [processModelPublished, setProcessModelPublished] = useState<any>(null); const [processModelPublished, setProcessModelPublished] = useState<any>(null);
const [publishDisabled, setPublishDisabled] = useState<boolean>(false);
const navigate = useNavigate(); const navigate = useNavigate();
const { targetUris } = useUriListForPermissions(); const { targetUris } = useUriListForPermissions();
const permissionRequestData: PermissionsToCheck = { const permissionRequestData: PermissionsToCheck = {
[targetUris.processModelShowPath]: ['PUT', 'DELETE'], [targetUris.processModelShowPath]: ['PUT', 'DELETE'],
[targetUris.processModelPublishPath]: ['POST'],
[targetUris.processInstanceListPath]: ['GET'], [targetUris.processInstanceListPath]: ['GET'],
[targetUris.processInstanceCreatePath]: ['POST'], [targetUris.processInstanceCreatePath]: ['POST'],
[targetUris.processModelFileCreatePath]: ['POST', 'PUT', 'GET', 'DELETE'], [targetUris.processModelFileCreatePath]: ['POST', 'PUT', 'GET', 'DELETE'],
@ -93,19 +96,17 @@ export default function ProcessModelShow() {
const processInstanceRunResultTag = () => { const processInstanceRunResultTag = () => {
if (processInstance) { if (processInstance) {
return ( return (
<div className="alert alert-success with-top-margin" role="alert"> <Notification
<p> title="Process Instance Kicked Off:"
Process Instance {processInstance.id} kicked off ( onClose={() => setProcessInstance(null)}
<Link >
to={`/admin/process-instances/${modifiedProcessModelId}/${processInstance.id}`} <Link
data-qa="process-instance-show-link" to={`/admin/process-instances/${modifiedProcessModelId}/${processInstance.id}`}
> data-qa="process-instance-show-link"
view >
</Link> view
). </Link>
</p> </Notification>
<br />
</div>
); );
} }
return null; return null;
@ -206,15 +207,17 @@ export default function ProcessModelShow() {
}; };
const postPublish = (value: any) => { const postPublish = (value: any) => {
setPublishDisabled(false);
setProcessModelPublished(value); setProcessModelPublished(value);
}; };
const publishProcessModel = () => { const publishProcessModel = () => {
setPublishDisabled(true);
setProcessModelPublished(null); setProcessModelPublished(null);
HttpService.makeCallToBackend({ HttpService.makeCallToBackend({
path: `/process-models/${modifiedProcessModelId}/publish`, path: `/process-models/${modifiedProcessModelId}/publish`,
successCallback: postPublish, successCallback: postPublish,
httpMethod: 'PUT', httpMethod: 'POST',
}); });
}; };
@ -529,16 +532,14 @@ export default function ProcessModelShow() {
if (processModelPublished) { if (processModelPublished) {
const prUrl: string = processModelPublished.pr_url; const prUrl: string = processModelPublished.pr_url;
return ( return (
<> <Notification
<InlineNotification title="Model Published:"
title="Model Published:" onClose={() => setProcessModelPublished(false)}
subtitle={`You can view the changes and create a Pull Request at ${prUrl}`} >
kind="success" <a href={prUrl} target="_void()">
type="banner" view the changes and create a Pull Request
links={prUrl} </a>
/> </Notification>
<br />
</>
); );
} }
return null; return null;
@ -548,7 +549,6 @@ export default function ProcessModelShow() {
return ( return (
<> <>
{fileUploadModal()} {fileUploadModal()}
{processModelPublishMessage()}
<ProcessBreadcrumb <ProcessBreadcrumb
hotCrumbs={[ hotCrumbs={[
['Process Groups', '/admin'], ['Process Groups', '/admin'],
@ -558,6 +558,8 @@ export default function ProcessModelShow() {
}, },
]} ]}
/> />
{processModelPublishMessage()}
{processInstanceRunResultTag()}
<Stack orientation="horizontal" gap={1}> <Stack orientation="horizontal" gap={1}>
<h1 className="with-icons"> <h1 className="with-icons">
Process Model: {processModel.display_name} Process Model: {processModel.display_name}
@ -603,11 +605,16 @@ export default function ProcessModelShow() {
<br /> <br />
</> </>
</Can> </Can>
<div> <Can
<Button onClick={publishProcessModel}>Publish Changes</Button> I="POST"
</div> a={targetUris.processModelPublishPath}
ability={ability}
>
<Button disabled={publishDisabled} onClick={publishProcessModel}>
Publish Changes
</Button>
</Can>
</Stack> </Stack>
{processInstanceRunResultTag()}
{processModelFilesSection()} {processModelFilesSection()}
<Can I="GET" a={targetUris.processInstanceListPath} ability={ability}> <Can I="GET" a={targetUris.processInstanceListPath} ability={ability}>
{processInstanceListTableButton()} {processInstanceListTableButton()}