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
7e9f44fa
Commit
7e9f44fa
authored
Oct 31, 2018
by
Mike Greiling
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Prettify remaining files with differences in CE and EE
parent
2accb0d3
Changes
91
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
91 changed files
with
2391 additions
and
2179 deletions
+2391
-2179
app/assets/javascripts/blob_edit/blob_bundle.js
app/assets/javascripts/blob_edit/blob_bundle.js
+1
-1
app/assets/javascripts/boards/components/board.js
app/assets/javascripts/boards/components/board.js
+15
-12
app/assets/javascripts/boards/components/board_blank_state.vue
...ssets/javascripts/boards/components/board_blank_state.vue
+7
-8
app/assets/javascripts/boards/components/board_card.vue
app/assets/javascripts/boards/components/board_card.vue
+64
-64
app/assets/javascripts/boards/components/board_new_issue.vue
app/assets/javascripts/boards/components/board_new_issue.vue
+2
-1
app/assets/javascripts/boards/components/board_sidebar.js
app/assets/javascripts/boards/components/board_sidebar.js
+23
-18
app/assets/javascripts/boards/components/issue_card_inner.vue
...assets/javascripts/boards/components/issue_card_inner.vue
+130
-130
app/assets/javascripts/boards/components/modal/empty_state.vue
...ssets/javascripts/boards/components/modal/empty_state.vue
+2
-2
app/assets/javascripts/boards/components/modal/footer.vue
app/assets/javascripts/boards/components/modal/footer.vue
+7
-9
app/assets/javascripts/boards/components/modal/header.vue
app/assets/javascripts/boards/components/modal/header.vue
+40
-40
app/assets/javascripts/boards/components/modal/index.vue
app/assets/javascripts/boards/components/modal/index.vue
+115
-114
app/assets/javascripts/boards/components/modal/list.vue
app/assets/javascripts/boards/components/modal/list.vue
+99
-99
app/assets/javascripts/boards/components/modal/tabs.vue
app/assets/javascripts/boards/components/modal/tabs.vue
+15
-15
app/assets/javascripts/boards/components/new_list_dropdown.js
...assets/javascripts/boards/components/new_list_dropdown.js
+24
-19
app/assets/javascripts/boards/components/project_select.vue
app/assets/javascripts/boards/components/project_select.vue
+4
-2
app/assets/javascripts/boards/components/sidebar/remove_issue.vue
...ts/javascripts/boards/components/sidebar/remove_issue.vue
+60
-62
app/assets/javascripts/boards/filtered_search_boards.js
app/assets/javascripts/boards/filtered_search_boards.js
+6
-3
app/assets/javascripts/boards/index.js
app/assets/javascripts/boards/index.js
+3
-3
app/assets/javascripts/boards/mixins/sortable_default_options.js
...ets/javascripts/boards/mixins/sortable_default_options.js
+7
-3
app/assets/javascripts/boards/models/issue.js
app/assets/javascripts/boards/models/issue.js
+17
-17
app/assets/javascripts/boards/models/list.js
app/assets/javascripts/boards/models/list.js
+2
-2
app/assets/javascripts/boards/services/board_service.js
app/assets/javascripts/boards/services/board_service.js
+9
-3
app/assets/javascripts/boards/stores/boards_store.js
app/assets/javascripts/boards/stores/boards_store.js
+31
-26
app/assets/javascripts/boards/stores/modal_store.js
app/assets/javascripts/boards/stores/modal_store.js
+6
-6
app/assets/javascripts/commons/gitlab_ui.js
app/assets/javascripts/commons/gitlab_ui.js
+1
-5
app/assets/javascripts/diffs/components/tree_list.vue
app/assets/javascripts/diffs/components/tree_list.vue
+2
-2
app/assets/javascripts/environments/components/environments_app.vue
.../javascripts/environments/components/environments_app.vue
+84
-86
app/assets/javascripts/environments/stores/environments_store.js
...ets/javascripts/environments/stores/environments_store.js
+12
-10
app/assets/javascripts/filtered_search/dropdown_user.js
app/assets/javascripts/filtered_search/dropdown_user.js
+4
-3
app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
...ripts/filtered_search/filtered_search_dropdown_manager.js
+1
-4
app/assets/javascripts/filtered_search/filtered_search_manager.js
...ts/javascripts/filtered_search/filtered_search_manager.js
+65
-48
app/assets/javascripts/flash.js
app/assets/javascripts/flash.js
+6
-2
app/assets/javascripts/gfm_auto_complete.js
app/assets/javascripts/gfm_auto_complete.js
+40
-21
app/assets/javascripts/jobs/components/job_app.vue
app/assets/javascripts/jobs/components/job_app.vue
+150
-150
app/assets/javascripts/jobs/components/job_log.vue
app/assets/javascripts/jobs/components/job_log.vue
+37
-37
app/assets/javascripts/jobs/index.js
app/assets/javascripts/jobs/index.js
+0
-1
app/assets/javascripts/jobs/store/getters.js
app/assets/javascripts/jobs/store/getters.js
+6
-3
app/assets/javascripts/labels_select.js
app/assets/javascripts/labels_select.js
+149
-97
app/assets/javascripts/lib/utils/ace_utils.js
app/assets/javascripts/lib/utils/ace_utils.js
+2
-2
app/assets/javascripts/members.js
app/assets/javascripts/members.js
+35
-21
app/assets/javascripts/milestone_select.js
app/assets/javascripts/milestone_select.js
+4
-1
app/assets/javascripts/monitoring/components/dashboard.vue
app/assets/javascripts/monitoring/components/dashboard.vue
+8
-4
app/assets/javascripts/notes/components/notes_app.vue
app/assets/javascripts/notes/components/notes_app.vue
+7
-1
app/assets/javascripts/notes/discussion_filters.js
app/assets/javascripts/notes/discussion_filters.js
+5
-3
app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
.../milestones/shared/components/promote_milestone_modal.vue
+0
-1
app/assets/javascripts/pages/projects/project.js
app/assets/javascripts/pages/projects/project.js
+3
-1
app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
...projects/shared/permissions/components/settings_panel.vue
+186
-188
app/assets/javascripts/projects/project_new.js
app/assets/javascripts/projects/project_new.js
+29
-15
app/assets/javascripts/right_sidebar.js
app/assets/javascripts/right_sidebar.js
+39
-18
app/assets/javascripts/search_autocomplete.js
app/assets/javascripts/search_autocomplete.js
+3
-1
app/assets/javascripts/sidebar/components/assignees/assignees.vue
...ts/javascripts/sidebar/components/assignees/assignees.vue
+2
-2
app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
...cripts/sidebar/components/subscriptions/subscriptions.vue
+63
-63
app/assets/javascripts/sidebar/sidebar_mediator.js
app/assets/javascripts/sidebar/sidebar_mediator.js
+12
-8
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
...ue_merge_request_widget/components/mr_widget_pipeline.vue
+10
-7
app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
...merge_request_widget/components/states/ready_to_merge.vue
+22
-12
app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
...avascripts/vue_merge_request_widget/mr_widget_options.vue
+8
-4
app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js
...ts/vue_merge_request_widget/services/mr_widget_service.js
+2
-2
app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
...cripts/vue_merge_request_widget/stores/mr_widget_store.js
+1
-2
app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
...cripts/vue_shared/components/filtered_search_dropdown.vue
+4
-2
app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
...vue_shared/components/sidebar/collapsed_calendar_icon.vue
+31
-31
app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue
...ared/components/sidebar/collapsed_grouped_date_picker.vue
+68
-73
app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
...onents/sidebar/labels_select/dropdown_value_collapsed.vue
+6
-1
ee/spec/javascripts/boards/models/list_spec.js
ee/spec/javascripts/boards/models/list_spec.js
+22
-14
ee/spec/javascripts/epics/sidebar/components/sidebar_app_spec.js
.../javascripts/epics/sidebar/components/sidebar_app_spec.js
+8
-4
ee/spec/javascripts/jobs/shared_runner_limit_block_spec.js
ee/spec/javascripts/jobs/shared_runner_limit_block_spec.js
+9
-4
ee/spec/javascripts/vue_mr_widget/ee_mr_widget_options_spec.js
...ec/javascripts/vue_mr_widget/ee_mr_widget_options_spec.js
+10
-5
spec/javascripts/boards/board_list_spec.js
spec/javascripts/boards/board_list_spec.js
+33
-53
spec/javascripts/boards/components/board_spec.js
spec/javascripts/boards/components/board_spec.js
+13
-24
spec/javascripts/boards/issue_card_spec.js
spec/javascripts/boards/issue_card_spec.js
+20
-24
spec/javascripts/environments/emtpy_state_spec.js
spec/javascripts/environments/emtpy_state_spec.js
+10
-12
spec/javascripts/environments/environment_item_spec.js
spec/javascripts/environments/environment_item_spec.js
+25
-31
spec/javascripts/environments/environment_table_spec.js
spec/javascripts/environments/environment_table_spec.js
+3
-5
spec/javascripts/environments/environments_app_spec.js
spec/javascripts/environments/environments_app_spec.js
+51
-42
spec/javascripts/environments/folder/environments_folder_view_spec.js
...ipts/environments/folder/environments_folder_view_spec.js
+54
-50
spec/javascripts/issue_show/components/title_spec.js
spec/javascripts/issue_show/components/title_spec.js
+6
-12
spec/javascripts/jobs/components/job_app_spec.js
spec/javascripts/jobs/components/job_app_spec.js
+1
-1
spec/javascripts/jobs/store/actions_spec.js
spec/javascripts/jobs/store/actions_spec.js
+4
-32
spec/javascripts/jobs/store/getters_spec.js
spec/javascripts/jobs/store/getters_spec.js
+3
-3
spec/javascripts/lib/utils/common_utils_spec.js
spec/javascripts/lib/utils/common_utils_spec.js
+118
-103
spec/javascripts/monitoring/graph/flag_spec.js
spec/javascripts/monitoring/graph/flag_spec.js
+17
-18
spec/javascripts/notes/components/discussion_filter_spec.js
spec/javascripts/notes/components/discussion_filter_spec.js
+13
-7
spec/javascripts/notes/components/note_app_spec.js
spec/javascripts/notes/components/note_app_spec.js
+2
-1
spec/javascripts/pipelines/graph/graph_component_spec.js
spec/javascripts/pipelines/graph/graph_component_spec.js
+39
-31
spec/javascripts/sidebar/assignees_spec.js
spec/javascripts/sidebar/assignees_spec.js
+49
-34
spec/javascripts/test_bundle.js
spec/javascripts/test_bundle.js
+4
-2
spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
...ripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
+36
-36
spec/javascripts/vue_mr_widget/mock_data.js
spec/javascripts/vue_mr_widget/mock_data.js
+1
-1
spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
+31
-28
spec/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
.../components/sidebar/collapsed_grouped_date_picker_spec.js
+4
-4
spec/javascripts/vue_shared/components/sidebar/date_picker_spec.js
...scripts/vue_shared/components/sidebar/date_picker_spec.js
+6
-6
spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
...ts/sidebar/labels_select/dropdown_value_collapsed_spec.js
+3
-1
No files found.
app/assets/javascripts/blob_edit/blob_bundle.js
View file @
7e9f44fa
...
@@ -13,7 +13,7 @@ export default () => {
...
@@ -13,7 +13,7 @@ export default () => {
if
(
editBlobForm
.
length
)
{
if
(
editBlobForm
.
length
)
{
const
urlRoot
=
editBlobForm
.
data
(
'
relativeUrlRoot
'
);
const
urlRoot
=
editBlobForm
.
data
(
'
relativeUrlRoot
'
);
const
assetsPath
=
editBlobForm
.
data
(
'
assetsPrefix
'
);
const
assetsPath
=
editBlobForm
.
data
(
'
assetsPrefix
'
);
const
filePath
=
editBlobForm
.
data
(
'
blobFilename
'
)
const
filePath
=
editBlobForm
.
data
(
'
blobFilename
'
)
;
const
currentAction
=
$
(
'
.js-file-title
'
).
data
(
'
currentAction
'
);
const
currentAction
=
$
(
'
.js-file-title
'
).
data
(
'
currentAction
'
);
const
projectId
=
editBlobForm
.
data
(
'
project-id
'
);
const
projectId
=
editBlobForm
.
data
(
'
project-id
'
);
...
...
app/assets/javascripts/boards/components/board.js
View file @
7e9f44fa
...
@@ -42,7 +42,7 @@ export default Vue.extend({
...
@@ -42,7 +42,7 @@ export default Vue.extend({
required
:
true
,
required
:
true
,
},
},
},
},
data
()
{
data
()
{
return
{
return
{
detailIssue
:
boardsStore
.
detail
,
detailIssue
:
boardsStore
.
detail
,
filter
:
boardsStore
.
filter
,
filter
:
boardsStore
.
filter
,
...
@@ -55,27 +55,26 @@ export default Vue.extend({
...
@@ -55,27 +55,26 @@ export default Vue.extend({
},
},
isNewIssueShown
()
{
isNewIssueShown
()
{
return
this
.
list
.
type
===
'
backlog
'
||
(
!
this
.
disabled
&&
this
.
list
.
type
!==
'
closed
'
);
return
this
.
list
.
type
===
'
backlog
'
||
(
!
this
.
disabled
&&
this
.
list
.
type
!==
'
closed
'
);
}
}
,
},
},
watch
:
{
watch
:
{
filter
:
{
filter
:
{
handler
()
{
handler
()
{
this
.
list
.
page
=
1
;
this
.
list
.
page
=
1
;
this
.
list
.
getIssues
(
true
)
this
.
list
.
getIssues
(
true
).
catch
(()
=>
{
.
catch
(()
=>
{
// TODO: handle request error
// TODO: handle request error
});
});
},
},
deep
:
true
,
deep
:
true
,
}
},
},
mounted
()
{
},
mounted
()
{
this
.
sortableOptions
=
getBoardSortableDefaultOptions
({
this
.
sortableOptions
=
getBoardSortableDefaultOptions
({
disabled
:
this
.
disabled
,
disabled
:
this
.
disabled
,
group
:
'
boards
'
,
group
:
'
boards
'
,
draggable
:
'
.is-draggable
'
,
draggable
:
'
.is-draggable
'
,
handle
:
'
.js-board-handle
'
,
handle
:
'
.js-board-handle
'
,
onEnd
:
(
e
)
=>
{
onEnd
:
e
=>
{
sortableEnd
();
sortableEnd
();
if
(
e
.
newIndex
!==
undefined
&&
e
.
oldIndex
!==
e
.
newIndex
)
{
if
(
e
.
newIndex
!==
undefined
&&
e
.
oldIndex
!==
e
.
newIndex
)
{
...
@@ -86,14 +85,15 @@ export default Vue.extend({
...
@@ -86,14 +85,15 @@ export default Vue.extend({
boardsStore
.
moveList
(
list
,
order
);
boardsStore
.
moveList
(
list
,
order
);
});
});
}
}
}
}
,
});
});
this
.
sortable
=
Sortable
.
create
(
this
.
$el
.
parentNode
,
this
.
sortableOptions
);
this
.
sortable
=
Sortable
.
create
(
this
.
$el
.
parentNode
,
this
.
sortableOptions
);
},
},
created
()
{
created
()
{
if
(
this
.
list
.
isExpandable
&&
AccessorUtilities
.
isLocalStorageAccessSafe
())
{
if
(
this
.
list
.
isExpandable
&&
AccessorUtilities
.
isLocalStorageAccessSafe
())
{
const
isCollapsed
=
localStorage
.
getItem
(
`boards.
${
this
.
boardId
}
.
${
this
.
list
.
type
}
.expanded`
)
===
'
false
'
;
const
isCollapsed
=
localStorage
.
getItem
(
`boards.
${
this
.
boardId
}
.
${
this
.
list
.
type
}
.expanded`
)
===
'
false
'
;
this
.
list
.
isExpanded
=
!
isCollapsed
;
this
.
list
.
isExpanded
=
!
isCollapsed
;
}
}
...
@@ -107,7 +107,10 @@ export default Vue.extend({
...
@@ -107,7 +107,10 @@ export default Vue.extend({
this
.
list
.
isExpanded
=
!
this
.
list
.
isExpanded
;
this
.
list
.
isExpanded
=
!
this
.
list
.
isExpanded
;
if
(
AccessorUtilities
.
isLocalStorageAccessSafe
())
{
if
(
AccessorUtilities
.
isLocalStorageAccessSafe
())
{
localStorage
.
setItem
(
`boards.
${
this
.
boardId
}
.
${
this
.
list
.
type
}
.expanded`
,
this
.
list
.
isExpanded
);
localStorage
.
setItem
(
`boards.
${
this
.
boardId
}
.
${
this
.
list
.
type
}
.expanded`
,
this
.
list
.
isExpanded
,
);
}
}
}
}
},
},
...
...
app/assets/javascripts/boards/components/board_blank_state.vue
View file @
7e9f44fa
...
@@ -32,16 +32,16 @@ export default {
...
@@ -32,16 +32,16 @@ export default {
boardsStore
.
state
.
lists
=
_
.
sortBy
(
boardsStore
.
state
.
lists
,
'
position
'
);
boardsStore
.
state
.
lists
=
_
.
sortBy
(
boardsStore
.
state
.
lists
,
'
position
'
);
// Save the labels
// Save the labels
gl
.
boardService
.
generateDefaultLists
()
gl
.
boardService
.
generateDefaultLists
()
.
then
(
res
=>
res
.
data
)
.
then
(
res
=>
res
.
data
)
.
then
(
(
data
)
=>
{
.
then
(
data
=>
{
data
.
forEach
(
(
listObj
)
=>
{
data
.
forEach
(
listObj
=>
{
const
list
=
boardsStore
.
findList
(
'
title
'
,
listObj
.
title
);
const
list
=
boardsStore
.
findList
(
'
title
'
,
listObj
.
title
);
list
.
id
=
listObj
.
id
;
list
.
id
=
listObj
.
id
;
list
.
label
.
id
=
listObj
.
label
.
id
;
list
.
label
.
id
=
listObj
.
label
.
id
;
list
.
getIssues
()
list
.
getIssues
().
catch
(()
=>
{
.
catch
(()
=>
{
// TODO: handle request error
// TODO: handle request error
});
});
});
});
...
@@ -57,7 +57,6 @@ export default {
...
@@ -57,7 +57,6 @@ export default {
clearBlankState
:
boardsStore
.
removeBlankState
.
bind
(
boardsStore
),
clearBlankState
:
boardsStore
.
removeBlankState
.
bind
(
boardsStore
),
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/boards/components/board_card.vue
View file @
7e9f44fa
<
script
>
<
script
>
/* eslint-disable vue/require-default-prop */
/* eslint-disable vue/require-default-prop */
import
IssueCardInner
from
'
./issue_card_inner.vue
'
;
import
IssueCardInner
from
'
./issue_card_inner.vue
'
;
import
eventHub
from
'
../eventhub
'
;
import
eventHub
from
'
../eventhub
'
;
import
boardsStore
from
'
../stores/boards_store
'
;
import
boardsStore
from
'
../stores/boards_store
'
;
export
default
{
export
default
{
name
:
'
BoardsIssueCard
'
,
name
:
'
BoardsIssueCard
'
,
components
:
{
components
:
{
IssueCardInner
,
IssueCardInner
,
...
@@ -71,7 +71,7 @@
...
@@ -71,7 +71,7 @@
}
}
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/boards/components/board_new_issue.vue
View file @
7e9f44fa
...
@@ -65,7 +65,8 @@ export default {
...
@@ -65,7 +65,8 @@ export default {
eventHub
.
$emit
(
`scroll-board-list-
${
this
.
list
.
id
}
`
);
eventHub
.
$emit
(
`scroll-board-list-
${
this
.
list
.
id
}
`
);
this
.
cancel
();
this
.
cancel
();
return
this
.
list
.
newIssue
(
issue
)
return
this
.
list
.
newIssue
(
issue
)
.
then
(()
=>
{
.
then
(()
=>
{
// Need this because our jQuery very kindly disables buttons on ALL form submissions
// Need this because our jQuery very kindly disables buttons on ALL form submissions
$
(
this
.
$refs
.
submitButton
).
enable
();
$
(
this
.
$refs
.
submitButton
).
enable
();
...
...
app/assets/javascripts/boards/components/board_sidebar.js
View file @
7e9f44fa
...
@@ -40,7 +40,7 @@ export default Vue.extend({
...
@@ -40,7 +40,7 @@ export default Vue.extend({
};
};
},
},
computed
:
{
computed
:
{
showSidebar
()
{
showSidebar
()
{
return
Object
.
keys
(
this
.
issue
).
length
;
return
Object
.
keys
(
this
.
issue
).
length
;
},
},
milestoneTitle
()
{
milestoneTitle
()
{
...
@@ -53,18 +53,20 @@ export default Vue.extend({
...
@@ -53,18 +53,20 @@ export default Vue.extend({
return
this
.
issue
.
labels
&&
this
.
issue
.
labels
.
length
;
return
this
.
issue
.
labels
&&
this
.
issue
.
labels
.
length
;
},
},
labelDropdownTitle
()
{
labelDropdownTitle
()
{
return
this
.
hasLabels
?
sprintf
(
__
(
'
%{firstLabel} +%{labelCount} more
'
),
{
return
this
.
hasLabels
?
sprintf
(
__
(
'
%{firstLabel} +%{labelCount} more
'
),
{
firstLabel
:
this
.
issue
.
labels
[
0
].
title
,
firstLabel
:
this
.
issue
.
labels
[
0
].
title
,
labelCount
:
this
.
issue
.
labels
.
length
-
1
labelCount
:
this
.
issue
.
labels
.
length
-
1
,
})
:
__
(
'
Label
'
);
})
:
__
(
'
Label
'
);
},
},
selectedLabels
()
{
selectedLabels
()
{
return
this
.
hasLabels
?
this
.
issue
.
labels
.
map
(
l
=>
l
.
title
).
join
(
'
,
'
)
:
''
;
return
this
.
hasLabels
?
this
.
issue
.
labels
.
map
(
l
=>
l
.
title
).
join
(
'
,
'
)
:
''
;
}
}
,
},
},
watch
:
{
watch
:
{
detail
:
{
detail
:
{
handler
()
{
handler
()
{
if
(
this
.
issue
.
id
!==
this
.
detail
.
issue
.
id
)
{
if
(
this
.
issue
.
id
!==
this
.
detail
.
issue
.
id
)
{
$
(
'
.block.assignee
'
)
$
(
'
.block.assignee
'
)
.
find
(
'
input:not(.js-vue)[name="issue[assignee_ids][]"]
'
)
.
find
(
'
input:not(.js-vue)[name="issue[assignee_ids][]"]
'
)
...
@@ -73,17 +75,19 @@ export default Vue.extend({
...
@@ -73,17 +75,19 @@ export default Vue.extend({
});
});
$
(
'
.js-issue-board-sidebar
'
,
this
.
$el
).
each
((
i
,
el
)
=>
{
$
(
'
.js-issue-board-sidebar
'
,
this
.
$el
).
each
((
i
,
el
)
=>
{
$
(
el
).
data
(
'
glDropdown
'
).
clearMenu
();
$
(
el
)
.
data
(
'
glDropdown
'
)
.
clearMenu
();
});
});
}
}
this
.
issue
=
this
.
detail
.
issue
;
this
.
issue
=
this
.
detail
.
issue
;
this
.
list
=
this
.
detail
.
list
;
this
.
list
=
this
.
detail
.
list
;
},
},
deep
:
true
deep
:
true
,
},
},
},
},
created
()
{
created
()
{
// Get events from glDropdown
// Get events from glDropdown
eventHub
.
$on
(
'
sidebar.removeAssignee
'
,
this
.
removeAssignee
);
eventHub
.
$on
(
'
sidebar.removeAssignee
'
,
this
.
removeAssignee
);
eventHub
.
$on
(
'
sidebar.addAssignee
'
,
this
.
addAssignee
);
eventHub
.
$on
(
'
sidebar.addAssignee
'
,
this
.
addAssignee
);
...
@@ -96,7 +100,7 @@ export default Vue.extend({
...
@@ -96,7 +100,7 @@ export default Vue.extend({
eventHub
.
$off
(
'
sidebar.removeAllAssignees
'
,
this
.
removeAllAssignees
);
eventHub
.
$off
(
'
sidebar.removeAllAssignees
'
,
this
.
removeAllAssignees
);
eventHub
.
$off
(
'
sidebar.saveAssignees
'
,
this
.
saveAssignees
);
eventHub
.
$off
(
'
sidebar.saveAssignees
'
,
this
.
saveAssignees
);
},
},
mounted
()
{
mounted
()
{
new
IssuableContext
(
this
.
currentUser
);
new
IssuableContext
(
this
.
currentUser
);
new
MilestoneSelect
();
new
MilestoneSelect
();
new
DueDateSelectors
();
new
DueDateSelectors
();
...
@@ -104,29 +108,30 @@ export default Vue.extend({
...
@@ -104,29 +108,30 @@ export default Vue.extend({
new
Sidebar
();
new
Sidebar
();
},
},
methods
:
{
methods
:
{
closeSidebar
()
{
closeSidebar
()
{
this
.
detail
.
issue
=
{};
this
.
detail
.
issue
=
{};
},
},
assignSelf
()
{
assignSelf
()
{
// Notify gl dropdown that we are now assigning to current user
// Notify gl dropdown that we are now assigning to current user
this
.
$refs
.
assigneeBlock
.
dispatchEvent
(
new
Event
(
'
assignYourself
'
));
this
.
$refs
.
assigneeBlock
.
dispatchEvent
(
new
Event
(
'
assignYourself
'
));
this
.
addAssignee
(
this
.
currentUser
);
this
.
addAssignee
(
this
.
currentUser
);
this
.
saveAssignees
();
this
.
saveAssignees
();
},
},
removeAssignee
(
a
)
{
removeAssignee
(
a
)
{
boardsStore
.
detail
.
issue
.
removeAssignee
(
a
);
boardsStore
.
detail
.
issue
.
removeAssignee
(
a
);
},
},
addAssignee
(
a
)
{
addAssignee
(
a
)
{
boardsStore
.
detail
.
issue
.
addAssignee
(
a
);
boardsStore
.
detail
.
issue
.
addAssignee
(
a
);
},
},
removeAllAssignees
()
{
removeAllAssignees
()
{
boardsStore
.
detail
.
issue
.
removeAllAssignees
();
boardsStore
.
detail
.
issue
.
removeAllAssignees
();
},
},
saveAssignees
()
{
saveAssignees
()
{
this
.
loadingAssignees
=
true
;
this
.
loadingAssignees
=
true
;
boardsStore
.
detail
.
issue
.
update
()
boardsStore
.
detail
.
issue
.
update
()
.
then
(()
=>
{
.
then
(()
=>
{
this
.
loadingAssignees
=
false
;
this
.
loadingAssignees
=
false
;
})
})
...
...
app/assets/javascripts/boards/components/issue_card_inner.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
$
from
'
jquery
'
;
import
$
from
'
jquery
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
IssueCardWeight
from
'
ee/boards/components/issue_card_weight.vue
'
;
import
IssueCardWeight
from
'
ee/boards/components/issue_card_weight.vue
'
;
import
UserAvatarLink
from
'
../../vue_shared/components/user_avatar/user_avatar_link.vue
'
;
import
UserAvatarLink
from
'
../../vue_shared/components/user_avatar/user_avatar_link.vue
'
;
import
eventHub
from
'
../eventhub
'
;
import
eventHub
from
'
../eventhub
'
;
import
tooltip
from
'
../../vue_shared/directives/tooltip
'
;
import
tooltip
from
'
../../vue_shared/directives/tooltip
'
;
import
boardsStore
from
'
../stores/boards_store
'
;
import
boardsStore
from
'
../stores/boards_store
'
;
export
default
{
export
default
{
components
:
{
components
:
{
UserAvatarLink
,
UserAvatarLink
,
Icon
,
Icon
,
...
@@ -138,7 +138,7 @@
...
@@ -138,7 +138,7 @@
};
};
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<div>
<div>
...
...
app/assets/javascripts/boards/components/modal/empty_state.vue
View file @
7e9f44fa
...
@@ -20,7 +20,7 @@ export default {
...
@@ -20,7 +20,7 @@ export default {
computed
:
{
computed
:
{
contents
()
{
contents
()
{
const
obj
=
{
const
obj
=
{
title
:
'
You haven
\'
t added any issues to your project yet
'
,
title
:
"
You haven't added any issues to your project yet
"
,
content
:
`
content
:
`
An issue can be a bug, a todo or a feature request that needs to be
An issue can be a bug, a todo or a feature request that needs to be
discussed in a project. Besides, issues are searchable and filterable.
discussed in a project. Besides, issues are searchable and filterable.
...
@@ -28,7 +28,7 @@ export default {
...
@@ -28,7 +28,7 @@ export default {
};
};
if
(
this
.
activeTab
===
'
selected
'
)
{
if
(
this
.
activeTab
===
'
selected
'
)
{
obj
.
title
=
'
You haven
\'
t selected any issues yet
'
;
obj
.
title
=
"
You haven't selected any issues yet
"
;
obj
.
content
=
`
obj
.
content
=
`
Go back to <strong>Open issues</strong> and select some issues
Go back to <strong>Open issues</strong> and select some issues
to add to your board.
to add to your board.
...
...
app/assets/javascripts/boards/components/modal/footer.vue
View file @
7e9f44fa
...
@@ -42,19 +42,17 @@ export default {
...
@@ -42,19 +42,17 @@ export default {
const
req
=
this
.
buildUpdateRequest
(
list
);
const
req
=
this
.
buildUpdateRequest
(
list
);
// Post the data to the backend
// Post the data to the backend
gl
.
boardService
gl
.
boardService
.
bulkUpdate
(
issueIds
,
req
).
catch
(()
=>
{
.
bulkUpdate
(
issueIds
,
req
)
.
catch
(()
=>
{
Flash
(
__
(
'
Failed to update issues, please try again.
'
));
Flash
(
__
(
'
Failed to update issues, please try again.
'
));
selectedIssues
.
forEach
((
issue
)
=>
{
selectedIssues
.
forEach
(
issue
=>
{
list
.
removeIssue
(
issue
);
list
.
removeIssue
(
issue
);
list
.
issuesSize
-=
1
;
list
.
issuesSize
-=
1
;
});
});
});
});
// Add the issues on the frontend
// Add the issues on the frontend
selectedIssues
.
forEach
(
(
issue
)
=>
{
selectedIssues
.
forEach
(
issue
=>
{
list
.
addIssue
(
issue
);
list
.
addIssue
(
issue
);
list
.
issuesSize
+=
1
;
list
.
issuesSize
+=
1
;
});
});
...
...
app/assets/javascripts/boards/components/modal/header.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
ModalFilters
from
'
./filters
'
;
import
ModalFilters
from
'
./filters
'
;
import
ModalTabs
from
'
./tabs.vue
'
;
import
ModalTabs
from
'
./tabs.vue
'
;
import
ModalStore
from
'
../../stores/modal_store
'
;
import
ModalStore
from
'
../../stores/modal_store
'
;
import
modalMixin
from
'
../../mixins/modal_mixins
'
;
import
modalMixin
from
'
../../mixins/modal_mixins
'
;
export
default
{
export
default
{
components
:
{
components
:
{
ModalTabs
,
ModalTabs
,
ModalFilters
,
ModalFilters
,
...
@@ -46,7 +46,7 @@
...
@@ -46,7 +46,7 @@
ModalStore
.
toggleAll
();
ModalStore
.
toggleAll
();
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<div>
<div>
...
...
app/assets/javascripts/boards/components/modal/index.vue
View file @
7e9f44fa
<
script
>
<
script
>
/* global ListIssue */
/* global ListIssue */
import
{
urlParamsToObject
}
from
'
~/lib/utils/common_utils
'
;
import
{
urlParamsToObject
}
from
'
~/lib/utils/common_utils
'
;
import
ModalHeader
from
'
./header.vue
'
;
import
ModalHeader
from
'
./header.vue
'
;
import
ModalList
from
'
./list.vue
'
;
import
ModalList
from
'
./list.vue
'
;
import
ModalFooter
from
'
./footer.vue
'
;
import
ModalFooter
from
'
./footer.vue
'
;
import
EmptyState
from
'
./empty_state.vue
'
;
import
EmptyState
from
'
./empty_state.vue
'
;
import
ModalStore
from
'
../../stores/modal_store
'
;
import
ModalStore
from
'
../../stores/modal_store
'
;
export
default
{
export
default
{
components
:
{
components
:
{
EmptyState
,
EmptyState
,
ModalHeader
,
ModalHeader
,
...
@@ -107,7 +107,8 @@
...
@@ -107,7 +107,8 @@
loadIssues
(
clearIssues
=
false
)
{
loadIssues
(
clearIssues
=
false
)
{
if
(
!
this
.
showAddIssuesModal
)
return
false
;
if
(
!
this
.
showAddIssuesModal
)
return
false
;
return
gl
.
boardService
.
getBacklog
({
return
gl
.
boardService
.
getBacklog
({
...
urlParamsToObject
(
this
.
filter
.
path
),
...
urlParamsToObject
(
this
.
filter
.
path
),
page
:
this
.
page
,
page
:
this
.
page
,
per
:
this
.
perPage
,
per
:
this
.
perPage
,
...
@@ -137,7 +138,7 @@
...
@@ -137,7 +138,7 @@
});
});
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<div
<div
...
...
app/assets/javascripts/boards/components/modal/list.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
Icon
from
'
~/vue_shared/components/icon.vue
'
;
import
bp
from
'
../../../breakpoints
'
;
import
bp
from
'
../../../breakpoints
'
;
import
ModalStore
from
'
../../stores/modal_store
'
;
import
ModalStore
from
'
../../stores/modal_store
'
;
import
IssueCardInner
from
'
../issue_card_inner.vue
'
;
import
IssueCardInner
from
'
../issue_card_inner.vue
'
;
export
default
{
export
default
{
components
:
{
components
:
{
IssueCardInner
,
IssueCardInner
,
Icon
,
Icon
,
...
@@ -114,7 +114,7 @@
...
@@ -114,7 +114,7 @@
}
}
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<section
<section
...
...
app/assets/javascripts/boards/components/modal/tabs.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
ModalStore
from
'
../../stores/modal_store
'
;
import
ModalStore
from
'
../../stores/modal_store
'
;
import
modalMixin
from
'
../../mixins/modal_mixins
'
;
import
modalMixin
from
'
../../mixins/modal_mixins
'
;
export
default
{
export
default
{
mixins
:
[
modalMixin
],
mixins
:
[
modalMixin
],
data
()
{
data
()
{
return
ModalStore
.
store
;
return
ModalStore
.
store
;
...
@@ -15,7 +15,7 @@
...
@@ -15,7 +15,7 @@
destroyed
()
{
destroyed
()
{
this
.
activeTab
=
'
all
'
;
this
.
activeTab
=
'
all
'
;
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<div
class=
"top-area prepend-top-10 append-bottom-10"
>
<div
class=
"top-area prepend-top-10 append-bottom-10"
>
...
...
app/assets/javascripts/boards/components/new_list_dropdown.js
View file @
7e9f44fa
...
@@ -6,7 +6,9 @@ import _ from 'underscore';
...
@@ -6,7 +6,9 @@ import _ from 'underscore';
import
CreateLabelDropdown
from
'
../../create_label
'
;
import
CreateLabelDropdown
from
'
../../create_label
'
;
import
boardsStore
from
'
../stores/boards_store
'
;
import
boardsStore
from
'
../stores/boards_store
'
;
$
(
document
).
off
(
'
created.label
'
).
on
(
'
created.label
'
,
(
e
,
label
)
=>
{
$
(
document
)
.
off
(
'
created.label
'
)
.
on
(
'
created.label
'
,
(
e
,
label
)
=>
{
boardsStore
.
new
({
boardsStore
.
new
({
title
:
label
.
title
,
title
:
label
.
title
,
position
:
boardsStore
.
state
.
lists
.
length
-
2
,
position
:
boardsStore
.
state
.
lists
.
length
-
2
,
...
@@ -17,25 +19,28 @@ $(document).off('created.label').on('created.label', (e, label) => {
...
@@ -17,25 +19,28 @@ $(document).off('created.label').on('created.label', (e, label) => {
color
:
label
.
color
,
color
:
label
.
color
,
},
},
});
});
});
});
export
default
function
initNewListDropdown
()
{
export
default
function
initNewListDropdown
()
{
$
(
'
.js-new-board-list
'
).
each
(
function
()
{
$
(
'
.js-new-board-list
'
).
each
(
function
()
{
const
$this
=
$
(
this
);
const
$this
=
$
(
this
);
new
CreateLabelDropdown
(
$this
.
closest
(
'
.dropdown
'
).
find
(
'
.dropdown-new-label
'
),
$this
.
data
(
'
namespacePath
'
),
$this
.
data
(
'
projectPath
'
));
new
CreateLabelDropdown
(
$this
.
closest
(
'
.dropdown
'
).
find
(
'
.dropdown-new-label
'
),
$this
.
data
(
'
namespacePath
'
),
$this
.
data
(
'
projectPath
'
),
);
$this
.
glDropdown
({
$this
.
glDropdown
({
data
(
term
,
callback
)
{
data
(
term
,
callback
)
{
axios
.
get
(
$this
.
attr
(
'
data-list-labels-path
'
))
axios
.
get
(
$this
.
attr
(
'
data-list-labels-path
'
)).
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
callback
(
data
);
callback
(
data
);
});
});
},
},
renderRow
(
label
)
{
renderRow
(
label
)
{
const
active
=
boardsStore
.
findList
(
'
title
'
,
label
.
title
);
const
active
=
boardsStore
.
findList
(
'
title
'
,
label
.
title
);
const
$li
=
$
(
'
<li />
'
);
const
$li
=
$
(
'
<li />
'
);
const
$a
=
$
(
'
<a />
'
,
{
const
$a
=
$
(
'
<a />
'
,
{
class
:
(
active
?
`is-active js-board-list-
${
active
.
id
}
`
:
''
)
,
class
:
active
?
`is-active js-board-list-
${
active
.
id
}
`
:
''
,
text
:
label
.
title
,
text
:
label
.
title
,
href
:
'
#
'
,
href
:
'
#
'
,
});
});
...
@@ -53,7 +58,7 @@ export default function initNewListDropdown() {
...
@@ -53,7 +58,7 @@ export default function initNewListDropdown() {
selectable
:
true
,
selectable
:
true
,
multiSelect
:
true
,
multiSelect
:
true
,
containerSelector
:
'
.js-tab-container-labels .dropdown-page-one .dropdown-content
'
,
containerSelector
:
'
.js-tab-container-labels .dropdown-page-one .dropdown-content
'
,
clicked
(
options
)
{
clicked
(
options
)
{
const
{
e
}
=
options
;
const
{
e
}
=
options
;
const
label
=
options
.
selectedObj
;
const
label
=
options
.
selectedObj
;
e
.
preventDefault
();
e
.
preventDefault
();
...
...
app/assets/javascripts/boards/components/project_select.vue
View file @
7e9f44fa
...
@@ -46,7 +46,7 @@ export default {
...
@@ -46,7 +46,7 @@ export default {
selectable
:
true
,
selectable
:
true
,
data
:
(
term
,
callback
)
=>
{
data
:
(
term
,
callback
)
=>
{
this
.
loading
=
true
;
this
.
loading
=
true
;
return
Api
.
groupProjects
(
this
.
groupId
,
term
,
{
with_issues_enabled
:
true
},
projects
=>
{
return
Api
.
groupProjects
(
this
.
groupId
,
term
,
{
with_issues_enabled
:
true
},
projects
=>
{
this
.
loading
=
false
;
this
.
loading
=
false
;
callback
(
projects
);
callback
(
projects
);
});
});
...
@@ -54,7 +54,9 @@ export default {
...
@@ -54,7 +54,9 @@ export default {
renderRow
(
project
)
{
renderRow
(
project
)
{
return
`
return
`
<li>
<li>
<a href='#' class='dropdown-menu-link' data-project-id="
${
project
.
id
}
" data-project-name="
${
project
.
name
}
">
<a href='#' class='dropdown-menu-link' data-project-id="
${
project
.
id
}
" data-project-name="
${
project
.
name
}
">
${
_
.
escape
(
project
.
name
)}
${
_
.
escape
(
project
.
name
)}
</a>
</a>
</li>
</li>
...
...
app/assets/javascripts/boards/components/sidebar/remove_issue.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
Vue
from
'
vue
'
;
import
Vue
from
'
vue
'
;
import
Flash
from
'
../../../flash
'
;
import
Flash
from
'
../../../flash
'
;
import
{
__
}
from
'
../../../locale
'
;
import
{
__
}
from
'
../../../locale
'
;
import
boardsStore
from
'
../../stores/boards_store
'
;
import
boardsStore
from
'
../../stores/boards_store
'
;
export
default
Vue
.
extend
({
export
default
Vue
.
extend
({
props
:
{
props
:
{
issue
:
{
issue
:
{
type
:
Object
,
type
:
Object
,
...
@@ -38,13 +38,13 @@
...
@@ -38,13 +38,13 @@
Vue
.
http
.
patch
(
this
.
updateUrl
,
data
).
catch
(()
=>
{
Vue
.
http
.
patch
(
this
.
updateUrl
,
data
).
catch
(()
=>
{
Flash
(
__
(
'
Failed to remove issue from board, please try again.
'
));
Flash
(
__
(
'
Failed to remove issue from board, please try again.
'
));
lists
.
forEach
((
list
)
=>
{
lists
.
forEach
(
list
=>
{
list
.
addIssue
(
issue
);
list
.
addIssue
(
issue
);
});
});
});
});
// Remove from the frontend store
// Remove from the frontend store
lists
.
forEach
((
list
)
=>
{
lists
.
forEach
(
list
=>
{
list
.
removeIssue
(
issue
);
list
.
removeIssue
(
issue
);
});
});
...
@@ -56,9 +56,7 @@
...
@@ -56,9 +56,7 @@
buildPatchRequest
(
issue
,
lists
)
{
buildPatchRequest
(
issue
,
lists
)
{
const
listLabelIds
=
lists
.
map
(
list
=>
list
.
label
.
id
);
const
listLabelIds
=
lists
.
map
(
list
=>
list
.
label
.
id
);
const
labelIds
=
issue
.
labels
const
labelIds
=
issue
.
labels
.
map
(
label
=>
label
.
id
).
filter
(
id
=>
!
listLabelIds
.
includes
(
id
));
.
map
(
label
=>
label
.
id
)
.
filter
(
id
=>
!
listLabelIds
.
includes
(
id
));
return
{
return
{
label_ids
:
labelIds
,
label_ids
:
labelIds
,
...
@@ -73,7 +71,7 @@
...
@@ -73,7 +71,7 @@
return
req
;
return
req
;
},
},
},
},
});
});
</
script
>
</
script
>
<
template
>
<
template
>
<div
<div
...
...
app/assets/javascripts/boards/filtered_search_boards.js
View file @
7e9f44fa
...
@@ -35,7 +35,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
...
@@ -35,7 +35,7 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
const
tokens
=
FilteredSearchContainer
.
container
.
querySelectorAll
(
'
.js-visual-token
'
);
const
tokens
=
FilteredSearchContainer
.
container
.
querySelectorAll
(
'
.js-visual-token
'
);
// Remove all the tokens as they will be replaced by the search manager
// Remove all the tokens as they will be replaced by the search manager
[].
forEach
.
call
(
tokens
,
(
el
)
=>
{
[].
forEach
.
call
(
tokens
,
el
=>
{
el
.
parentNode
.
removeChild
(
el
);
el
.
parentNode
.
removeChild
(
el
);
});
});
...
@@ -53,7 +53,10 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
...
@@ -53,7 +53,10 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
canEdit
(
tokenName
,
tokenValue
)
{
canEdit
(
tokenName
,
tokenValue
)
{
if
(
this
.
cantEdit
.
includes
(
tokenName
))
return
false
;
if
(
this
.
cantEdit
.
includes
(
tokenName
))
return
false
;
return
this
.
cantEditWithValue
.
findIndex
(
token
=>
token
.
name
===
tokenName
&&
return
(
token
.
value
===
tokenValue
)
===
-
1
;
this
.
cantEditWithValue
.
findIndex
(
token
=>
token
.
name
===
tokenName
&&
token
.
value
===
tokenValue
,
)
===
-
1
);
}
}
}
}
app/assets/javascripts/boards/index.js
View file @
7e9f44fa
...
@@ -39,9 +39,9 @@ export default () => {
...
@@ -39,9 +39,9 @@ export default () => {
const
issueBoardsContent
=
document
.
querySelector
(
'
.content-wrapper > .js-focus-mode-board
'
);
const
issueBoardsContent
=
document
.
querySelector
(
'
.content-wrapper > .js-focus-mode-board
'
);
// check for browser back and trigger a hard reload to circumvent browser caching.
// check for browser back and trigger a hard reload to circumvent browser caching.
window
.
addEventListener
(
'
pageshow
'
,
(
event
)
=>
{
window
.
addEventListener
(
'
pageshow
'
,
event
=>
{
const
isNavTypeBackForward
=
window
.
performance
&&
const
isNavTypeBackForward
=
window
.
performance
.
navigation
.
type
===
NavigationType
.
TYPE_BACK_FORWARD
;
window
.
performance
&&
window
.
performance
.
navigation
.
type
===
NavigationType
.
TYPE_BACK_FORWARD
;
if
(
event
.
persisted
||
isNavTypeBackForward
)
{
if
(
event
.
persisted
||
isNavTypeBackForward
)
{
window
.
location
.
reload
();
window
.
location
.
reload
();
...
...
app/assets/javascripts/boards/mixins/sortable_default_options.js
View file @
7e9f44fa
...
@@ -4,7 +4,8 @@ import $ from 'jquery';
...
@@ -4,7 +4,8 @@ import $ from 'jquery';
import
sortableConfig
from
'
ee/sortable/sortable_config
'
;
import
sortableConfig
from
'
ee/sortable/sortable_config
'
;
export
function
sortableStart
()
{
export
function
sortableStart
()
{
$
(
'
.has-tooltip
'
).
tooltip
(
'
hide
'
)
$
(
'
.has-tooltip
'
)
.
tooltip
(
'
hide
'
)
.
tooltip
(
'
disable
'
);
.
tooltip
(
'
disable
'
);
document
.
body
.
classList
.
add
(
'
is-dragging
'
);
document
.
body
.
classList
.
add
(
'
is-dragging
'
);
}
}
...
@@ -15,7 +16,8 @@ export function sortableEnd() {
...
@@ -15,7 +16,8 @@ export function sortableEnd() {
}
}
export
function
getBoardSortableDefaultOptions
(
obj
)
{
export
function
getBoardSortableDefaultOptions
(
obj
)
{
const
touchEnabled
=
(
'
ontouchstart
'
in
window
)
||
window
.
DocumentTouch
&&
document
instanceof
DocumentTouch
;
const
touchEnabled
=
'
ontouchstart
'
in
window
||
(
window
.
DocumentTouch
&&
document
instanceof
DocumentTouch
);
const
defaultSortOptions
=
Object
.
assign
({},
sortableConfig
,
{
const
defaultSortOptions
=
Object
.
assign
({},
sortableConfig
,
{
filter
:
'
.board-delete, .btn
'
,
filter
:
'
.board-delete, .btn
'
,
...
@@ -26,6 +28,8 @@ export function getBoardSortableDefaultOptions(obj) {
...
@@ -26,6 +28,8 @@ export function getBoardSortableDefaultOptions(obj) {
onEnd
:
sortableEnd
,
onEnd
:
sortableEnd
,
});
});
Object
.
keys
(
obj
).
forEach
((
key
)
=>
{
defaultSortOptions
[
key
]
=
obj
[
key
];
});
Object
.
keys
(
obj
).
forEach
(
key
=>
{
defaultSortOptions
[
key
]
=
obj
[
key
];
});
return
defaultSortOptions
;
return
defaultSortOptions
;
}
}
app/assets/javascripts/boards/models/issue.js
View file @
7e9f44fa
...
@@ -9,7 +9,7 @@ import IssueProject from './project';
...
@@ -9,7 +9,7 @@ import IssueProject from './project';
import
boardsStore
from
'
../stores/boards_store
'
;
import
boardsStore
from
'
../stores/boards_store
'
;
class
ListIssue
{
class
ListIssue
{
constructor
(
obj
,
defaultAvatar
)
{
constructor
(
obj
,
defaultAvatar
)
{
this
.
id
=
obj
.
id
;
this
.
id
=
obj
.
id
;
this
.
iid
=
obj
.
iid
;
this
.
iid
=
obj
.
iid
;
this
.
title
=
obj
.
title
;
this
.
title
=
obj
.
title
;
...
@@ -39,67 +39,67 @@ class ListIssue {
...
@@ -39,67 +39,67 @@ class ListIssue {
this
.
milestone_id
=
obj
.
milestone
.
id
;
this
.
milestone_id
=
obj
.
milestone
.
id
;
}
}
obj
.
labels
.
forEach
(
(
label
)
=>
{
obj
.
labels
.
forEach
(
label
=>
{
this
.
labels
.
push
(
new
ListLabel
(
label
));
this
.
labels
.
push
(
new
ListLabel
(
label
));
});
});
this
.
assignees
=
obj
.
assignees
.
map
(
a
=>
new
ListAssignee
(
a
,
defaultAvatar
));
this
.
assignees
=
obj
.
assignees
.
map
(
a
=>
new
ListAssignee
(
a
,
defaultAvatar
));
}
}
addLabel
(
label
)
{
addLabel
(
label
)
{
if
(
!
this
.
findLabel
(
label
))
{
if
(
!
this
.
findLabel
(
label
))
{
this
.
labels
.
push
(
new
ListLabel
(
label
));
this
.
labels
.
push
(
new
ListLabel
(
label
));
}
}
}
}
findLabel
(
findLabel
)
{
findLabel
(
findLabel
)
{
return
this
.
labels
.
filter
(
label
=>
label
.
title
===
findLabel
.
title
)[
0
];
return
this
.
labels
.
filter
(
label
=>
label
.
title
===
findLabel
.
title
)[
0
];
}
}
removeLabel
(
removeLabel
)
{
removeLabel
(
removeLabel
)
{
if
(
removeLabel
)
{
if
(
removeLabel
)
{
this
.
labels
=
this
.
labels
.
filter
(
label
=>
removeLabel
.
title
!==
label
.
title
);
this
.
labels
=
this
.
labels
.
filter
(
label
=>
removeLabel
.
title
!==
label
.
title
);
}
}
}
}
removeLabels
(
labels
)
{
removeLabels
(
labels
)
{
labels
.
forEach
(
this
.
removeLabel
.
bind
(
this
));
labels
.
forEach
(
this
.
removeLabel
.
bind
(
this
));
}
}
addAssignee
(
assignee
)
{
addAssignee
(
assignee
)
{
if
(
!
this
.
findAssignee
(
assignee
))
{
if
(
!
this
.
findAssignee
(
assignee
))
{
this
.
assignees
.
push
(
new
ListAssignee
(
assignee
));
this
.
assignees
.
push
(
new
ListAssignee
(
assignee
));
}
}
}
}
findAssignee
(
findAssignee
)
{
findAssignee
(
findAssignee
)
{
return
this
.
assignees
.
filter
(
assignee
=>
assignee
.
id
===
findAssignee
.
id
)[
0
];
return
this
.
assignees
.
filter
(
assignee
=>
assignee
.
id
===
findAssignee
.
id
)[
0
];
}
}
removeAssignee
(
removeAssignee
)
{
removeAssignee
(
removeAssignee
)
{
if
(
removeAssignee
)
{
if
(
removeAssignee
)
{
this
.
assignees
=
this
.
assignees
.
filter
(
assignee
=>
assignee
.
id
!==
removeAssignee
.
id
);
this
.
assignees
=
this
.
assignees
.
filter
(
assignee
=>
assignee
.
id
!==
removeAssignee
.
id
);
}
}
}
}
removeAllAssignees
()
{
removeAllAssignees
()
{
this
.
assignees
=
[];
this
.
assignees
=
[];
}
}
addMilestone
(
milestone
)
{
addMilestone
(
milestone
)
{
const
miletoneId
=
this
.
milestone
?
this
.
milestone
.
id
:
null
;
const
miletoneId
=
this
.
milestone
?
this
.
milestone
.
id
:
null
;
if
(
milestone
.
id
!==
miletoneId
)
{
if
(
milestone
.
id
!==
miletoneId
)
{
this
.
milestone
=
new
ListMilestone
(
milestone
);
this
.
milestone
=
new
ListMilestone
(
milestone
);
}
}
}
}
removeMilestone
(
removeMilestone
)
{
removeMilestone
(
removeMilestone
)
{
if
(
removeMilestone
&&
removeMilestone
.
id
===
this
.
milestone
.
id
)
{
if
(
removeMilestone
&&
removeMilestone
.
id
===
this
.
milestone
.
id
)
{
this
.
milestone
=
{};
this
.
milestone
=
{};
}
}
}
}
getLists
()
{
getLists
()
{
return
boardsStore
.
state
.
lists
.
filter
(
list
=>
list
.
findIssue
(
this
.
id
));
return
boardsStore
.
state
.
lists
.
filter
(
list
=>
list
.
findIssue
(
this
.
id
));
}
}
...
@@ -115,14 +115,14 @@ class ListIssue {
...
@@ -115,14 +115,14 @@ class ListIssue {
this
.
isLoading
[
key
]
=
value
;
this
.
isLoading
[
key
]
=
value
;
}
}
update
()
{
update
()
{
const
data
=
{
const
data
=
{
issue
:
{
issue
:
{
milestone_id
:
this
.
milestone
?
this
.
milestone
.
id
:
null
,
milestone_id
:
this
.
milestone
?
this
.
milestone
.
id
:
null
,
due_date
:
this
.
dueDate
,
due_date
:
this
.
dueDate
,
assignee_ids
:
this
.
assignees
.
length
>
0
?
this
.
assignees
.
map
(
(
u
)
=>
u
.
id
)
:
[
0
],
assignee_ids
:
this
.
assignees
.
length
>
0
?
this
.
assignees
.
map
(
u
=>
u
.
id
)
:
[
0
],
label_ids
:
this
.
labels
.
map
(
(
label
)
=>
label
.
id
)
label_ids
:
this
.
labels
.
map
(
label
=>
label
.
id
),
}
}
,
};
};
if
(
!
data
.
issue
.
label_ids
.
length
)
{
if
(
!
data
.
issue
.
label_ids
.
length
)
{
...
...
app/assets/javascripts/boards/models/list.js
View file @
7e9f44fa
...
@@ -247,11 +247,11 @@ class List {
...
@@ -247,11 +247,11 @@ class List {
});
});
}
}
getTypeInfo
(
type
)
{
getTypeInfo
(
type
)
{
return
TYPES
[
type
]
||
{};
return
TYPES
[
type
]
||
{};
}
}
onNewIssueResponse
(
issue
,
data
)
{
onNewIssueResponse
(
issue
,
data
)
{
issue
.
id
=
data
.
id
;
issue
.
id
=
data
.
id
;
issue
.
iid
=
data
.
iid
;
issue
.
iid
=
data
.
iid
;
issue
.
project
=
data
.
project
;
issue
.
project
=
data
.
project
;
...
...
app/assets/javascripts/boards/services/board_service.js
View file @
7e9f44fa
...
@@ -19,7 +19,9 @@ export default class BoardService {
...
@@ -19,7 +19,9 @@ export default class BoardService {
}
}
static
generateIssuePath
(
boardId
,
id
)
{
static
generateIssuePath
(
boardId
,
id
)
{
return
`
${
gon
.
relative_url_root
}
/-/boards/
${
boardId
?
`
${
boardId
}
`
:
''
}
/issues
${
id
?
`/
${
id
}
`
:
''
}
`
;
return
`
${
gon
.
relative_url_root
}
/-/boards/
${
boardId
?
`
${
boardId
}
`
:
''
}
/issues
${
id
?
`/
${
id
}
`
:
''
}
`
;
}
}
all
()
{
all
()
{
...
@@ -54,7 +56,9 @@ export default class BoardService {
...
@@ -54,7 +56,9 @@ export default class BoardService {
getIssuesForList
(
id
,
filter
=
{})
{
getIssuesForList
(
id
,
filter
=
{})
{
const
data
=
{
id
};
const
data
=
{
id
};
Object
.
keys
(
filter
).
forEach
((
key
)
=>
{
data
[
key
]
=
filter
[
key
];
});
Object
.
keys
(
filter
).
forEach
(
key
=>
{
data
[
key
]
=
filter
[
key
];
});
return
axios
.
get
(
mergeUrlParams
(
data
,
this
.
generateIssuesPath
(
id
)));
return
axios
.
get
(
mergeUrlParams
(
data
,
this
.
generateIssuesPath
(
id
)));
}
}
...
@@ -75,7 +79,9 @@ export default class BoardService {
...
@@ -75,7 +79,9 @@ export default class BoardService {
}
}
getBacklog
(
data
)
{
getBacklog
(
data
)
{
return
axios
.
get
(
mergeUrlParams
(
data
,
`
${
gon
.
relative_url_root
}
/-/boards/
${
this
.
boardId
}
/issues.json`
));
return
axios
.
get
(
mergeUrlParams
(
data
,
`
${
gon
.
relative_url_root
}
/-/boards/
${
this
.
boardId
}
/issues.json`
),
);
}
}
bulkUpdate
(
issueIds
,
extraData
=
{})
{
bulkUpdate
(
issueIds
,
extraData
=
{})
{
...
...
app/assets/javascripts/boards/stores/boards_store.js
View file @
7e9f44fa
...
@@ -27,7 +27,7 @@ const boardsStore = {
...
@@ -27,7 +27,7 @@ const boardsStore = {
issue
:
{},
issue
:
{},
list
:
{},
list
:
{},
},
},
create
()
{
create
()
{
this
.
state
.
lists
=
[];
this
.
state
.
lists
=
[];
this
.
filter
.
path
=
getUrlParamsArray
().
join
(
'
&
'
);
this
.
filter
.
path
=
getUrlParamsArray
().
join
(
'
&
'
);
this
.
detail
=
{
this
.
detail
=
{
...
@@ -45,13 +45,13 @@ const boardsStore = {
...
@@ -45,13 +45,13 @@ const boardsStore = {
this
.
state
.
reload
=
false
;
this
.
state
.
reload
=
false
;
this
.
state
.
currentPage
=
page
;
this
.
state
.
currentPage
=
page
;
},
},
addList
(
listObj
,
defaultAvatar
)
{
addList
(
listObj
,
defaultAvatar
)
{
const
list
=
new
List
(
listObj
,
defaultAvatar
);
const
list
=
new
List
(
listObj
,
defaultAvatar
);
this
.
state
.
lists
.
push
(
list
);
this
.
state
.
lists
.
push
(
list
);
return
list
;
return
list
;
},
},
new
(
listObj
)
{
new
(
listObj
)
{
const
list
=
this
.
addList
(
listObj
);
const
list
=
this
.
addList
(
listObj
);
const
backlogList
=
this
.
findList
(
'
type
'
,
'
backlog
'
,
'
backlog
'
);
const
backlogList
=
this
.
findList
(
'
type
'
,
'
backlog
'
,
'
backlog
'
);
...
@@ -68,44 +68,44 @@ const boardsStore = {
...
@@ -68,44 +68,44 @@ const boardsStore = {
});
});
this
.
removeBlankState
();
this
.
removeBlankState
();
},
},
updateNewListDropdown
(
listId
)
{
updateNewListDropdown
(
listId
)
{
$
(
`.js-board-list-
${
listId
}
`
).
removeClass
(
'
is-active
'
);
$
(
`.js-board-list-
${
listId
}
`
).
removeClass
(
'
is-active
'
);
},
},
shouldAddBlankState
()
{
shouldAddBlankState
()
{
// Decide whether to add the blank state
// Decide whether to add the blank state
return
!
(
this
.
state
.
lists
.
filter
(
list
=>
list
.
type
!==
'
backlog
'
&&
list
.
type
!==
'
closed
'
)[
0
])
;
return
!
this
.
state
.
lists
.
filter
(
list
=>
list
.
type
!==
'
backlog
'
&&
list
.
type
!==
'
closed
'
)[
0
]
;
},
},
addBlankState
()
{
addBlankState
()
{
if
(
!
this
.
shouldAddBlankState
()
||
this
.
welcomeIsHidden
()
||
this
.
disabled
)
return
;
if
(
!
this
.
shouldAddBlankState
()
||
this
.
welcomeIsHidden
()
||
this
.
disabled
)
return
;
this
.
addList
({
this
.
addList
({
id
:
'
blank
'
,
id
:
'
blank
'
,
list_type
:
'
blank
'
,
list_type
:
'
blank
'
,
title
:
'
Welcome to your Issue Board!
'
,
title
:
'
Welcome to your Issue Board!
'
,
position
:
0
position
:
0
,
});
});
this
.
state
.
lists
=
_
.
sortBy
(
this
.
state
.
lists
,
'
position
'
);
this
.
state
.
lists
=
_
.
sortBy
(
this
.
state
.
lists
,
'
position
'
);
},
},
removeBlankState
()
{
removeBlankState
()
{
this
.
removeList
(
'
blank
'
);
this
.
removeList
(
'
blank
'
);
Cookies
.
set
(
'
issue_board_welcome_hidden
'
,
'
true
'
,
{
Cookies
.
set
(
'
issue_board_welcome_hidden
'
,
'
true
'
,
{
expires
:
365
*
10
,
expires
:
365
*
10
,
path
:
''
path
:
''
,
});
});
},
},
welcomeIsHidden
()
{
welcomeIsHidden
()
{
return
Cookies
.
get
(
'
issue_board_welcome_hidden
'
)
===
'
true
'
;
return
Cookies
.
get
(
'
issue_board_welcome_hidden
'
)
===
'
true
'
;
},
},
removeList
(
id
,
type
=
'
blank
'
)
{
removeList
(
id
,
type
=
'
blank
'
)
{
const
list
=
this
.
findList
(
'
id
'
,
id
,
type
);
const
list
=
this
.
findList
(
'
id
'
,
id
,
type
);
if
(
!
list
)
return
;
if
(
!
list
)
return
;
this
.
state
.
lists
=
this
.
state
.
lists
.
filter
(
list
=>
list
.
id
!==
id
);
this
.
state
.
lists
=
this
.
state
.
lists
.
filter
(
list
=>
list
.
id
!==
id
);
},
},
moveList
(
listFrom
,
orderLists
)
{
moveList
(
listFrom
,
orderLists
)
{
orderLists
.
forEach
((
id
,
i
)
=>
{
orderLists
.
forEach
((
id
,
i
)
=>
{
const
list
=
this
.
findList
(
'
id
'
,
parseInt
(
id
,
10
));
const
list
=
this
.
findList
(
'
id
'
,
parseInt
(
id
,
10
));
...
@@ -113,21 +113,24 @@ const boardsStore = {
...
@@ -113,21 +113,24 @@ const boardsStore = {
});
});
listFrom
.
update
();
listFrom
.
update
();
},
},
moveIssueToList
(
listFrom
,
listTo
,
issue
,
newIndex
)
{
moveIssueToList
(
listFrom
,
listTo
,
issue
,
newIndex
)
{
const
issueTo
=
listTo
.
findIssue
(
issue
.
id
);
const
issueTo
=
listTo
.
findIssue
(
issue
.
id
);
const
issueLists
=
issue
.
getLists
();
const
issueLists
=
issue
.
getLists
();
const
listLabels
=
issueLists
.
map
(
listIssue
=>
listIssue
.
label
);
const
listLabels
=
issueLists
.
map
(
listIssue
=>
listIssue
.
label
);
if
(
!
issueTo
)
{
if
(
!
issueTo
)
{
// Check if target list assignee is already present in this issue
// Check if target list assignee is already present in this issue
if
((
listTo
.
type
===
'
assignee
'
&&
listFrom
.
type
===
'
assignee
'
)
&&
if
(
issue
.
findAssignee
(
listTo
.
assignee
))
{
listTo
.
type
===
'
assignee
'
&&
listFrom
.
type
===
'
assignee
'
&&
issue
.
findAssignee
(
listTo
.
assignee
)
)
{
const
targetIssue
=
listTo
.
findIssue
(
issue
.
id
);
const
targetIssue
=
listTo
.
findIssue
(
issue
.
id
);
targetIssue
.
removeAssignee
(
listFrom
.
assignee
);
targetIssue
.
removeAssignee
(
listFrom
.
assignee
);
}
else
if
(
listTo
.
type
===
'
milestone
'
)
{
}
else
if
(
listTo
.
type
===
'
milestone
'
)
{
const
currentMilestone
=
issue
.
milestone
;
const
currentMilestone
=
issue
.
milestone
;
const
currentLists
=
this
.
state
.
lists
const
currentLists
=
this
.
state
.
lists
.
filter
(
list
=>
(
list
.
type
===
'
milestone
'
&&
list
.
id
!==
listTo
.
id
)
)
.
filter
(
list
=>
list
.
type
===
'
milestone
'
&&
list
.
id
!==
listTo
.
id
)
.
filter
(
list
=>
list
.
issues
.
some
(
listIssue
=>
issue
.
id
===
listIssue
.
id
));
.
filter
(
list
=>
list
.
issues
.
some
(
listIssue
=>
issue
.
id
===
listIssue
.
id
));
issue
.
removeMilestone
(
currentMilestone
);
issue
.
removeMilestone
(
currentMilestone
);
...
@@ -144,7 +147,7 @@ const boardsStore = {
...
@@ -144,7 +147,7 @@ const boardsStore = {
}
}
if
(
listTo
.
type
===
'
closed
'
&&
listFrom
.
type
!==
'
backlog
'
)
{
if
(
listTo
.
type
===
'
closed
'
&&
listFrom
.
type
!==
'
backlog
'
)
{
issueLists
.
forEach
(
(
list
)
=>
{
issueLists
.
forEach
(
list
=>
{
list
.
removeIssue
(
issue
);
list
.
removeIssue
(
issue
);
});
});
issue
.
removeLabels
(
listLabels
);
issue
.
removeLabels
(
listLabels
);
...
@@ -162,26 +165,28 @@ const boardsStore = {
...
@@ -162,26 +165,28 @@ const boardsStore = {
return
(
return
(
(
listTo
.
type
!==
'
label
'
&&
listFrom
.
type
===
'
assignee
'
)
||
(
listTo
.
type
!==
'
label
'
&&
listFrom
.
type
===
'
assignee
'
)
||
(
listTo
.
type
!==
'
assignee
'
&&
listFrom
.
type
===
'
label
'
)
||
(
listTo
.
type
!==
'
assignee
'
&&
listFrom
.
type
===
'
label
'
)
||
(
listFrom
.
type
===
'
backlog
'
)
listFrom
.
type
===
'
backlog
'
);
);
},
},
moveIssueInList
(
list
,
issue
,
oldIndex
,
newIndex
,
idArray
)
{
moveIssueInList
(
list
,
issue
,
oldIndex
,
newIndex
,
idArray
)
{
const
beforeId
=
parseInt
(
idArray
[
newIndex
-
1
],
10
)
||
null
;
const
beforeId
=
parseInt
(
idArray
[
newIndex
-
1
],
10
)
||
null
;
const
afterId
=
parseInt
(
idArray
[
newIndex
+
1
],
10
)
||
null
;
const
afterId
=
parseInt
(
idArray
[
newIndex
+
1
],
10
)
||
null
;
list
.
moveIssue
(
issue
,
oldIndex
,
newIndex
,
beforeId
,
afterId
);
list
.
moveIssue
(
issue
,
oldIndex
,
newIndex
,
beforeId
,
afterId
);
},
},
findList
(
key
,
val
,
type
=
'
label
'
)
{
findList
(
key
,
val
,
type
=
'
label
'
)
{
const
filteredList
=
this
.
state
.
lists
.
filter
((
list
)
=>
{
const
filteredList
=
this
.
state
.
lists
.
filter
(
list
=>
{
const
byType
=
type
?
(
list
.
type
===
type
)
||
(
list
.
type
===
'
assignee
'
)
||
(
list
.
type
===
'
milestone
'
)
:
true
;
const
byType
=
type
?
list
.
type
===
type
||
list
.
type
===
'
assignee
'
||
list
.
type
===
'
milestone
'
:
true
;
return
list
[
key
]
===
val
&&
byType
;
return
list
[
key
]
===
val
&&
byType
;
});
});
return
filteredList
[
0
];
return
filteredList
[
0
];
},
},
updateFiltersUrl
()
{
updateFiltersUrl
()
{
window
.
history
.
pushState
(
null
,
null
,
`?
${
this
.
filter
.
path
}
`
);
window
.
history
.
pushState
(
null
,
null
,
`?
${
this
.
filter
.
path
}
`
);
}
}
,
};
};
BoardsStoreEE
.
initEESpecific
(
boardsStore
);
BoardsStoreEE
.
initEESpecific
(
boardsStore
);
...
...
app/assets/javascripts/boards/stores/modal_store.js
View file @
7e9f44fa
...
@@ -40,7 +40,7 @@ class ModalStore {
...
@@ -40,7 +40,7 @@ class ModalStore {
toggleAll
()
{
toggleAll
()
{
const
select
=
this
.
selectedCount
()
!==
this
.
store
.
issues
.
length
;
const
select
=
this
.
selectedCount
()
!==
this
.
store
.
issues
.
length
;
this
.
store
.
issues
.
forEach
(
(
issue
)
=>
{
this
.
store
.
issues
.
forEach
(
issue
=>
{
const
issueUpdate
=
issue
;
const
issueUpdate
=
issue
;
if
(
issueUpdate
.
selected
!==
select
)
{
if
(
issueUpdate
.
selected
!==
select
)
{
...
@@ -69,13 +69,14 @@ class ModalStore {
...
@@ -69,13 +69,14 @@ class ModalStore {
removeSelectedIssue
(
issue
,
forcePurge
=
false
)
{
removeSelectedIssue
(
issue
,
forcePurge
=
false
)
{
if
(
this
.
store
.
activeTab
===
'
all
'
||
forcePurge
)
{
if
(
this
.
store
.
activeTab
===
'
all
'
||
forcePurge
)
{
this
.
store
.
selectedIssues
=
this
.
store
.
selectedIssues
this
.
store
.
selectedIssues
=
this
.
store
.
selectedIssues
.
filter
(
.
filter
(
fIssue
=>
fIssue
.
id
!==
issue
.
id
);
fIssue
=>
fIssue
.
id
!==
issue
.
id
,
);
}
}
}
}
purgeUnselectedIssues
()
{
purgeUnselectedIssues
()
{
this
.
store
.
selectedIssues
.
forEach
(
(
issue
)
=>
{
this
.
store
.
selectedIssues
.
forEach
(
issue
=>
{
if
(
!
issue
.
selected
)
{
if
(
!
issue
.
selected
)
{
this
.
removeSelectedIssue
(
issue
,
true
);
this
.
removeSelectedIssue
(
issue
,
true
);
}
}
...
@@ -87,8 +88,7 @@ class ModalStore {
...
@@ -87,8 +88,7 @@ class ModalStore {
}
}
findSelectedIssue
(
issue
)
{
findSelectedIssue
(
issue
)
{
return
this
.
store
.
selectedIssues
return
this
.
store
.
selectedIssues
.
filter
(
filteredIssue
=>
filteredIssue
.
id
===
issue
.
id
)[
0
];
.
filter
(
filteredIssue
=>
filteredIssue
.
id
===
issue
.
id
)[
0
];
}
}
}
}
...
...
app/assets/javascripts/commons/gitlab_ui.js
View file @
7e9f44fa
import
Vue
from
'
vue
'
;
import
Vue
from
'
vue
'
;
import
{
import
{
GlProgressBar
,
GlLoadingIcon
,
GlTooltipDirective
}
from
'
@gitlab-org/gitlab-ui
'
;
GlProgressBar
,
GlLoadingIcon
,
GlTooltipDirective
,
}
from
'
@gitlab-org/gitlab-ui
'
;
Vue
.
component
(
'
gl-progress-bar
'
,
GlProgressBar
);
Vue
.
component
(
'
gl-progress-bar
'
,
GlProgressBar
);
Vue
.
component
(
'
gl-loading-icon
'
,
GlLoadingIcon
);
Vue
.
component
(
'
gl-loading-icon
'
,
GlLoadingIcon
);
...
...
app/assets/javascripts/diffs/components/tree_list.vue
View file @
7e9f44fa
...
@@ -18,8 +18,8 @@ export default {
...
@@ -18,8 +18,8 @@ export default {
},
},
data
()
{
data
()
{
const
treeListStored
=
localStorage
.
getItem
(
treeListStorageKey
);
const
treeListStored
=
localStorage
.
getItem
(
treeListStorageKey
);
const
renderTreeList
=
treeListStored
!==
null
?
const
renderTreeList
=
convertPermissionToBoolean
(
treeListStored
)
:
true
;
treeListStored
!==
null
?
convertPermissionToBoolean
(
treeListStored
)
:
true
;
return
{
return
{
search
:
''
,
search
:
''
,
...
...
app/assets/javascripts/environments/components/environments_app.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
Flash
from
'
../../flash
'
;
import
Flash
from
'
../../flash
'
;
import
{
s__
}
from
'
../../locale
'
;
import
{
s__
}
from
'
../../locale
'
;
import
emptyState
from
'
./empty_state.vue
'
;
import
emptyState
from
'
./empty_state.vue
'
;
import
eventHub
from
'
../event_hub
'
;
import
eventHub
from
'
../event_hub
'
;
import
environmentsMixin
from
'
../mixins/environments_mixin
'
;
import
environmentsMixin
from
'
../mixins/environments_mixin
'
;
import
CIPaginationMixin
from
'
../../vue_shared/mixins/ci_pagination_api_mixin
'
;
import
CIPaginationMixin
from
'
../../vue_shared/mixins/ci_pagination_api_mixin
'
;
import
StopEnvironmentModal
from
'
./stop_environment_modal.vue
'
;
import
StopEnvironmentModal
from
'
./stop_environment_modal.vue
'
;
export
default
{
export
default
{
components
:
{
components
:
{
emptyState
,
emptyState
,
StopEnvironmentModal
,
StopEnvironmentModal
,
},
},
mixins
:
[
mixins
:
[
CIPaginationMixin
,
environmentsMixin
],
CIPaginationMixin
,
environmentsMixin
,
],
props
:
{
props
:
{
endpoint
:
{
endpoint
:
{
...
@@ -79,7 +76,8 @@
...
@@ -79,7 +76,8 @@
fetchChildEnvironments
(
folder
,
showLoader
=
false
)
{
fetchChildEnvironments
(
folder
,
showLoader
=
false
)
{
this
.
store
.
updateEnvironmentProp
(
folder
,
'
isLoadingFolderContent
'
,
showLoader
);
this
.
store
.
updateEnvironmentProp
(
folder
,
'
isLoadingFolderContent
'
,
showLoader
);
this
.
service
.
getFolderContent
(
folder
.
folder_path
)
this
.
service
.
getFolderContent
(
folder
.
folder_path
)
.
then
(
response
=>
this
.
store
.
setfolderContent
(
folder
,
response
.
data
.
environments
))
.
then
(
response
=>
this
.
store
.
setfolderContent
(
folder
,
response
.
data
.
environments
))
.
then
(()
=>
this
.
store
.
updateEnvironmentProp
(
folder
,
'
isLoadingFolderContent
'
,
false
))
.
then
(()
=>
this
.
store
.
updateEnvironmentProp
(
folder
,
'
isLoadingFolderContent
'
,
false
))
.
catch
(()
=>
{
.
catch
(()
=>
{
...
@@ -98,7 +96,7 @@
...
@@ -98,7 +96,7 @@
}
}
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<div
:class=
"cssContainerClass"
>
<div
:class=
"cssContainerClass"
>
...
...
app/assets/javascripts/environments/stores/environments_store.js
View file @
7e9f44fa
...
@@ -42,9 +42,9 @@ export default class EnvironmentsStore {
...
@@ -42,9 +42,9 @@ export default class EnvironmentsStore {
* @returns {Array}
* @returns {Array}
*/
*/
storeEnvironments
(
environments
=
[])
{
storeEnvironments
(
environments
=
[])
{
const
filteredEnvironments
=
environments
.
map
(
(
env
)
=>
{
const
filteredEnvironments
=
environments
.
map
(
env
=>
{
const
oldEnvironmentState
=
this
.
state
.
environments
const
oldEnvironmentState
=
.
find
((
element
)
=>
{
this
.
state
.
environments
.
find
(
element
=>
{
if
(
env
.
latest
)
{
if
(
env
.
latest
)
{
return
element
.
id
===
env
.
latest
.
id
;
return
element
.
id
===
env
.
latest
.
id
;
}
}
...
@@ -73,10 +73,12 @@ export default class EnvironmentsStore {
...
@@ -73,10 +73,12 @@ export default class EnvironmentsStore {
if
(
filtered
.
size
===
1
&&
filtered
.
rollout_status
)
{
if
(
filtered
.
size
===
1
&&
filtered
.
rollout_status
)
{
filtered
=
Object
.
assign
({},
filtered
,
{
filtered
=
Object
.
assign
({},
filtered
,
{
hasDeployBoard
:
true
,
hasDeployBoard
:
true
,
isDeployBoardVisible
:
oldEnvironmentState
.
isDeployBoardVisible
===
false
?
isDeployBoardVisible
:
oldEnvironmentState
.
isDeployBoardVisible
:
oldEnvironmentState
.
isDeployBoardVisible
===
false
true
,
?
oldEnvironmentState
.
isDeployBoardVisible
deployBoardData
:
filtered
.
rollout_status
.
status
===
'
found
'
?
filtered
.
rollout_status
:
{},
:
true
,
deployBoardData
:
filtered
.
rollout_status
.
status
===
'
found
'
?
filtered
.
rollout_status
:
{},
isLoadingDeployBoard
:
filtered
.
rollout_status
.
status
===
'
loading
'
,
isLoadingDeployBoard
:
filtered
.
rollout_status
.
status
===
'
loading
'
,
isEmptyDeployBoard
:
filtered
.
rollout_status
.
status
===
'
not_found
'
,
isEmptyDeployBoard
:
filtered
.
rollout_status
.
status
===
'
not_found
'
,
});
});
...
@@ -152,7 +154,7 @@ export default class EnvironmentsStore {
...
@@ -152,7 +154,7 @@ export default class EnvironmentsStore {
* @return {Object}
* @return {Object}
*/
*/
setfolderContent
(
folder
,
environments
)
{
setfolderContent
(
folder
,
environments
)
{
const
updatedEnvironments
=
environments
.
map
(
(
env
)
=>
{
const
updatedEnvironments
=
environments
.
map
(
env
=>
{
let
updated
=
env
;
let
updated
=
env
;
if
(
env
.
latest
)
{
if
(
env
.
latest
)
{
...
@@ -181,7 +183,7 @@ export default class EnvironmentsStore {
...
@@ -181,7 +183,7 @@ export default class EnvironmentsStore {
updateEnvironmentProp
(
environment
,
prop
,
newValue
)
{
updateEnvironmentProp
(
environment
,
prop
,
newValue
)
{
const
{
environments
}
=
this
.
state
;
const
{
environments
}
=
this
.
state
;
const
updatedEnvironments
=
environments
.
map
(
(
env
)
=>
{
const
updatedEnvironments
=
environments
.
map
(
env
=>
{
const
updateEnv
=
Object
.
assign
({},
env
);
const
updateEnv
=
Object
.
assign
({},
env
);
if
(
env
.
id
===
environment
.
id
)
{
if
(
env
.
id
===
environment
.
id
)
{
updateEnv
[
prop
]
=
newValue
;
updateEnv
[
prop
]
=
newValue
;
...
@@ -208,7 +210,7 @@ export default class EnvironmentsStore {
...
@@ -208,7 +210,7 @@ export default class EnvironmentsStore {
toggleDeployBoard
(
environmentID
)
{
toggleDeployBoard
(
environmentID
)
{
const
environments
=
this
.
state
.
environments
.
slice
();
const
environments
=
this
.
state
.
environments
.
slice
();
this
.
state
.
environments
=
environments
.
map
(
(
env
)
=>
{
this
.
state
.
environments
=
environments
.
map
(
env
=>
{
let
updated
=
Object
.
assign
({},
env
);
let
updated
=
Object
.
assign
({},
env
);
if
(
env
.
id
===
environmentID
)
{
if
(
env
.
id
===
environmentID
)
{
...
...
app/assets/javascripts/filtered_search/dropdown_user.js
View file @
7e9f44fa
...
@@ -40,8 +40,9 @@ export default class DropdownUser extends FilteredSearchDropdown {
...
@@ -40,8 +40,9 @@ export default class DropdownUser extends FilteredSearchDropdown {
}
}
itemClicked
(
e
)
{
itemClicked
(
e
)
{
super
.
itemClicked
(
e
,
super
.
itemClicked
(
e
,
selected
=>
selected
=>
selected
.
querySelector
(
'
.dropdown-light-content
'
).
innerText
.
trim
());
selected
.
querySelector
(
'
.dropdown-light-content
'
).
innerText
.
trim
(),
);
}
}
renderContent
(
forceShowList
=
false
)
{
renderContent
(
forceShowList
=
false
)
{
...
@@ -82,7 +83,7 @@ export default class DropdownUser extends FilteredSearchDropdown {
...
@@ -82,7 +83,7 @@ export default class DropdownUser extends FilteredSearchDropdown {
// Removes the first character if it is a quotation so that we can search
// Removes the first character if it is a quotation so that we can search
// with multiple words
// with multiple words
if
(
value
[
0
]
===
'
"
'
||
value
[
0
]
===
'
\'
'
)
{
if
(
value
[
0
]
===
'
"
'
||
value
[
0
]
===
"
'
"
)
{
value
=
value
.
slice
(
1
);
value
=
value
.
slice
(
1
);
}
}
...
...
app/assets/javascripts/filtered_search/filtered_search_dropdown_manager.js
View file @
7e9f44fa
...
@@ -156,10 +156,7 @@ export default class FilteredSearchDropdownManager {
...
@@ -156,10 +156,7 @@ export default class FilteredSearchDropdownManager {
}
}
static
addWordToInput
(
tokenName
,
tokenValue
=
''
,
clicked
=
false
,
options
=
{})
{
static
addWordToInput
(
tokenName
,
tokenValue
=
''
,
clicked
=
false
,
options
=
{})
{
const
{
const
{
uppercaseTokenName
=
false
,
capitalizeTokenValue
=
false
}
=
options
;
uppercaseTokenName
=
false
,
capitalizeTokenValue
=
false
,
}
=
options
;
const
input
=
FilteredSearchContainer
.
container
.
querySelector
(
'
.filtered-search
'
);
const
input
=
FilteredSearchContainer
.
container
.
querySelector
(
'
.filtered-search
'
);
FilteredSearchVisualTokens
.
addFilterVisualToken
(
tokenName
,
tokenValue
,
{
FilteredSearchVisualTokens
.
addFilterVisualToken
(
tokenName
,
tokenValue
,
{
uppercaseTokenName
,
uppercaseTokenName
,
...
...
app/assets/javascripts/filtered_search/filtered_search_manager.js
View file @
7e9f44fa
This diff is collapsed.
Click to expand it.
app/assets/javascripts/flash.js
View file @
7e9f44fa
...
@@ -40,7 +40,9 @@ const createFlashEl = (message, type, isFixedLayout = false) => `
...
@@ -40,7 +40,9 @@ const createFlashEl = (message, type, isFixedLayout = false) => `
class="flash-
${
type
}
"
class="flash-
${
type
}
"
>
>
<div
<div
class="flash-text
${
isFixedLayout
?
'
container-fluid container-limited limit-container-width
'
:
''
}
"
class="flash-text
${
isFixedLayout
?
'
container-fluid container-limited limit-container-width
'
:
''
}
"
>
>
${
_
.
escape
(
message
)}
${
_
.
escape
(
message
)}
</div>
</div>
...
@@ -78,7 +80,9 @@ const createFlash = function createFlash(
...
@@ -78,7 +80,9 @@ const createFlash = function createFlash(
if
(
!
flashContainer
)
return
null
;
if
(
!
flashContainer
)
return
null
;
const
isFixedLayout
=
navigation
?
navigation
.
parentNode
.
classList
.
contains
(
'
container-limited
'
)
:
true
;
const
isFixedLayout
=
navigation
?
navigation
.
parentNode
.
classList
.
contains
(
'
container-limited
'
)
:
true
;
flashContainer
.
innerHTML
=
createFlashEl
(
message
,
type
,
isFixedLayout
);
flashContainer
.
innerHTML
=
createFlashEl
(
message
,
type
,
isFixedLayout
);
...
...
app/assets/javascripts/gfm_auto_complete.js
View file @
7e9f44fa
...
@@ -101,7 +101,7 @@ class GfmAutoComplete {
...
@@ -101,7 +101,7 @@ class GfmAutoComplete {
...
this
.
getDefaultCallbacks
(),
...
this
.
getDefaultCallbacks
(),
beforeSave
(
commands
)
{
beforeSave
(
commands
)
{
if
(
GfmAutoComplete
.
isLoading
(
commands
))
return
commands
;
if
(
GfmAutoComplete
.
isLoading
(
commands
))
return
commands
;
return
$
.
map
(
commands
,
(
c
)
=>
{
return
$
.
map
(
commands
,
c
=>
{
let
search
=
c
.
name
;
let
search
=
c
.
name
;
if
(
c
.
aliases
.
length
>
0
)
{
if
(
c
.
aliases
.
length
>
0
)
{
search
=
`
${
search
}
${
c
.
aliases
.
join
(
'
'
)}
`
;
search
=
`
${
search
}
${
c
.
aliases
.
join
(
'
'
)}
`
;
...
@@ -174,7 +174,7 @@ class GfmAutoComplete {
...
@@ -174,7 +174,7 @@ class GfmAutoComplete {
callbacks
:
{
callbacks
:
{
...
this
.
getDefaultCallbacks
(),
...
this
.
getDefaultCallbacks
(),
beforeSave
(
members
)
{
beforeSave
(
members
)
{
return
$
.
map
(
members
,
(
m
)
=>
{
return
$
.
map
(
members
,
m
=>
{
let
title
=
''
;
let
title
=
''
;
if
(
m
.
username
==
null
)
{
if
(
m
.
username
==
null
)
{
return
m
;
return
m
;
...
@@ -185,7 +185,9 @@ class GfmAutoComplete {
...
@@ -185,7 +185,9 @@ class GfmAutoComplete {
}
}
const
autoCompleteAvatar
=
m
.
avatar_url
||
m
.
username
.
charAt
(
0
).
toUpperCase
();
const
autoCompleteAvatar
=
m
.
avatar_url
||
m
.
username
.
charAt
(
0
).
toUpperCase
();
const
imgAvatar
=
`<img src="
${
m
.
avatar_url
}
" alt="
${
m
.
username
}
" class="avatar avatar-inline center s26"/>`
;
const
imgAvatar
=
`<img src="
${
m
.
avatar_url
}
" alt="
${
m
.
username
}
" class="avatar avatar-inline center s26"/>`
;
const
txtAvatar
=
`<div class="avatar center avatar-inline s26">
${
autoCompleteAvatar
}
</div>`
;
const
txtAvatar
=
`<div class="avatar center avatar-inline s26">
${
autoCompleteAvatar
}
</div>`
;
return
{
return
{
...
@@ -218,7 +220,7 @@ class GfmAutoComplete {
...
@@ -218,7 +220,7 @@ class GfmAutoComplete {
callbacks
:
{
callbacks
:
{
...
this
.
getDefaultCallbacks
(),
...
this
.
getDefaultCallbacks
(),
beforeSave
(
issues
)
{
beforeSave
(
issues
)
{
return
$
.
map
(
issues
,
(
i
)
=>
{
return
$
.
map
(
issues
,
i
=>
{
if
(
i
.
title
==
null
)
{
if
(
i
.
title
==
null
)
{
return
i
;
return
i
;
}
}
...
@@ -251,7 +253,7 @@ class GfmAutoComplete {
...
@@ -251,7 +253,7 @@ class GfmAutoComplete {
callbacks
:
{
callbacks
:
{
...
this
.
getDefaultCallbacks
(),
...
this
.
getDefaultCallbacks
(),
beforeSave
(
milestones
)
{
beforeSave
(
milestones
)
{
return
$
.
map
(
milestones
,
(
m
)
=>
{
return
$
.
map
(
milestones
,
m
=>
{
if
(
m
.
title
==
null
)
{
if
(
m
.
title
==
null
)
{
return
m
;
return
m
;
}
}
...
@@ -284,7 +286,7 @@ class GfmAutoComplete {
...
@@ -284,7 +286,7 @@ class GfmAutoComplete {
callbacks
:
{
callbacks
:
{
...
this
.
getDefaultCallbacks
(),
...
this
.
getDefaultCallbacks
(),
beforeSave
(
merges
)
{
beforeSave
(
merges
)
{
return
$
.
map
(
merges
,
(
m
)
=>
{
return
$
.
map
(
merges
,
m
=>
{
if
(
m
.
title
==
null
)
{
if
(
m
.
title
==
null
)
{
return
m
;
return
m
;
}
}
...
@@ -331,13 +333,20 @@ class GfmAutoComplete {
...
@@ -331,13 +333,20 @@ class GfmAutoComplete {
},
},
matcher
(
flag
,
subtext
)
{
matcher
(
flag
,
subtext
)
{
const
match
=
GfmAutoComplete
.
defaultMatcher
(
flag
,
subtext
,
this
.
app
.
controllers
);
const
match
=
GfmAutoComplete
.
defaultMatcher
(
flag
,
subtext
,
this
.
app
.
controllers
);
const
subtextNodes
=
subtext
.
split
(
/
\n
+/g
).
pop
().
split
(
GfmAutoComplete
.
regexSubtext
);
const
subtextNodes
=
subtext
.
split
(
/
\n
+/g
)
.
pop
()
.
split
(
GfmAutoComplete
.
regexSubtext
);
// Check if ~ is followed by '/label', '/relabel' or '/unlabel' commands.
// Check if ~ is followed by '/label', '/relabel' or '/unlabel' commands.
command
=
subtextNodes
.
find
((
node
)
=>
{
command
=
subtextNodes
.
find
(
node
=>
{
if
(
node
===
LABEL_COMMAND
.
LABEL
||
if
(
node
===
LABEL_COMMAND
.
LABEL
||
node
===
LABEL_COMMAND
.
RELABEL
||
node
===
LABEL_COMMAND
.
RELABEL
||
node
===
LABEL_COMMAND
.
UNLABEL
)
{
return
node
;
}
node
===
LABEL_COMMAND
.
UNLABEL
)
{
return
node
;
}
return
null
;
return
null
;
});
});
...
@@ -387,7 +396,7 @@ class GfmAutoComplete {
...
@@ -387,7 +396,7 @@ class GfmAutoComplete {
callbacks
:
{
callbacks
:
{
...
this
.
getDefaultCallbacks
(),
...
this
.
getDefaultCallbacks
(),
beforeSave
(
snippets
)
{
beforeSave
(
snippets
)
{
return
$
.
map
(
snippets
,
(
m
)
=>
{
return
$
.
map
(
snippets
,
m
=>
{
if
(
m
.
title
==
null
)
{
if
(
m
.
title
==
null
)
{
return
m
;
return
m
;
}
}
...
@@ -465,13 +474,17 @@ class GfmAutoComplete {
...
@@ -465,13 +474,17 @@ class GfmAutoComplete {
this
.
loadData
(
$input
,
at
,
validEmojiNames
);
this
.
loadData
(
$input
,
at
,
validEmojiNames
);
GfmAutoComplete
.
glEmojiTag
=
glEmojiTag
;
GfmAutoComplete
.
glEmojiTag
=
glEmojiTag
;
})
})
.
catch
(()
=>
{
this
.
isLoadingData
[
at
]
=
false
;
});
.
catch
(()
=>
{
this
.
isLoadingData
[
at
]
=
false
;
});
}
else
if
(
dataSource
)
{
}
else
if
(
dataSource
)
{
AjaxCache
.
retrieve
(
dataSource
,
true
)
AjaxCache
.
retrieve
(
dataSource
,
true
)
.
then
(
(
data
)
=>
{
.
then
(
data
=>
{
this
.
loadData
(
$input
,
at
,
data
);
this
.
loadData
(
$input
,
at
,
data
);
})
})
.
catch
(()
=>
{
this
.
isLoadingData
[
at
]
=
false
;
});
.
catch
(()
=>
{
this
.
isLoadingData
[
at
]
=
false
;
});
}
else
{
}
else
{
this
.
isLoadingData
[
at
]
=
false
;
this
.
isLoadingData
[
at
]
=
false
;
}
}
...
@@ -504,15 +517,16 @@ class GfmAutoComplete {
...
@@ -504,15 +517,16 @@ class GfmAutoComplete {
}
}
const
loadingState
=
GfmAutoComplete
.
defaultLoadingData
[
0
];
const
loadingState
=
GfmAutoComplete
.
defaultLoadingData
[
0
];
return
dataToInspect
&&
return
dataToInspect
&&
(
dataToInspect
===
loadingState
||
dataToInspect
.
name
===
loadingState
);
(
dataToInspect
===
loadingState
||
dataToInspect
.
name
===
loadingState
);
}
}
static
defaultMatcher
(
flag
,
subtext
,
controllers
)
{
static
defaultMatcher
(
flag
,
subtext
,
controllers
)
{
// The below is taken from At.js source
// The below is taken from At.js source
// Tweaked to commands to start without a space only if char before is a non-word character
// Tweaked to commands to start without a space only if char before is a non-word character
// https://github.com/ichord/At.js
// https://github.com/ichord/At.js
const
atSymbolsWithBar
=
Object
.
keys
(
controllers
).
join
(
'
|
'
).
replace
(
/
[
$
]
/
,
'
\\
$&
'
);
const
atSymbolsWithBar
=
Object
.
keys
(
controllers
)
.
join
(
'
|
'
)
.
replace
(
/
[
$
]
/
,
'
\\
$&
'
);
const
atSymbolsWithoutBar
=
Object
.
keys
(
controllers
).
join
(
''
);
const
atSymbolsWithoutBar
=
Object
.
keys
(
controllers
).
join
(
''
);
const
targetSubtext
=
subtext
.
split
(
GfmAutoComplete
.
regexSubtext
).
pop
();
const
targetSubtext
=
subtext
.
split
(
GfmAutoComplete
.
regexSubtext
).
pop
();
const
resultantFlag
=
flag
.
replace
(
/
[
-[
\]/
{}()*+?.
\\
^$|
]
/g
,
'
\\
$&
'
);
const
resultantFlag
=
flag
.
replace
(
/
[
-[
\]/
{}()*+?.
\\
^$|
]
/g
,
'
\\
$&
'
);
...
@@ -520,7 +534,10 @@ class GfmAutoComplete {
...
@@ -520,7 +534,10 @@ class GfmAutoComplete {
const
accentAChar
=
decodeURI
(
'
%C3%80
'
);
const
accentAChar
=
decodeURI
(
'
%C3%80
'
);
const
accentYChar
=
decodeURI
(
'
%C3%BF
'
);
const
accentYChar
=
decodeURI
(
'
%C3%BF
'
);
const
regexp
=
new
RegExp
(
`^(?:\\B|[^a-zA-Z0-9_\`
${
atSymbolsWithoutBar
}
]|\\s)
${
resultantFlag
}
(?!
${
atSymbolsWithBar
}
)((?:[A-Za-z
${
accentAChar
}
-
${
accentYChar
}
0-9_'.+-]|[^\\x00-\\x7a])*)$`
,
'
gi
'
);
const
regexp
=
new
RegExp
(
`^(?:\\B|[^a-zA-Z0-9_\`
${
atSymbolsWithoutBar
}
]|\\s)
${
resultantFlag
}
(?!
${
atSymbolsWithBar
}
)((?:[A-Za-z
${
accentAChar
}
-
${
accentYChar
}
0-9_'.+-]|[^\\x00-\\x7a])*)$`
,
'
gi
'
,
);
return
regexp
.
exec
(
targetSubtext
);
return
regexp
.
exec
(
targetSubtext
);
}
}
...
@@ -560,7 +577,8 @@ GfmAutoComplete.Members = {
...
@@ -560,7 +577,8 @@ GfmAutoComplete.Members = {
};
};
GfmAutoComplete
.
Labels
=
{
GfmAutoComplete
.
Labels
=
{
// eslint-disable-next-line no-template-curly-in-string
// eslint-disable-next-line no-template-curly-in-string
template
:
'
<li><span class="dropdown-label-box" style="background: ${color}"></span> ${title}</li>
'
,
template
:
'
<li><span class="dropdown-label-box" style="background: ${color}"></span> ${title}</li>
'
,
};
};
// Issues, MergeRequests and Snippets
// Issues, MergeRequests and Snippets
GfmAutoComplete
.
Issues
=
{
GfmAutoComplete
.
Issues
=
{
...
@@ -574,7 +592,8 @@ GfmAutoComplete.Milestones = {
...
@@ -574,7 +592,8 @@ GfmAutoComplete.Milestones = {
template
:
'
<li>${title}</li>
'
,
template
:
'
<li>${title}</li>
'
,
};
};
GfmAutoComplete
.
Loading
=
{
GfmAutoComplete
.
Loading
=
{
template
:
'
<li style="pointer-events: none;"><i class="fa fa-spinner fa-spin"></i> Loading...</li>
'
,
template
:
'
<li style="pointer-events: none;"><i class="fa fa-spinner fa-spin"></i> Loading...</li>
'
,
};
};
export
default
GfmAutoComplete
;
export
default
GfmAutoComplete
;
app/assets/javascripts/jobs/components/job_app.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
_
from
'
underscore
'
;
import
_
from
'
underscore
'
;
import
{
mapGetters
,
mapState
,
mapActions
}
from
'
vuex
'
;
import
{
mapGetters
,
mapState
,
mapActions
}
from
'
vuex
'
;
import
{
isScrolledToBottom
}
from
'
~/lib/utils/scroll_utils
'
;
import
{
isScrolledToBottom
}
from
'
~/lib/utils/scroll_utils
'
;
import
bp
from
'
~/breakpoints
'
;
import
bp
from
'
~/breakpoints
'
;
import
CiHeader
from
'
~/vue_shared/components/header_ci_component.vue
'
;
import
CiHeader
from
'
~/vue_shared/components/header_ci_component.vue
'
;
import
Callout
from
'
~/vue_shared/components/callout.vue
'
;
import
Callout
from
'
~/vue_shared/components/callout.vue
'
;
// ee-only start
// ee-only start
import
SharedRunner
from
'
ee/jobs/components/shared_runner_limit_block.vue
'
;
import
SharedRunner
from
'
ee/jobs/components/shared_runner_limit_block.vue
'
;
// ee-only end
// ee-only end
import
createStore
from
'
../store
'
;
import
createStore
from
'
../store
'
;
import
EmptyState
from
'
./empty_state.vue
'
;
import
EmptyState
from
'
./empty_state.vue
'
;
import
EnvironmentsBlock
from
'
./environments_block.vue
'
;
import
EnvironmentsBlock
from
'
./environments_block.vue
'
;
import
ErasedBlock
from
'
./erased_block.vue
'
;
import
ErasedBlock
from
'
./erased_block.vue
'
;
import
Log
from
'
./job_log.vue
'
;
import
Log
from
'
./job_log.vue
'
;
import
LogTopBar
from
'
./job_log_controllers.vue
'
;
import
LogTopBar
from
'
./job_log_controllers.vue
'
;
import
StuckBlock
from
'
./stuck_block.vue
'
;
import
StuckBlock
from
'
./stuck_block.vue
'
;
import
Sidebar
from
'
./sidebar.vue
'
;
import
Sidebar
from
'
./sidebar.vue
'
;
export
default
{
export
default
{
name
:
'
JobPageApp
'
,
name
:
'
JobPageApp
'
,
store
:
createStore
(),
store
:
createStore
(),
components
:
{
components
:
{
...
@@ -91,7 +91,7 @@
...
@@ -91,7 +91,7 @@
shouldRenderContent
()
{
shouldRenderContent
()
{
return
!
this
.
isLoading
&&
!
this
.
hasError
;
return
!
this
.
isLoading
&&
!
this
.
hasError
;
}
},
},
},
watch
:
{
watch
:
{
// Once the job log is loaded,
// Once the job log is loaded,
...
@@ -163,7 +163,7 @@
...
@@ -163,7 +163,7 @@
this
.
throttled
();
this
.
throttled
();
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<div>
<div>
...
...
app/assets/javascripts/jobs/components/job_log.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
{
mapState
,
mapActions
}
from
'
vuex
'
;
import
{
mapState
,
mapActions
}
from
'
vuex
'
;
export
default
{
export
default
{
name
:
'
JobLog
'
,
name
:
'
JobLog
'
,
props
:
{
props
:
{
trace
:
{
trace
:
{
...
@@ -39,7 +39,7 @@
...
@@ -39,7 +39,7 @@
}
}
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
<pre
class=
"js-build-trace build-trace qa-build-trace"
>
<pre
class=
"js-build-trace build-trace qa-build-trace"
>
...
...
app/assets/javascripts/jobs/index.js
View file @
7e9f44fa
...
@@ -23,4 +23,3 @@ export default () => {
...
@@ -23,4 +23,3 @@ export default () => {
},
},
});
});
};
};
app/assets/javascripts/jobs/store/getters.js
View file @
7e9f44fa
...
@@ -35,12 +35,14 @@ export const hasEnvironment = state => !_.isEmpty(state.job.deployment_status);
...
@@ -35,12 +35,14 @@ export const hasEnvironment = state => !_.isEmpty(state.job.deployment_status);
* Used to check if it should render the job log or the empty state
* Used to check if it should render the job log or the empty state
* @returns {Boolean}
* @returns {Boolean}
*/
*/
export
const
hasTrace
=
state
=>
state
.
job
.
has_trace
||
(
!
_
.
isEmpty
(
state
.
job
.
status
)
&&
state
.
job
.
status
.
group
===
'
running
'
);
export
const
hasTrace
=
state
=>
state
.
job
.
has_trace
||
(
!
_
.
isEmpty
(
state
.
job
.
status
)
&&
state
.
job
.
status
.
group
===
'
running
'
);
export
const
emptyStateIllustration
=
state
=>
export
const
emptyStateIllustration
=
state
=>
(
state
.
job
&&
state
.
job
.
status
&&
state
.
job
.
status
.
illustration
)
||
{};
(
state
.
job
&&
state
.
job
.
status
&&
state
.
job
.
status
.
illustration
)
||
{};
export
const
emptyStateAction
=
state
=>
(
state
.
job
&&
state
.
job
.
status
&&
state
.
job
.
status
.
action
)
||
{};
export
const
emptyStateAction
=
state
=>
(
state
.
job
&&
state
.
job
.
status
&&
state
.
job
.
status
.
action
)
||
{};
// ee-only start
// ee-only start
/**
/**
...
@@ -57,7 +59,8 @@ export const shouldRenderSharedRunnerLimitWarning = state =>
...
@@ -57,7 +59,8 @@ export const shouldRenderSharedRunnerLimitWarning = state =>
export
const
isScrollingDown
=
state
=>
isScrolledToBottom
()
&&
!
state
.
isTraceComplete
;
export
const
isScrollingDown
=
state
=>
isScrolledToBottom
()
&&
!
state
.
isTraceComplete
;
export
const
hasRunnersForProject
=
state
=>
state
.
job
.
runners
.
available
&&
!
state
.
job
.
runners
.
online
;
export
const
hasRunnersForProject
=
state
=>
state
.
job
.
runners
.
available
&&
!
state
.
job
.
runners
.
online
;
// prevent babel-plugin-rewire from generating an invalid default during karma tests
// prevent babel-plugin-rewire from generating an invalid default during karma tests
export
default
()
=>
{};
export
default
()
=>
{};
app/assets/javascripts/labels_select.js
View file @
7e9f44fa
This diff is collapsed.
Click to expand it.
app/assets/javascripts/lib/utils/ace_utils.js
View file @
7e9f44fa
/* global ace */
/* global ace */
export
default
function
getModeByFileExtension
(
path
)
{
export
default
function
getModeByFileExtension
(
path
)
{
const
modelist
=
ace
.
require
(
"
ace/ext/modelist
"
);
const
modelist
=
ace
.
require
(
'
ace/ext/modelist
'
);
return
modelist
.
getModeForPath
(
path
).
mode
;
return
modelist
.
getModeForPath
(
path
).
mode
;
}
;
}
app/assets/javascripts/members.js
View file @
7e9f44fa
...
@@ -10,11 +10,21 @@ export default class Members {
...
@@ -10,11 +10,21 @@ export default class Members {
}
}
addListeners
()
{
addListeners
()
{
$
(
'
.js-ldap-permissions
'
).
off
(
'
click
'
).
on
(
'
click
'
,
this
.
showLDAPPermissionsWarning
.
bind
(
this
));
$
(
'
.js-ldap-permissions
'
)
$
(
'
.js-ldap-override
'
).
off
(
'
click
'
).
on
(
'
click
'
,
this
.
toggleMemberAccessToggle
.
bind
(
this
));
.
off
(
'
click
'
)
$
(
'
.project_member, .group_member
'
).
off
(
'
ajax:success
'
).
on
(
'
ajax:success
'
,
this
.
removeRow
);
.
on
(
'
click
'
,
this
.
showLDAPPermissionsWarning
.
bind
(
this
));
$
(
'
.js-member-update-control
'
).
off
(
'
change
'
).
on
(
'
change
'
,
this
.
formSubmit
.
bind
(
this
));
$
(
'
.js-ldap-override
'
)
$
(
'
.js-edit-member-form
'
).
off
(
'
ajax:success
'
).
on
(
'
ajax:success
'
,
this
.
formSuccess
.
bind
(
this
));
.
off
(
'
click
'
)
.
on
(
'
click
'
,
this
.
toggleMemberAccessToggle
.
bind
(
this
));
$
(
'
.project_member, .group_member
'
)
.
off
(
'
ajax:success
'
)
.
on
(
'
ajax:success
'
,
this
.
removeRow
);
$
(
'
.js-member-update-control
'
)
.
off
(
'
change
'
)
.
on
(
'
change
'
,
this
.
formSubmit
.
bind
(
this
));
$
(
'
.js-edit-member-form
'
)
.
off
(
'
ajax:success
'
)
.
on
(
'
ajax:success
'
,
this
.
formSuccess
.
bind
(
this
));
gl
.
utils
.
disableButtonIfEmptyField
(
'
#user_ids
'
,
'
input[name=commit]
'
,
'
change
'
);
gl
.
utils
.
disableButtonIfEmptyField
(
'
#user_ids
'
,
'
input[name=commit]
'
,
'
change
'
);
}
}
...
@@ -42,7 +52,7 @@ export default class Members {
...
@@ -42,7 +52,7 @@ export default class Members {
return
$el
.
text
();
return
$el
.
text
();
},
},
clicked
:
(
options
)
=>
{
clicked
:
options
=>
{
const
$link
=
options
.
$el
;
const
$link
=
options
.
$el
;
if
(
!
$link
.
data
(
'
revert
'
))
{
if
(
!
$link
.
data
(
'
revert
'
))
{
...
@@ -53,8 +63,7 @@ export default class Members {
...
@@ -53,8 +63,7 @@ export default class Members {
$toggle
.
disable
();
$toggle
.
disable
();
$dateInput
.
disable
();
$dateInput
.
disable
();
this
.
overrideLdap
(
$memberListItem
,
$link
.
data
(
'
endpoint
'
),
false
)
this
.
overrideLdap
(
$memberListItem
,
$link
.
data
(
'
endpoint
'
),
false
).
catch
(()
=>
{
.
catch
(()
=>
{
$toggle
.
enable
();
$toggle
.
enable
();
$dateInput
.
enable
();
$dateInput
.
enable
();
});
});
...
@@ -111,11 +120,15 @@ export default class Members {
...
@@ -111,11 +120,15 @@ export default class Members {
$toggle
.
enable
();
$toggle
.
enable
();
$dateInput
.
enable
();
$dateInput
.
enable
();
})
})
.
catch
(
(
xhr
)
=>
{
.
catch
(
xhr
=>
{
$btn
.
enable
();
$btn
.
enable
();
if
(
xhr
.
status
===
403
)
{
if
(
xhr
.
status
===
403
)
{
Flash
(
__
(
'
You do not have the correct permissions to override the settings from the LDAP group sync.
'
));
Flash
(
__
(
'
You do not have the correct permissions to override the settings from the LDAP group sync.
'
,
),
);
}
else
{
}
else
{
Flash
(
__
(
'
An error occurred while saving LDAP override status. Please try again.
'
));
Flash
(
__
(
'
An error occurred while saving LDAP override status. Please try again.
'
));
}
}
...
@@ -123,7 +136,8 @@ export default class Members {
...
@@ -123,7 +136,8 @@ export default class Members {
}
}
// eslint-disable-next-line class-methods-use-this
// eslint-disable-next-line class-methods-use-this
overrideLdap
(
$memberListitem
,
endpoint
,
override
)
{
overrideLdap
(
$memberListitem
,
endpoint
,
override
)
{
return
axios
.
patch
(
endpoint
,
{
return
axios
.
patch
(
endpoint
,
{
group_member
:
{
group_member
:
{
override
,
override
,
},
},
...
...
app/assets/javascripts/milestone_select.js
View file @
7e9f44fa
...
@@ -9,7 +9,10 @@ import '~/gl_dropdown';
...
@@ -9,7 +9,10 @@ import '~/gl_dropdown';
import
axios
from
'
./lib/utils/axios_utils
'
;
import
axios
from
'
./lib/utils/axios_utils
'
;
import
{
timeFor
}
from
'
./lib/utils/datetime_utility
'
;
import
{
timeFor
}
from
'
./lib/utils/datetime_utility
'
;
import
ModalStore
from
'
./boards/stores/modal_store
'
;
import
ModalStore
from
'
./boards/stores/modal_store
'
;
import
boardsStore
,
{
boardStoreIssueSet
,
boardStoreIssueDelete
}
from
'
./boards/stores/boards_store
'
;
import
boardsStore
,
{
boardStoreIssueSet
,
boardStoreIssueDelete
,
}
from
'
./boards/stores/boards_store
'
;
export
default
class
MilestoneSelect
{
export
default
class
MilestoneSelect
{
constructor
(
currentProject
,
els
,
options
=
{})
{
constructor
(
currentProject
,
els
,
options
=
{})
{
...
...
app/assets/javascripts/monitoring/components/dashboard.vue
View file @
7e9f44fa
...
@@ -152,10 +152,14 @@ export default {
...
@@ -152,10 +152,14 @@ export default {
this
.
state
=
'
gettingStarted
'
;
this
.
state
=
'
gettingStarted
'
;
}
else
{
}
else
{
if
(
this
.
showEnvironmentDropdown
)
{
if
(
this
.
showEnvironmentDropdown
)
{
this
.
servicePromises
.
push
(
this
.
service
this
.
servicePromises
.
push
(
this
.
service
.
getEnvironmentsData
()
.
getEnvironmentsData
()
.
then
((
data
)
=>
this
.
store
.
storeEnvironmentsData
(
data
))
.
then
(
data
=>
this
.
store
.
storeEnvironmentsData
(
data
))
.
catch
(()
=>
Flash
(
s__
(
'
Metrics|There was an error getting environments information.
'
))));
.
catch
(()
=>
Flash
(
s__
(
'
Metrics|There was an error getting environments information.
'
)),
),
);
}
}
this
.
getGraphsData
();
this
.
getGraphsData
();
window
.
addEventListener
(
'
resize
'
,
this
.
resizeThrottled
,
false
);
window
.
addEventListener
(
'
resize
'
,
this
.
resizeThrottled
,
false
);
...
...
app/assets/javascripts/notes/components/notes_app.vue
View file @
7e9f44fa
...
@@ -54,7 +54,13 @@ export default {
...
@@ -54,7 +54,13 @@ export default {
};
};
},
},
computed
:
{
computed
:
{
...
mapGetters
([
'
isNotesFetched
'
,
'
discussions
'
,
'
getNotesDataByProp
'
,
'
discussionCount
'
,
'
isLoading
'
]),
...
mapGetters
([
'
isNotesFetched
'
,
'
discussions
'
,
'
getNotesDataByProp
'
,
'
discussionCount
'
,
'
isLoading
'
,
]),
noteableType
()
{
noteableType
()
{
return
this
.
noteableData
.
noteableType
;
return
this
.
noteableData
.
noteableType
;
},
},
...
...
app/assets/javascripts/notes/discussion_filters.js
View file @
7e9f44fa
import
Vue
from
'
vue
'
;
import
Vue
from
'
vue
'
;
import
DiscussionFilter
from
'
./components/discussion_filter.vue
'
;
import
DiscussionFilter
from
'
./components/discussion_filter.vue
'
;
export
default
(
store
)
=>
{
export
default
store
=>
{
const
discussionFilterEl
=
document
.
getElementById
(
'
js-vue-discussion-filter
'
);
const
discussionFilterEl
=
document
.
getElementById
(
'
js-vue-discussion-filter
'
);
if
(
discussionFilterEl
)
{
if
(
discussionFilterEl
)
{
const
{
defaultFilter
,
notesFilters
}
=
discussionFilterEl
.
dataset
;
const
{
defaultFilter
,
notesFilters
}
=
discussionFilterEl
.
dataset
;
const
defaultValue
=
defaultFilter
?
parseInt
(
defaultFilter
,
10
)
:
null
;
const
defaultValue
=
defaultFilter
?
parseInt
(
defaultFilter
,
10
)
:
null
;
const
filterValues
=
notesFilters
?
JSON
.
parse
(
notesFilters
)
:
{};
const
filterValues
=
notesFilters
?
JSON
.
parse
(
notesFilters
)
:
{};
const
filters
=
Object
.
keys
(
filterValues
).
map
(
entry
=>
const
filters
=
Object
.
keys
(
filterValues
).
map
(
entry
=>
({
({
title
:
entry
,
value
:
filterValues
[
entry
]
}));
title
:
entry
,
value
:
filterValues
[
entry
],
}));
return
new
Vue
({
return
new
Vue
({
el
:
discussionFilterEl
,
el
:
discussionFilterEl
,
...
...
app/assets/javascripts/pages/milestones/shared/components/promote_milestone_modal.vue
View file @
7e9f44fa
...
@@ -95,4 +95,3 @@ export default {
...
@@ -95,4 +95,3 @@ export default {
</div>
</div>
</gl-modal>
</gl-modal>
</template>
</template>
app/assets/javascripts/pages/projects/project.js
View file @
7e9f44fa
...
@@ -76,7 +76,9 @@ export default class Project {
...
@@ -76,7 +76,9 @@ export default class Project {
const
projectId
=
$
(
this
).
data
(
'
project-id
'
);
const
projectId
=
$
(
this
).
data
(
'
project-id
'
);
const
cookieKey
=
`hide_auto_devops_implicitly_enabled_banner_
${
projectId
}
`
;
const
cookieKey
=
`hide_auto_devops_implicitly_enabled_banner_
${
projectId
}
`
;
Cookies
.
set
(
cookieKey
,
'
false
'
);
Cookies
.
set
(
cookieKey
,
'
false
'
);
$
(
this
).
parents
(
'
.auto-devops-implicitly-enabled-banner
'
).
remove
();
$
(
this
)
.
parents
(
'
.auto-devops-implicitly-enabled-banner
'
)
.
remove
();
return
e
.
preventDefault
();
return
e
.
preventDefault
();
});
});
Project
.
projectSelectDropdown
();
Project
.
projectSelectDropdown
();
...
...
app/assets/javascripts/pages/projects/shared/permissions/components/settings_panel.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
projectFeatureSetting
from
'
./project_feature_setting.vue
'
;
import
projectFeatureSetting
from
'
./project_feature_setting.vue
'
;
import
projectFeatureToggle
from
'
../../../../../vue_shared/components/toggle_button.vue
'
;
import
projectFeatureToggle
from
'
../../../../../vue_shared/components/toggle_button.vue
'
;
import
projectSettingRow
from
'
./project_setting_row.vue
'
;
import
projectSettingRow
from
'
./project_setting_row.vue
'
;
import
{
visibilityOptions
,
visibilityLevelDescriptions
}
from
'
../constants
'
;
import
{
visibilityOptions
,
visibilityLevelDescriptions
}
from
'
../constants
'
;
import
{
toggleHiddenClassBySelector
}
from
'
../external
'
;
import
{
toggleHiddenClassBySelector
}
from
'
../external
'
;
export
default
{
export
default
{
components
:
{
components
:
{
projectFeatureSetting
,
projectFeatureSetting
,
projectFeatureToggle
,
projectFeatureToggle
,
...
@@ -102,9 +102,7 @@
...
@@ -102,9 +102,7 @@
computed
:
{
computed
:
{
featureAccessLevelOptions
()
{
featureAccessLevelOptions
()
{
const
options
=
[
const
options
=
[[
10
,
'
Only Project Members
'
]];
[
10
,
'
Only Project Members
'
],
];
if
(
this
.
visibilityLevel
!==
visibilityOptions
.
PRIVATE
)
{
if
(
this
.
visibilityLevel
!==
visibilityOptions
.
PRIVATE
)
{
options
.
push
([
20
,
'
Everyone With Access
'
]);
options
.
push
([
20
,
'
Everyone With Access
'
]);
}
}
...
@@ -209,7 +207,7 @@
...
@@ -209,7 +207,7 @@
return
this
.
allowedVisibilityOptions
.
includes
(
option
);
return
this
.
allowedVisibilityOptions
.
includes
(
option
);
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/projects/project_new.js
View file @
7e9f44fa
...
@@ -4,8 +4,10 @@ import { slugifyWithHyphens } from '../lib/utils/text_utility';
...
@@ -4,8 +4,10 @@ import { slugifyWithHyphens } from '../lib/utils/text_utility';
let
hasUserDefinedProjectPath
=
false
;
let
hasUserDefinedProjectPath
=
false
;
const
deriveProjectPathFromUrl
=
(
$projectImportUrl
)
=>
{
const
deriveProjectPathFromUrl
=
$projectImportUrl
=>
{
const
$currentProjectPath
=
$projectImportUrl
.
parents
(
'
.toggle-import-form
'
).
find
(
'
#project_path
'
);
const
$currentProjectPath
=
$projectImportUrl
.
parents
(
'
.toggle-import-form
'
)
.
find
(
'
#project_path
'
);
if
(
hasUserDefinedProjectPath
)
{
if
(
hasUserDefinedProjectPath
)
{
return
;
return
;
}
}
...
@@ -52,9 +54,11 @@ const bindEvents = () => {
...
@@ -52,9 +54,11 @@ const bindEvents = () => {
return
;
return
;
}
}
$
(
'
.how_to_import_link
'
).
on
(
'
click
'
,
(
e
)
=>
{
$
(
'
.how_to_import_link
'
).
on
(
'
click
'
,
e
=>
{
e
.
preventDefault
();
e
.
preventDefault
();
$
(
e
.
currentTarget
).
next
(
'
.modal
'
).
show
();
$
(
e
.
currentTarget
)
.
next
(
'
.modal
'
)
.
show
();
});
});
$
(
'
.modal-header .close
'
).
on
(
'
click
'
,
()
=>
{
$
(
'
.modal-header .close
'
).
on
(
'
click
'
,
()
=>
{
...
@@ -63,15 +67,21 @@ const bindEvents = () => {
...
@@ -63,15 +67,21 @@ const bindEvents = () => {
$
(
'
.btn_import_gitlab_project
'
).
on
(
'
click
'
,
()
=>
{
$
(
'
.btn_import_gitlab_project
'
).
on
(
'
click
'
,
()
=>
{
const
importHref
=
$
(
'
a.btn_import_gitlab_project
'
).
attr
(
'
href
'
);
const
importHref
=
$
(
'
a.btn_import_gitlab_project
'
).
attr
(
'
href
'
);
$
(
'
.btn_import_gitlab_project
'
)
$
(
'
.btn_import_gitlab_project
'
).
attr
(
.
attr
(
'
href
'
,
`
${
importHref
}
?namespace_id=
${
$
(
'
#project_namespace_id
'
).
val
()}
&name=
${
$projectName
.
val
()}
&path=
${
$projectPath
.
val
()}
`
);
'
href
'
,
`
${
importHref
}
?namespace_id=
${
$
(
'
#project_namespace_id
'
,
).
val
()}
&name=
${
$projectName
.
val
()}
&path=
${
$projectPath
.
val
()}
`
,
);
});
});
if
(
$pushNewProjectTipTrigger
)
{
if
(
$pushNewProjectTipTrigger
)
{
$pushNewProjectTipTrigger
$pushNewProjectTipTrigger
.
removeAttr
(
'
rel
'
)
.
removeAttr
(
'
rel
'
)
.
removeAttr
(
'
target
'
)
.
removeAttr
(
'
target
'
)
.
on
(
'
click
'
,
(
e
)
=>
{
e
.
preventDefault
();
})
.
on
(
'
click
'
,
e
=>
{
e
.
preventDefault
();
})
.
popover
({
.
popover
({
title
:
$pushNewProjectTipTrigger
.
data
(
'
title
'
),
title
:
$pushNewProjectTipTrigger
.
data
(
'
title
'
),
placement
:
'
bottom
'
,
placement
:
'
bottom
'
,
...
@@ -79,13 +89,15 @@ const bindEvents = () => {
...
@@ -79,13 +89,15 @@ const bindEvents = () => {
content
:
$
(
'
.push-new-project-tip-template
'
).
html
(),
content
:
$
(
'
.push-new-project-tip-template
'
).
html
(),
})
})
.
on
(
'
shown.bs.popover
'
,
()
=>
{
.
on
(
'
shown.bs.popover
'
,
()
=>
{
$
(
document
).
on
(
'
click.popover touchstart.popover
'
,
(
event
)
=>
{
$
(
document
).
on
(
'
click.popover touchstart.popover
'
,
event
=>
{
if
(
$
(
event
.
target
).
closest
(
'
.popover
'
).
length
===
0
)
{
if
(
$
(
event
.
target
).
closest
(
'
.popover
'
).
length
===
0
)
{
$pushNewProjectTipTrigger
.
trigger
(
'
click
'
);
$pushNewProjectTipTrigger
.
trigger
(
'
click
'
);
}
}
});
});
const
target
=
$
(
`#
${
$pushNewProjectTipTrigger
.
attr
(
'
aria-describedby
'
)}
`
).
find
(
'
.js-select-on-focus
'
);
const
target
=
$
(
`#
${
$pushNewProjectTipTrigger
.
attr
(
'
aria-describedby
'
)}
`
).
find
(
'
.js-select-on-focus
'
,
);
addSelectOnFocusBehaviour
(
target
);
addSelectOnFocusBehaviour
(
target
);
target
.
focus
();
target
.
focus
();
...
@@ -117,13 +129,15 @@ const bindEvents = () => {
...
@@ -117,13 +129,15 @@ const bindEvents = () => {
const
selectedTemplate
=
templates
[
value
];
const
selectedTemplate
=
templates
[
value
];
$selectedTemplateText
.
text
(
selectedTemplate
.
text
);
$selectedTemplateText
.
text
(
selectedTemplate
.
text
);
$
(
selectedTemplate
.
icon
).
clone
().
addClass
(
'
d-block
'
).
appendTo
(
$selectedIcon
);
$
(
selectedTemplate
.
icon
)
.
clone
()
.
addClass
(
'
d-block
'
)
.
appendTo
(
$selectedIcon
);
const
$activeTabProjectName
=
$
(
'
.tab-pane.active #project_name
'
);
const
$activeTabProjectName
=
$
(
'
.tab-pane.active #project_name
'
);
const
$activeTabProjectPath
=
$
(
'
.tab-pane.active #project_path
'
);
const
$activeTabProjectPath
=
$
(
'
.tab-pane.active #project_path
'
);
$activeTabProjectName
.
focus
();
$activeTabProjectName
.
focus
();
$activeTabProjectName
$activeTabProjectName
.
keyup
(()
=>
{
.
keyup
(()
=>
{
onProjectNameChange
(
$activeTabProjectName
,
$activeTabProjectPath
);
onProjectNameChange
(
$activeTabProjectName
,
$activeTabProjectPath
);
hasUserDefinedProjectPath
=
$activeTabProjectPath
.
val
().
trim
().
length
>
0
;
hasUserDefinedProjectPath
=
$activeTabProjectPath
.
val
().
trim
().
length
>
0
;
});
});
...
...
app/assets/javascripts/right_sidebar.js
View file @
7e9f44fa
...
@@ -21,7 +21,7 @@ Sidebar.initialize = function(currentUser) {
...
@@ -21,7 +21,7 @@ Sidebar.initialize = function(currentUser) {
}
}
};
};
Sidebar
.
prototype
.
removeListeners
=
function
()
{
Sidebar
.
prototype
.
removeListeners
=
function
()
{
this
.
sidebar
.
off
(
'
click
'
,
'
.sidebar-collapsed-icon
'
);
this
.
sidebar
.
off
(
'
click
'
,
'
.sidebar-collapsed-icon
'
);
this
.
sidebar
.
off
(
'
hidden.gl.dropdown
'
);
this
.
sidebar
.
off
(
'
hidden.gl.dropdown
'
);
$
(
'
.dropdown
'
).
off
(
'
loading.gl.dropdown
'
);
$
(
'
.dropdown
'
).
off
(
'
loading.gl.dropdown
'
);
...
@@ -38,10 +38,12 @@ Sidebar.prototype.addEventListeners = function() {
...
@@ -38,10 +38,12 @@ Sidebar.prototype.addEventListeners = function() {
$
(
'
.dropdown
'
).
on
(
'
loaded.gl.dropdown
'
,
this
.
sidebarDropdownLoaded
);
$
(
'
.dropdown
'
).
on
(
'
loaded.gl.dropdown
'
,
this
.
sidebarDropdownLoaded
);
$document
.
on
(
'
click
'
,
'
.js-sidebar-toggle
'
,
this
.
sidebarToggleClicked
);
$document
.
on
(
'
click
'
,
'
.js-sidebar-toggle
'
,
this
.
sidebarToggleClicked
);
return
$
(
document
).
off
(
'
click
'
,
'
.js-issuable-todo
'
).
on
(
'
click
'
,
'
.js-issuable-todo
'
,
this
.
toggleTodo
);
return
$
(
document
)
.
off
(
'
click
'
,
'
.js-issuable-todo
'
)
.
on
(
'
click
'
,
'
.js-issuable-todo
'
,
this
.
toggleTodo
);
};
};
Sidebar
.
prototype
.
sidebarToggleClicked
=
function
(
e
,
triggered
)
{
Sidebar
.
prototype
.
sidebarToggleClicked
=
function
(
e
,
triggered
)
{
var
$allGutterToggleIcons
,
$this
,
isExpanded
,
tooltipLabel
;
var
$allGutterToggleIcons
,
$this
,
isExpanded
,
tooltipLabel
;
e
.
preventDefault
();
e
.
preventDefault
();
$this
=
$
(
this
);
$this
=
$
(
this
);
...
@@ -51,18 +53,26 @@ Sidebar.prototype.sidebarToggleClicked = function (e, triggered) {
...
@@ -51,18 +53,26 @@ Sidebar.prototype.sidebarToggleClicked = function (e, triggered) {
if
(
isExpanded
)
{
if
(
isExpanded
)
{
$allGutterToggleIcons
.
removeClass
(
'
fa-angle-double-right
'
).
addClass
(
'
fa-angle-double-left
'
);
$allGutterToggleIcons
.
removeClass
(
'
fa-angle-double-right
'
).
addClass
(
'
fa-angle-double-left
'
);
$
(
'
aside.right-sidebar
'
).
removeClass
(
'
right-sidebar-expanded
'
).
addClass
(
'
right-sidebar-collapsed
'
);
$
(
'
aside.right-sidebar
'
)
$
(
'
.layout-page
'
).
removeClass
(
'
right-sidebar-expanded
'
).
addClass
(
'
right-sidebar-collapsed
'
);
.
removeClass
(
'
right-sidebar-expanded
'
)
.
addClass
(
'
right-sidebar-collapsed
'
);
$
(
'
.layout-page
'
)
.
removeClass
(
'
right-sidebar-expanded
'
)
.
addClass
(
'
right-sidebar-collapsed
'
);
}
else
{
}
else
{
$allGutterToggleIcons
.
removeClass
(
'
fa-angle-double-left
'
).
addClass
(
'
fa-angle-double-right
'
);
$allGutterToggleIcons
.
removeClass
(
'
fa-angle-double-left
'
).
addClass
(
'
fa-angle-double-right
'
);
$
(
'
aside.right-sidebar
'
).
removeClass
(
'
right-sidebar-collapsed
'
).
addClass
(
'
right-sidebar-expanded
'
);
$
(
'
aside.right-sidebar
'
)
$
(
'
.layout-page
'
).
removeClass
(
'
right-sidebar-collapsed
'
).
addClass
(
'
right-sidebar-expanded
'
);
.
removeClass
(
'
right-sidebar-collapsed
'
)
.
addClass
(
'
right-sidebar-expanded
'
);
$
(
'
.layout-page
'
)
.
removeClass
(
'
right-sidebar-collapsed
'
)
.
addClass
(
'
right-sidebar-expanded
'
);
}
}
$this
.
attr
(
'
data-original-title
'
,
tooltipLabel
);
$this
.
attr
(
'
data-original-title
'
,
tooltipLabel
);
if
(
!
triggered
)
{
if
(
!
triggered
)
{
Cookies
.
set
(
"
collapsed_gutter
"
,
$
(
'
.right-sidebar
'
).
hasClass
(
'
right-sidebar-collapsed
'
));
Cookies
.
set
(
'
collapsed_gutter
'
,
$
(
'
.right-sidebar
'
).
hasClass
(
'
right-sidebar-collapsed
'
));
}
}
};
};
...
@@ -71,21 +81,27 @@ Sidebar.prototype.toggleTodo = function(e) {
...
@@ -71,21 +81,27 @@ Sidebar.prototype.toggleTodo = function(e) {
$this
=
$
(
e
.
currentTarget
);
$this
=
$
(
e
.
currentTarget
);
ajaxType
=
$this
.
attr
(
'
data-delete-path
'
)
?
'
delete
'
:
'
post
'
;
ajaxType
=
$this
.
attr
(
'
data-delete-path
'
)
?
'
delete
'
:
'
post
'
;
if
(
$this
.
attr
(
'
data-delete-path
'
))
{
if
(
$this
.
attr
(
'
data-delete-path
'
))
{
url
=
""
+
(
$this
.
attr
(
'
data-delete-path
'
)
);
url
=
''
+
$this
.
attr
(
'
data-delete-path
'
);
}
else
{
}
else
{
url
=
""
+
(
$this
.
data
(
'
url
'
)
);
url
=
''
+
$this
.
data
(
'
url
'
);
}
}
$this
.
tooltip
(
'
hide
'
);
$this
.
tooltip
(
'
hide
'
);
$
(
'
.js-issuable-todo
'
).
disable
().
addClass
(
'
is-loading
'
);
$
(
'
.js-issuable-todo
'
)
.
disable
()
.
addClass
(
'
is-loading
'
);
axios
[
ajaxType
](
url
,
{
axios
[
ajaxType
](
url
,
{
issuable_id
:
$this
.
data
(
'
issuableId
'
),
issuable_id
:
$this
.
data
(
'
issuableId
'
),
issuable_type
:
$this
.
data
(
'
issuableType
'
),
issuable_type
:
$this
.
data
(
'
issuableType
'
),
}).
then
(({
data
})
=>
{
})
.
then
(({
data
})
=>
{
this
.
todoUpdateDone
(
data
);
this
.
todoUpdateDone
(
data
);
}).
catch
(()
=>
flash
(
`There was an error
${
ajaxType
===
'
post
'
?
'
adding a
'
:
'
deleting the
'
}
todo.`
));
})
.
catch
(()
=>
flash
(
`There was an error
${
ajaxType
===
'
post
'
?
'
adding a
'
:
'
deleting the
'
}
todo.`
),
);
};
};
Sidebar
.
prototype
.
todoUpdateDone
=
function
(
data
)
{
Sidebar
.
prototype
.
todoUpdateDone
=
function
(
data
)
{
...
@@ -99,7 +115,8 @@ Sidebar.prototype.todoUpdateDone = function(data) {
...
@@ -99,7 +115,8 @@ Sidebar.prototype.todoUpdateDone = function(data) {
const
$el
=
$
(
el
);
const
$el
=
$
(
el
);
const
$elText
=
$el
.
find
(
'
.js-issuable-todo-inner
'
);
const
$elText
=
$el
.
find
(
'
.js-issuable-todo-inner
'
);
$el
.
removeClass
(
'
is-loading
'
)
$el
.
removeClass
(
'
is-loading
'
)
.
enable
()
.
enable
()
.
attr
(
'
aria-label
'
,
$el
.
data
(
`
${
attrPrefix
}
Text`
))
.
attr
(
'
aria-label
'
,
$el
.
data
(
`
${
attrPrefix
}
Text`
))
.
attr
(
'
data-delete-path
'
,
deletePath
)
.
attr
(
'
data-delete-path
'
,
deletePath
)
...
@@ -119,7 +136,9 @@ Sidebar.prototype.todoUpdateDone = function(data) {
...
@@ -119,7 +136,9 @@ Sidebar.prototype.todoUpdateDone = function(data) {
Sidebar
.
prototype
.
sidebarDropdownLoading
=
function
(
e
)
{
Sidebar
.
prototype
.
sidebarDropdownLoading
=
function
(
e
)
{
var
$loading
,
$sidebarCollapsedIcon
,
i
,
img
;
var
$loading
,
$sidebarCollapsedIcon
,
i
,
img
;
$sidebarCollapsedIcon
=
$
(
this
).
closest
(
'
.block
'
).
find
(
'
.sidebar-collapsed-icon
'
);
$sidebarCollapsedIcon
=
$
(
this
)
.
closest
(
'
.block
'
)
.
find
(
'
.sidebar-collapsed-icon
'
);
img
=
$sidebarCollapsedIcon
.
find
(
'
img
'
);
img
=
$sidebarCollapsedIcon
.
find
(
'
img
'
);
i
=
$sidebarCollapsedIcon
.
find
(
'
i
'
);
i
=
$sidebarCollapsedIcon
.
find
(
'
i
'
);
$loading
=
$
(
'
<i class="fa fa-spinner fa-spin"></i>
'
);
$loading
=
$
(
'
<i class="fa fa-spinner fa-spin"></i>
'
);
...
@@ -134,7 +153,9 @@ Sidebar.prototype.sidebarDropdownLoading = function(e) {
...
@@ -134,7 +153,9 @@ Sidebar.prototype.sidebarDropdownLoading = function(e) {
Sidebar
.
prototype
.
sidebarDropdownLoaded
=
function
(
e
)
{
Sidebar
.
prototype
.
sidebarDropdownLoaded
=
function
(
e
)
{
var
$sidebarCollapsedIcon
,
i
,
img
;
var
$sidebarCollapsedIcon
,
i
,
img
;
$sidebarCollapsedIcon
=
$
(
this
).
closest
(
'
.block
'
).
find
(
'
.sidebar-collapsed-icon
'
);
$sidebarCollapsedIcon
=
$
(
this
)
.
closest
(
'
.block
'
)
.
find
(
'
.sidebar-collapsed-icon
'
);
img
=
$sidebarCollapsedIcon
.
find
(
'
img
'
);
img
=
$sidebarCollapsedIcon
.
find
(
'
img
'
);
$sidebarCollapsedIcon
.
find
(
'
i.fa-spin
'
).
remove
();
$sidebarCollapsedIcon
.
find
(
'
i.fa-spin
'
).
remove
();
i
=
$sidebarCollapsedIcon
.
find
(
'
i
'
);
i
=
$sidebarCollapsedIcon
.
find
(
'
i
'
);
...
@@ -220,7 +241,7 @@ Sidebar.prototype.isOpen = function() {
...
@@ -220,7 +241,7 @@ Sidebar.prototype.isOpen = function() {
};
};
Sidebar
.
prototype
.
getBlock
=
function
(
name
)
{
Sidebar
.
prototype
.
getBlock
=
function
(
name
)
{
return
this
.
sidebar
.
find
(
"
.block.
"
+
name
);
return
this
.
sidebar
.
find
(
'
.block.
'
+
name
);
};
};
export
default
Sidebar
;
export
default
Sidebar
;
app/assets/javascripts/search_autocomplete.js
View file @
7e9f44fa
...
@@ -234,7 +234,9 @@ export class SearchAutocomplete {
...
@@ -234,7 +234,9 @@ export class SearchAutocomplete {
icon
,
icon
,
text
:
term
,
text
:
term
,
template
,
template
,
url
:
`
${
gon
.
relative_url_root
}
/search?search=
${
term
}
&project_id=
${
this
.
projectInputEl
.
val
()}
&group_id=
${
this
.
groupInputEl
.
val
()}
`
,
url
:
`
${
gon
.
relative_url_root
}
/search?search=
${
term
}
&project_id=
${
this
.
projectInputEl
.
val
()}
&group_id=
${
this
.
groupInputEl
.
val
()}
`
,
});
});
}
}
}
}
...
...
app/assets/javascripts/sidebar/components/assignees/assignees.vue
View file @
7e9f44fa
...
@@ -74,8 +74,8 @@ export default {
...
@@ -74,8 +74,8 @@ export default {
}
}
if
(
!
this
.
users
.
length
)
{
if
(
!
this
.
users
.
length
)
{
const
emptyTooltipLabel
=
this
.
issuableType
===
'
issue
'
?
const
emptyTooltipLabel
=
__
(
'
Assignee(s)
'
)
:
__
(
'
Assignee
'
);
this
.
issuableType
===
'
issue
'
?
__
(
'
Assignee(s)
'
)
:
__
(
'
Assignee
'
);
names
.
push
(
emptyTooltipLabel
);
names
.
push
(
emptyTooltipLabel
);
}
}
...
...
app/assets/javascripts/sidebar/components/subscriptions/subscriptions.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
{
__
}
from
'
~/locale
'
;
import
{
__
}
from
'
~/locale
'
;
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
icon
from
'
~/vue_shared/components/icon.vue
'
;
import
toggleButton
from
'
~/vue_shared/components/toggle_button.vue
'
;
import
toggleButton
from
'
~/vue_shared/components/toggle_button.vue
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
eventHub
from
'
../../event_hub
'
;
import
eventHub
from
'
../../event_hub
'
;
const
ICON_ON
=
'
notifications
'
;
const
ICON_ON
=
'
notifications
'
;
const
ICON_OFF
=
'
notifications-off
'
;
const
ICON_OFF
=
'
notifications-off
'
;
const
LABEL_ON
=
__
(
'
Notifications on
'
);
const
LABEL_ON
=
__
(
'
Notifications on
'
);
const
LABEL_OFF
=
__
(
'
Notifications off
'
);
const
LABEL_OFF
=
__
(
'
Notifications off
'
);
export
default
{
export
default
{
directives
:
{
directives
:
{
tooltip
,
tooltip
,
},
},
...
@@ -69,7 +69,7 @@
...
@@ -69,7 +69,7 @@
this
.
$emit
(
'
toggleSidebar
'
);
this
.
$emit
(
'
toggleSidebar
'
);
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/sidebar/sidebar_mediator.js
View file @
7e9f44fa
...
@@ -39,9 +39,10 @@ export default class SidebarMediator {
...
@@ -39,9 +39,10 @@ export default class SidebarMediator {
}
}
fetch
()
{
fetch
()
{
return
this
.
service
.
get
()
return
this
.
service
.
get
()
.
then
(
response
=>
response
.
json
())
.
then
(
response
=>
response
.
json
())
.
then
(
(
data
)
=>
{
.
then
(
data
=>
{
this
.
processFetchedData
(
data
);
this
.
processFetchedData
(
data
);
})
})
.
catch
(()
=>
new
Flash
(
'
Error occurred when fetching sidebar data
'
));
.
catch
(()
=>
new
Flash
(
'
Error occurred when fetching sidebar data
'
));
...
@@ -56,30 +57,33 @@ export default class SidebarMediator {
...
@@ -56,30 +57,33 @@ export default class SidebarMediator {
toggleSubscription
()
{
toggleSubscription
()
{
this
.
store
.
setFetchingState
(
'
subscriptions
'
,
true
);
this
.
store
.
setFetchingState
(
'
subscriptions
'
,
true
);
return
this
.
service
.
toggleSubscription
()
return
this
.
service
.
toggleSubscription
()
.
then
(()
=>
{
.
then
(()
=>
{
this
.
store
.
setSubscribedState
(
!
this
.
store
.
subscribed
);
this
.
store
.
setSubscribedState
(
!
this
.
store
.
subscribed
);
this
.
store
.
setFetchingState
(
'
subscriptions
'
,
false
);
this
.
store
.
setFetchingState
(
'
subscriptions
'
,
false
);
})
})
.
catch
(
(
err
)
=>
{
.
catch
(
err
=>
{
this
.
store
.
setFetchingState
(
'
subscriptions
'
,
false
);
this
.
store
.
setFetchingState
(
'
subscriptions
'
,
false
);
throw
err
;
throw
err
;
});
});
}
}
fetchAutocompleteProjects
(
searchTerm
)
{
fetchAutocompleteProjects
(
searchTerm
)
{
return
this
.
service
.
getProjectsAutocomplete
(
searchTerm
)
return
this
.
service
.
getProjectsAutocomplete
(
searchTerm
)
.
then
(
response
=>
response
.
json
())
.
then
(
response
=>
response
.
json
())
.
then
(
(
data
)
=>
{
.
then
(
data
=>
{
this
.
store
.
setAutocompleteProjects
(
data
);
this
.
store
.
setAutocompleteProjects
(
data
);
return
this
.
store
.
autocompleteProjects
;
return
this
.
store
.
autocompleteProjects
;
});
});
}
}
moveIssue
()
{
moveIssue
()
{
return
this
.
service
.
moveIssue
(
this
.
store
.
moveToProjectId
)
return
this
.
service
.
moveIssue
(
this
.
store
.
moveToProjectId
)
.
then
(
response
=>
response
.
json
())
.
then
(
response
=>
response
.
json
())
.
then
(
(
data
)
=>
{
.
then
(
data
=>
{
if
(
window
.
location
.
pathname
!==
data
.
web_url
)
{
if
(
window
.
location
.
pathname
!==
data
.
web_url
)
{
visitUrl
(
data
.
web_url
);
visitUrl
(
data
.
web_url
);
}
}
...
...
app/assets/javascripts/vue_merge_request_widget/components/mr_widget_pipeline.vue
View file @
7e9f44fa
...
@@ -58,19 +58,22 @@ export default {
...
@@ -58,19 +58,22 @@ export default {
},
},
hasStages
()
{
hasStages
()
{
return
(
return
(
this
.
pipeline
.
details
&&
this
.
pipeline
.
details
&&
this
.
pipeline
.
details
.
stages
&&
this
.
pipeline
.
details
.
stages
.
length
this
.
pipeline
.
details
.
stages
&&
this
.
pipeline
.
details
.
stages
.
length
);
);
},
},
hasCommitInfo
()
{
hasCommitInfo
()
{
return
this
.
pipeline
.
commit
&&
Object
.
keys
(
this
.
pipeline
.
commit
).
length
>
0
;
return
this
.
pipeline
.
commit
&&
Object
.
keys
(
this
.
pipeline
.
commit
).
length
>
0
;
},
},
errorText
()
{
errorText
()
{
return
sprintf
(
__
(
'
Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}
'
),
{
return
sprintf
(
__
(
'
Could not retrieve the pipeline status. For troubleshooting steps, read the %{linkStart}documentation.%{linkEnd}
'
,
),
{
linkStart
:
`<a href="
${
this
.
troubleshootingDocsPath
}
">`
,
linkStart
:
`<a href="
${
this
.
troubleshootingDocsPath
}
">`
,
linkEnd
:
'
</a>
'
,
linkEnd
:
'
</a>
'
,
});
},
);
},
},
/* We typically set defaults ([]) in the store or prop declarations, but because triggered
/* We typically set defaults ([]) in the store or prop declarations, but because triggered
* and triggeredBy are appended to `pipeline`, we can't set defaults in the store, and we
* and triggeredBy are appended to `pipeline`, we can't set defaults in the store, and we
...
...
app/assets/javascripts/vue_merge_request_widget/components/states/ready_to_merge.vue
View file @
7e9f44fa
...
@@ -71,7 +71,12 @@ export default {
...
@@ -71,7 +71,12 @@ export default {
return
defaultClass
;
return
defaultClass
;
},
},
iconClass
()
{
iconClass
()
{
if
(
this
.
status
===
'
failed
'
||
!
this
.
commitMessage
.
length
||
!
this
.
mr
.
isMergeAllowed
||
this
.
mr
.
preventMerge
)
{
if
(
this
.
status
===
'
failed
'
||
!
this
.
commitMessage
.
length
||
!
this
.
mr
.
isMergeAllowed
||
this
.
mr
.
preventMerge
)
{
return
'
warning
'
;
return
'
warning
'
;
}
}
return
'
success
'
;
return
'
success
'
;
...
@@ -90,11 +95,13 @@ export default {
...
@@ -90,11 +95,13 @@ export default {
},
},
isMergeButtonDisabled
()
{
isMergeButtonDisabled
()
{
const
{
commitMessage
}
=
this
;
const
{
commitMessage
}
=
this
;
return
Boolean
(
!
commitMessage
.
length
return
Boolean
(
||
!
this
.
shouldShowMergeControls
()
!
commitMessage
.
length
||
||
this
.
isMakingRequest
!
this
.
shouldShowMergeControls
()
||
||
this
.
isApprovalNeeded
this
.
isMakingRequest
||
||
this
.
mr
.
preventMerge
);
this
.
isApprovalNeeded
||
this
.
mr
.
preventMerge
,
);
},
},
isRemoveSourceBranchButtonDisabled
()
{
isRemoveSourceBranchButtonDisabled
()
{
return
this
.
isMergeButtonDisabled
;
return
this
.
isMergeButtonDisabled
;
...
@@ -144,9 +151,10 @@ export default {
...
@@ -144,9 +151,10 @@ export default {
};
};
this
.
isMakingRequest
=
true
;
this
.
isMakingRequest
=
true
;
this
.
service
.
merge
(
options
)
this
.
service
.
merge
(
options
)
.
then
(
res
=>
res
.
data
)
.
then
(
res
=>
res
.
data
)
.
then
(
(
data
)
=>
{
.
then
(
data
=>
{
const
hasError
=
data
.
status
===
'
failed
'
||
data
.
status
===
'
hook_validation_error
'
;
const
hasError
=
data
.
status
===
'
failed
'
||
data
.
status
===
'
hook_validation_error
'
;
if
(
data
.
status
===
'
merge_when_pipeline_succeeds
'
)
{
if
(
data
.
status
===
'
merge_when_pipeline_succeeds
'
)
{
...
@@ -171,9 +179,10 @@ export default {
...
@@ -171,9 +179,10 @@ export default {
});
});
},
},
handleMergePolling
(
continuePolling
,
stopPolling
)
{
handleMergePolling
(
continuePolling
,
stopPolling
)
{
this
.
service
.
poll
()
this
.
service
.
poll
()
.
then
(
res
=>
res
.
data
)
.
then
(
res
=>
res
.
data
)
.
then
(
(
data
)
=>
{
.
then
(
data
=>
{
if
(
data
.
state
===
'
merged
'
)
{
if
(
data
.
state
===
'
merged
'
)
{
// If state is merged we should update the widget and stop the polling
// If state is merged we should update the widget and stop the polling
eventHub
.
$emit
(
'
MRWidgetUpdateRequested
'
);
eventHub
.
$emit
(
'
MRWidgetUpdateRequested
'
);
...
@@ -209,9 +218,10 @@ export default {
...
@@ -209,9 +218,10 @@ export default {
});
});
},
},
handleRemoveBranchPolling
(
continuePolling
,
stopPolling
)
{
handleRemoveBranchPolling
(
continuePolling
,
stopPolling
)
{
this
.
service
.
poll
()
this
.
service
.
poll
()
.
then
(
res
=>
res
.
data
)
.
then
(
res
=>
res
.
data
)
.
then
(
(
data
)
=>
{
.
then
(
data
=>
{
// If source branch exists then we should continue polling
// If source branch exists then we should continue polling
// because removing a source branch is a background task and takes time
// because removing a source branch is a background task and takes time
if
(
data
.
source_branch_exists
)
{
if
(
data
.
source_branch_exists
)
{
...
...
app/assets/javascripts/vue_merge_request_widget/mr_widget_options.vue
View file @
7e9f44fa
...
@@ -116,7 +116,7 @@ export default {
...
@@ -116,7 +116,7 @@ export default {
// init polling
// init polling
this
.
initPostMergeDeploymentsPolling
();
this
.
initPostMergeDeploymentsPolling
();
}
}
}
}
,
},
},
created
()
{
created
()
{
this
.
initPolling
();
this
.
initPolling
();
...
@@ -214,7 +214,7 @@ export default {
...
@@ -214,7 +214,7 @@ export default {
})
})
.
catch
(()
=>
this
.
throwDeploymentsError
());
.
catch
(()
=>
this
.
throwDeploymentsError
());
},
},
fetchPostMergeDeployments
(){
fetchPostMergeDeployments
()
{
return
this
.
fetchDeployments
(
'
merge_commit
'
)
return
this
.
fetchDeployments
(
'
merge_commit
'
)
.
then
(({
data
})
=>
{
.
then
(({
data
})
=>
{
if
(
data
.
length
)
{
if
(
data
.
length
)
{
...
@@ -224,7 +224,11 @@ export default {
...
@@ -224,7 +224,11 @@ export default {
.
catch
(()
=>
this
.
throwDeploymentsError
());
.
catch
(()
=>
this
.
throwDeploymentsError
());
},
},
throwDeploymentsError
()
{
throwDeploymentsError
()
{
createFlash
(
__
(
'
Something went wrong while fetching the environments for this merge request. Please try again.
'
));
createFlash
(
__
(
'
Something went wrong while fetching the environments for this merge request. Please try again.
'
,
),
);
},
},
fetchActionsContent
()
{
fetchActionsContent
()
{
this
.
service
this
.
service
...
...
app/assets/javascripts/vue_merge_request_widget/services/mr_widget_service.js
View file @
7e9f44fa
...
@@ -24,8 +24,8 @@ export default class MRWidgetService {
...
@@ -24,8 +24,8 @@ export default class MRWidgetService {
fetchDeployments
(
targetParam
)
{
fetchDeployments
(
targetParam
)
{
return
axios
.
get
(
this
.
endpoints
.
ciEnvironmentsStatusPath
,
{
return
axios
.
get
(
this
.
endpoints
.
ciEnvironmentsStatusPath
,
{
params
:
{
params
:
{
environment_target
:
targetParam
environment_target
:
targetParam
,
}
}
,
});
});
}
}
...
...
app/assets/javascripts/vue_merge_request_widget/stores/mr_widget_store.js
View file @
7e9f44fa
...
@@ -18,8 +18,7 @@ export default class MergeRequestStore {
...
@@ -18,8 +18,7 @@ export default class MergeRequestStore {
this
.
squash
=
data
.
squash
;
this
.
squash
=
data
.
squash
;
this
.
squashBeforeMergeHelpPath
=
this
.
squashBeforeMergeHelpPath
=
this
.
squashBeforeMergeHelpPath
||
data
.
squash_before_merge_help_path
;
this
.
squashBeforeMergeHelpPath
||
data
.
squash_before_merge_help_path
;
this
.
troubleshootingDocsPath
=
this
.
troubleshootingDocsPath
=
this
.
troubleshootingDocsPath
||
data
.
troubleshooting_docs_path
;
this
.
troubleshootingDocsPath
||
data
.
troubleshooting_docs_path
;
this
.
enableSquashBeforeMerge
=
this
.
enableSquashBeforeMerge
||
true
;
this
.
enableSquashBeforeMerge
=
this
.
enableSquashBeforeMerge
||
true
;
this
.
iid
=
data
.
iid
;
this
.
iid
=
data
.
iid
;
...
...
app/assets/javascripts/vue_shared/components/filtered_search_dropdown.vue
View file @
7e9f44fa
...
@@ -56,12 +56,14 @@ export default {
...
@@ -56,12 +56,14 @@ export default {
filteredResults
()
{
filteredResults
()
{
if
(
this
.
filter
!==
''
)
{
if
(
this
.
filter
!==
''
)
{
return
this
.
items
.
filter
(
return
this
.
items
.
filter
(
item
=>
item
[
this
.
filterKey
]
&&
item
[
this
.
filterKey
].
toLowerCase
().
includes
(
this
.
filter
.
toLowerCase
()),
item
=>
item
[
this
.
filterKey
]
&&
item
[
this
.
filterKey
].
toLowerCase
().
includes
(
this
.
filter
.
toLowerCase
()),
);
);
}
}
return
this
.
items
.
slice
(
0
,
this
.
visibleItems
);
return
this
.
items
.
slice
(
0
,
this
.
visibleItems
);
}
}
,
},
},
mounted
()
{
mounted
()
{
/**
/**
...
...
app/assets/javascripts/vue_shared/components/sidebar/collapsed_calendar_icon.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
import
tooltip
from
'
~/vue_shared/directives/tooltip
'
;
export
default
{
export
default
{
name
:
'
CollapsedCalendarIcon
'
,
name
:
'
CollapsedCalendarIcon
'
,
directives
:
{
directives
:
{
tooltip
,
tooltip
,
...
@@ -33,7 +33,7 @@
...
@@ -33,7 +33,7 @@
this
.
$emit
(
'
click
'
);
this
.
$emit
(
'
click
'
);
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker.vue
View file @
7e9f44fa
<
script
>
<
script
>
import
{
__
}
from
'
~/locale
'
;
import
{
__
}
from
'
~/locale
'
;
import
timeagoMixin
from
'
~/vue_shared/mixins/timeago
'
;
import
timeagoMixin
from
'
~/vue_shared/mixins/timeago
'
;
import
{
dateInWords
,
timeFor
}
from
'
~/lib/utils/datetime_utility
'
;
import
{
dateInWords
,
timeFor
}
from
'
~/lib/utils/datetime_utility
'
;
import
collapsedCalendarIcon
from
'
./collapsed_calendar_icon.vue
'
;
import
collapsedCalendarIcon
from
'
./collapsed_calendar_icon.vue
'
;
export
default
{
export
default
{
name
:
'
SidebarCollapsedGroupedDatePicker
'
,
name
:
'
SidebarCollapsedGroupedDatePicker
'
,
components
:
{
components
:
{
collapsedCalendarIcon
,
collapsedCalendarIcon
,
},
},
mixins
:
[
mixins
:
[
timeagoMixin
],
timeagoMixin
,
],
props
:
{
props
:
{
collapsed
:
{
collapsed
:
{
type
:
Boolean
,
type
:
Boolean
,
...
@@ -67,10 +65,7 @@
...
@@ -67,10 +65,7 @@
const
defaultText
=
dateType
===
'
min
'
?
__
(
'
Start date
'
)
:
__
(
'
Due date
'
);
const
defaultText
=
dateType
===
'
min
'
?
__
(
'
Start date
'
)
:
__
(
'
Due date
'
);
const
date
=
this
[
`
${
dateType
}
Date`
];
const
date
=
this
[
`
${
dateType
}
Date`
];
const
timeAgo
=
dateType
===
'
min
'
?
this
.
timeFormated
(
date
)
:
timeFor
(
date
);
const
timeAgo
=
dateType
===
'
min
'
?
this
.
timeFormated
(
date
)
:
timeFor
(
date
);
const
dateText
=
date
?
[
const
dateText
=
date
?
[
this
.
dateText
(
dateType
),
`(
${
timeAgo
}
)`
].
join
(
'
'
)
:
''
;
this
.
dateText
(
dateType
),
`(
${
timeAgo
}
)`
,
].
join
(
'
'
)
:
''
;
if
(
date
)
{
if
(
date
)
{
return
[
defaultText
,
dateText
].
join
(
'
<br />
'
);
return
[
defaultText
,
dateText
].
join
(
'
<br />
'
);
...
@@ -78,7 +73,7 @@
...
@@ -78,7 +73,7 @@
return
__
(
'
Start and due date
'
);
return
__
(
'
Start and due date
'
);
},
},
},
},
};
};
</
script
>
</
script
>
<
template
>
<
template
>
...
...
app/assets/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed.vue
View file @
7e9f44fa
...
@@ -14,7 +14,12 @@ export default {
...
@@ -14,7 +14,12 @@ export default {
},
},
computed
:
{
computed
:
{
labelsList
()
{
labelsList
()
{
const
labelsString
=
this
.
labels
.
length
?
this
.
labels
.
slice
(
0
,
5
).
map
(
label
=>
label
.
title
).
join
(
'
,
'
)
:
s__
(
'
LabelSelect|Labels
'
);
const
labelsString
=
this
.
labels
.
length
?
this
.
labels
.
slice
(
0
,
5
)
.
map
(
label
=>
label
.
title
)
.
join
(
'
,
'
)
:
s__
(
'
LabelSelect|Labels
'
);
if
(
this
.
labels
.
length
>
5
)
{
if
(
this
.
labels
.
length
>
5
)
{
return
sprintf
(
s__
(
'
LabelSelect|%{labelsString}, and %{remainingLabelCount} more
'
),
{
return
sprintf
(
s__
(
'
LabelSelect|%{labelsString}, and %{remainingLabelCount} more
'
),
{
...
...
ee/spec/javascripts/boards/models/list_spec.js
View file @
7e9f44fa
...
@@ -31,24 +31,32 @@ describe('List model', () => {
...
@@ -31,24 +31,32 @@ describe('List model', () => {
});
});
describe
(
'
getIssues
'
,
()
=>
{
describe
(
'
getIssues
'
,
()
=>
{
it
(
'
calls CE getIssues
'
,
(
done
)
=>
{
it
(
'
calls CE getIssues
'
,
done
=>
{
const
ceGetIssues
=
spyOn
(
CeList
.
prototype
,
'
getIssues
'
).
and
.
returnValue
(
Promise
.
resolve
({}));
const
ceGetIssues
=
spyOn
(
CeList
.
prototype
,
'
getIssues
'
).
and
.
returnValue
(
Promise
.
resolve
({}));
list
.
getIssues
().
then
(()
=>
{
list
.
getIssues
()
.
then
(()
=>
{
expect
(
ceGetIssues
).
toHaveBeenCalled
();
expect
(
ceGetIssues
).
toHaveBeenCalled
();
done
();
done
();
}).
catch
(
done
.
fail
);
})
.
catch
(
done
.
fail
);
});
});
it
(
'
sets total weight
'
,
(
done
)
=>
{
it
(
'
sets total weight
'
,
done
=>
{
spyOn
(
CeList
.
prototype
,
'
getIssues
'
).
and
.
returnValue
(
Promise
.
resolve
({
spyOn
(
CeList
.
prototype
,
'
getIssues
'
).
and
.
returnValue
(
Promise
.
resolve
({
total_weight
:
11
,
total_weight
:
11
,
}));
}),
);
list
.
getIssues
().
then
(()
=>
{
list
.
getIssues
()
.
then
(()
=>
{
expect
(
list
.
totalWeight
).
toBe
(
11
);
expect
(
list
.
totalWeight
).
toBe
(
11
);
done
();
done
();
}).
catch
(
done
.
fail
);
})
.
catch
(
done
.
fail
);
});
});
});
});
...
...
ee/spec/javascripts/epics/sidebar/components/sidebar_app_spec.js
View file @
7e9f44fa
...
@@ -205,10 +205,12 @@ describe('epicSidebar', () => {
...
@@ -205,10 +205,12 @@ describe('epicSidebar', () => {
Object
.
assign
({},
defaultPropsData
,
{
Object
.
assign
({},
defaultPropsData
,
{
startDateFromMilestones
:
startDateSourcingMilestoneDates
.
startDate
,
startDateFromMilestones
:
startDateSourcingMilestoneDates
.
startDate
,
dueDateFromMilestones
:
dueDateSourcingMilestoneDates
.
dueDate
,
dueDateFromMilestones
:
dueDateSourcingMilestoneDates
.
dueDate
,
})
})
,
);
);
expect
(
vmDatesFromMilestones
.
getDateFromMilestonesTooltip
(
'
start
'
)).
toBe
(
'
Milestone for Start Date<br/><span class="text-tertiary">Jan 1, 2010 – Dec 31, 2019</span>
'
);
expect
(
vmDatesFromMilestones
.
getDateFromMilestonesTooltip
(
'
start
'
)).
toBe
(
'
Milestone for Start Date<br/><span class="text-tertiary">Jan 1, 2010 – Dec 31, 2019</span>
'
,
);
vmDatesFromMilestones
.
$destroy
();
vmDatesFromMilestones
.
$destroy
();
});
});
...
@@ -229,10 +231,12 @@ describe('epicSidebar', () => {
...
@@ -229,10 +231,12 @@ describe('epicSidebar', () => {
},
},
startDateFromMilestones
:
startDate
,
startDateFromMilestones
:
startDate
,
dueDateFromMilestones
:
dueDate
,
dueDateFromMilestones
:
dueDate
,
})
})
,
);
);
expect
(
vmDatesFromMilestones
.
getDateFromMilestonesTooltip
(
'
start
'
)).
toBe
(
'
Milestone for Start Date<br/><span class="text-tertiary">Jan 1 – Mar 31, 2018</span>
'
);
expect
(
vmDatesFromMilestones
.
getDateFromMilestonesTooltip
(
'
start
'
)).
toBe
(
'
Milestone for Start Date<br/><span class="text-tertiary">Jan 1 – Mar 31, 2018</span>
'
,
);
vmDatesFromMilestones
.
$destroy
();
vmDatesFromMilestones
.
$destroy
();
});
});
...
...
ee/spec/javascripts/jobs/shared_runner_limit_block_spec.js
View file @
7e9f44fa
...
@@ -19,7 +19,9 @@ describe('Shared Runner Limit Block', () => {
...
@@ -19,7 +19,9 @@ describe('Shared Runner Limit Block', () => {
runnersPath
:
'
root/project/runners
'
,
runnersPath
:
'
root/project/runners
'
,
});
});
expect
(
vm
.
$el
.
textContent
).
toContain
(
'
You have used all your shared Runners pipeline minutes.
'
);
expect
(
vm
.
$el
.
textContent
).
toContain
(
'
You have used all your shared Runners pipeline minutes.
'
,
);
expect
(
vm
.
$el
.
textContent
).
toContain
(
'
1000 of 4000
'
);
expect
(
vm
.
$el
.
textContent
).
toContain
(
'
1000 of 4000
'
);
});
});
});
});
...
@@ -32,9 +34,10 @@ describe('Shared Runner Limit Block', () => {
...
@@ -32,9 +34,10 @@ describe('Shared Runner Limit Block', () => {
runnersPath
:
'
root/project/runners
'
,
runnersPath
:
'
root/project/runners
'
,
});
});
expect
(
trimText
(
vm
.
$el
.
textContent
)).
toContain
(
'
For more information, go to the Runners page.
'
);
expect
(
trimText
(
vm
.
$el
.
textContent
)).
toContain
(
'
For more information, go to the Runners page.
'
,
);
});
});
});
});
describe
(
'
without runnersPath
'
,
()
=>
{
describe
(
'
without runnersPath
'
,
()
=>
{
...
@@ -44,7 +47,9 @@ describe('Shared Runner Limit Block', () => {
...
@@ -44,7 +47,9 @@ describe('Shared Runner Limit Block', () => {
quotaLimit
:
4000
,
quotaLimit
:
4000
,
});
});
expect
(
trimText
(
vm
.
$el
.
textContent
)).
not
.
toContain
(
'
For more information, go to the Runners page.
'
);
expect
(
trimText
(
vm
.
$el
.
textContent
)).
not
.
toContain
(
'
For more information, go to the Runners page.
'
,
);
});
});
});
});
});
});
ee/spec/javascripts/vue_mr_widget/ee_mr_widget_options_spec.js
View file @
7e9f44fa
...
@@ -8,7 +8,12 @@ import mountComponent from 'spec/helpers/vue_mount_component_helper';
...
@@ -8,7 +8,12 @@ import mountComponent from 'spec/helpers/vue_mount_component_helper';
import
{
TEST_HOST
}
from
'
spec/test_constants
'
;
import
{
TEST_HOST
}
from
'
spec/test_constants
'
;
import
state
from
'
ee/vue_shared/security_reports/store/state
'
;
import
state
from
'
ee/vue_shared/security_reports/store/state
'
;
import
mockData
,
{
baseIssues
,
headIssues
,
basePerformance
,
headPerformance
}
from
'
spec/vue_mr_widget/mock_data
'
;
import
mockData
,
{
baseIssues
,
headIssues
,
basePerformance
,
headPerformance
,
}
from
'
spec/vue_mr_widget/mock_data
'
;
import
{
import
{
sastIssues
,
sastIssues
,
...
@@ -492,9 +497,7 @@ describe('ee merge request widget options', () => {
...
@@ -492,9 +497,7 @@ describe('ee merge request widget options', () => {
it
(
'
should render provided data
'
,
()
=>
{
it
(
'
should render provided data
'
,
()
=>
{
expect
(
expect
(
removeBreakLine
(
removeBreakLine
(
vm
.
$el
.
querySelector
(
'
.js-performance-widget .js-code-text
'
).
textContent
),
vm
.
$el
.
querySelector
(
'
.js-performance-widget .js-code-text
'
).
textContent
,
),
).
toEqual
(
'
No changes to performance metrics
'
);
).
toEqual
(
'
No changes to performance metrics
'
);
});
});
...
@@ -505,7 +508,9 @@ describe('ee merge request widget options', () => {
...
@@ -505,7 +508,9 @@ describe('ee merge request widget options', () => {
});
});
it
(
'
shows success icon
'
,
()
=>
{
it
(
'
shows success icon
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.js-performance-widget .js-ci-status-icon-success
'
)).
not
.
toBeNull
();
expect
(
vm
.
$el
.
querySelector
(
'
.js-performance-widget .js-ci-status-icon-success
'
),
).
not
.
toBeNull
();
});
});
});
});
...
...
spec/javascripts/boards/board_list_spec.js
View file @
7e9f44fa
...
@@ -18,7 +18,7 @@ describe('Board list component', () => {
...
@@ -18,7 +18,7 @@ describe('Board list component', () => {
let
mock
;
let
mock
;
let
component
;
let
component
;
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
const
el
=
document
.
createElement
(
'
div
'
);
const
el
=
document
.
createElement
(
'
div
'
);
document
.
body
.
appendChild
(
el
);
document
.
body
.
appendChild
(
el
);
...
@@ -66,27 +66,21 @@ describe('Board list component', () => {
...
@@ -66,27 +66,21 @@ describe('Board list component', () => {
});
});
it
(
'
renders component
'
,
()
=>
{
it
(
'
renders component
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
classList
.
contains
(
'
board-list-component
'
)).
toBe
(
true
);
component
.
$el
.
classList
.
contains
(
'
board-list-component
'
),
).
toBe
(
true
);
});
});
it
(
'
renders loading icon
'
,
(
done
)
=>
{
it
(
'
renders loading icon
'
,
done
=>
{
component
.
loading
=
true
;
component
.
loading
=
true
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.board-list-loading
'
)).
not
.
toBeNull
();
component
.
$el
.
querySelector
(
'
.board-list-loading
'
),
).
not
.
toBeNull
();
done
();
done
();
});
});
});
});
it
(
'
renders issues
'
,
()
=>
{
it
(
'
renders issues
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelectorAll
(
'
.board-card
'
).
length
).
toBe
(
1
);
component
.
$el
.
querySelectorAll
(
'
.board-card
'
).
length
,
).
toBe
(
1
);
});
});
it
(
'
renders link properly in issue
'
,
()
=>
{
it
(
'
renders link properly in issue
'
,
()
=>
{
...
@@ -96,98 +90,84 @@ describe('Board list component', () => {
...
@@ -96,98 +90,84 @@ describe('Board list component', () => {
});
});
it
(
'
sets data attribute with issue id
'
,
()
=>
{
it
(
'
sets data attribute with issue id
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.board-card
'
).
getAttribute
(
'
data-issue-id
'
)).
toBe
(
'
1
'
);
component
.
$el
.
querySelector
(
'
.board-card
'
).
getAttribute
(
'
data-issue-id
'
),
).
toBe
(
'
1
'
);
});
});
it
(
'
shows new issue form
'
,
(
done
)
=>
{
it
(
'
shows new issue form
'
,
done
=>
{
component
.
toggleForm
();
component
.
toggleForm
();
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.board-new-issue-form
'
)).
not
.
toBeNull
();
component
.
$el
.
querySelector
(
'
.board-new-issue-form
'
),
).
not
.
toBeNull
();
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.is-smaller
'
)).
not
.
toBeNull
();
component
.
$el
.
querySelector
(
'
.is-smaller
'
),
).
not
.
toBeNull
();
done
();
done
();
});
});
});
});
it
(
'
shows new issue form after eventhub event
'
,
(
done
)
=>
{
it
(
'
shows new issue form after eventhub event
'
,
done
=>
{
eventHub
.
$emit
(
`hide-issue-form-
${
component
.
list
.
id
}
`
);
eventHub
.
$emit
(
`hide-issue-form-
${
component
.
list
.
id
}
`
);
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.board-new-issue-form
'
)).
not
.
toBeNull
();
component
.
$el
.
querySelector
(
'
.board-new-issue-form
'
),
).
not
.
toBeNull
();
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.is-smaller
'
)).
not
.
toBeNull
();
component
.
$el
.
querySelector
(
'
.is-smaller
'
),
).
not
.
toBeNull
();
done
();
done
();
});
});
});
});
it
(
'
does not show new issue form for closed list
'
,
(
done
)
=>
{
it
(
'
does not show new issue form for closed list
'
,
done
=>
{
component
.
list
.
type
=
'
closed
'
;
component
.
list
.
type
=
'
closed
'
;
component
.
toggleForm
();
component
.
toggleForm
();
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.board-new-issue-form
'
)).
toBeNull
();
component
.
$el
.
querySelector
(
'
.board-new-issue-form
'
),
).
toBeNull
();
done
();
done
();
});
});
});
});
it
(
'
shows count list item
'
,
(
done
)
=>
{
it
(
'
shows count list item
'
,
done
=>
{
component
.
showCount
=
true
;
component
.
showCount
=
true
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.board-list-count
'
)).
not
.
toBeNull
();
component
.
$el
.
querySelector
(
'
.board-list-count
'
),
).
not
.
toBeNull
();
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.board-list-count
'
).
textContent
.
trim
()).
toBe
(
component
.
$el
.
querySelector
(
'
.board-list-count
'
).
textContent
.
trim
()
,
'
Showing all issues
'
,
)
.
toBe
(
'
Showing all issues
'
)
;
);
done
();
done
();
});
});
});
});
it
(
'
sets data attribute with invalid id
'
,
(
done
)
=>
{
it
(
'
sets data attribute with invalid id
'
,
done
=>
{
component
.
showCount
=
true
;
component
.
showCount
=
true
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.board-list-count
'
).
getAttribute
(
'
data-issue-id
'
)).
toBe
(
component
.
$el
.
querySelector
(
'
.board-list-count
'
).
getAttribute
(
'
data-issue-id
'
)
,
'
-1
'
,
)
.
toBe
(
'
-1
'
)
;
);
done
();
done
();
});
});
});
});
it
(
'
shows how many more issues to load
'
,
(
done
)
=>
{
it
(
'
shows how many more issues to load
'
,
done
=>
{
component
.
showCount
=
true
;
component
.
showCount
=
true
;
component
.
list
.
issuesSize
=
20
;
component
.
list
.
issuesSize
=
20
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.board-list-count
'
).
textContent
.
trim
()).
toBe
(
component
.
$el
.
querySelector
(
'
.board-list-count
'
).
textContent
.
trim
()
,
'
Showing 1 of 20 issues
'
,
)
.
toBe
(
'
Showing 1 of 20 issues
'
)
;
);
done
();
done
();
});
});
});
});
it
(
'
loads more issues after scrolling
'
,
(
done
)
=>
{
it
(
'
loads more issues after scrolling
'
,
done
=>
{
spyOn
(
component
.
list
,
'
nextPage
'
);
spyOn
(
component
.
list
,
'
nextPage
'
);
component
.
$refs
.
list
.
style
.
height
=
'
100px
'
;
component
.
$refs
.
list
.
style
.
height
=
'
100px
'
;
component
.
$refs
.
list
.
style
.
overflow
=
'
scroll
'
;
component
.
$refs
.
list
.
style
.
overflow
=
'
scroll
'
;
...
@@ -210,7 +190,9 @@ describe('Board list component', () => {
...
@@ -210,7 +190,9 @@ describe('Board list component', () => {
});
});
it
(
'
does not load issues if already loading
'
,
()
=>
{
it
(
'
does not load issues if already loading
'
,
()
=>
{
component
.
list
.
nextPage
=
spyOn
(
component
.
list
,
'
nextPage
'
).
and
.
returnValue
(
new
Promise
(()
=>
{}));
component
.
list
.
nextPage
=
spyOn
(
component
.
list
,
'
nextPage
'
).
and
.
returnValue
(
new
Promise
(()
=>
{}),
);
component
.
onScroll
();
component
.
onScroll
();
component
.
onScroll
();
component
.
onScroll
();
...
@@ -218,14 +200,12 @@ describe('Board list component', () => {
...
@@ -218,14 +200,12 @@ describe('Board list component', () => {
expect
(
component
.
list
.
nextPage
).
toHaveBeenCalledTimes
(
1
);
expect
(
component
.
list
.
nextPage
).
toHaveBeenCalledTimes
(
1
);
});
});
it
(
'
shows loading more spinner
'
,
(
done
)
=>
{
it
(
'
shows loading more spinner
'
,
done
=>
{
component
.
showCount
=
true
;
component
.
showCount
=
true
;
component
.
list
.
loadingMore
=
true
;
component
.
list
.
loadingMore
=
true
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.board-list-count .fa-spinner
'
)).
not
.
toBeNull
();
component
.
$el
.
querySelector
(
'
.board-list-count .fa-spinner
'
),
).
not
.
toBeNull
();
done
();
done
();
});
});
...
...
spec/javascripts/boards/components/board_spec.js
View file @
7e9f44fa
...
@@ -8,7 +8,7 @@ describe('Board component', () => {
...
@@ -8,7 +8,7 @@ describe('Board component', () => {
let
vm
;
let
vm
;
let
el
;
let
el
;
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
loadFixtures
(
'
boards/show.html.raw
'
);
loadFixtures
(
'
boards/show.html.raw
'
);
el
=
document
.
createElement
(
'
div
'
);
el
=
document
.
createElement
(
'
div
'
);
...
@@ -50,56 +50,46 @@ describe('Board component', () => {
...
@@ -50,56 +50,46 @@ describe('Board component', () => {
});
});
it
(
'
board is expandable when list type is backlog
'
,
()
=>
{
it
(
'
board is expandable when list type is backlog
'
,
()
=>
{
expect
(
expect
(
vm
.
$el
.
classList
.
contains
(
'
is-expandable
'
)).
toBe
(
true
);
vm
.
$el
.
classList
.
contains
(
'
is-expandable
'
),
).
toBe
(
true
);
});
});
it
(
'
board is expandable when list type is closed
'
,
(
done
)
=>
{
it
(
'
board is expandable when list type is closed
'
,
done
=>
{
vm
.
list
.
type
=
'
closed
'
;
vm
.
list
.
type
=
'
closed
'
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
vm
.
$el
.
classList
.
contains
(
'
is-expandable
'
)).
toBe
(
true
);
vm
.
$el
.
classList
.
contains
(
'
is-expandable
'
),
).
toBe
(
true
);
done
();
done
();
});
});
});
});
it
(
'
board is not expandable when list type is label
'
,
(
done
)
=>
{
it
(
'
board is not expandable when list type is label
'
,
done
=>
{
vm
.
list
.
type
=
'
label
'
;
vm
.
list
.
type
=
'
label
'
;
vm
.
list
.
isExpandable
=
false
;
vm
.
list
.
isExpandable
=
false
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
vm
.
$el
.
classList
.
contains
(
'
is-expandable
'
)).
toBe
(
false
);
vm
.
$el
.
classList
.
contains
(
'
is-expandable
'
),
).
toBe
(
false
);
done
();
done
();
});
});
});
});
it
(
'
collapses when clicking header
'
,
(
done
)
=>
{
it
(
'
collapses when clicking header
'
,
done
=>
{
vm
.
$el
.
querySelector
(
'
.board-header
'
).
click
();
vm
.
$el
.
querySelector
(
'
.board-header
'
).
click
();
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
vm
.
$el
.
classList
.
contains
(
'
is-collapsed
'
)).
toBe
(
true
);
vm
.
$el
.
classList
.
contains
(
'
is-collapsed
'
),
).
toBe
(
true
);
done
();
done
();
});
});
});
});
it
(
'
created sets isExpanded to true from localStorage
'
,
(
done
)
=>
{
it
(
'
created sets isExpanded to true from localStorage
'
,
done
=>
{
vm
.
$el
.
querySelector
(
'
.board-header
'
).
click
();
vm
.
$el
.
querySelector
(
'
.board-header
'
).
click
();
return
Vue
.
nextTick
()
return
Vue
.
nextTick
()
.
then
(()
=>
{
.
then
(()
=>
{
expect
(
expect
(
vm
.
$el
.
classList
.
contains
(
'
is-collapsed
'
)).
toBe
(
true
);
vm
.
$el
.
classList
.
contains
(
'
is-collapsed
'
),
).
toBe
(
true
);
// call created manually
// call created manually
vm
.
$options
.
created
[
0
].
call
(
vm
);
vm
.
$options
.
created
[
0
].
call
(
vm
);
...
@@ -107,11 +97,10 @@ describe('Board component', () => {
...
@@ -107,11 +97,10 @@ describe('Board component', () => {
return
Vue
.
nextTick
();
return
Vue
.
nextTick
();
})
})
.
then
(()
=>
{
.
then
(()
=>
{
expect
(
expect
(
vm
.
$el
.
classList
.
contains
(
'
is-collapsed
'
)).
toBe
(
true
);
vm
.
$el
.
classList
.
contains
(
'
is-collapsed
'
),
).
toBe
(
true
);
done
();
done
();
}).
catch
(
done
.
fail
);
})
.
catch
(
done
.
fail
);
});
});
});
});
spec/javascripts/boards/issue_card_spec.js
View file @
7e9f44fa
...
@@ -291,46 +291,42 @@ describe('Issue card component', () => {
...
@@ -291,46 +291,42 @@ describe('Issue card component', () => {
.
catch
(
done
.
fail
);
.
catch
(
done
.
fail
);
});
});
it
(
'
shows group labels on group boards
'
,
(
done
)
=>
{
it
(
'
shows group labels on group boards
'
,
done
=>
{
component
.
issue
.
addLabel
(
new
ListLabel
({
component
.
issue
.
addLabel
(
new
ListLabel
({
id
:
_
.
random
(
10000
),
id
:
_
.
random
(
10000
),
title
:
'
Group label
'
,
title
:
'
Group label
'
,
type
:
'
GroupLabel
'
,
type
:
'
GroupLabel
'
,
}));
}),
);
component
.
groupId
=
1
;
component
.
groupId
=
1
;
Vue
.
nextTick
()
Vue
.
nextTick
()
.
then
(()
=>
{
.
then
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelectorAll
(
'
.badge
'
).
length
).
toBe
(
3
);
component
.
$el
.
querySelectorAll
(
'
.badge
'
).
length
,
).
toBe
(
3
);
expect
(
expect
(
component
.
$el
.
textContent
).
toContain
(
'
Group label
'
);
component
.
$el
.
textContent
,
).
toContain
(
'
Group label
'
);
done
();
done
();
})
})
.
catch
(
done
.
fail
);
.
catch
(
done
.
fail
);
});
});
it
(
'
shows project labels on group boards
'
,
(
done
)
=>
{
it
(
'
shows project labels on group boards
'
,
done
=>
{
component
.
issue
.
addLabel
(
new
ListLabel
({
component
.
issue
.
addLabel
(
new
ListLabel
({
id
:
123
,
id
:
123
,
title
:
'
Project label
'
,
title
:
'
Project label
'
,
type
:
'
ProjectLabel
'
,
type
:
'
ProjectLabel
'
,
}));
}),
);
component
.
groupId
=
1
;
component
.
groupId
=
1
;
Vue
.
nextTick
()
Vue
.
nextTick
()
.
then
(()
=>
{
.
then
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelectorAll
(
'
.badge
'
).
length
).
toBe
(
3
);
component
.
$el
.
querySelectorAll
(
'
.badge
'
).
length
,
).
toBe
(
3
);
expect
(
expect
(
component
.
$el
.
textContent
).
toContain
(
'
Project label
'
);
component
.
$el
.
textContent
,
).
toContain
(
'
Project label
'
);
done
();
done
();
})
})
...
...
spec/javascripts/environments/emtpy_state_spec.js
View file @
7e9f44fa
...
@@ -24,13 +24,13 @@ describe('environments empty state', () => {
...
@@ -24,13 +24,13 @@ describe('environments empty state', () => {
});
});
it
(
'
renders empty state and new environment button
'
,
()
=>
{
it
(
'
renders empty state and new environment button
'
,
()
=>
{
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.js-blank-state-title
'
).
textContent
.
trim
()).
toEqual
(
vm
.
$el
.
querySelector
(
'
.js-blank-state-title
'
).
textContent
.
trim
()
,
"
You don't have any environments right now
"
,
)
.
toEqual
(
'
You don
\'
t have any environments right now
'
)
;
);
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.js-new-environment-button
'
).
getAttribute
(
'
href
'
)).
toEqual
(
vm
.
$el
.
querySelector
(
'
.js-new-environment-button
'
).
getAttribute
(
'
href
'
)
,
'
foo
'
,
)
.
toEqual
(
'
foo
'
)
;
);
});
});
});
});
...
@@ -44,13 +44,11 @@ describe('environments empty state', () => {
...
@@ -44,13 +44,11 @@ describe('environments empty state', () => {
});
});
it
(
'
renders empty state without new button
'
,
()
=>
{
it
(
'
renders empty state without new button
'
,
()
=>
{
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.js-blank-state-title
'
).
textContent
.
trim
()).
toEqual
(
vm
.
$el
.
querySelector
(
'
.js-blank-state-title
'
).
textContent
.
trim
()
,
"
You don't have any environments right now
"
,
)
.
toEqual
(
'
You don
\'
t have any environments right now
'
)
;
);
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.js-new-environment-button
'
)).
toBeNull
();
vm
.
$el
.
querySelector
(
'
.js-new-environment-button
'
),
).
toBeNull
();
});
});
});
});
});
});
spec/javascripts/environments/environment_item_spec.js
View file @
7e9f44fa
...
@@ -41,7 +41,9 @@ describe('Environment item', () => {
...
@@ -41,7 +41,9 @@ describe('Environment item', () => {
});
});
it
(
'
Should render the number of children in a badge
'
,
()
=>
{
it
(
'
Should render the number of children in a badge
'
,
()
=>
{
expect
(
component
.
$el
.
querySelector
(
'
.folder-name .badge
'
).
textContent
).
toContain
(
mockItem
.
size
);
expect
(
component
.
$el
.
querySelector
(
'
.folder-name .badge
'
).
textContent
).
toContain
(
mockItem
.
size
,
);
});
});
});
});
...
@@ -71,7 +73,8 @@ describe('Environment item', () => {
...
@@ -71,7 +73,8 @@ describe('Environment item', () => {
username
:
'
root
'
,
username
:
'
root
'
,
id
:
1
,
id
:
1
,
state
:
'
active
'
,
state
:
'
active
'
,
avatar_url
:
'
https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80
\
u0026d=identicon
'
,
avatar_url
:
'
https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80
\
u0026d=identicon
'
,
web_url
:
'
http://localhost:3000/root
'
,
web_url
:
'
http://localhost:3000/root
'
,
},
},
commit
:
{
commit
:
{
...
@@ -87,7 +90,8 @@ describe('Environment item', () => {
...
@@ -87,7 +90,8 @@ describe('Environment item', () => {
username
:
'
root
'
,
username
:
'
root
'
,
id
:
1
,
id
:
1
,
state
:
'
active
'
,
state
:
'
active
'
,
avatar_url
:
'
https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80
\
u0026d=identicon
'
,
avatar_url
:
'
https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80
\
u0026d=identicon
'
,
web_url
:
'
http://localhost:3000/root
'
,
web_url
:
'
http://localhost:3000/root
'
,
},
},
commit_path
:
'
/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd
'
,
commit_path
:
'
/root/ci-folders/tree/500aabcb17c97bdcf2d0c410b70cb8556f0362dd
'
,
...
@@ -127,18 +131,18 @@ describe('Environment item', () => {
...
@@ -127,18 +131,18 @@ describe('Environment item', () => {
});
});
it
(
'
should render environment name
'
,
()
=>
{
it
(
'
should render environment name
'
,
()
=>
{
expect
(
component
.
$el
.
querySelector
(
'
.environment-name
'
).
textContent
).
toContain
(
environment
.
name
);
expect
(
component
.
$el
.
querySelector
(
'
.environment-name
'
).
textContent
).
toContain
(
environment
.
name
,
);
});
});
describe
(
'
With deployment
'
,
()
=>
{
describe
(
'
With deployment
'
,
()
=>
{
it
(
'
should render deployment internal id
'
,
()
=>
{
it
(
'
should render deployment internal id
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.deployment-column span
'
).
textContent
).
toContain
(
component
.
$el
.
querySelector
(
'
.deployment-column span
'
).
textContent
,
environment
.
last_deployment
.
iid
,
)
.
toContain
(
environment
.
last_deployment
.
iid
)
;
);
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.deployment-column span
'
).
textContent
).
toContain
(
'
#
'
);
component
.
$el
.
querySelector
(
'
.deployment-column span
'
).
textContent
,
).
toContain
(
'
#
'
);
});
});
it
(
'
should render last deployment date
'
,
()
=>
{
it
(
'
should render last deployment date
'
,
()
=>
{
...
@@ -162,56 +166,46 @@ describe('Environment item', () => {
...
@@ -162,56 +166,46 @@ describe('Environment item', () => {
describe
(
'
With build url
'
,
()
=>
{
describe
(
'
With build url
'
,
()
=>
{
it
(
'
Should link to build url provided
'
,
()
=>
{
it
(
'
Should link to build url provided
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.build-link
'
).
getAttribute
(
'
href
'
)).
toEqual
(
component
.
$el
.
querySelector
(
'
.build-link
'
).
getAttribute
(
'
href
'
)
,
environment
.
last_deployment
.
deployable
.
build_path
,
)
.
toEqual
(
environment
.
last_deployment
.
deployable
.
build_path
)
;
);
});
});
it
(
'
Should render deployable name and id
'
,
()
=>
{
it
(
'
Should render deployable name and id
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.build-link
'
).
getAttribute
(
'
href
'
)).
toEqual
(
component
.
$el
.
querySelector
(
'
.build-link
'
).
getAttribute
(
'
href
'
)
,
environment
.
last_deployment
.
deployable
.
build_path
,
)
.
toEqual
(
environment
.
last_deployment
.
deployable
.
build_path
)
;
);
});
});
});
});
describe
(
'
With commit information
'
,
()
=>
{
describe
(
'
With commit information
'
,
()
=>
{
it
(
'
should render commit component
'
,
()
=>
{
it
(
'
should render commit component
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-commit-component
'
)).
toBeDefined
();
component
.
$el
.
querySelector
(
'
.js-commit-component
'
),
).
toBeDefined
();
});
});
});
});
});
});
describe
(
'
With manual actions
'
,
()
=>
{
describe
(
'
With manual actions
'
,
()
=>
{
it
(
'
Should render actions component
'
,
()
=>
{
it
(
'
Should render actions component
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-manual-actions-container
'
)).
toBeDefined
();
component
.
$el
.
querySelector
(
'
.js-manual-actions-container
'
),
).
toBeDefined
();
});
});
});
});
describe
(
'
With external URL
'
,
()
=>
{
describe
(
'
With external URL
'
,
()
=>
{
it
(
'
should render external url component
'
,
()
=>
{
it
(
'
should render external url component
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-external-url-container
'
)).
toBeDefined
();
component
.
$el
.
querySelector
(
'
.js-external-url-container
'
),
).
toBeDefined
();
});
});
});
});
describe
(
'
With stop action
'
,
()
=>
{
describe
(
'
With stop action
'
,
()
=>
{
it
(
'
Should render stop action component
'
,
()
=>
{
it
(
'
Should render stop action component
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-stop-component-container
'
)).
toBeDefined
();
component
.
$el
.
querySelector
(
'
.js-stop-component-container
'
),
).
toBeDefined
();
});
});
});
});
describe
(
'
With retry action
'
,
()
=>
{
describe
(
'
With retry action
'
,
()
=>
{
it
(
'
Should render rollback component
'
,
()
=>
{
it
(
'
Should render rollback component
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-rollback-component-container
'
)).
toBeDefined
();
component
.
$el
.
querySelector
(
'
.js-rollback-component-container
'
),
).
toBeDefined
();
});
});
});
});
});
});
...
...
spec/javascripts/environments/environment_table_spec.js
View file @
7e9f44fa
...
@@ -57,7 +57,7 @@ describe('Environment table', () => {
...
@@ -57,7 +57,7 @@ describe('Environment table', () => {
expect
(
vm
.
$el
.
querySelector
(
'
.deploy-board-icon
'
)).
not
.
toBeNull
();
expect
(
vm
.
$el
.
querySelector
(
'
.deploy-board-icon
'
)).
not
.
toBeNull
();
});
});
it
(
'
should toggle deploy board visibility when arrow is clicked
'
,
(
done
)
=>
{
it
(
'
should toggle deploy board visibility when arrow is clicked
'
,
done
=>
{
const
mockItem
=
{
const
mockItem
=
{
name
:
'
review
'
,
name
:
'
review
'
,
size
:
1
,
size
:
1
,
...
@@ -65,9 +65,7 @@ describe('Environment table', () => {
...
@@ -65,9 +65,7 @@ describe('Environment table', () => {
id
:
1
,
id
:
1
,
hasDeployBoard
:
true
,
hasDeployBoard
:
true
,
deployBoardData
:
{
deployBoardData
:
{
instances
:
[
instances
:
[{
status
:
'
ready
'
,
tooltip
:
'
foo
'
}],
{
status
:
'
ready
'
,
tooltip
:
'
foo
'
},
],
abort_url
:
'
url
'
,
abort_url
:
'
url
'
,
rollback_url
:
'
url
'
,
rollback_url
:
'
url
'
,
completion
:
100
,
completion
:
100
,
...
@@ -76,7 +74,7 @@ describe('Environment table', () => {
...
@@ -76,7 +74,7 @@ describe('Environment table', () => {
isDeployBoardVisible
:
false
,
isDeployBoardVisible
:
false
,
};
};
eventHub
.
$on
(
'
toggleDeployBoard
'
,
(
env
)
=>
{
eventHub
.
$on
(
'
toggleDeployBoard
'
,
env
=>
{
expect
(
env
.
id
).
toEqual
(
mockItem
.
id
);
expect
(
env
.
id
).
toEqual
(
mockItem
.
id
);
done
();
done
();
});
});
...
...
spec/javascripts/environments/environments_app_spec.js
View file @
7e9f44fa
...
@@ -33,7 +33,7 @@ describe('Environment', () => {
...
@@ -33,7 +33,7 @@ describe('Environment', () => {
describe
(
'
successfull request
'
,
()
=>
{
describe
(
'
successfull request
'
,
()
=>
{
describe
(
'
without environments
'
,
()
=>
{
describe
(
'
without environments
'
,
()
=>
{
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
200
,
{
environments
:
[]
});
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
200
,
{
environments
:
[]
});
component
=
mountComponent
(
EnvironmentsComponent
,
mockData
);
component
=
mountComponent
(
EnvironmentsComponent
,
mockData
);
...
@@ -44,30 +44,34 @@ describe('Environment', () => {
...
@@ -44,30 +44,34 @@ describe('Environment', () => {
});
});
it
(
'
should render the empty state
'
,
()
=>
{
it
(
'
should render the empty state
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-new-environment-button
'
).
textContent
).
toContain
(
component
.
$el
.
querySelector
(
'
.js-new-environment-button
'
).
textContent
,
'
New environment
'
,
)
.
toContain
(
'
New environment
'
)
;
);
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-blank-state-title
'
).
textContent
).
toContain
(
component
.
$el
.
querySelector
(
'
.js-blank-state-title
'
).
textContent
,
"
You don't have any environments right now
"
,
)
.
toContain
(
'
You don
\'
t have any environments right now
'
)
;
);
});
});
});
});
describe
(
'
with paginated environments
'
,
()
=>
{
describe
(
'
with paginated environments
'
,
()
=>
{
beforeEach
((
done
)
=>
{
beforeEach
(
done
=>
{
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
200
,
{
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
200
,
{
environments
:
[
environment
],
environments
:
[
environment
],
stopped_count
:
1
,
stopped_count
:
1
,
available_count
:
0
,
available_count
:
0
,
},
{
},
{
'
X-nExt-pAge
'
:
'
2
'
,
'
X-nExt-pAge
'
:
'
2
'
,
'
x-page
'
:
'
1
'
,
'
x-page
'
:
'
1
'
,
'
X-Per-Page
'
:
'
1
'
,
'
X-Per-Page
'
:
'
1
'
,
'
X-Prev-Page
'
:
''
,
'
X-Prev-Page
'
:
''
,
'
X-TOTAL
'
:
'
37
'
,
'
X-TOTAL
'
:
'
37
'
,
'
X-Total-Pages
'
:
'
2
'
,
'
X-Total-Pages
'
:
'
2
'
,
});
},
);
component
=
mountComponent
(
EnvironmentsComponent
,
mockData
);
component
=
mountComponent
(
EnvironmentsComponent
,
mockData
);
...
@@ -78,19 +82,17 @@ describe('Environment', () => {
...
@@ -78,19 +82,17 @@ describe('Environment', () => {
it
(
'
should render a table with environments
'
,
()
=>
{
it
(
'
should render a table with environments
'
,
()
=>
{
expect
(
component
.
$el
.
querySelectorAll
(
'
table
'
)).
not
.
toBeNull
();
expect
(
component
.
$el
.
querySelectorAll
(
'
table
'
)).
not
.
toBeNull
();
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.environment-name
'
).
textContent
.
trim
()).
toEqual
(
component
.
$el
.
querySelector
(
'
.environment-name
'
).
textContent
.
trim
()
,
environment
.
name
,
)
.
toEqual
(
environment
.
name
)
;
);
});
});
describe
(
'
pagination
'
,
()
=>
{
describe
(
'
pagination
'
,
()
=>
{
it
(
'
should render pagination
'
,
()
=>
{
it
(
'
should render pagination
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelectorAll
(
'
.gl-pagination li
'
).
length
).
toEqual
(
5
);
component
.
$el
.
querySelectorAll
(
'
.gl-pagination li
'
).
length
,
).
toEqual
(
5
);
});
});
it
(
'
should make an API request when page is clicked
'
,
(
done
)
=>
{
it
(
'
should make an API request when page is clicked
'
,
done
=>
{
spyOn
(
component
,
'
updateContent
'
);
spyOn
(
component
,
'
updateContent
'
);
setTimeout
(()
=>
{
setTimeout
(()
=>
{
component
.
$el
.
querySelector
(
'
.gl-pagination li:nth-child(5) a
'
).
click
();
component
.
$el
.
querySelector
(
'
.gl-pagination li:nth-child(5) a
'
).
click
();
...
@@ -100,7 +102,7 @@ describe('Environment', () => {
...
@@ -100,7 +102,7 @@ describe('Environment', () => {
},
0
);
},
0
);
});
});
it
(
'
should make an API request when using tabs
'
,
(
done
)
=>
{
it
(
'
should make an API request when using tabs
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
spyOn
(
component
,
'
updateContent
'
);
spyOn
(
component
,
'
updateContent
'
);
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped
'
).
click
();
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped
'
).
click
();
...
@@ -112,9 +114,11 @@ describe('Environment', () => {
...
@@ -112,9 +114,11 @@ describe('Environment', () => {
});
});
describe
(
'
deploy boards
'
,
()
=>
{
describe
(
'
deploy boards
'
,
()
=>
{
it
(
'
should render arrow to open deploy boards
'
,
(
done
)
=>
{
it
(
'
should render arrow to open deploy boards
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
expect
(
component
.
$el
.
querySelector
(
'
.deploy-board-icon.ic-chevron-right
'
)).
toBeDefined
();
expect
(
component
.
$el
.
querySelector
(
'
.deploy-board-icon.ic-chevron-right
'
),
).
toBeDefined
();
done
();
done
();
},
0
);
},
0
);
});
});
...
@@ -123,7 +127,7 @@ describe('Environment', () => {
...
@@ -123,7 +127,7 @@ describe('Environment', () => {
});
});
describe
(
'
unsuccessfull request
'
,
()
=>
{
describe
(
'
unsuccessfull request
'
,
()
=>
{
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
500
,
{});
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
500
,
{});
component
=
mountComponent
(
EnvironmentsComponent
,
mockData
);
component
=
mountComponent
(
EnvironmentsComponent
,
mockData
);
...
@@ -134,15 +138,16 @@ describe('Environment', () => {
...
@@ -134,15 +138,16 @@ describe('Environment', () => {
});
});
it
(
'
should render empty state
'
,
()
=>
{
it
(
'
should render empty state
'
,
()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-blank-state-title
'
).
textContent
).
toContain
(
component
.
$el
.
querySelector
(
'
.js-blank-state-title
'
).
textContent
,
"
You don't have any environments right now
"
,
)
.
toContain
(
'
You don
\'
t have any environments right now
'
)
;
);
});
});
});
});
describe
(
'
expandable folders
'
,
()
=>
{
describe
(
'
expandable folders
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
200
,
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
200
,
{
{
environments
:
[
folder
],
environments
:
[
folder
],
stopped_count
:
0
,
stopped_count
:
0
,
...
@@ -163,7 +168,7 @@ describe('Environment', () => {
...
@@ -163,7 +168,7 @@ describe('Environment', () => {
component
=
mountComponent
(
EnvironmentsComponent
,
mockData
);
component
=
mountComponent
(
EnvironmentsComponent
,
mockData
);
});
});
it
(
'
should open a closed folder
'
,
(
done
)
=>
{
it
(
'
should open a closed folder
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
component
.
$el
.
querySelector
(
'
.folder-name
'
).
click
();
component
.
$el
.
querySelector
(
'
.folder-name
'
).
click
();
...
@@ -174,7 +179,7 @@ describe('Environment', () => {
...
@@ -174,7 +179,7 @@ describe('Environment', () => {
},
0
);
},
0
);
});
});
it
(
'
should close an opened folder
'
,
(
done
)
=>
{
it
(
'
should close an opened folder
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
// open folder
// open folder
component
.
$el
.
querySelector
(
'
.folder-name
'
).
click
();
component
.
$el
.
querySelector
(
'
.folder-name
'
).
click
();
...
@@ -191,7 +196,7 @@ describe('Environment', () => {
...
@@ -191,7 +196,7 @@ describe('Environment', () => {
},
0
);
},
0
);
});
});
it
(
'
should show children environments and a button to show all environments
'
,
(
done
)
=>
{
it
(
'
should show children environments and a button to show all environments
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
// open folder
// open folder
component
.
$el
.
querySelector
(
'
.folder-name
'
).
click
();
component
.
$el
.
querySelector
(
'
.folder-name
'
).
click
();
...
@@ -200,7 +205,9 @@ describe('Environment', () => {
...
@@ -200,7 +205,9 @@ describe('Environment', () => {
// wait for next async request
// wait for next async request
setTimeout
(()
=>
{
setTimeout
(()
=>
{
expect
(
component
.
$el
.
querySelectorAll
(
'
.js-child-row
'
).
length
).
toEqual
(
1
);
expect
(
component
.
$el
.
querySelectorAll
(
'
.js-child-row
'
).
length
).
toEqual
(
1
);
expect
(
component
.
$el
.
querySelector
(
'
.text-center > a.btn
'
).
textContent
).
toContain
(
'
Show all
'
);
expect
(
component
.
$el
.
querySelector
(
'
.text-center > a.btn
'
).
textContent
).
toContain
(
'
Show all
'
,
);
done
();
done
();
});
});
});
});
...
@@ -210,7 +217,8 @@ describe('Environment', () => {
...
@@ -210,7 +217,8 @@ describe('Environment', () => {
describe
(
'
methods
'
,
()
=>
{
describe
(
'
methods
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
200
,
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
200
,
{
{
environments
:
[],
environments
:
[],
stopped_count
:
0
,
stopped_count
:
0
,
...
@@ -224,8 +232,9 @@ describe('Environment', () => {
...
@@ -224,8 +232,9 @@ describe('Environment', () => {
});
});
describe
(
'
updateContent
'
,
()
=>
{
describe
(
'
updateContent
'
,
()
=>
{
it
(
'
should set given parameters
'
,
(
done
)
=>
{
it
(
'
should set given parameters
'
,
done
=>
{
component
.
updateContent
({
scope
:
'
stopped
'
,
page
:
'
3
'
})
component
.
updateContent
({
scope
:
'
stopped
'
,
page
:
'
3
'
})
.
then
(()
=>
{
.
then
(()
=>
{
expect
(
component
.
page
).
toEqual
(
'
3
'
);
expect
(
component
.
page
).
toEqual
(
'
3
'
);
expect
(
component
.
scope
).
toEqual
(
'
stopped
'
);
expect
(
component
.
scope
).
toEqual
(
'
stopped
'
);
...
...
spec/javascripts/environments/folder/environments_folder_view_spec.js
View file @
7e9f44fa
...
@@ -32,37 +32,41 @@ describe('Environments Folder View', () => {
...
@@ -32,37 +32,41 @@ describe('Environments Folder View', () => {
describe
(
'
successfull request
'
,
()
=>
{
describe
(
'
successfull request
'
,
()
=>
{
beforeEach
(()
=>
{
beforeEach
(()
=>
{
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
200
,
{
mock
.
onGet
(
mockData
.
endpoint
).
reply
(
200
,
{
environments
:
environmentsList
,
environments
:
environmentsList
,
stopped_count
:
1
,
stopped_count
:
1
,
available_count
:
0
,
available_count
:
0
,
},
{
},
{
'
X-nExt-pAge
'
:
'
2
'
,
'
X-nExt-pAge
'
:
'
2
'
,
'
x-page
'
:
'
1
'
,
'
x-page
'
:
'
1
'
,
'
X-Per-Page
'
:
'
2
'
,
'
X-Per-Page
'
:
'
2
'
,
'
X-Prev-Page
'
:
''
,
'
X-Prev-Page
'
:
''
,
'
X-TOTAL
'
:
'
20
'
,
'
X-TOTAL
'
:
'
20
'
,
'
X-Total-Pages
'
:
'
10
'
,
'
X-Total-Pages
'
:
'
10
'
,
});
},
);
component
=
mountComponent
(
Component
,
mockData
);
component
=
mountComponent
(
Component
,
mockData
);
});
});
it
(
'
should render a table with environments
'
,
(
done
)
=>
{
it
(
'
should render a table with environments
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
expect
(
component
.
$el
.
querySelectorAll
(
'
table
'
)).
not
.
toBeNull
();
expect
(
component
.
$el
.
querySelectorAll
(
'
table
'
)).
not
.
toBeNull
();
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.environment-name
'
).
textContent
.
trim
()).
toEqual
(
component
.
$el
.
querySelector
(
'
.environment-name
'
).
textContent
.
trim
()
,
environmentsList
[
0
].
name
,
)
.
toEqual
(
environmentsList
[
0
].
name
)
;
);
done
();
done
();
},
0
);
},
0
);
});
});
it
(
'
should render available tab with count
'
,
(
done
)
=>
{
it
(
'
should render available tab with count
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-available
'
).
textContent
).
toContain
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-available
'
).
textContent
,
'
Available
'
,
)
.
toContain
(
'
Available
'
)
;
);
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-available .badge
'
).
textContent
,
component
.
$el
.
querySelector
(
'
.js-environments-tab-available .badge
'
).
textContent
,
...
@@ -71,11 +75,11 @@ describe('Environments Folder View', () => {
...
@@ -71,11 +75,11 @@ describe('Environments Folder View', () => {
},
0
);
},
0
);
});
});
it
(
'
should render stopped tab with count
'
,
(
done
)
=>
{
it
(
'
should render stopped tab with count
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped
'
).
textContent
).
toContain
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped
'
).
textContent
,
'
Stopped
'
,
)
.
toContain
(
'
Stopped
'
)
;
);
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped .badge
'
).
textContent
,
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped .badge
'
).
textContent
,
...
@@ -84,36 +88,37 @@ describe('Environments Folder View', () => {
...
@@ -84,36 +88,37 @@ describe('Environments Folder View', () => {
},
0
);
},
0
);
});
});
it
(
'
should render parent folder name
'
,
(
done
)
=>
{
it
(
'
should render parent folder name
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-folder-name
'
).
textContent
).
toContain
(
component
.
$el
.
querySelector
(
'
.js-folder-name
'
).
textContent
,
'
Environments / review
'
,
)
.
toContain
(
'
Environments / review
'
)
;
);
done
();
done
();
},
0
);
},
0
);
});
});
describe
(
'
pagination
'
,
()
=>
{
describe
(
'
pagination
'
,
()
=>
{
it
(
'
should render pagination
'
,
(
done
)
=>
{
it
(
'
should render pagination
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelectorAll
(
'
.gl-pagination
'
)).
not
.
toBeNull
();
component
.
$el
.
querySelectorAll
(
'
.gl-pagination
'
),
).
not
.
toBeNull
();
done
();
done
();
},
0
);
},
0
);
});
});
it
(
'
should make an API request when changing page
'
,
(
done
)
=>
{
it
(
'
should make an API request when changing page
'
,
done
=>
{
spyOn
(
component
,
'
updateContent
'
);
spyOn
(
component
,
'
updateContent
'
);
setTimeout
(()
=>
{
setTimeout
(()
=>
{
component
.
$el
.
querySelector
(
'
.gl-pagination .js-last-button a
'
).
click
();
component
.
$el
.
querySelector
(
'
.gl-pagination .js-last-button a
'
).
click
();
expect
(
component
.
updateContent
).
toHaveBeenCalledWith
({
scope
:
component
.
scope
,
page
:
'
10
'
});
expect
(
component
.
updateContent
).
toHaveBeenCalledWith
({
scope
:
component
.
scope
,
page
:
'
10
'
,
});
done
();
done
();
},
0
);
},
0
);
});
});
it
(
'
should make an API request when using tabs
'
,
(
done
)
=>
{
it
(
'
should make an API request when using tabs
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
spyOn
(
component
,
'
updateContent
'
);
spyOn
(
component
,
'
updateContent
'
);
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped
'
).
click
();
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped
'
).
click
();
...
@@ -125,7 +130,7 @@ describe('Environments Folder View', () => {
...
@@ -125,7 +130,7 @@ describe('Environments Folder View', () => {
});
});
describe
(
'
deploy boards
'
,
()
=>
{
describe
(
'
deploy boards
'
,
()
=>
{
it
(
'
should render arrow to open deploy boards
'
,
(
done
)
=>
{
it
(
'
should render arrow to open deploy boards
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
expect
(
component
.
$el
.
querySelector
(
'
.folder-icon.ic-chevron-right
'
)).
not
.
toBeNull
();
expect
(
component
.
$el
.
querySelector
(
'
.folder-icon.ic-chevron-right
'
)).
not
.
toBeNull
();
done
();
done
();
...
@@ -143,20 +148,18 @@ describe('Environments Folder View', () => {
...
@@ -143,20 +148,18 @@ describe('Environments Folder View', () => {
component
=
mountComponent
(
Component
,
mockData
);
component
=
mountComponent
(
Component
,
mockData
);
});
});
it
(
'
should not render a table
'
,
(
done
)
=>
{
it
(
'
should not render a table
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
table
'
)).
toBe
(
null
);
component
.
$el
.
querySelector
(
'
table
'
),
).
toBe
(
null
);
done
();
done
();
},
0
);
},
0
);
});
});
it
(
'
should render available tab with count 0
'
,
(
done
)
=>
{
it
(
'
should render available tab with count 0
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-available
'
).
textContent
).
toContain
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-available
'
).
textContent
,
'
Available
'
,
)
.
toContain
(
'
Available
'
)
;
);
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-available .badge
'
).
textContent
,
component
.
$el
.
querySelector
(
'
.js-environments-tab-available .badge
'
).
textContent
,
...
@@ -165,11 +168,11 @@ describe('Environments Folder View', () => {
...
@@ -165,11 +168,11 @@ describe('Environments Folder View', () => {
},
0
);
},
0
);
});
});
it
(
'
should render stopped tab with count 0
'
,
(
done
)
=>
{
it
(
'
should render stopped tab with count 0
'
,
done
=>
{
setTimeout
(()
=>
{
setTimeout
(()
=>
{
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped
'
).
textContent
).
toContain
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped
'
).
textContent
,
'
Stopped
'
,
)
.
toContain
(
'
Stopped
'
)
;
);
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped .badge
'
).
textContent
,
component
.
$el
.
querySelector
(
'
.js-environments-tab-stopped .badge
'
).
textContent
,
...
@@ -190,8 +193,9 @@ describe('Environments Folder View', () => {
...
@@ -190,8 +193,9 @@ describe('Environments Folder View', () => {
});
});
describe
(
'
updateContent
'
,
()
=>
{
describe
(
'
updateContent
'
,
()
=>
{
it
(
'
should set given parameters
'
,
(
done
)
=>
{
it
(
'
should set given parameters
'
,
done
=>
{
component
.
updateContent
({
scope
:
'
stopped
'
,
page
:
'
4
'
})
component
.
updateContent
({
scope
:
'
stopped
'
,
page
:
'
4
'
})
.
then
(()
=>
{
.
then
(()
=>
{
expect
(
component
.
page
).
toEqual
(
'
4
'
);
expect
(
component
.
page
).
toEqual
(
'
4
'
);
expect
(
component
.
scope
).
toEqual
(
'
stopped
'
);
expect
(
component
.
scope
).
toEqual
(
'
stopped
'
);
...
...
spec/javascripts/issue_show/components/title_spec.js
View file @
7e9f44fa
...
@@ -25,25 +25,21 @@ describe('Title component', () => {
...
@@ -25,25 +25,21 @@ describe('Title component', () => {
});
});
it
(
'
renders title HTML
'
,
()
=>
{
it
(
'
renders title HTML
'
,
()
=>
{
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.title
'
).
innerHTML
.
trim
()).
toBe
(
'
Testing <img>
'
);
vm
.
$el
.
querySelector
(
'
.title
'
).
innerHTML
.
trim
(),
).
toBe
(
'
Testing <img>
'
);
});
});
it
(
'
updates page title when changing titleHtml
'
,
(
done
)
=>
{
it
(
'
updates page title when changing titleHtml
'
,
done
=>
{
spyOn
(
vm
,
'
setPageTitle
'
);
spyOn
(
vm
,
'
setPageTitle
'
);
vm
.
titleHtml
=
'
test
'
;
vm
.
titleHtml
=
'
test
'
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
vm
.
setPageTitle
).
toHaveBeenCalled
();
vm
.
setPageTitle
,
).
toHaveBeenCalled
();
done
();
done
();
});
});
});
});
it
(
'
animates title changes
'
,
(
done
)
=>
{
it
(
'
animates title changes
'
,
done
=>
{
vm
.
titleHtml
=
'
test
'
;
vm
.
titleHtml
=
'
test
'
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
...
@@ -61,14 +57,12 @@ describe('Title component', () => {
...
@@ -61,14 +57,12 @@ describe('Title component', () => {
});
});
});
});
it
(
'
updates page title after changing title
'
,
(
done
)
=>
{
it
(
'
updates page title after changing title
'
,
done
=>
{
vm
.
titleHtml
=
'
changed
'
;
vm
.
titleHtml
=
'
changed
'
;
vm
.
titleText
=
'
changed
'
;
vm
.
titleText
=
'
changed
'
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
expect
(
document
.
querySelector
(
'
title
'
).
textContent
.
trim
()).
toContain
(
'
changed
'
);
document
.
querySelector
(
'
title
'
).
textContent
.
trim
(),
).
toContain
(
'
changed
'
);
done
();
done
();
});
});
...
...
spec/javascripts/jobs/components/job_app_spec.js
View file @
7e9f44fa
...
@@ -234,7 +234,7 @@ describe('Job App ', () => {
...
@@ -234,7 +234,7 @@ describe('Job App ', () => {
);
);
done
();
done
();
},
0
);
},
0
);
})
})
;
});
});
it
(
'
does not renders stuck block when there are no runners
'
,
done
=>
{
it
(
'
does not renders stuck block when there are no runners
'
,
done
=>
{
...
...
spec/javascripts/jobs/store/actions_spec.js
View file @
7e9f44fa
...
@@ -68,41 +68,20 @@ describe('Job State actions', () => {
...
@@ -68,41 +68,20 @@ describe('Job State actions', () => {
describe
(
'
hideSidebar
'
,
()
=>
{
describe
(
'
hideSidebar
'
,
()
=>
{
it
(
'
should commit HIDE_SIDEBAR mutation
'
,
done
=>
{
it
(
'
should commit HIDE_SIDEBAR mutation
'
,
done
=>
{
testAction
(
testAction
(
hideSidebar
,
null
,
mockedState
,
[{
type
:
types
.
HIDE_SIDEBAR
}],
[],
done
);
hideSidebar
,
null
,
mockedState
,
[{
type
:
types
.
HIDE_SIDEBAR
}],
[],
done
,
);
});
});
});
});
describe
(
'
showSidebar
'
,
()
=>
{
describe
(
'
showSidebar
'
,
()
=>
{
it
(
'
should commit HIDE_SIDEBAR mutation
'
,
done
=>
{
it
(
'
should commit HIDE_SIDEBAR mutation
'
,
done
=>
{
testAction
(
testAction
(
showSidebar
,
null
,
mockedState
,
[{
type
:
types
.
SHOW_SIDEBAR
}],
[],
done
);
showSidebar
,
null
,
mockedState
,
[{
type
:
types
.
SHOW_SIDEBAR
}],
[],
done
,
);
});
});
});
});
describe
(
'
toggleSidebar
'
,
()
=>
{
describe
(
'
toggleSidebar
'
,
()
=>
{
describe
(
'
when isSidebarOpen is true
'
,
()
=>
{
describe
(
'
when isSidebarOpen is true
'
,
()
=>
{
it
(
'
should dispatch hideSidebar
'
,
done
=>
{
it
(
'
should dispatch hideSidebar
'
,
done
=>
{
testAction
(
testAction
(
toggleSidebar
,
null
,
mockedState
,
[],
[{
type
:
'
hideSidebar
'
}],
done
);
toggleSidebar
,
null
,
mockedState
,
[],
[{
type
:
'
hideSidebar
'
}],
done
,
);
});
});
});
});
...
@@ -110,14 +89,7 @@ describe('Job State actions', () => {
...
@@ -110,14 +89,7 @@ describe('Job State actions', () => {
it
(
'
should dispatch showSidebar
'
,
done
=>
{
it
(
'
should dispatch showSidebar
'
,
done
=>
{
mockedState
.
isSidebarOpen
=
false
;
mockedState
.
isSidebarOpen
=
false
;
testAction
(
testAction
(
toggleSidebar
,
null
,
mockedState
,
[],
[{
type
:
'
showSidebar
'
}],
done
);
toggleSidebar
,
null
,
mockedState
,
[],
[{
type
:
'
showSidebar
'
}],
done
,
);
});
});
});
});
});
});
...
...
spec/javascripts/jobs/store/getters_spec.js
View file @
7e9f44fa
...
@@ -235,7 +235,7 @@ describe('Job Store Getters', () => {
...
@@ -235,7 +235,7 @@ describe('Job Store Getters', () => {
it
(
'
returns true
'
,
()
=>
{
it
(
'
returns true
'
,
()
=>
{
localState
.
job
.
runners
=
{
localState
.
job
.
runners
=
{
available
:
true
,
available
:
true
,
online
:
false
online
:
false
,
};
};
expect
(
getters
.
hasRunnersForProject
(
localState
)).
toEqual
(
true
);
expect
(
getters
.
hasRunnersForProject
(
localState
)).
toEqual
(
true
);
...
@@ -246,7 +246,7 @@ describe('Job Store Getters', () => {
...
@@ -246,7 +246,7 @@ describe('Job Store Getters', () => {
it
(
'
returns false
'
,
()
=>
{
it
(
'
returns false
'
,
()
=>
{
localState
.
job
.
runners
=
{
localState
.
job
.
runners
=
{
available
:
false
,
available
:
false
,
online
:
false
online
:
false
,
};
};
expect
(
getters
.
hasRunnersForProject
(
localState
)).
toEqual
(
false
);
expect
(
getters
.
hasRunnersForProject
(
localState
)).
toEqual
(
false
);
...
@@ -257,7 +257,7 @@ describe('Job Store Getters', () => {
...
@@ -257,7 +257,7 @@ describe('Job Store Getters', () => {
it
(
'
returns false
'
,
()
=>
{
it
(
'
returns false
'
,
()
=>
{
localState
.
job
.
runners
=
{
localState
.
job
.
runners
=
{
available
:
false
,
available
:
false
,
online
:
true
online
:
true
,
};
};
expect
(
getters
.
hasRunnersForProject
(
localState
)).
toEqual
(
false
);
expect
(
getters
.
hasRunnersForProject
(
localState
)).
toEqual
(
false
);
...
...
spec/javascripts/lib/utils/common_utils_spec.js
View file @
7e9f44fa
This diff is collapsed.
Click to expand it.
spec/javascripts/monitoring/graph/flag_spec.js
View file @
7e9f44fa
...
@@ -2,7 +2,7 @@ import Vue from 'vue';
...
@@ -2,7 +2,7 @@ import Vue from 'vue';
import
GraphFlag
from
'
~/monitoring/components/graph/flag.vue
'
;
import
GraphFlag
from
'
~/monitoring/components/graph/flag.vue
'
;
import
{
deploymentData
}
from
'
../mock_data
'
;
import
{
deploymentData
}
from
'
../mock_data
'
;
const
createComponent
=
(
propsData
)
=>
{
const
createComponent
=
propsData
=>
{
const
Component
=
Vue
.
extend
(
GraphFlag
);
const
Component
=
Vue
.
extend
(
GraphFlag
);
return
new
Component
({
return
new
Component
({
...
@@ -51,8 +51,7 @@ describe('GraphFlag', () => {
...
@@ -51,8 +51,7 @@ describe('GraphFlag', () => {
it
(
'
has a line at the currentXCoordinate
'
,
()
=>
{
it
(
'
has a line at the currentXCoordinate
'
,
()
=>
{
component
=
createComponent
(
defaultValuesComponent
);
component
=
createComponent
(
defaultValuesComponent
);
expect
(
component
.
$el
.
style
.
left
)
expect
(
component
.
$el
.
style
.
left
).
toEqual
(
`
${
70
+
component
.
currentXCoordinate
}
px`
);
.
toEqual
(
`
${
70
+
component
.
currentXCoordinate
}
px`
);
});
});
describe
(
'
Deployment flag
'
,
()
=>
{
describe
(
'
Deployment flag
'
,
()
=>
{
...
@@ -62,9 +61,9 @@ describe('GraphFlag', () => {
...
@@ -62,9 +61,9 @@ describe('GraphFlag', () => {
deploymentFlagData
,
deploymentFlagData
,
});
});
expect
(
expect
(
deploymentFlagComponent
.
$el
.
querySelector
(
'
.popover-header
'
)).
toContainText
(
deploymentFlagComponent
.
$el
.
querySelector
(
'
.popover-header
'
)
,
'
Deployed
'
,
)
.
toContainText
(
'
Deployed
'
)
;
);
});
});
it
(
'
contains the ref when a tag is available
'
,
()
=>
{
it
(
'
contains the ref when a tag is available
'
,
()
=>
{
...
@@ -78,13 +77,13 @@ describe('GraphFlag', () => {
...
@@ -78,13 +77,13 @@ describe('GraphFlag', () => {
},
},
});
});
expect
(
expect
(
deploymentFlagComponent
.
$el
.
querySelector
(
'
.deploy-meta-content
'
)).
toContainText
(
deploymentFlagComponent
.
$el
.
querySelector
(
'
.deploy-meta-content
'
)
,
'
f5bcd1d9
'
,
)
.
toContainText
(
'
f5bcd1d9
'
)
;
);
expect
(
expect
(
deploymentFlagComponent
.
$el
.
querySelector
(
'
.deploy-meta-content
'
)).
toContainText
(
deploymentFlagComponent
.
$el
.
querySelector
(
'
.deploy-meta-content
'
)
,
'
1.0
'
,
)
.
toContainText
(
'
1.0
'
)
;
);
});
});
it
(
'
does not contain the ref when a tag is unavailable
'
,
()
=>
{
it
(
'
does not contain the ref when a tag is unavailable
'
,
()
=>
{
...
@@ -98,13 +97,13 @@ describe('GraphFlag', () => {
...
@@ -98,13 +97,13 @@ describe('GraphFlag', () => {
},
},
});
});
expect
(
expect
(
deploymentFlagComponent
.
$el
.
querySelector
(
'
.deploy-meta-content
'
)).
toContainText
(
deploymentFlagComponent
.
$el
.
querySelector
(
'
.deploy-meta-content
'
)
,
'
f5bcd1d9
'
,
)
.
toContainText
(
'
f5bcd1d9
'
)
;
);
expect
(
expect
(
deploymentFlagComponent
.
$el
.
querySelector
(
'
.deploy-meta-content
'
)).
not
.
toContainText
(
deploymentFlagComponent
.
$el
.
querySelector
(
'
.deploy-meta-content
'
)
,
'
1.0
'
,
)
.
not
.
toContainText
(
'
1.0
'
)
;
);
});
});
});
});
...
...
spec/javascripts/notes/components/discussion_filter_spec.js
View file @
7e9f44fa
...
@@ -11,11 +11,13 @@ describe('DiscussionFilter component', () => {
...
@@ -11,11 +11,13 @@ describe('DiscussionFilter component', () => {
beforeEach
(()
=>
{
beforeEach
(()
=>
{
store
=
createStore
();
store
=
createStore
();
const
discussions
=
[{
const
discussions
=
[
{
...
discussionMock
,
...
discussionMock
,
id
:
discussionMock
.
id
,
id
:
discussionMock
.
id
,
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolvable
:
true
,
resolved
:
true
}],
notes
:
[{
...
discussionMock
.
notes
[
0
],
resolvable
:
true
,
resolved
:
true
}],
}];
},
];
const
Component
=
Vue
.
extend
(
DiscussionFilter
);
const
Component
=
Vue
.
extend
(
DiscussionFilter
);
const
defaultValue
=
discussionFiltersMock
[
0
].
value
;
const
defaultValue
=
discussionFiltersMock
[
0
].
value
;
...
@@ -35,11 +37,15 @@ describe('DiscussionFilter component', () => {
...
@@ -35,11 +37,15 @@ describe('DiscussionFilter component', () => {
});
});
it
(
'
renders the all filters
'
,
()
=>
{
it
(
'
renders the all filters
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelectorAll
(
'
.dropdown-menu li
'
).
length
).
toEqual
(
discussionFiltersMock
.
length
);
expect
(
vm
.
$el
.
querySelectorAll
(
'
.dropdown-menu li
'
).
length
).
toEqual
(
discussionFiltersMock
.
length
,
);
});
});
it
(
'
renders the default selected item
'
,
()
=>
{
it
(
'
renders the default selected item
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
#discussion-filter-dropdown
'
).
textContent
.
trim
()).
toEqual
(
discussionFiltersMock
[
0
].
title
);
expect
(
vm
.
$el
.
querySelector
(
'
#discussion-filter-dropdown
'
).
textContent
.
trim
()).
toEqual
(
discussionFiltersMock
[
0
].
title
,
);
});
});
it
(
'
updates to the selected item
'
,
()
=>
{
it
(
'
updates to the selected item
'
,
()
=>
{
...
...
spec/javascripts/notes/components/note_app_spec.js
View file @
7e9f44fa
...
@@ -97,7 +97,8 @@ describe('note_app', () => {
...
@@ -97,7 +97,8 @@ describe('note_app', () => {
});
});
it
(
'
should render list of notes
'
,
done
=>
{
it
(
'
should render list of notes
'
,
done
=>
{
const
note
=
mockData
.
INDIVIDUAL_NOTE_RESPONSE_MAP
.
GET
[
const
note
=
mockData
.
INDIVIDUAL_NOTE_RESPONSE_MAP
.
GET
[
'
/gitlab-org/gitlab-ce/issues/26/discussions.json
'
'
/gitlab-org/gitlab-ce/issues/26/discussions.json
'
][
0
].
notes
[
0
];
][
0
].
notes
[
0
];
...
...
spec/javascripts/pipelines/graph/graph_component_spec.js
View file @
7e9f44fa
...
@@ -28,83 +28,89 @@ describe('graph component', () => {
...
@@ -28,83 +28,89 @@ describe('graph component', () => {
});
});
});
});
describe
(
'
when linked pipelines are present
'
,
function
()
{
describe
(
'
when linked pipelines are present
'
,
function
()
{
beforeEach
(
function
()
{
beforeEach
(
function
()
{
component
=
mountComponent
(
GraphComponent
,
{
component
=
mountComponent
(
GraphComponent
,
{
isLoading
:
false
,
isLoading
:
false
,
pipeline
:
graphJSON
,
pipeline
:
graphJSON
,
});
});
});
});
describe
(
'
rendered output
'
,
function
()
{
describe
(
'
rendered output
'
,
function
()
{
it
(
'
should include the pipelines graph
'
,
function
()
{
it
(
'
should include the pipelines graph
'
,
function
()
{
expect
(
component
.
$el
.
classList
.
contains
(
'
js-pipeline-graph
'
)).
toEqual
(
true
);
expect
(
component
.
$el
.
classList
.
contains
(
'
js-pipeline-graph
'
)).
toEqual
(
true
);
});
});
it
(
'
should not include the loading icon
'
,
function
()
{
it
(
'
should not include the loading icon
'
,
function
()
{
expect
(
component
.
$el
.
querySelector
(
'
.fa-spinner
'
)).
toBeNull
();
expect
(
component
.
$el
.
querySelector
(
'
.fa-spinner
'
)).
toBeNull
();
});
});
it
(
'
should include the stage column list
'
,
function
()
{
it
(
'
should include the stage column list
'
,
function
()
{
expect
(
component
.
$el
.
querySelector
(
'
.stage-column-list
'
)).
not
.
toBeNull
();
expect
(
component
.
$el
.
querySelector
(
'
.stage-column-list
'
)).
not
.
toBeNull
();
});
});
it
(
'
should include the no-margin class on the first child
'
,
function
()
{
it
(
'
should include the no-margin class on the first child
'
,
function
()
{
const
firstStageColumnElement
=
component
.
$el
.
querySelector
(
'
.stage-column-list .stage-column
'
);
const
firstStageColumnElement
=
component
.
$el
.
querySelector
(
'
.stage-column-list .stage-column
'
,
);
expect
(
firstStageColumnElement
.
classList
.
contains
(
'
no-margin
'
)).
toEqual
(
true
);
expect
(
firstStageColumnElement
.
classList
.
contains
(
'
no-margin
'
)).
toEqual
(
true
);
});
});
it
(
'
should include the has-only-one-job class on the first child
'
,
function
()
{
it
(
'
should include the has-only-one-job class on the first child
'
,
function
()
{
const
firstStageColumnElement
=
component
.
$el
.
querySelector
(
'
.stage-column-list .stage-column
'
);
const
firstStageColumnElement
=
component
.
$el
.
querySelector
(
'
.stage-column-list .stage-column
'
,
);
expect
(
firstStageColumnElement
.
classList
.
contains
(
'
has-only-one-job
'
)).
toEqual
(
true
);
expect
(
firstStageColumnElement
.
classList
.
contains
(
'
has-only-one-job
'
)).
toEqual
(
true
);
});
});
it
(
'
should include the left-margin class on the second child
'
,
function
()
{
it
(
'
should include the left-margin class on the second child
'
,
function
()
{
const
firstStageColumnElement
=
component
.
$el
.
querySelector
(
'
.stage-column-list .stage-column:last-child
'
);
const
firstStageColumnElement
=
component
.
$el
.
querySelector
(
'
.stage-column-list .stage-column:last-child
'
,
);
expect
(
firstStageColumnElement
.
classList
.
contains
(
'
left-margin
'
)).
toEqual
(
true
);
expect
(
firstStageColumnElement
.
classList
.
contains
(
'
left-margin
'
)).
toEqual
(
true
);
});
});
it
(
'
should include the has-linked-pipelines flag
'
,
function
()
{
it
(
'
should include the has-linked-pipelines flag
'
,
function
()
{
expect
(
component
.
$el
.
querySelector
(
'
.has-linked-pipelines
'
)).
not
.
toBeNull
();
expect
(
component
.
$el
.
querySelector
(
'
.has-linked-pipelines
'
)).
not
.
toBeNull
();
});
});
});
});
describe
(
'
computeds and methods
'
,
function
()
{
describe
(
'
computeds and methods
'
,
function
()
{
describe
(
'
capitalizeStageName
'
,
function
()
{
describe
(
'
capitalizeStageName
'
,
function
()
{
it
(
'
it capitalizes the stage name
'
,
function
()
{
it
(
'
it capitalizes the stage name
'
,
function
()
{
expect
(
component
.
capitalizeStageName
(
'
mystage
'
)).
toBe
(
'
Mystage
'
);
expect
(
component
.
capitalizeStageName
(
'
mystage
'
)).
toBe
(
'
Mystage
'
);
});
});
});
});
describe
(
'
stageConnectorClass
'
,
function
()
{
describe
(
'
stageConnectorClass
'
,
function
()
{
it
(
'
it returns left-margin when there is a triggerer
'
,
function
()
{
it
(
'
it returns left-margin when there is a triggerer
'
,
function
()
{
expect
(
component
.
stageConnectorClass
(
0
,
{
groups
:
[
'
job
'
]
})).
toBe
(
'
no-margin
'
);
expect
(
component
.
stageConnectorClass
(
0
,
{
groups
:
[
'
job
'
]
})).
toBe
(
'
no-margin
'
);
});
});
});
});
});
});
describe
(
'
linked pipelines components
'
,
function
()
{
describe
(
'
linked pipelines components
'
,
function
()
{
it
(
'
should coerce triggeredBy into a collection
'
,
function
()
{
it
(
'
should coerce triggeredBy into a collection
'
,
function
()
{
expect
(
component
.
triggeredBy
.
length
).
toBe
(
1
);
expect
(
component
.
triggeredBy
.
length
).
toBe
(
1
);
});
});
it
(
'
should render an upstream pipelines column
'
,
function
()
{
it
(
'
should render an upstream pipelines column
'
,
function
()
{
expect
(
component
.
$el
.
querySelector
(
'
.linked-pipelines-column
'
)).
not
.
toBeNull
();
expect
(
component
.
$el
.
querySelector
(
'
.linked-pipelines-column
'
)).
not
.
toBeNull
();
expect
(
component
.
$el
.
innerHTML
).
toContain
(
'
Upstream
'
);
expect
(
component
.
$el
.
innerHTML
).
toContain
(
'
Upstream
'
);
});
});
it
(
'
should render a downstream pipelines column
'
,
function
()
{
it
(
'
should render a downstream pipelines column
'
,
function
()
{
expect
(
component
.
$el
.
querySelector
(
'
.linked-pipelines-column
'
)).
not
.
toBeNull
();
expect
(
component
.
$el
.
querySelector
(
'
.linked-pipelines-column
'
)).
not
.
toBeNull
();
expect
(
component
.
$el
.
innerHTML
).
toContain
(
'
Downstream
'
);
expect
(
component
.
$el
.
innerHTML
).
toContain
(
'
Downstream
'
);
});
});
});
});
});
});
describe
(
'
when linked pipelines are not present
'
,
function
()
{
describe
(
'
when linked pipelines are not present
'
,
function
()
{
beforeEach
(
function
()
{
beforeEach
(
function
()
{
const
pipeline
=
Object
.
assign
(
graphJSON
,
{
triggered
:
null
,
triggered_by
:
null
});
const
pipeline
=
Object
.
assign
(
graphJSON
,
{
triggered
:
null
,
triggered_by
:
null
});
component
=
mountComponent
(
GraphComponent
,
{
component
=
mountComponent
(
GraphComponent
,
{
isLoading
:
false
,
isLoading
:
false
,
...
@@ -112,24 +118,24 @@ describe('graph component', () => {
...
@@ -112,24 +118,24 @@ describe('graph component', () => {
});
});
});
});
describe
(
'
rendered output
'
,
function
()
{
describe
(
'
rendered output
'
,
function
()
{
it
(
'
should include the first column with a no margin
'
,
function
()
{
it
(
'
should include the first column with a no margin
'
,
function
()
{
const
firstColumn
=
component
.
$el
.
querySelector
(
'
.stage-column:first-child
'
);
const
firstColumn
=
component
.
$el
.
querySelector
(
'
.stage-column:first-child
'
);
expect
(
firstColumn
.
classList
.
contains
(
'
no-margin
'
)).
toEqual
(
true
);
expect
(
firstColumn
.
classList
.
contains
(
'
no-margin
'
)).
toEqual
(
true
);
});
});
it
(
'
should not render a linked pipelines column
'
,
function
()
{
it
(
'
should not render a linked pipelines column
'
,
function
()
{
expect
(
component
.
$el
.
querySelector
(
'
.linked-pipelines-column
'
)).
toBeNull
();
expect
(
component
.
$el
.
querySelector
(
'
.linked-pipelines-column
'
)).
toBeNull
();
});
});
});
});
describe
(
'
stageConnectorClass
'
,
function
()
{
describe
(
'
stageConnectorClass
'
,
function
()
{
it
(
'
it returns left-margin when no triggerer and there is one job
'
,
function
()
{
it
(
'
it returns left-margin when no triggerer and there is one job
'
,
function
()
{
expect
(
component
.
stageConnectorClass
(
0
,
{
groups
:
[
'
job
'
]
})).
toBe
(
'
no-margin
'
);
expect
(
component
.
stageConnectorClass
(
0
,
{
groups
:
[
'
job
'
]
})).
toBe
(
'
no-margin
'
);
});
});
it
(
'
it returns left-margin when no triggerer and not the first stage
'
,
function
()
{
it
(
'
it returns left-margin when no triggerer and not the first stage
'
,
function
()
{
expect
(
component
.
stageConnectorClass
(
99
,
{
groups
:
[
'
job
'
]
})).
toBe
(
'
left-margin
'
);
expect
(
component
.
stageConnectorClass
(
99
,
{
groups
:
[
'
job
'
]
})).
toBe
(
'
left-margin
'
);
});
});
});
});
...
@@ -142,7 +148,9 @@ describe('graph component', () => {
...
@@ -142,7 +148,9 @@ describe('graph component', () => {
pipeline
:
graphJSON
,
pipeline
:
graphJSON
,
});
});
expect
(
component
.
$el
.
querySelector
(
'
.stage-column:nth-child(2) .stage-name
'
).
textContent
.
trim
()).
toEqual
(
'
Deploy <img src=x onerror=alert(document.domain)>
'
);
expect
(
component
.
$el
.
querySelector
(
'
.stage-column:nth-child(2) .stage-name
'
).
textContent
.
trim
(),
).
toEqual
(
'
Deploy <img src=x onerror=alert(document.domain)>
'
);
});
});
});
});
});
});
spec/javascripts/sidebar/assignees_spec.js
View file @
7e9f44fa
...
@@ -78,9 +78,7 @@ describe('Assignee component', () => {
...
@@ -78,9 +78,7 @@ describe('Assignee component', () => {
component
=
new
AssigneeComponent
({
component
=
new
AssigneeComponent
({
propsData
:
{
propsData
:
{
rootPath
:
'
http://localhost:3000
'
,
rootPath
:
'
http://localhost:3000
'
,
users
:
[
users
:
[
UsersMock
.
user
],
UsersMock
.
user
,
],
editable
:
false
,
editable
:
false
,
},
},
}).
$mount
();
}).
$mount
();
...
@@ -90,7 +88,9 @@ describe('Assignee component', () => {
...
@@ -90,7 +88,9 @@ describe('Assignee component', () => {
expect
(
collapsed
.
childElementCount
).
toEqual
(
1
);
expect
(
collapsed
.
childElementCount
).
toEqual
(
1
);
expect
(
assignee
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
src
'
)).
toEqual
(
UsersMock
.
user
.
avatar
);
expect
(
assignee
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
src
'
)).
toEqual
(
UsersMock
.
user
.
avatar
);
expect
(
assignee
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
alt
'
)).
toEqual
(
`
${
UsersMock
.
user
.
name
}
's avatar`
);
expect
(
assignee
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
alt
'
)).
toEqual
(
`
${
UsersMock
.
user
.
name
}
's avatar`
,
);
expect
(
assignee
.
querySelector
(
'
.author
'
).
innerText
.
trim
()).
toEqual
(
UsersMock
.
user
.
name
);
expect
(
assignee
.
querySelector
(
'
.author
'
).
innerText
.
trim
()).
toEqual
(
UsersMock
.
user
.
name
);
});
});
...
@@ -98,34 +98,38 @@ describe('Assignee component', () => {
...
@@ -98,34 +98,38 @@ describe('Assignee component', () => {
component
=
new
AssigneeComponent
({
component
=
new
AssigneeComponent
({
propsData
:
{
propsData
:
{
rootPath
:
'
http://localhost:3000/
'
,
rootPath
:
'
http://localhost:3000/
'
,
users
:
[
users
:
[
UsersMock
.
user
],
UsersMock
.
user
,
],
editable
:
true
,
editable
:
true
,
},
},
}).
$mount
();
}).
$mount
();
expect
(
component
.
$el
.
querySelector
(
'
.author-link
'
)).
not
.
toBeNull
();
expect
(
component
.
$el
.
querySelector
(
'
.author-link
'
)).
not
.
toBeNull
();
// The image
// The image
expect
(
component
.
$el
.
querySelector
(
'
.author-link img
'
).
getAttribute
(
'
src
'
)).
toEqual
(
UsersMock
.
user
.
avatar
);
expect
(
component
.
$el
.
querySelector
(
'
.author-link img
'
).
getAttribute
(
'
src
'
)).
toEqual
(
UsersMock
.
user
.
avatar
,
);
// Author name
// Author name
expect
(
component
.
$el
.
querySelector
(
'
.author-link .author
'
).
innerText
.
trim
()).
toEqual
(
UsersMock
.
user
.
name
);
expect
(
component
.
$el
.
querySelector
(
'
.author-link .author
'
).
innerText
.
trim
()).
toEqual
(
UsersMock
.
user
.
name
,
);
// Username
// Username
expect
(
component
.
$el
.
querySelector
(
'
.author-link .username
'
).
innerText
.
trim
()).
toEqual
(
`@
${
UsersMock
.
user
.
username
}
`
);
expect
(
component
.
$el
.
querySelector
(
'
.author-link .username
'
).
innerText
.
trim
()).
toEqual
(
`@
${
UsersMock
.
user
.
username
}
`
,
);
});
});
it
(
'
has the root url present in the assigneeUrl method
'
,
()
=>
{
it
(
'
has the root url present in the assigneeUrl method
'
,
()
=>
{
component
=
new
AssigneeComponent
({
component
=
new
AssigneeComponent
({
propsData
:
{
propsData
:
{
rootPath
:
'
http://localhost:3000/
'
,
rootPath
:
'
http://localhost:3000/
'
,
users
:
[
users
:
[
UsersMock
.
user
],
UsersMock
.
user
,
],
editable
:
true
,
editable
:
true
,
},
},
}).
$mount
();
}).
$mount
();
expect
(
component
.
assigneeUrl
(
UsersMock
.
user
).
indexOf
(
'
http://localhost:3000/
'
)).
not
.
toEqual
(
-
1
);
expect
(
component
.
assigneeUrl
(
UsersMock
.
user
).
indexOf
(
'
http://localhost:3000/
'
)).
not
.
toEqual
(
-
1
,
);
});
});
});
});
...
@@ -147,13 +151,17 @@ describe('Assignee component', () => {
...
@@ -147,13 +151,17 @@ describe('Assignee component', () => {
const
first
=
collapsed
.
children
[
0
];
const
first
=
collapsed
.
children
[
0
];
expect
(
first
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
src
'
)).
toEqual
(
users
[
0
].
avatar
);
expect
(
first
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
src
'
)).
toEqual
(
users
[
0
].
avatar
);
expect
(
first
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
alt
'
)).
toEqual
(
`
${
users
[
0
].
name
}
's avatar`
);
expect
(
first
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
alt
'
)).
toEqual
(
`
${
users
[
0
].
name
}
's avatar`
,
);
expect
(
first
.
querySelector
(
'
.author
'
).
innerText
.
trim
()).
toEqual
(
users
[
0
].
name
);
expect
(
first
.
querySelector
(
'
.author
'
).
innerText
.
trim
()).
toEqual
(
users
[
0
].
name
);
const
second
=
collapsed
.
children
[
1
];
const
second
=
collapsed
.
children
[
1
];
expect
(
second
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
src
'
)).
toEqual
(
users
[
1
].
avatar
);
expect
(
second
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
src
'
)).
toEqual
(
users
[
1
].
avatar
);
expect
(
second
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
alt
'
)).
toEqual
(
`
${
users
[
1
].
name
}
's avatar`
);
expect
(
second
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
alt
'
)).
toEqual
(
`
${
users
[
1
].
name
}
's avatar`
,
);
expect
(
second
.
querySelector
(
'
.author
'
).
innerText
.
trim
()).
toEqual
(
users
[
1
].
name
);
expect
(
second
.
querySelector
(
'
.author
'
).
innerText
.
trim
()).
toEqual
(
users
[
1
].
name
);
});
});
...
@@ -174,7 +182,9 @@ describe('Assignee component', () => {
...
@@ -174,7 +182,9 @@ describe('Assignee component', () => {
const
first
=
collapsed
.
children
[
0
];
const
first
=
collapsed
.
children
[
0
];
expect
(
first
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
src
'
)).
toEqual
(
users
[
0
].
avatar
);
expect
(
first
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
src
'
)).
toEqual
(
users
[
0
].
avatar
);
expect
(
first
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
alt
'
)).
toEqual
(
`
${
users
[
0
].
name
}
's avatar`
);
expect
(
first
.
querySelector
(
'
.avatar
'
).
getAttribute
(
'
alt
'
)).
toEqual
(
`
${
users
[
0
].
name
}
's avatar`
,
);
expect
(
first
.
querySelector
(
'
.author
'
).
innerText
.
trim
()).
toEqual
(
users
[
0
].
name
);
expect
(
first
.
querySelector
(
'
.author
'
).
innerText
.
trim
()).
toEqual
(
users
[
0
].
name
);
const
second
=
collapsed
.
children
[
1
];
const
second
=
collapsed
.
children
[
1
];
...
@@ -206,12 +216,10 @@ describe('Assignee component', () => {
...
@@ -206,12 +216,10 @@ describe('Assignee component', () => {
},
},
}).
$mount
();
}).
$mount
();
expect
(
expect
(
component
.
$el
.
querySelector
(
'
.user-link
'
).
getAttribute
(
'
data-container
'
)).
toBe
(
'
body
'
);
component
.
$el
.
querySelector
(
'
.user-link
'
).
getAttribute
(
'
data-container
'
),
).
toBe
(
'
body
'
);
});
});
it
(
'
Shows the "show-less" assignees label
'
,
(
done
)
=>
{
it
(
'
Shows the "show-less" assignees label
'
,
done
=>
{
const
users
=
UsersMockHelper
.
createNumberRandomUsers
(
6
);
const
users
=
UsersMockHelper
.
createNumberRandomUsers
(
6
);
component
=
new
AssigneeComponent
({
component
=
new
AssigneeComponent
({
propsData
:
{
propsData
:
{
...
@@ -221,21 +229,25 @@ describe('Assignee component', () => {
...
@@ -221,21 +229,25 @@ describe('Assignee component', () => {
},
},
}).
$mount
();
}).
$mount
();
expect
(
component
.
$el
.
querySelectorAll
(
'
.user-item
'
).
length
).
toEqual
(
component
.
defaultRenderCount
);
expect
(
component
.
$el
.
querySelectorAll
(
'
.user-item
'
).
length
).
toEqual
(
component
.
defaultRenderCount
,
);
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more
'
)).
not
.
toBe
(
null
);
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more
'
)).
not
.
toBe
(
null
);
const
usersLabelExpectation
=
users
.
length
-
component
.
defaultRenderCount
;
const
usersLabelExpectation
=
users
.
length
-
component
.
defaultRenderCount
;
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
innerText
.
trim
())
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
innerText
.
trim
()).
not
.
toBe
(
.
not
.
toBe
(
`+
${
usersLabelExpectation
}
more`
);
`+
${
usersLabelExpectation
}
more`
,
);
component
.
toggleShowLess
();
component
.
toggleShowLess
();
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
innerText
.
trim
())
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
innerText
.
trim
()).
toBe
(
.
toBe
(
'
- show less
'
);
'
- show less
'
,
);
done
();
done
();
});
});
});
});
it
(
'
Shows the "show-less" when "n+ more " label is clicked
'
,
(
done
)
=>
{
it
(
'
Shows the "show-less" when "n+ more " label is clicked
'
,
done
=>
{
const
users
=
UsersMockHelper
.
createNumberRandomUsers
(
6
);
const
users
=
UsersMockHelper
.
createNumberRandomUsers
(
6
);
component
=
new
AssigneeComponent
({
component
=
new
AssigneeComponent
({
propsData
:
{
propsData
:
{
...
@@ -247,8 +259,9 @@ describe('Assignee component', () => {
...
@@ -247,8 +259,9 @@ describe('Assignee component', () => {
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
click
();
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
click
();
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
innerText
.
trim
())
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
innerText
.
trim
()).
toBe
(
.
toBe
(
'
- show less
'
);
'
- show less
'
,
);
done
();
done
();
});
});
});
});
...
@@ -279,16 +292,18 @@ describe('Assignee component', () => {
...
@@ -279,16 +292,18 @@ describe('Assignee component', () => {
});
});
it
(
'
shows "+1 more" label
'
,
()
=>
{
it
(
'
shows "+1 more" label
'
,
()
=>
{
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
innerText
.
trim
())
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
innerText
.
trim
()).
toBe
(
.
toBe
(
'
+ 1 more
'
);
'
+ 1 more
'
,
);
});
});
it
(
'
shows "show less" label
'
,
(
done
)
=>
{
it
(
'
shows "show less" label
'
,
done
=>
{
component
.
toggleShowLess
();
component
.
toggleShowLess
();
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
innerText
.
trim
())
expect
(
component
.
$el
.
querySelector
(
'
.user-list-more .btn-link
'
).
innerText
.
trim
()).
toBe
(
.
toBe
(
'
- show less
'
);
'
- show less
'
,
);
done
();
done
();
});
});
});
});
...
...
spec/javascripts/test_bundle.js
View file @
7e9f44fa
...
@@ -200,8 +200,10 @@ if (process.env.BABEL_ENV === 'coverage') {
...
@@ -200,8 +200,10 @@ if (process.env.BABEL_ENV === 'coverage') {
require
.
context
(
'
~
'
,
true
,
/
\.(
js|vue
)
$/
),
require
.
context
(
'
~
'
,
true
,
/
\.(
js|vue
)
$/
),
require
.
context
(
'
ee
'
,
true
,
/
\.(
js|vue
)
$/
),
require
.
context
(
'
ee
'
,
true
,
/
\.(
js|vue
)
$/
),
];
];
const
allTestFiles
=
testContexts
.
reduce
((
accumulator
,
context
)
=>
const
allTestFiles
=
testContexts
.
reduce
(
accumulator
.
concat
(
context
.
keys
()),
[]);
(
accumulator
,
context
)
=>
accumulator
.
concat
(
context
.
keys
()),
[],
);
$
.
holdReady
(
true
);
$
.
holdReady
(
true
);
...
...
spec/javascripts/vue_mr_widget/components/mr_widget_pipeline_spec.js
View file @
7e9f44fa
...
@@ -73,9 +73,9 @@ describe('MRWidgetPipeline', () => {
...
@@ -73,9 +73,9 @@ describe('MRWidgetPipeline', () => {
troubleshootingDocsPath
:
'
help
'
,
troubleshootingDocsPath
:
'
help
'
,
});
});
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
.
trim
()).
toContain
(
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
.
trim
()
,
'
Could not retrieve the pipeline status. For troubleshooting steps, read the <a href="help">documentation.</a>
'
,
)
.
toContain
(
'
Could not retrieve the pipeline status. For troubleshooting steps, read the <a href="help">documentation.</a>
'
)
;
);
});
});
describe
(
'
with a pipeline
'
,
()
=>
{
describe
(
'
with a pipeline
'
,
()
=>
{
...
@@ -89,34 +89,36 @@ describe('MRWidgetPipeline', () => {
...
@@ -89,34 +89,36 @@ describe('MRWidgetPipeline', () => {
});
});
it
(
'
should render pipeline ID
'
,
()
=>
{
it
(
'
should render pipeline ID
'
,
()
=>
{
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.pipeline-id
'
).
textContent
.
trim
()).
toEqual
(
vm
.
$el
.
querySelector
(
'
.pipeline-id
'
).
textContent
.
trim
()
,
`#
${
mockData
.
pipeline
.
id
}
`
,
)
.
toEqual
(
`#
${
mockData
.
pipeline
.
id
}
`
)
;
);
});
});
it
(
'
should render pipeline status and commit id
'
,
()
=>
{
it
(
'
should render pipeline status and commit id
'
,
()
=>
{
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
.
trim
()).
toContain
(
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
.
trim
()
,
mockData
.
pipeline
.
details
.
status
.
label
,
)
.
toContain
(
mockData
.
pipeline
.
details
.
status
.
label
)
;
);
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.js-commit-link
'
).
textContent
.
trim
()).
toEqual
(
vm
.
$el
.
querySelector
(
'
.js-commit-link
'
).
textContent
.
trim
()
,
mockData
.
pipeline
.
commit
.
short_id
,
)
.
toEqual
(
mockData
.
pipeline
.
commit
.
short_id
)
;
);
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.js-commit-link
'
).
getAttribute
(
'
href
'
)).
toEqual
(
vm
.
$el
.
querySelector
(
'
.js-commit-link
'
).
getAttribute
(
'
href
'
)
,
mockData
.
pipeline
.
commit
.
commit_path
,
)
.
toEqual
(
mockData
.
pipeline
.
commit
.
commit_path
)
;
);
});
});
it
(
'
should render pipeline graph
'
,
()
=>
{
it
(
'
should render pipeline graph
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.mr-widget-pipeline-graph
'
)).
toBeDefined
();
expect
(
vm
.
$el
.
querySelector
(
'
.mr-widget-pipeline-graph
'
)).
toBeDefined
();
expect
(
vm
.
$el
.
querySelectorAll
(
'
.stage-container
'
).
length
).
toEqual
(
mockData
.
pipeline
.
details
.
stages
.
length
);
expect
(
vm
.
$el
.
querySelectorAll
(
'
.stage-container
'
).
length
).
toEqual
(
mockData
.
pipeline
.
details
.
stages
.
length
,
);
});
});
it
(
'
should render coverage information
'
,
()
=>
{
it
(
'
should render coverage information
'
,
()
=>
{
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
).
toContain
(
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
,
`Coverage
${
mockData
.
pipeline
.
coverage
}
`
,
)
.
toContain
(
`Coverage
${
mockData
.
pipeline
.
coverage
}
`
)
;
);
});
});
});
});
...
@@ -134,30 +136,30 @@ describe('MRWidgetPipeline', () => {
...
@@ -134,30 +136,30 @@ describe('MRWidgetPipeline', () => {
});
});
it
(
'
should render pipeline ID
'
,
()
=>
{
it
(
'
should render pipeline ID
'
,
()
=>
{
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.pipeline-id
'
).
textContent
.
trim
()).
toEqual
(
vm
.
$el
.
querySelector
(
'
.pipeline-id
'
).
textContent
.
trim
()
,
`#
${
mockData
.
pipeline
.
id
}
`
,
)
.
toEqual
(
`#
${
mockData
.
pipeline
.
id
}
`
)
;
);
});
});
it
(
'
should render pipeline status
'
,
()
=>
{
it
(
'
should render pipeline status
'
,
()
=>
{
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
.
trim
()).
toContain
(
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
.
trim
()
,
mockData
.
pipeline
.
details
.
status
.
label
,
)
.
toContain
(
mockData
.
pipeline
.
details
.
status
.
label
)
;
);
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.js-commit-link
'
)).
toBeNull
();
vm
.
$el
.
querySelector
(
'
.js-commit-link
'
),
).
toBeNull
();
});
});
it
(
'
should render pipeline graph
'
,
()
=>
{
it
(
'
should render pipeline graph
'
,
()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.mr-widget-pipeline-graph
'
)).
toBeDefined
();
expect
(
vm
.
$el
.
querySelector
(
'
.mr-widget-pipeline-graph
'
)).
toBeDefined
();
expect
(
vm
.
$el
.
querySelectorAll
(
'
.stage-container
'
).
length
).
toEqual
(
mockData
.
pipeline
.
details
.
stages
.
length
);
expect
(
vm
.
$el
.
querySelectorAll
(
'
.stage-container
'
).
length
).
toEqual
(
mockData
.
pipeline
.
details
.
stages
.
length
,
);
});
});
it
(
'
should render coverage information
'
,
()
=>
{
it
(
'
should render coverage information
'
,
()
=>
{
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
).
toContain
(
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
,
`Coverage
${
mockData
.
pipeline
.
coverage
}
`
,
)
.
toContain
(
`Coverage
${
mockData
.
pipeline
.
coverage
}
`
)
;
);
});
});
});
});
...
@@ -173,9 +175,7 @@ describe('MRWidgetPipeline', () => {
...
@@ -173,9 +175,7 @@ describe('MRWidgetPipeline', () => {
troubleshootingDocsPath
:
'
help
'
,
troubleshootingDocsPath
:
'
help
'
,
});
});
expect
(
expect
(
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
).
not
.
toContain
(
'
Coverage
'
);
vm
.
$el
.
querySelector
(
'
.media-body
'
).
textContent
,
).
not
.
toContain
(
'
Coverage
'
);
});
});
});
});
...
...
spec/javascripts/vue_mr_widget/mock_data.js
View file @
7e9f44fa
...
@@ -230,7 +230,7 @@ export default {
...
@@ -230,7 +230,7 @@ export default {
'
/help/user/project/merge_requests/index#interacting-with-security-reports-ultimate
'
,
'
/help/user/project/merge_requests/index#interacting-with-security-reports-ultimate
'
,
merge_commit_path
:
merge_commit_path
:
'
http://localhost:3000/root/acets-app/commit/53027d060246c8f47e4a9310fb332aa52f221775
'
,
'
http://localhost:3000/root/acets-app/commit/53027d060246c8f47e4a9310fb332aa52f221775
'
,
troubleshooting_docs_path
:
'
help
'
troubleshooting_docs_path
:
'
help
'
,
};
};
// Codeclimate
// Codeclimate
export
const
headIssues
=
[
export
const
headIssues
=
[
...
...
spec/javascripts/vue_mr_widget/mr_widget_options_spec.js
View file @
7e9f44fa
...
@@ -454,7 +454,7 @@ describe('mrWidgetOptions', () => {
...
@@ -454,7 +454,7 @@ describe('mrWidgetOptions', () => {
deployed_at
:
'
2017-03-22T22:44:42.258Z
'
,
deployed_at
:
'
2017-03-22T22:44:42.258Z
'
,
deployed_at_formatted
:
'
Mar 22, 2017 10:44pm
'
,
deployed_at_formatted
:
'
Mar 22, 2017 10:44pm
'
,
changes
,
changes
,
status
:
'
success
'
status
:
'
success
'
,
};
};
beforeEach
(
done
=>
{
beforeEach
(
done
=>
{
...
@@ -607,7 +607,8 @@ describe('mrWidgetOptions', () => {
...
@@ -607,7 +607,8 @@ describe('mrWidgetOptions', () => {
describe
(
'
with post merge deployments
'
,
()
=>
{
describe
(
'
with post merge deployments
'
,
()
=>
{
beforeEach
(
done
=>
{
beforeEach
(
done
=>
{
vm
.
mr
.
postMergeDeployments
=
[{
vm
.
mr
.
postMergeDeployments
=
[
{
id
:
15
,
id
:
15
,
name
:
'
review/diplo
'
,
name
:
'
review/diplo
'
,
url
:
'
/root/acets-review-apps/environments/15
'
,
url
:
'
/root/acets-review-apps/environments/15
'
,
...
@@ -625,15 +626,17 @@ describe('mrWidgetOptions', () => {
...
@@ -625,15 +626,17 @@ describe('mrWidgetOptions', () => {
},
},
{
{
path
:
'
imgs/gallery.html
'
,
path
:
'
imgs/gallery.html
'
,
external_url
:
'
http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html
'
,
external_url
:
'
http://root-master-patch-91341.volatile-watch.surge.sh/imgs/gallery.html
'
,
},
},
{
{
path
:
'
about/
'
,
path
:
'
about/
'
,
external_url
:
'
http://root-master-patch-91341.volatile-watch.surge.sh/about/
'
,
external_url
:
'
http://root-master-patch-91341.volatile-watch.surge.sh/about/
'
,
},
},
],
],
status
:
'
success
'
status
:
'
success
'
,
}];
},
];
vm
.
$nextTick
(
done
);
vm
.
$nextTick
(
done
);
});
});
...
...
spec/javascripts/vue_shared/components/sidebar/collapsed_grouped_date_picker_spec.js
View file @
7e9f44fa
...
@@ -12,7 +12,7 @@ describe('collapsedGroupedDatePicker', () => {
...
@@ -12,7 +12,7 @@ describe('collapsedGroupedDatePicker', () => {
});
});
describe
(
'
toggleCollapse events
'
,
()
=>
{
describe
(
'
toggleCollapse events
'
,
()
=>
{
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
spyOn
(
vm
,
'
toggleSidebar
'
);
spyOn
(
vm
,
'
toggleSidebar
'
);
vm
.
minDate
=
new
Date
(
'
07/17/2016
'
);
vm
.
minDate
=
new
Date
(
'
07/17/2016
'
);
Vue
.
nextTick
(
done
);
Vue
.
nextTick
(
done
);
...
@@ -26,7 +26,7 @@ describe('collapsedGroupedDatePicker', () => {
...
@@ -26,7 +26,7 @@ describe('collapsedGroupedDatePicker', () => {
});
});
describe
(
'
minDate and maxDate
'
,
()
=>
{
describe
(
'
minDate and maxDate
'
,
()
=>
{
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
vm
.
minDate
=
new
Date
(
'
07/17/2016
'
);
vm
.
minDate
=
new
Date
(
'
07/17/2016
'
);
vm
.
maxDate
=
new
Date
(
'
07/17/2017
'
);
vm
.
maxDate
=
new
Date
(
'
07/17/2017
'
);
Vue
.
nextTick
(
done
);
Vue
.
nextTick
(
done
);
...
@@ -42,7 +42,7 @@ describe('collapsedGroupedDatePicker', () => {
...
@@ -42,7 +42,7 @@ describe('collapsedGroupedDatePicker', () => {
});
});
describe
(
'
minDate
'
,
()
=>
{
describe
(
'
minDate
'
,
()
=>
{
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
vm
.
minDate
=
new
Date
(
'
07/17/2016
'
);
vm
.
minDate
=
new
Date
(
'
07/17/2016
'
);
Vue
.
nextTick
(
done
);
Vue
.
nextTick
(
done
);
});
});
...
@@ -56,7 +56,7 @@ describe('collapsedGroupedDatePicker', () => {
...
@@ -56,7 +56,7 @@ describe('collapsedGroupedDatePicker', () => {
});
});
describe
(
'
maxDate
'
,
()
=>
{
describe
(
'
maxDate
'
,
()
=>
{
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
vm
.
maxDate
=
new
Date
(
'
07/17/2017
'
);
vm
.
maxDate
=
new
Date
(
'
07/17/2017
'
);
Vue
.
nextTick
(
done
);
Vue
.
nextTick
(
done
);
});
});
...
...
spec/javascripts/vue_shared/components/sidebar/date_picker_spec.js
View file @
7e9f44fa
...
@@ -32,7 +32,7 @@ describe('sidebarDatePicker', () => {
...
@@ -32,7 +32,7 @@ describe('sidebarDatePicker', () => {
expect
(
vm
.
$el
.
querySelector
(
'
.value-content span
'
).
innerText
.
trim
()).
toEqual
(
'
None
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.value-content span
'
).
innerText
.
trim
()).
toEqual
(
'
None
'
);
});
});
it
(
'
should render date-picker when editing
'
,
(
done
)
=>
{
it
(
'
should render date-picker when editing
'
,
done
=>
{
vm
.
editing
=
true
;
vm
.
editing
=
true
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.pika-label
'
)).
toBeDefined
();
expect
(
vm
.
$el
.
querySelector
(
'
.pika-label
'
)).
toBeDefined
();
...
@@ -41,7 +41,7 @@ describe('sidebarDatePicker', () => {
...
@@ -41,7 +41,7 @@ describe('sidebarDatePicker', () => {
});
});
describe
(
'
editable
'
,
()
=>
{
describe
(
'
editable
'
,
()
=>
{
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
vm
.
editable
=
true
;
vm
.
editable
=
true
;
Vue
.
nextTick
(
done
);
Vue
.
nextTick
(
done
);
});
});
...
@@ -50,7 +50,7 @@ describe('sidebarDatePicker', () => {
...
@@ -50,7 +50,7 @@ describe('sidebarDatePicker', () => {
expect
(
vm
.
$el
.
querySelector
(
'
.title .btn-blank
'
).
innerText
.
trim
()).
toEqual
(
'
Edit
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.title .btn-blank
'
).
innerText
.
trim
()).
toEqual
(
'
Edit
'
);
});
});
it
(
'
should enable editing when edit button is clicked
'
,
(
done
)
=>
{
it
(
'
should enable editing when edit button is clicked
'
,
done
=>
{
vm
.
isLoading
=
false
;
vm
.
isLoading
=
false
;
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
vm
.
$el
.
querySelector
(
'
.title .btn-blank
'
).
click
();
vm
.
$el
.
querySelector
(
'
.title .btn-blank
'
).
click
();
...
@@ -61,7 +61,7 @@ describe('sidebarDatePicker', () => {
...
@@ -61,7 +61,7 @@ describe('sidebarDatePicker', () => {
});
});
});
});
it
(
'
should render date if selectedDate
'
,
(
done
)
=>
{
it
(
'
should render date if selectedDate
'
,
done
=>
{
vm
.
selectedDate
=
new
Date
(
'
07/07/2017
'
);
vm
.
selectedDate
=
new
Date
(
'
07/07/2017
'
);
Vue
.
nextTick
(()
=>
{
Vue
.
nextTick
(()
=>
{
expect
(
vm
.
$el
.
querySelector
(
'
.value-content strong
'
).
innerText
.
trim
()).
toEqual
(
'
Jul 7, 2017
'
);
expect
(
vm
.
$el
.
querySelector
(
'
.value-content strong
'
).
innerText
.
trim
()).
toEqual
(
'
Jul 7, 2017
'
);
...
@@ -70,7 +70,7 @@ describe('sidebarDatePicker', () => {
...
@@ -70,7 +70,7 @@ describe('sidebarDatePicker', () => {
});
});
describe
(
'
selectedDate and editable
'
,
()
=>
{
describe
(
'
selectedDate and editable
'
,
()
=>
{
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
vm
.
selectedDate
=
new
Date
(
'
07/07/2017
'
);
vm
.
selectedDate
=
new
Date
(
'
07/07/2017
'
);
vm
.
editable
=
true
;
vm
.
editable
=
true
;
Vue
.
nextTick
(
done
);
Vue
.
nextTick
(
done
);
...
@@ -91,7 +91,7 @@ describe('sidebarDatePicker', () => {
...
@@ -91,7 +91,7 @@ describe('sidebarDatePicker', () => {
});
});
describe
(
'
showToggleSidebar
'
,
()
=>
{
describe
(
'
showToggleSidebar
'
,
()
=>
{
beforeEach
(
(
done
)
=>
{
beforeEach
(
done
=>
{
vm
.
showToggleSidebar
=
true
;
vm
.
showToggleSidebar
=
true
;
Vue
.
nextTick
(
done
);
Vue
.
nextTick
(
done
);
});
});
...
...
spec/javascripts/vue_shared/components/sidebar/labels_select/dropdown_value_collapsed_spec.js
View file @
7e9f44fa
...
@@ -49,7 +49,9 @@ describe('DropdownValueCollapsedComponent', () => {
...
@@ -49,7 +49,9 @@ describe('DropdownValueCollapsedComponent', () => {
const
vmMoreLabels
=
createComponent
(
mockMoreLabels
);
const
vmMoreLabels
=
createComponent
(
mockMoreLabels
);
expect
(
vmMoreLabels
.
labelsList
).
toBe
(
'
Foo Label, Foo Label, Foo Label, Foo Label, Foo Label, and 2 more
'
);
expect
(
vmMoreLabels
.
labelsList
).
toBe
(
'
Foo Label, Foo Label, Foo Label, Foo Label, Foo Label, and 2 more
'
,
);
vmMoreLabels
.
$destroy
();
vmMoreLabels
.
$destroy
();
});
});
...
...
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