Skip to content

Commit

Permalink
Fix TV Category not found in Template and TV editing panels (#16610)
Browse files Browse the repository at this point in the history
### What does it do?
Changed the (grid filtering) category combo configs to:
1. Prevent submission of their values on post
2. Not create a hidden submit field
3. Ignore the initial request value of "undefined" when creating a new
Template/TV

The first commit contains the functional changes, while the remaining
ones provide code style and quality fixes.

### Why is it needed?
A change somewhere in the current development branch created a condition
where form panel pages with both a Category field and a Category grid
filter would not save properly. (This is seen only in the current
3.1.0-dev branch.)

**Note:** I added the "Urgent" label to this PR because we'll need it
incorporated into 3.1 _before_ its -pl release, as the issue it solves
prevents proper operation of the referenced panels.

### How to test

1. Before pulling down this PR, observe that when trying to create a new
TV or Template, you are prevented from doing so. The Category field will
always have an error, not matter what you do. Also, if you go to the
Template Access tab of a TV and filter the grid by Category using the
dropdown and then immediately save, note how the Category of the TV
itself will have been changed to the one you chose in the grid filter
(not what you want).
2. After applying this PR, create and edit a Template and a TV to verify
you are able to save and update each as expected, and that filtering on
the TV/Template Access grids within each does not affect the saved
Element's Category.

### Related issue(s)/PR(s)
None, I discovered this issue when I was working on another PR.
  • Loading branch information
smg6511 authored Sep 3, 2024
1 parent aab292e commit df9bed8
Show file tree
Hide file tree
Showing 5 changed files with 1,629 additions and 1,576 deletions.
4 changes: 4 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@ module.exports = {
'one-var': ['error', 'consecutive'],
'prefer-arrow-callback': 'warn',
'prefer-rest-params': 'warn',
'semi-spacing': ['warn', {
before: false,
after: true
}],
'semi-style': ['warn', 'last'],
'space-before-function-paren': ['error', 'never']
}
Expand Down
246 changes: 129 additions & 117 deletions manager/assets/modext/widgets/element/modx.grid.template.tv.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,19 @@
* @param {Object} config An object of options.
* @xtype modx-grid-template-tv
*/
// eslint-disable-next-line func-names
MODx.grid.TemplateTV = function(config = {}) {
const tt = new Ext.ux.grid.CheckColumn({
header: _('access')
,dataIndex: 'access'
,width: 70
,sortable: true
const accessCheckboxCol = new Ext.ux.grid.CheckColumn({
header: _('access'),
dataIndex: 'access',
width: 70,
sortable: true
});
Ext.applyIf(config,{
title: _('template_assignedtv_tab')
,id: 'modx-grid-template-tv'
,url: MODx.config.connector_url
,fields: [
Ext.applyIf(config, {
title: _('template_assignedtv_tab'),
id: 'modx-grid-template-tv',
url: MODx.config.connector_url,
fields: [
'id',
'name',
'caption',
Expand All @@ -26,74 +27,80 @@ MODx.grid.TemplateTV = function(config = {}) {
'perm',
'category_name',
'category'
]
,baseParams: {
action: 'Element/Template/TemplateVar/GetList'
,template: config.template
,sort: 'tv_rank'
,category: MODx.request.category || null
}
,saveParams: {
],
baseParams: {
action: 'Element/Template/TemplateVar/GetList',
template: config.template,
sort: 'tv_rank',
category: MODx.request.category || null
},
saveParams: {
template: config.template
}
,width: 800
,paging: true
,plugins: tt
,remoteSort: true
,sortBy: 'category_name, tv_rank'
,grouping: true
,groupBy: 'category_name'
,singleText: _('tv')
,pluralText: _('tvs')
,enableDragDrop: true
,ddGroup : 'template-tvs-ddsort'
,sm: new Ext.grid.RowSelectionModel({
singleSelect: true
,listeners: {
},
width: 800,
paging: true,
plugins: accessCheckboxCol,
remoteSort: true,
sortBy: 'category_name, tv_rank',
grouping: true,
groupBy: 'category_name',
singleText: _('tv'),
pluralText: _('tvs'),
enableDragDrop: true,
ddGroup: 'template-tvs-ddsort',
sm: new Ext.grid.RowSelectionModel({
singleSelect: true,
listeners: {
beforerowselect: function(sm, idx, keep, record) {
sm.grid.ddText = '<div>'+ record.data.name +'</div>';
// eslint-disable-next-line no-param-reassign
sm.grid.ddText = `<div>${record.data.name}</div>`;
}
}
})
,columns: [{
header: _('name')
,dataIndex: 'name'
,width: 150
,sortable: true
,renderer: { fn: function(v,md,record) {
return this.renderLink(v, {
href: '?a=element/tv/update&id=' + record.data.id
,target: '_blank'
});
}, scope: this }
},{
header: _('category')
,dataIndex: 'category_name'
,width: 150
,sortable: true
},{
header: _('caption')
,dataIndex: 'caption'
,width: 350
,sortable: false
},tt,{
header: _('rank')
,dataIndex: 'tv_rank'
,width: 100
,editor: { xtype: 'textfield' ,allowBlank: false }
,sortable: true
}]
,tbar: [
}),
columns: [{
header: _('name'),
dataIndex: 'name',
width: 150,
sortable: true,
renderer: {
fn: function(value, metadata, record) {
return this.renderLink(value, {
href: `?a=element/tv/update&id=${record.data.id}`,
target: '_blank'
});
},
scope: this
}
}, {
header: _('category'),
dataIndex: 'category_name',
width: 150,
sortable: true
}, {
header: _('caption'),
dataIndex: 'caption',
width: 350,
sortable: false
}, accessCheckboxCol, {
header: _('rank'),
dataIndex: 'tv_rank',
width: 100,
editor: { xtype: 'textfield', allowBlank: false },
sortable: true
}],
tbar: [
'->',
{
xtype: 'modx-combo-category'
,itemId: 'filter-category'
,emptyText: _('filter_by_category')
,value: MODx.request.category || null
,width: 200
,listeners: {
xtype: 'modx-combo-category',
itemId: 'filter-category',
emptyText: _('filter_by_category'),
value: MODx.request.category !== 'undefined' ? MODx.request.category : null,
submitValue: false,
hiddenName: '',
width: 200,
listeners: {
select: {
fn: function (cmp, record, selectedIndex) {
fn: function(cmp, record, selectedIndex) {
this.applyGridFilter(cmp, 'category');
},
scope: this
Expand All @@ -104,83 +111,88 @@ MODx.grid.TemplateTV = function(config = {}) {
this.getClearFiltersButton('filter-category, filter-query')
]
});
MODx.grid.TemplateTV.superclass.constructor.call(this,config);
MODx.grid.TemplateTV.superclass.constructor.call(this, config);
this.on('render', this.prepareDDSort, this);
};
Ext.extend(MODx.grid.TemplateTV,MODx.grid.Grid,{
Ext.extend(MODx.grid.TemplateTV, MODx.grid.Grid, {
getMenu: function() {
var r = this.getSelectionModel().getSelected();
var p = r.data.perm;
var m = [];

if (p.indexOf('pedit') != -1) {
m.push({
text: _('edit')
,handler: this.updateTV
const
record = this.getSelectionModel().getSelected(),
permissions = record.data.perm,
menu = []
;
if (permissions.indexOf('pedit') !== -1) {
menu.push({
text: _('edit'),
handler: this.updateTV
});
}
return m;
}

,updateTV: function(itm,e) {
MODx.loadPage('element/tv/update', 'id='+this.menu.record.id);
}
return menu;
},

,sortTVs: function(sourceNode, targetNode) {
var store = this.getStore();
var sourceIdx = store.indexOf(sourceNode);
var targetIdx = store.indexOf(targetNode);
updateTV: function(itm, e) {
MODx.loadPage('element/tv/update', `id=${this.menu.record.id}`);
},

sortTVs: function(sourceNode, targetNode) {
const
store = this.getStore(),
sourceIdx = store.indexOf(sourceNode),
targetIdx = store.indexOf(targetNode)
;
// Insert the selection to the target (and remove original selection)
store.removeAt(sourceIdx);
store.insert(targetIdx, sourceNode);

// Extract the store items with the same category_name as the sourceNode to start the index at 0 for each category
var filteredStore = store.queryBy(function(rec, id) {
if (rec.get('category_name') === sourceNode.get('category_name')) {
// eslint-disable-next-line func-names, prefer-arrow-callback
const filteredStore = store.queryBy(function(record, id) {
if (record.get('category_name') === sourceNode.get('category_name')) {
return true;
}
return false;
}, this);

// Loop trough the filtered store and re-apply the re-calculated ranks to the store records
// eslint-disable-next-line func-names, prefer-arrow-callback
Ext.each(filteredStore.items, function(item, index, allItems) {
if (sourceNode.get('category_name') === item.get('category_name')) {
var record = store.getById(item.id);
const record = store.getById(item.id);
record.set('tv_rank', index);
}
}, this);
}
},

,prepareDDSort: function(grid) {
prepareDDSort: function(grid) {
this.dropTarget = new Ext.dd.DropTarget(grid.getView().mainBody, {
ddGroup: 'template-tvs-ddsort'
,copy: false
,notifyOver: function(dragSource, e, data) {
ddGroup: 'template-tvs-ddsort',
copy: false,
notifyOver: function(dragSource, e, data) {
if (dragSource.getDragData(e)) {
var targetNode = dragSource.getDragData(e).selections[0];
var sourceNode = data.selections[0];

if ((sourceNode.data['category_name'] != targetNode.data['category_name']) ||
!sourceNode.data['access'] ||
!targetNode.data['access'] ||
(sourceNode.data['id'] == targetNode.data['id'])
) {
const
targetNode = dragSource.getDragData(e).selections[0],
sourceNode = data.selections[0]
;
if ((sourceNode.data.category_name !== targetNode.data.category_name)
|| !sourceNode.data.access
|| !targetNode.data.access
|| (sourceNode.data.id === targetNode.data.id)
) {
return this.dropNotAllowed;
}

return this.dropAllowed;
}

return this.dropNotAllowed;
}
,notifyDrop : function(dragSource, e, data) {
},
notifyDrop: function(dragSource, e, data) {
if (dragSource.getDragData(e)) {
var targetNode = dragSource.getDragData(e).selections[0];
var sourceNode = data.selections[0];
if ((targetNode.id != sourceNode.id) &&
(targetNode.get('category_name') === sourceNode.get('category_name')) &&
sourceNode.get('access')
const
targetNode = dragSource.getDragData(e).selections[0],
sourceNode = data.selections[0]
;
if ((targetNode.id !== sourceNode.id)
&& (targetNode.get('category_name') === sourceNode.get('category_name'))
&& sourceNode.get('access')
) {
grid.sortTVs(sourceNode, targetNode);
}
Expand All @@ -189,4 +201,4 @@ Ext.extend(MODx.grid.TemplateTV,MODx.grid.Grid,{
});
}
});
Ext.reg('modx-grid-template-tv',MODx.grid.TemplateTV);
Ext.reg('modx-grid-template-tv', MODx.grid.TemplateTV);
Loading

0 comments on commit df9bed8

Please sign in to comment.