Commit 07989af1 authored by Jacob Schatz's avatar Jacob Schatz

Merge branch '13664-abuse-report-page-should-have-a-maximum-width' into 'master'

Abuse Reports message truncation

## What does this MR do?

Adds dynamic message truncation to abuse reports

## Are there points in the code the reviewer needs to double check?

Is the new UI OK?

## Why was this MR needed?

Admin UX

## What are the relevant issue numbers?

Closes #13664.

## Screenshots (if relevant)

**UPDATED:**

![Screen_Shot_2016-07-07_at_03.02.43](/uploads/2e1a1122e0194f8ffa48054c18523ccd/Screen_Shot_2016-07-07_at_03.02.43.png)

## Does this MR meet the acceptance criteria?

- [ ] [CHANGELOG](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CHANGELOG) entry added
- [ ] [Documentation created/updated](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/development/doc_styleguide.md)
- [ ] API support added
- Tests
  - [ ] Added for this feature/bug
  - [ ] All builds are passing
- [x] Conform by the [style guides](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/CONTRIBUTING.md#style-guides)
- [x] Branch has no merge conflicts with `master` (if you do - rebase it please)
- [x] [Squashed related commits together](https://git-scm.com/book/en/Git-Tools-Rewriting-History#Squashing-Commits)
Closes #13664

See merge request !5032
parents 2b487edc 32060d45
window.gl = window.gl || {};
((global) => {
const MAX_MESSAGE_LENGTH = 500;
const MESSAGE_CELL_SELECTOR = '.abuse-reports .message';
class AbuseReports {
constructor() {
$(MESSAGE_CELL_SELECTOR).each(this.truncateLongMessage);
$(document)
.off('click', MESSAGE_CELL_SELECTOR)
.on('click', MESSAGE_CELL_SELECTOR, this.toggleMessageTruncation);
}
truncateLongMessage() {
const $messageCellElement = $(this);
const reportMessage = $messageCellElement.text();
if (reportMessage.length > MAX_MESSAGE_LENGTH) {
$messageCellElement.data('original-message', reportMessage);
$messageCellElement.data('message-truncated', 'true');
$messageCellElement.text(global.text.truncate(reportMessage, MAX_MESSAGE_LENGTH));
}
}
toggleMessageTruncation() {
const $messageCellElement = $(this);
const originalMessage = $messageCellElement.data('original-message');
if (!originalMessage) return;
if ($messageCellElement.data('message-truncated') === 'true') {
$messageCellElement.data('message-truncated', 'false');
$messageCellElement.text(originalMessage);
} else {
$messageCellElement.data('message-truncated', 'true');
$messageCellElement.text(`${originalMessage.substr(0, (MAX_MESSAGE_LENGTH - 3))}...`);
}
}
}
global.AbuseReports = AbuseReports;
})(window.gl);
......@@ -196,6 +196,9 @@
case 'edit':
new Labels();
}
case 'abuse_reports':
new gl.AbuseReports();
break;
}
break;
case 'dashboard':
......
......@@ -104,9 +104,12 @@
return self.updateText($this.closest('.md-area').find('textarea'), $this.data('md-tag'), $this.data('md-block'), !$this.data('md-prepend'));
});
};
return gl.text.removeListeners = function(form) {
gl.text.removeListeners = function(form) {
return $('.js-md', form).off();
};
return gl.text.truncate = function(string, maxLength) {
return string.substr(0, (maxLength - 3)) + '...';
};
})(window);
}).call(this);
......@@ -72,7 +72,6 @@
margin-bottom: 20px;
}
// Users List
.users-list {
......@@ -98,3 +97,44 @@
}
}
}
.abuse-reports {
.table {
table-layout: fixed;
}
.subheading {
padding-bottom: $gl-padding;
}
.message {
word-wrap: break-word;
}
.btn {
white-space: normal;
padding: $gl-btn-padding;
}
th {
width: 15%;
&.wide {
width: 55%;
}
}
@media (max-width: $screen-sm-max) {
th {
width: 100%;
}
td {
width: 100%;
float: left;
}
}
.no-reports {
.emoji-icon {
margin-left: $btn-side-margin;
margin-top: 3px;
}
span {
font-size: 19px;
}
}
}
- reporter = abuse_report.reporter
- user = abuse_report.user
%tr
%th.visible-xs-block.visible-sm-block
%strong User
%td
- if user
= link_to user.name, user
......@@ -9,6 +11,7 @@
- else
(removed)
%td
%strong.subheading.visible-xs-block.visible-sm-block Reported by
- if reporter
= link_to reporter.name, reporter
- else
......@@ -16,16 +19,16 @@
.light.small
= time_ago_with_tooltip(abuse_report.created_at)
%td
= markdown(abuse_report.message.squish!, pipeline: :single_line, author: reporter)
%strong.subheading.visible-xs-block.visible-sm-block Message
.message
= markdown(abuse_report.message.squish!, pipeline: :single_line, author: reporter)
%td
- if user
= link_to 'Remove user & report', admin_abuse_report_path(abuse_report, remove_user: true),
data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" }, remote: true, method: :delete, class: "btn btn-xs btn-remove js-remove-tr"
%td
data: { confirm: "USER #{user.name} WILL BE REMOVED! Are you sure?" }, remote: true, method: :delete, class: "btn btn-sm btn-block btn-remove js-remove-tr"
- if user && !user.blocked?
= link_to 'Block user', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "btn btn-xs"
= link_to 'Block user', block_admin_user_path(user), data: {confirm: 'USER WILL BE BLOCKED! Are you sure?'}, method: :put, class: "btn btn-sm btn-block"
- else
.btn.btn-xs.disabled
.btn.btn-sm.disabled.btn-block
Already Blocked
= link_to 'Remove report', [:admin, abuse_report], remote: true, method: :delete, class: "btn btn-xs btn-close js-remove-tr"
= link_to 'Remove report', [:admin, abuse_report], remote: true, method: :delete, class: "btn btn-sm btn-block btn-close js-remove-tr"
- page_title "Abuse Reports"
- page_title 'Abuse Reports'
%h3.page-title Abuse Reports
%hr
- if @abuse_reports.present?
.table-holder
%table.table
%thead
%tr
%th User
%th Reported by
%th Message
%th Primary action
%th
= render @abuse_reports
= paginate @abuse_reports
- else
%h4 There are no abuse reports
.abuse-reports
- if @abuse_reports.present?
.table-holder
%table.table
%thead.hidden-sm.hidden-xs
%tr
%th User
%th Reported by
%th.wide Message
%th Action
= render @abuse_reports
- else
.no-reports
%span.pull-left
There are no abuse reports!
.pull-left
= emoji_icon 'tada'
/*= require abuse_reports */
/*= require jquery */
((global) => {
const FIXTURE = 'abuse_reports.html';
const MAX_MESSAGE_LENGTH = 500;
function assertMaxLength($message) {
expect($message.text().length).toEqual(MAX_MESSAGE_LENGTH);
}
describe('Abuse Reports', function() {
fixture.preload(FIXTURE);
beforeEach(function() {
fixture.load(FIXTURE);
new global.AbuseReports();
});
it('should truncate long messages', function() {
const $longMessage = $('#long');
expect($longMessage.data('original-message')).toEqual(jasmine.anything());
assertMaxLength($longMessage);
});
it('should not truncate short messages', function() {
const $shortMessage = $('#short');
expect($shortMessage.data('original-message')).not.toEqual(jasmine.anything());
});
it('should allow clicking a truncated message to expand and collapse the full message', function() {
const $longMessage = $('#long');
$longMessage.click();
expect($longMessage.data('original-message').length).toEqual($longMessage.text().length);
$longMessage.click();
assertMaxLength($longMessage);
});
});
})(window.gl);
.abuse-reports
.message#long
Cat ipsum dolor sit amet, hide head under blanket so no one can see.
Gate keepers of hell eat and than sleep on your face but hunt by meowing
loudly at 5am next to human slave food dispenser cats go for world
domination or chase laser, yet poop on grasses chirp at birds. Cat is love,
cat is life chase after silly colored fish toys around the house climb a
tree, wait for a fireman jump to fireman then scratch his face fall asleep
on the washing machine lies down always hungry so caticus cuteicus. Sit on
human. Spot something, big eyes, big eyes, crouch, shake butt, prepare to
pounce sleep in the bathroom sink hiss at vacuum cleaner hide head under
blanket so no one can see throwup on your pillow.
.message#short
Cat ipsum dolor sit amet, groom yourself 4 hours - checked, have your
beauty sleep 18 hours - checked, be fabulous for the rest of the day -
checked! for shake treat bag.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment