Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX Clear filter from url state #1580

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion client/dist/js/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion client/dist/js/vendor.js

Large diffs are not rendered by default.

69 changes: 48 additions & 21 deletions client/src/legacy/GridField.js
sabina-talipova marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -200,42 +200,69 @@ $.entwine('ss', function($) {
}
},

/**
* This will first retrieve state of the gridfield which is generated by PHP and sent to the
* browser as HTML via PJAX and stored in the data-schema attribute on all of the '3 dots'
* elements on each gridfield row
*
* It will then update the browser location with the new state of the gridfield using
* window.ss.router
*
* This allows users to bookmark different views in the CMS
*/
keepStateInHistory: function() {
const newSchema = $(this).find('.gridfield-actionmenu__container').data('schema');
const gridFieldName = $(this).data('name');
if (newSchema && newSchema.length > 0) {
newSchema.filter( e => {
if (e.type === 'link') {
const reqString = this.buildURLString(e.url)
const searchParam = reqString ? '?' + reqString.join('&') : '';
window.ss.router.replace(window.location.pathname + searchParam, undefined, undefined, false);
const urlQueryString = this.buildUrlQueryString(e.url, gridFieldName);
sabina-talipova marked this conversation as resolved.
Show resolved Hide resolved
const url = window.location.pathname + urlQueryString;
window.ss.router.replace(url, undefined, undefined, false);
}
})
}
},

/**
* A params string can have duplicate keys.
* Function buildURLString splits string to "key => value" array
* and replaces values for existing keys with the new value
* and returns string with unique keys only
* Builds a url query string from the existing query string in window.location
* and overrides it with the params from the query string in the pjaxUrl param
*
* For any query string params that relate to the gridState of the gridFieldName, only
* take these from the pjaxUrl param
*
* @param {string} url
* @returns string
*/
buildURLString: function(url) {
const link = [window.location.origin, url].join('/');
const params = [window.location.search, (new URL(link)).searchParams.toString()].join('&').substring(1);
const newrequest = [];
const reqString = [];
params.split('&').forEach(param => {
const newVal = param.split('=');
newrequest[newVal[0]] = newVal[1] ? newVal[1] : '';
});
Object.keys(newrequest).forEach(param => {
reqString.push([param, newrequest[param]].join('='));
});

return reqString;
buildUrlQueryString: function(pjaxUrl, gridFieldName) {
const locationObj = {};
for (const param of window.location.search.replace(/^\?/, '').split('&')) {
const [key, val] = param.split('=');
// This regex will naively match the gridfield number \-[0-9]$, so if there are multiple
// gridfields with the same name (i.e. class) on the screen, it will be overly
// aggressive in removing their state. This limitation is because I couldn't find an
// easy way to extract the gridfield number from the gridfield
if (key.match(new RegExp(`^gridState\\-${gridFieldName}\\-[0-9]$`))) {
continue;
}
locationObj[key] = val;
}
const pjaxUrlObj = {};
const link = [window.location.origin, pjaxUrl].join('/');
const searchParams = (new URL(link)).searchParams;
for (const [key, val] of searchParams.entries()) {
pjaxUrlObj[key] = val;
}
const retObj = Object.assign(locationObj, pjaxUrlObj);
const retArr = [];
for (const key in retObj) {
if (key === '') {
continue;
}
const val = encodeURIComponent(retObj[key]);
retArr.push([key, val].join('='));
}
return retArr.length === 0 ? '' : '?' + retArr.join('&');
}
});

Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
"require-dev": {
"phpunit/phpunit": "^9.5",
"silverstripe/frameworktest": "^0.4.3",
"silverstripe/frameworktest": "^0.4.14",
"squizlabs/php_codesniffer": "^3",
"nikic/php-parser": "^3 || ^4",
"monolog/monolog": "~1.16"
Expand Down
28 changes: 26 additions & 2 deletions tests/behat/features/gridfield-search.feature
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,15 @@ Feature: Search in GridField
So that I see proper result and don't see warning

Background:
Given the "Company" "Walmart" with "Category"="Retail"
And the "Company" "ExxonMobil" with "Category"="Oil"
Given the "Company" "ExxonMobil" with "Category"="Oil"
And the "Company" "Vitol" with "Category"="Other"
And the "Company" "Walmart" with "Category"="Retail"
And the "Company" "Walmart B" with "Category"="Retail"
And the "Company" "Walmart C" with "Category"="Retail"
And the "Company" "Walmart D" with "Category"="Retail"
And the "group" "EDITOR" has permissions "Access to 'Pages' section" and "Access to 'Test ModelAdmin' section" and "TEST_DATAOBJECT_EDIT"
# This extension will limit to only showing 3 records per page so that pagination shows
And I add an extension "FrameworkTestModelAdminExtension" to the "TestModelAdmin" class
And I am logged in as a member of "EDITOR" group
And I go to "/admin/test"

Expand All @@ -23,3 +28,22 @@ Feature: Search in GridField
And I click "Walmart" in the "#Form_EditForm" element
Then I should see "Walmart"
And I should see "Walmart" in the ".breadcrumbs-wrapper" element

Scenario: I can clear search and paginate
When I press the "Open search and filter" button
# This will match on all of the "Walmart" records
And I fill in "SearchBox__q" with "a a"
And I press the "Enter" key in the "SearchBox__q" field
Then the "[name=SearchBox__q]" element "value" attribute should be "a a"
sabina-talipova marked this conversation as resolved.
Show resolved Hide resolved
And I should see "Walmart" in the ".ss-gridfield-item:nth-of-type(1) .col-Name" element
And I should see "Walmart B" in the ".ss-gridfield-item:nth-of-type(2) .col-Name" element
And I should see "Walmart C" in the ".ss-gridfield-item:nth-of-type(3) .col-Name" element
And I should not see "ExxonMobil" in the ".col-Name" element
And I should not see "Vitol" in the ".col-Name" element
And I click on the ".search-box__cancel" element
When I click on the "#action_pagination_next" element
And I press the "Open search and filter" button
Then the "[name=SearchBox__q]" element "value" attribute should be ""
sabina-talipova marked this conversation as resolved.
Show resolved Hide resolved
And I should see "Walmart B" in the ".ss-gridfield-item:nth-of-type(1) .col-Name" element
And I should see "Walmart C" in the ".ss-gridfield-item:nth-of-type(2) .col-Name" element
And I should see "Walmart D" in the ".ss-gridfield-item:nth-of-type(3) .col-Name" element
sabina-talipova marked this conversation as resolved.
Show resolved Hide resolved
Loading