mirror of
https://github.com/sartography/spiff-arena.git
synced 2025-01-12 18:44:14 +00:00
Feature/pi short link (#503)
* moved adminroutes to homepage to get rid of /admin from urls * removed admin prefix from urls * moved top level base routes to their own routes file w/ burnettk * added ability to get and use a short link to the process instance show page w/ burnettk * give the person some feedback * move about page to baseroutes so it acts like the other pages * use the normal notificaiton component for the copied link notification * added 404 page and backend is down page w/ burnettk --------- Co-authored-by: jasquat <jasquat@users.noreply.github.com> Co-authored-by: burnettk <burnettk@users.noreply.github.com>
This commit is contained in:
parent
00158df03d
commit
ff83b8c801
@ -14,7 +14,6 @@ export default function App() {
|
||||
}
|
||||
|
||||
const ability = defineAbility(() => {});
|
||||
|
||||
return (
|
||||
<div className="cds--white">
|
||||
{/* @ts-ignore */}
|
||||
|
@ -4,10 +4,6 @@ import React, { useEffect, useState } from 'react';
|
||||
import { ErrorBoundary } from 'react-error-boundary';
|
||||
import NavigationBar from './components/NavigationBar';
|
||||
|
||||
import HomePageRoutes from './routes/HomePageRoutes';
|
||||
import About from './routes/About';
|
||||
import AdminRoutes from './routes/AdminRoutes';
|
||||
|
||||
import ScrollToTop from './components/ScrollToTop';
|
||||
import EditorRoutes from './routes/EditorRoutes';
|
||||
import Extension from './routes/Extension';
|
||||
@ -20,8 +16,11 @@ import {
|
||||
} from './extension_ui_schema_interfaces';
|
||||
import HttpService from './services/HttpService';
|
||||
import { ErrorBoundaryFallback } from './ErrorBoundaryFallack';
|
||||
import BaseRoutes from './routes/BaseRoutes';
|
||||
import BackendIsDown from './routes/BackendIsDown';
|
||||
|
||||
export default function ContainerForExtensions() {
|
||||
const [backendIsUp, setBackendIsUp] = useState<boolean | null>(null);
|
||||
const [extensionUxElements, setExtensionNavigationItems] = useState<
|
||||
UiSchemaUxElement[] | null
|
||||
>(null);
|
||||
@ -40,10 +39,6 @@ export default function ContainerForExtensions() {
|
||||
|
||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
useEffect(() => {
|
||||
if (!permissionsLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
const processExtensionResult = (processModels: ProcessModel[]) => {
|
||||
const eni: UiSchemaUxElement[] = processModels
|
||||
.map((processModel: ProcessModel) => {
|
||||
@ -72,13 +67,57 @@ export default function ContainerForExtensions() {
|
||||
}
|
||||
};
|
||||
|
||||
if (ability.can('GET', targetUris.extensionListPath)) {
|
||||
HttpService.makeCallToBackend({
|
||||
path: targetUris.extensionListPath,
|
||||
successCallback: processExtensionResult,
|
||||
});
|
||||
const getExtensions = () => {
|
||||
if (!permissionsLoaded) {
|
||||
return;
|
||||
}
|
||||
setBackendIsUp(true);
|
||||
if (ability.can('GET', targetUris.extensionListPath)) {
|
||||
HttpService.makeCallToBackend({
|
||||
path: targetUris.extensionListPath,
|
||||
successCallback: processExtensionResult,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
HttpService.makeCallToBackend({
|
||||
path: targetUris.statusPath,
|
||||
successCallback: getExtensions,
|
||||
failureCallback: () => setBackendIsUp(false),
|
||||
});
|
||||
}, [
|
||||
targetUris.extensionListPath,
|
||||
targetUris.statusPath,
|
||||
permissionsLoaded,
|
||||
ability,
|
||||
]);
|
||||
|
||||
const routeComponents = () => {
|
||||
return (
|
||||
<Routes>
|
||||
<Route
|
||||
path="/*"
|
||||
element={<BaseRoutes extensionUxElements={extensionUxElements} />}
|
||||
/>
|
||||
<Route path="/editor/*" element={<EditorRoutes />} />
|
||||
<Route path="/extensions/:page_identifier" element={<Extension />} />
|
||||
</Routes>
|
||||
);
|
||||
};
|
||||
|
||||
const backendIsDownPage = () => {
|
||||
return <BackendIsDown />;
|
||||
};
|
||||
|
||||
const innerComponents = () => {
|
||||
if (backendIsUp === null) {
|
||||
return null;
|
||||
}
|
||||
}, [targetUris.extensionListPath, permissionsLoaded, ability]);
|
||||
if (backendIsUp) {
|
||||
return routeComponents();
|
||||
}
|
||||
return backendIsDownPage();
|
||||
};
|
||||
|
||||
return (
|
||||
<>
|
||||
@ -86,22 +125,7 @@ export default function ContainerForExtensions() {
|
||||
<Content className={contentClassName}>
|
||||
<ScrollToTop />
|
||||
<ErrorBoundary FallbackComponent={ErrorBoundaryFallback}>
|
||||
<Routes>
|
||||
<Route path="/*" element={<HomePageRoutes />} />
|
||||
<Route path="/about" element={<About />} />
|
||||
<Route path="/tasks/*" element={<HomePageRoutes />} />
|
||||
<Route
|
||||
path="/admin/*"
|
||||
element={
|
||||
<AdminRoutes extensionUxElements={extensionUxElements} />
|
||||
}
|
||||
/>
|
||||
<Route path="/editor/*" element={<EditorRoutes />} />
|
||||
<Route
|
||||
path="/extensions/:page_identifier"
|
||||
element={<Extension />}
|
||||
/>
|
||||
</Routes>
|
||||
{innerComponents()}
|
||||
</ErrorBoundary>
|
||||
</Content>
|
||||
</>
|
||||
|
@ -1,24 +1,7 @@
|
||||
import { Button, Content } from '@carbon/react';
|
||||
import { Routes, Route } from 'react-router-dom';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { ErrorBoundary, useErrorBoundary } from 'react-error-boundary';
|
||||
import NavigationBar from './components/NavigationBar';
|
||||
import { Button } from '@carbon/react';
|
||||
import React from 'react';
|
||||
import { useErrorBoundary } from 'react-error-boundary';
|
||||
|
||||
import HomePageRoutes from './routes/HomePageRoutes';
|
||||
import About from './routes/About';
|
||||
import AdminRoutes from './routes/AdminRoutes';
|
||||
|
||||
import ScrollToTop from './components/ScrollToTop';
|
||||
import EditorRoutes from './routes/EditorRoutes';
|
||||
import Extension from './routes/Extension';
|
||||
import { useUriListForPermissions } from './hooks/UriListForPermissions';
|
||||
import { PermissionsToCheck, ProcessFile, ProcessModel } from './interfaces';
|
||||
import { usePermissionFetcher } from './hooks/PermissionService';
|
||||
import {
|
||||
ExtensionUiSchema,
|
||||
UiSchemaUxElement,
|
||||
} from './extension_ui_schema_interfaces';
|
||||
import HttpService from './services/HttpService';
|
||||
import { Notification } from './components/Notification';
|
||||
|
||||
type ErrorProps = {
|
||||
@ -44,90 +27,3 @@ export function ErrorBoundaryFallback({ error }: ErrorProps) {
|
||||
</Notification>
|
||||
);
|
||||
}
|
||||
|
||||
export default function ContainerForExtensions() {
|
||||
const [extensionUxElements, setExtensionNavigationItems] = useState<
|
||||
UiSchemaUxElement[] | null
|
||||
>(null);
|
||||
|
||||
let contentClassName = 'main-site-body-centered';
|
||||
if (window.location.pathname.startsWith('/editor/')) {
|
||||
contentClassName = 'no-center-stuff';
|
||||
}
|
||||
const { targetUris } = useUriListForPermissions();
|
||||
const permissionRequestData: PermissionsToCheck = {
|
||||
[targetUris.extensionListPath]: ['GET'],
|
||||
};
|
||||
const { ability, permissionsLoaded } = usePermissionFetcher(
|
||||
permissionRequestData
|
||||
);
|
||||
|
||||
// eslint-disable-next-line sonarjs/cognitive-complexity
|
||||
useEffect(() => {
|
||||
if (!permissionsLoaded) {
|
||||
return;
|
||||
}
|
||||
|
||||
const processExtensionResult = (processModels: ProcessModel[]) => {
|
||||
const eni: UiSchemaUxElement[] = processModels
|
||||
.map((processModel: ProcessModel) => {
|
||||
const extensionUiSchemaFile = processModel.files.find(
|
||||
(file: ProcessFile) => file.name === 'extension_uischema.json'
|
||||
);
|
||||
if (extensionUiSchemaFile && extensionUiSchemaFile.file_contents) {
|
||||
try {
|
||||
const extensionUiSchema: ExtensionUiSchema = JSON.parse(
|
||||
extensionUiSchemaFile.file_contents
|
||||
);
|
||||
if (extensionUiSchema.ux_elements) {
|
||||
return extensionUiSchema.ux_elements;
|
||||
}
|
||||
} catch (jsonParseError: any) {
|
||||
console.error(
|
||||
`Unable to get navigation items for ${processModel.id}`
|
||||
);
|
||||
}
|
||||
}
|
||||
return [] as UiSchemaUxElement[];
|
||||
})
|
||||
.flat();
|
||||
if (eni) {
|
||||
setExtensionNavigationItems(eni);
|
||||
}
|
||||
};
|
||||
|
||||
if (ability.can('GET', targetUris.extensionListPath)) {
|
||||
HttpService.makeCallToBackend({
|
||||
path: targetUris.extensionListPath,
|
||||
successCallback: processExtensionResult,
|
||||
});
|
||||
}
|
||||
}, [targetUris.extensionListPath, permissionsLoaded, ability]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<NavigationBar extensionUxElements={extensionUxElements} />
|
||||
<Content className={contentClassName}>
|
||||
<ScrollToTop />
|
||||
<ErrorBoundary fallback={<h1>Something went wrong.</h1>}>
|
||||
<Routes>
|
||||
<Route path="/*" element={<HomePageRoutes />} />
|
||||
<Route path="/about" element={<About />} />
|
||||
<Route path="/tasks/*" element={<HomePageRoutes />} />
|
||||
<Route
|
||||
path="/admin/*"
|
||||
element={
|
||||
<AdminRoutes extensionUxElements={extensionUxElements} />
|
||||
}
|
||||
/>
|
||||
<Route path="/editor/*" element={<EditorRoutes />} />
|
||||
<Route
|
||||
path="/extensions/:page_identifier"
|
||||
element={<Extension />}
|
||||
/>
|
||||
</Routes>
|
||||
</ErrorBoundary>
|
||||
</Content>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
@ -100,7 +100,7 @@ export default function MessageInstanceList({ processInstanceId }: OwnProps) {
|
||||
instanceLink = (
|
||||
<Link
|
||||
data-qa="process-instance-show-link"
|
||||
to={`/admin/process-instances/${modifyProcessIdentifierForPathParam(
|
||||
to={`/process-instances/${modifyProcessIdentifierForPathParam(
|
||||
row.process_model_identifier
|
||||
)}/${row.process_instance_id}`}
|
||||
>
|
||||
@ -167,7 +167,7 @@ export default function MessageInstanceList({ processInstanceId }: OwnProps) {
|
||||
},
|
||||
[
|
||||
`Process Instance: ${searchParams.get('process_instance_id')}`,
|
||||
`/admin/process-instances/${searchParams.get(
|
||||
`/process-instances/${searchParams.get(
|
||||
'process_model_id'
|
||||
)}/${searchParams.get('process_instance_id')}`,
|
||||
],
|
||||
|
@ -11,7 +11,7 @@ export function FormatProcessModelDisplayName(
|
||||
} = instanceObject;
|
||||
return (
|
||||
<Link
|
||||
to={`/admin/process-models/${modifyProcessIdentifierForPathParam(
|
||||
to={`/process-models/${modifyProcessIdentifierForPathParam(
|
||||
processModelIdentifier
|
||||
)}`}
|
||||
title={processModelIdentifier}
|
||||
|
@ -76,19 +76,17 @@ export default function NavigationBar({ extensionUxElements }: OwnProps) {
|
||||
const versionInfo = appVersionInfo();
|
||||
|
||||
useEffect(() => {
|
||||
let newActiveKey = '/admin/process-groups';
|
||||
if (location.pathname.match(/^\/admin\/messages\b/)) {
|
||||
newActiveKey = '/admin/messages';
|
||||
} else if (
|
||||
location.pathname.match(/^\/admin\/process-instances\/reports\b/)
|
||||
) {
|
||||
newActiveKey = '/admin/process-instances/reports';
|
||||
} else if (location.pathname.match(/^\/admin\/process-instances\b/)) {
|
||||
newActiveKey = '/admin/process-instances';
|
||||
} else if (location.pathname.match(/^\/admin\/configuration\b/)) {
|
||||
newActiveKey = '/admin/configuration';
|
||||
} else if (location.pathname.match(/^\/admin\/data-stores\b/)) {
|
||||
newActiveKey = '/admin/data-stores';
|
||||
let newActiveKey = '/process-groups';
|
||||
if (location.pathname.match(/^\/messages\b/)) {
|
||||
newActiveKey = '/messages';
|
||||
} else if (location.pathname.match(/^\/process-instances\/reports\b/)) {
|
||||
newActiveKey = '/process-instances/reports';
|
||||
} else if (location.pathname.match(/^\/process-instances\b/)) {
|
||||
newActiveKey = '/process-instances';
|
||||
} else if (location.pathname.match(/^\/configuration\b/)) {
|
||||
newActiveKey = '/configuration';
|
||||
} else if (location.pathname.match(/^\/data-stores\b/)) {
|
||||
newActiveKey = '/data-stores';
|
||||
} else if (location.pathname === '/') {
|
||||
newActiveKey = '/';
|
||||
} else if (location.pathname.match(/^\/tasks\b/)) {
|
||||
@ -205,8 +203,8 @@ export default function NavigationBar({ extensionUxElements }: OwnProps) {
|
||||
if (secretAllowed || authenticationAllowed) {
|
||||
return (
|
||||
<HeaderMenuItem
|
||||
href="/admin/configuration"
|
||||
isCurrentPage={isActivePage('/admin/configuration')}
|
||||
href="/configuration"
|
||||
isCurrentPage={isActivePage('/configuration')}
|
||||
>
|
||||
Configuration
|
||||
</HeaderMenuItem>
|
||||
@ -249,8 +247,8 @@ export default function NavigationBar({ extensionUxElements }: OwnProps) {
|
||||
</HeaderMenuItem>
|
||||
<Can I="GET" a={targetUris.processGroupListPath} ability={ability}>
|
||||
<HeaderMenuItem
|
||||
href="/admin/process-groups"
|
||||
isCurrentPage={isActivePage('/admin/process-groups')}
|
||||
href="/process-groups"
|
||||
isCurrentPage={isActivePage('/process-groups')}
|
||||
data-qa="header-nav-processes"
|
||||
>
|
||||
Processes
|
||||
@ -262,24 +260,24 @@ export default function NavigationBar({ extensionUxElements }: OwnProps) {
|
||||
ability={ability}
|
||||
>
|
||||
<HeaderMenuItem
|
||||
href="/admin/process-instances"
|
||||
isCurrentPage={isActivePage('/admin/process-instances')}
|
||||
href="/process-instances"
|
||||
isCurrentPage={isActivePage('/process-instances')}
|
||||
>
|
||||
Process Instances
|
||||
</HeaderMenuItem>
|
||||
</Can>
|
||||
<Can I="GET" a={targetUris.messageInstanceListPath} ability={ability}>
|
||||
<HeaderMenuItem
|
||||
href="/admin/messages"
|
||||
isCurrentPage={isActivePage('/admin/messages')}
|
||||
href="/messages"
|
||||
isCurrentPage={isActivePage('/messages')}
|
||||
>
|
||||
Messages
|
||||
</HeaderMenuItem>
|
||||
</Can>
|
||||
<Can I="GET" a={targetUris.dataStoreListPath} ability={ability}>
|
||||
<HeaderMenuItem
|
||||
href="/admin/data-stores"
|
||||
isCurrentPage={isActivePage('/admin/data-stores')}
|
||||
href="/data-stores"
|
||||
isCurrentPage={isActivePage('/data-stores')}
|
||||
>
|
||||
Data Stores
|
||||
</HeaderMenuItem>
|
||||
|
@ -15,6 +15,8 @@ type OwnProps = {
|
||||
type?: string;
|
||||
hideCloseButton?: boolean;
|
||||
allowTogglingFullMessage?: boolean;
|
||||
timeout?: number;
|
||||
withBottomMargin?: boolean;
|
||||
};
|
||||
|
||||
export function Notification({
|
||||
@ -24,6 +26,8 @@ export function Notification({
|
||||
type = 'success',
|
||||
hideCloseButton = false,
|
||||
allowTogglingFullMessage = false,
|
||||
timeout,
|
||||
withBottomMargin = true,
|
||||
}: OwnProps) {
|
||||
const [showMessage, setShowMessage] = useState<boolean>(
|
||||
!allowTogglingFullMessage
|
||||
@ -33,11 +37,19 @@ export function Notification({
|
||||
iconComponent = <Error className="notification-icon" />;
|
||||
}
|
||||
|
||||
if (timeout && onClose) {
|
||||
setTimeout(() => {
|
||||
onClose();
|
||||
}, timeout);
|
||||
}
|
||||
|
||||
let classes = `cds--inline-notification cds--inline-notification--low-contrast cds--inline-notification--${type}`;
|
||||
if (withBottomMargin) {
|
||||
classes = `${classes} with-bottom-margin`;
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
role="status"
|
||||
className={`with-bottom-margin cds--inline-notification cds--inline-notification--low-contrast cds--inline-notification--${type}`}
|
||||
>
|
||||
<div role="status" className={classes}>
|
||||
<div className="cds--inline-notification__details">
|
||||
<div className="cds--inline-notification__text-wrapper">
|
||||
{iconComponent}
|
||||
|
@ -58,7 +58,7 @@ export default function ProcessBreadcrumb({ hotCrumbs }: OwnProps) {
|
||||
) {
|
||||
const breadcrumbs = processEntity.parent_groups.map(
|
||||
(parentGroup: ProcessGroupLite) => {
|
||||
const fullUrl = `/admin/process-groups/${modifyProcessIdentifierForPathParam(
|
||||
const fullUrl = `/process-groups/${modifyProcessIdentifierForPathParam(
|
||||
parentGroup.id
|
||||
)}`;
|
||||
return (
|
||||
@ -70,10 +70,10 @@ export default function ProcessBreadcrumb({ hotCrumbs }: OwnProps) {
|
||||
);
|
||||
|
||||
if (crumb.linkLastItem) {
|
||||
let apiBase = '/admin/process-groups';
|
||||
let apiBase = '/process-groups';
|
||||
let dataQaTag = '';
|
||||
if (crumb.entityType.startsWith('process-model')) {
|
||||
apiBase = '/admin/process-models';
|
||||
apiBase = '/process-models';
|
||||
dataQaTag = 'process-model-breadcrumb-link';
|
||||
}
|
||||
const fullUrl = `${apiBase}/${modifyProcessIdentifierForPathParam(
|
||||
|
@ -27,7 +27,7 @@ export default function ProcessGroupForm({
|
||||
const navigateToProcessGroup = (_result: any) => {
|
||||
if (newProcessGroupId) {
|
||||
navigate(
|
||||
`/admin/process-groups/${modifyProcessIdentifierForPathParam(
|
||||
`/process-groups/${modifyProcessIdentifierForPathParam(
|
||||
newProcessGroupId
|
||||
)}`
|
||||
);
|
||||
|
@ -56,7 +56,7 @@ export default function ProcessGroupListTiles({
|
||||
<ClickableTile
|
||||
id={`process-group-tile-${row.id}`}
|
||||
className="tile-process-group"
|
||||
href={`/admin/process-groups/${modifyProcessIdentifierForPathParam(
|
||||
href={`/process-groups/${modifyProcessIdentifierForPathParam(
|
||||
row.id
|
||||
)}`}
|
||||
>
|
||||
|
@ -123,6 +123,7 @@ export default function ProcessInstanceListTable({
|
||||
headerElement,
|
||||
tableHtmlId,
|
||||
}: OwnProps) {
|
||||
// eslint-disable-next-line sonarjs/no-duplicate-string
|
||||
let processInstanceApiSearchPath = '/process-instances/for-me';
|
||||
if (variant === 'all') {
|
||||
processInstanceApiSearchPath = '/process-instances';
|
||||
@ -177,13 +178,9 @@ export default function ProcessInstanceListTable({
|
||||
};
|
||||
|
||||
const processInstanceListPathPrefix =
|
||||
variant === 'all'
|
||||
? '/admin/process-instances/all'
|
||||
: '/admin/process-instances/for-me';
|
||||
variant === 'all' ? '/process-instances/all' : '/process-instances/for-me';
|
||||
const processInstanceShowPathPrefix =
|
||||
variant === 'all'
|
||||
? '/admin/process-instances'
|
||||
: '/admin/process-instances/for-me';
|
||||
variant === 'all' ? '/process-instances' : '/process-instances/for-me';
|
||||
|
||||
const [processStatusAllOptions, setProcessStatusAllOptions] = useState<any[]>(
|
||||
[]
|
||||
@ -1834,7 +1831,7 @@ export default function ProcessInstanceListTable({
|
||||
hasIconOnly
|
||||
size="md"
|
||||
onClick={() =>
|
||||
navigate(`/admin/process-instances?report_hash=${reportHash}`)
|
||||
navigate(`/process-instances?report_hash=${reportHash}`)
|
||||
}
|
||||
/>
|
||||
</Column>
|
||||
|
@ -32,7 +32,7 @@ export default function ProcessInstanceListTabs({ variant }: OwnProps) {
|
||||
title="Only show process instances for the current user."
|
||||
data-qa="process-instance-list-for-me"
|
||||
onClick={() => {
|
||||
navigate('/admin/process-instances/for-me');
|
||||
navigate('/process-instances/for-me');
|
||||
}}
|
||||
>
|
||||
For Me
|
||||
@ -42,7 +42,7 @@ export default function ProcessInstanceListTabs({ variant }: OwnProps) {
|
||||
title="Show all process instances for all users."
|
||||
data-qa="process-instance-list-all"
|
||||
onClick={() => {
|
||||
navigate('/admin/process-instances/all');
|
||||
navigate('/process-instances/all');
|
||||
}}
|
||||
>
|
||||
All
|
||||
@ -52,7 +52,7 @@ export default function ProcessInstanceListTabs({ variant }: OwnProps) {
|
||||
title="Search for a process instance by id."
|
||||
data-qa="process-instance-list-find-by-id"
|
||||
onClick={() => {
|
||||
navigate('/admin/process-instances/find-by-id');
|
||||
navigate('/process-instances/find-by-id');
|
||||
}}
|
||||
>
|
||||
Find By Id
|
||||
|
@ -78,9 +78,9 @@ export default function ProcessInstanceLogList({
|
||||
shouldDisplayClearButton = true;
|
||||
}
|
||||
|
||||
let processInstanceShowPageBaseUrl = `/admin/process-instances/for-me/${processModelId}`;
|
||||
let processInstanceShowPageBaseUrl = `/process-instances/for-me/${processModelId}`;
|
||||
if (variant === 'all') {
|
||||
processInstanceShowPageBaseUrl = `/admin/process-instances/${processModelId}`;
|
||||
processInstanceShowPageBaseUrl = `/process-instances/${processModelId}`;
|
||||
}
|
||||
const taskNameHeader = isEventsView ? 'Task name' : 'Milestone';
|
||||
const tableType = isEventsView ? 'events' : 'milestones';
|
||||
|
@ -98,7 +98,7 @@ export default function ProcessInstanceRun({
|
||||
const onProcessInstanceRun = (processInstance: any) => {
|
||||
const processInstanceId = (processInstance as any).id;
|
||||
navigate(
|
||||
`/admin/process-instances/for-me/${modifyProcessIdentifierForPathParam(
|
||||
`/process-instances/for-me/${modifyProcessIdentifierForPathParam(
|
||||
processModel.id
|
||||
)}/${processInstanceId}/interstitial`
|
||||
);
|
||||
|
@ -42,7 +42,7 @@ export default function ProcessModelForm({
|
||||
if ('id' in result) {
|
||||
const modifiedProcessModelPathFromResult =
|
||||
modifyProcessIdentifierForPathParam(result.id);
|
||||
navigate(`/admin/process-models/${modifiedProcessModelPathFromResult}`);
|
||||
navigate(`/process-models/${modifiedProcessModelPathFromResult}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -56,7 +56,7 @@ export default function ProcessModelListTiles({
|
||||
onClose={() => setProcessInstance(null)}
|
||||
>
|
||||
<Link
|
||||
to={`/admin/process-instances/${modifyProcessIdentifierForPathParam(
|
||||
to={`/process-instances/${modifyProcessIdentifierForPathParam(
|
||||
processInstance.process_model_identifier
|
||||
)}/${processInstance.id}`}
|
||||
data-qa="process-instance-show-link"
|
||||
@ -83,7 +83,7 @@ export default function ProcessModelListTiles({
|
||||
<a
|
||||
title={row.id}
|
||||
data-qa="process-model-show-link"
|
||||
href={`/admin/process-models/${modifyProcessIdentifierForPathParam(
|
||||
href={`/process-models/${modifyProcessIdentifierForPathParam(
|
||||
row.id
|
||||
)}`}
|
||||
>
|
||||
|
@ -632,7 +632,7 @@ export default function ReactDiagramEditor({
|
||||
<li>
|
||||
<Link
|
||||
size="lg"
|
||||
href={`/admin/process-models/${modifyProcessIdentifierForPathParam(
|
||||
href={`/process-models/${modifyProcessIdentifierForPathParam(
|
||||
ref.process_model_id
|
||||
)}`}
|
||||
>
|
||||
@ -704,7 +704,7 @@ export default function ReactDiagramEditor({
|
||||
<Button
|
||||
onClick={() => {
|
||||
navigate(
|
||||
`/admin/process-models/${processModelId}/form/${fileName}`
|
||||
`/process-models/${processModelId}/form/${fileName}`
|
||||
);
|
||||
}}
|
||||
>
|
||||
|
@ -1,13 +0,0 @@
|
||||
import React from 'react';
|
||||
import UserService from '../services/UserService';
|
||||
|
||||
type Props = {
|
||||
roles: string[];
|
||||
children: React.ReactNode;
|
||||
};
|
||||
|
||||
function RenderOnRole({ roles, children }: Props) {
|
||||
return UserService.hasRole(roles) ? children : null;
|
||||
}
|
||||
|
||||
export default RenderOnRole;
|
@ -214,7 +214,7 @@ export default function TaskListTable({
|
||||
<td>
|
||||
<Link
|
||||
data-qa="process-instance-show-link-id"
|
||||
to={`/admin/process-instances/for-me/${modifiedProcessModelIdentifier}/${processInstanceTask.process_instance_id}`}
|
||||
to={`/process-instances/for-me/${modifiedProcessModelIdentifier}/${processInstanceTask.process_instance_id}`}
|
||||
title={`View process instance ${processInstanceTask.process_instance_id}`}
|
||||
>
|
||||
{processInstanceTask.process_instance_id}
|
||||
@ -239,7 +239,7 @@ export default function TaskListTable({
|
||||
<td>
|
||||
<Link
|
||||
data-qa="process-model-show-link"
|
||||
to={`/admin/process-models/${modifiedProcessModelIdentifier}`}
|
||||
to={`/process-models/${modifiedProcessModelIdentifier}`}
|
||||
title={processInstanceTask.process_model_identifier}
|
||||
>
|
||||
{processInstanceTask.process_model_display_name}
|
||||
|
@ -6,6 +6,7 @@ export const useUriListForPermissions = () => {
|
||||
const targetUris = useMemo(() => {
|
||||
return {
|
||||
authenticationListPath: `/v1.0/authentications`,
|
||||
statusPath: `/v1.0/status`,
|
||||
messageInstanceListPath: '/v1.0/messages',
|
||||
dataStoreListPath: '/v1.0/data-stores',
|
||||
extensionListPath: '/v1.0/extensions',
|
||||
|
@ -1,7 +1,6 @@
|
||||
// @ts-ignore
|
||||
import { Table } from '@carbon/react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import ErrorDisplay from '../components/ErrorDisplay';
|
||||
import appVersionInfo from '../helpers/appVersionInfo';
|
||||
import { ObjectWithStringKeysAndValues } from '../interfaces';
|
||||
import HttpService from '../services/HttpService';
|
||||
@ -58,7 +57,6 @@ export default function About() {
|
||||
|
||||
return (
|
||||
<div>
|
||||
<ErrorDisplay />
|
||||
<h1>About</h1>
|
||||
{versionInfoFromDict('Frontend version information', frontendVersionInfo)}
|
||||
{versionInfoFromDict('Backend version information', backendVersionInfo)}
|
||||
|
@ -1,151 +0,0 @@
|
||||
import { Routes, Route, useLocation } from 'react-router-dom';
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import ProcessGroupList from './ProcessGroupList';
|
||||
import ProcessGroupShow from './ProcessGroupShow';
|
||||
import ProcessGroupNew from './ProcessGroupNew';
|
||||
import ProcessGroupEdit from './ProcessGroupEdit';
|
||||
import ProcessModelShow from './ProcessModelShow';
|
||||
import ProcessInstanceList from './ProcessInstanceList';
|
||||
import ProcessModelNew from './ProcessModelNew';
|
||||
import ProcessModelEdit from './ProcessModelEdit';
|
||||
import ProcessInstanceShow from './ProcessInstanceShow';
|
||||
import UserService from '../services/UserService';
|
||||
import ProcessInstanceReportList from './ProcessInstanceReportList';
|
||||
import ProcessInstanceReportNew from './ProcessInstanceReportNew';
|
||||
import ProcessInstanceReportEdit from './ProcessInstanceReportEdit';
|
||||
import ReactFormEditor from './ReactFormEditor';
|
||||
import Configuration from './Configuration';
|
||||
import JsonSchemaFormBuilder from './JsonSchemaFormBuilder';
|
||||
import ProcessModelNewExperimental from './ProcessModelNewExperimental';
|
||||
import ProcessInstanceFindById from './ProcessInstanceFindById';
|
||||
import ProcessInterstitialPage from './ProcessInterstitialPage';
|
||||
import MessageListPage from './MessageListPage';
|
||||
import DataStorePage from './DataStorePage';
|
||||
import ErrorDisplay from '../components/ErrorDisplay';
|
||||
import { UiSchemaUxElement } from '../extension_ui_schema_interfaces';
|
||||
|
||||
type OwnProps = {
|
||||
extensionUxElements?: UiSchemaUxElement[] | null;
|
||||
};
|
||||
|
||||
export default function AdminRoutes({ extensionUxElements }: OwnProps) {
|
||||
const location = useLocation();
|
||||
|
||||
useEffect(() => {}, [location]);
|
||||
|
||||
if (UserService.hasRole(['admin'])) {
|
||||
return (
|
||||
<div className="fixed-width-container">
|
||||
<ErrorDisplay />
|
||||
<Routes>
|
||||
<Route path="/" element={<ProcessGroupList />} />
|
||||
<Route path="process-groups" element={<ProcessGroupList />} />
|
||||
<Route
|
||||
path="process-groups/:process_group_id"
|
||||
element={<ProcessGroupShow />}
|
||||
/>
|
||||
<Route path="process-groups/new" element={<ProcessGroupNew />} />
|
||||
<Route
|
||||
path="process-groups/:process_group_id/edit"
|
||||
element={<ProcessGroupEdit />}
|
||||
/>
|
||||
|
||||
<Route
|
||||
path="process-models/:process_group_id/new"
|
||||
element={<ProcessModelNew />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_group_id/new-e"
|
||||
element={<ProcessModelNewExperimental />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_model_id"
|
||||
element={<ProcessModelShow />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_model_id/edit"
|
||||
element={<ProcessModelEdit />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/for-me/:process_model_id/:process_instance_id"
|
||||
element={<ProcessInstanceShow variant="for-me" />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/for-me/:process_model_id/:process_instance_id/:to_task_guid"
|
||||
element={<ProcessInstanceShow variant="for-me" />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/for-me/:process_model_id/:process_instance_id/interstitial"
|
||||
element={<ProcessInterstitialPage variant="for-me" />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/:process_model_id/:process_instance_id/interstitial"
|
||||
element={<ProcessInterstitialPage variant="all" />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/:process_model_id/:process_instance_id"
|
||||
element={<ProcessInstanceShow variant="all" />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/:process_model_id/:process_instance_id/:to_task_guid"
|
||||
element={<ProcessInstanceShow variant="all" />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/reports"
|
||||
element={<ProcessInstanceReportList />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/reports/new"
|
||||
element={<ProcessInstanceReportNew />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/reports/:report_identifier/edit"
|
||||
element={<ProcessInstanceReportEdit />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_model_id/form"
|
||||
element={<ReactFormEditor />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_model_id/form/:file_name"
|
||||
element={<ReactFormEditor />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances"
|
||||
element={<ProcessInstanceList variant="for-me" />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/for-me"
|
||||
element={<ProcessInstanceList variant="for-me" />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/all"
|
||||
element={<ProcessInstanceList variant="all" />}
|
||||
/>
|
||||
<Route
|
||||
path="configuration/*"
|
||||
element={
|
||||
<Configuration extensionUxElements={extensionUxElements} />
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_model_id/form-builder"
|
||||
element={<JsonSchemaFormBuilder />}
|
||||
/>
|
||||
<Route
|
||||
path="process-instances/find-by-id"
|
||||
element={<ProcessInstanceFindById />}
|
||||
/>
|
||||
<Route path="messages" element={<MessageListPage />} />
|
||||
<Route path="data-stores" element={<DataStorePage />} />
|
||||
</Routes>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<main>
|
||||
<h1>404</h1>
|
||||
</main>
|
||||
);
|
||||
}
|
12
spiffworkflow-frontend/src/routes/BackendIsDown.tsx
Normal file
12
spiffworkflow-frontend/src/routes/BackendIsDown.tsx
Normal file
@ -0,0 +1,12 @@
|
||||
export default function BackendIsDown() {
|
||||
return (
|
||||
<div>
|
||||
<h1>Server error</h1>
|
||||
<p>
|
||||
We are sorry, but our service is temporarily unavailable due to
|
||||
technical difficulties. Please bear with us while we work to resolve the
|
||||
issue. If the problem persists, please contact the site administrator.
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
}
|
44
spiffworkflow-frontend/src/routes/BaseRoutes.tsx
Normal file
44
spiffworkflow-frontend/src/routes/BaseRoutes.tsx
Normal file
@ -0,0 +1,44 @@
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
import Configuration from './Configuration';
|
||||
import MessageListPage from './MessageListPage';
|
||||
import DataStorePage from './DataStorePage';
|
||||
import { UiSchemaUxElement } from '../extension_ui_schema_interfaces';
|
||||
import HomeRoutes from './HomeRoutes';
|
||||
import ProcessGroupRoutes from './ProcessGroupRoutes';
|
||||
import ProcessModelRoutes from './ProcessModelRoutes';
|
||||
import ProcessInstanceRoutes from './ProcessInstanceRoutes';
|
||||
import ErrorDisplay from '../components/ErrorDisplay';
|
||||
import ProcessInstanceShortLink from './ProcessInstanceShortLink';
|
||||
import About from './About';
|
||||
import Page404 from './Page404';
|
||||
|
||||
type OwnProps = {
|
||||
extensionUxElements?: UiSchemaUxElement[] | null;
|
||||
};
|
||||
|
||||
export default function BaseRoutes({ extensionUxElements }: OwnProps) {
|
||||
return (
|
||||
<div className="fixed-width-container">
|
||||
<ErrorDisplay />
|
||||
<Routes>
|
||||
<Route path="/" element={<HomeRoutes />} />
|
||||
<Route path="tasks/*" element={<HomeRoutes />} />
|
||||
<Route path="process-groups/*" element={<ProcessGroupRoutes />} />
|
||||
<Route path="process-models/*" element={<ProcessModelRoutes />} />
|
||||
<Route path="process-instances/*" element={<ProcessInstanceRoutes />} />
|
||||
<Route
|
||||
path="i/:process_instance_id"
|
||||
element={<ProcessInstanceShortLink />}
|
||||
/>
|
||||
<Route
|
||||
path="configuration/*"
|
||||
element={<Configuration extensionUxElements={extensionUxElements} />}
|
||||
/>
|
||||
<Route path="messages" element={<MessageListPage />} />
|
||||
<Route path="data-stores" element={<DataStorePage />} />
|
||||
<Route path="about" element={<About />} />
|
||||
<Route path="/*" element={<Page404 />} />
|
||||
</Routes>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -39,7 +39,7 @@ export default function Configuration({ extensionUxElements }: OwnProps) {
|
||||
removeError();
|
||||
setPageTitle(['Configuration']);
|
||||
let newSelectedTabIndex = 0;
|
||||
if (location.pathname.match(/^\/admin\/configuration\/authentications\b/)) {
|
||||
if (location.pathname.match(/^\/configuration\/authentications\b/)) {
|
||||
newSelectedTabIndex = 1;
|
||||
}
|
||||
setSelectedTabIndex(newSelectedTabIndex);
|
||||
@ -49,7 +49,7 @@ export default function Configuration({ extensionUxElements }: OwnProps) {
|
||||
uxElement: UiSchemaUxElement,
|
||||
uxElementIndex: number
|
||||
) => {
|
||||
const navItemPage = `/admin/configuration/extension${uxElement.page}`;
|
||||
const navItemPage = `/configuration/extension${uxElement.page}`;
|
||||
|
||||
let pagesToCheck = [uxElement.page];
|
||||
if (
|
||||
@ -60,7 +60,7 @@ export default function Configuration({ extensionUxElements }: OwnProps) {
|
||||
}
|
||||
|
||||
pagesToCheck.forEach((pageToCheck: string) => {
|
||||
const pageToCheckNavItem = `/admin/configuration/extension${pageToCheck}`;
|
||||
const pageToCheckNavItem = `/configuration/extension${pageToCheck}`;
|
||||
if (pageToCheckNavItem === location.pathname) {
|
||||
setSelectedTabIndex(uxElementIndex + 2);
|
||||
}
|
||||
@ -80,14 +80,12 @@ export default function Configuration({ extensionUxElements }: OwnProps) {
|
||||
<Tabs selectedIndex={selectedTabIndex}>
|
||||
<TabList aria-label="List of tabs">
|
||||
<Can I="GET" a={targetUris.secretListPath} ability={ability}>
|
||||
<Tab onClick={() => navigate('/admin/configuration/secrets')}>
|
||||
<Tab onClick={() => navigate('/configuration/secrets')}>
|
||||
Secrets
|
||||
</Tab>
|
||||
</Can>
|
||||
<Can I="GET" a={targetUris.authenticationListPath} ability={ability}>
|
||||
<Tab
|
||||
onClick={() => navigate('/admin/configuration/authentications')}
|
||||
>
|
||||
<Tab onClick={() => navigate('/configuration/authentications')}>
|
||||
Authentications
|
||||
</Tab>
|
||||
</Can>
|
||||
|
@ -2,7 +2,6 @@ import { Routes, Route, useLocation } from 'react-router-dom';
|
||||
|
||||
import React, { useEffect } from 'react';
|
||||
import ProcessModelEditDiagram from './ProcessModelEditDiagram';
|
||||
import UserService from '../services/UserService';
|
||||
import ErrorDisplay from '../components/ErrorDisplay';
|
||||
|
||||
export default function EditorRoutes() {
|
||||
@ -10,26 +9,19 @@ export default function EditorRoutes() {
|
||||
|
||||
useEffect(() => {}, [location]);
|
||||
|
||||
if (UserService.hasRole(['admin'])) {
|
||||
return (
|
||||
<div className="full-width-container no-center-stuff">
|
||||
<ErrorDisplay />
|
||||
<Routes>
|
||||
<Route
|
||||
path="process-models/:process_model_id/files"
|
||||
element={<ProcessModelEditDiagram />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_model_id/files/:file_name"
|
||||
element={<ProcessModelEditDiagram />}
|
||||
/>
|
||||
</Routes>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<main>
|
||||
<h1>404</h1>
|
||||
</main>
|
||||
<div className="full-width-container no-center-stuff">
|
||||
<ErrorDisplay />
|
||||
<Routes>
|
||||
<Route
|
||||
path="process-models/:process_model_id/files"
|
||||
element={<ProcessModelEditDiagram />}
|
||||
/>
|
||||
<Route
|
||||
path="process-models/:process_model_id/files/:file_name"
|
||||
element={<ProcessModelEditDiagram />}
|
||||
/>
|
||||
</Routes>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -7,9 +7,8 @@ import CompletedInstances from './CompletedInstances';
|
||||
import CreateNewInstance from './CreateNewInstance';
|
||||
import InProgressInstances from './InProgressInstances';
|
||||
import OnboardingView from './OnboardingView';
|
||||
import ErrorDisplay from '../components/ErrorDisplay';
|
||||
|
||||
export default function HomePageRoutes() {
|
||||
export default function HomeRoutes() {
|
||||
const location = useLocation();
|
||||
const [selectedTabIndex, setSelectedTabIndex] = useState<number>(0);
|
||||
const navigate = useNavigate();
|
||||
@ -49,8 +48,7 @@ export default function HomePageRoutes() {
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="fixed-width-container">
|
||||
<ErrorDisplay />
|
||||
<>
|
||||
<OnboardingView />
|
||||
{renderTabs()}
|
||||
<Routes>
|
||||
@ -61,6 +59,6 @@ export default function HomePageRoutes() {
|
||||
<Route path="completed-instances" element={<CompletedInstances />} />
|
||||
<Route path="create-new-instance" element={<CreateNewInstance />} />
|
||||
</Routes>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
@ -296,7 +296,7 @@ export default function JsonSchemaFormBuilder() {
|
||||
const httpMethod = 'DELETE';
|
||||
|
||||
const navigateToProcessModelShow = (_httpResult: any) => {
|
||||
navigate(`/admin/process-models/${modifiedProcessModelId}`);
|
||||
navigate(`/process-models/${modifiedProcessModelId}`);
|
||||
};
|
||||
|
||||
HttpService.makeCallToBackend({
|
||||
@ -339,7 +339,7 @@ export default function JsonSchemaFormBuilder() {
|
||||
<Button
|
||||
onClick={() =>
|
||||
navigate(
|
||||
`/admin/process-models/${
|
||||
`/process-models/${
|
||||
params.process_model_id
|
||||
}/form/${searchParams.get('file_name')}`
|
||||
)
|
||||
|
@ -61,7 +61,7 @@ export default function MyTasks() {
|
||||
onClose={() => setProcessInstance(null)}
|
||||
>
|
||||
<Link
|
||||
to={`/admin/process-instances/${modifyProcessIdentifierForPathParam(
|
||||
to={`/process-instances/${modifyProcessIdentifierForPathParam(
|
||||
processInstance.process_model_identifier
|
||||
)}/${processInstance.id}`}
|
||||
data-qa="process-instance-show-link"
|
||||
@ -91,7 +91,7 @@ export default function MyTasks() {
|
||||
<td>
|
||||
<Link
|
||||
data-qa="process-model-show-link"
|
||||
to={`/admin/process-models/${modifiedProcessModelIdentifier}`}
|
||||
to={`/process-models/${modifiedProcessModelIdentifier}`}
|
||||
>
|
||||
{rowToUse.process_model_display_name}
|
||||
</Link>
|
||||
@ -99,7 +99,7 @@ export default function MyTasks() {
|
||||
<td>
|
||||
<Link
|
||||
data-qa="process-instance-show-link"
|
||||
to={`/admin/process-instances/${modifiedProcessModelIdentifier}/${rowToUse.process_instance_id}`}
|
||||
to={`/process-instances/${modifiedProcessModelIdentifier}/${rowToUse.process_instance_id}`}
|
||||
>
|
||||
{rowToUse.process_instance_id}
|
||||
</Link>
|
||||
@ -158,7 +158,7 @@ export default function MyTasks() {
|
||||
<td>
|
||||
<Link
|
||||
data-qa="process-model-show-link"
|
||||
to={`/admin/process-models/${modifiedProcessModelId}`}
|
||||
to={`/process-models/${modifiedProcessModelId}`}
|
||||
>
|
||||
{row.processModelDisplayName}
|
||||
</Link>
|
||||
|
8
spiffworkflow-frontend/src/routes/Page404.tsx
Normal file
8
spiffworkflow-frontend/src/routes/Page404.tsx
Normal file
@ -0,0 +1,8 @@
|
||||
export default function Page404() {
|
||||
return (
|
||||
<div>
|
||||
<h1>404 not found</h1>
|
||||
<p>This page does not exist. Please check the url.</p>
|
||||
</div>
|
||||
);
|
||||
}
|
@ -49,7 +49,7 @@ export default function ProcessGroupList() {
|
||||
const processModelSearchOnChange = (selection: CarbonComboBoxSelection) => {
|
||||
const processModel = selection.selectedItem;
|
||||
navigate(
|
||||
`/admin/process-models/${modifyProcessIdentifierForPathParam(
|
||||
`/process-models/${modifyProcessIdentifierForPathParam(
|
||||
processModel.id
|
||||
)}`
|
||||
);
|
||||
@ -68,7 +68,7 @@ export default function ProcessGroupList() {
|
||||
<>
|
||||
<ProcessBreadcrumb hotCrumbs={[['Process Groups']]} />
|
||||
<Can I="POST" a={targetUris.processGroupListPath} ability={ability}>
|
||||
<Button kind="secondary" href="/admin/process-groups/new">
|
||||
<Button kind="secondary" href="/process-groups/new">
|
||||
Add a process group
|
||||
</Button>
|
||||
<br />
|
||||
|
16
spiffworkflow-frontend/src/routes/ProcessGroupRoutes.tsx
Normal file
16
spiffworkflow-frontend/src/routes/ProcessGroupRoutes.tsx
Normal file
@ -0,0 +1,16 @@
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
import ProcessGroupList from './ProcessGroupList';
|
||||
import ProcessGroupShow from './ProcessGroupShow';
|
||||
import ProcessGroupNew from './ProcessGroupNew';
|
||||
import ProcessGroupEdit from './ProcessGroupEdit';
|
||||
|
||||
export default function ProcessGroupRoutes() {
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="/" element={<ProcessGroupList />} />
|
||||
<Route path="/:process_group_id" element={<ProcessGroupShow />} />
|
||||
<Route path="new" element={<ProcessGroupNew />} />
|
||||
<Route path=":process_group_id/edit" element={<ProcessGroupEdit />} />
|
||||
</Routes>
|
||||
);
|
||||
}
|
@ -86,7 +86,7 @@ export default function ProcessGroupShow() {
|
||||
// <tr key={row.id}>
|
||||
// <td>
|
||||
// <Link
|
||||
// to={`/admin/process-models/${modifiedProcessModelId}`}
|
||||
// to={`/process-models/${modifiedProcessModelId}`}
|
||||
// data-qa="process-model-show-link"
|
||||
// >
|
||||
// {row.id}
|
||||
@ -113,7 +113,7 @@ export default function ProcessGroupShow() {
|
||||
// };
|
||||
|
||||
const navigateToProcessGroups = (_result: any) => {
|
||||
navigate(`/admin/process-groups`);
|
||||
navigate(`/process-groups`);
|
||||
};
|
||||
|
||||
const deleteProcessGroup = () => {
|
||||
@ -155,7 +155,7 @@ export default function ProcessGroupShow() {
|
||||
renderIcon={Edit}
|
||||
iconDescription="Edit Process Group"
|
||||
hasIconOnly
|
||||
href={`/admin/process-groups/${modifiedProcessGroupId}/edit`}
|
||||
href={`/process-groups/${modifiedProcessGroupId}/edit`}
|
||||
>
|
||||
Edit process group
|
||||
</Button>
|
||||
@ -178,7 +178,7 @@ export default function ProcessGroupShow() {
|
||||
<Stack orientation="horizontal" gap={3}>
|
||||
<Can I="POST" a={targetUris.processGroupListPath} ability={ability}>
|
||||
<Button
|
||||
href={`/admin/process-groups/new?parentGroupId=${processGroup.id}`}
|
||||
href={`/process-groups/new?parentGroupId=${processGroup.id}`}
|
||||
>
|
||||
Add a process group
|
||||
</Button>
|
||||
@ -188,9 +188,7 @@ export default function ProcessGroupShow() {
|
||||
a={targetUris.processModelCreatePath}
|
||||
ability={ability}
|
||||
>
|
||||
<Button
|
||||
href={`/admin/process-models/${modifiedProcessGroupId}/new`}
|
||||
>
|
||||
<Button href={`/process-models/${modifiedProcessGroupId}/new`}>
|
||||
Add a process model
|
||||
</Button>
|
||||
</Can>
|
||||
|
@ -16,7 +16,7 @@ export default function ProcessInstanceFindById() {
|
||||
|
||||
const handleProcessInstanceNavigation = (result: any) => {
|
||||
const processInstance: ProcessInstance = result.process_instance;
|
||||
let path = '/admin/process-instances/';
|
||||
let path = '/process-instances/';
|
||||
if (result.uri_type === 'for-me') {
|
||||
path += 'for-me/';
|
||||
}
|
||||
|
@ -23,11 +23,11 @@ export default function ProcessInstanceReportEdit() {
|
||||
const [filterBy, setFilterBy] = useState('');
|
||||
|
||||
const navigateToProcessInstanceReport = (_result: any) => {
|
||||
navigate(`/admin/process-instances/reports/${params.report_identifier}`);
|
||||
navigate(`/process-instances/reports/${params.report_identifier}`);
|
||||
};
|
||||
|
||||
const navigateToProcessInstanceReports = (_result: any) => {
|
||||
navigate(`/admin/process-instances/reports`);
|
||||
navigate(`/process-instances/reports`);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
|
@ -31,7 +31,7 @@ export default function ProcessInstanceReportList() {
|
||||
return (
|
||||
<tr key={(row as any).id}>
|
||||
<td>
|
||||
<Link to={`/admin/process-instances?report_id=${rowToUse.id}`}>
|
||||
<Link to={`/process-instances?report_id=${rowToUse.id}`}>
|
||||
{rowToUse.identifier}
|
||||
</Link>
|
||||
</td>
|
||||
@ -54,7 +54,7 @@ export default function ProcessInstanceReportList() {
|
||||
<>
|
||||
<h1>Process Instance Perspectives</h1>
|
||||
<Can I="POST" a={targetUris.processInstanceListPath} ability={ability}>
|
||||
<Button href="/admin/process-instances/reports/new">
|
||||
<Button href="/process-instances/reports/new">
|
||||
Add a process instance perspective
|
||||
</Button>
|
||||
</Can>
|
||||
|
@ -12,7 +12,7 @@ export default function ProcessInstanceReportNew() {
|
||||
const [filterBy, setFilterBy] = useState('');
|
||||
|
||||
const navigateToNewProcessInstance = (_result: any) => {
|
||||
navigate(`/admin/process-instances/reports/${identifier}`);
|
||||
navigate(`/process-instances/reports/${identifier}`);
|
||||
};
|
||||
|
||||
const addProcessInstanceReport = (event: any) => {
|
||||
|
49
spiffworkflow-frontend/src/routes/ProcessInstanceRoutes.tsx
Normal file
49
spiffworkflow-frontend/src/routes/ProcessInstanceRoutes.tsx
Normal file
@ -0,0 +1,49 @@
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
import ProcessInstanceList from './ProcessInstanceList';
|
||||
import ProcessInstanceShow from './ProcessInstanceShow';
|
||||
import ProcessInstanceReportList from './ProcessInstanceReportList';
|
||||
import ProcessInstanceReportNew from './ProcessInstanceReportNew';
|
||||
import ProcessInstanceReportEdit from './ProcessInstanceReportEdit';
|
||||
import ProcessInstanceFindById from './ProcessInstanceFindById';
|
||||
import ProcessInterstitialPage from './ProcessInterstitialPage';
|
||||
|
||||
export default function ProcessInstanceRoutes() {
|
||||
return (
|
||||
<Routes>
|
||||
<Route path="/" element={<ProcessInstanceList variant="for-me" />} />
|
||||
<Route path="for-me" element={<ProcessInstanceList variant="for-me" />} />
|
||||
<Route path="all" element={<ProcessInstanceList variant="all" />} />
|
||||
<Route
|
||||
path="for-me/:process_model_id/:process_instance_id"
|
||||
element={<ProcessInstanceShow variant="for-me" />}
|
||||
/>
|
||||
<Route
|
||||
path="for-me/:process_model_id/:process_instance_id/:to_task_guid"
|
||||
element={<ProcessInstanceShow variant="for-me" />}
|
||||
/>
|
||||
<Route
|
||||
path="for-me/:process_model_id/:process_instance_id/interstitial"
|
||||
element={<ProcessInterstitialPage variant="for-me" />}
|
||||
/>
|
||||
<Route
|
||||
path=":process_model_id/:process_instance_id/interstitial"
|
||||
element={<ProcessInterstitialPage variant="all" />}
|
||||
/>
|
||||
<Route
|
||||
path=":process_model_id/:process_instance_id"
|
||||
element={<ProcessInstanceShow variant="all" />}
|
||||
/>
|
||||
<Route
|
||||
path=":process_model_id/:process_instance_id/:to_task_guid"
|
||||
element={<ProcessInstanceShow variant="all" />}
|
||||
/>
|
||||
<Route path="reports" element={<ProcessInstanceReportList />} />
|
||||
<Route path="reports/new" element={<ProcessInstanceReportNew />} />
|
||||
<Route
|
||||
path="reports/:report_identifier/edit"
|
||||
element={<ProcessInstanceReportEdit />}
|
||||
/>
|
||||
<Route path="find-by-id" element={<ProcessInstanceFindById />} />
|
||||
</Routes>
|
||||
);
|
||||
}
|
@ -0,0 +1,31 @@
|
||||
import { useEffect } from 'react';
|
||||
import { useNavigate, useParams } from 'react-router-dom';
|
||||
import { modifyProcessIdentifierForPathParam } from '../helpers';
|
||||
import HttpService from '../services/HttpService';
|
||||
import { ProcessInstance } from '../interfaces';
|
||||
|
||||
export default function ProcessInstanceShortLink() {
|
||||
const params = useParams();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
const handleProcessInstanceNavigation = (result: any) => {
|
||||
const processInstance: ProcessInstance = result.process_instance;
|
||||
let path = '/process-instances/';
|
||||
if (result.uri_type === 'for-me') {
|
||||
path += 'for-me/';
|
||||
}
|
||||
path += `${modifyProcessIdentifierForPathParam(
|
||||
processInstance.process_model_identifier
|
||||
)}/${processInstance.id}`;
|
||||
navigate(path);
|
||||
};
|
||||
|
||||
HttpService.makeCallToBackend({
|
||||
path: `/process-instances/find-by-id/${params.process_instance_id}`,
|
||||
successCallback: handleProcessInstanceNavigation,
|
||||
});
|
||||
}, [params.process_instance_id, navigate]);
|
||||
|
||||
return null;
|
||||
}
|
@ -21,6 +21,7 @@ import {
|
||||
StopOutline,
|
||||
TrashCan,
|
||||
Warning,
|
||||
Link as LinkIcon,
|
||||
} from '@carbon/icons-react';
|
||||
import {
|
||||
Accordion,
|
||||
@ -117,6 +118,8 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||
>(null);
|
||||
|
||||
const [selectedTabIndex, setSelectedTabIndex] = useState<number>(0);
|
||||
const [copiedShortLinkToClipboard, setCopiedShortLinkToClipboard] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const { addError, removeError } = useAPIError();
|
||||
const unModifiedProcessModelId = unModifyProcessIdentifierForPathParam(
|
||||
@ -151,12 +154,12 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||
|
||||
const navigateToProcessInstances = (_result: any) => {
|
||||
navigate(
|
||||
`/admin/process-instances?process_model_identifier=${unModifiedProcessModelId}`
|
||||
`/process-instances?process_model_identifier=${unModifiedProcessModelId}`
|
||||
);
|
||||
};
|
||||
|
||||
let processInstanceShowPageBaseUrl = `/admin/process-instances/for-me/${params.process_model_id}/${params.process_instance_id}`;
|
||||
const processInstanceShowPageBaseUrlAllVariant = `/admin/process-instances/${params.process_model_id}/${params.process_instance_id}`;
|
||||
let processInstanceShowPageBaseUrl = `/process-instances/for-me/${params.process_model_id}/${params.process_instance_id}`;
|
||||
const processInstanceShowPageBaseUrlAllVariant = `/process-instances/${params.process_model_id}/${params.process_instance_id}`;
|
||||
if (variant === 'all') {
|
||||
processInstanceShowPageBaseUrl = processInstanceShowPageBaseUrlAllVariant;
|
||||
}
|
||||
@ -427,7 +430,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||
<dd>
|
||||
<Link
|
||||
data-qa="go-to-current-diagram-process-model"
|
||||
to={`/admin/process-models/${modifyProcessIdentifierForPathParam(
|
||||
to={`/process-models/${modifyProcessIdentifierForPathParam(
|
||||
processInstance.process_model_with_diagram_identifier || ''
|
||||
)}`}
|
||||
>
|
||||
@ -475,6 +478,14 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||
);
|
||||
};
|
||||
|
||||
const copyProcessInstanceShortLink = () => {
|
||||
if (processInstance) {
|
||||
const piShortLink = `${window.location.origin}/i/${processInstance.id}`;
|
||||
navigator.clipboard.writeText(piShortLink);
|
||||
setCopiedShortLinkToClipboard(true);
|
||||
}
|
||||
};
|
||||
|
||||
const terminateButton = () => {
|
||||
if (
|
||||
processInstance &&
|
||||
@ -518,6 +529,19 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||
return <div />;
|
||||
};
|
||||
|
||||
const copyProcessInstanceShortLinkButton = () => {
|
||||
return (
|
||||
<Button
|
||||
onClick={copyProcessInstanceShortLink}
|
||||
kind="ghost"
|
||||
renderIcon={LinkIcon}
|
||||
iconDescription="Copy short link for sharing"
|
||||
hasIconOnly
|
||||
size="lg"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const resumeButton = () => {
|
||||
if (processInstance && processInstance.status === 'suspended') {
|
||||
return (
|
||||
@ -1314,6 +1338,7 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||
return null;
|
||||
}
|
||||
const elements = [];
|
||||
elements.push(copyProcessInstanceShortLinkButton());
|
||||
if (ability.can('POST', `${targetUris.processInstanceTerminatePath}`)) {
|
||||
elements.push(terminateButton());
|
||||
}
|
||||
@ -1326,6 +1351,20 @@ export default function ProcessInstanceShow({ variant }: OwnProps) {
|
||||
if (ability.can('DELETE', targetUris.processInstanceActionPath)) {
|
||||
elements.push(deleteButton());
|
||||
}
|
||||
let toast = null;
|
||||
if (copiedShortLinkToClipboard) {
|
||||
toast = (
|
||||
<Notification
|
||||
onClose={() => setCopiedShortLinkToClipboard(false)}
|
||||
type="success"
|
||||
title="Copied link to clipboard"
|
||||
timeout={3000}
|
||||
hideCloseButton
|
||||
withBottomMargin={false}
|
||||
/>
|
||||
);
|
||||
elements.push(toast);
|
||||
}
|
||||
return elements;
|
||||
};
|
||||
|
||||
|
@ -10,9 +10,9 @@ type OwnProps = {
|
||||
|
||||
export default function ProcessInterstitialPage({ variant }: OwnProps) {
|
||||
const params = useParams();
|
||||
let processInstanceShowPageUrl = `/admin/process-instances/for-me/${params.process_model_id}/${params.process_instance_id}`;
|
||||
let processInstanceShowPageUrl = `/process-instances/for-me/${params.process_model_id}/${params.process_instance_id}`;
|
||||
if (variant === 'all') {
|
||||
processInstanceShowPageUrl = `/admin/process-instances/${params.process_model_id}/${params.process_instance_id}`;
|
||||
processInstanceShowPageUrl = `/process-instances/${params.process_model_id}/${params.process_instance_id}`;
|
||||
}
|
||||
|
||||
return (
|
||||
|
@ -266,7 +266,7 @@ export default function ProcessModelEditDiagram() {
|
||||
const httpMethod = 'DELETE';
|
||||
|
||||
const navigateToProcessModelShow = (_httpResult: any) => {
|
||||
navigate(`/admin/process-models/${modifiedProcessModelId}`);
|
||||
navigate(`/process-models/${modifiedProcessModelId}`);
|
||||
};
|
||||
HttpService.makeCallToBackend({
|
||||
path: url,
|
||||
|
@ -20,7 +20,7 @@ export default function ProcessModelNewExperimental() {
|
||||
if ('id' in result) {
|
||||
const modifiedProcessModelPathFromResult =
|
||||
modifyProcessIdentifierForPathParam(result.id);
|
||||
navigate(`/admin/process-models/${modifiedProcessModelPathFromResult}`);
|
||||
navigate(`/process-models/${modifiedProcessModelPathFromResult}`);
|
||||
}
|
||||
};
|
||||
|
||||
|
30
spiffworkflow-frontend/src/routes/ProcessModelRoutes.tsx
Normal file
30
spiffworkflow-frontend/src/routes/ProcessModelRoutes.tsx
Normal file
@ -0,0 +1,30 @@
|
||||
import { Route, Routes } from 'react-router-dom';
|
||||
import JsonSchemaFormBuilder from './JsonSchemaFormBuilder';
|
||||
import ProcessModelEdit from './ProcessModelEdit';
|
||||
import ProcessModelNew from './ProcessModelNew';
|
||||
import ProcessModelNewExperimental from './ProcessModelNewExperimental';
|
||||
import ProcessModelShow from './ProcessModelShow';
|
||||
import ReactFormEditor from './ReactFormEditor';
|
||||
|
||||
export default function ProcessModelRoutes() {
|
||||
return (
|
||||
<Routes>
|
||||
<Route path=":process_group_id/new" element={<ProcessModelNew />} />
|
||||
<Route
|
||||
path=":process_group_id/new-e"
|
||||
element={<ProcessModelNewExperimental />}
|
||||
/>
|
||||
<Route path=":process_model_id" element={<ProcessModelShow />} />
|
||||
<Route path=":process_model_id/edit" element={<ProcessModelEdit />} />
|
||||
<Route path=":process_model_id/form" element={<ReactFormEditor />} />
|
||||
<Route
|
||||
path=":process_model_id/form/:file_name"
|
||||
element={<ReactFormEditor />}
|
||||
/>
|
||||
<Route
|
||||
path=":process_model_id/form-builder"
|
||||
element={<JsonSchemaFormBuilder />}
|
||||
/>
|
||||
</Routes>
|
||||
);
|
||||
}
|
@ -128,7 +128,7 @@ export default function ProcessModelShow() {
|
||||
onClose={() => setProcessInstance(null)}
|
||||
>
|
||||
<Link
|
||||
to={`/admin/process-instances/for-me/${modifiedProcessModelId}/${processInstance.id}`}
|
||||
to={`/process-instances/for-me/${modifiedProcessModelId}/${processInstance.id}`}
|
||||
data-qa="process-instance-show-link"
|
||||
>
|
||||
view
|
||||
@ -211,7 +211,7 @@ export default function ProcessModelShow() {
|
||||
return `/editor/process-models/${modifiedProcessModelId}/files/${processModelFile.name}`;
|
||||
}
|
||||
if (processModelFile.name.match(/\.(json|md)$/)) {
|
||||
return `/admin/process-models/${modifiedProcessModelId}/form/${processModelFile.name}`;
|
||||
return `/process-models/${modifiedProcessModelId}/form/${processModelFile.name}`;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@ -219,9 +219,7 @@ export default function ProcessModelShow() {
|
||||
|
||||
const navigateToProcessModels = (_result: any) => {
|
||||
navigate(
|
||||
`/admin/process-groups/${getGroupFromModifiedModelId(
|
||||
modifiedProcessModelId
|
||||
)}`
|
||||
`/process-groups/${getGroupFromModifiedModelId(modifiedProcessModelId)}`
|
||||
);
|
||||
};
|
||||
|
||||
@ -561,11 +559,11 @@ export default function ProcessModelShow() {
|
||||
);
|
||||
} else if (a.selectedItem.text === 'New JSON File') {
|
||||
navigate(
|
||||
`/admin/process-models/${modifiedProcessModelId}/form?file_ext=json`
|
||||
`/process-models/${modifiedProcessModelId}/form?file_ext=json`
|
||||
);
|
||||
} else if (a.selectedItem.text === 'New Markdown File') {
|
||||
navigate(
|
||||
`/admin/process-models/${modifiedProcessModelId}/form?file_ext=md`
|
||||
`/process-models/${modifiedProcessModelId}/form?file_ext=md`
|
||||
);
|
||||
} else {
|
||||
console.log('a.selectedItem.text', a.selectedItem.text);
|
||||
@ -760,7 +758,7 @@ export default function ProcessModelShow() {
|
||||
renderIcon={Edit}
|
||||
iconDescription="Edit Process Model"
|
||||
hasIconOnly
|
||||
href={`/admin/process-models/${modifiedProcessModelId}/edit`}
|
||||
href={`/process-models/${modifiedProcessModelId}/edit`}
|
||||
/>
|
||||
</Can>
|
||||
<Can I="DELETE" a={targetUris.processModelShowPath} ability={ability}>
|
||||
|
@ -111,7 +111,7 @@ export default function ReactFormEditor() {
|
||||
const fileNameWithExtension =
|
||||
defaultFileName ?? `${newFileName}.${fileExtension}`;
|
||||
navigate(
|
||||
`/admin/process-models/${modifiedProcessModelId}/form/${fileNameWithExtension}`
|
||||
`/process-models/${modifiedProcessModelId}/form/${fileNameWithExtension}`
|
||||
);
|
||||
}
|
||||
};
|
||||
@ -160,7 +160,7 @@ export default function ReactFormEditor() {
|
||||
const httpMethod = 'DELETE';
|
||||
|
||||
const navigateToProcessModelShow = (_httpResult: any) => {
|
||||
navigate(`/admin/process-models/${modifiedProcessModelId}`);
|
||||
navigate(`/process-models/${modifiedProcessModelId}`);
|
||||
};
|
||||
|
||||
HttpService.makeCallToBackend({
|
||||
@ -308,7 +308,7 @@ export default function ReactFormEditor() {
|
||||
<Button
|
||||
onClick={() =>
|
||||
navigate(
|
||||
`/admin/process-models/${params.process_model_id}/form-builder${formBuildFileParam}`
|
||||
`/process-models/${params.process_model_id}/form-builder${formBuildFileParam}`
|
||||
)
|
||||
}
|
||||
variant="danger"
|
||||
|
@ -36,7 +36,7 @@ export default function SecretList() {
|
||||
!ability.can('GET', targetUris.secretListPath) &&
|
||||
ability.can('GET', targetUris.authenticationListPath)
|
||||
) {
|
||||
navigate('/admin/configuration/authentications');
|
||||
navigate('/configuration/authentications');
|
||||
} else {
|
||||
const { page, perPage } = getPageInfoFromSearchParams(searchParams);
|
||||
HttpService.makeCallToBackend({
|
||||
@ -71,12 +71,12 @@ export default function SecretList() {
|
||||
return (
|
||||
<tr key={(row as any).key}>
|
||||
<td>
|
||||
<Link to={`/admin/configuration/secrets/${(row as any).key}`}>
|
||||
<Link to={`/configuration/secrets/${(row as any).key}`}>
|
||||
{(row as any).id}
|
||||
</Link>
|
||||
</td>
|
||||
<td>
|
||||
<Link to={`/admin/configuration/secrets/${(row as any).key}`}>
|
||||
<Link to={`/configuration/secrets/${(row as any).key}`}>
|
||||
{(row as any).key}
|
||||
</Link>
|
||||
</td>
|
||||
@ -125,7 +125,7 @@ export default function SecretList() {
|
||||
<div>
|
||||
<h1>Secrets</h1>
|
||||
{SecretsDisplayArea()}
|
||||
<Button href="/admin/configuration/secrets/new">Add a secret</Button>
|
||||
<Button href="/configuration/secrets/new">Add a secret</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@ -11,11 +11,11 @@ export default function SecretNew() {
|
||||
const navigate = useNavigate();
|
||||
|
||||
const navigateToSecret = (_result: any) => {
|
||||
navigate(`/admin/configuration/secrets/${key}`);
|
||||
navigate(`/configuration/secrets/${key}`);
|
||||
};
|
||||
|
||||
const navigateToSecrets = () => {
|
||||
navigate(`/admin/configuration/secrets`);
|
||||
navigate(`/configuration/secrets`);
|
||||
};
|
||||
|
||||
const addSecret = (event: any) => {
|
||||
|
@ -46,7 +46,7 @@ export default function SecretShow() {
|
||||
};
|
||||
|
||||
const navigateToSecrets = (_result: any) => {
|
||||
navigate(`/admin/configuration/secrets`);
|
||||
navigate(`/configuration/secrets`);
|
||||
};
|
||||
|
||||
const deleteSecret = () => {
|
||||
|
@ -54,7 +54,7 @@ export default function TaskShow() {
|
||||
setGuestConfirmationText('Thank you!');
|
||||
} else {
|
||||
navigate(
|
||||
`/admin/process-instances/for-me/${modifyProcessIdentifierForPathParam(
|
||||
`/process-instances/for-me/${modifyProcessIdentifierForPathParam(
|
||||
myTask.process_model_identifier
|
||||
)}/${myTask.process_instance_id}/interstitial`
|
||||
);
|
||||
@ -378,7 +378,7 @@ export default function TaskShow() {
|
||||
hotCrumbs={[
|
||||
[
|
||||
`Process Instance Id: ${params.process_instance_id}`,
|
||||
`/admin/process-instances/for-me/${modifyProcessIdentifierForPathParam(
|
||||
`/process-instances/for-me/${modifyProcessIdentifierForPathParam(
|
||||
basicTask.process_model_identifier
|
||||
)}/${params.process_instance_id}`,
|
||||
],
|
||||
|
@ -115,10 +115,6 @@ const loginIfNeeded = () => {
|
||||
}
|
||||
};
|
||||
|
||||
const hasRole = (_roles: string[]): boolean => {
|
||||
return isLoggedIn();
|
||||
};
|
||||
|
||||
const UserService = {
|
||||
authenticationDisabled,
|
||||
doLogin,
|
||||
@ -126,7 +122,6 @@ const UserService = {
|
||||
getAccessToken,
|
||||
getPreferredUsername,
|
||||
getUserEmail,
|
||||
hasRole,
|
||||
isLoggedIn,
|
||||
loginIfNeeded,
|
||||
onlyGuestTaskCompletion,
|
||||
|
Loading…
x
Reference in New Issue
Block a user