Skip to content
Snippets Groups Projects
Verified Commit cc1e51ef authored by Luke "Jared" Bennett's avatar Luke "Jared" Bennett
Browse files

Added report issuable feature

parent 87d90b5b
No related branches found
No related tags found
No related merge requests found
Showing
with 349 additions and 82 deletions
import DropLab from './droplab/drop_lab';
import ISetter from './droplab/plugins/input_setter';
// Todo: Remove this when fixing issue in input_setter plugin
const InputSetter = Object.assign({}, ISetter);
class CloseReopenReportToggle {
constructor(opts = {}) {
this.dropdownTrigger = opts.dropdownTrigger;
this.dropdownList = opts.dropdownList;
this.button = opts.button;
this.reopenItem = this.dropdownList.querySelector('.reopen-item');
this.closeItem = this.dropdownList.querySelector('.close-item');
}
initDroplab() {
this.droplab = new DropLab();
const config = this.setConfig();
this.droplab.init(this.dropdownTrigger, this.dropdownList, [InputSetter], config);
}
updateButton(isClosed) {
const action = isClosed ? this.showReopen : this.showClose;
action.call(this);
this.button.blur();
}
showClose() {
this.closeItem.classList.remove('hidden');
this.closeItem.classList.add('droplab-item-selected');
this.reopenItem.classList.add('hidden');
this.reopenItem.classList.remove('droplab-item-selected');
this.closeItem.click();
}
showReopen() {
this.reopenItem.classList.remove('hidden');
this.reopenItem.classList.add('droplab-item-selected');
this.closeItem.classList.add('hidden');
this.closeItem.classList.remove('droplab-item-selected');
this.reopenItem.click();
}
setDisable(shouldDisable) {
if (shouldDisable) {
this.button.setAttribute('disabled', 'true');
this.dropdownTrigger.setAttribute('disabled', 'true');
} else {
this.button.removeAttribute('disabled');
this.dropdownTrigger.removeAttribute('disabled');
}
}
setConfig() {
const config = {
InputSetter: [
{
input: this.button,
valueAttribute: 'data-text',
inputAttribute: 'data-value',
},
{
input: this.button,
valueAttribute: 'data-text',
inputAttribute: 'title',
},
{
input: this.button,
valueAttribute: 'data-button-class',
inputAttribute: 'class',
},
{
input: this.dropdownTrigger,
valueAttribute: 'data-toggle-class',
inputAttribute: 'class',
},
{
input: this.button,
valueAttribute: 'data-url',
inputAttribute: 'href',
},
{
input: this.button,
valueAttribute: 'data-method',
inputAttribute: 'data-method',
},
],
};
return config;
}
}
export default CloseReopenReportToggle;
import DropLab from './droplab/drop_lab';
import InputSetter from './droplab/plugins/input_setter';
import ISetter from './droplab/plugins/input_setter';
// Todo: Remove this when fixing issue in input_setter plugin
const InputSetter = Object.assign({}, ISetter);
 
class CommentTypeToggle {
constructor(opts = {}) {
Loading
Loading
Loading
Loading
@@ -6,6 +6,7 @@ import '~/lib/utils/text_utility';
import './flash';
import './task_list';
import CreateMergeRequestDropdown from './create_merge_request_dropdown';
import CloseReopenReportToggle from './close_reopen_report_toggle';
 
class Issue {
constructor() {
Loading
Loading
@@ -28,6 +29,8 @@ class Issue {
Issue.initMergeRequests();
Issue.initRelatedBranches();
 
this.initCloseReopenReport();
if (Issue.createMrDropdownWrap) {
this.createMergeRequestDropdown = new CreateMergeRequestDropdown(Issue.createMrDropdownWrap);
}
Loading
Loading
@@ -35,13 +38,11 @@ class Issue {
 
initIssueBtnEventListeners() {
const issueFailMessage = 'Unable to update this issue at this time.';
const closeButtons = $('a.btn-close');
const isClosedBadge = $('div.status-box-closed');
const isOpenBadge = $('div.status-box-open');
const projectIssuesCounter = $('.issue_counter');
const reopenButtons = $('a.btn-reopen');
 
return closeButtons.add(reopenButtons).on('click', (e) => {
return $(document).on('click', 'a.btn-close, a.btn-reopen', (e) => {
var $button, shouldSubmit, url;
e.preventDefault();
e.stopImmediatePropagation();
Loading
Loading
@@ -50,7 +51,9 @@ class Issue {
if (shouldSubmit) {
Issue.submitNoteForm($button.closest('form'));
}
$button.prop('disabled', true);
this.closeReopenReportToggle.setDisable(true);
url = $button.attr('href');
return $.ajax({
type: 'PUT',
Loading
Loading
@@ -62,11 +65,11 @@ class Issue {
$(document).trigger('issuable:change');
 
const isClosed = $button.hasClass('btn-close');
closeButtons.toggleClass('hidden', isClosed);
reopenButtons.toggleClass('hidden', !isClosed);
isClosedBadge.toggleClass('hidden', !isClosed);
isOpenBadge.toggleClass('hidden', isClosed);
 
this.closeReopenReportToggle.updateButton(isClosed);
let numProjectIssues = Number(projectIssuesCounter.text().replace(/[^\d]/, ''));
numProjectIssues = isClosed ? numProjectIssues - 1 : numProjectIssues + 1;
projectIssuesCounter.text(gl.text.addDelimiter(numProjectIssues));
Loading
Loading
@@ -84,11 +87,26 @@ class Issue {
new Flash(issueFailMessage);
}
 
$button.prop('disabled', false);
this.closeReopenReportToggle.setDisable(false);
});
});
}
 
initCloseReopenReport() {
const container = document.querySelector('.js-issuable-close-dropdown');
const dropdownTrigger = container.querySelector('.js-issuable-close-toggle');
const dropdownList = container.querySelector('.js-issuable-close-menu');
const button = container.querySelector('.js-issuable-close-button');
this.closeReopenReportToggle = new CloseReopenReportToggle({
dropdownTrigger,
dropdownList,
button,
});
this.closeReopenReportToggle.initDroplab();
}
static submitNoteForm(form) {
var noteText;
noteText = form.find("textarea.js-note-text").val();
Loading
Loading
Loading
Loading
@@ -4,6 +4,7 @@
import 'vendor/jquery.waitforimages';
import './task_list';
import './merge_request_tabs';
import CloseReopenReportToggle from './close_reopen_report_toggle';
 
(function() {
this.MergeRequest = (function() {
Loading
Loading
@@ -24,6 +25,7 @@ import './merge_request_tabs';
this.initTabs();
this.initMRBtnListeners();
this.initCommitMessageListeners();
MergeRequest.initCloseReopenReport();
if ($("a.btn-close").length) {
this.taskList = new gl.TaskList({
dataType: 'merge_request',
Loading
Loading
@@ -119,6 +121,21 @@ import './merge_request_tabs';
$el.text(gl.text.addDelimiter(count));
};
 
MergeRequest.initCloseReopenReport = function () {
const container = document.querySelector('.js-issuable-close-dropdown');
const dropdownTrigger = container.querySelector('.js-issuable-close-toggle');
const dropdownList = container.querySelector('.js-issuable-close-menu');
const button = container.querySelector('.js-issuable-close-button');
const closeReopenReportToggle = new CloseReopenReportToggle({
dropdownTrigger,
dropdownList,
button,
});
closeReopenReportToggle.initDroplab();
};
return MergeRequest;
})();
}).call(window);
Loading
Loading
@@ -20,17 +20,29 @@
color: $text;
border-color: $border;
 
> i {
color: $text;
}
&:hover,
&:focus {
background-color: $hover-background;
border-color: $hover-border;
color: $hover-text;
> i {
color: $hover-text;
}
}
 
&:active {
background-color: $active-background;
border-color: $active-border;
color: $hover-text;
> i {
color: $hover-text;
}
}
}
 
Loading
Loading
@@ -163,7 +175,8 @@
@include btn-orange;
}
 
&.btn-close {
&.btn-close,
&.btn-close-color {
@include btn-outline($white-light, $orange-600, $orange-500, $orange-500, $white-light, $orange-600, $orange-600, $orange-700);
}
 
Loading
Loading
@@ -181,7 +194,8 @@
float: right;
}
 
&.btn-reopen {
&.btn-reopen,
.btn-reopen-color {
/* should be same as parent class for now */
}
 
Loading
Loading
Loading
Loading
@@ -295,9 +295,65 @@
}
}
 
.filtered-search-box-input-container .dropdown-menu,
.filtered-search-box-input-container .dropdown-menu-nav,
.comment-type-dropdown .dropdown-menu {
.droplab-dropdown {
.description {
display: inline-block;
white-space: normal;
margin-left: 8px;
padding-right: 33px;
}
.dropdown-toggle > i {
pointer-events: none;
}
li {
padding-top: 6px;
& > a {
margin: 0;
padding: 0;
color: inherit;
border-radius: 0;
text-overflow: inherit;
&:hover,
&:focus {
background-color: inherit;
color: inherit;
}
}
&:hover,
&:focus {
background-color: $dropdown-hover-color;
color: $white-light;
}
&.droplab-item-selected i {
visibility: visible;
}
i {
visibility: hidden;
}
}
i {
display: inline-block;
vertical-align: top;
padding-top: 2px;
}
.divider {
margin: 0 8px;
padding: 0;
border-top: $gray-darkest;
}
}
.droplab-dropdown .dropdown-menu,
.droplab-dropdown .dropdown-menu-nav {
display: none;
opacity: 1;
visibility: visible;
Loading
Loading
Loading
Loading
@@ -799,3 +799,14 @@
}
}
}
.issuable-close-button,
.issuable-close-toggle {
@include transition(border-color, color);
}
.issuable-close-dropdown .dropdown-menu {
min-width: 270px;
left: auto;
right: 0;
}
Loading
Loading
@@ -356,7 +356,6 @@
color: $white-light;
padding-right: 2px;
margin-top: 2px;
pointer-events: none;
}
}
 
Loading
Loading
@@ -366,56 +365,6 @@
width: 298px;
}
 
.description {
display: inline-block;
white-space: normal;
margin-left: 8px;
padding-right: 33px;
}
li {
padding-top: 6px;
& > a {
margin: 0;
padding: 0;
color: inherit;
border-radius: 0;
text-overflow: inherit;
&:hover,
&:focus {
background-color: inherit;
color: inherit;
}
}
&:hover,
&:focus {
background-color: $dropdown-hover-color;
color: $white-light;
}
&.droplab-item-selected i {
visibility: visible;
}
i {
visibility: hidden;
}
}
i {
display: inline-block;
vertical-align: top;
padding-top: 2px;
}
.divider {
margin: 0 8px;
padding: 0;
border-top: $gray-darkest;
}
 
@media (max-width: $screen-xs-max) {
display: flex;
Loading
Loading
Loading
Loading
@@ -245,6 +245,40 @@ module IssuablesHelper
@counts[cache_key][state]
end
 
def close_issuable_path(issuable)
params = state_event_hash(issuable, :close)
params[:format] = 'json' if issuable.is_a?(Issue)
issuable_path(issuable, params)
end
def reopen_issuable_path(issuable)
params = state_event_hash(issuable, :reopen)
params[:format] = 'json' if issuable.is_a?(Issue)
issuable_path(issuable, params)
end
def close_reopen_issuable_path(issuable)
issuable.closed? ? reopen_issuable_path(issuable) : close_issuable_path(issuable)
end
def issuable_path(issuable, *path_options)
case issuable
when Issue then issue_path(issuable, *path_options)
when MergeRequest then merge_request_path(issuable, *path_options)
else raise 'unknown issuable type'
end
end
def issuable_url(issuable, *path_options)
case issuable
when Issue then issue_url(issuable, *path_options)
when MergeRequest then merge_request_url(issuable, *path_options)
else raise 'unknown issuable type'
end
end
private
 
def sidebar_gutter_collapsed?
Loading
Loading
@@ -301,4 +335,11 @@ module IssuablesHelper
container: (is_collapsed ? 'body' : nil)
}
end
def state_event_hash(issuable, event_symbol)
event_hash = {}
event_hash[:"#{issuable.class.to_s.underscore}"] = { state_event: event_symbol }
event_hash
end
end
Loading
Loading
@@ -30,12 +30,14 @@
.dropdown-menu.dropdown-menu-align-right.hidden-lg
%ul
- if can_update_issue
%li
= link_to 'Edit', edit_project_issue_path(@project, @issue), class: 'issuable-edit'
%li
= link_to 'Close issue', issue_path(@issue, issue: { state_event: :close }, format: 'json'), class: "btn-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
%li
= link_to 'Reopen issue', issue_path(@issue, issue: { state_event: :reopen }, format: 'json'), class: "btn-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue'
%li
= link_to 'Edit', edit_project_issue_path(@project, @issue)
%li
= link_to 'Report abuse', new_abuse_report_path(user_id: @issue.author.id, ref_url: issue_url(@issue))
- if can_report_spam
%li
= link_to 'Submit as spam', mark_as_spam_project_issue_path(@project, @issue), method: :post, class: 'btn-spam', title: 'Submit as spam'
Loading
Loading
@@ -46,8 +48,9 @@
 
- if can_update_issue
= link_to 'Edit', edit_project_issue_path(@project, @issue), class: 'hidden-xs hidden-sm btn btn-grouped issuable-edit'
= link_to 'Close issue', issue_path(@issue, issue: { state_event: :close }, format: 'json'), class: "hidden-xs hidden-sm btn btn-grouped btn-close #{issue_button_visibility(@issue, true)}", title: 'Close issue'
= link_to 'Reopen issue', issue_path(@issue, issue: { state_event: :reopen }, format: 'json'), class: "hidden-xs hidden-sm btn btn-grouped btn-reopen #{issue_button_visibility(@issue, false)}", title: 'Reopen issue'
= render 'shared/issuable/close_reopen_button', issuable: @issue, can_update: can_update_issue
- if can_report_spam
= link_to 'Submit as spam', mark_as_spam_project_issue_path(@project, @issue), method: :post, class: 'hidden-xs hidden-sm btn btn-grouped btn-spam', title: 'Submit as spam'
= link_to new_project_issue_path(@project), class: 'hidden-xs hidden-sm btn btn-grouped new-issue-link btn-new btn-inverted', title: 'New issue', id: 'new_issue_link' do
Loading
Loading
- can_update_merge_request = can?(current_user, :update_merge_request, @merge_request)
- if @merge_request.closed_without_fork?
.alert.alert-danger
%p The source project of this merge request has been removed.
Loading
Loading
@@ -15,21 +17,24 @@
.issuable-meta
= issuable_meta(@merge_request, @project, "Merge request")
 
- if can?(current_user, :update_merge_request, @merge_request)
.issuable-actions
.clearfix.issue-btn-group.dropdown
%button.btn.btn-default.pull-left.hidden-md.hidden-lg{ type: "button", data: { toggle: "dropdown" } }
Options
= icon('caret-down')
.dropdown-menu.dropdown-menu-align-right.hidden-lg
%ul
.issuable-actions
.clearfix.issue-btn-group.dropdown
%button.btn.btn-default.pull-left.hidden-md.hidden-lg{ type: "button", data: { toggle: "dropdown" } }
Options
= icon('caret-down')
.dropdown-menu.dropdown-menu-align-right.hidden-lg
%ul
- if can_update_merge_request
%li{ class: merge_request_button_visibility(@merge_request, true) }
= link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, title: 'Close merge request'
%li{ class: merge_request_button_visibility(@merge_request, false) }
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: 'reopen-mr-link', title: 'Reopen merge request'
%li
= link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), class: 'issuable-edit'
= link_to 'Close', merge_request_path(@merge_request, merge_request: { state_event: :close }), method: :put, class: "hidden-xs hidden-sm btn btn-grouped btn-close #{merge_request_button_visibility(@merge_request, true)}", title: 'Close merge request'
= link_to 'Reopen', merge_request_path(@merge_request, merge_request: {state_event: :reopen }), method: :put, class: "hidden-xs hidden-sm btn btn-grouped btn-reopen reopen-mr-link #{merge_request_button_visibility(@merge_request, false)}", title: 'Reopen merge request'
= link_to edit_project_merge_request_path(@project, @merge_request), class: "hidden-xs hidden-sm btn btn-grouped issuable-edit" do
Edit
%li
= link_to 'Report abuse', new_abuse_report_path(user_id: @merge_request.author.id, ref_url: merge_request_url(@merge_request))
- if can_update_merge_request
= link_to 'Edit', edit_project_merge_request_path(@project, @merge_request), class: "hidden-xs hidden-sm btn btn-grouped issuable-edit"
= render 'shared/issuable/close_reopen_button', issuable: @merge_request, can_update: can_update_merge_request
- if can_update
= render 'shared/issuable/close_reopen_report_toggle', issuable: issuable
- else
= link_to 'Report abuse', new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)), class: 'hidden-xs hidden-sm btn btn-grouped btn-close-color', title: 'Report abuse'
- display_issuable_type = issuable.model_name.human.downcase
- button_action = issuable.closed? ? 'reopen' : 'close'
- display_button_action = button_action.capitalize
- button_responsive_class = 'hidden-xs hidden-sm'
- button_class = "#{button_responsive_class} btn btn-grouped js-issuable-close-button issuable-close-button"
- toggle_class = "#{button_responsive_class} btn btn-nr dropdown-toggle js-issuable-close-toggle"
- button_method = issuable.is_a?(MergeRequest) ? 'put' : ''
.pull-left.btn-group.prepend-left-10.issuable-close-dropdown.droplab-dropdown.js-issuable-close-dropdown
= link_to "#{display_button_action} #{display_issuable_type}", close_reopen_issuable_path(issuable), { method: button_method.to_s, class: "#{button_class} btn-#{button_action}", title: "#{display_button_action} #{display_issuable_type}" }
= button_tag type: 'button', class: "#{toggle_class} btn-#{button_action}-color", data: { 'dropdown-trigger' => '#issuable-close-menu' }, 'aria-label' => 'Open close dropdown' do
= icon('caret-down', class: 'toggle-icon')
%ul#issuable-close-menu.js-issuable-close-menu.dropdown-menu{ class: button_responsive_class, data: { dropdown: true } }
%li.close-item{ class: "#{issuable.closed? ? 'hidden' : 'droplab-item-selected'}", data: { text: "Close #{display_issuable_type}", url: close_issuable_path(issuable), button_class: "#{button_class} btn-close", toggle_class: "#{toggle_class} btn-close-color", method: button_method } }
%a{ href: '#' }
= icon('check')
.description
%strong
Close
= display_issuable_type
%p
%li.reopen-item{ class: "#{issuable.closed? ? 'droplab-item-selected' : 'hidden'}", data: { text: "Reopen #{display_issuable_type}", url: reopen_issuable_path(issuable), button_class: "#{button_class} btn-reopen", toggle_class: "#{toggle_class} btn-reopen-color", method: button_method } }
%a{ href: '#' }
= icon('check')
.description
%strong
Reopen
= display_issuable_type
%p
%li.divider.droplab-item-ignore
%li{ data: { text: 'Report abuse', url: new_abuse_report_path(user_id: issuable.author.id, ref_url: issuable_url(issuable)), button_class: "#{button_class} btn-close-color", toggle_class: "#{toggle_class} btn-close-color", method: '' } }
%a{ href: '#' }
= icon('check')
.description
%strong Report abuse
%p
Report
= display_issuable_type.pluralize
that are abusive, inappropriate or spam.
Loading
Loading
@@ -19,7 +19,7 @@
content_class: "filtered-search-history-dropdown-content",
title: "Recent searches" }) do
.js-filtered-search-history-dropdown{ data: { project_full_path: @project.full_path } }
.filtered-search-box-input-container
.filtered-search-box-input-container.droplab-dropdown
.scroll-container
%ul.tokens-container.list-unstyled
%li.input-token
Loading
Loading
- noteable_name = @note.noteable.human_class_name
 
.pull-left.btn-group.append-right-10.comment-type-dropdown.js-comment-type-dropdown
.pull-left.btn-group.append-right-10.droplab-dropdown.comment-type-dropdown.js-comment-type-dropdown
%input.btn.btn-nr.btn-create.comment-btn.js-comment-button.js-comment-submit-button{ type: 'submit', value: 'Comment' }
 
- if @note.can_be_discussion_note?
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment