Commit 1c1ba73d authored by Olena Horal-Koretska's avatar Olena Horal-Koretska

Restrict rotation to time

parent 4e249f7e
......@@ -39,6 +39,10 @@ export const i18n = {
enableToggle: s__('OnCallSchedules|Enable end date'),
title: __('Ends on'),
},
restrictToTime: {
enableToggle: s__('OnCallSchedules|Restrict to time intervals'),
title: s__('OnCallSchedules|For this rotation, on-call will be:'),
},
},
};
......@@ -91,6 +95,7 @@ export default {
return {
participantsArr: [],
endDateEnabled: false,
restrictToTimeEnabled: false,
};
},
methods: {
......@@ -100,7 +105,8 @@ export default {
</script>
<template>
<gl-form class="w-75 gl-xs-w-full!" @submit.prevent="createRotation">
<gl-form @submit.prevent="createRotation">
<div class="w-75 gl-xs-w-full!">
<gl-form-group
:label="$options.i18n.fields.name.title"
label-size="sm"
......@@ -176,7 +182,6 @@ export default {
<gl-form-group
:label="$options.i18n.fields.startsAt.title"
label-size="sm"
label-for="rotation-start-time"
:invalid-feedback="$options.i18n.fields.startsAt.error"
:state="validationState.startsAt"
>
......@@ -191,14 +196,17 @@ export default {
:value="formattedDate"
:placeholder="__(`YYYY-MM-DD`)"
@blur="
$emit('update-rotation-form', { type: 'startsAt.date', value: $event.target.value })
$emit('update-rotation-form', {
type: 'startsAt.date',
value: $event.target.value,
})
"
/>
</template>
</gl-datepicker>
<span> {{ __('at') }} </span>
<gl-dropdown
id="rotation-start-time"
data-testid="rotation-start-time"
:text="format24HourTimeStringFromInt(form.startsAt.time)"
class="gl-w-12 gl-pl-3"
>
......@@ -215,6 +223,7 @@ export default {
<span class="gl-pl-5"> {{ schedule.timezone }} </span>
</div>
</gl-form-group>
</div>
<gl-toggle
v-model="endDateEnabled"
......@@ -223,11 +232,10 @@ export default {
class="gl-mb-5"
/>
<gl-card v-if="endDateEnabled" class="gl-min-w-fit-content" data-testid="rotation-ends-on">
<gl-card v-if="endDateEnabled" data-testid="rotation-ends-on">
<gl-form-group
:label="$options.i18n.fields.endsOn.title"
label-size="sm"
label-for="rotation-end-time"
:invalid-feedback="$options.i18n.fields.endsOn.error"
>
<div class="gl-display-flex gl-align-items-center">
......@@ -237,7 +245,7 @@ export default {
/>
<span> {{ __('at') }} </span>
<gl-dropdown
id="rotation-end-time"
data-testid="rotation-end-time"
:text="format24HourTimeStringFromInt(form.endsOn.time)"
class="gl-w-12 gl-pl-3"
>
......@@ -255,5 +263,56 @@ export default {
</div>
</gl-form-group>
</gl-card>
<gl-toggle
v-model="restrictToTimeEnabled"
data-testid="restricted-to-toggle"
:label="$options.i18n.fields.restrictToTime.enableToggle"
label-position="left"
class="gl-my-5"
/>
<gl-card v-if="restrictToTimeEnabled" data-testid="restricted-to-time">
<gl-form-group
:label="$options.i18n.fields.restrictToTime.title"
label-size="sm"
:invalid-feedback="$options.i18n.fields.endsOn.error"
>
<div class="gl-display-flex gl-align-items-center">
<span> {{ __('From') }} </span>
<gl-dropdown
data-testid="restricted-from"
:text="format24HourTimeStringFromInt(form.restrictedTo.from)"
class="gl-px-3"
>
<gl-dropdown-item
v-for="time in $options.HOURS_IN_DAY"
:key="time"
:is-checked="form.restrictedTo.from === time"
is-check-item
@click="$emit('update-rotation-form', { type: 'restrictedTo.from', value: time })"
>
<span class="gl-white-space-nowrap"> {{ format24HourTimeStringFromInt(time) }}</span>
</gl-dropdown-item>
</gl-dropdown>
<span> {{ __('To') }} </span>
<gl-dropdown
data-testid="restricted-to"
:text="format24HourTimeStringFromInt(form.restrictedTo.to)"
class="gl-px-3"
>
<gl-dropdown-item
v-for="time in $options.HOURS_IN_DAY"
:key="time"
:is-checked="form.restrictedTo.to === time"
is-check-item
@click="$emit('update-rotation-form', { type: 'restrictedTo.to', value: time })"
>
<span class="gl-white-space-nowrap"> {{ format24HourTimeStringFromInt(time) }}</span>
</gl-dropdown-item>
</gl-dropdown>
</div>
</gl-form-group>
</gl-card>
</gl-form>
</template>
......@@ -84,6 +84,10 @@ export default {
date: null,
time: 0,
},
restrictedTo: {
from: 0,
to: 0,
},
},
error: '',
validationState: {
......
......@@ -44,6 +44,10 @@ describe('AddEditRotationForm', () => {
date: null,
time: 0,
},
restrictedTo: {
from: 0,
to: 0,
},
},
},
provide: {
......@@ -63,14 +67,20 @@ describe('AddEditRotationForm', () => {
});
const findRotationLength = () => wrapper.find('[id="rotation-length"]');
const findRotationStartTime = () => wrapper.find('[id="rotation-start-time"]');
const findRotationStartTime = () => wrapper.find('[data-testid="rotation-start-time"]');
const findRotationEndsContainer = () => wrapper.find('[data-testid="rotation-ends-on"]');
const findEndDateToggle = () => wrapper.find(GlToggle);
const findRotationEndTime = () => wrapper.find('[id="rotation-end-time"]');
const findRotationEndTime = () => wrapper.find('[data-testid="rotation-end-time"]');
const findUserSelector = () => wrapper.find(GlTokenSelector);
const findRotationFormGroups = () => wrapper.findAllComponents(GlFormGroup);
const findStartsOnTimeOptions = () => findRotationStartTime().findAllComponents(GlDropdownItem);
const findEndsOnTimeOptions = () => findRotationEndTime().findAllComponents(GlDropdownItem);
const findRestrictedToTime = () => wrapper.find('[data-testid="restricted-to-time"]');
const findRestrictedToToggle = () => wrapper.find('[data-testid="restricted-to-toggle"]');
const findRestrictedFromOptions = () =>
wrapper.find('[data-testid="restricted-from"]').findAllComponents(GlDropdownItem);
const findRestrictedToOptions = () =>
wrapper.find('[data-testid="restricted-to"]').findAllComponents(GlDropdownItem);
describe('Rotation form validation', () => {
it.each`
......@@ -179,6 +189,68 @@ describe('AddEditRotationForm', () => {
});
});
describe('Rotation restricted to time', () => {
it('toggles restricted to time visibility', async () => {
const toggle = findRestrictedToToggle().vm;
toggle.$emit('change', false);
await wrapper.vm.$nextTick();
expect(findRestrictedToTime().exists()).toBe(false);
toggle.$emit('change', true);
await wrapper.vm.$nextTick();
expect(findRestrictedToTime().exists()).toBe(true);
});
it('should emit an event with selected value on restricted FROM time selection', async () => {
findRestrictedToToggle().vm.$emit('change', true);
await wrapper.vm.$nextTick();
const timeFrom = 5;
const timeTo = 22;
findRestrictedFromOptions().at(timeFrom).vm.$emit('click');
findRestrictedToOptions().at(timeTo).vm.$emit('click');
await wrapper.vm.$nextTick();
const emittedEvent = wrapper.emitted('update-rotation-form');
expect(emittedEvent).toHaveLength(2);
expect(emittedEvent[0][0]).toEqual({ type: 'restrictedTo.from', value: timeFrom + 1 });
expect(emittedEvent[1][0]).toEqual({ type: 'restrictedTo.to', value: timeTo + 1 });
});
it('should add a checkmark to a selected restricted FROM time', async () => {
findRestrictedToToggle().vm.$emit('change', true);
const timeFrom = 5;
const timeTo = 22;
wrapper.setProps({
form: {
endsOn: {
time: 0,
},
startsAt: {
time: 0,
},
restrictedTo: {
from: timeFrom,
to: timeTo,
},
rotationLength: {
length: 1,
unit: LENGTH_ENUM.hours,
},
},
});
await wrapper.vm.$nextTick();
expect(
findRestrictedFromOptions()
.at(timeFrom - 1)
.props('isChecked'),
).toBe(true);
expect(
findRestrictedToOptions()
.at(timeTo - 1)
.props('isChecked'),
).toBe(true);
});
});
describe('filter participants', () => {
beforeEach(() => {
createComponent();
......
......@@ -19606,12 +19606,18 @@ msgstr ""
msgid "OnCallSchedules|Failed to edit schedule"
msgstr ""
msgid "OnCallSchedules|For this rotation, on-call will be:"
msgstr ""
msgid "OnCallSchedules|On-call schedule"
msgstr ""
msgid "OnCallSchedules|On-call schedule for the %{timezone}"
msgstr ""
msgid "OnCallSchedules|Restrict to time intervals"
msgstr ""
msgid "OnCallSchedules|Rotation length"
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment