process model show page lists files as accordion with action icons w/ burnettk
This commit is contained in:
parent
97396fc7ae
commit
1ed2b96773
|
@ -4,12 +4,12 @@ import { Button, Modal } from '@carbon/react';
|
||||||
|
|
||||||
type OwnProps = {
|
type OwnProps = {
|
||||||
description?: string;
|
description?: string;
|
||||||
buttonLabel: string;
|
buttonLabel?: string;
|
||||||
onConfirmation: (..._args: any[]) => any;
|
onConfirmation: (..._args: any[]) => any;
|
||||||
title?: string;
|
title?: string;
|
||||||
confirmButtonLabel?: string;
|
confirmButtonLabel?: string;
|
||||||
kind?: string;
|
kind?: string;
|
||||||
renderIcon?: boolean | null;
|
renderIcon?: boolean;
|
||||||
iconDescription?: string | null;
|
iconDescription?: string | null;
|
||||||
hasIconOnly?: boolean;
|
hasIconOnly?: boolean;
|
||||||
};
|
};
|
||||||
|
@ -21,7 +21,7 @@ export default function ButtonWithConfirmation({
|
||||||
title = 'Are you sure?',
|
title = 'Are you sure?',
|
||||||
confirmButtonLabel = 'OK',
|
confirmButtonLabel = 'OK',
|
||||||
kind = 'danger',
|
kind = 'danger',
|
||||||
renderIcon = null,
|
renderIcon = false,
|
||||||
iconDescription = null,
|
iconDescription = null,
|
||||||
hasIconOnly = false,
|
hasIconOnly = false,
|
||||||
}: OwnProps) {
|
}: OwnProps) {
|
||||||
|
|
|
@ -32,6 +32,7 @@ export interface ProcessFile {
|
||||||
references: ProcessFileReference[];
|
references: ProcessFileReference[];
|
||||||
size: number;
|
size: number;
|
||||||
type: string;
|
type: string;
|
||||||
|
file_contents?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ProcessModel {
|
export interface ProcessModel {
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
import { useContext, useEffect, useState } from 'react';
|
import { useContext, useEffect, useState } from 'react';
|
||||||
import { Link, useParams } from 'react-router-dom';
|
import { Link, useNavigate, useParams } from 'react-router-dom';
|
||||||
// @ts-ignore
|
import {
|
||||||
import { Add, Upload } from '@carbon/icons-react';
|
Add,
|
||||||
|
Upload,
|
||||||
|
Download,
|
||||||
|
TrashCan,
|
||||||
|
Favorite,
|
||||||
|
Edit,
|
||||||
|
// @ts-ignore
|
||||||
|
} from '@carbon/icons-react';
|
||||||
import {
|
import {
|
||||||
Accordion,
|
Accordion,
|
||||||
AccordionItem,
|
AccordionItem,
|
||||||
|
@ -23,11 +30,14 @@ import ProcessBreadcrumb from '../components/ProcessBreadcrumb';
|
||||||
import HttpService from '../services/HttpService';
|
import HttpService from '../services/HttpService';
|
||||||
import ErrorContext from '../contexts/ErrorContext';
|
import ErrorContext from '../contexts/ErrorContext';
|
||||||
import { ProcessFile, ProcessModel, RecentProcessModel } from '../interfaces';
|
import { ProcessFile, ProcessModel, RecentProcessModel } from '../interfaces';
|
||||||
|
import ButtonWithConfirmation from '../components/ButtonWithConfirmation';
|
||||||
|
|
||||||
interface ProcessModelFileCarbonDropdownItem {
|
interface ProcessModelFileCarbonDropdownItem {
|
||||||
label: string;
|
label: string;
|
||||||
action: string;
|
action: string;
|
||||||
processModelFile: ProcessFile;
|
processModelFile: ProcessFile;
|
||||||
|
needsConfirmation: boolean;
|
||||||
|
icon: any;
|
||||||
}
|
}
|
||||||
|
|
||||||
const storeRecentProcessModelInLocalStorage = (
|
const storeRecentProcessModelInLocalStorage = (
|
||||||
|
@ -94,6 +104,7 @@ export default function ProcessModelShow() {
|
||||||
const [filesToUpload, setFilesToUpload] = useState<any>(null);
|
const [filesToUpload, setFilesToUpload] = useState<any>(null);
|
||||||
const [showFileUploadModal, setShowFileUploadModal] =
|
const [showFileUploadModal, setShowFileUploadModal] =
|
||||||
useState<boolean>(false);
|
useState<boolean>(false);
|
||||||
|
const navigate = useNavigate();
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const processResult = (result: ProcessModel) => {
|
const processResult = (result: ProcessModel) => {
|
||||||
|
@ -163,14 +174,14 @@ export default function ProcessModelShow() {
|
||||||
const onUploadedCallback = () => {
|
const onUploadedCallback = () => {
|
||||||
setReloadModel(true);
|
setReloadModel(true);
|
||||||
};
|
};
|
||||||
|
const reloadModelOhYeah = (_httpResult: any) => {
|
||||||
|
setReloadModel(!reloadModel);
|
||||||
|
};
|
||||||
|
|
||||||
// Remove this code from
|
// Remove this code from
|
||||||
const onDeleteFile = (fileName: string) => {
|
const onDeleteFile = (fileName: string) => {
|
||||||
const url = `/process-models/${params.process_group_id}/${params.process_model_id}/files/${fileName}`;
|
const url = `/process-models/${params.process_group_id}/${params.process_model_id}/files/${fileName}`;
|
||||||
const httpMethod = 'DELETE';
|
const httpMethod = 'DELETE';
|
||||||
const reloadModelOhYeah = (_httpResult: any) => {
|
|
||||||
setReloadModel(!reloadModel);
|
|
||||||
};
|
|
||||||
HttpService.makeCallToBackend({
|
HttpService.makeCallToBackend({
|
||||||
path: url,
|
path: url,
|
||||||
successCallback: reloadModelOhYeah,
|
successCallback: reloadModelOhYeah,
|
||||||
|
@ -185,99 +196,155 @@ export default function ProcessModelShow() {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onSetPrimaryFile = (fileName: string) => {
|
||||||
|
const url = `/process-models/${params.process_group_id}/${params.process_model_id}`;
|
||||||
|
const httpMethod = 'PUT';
|
||||||
|
|
||||||
|
const processModelToPass = {
|
||||||
|
primary_file_name: fileName,
|
||||||
|
};
|
||||||
|
HttpService.makeCallToBackend({
|
||||||
|
path: url,
|
||||||
|
successCallback: onUploadedCallback,
|
||||||
|
httpMethod,
|
||||||
|
postBody: processModelToPass,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
const handleProcessModelFileResult = (processModelFile: ProcessFile) => {
|
||||||
|
if (
|
||||||
|
!('file_contents' in processModelFile) ||
|
||||||
|
processModelFile.file_contents === undefined
|
||||||
|
) {
|
||||||
|
setErrorMessage({
|
||||||
|
message: `Could not file file contents for file: ${processModelFile.name}`,
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let contentType = 'application/xml';
|
||||||
|
if (processModelFile.type === 'json') {
|
||||||
|
contentType = 'application/json';
|
||||||
|
}
|
||||||
|
const element = document.createElement('a');
|
||||||
|
const file = new Blob([processModelFile.file_contents], {
|
||||||
|
type: contentType,
|
||||||
|
});
|
||||||
|
const downloadFileName = processModelFile.name;
|
||||||
|
element.href = URL.createObjectURL(file);
|
||||||
|
element.download = downloadFileName;
|
||||||
|
document.body.appendChild(element);
|
||||||
|
element.click();
|
||||||
|
};
|
||||||
|
|
||||||
|
const downloadFile = (fileName: string) => {
|
||||||
|
setErrorMessage(null);
|
||||||
|
const processModelPath = `process-models/${params.process_group_id}/${params.process_model_id}`;
|
||||||
|
HttpService.makeCallToBackend({
|
||||||
|
path: `/${processModelPath}/files/${fileName}`,
|
||||||
|
successCallback: handleProcessModelFileResult,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const navigateToFileEdit = (processModelFile: ProcessFile) => {
|
||||||
|
if (processModel) {
|
||||||
|
if (processModelFile.name.match(/\.(dmn|bpmn)$/)) {
|
||||||
|
navigate(
|
||||||
|
`/admin/process-models/${processModel.process_group_id}/${processModel.id}/files/${processModelFile.name}`
|
||||||
|
);
|
||||||
|
} else if (processModelFile.name.match(/\.(json|md)$/)) {
|
||||||
|
navigate(
|
||||||
|
`/admin/process-models/${processModel.process_group_id}/${processModel.id}/form/${processModelFile.name}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderButtonElements = (
|
||||||
|
processModelFile: ProcessFile,
|
||||||
|
isPrimaryBpmnFile: boolean
|
||||||
|
) => {
|
||||||
|
const elements = [];
|
||||||
|
elements.push(
|
||||||
|
<Button
|
||||||
|
kind="ghost"
|
||||||
|
renderIcon={Edit}
|
||||||
|
iconDescription="Edit File"
|
||||||
|
hasIconOnly
|
||||||
|
size="lg"
|
||||||
|
onClick={() => navigateToFileEdit(processModelFile)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
elements.push(
|
||||||
|
<Button
|
||||||
|
kind="ghost"
|
||||||
|
renderIcon={Download}
|
||||||
|
iconDescription="Download File"
|
||||||
|
hasIconOnly
|
||||||
|
size="lg"
|
||||||
|
onClick={() => downloadFile(processModelFile.name)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
elements.push(
|
||||||
|
<ButtonWithConfirmation
|
||||||
|
kind="ghost"
|
||||||
|
renderIcon={TrashCan}
|
||||||
|
iconDescription="Delete File"
|
||||||
|
hasIconOnly
|
||||||
|
description={`Delete file: ${processModelFile.name}`}
|
||||||
|
onConfirmation={() => {
|
||||||
|
onDeleteFile(processModelFile.name);
|
||||||
|
}}
|
||||||
|
confirmButtonLabel="Delete"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
if (processModelFile.name.match(/\.bpmn$/) && !isPrimaryBpmnFile) {
|
||||||
|
elements.push(
|
||||||
|
<Button
|
||||||
|
kind="ghost"
|
||||||
|
renderIcon={Favorite}
|
||||||
|
iconDescription="Set As Primary File"
|
||||||
|
hasIconOnly
|
||||||
|
size="lg"
|
||||||
|
onClick={() => onSetPrimaryFile(processModelFile.name)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return elements;
|
||||||
|
};
|
||||||
|
|
||||||
const processModelFileList = () => {
|
const processModelFileList = () => {
|
||||||
if (!processModel) {
|
if (!processModel) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
let constructedTag;
|
let constructedTag;
|
||||||
const tags = processModel.files.map(
|
const tags = processModel.files.map((processModelFile: ProcessFile) => {
|
||||||
(processModelFile: any, index: number) => {
|
const isPrimaryBpmnFile =
|
||||||
const isPrimaryBpmnFile =
|
processModelFile.name === processModel.primary_file_name;
|
||||||
processModelFile.name === processModel.primary_file_name;
|
|
||||||
const items: ProcessModelFileCarbonDropdownItem[] = [
|
|
||||||
{
|
|
||||||
label: 'Delete',
|
|
||||||
action: 'delete',
|
|
||||||
processModelFile,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
if (processModelFile.name.match(/\.bpmn$/) && !isPrimaryBpmnFile) {
|
|
||||||
items.push({
|
|
||||||
label: 'Mark as Primary',
|
|
||||||
action: 'mark_as_primary',
|
|
||||||
processModelFile,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
let actionDropDirection = 'bottom';
|
let actionsTableCell = null;
|
||||||
if (index + 1 === processModel.files.length) {
|
if (processModelFile.name.match(/\.(dmn|bpmn|json|md)$/)) {
|
||||||
actionDropDirection = 'bottom';
|
actionsTableCell = (
|
||||||
}
|
|
||||||
|
|
||||||
// The dropdown will get covered up if it extends passed the table container.
|
|
||||||
// Using bottom direction at least gives a scrollbar so use that and hopefully
|
|
||||||
// carbon will give access to z-index at some point.
|
|
||||||
// https://github.com/carbon-design-system/carbon-addons-iot-react/issues/1487
|
|
||||||
const actionsTableCell = (
|
|
||||||
<TableCell key={`${processModelFile.name}-cell`}>
|
<TableCell key={`${processModelFile.name}-cell`}>
|
||||||
<Dropdown
|
{renderButtonElements(processModelFile, isPrimaryBpmnFile)}
|
||||||
id="default"
|
|
||||||
direction={actionDropDirection}
|
|
||||||
label="Select an action"
|
|
||||||
onChange={(e: any) => {
|
|
||||||
onProcessModelFileAction(e);
|
|
||||||
}}
|
|
||||||
items={items}
|
|
||||||
itemToString={(item: ProcessModelFileCarbonDropdownItem) =>
|
|
||||||
item ? item.label : ''
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
</TableCell>
|
</TableCell>
|
||||||
);
|
);
|
||||||
|
|
||||||
if (processModelFile.name.match(/\.(dmn|bpmn)$/)) {
|
|
||||||
let primarySuffix = '';
|
|
||||||
if (isPrimaryBpmnFile) {
|
|
||||||
primarySuffix = '- Primary File';
|
|
||||||
}
|
|
||||||
constructedTag = (
|
|
||||||
<TableRow key={processModelFile.name}>
|
|
||||||
<TableCell key={`${processModelFile.name}-cell`}>
|
|
||||||
<Link
|
|
||||||
to={`/admin/process-models/${processModel.process_group_id}/${processModel.id}/files/${processModelFile.name}`}
|
|
||||||
>
|
|
||||||
{processModelFile.name}
|
|
||||||
</Link>
|
|
||||||
{primarySuffix}
|
|
||||||
</TableCell>
|
|
||||||
{actionsTableCell}
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
} else if (processModelFile.name.match(/\.(json|md)$/)) {
|
|
||||||
constructedTag = (
|
|
||||||
<TableRow key={processModelFile.name}>
|
|
||||||
<TableCell key={`${processModelFile.name}-cell`}>
|
|
||||||
<Link
|
|
||||||
to={`/admin/process-models/${processModel.process_group_id}/${processModel.id}/form/${processModelFile.name}`}
|
|
||||||
>
|
|
||||||
{processModelFile.name}
|
|
||||||
</Link>
|
|
||||||
</TableCell>
|
|
||||||
{actionsTableCell}
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
constructedTag = (
|
|
||||||
<TableRow key={processModelFile.name}>
|
|
||||||
<TableCell key={`${processModelFile.name}-cell`}>
|
|
||||||
{processModelFile.name}
|
|
||||||
</TableCell>
|
|
||||||
</TableRow>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return constructedTag;
|
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
let primarySuffix = '';
|
||||||
|
if (isPrimaryBpmnFile) {
|
||||||
|
primarySuffix = '- Primary File';
|
||||||
|
}
|
||||||
|
constructedTag = (
|
||||||
|
<TableRow key={processModelFile.name}>
|
||||||
|
<TableCell key={`${processModelFile.name}-cell`}>
|
||||||
|
{processModelFile.name}
|
||||||
|
{primarySuffix}
|
||||||
|
</TableCell>
|
||||||
|
{actionsTableCell}
|
||||||
|
</TableRow>
|
||||||
|
);
|
||||||
|
return constructedTag;
|
||||||
|
});
|
||||||
|
|
||||||
// return <ul>{tags}</ul>;
|
// return <ul>{tags}</ul>;
|
||||||
const headers = ['Name', 'Actions'];
|
const headers = ['Name', 'Actions'];
|
||||||
|
|
Loading…
Reference in New Issue