Commit 68eb55b8 authored by Mikel Martín Corrales's avatar Mikel Martín Corrales
Browse files

MDL-72565 reportbuilder: Add card view functionality

Use card view settings to show a 'card view' for custom reports in small devices
parent eab63e82
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
File suppressed by a .gitattributes entry or the file's encoding is unsupported.
......@@ -72,6 +72,7 @@ const SELECTORS = {
audienceAdd: '[data-action="add-audience"]',
audienceEdit: '[data-action="edit-audience"]',
audienceDelete: '[data-action="delete-audience"]',
toggleCardView: '[data-action="toggle-card"]',
},
};
......
......@@ -26,6 +26,13 @@ import * as reportSelectors from 'core_reportbuilder/local/selectors';
import {setPageNumber, refreshTableContent} from 'core_table/dynamic';
import * as tableSelectors from 'core_table/local/dynamic/selectors';
const CLASSES = {
COLLAPSED: 'collapsed',
EXPANDED: 'show',
ICONUP: 'fa-angle-up',
ICONDOWN: 'fa-angle-down'
};
let initialized = false;
/**
......@@ -65,5 +72,26 @@ export const init = () => {
window.openpopup(event, popupAction.jsfunctionargs);
});
// Listen for card view toggle events.
document.addEventListener('click', (event) => {
const toggleCard = event.target.closest(reportSelectors.actions.toggleCardView);
if (toggleCard) {
const tableCard = toggleCard.closest('tr');
const toggleIcon = toggleCard.querySelector('i');
event.preventDefault();
if (toggleCard.classList.contains(CLASSES.COLLAPSED)) {
tableCard.classList.add(CLASSES.EXPANDED);
toggleIcon.classList.replace(CLASSES.ICONDOWN, CLASSES.ICONUP);
toggleCard.classList.remove(CLASSES.COLLAPSED);
toggleCard.setAttribute('aria-expanded', "true");
} else {
tableCard.classList.remove(CLASSES.EXPANDED);
toggleIcon.classList.replace(CLASSES.ICONUP, CLASSES.ICONDOWN);
toggleCard.classList.add(CLASSES.COLLAPSED);
toggleCard.removeAttribute('aria-expanded');
}
}
});
initialized = true;
};
......@@ -93,6 +93,7 @@ class custom_report_table extends base_report_table {
$hasaggregatedcolumns = !empty($aggregatedcolumns);
$columnheaders = [];
$columnsattributes = [];
foreach ($columns as $column) {
$columnheading = $column->get_persistent()->get_formatted_heading($this->report->get_context());
$columnheaders[$column->get_column_alias()] = $columnheading !== '' ? $columnheading : $column->get_title();
......@@ -111,11 +112,28 @@ class custom_report_table extends base_report_table {
if (!$column->get_is_sortable()) {
$this->no_sorting($column->get_column_alias());
}
// Add column attributes needed for card view.
$settings = $this->report->get_settings_values();
$showfirsttitle = $settings['cardview_showfirsttitle'] ?? false;
$visiblecolumns = max($settings['cardview_visiblecolumns'] ?? 1, count($this->columns));
if ($showfirsttitle || $column->get_persistent()->get('columnorder') > 1) {
$column->add_attributes(['data-cardtitle' => $columnheaders[$column->get_column_alias()]]);
}
if ($column->get_persistent()->get('columnorder') > $visiblecolumns) {
$column->add_attributes(['data-cardviewhidden' => '']);
}
// Generate row attributes to be included in each cell.
$columnsattributes[$column->get_column_alias()] = $column->get_attributes();
}
$this->define_columns(array_keys($columnheaders));
$this->define_headers(array_values($columnheaders));
// Add column attributes to the table.
$this->set_columnsattributes($columnsattributes);
// Table configuration.
$this->initialbars(false);
$this->collapsible(false);
......@@ -278,4 +296,32 @@ class custom_report_table extends base_report_table {
echo $this->get_dynamic_table_html_end();
}
/**
* Override get_row_cells_html to add an extra cell with the toggle button for card view.
*
* @param string $rowid
* @param array $row
* @param array|null $suppresslastrow
* @return string
*/
public function get_row_cells_html(string $rowid, array $row, ?array $suppresslastrow): string {
$html = parent::get_row_cells_html($rowid, $row, $suppresslastrow);
// Add extra 'td' in the row with card toggle button (only visible in card view).
$visiblecolumns = $this->report->get_settings_values()['cardview_visiblecolumns'] ?? 1;
if ($visiblecolumns < count($this->columns)) {
$buttonicon = html_writer::tag('i', '', ['class' => 'fa fa-angle-down']);
$buttonatttributes = [
'type' => 'button',
'class' => 'btn collapsed',
'title' => get_string('showhide', 'core_reportbuilder', reset($row)),
'data-toggle' => 'collapse',
'data-action' => 'toggle-card'
];
$button = html_writer::tag('button', $buttonicon, $buttonatttributes);
$html .= html_writer::tag('td', $button, ['class' => 'card-toggle d-none']);
}
return $html;
}
}
......@@ -81,10 +81,14 @@
}],
"heading": "Email address"
}]
}]
}],
"cardview": {
"form": "form"
}
}
}}
<div data-region="core_reportbuilder/report"
<div class="reportbuilder-report"
data-region="core_reportbuilder/report"
data-report-id="{{id}}"
data-report-type="{{type}}"
data-parameter="[]"
......
......@@ -68,7 +68,10 @@
}],
"heading": "Email address"
}]
}]
}],
"cardview": {
"form": "form"
}
}
}}
......
......@@ -21,7 +21,9 @@
Example context (json):
{
"form": "form"
"cardview": {
"form": "form"
}
}
}}
......
......@@ -30,7 +30,8 @@
"filtersform": "form"
}
}}
<div data-region="core_reportbuilder/report"
<div class="reportbuilder-report"
data-region="core_reportbuilder/report"
data-report-id="{{id}}"
data-report-type="{{type}}"
data-parameter="{{parameters}}">
......
@core_reportbuilder @javascript
Feature: Manage card view settings in the report editor
In order to manage a report card view settings
As an admin
I need to be able to edit and save the form
Background:
Given the following "core_reportbuilder > Reports" exist:
| name | source | default |
| My report | core_user\reportbuilder\datasource\users | 0 |
And the following "core_reportbuilder > Columns" exist:
| report | uniqueidentifier |
| My report | user:fullname |
| My report | user:email |
| My report | user:city |
And the following "users" exist:
| username | firstname | lastname | email | city |
| l.smith | Lionel | Smith | lionel@smith.com | Bilbao |
Scenario: Edit card view settings form
When I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
Then I change window size to "large"
And I click on "Show/hide settings sidebar" "button"
And I click on "Show/hide 'Card view'" "button"
# Check default values.
And the following fields match these values:
| Columns visible | 1 |
| First column title | No |
And I set the following fields to these values:
| Columns visible | 3 |
| First column title | Yes |
And I press "Save changes"
And I should see "Card view settings saved"
# Let's check that after switching to preview mode card view form gets rendered again.
And I click on "Switch to preview mode" "button"
And I click on "Switch to edit mode" "button"
And I click on "Show/hide settings sidebar" "button"
And I click on "Show/hide 'Card view'" "button"
And the following fields match these values:
| Columns visible | 3 |
| First column title | Yes |
And I click on "Delete column 'Full name'" "link"
And I click on "Delete" "button" in the "Delete column 'Full name'" "dialogue"
# Check that 'Columns visible' select updates taking into account report maximum columns.
And the field "visiblecolumns" matches value "2"
And the "visiblecolumns" select box should not contain "3"
Scenario: Show Card view
When I am on the "My report" "reportbuilder > Editor" page logged in as "admin"
And I change window size to "large"
And I press "Switch to preview mode"
And I change window size to "530x812"
# Card view should just show user fullname while collapsed with default settings.
And I should see "Lionel Smith" in the "reportbuilder-table" "table"
And I should not see "lionel@smith.com" in the "reportbuilder-table" "table"
And I press "Show/hide 'Lionel Smith'"
And I should see "lionel@smith.com" in the "reportbuilder-table" "table"
And I should see "Bilbao" in the "reportbuilder-table" "table"
# Card view do not show first column title with default settings.
And "[data-cardtitle=\"Full name\"]" "css_element" should not exist in the "reportbuilder-table" "table"
And "[data-cardtitle=\"Email address\"]" "css_element" should exist in the "reportbuilder-table" "table"
And "[data-cardtitle=\"City/town\"]" "css_element" should exist in the "reportbuilder-table" "table"
# Change 'Columns visible' to 3 and 'First column title' to yes.
And I change window size to "large"
And I press "Switch to edit mode"
And I click on "Show/hide settings sidebar" "button"
And I click on "Show/hide 'Card view'" "button"
And I set the following fields to these values:
| Columns visible | 3 |
| First column title | Yes |
And I press "Save changes"
# Check now all the columns are shown in the card and there is no toggle button.
And I press "Switch to preview mode"
And I change window size to "530x812"
And I should see "Lionel Smith" in the "reportbuilder-table" "table"
And I should see "lionel@smith.com" in the "reportbuilder-table" "table"
And I should see "Bilbao" in the "reportbuilder-table" "table"
And "[data-cardtitle=\"Full name\"]" "css_element" should exist in the "reportbuilder-table" "table"
And "[data-cardtitle=\"Email address\"]" "css_element" should exist in the "reportbuilder-table" "table"
And "[data-cardtitle=\"City/town\"]" "css_element" should exist in the "reportbuilder-table" "table"
And "Show/hide 'Lionel Smith'" "button" should not exist
......@@ -112,6 +112,7 @@ class get_test extends externallib_advanced_testcase {
$this->assertEmpty($result['filters']);
$this->assertEmpty($result['conditions']);
$this->assertEmpty($result['sorting']);
$this->assertEmpty($result['cardview']);
}
/**
......
......@@ -254,3 +254,76 @@
}
}
}
/* Report table card view styles */
@mixin table-cards {
table.reportbuilder-table {
thead {
display: none;
}
tr {
display: flex;
flex-direction: column;
margin: .5rem 0;
padding: .25rem .5rem 0 .5rem;
background-color: $card-bg !important; /* stylelint-disable-line declaration-no-important */
word-wrap: break-word;
background-clip: border-box;
border: $card-border-width solid $card-border-color;
@include border-radius($card-border-radius);
&:hover {
background-color: $card-bg !important; /* stylelint-disable-line declaration-no-important */
}
&.emptyrow {
display: none;
}
&:not(.show) {
td[data-cardviewhidden] {
display: none;
}
}
td {
display: block;
min-height: 3.6rem;
padding: .5rem .25rem;
border: none;
&::before {
content: attr(data-cardtitle);
display: block;
text-transform: uppercase;
font-size: 70%;
color: $gray-800;
}
&:not([data-cardtitle]) {
min-height: 3rem;
}
&:not(:first-child):not(.card-toggle) {
border-top: $card-border-width solid $card-border-color;
}
&:first-child {
padding-right: 2rem;
}
}
td.card-toggle {
display: block !important; /* stylelint-disable-line declaration-no-important */
position: absolute;
right: 10px;
button {
padding: 0 .5rem;
color: $gray-600;
i {
font-size: 1.5em;
font-weight: bold;
}
}
}
}
}
}
/* Report table card view for small screens */
.reportbuilder-report[data-report-type="0"]:not([data-editing]) {
@include media-breakpoint-down(xs) {
@include table-cards;
}
}
......@@ -20816,6 +20816,58 @@ div.editor_atto_toolbar button .icon {
.reportbuilder-audiences-container .instance-card .card-header i.icon {
margin-right: 0; }
 
/* Report table card view styles */
/* Report table card view for small screens */
@media (max-width: 575.98px) {
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table thead {
display: none; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr {
display: flex;
flex-direction: column;
margin: .5rem 0;
padding: .25rem .5rem 0 .5rem;
background-color: #fff !important;
/* stylelint-disable-line declaration-no-important */
word-wrap: break-word;
background-clip: border-box;
border: 1px solid rgba(0, 0, 0, 0.125);
border-radius: 0.25rem; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr:hover {
background-color: #fff !important;
/* stylelint-disable-line declaration-no-important */ }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr.emptyrow {
display: none; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr:not(.show) td[data-cardviewhidden] {
display: none; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td {
display: block;
min-height: 3.6rem;
padding: .5rem .25rem;
border: none; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td::before {
content: attr(data-cardtitle);
display: block;
text-transform: uppercase;
font-size: 70%;
color: #343a40; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td:not([data-cardtitle]) {
min-height: 3rem; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td:not(:first-child):not(.card-toggle) {
border-top: 1px solid rgba(0, 0, 0, 0.125); }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td:first-child {
padding-right: 2rem; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td.card-toggle {
display: block !important;
/* stylelint-disable-line declaration-no-important */
position: absolute;
right: 10px; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td.card-toggle button {
padding: 0 .5rem;
color: #6a737b; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td.card-toggle button i {
font-size: 1.5em;
font-weight: bold; } }
.courseindex .courseindex-heading {
padding: 0.5rem 1rem; }
 
......
......@@ -20762,6 +20762,58 @@ div.editor_atto_toolbar button .icon {
.reportbuilder-audiences-container .instance-card .card-header i.icon {
margin-right: 0; }
 
/* Report table card view styles */
/* Report table card view for small screens */
@media (max-width: 575.98px) {
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table thead {
display: none; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr {
display: flex;
flex-direction: column;
margin: .5rem 0;
padding: .25rem .5rem 0 .5rem;
background-color: #fff !important;
/* stylelint-disable-line declaration-no-important */
word-wrap: break-word;
background-clip: border-box;
border: 1px solid rgba(0, 0, 0, 0.125);
border-radius: 0.25rem; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr:hover {
background-color: #fff !important;
/* stylelint-disable-line declaration-no-important */ }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr.emptyrow {
display: none; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr:not(.show) td[data-cardviewhidden] {
display: none; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td {
display: block;
min-height: 3.6rem;
padding: .5rem .25rem;
border: none; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td::before {
content: attr(data-cardtitle);
display: block;
text-transform: uppercase;
font-size: 70%;
color: #343a40; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td:not([data-cardtitle]) {
min-height: 3rem; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td:not(:first-child):not(.card-toggle) {
border-top: 1px solid rgba(0, 0, 0, 0.125); }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td:first-child {
padding-right: 2rem; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td.card-toggle {
display: block !important;
/* stylelint-disable-line declaration-no-important */
position: absolute;
right: 10px; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td.card-toggle button {
padding: 0 .5rem;
color: #6a737b; }
.reportbuilder-report[data-report-type="0"]:not([data-editing]) table.reportbuilder-table tr td.card-toggle button i {
font-size: 1.5em;
font-weight: bold; } }
.courseindex .courseindex-heading {
padding: 0.5rem 1rem; }
 
......
Supports Markdown
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