diff --git a/webpack/JobInvocationDetail/JobInvocationActions.js b/webpack/JobInvocationDetail/JobInvocationActions.js
index 131696068..e89bdeeb0 100644
--- a/webpack/JobInvocationDetail/JobInvocationActions.js
+++ b/webpack/JobInvocationDetail/JobInvocationActions.js
@@ -12,6 +12,7 @@ import {
CHANGE_ENABLED_RECURRING_LOGIC,
GET_TASK,
JOB_INVOCATION_KEY,
+ POLLING_INTERVAL_MS,
UPDATE_JOB,
} from './JobInvocationConstants';
@@ -32,7 +33,7 @@ export const getJobInvocation = url => dispatch => {
response?.data?.error?.message ||
'Error',
}),
- 1000
+ POLLING_INTERVAL_MS
);
dispatch(fetchData);
diff --git a/webpack/JobInvocationDetail/JobInvocationConstants.js b/webpack/JobInvocationDetail/JobInvocationConstants.js
index 12d6deb11..79352913c 100644
--- a/webpack/JobInvocationDetail/JobInvocationConstants.js
+++ b/webpack/JobInvocationDetail/JobInvocationConstants.js
@@ -20,6 +20,13 @@ export const DIRECT_OPEN_HOST_LIMIT = 3;
export const ALL_JOB_HOSTS = 'ALL_JOB_HOSTS';
export const AWAITING_STATUS_FILTER = '(job_invocation.result = N/A)';
+export const POLLING_INTERVAL_MS = 1000;
+export const AUTO_REFRESH_INTERVAL_MS = 5000;
+export const UNIX_TO_JS_TIMESTAMP_FACTOR = 1000;
+export const DEFAULT_CHART_LEGEND_WIDTH = 270;
+export const CLIPBOARD_COPIED_EXIT_DELAY_MS = 1500;
+export const CLIPBOARD_DEFAULT_EXIT_DELAY_MS = 600;
+
export const showTemplateInvocationUrl = (hostID, jobID) =>
`/show_template_invocation_by_host/${hostID}/job_invocation/${jobID}`;
export const LIST_TEMPLATE_INVOCATIONS = 'LIST_TEMPLATE_INVOCATIONS';
diff --git a/webpack/JobInvocationDetail/JobInvocationSystemStatusChart.js b/webpack/JobInvocationDetail/JobInvocationSystemStatusChart.js
index f44f9b707..77a46e3c7 100644
--- a/webpack/JobInvocationDetail/JobInvocationSystemStatusChart.js
+++ b/webpack/JobInvocationDetail/JobInvocationSystemStatusChart.js
@@ -23,7 +23,10 @@ import {
global_palette_blue_300 as inProgressColor,
global_palette_green_500 as successedColor,
} from '@patternfly/react-tokens';
-import { STATUS_TITLES } from './JobInvocationConstants';
+import {
+ STATUS_TITLES,
+ DEFAULT_CHART_LEGEND_WIDTH,
+} from './JobInvocationConstants';
import './JobInvocationDetail.scss';
const JobInvocationSystemStatusChart = ({
@@ -52,7 +55,7 @@ const JobInvocationSystemStatusChart = ({
return '0';
};
const chartSize = 105;
- const [legendWidth, setLegendWidth] = useState(270);
+ const [legendWidth, setLegendWidth] = useState(DEFAULT_CHART_LEGEND_WIDTH);
// Calculates chart legend width based on its content
useEffect(() => {
diff --git a/webpack/JobInvocationDetail/TemplateInvocation.js b/webpack/JobInvocationDetail/TemplateInvocation.js
index 9045be218..faad034f8 100644
--- a/webpack/JobInvocationDetail/TemplateInvocation.js
+++ b/webpack/JobInvocationDetail/TemplateInvocation.js
@@ -11,6 +11,9 @@ import {
showTemplateInvocationUrl,
templateInvocationPageUrl,
GET_TEMPLATE_INVOCATION,
+ CLIPBOARD_COPIED_EXIT_DELAY_MS,
+ CLIPBOARD_DEFAULT_EXIT_DELAY_MS,
+ AUTO_REFRESH_INTERVAL_MS,
} from './JobInvocationConstants';
import {
selectTemplateInvocationStatus,
@@ -41,7 +44,11 @@ const CopyToClipboard = ({ fullOutput }) => {
textId="code-content"
aria-label="Copy to clipboard"
onClick={e => onClick(e, fullOutput)}
- exitDelay={copied ? 1500 : 600}
+ exitDelay={
+ copied
+ ? CLIPBOARD_COPIED_EXIT_DELAY_MS
+ : CLIPBOARD_DEFAULT_EXIT_DELAY_MS
+ }
maxWidth="110px"
variant="plain"
onTooltipHidden={() => setCopied(false)}
@@ -111,7 +118,7 @@ export const TemplateInvocation = ({
} else if (intervalRef.current) {
clearInterval(intervalRef.current);
}
- }, 5000);
+ }, AUTO_REFRESH_INTERVAL_MS);
}
return () => {
diff --git a/webpack/JobInvocationDetail/TemplateInvocationComponents/OutputCodeBlock.js b/webpack/JobInvocationDetail/TemplateInvocationComponents/OutputCodeBlock.js
index 759b7b280..3a4a57644 100644
--- a/webpack/JobInvocationDetail/TemplateInvocationComponents/OutputCodeBlock.js
+++ b/webpack/JobInvocationDetail/TemplateInvocationComponents/OutputCodeBlock.js
@@ -7,6 +7,7 @@ import React, {
import PropTypes from 'prop-types';
import { Button } from '@patternfly/react-core';
import { translate as __ } from 'foremanReact/common/I18n';
+import { UNIX_TO_JS_TIMESTAMP_FACTOR } from '../JobInvocationConstants';
export const OutputCodeBlock = ({ code, showOutputType, scrollElement }) => {
let lineCounter = 0;
@@ -122,7 +123,9 @@ export const OutputCodeBlock = ({ code, showOutputType, scrollElement }) => {
{lineCounter.toString().padStart(4, '\u00A0')}:{' '}
diff --git a/webpack/JobWizard/JobWizard.js b/webpack/JobWizard/JobWizard.js
index 68f2a820c..8e244c628 100644
--- a/webpack/JobWizard/JobWizard.js
+++ b/webpack/JobWizard/JobWizard.js
@@ -18,6 +18,7 @@ import {
WIZARD_TITLES,
SCHEDULE_TYPES,
initialScheduleState,
+ STARTS_ERROR_CHECK_INTERVAL_MS,
} from './JobWizardConstants';
import {
selectTemplateError,
@@ -237,7 +238,10 @@ export const JobWizard = ({ rerunData }) => {
}
};
updateStartsError();
- const interval = setInterval(updateStartsError, 5000);
+ const interval = setInterval(
+ updateStartsError,
+ STARTS_ERROR_CHECK_INTERVAL_MS
+ );
return () => {
interval && clearInterval(interval);
diff --git a/webpack/JobWizard/JobWizardConstants.js b/webpack/JobWizard/JobWizardConstants.js
index ca1bfcdc0..a1db56bca 100644
--- a/webpack/JobWizard/JobWizardConstants.js
+++ b/webpack/JobWizard/JobWizardConstants.js
@@ -78,3 +78,12 @@ export const HOST_IDS = 'HOST_IDS';
export const REX_FEATURE = 'REX_FEATURE';
export const JOB_API_KEY = 'JOB_API_KEY';
+
+export const MINUTES_IN_HOUR = 60;
+export const DAYS_IN_WEEK = 7;
+export const SUNDAY_BASE_YEAR = 2017;
+export const DEFAULT_MINUTE_OPTIONS = [0, 15, 30, 45];
+export const MS_PER_MINUTE = 60000;
+export const STARTS_ERROR_CHECK_INTERVAL_MS = 5000;
+export const DATE_PADDING_SLICE = -2;
+export const DEBOUNCE_INPUT_MS = 1000;
diff --git a/webpack/JobWizard/steps/Schedule/RepeatHour.js b/webpack/JobWizard/steps/Schedule/RepeatHour.js
index 28e8f588e..90a7ff0a6 100644
--- a/webpack/JobWizard/steps/Schedule/RepeatHour.js
+++ b/webpack/JobWizard/steps/Schedule/RepeatHour.js
@@ -13,12 +13,16 @@ import {
} from '@patternfly/react-core/deprecated';
import { translate as __ } from 'foremanReact/common/I18n';
import { helpLabel } from '../form/FormHelpers';
+import {
+ MINUTES_IN_HOUR,
+ DEFAULT_MINUTE_OPTIONS,
+} from '../../JobWizardConstants';
export const RepeatHour = ({ repeatData, setRepeatData }) => {
const isValidMinute = newMinute =>
Number.isInteger(parseInt(newMinute, 10)) &&
newMinute >= 0 &&
- newMinute < 60;
+ newMinute < MINUTES_IN_HOUR;
const { minute } = repeatData;
useEffect(() => {
@@ -27,7 +31,7 @@ export const RepeatHour = ({ repeatData, setRepeatData }) => {
}
}, [minute, setRepeatData]);
const [minuteOpen, setMinuteOpen] = useState(false);
- const [options, setOptions] = useState([0, 15, 30, 45]);
+ const [options, setOptions] = useState(DEFAULT_MINUTE_OPTIONS);
const [isAlertOpen, setIsAlertOpen] = useState(false);
return (
{
const locale = documentLocale().replace(/-/g, '_');
- const baseDate = new Date(Date.UTC(2017, 0, 1)); // just a Sunday
+ const baseDate = new Date(Date.UTC(SUNDAY_BASE_YEAR, 0, 1)); // just a Sunday
const weekDays = [];
const formatOptions = { weekday: 'short', timeZone: 'UTC' };
- for (let i = 0; i < 7; i++) {
+ for (let i = 0; i < DAYS_IN_WEEK; i++) {
try {
weekDays.push(baseDate.toLocaleDateString(locale, formatOptions));
} catch {
diff --git a/webpack/JobWizard/steps/Schedule/ScheduleRecurring.js b/webpack/JobWizard/steps/Schedule/ScheduleRecurring.js
index 6668a9924..d2427b896 100644
--- a/webpack/JobWizard/steps/Schedule/ScheduleRecurring.js
+++ b/webpack/JobWizard/steps/Schedule/ScheduleRecurring.js
@@ -13,7 +13,7 @@ import {
import { ExclamationCircleIcon } from '@patternfly/react-icons';
import { translate as __ } from 'foremanReact/common/I18n';
import { RepeatOn } from './RepeatOn';
-import { SCHEDULE_TYPES } from '../../JobWizardConstants';
+import { SCHEDULE_TYPES, MS_PER_MINUTE } from '../../JobWizardConstants';
import { PurposeField } from './PurposeField';
import { DateTimePicker } from '../form/DateTimePicker';
import { WizardTitle } from '../form/WizardTitle';
@@ -114,7 +114,7 @@ export const ScheduleRecurring = ({
setScheduleValue(current => ({
...current,
startsAt: new Date(
- new Date().getTime() + 60000
+ new Date().getTime() + MS_PER_MINUTE
).toISOString(), // 1 minute in the future
isFuture: true,
}))
diff --git a/webpack/JobWizard/steps/Schedule/ScheduleType.js b/webpack/JobWizard/steps/Schedule/ScheduleType.js
index 77862c1f4..07857fa40 100644
--- a/webpack/JobWizard/steps/Schedule/ScheduleType.js
+++ b/webpack/JobWizard/steps/Schedule/ScheduleType.js
@@ -6,6 +6,7 @@ import {
WIZARD_TITLES,
SCHEDULE_TYPES,
repeatTypes,
+ MS_PER_MINUTE,
} from '../../JobWizardConstants';
import { WizardTitle } from '../form/WizardTitle';
import { QueryType } from './QueryType';
@@ -49,7 +50,9 @@ export const ScheduleType = ({
onChange={() => {
setScheduleValue(current => ({
...current,
- startsAt: new Date(new Date().getTime() + 60000).toISOString(), // 1 minute in the future
+ startsAt: new Date(
+ new Date().getTime() + MS_PER_MINUTE
+ ).toISOString(), // 1 minute in the future
scheduleType: SCHEDULE_TYPES.FUTURE,
repeatType: repeatTypes.noRepeat,
}));
diff --git a/webpack/JobWizard/steps/form/DateTimePicker.js b/webpack/JobWizard/steps/form/DateTimePicker.js
index 4c12012b6..2917d968e 100644
--- a/webpack/JobWizard/steps/form/DateTimePicker.js
+++ b/webpack/JobWizard/steps/form/DateTimePicker.js
@@ -7,13 +7,19 @@ import {
} from '@patternfly/react-core';
import { debounce } from 'lodash';
import { translate as __, documentLocale } from 'foremanReact/common/I18n';
+import {
+ DATE_PADDING_SLICE,
+ DEBOUNCE_INPUT_MS,
+} from '../../JobWizardConstants';
const formatDateTime = d =>
`${d.getFullYear()}-${`0${d.getMonth() + 1}`.slice(
- -2
- )}-${`0${d.getDate()}`.slice(-2)} ${`0${d.getHours()}`.slice(
- -2
- )}:${`0${d.getMinutes()}`.slice(-2)}:${`0${d.getSeconds()}`.slice(-2)}`;
+ DATE_PADDING_SLICE
+ )}-${`0${d.getDate()}`.slice(DATE_PADDING_SLICE)} ${`0${d.getHours()}`.slice(
+ DATE_PADDING_SLICE
+ )}:${`0${d.getMinutes()}`.slice(
+ DATE_PADDING_SLICE
+ )}:${`0${d.getSeconds()}`.slice(DATE_PADDING_SLICE)}`;
export const DateTimePicker = ({
dateTime,
@@ -103,7 +109,7 @@ export const DateTimePicker = ({
aria-label={`${ariaLabel} datepicker`}
value={formattedDate}
placeholder="yyyy/mm/dd"
- onChange={debounce(onDateChange, 1000, {
+ onChange={debounce(onDateChange, DEBOUNCE_INPUT_MS, {
leading: false,
trailing: true,
})}
@@ -123,7 +129,7 @@ export const DateTimePicker = ({
time={dateTime ? dateObject.toString() : ''}
inputProps={dateTime ? {} : { value: '' }}
placeholder={includeSeconds ? 'hh:mm:ss' : 'hh:mm'}
- onChange={debounce(onTimeChange, 1000, {
+ onChange={debounce(onTimeChange, DEBOUNCE_INPUT_MS, {
leading: false,
trailing: true,
})}
diff --git a/webpack/react_app/components/TargetingHosts/TargetingHostsConsts.js b/webpack/react_app/components/TargetingHosts/TargetingHostsConsts.js
index 5fd27d8c8..3642c0393 100644
--- a/webpack/react_app/components/TargetingHosts/TargetingHostsConsts.js
+++ b/webpack/react_app/components/TargetingHosts/TargetingHostsConsts.js
@@ -1,2 +1,3 @@
export const TARGETING_HOSTS = 'TARGETING_HOSTS';
export const TARGETING_HOSTS_AUTOCOMPLETE = 'targeting_hosts_search';
+export const TARGETING_HOSTS_POLLING_INTERVAL_MS = 1000;
diff --git a/webpack/react_app/components/TargetingHosts/index.js b/webpack/react_app/components/TargetingHosts/index.js
index 76f1ec728..415fb660b 100644
--- a/webpack/react_app/components/TargetingHosts/index.js
+++ b/webpack/react_app/components/TargetingHosts/index.js
@@ -17,7 +17,10 @@ import {
selectStatusFilter,
} from './TargetingHostsSelectors';
import { getApiUrl } from './TargetingHostsHelpers';
-import { TARGETING_HOSTS } from './TargetingHostsConsts';
+import {
+ TARGETING_HOSTS,
+ TARGETING_HOSTS_POLLING_INTERVAL_MS,
+} from './TargetingHostsConsts';
import TargetingHostsPage from './TargetingHostsPage';
import { chartFilter } from '../../redux/actions/jobInvocations';
@@ -100,7 +103,7 @@ const WrappedTargetingHosts = () => {
dispatch(stopInterval(TARGETING_HOSTS));
},
}),
- 1000
+ TARGETING_HOSTS_POLLING_INTERVAL_MS
),
[dispatch]
);
diff --git a/webpack/react_app/redux/actions/jobInvocations/index.js b/webpack/react_app/redux/actions/jobInvocations/index.js
index 968d83923..885712656 100644
--- a/webpack/react_app/redux/actions/jobInvocations/index.js
+++ b/webpack/react_app/redux/actions/jobInvocations/index.js
@@ -5,6 +5,7 @@ import {
JOB_INVOCATIONS_GET_JOB_INVOCATIONS,
JOB_INVOCATIONS_POLLING_STARTED,
JOB_INVOCATIONS_JOB_FINISHED,
+ HTTP_UNAUTHORIZED,
} from '../../consts';
const defaultJobInvocationsPollingInterval = 1000;
@@ -32,7 +33,7 @@ const getJobInvocations = url => async (dispatch, getState) => {
}
function onGetJobInvocationsFailed(error) {
- if (error.response.status === 401) {
+ if (error.response.status === HTTP_UNAUTHORIZED) {
window.location.replace('/users/login');
}
}
diff --git a/webpack/react_app/redux/consts.js b/webpack/react_app/redux/consts.js
index 02c09fc35..1cdc74474 100644
--- a/webpack/react_app/redux/consts.js
+++ b/webpack/react_app/redux/consts.js
@@ -3,3 +3,4 @@ export const JOB_INVOCATIONS_POLLING_STARTED =
export const JOB_INVOCATIONS_GET_JOB_INVOCATIONS =
'JOB_INVOCATIONS_GET_JOB_INVOCATIONS';
export const JOB_INVOCATIONS_JOB_FINISHED = 'JOB_INVOCATIONS_JOB_FINISHED';
+export const HTTP_UNAUTHORIZED = 401;