salix/front/core/components/contextmenu/index.js

225 lines
5.5 KiB
JavaScript
Raw Normal View History

2020-05-28 06:07:26 +00:00
import ngModule from '../../module';
2020-06-09 10:16:40 +00:00
import {buildFilter} from 'vn-loopback/util/filter';
2020-06-08 11:15:48 +00:00
import './style.scss';
2020-05-28 06:07:26 +00:00
export default class Contextmenu {
2020-05-29 09:10:58 +00:00
constructor($element, $, $transclude) {
2020-05-28 06:07:26 +00:00
this.$element = $element;
this.element = $element[0];
this.$ = $;
2020-05-29 09:10:58 +00:00
this.$transclude = $transclude;
2020-05-28 06:07:26 +00:00
}
2020-05-29 09:10:58 +00:00
get targets() {
return this._targets;
}
set targets(value) {
this._targets = value;
2020-05-28 06:07:26 +00:00
if (!value) return;
2020-05-29 09:10:58 +00:00
for (let selector of value) {
2020-06-08 10:14:27 +00:00
const target = document.querySelector(selector);
2020-05-29 09:10:58 +00:00
if (!target) continue;
2020-05-28 06:07:26 +00:00
2020-05-29 09:10:58 +00:00
target.addEventListener('contextmenu', event => {
2020-06-08 10:14:27 +00:00
this.target = event.target;
2020-05-29 09:10:58 +00:00
if (!event.defaultPrevented)
event.preventDefault();
2020-05-28 06:07:26 +00:00
2020-06-08 10:14:27 +00:00
if (!this.isFilterEnabled()) return;
2020-05-29 09:10:58 +00:00
const parent = this.$.contextmenu;
parent.style.top = event.pageY + 'px';
parent.style.left = event.pageX + 'px';
2020-05-28 06:07:26 +00:00
2020-05-29 09:10:58 +00:00
this.$.menu.show(parent);
});
}
}
2020-06-08 10:14:27 +00:00
get row() {
if (!this.target) return null;
return this.target.closest('vn-tr, .vn-tr');
}
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
get rowIndex() {
if (!this.row) return null;
const table = this.row.closest('vn-table, .vn-table');
const tBody = table.querySelector('vn-tbody, .vn-tbody');
const rows = tBody.querySelectorAll('vn-tr, .vn-tr');
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
return Array.from(rows).findIndex(
rowItem => rowItem == this.row
);
}
get rowData() {
2020-05-29 09:10:58 +00:00
const model = this.model;
2020-06-08 10:14:27 +00:00
const rowData = model.data[this.rowIndex];
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
return rowData;
}
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
get cell() {
if (!this.target) return null;
2020-05-29 09:10:58 +00:00
return this.target.closest('vn-td, .vn-td, vn-td-editable');
2020-06-08 10:14:27 +00:00
}
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
get cellIndex() {
if (!this.row) return null;
2020-05-29 09:10:58 +00:00
const cells = this.row.querySelectorAll('vn-td, .vn-td, vn-td-editable');
2020-06-08 10:14:27 +00:00
return Array.from(cells).findIndex(
cellItem => cellItem == this.cell
);
}
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
get rowHeader() {
if (!this.row) return null;
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
const table = this.row.closest('vn-table, .vn-table');
const headerCells = table && table.querySelectorAll('vn-thead vn-th');
const headerCell = headerCells && headerCells[this.cellIndex];
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
return headerCell;
2020-05-29 09:10:58 +00:00
}
2020-06-08 10:14:27 +00:00
/**
* Selected model field name
*
* @return {string}
*/
get fieldName() {
if (!this.rowHeader) return null;
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
return this.rowHeader.getAttribute('field');
}
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
/**
* Selected field value
*
* @return {any}
*/
get fieldValue() {
return this.rowData[this.fieldName];
}
/**
* Returns true if filter is not disabled
*
* @return {Boolean}
*/
isFilterEnabled() {
if (!this.rowHeader) return true;
const isEnabled = this.rowHeader.getAttribute('filter-enabled');
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
return isEnabled != 'false';
}
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
/**
* Returns true if filter
* by selection is allowed
*
* @return {Boolean}
*/
isFilterAllowed() {
if (!this.target) return false;
const isTableCell = this.target.closest('vn-td, .vn-td');
return isTableCell && this.fieldName;
}
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
/**
* Filter by current field selection
*/
filterBySelection() {
2020-06-09 10:16:40 +00:00
let where = {[this.fieldName]: this.fieldValue};
if (this.exprBuilder) {
where = buildFilter(where, (param, value) =>
this.exprBuilder({param, value})
);
}
2020-05-29 09:10:58 +00:00
2020-06-09 10:16:40 +00:00
this.model.addFilter({where});
2020-06-08 10:14:27 +00:00
}
2020-05-29 09:10:58 +00:00
2020-06-08 10:14:27 +00:00
/**
* Exclude by current field selection
*/
excludeSelection() {
2020-06-09 10:16:40 +00:00
let where = {[this.fieldName]: {neq: this.fieldValue}};
if (this.exprBuilder) {
where = buildFilter(where, (param, value) =>
this.exprBuilder({param, value})
);
}
2020-05-29 09:10:58 +00:00
2020-06-09 10:16:40 +00:00
this.model.addFilter({where});
}
removeFilter() {
const userFilter = this.model.userFilter;
const userParams = this.model.userParams;
const where = userFilter.where;
let filterKey = this.fieldName;
if (this.exprBuilder) {
const param = this.exprBuilder({
param: filterKey,
value: null
});
[filterKey] = Object.keys(param);
}
const whereKeys = Object.keys(where);
for (let key of whereKeys)
removeProp(where, filterKey, key);
function removeProp(instance, findProp, prop) {
if (prop == findProp)
delete instance[prop];
if (prop === 'and') {
for (let [index, param] of instance[prop].entries()) {
const [key] = Object.keys(param);
if (key == findProp)
instance[prop].splice(index, 1);
2020-06-09 10:43:14 +00:00
if (param[key] instanceof Array)
removeProp(param, filterKey, key);
2020-06-09 10:16:40 +00:00
}
}
}
this.model.applyFilter(userFilter, userParams);
2020-05-29 09:10:58 +00:00
}
2020-05-28 06:07:26 +00:00
2020-06-08 10:14:27 +00:00
/**
* Removes all applied filters
*/
2020-06-09 10:16:40 +00:00
removeAllFilters() {
const userParams = this.model.userParams;
this.model.applyFilter(null, userParams);
2020-05-28 06:07:26 +00:00
}
}
2020-05-29 09:10:58 +00:00
Contextmenu.$inject = ['$element', '$scope', '$transclude'];
2020-05-28 06:07:26 +00:00
ngModule.vnComponent('vnContextmenu', {
controller: Contextmenu,
template: require('./index.html'),
bindings: {
2020-05-29 09:10:58 +00:00
targets: '<?',
2020-06-09 10:16:40 +00:00
model: '<?',
exprBuilder: '&?'
2020-05-28 06:07:26 +00:00
},
transclude: {
menu: '?slotMenu'
}
});