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
94e71a8e
Commit
94e71a8e
authored
Jan 20, 2022
by
Florie Guibert
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Introduce Roadmap settings sidebar
Introduce roadmap_settings feature flag
parent
c200c4f8
Changes
11
Hide whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
185 additions
and
15 deletions
+185
-15
config/feature_flags/development/roadmap_settings.yml
config/feature_flags/development/roadmap_settings.yml
+8
-0
ee/app/assets/javascripts/roadmap/components/roadmap_app.vue
ee/app/assets/javascripts/roadmap/components/roadmap_app.vue
+21
-0
ee/app/assets/javascripts/roadmap/components/roadmap_filters.vue
...assets/javascripts/roadmap/components/roadmap_filters.vue
+17
-1
ee/app/assets/javascripts/roadmap/components/roadmap_settings.vue
...ssets/javascripts/roadmap/components/roadmap_settings.vue
+39
-0
ee/app/assets/stylesheets/page_bundles/roadmap.scss
ee/app/assets/stylesheets/page_bundles/roadmap.scss
+1
-1
ee/app/controllers/groups/roadmap_controller.rb
ee/app/controllers/groups/roadmap_controller.rb
+4
-0
ee/spec/features/groups/group_roadmap_spec.rb
ee/spec/features/groups/group_roadmap_spec.rb
+13
-0
ee/spec/frontend/roadmap/components/roadmap_app_spec.js
ee/spec/frontend/roadmap/components/roadmap_app_spec.js
+23
-8
ee/spec/frontend/roadmap/components/roadmap_filters_spec.js
ee/spec/frontend/roadmap/components/roadmap_filters_spec.js
+26
-5
ee/spec/frontend/roadmap/components/roadmap_settings_spec.js
ee/spec/frontend/roadmap/components/roadmap_settings_spec.js
+30
-0
locale/gitlab.pot
locale/gitlab.pot
+3
-0
No files found.
config/feature_flags/development/roadmap_settings.yml
0 → 100644
View file @
94e71a8e
---
name
:
roadmap_settings
introduced_by_url
:
https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78626
rollout_issue_url
:
https://gitlab.com/gitlab-org/gitlab/-/issues/350830
milestone
:
'
14.8'
type
:
development
group
:
group::product planning
default_enabled
:
false
ee/app/assets/javascripts/roadmap/components/roadmap_app.vue
View file @
94e71a8e
...
...
@@ -2,9 +2,12 @@
import
{
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
{
mapState
,
mapActions
}
from
'
vuex
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
{
DATE_RANGES
}
from
'
../constants
'
;
import
EpicsListEmpty
from
'
./epics_list_empty.vue
'
;
import
RoadmapFilters
from
'
./roadmap_filters.vue
'
;
import
RoadmapSettings
from
'
./roadmap_settings.vue
'
;
import
RoadmapShell
from
'
./roadmap_shell.vue
'
;
export
default
{
...
...
@@ -12,8 +15,10 @@ export default {
EpicsListEmpty
,
GlLoadingIcon
,
RoadmapFilters
,
RoadmapSettings
,
RoadmapShell
,
},
mixins
:
[
glFeatureFlagMixin
()],
props
:
{
timeframeRangeType
:
{
type
:
String
,
...
...
@@ -29,6 +34,11 @@ export default {
required
:
true
,
},
},
data
()
{
return
{
isSettingsSidebarOpen
:
false
,
};
},
computed
:
{
...
mapState
([
'
currentGroupId
'
,
...
...
@@ -66,6 +76,9 @@ export default {
},
methods
:
{
...
mapActions
([
'
fetchEpics
'
,
'
fetchMilestones
'
]),
toggleSettings
()
{
this
.
isSettingsSidebarOpen
=
!
this
.
isSettingsSidebarOpen
;
},
},
};
</
script
>
...
...
@@ -75,6 +88,7 @@ export default {
<roadmap-filters
v-if=
"showFilteredSearchbar && !epicIid"
:timeframe-range-type=
"timeframeRangeType"
@
toggleSettings=
"toggleSettings"
/>
<div
:class=
"
{ 'overflow-reset': epicsFetchResultEmpty }" class="roadmap-container">
<gl-loading-icon
v-if=
"epicsFetchInProgress"
class=
"gl-mt-5"
size=
"md"
/>
...
...
@@ -96,6 +110,13 @@ export default {
:timeframe=
"timeframe"
:current-group-id=
"currentGroupId"
:has-filters-applied=
"hasFiltersApplied"
:is-settings-sidebar-open=
"isSettingsSidebarOpen"
/>
<roadmap-settings
v-if=
"glFeatures.roadmapSettings"
:is-open=
"isSettingsSidebarOpen"
data-testid=
"roadmap-settings"
@
toggleSettings=
"toggleSettings"
/>
</div>
</div>
...
...
ee/app/assets/javascripts/roadmap/components/roadmap_filters.vue
View file @
94e71a8e
<
script
>
import
{
GlButton
,
GlFormGroup
,
GlSegmentedControl
,
GlDropdown
,
...
...
@@ -11,6 +12,7 @@ import { mapState, mapActions } from 'vuex';
import
{
visitUrl
,
mergeUrlParams
,
updateHistory
,
setUrlParams
}
from
'
~/lib/utils/url_utility
'
;
import
{
__
,
s__
}
from
'
~/locale
'
;
import
FilteredSearchBar
from
'
~/vue_shared/components/filtered_search_bar/filtered_search_bar_root.vue
'
;
import
glFeatureFlagMixin
from
'
~/vue_shared/mixins/gl_feature_flags_mixin
'
;
import
{
EPICS_STATES
,
PRESET_TYPES
,
DATE_RANGES
}
from
'
../constants
'
;
import
EpicsFilteredSearchMixin
from
'
../mixins/filtered_search_mixin
'
;
...
...
@@ -48,6 +50,7 @@ export default {
},
],
components
:
{
GlButton
,
GlFormGroup
,
GlSegmentedControl
,
GlDropdown
,
...
...
@@ -55,7 +58,7 @@ export default {
GlDropdownDivider
,
FilteredSearchBar
,
},
mixins
:
[
EpicsFilteredSearchMixin
],
mixins
:
[
EpicsFilteredSearchMixin
,
glFeatureFlagMixin
()
],
props
:
{
timeframeRangeType
:
{
type
:
String
,
...
...
@@ -161,6 +164,9 @@ export default {
this
.
fetchEpics
();
},
},
i18n
:
{
settings
:
__
(
'
Settings
'
),
},
};
</
script
>
...
...
@@ -232,6 +238,16 @@ export default {
@
onFilter=
"handleFilterEpics"
@
onSort=
"handleSortEpics"
/>
<gl-button
v-if=
"glFeatures.roadmapSettings"
icon=
"settings"
class=
"gl-mb-3 gl-lg-ml-3 gl-sm-mt-3"
:aria-label=
"$options.i18n.settings"
data-testid=
"settings-button"
@
click=
"$emit('toggleSettings', $event)"
>
{{
$options
.
i18n
.
settings
}}
</gl-button>
</div>
</div>
</
template
>
ee/app/assets/javascripts/roadmap/components/roadmap_settings.vue
0 → 100644
View file @
94e71a8e
<
script
>
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
export
default
{
components
:
{
GlDrawer
,
},
props
:
{
isOpen
:
{
type
:
Boolean
,
required
:
true
,
},
},
methods
:
{
getDrawerHeaderHeight
()
{
const
wrapperEl
=
document
.
querySelector
(
'
.roadmap-container
'
);
if
(
wrapperEl
)
{
return
`
${
wrapperEl
.
offsetTop
}
px`
;
}
return
''
;
},
},
};
</
script
>
<
template
>
<gl-drawer
v-bind=
"$attrs"
:open=
"isOpen"
:header-height=
"getDrawerHeaderHeight()"
@
close=
"$emit('toggleSettings', $event)"
>
<template
#title
>
<h2
class=
"gl-my-0 gl-font-size-h2 gl-line-height-24"
>
{{
__
(
'
Roadmap settings
'
)
}}
</h2>
</
template
>
</gl-drawer>
</template>
ee/app/assets/stylesheets/page_bundles/roadmap.scss
View file @
94e71a8e
...
...
@@ -135,7 +135,7 @@ html.group-epics-roadmap-html {
position
:
sticky
;
position
:
-
webkit-sticky
;
top
:
0
;
z-index
:
20
;
z-index
:
9
;
.timeline-header-blank
,
.timeline-header-item
{
...
...
ee/app/controllers/groups/roadmap_controller.rb
View file @
94e71a8e
...
...
@@ -8,6 +8,10 @@ module Groups
before_action
:check_epics_available!
before_action
:persist_roadmap_layout
,
only:
[
:show
]
before_action
do
push_frontend_feature_flag
(
:roadmap_settings
,
@group
,
default_enabled: :yaml
)
end
feature_category
:portfolio_management
# show roadmap for a group
...
...
ee/spec/features/groups/group_roadmap_spec.rb
View file @
94e71a8e
...
...
@@ -119,6 +119,19 @@ RSpec.describe 'group epic roadmap', :js do
expect
(
page
).
to
have_selector
(
'.epics-list-item .epic-title'
,
count:
3
)
end
end
it
'toggles settings sidebar on click settings button'
do
page
.
within
(
'.content-wrapper .content'
)
do
expect
(
page
).
not_to
have_selector
(
'[data-testid="roadmap-sidebar"]'
)
expect
(
page
).
to
have_selector
(
'[data-testid="settings-button"]'
)
click_button
'Settings'
expect
(
page
).
to
have_selector
(
'[data-testid="roadmap-settings"]'
)
click_button
'Settings'
expect
(
page
).
not_to
have_selector
(
'[data-testid="roadmap-settings"]'
)
end
end
end
describe
'roadmap page with epics state filter'
do
...
...
ee/spec/frontend/roadmap/components/roadmap_app_spec.js
View file @
94e71a8e
import
{
GlLoadingIcon
}
from
'
@gitlab/ui
'
;
import
{
shallowMount
,
createLocalVue
}
from
'
@vue/test-utils
'
;
import
Vue
from
'
vue
'
;
import
Vuex
from
'
vuex
'
;
import
{
shallowMountExtended
}
from
'
helpers/vue_test_utils_helper
'
;
import
EpicsListEmpty
from
'
ee/roadmap/components/epics_list_empty.vue
'
;
import
RoadmapApp
from
'
ee/roadmap/components/roadmap_app.vue
'
;
import
RoadmapFilters
from
'
ee/roadmap/components/roadmap_filters.vue
'
;
...
...
@@ -18,13 +19,12 @@ import {
mockTimeframeInitialDate
,
}
from
'
ee_jest/roadmap/mock_data
'
;
Vue
.
use
(
Vuex
);
describe
(
'
RoadmapApp
'
,
()
=>
{
const
localVue
=
createLocalVue
();
let
store
;
let
wrapper
;
localVue
.
use
(
Vuex
);
const
currentGroupId
=
mockGroupId
;
const
emptyStateIllustrationPath
=
mockSvgPath
;
const
epics
=
[
mockFormattedEpic
];
...
...
@@ -36,9 +36,8 @@ describe('RoadmapApp', () => {
initialDate
:
mockTimeframeInitialDate
,
});
const
createComponent
=
(
mountFunction
=
shallowMount
)
=>
{
return
mountFunction
(
RoadmapApp
,
{
localVue
,
const
createComponent
=
({
roadmapSettings
=
false
}
=
{})
=>
{
return
shallowMountExtended
(
RoadmapApp
,
{
propsData
:
{
emptyStateIllustrationPath
,
presetType
,
...
...
@@ -47,11 +46,14 @@ describe('RoadmapApp', () => {
groupFullPath
:
'
gitlab-org
'
,
groupMilestonesPath
:
'
/groups/gitlab-org/-/milestones.json
'
,
listEpicsPath
:
'
/groups/gitlab-org/-/epics
'
,
glFeatures
:
{
roadmapSettings
},
},
store
,
});
};
const
findSettingsSidebar
=
()
=>
wrapper
.
findByTestId
(
'
roadmap-settings
'
);
beforeEach
(()
=>
{
store
=
createStore
();
store
.
dispatch
(
'
setInitialData
'
,
{
...
...
@@ -67,7 +69,6 @@ describe('RoadmapApp', () => {
afterEach
(()
=>
{
wrapper
.
destroy
();
wrapper
=
null
;
});
describe
.
each
`
...
...
@@ -152,5 +153,19 @@ describe('RoadmapApp', () => {
milestones
:
[],
});
});
it
(
'
does not render settings sidebar
'
,
()
=>
{
expect
(
findSettingsSidebar
().
exists
()).
toBe
(
false
);
});
describe
(
'
when roadmapSettings feature flag is on
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
roadmapSettings
:
true
});
});
it
(
'
renders settings button
'
,
()
=>
{
expect
(
findSettingsSidebar
().
exists
()).
toBe
(
true
);
});
});
});
});
ee/spec/frontend/roadmap/components/roadmap_filters_spec.js
View file @
94e71a8e
import
{
GlSegmentedControl
,
GlDropdown
,
GlDropdownItem
}
from
'
@gitlab/ui
'
;
import
{
createLocalVue
}
from
'
@vue/test-utils
'
;
import
Vue
from
'
vue
'
;
import
Vuex
from
'
vuex
'
;
import
RoadmapFilters
from
'
ee/roadmap/components/roadmap_filters.vue
'
;
...
...
@@ -29,6 +29,8 @@ jest.mock('~/lib/utils/url_utility', () => ({
updateHistory
:
jest
.
requireActual
(
'
~/lib/utils/url_utility
'
).
updateHistory
,
}));
Vue
.
use
(
Vuex
);
const
createComponent
=
({
presetType
=
PRESET_TYPES
.
MONTHS
,
epicsState
=
EPICS_STATES
.
ALL
,
...
...
@@ -43,12 +45,10 @@ const createComponent = ({
}),
filterParams
=
{},
timeframeRangeType
=
DATE_RANGES
.
THREE_YEARS
,
roadmapSettings
=
false
,
}
=
{})
=>
{
const
localVue
=
createLocalVue
();
const
store
=
createStore
();
localVue
.
use
(
Vuex
);
store
.
dispatch
(
'
setInitialData
'
,
{
presetType
,
epicsState
,
...
...
@@ -58,12 +58,12 @@ const createComponent = ({
});
return
shallowMountExtended
(
RoadmapFilters
,
{
localVue
,
store
,
provide
:
{
groupFullPath
,
groupMilestonesPath
,
listEpicsPath
,
glFeatures
:
{
roadmapSettings
},
},
props
:
{
timeframeRangeType
,
...
...
@@ -73,6 +73,7 @@ const createComponent = ({
describe
(
'
RoadmapFilters
'
,
()
=>
{
let
wrapper
;
const
findSettingsButton
=
()
=>
wrapper
.
findByTestId
(
'
settings-button
'
);
beforeEach
(()
=>
{
wrapper
=
createComponent
();
...
...
@@ -153,6 +154,10 @@ describe('RoadmapFilters', () => {
expect
(
epicsStateDropdown
.
findAll
(
GlDropdownItem
)).
toHaveLength
(
3
);
});
it
(
'
does not render settings button
'
,
()
=>
{
expect
(
findSettingsButton
().
exists
()).
toBe
(
false
);
});
describe
(
'
FilteredSearchBar
'
,
()
=>
{
const
mockInitialFilterValue
=
[
{
...
...
@@ -383,4 +388,20 @@ describe('RoadmapFilters', () => {
);
});
});
describe
(
'
when roadmapSettings feature flag is on
'
,
()
=>
{
beforeEach
(()
=>
{
wrapper
=
createComponent
({
roadmapSettings
:
true
});
});
it
(
'
renders settings button
'
,
()
=>
{
expect
(
findSettingsButton
().
exists
()).
toBe
(
true
);
});
it
(
'
emits toggleSettings event on click settings button
'
,
()
=>
{
findSettingsButton
().
vm
.
$emit
(
'
click
'
);
expect
(
wrapper
.
emitted
(
'
toggleSettings
'
)).
toBeTruthy
();
});
});
});
ee/spec/frontend/roadmap/components/roadmap_settings_spec.js
0 → 100644
View file @
94e71a8e
import
{
GlDrawer
}
from
'
@gitlab/ui
'
;
import
{
shallowMountExtended
}
from
'
helpers/vue_test_utils_helper
'
;
import
RoadmapSettings
from
'
ee/roadmap/components/roadmap_settings.vue
'
;
describe
(
'
RoadmapSettings
'
,
()
=>
{
let
wrapper
;
const
createComponent
=
({
isOpen
=
false
}
=
{})
=>
{
wrapper
=
shallowMountExtended
(
RoadmapSettings
,
{
propsData
:
{
isOpen
},
});
};
const
findSettingsDrawer
=
()
=>
wrapper
.
findComponent
(
GlDrawer
);
beforeEach
(()
=>
{
createComponent
();
});
afterEach
(()
=>
{
wrapper
.
destroy
();
});
describe
(
'
template
'
,
()
=>
{
it
(
'
render drawer and title
'
,
()
=>
{
expect
(
findSettingsDrawer
().
exists
()).
toBe
(
true
);
expect
(
findSettingsDrawer
().
text
()).
toContain
(
'
Roadmap settings
'
);
});
});
});
locale/gitlab.pot
View file @
94e71a8e
...
...
@@ -30633,6 +30633,9 @@ msgstr ""
msgid "Roadmap"
msgstr ""
msgid "Roadmap settings"
msgstr ""
msgid "Role"
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