diff --git a/litmus-portal/frontend/public/icons/error-upload.svg b/litmus-portal/frontend/public/icons/error-upload.svg new file mode 100644 index 000000000..c6da80902 --- /dev/null +++ b/litmus-portal/frontend/public/icons/error-upload.svg @@ -0,0 +1,4 @@ + + + + diff --git a/litmus-portal/frontend/public/icons/retry.svg b/litmus-portal/frontend/public/icons/retry.svg new file mode 100644 index 000000000..fa7d07964 --- /dev/null +++ b/litmus-portal/frontend/public/icons/retry.svg @@ -0,0 +1,3 @@ + + + diff --git a/litmus-portal/frontend/public/icons/sync-wf.svg b/litmus-portal/frontend/public/icons/sync-wf.svg new file mode 100644 index 000000000..19b987358 --- /dev/null +++ b/litmus-portal/frontend/public/icons/sync-wf.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/litmus-portal/frontend/public/icons/terminate-wf.svg b/litmus-portal/frontend/public/icons/terminate-wf.svg new file mode 100644 index 000000000..e9019f415 --- /dev/null +++ b/litmus-portal/frontend/public/icons/terminate-wf.svg @@ -0,0 +1,11 @@ + + + + + + + + + + + diff --git a/litmus-portal/frontend/public/icons/warning.svg b/litmus-portal/frontend/public/icons/warning.svg new file mode 100644 index 000000000..d11bab8b7 --- /dev/null +++ b/litmus-portal/frontend/public/icons/warning.svg @@ -0,0 +1,3 @@ + + + diff --git a/litmus-portal/frontend/public/locales/en/translation.yaml b/litmus-portal/frontend/public/locales/en/translation.yaml index 944bb1ad9..314a8097d 100644 --- a/litmus-portal/frontend/public/locales/en/translation.yaml +++ b/litmus-portal/frontend/public/locales/en/translation.yaml @@ -421,6 +421,11 @@ chaosWorkflows: reliabilityDetails: Reliability Details experiments: Experiments lastRun: Last Run + wfIssue: Seems like there has been some issue in workflow. + runningFrom: Running from last + min: mins. + sync: Sync Workflow + terminate: Terminate Workflow tableData: overallRR: 'Overall RR : ' experimentsPassed: 'Experiments Passed : ' @@ -1075,9 +1080,11 @@ myhub: syncingRepo: Loading Charts, Please Wait...! preDefined: Pre-defined workflows chaosCharts: Chaos-charts - noExp: No predefined workflows available with information in this Hub + noPredefinedExp: No predefined workflows available with information in this Hub + noExp: No experiments found lastSynced: 'Last synced at: ' repoLink: 'Repository Link: ' + repoBranch: 'Repository Branch: ' connectHubPage: connectHub: Connect a new chaos hub editHub: Edit hub configuration @@ -1145,6 +1152,8 @@ customWorkflow: upload: Upload your yaml: YAML uploadFile: Select YAML file from your device + errorUpload: Error while uploading YAML + retryUpload: Retry Upload uploadSuccess: Successfully uploaded drag: Drag & Drop YAML file to upload chooseExp: Choose the experiment diff --git a/litmus-portal/frontend/src/graphql/mutations.ts b/litmus-portal/frontend/src/graphql/mutations.ts index 705389af1..bf274dc77 100644 --- a/litmus-portal/frontend/src/graphql/mutations.ts +++ b/litmus-portal/frontend/src/graphql/mutations.ts @@ -89,12 +89,6 @@ export const DECLINE_INVITE = gql` } `; -export const DELETE_SCHEDULE = gql` - mutation deleteWorkflow($workflow_id: String!) { - deleteChaosWorkflow(workflowid: $workflow_id) - } -`; - export const UPDATE_SCHEDULE = gql` mutation updateChaos($ChaosWorkFlowInput: ChaosWorkFlowInput!) { updateChaosWorkflow(input: $ChaosWorkFlowInput) { @@ -323,3 +317,18 @@ export const UPDATE_IMAGE_REGISTRY = gql` } } `; + +export const SYNC_WORKFLOW = gql` + mutation syncWorkflow($workflowid: String!, $workflow_run_id: String!) { + syncWorkflow(workflowid: $workflowid, workflow_run_id: $workflow_run_id) + } +`; + +export const DELETE_WORKFLOW = gql` + mutation deleteWorkflow($workflowid: String!, $workflow_run_id: String!) { + deleteChaosWorkflow( + workflowid: $workflowid + workflow_run_id: $workflow_run_id + ) + } +`; diff --git a/litmus-portal/frontend/src/graphql/queries.ts b/litmus-portal/frontend/src/graphql/queries.ts index 24d1a73bc..3aa5b0428 100644 --- a/litmus-portal/frontend/src/graphql/queries.ts +++ b/litmus-portal/frontend/src/graphql/queries.ts @@ -14,6 +14,7 @@ export const WORKFLOW_DETAILS_WITH_EXEC_DATA = gql` phase execution_data resiliency_score + isRemoved } } } @@ -33,6 +34,7 @@ export const WORKFLOW_DETAILS = gql` resiliency_score experiments_passed total_experiments + isRemoved } } } diff --git a/litmus-portal/frontend/src/models/graphql/workflowData.ts b/litmus-portal/frontend/src/models/graphql/workflowData.ts index edec375f0..a7a9d15c0 100644 --- a/litmus-portal/frontend/src/models/graphql/workflowData.ts +++ b/litmus-portal/frontend/src/models/graphql/workflowData.ts @@ -57,6 +57,7 @@ export interface WorkflowRun { resiliency_score?: number; experiments_passed?: number; total_experiments?: number; + isRemoved: boolean; } interface GetWorkflowRunsOutput { @@ -106,6 +107,7 @@ export interface WorkflowRunFilterInput { cluster_name?: string; workflow_status?: WorkflowStatus; date_range?: DateRange; + isRemoved?: boolean | null; } export interface WorkflowDataVars { diff --git a/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseSchedule/index.tsx b/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseSchedule/index.tsx index cb4a3b269..c58c8f8fb 100644 --- a/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseSchedule/index.tsx +++ b/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseSchedule/index.tsx @@ -25,7 +25,7 @@ import { useTranslation } from 'react-i18next'; import YAML from 'yaml'; import Loader from '../../../components/Loader'; import { - DELETE_SCHEDULE, + DELETE_WORKFLOW, SCHEDULE_DETAILS, UPDATE_SCHEDULE, } from '../../../graphql'; @@ -75,7 +75,7 @@ const BrowseSchedule: React.FC = () => { ); // Apollo mutation to delete the selected schedule - const [deleteSchedule] = useMutation(DELETE_SCHEDULE, { + const [deleteSchedule] = useMutation(DELETE_WORKFLOW, { refetchQueries: [{ query: SCHEDULE_DETAILS, variables: { projectID } }], }); @@ -188,7 +188,7 @@ const BrowseSchedule: React.FC = () => { const deleteRow = (wfid: string) => { deleteSchedule({ - variables: { workflow_id: wfid }, + variables: { workflowid: wfid, workflow_run_id: '' }, }); }; return ( diff --git a/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/TableData.tsx b/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/TableData.tsx index 1bcd1b287..6b6bc0b9a 100644 --- a/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/TableData.tsx +++ b/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/TableData.tsx @@ -1,4 +1,4 @@ -import { useQuery } from '@apollo/client'; +import { useMutation, useQuery } from '@apollo/client'; import { Button, IconButton, @@ -11,10 +11,15 @@ import { import ChevronRightIcon from '@material-ui/icons/ChevronRight'; import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown'; import MoreVertIcon from '@material-ui/icons/MoreVert'; +import { ButtonFilled } from 'litmus-ui'; import React from 'react'; import { useTranslation } from 'react-i18next'; import TimePopOver from '../../../components/TimePopOver'; -import { WORKFLOW_LIST_DETAILS } from '../../../graphql'; +import { + DELETE_WORKFLOW, + SYNC_WORKFLOW, + WORKFLOW_LIST_DETAILS, +} from '../../../graphql'; import { WorkflowRun } from '../../../models/graphql/workflowData'; import { WorkflowList, @@ -30,21 +35,20 @@ import useStyles from './styles'; interface TableDataProps { data: Partial; + refetchQuery: any; } -const TableData: React.FC = ({ data }) => { +const TableData: React.FC = ({ data, refetchQuery }) => { const classes = useStyles(); const projectID = getProjectID(); const projectRole = getProjectRole(); const { t } = useTranslation(); - const [anchorEl, setAnchorEl] = React.useState(null); const open = Boolean(anchorEl); const nodeSelection = useActions(NodeSelectionActions); const handleClick = (event: React.MouseEvent) => { setAnchorEl(event.currentTarget); }; - const handleClose = () => { setAnchorEl(null); }; @@ -79,6 +83,44 @@ const TableData: React.FC = ({ data }) => { setPopAnchorEl(event.currentTarget); }; + /** + * State variables for warning popover + */ + const [popWarningAnchorEl, setWarningPopAnchorEl] = + React.useState(null); + const isWarningOpen = Boolean(popWarningAnchorEl); + const idWarning = isWarningOpen ? 'simple-popover' : undefined; + const handleWarningPopOverClose = () => { + setWarningPopAnchorEl(null); + }; + const handleWarningPopOverClick = (event: React.MouseEvent) => { + setWarningPopAnchorEl(event.currentTarget); + }; + + /** + * Sync workflow to sync a chaos workflow + */ + const [syncWorkflow] = useMutation(SYNC_WORKFLOW, { + onCompleted: (data) => { + if (data.syncWorkflow) { + handleWarningPopOverClose(); + refetchQuery(); + } + }, + }); + + /** + * Delete workflow mutation to delete a chaos workflow + */ + const [deleteWorkflow] = useMutation(DELETE_WORKFLOW, { + onCompleted: (data) => { + if (data.deleteChaosWorkflow) { + handleWarningPopOverClose(); + refetchQuery(); + } + }, + }); + function getResiliencyScoreColor(score: number) { if (score < 39) { return classes.less; @@ -89,9 +131,98 @@ const TableData: React.FC = ({ data }) => { return classes.high; } + // Function to find the time different in minutes + const timeDiff = (currentTime: number, lastUpdated: string) => { + const current = currentTime; + const last = parseInt(lastUpdated, 10) * 1000; + const timeDifference = (current - last) / (60 * 1000); + return timeDifference; + }; + return ( <> - + {/* Table cell for warning (if the workflow is in running state from 20 mins) */} + + {timeDiff(new Date().getTime(), data.last_updated ?? '') >= 20 && + data.phase?.toLowerCase() === 'running' ? ( + + warning + + ) : ( + <> + )} + {/* Warning PopOver */} + +
+ + {t('chaosWorkflows.browseWorkflows.wfIssue')} + +
+ running{' '} + + {t('chaosWorkflows.browseWorkflows.runningFrom')}{' '} + {Math.round( + timeDiff(new Date().getTime(), data.last_updated ?? '') + )}{' '} + {t('chaosWorkflows.browseWorkflows.min')} + +
+ {/* Buttons to sync and terminate the workflow */} +
+ { + syncWorkflow({ + variables: { + workflowid: data.workflow_id, + workflow_run_id: data.workflow_run_id, + }, + }); + }} + > + sync + + {t('chaosWorkflows.browseWorkflows.sync')} + + + { + deleteWorkflow({ + variables: { + workflowid: data.workflow_id, + workflow_run_id: data.workflow_run_id, + }, + }); + }} + className={classes.terminateText} + > + terminate + + {t('chaosWorkflows.browseWorkflows.terminate')} + + +
+
+
+
+ = ({ data }) => { nodeSelection.selectNode({ pod_name: '', }); - history.push({ - pathname: `/workflows/${data.workflow_run_id}`, - search: `?projectID=${projectID}&projectRole=${projectRole}`, - }); + if (data.phase?.toLowerCase() !== 'notavailable') + history.push({ + pathname: `/workflows/${data.workflow_run_id}`, + search: `?projectID=${projectID}&projectRole=${projectRole}`, + }); }} > @@ -235,10 +367,11 @@ const TableData: React.FC = ({ data }) => { nodeSelection.selectNode({ pod_name: '', }); - history.push({ - pathname: `/workflows/${data.workflow_run_id}`, - search: `?projectID=${projectID}&projectRole=${projectRole}`, - }); + if (data.phase?.toLowerCase() !== 'notavailable') + history.push({ + pathname: `/workflows/${data.workflow_run_id}`, + search: `?projectID=${projectID}&projectRole=${projectRole}`, + }); }} >
@@ -255,10 +388,11 @@ const TableData: React.FC = ({ data }) => { { - history.push({ - pathname: `/workflows/analytics/${data.workflow_id}`, - search: `?projectID=${projectID}&projectRole=${projectRole}`, - }); + if (data.phase?.toLowerCase() !== 'notavailable') + history.push({ + pathname: `/workflows/analytics/${data.workflow_id}`, + search: `?projectID=${projectID}&projectRole=${projectRole}`, + }); }} >
diff --git a/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/index.tsx b/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/index.tsx index d7411239f..48115c3fe 100644 --- a/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/index.tsx +++ b/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/index.tsx @@ -110,23 +110,23 @@ const BrowseWorkflow: React.FC = () => { ); // Query to get workflows - const { subscribeToMore, data, error } = useQuery( - WORKFLOW_DETAILS, - { - variables: { - workflowRunsInput: { - project_id: projectID, - pagination: { - page: paginationData.page, - limit: paginationData.limit, - }, - sort: sortData, - filter: filters, + const { subscribeToMore, data, error, refetch } = useQuery< + Workflow, + WorkflowDataVars + >(WORKFLOW_DETAILS, { + variables: { + workflowRunsInput: { + project_id: projectID, + pagination: { + page: paginationData.page, + limit: paginationData.limit, }, + sort: sortData, + filter: filters, }, - fetchPolicy: 'cache-and-network', - } - ); + }, + fetchPolicy: 'cache-and-network', + }); // Using subscription to get realtime data useEffect(() => { @@ -272,6 +272,7 @@ const BrowseWorkflow: React.FC = () => { + {/* Status */} {t('chaosWorkflows.browseWorkflows.status')} @@ -387,7 +388,7 @@ const BrowseWorkflow: React.FC = () => { data-cy="WorkflowRunsTableRow" key={dataRow.workflow_run_id} > - + )) ) : ( diff --git a/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/styles.ts b/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/styles.ts index 7cb721666..b1c1cf5ca 100644 --- a/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/styles.ts +++ b/litmus-portal/frontend/src/views/ChaosWorkflows/BrowseWorkflow/styles.ts @@ -83,7 +83,7 @@ const useStyles = makeStyles((theme) => ({ }, }, headerStatus: { - paddingLeft: theme.spacing(10), + paddingLeft: theme.spacing(4), }, workflowName: { @@ -94,9 +94,6 @@ const useStyles = makeStyles((theme) => ({ paddingLeft: theme.spacing(5), }, - tableDataStatus: { - paddingLeft: theme.spacing(8.5), - }, sortDiv: { display: 'flex', flexDirection: 'column', @@ -181,6 +178,53 @@ const useStyles = makeStyles((theme) => ({ pointer: 'cursor', }, }, + runningSmallIcon: { + animation: 'runningNodeSpinAnimationSmall 2s ease-in-out infinite', + }, + '@global': { + '@keyframes runningNodeSpinAnimationSmall': { + from: { + transform: `rotate(0deg)`, + }, + to: { + transform: `rotate(360deg)`, + }, + }, + }, + popoverWarning: { + padding: theme.spacing(3.125, 2.6), + width: 'fit-content', + }, + runningText: { + color: theme.palette.text.hint, + marginLeft: theme.spacing(1), + }, + + // Warning pop-over styles + warningTableCell: { + maxWidth: '2.5rem', + }, + imageRunning: { + display: 'flex', + marginTop: theme.spacing(1), + }, + warningBtnDiv: { + marginTop: theme.spacing(5), + marginLeft: theme.spacing(2.5), + }, + syncBtn: { + backgroundColor: 'transparent !important', + color: theme.palette.primary.main, + marginRight: theme.spacing(1.25), + }, + waitingBtnText: { + fontSize: '0.75rem', + marginLeft: theme.spacing(0.625), + }, + terminateText: { + backgroundColor: 'transparent !important', + color: theme.palette.primary.main, + }, })); export default useStyles; diff --git a/litmus-portal/frontend/src/views/ChaosWorkflows/CustomStatus/Status.tsx b/litmus-portal/frontend/src/views/ChaosWorkflows/CustomStatus/Status.tsx index 68be52720..f07a1aeba 100644 --- a/litmus-portal/frontend/src/views/ChaosWorkflows/CustomStatus/Status.tsx +++ b/litmus-portal/frontend/src/views/ChaosWorkflows/CustomStatus/Status.tsx @@ -19,6 +19,9 @@ const CustomStatus: React.FC = ({ status }) => { if (status === 'Running' || status === 'Pending') { return setLabel(`${classes.status} ${classes.running}`); } + if (status === 'NotAvailable') { + return setLabel(`${classes.naStatus} ${classes.notAvailable}`); + } return setLabel(`${classes.status} ${classes.failed}`); }, [status]); diff --git a/litmus-portal/frontend/src/views/ChaosWorkflows/CustomStatus/styles.ts b/litmus-portal/frontend/src/views/ChaosWorkflows/CustomStatus/styles.ts index 0c51bca81..b40b5bcf4 100644 --- a/litmus-portal/frontend/src/views/ChaosWorkflows/CustomStatus/styles.ts +++ b/litmus-portal/frontend/src/views/ChaosWorkflows/CustomStatus/styles.ts @@ -8,6 +8,17 @@ const useStyles = makeStyles((theme) => ({ paddingTop: theme.spacing(0.375), paddingBottom: theme.spacing(0.375), }, + naStatus: { + width: '4.8rem', + textAlign: 'center', + borderRadius: 3, + paddingTop: theme.spacing(0.375), + paddingBottom: theme.spacing(0.375), + }, + notAvailable: { + color: theme.palette.text.secondary, + backgroundColor: theme.palette.status.pending, + }, completed: { color: theme.palette.success.main, backgroundColor: theme.palette.success.light, @@ -17,8 +28,8 @@ const useStyles = makeStyles((theme) => ({ backgroundColor: theme.palette.warning.light, }, failed: { - color: theme.palette.status.failed, - backgroundColor: theme.palette.status.failed, + color: theme.palette.error.main, + backgroundColor: theme.palette.error.light, }, statusFont: { fontSize: '0.725rem', diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/styles.ts b/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/styles.ts index d31d3cbe3..88527c74a 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/styles.ts +++ b/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/styles.ts @@ -257,6 +257,18 @@ const useStyles = makeStyles((theme: Theme) => ({ noTemplatesDesc: { fontSize: '1rem', }, + + errorText: { + marginLeft: theme.spacing(1.25), + }, + errorBtn: { + backgroundColor: 'transparent !important', + color: theme.palette.primary.main, + marginLeft: theme.spacing(2.5), + }, + retryText: { + marginLeft: theme.spacing(1.25), + }, })); export default useStyles; diff --git a/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/uploadYAML.tsx b/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/uploadYAML.tsx index 6d0565e6c..6e4557a6a 100644 --- a/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/uploadYAML.tsx +++ b/litmus-portal/frontend/src/views/CreateWorkflow/ChooseWorkflow/uploadYAML.tsx @@ -1,4 +1,5 @@ import { AccordionDetails, Button, Paper, Typography } from '@material-ui/core'; +import { ButtonFilled } from 'litmus-ui'; import localforage from 'localforage'; import React, { useState } from 'react'; import { useTranslation } from 'react-i18next'; @@ -19,6 +20,7 @@ const UploadYAML = () => { const { t } = useTranslation(); const [uploadedYAML, setUploadedYAML] = useState(''); const [fileName, setFileName] = useState(''); + const [uploadError, setUploadError] = useState(false); const workflowAction = useActions(WorkflowActions); const { namespace } = useSelector((state: RootState) => state.workflowData); @@ -42,11 +44,19 @@ const UploadYAML = () => { const readFile = await file.text(); setUploadedYAML(readFile); setFileName(file.name); - const wfmanifest = updateEngineName(YAML.parse(readFile)); - const updatedManifest = updateNamespace(wfmanifest, namespace); - workflowAction.setWorkflowManifest({ - manifest: YAML.stringify(updatedManifest), - }); + try { + setUploadError(false); + const wfmanifest = updateEngineName(YAML.parse(readFile)); + const updatedManifest = updateNamespace(wfmanifest, namespace); + workflowAction.setWorkflowManifest({ + manifest: YAML.stringify(updatedManifest), + }); + } catch { + setUploadError(true); + workflowAction.setWorkflowManifest({ + manifest: '', + }); + } }); saveToLocalForage(); }; @@ -61,15 +71,19 @@ const UploadYAML = () => { if ((extension === 'yaml' || extension === 'yml') && readFile) { readFile.text().then((response) => { setUploadedYAML(response); - const wfmanifest = updateEngineName(YAML.parse(response)); - const updatedManifest = updateNamespace(wfmanifest, namespace); - workflowAction.setWorkflowManifest({ - manifest: YAML.stringify(updatedManifest), - }); - }); - } else { - workflowAction.setWorkflowManifest({ - manifest: '', + try { + setUploadError(false); + const wfmanifest = updateEngineName(YAML.parse(response)); + const updatedManifest = updateNamespace(wfmanifest, namespace); + workflowAction.setWorkflowManifest({ + manifest: YAML.stringify(updatedManifest), + }); + } catch { + setUploadError(true); + workflowAction.setWorkflowManifest({ + manifest: '', + }); + } }); } saveToLocalForage(); @@ -88,7 +102,31 @@ const UploadYAML = () => { }} className={classes.uploadYAMLDiv} > - {uploadedYAML === '' ? ( + {uploadError ? ( +
+ upload error + + {t('customWorkflow.createWorkflow.errorUpload')} + + { + setUploadedYAML(''); + setUploadError(false); + }} + > + Retry + + {t('customWorkflow.createWorkflow.retryUpload')} + + +
+ ) : uploadedYAML === '' ? (
{ InputProps={{ readOnly: true, }} + disabled className={classes.nsInput} label={t('createWorkflow.chooseWorkflow.label.namespace')} value={workflowData.namespace} diff --git a/litmus-portal/frontend/src/views/MyHub/MyHubCharts/index.tsx b/litmus-portal/frontend/src/views/MyHub/MyHubCharts/index.tsx index 6a8634f4b..ecf8aacda 100644 --- a/litmus-portal/frontend/src/views/MyHub/MyHubCharts/index.tsx +++ b/litmus-portal/frontend/src/views/MyHub/MyHubCharts/index.tsx @@ -121,6 +121,20 @@ const MyHub: React.FC = () => { } }, [data]); + const filteredWorkflow = + predefinedData?.GetPredefinedWorkflowList && + predefinedData?.GetPredefinedWorkflowList.filter((data: string) => + data.toLowerCase().includes(searchPredefined.trim()) + ); + + const filteredExperiment = + totalExp && + totalExp.filter( + (data) => + data.ChaosName.toLowerCase().includes(search.trim()) || + data.ExperimentName.toLowerCase().includes(search.trim()) + ); + return loading || predefinedLoading ? ( @@ -137,11 +151,13 @@ const MyHub: React.FC = () => { {UserHub?.HubName} - + {t('myhub.myhubChart.repoLink')} - - {UserHub?.RepoURL}/{UserHub?.RepoBranch} - + {UserHub?.RepoURL} + + + {t('myhub.myhubChart.repoBranch')} + {UserHub?.RepoBranch} {t('myhub.myhubChart.lastSynced')}{' '} @@ -173,11 +189,8 @@ const MyHub: React.FC = () => { changeSearch={handlePreDefinedSearch} />
- {predefinedData?.GetPredefinedWorkflowList.length > 0 ? ( - predefinedData?.GetPredefinedWorkflowList.filter( - (data: string) => - data.toLowerCase().includes(searchPredefined.trim()) - ).map((expName: string) => { + {filteredWorkflow?.length > 0 ? ( + filteredWorkflow.map((expName: string) => { return ( { height="80px" /> - {t('myhub.myhubChart.noExp')} + {t('myhub.myhubChart.noPredefinedExp')} )} @@ -232,27 +245,33 @@ const MyHub: React.FC = () => {
- {totalExp && - totalExp.length > 0 && - totalExp - .filter( - (data) => - data.ChaosName.toLowerCase().includes(search.trim()) || - data.ExperimentName.toLowerCase().includes(search.trim()) - ) - .map((expName: ChartName) => { - return ( - - ); - })} + {filteredExperiment?.length > 0 ? ( + filteredExperiment.map((expName: ChartName) => { + return ( + + ); + }) + ) : ( + <> + no experiment + + {t('myhub.myhubChart.noExp')} + + + )}