This commit is contained in:
Yuri Kuznetsov
2023-06-09 17:26:29 +03:00
parent 24473783e9
commit c9a959d548
8 changed files with 193 additions and 308 deletions
+91 -205
View File
@@ -64,93 +64,93 @@
/**
* A search manager.
*
* @class
* @param {module:collection} collection A collection.
* @param {string|null} type A type. Used for a storage key.
* @param {module:storage|null} storage A storage.
* @param {module:date-time|null} dateTime A date-time util.
* @param {module:search-manager~data|null} [defaultData=null] Default search data.
* @param {boolean} [emptyOnReset=false] To empty on reset.
*/
const SearchManager = function (
collection,
type,
storage,
dateTime,
defaultData,
emptyOnReset
) {
/**
* @private
* @type {module:collection}
*/
this.collection = collection;
class SearchManager {
/**
* An entity type.
*
* @public
* @type {string}
* @param {module:collection} collection A collection.
* @param {string|null} type A type. Used for a storage key.
* @param {module:storage|null} storage A storage.
* @param {module:date-time|null} dateTime A date-time util.
* @param {module:search-manager~data|null} [defaultData=null] Default search data.
* @param {boolean} [emptyOnReset=false] To empty on reset.
*/
this.scope = collection.name;
constructor(
collection,
type,
storage,
dateTime,
defaultData,
emptyOnReset
) {
/**
* @private
* @type {module:collection}
*/
this.collection = collection;
/**
* @private
* @type {module:storage|null}
*/
this.storage = storage;
/**
* An entity type.
*
* @public
* @type {string}
*/
this.scope = collection.name;
/**
* @private
* @type {string}
*/
this.type = type || 'list';
/**
* @private
* @type {module:storage|null}
*/
this.storage = storage;
/**
* @private
* @type {module:date-time|null}
*/
this.dateTime = dateTime;
/**
* @private
* @type {string}
*/
this.type = type || 'list';
/**
* @private
* @type {boolean}
*/
this.emptyOnReset = emptyOnReset;
/**
* @private
* @type {module:date-time|null}
*/
this.dateTime = dateTime;
/**
* @private
* @type {Object}
*/
this.emptyData = {
textFilter: '',
bool: {},
advanced: {},
primary: null,
};
/**
* @private
* @type {boolean}
*/
this.emptyOnReset = emptyOnReset;
if (defaultData) {
this.defaultData = defaultData;
/**
* @private
* @type {Object}
*/
this.emptyData = {
textFilter: '',
bool: {},
advanced: {},
primary: null,
};
for (let p in this.emptyData) {
if (!(p in defaultData)) {
defaultData[p] = Espo.Utils.clone(this.emptyData[p]);
if (defaultData) {
this.defaultData = defaultData;
for (let p in this.emptyData) {
if (!(p in defaultData)) {
defaultData[p] = Espo.Utils.clone(this.emptyData[p]);
}
}
}
this.data = Espo.Utils.clone(defaultData) || this.emptyData;
this.sanitizeData();
}
this.data = Espo.Utils.clone(defaultData) || this.emptyData;
this.sanitizeData();
};
_.extend(SearchManager.prototype, /** @lends SearchManager# */{
/**
* @private
*/
sanitizeData: function () {
sanitizeData() {
if (!('advanced' in this.data)) {
this.data.advanced = {};
}
@@ -162,14 +162,14 @@ _.extend(SearchManager.prototype, /** @lends SearchManager# */{
if (!('textFilter' in this.data)) {
this.data.textFilter = '';
}
},
}
/**
* Get a where clause. The where clause to be sent to the backend.
*
* @returns {module:search-manager~whereItem[]}
*/
getWhere: function () {
getWhere() {
let where = [];
if (this.data.textFilter && this.data.textFilter !== '') {
@@ -222,12 +222,12 @@ _.extend(SearchManager.prototype, /** @lends SearchManager# */{
}
return where;
},
}
/**
* @private
*/
getWherePart: function (name, defs) {
getWherePart(name, defs) {
var attribute = name;
if ('where' in defs) {
@@ -276,14 +276,14 @@ _.extend(SearchManager.prototype, /** @lends SearchManager# */{
attribute: attribute,
value: value
};
},
}
/**
* Load stored data.
*
* @returns {module:search-manager}
*/
loadStored: function () {
loadStored() {
this.data =
this.storage.get(this.type + 'Search', this.scope) ||
Espo.Utils.clone(this.defaultData) ||
@@ -292,16 +292,16 @@ _.extend(SearchManager.prototype, /** @lends SearchManager# */{
this.sanitizeData();
return this;
},
}
/**
* Get data.
*
* @returns {module:search-manager~data}
*/
get: function () {
get() {
return this.data;
},
}
/**
* Set advanced filters.
@@ -309,40 +309,40 @@ _.extend(SearchManager.prototype, /** @lends SearchManager# */{
* @param {{string: module:search-manager~advancedFilter}} advanced Advanced filters.
* Pairs of field => advancedFilter.
*/
setAdvanced: function (advanced) {
setAdvanced(advanced) {
this.data = Espo.Utils.clone(this.data);
this.data.advanced = advanced;
},
}
/**
* Set bool filters.
*
* @param {Object.<string, boolean>} bool Bool filters.
*/
setBool: function (bool) {
setBool(bool) {
this.data = Espo.Utils.clone(this.data);
this.data.bool = bool;
},
}
/**
* Set a primary filter.
*
* @param {string} primary A filter.
*/
setPrimary: function (primary) {
setPrimary(primary) {
this.data = Espo.Utils.clone(this.data);
this.data.primary = primary;
},
}
/**
* Set data.
*
* @param {module:search-manager~data} data Data.
*/
set: function (data) {
set(data) {
this.data = data;
if (this.storage) {
@@ -351,23 +351,23 @@ _.extend(SearchManager.prototype, /** @lends SearchManager# */{
this.storage.set(this.type + 'Search', this.scope, data);
}
},
}
/**
* Empty data.
*/
empty: function () {
empty() {
this.data = Espo.Utils.clone(this.emptyData);
if (this.storage) {
this.storage.clear(this.type + 'Search', this.scope);
}
},
}
/**
* Reset.
*/
reset: function () {
reset() {
if (this.emptyOnReset) {
this.empty();
@@ -379,121 +379,7 @@ _.extend(SearchManager.prototype, /** @lends SearchManager# */{
if (this.storage) {
this.storage.clear(this.type + 'Search', this.scope);
}
},
/**
* @private
* @todo Revise.
*/
getDateTimeWhere: function (type, field, value) {
var where = {
field: field
};
if (!value && ~['on', 'before', 'after'].indexOf(type)) {
return null;
}
let start, from, to;
switch (type) {
case 'today':
where.type = 'between';
start = this.dateTime.getNowMoment().startOf('day').utc();
from = start.format(this.dateTime.internalDateTimeFormat);
to = start.add(1, 'days').format(this.dateTime.internalDateTimeFormat);
where.value = [from, to];
break;
case 'past':
where.type = 'before';
where.value = this.dateTime.getNowMoment().utc().format(this.dateTime.internalDateTimeFormat);
break;
case 'future':
where.type = 'after';
where.value = this.dateTime.getNowMoment().utc().format(this.dateTime.internalDateTimeFormat);
break;
case 'on':
where.type = 'between';
start = moment(value, this.dateTime.internalDateFormat, this.timeZone).utc();
from = start.format(this.dateTime.internalDateTimeFormat);
to = start.add(1, 'days').format(this.dateTime.internalDateTimeFormat);
where.value = [from, to];
break;
case 'before':
where.type = 'before';
where.value =
moment(
value,
this.dateTime.internalDateFormat,
this.timeZone
)
.utc()
.format(this.dateTime.internalDateTimeFormat );
break;
case 'after':
where.type = 'after';
where.value =
moment(
value,
this.dateTime.internalDateFormat,
this.timeZone
)
.utc()
.format(this.dateTime.internalDateTimeFormat);
break;
case 'between':
where.type = 'between';
if (value[0] && value[1]) {
let from =
moment(
value[0],
this.dateTime.internalDateFormat,
this.timeZone
)
.utc()
.format(this.dateTime.internalDateTimeFormat);
let to =
moment(
value[1],
this.dateTime.internalDateFormat,
this.timeZone
)
.utc()
.format(this.dateTime.internalDateTimeFormat);
where.value = [from, to];
}
break;
default:
where.type = type;
}
return where;
},
});
}
}
export default SearchManager;
@@ -26,89 +26,90 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
define('views/record/list-nested-categories', ['view'], function (Dep) {
import View from 'view';
return Dep.extend({
class ListNestedCategoriesRecordView extends View {
template: 'record/list-nested-categories',
template = 'record/list-nested-categories'
events: {
'click .action': function (e) {
var $el = $(e.currentTarget);
var action = $el.data('action');
var method = 'action' + Espo.Utils.upperCaseFirst(action);
events = {
'click .action': function (e) {
let $el = $(e.currentTarget);
let action = $el.data('action');
let method = 'action' + Espo.Utils.upperCaseFirst(action);
if (typeof this[method] === 'function') {
var data = $el.data();
if (typeof this[method] === 'function') {
var data = $el.data();
this[method](data, e);
this[method](data, e);
e.preventDefault();
}
},
},
data: function () {
var data = {};
if (!this.isLoading) {
data.list = this.getDataList();
e.preventDefault();
}
data.scope = this.collection.name;
data.isLoading = this.isLoading;
data.currentId = this.collection.currentCategoryId;
data.currentName = this.collection.currentCategoryName;
data.categoryData = this.collection.categoryData;
data.hasExpandedToggler = this.options.hasExpandedToggler;
data.showEditLink = this.options.showEditLink;
data.hasNavigationPanel = this.options.hasNavigationPanel;
let categoryData = this.collection.categoryData || {};
data.upperLink = categoryData.upperId ?
'#' + this.subjectEntityType + '/list/categoryId=' + categoryData.upperId:
'#' + this.subjectEntityType;
return data;
},
}
getDataList: function () {
var list = [];
data() {
let data = {};
this.collection.forEach(model => {
let o = {
id: model.id,
name: model.get('name'),
recordCount: model.get('recordCount'),
isEmpty: model.get('isEmpty'),
link: '#' + this.subjectEntityType + '/list/categoryId=' + model.id,
};
if (!this.isLoading) {
data.list = this.getDataList();
}
list.push(o);
});
data.scope = this.collection.name;
data.isLoading = this.isLoading;
data.currentId = this.collection.currentCategoryId;
return list;
},
data.currentName = this.collection.currentCategoryName;
setup: function () {
this.listenTo(this.collection, 'sync', () => {
this.reRender();
});
data.categoryData = this.collection.categoryData;
this.subjectEntityType = this.options.subjectEntityType;
},
data.hasExpandedToggler = this.options.hasExpandedToggler;
data.showEditLink = this.options.showEditLink;
data.hasNavigationPanel = this.options.hasNavigationPanel;
actionShowMore: function () {
this.$el.find('.category-item.show-more').addClass('hidden');
let categoryData = this.collection.categoryData || {};
this.collection.fetch({
remove: false,
more: true,
});
},
});
});
data.upperLink = categoryData.upperId ?
'#' + this.subjectEntityType + '/list/categoryId=' + categoryData.upperId:
'#' + this.subjectEntityType;
return data;
}
getDataList() {
var list = [];
this.collection.forEach(model => {
let o = {
id: model.id,
name: model.get('name'),
recordCount: model.get('recordCount'),
isEmpty: model.get('isEmpty'),
link: '#' + this.subjectEntityType + '/list/categoryId=' + model.id,
};
list.push(o);
});
return list;
}
setup() {
this.listenTo(this.collection, 'sync', () => {
this.reRender();
});
this.subjectEntityType = this.options.subjectEntityType;
}
actionShowMore() {
this.$el.find('.category-item.show-more').addClass('hidden');
this.collection.fetch({
remove: false,
more: true,
});
}
}
export default ListNestedCategoriesRecordView;
+5 -5
View File
@@ -28,7 +28,7 @@
import View from 'view';
class ListTreeRecordItem extends View {
class ListTreeRecordItemView extends View {
template = 'record/list-tree-item'
@@ -49,19 +49,19 @@ class ListTreeRecordItem extends View {
}
events = {
/** @this ListTreeRecordItem */
/** @this ListTreeRecordItemView */
'click [data-action="unfold"]': function (e) {
this.unfold();
e.stopPropagation();
},
/** @this ListTreeRecordItem */
/** @this ListTreeRecordItemView */
'click [data-action="fold"]': function (e) {
this.fold();
e.stopPropagation();
},
/** @this ListTreeRecordItem */
/** @this ListTreeRecordItemView */
'click [data-action="remove"]': function (e) {
this.actionRemove();
@@ -336,4 +336,4 @@ class ListTreeRecordItem extends View {
}
}
export default ListTreeRecordItem;
export default ListTreeRecordItemView;
+2 -2
View File
@@ -33,7 +33,7 @@ import View from 'view';
/**
* A bottom panel.
*/
class BottomPanel extends View {
class BottomPanelView extends View {
template = 'record/panels/side'
@@ -366,4 +366,4 @@ class BottomPanel extends View {
}
}
export default BottomPanel;
export default BottomPanelView;
@@ -26,12 +26,12 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
import SidePanel from 'views/record/panels/side';
import SidePanelView from 'views/record/panels/side';
/**
* A default side panel.
*/
class DefaultSidePanel extends SidePanel {
class DefaultSidePanelView extends SidePanelView {
data() {
let data = super.data();
@@ -148,4 +148,4 @@ class DefaultSidePanel extends SidePanel {
}
}
export default DefaultSidePanel;
export default DefaultSidePanelView;
@@ -28,14 +28,14 @@
/** @module views/record/panels/relationship */
import BottomPanel from 'views/record/panels/bottom';
import BottomPanelView from 'views/record/panels/bottom';
import SearchManager from 'search-manager';
import RecordModal from 'helpers/record-modal';
/**
* A relationship panel.
*/
class RelationshipPanel extends BottomPanel {
class RelationshipPanelView extends BottomPanelView {
/** @inheritDoc */
template = 'record/panels/relationship'
@@ -757,4 +757,4 @@ class RelationshipPanel extends BottomPanel {
}
}
export default RelationshipPanel;
export default RelationshipPanelView;
+2 -2
View File
@@ -33,7 +33,7 @@ import View from 'view';
/**
* A side panel.
*/
class SidePanel extends View {
class SidePanelView extends View {
template = 'record/panels/side'
@@ -408,4 +408,4 @@ class SidePanel extends View {
}
}
export default SidePanel;
export default SidePanelView;
+16 -18
View File
@@ -26,24 +26,20 @@
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
************************************************************************/
import Dep from 'view';
import View from 'view';
/**
* A detail-side record view.
*
* @class
* @name Class
* @extends module:view
* Row actions.
*/
export default Dep.extend(/** @lends Class# */{
class DefaultRowActionsView extends View {
template: 'record/row-actions/default',
template ='record/row-actions/default'
setup: function () {
setup() {
this.options.acl = this.options.acl || {};
},
}
afterRender: function () {
afterRender() {
let $dd = this.$el.find('button[data-toggle="dropdown"]').parent();
let isChecked = false;
@@ -65,15 +61,15 @@ export default Dep.extend(/** @lends Class# */{
this.$el.closest('.list-row').removeClass('active');
}
});
},
}
/**
* Get an action list.
*
* @return {module:views/record/list~rowAction[]}
*/
getActionList: function () {
var list = [{
getActionList() {
let list = [{
action: 'quickView',
label: 'View',
data: {
@@ -104,13 +100,15 @@ export default Dep.extend(/** @lends Class# */{
}
return list;
},
}
data: function () {
data() {
return {
acl: this.options.acl,
actionList: this.getActionList(),
scope: this.model.name,
};
},
});
}
}
export default DefaultRowActionsView;