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
fa18ec94
Commit
fa18ec94
authored
Aug 02, 2021
by
Doug Stull
Committed by
Brandon Labuschagne
Aug 02, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Experiment: add area of focus question to invite modal
parent
5c794438
Changes
12
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
348 additions
and
51 deletions
+348
-51
app/assets/javascripts/invite_members/components/invite_members_modal.vue
...cripts/invite_members/components/invite_members_modal.vue
+52
-9
app/assets/javascripts/invite_members/constants.js
app/assets/javascripts/invite_members/constants.js
+5
-0
app/assets/javascripts/invite_members/init_invite_members_modal.js
...s/javascripts/invite_members/init_invite_members_modal.js
+2
-0
app/helpers/invite_members_helper.rb
app/helpers/invite_members_helper.rb
+39
-0
app/views/groups/_invite_members_modal.html.haml
app/views/groups/_invite_members_modal.html.haml
+2
-5
app/views/projects/_invite_members_modal.html.haml
app/views/projects/_invite_members_modal.html.haml
+2
-5
config/feature_flags/experiment/member_areas_of_focus.yml
config/feature_flags/experiment/member_areas_of_focus.yml
+8
-0
locale/gitlab.pot
locale/gitlab.pot
+18
-0
spec/features/groups/members/manage_members_spec.rb
spec/features/groups/members/manage_members_spec.rb
+54
-0
spec/frontend/invite_members/components/invite_members_modal_spec.js
...nd/invite_members/components/invite_members_modal_spec.js
+106
-30
spec/helpers/invite_members_helper_spec.rb
spec/helpers/invite_members_helper_spec.rb
+50
-0
spec/support/helpers/features/invite_members_modal_helper.rb
spec/support/helpers/features/invite_members_modal_helper.rb
+10
-2
No files found.
app/assets/javascripts/invite_members/components/invite_members_modal.vue
View file @
fa18ec94
...
...
@@ -9,13 +9,14 @@ import {
GlSprintf
,
GlButton
,
GlFormInput
,
GlFormCheckboxGroup
,
}
from
'
@gitlab/ui
'
;
import
{
partition
,
isString
}
from
'
lodash
'
;
import
Api
from
'
~/api
'
;
import
ExperimentTracking
from
'
~/experimentation/experiment_tracking
'
;
import
{
BV_SHOW_MODAL
,
BV_HIDE_MODAL
}
from
'
~/lib/utils/constants
'
;
import
{
BV_SHOW_MODAL
}
from
'
~/lib/utils/constants
'
;
import
{
s__
,
sprintf
}
from
'
~/locale
'
;
import
{
INVITE_MEMBERS_IN_COMMENT
,
GROUP_FILTERS
}
from
'
../constants
'
;
import
{
INVITE_MEMBERS_IN_COMMENT
,
GROUP_FILTERS
,
MEMBER_AREAS_OF_FOCUS
}
from
'
../constants
'
;
import
eventHub
from
'
../event_hub
'
;
import
{
responseMessageFromError
,
...
...
@@ -36,6 +37,7 @@ export default {
GlSprintf
,
GlButton
,
GlFormInput
,
GlFormCheckboxGroup
,
MembersTokenSelect
,
GroupSelect
,
},
...
...
@@ -74,6 +76,14 @@ export default {
type
:
String
,
required
:
true
,
},
areasOfFocusOptions
:
{
type
:
Array
,
required
:
true
,
},
noSelectionAreasOfFocus
:
{
type
:
Array
,
required
:
true
,
},
},
data
()
{
return
{
...
...
@@ -83,6 +93,7 @@ export default {
inviteeType
:
'
members
'
,
newUsersToInvite
:
[],
selectedDate
:
undefined
,
selectedAreasOfFocus
:
[],
groupToBeSharedWith
:
{},
source
:
'
unknown
'
,
invalidFeedbackMessage
:
''
,
...
...
@@ -128,10 +139,21 @@ export default {
this
.
newUsersToInvite
.
length
===
0
&&
Object
.
keys
(
this
.
groupToBeSharedWith
).
length
===
0
);
},
areasOfFocusEnabled
()
{
return
this
.
areasOfFocusOptions
.
length
!==
0
;
},
areasOfFocusForPost
()
{
if
(
this
.
selectedAreasOfFocus
.
length
===
0
&&
this
.
areasOfFocusEnabled
)
{
return
this
.
noSelectionAreasOfFocus
;
}
return
this
.
selectedAreasOfFocus
;
},
},
mounted
()
{
eventHub
.
$on
(
'
openModal
'
,
(
options
)
=>
{
this
.
openModal
(
options
);
this
.
trackEvent
(
MEMBER_AREAS_OF_FOCUS
.
name
,
MEMBER_AREAS_OF_FOCUS
.
view
);
});
},
methods
:
{
...
...
@@ -152,9 +174,12 @@ export default {
this
.
$root
.
$emit
(
BV_SHOW_MODAL
,
this
.
modalId
);
},
trackEvent
(
experimentName
,
eventName
)
{
const
tracking
=
new
ExperimentTracking
(
experimentName
);
tracking
.
event
(
eventName
);
},
closeModal
()
{
this
.
resetFields
();
this
.
$root
.
$emit
(
BV_HIDE_MODAL
,
this
.
modalId
);
this
.
$refs
.
modal
.
hide
();
},
sendInvite
()
{
if
(
this
.
isInviteGroup
)
{
...
...
@@ -165,9 +190,10 @@ export default {
},
trackInvite
()
{
if
(
this
.
source
===
INVITE_MEMBERS_IN_COMMENT
)
{
const
tracking
=
new
ExperimentTracking
(
INVITE_MEMBERS_IN_COMMENT
);
tracking
.
event
(
'
comment_invite_success
'
);
this
.
trackEvent
(
INVITE_MEMBERS_IN_COMMENT
,
'
comment_invite_success
'
);
}
this
.
trackEvent
(
MEMBER_AREAS_OF_FOCUS
.
name
,
MEMBER_AREAS_OF_FOCUS
.
submit
);
},
resetFields
()
{
this
.
isLoading
=
false
;
...
...
@@ -176,6 +202,7 @@ export default {
this
.
newUsersToInvite
=
[];
this
.
groupToBeSharedWith
=
{};
this
.
invalidFeedbackMessage
=
''
;
this
.
selectedAreasOfFocus
=
[];
},
changeSelectedItem
(
item
)
{
this
.
selectedAccessLevel
=
item
;
...
...
@@ -223,6 +250,7 @@ export default {
email
:
usersToInviteByEmail
,
access_level
:
this
.
selectedAccessLevel
,
invite_source
:
this
.
source
,
areas_of_focus
:
this
.
areasOfFocusForPost
,
};
},
addByUserIdPostData
(
usersToAddById
)
{
...
...
@@ -231,6 +259,7 @@ export default {
user_id
:
usersToAddById
,
access_level
:
this
.
selectedAccessLevel
,
invite_source
:
this
.
source
,
areas_of_focus
:
this
.
areasOfFocusForPost
,
};
},
shareWithGroupPostData
(
groupToBeSharedWith
)
{
...
...
@@ -304,18 +333,22 @@ export default {
inviteButtonText
:
s__
(
'
InviteMembersModal|Invite
'
),
cancelButtonText
:
s__
(
'
InviteMembersModal|Cancel
'
),
headerCloseLabel
:
s__
(
'
InviteMembersModal|Close invite team members
'
),
areasOfFocusLabel
:
s__
(
'
InviteMembersModal|What would you like new member(s) to focus on? (optional)
'
,
),
},
membersTokenSelectLabelId
:
'
invite-members-input
'
,
};
</
script
>
<
template
>
<gl-modal
ref=
"modal"
:modal-id=
"modalId"
size=
"sm"
data-qa-selector=
"invite_members_modal_content"
:title=
"$options.labels[inviteeType].modalTitle"
:header-close-label=
"$options.labels.headerCloseLabel"
@
close
=
"resetFields"
@
hidden
=
"resetFields"
>
<div>
<p
ref=
"introText"
>
...
...
@@ -351,7 +384,7 @@ export default {
/>
</gl-form-group>
<label
class=
"gl-
font-weight-bold gl-
mt-3"
>
{{ $options.labels.accessLevel }}
</label>
<label
class=
"gl-mt-3"
>
{{ $options.labels.accessLevel }}
</label>
<div
class=
"gl-mt-2 gl-w-half gl-xs-w-full"
>
<gl-dropdown
class=
"gl-shadow-none gl-w-full"
...
...
@@ -381,7 +414,7 @@ export default {
</gl-sprintf>
</div>
<label
class=
"gl-
font-weight-bold gl-
mt-5 gl-display-block"
for=
"expires_at"
>
{{
<label
class=
"gl-mt-5 gl-display-block"
for=
"expires_at"
>
{{
$options.labels.accessExpireDate
}}
</label>
<div
class=
"gl-mt-2 gl-w-half gl-xs-w-full gl-display-inline-block"
>
...
...
@@ -400,6 +433,16 @@ export default {
</
template
>
</gl-datepicker>
</div>
<div
v-if=
"areasOfFocusEnabled"
>
<label
class=
"gl-mt-5"
>
{{ $options.labels.areasOfFocusLabel }}
</label>
<gl-form-checkbox-group
v-model=
"selectedAreasOfFocus"
:options=
"areasOfFocusOptions"
data-testid=
"area-of-focus-checks"
/>
</div>
</div>
<
template
#modal-footer
>
...
...
app/assets/javascripts/invite_members/constants.js
View file @
fa18ec94
...
...
@@ -3,6 +3,11 @@ import { __ } from '~/locale';
export
const
SEARCH_DELAY
=
200
;
export
const
INVITE_MEMBERS_IN_COMMENT
=
'
invite_members_in_comment
'
;
export
const
MEMBER_AREAS_OF_FOCUS
=
{
name
:
'
member_areas_of_focus
'
,
view
:
'
view
'
,
submit
:
'
submit
'
,
};
export
const
GROUP_FILTERS
=
{
ALL
:
'
all
'
,
...
...
app/assets/javascripts/invite_members/init_invite_members_modal.js
View file @
fa18ec94
...
...
@@ -23,6 +23,8 @@ export default function initInviteMembersModal() {
defaultAccessLevel
:
parseInt
(
el
.
dataset
.
defaultAccessLevel
,
10
),
groupSelectFilter
:
el
.
dataset
.
groupsFilter
,
groupSelectParentId
:
parseInt
(
el
.
dataset
.
parentId
,
10
),
areasOfFocusOptions
:
JSON
.
parse
(
el
.
dataset
.
areasOfFocusOptions
),
noSelectionAreasOfFocus
:
JSON
.
parse
(
el
.
dataset
.
noSelectionAreasOfFocus
),
},
}),
});
...
...
app/helpers/invite_members_helper.rb
View file @
fa18ec94
...
...
@@ -39,4 +39,43 @@ module InviteMembersHelper
{}
end
end
def
common_invite_modal_dataset
(
source
)
dataset
=
{
id:
source
.
id
,
name:
source
.
name
,
default_access_level:
Gitlab
::
Access
::
GUEST
}
experiment
(
:member_areas_of_focus
,
user:
current_user
)
do
|
e
|
e
.
publish_to_database
e
.
control
{
dataset
.
merge!
(
areas_of_focus_options:
[],
no_selection_areas_of_focus:
[])
}
e
.
candidate
{
dataset
.
merge!
(
areas_of_focus_options:
member_areas_of_focus_options
.
to_json
,
no_selection_areas_of_focus:
[
'no_selection'
])
}
end
dataset
end
private
def
member_areas_of_focus_options
[
{
value:
'Contribute to the codebase'
,
text:
s_
(
'InviteMembersModal|Contribute to the codebase'
)
},
{
value:
'Collaborate on open issues and merge requests'
,
text:
s_
(
'InviteMembersModal|Collaborate on open issues and merge requests'
)
},
{
value:
'Configure CI/CD'
,
text:
s_
(
'InviteMembersModal|Configure CI/CD'
)
},
{
value:
'Configure security features'
,
text:
s_
(
'InviteMembersModal|Configure security features'
)
},
{
value:
'Other'
,
text:
s_
(
'InviteMembersModal|Other'
)
}
]
end
end
app/views/groups/_invite_members_modal.html.haml
View file @
fa18ec94
-
return
unless
can_manage_members?
(
group
)
.js-invite-members-modal
{
data:
{
id:
group
.
id
,
name:
group
.
name
,
is_project:
'false'
,
.js-invite-members-modal
{
data:
{
is_project:
'false'
,
access_levels:
GroupMember
.
access_level_roles
.
to_json
,
default_access_level:
Gitlab
::
Access
::
GUEST
,
help_link:
help_page_url
(
'user/permissions'
)
}.
merge
(
group_select_data
(
group
))
}
help_link:
help_page_url
(
'user/permissions'
)
}.
merge
(
group_select_data
(
group
)).
merge
(
common_invite_modal_dataset
(
group
))
}
app/views/projects/_invite_members_modal.html.haml
View file @
fa18ec94
-
return
unless
can_import_members?
.js-invite-members-modal
{
data:
{
id:
project
.
id
,
name:
project
.
name
,
is_project:
'true'
,
.js-invite-members-modal
{
data:
{
is_project:
'true'
,
access_levels:
ProjectMember
.
access_level_roles
.
to_json
,
default_access_level:
Gitlab
::
Access
::
GUEST
,
help_link:
help_page_url
(
'user/permissions'
)
}
}
help_link:
help_page_url
(
'user/permissions'
)
}.
merge
(
common_invite_modal_dataset
(
project
))
}
config/feature_flags/experiment/member_areas_of_focus.yml
0 → 100644
View file @
fa18ec94
---
name
:
member_areas_of_focus
introduced_by_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65273
rollout_issue_url
:
https://gitlab.com/gitlab-org/growth/team-tasks/-/issues/406
milestone
:
'
14.2'
type
:
experiment
group
:
group::expansion
default_enabled
:
false
locale/gitlab.pot
View file @
fa18ec94
...
...
@@ -18032,6 +18032,18 @@ msgstr ""
msgid "InviteMembersModal|Close invite team members"
msgstr ""
msgid "InviteMembersModal|Collaborate on open issues and merge requests"
msgstr ""
msgid "InviteMembersModal|Configure CI/CD"
msgstr ""
msgid "InviteMembersModal|Configure security features"
msgstr ""
msgid "InviteMembersModal|Contribute to the codebase"
msgstr ""
msgid "InviteMembersModal|GitLab member or email address"
msgstr ""
...
...
@@ -18047,6 +18059,9 @@ msgstr ""
msgid "InviteMembersModal|Members were successfully added"
msgstr ""
msgid "InviteMembersModal|Other"
msgstr ""
msgid "InviteMembersModal|Search for a group to invite"
msgstr ""
...
...
@@ -18062,6 +18077,9 @@ msgstr ""
msgid "InviteMembersModal|Something went wrong"
msgstr ""
msgid "InviteMembersModal|What would you like new member(s) to focus on? (optional)"
msgstr ""
msgid "InviteMembersModal|You're inviting a group to the %{strongStart}%{name}%{strongEnd} group."
msgstr ""
...
...
spec/features/groups/members/manage_members_spec.rb
View file @
fa18ec94
...
...
@@ -84,6 +84,33 @@ RSpec.describe 'Groups > Members > Manage members' do
property:
'existing_user'
,
user:
user1
)
expect_no_snowplow_event
(
category:
'Members::CreateService'
,
action:
'area_of_focus'
)
end
it
'adds a user to group with area_of_focus'
,
:js
,
:snowplow
,
:aggregate_failures
do
stub_experiments
(
member_areas_of_focus: :candidate
)
group
.
add_owner
(
user1
)
visit
group_group_members_path
(
group
)
invite_member
(
user2
.
name
,
role:
'Reporter'
,
area_of_focus:
true
)
wait_for_requests
expect_snowplow_event
(
category:
'Members::CreateService'
,
action:
'area_of_focus'
,
label:
'Contribute to the codebase'
,
property:
group
.
members
.
last
.
id
.
to_s
)
expect_snowplow_event
(
category:
'Members::CreateService'
,
action:
'area_of_focus'
,
label:
'Collaborate on open issues and merge requests'
,
property:
group
.
members
.
last
.
id
.
to_s
)
end
it
'do not disclose email addresses'
,
:js
do
...
...
@@ -193,9 +220,36 @@ RSpec.describe 'Groups > Members > Manage members' do
property:
'net_new_user'
,
user:
user1
)
expect_no_snowplow_event
(
category:
'Members::CreateService'
,
action:
'area_of_focus'
)
end
end
it
'invite user to group with area_of_focus'
,
:js
,
:snowplow
,
:aggregate_failures
do
stub_experiments
(
member_areas_of_focus: :candidate
)
group
.
add_owner
(
user1
)
visit
group_group_members_path
(
group
)
invite_member
(
'test@example.com'
,
role:
'Reporter'
,
area_of_focus:
true
)
wait_for_requests
expect_snowplow_event
(
category:
'Members::InviteService'
,
action:
'area_of_focus'
,
label:
'Contribute to the codebase'
,
property:
group
.
members
.
last
.
id
.
to_s
)
expect_snowplow_event
(
category:
'Members::InviteService'
,
action:
'area_of_focus'
,
label:
'Collaborate on open issues and merge requests'
,
property:
group
.
members
.
last
.
id
.
to_s
)
end
context
'when user is a guest'
do
before
do
group
.
add_guest
(
user1
)
...
...
spec/frontend/invite_members/components/invite_members_modal_spec.js
View file @
fa18ec94
This diff is collapsed.
Click to expand it.
spec/helpers/invite_members_helper_spec.rb
View file @
fa18ec94
...
...
@@ -14,6 +14,56 @@ RSpec.describe InviteMembersHelper do
helper
.
extend
(
Gitlab
::
Experimentation
::
ControllerConcern
)
end
describe
'#common_invite_modal_dataset'
do
context
'when member_areas_of_focus is enabled'
,
:experiment
do
context
'with control experience'
do
before
do
stub_experiments
(
member_areas_of_focus: :control
)
end
it
'has expected attributes'
do
attributes
=
{
areas_of_focus_options:
[],
no_selection_areas_of_focus:
[]
}
expect
(
helper
.
common_invite_modal_dataset
(
project
)).
to
include
(
attributes
)
end
end
context
'with candidate experience'
do
before
do
stub_experiments
(
member_areas_of_focus: :candidate
)
end
it
'has expected attributes'
,
:aggregate_failures
do
output
=
helper
.
common_invite_modal_dataset
(
project
)
expect
(
output
[
:no_selection_areas_of_focus
]).
to
eq
[
'no_selection'
]
expect
(
Gitlab
::
Json
.
parse
(
output
[
:areas_of_focus_options
]).
first
[
'value'
]).
to
eq
'Contribute to the codebase'
end
end
end
context
'when member_areas_of_focus is disabled'
do
before
do
stub_feature_flags
(
member_areas_of_focus:
false
)
end
it
'has expected attributes'
do
attributes
=
{
id:
project
.
id
,
name:
project
.
name
,
default_access_level:
Gitlab
::
Access
::
GUEST
,
areas_of_focus_options:
[],
no_selection_areas_of_focus:
[]
}
expect
(
helper
.
common_invite_modal_dataset
(
project
)).
to
match
(
attributes
)
end
end
end
context
'with project'
do
before
do
allow
(
helper
).
to
receive
(
:current_user
)
{
owner
}
...
...
spec/support/helpers/features/invite_members_modal_helper.rb
View file @
fa18ec94
...
...
@@ -5,7 +5,7 @@ module Spec
module
Helpers
module
Features
module
InviteMembersModalHelper
def
invite_member
(
name
,
role:
'Guest'
,
expires_at:
nil
)
def
invite_member
(
name
,
role:
'Guest'
,
expires_at:
nil
,
area_of_focus:
false
)
click_on
'Invite members'
page
.
within
'#invite-members-modal'
do
...
...
@@ -14,6 +14,7 @@ module Spec
wait_for_requests
click_button
name
choose_options
(
role
,
expires_at
)
choose_area_of_focus
if
area_of_focus
click_button
'Invite'
...
...
@@ -41,7 +42,14 @@ module Spec
click_button
role
end
fill_in
'YYYY-MM-DD'
,
with:
expires_at
.
try
(
:strftime
,
'%Y-%m-%d'
)
fill_in
'YYYY-MM-DD'
,
with:
expires_at
.
strftime
(
'%Y-%m-%d'
)
if
expires_at
end
def
choose_area_of_focus
page
.
within
'[data-testid="area-of-focus-checks"]'
do
check
'Contribute to the codebase'
check
'Collaborate on open issues and merge requests'
end
end
end
end
...
...
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