Skip to content

Commit

Permalink
Enhancement: Moving pagination, sorting and filtering of workflow run…
Browse files Browse the repository at this point in the history
…s table to the backend (#2829)

* added pagination for QueryWorkflowRuns

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* filtering workflowRuns based on workflowRunIDs

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* changed the API for getWorkflowRuns in frontend

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* added pagination for frontend and refactored code to accomodate the changes

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* Added Sorting and Filtering

Signed-off-by: SarthakJain26 <sarthak@chaosnative.com>

* sorting added from backend api call

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* filtering removed from frontend and used backend APIs to filter data

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* typed execution data in backend and sent common metadata from execution data in workflowruns hence reducing the data size in frontend; sorting based on workflowrun phase done in backend

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* changing resiliency score to null in case of running workflows

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* WIP: filtering and sorting done, pagination remaining

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* pagination completed in database

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* reverted ID -> String changes

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* changed the sortStage

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* Added condition to check no workflows

Signed-off-by: SarthakJain26 <sarthak@chaosnative.com>

* Pagination bug fix (#1)

* bug fix trails #1

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* reverting local dev changes

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* fixed the workflow subscription bugs...EVERYTHING FINALLY WORKS

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* removed comments from config

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* resolved review comments: translations, formatting and removing binary file

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* fixed some bugs and added Execution data to types.go

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

* go fmt project

Signed-off-by: arkajyotiMukherjee <arko@chaosnative.com>

Co-authored-by: SarthakJain26 <sarthak@chaosnative.com>
  • Loading branch information
arkajyotiMukherjee and SarthakJain26 committed Jun 7, 2021
1 parent c77e5d2 commit aa5fe68
Show file tree
Hide file tree
Showing 26 changed files with 1,740 additions and 639 deletions.
1 change: 1 addition & 0 deletions litmus-portal/frontend/public/locales/en/translation.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -416,6 +416,7 @@ chaosWorkflows:
browseWorkflows:
status: Status
name: Name
dateFilterHelperText: Select a period
targetAgent: Target Agent
reliabilityDetails: Reliability Details
experiments: Experiments
Expand Down
52 changes: 41 additions & 11 deletions litmus-portal/frontend/src/graphql/queries.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,39 @@
import { gql } from '@apollo/client';

export const WORKFLOW_DETAILS_WITH_EXEC_DATA = gql`
query workflowDetails($workflowRunsInput: GetWorkflowRunsInput!) {
getWorkflowRuns(workflowRunsInput: $workflowRunsInput) {
total_no_of_workflow_runs
workflow_runs {
workflow_id
workflow_name
workflow_run_id
cluster_name
last_updated
cluster_id
phase
execution_data
resiliency_score
}
}
}
`;

export const WORKFLOW_DETAILS = gql`
query workflowDetails($projectID: String!) {
getWorkFlowRuns(project_id: $projectID) {
workflow_id
workflow_name
workflow_run_id
execution_data
project_id
cluster_name
last_updated
cluster_type
cluster_id
query workflowDetails($workflowRunsInput: GetWorkflowRunsInput!) {
getWorkflowRuns(workflowRunsInput: $workflowRunsInput) {
total_no_of_workflow_runs
workflow_runs {
workflow_id
workflow_name
workflow_run_id
cluster_name
last_updated
phase
resiliency_score
experiments_passed
total_experiments
}
}
}
`;
Expand Down Expand Up @@ -150,6 +172,14 @@ export const GET_CLUSTER_LENGTH = gql`
}
`;

export const GET_CLUSTER_NAMES = gql`
query getClusters($project_id: String!) {
getCluster(project_id: $project_id) {
cluster_name
}
}
`;

export const ALL_USERS = gql`
query allUsers {
users {
Expand Down
23 changes: 20 additions & 3 deletions litmus-portal/frontend/src/graphql/subscriptions.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,33 @@
import { gql } from '@apollo/client';

export const WORKFLOW_EVENTS = gql`
export const WORKFLOW_EVENTS_WITH_EXEC_DATA = gql`
subscription workflowEvents($projectID: String!) {
workflowEventListener(project_id: $projectID) {
workflow_id
workflow_name
workflow_run_id
execution_data
project_id
cluster_name
last_updated
cluster_id
phase
execution_data
resiliency_score
}
}
`;

export const WORKFLOW_EVENTS = gql`
subscription workflowEvents($projectID: String!) {
workflowEventListener(project_id: $projectID) {
workflow_id
workflow_name
workflow_run_id
cluster_name
last_updated
phase
resiliency_score
experiments_passed
total_experiments
}
}
`;
Expand Down
55 changes: 53 additions & 2 deletions litmus-portal/frontend/src/models/graphql/workflowData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,16 +53,67 @@ export interface WorkflowRun {
workflow_run_id: string;
cluster_type: string;
cluster_id: string;
phase: string;
resiliency_score?: number;
experiments_passed?: number;
total_experiments?: number;
}

interface GetWorkflowRunsOutput {
total_no_of_workflow_runs: number;
workflow_runs: WorkflowRun[];
}

export interface Workflow {
getWorkFlowRuns: WorkflowRun[];
getWorkflowRuns: GetWorkflowRunsOutput;
}

export interface WorkflowSubscription {
workflowEventListener: WorkflowRun;
}

export interface WorkflowDataVars {
export interface WorkflowSubscriptionInput {
projectID: string;
}

// Pagination
export interface Pagination {
page: number;
limit: number;
}

// Sort
export interface SortInput {
field: 'Name' | 'Time';
descending?: boolean;
}

// Filter
interface DateRange {
start_date: string;
end_date?: string;
}

export type WorkflowStatus =
| 'All'
| 'Failed'
| 'Running'
| 'Succeeded'
| undefined;

export interface WorkflowRunFilterInput {
workflow_name?: string;
cluster_name?: string;
workflow_status?: WorkflowStatus;
date_range?: DateRange;
}

export interface WorkflowDataVars {
workflowRunsInput: {
project_id: string;
workflow_run_ids?: string[];
pagination?: Pagination;
sort?: SortInput;
filter?: WorkflowRunFilterInput;
};
}
77 changes: 43 additions & 34 deletions litmus-portal/frontend/src/pages/WorkflowDetails/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@ import Tabs from '@material-ui/core/Tabs/Tabs';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { useSelector } from 'react-redux';
import { useLocation } from 'react-router-dom';
import { useParams } from 'react-router-dom';
import BackButton from '../../components/Button/BackButton';
import Loader from '../../components/Loader';
import { StyledTab, TabPanel } from '../../components/Tabs';
import Scaffold from '../../containers/layouts/Scaffold';
import {
SCHEDULE_DETAILS,
WORKFLOW_DETAILS,
WORKFLOW_EVENTS,
WORKFLOW_DETAILS_WITH_EXEC_DATA,
WORKFLOW_EVENTS_WITH_EXEC_DATA,
} from '../../graphql';
import {
ScheduleDataVars,
Expand All @@ -24,6 +24,7 @@ import {
Workflow,
WorkflowDataVars,
WorkflowSubscription,
WorkflowSubscriptionInput,
} from '../../models/graphql/workflowData';
import useActions from '../../redux/actions';
import * as NodeSelectionActions from '../../redux/actions/nodeSelection';
Expand All @@ -37,6 +38,10 @@ import WorkflowNodeInfo from '../../views/WorkflowDetails/WorkflowNodeInfo';
import NodeTable from '../../views/WorkflowDetails/WorkflowTable';
import useStyles from './styles';

interface URLParams {
workflowRunId: string;
}

const WorkflowDetails: React.FC = () => {
const theme = useTheme();
const { t } = useTranslation();
Expand All @@ -62,19 +67,23 @@ const WorkflowDetails: React.FC = () => {

const { pod_name } = useSelector((state: RootState) => state.selectedNode);

// Getting the workflow nome from the pathname
const { pathname } = useLocation();
const workflowRunId = pathname.split('/')[2];
const { workflowRunId }: URLParams = useParams();

// Query to get workflows
const { subscribeToMore, data, error } = useQuery<Workflow, WorkflowDataVars>(
WORKFLOW_DETAILS,
{ variables: { projectID } }
WORKFLOW_DETAILS_WITH_EXEC_DATA,
{
variables: {
workflowRunsInput: {
project_id: projectID,
workflow_run_ids: [workflowRunId],
},
},
fetchPolicy: 'cache-and-network',
}
);

const workflow = data?.getWorkFlowRuns.filter(
(w) => w.workflow_run_id === workflowRunId
)[0];
const workflow = data?.getWorkflowRuns.workflow_runs[0];

// Apollo query to get the scheduled data
const { data: SchedulesData, loading } = useQuery<
Expand All @@ -87,34 +96,32 @@ const WorkflowDetails: React.FC = () => {

// Using subscription to get realtime data
useEffect(() => {
if (
workflow?.execution_data &&
(JSON.parse(workflow?.execution_data) as ExecutionData).phase ===
'Running'
) {
subscribeToMore<WorkflowSubscription>({
document: WORKFLOW_EVENTS,
if (workflow?.phase && workflow.phase === 'Running') {
subscribeToMore<WorkflowSubscription, WorkflowSubscriptionInput>({
document: WORKFLOW_EVENTS_WITH_EXEC_DATA,
variables: { projectID },
updateQuery: (prev, { subscriptionData }) => {
if (!subscriptionData.data) return prev;
const modifiedWorkflows = prev.getWorkFlowRuns.slice();
if (!subscriptionData.data || !prev || !prev.getWorkflowRuns)
return prev;

const modifiedWorkflows = prev.getWorkflowRuns.workflow_runs.slice();
const newWorkflow = subscriptionData.data.workflowEventListener;

// Updating the query data
let i = 0;
for (; i < modifiedWorkflows.length; i++) {
if (
modifiedWorkflows[i].workflow_run_id ===
newWorkflow.workflow_run_id
) {
modifiedWorkflows[i] = newWorkflow;
break;
}
}
if (i === modifiedWorkflows.length)
modifiedWorkflows.unshift(newWorkflow);
// Update only the required workflowRun
if (
modifiedWorkflows[0].workflow_run_id === newWorkflow.workflow_run_id
)
modifiedWorkflows[0] = newWorkflow;

const totalNoOfWorkflows =
prev.getWorkflowRuns.total_no_of_workflow_runs;

return { ...prev, getWorkFlowRuns: modifiedWorkflows };
return {
getWorkflowRuns: {
total_no_of_workflow_runs: totalNoOfWorkflows,
workflow_runs: modifiedWorkflows,
},
};
},
});
}
Expand Down Expand Up @@ -233,6 +240,7 @@ const WorkflowDetails: React.FC = () => {
data={
JSON.parse(workflow.execution_data) as ExecutionData
}
resiliency_score={workflow.resiliency_score}
/>
)}
</div>
Expand All @@ -245,6 +253,7 @@ const WorkflowDetails: React.FC = () => {
tab={2}
cluster_name={workflow.cluster_name}
data={JSON.parse(workflow.execution_data) as ExecutionData}
resiliency_score={workflow.resiliency_score}
/>
{/* Table for all Node details */}
<NodeTable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,16 @@ import React, { useState } from 'react';
import { DateRangePicker } from 'react-date-range';
import 'react-date-range/dist/styles.css'; // main css file
import 'react-date-range/dist/theme/default.css'; // theme css file
import { Workflow, WorkflowRun } from '../../../models/graphql/workflowData';
import { Clusters } from '../../../models/graphql/clusterData';
import { WorkflowStatus } from '../../../models/graphql/workflowData';
import useStyles from './styles';

interface HeaderSectionProps {
searchValue: string;
statusValue: string;
clusterValue: string;
searchValue?: string;
statusValue?: WorkflowStatus;
clusterValue?: string;
isOpen: boolean;
data: Workflow | undefined;
getClusters: (wfdata: WorkflowRun[]) => string[];
clusterList?: Partial<Clusters>;
isDateOpen: boolean;
popAnchorEl: HTMLElement | null;
displayDate: string;
Expand Down Expand Up @@ -62,10 +62,9 @@ const HeaderSection: React.FC<HeaderSectionProps> = ({
statusValue,
clusterValue,
isOpen,
data,
popAnchorEl,
displayDate,
getClusters,
clusterList,
changeSearch,
changeStatus,
changeCluster,
Expand All @@ -82,6 +81,7 @@ const HeaderSection: React.FC<HeaderSectionProps> = ({
key: 'selection',
},
]);

return (
<div>
<div className={classes.headerSection}>
Expand Down Expand Up @@ -127,13 +127,11 @@ const HeaderSection: React.FC<HeaderSectionProps> = ({
className={classes.selectText}
>
<MenuItem value="All">All</MenuItem>
{(data ? getClusters(data.getWorkFlowRuns) : []).map(
(cluster: string) => (
<MenuItem key={cluster} value={cluster}>
{cluster}
</MenuItem>
)
)}
{clusterList?.getCluster?.map((cluster) => (
<MenuItem key={cluster.cluster_name} value={cluster.cluster_name}>
{cluster.cluster_name}
</MenuItem>
))}
</Select>
</FormControl>

Expand Down
Loading

0 comments on commit aa5fe68

Please sign in to comment.