Last active
September 11, 2018 16:33
-
-
Save santaklouse/d7734ef21bbe3982821748686539415f to your computer and use it in GitHub Desktop.
AngularJS services example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function(angular) { | |
'use strict'; | |
angular.module('noname.services', ['ngResource']) | |
.factory('templateUrl', ['$templateCache', 'config', 'feature', function($templateCache, config, feature) { | |
return function(placement, name) { | |
var templatePath = function(role) { | |
var path; | |
role = role || 'common'; | |
path = ['@UnknownBundle', role, placement, name].join('/'); | |
return (_.last(path) === '/') ? path.slice(0, path.length-1) : path; | |
}; | |
if ($templateCache.get(templatePath(config.getRole()))) { | |
return templatePath(config.getRole()); | |
} | |
return templatePath(); | |
} | |
}]) | |
.service('urlTemplate', ['$filter', 'dateUtils', 'utils', '$injector', function($filter, dateUtils, utils, $injector) { | |
return { | |
/** | |
* Returns object with params prepared for urlTemplate function (filling url template) | |
* | |
* @param {Array} fieldsFromConfig names of fields which should be taken from config) | |
* @param {Object} [params] additional params that should be added to url (together with config values) | |
* @param {Boolean} [shouldFormatDate] if true and in params 'date' exists - formats date to 'yyyyMMdd' format | |
* | |
* @return {Object} | |
*/ | |
prepareParams: function(fieldsFromConfig, params, shouldFormatDate) { | |
var config = $injector.get('config'); | |
var result = _.pick(config, fieldsFromConfig); | |
if (result.date && _.isDate(result.date) && shouldFormatDate) { | |
result.date = $filter('date')(result.date, 'yyyyMMdd'); | |
} | |
if (params && utils.isObject(params)) { | |
return _.assignIn(result, params); | |
} | |
return result; | |
}, | |
/** | |
* @param {String} urlTemplate template str (${...} - will be replaced with values from params object) | |
* @param {Object} params params which be included to template string | |
* | |
* @return {String|Array} | |
*/ | |
fill: function(urlTemplate, params) { | |
var value; | |
return urlTemplate.replace(/[\$%]{(\w+?)}/gi, function(match, field) { | |
value = params[field]; | |
return value === undefined ? '' : value; | |
}); | |
}, | |
/** | |
* Converts urlTemplate template pattern (like /${date}/) to angular format (like /:date/) | |
* | |
* @param {String} urlTemplate - str with marks, like: ${contractId}/%{date}/%{tz} | |
* % - can be used for building angular routing with optional params | |
* e.g.: /${id}/%{smth_optional} -> /:id/:smth_optional? | |
* @return {String} | |
*/ | |
toAngularRouteFormat: function(urlTemplate) { | |
urlTemplate = String(urlTemplate); | |
if (urlTemplate[0] !== '/') { | |
urlTemplate = '/' + urlTemplate; | |
} | |
return urlTemplate.replace(/[\$%]{(\w+?)}/gi, function(match, field) { | |
if (!field) { | |
return ''; | |
} | |
return ':' + field + (match[0] === '%' ? '?' : ''); | |
}); | |
}, | |
/** | |
* Return array of 'config' service field names (${...} - params inside of this will be returned as array) | |
* | |
* @param {String} urlTemplate template str | |
* @param {Array} [config.allowedConfigFields] list of allowed to change config fields | |
* @return {Array} | |
*/ | |
parse: function(urlTemplate, useAnyFields) { | |
var result = [], config = $injector.get('config'); | |
urlTemplate.replace(/[\$%]{(\w+?)}/gi, function(match, field) { | |
result.push(field); | |
return match; | |
}); | |
if (useAnyFields || !config.allowedConfigFields) { | |
return result; | |
} | |
return result.filter(function(val) { | |
return config.allowedConfigFields.indexOf(val) !== -1; | |
}); | |
}, | |
/** | |
* Compiles url string from template string | |
* | |
* @param {String} url template str ${...} - will be replaced with values from params object | |
* @param {Array} fieldsFromConfig names of fields which should be taken from config | |
* @param {Object} [params] additional params that should be added to url (besides config values | |
* | |
* @return {String} | |
*/ | |
compile: function(url, fieldsFromConfig, params) { | |
return this.fill( | |
url, | |
this.prepareParams(fieldsFromConfig, params, true) | |
); | |
}, | |
extractLocationParams: function(path) { | |
var config = $injector.get('config'), | |
configKeysFromTemplate = config.urlTemplateKeysList, | |
urlPathValues = _.compact(path.split('/')).filter(function(val) { | |
//remove parts of pattern | |
return config.urlTemplatePattern.indexOf(val) === -1; | |
}); | |
if (!urlPathValues.length) { | |
return {}; | |
} | |
var getParamFromUrl = function(param, defaultVal) { | |
var paramIndex = configKeysFromTemplate.indexOf(param); | |
return (paramIndex !== -1 && urlPathValues[paramIndex]) | |
|| (utils.isUndefined(defaultVal) ? null : defaultVal); | |
}; | |
//build hash of path params with values (key=>val) | |
return _.chain(configKeysFromTemplate) | |
.map(function(param) { | |
if (config.allowedConfigFields.indexOf(param) === -1) { | |
return; | |
} | |
return [param, getParamFromUrl(param, null)]; | |
}) | |
.compact() | |
.fromPairs() | |
.value(); | |
} | |
}; | |
}]) | |
.factory('generateSnapshotUrl', ['snapshotPageUrlTemplate', '$location', 'urlTemplate', function(snapshotPageUrlTemplate, $location, urlTemplate) { | |
return function(time, baseUrl) { | |
if (!time) { | |
return '#'; | |
} | |
baseUrl = baseUrl || $location.absUrl(); | |
return urlTemplate.compile( | |
snapshotPageUrlTemplate, | |
['contractId'], | |
{ | |
base: location.origin, | |
time: time, | |
backUrl: encodeURIComponent(baseUrl) | |
} | |
); | |
}; | |
}]) | |
.service('utils', [function() { | |
var _CRCTable = [], | |
getType = {}, | |
dateIdentifier = 'Date', | |
crypto = window.crypto, | |
u32_4 = new Uint32Array(4), | |
a16 = Array(16), | |
charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", | |
charsetLength = charset.length, | |
getCharCode = _.memoize(function(i) { | |
return charset.charCodeAt(i); | |
}), | |
dateString = /^([1-2][0-9]{3})(0[1-9]|1[0-2])([0-2][0-9]|3[0-1])$/; | |
var _makeCRCTable = _.memoize(function(val) { | |
if (val !== undefined) { | |
return (_CRCTable.length ? _CRCTable : _makeCRCTable())[val]; | |
} | |
var c, n = 0; | |
for (; n < 256; n++) { | |
c = n; | |
for (var k = 0; k < 8; k++) { | |
c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1)); | |
} | |
_CRCTable[n] = c; | |
} | |
return _CRCTable; | |
}); | |
var utils = { | |
memoizeHasher: function(){ | |
return _.chain(_.toArray(arguments)) | |
.map(function(value) { | |
if (utils.isObject(value)) { | |
return JSON.stringify(value) + typeof(value); | |
} | |
return String(value) + typeof(value); | |
}) | |
.value() | |
.join() | |
}, | |
/** | |
* Checks if `value` is classified as an Function. | |
* | |
* @description (faster a bit smaller ~x3 than _.isFunction and ) | |
* @param {*} value | |
* @returns {Boolean} | |
*/ | |
isFunction: function(value) { | |
return typeof value === 'function' || value instanceof Function; | |
}, | |
/** | |
* Checks if `value` is classified as an Date object. | |
* | |
* @description (faster >x3 than _.isDate and ~x10 angular.isDate) | |
* @param {*} value | |
* @returns {Boolean} | |
*/ | |
isDate: function (value){ | |
return getType.toString.call(value).indexOf(dateIdentifier) !== -1; | |
}, | |
/** | |
* Checks that string has valid WD URL date format: yyyymmdd (like 19991231) | |
* @param {String} str | |
* @returns {Boolean} | |
*/ | |
isValidWDDate: function(str){ | |
if (!str) { | |
return false; | |
} | |
return dateString.test(str); | |
}, | |
/** | |
* Checks if `value` has boolean type. | |
* | |
* @param {*} value | |
* @returns {Boolean} | |
*/ | |
isBoolean: function (value){ | |
return typeof(value) === 'boolean'; | |
}, | |
/** | |
* Checks if `value` is classified as an Number. | |
* | |
* @param {*} value | |
* @description (a bit faster than _.isNumber) | |
* @returns {Boolean} | |
*/ | |
isNumber: function (value){ | |
return typeof(value) === 'number' || value instanceof Number; | |
}, | |
/** | |
* Checks is `value` is Integer (no fractional). | |
* | |
* @param num | |
* @returns {boolean} | |
*/ | |
isInteger: function (value) { | |
return (value ^ 0) === value; | |
}, | |
/** | |
* Checks if `value` is classified as an undefined. | |
* | |
* @param {*} value | |
* @description (a bit faster than _.isUndefined) | |
* @returns {Boolean} | |
*/ | |
isUndefined: function (value) { | |
return value === undefined; | |
}, | |
/** | |
* Checks if `value` is null. | |
* | |
* @param {*} value | |
* @returns {Boolean} | |
*/ | |
isNull: function(value) { | |
return value === null; | |
}, | |
/** | |
* Checks if `value` is the of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`) | |
* | |
* @description (faster >x10 than _.iObject) | |
* @param {*} value The value to check. | |
* @returns {Boolean} | |
* | |
* @example | |
* | |
* utils.isObject({}); | |
* // => true | |
* | |
* utils.isObject([1, 2, 3]); | |
* // => true | |
* | |
* utils.isObject(_.noop); | |
* // => true | |
* | |
* utils.isObject(1); | |
* // => false | |
* | |
* utils.isObject('str'); | |
* // => false | |
* | |
* utils.isObject(undefined); | |
* // => false | |
*/ | |
isObject: function (value){ | |
if (value === null) { | |
return false; | |
} | |
value = typeof(value); | |
return value === 'object' || value === 'function'; | |
}, | |
/** | |
* Checks if `value` is the String. | |
* | |
* @description (mostly faster than _.iObject for many input types) | |
* @param {*} value The value to check. | |
* @returns {Boolean} | |
*/ | |
isString: function (value){ | |
return (typeof value === 'string' || value instanceof String) | |
}, | |
fastArrayJoin: function(array) { | |
var i = 0, l = array.length, result = ''; | |
for(;i<l;){ | |
result += array[i++]; | |
} | |
return result; | |
}, | |
/** | |
* Checks if `string` contains at least one substring from list of substrings | |
* | |
* @param {String} string The main string. | |
* @param {Array|String} substrings The list of substrings to check. | |
* @returns {Boolean} | |
*/ | |
isStringContainsOneOfSubstrings: function(string, substrings) { | |
if (!string) { | |
return false; | |
} | |
if (!angular.isArray(substrings)) { | |
if (utils.isString(substrings)) { | |
return string.indexOf(substrings) !== -1; | |
} | |
return false; | |
} | |
return substrings.some(function(substring) { | |
return string.indexOf(substring) !== -1; | |
}); | |
}, | |
/** | |
* Just if you need random string | |
* | |
* @link https://bocoup.com/weblog/random-numbers | |
* @link https://developer.mozilla.org/en-US/docs/Web/API/RandomSource/getRandomValues | |
* @returns {String} | |
*/ | |
rand: function() { | |
if (crypto && crypto.getRandomValues) { | |
return utils.fastArrayJoin(crypto.getRandomValues.call(crypto, u32_4)); | |
} | |
var i = 0, result = ''; | |
for (; i < a16.length; i++) { | |
result += getCharCode(Math.random() * charsetLength|0); | |
} | |
}, | |
/** | |
* Simple, fast generation of RFC4122 UUIDS. | |
* | |
* @link http://www.ietf.org/rfc/rfc4122.txt | |
* @return {String} | |
*/ | |
UUID: function() { | |
var b = function (a) { | |
return a?(a^Math.random()*16>>a/4).toString(16):([1e7]+-1e3+-4e3+-8e3+-1e11) | |
.replace(/[018]/g, b) | |
}; | |
return b(); | |
}, | |
/** | |
* Javascript implementation of Java’s String.hashCode() method | |
* @param {String} str | |
* @param {Boolean} [inHex] | |
* @param {Number} [radix=10] - scale of notation (radix=16 if inHex is false) | |
* @returns {String} | |
*/ | |
hashCode: _.memoize(function(value, inHex, radix) { | |
if (utils.isObject(value)) { | |
value = _.toPairs(value); | |
} | |
if (!utils.isString(value)) { | |
value = !value ? '0' : value.toString(); | |
} | |
var hash = 0, i = 0, | |
length = value.length; | |
if (!length) { | |
return hash; | |
} | |
for (; i < length; i++) { | |
hash = ((hash << 5) - hash) + value.charCodeAt(i); | |
hash = hash & hash; | |
} | |
radix = inHex ? 16 : (radix ? radix : 10); | |
return Math.abs(hash).toString(radix); | |
}, function(value, inHex, radix){ | |
return _.chain([value, inHex, radix]) | |
.map(function(value) { | |
if (utils.isObject(value)){ | |
return JSON.stringify(value) + typeof(value); | |
} | |
return String(value) + typeof(value); | |
}) | |
.value() | |
.join() | |
}), | |
hash: function(value) { | |
return utils.hashCode(value, 0, 36); | |
}, | |
/** | |
* Generates CRC32 for string | |
* https://jsperf.com/js-crc32 | |
*/ | |
CRC32: _.memoize(function(str) { | |
if (utils.isObject(str)){ | |
str = JSON.stringify(str) + typeof(str); | |
} else { | |
str = String(str); | |
} | |
var i = 0, l = str.length, crc = 0 ^ (-1); | |
for (; i < l; ) { | |
crc = (crc >>> 8) ^ _makeCRCTable((crc ^ str.charCodeAt(++i)) & 0xFF); | |
} | |
return (crc ^ (-1)) >>> 0; | |
}, function(str){ | |
return utils.isObject(str) ? JSON.stringify(str) + typeof(str):String(str); | |
}), | |
/** | |
* Capitalize str | |
* | |
* @param {String} str | |
* @param {Boolean} lowercaseRest - if true other part of string will be lowercased | |
* @returns {String} | |
*/ | |
capitalize: _.memoize(function(str, lowercaseRest) { | |
if (!str) { | |
return str; | |
} | |
if (!utils.isString(str)) { | |
str = String(str); | |
} | |
return str.charAt(0).toUpperCase() + (lowercaseRest ? str.slice(1).toLowerCase() : str.slice(1)); | |
}, function(str, lowercaseRest) {return [str + typeof(str), lowercaseRest + typeof(lowercaseRest)].join()}) | |
}; | |
return utils; | |
}]) | |
.service('Engagements', ['requestCanceler', 'config', '$filter', '$http', 'singleEngagementTemplateUrl', 'engagementsTemplateUrl', 'dateUtils', 'oca_root', 'getApiCache', 'getCached', 'dateRange', 'utils', 'feature', 'sendLegacyApiRequest', 'urlTemplate', function(requestCanceler, config, $filter, $http, singleEngagementTemplateUrl, engagementsTemplateUrl, dateUtils, oca_root, getApiCache, getCached, dateRange, utils, feature, sendLegacyApiRequest, urlTemplate) { | |
/* | |
* contract fields example (engagements API) | |
{ | |
hourly_charge_rate: "240", | |
engagement_end_ts: "", | |
status: "active", | |
weekly_salary_charge_amount: "0", | |
buyer_company__name: "Company Name 1+2={{1+2}}", | |
buyer_company__reference: "188955", | |
created_time: "1500394588000", | |
job__title: "Round test 4", | |
provider_company__name: "", | |
cj_job_application_uid: "", | |
reference: "402718", | |
engagement_start_date: "1500336000000", | |
provider_company__reference: "", | |
weekly_hours_limit: "", | |
engagement_job_type: "hourly", | |
buyer_team__name: "Company Name 1+2={{1+2}}", | |
provider_team__reference: "", | |
job_application_ref: "", | |
job_ref_ciphertext: "~01ff2bc8a79192ae6a", | |
active_milestone: "", | |
is_paused: "0", | |
engagement_start_ts: "1500394588000", | |
is_autopaused: "0", | |
buyer_team__reference: "188955", | |
engagement_end_date: "", | |
provider__name: "Alex Black", | |
provider_team__id: "", | |
offer_id: "", | |
weekly_stipend_hours: "", | |
dev_recno_ciphertext: "~019dc6e32gb52f9f99", | |
buyer_team__id: "xtyqmd1xmiy67eag", | |
provider__reference: "789390", | |
provider_team__name: "", | |
engagement_title: "Round test 4", | |
provider__id: "alexblack", | |
description: "", | |
portrait_url: "https://nonane-portraits.s3.amazonaws.com/Users:alexblack:PortraitUrl_original?AWSAccessKeyId=AKIAI6O4KKJ4MFGGZ5AA&Expires=2147483647&Signature=xWWUa%2FgIsqxrJlUlFTMGgLcQTj4%3D&1474484153340556" | |
} | |
*/ | |
var unknownFF = feature.isEnabled('unknownFeature'), | |
requestParams = { | |
method: 'GET', | |
transformResponse: function(response, headersGetter, status) { | |
if (!response) { | |
return []; | |
} | |
//if 401 Unauthorized | |
if (!unknownFF && parseInt(status, 10) === 401) { | |
return location.reload(); | |
} | |
response = angular.fromJson(response); | |
if (_.get(response, 'engagement')) { | |
var engagement = _.get(response, 'engagement'); | |
engagement.engagement_title = _.get(engagement, 'job__title', ''); | |
return { | |
engagement: engagement | |
}; | |
} | |
return { | |
lister: _.get(response, 'engagements.lister', []), | |
engagements: _.get(response, 'engagements.engagement', []) | |
}; | |
} | |
}, | |
cache = getApiCache('engagements'); | |
var engagements = { | |
all: [], | |
hashFunction: function(params) { | |
if (_.isString(params)) { | |
return utils.hash(params); | |
} | |
return utils.hash([params.buyer_team__reference, params.status, params.page, params.limit, params.regex].join()); | |
}, | |
result: function (url, cache) { | |
return getCached(url, cache, requestParams.transformResponse); | |
}, | |
_prepareAndSend: function(successCallback, errorCallback) { | |
// debugger; | |
return sendLegacyApiRequest(requestParams, function(data) { | |
if (utils.isFunction(successCallback)) { | |
successCallback(engagements.result(requestParams.url, cache) || data); | |
} | |
}, function(obj, status) { | |
if (utils.isFunction(errorCallback)) { | |
errorCallback(status); | |
} | |
}); | |
}, | |
one: function(ref, successCallback, errorCallback) { | |
// debugger; | |
cache = getApiCache('engagement'); | |
requestParams.url = urlTemplate.fill(singleEngagementTemplateUrl, {contract_reference: ref}); | |
requestParams.params = { | |
field_set: ["basic", "buyer_team__name", "parent_reference", "buyer_company__reference", "buyer_company__name", "provider__name", "provider_team__name", "provider_company__name", "provider_company__reference"].join(';'), | |
}; | |
requestCanceler | |
.setApiIdentifier('engagement') | |
.setUrl(requestParams.url+ref) | |
.setCache(cache); | |
var cachedResponse = getCached(requestParams.url, cache, requestParams.transformResponse); | |
if (cachedResponse) { | |
if (utils.isFunction(successCallback)) { | |
successCallback(cachedResponse); | |
} | |
var deferred = $q.defer(); | |
deferred.resolve(cachedResponse); | |
return deferred.promise; | |
} | |
_.assignIn(requestParams, { | |
timeout: requestCanceler | |
.cancelRequestIfNeeded() | |
.getPromise(), | |
cache: cache, | |
cancelable: true | |
}); | |
return this._prepareAndSend(successCallback, errorCallback); | |
}, | |
fetch: function(params, successCallback, errorCallback) { | |
cache = getApiCache('engagements'); | |
requestParams.url = engagementsTemplateUrl; | |
requestParams.params = _.assignIn({ | |
field_set: ["basic", "buyer_team__name", "parent_reference", "buyer_company__reference", "buyer_company__name", "provider__name", "provider_team__name", "provider_company__name", "provider_company__reference"].join(';'), | |
order_by: ['provider__name', 'engagement_title'].join(';')+'A', | |
page: 0, | |
role: ['buyer', 'buyer_wd'].join(';'), | |
include_sub_teams: true | |
// regex: params.regex | |
}, params, { | |
status: params.includePast ? ['closed', 'active'].join(';') : 'active', | |
buyer_team__reference: config.getTeam().reference | |
}); | |
requestCanceler | |
.setApiIdentifier('engagements') | |
.setUrl(requestParams.url+this.hashFunction(requestParams.params)) | |
.setCache(cache); | |
var cachedResponse = getCached(requestParams.url, cache, requestParams.transformResponse); | |
if (cachedResponse) { | |
if (utils.isFunction(successCallback)) { | |
successCallback(cachedResponse); | |
} | |
var deferred = $q.defer(); | |
deferred.resolve(cachedResponse); | |
return deferred.promise; | |
} | |
_.assignIn(requestParams, { | |
timeout: requestCanceler | |
.cancelRequestIfNeeded() | |
.getPromise(), | |
cache: cache, | |
cancelable: true | |
}); | |
return this._prepareAndSend(successCallback, errorCallback); | |
} | |
}; | |
return engagements; | |
}]) | |
.factory('config', ['baseConfig', 'contracts', function(baseConfig, contracts) { | |
var config = { | |
contractId: null, | |
tz: baseConfig.findInitialTimezone() | |
}; | |
config = _.assignIn(baseConfig, config); | |
config.tzOffset = config.getTzOffset(); | |
config.date = config.getInitDate(); | |
config.changeContract(config.contractId); | |
return config; | |
}]) | |
.service('Snapshots', ['$timeout', 'Workdiary', 'Workdays', 'config', 'loading', 'dateUtils', '$filter', '$q', function($timeout, Workdiary, Workdays, config, loading, dateUtils, $filter, $q) { | |
var errorsCatcher = function(deffered) { | |
return function() { | |
deffered.reject({ | |
error: arguments | |
}); | |
} | |
}; | |
return { | |
selected_time: null, | |
snapshot: null, | |
_allSnapshots: [], | |
snapshots: function(index) { | |
return !_.isUndefined(index) ? _.get(this._allSnapshots, index) : this._allSnapshots; | |
}, | |
count: function() { | |
return this.snapshots().length; | |
}, | |
fillSnapshots: function() { | |
this._allSnapshots = _.chain(Workdiary.snapshots) | |
.values() | |
.concat(this._allSnapshots) | |
.flatten() | |
.compact() | |
.uniqBy('cell_time') | |
.sortBy('cell_time') | |
.value(); | |
return this; | |
}, | |
move: function (direction) { | |
if (this.count() !== _.size(_.values(Workdiary.snapshots))) { | |
this.fillSnapshots(); | |
} | |
return this.setCurrent(this.snapshots(this.findIndex() + direction)); | |
}, | |
find: function(time) { | |
time = +time || this.selected_time; | |
return _.find(this.snapshots(), function(s) { | |
return +s.time === time || +s.cell_time === time; | |
}); | |
}, | |
findIndex: function(time) { | |
time = +time || this.selected_time; | |
return _.findIndex(this.snapshots(), function(s) { | |
return +s.time === time || +s.cell_time === time; | |
}); | |
}, | |
checkNeighbour: function(direction) { | |
var deffered = $q.defer(); | |
var keys = Workdays.all; | |
var time = this.selected_time * 1000; | |
var key = _.indexOf(keys, $filter('date')(dateUtils.utcToLocal(dateUtils.sparse(time+'u')), 'yyyyMMdd')); | |
var result = _.get(Workdays.all, key + direction); | |
if (result) { | |
var next_date_timestamp = dateUtils.shortDateParse(result, false, true); | |
} else { | |
deffered.resolve(); | |
return deffered.promise; | |
} | |
Workdiary.fetchByDate(next_date_timestamp, function(data) { | |
this.fillSnapshots(); | |
this.setCurrent(); | |
deffered.resolve(); | |
}.bind(this), function() { | |
errorsCatcher(deffered).apply(this, arguments); | |
}.bind(this)); | |
return deffered.promise; | |
}, | |
setCurrent: function(newSnapshot, index) { | |
var selected_time; | |
if (this.count() !== _.size(_.values(Workdiary.snapshots))) { | |
this.fillSnapshots(); | |
} | |
if (newSnapshot) { | |
if (_.isObject(newSnapshot)) { | |
selected_time = +_.get(newSnapshot, 'time', newSnapshot.cell_time); | |
} | |
this.selected_time = +selected_time || +newSnapshot; | |
this.snapshot = this.find(this.selected_time); | |
} | |
this.next = this.snapshots(this.findIndex() + 1); | |
this.prev = this.snapshots(this.findIndex() - 1); | |
return this; | |
}, | |
neighbour: function(direction) { | |
return this.snapshots(this.findIndex() + direction); | |
} | |
}; | |
}]) | |
.service('Contracts', ['$timeout', '$injector', 'loading', 'dateUtils', '$filter', '$q', 'contracts', 'utils', 'Engagements', 'config', function($timeout, $injector, loading, dateUtils, $filter, $q, contracts, utils, Engagements, config) { | |
var limit = 20; | |
var _items = _.chain(config.contracts) | |
.values() | |
.concat(contracts) | |
.flatten() | |
.compact() | |
.uniqBy('reference') | |
.sortBy('reference') | |
.value(); | |
var loaded = {}; | |
//teamId { page: is past } | |
return { | |
page: 0, | |
lastQuery: '', | |
query: function(query) { | |
if (query) { | |
this.lastQuery = query; | |
return this; | |
} | |
return this.lastQuery; | |
}, | |
cache: {}, | |
add: function(query, data) { | |
var contract, i = 0, l = data.length, | |
hash = this.hasher(query), | |
contracts = this.cache[hash]; | |
if (!contracts) { | |
this.cache[hash] = []; | |
contracts = this.cache[hash]; | |
} | |
for (; i < l; ) { | |
contract = data[i++]; | |
if (_.find(contracts, { 'reference': contract.reference })) { | |
continue; | |
} | |
contract.buyer_team_id = contract.buyer_team__id; | |
contracts.push(contract); | |
} | |
return data; | |
}, | |
isLoaded: function(query) { | |
return !!this.cache[this.hasher(query)]; | |
}, | |
get: function(query) { | |
return this.cache[this.hasher(query)] || []; | |
}, | |
all: function() { | |
if (!_.size(this.cache)) { | |
return []; | |
} | |
return _.chain(this.cache) | |
.values() | |
.flatten() | |
.compact() | |
.value(); | |
}, | |
count: function(query, teamId) { | |
return _.get(this.cache, this.hasher(query, teamId), []).length; | |
}, | |
hasher: _.memoize(function(str, teamId) { | |
str = str || ''; | |
teamId = teamId || config.teamId; | |
return utils.hash('' + str + teamId + config.includePast); | |
}, function(str, teamId) { | |
return '' + str + (teamId || config.teamId) + config.includePast; | |
}), | |
lister: {}, | |
pageHashes: {}, | |
find: function(ref) { | |
if (!ref) { | |
return; | |
} | |
return _.find(this.all(), function(contract) { | |
return _.includes([ | |
String(contract.reference), | |
String(contract.parent_reference) | |
], | |
ref.toString() | |
); | |
}); | |
}, | |
getPage: function(query) { | |
var hash = this.hasher(query); | |
if (utils.isUndefined(this.pageHashes[hash])) { | |
this.pageHashes[hash] = 0; | |
} | |
return this.pageHashes[hash]; | |
}, | |
incPage: function(query) { | |
var hash = this.hasher(query); | |
if (utils.isUndefined(this.pageHashes[hash])) { | |
this.pageHashes[hash] = 0; | |
} | |
this.pageHashes[hash]++; | |
}, | |
requests: {}, | |
fetch: function(query, page) { | |
query = query || ''; | |
this.page = _.isUndefined(page) ? this.getPage(query) : page; | |
var params = { | |
//offset:count | |
page: (+this.page*limit)+';'+limit, | |
}; | |
params.regex = query; | |
var self = this; | |
params.includePast = config.includePast; | |
this.query(query); | |
if (this.requests[this.hasher(query)]) { | |
return this.requests[this.hasher(query)]; | |
} | |
this.requests[this.hasher(query)] = Engagements | |
.fetch(params) | |
.then(function(response) { | |
self.incPage(query); | |
self.lister = _.get(response, 'data.lister', []); | |
self.requests[self.hasher(query)] = false; | |
return self.add(query, _.get(response, 'data.engagements', [])); | |
}); | |
return this.requests[this.hasher(query)]; | |
}, | |
fetchByRef: function(ref, successCallback, errorCallback) { | |
var self = this; | |
if (this.requests[this.hasher(ref)]) { | |
return this.requests[this.hasher(ref)]; | |
} | |
this.requests[this.hasher(ref)] = Engagements | |
.one(ref, successCallback, errorCallback) | |
.then(function(response) { | |
var contract = _.get(response, 'data.engagement'); | |
if (contract) { | |
self.add(ref, [contract]); | |
config.contracts.push(contract); | |
} | |
self.requests[self.hasher(ref)] = false; | |
return contract; | |
}); | |
return this.requests[this.hasher(ref)]; | |
}, | |
byTeamRef: function(teamId) { | |
teamId = teamId || config.teamId; | |
return _.filter(this.all(), {buyer_team__id: teamId}); | |
}, | |
getFirstActiveContract: function(teamRef) { | |
return _.chain(this.all()) | |
.filter(['is_paused', false]) | |
.orderBy(['engagement_title', 'provider__name'], ['asc', 'asc']) | |
.first() | |
.value(); | |
}, | |
}; | |
}]) | |
; | |
})(angular); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment