chore(litmus-portal): Added env tunables, date range for usage stats and fixed logs issue (#2958)
* Added env tunables, date range for usage stats and fixed logs issues * Minor theme change * Minor translations fix Signed-off-by: Amit Kumar Das <amit@chaosnative.com>
This commit is contained in:
parent
5bc3896171
commit
9c38833287
|
@ -25,7 +25,6 @@ getStarted:
|
|||
|
||||
sidebar:
|
||||
title: Litmus
|
||||
version: "Version: 1.13"
|
||||
|
||||
header:
|
||||
projectDropdown:
|
||||
|
@ -34,7 +33,7 @@ header:
|
|||
otherProjects: Other Projects
|
||||
noProjectsOther: You are not part of any projects not owned by you
|
||||
profileDropdown:
|
||||
signedIn: "Signed in as:"
|
||||
signedIn: 'Signed in as:'
|
||||
emailUnset: Email not set
|
||||
emailSet: Set up your email
|
||||
switchProject: Please switch to a project you own to access settings
|
||||
|
@ -89,7 +88,7 @@ workflowStepper:
|
|||
back: Back
|
||||
|
||||
editor:
|
||||
status: "YAML Status:"
|
||||
status: 'YAML Status:'
|
||||
|
||||
######################################
|
||||
############ Pages #############
|
||||
|
@ -107,14 +106,14 @@ login:
|
|||
tooltipText: You need to contact your admin to reset your password.
|
||||
|
||||
schedule:
|
||||
heading: "Schedule a workflow"
|
||||
headingDesc: "Click on test to see detailed log of your workflow"
|
||||
headingText: "Schedule details:"
|
||||
description: "Choose the right time to schedule your first workflow. Below you can find some options that may be convenient for you."
|
||||
save: "Save Changes"
|
||||
heading: 'Schedule a workflow'
|
||||
headingDesc: 'Click on test to see detailed log of your workflow'
|
||||
headingText: 'Schedule details:'
|
||||
description: 'Choose the right time to schedule your first workflow. Below you can find some options that may be convenient for you.'
|
||||
save: 'Save Changes'
|
||||
scheduleNow: Schedule now
|
||||
scheduleAfter: Schedule after some time
|
||||
scheduleAfterSometime: "Choose the minutes, hours, or days when you want to start workflow"
|
||||
scheduleAfterSometime: 'Choose the minutes, hours, or days when you want to start workflow'
|
||||
scheduleSpecificTime: Schedule at a specific time
|
||||
scheduleFuture: Select date and time to start workflow in future
|
||||
scheduleRecurring: Recurring Schedule
|
||||
|
@ -122,7 +121,7 @@ schedule:
|
|||
after: After
|
||||
at: at
|
||||
At: At
|
||||
scheduleOn: "On"
|
||||
scheduleOn: 'On'
|
||||
missingPerm: Missing sufficient permissions :(
|
||||
requiredPerm: Looks like you do not have the required permission to create a new workflow on this project.
|
||||
contact: Contact portal administrator to upgrade your permission.
|
||||
|
@ -143,11 +142,11 @@ editSchedule:
|
|||
successfullyCreated: is successfully created
|
||||
|
||||
community:
|
||||
title: "Community"
|
||||
heading: "Litmus Insights"
|
||||
headingDesc: "Stats for the Litmus community"
|
||||
analyticDesc: "Periodic growth of Litmus"
|
||||
statsHeading: "Litmus users around the world:"
|
||||
title: 'Community'
|
||||
heading: 'Litmus Insights'
|
||||
headingDesc: 'Stats for the Litmus community'
|
||||
analyticDesc: 'Periodic growth of Litmus'
|
||||
statsHeading: 'Litmus users around the world:'
|
||||
litmusChaos: Litmuschaos
|
||||
follow: Follow
|
||||
|
||||
|
@ -158,8 +157,8 @@ analytics:
|
|||
comingSoon: Analytics Coming Soon !
|
||||
waitingMessage: Waiting for workflow to start running !
|
||||
chaosCompleteWaitingMessage: Waiting for chaos experiment to finish !
|
||||
highestScore: "Highest Score:"
|
||||
lowestScore: "Lowest Score:"
|
||||
highestScore: 'Highest Score:'
|
||||
lowestScore: 'Lowest Score:'
|
||||
exportPDF: Export PDF
|
||||
compareWorkflows: Compare workflows
|
||||
targetCluster: Target cluster
|
||||
|
@ -443,7 +442,7 @@ analyticsDashboard:
|
|||
warning:
|
||||
text: Unexpected bad things will happen if you don’t read this!
|
||||
info: The data source seems to be connected to following Application dashboards. Dashboards will be unable to show metrics if the data source is deleted.
|
||||
connectedDashboards: "Connected Dashboards :"
|
||||
connectedDashboards: 'Connected Dashboards :'
|
||||
showLess: Show Less Dashboards
|
||||
dashboards: Dashboards
|
||||
deletionSuccess: Successfully deleted the data source
|
||||
|
@ -547,8 +546,8 @@ homeViews:
|
|||
recentWorkflowRuns:
|
||||
workflowRunCard:
|
||||
cardTitle: Browse workflow
|
||||
resilienceRate: "Overall resilience rate:"
|
||||
lastRun: "Last Run:"
|
||||
resilienceRate: 'Overall resilience rate:'
|
||||
lastRun: 'Last Run:'
|
||||
showAnalytics: Show the analytics
|
||||
downloadManifest: Download manifest
|
||||
heading: Recent Workflow runs
|
||||
|
@ -591,7 +590,7 @@ chaosWorkflows:
|
|||
disableSchedule: Disable Schedule
|
||||
enableSchedule: Enable Schedule
|
||||
saveTemplate: Save Template
|
||||
updateEngine: "Note: Make sure to update the chaos engine names"
|
||||
updateEngine: 'Note: Make sure to update the chaos engine names'
|
||||
saveChanges: Save Changes
|
||||
savedSuccessfully: Successfully saved template.
|
||||
cancel: Cancel
|
||||
|
@ -613,8 +612,8 @@ chaosWorkflows:
|
|||
sync: Sync Workflow
|
||||
terminate: Terminate Workflow
|
||||
tableData:
|
||||
overallRR: "Overall RR : "
|
||||
experimentsPassed: "Experiments Passed : "
|
||||
overallRR: 'Overall RR : '
|
||||
experimentsPassed: 'Experiments Passed : '
|
||||
showExperiments: Show Experiments
|
||||
showTheWorkflow: Show the workflow
|
||||
showTheAnalytics: Show the analytics
|
||||
|
@ -803,7 +802,7 @@ settings:
|
|||
disconnect: Are you sure you want to disconnect?
|
||||
save: Save Locally
|
||||
repo: Git Repository
|
||||
desc: "* Any existing or active workflows saved locally will not be synced into the git repository"
|
||||
desc: '* Any existing or active workflows saved locally will not be synced into the git repository'
|
||||
connect: Connect
|
||||
branch: Branch
|
||||
URL: Git URL
|
||||
|
@ -818,11 +817,11 @@ settings:
|
|||
headingDesc: Your image registry for the workflow manifest
|
||||
defaultValues: Use the default values
|
||||
defaultText: All YAML files use these default values provided by Litmus. The values cannot be changed.
|
||||
registry: "Registry : "
|
||||
repo: "Repository : "
|
||||
repoType: "Registry Type : "
|
||||
dockerio: "docker.io"
|
||||
litmus: "litmuschaos"
|
||||
registry: 'Registry : '
|
||||
repo: 'Repository : '
|
||||
repoType: 'Registry Type : '
|
||||
dockerio: 'docker.io'
|
||||
litmus: 'litmuschaos'
|
||||
public: Public
|
||||
private: Private
|
||||
defaultReg: Use Default Registry
|
||||
|
@ -854,12 +853,12 @@ workflowDetailsView:
|
|||
Completed: Completed
|
||||
runTime:
|
||||
runTimeHeader: Run Time
|
||||
startTime: "Start Time :"
|
||||
endTime: "End Time :"
|
||||
startTime: 'Start Time :'
|
||||
endTime: 'End Time :'
|
||||
targets:
|
||||
targetsHeader: Target
|
||||
cluster: "Cluster :"
|
||||
namespace: "Workflow Namespace :"
|
||||
cluster: 'Cluster :'
|
||||
namespace: 'Workflow Namespace :'
|
||||
workflowNodeInfo:
|
||||
name: Name
|
||||
type: Type
|
||||
|
@ -914,8 +913,8 @@ createWorkflow:
|
|||
revertSchedule: Revert Schedule
|
||||
noTemplates: No template available.
|
||||
addTemplate: You can add a template from the scheduled workflows table.
|
||||
trueValue: "True"
|
||||
falseValue: "False"
|
||||
trueValue: 'True'
|
||||
falseValue: 'False'
|
||||
table:
|
||||
head1: Sequence
|
||||
head2: Name
|
||||
|
@ -1010,8 +1009,8 @@ createWorkflow:
|
|||
myHubInfo: Experiment details
|
||||
annotationInfo: Provide target application details where you want to induce the chaos.
|
||||
annotation: Annotation Check
|
||||
true: "True"
|
||||
false: "False"
|
||||
true: 'True'
|
||||
false: 'False'
|
||||
annotationDesc: The target application does not have an annotation “Chaos=true”. Ideally, you cannot run this experiment unless the annotation is patched to the application. However, this service account has the privileges to disable the enforcement of annotation checks. Mark the annotation as false to proceed.
|
||||
appkind: appKind
|
||||
deployment: Deployment
|
||||
|
@ -1020,7 +1019,7 @@ createWorkflow:
|
|||
deploymentconfig: Deploymentconfig
|
||||
rollout: Rollout
|
||||
nodeselector: NodeSelector
|
||||
selector: "kubernetes.io/hostname :"
|
||||
selector: 'kubernetes.io/hostname :'
|
||||
nsError: Namespace not available
|
||||
labelError: Label not available in the resource or namespace
|
||||
deleteExp: Delete the experiment
|
||||
|
@ -1034,9 +1033,16 @@ createWorkflow:
|
|||
showDetails: Show Details
|
||||
showProp: Show Properties
|
||||
addProbe: Please add probes to see the data
|
||||
addNewProbe: "+ Add a new Probe"
|
||||
addNewProbe: '+ Add a new Probe'
|
||||
back: Back
|
||||
finish: Finish
|
||||
env:
|
||||
envHeading: Tune the environment variables of the experiment
|
||||
showMoreEnv: Show more environment variables
|
||||
showLessEnv: Show less environment variables
|
||||
key: Key Tunables
|
||||
addKey: Add a key-value pair
|
||||
finish: Finish
|
||||
addProbe:
|
||||
heading: Add
|
||||
headingStrong: Probe
|
||||
|
@ -1216,7 +1222,7 @@ browseTemplate:
|
|||
#########################################
|
||||
|
||||
internetIssues:
|
||||
fetchData: "Fetching the data..."
|
||||
fetchData: 'Fetching the data...'
|
||||
connectionError: It seems you have no internet connection, Please try again When connectivity resumes.
|
||||
|
||||
######################################
|
||||
|
@ -1226,14 +1232,14 @@ myhub:
|
|||
title: MyHubs
|
||||
connectTarget: Connect the target
|
||||
viewMyHub: View My Hub
|
||||
error: "[Error: could not connect]"
|
||||
error: '[Error: could not connect]'
|
||||
view: View
|
||||
validationEmptySpace: Should not start with an empty space
|
||||
validURL: Enter a valid URL
|
||||
edit: Edit Hub
|
||||
refresh: Refresh Hub
|
||||
disconnect: Disconnect Hub
|
||||
lastSync: "Last synced at:"
|
||||
lastSync: 'Last synced at:'
|
||||
mainPage:
|
||||
header: ChaosHubs
|
||||
github: github.com/
|
||||
|
@ -1261,9 +1267,9 @@ myhub:
|
|||
chaosCharts: Chaos-charts
|
||||
noPredefinedExp: No predefined workflows available with information in this Hub
|
||||
noExp: No experiments found
|
||||
lastSynced: "Last synced at: "
|
||||
repoLink: "Repository Link: "
|
||||
repoBranch: "Repository Branch: "
|
||||
lastSynced: 'Last synced at: '
|
||||
repoLink: 'Repository Link: '
|
||||
repoBranch: 'Repository Branch: '
|
||||
connectHubPage:
|
||||
connectHub: Connect a new chaos hub
|
||||
editHub: Edit hub configuration
|
||||
|
@ -1281,7 +1287,7 @@ myhub:
|
|||
accessToken: Access Token
|
||||
ssh: SSH
|
||||
sshText: Please enable read / write access on the above git repository for the following key
|
||||
sshAlert: "*Make sure to provide the SSH link of the Git Repository"
|
||||
sshAlert: '*Make sure to provide the SSH link of the Git Repository'
|
||||
saveLater: Save for later
|
||||
updateHub: Update the MyHub with correct details from the MyHubs section
|
||||
cancel: Cancel
|
||||
|
|
|
@ -0,0 +1,90 @@
|
|||
import React, { useState } from 'react';
|
||||
import { Button, IconButton, Popover, Typography } from '@material-ui/core';
|
||||
import { useTheme } from '@material-ui/core/styles';
|
||||
import ChevronRightIcon from '@material-ui/icons/ChevronRight';
|
||||
import KeyboardArrowDownIcon from '@material-ui/icons/KeyboardArrowDown';
|
||||
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 useStyles from './styles';
|
||||
|
||||
interface UsageRangePickerProps {
|
||||
isOpen: boolean;
|
||||
popAnchorEl: HTMLElement | null;
|
||||
displayDate: string;
|
||||
popOverClick: (
|
||||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
|
||||
) => void;
|
||||
popOverClose: (
|
||||
event: React.MouseEvent<HTMLButtonElement, MouseEvent>
|
||||
) => void;
|
||||
selectDate: (selectFromDate: string, selectToDate: string) => void;
|
||||
}
|
||||
|
||||
const UsageRangePicker: React.FC<UsageRangePickerProps> = ({
|
||||
isOpen,
|
||||
popAnchorEl,
|
||||
displayDate,
|
||||
popOverClick,
|
||||
popOverClose,
|
||||
selectDate,
|
||||
}) => {
|
||||
const classes = useStyles();
|
||||
const { palette } = useTheme();
|
||||
const [state, setState] = useState([
|
||||
{
|
||||
startDate: new Date(new Date().getFullYear(), new Date().getMonth(), 1),
|
||||
endDate: new Date(),
|
||||
key: 'selection',
|
||||
},
|
||||
]);
|
||||
|
||||
return (
|
||||
<div className={classes.dateRangeDiv}>
|
||||
<Button className={classes.selectDate} onClick={popOverClick}>
|
||||
<Typography className={classes.displayDate}>
|
||||
{displayDate}
|
||||
<IconButton className={classes.dateRangeIcon}>
|
||||
{isOpen ? <KeyboardArrowDownIcon /> : <ChevronRightIcon />}
|
||||
</IconButton>
|
||||
</Typography>
|
||||
</Button>
|
||||
<Popover
|
||||
open={isOpen}
|
||||
anchorEl={popAnchorEl}
|
||||
onClose={popOverClose}
|
||||
anchorOrigin={{
|
||||
vertical: 'bottom',
|
||||
horizontal: 'center',
|
||||
}}
|
||||
transformOrigin={{
|
||||
vertical: 'top',
|
||||
horizontal: 'center',
|
||||
}}
|
||||
style={{
|
||||
marginTop: 10,
|
||||
}}
|
||||
>
|
||||
<DateRangePicker
|
||||
onChange={(item) => {
|
||||
setState([(item as any).selection]);
|
||||
selectDate(
|
||||
`${(item as any).selection.startDate}`,
|
||||
`${(item as any).selection.endDate}`
|
||||
);
|
||||
}}
|
||||
showSelectionPreview
|
||||
moveRangeOnFirstSelection={false}
|
||||
months={1}
|
||||
ranges={state}
|
||||
direction="vertical"
|
||||
editableDateInputs
|
||||
rangeColors={[palette.primary.dark]}
|
||||
showMonthAndYearPickers
|
||||
/>
|
||||
</Popover>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default UsageRangePicker;
|
|
@ -1,28 +1,93 @@
|
|||
import { Typography } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import moment from 'moment';
|
||||
import Scaffold from '../../containers/layouts/Scaffold';
|
||||
import UsageStats from '../../views/UsageStatistics/UsageStats';
|
||||
import UsageTable from '../../views/UsageStatistics/UsageTable';
|
||||
import UsageRangePicker from './datePicker';
|
||||
import useStyles from './styles';
|
||||
|
||||
interface DateRange {
|
||||
start_date: string;
|
||||
end_date: string;
|
||||
}
|
||||
|
||||
const UsageStatistics = () => {
|
||||
const classes = useStyles();
|
||||
const { t } = useTranslation();
|
||||
const [popAnchorEl, setPopAnchorEl] = React.useState<null | HTMLElement>(
|
||||
null
|
||||
);
|
||||
|
||||
/**
|
||||
* State variable to set date in UNIX format
|
||||
*/
|
||||
const [dates, setDates] = React.useState<DateRange>({
|
||||
start_date: Math.trunc(
|
||||
new Date(new Date().getFullYear(), new Date().getMonth(), 1).getTime() /
|
||||
1000
|
||||
).toString(),
|
||||
end_date: Math.trunc(new Date().getTime() / 1000).toString(),
|
||||
});
|
||||
|
||||
/**
|
||||
* State variable for displaying dates
|
||||
*/
|
||||
const [displayDate, setDisplayDate] = React.useState<string>(
|
||||
`${moment(parseInt(dates.start_date, 10) * 1000).format(
|
||||
'DD.MM.YY'
|
||||
)}-${moment(parseInt(dates.end_date, 10) * 1000).format('DD.MM.YY')}`
|
||||
);
|
||||
|
||||
const isOpen = Boolean(popAnchorEl);
|
||||
|
||||
const handlePopOverClose = () => {
|
||||
setPopAnchorEl(null);
|
||||
};
|
||||
|
||||
const handlePopOverClick = (event: React.MouseEvent<HTMLElement>) => {
|
||||
setPopAnchorEl(event.currentTarget);
|
||||
};
|
||||
const dateChange = (selectStartDate: string, selectEndDate: string) => {
|
||||
// Change the display value of date range
|
||||
setDisplayDate(
|
||||
`${moment(selectStartDate).format('DD.MM.YYYY').toString()}-${moment(
|
||||
selectEndDate
|
||||
)
|
||||
.format('DD.MM.YYYY')
|
||||
.toString()}`
|
||||
);
|
||||
setDates({
|
||||
start_date: moment(selectStartDate).unix().toString(),
|
||||
end_date: moment(selectEndDate).unix().toString(),
|
||||
});
|
||||
};
|
||||
return (
|
||||
<Scaffold>
|
||||
<Typography variant="h3">{t('usage.usageHeader')}</Typography>
|
||||
<Typography className={classes.description}>
|
||||
{t('usage.usageSubtitle')}
|
||||
</Typography>
|
||||
<UsageStats />
|
||||
<div style={{ display: 'flex' }}>
|
||||
<Typography className={classes.description}>
|
||||
{t('usage.usageSubtitle')}
|
||||
</Typography>
|
||||
<UsageRangePicker
|
||||
popOverClick={handlePopOverClick}
|
||||
popOverClose={handlePopOverClose}
|
||||
isOpen={isOpen}
|
||||
popAnchorEl={popAnchorEl}
|
||||
displayDate={displayDate}
|
||||
selectDate={dateChange}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<UsageStats start_time={dates.start_date} end_time={dates.end_date} />
|
||||
<br />
|
||||
<br />
|
||||
<Typography variant="h4">{t('usage.projectStatistics')}</Typography>
|
||||
<Typography className={classes.description}>
|
||||
{t('usage.projectSubtitle')}
|
||||
</Typography>
|
||||
<UsageTable />
|
||||
<UsageTable start_time={dates.start_date} end_time={dates.end_date} />
|
||||
</Scaffold>
|
||||
);
|
||||
};
|
||||
|
|
|
@ -10,5 +10,26 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||
margin: theme.spacing(3, 0),
|
||||
color: theme.palette.text.hint,
|
||||
},
|
||||
selectDate: {
|
||||
display: 'flex',
|
||||
flexDirection: 'row',
|
||||
height: '2.5rem',
|
||||
minWidth: '9rem',
|
||||
border: '0.125rem solid',
|
||||
marginRight: theme.spacing(3.75),
|
||||
textTransform: 'none',
|
||||
borderColor: theme.palette.primary.main,
|
||||
},
|
||||
displayDate: {
|
||||
marginLeft: theme.spacing(1),
|
||||
width: '100%',
|
||||
},
|
||||
dateRangeDiv: {
|
||||
marginLeft: 'auto',
|
||||
},
|
||||
dateRangeIcon: {
|
||||
width: '0.625rem',
|
||||
height: '0.625rem',
|
||||
},
|
||||
}));
|
||||
export default useStyles;
|
||||
|
|
|
@ -8,6 +8,7 @@ import { ButtonOutlined } from 'litmus-ui';
|
|||
import General from '../TuneWorkflowSteps/General';
|
||||
import SteadyState from '../TuneWorkflowSteps/SteadyState';
|
||||
import TargetApplication from '../TuneWorkflowSteps/TargetApplication';
|
||||
import EnvironmentVariables from '../TuneWorkflowSteps/EnvironmentVariables';
|
||||
import useStyles from './styles';
|
||||
|
||||
interface ConfigurationStepperProps {
|
||||
|
@ -29,12 +30,12 @@ function getStepContent(
|
|||
case 0:
|
||||
return <General isCustom={isCustom} gotoStep={gotoStep} />;
|
||||
case 1:
|
||||
return (
|
||||
<TargetApplication engineIndex={engineIndex} gotoStep={gotoStep} />
|
||||
);
|
||||
return <TargetApplication gotoStep={gotoStep} />;
|
||||
case 2:
|
||||
return <SteadyState gotoStep={gotoStep} />;
|
||||
case 3:
|
||||
return (
|
||||
<SteadyState
|
||||
<EnvironmentVariables
|
||||
engineIndex={engineIndex}
|
||||
gotoStep={gotoStep}
|
||||
closeStepper={closeStepper}
|
||||
|
@ -60,6 +61,7 @@ const ConfigurationStepper: React.FC<ConfigurationStepperProps> = ({
|
|||
'General',
|
||||
'Target Application',
|
||||
'Define the steady state for this application',
|
||||
'Tune Experiment',
|
||||
];
|
||||
|
||||
const gotoStep = (page: number) => {
|
||||
|
|
|
@ -0,0 +1,210 @@
|
|||
import { Button, Typography } from '@material-ui/core';
|
||||
import { ButtonFilled, InputField } from 'litmus-ui';
|
||||
import ArrowUpwardIcon from '@material-ui/icons/ArrowUpward';
|
||||
import ArrowDownwardIcon from '@material-ui/icons/ArrowDownward';
|
||||
import React, { useState } from 'react';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useSelector } from 'react-redux';
|
||||
import YAML from 'yaml';
|
||||
import AddIcon from '@material-ui/icons/Add';
|
||||
import { WorkflowManifest } from '../../../../models/redux/workflow';
|
||||
import useActions from '../../../../redux/actions';
|
||||
import * as WorkflowActions from '../../../../redux/actions/workflow';
|
||||
import { RootState } from '../../../../redux/reducers';
|
||||
import useStyles from './styles';
|
||||
|
||||
interface EnvVariableProps {
|
||||
engineIndex: number;
|
||||
gotoStep: (page: number) => void;
|
||||
closeStepper: () => void;
|
||||
}
|
||||
|
||||
interface EnvValues {
|
||||
name: string;
|
||||
value: string;
|
||||
}
|
||||
|
||||
const EnvironmentVariables: React.FC<EnvVariableProps> = ({
|
||||
gotoStep,
|
||||
engineIndex,
|
||||
closeStepper,
|
||||
}) => {
|
||||
const { t } = useTranslation();
|
||||
const classes = useStyles();
|
||||
const workflow = useActions(WorkflowActions);
|
||||
const manifest: WorkflowManifest = useSelector(
|
||||
(state: RootState) => state.workflowManifest
|
||||
);
|
||||
|
||||
/**
|
||||
* State variable for managing the additional key-value pair
|
||||
*/
|
||||
const [addEnv, setAddEnv] = useState<EnvValues>({
|
||||
name: '',
|
||||
value: '',
|
||||
});
|
||||
|
||||
/**
|
||||
* State variable to display Show More / Show Less
|
||||
*/
|
||||
const [showMore, setShowMore] = useState(false);
|
||||
const engine = useSelector(
|
||||
(state: RootState) => state.workflowManifest.engineYAML
|
||||
);
|
||||
const engineYAML = YAML.parse(engine);
|
||||
|
||||
/**
|
||||
* State variable to store all the env varaibles from the engine
|
||||
*/
|
||||
const [env, setEnvs] = useState<EnvValues[]>(
|
||||
engineYAML.spec.experiments[0].spec.components.env
|
||||
);
|
||||
|
||||
/**
|
||||
* getShowMoreItems functions returns all the envs
|
||||
* if showMore is true, else this returns maximum of
|
||||
* 3 envs.
|
||||
*/
|
||||
const getShowMoreItems = (env: EnvValues[]) => {
|
||||
if (showMore) {
|
||||
return env;
|
||||
}
|
||||
return env.slice(0, 3);
|
||||
};
|
||||
|
||||
/**
|
||||
* handleMainYAMLChange funtion makes the changes
|
||||
* in the engine YAML and then adds the engine manifest
|
||||
* to the overall workflow YAML
|
||||
*/
|
||||
const handleMainYAMLChange = () => {
|
||||
engineYAML.spec.experiments[0].spec.components.env = env;
|
||||
const mainManifest = YAML.parse(manifest.manifest);
|
||||
mainManifest.spec.templates[engineIndex].inputs.artifacts[0].raw.data =
|
||||
YAML.stringify(engineYAML);
|
||||
workflow.setWorkflowManifest({
|
||||
manifest: YAML.stringify(mainManifest),
|
||||
engineYAML: YAML.stringify(engineYAML),
|
||||
});
|
||||
closeStepper();
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Typography>{t('createWorkflow.tuneWorkflow.env.envHeading')}</Typography>
|
||||
<br />
|
||||
<div className={classes.inputDiv}>
|
||||
{getShowMoreItems(env).map((data, index) => {
|
||||
return (
|
||||
<>
|
||||
<InputField
|
||||
width="auto"
|
||||
label={data.name}
|
||||
value={env[index].value}
|
||||
onChange={(event) => {
|
||||
env[index].value = event.target.value;
|
||||
setEnvs([...env]);
|
||||
}}
|
||||
/>
|
||||
<br />
|
||||
</>
|
||||
);
|
||||
})}
|
||||
<div>
|
||||
{env.length > 3 && !showMore ? (
|
||||
<ButtonFilled
|
||||
className={classes.showMoreBtn}
|
||||
onClick={() => {
|
||||
setShowMore(true);
|
||||
}}
|
||||
>
|
||||
<ArrowDownwardIcon />
|
||||
<Typography>
|
||||
{t('createWorkflow.tuneWorkflow.env.showMoreEnv')}
|
||||
</Typography>
|
||||
</ButtonFilled>
|
||||
) : showMore ? (
|
||||
<ButtonFilled
|
||||
className={classes.showMoreBtn}
|
||||
onClick={() => {
|
||||
setShowMore(false);
|
||||
}}
|
||||
>
|
||||
<ArrowUpwardIcon />
|
||||
<Typography>
|
||||
{t('createWorkflow.tuneWorkflow.env.showLessEnv')}
|
||||
</Typography>
|
||||
</ButtonFilled>
|
||||
) : (
|
||||
<></>
|
||||
)}
|
||||
</div>
|
||||
<div>
|
||||
<Typography className={classes.keyText}>
|
||||
{t('createWorkflow.tuneWorkflow.env.key')}
|
||||
</Typography>
|
||||
<br />
|
||||
<div style={{ display: 'flex' }}>
|
||||
<InputField
|
||||
label="Add Key"
|
||||
value={addEnv.name}
|
||||
onChange={(event) => {
|
||||
setAddEnv({
|
||||
...addEnv,
|
||||
name: event.target.value,
|
||||
});
|
||||
}}
|
||||
width="20"
|
||||
className={classes.addKeyInput}
|
||||
/>
|
||||
<InputField
|
||||
label="Add Value"
|
||||
value={addEnv.value}
|
||||
onChange={(event) => {
|
||||
setAddEnv({
|
||||
...addEnv,
|
||||
value: event.target.value,
|
||||
});
|
||||
}}
|
||||
width="20"
|
||||
/>
|
||||
</div>
|
||||
<ButtonFilled
|
||||
className={classes.addKeyValue}
|
||||
onClick={() => {
|
||||
env[env.length] = {
|
||||
name: addEnv.name,
|
||||
value: addEnv.value,
|
||||
};
|
||||
setEnvs(env);
|
||||
setAddEnv({
|
||||
name: '',
|
||||
value: '',
|
||||
});
|
||||
}}
|
||||
disabled={addEnv.name.trim() === '' || addEnv.value.trim() === ''}
|
||||
>
|
||||
<AddIcon /> {t('createWorkflow.tuneWorkflow.env.addKey')}
|
||||
</ButtonFilled>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<Button onClick={() => gotoStep(2)} className={classes.button}>
|
||||
{t('workflowStepper.back')}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => handleMainYAMLChange()}
|
||||
className={classes.button}
|
||||
>
|
||||
{t('createWorkflow.tuneWorkflow.env.finish')}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EnvironmentVariables;
|
|
@ -24,16 +24,10 @@ import AddProbe from '../AddProbe';
|
|||
import useStyles from './styles';
|
||||
|
||||
interface SteadyStateProps {
|
||||
engineIndex: number;
|
||||
gotoStep: (page: number) => void;
|
||||
closeStepper: () => void;
|
||||
}
|
||||
|
||||
const SteadyState: React.FC<SteadyStateProps> = ({
|
||||
engineIndex,
|
||||
gotoStep,
|
||||
closeStepper,
|
||||
}) => {
|
||||
const SteadyState: React.FC<SteadyStateProps> = ({ gotoStep }) => {
|
||||
const classes = useStyles();
|
||||
const { t } = useTranslation();
|
||||
const workflow = useActions(WorkflowActions);
|
||||
|
@ -55,14 +49,9 @@ const SteadyState: React.FC<SteadyStateProps> = ({
|
|||
setAddProbe(false);
|
||||
};
|
||||
|
||||
// handleManiYAMLChange allows to update the main manifest
|
||||
// with the changes in individual Chaos Engines
|
||||
// handleManiYAMLChange allows to update the changes in individual Chaos Engines
|
||||
const handleMainYAMLChange = () => {
|
||||
const mainManifest = YAML.parse(manifest.manifest);
|
||||
mainManifest.spec.templates[engineIndex].inputs.artifacts[0].raw.data =
|
||||
YAML.stringify(chaosEngine);
|
||||
workflow.setWorkflowManifest({
|
||||
manifest: YAML.stringify(mainManifest),
|
||||
engineYAML: YAML.stringify(chaosEngine),
|
||||
});
|
||||
};
|
||||
|
@ -103,10 +92,10 @@ const SteadyState: React.FC<SteadyStateProps> = ({
|
|||
setAddProbe(false);
|
||||
};
|
||||
|
||||
const handleStepperClose = () => {
|
||||
const handleNext = () => {
|
||||
chaosEngine.spec.experiments[0].spec.probe = probesData;
|
||||
handleMainYAMLChange();
|
||||
return closeStepper();
|
||||
gotoStep(3);
|
||||
};
|
||||
|
||||
return (
|
||||
|
@ -269,10 +258,10 @@ const SteadyState: React.FC<SteadyStateProps> = ({
|
|||
<Button
|
||||
variant="contained"
|
||||
color="primary"
|
||||
onClick={() => handleStepperClose()}
|
||||
onClick={() => handleNext()}
|
||||
className={classes.button}
|
||||
>
|
||||
{t('createWorkflow.tuneWorkflow.steadyState.finish')}
|
||||
Next
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -51,14 +51,10 @@ interface TargetApplicationData {
|
|||
}
|
||||
|
||||
interface TargetApplicationProp {
|
||||
engineIndex: number;
|
||||
gotoStep: (page: number) => void;
|
||||
}
|
||||
|
||||
const TargetApplication: React.FC<TargetApplicationProp> = ({
|
||||
engineIndex,
|
||||
gotoStep,
|
||||
}) => {
|
||||
const TargetApplication: React.FC<TargetApplicationProp> = ({ gotoStep }) => {
|
||||
const { t } = useTranslation();
|
||||
/**
|
||||
* State Variables to manage theme changes
|
||||
|
@ -152,9 +148,7 @@ const TargetApplication: React.FC<TargetApplicationProp> = ({
|
|||
];
|
||||
}
|
||||
engineManifest.spec.jobCleanUpPolicy = targetApp.jobCleanUpPolicy;
|
||||
const mainManifest = YAML.parse(manifest.manifest);
|
||||
mainManifest.spec.templates[engineIndex].inputs.artifacts[0].raw.data =
|
||||
YAML.stringify(engineManifest);
|
||||
|
||||
workflow.setWorkflowManifest({
|
||||
engineYAML: YAML.stringify(engineManifest),
|
||||
});
|
||||
|
|
|
@ -10,6 +10,13 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||
marginTop: theme.spacing(1),
|
||||
marginRight: theme.spacing(1),
|
||||
},
|
||||
showMoreBtn: {
|
||||
display: 'flex',
|
||||
color: theme.palette.primary.main,
|
||||
backgroundColor: 'transparent !important',
|
||||
cursor: 'pointer',
|
||||
marginBottom: theme.spacing(2.5),
|
||||
},
|
||||
actionsContainer: {
|
||||
marginBottom: theme.spacing(2),
|
||||
},
|
||||
|
@ -20,7 +27,12 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||
border: 'none !important',
|
||||
color: theme.palette.primary.main,
|
||||
},
|
||||
|
||||
keyText: {
|
||||
fontSize: '1rem',
|
||||
},
|
||||
addKeyInput: {
|
||||
marginRight: theme.spacing(2.25),
|
||||
},
|
||||
// General Component
|
||||
generalContainer: {
|
||||
display: 'flex',
|
||||
|
@ -33,6 +45,14 @@ const useStyles = makeStyles((theme: Theme) => ({
|
|||
flexDirection: 'column',
|
||||
maxWidth: '25rem',
|
||||
},
|
||||
|
||||
addKeyValue: {
|
||||
backgroundColor: 'transparent !important',
|
||||
color: theme.palette.primary.main,
|
||||
marginTop: theme.spacing(1.25),
|
||||
marginBottom: theme.spacing(2.25),
|
||||
},
|
||||
|
||||
annotation: {
|
||||
fontSize: '0.875rem',
|
||||
margin: theme.spacing(0.6, 2, 0, 0),
|
||||
|
|
|
@ -6,7 +6,12 @@ import { GET_GLOBAL_STATS } from '../../../graphql';
|
|||
import Card from './Cards';
|
||||
import useStyles from './styles';
|
||||
|
||||
const UsageStats = () => {
|
||||
interface TimeRange {
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
}
|
||||
|
||||
const UsageStats: React.FC<TimeRange> = ({ start_time, end_time }) => {
|
||||
const classes = useStyles();
|
||||
const { t } = useTranslation();
|
||||
const [usageQuery, { loading, data }] = useLazyQuery(GET_GLOBAL_STATS);
|
||||
|
@ -16,19 +21,13 @@ const UsageStats = () => {
|
|||
variables: {
|
||||
query: {
|
||||
DateRange: {
|
||||
start_date: Math.trunc(
|
||||
new Date(
|
||||
new Date().getFullYear(),
|
||||
new Date().getMonth(),
|
||||
1
|
||||
).getTime() / 1000
|
||||
).toString(),
|
||||
end_date: Math.trunc(new Date().getTime() / 1000).toString(),
|
||||
start_date: start_time,
|
||||
end_date: end_time,
|
||||
},
|
||||
},
|
||||
},
|
||||
});
|
||||
}, []);
|
||||
}, [start_time, end_time]);
|
||||
|
||||
return (
|
||||
<div className={classes.cardDiv}>
|
||||
|
|
|
@ -33,7 +33,12 @@ interface SortInput {
|
|||
Descending?: boolean;
|
||||
}
|
||||
|
||||
const UsageTable = () => {
|
||||
interface TimeRange {
|
||||
start_time: string;
|
||||
end_time: string;
|
||||
}
|
||||
|
||||
const UsageTable: React.FC<TimeRange> = ({ start_time, end_time }) => {
|
||||
const classes = useStyles();
|
||||
const { t } = useTranslation();
|
||||
const [paginationData, setPaginationData] = useState<Pagination>({
|
||||
|
@ -46,21 +51,15 @@ const UsageTable = () => {
|
|||
});
|
||||
const [search, setSearch] = useState<string>('');
|
||||
|
||||
const [usageQuery, { loading, data }] = useLazyQuery(GLOBAL_PROJECT_DATA, {});
|
||||
const [usageQuery, { loading, data }] = useLazyQuery(GLOBAL_PROJECT_DATA);
|
||||
|
||||
useEffect(() => {
|
||||
usageQuery({
|
||||
variables: {
|
||||
query: {
|
||||
DateRange: {
|
||||
start_date: Math.trunc(
|
||||
new Date(
|
||||
new Date().getFullYear(),
|
||||
new Date().getMonth(),
|
||||
1
|
||||
).getTime() / 1000
|
||||
).toString(),
|
||||
end_date: Math.trunc(new Date().getTime() / 1000).toString(),
|
||||
start_date: start_time,
|
||||
end_date: end_time,
|
||||
},
|
||||
Pagination: {
|
||||
page: paginationData.page,
|
||||
|
@ -71,7 +70,7 @@ const UsageTable = () => {
|
|||
},
|
||||
},
|
||||
});
|
||||
}, [paginationData, search, sortData]);
|
||||
}, [paginationData, search, sortData, start_time, end_time]);
|
||||
|
||||
return (
|
||||
<div className={classes.table}>
|
||||
|
|
|
@ -87,7 +87,7 @@ const LogsSwitcher: React.FC<LogsSwitcherProps> = ({
|
|||
chaos_namespace: '',
|
||||
});
|
||||
}
|
||||
}, [workflow_data]);
|
||||
}, [workflow_data, pod_name]);
|
||||
|
||||
const [chaosResult, setChaosResult] = useState('');
|
||||
|
||||
|
|
Loading…
Reference in New Issue