Skip to content

Commit

Permalink
Add second set of data table action icons below the report title (#22827
Browse files Browse the repository at this point in the history
)

* Move top actions below the title
* Ensure search is functional and correctly focusing used input
* Hide top controls on dashboard
* Hide top controls when report doesn't have data
* Adjust spacing of top controls to be in line with bottom controls
* Update UI test screenshots
* Build vue files
* Move mouse out of view for UI test screenshot consistency

---------

Co-authored-by: Stefan Giehl <[email protected]>
  • Loading branch information
michalkleiner and sgiehl authored Jan 14, 2025
1 parent eb7ef0b commit 2707d39
Show file tree
Hide file tree
Showing 218 changed files with 558 additions and 510 deletions.
1 change: 1 addition & 0 deletions plugins/Actions/tests/UI/ActionsDataTable_spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ describe("ActionsDataTable", function () {
it("should exclude low population rows when exclude low population link clicked", async function() {
await page.click('.dropdownConfigureIcon');
await page.click('.dataTableExcludeLowPopulation');
await page.mouse.move(-10, -10);
await page.waitForNetworkIdle();

expect(await page.screenshot({ fullPage: true })).to.matchImage('exclude_low_population');
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
60 changes: 47 additions & 13 deletions plugins/CoreHome/javascripts/dataTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,8 @@ $.extend(DataTable.prototype, UIControl.prototype, {
'include_aggregate_rows',
'totalRows',
'pivotBy',
'pivotByColumn'
'pivotByColumn',
'filter_trigger_id'
];

for (var key = 0; key < filters.length; key++) {
Expand Down Expand Up @@ -850,8 +851,8 @@ $.extend(DataTable.prototype, UIControl.prototype, {

var $searchInput = $('.dataTableSearchInput', domElem);

function getOptimalWidthForSearchField() {
var controlBarWidth = $('.dataTableControls', domElem).width();
function getOptimalWidthForSearchField($searchAction) {
var controlBarWidth = $searchAction.parents('.dataTableControls').first().width();
var spaceLeft = controlBarWidth - $searchAction.position().left;
var idealWidthForSearchBar = 250;
var minimalWidthForSearchBar = 150; // if it's only 150 pixel we still show it on same line
Expand Down Expand Up @@ -889,18 +890,42 @@ $.extend(DataTable.prototype, UIControl.prototype, {
event.preventDefault();
event.stopPropagation();

var triggerField;
if (typeof self.param.filter_trigger_id != "undefined"
&& self.param.filter_trigger_id.length > 0) {
triggerField = document.getElementById(self.param.filter_trigger_id);
} else if (event && event.target) {
triggerField = $(event.target).siblings('input');
}

var $searchAction = $(this);
$searchAction.addClass('searchActive forceActionVisible');
var width = getOptimalWidthForSearchField();
var width = getOptimalWidthForSearchField($searchAction);
$searchAction.css('width', width + 'px');
$searchAction.find('.dataTableSearchInput').focus();

if (triggerField) {
triggerField.focus();
}

$searchAction.find('.icon-search').on('click', searchForPattern);
$searchAction.off('click', showSearch);
}

function searchForPattern() {
var keyword = $searchInput.val();
function searchForPattern(event) {
var keyword = '';
if (event) {
var $input;
if (event.target.tagName.toLowerCase() === 'input') {
$input = $(event.target);
} else if (event.target.tagName.toLowerCase() === 'span') {
$input = $(event.target).siblings('input');
}

if ($input && $input.length) {
keyword = $input.val();
self.param.filter_trigger_id = $input.attr('id');
}
}

if (!keyword && !currentPattern) {
// we search only if a keyword is actually given, or if no keyword is given and a search was performed
Expand Down Expand Up @@ -932,15 +957,19 @@ $.extend(DataTable.prototype, UIControl.prototype, {

$searchInput.on("keyup", function (e) {
if (isEnterKey(e)) {
searchForPattern();
searchForPattern(e);
} else if (isEscapeKey(e)) {
$searchAction.find('.icon-close').click();
}
});

const $dataTable = $searchInput.parents('.dataTable').first();
if (currentPattern) {
$dataTable.addClass('hasSearchKeyword');
$searchInput.val(currentPattern);
$searchAction.click();
} else {
$dataTable.removeClass('hasSearchKeyword');
}

if (this.isEmpty && !currentPattern) {
Expand Down Expand Up @@ -1239,10 +1268,15 @@ $.extend(DataTable.prototype, UIControl.prototype, {
if ((typeof self.numberOfSubtables == 'undefined' || self.numberOfSubtables == 0)
&& (typeof self.param.flat == 'undefined' || self.param.flat != 1)
) {
// if there are no subtables, remove the flatten action
const dataTableActionsVueApp = $('[vue-entry="CoreHome.DataTableActions"]', domElem).data('vueAppInstance');
if (dataTableActionsVueApp) {
dataTableActionsVueApp.showFlattenTable_ = false;
// if there are no subtables, remove the flatten action from all data table actions
const dataTableActionsVueApps = $('[vue-entry="CoreHome.DataTableActions"]', domElem);
if (dataTableActionsVueApps.length) {
dataTableActionsVueApps.each(function() {
const appData = $(this).data('vueAppInstance');
if (appData) {
appData.showFlattenTable_ = false;
}
});
}
}

Expand Down Expand Up @@ -1487,7 +1521,7 @@ $.extend(DataTable.prototype, UIControl.prototype, {
self.param.idSubtable = idSubTable;
self.param.action = self.props.subtable_controller_action;

delete self.param.totalRows;
delete self.param.totalRows;

var extraParams = {};
extraParams.comparisonIdSubtables = self.getComparisonIdSubtables($(this));
Expand Down
18 changes: 17 additions & 1 deletion plugins/CoreHome/stylesheets/dataTable/_dataTable.less
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,16 @@ td.cellSubDataTable .loadingPiwik {
overflow-x: scroll;
}
}
.dataTableHeaderControls {
margin-top: -10px;
margin-bottom: 5px;

.widgetpreview-preview .widget &,
#dashboardWidgetsArea .widget &,
.dataTable.isDataTableEmpty:not(.hasSearchKeyword) & {
display: none;
}
}

.theWidgetContent .card .card-content, table.dataTable {
div.dataTableScroller {
Expand All @@ -665,7 +675,7 @@ td.cellSubDataTable .loadingPiwik {

@media only screen and (min-width: 993px) {
#dashboardWidgetsArea .widget,
.theWidgetContent > div:not(#dashboard) {
.theWidgetContent .isDataTableEmpty {
&:hover {
.limitSelection,
.dataTableControls .dataTableAction {
Expand All @@ -681,6 +691,12 @@ td.cellSubDataTable .loadingPiwik {
}
}
}
.theWidgetContent .isDataTableEmpty.hasSearchKeyword {
.limitSelection,
.dataTableControls .dataTableAction {
visibility: visible;
}
}
}

@media only screen and (max-width: 700px) {
Expand Down
17 changes: 16 additions & 1 deletion plugins/CoreHome/templates/_dataTable.twig
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,13 @@
{% set showCardAsContentBlock = (properties.show_as_content_block and properties.show_title and not isWidget) %}
{% set showOnlyTitleWithoutCard = not showCardAsContentBlock and properties.title and properties.show_title %}

{#
using the show_footer to control the header actions as well since this is going to be refactored with the goal
of moving the table actions to the top of the report for all reports, at which point the config for the report
can be renamed to show_header and show_header_icons
#}
{% set showTableActionsInHeader = properties.show_footer and properties.show_footer_icons %}

{% if showCardAsContentBlock %}
<div class="card">
<div class="card-content">
Expand All @@ -30,7 +37,7 @@

{% set summaryRowId = constant('Piwik\\DataTable::ID_SUMMARY_ROW') %}{# ID_SUMMARY_ROW #}
{% set isSubtable = javascriptVariablesToSet.idSubtable is defined and javascriptVariablesToSet.idSubtable != 0 %}
<div class="dataTable {{ visualizationCssClass }} {{ properties.datatable_css_class|default('') }} {% if isSubtable %}subDataTable{% endif %} {% if isComparing|default(false) %}isComparing{% endif %}"
<div class="dataTable {{ visualizationCssClass }} {{ properties.datatable_css_class|default('') }}{% if isSubtable %} subDataTable{% endif %}{% if isComparing|default(false) %} isComparing{% endif %}{% if isDataTableEmpty %} isDataTableEmpty{% endif %}"
data-table-type="{{ properties.datatable_js_type }}"
data-report="{{ properties.report_id }}"
data-report-metadata="{{ reportMetdadata|json_encode|e('html_attr') }}"
Expand All @@ -50,6 +57,14 @@
{% if error is defined %}
<div vue-entry="CoreHome.Alert" severity="danger">{{ error.message }}</div>
{% else %}
{% if showTableActionsInHeader %}
<div class="row dataTableHeaderControls">
<div class="col dataTableControls s12">
{% include "@CoreHome/_dataTableActions.twig" with { placement: 'top' } %}
</div>
</div>
{% endif %}

{% if properties.show_header_message is defined and properties.show_header_message is not empty %}
<div class='datatableHeaderMessage'>{{ properties.show_header_message | raw }}</div>
{% endif %}
Expand Down
1 change: 1 addition & 0 deletions plugins/CoreHome/templates/_dataTableActions.twig
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,5 @@
view-data-table="{{ clientSideParameters.viewDataTable|json_encode }}"
pivot-dimension-name="{{ properties.pivot_dimension_name|default(null)|json_encode }}"
selectable-periods="{{ properties.selectable_periods|default([])|json_encode }}"
placement="{{ placement|default('footer')|json_encode }}"
></div>
Loading

0 comments on commit 2707d39

Please sign in to comment.