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
f86d9a37
Commit
f86d9a37
authored
Jul 20, 2020
by
Olena Horal-Koretska
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Basic incidents list
parent
b54152f5
Changes
21
Hide whitespace changes
Inline
Side-by-side
Showing
21 changed files
with
422 additions
and
18 deletions
+422
-18
app/assets/javascripts/alert_management/components/alert_management_table.vue
...ts/alert_management/components/alert_management_table.vue
+1
-1
app/assets/javascripts/incidents/components/incidents_list.vue
...ssets/javascripts/incidents/components/incidents_list.vue
+129
-0
app/assets/javascripts/incidents/constants.js
app/assets/javascripts/incidents/constants.js
+7
-0
app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
...pts/incidents/graphql/queries/get_incidents.query.graphql
+22
-0
app/assets/javascripts/incidents/list.js
app/assets/javascripts/incidents/list.js
+34
-0
app/assets/javascripts/pages/projects/incidents/index/index.js
...ssets/javascripts/pages/projects/incidents/index/index.js
+5
-0
app/assets/stylesheets/pages/alert_management/severity-icons.scss
...ts/stylesheets/pages/alert_management/severity-icons.scss
+1
-1
app/assets/stylesheets/pages/incident_management_list.scss
app/assets/stylesheets/pages/incident_management_list.scss
+17
-14
app/controllers/projects/incidents_controller.rb
app/controllers/projects/incidents_controller.rb
+8
-0
app/helpers/projects/incidents_helper.rb
app/helpers/projects/incidents_helper.rb
+9
-0
app/helpers/projects_helper.rb
app/helpers/projects_helper.rb
+3
-0
app/policies/project_policy.rb
app/policies/project_policy.rb
+1
-0
app/views/layouts/nav/sidebar/_project.html.haml
app/views/layouts/nav/sidebar/_project.html.haml
+8
-2
app/views/projects/incidents/index.html.haml
app/views/projects/incidents/index.html.haml
+3
-0
changelogs/unreleased/229399-incidents-list-mvc.yml
changelogs/unreleased/229399-incidents-list-mvc.yml
+5
-0
config/routes/project.rb
config/routes/project.rb
+2
-0
locale/gitlab.pot
locale/gitlab.pot
+24
-0
spec/controllers/projects/incidents_controller_spec.rb
spec/controllers/projects/incidents_controller_spec.rb
+46
-0
spec/frontend/incidents/components/incidents_list_spec.js
spec/frontend/incidents/components/incidents_list_spec.js
+78
-0
spec/helpers/projects/incidents_helper_spec.rb
spec/helpers/projects/incidents_helper_spec.rb
+18
-0
spec/support/shared_contexts/navbar_structure_context.rb
spec/support/shared_contexts/navbar_structure_context.rb
+1
-0
No files found.
app/assets/javascripts/alert_management/components/alert_management_table.vue
View file @
f86d9a37
...
...
@@ -318,7 +318,7 @@ export default {
</
script
>
<
template
>
<div>
<div
class=
"
aler
t-management-list"
>
<div
class=
"
inciden
t-management-list"
>
<gl-alert
v-if=
"showNoAlertsMsg"
@
dismiss=
"isAlertDismissed = true"
>
<gl-sprintf
:message=
"$options.i18n.noAlertsMsg"
>
<template
#link
="
{ content }">
...
...
app/assets/javascripts/incidents/components/incidents_list.vue
0 → 100644
View file @
f86d9a37
<
script
>
import
{
GlLoadingIcon
,
GlTable
,
GlAlert
}
from
'
@gitlab/ui
'
;
import
{
s__
}
from
'
~/locale
'
;
import
getIncidents
from
'
../graphql/queries/get_incidents.query.graphql
'
;
import
{
I18N
}
from
'
../constants
'
;
const
tdClass
=
'
table-col gl-display-flex d-md-table-cell gl-align-items-center gl-white-space-nowrap
'
;
const
thClass
=
'
gl-hover-bg-blue-50
'
;
const
bodyTrClass
=
'
gl-border-1 gl-border-t-solid gl-border-gray-100 gl-hover-bg-blue-50 gl-hover-border-b-solid gl-hover-border-blue-200
'
;
export
default
{
i18n
:
I18N
,
fields
:
[
{
key
:
'
title
'
,
label
:
s__
(
'
IncidentManagement|Incident
'
),
thClass
:
`gl-pointer-events-none gl-w-half`
,
tdClass
,
},
{
key
:
'
createdAt
'
,
label
:
s__
(
'
IncidentManagement|Date created
'
),
thClass
:
`
${
thClass
}
gl-pointer-events-none`
,
tdClass
,
},
{
key
:
'
assignees
'
,
label
:
s__
(
'
IncidentManagement|Assignees
'
),
thClass
:
'
gl-pointer-events-none
'
,
tdClass
,
},
],
components
:
{
GlLoadingIcon
,
GlTable
,
GlAlert
,
},
inject
:
[
'
projectPath
'
],
apollo
:
{
incidents
:
{
query
:
getIncidents
,
variables
()
{
return
{
projectPath
:
this
.
projectPath
,
labelNames
:
[
'
incident
'
],
};
},
update
:
({
project
:
{
issues
:
{
nodes
=
[]
}
=
{}
}
=
{}
})
=>
nodes
,
error
()
{
this
.
errored
=
true
;
},
},
},
data
()
{
return
{
errored
:
false
,
isErrorAlertDismissed
:
false
,
};
},
computed
:
{
showErrorMsg
()
{
return
this
.
errored
&&
!
this
.
isErrorAlertDismissed
;
},
loading
()
{
return
this
.
$apollo
.
queries
.
incidents
.
loading
;
},
hasIncidents
()
{
return
this
.
incidents
?.
length
;
},
tbodyTrClass
()
{
return
{
[
bodyTrClass
]:
!
this
.
loading
&&
this
.
hasIncidents
,
};
},
},
methods
:
{
getAssignees
(
assignees
)
{
return
assignees
.
nodes
?.
length
>
0
?
assignees
.
nodes
[
0
]?.
username
:
s__
(
'
IncidentManagement|Unassigned
'
);
},
},
};
</
script
>
<
template
>
<div
class=
"incident-management-list"
>
<gl-alert
v-if=
"showErrorMsg"
variant=
"danger"
@
dismiss=
"isErrorAlertDismissed = true"
>
{{
$options
.
i18n
.
errorMsg
}}
</gl-alert>
<h4
class=
"gl-display-block d-md-none my-3"
>
{{
s__
(
'
IncidentManagement|Incidents
'
)
}}
</h4>
<gl-table
:items=
"incidents"
:fields=
"$options.fields"
:show-empty=
"true"
:busy=
"loading"
stacked=
"md"
:tbody-tr-class=
"tbodyTrClass"
:no-local-sorting=
"true"
fixed
>
<template
#cell(title)=
"
{ item }">
<div
class=
"gl-max-w-full text-truncate"
:title=
"item.title"
>
{{
item
.
title
}}
</div>
</
template
>
<
template
#cell(createdAt)=
"{ item }"
>
{{
item
.
createdAt
}}
</
template
>
<
template
#cell(assignees)=
"{ item }"
>
<div
class=
"gl-max-w-full text-truncate"
data-testid=
"assigneesField"
>
{{
getAssignees
(
item
.
assignees
)
}}
</div>
</
template
>
<
template
#table-busy
>
<gl-loading-icon
size=
"lg"
color=
"dark"
class=
"mt-3"
/>
</
template
>
<
template
#empty
>
{{
$options
.
i18n
.
noIncidents
}}
</
template
>
</gl-table>
</div>
</template>
app/assets/javascripts/incidents/constants.js
0 → 100644
View file @
f86d9a37
/* eslint-disable import/prefer-default-export */
import
{
s__
}
from
'
~/locale
'
;
export
const
I18N
=
{
errorMsg
:
s__
(
'
IncidentManagement|There was an error displaying the incidents.
'
),
noIncidents
:
s__
(
'
IncidentManagement|No incidents to display.
'
),
};
app/assets/javascripts/incidents/graphql/queries/get_incidents.query.graphql
0 → 100644
View file @
f86d9a37
query
getIncidents
(
$projectPath
:
ID
!,
$labelNames
:
[
String
],
$state
:
IssuableState
)
{
project
(
fullPath
:
$projectPath
)
{
issues
(
state
:
$state
,
labelName
:
$labelNames
)
{
nodes
{
iid
title
createdAt
labels
{
nodes
{
title
color
}
}
assignees
{
nodes
{
username
}
}
}
}
}
}
app/assets/javascripts/incidents/list.js
0 → 100644
View file @
f86d9a37
import
Vue
from
'
vue
'
;
import
VueApollo
from
'
vue-apollo
'
;
import
createDefaultClient
from
'
~/lib/graphql
'
;
import
IncidentsList
from
'
./components/incidents_list.vue
'
;
Vue
.
use
(
VueApollo
);
export
default
()
=>
{
const
selector
=
'
#js-incidents
'
;
const
domEl
=
document
.
querySelector
(
selector
);
const
{
projectPath
}
=
domEl
.
dataset
;
const
apolloProvider
=
new
VueApollo
({
defaultClient
:
createDefaultClient
(),
});
return
new
Vue
({
el
:
selector
,
provide
:
{
projectPath
,
},
apolloProvider
,
components
:
{
IncidentsList
,
},
render
(
createElement
)
{
return
createElement
(
'
incidents-list
'
,
{
props
:
{
projectPath
,
},
});
},
});
};
app/assets/javascripts/pages/projects/incidents/index/index.js
0 → 100644
View file @
f86d9a37
import
IncidentsList
from
'
~/incidents/list
'
;
document
.
addEventListener
(
'
DOMContentLoaded
'
,
()
=>
{
IncidentsList
();
});
app/assets/stylesheets/pages/alert_management/severity-icons.scss
View file @
f86d9a37
.
aler
t-management-list
,
.
inciden
t-management-list
,
.alert-management-details
{
.icon-critical
{
color
:
$red-800
;
...
...
app/assets/stylesheets/pages/
alert_management/
list.scss
→
app/assets/stylesheets/pages/
incident_management_
list.scss
View file @
f86d9a37
.
aler
t-management-list
{
.
inciden
t-management-list
{
.new-alert
{
background-color
:
$issues-today-bg
;
}
// these styles need to be deleted once GlTable component looks in GitLab same as in @gitlab/ui
table
{
color
:
$
gray-700
;
@include
gl-text-
gray-700
;
tr
{
&
:focus
{
...
...
@@ -24,9 +24,9 @@
}
th
{
background-color
:
transparent
;
font-weight
:
$
gl-font-weight-bold
;
color
:
$gl
-gray-600
;
@include
gl-bg-
transparent
;
@include
gl-font-weight-bold
;
@include
gl-text
-gray-600
;
&
[
aria-sort
=
'none'
]
:hover
{
background-image
:
url('data:image/svg+xml, %3csvg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="4 0 8 16"%3e %3cpath style="fill: %23BABABA;" fill-rule="evenodd" d="M11.707085,11.7071 L7.999975,15.4142 L4.292875,11.7071 C3.902375,11.3166 3.902375, 10.6834 4.292875,10.2929 C4.683375,9.90237 5.316575,9.90237 5.707075,10.2929 L6.999975, 11.5858 L6.999975,2 C6.999975,1.44771 7.447695,1 7.999975,1 C8.552255,1 8.999975,1.44771 8.999975,2 L8.999975,11.5858 L10.292865,10.2929 C10.683395 ,9.90237 11.316555,9.90237 11.707085,10.2929 C12.097605,10.6834 12.097605,11.3166 11.707085,11.7071 Z"/%3e %3c/svg%3e')
;
...
...
@@ -46,15 +46,24 @@
}
@include
media-breakpoint-down
(
sm
)
{
.alert-management-
table
{
table
{
tr
{
border-top
:
0
;
@include
gl-border-t-
0
;
.table-col
{
min-height
:
68px
;
}
&
:hover
{
@include
gl-bg-white
;
@include
gl-border-none
;
}
}
&
.alert-management-table
{
.table-col
{
&
:last-child
{
background-color
:
$
gray-10
;
@include
gl-bg-
gray-10
;
&
:
:
before
{
content
:
none
!
important
;
...
...
@@ -66,12 +75,6 @@
}
}
}
&
:hover
{
background-color
:
$white
;
border-color
:
$white
;
border-bottom-style
:
none
;
}
}
}
}
...
...
app/controllers/projects/incidents_controller.rb
0 → 100644
View file @
f86d9a37
# frozen_string_literal: true
class
Projects::IncidentsController
<
Projects
::
ApplicationController
before_action
:authorize_read_incidents!
def
index
end
end
app/helpers/projects/incidents_helper.rb
0 → 100644
View file @
f86d9a37
# frozen_string_literal: true
module
Projects::IncidentsHelper
def
incidents_data
(
project
)
{
'project-path'
=>
project
.
full_path
}
end
end
app/helpers/projects_helper.rb
View file @
f86d9a37
...
...
@@ -465,6 +465,7 @@ module ProjectsHelper
serverless: :read_cluster
,
error_tracking: :read_sentry_issue
,
alert_management: :read_alert_management_alert
,
incidents: :read_incidents
,
labels: :read_label
,
issues: :read_issue
,
project_members: :read_project_member
,
...
...
@@ -732,6 +733,8 @@ module ProjectsHelper
functions
error_tracking
alert_management
incidents
incident_management
user
gcp
logs
...
...
app/policies/project_policy.rb
View file @
f86d9a37
...
...
@@ -258,6 +258,7 @@ class ProjectPolicy < BasePolicy
enable
:read_merge_request
enable
:read_sentry_issue
enable
:update_sentry_issue
enable
:read_incidents
enable
:read_prometheus
enable
:read_metrics_dashboard_annotation
enable
:metrics_dashboard
...
...
app/views/layouts/nav/sidebar/_project.html.haml
View file @
f86d9a37
...
...
@@ -228,10 +228,16 @@
-
if
project_nav_tab?
(
:alert_management
)
=
nav_link
(
controller: :alert_management
)
do
=
link_to
project_alert_management_index_path
(
@project
),
title:
_
(
'Alerts'
)
,
class:
'shortcuts-tracking qa-operations-tracking-link'
do
=
link_to
project_alert_management_index_path
(
@project
),
title:
_
(
'Alerts'
)
do
%span
=
_
(
'Alerts'
)
-
if
project_nav_tab?
(
:incidents
)
=
nav_link
(
controller: :incidents
)
do
=
link_to
project_incidents_path
(
@project
),
title:
_
(
'Incidents'
)
do
%span
=
_
(
'Incidents'
)
-
if
project_nav_tab?
:environments
=
render_if_exists
"layouts/nav/sidebar/tracing_link"
...
...
@@ -242,7 +248,7 @@
-
if
project_nav_tab?
(
:error_tracking
)
=
nav_link
(
controller: :error_tracking
)
do
=
link_to
project_error_tracking_index_path
(
@project
),
title:
_
(
'Error Tracking'
)
,
class:
'shortcuts-tracking qa-operations-tracking-link'
do
=
link_to
project_error_tracking_index_path
(
@project
),
title:
_
(
'Error Tracking'
)
do
%span
=
_
(
'Error Tracking'
)
...
...
app/views/projects/incidents/index.html.haml
0 → 100644
View file @
f86d9a37
-
page_title
_
(
'Incidents'
)
#js-incidents
{
data:
incidents_data
(
@project
)
}
changelogs/unreleased/229399-incidents-list-mvc.yml
0 → 100644
View file @
f86d9a37
---
title
:
Add basic incidents list
merge_request
:
37314
author
:
type
:
added
config/routes/project.rb
View file @
f86d9a37
...
...
@@ -300,6 +300,8 @@ constraints(::Constraints::ProjectUrlConstrainer.new) do
post
'incidents/integrations/pagerduty'
,
to:
'incident_management/pager_duty_incidents#create'
resources
:incidents
,
only:
[
:index
]
namespace
:error_tracking
do
resources
:projects
,
only: :index
end
...
...
locale/gitlab.pot
View file @
f86d9a37
...
...
@@ -12650,6 +12650,27 @@ msgstr ""
msgid "Incident Management Limits"
msgstr ""
msgid "IncidentManagement|Assignees"
msgstr ""
msgid "IncidentManagement|Date created"
msgstr ""
msgid "IncidentManagement|Incident"
msgstr ""
msgid "IncidentManagement|Incidents"
msgstr ""
msgid "IncidentManagement|No incidents to display."
msgstr ""
msgid "IncidentManagement|There was an error displaying the incidents."
msgstr ""
msgid "IncidentManagement|Unassigned"
msgstr ""
msgid "IncidentSettings|Alert integration"
msgstr ""
...
...
@@ -12665,6 +12686,9 @@ msgstr ""
msgid "IncidentSettings|Set up integrations with external tools to help better manage incidents."
msgstr ""
msgid "Incidents"
msgstr ""
msgid "Include a Terms of Service agreement and Privacy Policy that all users must accept."
msgstr ""
...
...
spec/controllers/projects/incidents_controller_spec.rb
0 → 100644
View file @
f86d9a37
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Projects
::
IncidentsController
do
let_it_be
(
:project
)
{
create
(
:project
)
}
let_it_be
(
:developer
)
{
create
(
:user
)
}
let_it_be
(
:guest
)
{
create
(
:user
)
}
before_all
do
project
.
add_developer
(
developer
)
project
.
add_guest
(
guest
)
end
describe
'GET #index'
do
def
make_request
get
:index
,
params:
{
namespace_id:
project
.
namespace
,
project_id:
project
}
end
it
'shows the page for user with developer role'
do
sign_in
(
developer
)
make_request
expect
(
response
).
to
have_gitlab_http_status
(
:ok
)
expect
(
response
).
to
render_template
(
:index
)
end
context
'when user is unauthorized'
do
it
'redirects to the login page'
do
sign_out
(
developer
)
make_request
expect
(
response
).
to
redirect_to
(
new_user_session_path
)
end
end
context
'when user is a guest'
do
it
'shows 404'
do
sign_in
(
guest
)
make_request
expect
(
response
).
to
have_gitlab_http_status
(
:not_found
)
end
end
end
end
spec/frontend/incidents/components/incidents_list_spec.js
0 → 100644
View file @
f86d9a37
import
{
mount
}
from
'
@vue/test-utils
'
;
import
{
GlAlert
,
GlLoadingIcon
,
GlTable
}
from
'
@gitlab/ui
'
;
import
IncidentsList
from
'
~/incidents/components/incidents_list.vue
'
;
import
{
I18N
}
from
'
~/incidents/constants
'
;
describe
(
'
Incidents List
'
,
()
=>
{
let
wrapper
;
const
findTable
=
()
=>
wrapper
.
find
(
GlTable
);
const
findTableRows
=
()
=>
wrapper
.
findAll
(
'
table tbody tr
'
);
const
findAlert
=
()
=>
wrapper
.
find
(
GlAlert
);
const
findLoader
=
()
=>
wrapper
.
find
(
GlLoadingIcon
);
function
mountComponent
({
data
=
{
incidents
:
[]
},
loading
=
false
})
{
wrapper
=
mount
(
IncidentsList
,
{
data
()
{
return
data
;
},
mocks
:
{
$apollo
:
{
queries
:
{
incidents
:
{
loading
,
},
},
},
},
provide
:
{
projectPath
:
'
/project/path
'
,
},
});
}
afterEach
(()
=>
{
if
(
wrapper
)
{
wrapper
.
destroy
();
wrapper
=
null
;
}
});
it
(
'
shows the loading state
'
,
()
=>
{
mountComponent
({
props
:
{
alertManagementEnabled
:
true
,
userCanEnableAlertManagement
:
true
},
loading
:
true
,
});
expect
(
findLoader
().
exists
()).
toBe
(
true
);
});
it
(
'
shows empty state
'
,
()
=>
{
mountComponent
({
data
:
{
incidents
:
[]
},
loading
:
false
,
});
expect
(
findTable
().
text
()).
toContain
(
I18N
.
noIncidents
);
});
it
(
'
shows error state
'
,
()
=>
{
mountComponent
({
data
:
{
incidents
:
[],
errored
:
true
},
loading
:
false
,
});
expect
(
findTable
().
text
()).
toContain
(
I18N
.
noIncidents
);
expect
(
findAlert
().
exists
()).
toBe
(
true
);
});
it
(
'
displays basic list
'
,
()
=>
{
const
incidents
=
[
{
title
:
1
,
assignees
:
[]
},
{
title
:
2
,
assignees
:
[]
},
{
title
:
3
,
assignees
:
[]
},
];
mountComponent
({
data
:
{
incidents
},
loading
:
false
,
});
expect
(
findTableRows
().
length
).
toBe
(
incidents
.
length
);
});
});
spec/helpers/projects/incidents_helper_spec.rb
0 → 100644
View file @
f86d9a37
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
Projects
::
IncidentsHelper
do
include
Gitlab
::
Routing
.
url_helpers
let
(
:project
)
{
create
(
:project
)
}
let
(
:project_path
)
{
project
.
full_path
}
describe
'#incidents_data'
do
subject
(
:data
)
{
helper
.
incidents_data
(
project
)
}
it
'returns frontend configuration'
do
expect
(
data
).
to
match
(
'project-path'
=>
project_path
)
end
end
end
spec/support/shared_contexts/navbar_structure_context.rb
View file @
f86d9a37
...
...
@@ -64,6 +64,7 @@ RSpec.shared_context 'project navbar structure' do
nav_sub_items:
[
_
(
'Metrics'
),
_
(
'Alerts'
),
_
(
'Incidents'
),
_
(
'Environments'
),
_
(
'Error Tracking'
),
_
(
'Serverless'
),
...
...
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