Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
gitlab-ce
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
1
Merge Requests
1
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
nexedi
gitlab-ce
Commits
80c02ae6
Commit
80c02ae6
authored
Mar 03, 2021
by
Olena Horal-Koretska
Committed by
Phil Hughes
Mar 03, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Create rotation with endsAt date - integration
parent
f1954931
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
219 additions
and
23 deletions
+219
-23
ee/app/assets/javascripts/oncall_schedules/components/rotations/components/add_edit_rotation_form.vue
...omponents/rotations/components/add_edit_rotation_form.vue
+26
-10
ee/app/assets/javascripts/oncall_schedules/components/rotations/components/add_edit_rotation_modal.vue
...mponents/rotations/components/add_edit_rotation_modal.vue
+30
-5
ee/app/assets/javascripts/oncall_schedules/graphql/fragments/oncall_schedule_rotation.fragment.graphql
...aphql/fragments/oncall_schedule_rotation.fragment.graphql
+1
-0
ee/spec/frontend/oncall_schedule/mocks/apollo_mock.js
ee/spec/frontend/oncall_schedule/mocks/apollo_mock.js
+4
-2
ee/spec/frontend/oncall_schedule/mocks/mock_rotation.json
ee/spec/frontend/oncall_schedule/mocks/mock_rotation.json
+4
-0
ee/spec/frontend/oncall_schedule/rotations/components/add_edit_rotation_form_spec.js
...edule/rotations/components/add_edit_rotation_form_spec.js
+4
-4
ee/spec/frontend/oncall_schedule/rotations/components/add_edit_rotation_modal_spec.js
...dule/rotations/components/add_edit_rotation_modal_spec.js
+147
-2
locale/gitlab.pot
locale/gitlab.pot
+3
-0
No files found.
ee/app/assets/javascripts/oncall_schedules/components/rotations/components/add_edit_rotation_form.vue
View file @
80c02ae6
...
...
@@ -40,9 +40,10 @@ export const i18n = {
title
:
__
(
'
Starts on
'
),
error
:
s__
(
'
OnCallSchedules|Rotation start date cannot be empty
'
),
},
ends
On
:
{
ends
At
:
{
enableToggle
:
s__
(
'
OnCallSchedules|Enable end date
'
),
title
:
__
(
'
Ends on
'
),
error
:
s__
(
'
OnCallSchedules|Rotation end date/time must come after start date/time
'
),
},
restrictToTime
:
{
enableToggle
:
s__
(
'
OnCallSchedules|Restrict to time intervals
'
),
...
...
@@ -234,7 +235,7 @@ export default {
<div
class=
"gl-display-inline-block"
>
<gl-toggle
v-model=
"endDateEnabled"
:label=
"$options.i18n.fields.ends
On
.enableToggle"
:label=
"$options.i18n.fields.ends
At
.enableToggle"
label-position=
"left"
class=
"gl-mb-5"
/>
...
...
@@ -245,28 +246,43 @@ export default {
class=
"gl-border-gray-400 gl-bg-gray-10"
>
<gl-form-group
:label=
"$options.i18n.fields.ends
On
.title"
:label=
"$options.i18n.fields.ends
At
.title"
label-size=
"sm"
:invalid-feedback=
"$options.i18n.fields.endsOn.error"
:state=
"validationState.endsAt"
:invalid-feedback=
"$options.i18n.fields.endsAt.error"
class=
"gl-mb-0"
>
<div
class=
"gl-display-flex gl-align-items-center"
>
<gl-datepicker
class=
"gl-mr-3"
@
input=
"$emit('update-rotation-form', { type: 'endsOn.date', value: $event })"
@
input=
"$emit('update-rotation-form', { type: 'endsAt.date', value: $event })"
>
<
template
#default=
"{ formattedDate }"
>
<gl-form-input
class=
"gl-w-full"
:value=
"formattedDate"
:placeholder=
"__(`YYYY-MM-DD`)"
@
blur=
"
$emit('update-rotation-form',
{
type: 'endsAt.date',
value: $event.target.value,
})
"
/>
</
template
>
</gl-datepicker>
<span>
{{ __('at') }}
</span>
<gl-dropdown
data-testid=
"rotation-end-time"
:text=
"format24HourTimeStringFromInt(form.ends
On
.time)"
:text=
"format24HourTimeStringFromInt(form.ends
At
.time)"
class=
"gl-px-3"
>
<gl-dropdown-item
v-for=
"time in $options.HOURS_IN_DAY"
:key=
"time"
:is-checked=
"form.ends
On
.time === time"
:is-checked=
"form.ends
At
.time === time"
is-check-item
@
click=
"$emit('update-rotation-form', { type: 'ends
On
.time', value: time })"
@
click=
"$emit('update-rotation-form', { type: 'ends
At
.time', value: time })"
>
<span
class=
"gl-white-space-nowrap"
>
{{ format24HourTimeStringFromInt(time) }}
</span
...
...
@@ -294,7 +310,7 @@ export default {
<gl-form-group
:label=
"$options.i18n.fields.restrictToTime.title"
label-size=
"sm"
:invalid-feedback=
"$options.i18n.fields.ends
On
.error"
:invalid-feedback=
"$options.i18n.fields.ends
At
.error"
class=
"gl-mb-0"
>
<div
class=
"gl-display-flex gl-align-items-center"
>
...
...
ee/app/assets/javascripts/oncall_schedules/components/rotations/components/add_edit_rotation_modal.vue
View file @
80c02ae6
...
...
@@ -78,7 +78,7 @@ export default {
date
:
null
,
time
:
0
,
},
ends
On
:
{
ends
At
:
{
date
:
null
,
time
:
0
,
},
...
...
@@ -92,6 +92,7 @@ export default {
name
:
true
,
participants
:
true
,
startsAt
:
true
,
endsAt
:
true
,
},
};
},
...
...
@@ -129,7 +130,8 @@ export default {
name
,
rotationLength
,
participants
,
startsAt
:
{
date
,
time
},
startsAt
:
{
date
:
startDate
,
time
:
startTime
},
endsAt
:
{
date
:
endDate
,
time
:
endTime
},
}
=
this
.
form
;
return
{
...
...
@@ -137,9 +139,15 @@ export default {
scheduleIid
:
this
.
schedule
.
iid
,
name
,
startsAt
:
{
date
:
formatDate
(
d
ate
,
'
yyyy-mm-dd
'
),
time
:
format24HourTimeStringFromInt
(
t
ime
),
date
:
formatDate
(
startD
ate
,
'
yyyy-mm-dd
'
),
time
:
format24HourTimeStringFromInt
(
startT
ime
),
},
endsAt
:
endDate
?
{
date
:
formatDate
(
endDate
,
'
yyyy-mm-dd
'
),
time
:
format24HourTimeStringFromInt
(
endTime
),
}
:
null
,
rotationLength
:
{
...
rotationLength
,
length
:
parseInt
(
rotationLength
.
length
,
10
),
...
...
@@ -150,6 +158,20 @@ export default {
title
()
{
return
this
.
isEditMode
?
this
.
$options
.
i18n
.
editRotation
:
this
.
$options
.
i18n
.
addRotation
;
},
isEndDateValid
()
{
const
startsAt
=
this
.
form
.
startsAt
.
date
?.
getTime
();
const
endsAt
=
this
.
form
.
endsAt
.
date
?.
getTime
();
if
(
!
startsAt
||
!
endsAt
)
{
// If start or end is not present, we consider the end date valid
return
true
;
}
else
if
(
startsAt
<
endsAt
)
{
return
true
;
}
else
if
(
startsAt
===
endsAt
)
{
return
this
.
form
.
startsAt
.
time
<
this
.
form
.
endsAt
.
time
;
}
return
false
;
},
},
methods
:
{
createRotation
()
{
...
...
@@ -244,8 +266,11 @@ export default {
this
.
validationState
.
name
=
isNameFieldValid
(
this
.
form
.
name
);
}
else
if
(
key
===
'
participants
'
)
{
this
.
validationState
.
participants
=
this
.
form
.
participants
.
length
>
0
;
}
else
if
(
key
===
'
startsAt.date
'
)
{
}
else
if
(
key
===
'
startsAt.date
'
||
key
===
'
startsAt.time
'
)
{
this
.
validationState
.
startsAt
=
Boolean
(
this
.
form
.
startsAt
.
date
);
this
.
validationState
.
endsAt
=
this
.
isEndDateValid
;
}
else
if
(
key
===
'
endsAt.date
'
||
key
===
'
endsAt.time
'
)
{
this
.
validationState
.
endsAt
=
this
.
isEndDateValid
;
}
},
},
...
...
ee/app/assets/javascripts/oncall_schedules/graphql/fragments/oncall_schedule_rotation.fragment.graphql
View file @
80c02ae6
...
...
@@ -4,6 +4,7 @@ fragment OnCallRotation on IncidentManagementOncallRotation {
id
name
startsAt
endsAt
length
lengthUnit
participants
{
...
...
ee/spec/frontend/oncall_schedule/mocks/apollo_mock.js
View file @
80c02ae6
...
...
@@ -138,7 +138,8 @@ export const createRotationResponse = {
oncallRotation
:
{
id
:
'
44
'
,
name
:
'
Test
'
,
startsAt
:
'
2020-12-17T12:00:00Z
'
,
startsAt
:
'
2020-12-20T12:00:00Z
'
,
endsAt
:
'
2021-03-17T12:00:00Z
'
,
length
:
5
,
lengthUnit
:
'
WEEKS
'
,
participants
:
{
...
...
@@ -171,7 +172,8 @@ export const createRotationResponseWithErrors = {
oncallRotation
:
{
id
:
'
44
'
,
name
:
'
Test
'
,
startsAt
:
'
2020-12-17T12:00:00Z
'
,
startsAt
:
'
2020-12-20T12:00:00Z
'
,
endsAt
:
'
2021-03-17T12:00:00Z
'
,
length
:
5
,
lengthUnit
:
'
WEEKS
'
,
participants
:
{
...
...
ee/spec/frontend/oncall_schedule/mocks/mock_rotation.json
View file @
80c02ae6
...
...
@@ -2,6 +2,7 @@
"id"
:
"gid://gitlab/IncidentManagement::OncallRotation/2"
,
"name"
:
"Rotation 242"
,
"startsAt"
:
"2021-01-13T10:04:56.333Z"
,
"endsAt"
:
"2021-03-13T10:04:56.333Z"
,
"length"
:
1
,
"lengthUnit"
:
"WEEKS"
,
"participants"
:
{
...
...
@@ -54,6 +55,7 @@
"id"
:
"gid://gitlab/IncidentManagement::OncallRotation/55"
,
"name"
:
"Rotation 242"
,
"startsAt"
:
"2021-01-13T10:04:56.333Z"
,
"endsAt"
:
"2021-03-13T10:04:56.333Z"
,
"length"
:
1
,
"lengthUnit"
:
"WEEKS"
,
"participants"
:
{
...
...
@@ -102,6 +104,7 @@
"id"
:
"gid://gitlab/IncidentManagement::OncallRotation/3"
,
"name"
:
"Rotation 244"
,
"startsAt"
:
"2021-01-06T10:04:56.333Z"
,
"endsAt"
:
"2021-01-10T10:04:56.333Z"
,
"length"
:
1
,
"lengthUnit"
:
"WEEKS"
,
"participants"
:
{
...
...
@@ -150,6 +153,7 @@
"id"
:
"gid://gitlab/IncidentManagement::OncallRotation/5"
,
"name"
:
"Rotation 247"
,
"startsAt"
:
"2021-01-06T10:04:56.333Z"
,
"endsAt"
:
"2021-01-11T10:04:56.333Z"
,
"length"
:
1
,
"lengthUnit"
:
"WEEKS"
,
"participants"
:
{
...
...
ee/spec/frontend/oncall_schedule/rotations/components/add_edit_rotation_form_spec.js
View file @
80c02ae6
...
...
@@ -40,7 +40,7 @@ describe('AddEditRotationForm', () => {
date
:
null
,
time
:
0
,
},
ends
On
:
{
ends
At
:
{
date
:
null
,
time
:
0
,
},
...
...
@@ -160,7 +160,7 @@ describe('AddEditRotationForm', () => {
await
wrapper
.
vm
.
$nextTick
();
const
emittedEvent
=
wrapper
.
emitted
(
'
update-rotation-form
'
);
expect
(
emittedEvent
).
toHaveLength
(
1
);
expect
(
emittedEvent
[
0
][
0
]).
toEqual
({
type
:
'
ends
On
.time
'
,
value
:
option
+
1
});
expect
(
emittedEvent
[
0
][
0
]).
toEqual
({
type
:
'
ends
At
.time
'
,
value
:
option
+
1
});
});
it
(
'
should add a checkmark to a selected end time
'
,
async
()
=>
{
...
...
@@ -168,7 +168,7 @@ describe('AddEditRotationForm', () => {
const
time
=
5
;
wrapper
.
setProps
({
form
:
{
ends
On
:
{
ends
At
:
{
time
,
},
startsAt
:
{
...
...
@@ -221,7 +221,7 @@ describe('AddEditRotationForm', () => {
wrapper
.
setProps
({
form
:
{
ends
On
:
{
ends
At
:
{
time
:
0
,
},
startsAt
:
{
...
...
ee/spec/frontend/oncall_schedule/rotations/components/add_edit_rotation_modal_spec.js
View file @
80c02ae6
import
{
GlModal
,
GlAlert
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
AddEditRotationForm
from
'
ee/oncall_schedules/components/rotations/components/add_edit_rotation_form.vue
'
;
import
AddEditRotationModal
,
{
i18n
,
}
from
'
ee/oncall_schedules/components/rotations/components/add_edit_rotation_modal.vue
'
;
...
...
@@ -129,8 +130,9 @@ describe('AddEditRotationModal', () => {
wrapper
=
null
;
});
const
findModal
=
()
=>
wrapper
.
find
(
GlModal
);
const
findAlert
=
()
=>
wrapper
.
find
(
GlAlert
);
const
findModal
=
()
=>
wrapper
.
findComponent
(
GlModal
);
const
findAlert
=
()
=>
wrapper
.
findComponent
(
GlAlert
);
const
findForm
=
()
=>
wrapper
.
findComponent
(
AddEditRotationForm
);
it
(
'
renders rotation modal layout
'
,
()
=>
{
expect
(
wrapper
.
element
).
toMatchSnapshot
();
...
...
@@ -155,6 +157,149 @@ describe('AddEditRotationModal', () => {
expect
(
findAlert
().
exists
()).
toBe
(
true
);
expect
(
findAlert
().
text
()).
toContain
(
error
);
});
describe
(
'
Validation
'
,
()
=>
{
describe
(
'
name
'
,
()
=>
{
it
(
'
is valid when name is NOT empty
'
,
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
name
'
,
value
:
''
});
expect
(
form
.
props
(
'
validationState
'
).
name
).
toBe
(
false
);
});
it
(
'
is NOT valid when name is empty
'
,
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
name
'
,
value
:
'
Some value
'
});
expect
(
form
.
props
(
'
validationState
'
).
name
).
toBe
(
true
);
});
});
describe
(
'
participants
'
,
()
=>
{
it
(
'
is valid when participants array is NOT empty
'
,
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
participants
'
,
value
:
[
'
user1
'
,
'
user2
'
],
});
expect
(
form
.
props
(
'
validationState
'
).
participants
).
toBe
(
true
);
});
it
(
'
is NOT valid when participants array is empty
'
,
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
participants
'
,
value
:
[]
});
expect
(
form
.
props
(
'
validationState
'
).
participants
).
toBe
(
false
);
});
});
describe
(
'
startsAt date
'
,
()
=>
{
it
(
'
is valid when date is NOT empty
'
,
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
startsAt.date
'
,
value
:
new
Date
(
'
10/12/2021
'
),
});
expect
(
form
.
props
(
'
validationState
'
).
startsAt
).
toBe
(
true
);
});
it
(
'
is NOT valid when date is empty
'
,
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
startsAt.time
'
,
value
:
null
});
expect
(
form
.
props
(
'
validationState
'
).
startsAt
).
toBe
(
false
);
});
});
describe
(
'
endsAt date
'
,
()
=>
{
it
(
'
is valid when date is empty
'
,
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
endsAt.date
'
,
value
:
null
});
expect
(
form
.
props
(
'
validationState
'
).
endsAt
).
toBe
(
true
);
});
it
(
'
is valid when start date is smaller then end date
'
,
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
startsAt.date
'
,
value
:
new
Date
(
'
9/11/2021
'
),
});
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
endsAt.date
'
,
value
:
new
Date
(
'
10/11/2021
'
),
});
expect
(
form
.
props
(
'
validationState
'
).
endsAt
).
toBe
(
true
);
});
it
(
'
is invalid when start date is larger then end date
'
,
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
startsAt.date
'
,
value
:
new
Date
(
'
11/11/2021
'
),
});
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
endsAt.date
'
,
value
:
new
Date
(
'
10/11/2021
'
),
});
expect
(
form
.
props
(
'
validationState
'
).
endsAt
).
toBe
(
false
);
});
it
(
'
is valid when start and end dates are equal but time is smaller on start date
'
,
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
startsAt.date
'
,
value
:
new
Date
(
'
11/11/2021
'
),
});
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
startsAt.time
'
,
value
:
10
});
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
endsAt.date
'
,
value
:
new
Date
(
'
11/11/2021
'
),
});
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
endsAt.time
'
,
value
:
22
});
expect
(
form
.
props
(
'
validationState
'
).
endsAt
).
toBe
(
true
);
});
it
(
'
is invalid when start and end dates are equal but time is larger on start date
'
,
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
startsAt.date
'
,
value
:
new
Date
(
'
11/11/2021
'
),
});
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
startsAt.time
'
,
value
:
10
});
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
endsAt.date
'
,
value
:
new
Date
(
'
11/11/2021
'
),
});
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
endsAt.time
'
,
value
:
8
});
expect
(
form
.
props
(
'
validationState
'
).
endsAt
).
toBe
(
false
);
});
});
describe
(
'
Toggle primary button state
'
,
()
=>
{
it
(
'
should disable primary button when any of the fields is invalid
'
,
async
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
name
'
,
value
:
'
lalal
'
});
await
wrapper
.
vm
.
$nextTick
();
expect
(
findModal
().
props
(
'
actionPrimary
'
).
attributes
).
toEqual
(
expect
.
arrayContaining
([{
disabled
:
true
}]),
);
});
it
(
'
should enable primary button when all fields are valid
'
,
async
()
=>
{
const
form
=
findForm
();
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
name
'
,
value
:
'
Value
'
});
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
participants
'
,
value
:
[
1
,
2
,
3
]
});
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
startsAt.date
'
,
value
:
new
Date
(
'
11/10/2021
'
),
});
form
.
vm
.
$emit
(
'
update-rotation-form
'
,
{
type
:
'
endsAt.date
'
,
value
:
new
Date
(
'
12/10/2021
'
),
});
await
wrapper
.
vm
.
$nextTick
();
expect
(
findModal
().
props
(
'
actionPrimary
'
).
attributes
).
toEqual
(
expect
.
arrayContaining
([{
disabled
:
false
}]),
);
});
});
});
});
describe
(
'
with mocked Apollo client
'
,
()
=>
{
...
...
locale/gitlab.pot
View file @
80c02ae6
...
...
@@ -20942,6 +20942,9 @@ msgstr ""
msgid "OnCallSchedules|Restrict to time intervals"
msgstr ""
msgid "OnCallSchedules|Rotation end date/time must come after start date/time"
msgstr ""
msgid "OnCallSchedules|Rotation length"
msgstr ""
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment