diff --git a/spiffworkflow-frontend/src/components/ButtonWithConfirmation.tsx b/spiffworkflow-frontend/src/components/ButtonWithConfirmation.tsx index 075787d5..88386919 100644 --- a/spiffworkflow-frontend/src/components/ButtonWithConfirmation.tsx +++ b/spiffworkflow-frontend/src/components/ButtonWithConfirmation.tsx @@ -4,12 +4,12 @@ import { Button, Modal } from '@carbon/react'; type OwnProps = { description?: string; - buttonLabel: string; + buttonLabel?: string; onConfirmation: (..._args: any[]) => any; title?: string; confirmButtonLabel?: string; kind?: string; - renderIcon?: boolean | null; + renderIcon?: boolean; iconDescription?: string | null; hasIconOnly?: boolean; }; @@ -21,7 +21,7 @@ export default function ButtonWithConfirmation({ title = 'Are you sure?', confirmButtonLabel = 'OK', kind = 'danger', - renderIcon = null, + renderIcon = false, iconDescription = null, hasIconOnly = false, }: OwnProps) { diff --git a/spiffworkflow-frontend/src/interfaces.ts b/spiffworkflow-frontend/src/interfaces.ts index ccf636e7..342785ec 100644 --- a/spiffworkflow-frontend/src/interfaces.ts +++ b/spiffworkflow-frontend/src/interfaces.ts @@ -32,6 +32,7 @@ export interface ProcessFile { references: ProcessFileReference[]; size: number; type: string; + file_contents?: string; } export interface ProcessModel { diff --git a/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx b/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx index af64a862..15db9518 100644 --- a/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessModelShow.tsx @@ -1,7 +1,14 @@ import { useContext, useEffect, useState } from 'react'; -import { Link, useParams } from 'react-router-dom'; -// @ts-ignore -import { Add, Upload } from '@carbon/icons-react'; +import { Link, useNavigate, useParams } from 'react-router-dom'; +import { + Add, + Upload, + Download, + TrashCan, + Favorite, + Edit, + // @ts-ignore +} from '@carbon/icons-react'; import { Accordion, AccordionItem, @@ -23,11 +30,14 @@ import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; import HttpService from '../services/HttpService'; import ErrorContext from '../contexts/ErrorContext'; import { ProcessFile, ProcessModel, RecentProcessModel } from '../interfaces'; +import ButtonWithConfirmation from '../components/ButtonWithConfirmation'; interface ProcessModelFileCarbonDropdownItem { label: string; action: string; processModelFile: ProcessFile; + needsConfirmation: boolean; + icon: any; } const storeRecentProcessModelInLocalStorage = ( @@ -94,6 +104,7 @@ export default function ProcessModelShow() { const [filesToUpload, setFilesToUpload] = useState(null); const [showFileUploadModal, setShowFileUploadModal] = useState(false); + const navigate = useNavigate(); useEffect(() => { const processResult = (result: ProcessModel) => { @@ -163,14 +174,14 @@ export default function ProcessModelShow() { const onUploadedCallback = () => { setReloadModel(true); }; + const reloadModelOhYeah = (_httpResult: any) => { + setReloadModel(!reloadModel); + }; // Remove this code from const onDeleteFile = (fileName: string) => { const url = `/process-models/${params.process_group_id}/${params.process_model_id}/files/${fileName}`; const httpMethod = 'DELETE'; - const reloadModelOhYeah = (_httpResult: any) => { - setReloadModel(!reloadModel); - }; HttpService.makeCallToBackend({ path: url, 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( +