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
8bdbb463
Commit
8bdbb463
authored
Dec 04, 2020
by
GitLab Bot
Browse files
Options
Browse Files
Download
Plain Diff
Automatic merge of gitlab-org/gitlab master
parents
97259abf
4c3a6eff
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
154 additions
and
138 deletions
+154
-138
app/assets/javascripts/pages/admin/users/components/user_modal_manager.vue
...ripts/pages/admin/users/components/user_modal_manager.vue
+6
-12
app/assets/javascripts/pages/admin/users/index.js
app/assets/javascripts/pages/admin/users/index.js
+2
-8
app/views/admin/users/_modals.html.haml
app/views/admin/users/_modals.html.haml
+2
-2
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
+15
-15
ee/spec/frontend/fixtures/analytics/charts.rb
ee/spec/frontend/fixtures/analytics/charts.rb
+46
-0
ee/spec/frontend/fixtures/analytics/metrics.rb
ee/spec/frontend/fixtures/analytics/metrics.rb
+72
-0
ee/spec/frontend/fixtures/analytics/value_streams.rb
ee/spec/frontend/fixtures/analytics/value_streams.rb
+8
-90
spec/frontend/pages/admin/users/components/user_modal_manager_spec.js
...d/pages/admin/users/components/user_modal_manager_spec.js
+3
-11
No files found.
app/assets/javascripts/pages/admin/users/components/user_modal_manager.vue
View file @
8bdbb463
<
script
>
import
DeleteUserModal
from
'
./delete_user_modal.vue
'
;
export
default
{
components
:
{
DeleteUserModal
},
props
:
{
modalConfiguration
:
{
required
:
true
,
type
:
Object
,
},
actionModals
:
{
required
:
true
,
type
:
Object
,
},
csrfToken
:
{
required
:
true
,
type
:
String
,
...
...
@@ -21,10 +20,7 @@ export default {
},
computed
:
{
activeModal
()
{
if
(
!
this
.
currentModalData
)
return
null
;
const
{
glModalAction
:
action
}
=
this
.
currentModalData
;
return
this
.
actionModals
[
action
];
return
Boolean
(
this
.
currentModalData
);
},
modalProps
()
{
...
...
@@ -56,9 +52,7 @@ export default {
show
(
modalData
)
{
const
{
glModalAction
:
requestedAction
}
=
modalData
;
if
(
!
this
.
actionModals
[
requestedAction
])
{
throw
new
Error
(
`Requested non-existing modal action
${
requestedAction
}
`
);
}
if
(
!
this
.
modalConfiguration
[
requestedAction
])
{
throw
new
Error
(
`Modal action
${
requestedAction
}
has no configuration in HTML`
);
}
...
...
@@ -73,5 +67,5 @@ export default {
};
</
script
>
<
template
>
<d
iv
:is=
"activeModal"
v-if=
"activeModal"
ref=
"modal"
v-bind=
"modalProps"
/>
<d
elete-user-modal
v-if=
"activeModal"
ref=
"modal"
v-bind=
"modalProps"
/>
</
template
>
app/assets/javascripts/pages/admin/users/index.js
View file @
8bdbb463
...
...
@@ -2,16 +2,11 @@ import Vue from 'vue';
import
Translate
from
'
~/vue_shared/translate
'
;
import
ModalManager
from
'
./components/user_modal_manager.vue
'
;
import
DeleteUserModal
from
'
./components/delete_user_modal.vue
'
;
import
csrf
from
'
~/lib/utils/csrf
'
;
import
initConfirmModal
from
'
~/confirm_modal
'
;
const
MODAL_TEXTS_CONTAINER_SELECTOR
=
'
#modal-texts
'
;
const
MODAL_MANAGER_SELECTOR
=
'
#user-modal
'
;
const
ACTION_MODALS
=
{
delete
:
DeleteUserModal
,
'
delete-with-contributions
'
:
DeleteUserModal
,
};
const
MODAL_TEXTS_CONTAINER_SELECTOR
=
'
#js-modal-texts
'
;
const
MODAL_MANAGER_SELECTOR
=
'
#js-delete-user-modal
'
;
function
loadModalsConfigurationFromHtml
(
modalsElement
)
{
const
modalsConfiguration
=
{};
...
...
@@ -54,7 +49,6 @@ document.addEventListener('DOMContentLoaded', () => {
ref
:
'
manager
'
,
props
:
{
modalConfiguration
,
actionModals
:
ACTION_MODALS
,
csrfToken
:
csrf
.
token
,
},
});
...
...
app/views/admin/users/_modals.html.haml
View file @
8bdbb463
#user-modal
#modal-texts
.hidden
{
"hidden"
:
true
,
"aria-hidden"
:
true
}
#
js-delete-
user-modal
#
js-
modal-texts
.hidden
{
"hidden"
:
true
,
"aria-hidden"
:
true
}
%div
{
data:
{
modal:
"delete"
,
title:
s_
(
"AdminUsers|Delete User %{username}?"
),
action:
s_
(
'AdminUsers|Delete user'
),
...
...
ee/spec/frontend/analytics/cycle_analytics/mock_data.js
View file @
8bdbb463
...
...
@@ -20,8 +20,8 @@ const fixtureEndpoints = {
customizableCycleAnalyticsStagesAndEvents
:
'
analytics/value_stream_analytics/stages.json
'
,
// customizable stages and events endpoint
stageEvents
:
stage
=>
`analytics/value_stream_analytics/stages/
${
stage
}
/records.json`
,
stageMedian
:
stage
=>
`analytics/value_stream_analytics/stages/
${
stage
}
/median.json`
,
recentActivityData
:
'
analytics/value_stream_analytics/summary.json
'
,
timeMetricsData
:
'
analytics/value_stream_analytics/time_summary.json
'
,
recentActivityData
:
'
analytics/
metrics/
value_stream_analytics/summary.json
'
,
timeMetricsData
:
'
analytics/
metrics/
value_stream_analytics/time_summary.json
'
,
groupLabels
:
'
api/group_labels.json
'
,
};
...
...
@@ -161,17 +161,17 @@ export const customStageFormErrors = convertObjectPropsToCamelCase(rawCustomStag
const
dateRange
=
getDatesInRange
(
startDate
,
endDate
,
toYmd
);
export
const
apiTasksByTypeData
=
getJSONFixture
(
'
analytics/type_of_work/tasks_by_type.json
'
).
map
(
labelData
=>
{
// add data points for our mock date range
const
maxValue
=
10
;
const
series
=
dateRange
.
map
(
date
=>
[
date
,
Math
.
floor
(
Math
.
random
()
*
Math
.
floor
(
maxValue
))])
;
return
{
...
labelData
,
series
,
};
}
,
);
export
const
apiTasksByTypeData
=
getJSONFixture
(
'
analytics/charts/type_of_work/tasks_by_type.json
'
,
).
map
(
labelData
=>
{
// add data points for our mock date range
const
maxValue
=
10
;
const
series
=
dateRange
.
map
(
date
=>
[
date
,
Math
.
floor
(
Math
.
random
()
*
Math
.
floor
(
maxValue
))]);
return
{
...
labelData
,
series
,
}
;
}
);
export
const
rawTasksByTypeData
=
transformRawTasksByTypeData
(
apiTasksByTypeData
);
export
const
transformedTasksByTypeData
=
getTasksByTypeData
(
apiTasksByTypeData
);
...
...
@@ -264,5 +264,5 @@ export const selectedProjects = [
},
];
// Value returned from JSON fixture is
345600 for issue stage which equals 4
d
export
const
pathNavIssueMetric
=
'
4
d
'
;
// Value returned from JSON fixture is
172800 for issue stage which equals 2
d
export
const
pathNavIssueMetric
=
'
2
d
'
;
ee/spec/frontend/fixtures/analytics/charts.rb
0 → 100644
View file @
8bdbb463
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'Analytics (JavaScript fixtures)'
,
:sidekiq_inline
do
include
JavaScriptFixturesHelpers
let_it_be
(
:group
)
{
create
(
:group
)
}
let_it_be
(
:project
)
{
create
(
:project
,
:repository
,
namespace:
group
)
}
let_it_be
(
:user
)
{
create
(
:user
,
:admin
)
}
around
do
|
example
|
freeze_time
{
example
.
run
}
end
before
(
:all
)
do
clean_frontend_fixtures
(
'analytics/charts/'
)
end
describe
Groups
::
Analytics
::
TasksByTypeController
,
type: :controller
do
render_views
let_it_be
(
:labels
)
{
create_list
(
:group_label
,
3
,
group:
group
)
}
before
do
2
.
times
do
|
i
|
create
(
:labeled_issue
,
created_at:
i
.
days
.
ago
,
project:
create
(
:project
,
group:
group
),
labels:
[
labels
[
0
]])
create
(
:labeled_issue
,
created_at:
i
.
days
.
ago
,
project:
create
(
:project
,
group:
group
),
labels:
[
labels
[
1
]])
create
(
:labeled_issue
,
created_at:
i
.
days
.
ago
,
project:
create
(
:project
,
group:
group
),
labels:
[
labels
[
2
]])
end
stub_licensed_features
(
type_of_work_analytics:
true
)
group
.
add_maintainer
(
user
)
sign_in
(
user
)
end
it
'analytics/charts/type_of_work/tasks_by_type.json'
do
params
=
{
group_id:
group
.
full_path
,
label_ids:
labels
.
map
(
&
:id
),
created_after:
10
.
days
.
ago
,
subject:
'Issue'
}
get
(
:show
,
params:
params
,
format: :json
)
expect
(
response
).
to
have_gitlab_http_status
(
:success
)
end
end
end
ee/spec/frontend/fixtures/analytics/metrics.rb
0 → 100644
View file @
8bdbb463
# frozen_string_literal: true
require
'spec_helper'
RSpec
.
describe
'Analytics (JavaScript fixtures)'
,
:sidekiq_inline
do
include
JavaScriptFixturesHelpers
let_it_be
(
:group
)
{
create
(
:group
)
}
let_it_be
(
:project
)
{
create
(
:project
,
:repository
,
namespace:
group
)
}
let_it_be
(
:user
)
{
create
(
:user
,
:admin
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
,
created_at:
4
.
days
.
ago
)
}
let
(
:issue_1
)
{
create
(
:issue
,
project:
project
,
created_at:
5
.
days
.
ago
)
}
let
(
:issue_2
)
{
create
(
:issue
,
project:
project
,
created_at:
4
.
days
.
ago
)
}
let
(
:issue_3
)
{
create
(
:issue
,
project:
project
,
created_at:
3
.
days
.
ago
)
}
def
prepare_cycle_analytics_data
group
.
add_maintainer
(
user
)
project
.
add_maintainer
(
user
)
create_commit_referencing_issue
(
issue_1
)
create_commit_referencing_issue
(
issue_2
)
create_merge_request_closing_issue
(
user
,
project
,
issue_1
)
create_merge_request_closing_issue
(
user
,
project
,
issue_2
)
merge_merge_requests_closing_issue
(
user
,
project
,
issue_3
)
end
around
do
|
example
|
freeze_time
{
example
.
run
}
end
before
(
:all
)
do
clean_frontend_fixtures
(
'analytics/metrics'
)
end
describe
Groups
::
Analytics
::
CycleAnalytics
::
SummaryController
,
type: :controller
do
render_views
let
(
:params
)
{
{
created_after:
3
.
months
.
ago
,
created_before:
Time
.
now
,
group_id:
group
.
full_path
}
}
def
prepare_cycle_time_data
issue
.
update!
(
created_at:
5
.
days
.
ago
)
issue
.
metrics
.
update!
(
first_mentioned_in_commit_at:
4
.
days
.
ago
)
issue
.
update!
(
closed_at:
3
.
days
.
ago
)
issue_1
.
update!
(
created_at:
8
.
days
.
ago
)
issue_1
.
metrics
.
update!
(
first_mentioned_in_commit_at:
6
.
days
.
ago
)
issue_1
.
update!
(
closed_at:
1
.
day
.
ago
)
end
before
do
stub_licensed_features
(
cycle_analytics_for_groups:
true
)
prepare_cycle_analytics_data
prepare_cycle_time_data
sign_in
(
user
)
end
it
'analytics/metrics/value_stream_analytics/summary.json'
do
get
(
:show
,
params:
params
,
format: :json
)
expect
(
response
).
to
be_successful
end
it
'analytics/metrics/value_stream_analytics/time_summary.json'
do
get
(
:time_summary
,
params:
params
,
format: :json
)
expect
(
response
).
to
be_successful
end
end
end
ee/spec/frontend/fixtures/analytics.rb
→
ee/spec/frontend/fixtures/analytics
/value_streams
.rb
View file @
8bdbb463
...
...
@@ -4,11 +4,11 @@ require 'spec_helper'
RSpec
.
describe
'Analytics (JavaScript fixtures)'
,
:sidekiq_inline
do
include
JavaScriptFixturesHelpers
let
(
:group
)
{
create
(
:group
)
}
let
(
:value_stream
)
{
create
(
:cycle_analytics_group_value_stream
,
group:
group
)
}
let
(
:project
)
{
create
(
:project
,
:repository
,
namespace:
group
)
}
let
(
:user
)
{
create
(
:user
,
:admin
)
}
let
(
:milestone
)
{
create
(
:milestone
,
project:
project
)
}
let
_it_be
(
:group
)
{
create
(
:group
)
}
let
_it_be
(
:value_stream
)
{
create
(
:cycle_analytics_group_value_stream
,
group:
group
)
}
let
_it_be
(
:project
)
{
create
(
:project
,
:repository
,
namespace:
group
)
}
let
_it_be
(
:user
)
{
create
(
:user
,
:admin
)
}
let
_it_be
(
:milestone
)
{
create
(
:milestone
,
project:
project
)
}
let
(
:issue
)
{
create
(
:issue
,
project:
project
,
created_at:
4
.
days
.
ago
)
}
let
(
:issue_1
)
{
create
(
:issue
,
project:
project
,
created_at:
5
.
days
.
ago
)
}
...
...
@@ -17,18 +17,14 @@ RSpec.describe 'Analytics (JavaScript fixtures)', :sidekiq_inline do
let
(
:label
)
{
create
(
:group_label
,
name:
'in-code-review'
,
group:
group
)
}
let
(
:mr
)
{
create_merge_request_closing_issue
(
user
,
project
,
issue
,
commit_message:
"References
#{
issue
.
to_reference
}
"
)
}
let
(
:mr_1
)
{
create
(
:merge_request
,
source_project:
project
,
allow_broken:
true
,
created_at:
20
.
days
.
ago
)
}
let
(
:mr_2
)
{
create
(
:merge_request
,
source_project:
project
,
allow_broken:
true
,
created_at:
19
.
days
.
ago
)
}
let
(
:mr_3
)
{
create
(
:merge_request
,
source_project:
project
,
allow_broken:
true
,
created_at:
18
.
days
.
ago
)
}
let
(
:pipeline_1
)
{
create
(
:ci_empty_pipeline
,
status:
'created'
,
project:
project
,
ref:
mr_1
.
source_branch
,
sha:
mr_1
.
source_branch_sha
,
head_pipeline_of:
mr_1
)
}
let
(
:pipeline_2
)
{
create
(
:ci_empty_pipeline
,
status:
'created'
,
project:
project
,
ref:
mr_2
.
source_branch
,
sha:
mr_2
.
source_branch_sha
,
head_pipeline_of:
mr_2
)
}
let
(
:pipeline_3
)
{
create
(
:ci_empty_pipeline
,
status:
'created'
,
project:
project
,
ref:
mr_3
.
source_branch
,
sha:
mr_3
.
source_branch_sha
,
head_pipeline_of:
mr_3
)
}
let
(
:build_1
)
{
create
(
:ci_build
,
:success
,
pipeline:
pipeline_1
,
author:
user
)
}
let
(
:build_2
)
{
create
(
:ci_build
,
:success
,
pipeline:
pipeline_2
,
author:
user
)
}
let
(
:build_3
)
{
create
(
:ci_build
,
:success
,
pipeline:
pipeline_3
,
author:
user
)
}
let
(
:label_based_stage
)
do
create
(
:cycle_analytics_group_stage
,
{
...
...
@@ -45,9 +41,6 @@ RSpec.describe 'Analytics (JavaScript fixtures)', :sidekiq_inline do
group
.
add_maintainer
(
user
)
project
.
add_maintainer
(
user
)
create_cycle
(
user
,
project
,
issue_1
,
mr_1
,
milestone
,
pipeline_1
)
create_cycle
(
user
,
project
,
issue_2
,
mr_2
,
milestone
,
pipeline_2
)
create_commit_referencing_issue
(
issue_1
)
create_commit_referencing_issue
(
issue_2
)
...
...
@@ -62,8 +55,8 @@ RSpec.describe 'Analytics (JavaScript fixtures)', :sidekiq_inline do
end
def
update_metrics
issue_1
.
metrics
.
update
(
first_added_to_board_at:
3
.
days
.
ago
,
first_mentioned_in_commit_at:
2
.
days
.
ago
)
issue_2
.
metrics
.
update
(
first_added_to_board_at:
2
.
days
.
ago
,
first_mentioned_in_commit_at:
1
.
day
.
ago
)
issue_1
.
metrics
.
update
!
(
first_added_to_board_at:
3
.
days
.
ago
,
first_mentioned_in_commit_at:
2
.
days
.
ago
)
issue_2
.
metrics
.
update
!
(
first_added_to_board_at:
2
.
days
.
ago
,
first_mentioned_in_commit_at:
1
.
day
.
ago
)
mr_1
.
metrics
.
update!
({
merged_at:
5
.
days
.
ago
,
...
...
@@ -87,9 +80,6 @@ RSpec.describe 'Analytics (JavaScript fixtures)', :sidekiq_inline do
update_metrics
create_cycle
(
user
,
project
,
issue_1
,
mr_1
,
milestone
,
pipeline_1
)
create_cycle
(
user
,
project
,
issue_2
,
mr_2
,
milestone
,
pipeline_2
)
create_cycle
(
user
,
project
,
issue_3
,
mr_3
,
milestone
,
pipeline_3
)
deploy_master
(
user
,
project
,
environment:
'staging'
)
end
...
...
@@ -115,13 +105,8 @@ RSpec.describe 'Analytics (JavaScript fixtures)', :sidekiq_inline do
end
end
around
do
|
example
|
Timecop
.
freeze
{
example
.
run
}
end
before
(
:all
)
do
clean_frontend_fixtures
(
'analytics/'
)
clean_frontend_fixtures
(
'cycle_analytics/'
)
clean_frontend_fixtures
(
'analytics/value_stream_analytics/'
)
end
describe
Groups
::
Analytics
::
CycleAnalytics
::
StagesController
,
type: :controller
do
...
...
@@ -181,71 +166,4 @@ RSpec.describe 'Analytics (JavaScript fixtures)', :sidekiq_inline do
expect
(
response
).
to
be_successful
end
end
describe
Groups
::
Analytics
::
CycleAnalytics
::
SummaryController
,
type: :controller
do
render_views
let
(
:params
)
{
{
created_after:
3
.
months
.
ago
,
created_before:
Time
.
now
,
group_id:
group
.
full_path
}
}
def
prepare_cycle_time_data
issue
.
update!
(
created_at:
5
.
days
.
ago
)
issue
.
metrics
.
update!
(
first_mentioned_in_commit_at:
4
.
days
.
ago
)
issue
.
update!
(
closed_at:
3
.
days
.
ago
)
issue_1
.
update!
(
created_at:
8
.
days
.
ago
)
issue_1
.
metrics
.
update!
(
first_mentioned_in_commit_at:
6
.
days
.
ago
)
issue_1
.
update!
(
closed_at:
1
.
day
.
ago
)
end
before
do
stub_licensed_features
(
cycle_analytics_for_groups:
true
)
prepare_cycle_analytics_data
prepare_cycle_time_data
sign_in
(
user
)
end
it
'analytics/value_stream_analytics/summary.json'
do
get
(
:show
,
params:
params
,
format: :json
)
expect
(
response
).
to
be_successful
end
it
'analytics/value_stream_analytics/time_summary.json'
do
get
(
:time_summary
,
params:
params
,
format: :json
)
expect
(
response
).
to
be_successful
end
end
describe
Groups
::
Analytics
::
TasksByTypeController
,
type: :controller
do
render_views
let
(
:label
)
{
create
(
:group_label
,
group:
group
)
}
let
(
:label2
)
{
create
(
:group_label
,
group:
group
)
}
let
(
:label3
)
{
create
(
:group_label
,
group:
group
)
}
before
do
5
.
times
do
|
i
|
create
(
:labeled_issue
,
created_at:
i
.
days
.
ago
,
project:
create
(
:project
,
group:
group
),
labels:
[
label
])
create
(
:labeled_issue
,
created_at:
i
.
days
.
ago
,
project:
create
(
:project
,
group:
group
),
labels:
[
label2
])
create
(
:labeled_issue
,
created_at:
i
.
days
.
ago
,
project:
create
(
:project
,
group:
group
),
labels:
[
label3
])
end
stub_licensed_features
(
type_of_work_analytics:
true
)
group
.
add_maintainer
(
user
)
sign_in
(
user
)
end
it
'analytics/type_of_work/tasks_by_type.json'
do
params
=
{
group_id:
group
.
full_path
,
label_ids:
[
label
.
id
,
label2
.
id
,
label3
.
id
],
created_after:
10
.
days
.
ago
,
subject:
'Issue'
}
get
(
:show
,
params:
params
,
format: :json
)
expect
(
response
).
to
be_successful
end
end
end
spec/frontend/pages/admin/users/components/user_modal_manager_spec.js
View file @
8bdbb463
...
...
@@ -14,21 +14,18 @@ describe('Users admin page Modal Manager', () => {
},
};
const
actionModals
=
{
action1
:
ModalStub
,
action2
:
ModalStub
,
};
let
wrapper
;
const
createComponent
=
(
props
=
{})
=>
{
wrapper
=
mount
(
UserModalManager
,
{
propsData
:
{
actionModals
,
modalConfiguration
,
csrfToken
:
'
dummyCSRF
'
,
...
props
,
},
stubs
:
{
DeleteUserModal
:
ModalStub
,
},
});
};
...
...
@@ -43,11 +40,6 @@ describe('Users admin page Modal Manager', () => {
expect
(
wrapper
.
find
({
ref
:
'
modal
'
}).
exists
()).
toBeFalsy
();
});
it
(
'
throws if non-existing action is requested
'
,
()
=>
{
createComponent
();
expect
(()
=>
wrapper
.
vm
.
show
({
glModalAction
:
'
non-existing
'
})).
toThrow
();
});
it
(
'
throws if action has no proper configuration
'
,
()
=>
{
createComponent
({
modalConfiguration
:
{},
...
...
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