devextreme
Version:
HTML5 JavaScript Component Suite for Responsive Web Development
402 lines (400 loc) • 16.3 kB
JavaScript
/**
* DevExtreme (ui/scheduler/ui.scheduler.resource_manager.js)
* Version: 18.1.3
* Build date: Tue May 15 2018
*
* Copyright (c) 2012 - 2018 Developer Express Inc. ALL RIGHTS RESERVED
* Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/
*/
"use strict";
var Class = require("../../core/class"),
arrayUtils = require("../../core/utils/array"),
grep = require("../../core/utils/common").grep,
isDefined = require("../../core/utils/type").isDefined,
objectUtils = require("../../core/utils/object"),
iteratorUtils = require("../../core/utils/iterator"),
extend = require("../../core/utils/extend").extend,
inArray = require("../../core/utils/array").inArray,
query = require("../../data/query"),
dataCoreUtils = require("../../core/utils/data"),
DataSourceModule = require("../../data/data_source/data_source"),
deferredUtils = require("../../core/utils/deferred"),
when = deferredUtils.when,
Deferred = deferredUtils.Deferred;
var getValueExpr = function(resource) {
return resource.valueExpr || "id"
},
getDisplayExpr = function(resource) {
return resource.displayExpr || "text"
};
var ResourceManager = Class.inherit({
_wrapDataSource: function(dataSource) {
if (dataSource instanceof DataSourceModule.DataSource) {
return dataSource
} else {
return new DataSourceModule.DataSource({
store: DataSourceModule.normalizeDataSourceOptions(dataSource).store,
pageSize: 0
})
}
},
_mapResourceData: function(resource, data) {
var valueGetter = dataCoreUtils.compileGetter(getValueExpr(resource)),
displayGetter = dataCoreUtils.compileGetter(getDisplayExpr(resource));
return iteratorUtils.map(data, function(item) {
var result = {
id: valueGetter(item),
text: displayGetter(item)
};
if (item.color) {
result.color = item.color
}
return result
})
},
_isMultipleResource: function(resourceField) {
var result = false;
iteratorUtils.each(this.getResources(), function(_, resource) {
var field = this.getField(resource);
if (field === resourceField) {
result = resource.allowMultiple;
return false
}
}.bind(this));
return result
},
ctor: function(resources) {
this.setResources(resources)
},
getDataAccessors: function(field, type) {
var result = null;
iteratorUtils.each(this._dataAccessors[type], function(accessorName, accessors) {
if (field === accessorName) {
result = accessors;
return false
}
});
return result
},
getField: function(resource) {
return resource.fieldExpr || resource.field
},
setResources: function(resources) {
this._resources = resources;
this._dataAccessors = {
getter: {},
setter: {}
};
this._resourceFields = iteratorUtils.map(resources || [], function(resource) {
var field = this.getField(resource);
this._dataAccessors.getter[field] = dataCoreUtils.compileGetter(field);
this._dataAccessors.setter[field] = dataCoreUtils.compileSetter(field);
return field
}.bind(this))
},
getResources: function() {
return this._resources || []
},
getResourcesData: function() {
return this._resourcesData || []
},
getEditors: function() {
var result = [],
that = this;
iteratorUtils.each(this.getResources(), function(i, resource) {
var field = that.getField(resource),
currentResourceItems = that._getResourceDataByField(field);
result.push({
editorOptions: {
dataSource: currentResourceItems.length ? currentResourceItems : that._wrapDataSource(resource.dataSource),
displayExpr: getDisplayExpr(resource),
valueExpr: getValueExpr(resource)
},
dataField: field,
editorType: resource.allowMultiple ? "dxTagBox" : "dxSelectBox",
label: {
text: resource.label || field
}
})
});
return result
},
_resourceLoader: {},
getResourceDataByValue: function(field, value) {
var that = this,
result = new Deferred;
iteratorUtils.each(this.getResources(), function(_, resource) {
var resourceField = that.getField(resource);
if (resourceField === field) {
var dataSource = that._wrapDataSource(resource.dataSource),
valueExpr = getValueExpr(resource);
if (!that._resourceLoader[field]) {
that._resourceLoader[field] = dataSource.load()
}
that._resourceLoader[field].done(function(data) {
var filteredData = query(data).filter(valueExpr, value).toArray();
delete that._resourceLoader[field];
result.resolve(filteredData[0])
}).fail(function() {
delete that._resourceLoader[field];
result.reject()
});
return false
}
});
return result.promise()
},
setResourcesToItem: function(itemData, resources) {
var resourcesSetter = this._dataAccessors.setter;
for (var name in resources) {
if (resources.hasOwnProperty(name)) {
var resourceData = resources[name];
resourcesSetter[name](itemData, this._isMultipleResource(name) ? arrayUtils.wrapToArray(resourceData) : resourceData)
}
}
},
getResourcesFromItem: function(itemData, wrapOnlyMultipleResources) {
var that = this,
result = null;
if (!isDefined(wrapOnlyMultipleResources)) {
wrapOnlyMultipleResources = false
}
iteratorUtils.each(that._resourceFields, function(index, field) {
iteratorUtils.each(itemData, function(fieldName, fieldValue) {
var tmp = {};
tmp[fieldName] = fieldValue;
var resourceData = that.getDataAccessors(field, "getter")(tmp);
if (resourceData) {
if (!result) {
result = {}
}
if (1 === resourceData.length) {
resourceData = resourceData[0]
}
if (!wrapOnlyMultipleResources || wrapOnlyMultipleResources && that._isMultipleResource(field)) {
that.getDataAccessors(field, "setter")(tmp, arrayUtils.wrapToArray(resourceData))
} else {
that.getDataAccessors(field, "setter")(tmp, resourceData)
}
extend(result, tmp);
return true
}
})
});
return result
},
loadResources: function(groups) {
var result = new Deferred,
that = this,
deferreds = [];
iteratorUtils.each(this.getResourcesByFields(groups), function(i, resource) {
var deferred = new Deferred,
field = that.getField(resource);
deferreds.push(deferred);
that._wrapDataSource(resource.dataSource).load().done(function(data) {
deferred.resolve({
name: field,
items: that._mapResourceData(resource, data),
data: data
})
}).fail(function() {
deferred.reject()
})
});
if (!deferreds.length) {
return result.resolve([])
}
when.apply(null, deferreds).done(function() {
var data = Array.prototype.slice.call(arguments),
mapFunction = function(obj) {
return {
name: obj.name,
items: obj.items,
data: obj.data
}
};
that._resourcesData = data;
result.resolve(data.map(mapFunction))
}).fail(function() {
result.reject()
});
return result.promise()
},
getResourcesByFields: function(fields) {
return grep(this.getResources(), function(resource) {
var field = this.getField(resource);
return inArray(field, fields) > -1
}.bind(this))
},
getResourceByField: function(field) {
return this.getResourcesByFields([field])[0] || {}
},
getResourceColor: function(field, value) {
var valueExpr = this.getResourceByField(field).valueExpr || "id",
valueGetter = dataCoreUtils.compileGetter(valueExpr),
colorExpr = this.getResourceByField(field).colorExpr || "color",
colorGetter = dataCoreUtils.compileGetter(colorExpr);
var color, result = new Deferred,
resourceData = this._getResourceDataByField(field),
resourceDataLength = resourceData.length;
if (resourceDataLength) {
for (var i = 0; i < resourceDataLength; i++) {
if (valueGetter(resourceData[i]) === value) {
color = colorGetter(resourceData[i]);
break
}
}
result.resolve(color)
} else {
this.getResourceDataByValue(field, value).done(function(resourceData) {
if (resourceData) {
color = colorGetter(resourceData)
}
result.resolve(color)
}).fail(function() {
result.reject()
})
}
return result.promise()
},
getResourceForPainting: function(groups) {
var result, resources = this.getResources();
iteratorUtils.each(resources, function(index, resource) {
if (resource.useColorAsDefault) {
result = resource;
return false
}
});
if (!result) {
if (Array.isArray(groups) && groups.length) {
resources = this.getResourcesByFields(groups)
}
result = resources[resources.length - 1]
}
return result
},
createResourcesTree: function(groups) {
var leafIndex = 0,
groupIndex = groupIndex || 0;
function make(group, groupIndex, result, parent) {
result = result || [];
for (var i = 0; i < group.items.length; i++) {
var currentGroupItem = group.items[i];
var resultItem = {
name: group.name,
value: currentGroupItem.id,
title: currentGroupItem.text,
data: group.data && group.data[i],
children: [],
parent: parent ? parent : null
};
result.push(resultItem);
var nextGroupIndex = groupIndex + 1;
if (groups[nextGroupIndex]) {
make.call(this, groups[nextGroupIndex], nextGroupIndex, resultItem.children, resultItem)
}
if (!resultItem.children.length) {
resultItem.leafIndex = leafIndex;
leafIndex++
}
}
return result
}
return make.call(this, groups[0], 0)
},
_hasGroupItem: function(appointmentResources, groupName, itemValue) {
var group = this.getDataAccessors(groupName, "getter")(appointmentResources);
if (group) {
if (inArray(itemValue, group) > -1) {
return true
}
}
return false
},
_getResourceDataByField: function(fieldName) {
var loadedResources = this.getResourcesData(),
currentResourceData = [];
for (var i = 0, resourceCount = loadedResources.length; i < resourceCount; i++) {
if (loadedResources[i].name === fieldName) {
currentResourceData = loadedResources[i].data;
break
}
}
return currentResourceData
},
getResourceTreeLeaves: function(tree, appointmentResources, result) {
result = result || [];
for (var i = 0; i < tree.length; i++) {
if (!this._hasGroupItem(appointmentResources, tree[i].name, tree[i].value)) {
continue
}
if (isDefined(tree[i].leafIndex)) {
result.push(tree[i].leafIndex)
}
if (tree[i].children) {
this.getResourceTreeLeaves(tree[i].children, appointmentResources, result)
}
}
return result
},
groupAppointmentsByResources: function(appointments, resources) {
var tree = this.createResourcesTree(resources),
result = {};
iteratorUtils.each(appointments, function(_, appointment) {
var appointmentResources = this.getResourcesFromItem(appointment),
treeLeaves = this.getResourceTreeLeaves(tree, appointmentResources);
for (var i = 0; i < treeLeaves.length; i++) {
if (!result[treeLeaves[i]]) {
result[treeLeaves[i]] = []
}
result[treeLeaves[i]].push(objectUtils.deepExtendArraySafe({}, appointment, true))
}
}.bind(this));
return result
},
reduceResourcesTree: function(tree, existingAppointments, _result) {
_result = _result ? _result.children : [];
var that = this;
tree.forEach(function(node, index) {
var ok = false,
resourceName = node.name,
resourceValue = node.value,
resourceTitle = node.title,
resourceData = node.data,
resourceGetter = that.getDataAccessors(resourceName, "getter");
existingAppointments.forEach(function(appointment) {
if (!ok) {
var resourceFromAppointment = resourceGetter(appointment);
if (Array.isArray(resourceFromAppointment)) {
if (resourceFromAppointment.indexOf(resourceValue) > -1) {
_result.push({
name: resourceName,
value: resourceValue,
title: resourceTitle,
data: resourceData,
children: []
});
ok = true
}
} else {
if (resourceFromAppointment === resourceValue) {
_result.push({
name: resourceName,
value: resourceValue,
title: resourceTitle,
data: resourceData,
children: []
});
ok = true
}
}
}
});
if (ok && node.children && node.children.length) {
that.reduceResourcesTree(node.children, existingAppointments, _result[index])
}
});
return _result
}
});
module.exports = ResourceManager;