Skip to content
This repository has been archived by the owner on Jul 23, 2024. It is now read-only.

Commit

Permalink
Merge pull request #161 from parodos-dev/revert-160-dl/request-access…
Browse files Browse the repository at this point in the history
…-call

Revert "Add request access to a project"
  • Loading branch information
wKich committed Jun 9, 2023
2 parents 95ebe6a + eef3202 commit 1fcd4dd
Show file tree
Hide file tree
Showing 12 changed files with 109 additions and 278 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ export function usePollApi() {
const alertApi = useApi(alertApiRef);
const projectError = useStore(state => state.projectsError);
const fetchProjects = useStore(state => state.fetchProjects);
const fetchRequestAccessStatuses = useStore(
state => state.fetchRequestAccessStatuses,
);

useEffect(() => {
const error = notificationsError ?? projectError;
Expand Down Expand Up @@ -45,6 +42,5 @@ export function usePollApi() {
});

fetchProjects(fetch);
fetchRequestAccessStatuses(fetch);
}, pollingInterval);
}
67 changes: 6 additions & 61 deletions plugins/parodos/src/components/projects/ProjectsTable.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useEffect, useMemo, useRef, useState } from 'react';
import React, { useMemo, useRef, useState } from 'react';
import { LinkButton, Table, TableColumn } from '@backstage/core-components';
import FilterListIcon from '@material-ui/icons/FilterList';
import {
Expand All @@ -15,10 +15,6 @@ import {
import { AccessRole, Project } from '../../models/project';
import { getHumanReadableDate } from '../converters';
import { pluginRoutePrefix } from '../ParodosPage/navigationMap';
import { useRequestAccess } from './hooks/useRequestAccess';
import { useStore } from '../../stores/workflowStore/workflowStore';
import { WorkflowStatus } from '../../models/workflowTaskSchema';
import { errorApiRef, useApi } from '@backstage/core-plugin-api';

type ProjectsTableData = {
[K in Pick<Project, 'name' | 'createdBy' | 'createdDate' | 'accessRole'> &
Expand All @@ -45,8 +41,6 @@ const accessRoleMap: Record<AccessRoleFilter, string> = {
type AccessRoleMapKeys = keyof typeof accessRoleMap;

export function ProjectsTable({ projects }: { projects: Project[] }) {
const errorApi = useApi(errorApiRef);
const requestAccessStatuses = useStore(state => state.requestAccessStatuses);
const filterIconRef = useRef<HTMLButtonElement>(null);
const [openFilter, setOpenFilter] = useState(false);
const handleFilterToggle = () => setOpenFilter(prevOpen => !prevOpen);
Expand All @@ -57,13 +51,6 @@ export function ProjectsTable({ projects }: { projects: Project[] }) {

setOpenFilter(false);
};
const requestAccessStatusByProjectId = useMemo(() => {
const statuses: Record<string, WorkflowStatus['status']> = {};
Object.values(requestAccessStatuses).forEach(({ projectId, status }) => {
statuses[projectId] = status;
});
return statuses;
}, [requestAccessStatuses]);
const [search, setSearch] = useState('');
const [accessRoleFilter, setAccessRoleFilter] =
useState<AccessRoleFilter>('All');
Expand All @@ -83,17 +70,6 @@ export function ProjectsTable({ projects }: { projects: Project[] }) {
setAccessRoleFilter(filter);
};

const [{ error }, requestAccess] = useRequestAccess();

useEffect(() => {
if (error) {
// eslint-disable-next-line no-console
console.error(error);

errorApi.post(new Error('Start workflow failed'));
}
}, [errorApi, error]);

const tableData = useMemo(
() =>
projects
Expand Down Expand Up @@ -168,51 +144,20 @@ export function ProjectsTable({ projects }: { projects: Project[] }) {
data={tableData}
components={{
Cell: ({ columnDef, rowData }) => {
const hasAccess =
rowData.accessRole ||
requestAccessStatusByProjectId[rowData.id] === 'COMPLETED';

if (columnDef.field === 'accessRole') {
const isPendingAccess =
requestAccessStatusByProjectId[rowData.id] === 'IN_PROGRESS' ||
requestAccessStatusByProjectId[rowData.id] === 'PENDING';
const isFailedAccess =
requestAccessStatusByProjectId[rowData.id] === 'FAILED' ||
requestAccessStatusByProjectId[rowData.id] === 'REJECTED';
if (hasAccess) {
return (
<TableCell>{rowData.accessRole ?? 'Access granted'}</TableCell>
);
} else if (isPendingAccess) {
return (
<TableCell>
<Typography color="textSecondary" component="em">
Pending Access
</Typography>
</TableCell>
);
} else if (isFailedAccess) {
return (
<TableCell>
<Typography color="error">Access Failed/Reject</Typography>
</TableCell>
);
}
return (
return rowData.accessRole ? (
<TableCell>{rowData.accessRole}</TableCell>
) : (
<TableCell>
<LinkButton
color="primary"
to="#"
onClick={() => requestAccess(rowData.id)}
>
<LinkButton color="primary" to="#">
Request Access
</LinkButton>
</TableCell>
);
} else if (columnDef.field === 'view') {
return (
<TableCell>
{hasAccess && (
{rowData.accessRole && (
<LinkButton
color="primary"
to={`${pluginRoutePrefix}/workflows?project=${rowData.id}`}
Expand Down
29 changes: 0 additions & 29 deletions plugins/parodos/src/components/projects/hooks/useRequestAccess.ts

This file was deleted.

4 changes: 2 additions & 2 deletions plugins/parodos/src/components/workflow/Workflow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ export function Workflow(): JSX.Element {
const formSchema = useGetProjectAssessmentSchema();

const [{ error: createWorkflowError, loading: _ }, createWorkflow] =
useCreateWorkflow(assessment);
useCreateWorkflow({ assessment });

const [{ error: startAssessmentError }, startAssessment] = useAsyncFn(
async ({ formData }: IChangeEvent<Record<string, ProjectsPayload>>) => {
Expand All @@ -66,7 +66,7 @@ export function Workflow(): JSX.Element {
setAssessmentStatus('inprogress');

setWorkflowOptions(
await createWorkflow({ projectId: selectedProject.id, formData }),
await createWorkflow({ project: selectedProject, formData }),
);

setAssessmentStatus('complete');
Expand Down
54 changes: 40 additions & 14 deletions plugins/parodos/src/components/workflow/hooks/useCreateWorkflow.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import useAsyncFn from 'react-use/lib/useAsyncFn';
import {
displayableWorkflowOptions,
workflowExecute,
WorkflowOptionItem,
} from '../../../models/workflow';
import * as urls from '../../../urls';
import { taskDisplayName } from '../../../utils/string';
import type { Project } from '../../../models/project';
import { type Project } from '../../../models/project';
import { useStore } from '../../../stores/workflowStore/workflowStore';
import { fetchApiRef, useApi } from '@backstage/core-plugin-api';
import { getWorkflowOptions } from './getWorkflowOptions';
import { pollWorkflowStatus } from './pollWorkflowStatus';
import {
ExecuteWorkflow,
useExecuteWorkflow,
} from '../../../hooks/useExecuteWorkflow';
import { fetchApiRef, useApi } from '@backstage/core-plugin-api';
import { getWorklfowsPayload } from './workflowsPayload';
import assert from 'assert-ts';

export type WorkflowOptionsListItem = WorkflowOptionItem & { type: string };

Expand All @@ -24,22 +23,49 @@ export interface ProjectsPayload {
project?: Project;
}

export function useCreateWorkflow(assessment: string) {
const { fetch } = useApi(fetchApiRef);
export function useCreateWorkflow({ assessment }: { assessment: string }) {
const workflowsUrl = useStore(state => state.getApiUrl(urls.Workflows));
const executeWorkflow = useExecuteWorkflow(assessment);
const assessmentWorkflow = useStore(state =>
state.getWorkDefinitionBy('byName', assessment),
);

assert(!!assessmentWorkflow, `no assessmentWorkflow found for ${assessment}`);

const { fetch } = useApi(fetchApiRef);

return useAsyncFn(
async (executionOptions: ExecuteWorkflow) => {
const { workFlowExecutionId } = await executeWorkflow(executionOptions);
async ({
project,
formData,
}: {
project: Project;
formData: Record<string, ProjectsPayload>;
}) => {
const payload = getWorklfowsPayload({
projectId: project.id,
workflow: assessmentWorkflow,
schema: formData,
});

// TODO: task here should be dynamic based on assessment workflow definition
const workFlowResponse = await fetch(workflowsUrl, {
method: 'POST',
body: JSON.stringify(payload),
});

if (!workFlowResponse.ok) {
throw new Error(workFlowResponse.statusText);
}

const workflow = workflowExecute.parse(await workFlowResponse.json());

await pollWorkflowStatus(fetch, {
workflowsUrl,
executionId: workFlowExecutionId,
executionId: workflow.workFlowExecutionId,
});
const workflowOptions = await getWorkflowOptions(fetch, {
workflowsUrl,
executionId: workFlowExecutionId,
executionId: workflow.workFlowExecutionId,
});

const options = displayableWorkflowOptions.flatMap(option => {
Expand All @@ -59,6 +85,6 @@ export function useCreateWorkflow(assessment: string) {

return options;
},
[fetch, executeWorkflow, workflowsUrl],
[assessmentWorkflow, fetch, workflowsUrl],
);
}
34 changes: 26 additions & 8 deletions plugins/parodos/src/components/workflow/hooks/useStartWorkflow.ts
Original file line number Diff line number Diff line change
@@ -1,37 +1,55 @@
import { fetchApiRef, useApi } from '@backstage/core-plugin-api';
import { IChangeEvent } from '@rjsf/core-v5';
import { type StrictRJSFSchema } from '@rjsf/utils';
import { useNavigate } from 'react-router-dom';
import useAsyncFn, { type AsyncFnReturn } from 'react-use/lib/useAsyncFn';
import { useExecuteWorkflow } from '../../../hooks/useExecuteWorkflow';
import { WorkflowDefinition } from '../../../models/workflowDefinitionSchema';
import { WorkflowStatus } from '../../../models/workflowTaskSchema';
import { getWorklfowsPayload } from './workflowsPayload';

interface UseStartWorkflow {
workflowName: string;
workflowsUrl: string;
workflow: WorkflowDefinition;
projectId: string;
isNew: boolean;
}

export function useStartWorkflow({
workflowName,
workflowsUrl,
workflow,
projectId,
isNew,
}: UseStartWorkflow): AsyncFnReturn<(e?: IChangeEvent) => Promise<void>> {
const { fetch } = useApi(fetchApiRef);
const navigate = useNavigate();
const executeWorkflow = useExecuteWorkflow(workflowName);

return useAsyncFn(
async ({ formData = {} } = {} as IChangeEvent<StrictRJSFSchema>) => {
const { workFlowExecutionId } = await executeWorkflow({
const payload = getWorklfowsPayload({
projectId,
formData,
workflow,
schema: formData,
});

const data = await fetch(workflowsUrl, {
method: 'POST',
body: JSON.stringify(payload),
});

if (!data.ok) {
throw new Error(`${data.status} - ${data.statusText}`);
}

const response = (await data.json()) as WorkflowStatus;
const executionId = response.workFlowExecutionId;

navigate(
`/parodos/onboarding/${projectId}/${workFlowExecutionId}/workflow-detail`,
`/parodos/onboarding/${projectId}/${executionId}/workflow-detail`,
{
state: { isNew },
},
);
},
[projectId, navigate, isNew, executeWorkflow],
[projectId, workflow, fetch, workflowsUrl, navigate, isNew],
);
}
Loading

0 comments on commit 1fcd4dd

Please sign in to comment.