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
f23a606c
Commit
f23a606c
authored
Jun 04, 2021
by
Olena Horal-Koretska
Committed by
Ezekiel Kigbo
Jun 04, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Update validation for escalation rule
parent
9641dac4
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
104 additions
and
59 deletions
+104
-59
app/assets/stylesheets/page_bundles/escalation_policies.scss
app/assets/stylesheets/page_bundles/escalation_policies.scss
+0
-4
ee/app/assets/javascripts/escalation_policies/components/add_edit_escalation_policy_form.vue
...n_policies/components/add_edit_escalation_policy_form.vue
+5
-5
ee/app/assets/javascripts/escalation_policies/components/add_edit_escalation_policy_modal.vue
..._policies/components/add_edit_escalation_policy_modal.vue
+16
-10
ee/app/assets/javascripts/escalation_policies/components/escalation_rule.vue
...cripts/escalation_policies/components/escalation_rule.vue
+30
-13
ee/app/assets/javascripts/escalation_policies/utils.js
ee/app/assets/javascripts/escalation_policies/utils.js
+6
-1
ee/spec/frontend/escalation_policies/add_edit_escalation_policy_form_spec.js
...calation_policies/add_edit_escalation_policy_form_spec.js
+1
-15
ee/spec/frontend/escalation_policies/escalation_rule_spec.js
ee/spec/frontend/escalation_policies/escalation_rule_spec.js
+43
-11
locale/gitlab.pot
locale/gitlab.pot
+3
-0
No files found.
app/assets/stylesheets/page_bundles/escalation_policies.scss
View file @
f23a606c
...
@@ -6,10 +6,6 @@
...
@@ -6,10 +6,6 @@
width
:
240px
;
width
:
240px
;
}
}
.rule-elapsed-minutes
{
width
:
56px
;
}
.rule-close-icon
{
.rule-close-icon
{
right
:
1rem
;
right
:
1rem
;
}
}
ee/app/assets/javascripts/escalation_policies/components/add_edit_escalation_policy_form.vue
View file @
f23a606c
...
@@ -81,14 +81,14 @@ export default {
...
@@ -81,14 +81,14 @@ export default {
this
.
rules
.
push
({
...
cloneDeep
(
defaultEscalationRule
),
key
:
this
.
getUid
()
});
this
.
rules
.
push
({
...
cloneDeep
(
defaultEscalationRule
),
key
:
this
.
getUid
()
});
},
},
updateEscalationRules
(
index
,
rule
)
{
updateEscalationRules
(
index
,
rule
)
{
this
.
rules
[
index
]
=
rule
;
this
.
rules
[
index
]
=
{
...
this
.
rules
[
index
],
...
rule
}
;
this
.
emitUpdate
();
this
.
emit
Rules
Update
();
},
},
removeEscalationRule
(
index
)
{
removeEscalationRule
(
index
)
{
this
.
rules
.
splice
(
index
,
1
);
this
.
rules
.
splice
(
index
,
1
);
this
.
emitUpdate
();
this
.
emit
Rules
Update
();
},
},
emitUpdate
()
{
emit
Rules
Update
()
{
this
.
$emit
(
'
update-escalation-policy-form
'
,
{
field
:
'
rules
'
,
value
:
this
.
rules
});
this
.
$emit
(
'
update-escalation-policy-form
'
,
{
field
:
'
rules
'
,
value
:
this
.
rules
});
},
},
getUid
()
{
getUid
()
{
...
@@ -146,7 +146,7 @@ export default {
...
@@ -146,7 +146,7 @@ export default {
:index=
"index"
:index=
"index"
:schedules=
"schedules"
:schedules=
"schedules"
:schedules-loading=
"schedulesLoading"
:schedules-loading=
"schedulesLoading"
:
is-valid
=
"validationState.rules[index]"
:
validation-state
=
"validationState.rules[index]"
@
update-escalation-rule=
"updateEscalationRules"
@
update-escalation-rule=
"updateEscalationRules"
@
remove-escalation-rule=
"removeEscalationRule"
@
remove-escalation-rule=
"removeEscalationRule"
/>
/>
...
...
ee/app/assets/javascripts/escalation_policies/components/add_edit_escalation_policy_modal.vue
View file @
f23a606c
...
@@ -61,15 +61,12 @@ export default {
...
@@ -61,15 +61,12 @@ export default {
};
};
},
},
isFormValid
()
{
isFormValid
()
{
return
this
.
validationState
.
name
&&
this
.
validationState
.
rules
.
every
(
Boolean
);
return
(
},
this
.
validationState
.
name
&&
serializedData
()
{
this
.
validationState
.
rules
.
every
(
const
rules
=
this
.
form
.
rules
.
map
(({
status
,
elapsedTimeSeconds
,
oncallScheduleIid
})
=>
({
({
isTimeValid
,
isScheduleValid
})
=>
isTimeValid
&&
isScheduleValid
,
status
,
)
elapsedTimeSeconds
,
);
oncallScheduleIid
,
}));
return
{
...
this
.
form
,
rules
};
},
},
},
},
methods
:
{
methods
:
{
...
@@ -86,7 +83,7 @@ export default {
...
@@ -86,7 +83,7 @@ export default {
variables
:
{
variables
:
{
input
:
{
input
:
{
projectPath
,
projectPath
,
...
this
.
serializedData
,
...
this
.
getRequestParams
()
,
},
},
},
},
})
})
...
@@ -113,6 +110,15 @@ export default {
...
@@ -113,6 +110,15 @@ export default {
this
.
loading
=
false
;
this
.
loading
=
false
;
});
});
},
},
getRequestParams
()
{
const
rules
=
this
.
form
.
rules
.
map
(({
status
,
elapsedTimeSeconds
,
oncallScheduleIid
})
=>
({
status
,
elapsedTimeSeconds
,
oncallScheduleIid
,
}));
return
{
...
this
.
form
,
rules
};
},
validateForm
(
field
)
{
validateForm
(
field
)
{
if
(
field
===
'
name
'
)
{
if
(
field
===
'
name
'
)
{
this
.
validationState
.
name
=
isNameFieldValid
(
this
.
form
.
name
);
this
.
validationState
.
name
=
isNameFieldValid
(
this
.
form
.
name
);
...
...
ee/app/assets/javascripts/escalation_policies/components/escalation_rule.vue
View file @
f23a606c
...
@@ -19,13 +19,16 @@ export const i18n = {
...
@@ -19,13 +19,16 @@ export const i18n = {
condition
:
s__
(
'
EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes
'
),
condition
:
s__
(
'
EscalationPolicies|IF alert is not %{alertStatus} in %{minutes} minutes
'
),
action
:
s__
(
'
EscalationPolicies|THEN %{doAction} %{schedule}
'
),
action
:
s__
(
'
EscalationPolicies|THEN %{doAction} %{schedule}
'
),
selectSchedule
:
s__
(
'
EscalationPolicies|Select schedule
'
),
selectSchedule
:
s__
(
'
EscalationPolicies|Select schedule
'
),
validationMsg
:
s__
(
'
EscalationPolicies|A schedule is required for adding an escalation policy.
'
,
),
noSchedules
:
s__
(
noSchedules
:
s__
(
'
EscalationPolicies|A schedule is required for adding an escalation policy. Please create an on-call schedule first.
'
,
'
EscalationPolicies|A schedule is required for adding an escalation policy. Please create an on-call schedule first.
'
,
),
),
removeRuleLabel
:
s__
(
'
EscalationPolicies|Remove escalation rule
'
),
removeRuleLabel
:
s__
(
'
EscalationPolicies|Remove escalation rule
'
),
emptyScheduleValidationMsg
:
s__
(
'
EscalationPolicies|A schedule is required for adding an escalation policy.
'
,
),
invalidTimeValidationMsg
:
s__
(
'
EscalationPolicies|Elapsed time must be greater than or equal to zero.
'
,
),
},
},
},
},
};
};
...
@@ -66,10 +69,10 @@ export default {
...
@@ -66,10 +69,10 @@ export default {
type
:
Number
,
type
:
Number
,
required
:
true
,
required
:
true
,
},
},
isValid
:
{
validationState
:
{
type
:
Boolean
,
type
:
Object
,
required
:
false
,
required
:
false
,
default
:
true
,
default
:
()
=>
{}
,
},
},
},
},
data
()
{
data
()
{
...
@@ -90,6 +93,15 @@ export default {
...
@@ -90,6 +93,15 @@ export default {
noSchedules
()
{
noSchedules
()
{
return
!
this
.
schedulesLoading
&&
!
this
.
schedules
.
length
;
return
!
this
.
schedulesLoading
&&
!
this
.
schedules
.
length
;
},
},
isValid
()
{
return
this
.
isTimeValid
&&
this
.
isScheduleValid
;
},
isTimeValid
()
{
return
this
.
validationState
?.
isTimeValid
;
},
isScheduleValid
()
{
return
this
.
validationState
?.
isScheduleValid
;
},
},
},
methods
:
{
methods
:
{
setOncallSchedule
({
iid
})
{
setOncallSchedule
({
iid
})
{
...
@@ -123,11 +135,16 @@ export default {
...
@@ -123,11 +135,16 @@ export default {
class=
"gl-absolute rule-close-icon"
class=
"gl-absolute rule-close-icon"
@
click=
"$emit('remove-escalation-rule', index)"
@
click=
"$emit('remove-escalation-rule', index)"
/>
/>
<gl-form-group
<gl-form-group
:state=
"isValid"
class=
"gl-mb-0"
>
:invalid-feedback=
"$options.i18n.fields.rules.validationMsg"
<template
#invalid-feedback
>
:state=
"isValid"
<div
v-if=
"!isScheduleValid"
>
class=
"gl-mb-0"
{{
$options
.
i18n
.
fields
.
rules
.
emptyScheduleValidationMsg
}}
>
</div>
<div
v-if=
"!isTimeValid"
class=
"gl-display-inline-block gl-mt-2"
>
{{
$options
.
i18n
.
fields
.
rules
.
invalidTimeValidationMsg
}}
</div>
</
template
>
<div
class=
"gl-display-flex gl-align-items-center"
>
<div
class=
"gl-display-flex gl-align-items-center"
>
<gl-sprintf
:message=
"$options.i18n.fields.rules.condition"
>
<gl-sprintf
:message=
"$options.i18n.fields.rules.condition"
>
<
template
#alertStatus
>
<
template
#alertStatus
>
...
@@ -150,10 +167,10 @@ export default {
...
@@ -150,10 +167,10 @@ export default {
<
template
#minutes
>
<
template
#minutes
>
<gl-form-input
<gl-form-input
v-model=
"elapsedTimeSeconds"
v-model=
"elapsedTimeSeconds"
class=
"gl-mx-3 gl-inset-border-1-gray-200!
rule-elapsed-minutes
"
class=
"gl-mx-3 gl-inset-border-1-gray-200!
gl-w-12
"
type=
"number"
type=
"number"
min=
"0"
min=
"0"
@
change
=
"emitUpdate"
@
input
=
"emitUpdate"
/>
/>
</
template
>
</
template
>
</gl-sprintf>
</gl-sprintf>
...
...
ee/app/assets/javascripts/escalation_policies/utils.js
View file @
f23a606c
...
@@ -15,5 +15,10 @@ export const isNameFieldValid = (name) => {
...
@@ -15,5 +15,10 @@ export const isNameFieldValid = (name) => {
* @returns {Array}
* @returns {Array}
*/
*/
export
const
getRulesValidationState
=
(
rules
)
=>
{
export
const
getRulesValidationState
=
(
rules
)
=>
{
return
rules
.
map
((
rule
)
=>
Boolean
(
rule
.
oncallScheduleIid
));
return
rules
.
map
((
rule
)
=>
{
return
{
isTimeValid
:
parseInt
(
rule
.
elapsedTimeSeconds
,
10
)
>=
0
,
isScheduleValid
:
Boolean
(
rule
.
oncallScheduleIid
),
};
});
};
};
ee/spec/frontend/escalation_policies/add_edit_escalation_policy_form_spec.js
View file @
f23a606c
...
@@ -46,23 +46,9 @@ describe('AddEscalationPolicyForm', () => {
...
@@ -46,23 +46,9 @@ describe('AddEscalationPolicyForm', () => {
wrapper
.
destroy
();
wrapper
.
destroy
();
});
});
const
findPolicyName
=
()
=>
wrapper
.
findByTestId
(
'
escalation-policy-name
'
);
const
findRules
=
()
=>
wrapper
.
findAllComponents
(
EscalationRule
);
const
findRules
=
()
=>
wrapper
.
findAllComponents
(
EscalationRule
);
const
findAddRuleLink
=
()
=>
wrapper
.
findComponent
(
GlLink
);
const
findAddRuleLink
=
()
=>
wrapper
.
findComponent
(
GlLink
);
describe
(
'
Escalation policy form validation
'
,
()
=>
{
it
(
'
should set correct validation state for validated controls
'
,
async
()
=>
{
createComponent
({
props
:
{
validationState
:
{
name
:
false
,
rules
:
[
false
]
},
},
});
await
wrapper
.
vm
.
$nextTick
();
expect
(
findPolicyName
().
attributes
(
'
state
'
)).
toBeUndefined
();
expect
(
findRules
().
at
(
0
).
attributes
(
'
is-valid
'
)).
toBeUndefined
();
});
});
describe
(
'
Escalation rules
'
,
()
=>
{
describe
(
'
Escalation rules
'
,
()
=>
{
it
(
'
should render one default rule
'
,
()
=>
{
it
(
'
should render one default rule
'
,
()
=>
{
expect
(
findRules
().
length
).
toBe
(
1
);
expect
(
findRules
().
length
).
toBe
(
1
);
...
@@ -96,7 +82,7 @@ describe('AddEscalationPolicyForm', () => {
...
@@ -96,7 +82,7 @@ describe('AddEscalationPolicyForm', () => {
};
};
findRules
().
at
(
0
).
vm
.
$emit
(
'
update-escalation-rule
'
,
0
,
updatedRule
);
findRules
().
at
(
0
).
vm
.
$emit
(
'
update-escalation-rule
'
,
0
,
updatedRule
);
expect
(
wrapper
.
emitted
(
'
update-escalation-policy-form
'
)[
0
]).
toEqual
([
expect
(
wrapper
.
emitted
(
'
update-escalation-policy-form
'
)[
0
]).
toEqual
([
{
field
:
'
rules
'
,
value
:
[
updatedRule
]
},
{
field
:
'
rules
'
,
value
:
[
expect
.
objectContaining
(
updatedRule
)
]
},
]);
]);
});
});
...
...
ee/spec/frontend/escalation_policies/escalation_rule_spec.js
View file @
f23a606c
import
{
GlDropdownItem
,
GlFormGroup
,
GlSprintf
}
from
'
@gitlab/ui
'
;
import
{
GlDropdownItem
,
GlFormGroup
,
GlSprintf
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
shallowMount
}
from
'
@vue/test-utils
'
;
import
{
cloneDeep
}
from
'
lodash
'
;
import
{
cloneDeep
}
from
'
lodash
'
;
import
EscalationRule
from
'
ee/escalation_policies/components/escalation_rule.vue
'
;
import
EscalationRule
,
{
i18n
}
from
'
ee/escalation_policies/components/escalation_rule.vue
'
;
import
{
defaultEscalationRule
,
ACTIONS
,
ALERT_STATUSES
}
from
'
ee/escalation_policies/constants
'
;
import
{
defaultEscalationRule
,
ACTIONS
,
ALERT_STATUSES
}
from
'
ee/escalation_policies/constants
'
;
import
{
extendedWrapper
}
from
'
helpers/vue_test_utils_helper
'
;
import
{
extendedWrapper
}
from
'
helpers/vue_test_utils_helper
'
;
...
@@ -11,6 +11,9 @@ const mockSchedules = [
...
@@ -11,6 +11,9 @@ const mockSchedules = [
{
id
:
3
,
name
:
'
schedule3
'
},
{
id
:
3
,
name
:
'
schedule3
'
},
];
];
const
emptyScheduleMsg
=
i18n
.
fields
.
rules
.
emptyScheduleValidationMsg
;
const
invalidTimeMsg
=
i18n
.
fields
.
rules
.
invalidTimeValidationMsg
;
describe
(
'
EscalationRule
'
,
()
=>
{
describe
(
'
EscalationRule
'
,
()
=>
{
let
wrapper
;
let
wrapper
;
const
createComponent
=
({
props
=
{}
}
=
{})
=>
{
const
createComponent
=
({
props
=
{}
}
=
{})
=>
{
...
@@ -25,6 +28,7 @@ describe('EscalationRule', () => {
...
@@ -25,6 +28,7 @@ describe('EscalationRule', () => {
...
props
,
...
props
,
},
},
stubs
:
{
stubs
:
{
GlFormGroup
,
GlSprintf
,
GlSprintf
,
},
},
}),
}),
...
@@ -96,17 +100,45 @@ describe('EscalationRule', () => {
...
@@ -96,17 +100,45 @@ describe('EscalationRule', () => {
});
});
describe
(
'
Validation
'
,
()
=>
{
describe
(
'
Validation
'
,
()
=>
{
it
.
each
`
describe
.
each
`
isValid | state
validationState | formState
${
true
}
|
${
'
true
'
}
${{
isTimeValid
:
true
,
isScheduleValid
:
true
}
} |
${
'
true
'
}
${
false
}
|
${
undefined
}
${{
isTimeValid
:
false
,
isScheduleValid
:
true
}
} |
${
undefined
}
`
(
'
when $isValid sets from group state to $state
'
,
({
isValid
,
state
})
=>
{
${{
isTimeValid
:
true
,
isScheduleValid
:
false
}
} |
${
undefined
}
createComponent
({
${{
isTimeValid
:
false
,
isScheduleValid
:
false
}
} |
${
undefined
}
props
:
{
`
(
`when`
,
({
validationState
,
formState
})
=>
{
isValid
,
describe
(
`elapsed minutes control is
${
},
validationState
.
isTimeValid
?
'
valid
'
:
'
invalid
'
}
and schedule control is
${
validationState
.
isScheduleValid
?
'
valid
'
:
'
invalid
'
}
`
,
()
=>
{
beforeEach
(()
=>
{
createComponent
({
props
:
{
validationState
,
},
});
});
it
(
`sets form group validation state to
${
formState
}
`
,
()
=>
{
expect
(
findFormGroup
().
attributes
(
'
state
'
)).
toBe
(
formState
);
});
it
(
`does
${
validationState
.
isTimeValid
?
'
not show
'
:
'
show
'
}
invalid time error message && does
${
validationState
.
isScheduleValid
?
'
not show
'
:
'
show
'
}
invalid schedule error message `
,
()
=>
{
if
(
validationState
.
isTimeValid
)
{
expect
(
findFormGroup
().
text
()).
not
.
toContain
(
invalidTimeMsg
);
}
else
{
expect
(
findFormGroup
().
text
()).
toContain
(
invalidTimeMsg
);
}
if
(
validationState
.
isScheduleValid
)
{
expect
(
findFormGroup
().
text
()).
not
.
toContain
(
emptyScheduleMsg
);
}
else
{
expect
(
findFormGroup
().
text
()).
toContain
(
emptyScheduleMsg
);
}
});
});
});
expect
(
findFormGroup
().
attributes
(
'
state
'
)).
toBe
(
state
);
});
});
});
});
});
});
locale/gitlab.pot
View file @
f23a606c
...
@@ -13108,6 +13108,9 @@ msgstr ""
...
@@ -13108,6 +13108,9 @@ msgstr ""
msgid "EscalationPolicies|Edit escalation policy"
msgid "EscalationPolicies|Edit escalation policy"
msgstr ""
msgstr ""
msgid "EscalationPolicies|Elapsed time must be greater than or equal to zero."
msgstr ""
msgid "EscalationPolicies|Email on-call user in schedule"
msgid "EscalationPolicies|Email on-call user in schedule"
msgstr ""
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