diff --git a/spiffworkflow-frontend/src/components/ActiveUsers.tsx b/spiffworkflow-frontend/src/components/ActiveUsers.tsx new file mode 100644 index 00000000..012f9f67 --- /dev/null +++ b/spiffworkflow-frontend/src/components/ActiveUsers.tsx @@ -0,0 +1,52 @@ +import { useEffect, useState } from 'react'; + +import HttpService from '../services/HttpService'; +import { + encodeBase64, + refreshAtInterval, + REFRESH_TIMEOUT_SECONDS, +} from '../helpers'; +import { User } from '../interfaces'; + +export default function ActiveUsers() { + // Handles getting and displaying active users. + const [activeUsers, setActiveUsers] = useState([]); + + const lastVisitedIdentifier = encodeBase64(window.location.pathname); + useEffect(() => { + const updateActiveUsers = () => { + HttpService.makeCallToBackend({ + path: `/active-users/updates/${lastVisitedIdentifier}`, + successCallback: setActiveUsers, + }); + }; + + const unregisterUser = () => { + HttpService.makeCallToBackend({ + path: `/active-users/unregister/${lastVisitedIdentifier}`, + successCallback: setActiveUsers, + }); + }; + updateActiveUsers(); + + return refreshAtInterval( + 15, + REFRESH_TIMEOUT_SECONDS, + updateActiveUsers, + unregisterUser + ); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); // it is critical to only run this once. + + const au = activeUsers.map((activeUser: User) => { + return ( +
+ {activeUser.username.charAt(0).toUpperCase()} +
+ ); + }); + return
{au}
; +} diff --git a/spiffworkflow-frontend/src/components/ReactDiagramEditor.tsx b/spiffworkflow-frontend/src/components/ReactDiagramEditor.tsx index 1855f955..a95c43b7 100644 --- a/spiffworkflow-frontend/src/components/ReactDiagramEditor.tsx +++ b/spiffworkflow-frontend/src/components/ReactDiagramEditor.tsx @@ -674,7 +674,14 @@ export default function ReactDiagramEditor({ )} {getReferencesButton()} - {activeUserElement || null} + {/* only show other users if the current user can save the current diagram */} + + {activeUserElement || null} + ); } diff --git a/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx b/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx index 1d436396..0ba15f14 100644 --- a/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx +++ b/spiffworkflow-frontend/src/routes/ProcessModelEditDiagram.tsx @@ -29,24 +29,18 @@ import HttpService from '../services/HttpService'; import ReactDiagramEditor from '../components/ReactDiagramEditor'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; import useAPIError from '../hooks/UseApiError'; -import { - makeid, - modifyProcessIdentifierForPathParam, - encodeBase64, - refreshAtInterval, - REFRESH_TIMEOUT_SECONDS, -} from '../helpers'; +import { makeid, modifyProcessIdentifierForPathParam } from '../helpers'; import { CarbonComboBoxProcessSelection, ProcessFile, ProcessModel, ProcessModelCaller, ProcessReference, - User, } from '../interfaces'; import ProcessSearch from '../components/ProcessSearch'; import { Notification } from '../components/Notification'; import { usePrompt } from '../hooks/UsePrompt'; +import ActiveUsers from '../components/ActiveUsers'; export default function ProcessModelEditDiagram() { const [showFileNameEditor, setShowFileNameEditor] = useState(false); @@ -73,7 +67,6 @@ export default function ProcessModelEditDiagram() { useState(false); const [processModelFileInvalidText, setProcessModelFileInvalidText] = useState(''); - const [activeUsers, setActiveUsers] = useState([]); const handleShowMarkdownEditor = () => setShowMarkdownEditor(true); @@ -132,14 +125,7 @@ export default function ProcessModelEditDiagram() { usePrompt('Changes you made may not be saved.', diagramHasChanges); - const lastVisitedIdentifier = encodeBase64(window.location.pathname); useEffect(() => { - const updateActiveUsers = () => { - HttpService.makeCallToBackend({ - path: `/active-users/updates/${lastVisitedIdentifier}`, - successCallback: setActiveUsers, - }); - }; // Grab all available process models in case we need to search for them. // Taken from the Process Group List const processResults = (result: any) => { @@ -154,21 +140,6 @@ export default function ProcessModelEditDiagram() { path: `/processes`, successCallback: processResults, }); - - const unregisterUser = () => { - HttpService.makeCallToBackend({ - path: `/active-users/unregister/${lastVisitedIdentifier}`, - successCallback: setActiveUsers, - }); - }; - updateActiveUsers(); - - return refreshAtInterval( - 15, - REFRESH_TIMEOUT_SECONDS, - updateActiveUsers, - unregisterUser - ); // eslint-disable-next-line react-hooks/exhaustive-deps }, []); // it is critical to only run this once. @@ -959,20 +930,6 @@ export default function ProcessModelEditDiagram() { return searchParams.get('file_type') === 'dmn' || fileName.endsWith('.dmn'); }; - const activeUserElement = () => { - const au = activeUsers.map((activeUser: User) => { - return ( -
- {activeUser.username.charAt(0).toUpperCase()} -
- ); - }); - return
{au}
; - }; - const appropriateEditor = () => { if (isDmn()) { return ( @@ -1017,7 +974,7 @@ export default function ProcessModelEditDiagram() { onSearchProcessModels={onSearchProcessModels} onElementsChanged={onElementsChanged} callers={callers} - activeUserElement={activeUserElement()} + activeUserElement={} /> ); }; diff --git a/spiffworkflow-frontend/src/routes/ReactFormEditor.tsx b/spiffworkflow-frontend/src/routes/ReactFormEditor.tsx index 26b1ef70..e4e72290 100644 --- a/spiffworkflow-frontend/src/routes/ReactFormEditor.tsx +++ b/spiffworkflow-frontend/src/routes/ReactFormEditor.tsx @@ -4,7 +4,7 @@ import { useEffect, useState } from 'react'; import Editor from '@monaco-editor/react'; import { useNavigate, useParams, useSearchParams } from 'react-router-dom'; // @ts-ignore -import { Button, Modal } from '@carbon/react'; +import { Button, ButtonSet, Modal } from '@carbon/react'; import { Can } from '@casl/react'; import ProcessBreadcrumb from '../components/ProcessBreadcrumb'; import HttpService from '../services/HttpService'; @@ -15,6 +15,7 @@ import { Notification } from '../components/Notification'; import useAPIError from '../hooks/UseApiError'; import { usePermissionFetcher } from '../hooks/PermissionService'; import { useUriListForPermissions } from '../hooks/UriListForPermissions'; +import ActiveUsers from '../components/ActiveUsers'; // NOTE: This is mostly the same as ProcessModelEditDiagram and if we go this route could // possibly be merged into it. I'm leaving as a separate file now in case it does // end up diverging greatly @@ -231,59 +232,80 @@ export default function ReactFormEditor() { {newFileNameBox()} {saveFileMessage()} - - - - - {params.file_name ? ( - - ) : null} - - - {hasFormBuilder ? ( - ) : null} - - - {hasDiagram ? ( - - ) : null} - + + + {params.file_name ? ( + + ) : null} + + + {hasFormBuilder ? ( + + ) : null} + + + {hasDiagram ? ( + + ) : null} + + + + +