Skip to content

Commit

Permalink
Orchestrator: Workflow runs (#166)
Browse files Browse the repository at this point in the history
* feat(orchestrator): add workflow runs tab

* fix filter

* v1

Signed-off-by: Lior Soffer <[email protected]>

* fix

Signed-off-by: Lior Soffer <[email protected]>

* fixes

Signed-off-by: Lior Soffer <[email protected]>

* show full ID

Signed-off-by: Lior Soffer <[email protected]>

* fix type

Signed-off-by: Lior Soffer <[email protected]>

---------

Signed-off-by: Lior Soffer <[email protected]>
  • Loading branch information
LiorSoffer authored Dec 18, 2024
1 parent 4cf968f commit f3ace9e
Show file tree
Hide file tree
Showing 12 changed files with 305 additions and 170 deletions.
5 changes: 5 additions & 0 deletions workspaces/orchestrator/.changeset/yellow-poets-fold.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@red-hat-developer-hub/backstage-plugin-orchestrator': patch
---

add workflow tabs - details and runs
Original file line number Diff line number Diff line change
Expand Up @@ -18,30 +18,28 @@ import { Route, Routes } from 'react-router-dom';

import {
executeWorkflowRouteRef,
workflowDefinitionsRouteRef,
workflowInstanceRouteRef,
workflowRouteRef,
} from '../routes';
import { ExecuteWorkflowPage } from './ExecuteWorkflowPage/ExecuteWorkflowPage';
import { OrchestratorPage } from './OrchestratorPage';
import { WorkflowDefinitionViewerPage } from './WorkflowDefinitionViewerPage';
import { WorkflowInstancePage } from './WorkflowInstancePage';
import { WorkflowPage } from './WorkflowPage';

export const Router = () => {
return (
// relative to orchestrator/
<Routes>
<Route path="/*" element={<OrchestratorPage />} />
<Route
path={workflowInstanceRouteRef.path}
element={<WorkflowInstancePage />}
/>
<Route
path={workflowDefinitionsRouteRef.path}
element={<WorkflowDefinitionViewerPage />}
/>
<Route path={`${workflowRouteRef.path}/*`} element={<WorkflowPage />} />
<Route
path={executeWorkflowRouteRef.path}
element={<ExecuteWorkflowPage />}
/>
<Route
path={workflowInstanceRouteRef.path}
element={<WorkflowInstancePage />}
/>
</Routes>
);
};

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ import {
} from '@red-hat-developer-hub/backstage-plugin-orchestrator-common';

import { orchestratorApiRef } from '../../api';
import { workflowDefinitionsRouteRef } from '../../routes';
import { workflowRouteRef } from '../../routes';
import { WorkflowEditorLanguageService } from './channel/WorkflowEditorLanguageService';
import { WorkflowEditorLanguageServiceChannelApiImpl } from './channel/WorkflowEditorLanguageServiceChannelApiImpl';

Expand Down Expand Up @@ -111,7 +111,7 @@ const RefForwardingWorkflowEditor: ForwardRefRenderFunction<
const [canRender, setCanRender] = useState(false);
const [ready, setReady] = useState(false);
const navigate = useNavigate();
const viewWorkflowLink = useRouteRef(workflowDefinitionsRouteRef);
const viewWorkflowLink = useRouteRef(workflowRouteRef);

const currentProcessInstance = useMemo(() => {
if (kind !== EditorViewKind.RUNTIME) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import React, { useMemo } from 'react';

import { InfoCard } from '@backstage/core-components';
import { useRouteRefParams } from '@backstage/core-plugin-api';

import { Grid } from '@material-ui/core';

import { WorkflowOverviewDTO } from '@red-hat-developer-hub/backstage-plugin-orchestrator-common';

import { workflowRouteRef } from '../../routes';
import { EditorViewKind, WorkflowEditor } from '../WorkflowEditor';
import WorkflowDefinitionDetailsCard from './WorkflowDetailsCard';

interface Props {
loading: boolean;
workflowOverviewDTO: WorkflowOverviewDTO | undefined;
}

export const WorkflowDetailsTabContent = ({
loading,
workflowOverviewDTO,
}: Props) => {
const { workflowId, format } = useRouteRefParams(workflowRouteRef);
const workflowFormat = useMemo(
() => (format === 'json' ? 'json' : 'yaml'),
[format],
);

return (
<>
<Grid item>
<WorkflowDefinitionDetailsCard
workflowOverview={workflowOverviewDTO}
loading={loading}
/>
</Grid>
<Grid item>
<InfoCard title="Workflow definition">
<div style={{ height: '600px' }}>
<WorkflowEditor
kind={EditorViewKind.EXTENDED_DIAGRAM_VIEWER}
workflowId={workflowId}
format={workflowFormat}
/>
</div>
</InfoCard>
</Grid>
</>
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
/*
* Copyright 2024 The Backstage Authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/

import React from 'react';
import { useAsync } from 'react-use';

import { TabbedLayout } from '@backstage/core-components';
import { useApi, useRouteRefParams } from '@backstage/core-plugin-api';

import {
orchestratorWorkflowUsePermission,
orchestratorWorkflowUseSpecificPermission,
} from '@red-hat-developer-hub/backstage-plugin-orchestrator-common';

import { orchestratorApiRef } from '../../api';
import { usePermissionArrayDecision } from '../../hooks/usePermissionArray';
import { workflowRouteRef, workflowRunsRoutePath } from '../../routes';
import { BaseOrchestratorPage } from '../BaseOrchestratorPage';
import { WorkflowRunsTabContent } from '../WorkflowRunsTabContent';
import { WorkflowDetailsTabContent } from './WorkflowDetailsTabContent';
import { WorkflowPageTabContent } from './WorkflowPageTabContent';

export const WorkflowPage = () => {
const { workflowId } = useRouteRefParams(workflowRouteRef);
const orchestratorApi = useApi(orchestratorApiRef);

const { loading: loadingPermission, allowed: canRun } =
usePermissionArrayDecision([
orchestratorWorkflowUsePermission,
orchestratorWorkflowUseSpecificPermission(workflowId),
]);

const {
value: workflowOverviewDTO,
loading,
error,
} = useAsync(() => {
return orchestratorApi.getWorkflowOverview(workflowId);
}, []);

return (
<BaseOrchestratorPage
title={workflowOverviewDTO?.data.name || workflowId}
type="Workflows"
typeLink="/orchestrator"
noPadding
>
<TabbedLayout>
<TabbedLayout.Route path="/" title="Workflow details">
<WorkflowPageTabContent
error={error}
loadingPermission={loadingPermission}
loading={loading}
canRun={canRun}
>
<WorkflowDetailsTabContent
loading={loading}
workflowOverviewDTO={workflowOverviewDTO?.data}
/>
</WorkflowPageTabContent>
</TabbedLayout.Route>
<TabbedLayout.Route path={workflowRunsRoutePath} title="Workflow runs">
<WorkflowPageTabContent
error={error}
loadingPermission={loadingPermission}
loading={loading}
canRun={canRun}
>
<WorkflowRunsTabContent />
</WorkflowPageTabContent>
</TabbedLayout.Route>
</TabbedLayout>
</BaseOrchestratorPage>
);
};
Loading

0 comments on commit f3ace9e

Please sign in to comment.