Skip to content

Commit

Permalink
Merge pull request #1883 from glific/feature/update-triggers-hourly
Browse files Browse the repository at this point in the history
Added hourly triggers
  • Loading branch information
mdshamoon authored Jan 31, 2022
2 parents b46b7e1 + 75d7e11 commit adc6754
Show file tree
Hide file tree
Showing 6 changed files with 178 additions and 58 deletions.
19 changes: 19 additions & 0 deletions src/common/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,25 @@ export const dateList: any = Array.from(Array(31), (_, i) => ({
label: (i + 1).toString(),
}));

export const hourList: any = Array.from(Array(24), (_, i) => {
let timeOfDay = 'AM';
let hour = i;
if (i > 11) {
timeOfDay = 'PM';
hour -= 12;
}

let hourLabel = hour.toString();
if (hour === 0) {
hourLabel = '12';
}

return {
id: i,
label: `${hourLabel} ${timeOfDay}`,
};
});

export const dayList: any = [
{ id: 1, label: 'Monday' },
{ id: 2, label: 'Tuesday' },
Expand Down
30 changes: 29 additions & 1 deletion src/containers/Trigger/Trigger.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { MemoryRouter } from 'react-router';
import { LIST_ITEM_MOCKS } from 'containers/SettingList/SettingList.test.helper';
import { LIST_ITEM_MOCKS as SearchMocks } from 'containers/Search/Search.test.helper';
import * as AutoComplete from 'components/UI/Form/AutoComplete/AutoComplete';
import { getTriggerQuery } from 'mocks/Trigger';
import { getTriggerQuery, hourlyTrigger } from 'mocks/Trigger';
import { Trigger } from './Trigger';

describe('trigger with daily frequency', () => {
Expand Down Expand Up @@ -60,6 +60,34 @@ describe('trigger with no frequency', () => {
});
});

describe('trigger with hourly frequency', () => {
const mocks = [hourlyTrigger(), ...LIST_ITEM_MOCKS, ...SearchMocks];

const wrapper = (
<MockedProvider mocks={mocks} addTypename={false}>
<MemoryRouter>
<Trigger match={{ params: { id: '1' } }} />
</MemoryRouter>
</MockedProvider>
);

test('should load trigger edit form', async () => {
const { getByText, getByTestId } = render(wrapper);

// loading is show initially
expect(getByText('Loading...')).toBeInTheDocument();
await waitFor(() => {
const formLayout = getByTestId('formLayout');
expect(formLayout).toHaveTextContent('hours');
});

await waitFor(() => {
expect(getByText('1 AM')).toBeInTheDocument();
expect(getByText('1 PM')).toBeInTheDocument();
});
});
});

describe('trigger with weekly frequency', () => {
const mocks = [getTriggerQuery('weekly'), ...LIST_ITEM_MOCKS, ...SearchMocks];

Expand Down
172 changes: 115 additions & 57 deletions src/containers/Trigger/Trigger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { useLocation } from 'react-router-dom';
import { useTranslation } from 'react-i18next';

import { ReactComponent as TriggerIcon } from 'assets/images/icons/Trigger/Union.svg';
import { dateList, dayList, FLOW_STATUS_PUBLISHED, setVariables } from 'common/constants';
import { dateList, dayList, FLOW_STATUS_PUBLISHED, hourList, setVariables } from 'common/constants';
import { FormLayout } from 'containers/Form/FormLayout';
import { AutoComplete } from 'components/UI/Form/AutoComplete/AutoComplete';
import { Loading } from 'components/UI/Layout/Loading/Loading';
Expand Down Expand Up @@ -37,6 +37,77 @@ const checkDateTimeValidation = (startAtValue: string, startDateValue: string) =
return true;
};

const setPayload = (payload: any) => {
const payloadCopy = payload;

const { startDate, startTime, isActive, flowId, frequencyValues, groupId, endDate, frequency } =
payloadCopy;
// covert the time to UTC
const startAt = moment(`
${moment(startDate).format('yyyy-MM-DD')}${startTime}`).utc();
const updatedPayload = {
isActive,
isRepeating: true,
flowId: flowId.id,
days: [],
hours: [],
groupId: groupId.id,
startDate: moment(startAt).utc().format('yyyy-MM-DD'),
endDate: moment(endDate).utc().format('yyyy-MM-DD'),
startTime: moment(startAt).utc().format('THH:mm:ss'),
frequency: frequency.value,
};

switch (updatedPayload.frequency) {
case 'weekly':
case 'monthly':
updatedPayload.days = frequencyValues.map((value: any) => value.id);
break;
case 'hourly':
updatedPayload.hours = frequencyValues.map((value: any) => value.id);
break;
case 'daily':
updatedPayload.days = [];
updatedPayload.hours = [];
break;
default:
updatedPayload.days = [];
updatedPayload.hours = [];
updatedPayload.isRepeating = false;
}

return updatedPayload;
};

const getFrequencyDetails = (
frequencyValue: string,
daysValue: Array<any>,
hoursValue: Array<any>
) => {
const frequencyDetails = {
values: [],
options: dayList,
placeholder: 'Select days',
};
switch (frequencyValue) {
case 'weekly':
frequencyDetails.values = dayList.filter((day: any) => daysValue.includes(day.id));
break;
case 'monthly':
frequencyDetails.values = dateList.filter((day: any) => daysValue.includes(day.id));
frequencyDetails.options = dateList;
frequencyDetails.placeholder = 'Select dates';
break;
case 'hourly':
frequencyDetails.values = hourList.filter((day: any) => hoursValue.includes(day.id));
frequencyDetails.options = hourList;
frequencyDetails.placeholder = 'Select hours';
break;
default:
}

return frequencyDetails;
};
export const Trigger: React.SFC<TriggerProps> = ({ match }) => {
let isEditing = false;
if (match.params.id) {
Expand All @@ -50,11 +121,12 @@ export const Trigger: React.SFC<TriggerProps> = ({ match }) => {
const [frequency, setfrequency] = useState<any>(null);
const [endDate, setEndDate] = useState('');
const [isRepeating, setIsRepeating] = useState('');
const [days, setDays] = useState([]);
const [frequencyValues, setFrequencyValues] = useState([]);
const [daysDisabled, setDaysDisabled] = useState(true);
const [groupId, setGroupId] = useState<any>(null);
const [minDate, setMinDate] = useState<any>(new Date());
const [monthly, setMonthly] = useState(false);
const [frequencyPlaceholder, setFrequencyPlaceholder] = useState('Select days');
const [frequencyOptions, setFrequencyOptions] = useState(dayList);

const location = useLocation();
const { t } = useTranslation();
Expand All @@ -65,13 +137,14 @@ export const Trigger: React.SFC<TriggerProps> = ({ match }) => {
frequency,
endDate,
isRepeating,
days,
frequencyValues,
groupId,
isActive,
};

const triggerFrequencyOptions = [
{ label: t('Does not repeat'), value: 'none' },
{ label: t('Hourly'), value: 'hourly' },
{ label: t('Daily'), value: 'daily' },
{ label: t('Weekly'), value: 'weekly' },
{ label: t('Monthly'), value: 'monthly' },
Expand Down Expand Up @@ -145,19 +218,26 @@ export const Trigger: React.SFC<TriggerProps> = ({ match }) => {

const handleFrequencyChange = (triggerFrequency: any) => {
if (!triggerFrequency) return;

const { value } = triggerFrequency;
if (value === 'weekly') {
setDaysDisabled(false);
setMonthly(false);
} else if (value === 'monthly') {
setDaysDisabled(false);
setMonthly(true);
} else {
setDaysDisabled(true);
setMonthly(false);
setDaysDisabled(false);

switch (value) {
case 'weekly':
setFrequencyPlaceholder(t('Select days'));
setFrequencyOptions(dayList);
break;
case 'monthly':
setFrequencyPlaceholder(t('Select dates'));
setFrequencyOptions(dateList);
break;
case 'hourly':
setFrequencyPlaceholder(t('Select hours'));
setFrequencyOptions(hourList);
break;
default:
setDaysDisabled(true);
}
setDays([]);
setFrequencyValues([]);
};

const formFields = [
Expand Down Expand Up @@ -222,20 +302,21 @@ export const Trigger: React.SFC<TriggerProps> = ({ match }) => {
},
{
component: AutoComplete,
name: 'days',
placeholder: monthly ? t('Select date') : t('Select days'),
options: monthly ? dateList : dayList,
name: 'frequencyValues',
placeholder: frequencyPlaceholder,
options: frequencyOptions,
disabled: isEditing || daysDisabled,
optionLabel: 'label',
textFieldProps: {
label: monthly ? t('Select dates') : t('Select days'),
label: frequencyPlaceholder,
variant: 'outlined',
},
helperText: monthly
? t(
'If you are selecting end of the month dates, then for the ones not present i.e. 30, 31, the selection will default to the last day of that month.'
)
: null,
helperText:
frequency === 'monthly'
? t(
'If you are selecting end of the month dates, then for the ones not present i.e. 30, 31, the selection will default to the last day of that month.'
)
: null,
},
{
component: AutoComplete,
Expand All @@ -254,6 +335,7 @@ export const Trigger: React.SFC<TriggerProps> = ({ match }) => {

const setStates = ({
days: daysValue,
hours: hoursValue,
endDate: endDateValue,
flow: flowValue,
frequency: frequencyValue,
Expand All @@ -265,12 +347,15 @@ export const Trigger: React.SFC<TriggerProps> = ({ match }) => {
setIsRepeating(isRepeatingValue);
setIsActive(isActiveValue);
setEndDate(moment(endDateValue).format('yyyy-MM-DD'));
let savedDays = dayList.filter((day: any) => daysValue.includes(day.id));
if (frequencyValue === 'monthly') {
setMonthly(true);
savedDays = dateList.filter((day: any) => daysValue.includes(day.id));
}
setDays(savedDays);

const { values, options, placeholder } = getFrequencyDetails(
frequencyValue,
daysValue,
hoursValue
);
setFrequencyValues(values);
setFrequencyOptions(options);
setFrequencyPlaceholder(placeholder);
setStartDate(moment(startAtValue).format('yyyy-MM-DD'));
// If a user wants to update the trigger
if (moment(new Date()).isAfter(startAtValue, 'days')) {
Expand All @@ -292,33 +377,6 @@ export const Trigger: React.SFC<TriggerProps> = ({ match }) => {
}
};

const setPayload = (payload: any) => {
const payloadCopy = payload;

// covert the time to UTC
const startAt = moment(`
${moment(payloadCopy.startDate).format('yyyy-MM-DD')}${payloadCopy.startTime}`).utc();
const newPayload = {
isActive: payloadCopy.isActive,
isRepeating: true,
flowId: payloadCopy.flowId.id,
days: payloadCopy.days.map((day: any) => day.id),
groupId: payloadCopy.groupId.id,
startDate: moment(startAt).utc().format('yyyy-MM-DD'),
endDate: moment(payloadCopy.endDate).utc().format('yyyy-MM-DD'),
startTime: moment(startAt).utc().format('THH:mm:ss'),
frequency: payloadCopy.frequency.value,
};

if (newPayload.frequency === 'none') {
newPayload.isRepeating = false;
newPayload.days = [];
} else if (newPayload.frequency === 'daily') {
newPayload.days = [];
}
return newPayload;
};

return (
<FormLayout
{...queries}
Expand Down
2 changes: 2 additions & 0 deletions src/graphql/mutations/Trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ export const CREATE_TRIGGER = gql`
}
id
isActive
hours
isRepeating
name
startAt
Expand All @@ -49,6 +50,7 @@ export const UPDATE_TRIGGER = gql`
}
id
isActive
hours
isRepeating
name
startAt
Expand Down
1 change: 1 addition & 0 deletions src/graphql/queries/Trigger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export const GET_TRIGGER = gql`
group {
id
}
hours
id
isActive
isRepeating
Expand Down
12 changes: 12 additions & 0 deletions src/mocks/Trigger.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ export const triggerListQuery = {
flow: { id: '1', name: 'Help Workflow' },
group: { id: '1', label: 'Optin contacts' },
endDate: '2021-03-13',
hours: [],
isActive: true,
isRepeating: true,
startAt: '2020-12-30T13:15:19Z',
Expand All @@ -38,6 +39,7 @@ export const triggerListQuery = {
group: { id: '1', label: 'Optin contacts' },
endDate: '2021-03-13',
isActive: false,
hours: [],
isRepeating: true,
startAt: '2020-12-30T13:15:19Z',
},
Expand Down Expand Up @@ -78,6 +80,7 @@ export const getTriggerQuery = (frequency: any) => ({
id: '1',
},
frequency,
hours: [],
group: {
id: '1',
},
Expand All @@ -90,3 +93,12 @@ export const getTriggerQuery = (frequency: any) => ({
},
},
});

const hourlyTrigger = () => {
const hourlyTrigger: any = getTriggerQuery('hourly');
hourlyTrigger.result.data.trigger.trigger.days = [];
hourlyTrigger.result.data.trigger.trigger.hours = [1, 13];
return hourlyTrigger;
};

export { hourlyTrigger };

0 comments on commit adc6754

Please sign in to comment.