UNPKG

24.9 kBJavaScriptView Raw
1"use strict";
2var __assign = (this && this.__assign) || function () {
3 __assign = Object.assign || function(t) {
4 for (var s, i = 1, n = arguments.length; i < n; i++) {
5 s = arguments[i];
6 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7 t[p] = s[p];
8 }
9 return t;
10 };
11 return __assign.apply(this, arguments);
12};
13var __importDefault = (this && this.__importDefault) || function (mod) {
14 return (mod && mod.__esModule) ? mod : { "default": mod };
15};
16Object.defineProperty(exports, "__esModule", { value: true });
17// (C) 2007-2020 GoodData Corporation
18var md5_1 = __importDefault(require("md5"));
19var invariant_1 = __importDefault(require("invariant"));
20var cloneDeep_1 = __importDefault(require("lodash/cloneDeep"));
21var compact_1 = __importDefault(require("lodash/compact"));
22var filter_1 = __importDefault(require("lodash/filter"));
23var first_1 = __importDefault(require("lodash/first"));
24var find_1 = __importDefault(require("lodash/find"));
25var map_1 = __importDefault(require("lodash/map"));
26var merge_1 = __importDefault(require("lodash/merge"));
27var every_1 = __importDefault(require("lodash/every"));
28var get_1 = __importDefault(require("lodash/get"));
29var isEmpty_1 = __importDefault(require("lodash/isEmpty"));
30var negate_1 = __importDefault(require("lodash/negate"));
31var partial_1 = __importDefault(require("lodash/partial"));
32var flatten_1 = __importDefault(require("lodash/flatten"));
33var set_1 = __importDefault(require("lodash/set"));
34var rules_1 = require("../utils/rules");
35var definitions_1 = require("../utils/definitions");
36var attributesMapLoader_1 = require("../utils/attributesMapLoader");
37var visualizationObjectHelper_1 = require("../utils/visualizationObjectHelper");
38var notEmpty = negate_1.default(isEmpty_1.default);
39function findHeaderForMappingFn(mapping, header) {
40 return ((mapping.element === header.id || mapping.element === header.uri) && header.measureIndex === undefined);
41}
42function wrapMeasureIndexesFromMappings(metricMappings, headers) {
43 if (metricMappings) {
44 metricMappings.forEach(function (mapping) {
45 var header = find_1.default(headers, partial_1.default(findHeaderForMappingFn, mapping));
46 if (header) {
47 header.measureIndex = mapping.measureIndex;
48 header.isPoP = mapping.isPoP;
49 }
50 });
51 }
52 return headers;
53}
54var emptyResult = {
55 extendedTabularDataResult: {
56 values: [],
57 warnings: [],
58 },
59};
60var MAX_TITLE_LENGTH = 1000;
61function getMetricTitle(suffix, title) {
62 var maxLength = MAX_TITLE_LENGTH - suffix.length;
63 if (title && title.length > maxLength) {
64 if (title[title.length - 1] === ")") {
65 return title.substring(0, maxLength - 2) + "\u2026)" + suffix;
66 }
67 return title.substring(0, maxLength - 1) + "\u2026" + suffix;
68 }
69 return "" + title + suffix;
70}
71var getBaseMetricTitle = partial_1.default(getMetricTitle, "");
72var CONTRIBUTION_METRIC_FORMAT = "#,##0.00%";
73function getPoPDefinition(measure) {
74 return get_1.default(measure, ["definition", "popMeasureDefinition"], {});
75}
76function getAggregation(measure) {
77 return get_1.default(visualizationObjectHelper_1.getDefinition(measure), "aggregation", "").toLowerCase();
78}
79function isEmptyFilter(metricFilter) {
80 if (get_1.default(metricFilter, "positiveAttributeFilter")) {
81 return isEmpty_1.default(get_1.default(metricFilter, ["positiveAttributeFilter", "in"]));
82 }
83 if (get_1.default(metricFilter, "negativeAttributeFilter")) {
84 return isEmpty_1.default(get_1.default(metricFilter, ["negativeAttributeFilter", "notIn"]));
85 }
86 if (get_1.default(metricFilter, "absoluteDateFilter")) {
87 return (get_1.default(metricFilter, ["absoluteDateFilter", "from"]) === undefined &&
88 get_1.default(metricFilter, ["absoluteDateFilter", "to"]) === undefined);
89 }
90 return (get_1.default(metricFilter, ["relativeDateFilter", "from"]) === undefined &&
91 get_1.default(metricFilter, ["relativeDateFilter", "to"]) === undefined);
92}
93function allFiltersEmpty(item) {
94 return every_1.default(map_1.default(visualizationObjectHelper_1.getMeasureFilters(item), function (f) { return isEmptyFilter(f); }));
95}
96function isDerived(measure) {
97 var aggregation = getAggregation(measure);
98 return aggregation !== "" || !allFiltersEmpty(measure);
99}
100function getAttrTypeFromMap(dfUri, attributesMap) {
101 return get_1.default(get_1.default(attributesMap, [dfUri], {}), ["attribute", "content", "type"]);
102}
103function getAttrUriFromMap(dfUri, attributesMap) {
104 return get_1.default(get_1.default(attributesMap, [dfUri], {}), ["attribute", "meta", "uri"]);
105}
106function isAttrFilterNegative(attributeFilter) {
107 return get_1.default(attributeFilter, "negativeAttributeFilter") !== undefined;
108}
109function getAttrFilterElements(attributeFilter) {
110 var isNegative = isAttrFilterNegative(attributeFilter);
111 var pathToElements = isNegative
112 ? ["negativeAttributeFilter", "notIn"]
113 : ["positiveAttributeFilter", "in"];
114 return get_1.default(attributeFilter, pathToElements, []);
115}
116function getAttrFilterExpression(measureFilter, attributesMap) {
117 var isNegative = get_1.default(measureFilter, "negativeAttributeFilter", false);
118 var detailPath = isNegative ? "negativeAttributeFilter" : "positiveAttributeFilter";
119 var attributeUri = getAttrUriFromMap(get_1.default(measureFilter, [detailPath, "displayForm", "uri"]), attributesMap);
120 var elements = getAttrFilterElements(measureFilter);
121 if (isEmpty_1.default(elements)) {
122 return null;
123 }
124 var elementsForQuery = map_1.default(elements, function (e) { return "[" + e + "]"; });
125 var negative = isNegative ? "NOT " : "";
126 return "[" + attributeUri + "] " + negative + "IN (" + elementsForQuery.join(",") + ")";
127}
128function getDateFilterExpression() {
129 // measure date filter was never supported
130 return "";
131}
132function getFilterExpression(attributesMap, measureFilter) {
133 if (visualizationObjectHelper_1.isAttributeMeasureFilter(measureFilter)) {
134 return getAttrFilterExpression(measureFilter, attributesMap);
135 }
136 return getDateFilterExpression();
137}
138function getGeneratedMetricExpression(item, attributesMap) {
139 var aggregation = getAggregation(item).toUpperCase();
140 var objectUri = get_1.default(visualizationObjectHelper_1.getDefinition(item), "item.uri");
141 var where = filter_1.default(map_1.default(visualizationObjectHelper_1.getMeasureFilters(item), partial_1.default(getFilterExpression, attributesMap)), function (e) { return !!e; });
142 return "SELECT " + (aggregation ? aggregation + "([" + objectUri + "])" : "[" + objectUri + "]") + (notEmpty(where) ? " WHERE " + where.join(" AND ") : "");
143}
144function getPercentMetricExpression(category, attributesMap, measure) {
145 var metricExpressionWithoutFilters = "SELECT [" + get_1.default(visualizationObjectHelper_1.getDefinition(measure), "item.uri") + "]";
146 if (isDerived(measure)) {
147 metricExpressionWithoutFilters = getGeneratedMetricExpression(set_1.default(cloneDeep_1.default(measure), ["definition", "measureDefinition", "filters"], []), attributesMap);
148 }
149 var attributeUri = getAttrUriFromMap(get_1.default(category, "displayForm.uri"), attributesMap);
150 var whereFilters = filter_1.default(map_1.default(visualizationObjectHelper_1.getMeasureFilters(measure), partial_1.default(getFilterExpression, attributesMap)), function (e) { return !!e; });
151 var whereExpression = notEmpty(whereFilters) ? " WHERE " + whereFilters.join(" AND ") : "";
152 // tslint:disable-next-line:max-line-length
153 return "SELECT (" + metricExpressionWithoutFilters + whereExpression + ") / (" + metricExpressionWithoutFilters + " BY ALL [" + attributeUri + "]" + whereExpression + ")";
154}
155function getPoPExpression(attributeUri, metricExpression) {
156 return "SELECT " + metricExpression + " FOR PREVIOUS ([" + attributeUri + "])";
157}
158function getGeneratedMetricHash(title, format, expression) {
159 return md5_1.default(expression + "#" + title + "#" + format);
160}
161function getMeasureType(measure) {
162 var aggregation = getAggregation(measure);
163 if (aggregation === "") {
164 return "metric";
165 }
166 else if (aggregation === "count") {
167 return "attribute";
168 }
169 return "fact";
170}
171function getGeneratedMetricIdentifier(item, aggregation, expressionCreator, hasher, attributesMap) {
172 var _a = get_1.default(visualizationObjectHelper_1.getDefinition(item), "item.uri", "").split("/"), prjId = _a[3], id = _a[5];
173 var identifier = prjId + "_" + id;
174 var hash = hasher(expressionCreator(item, attributesMap));
175 var hasNoFilters = isEmpty_1.default(visualizationObjectHelper_1.getMeasureFilters(item));
176 var type = getMeasureType(item);
177 var prefix = hasNoFilters || allFiltersEmpty(item) ? "" : "_filtered";
178 return type + "_" + identifier + ".generated." + hash + prefix + "_" + aggregation;
179}
180function isDateAttribute(attribute, attributesMap) {
181 if (attributesMap === void 0) { attributesMap = {}; }
182 return getAttrTypeFromMap(get_1.default(attribute, ["displayForm", "uri"]), attributesMap) !== undefined;
183}
184function getMeasureSorting(measure, mdObj) {
185 var sorting = get_1.default(mdObj, ["properties", "sortItems"], []);
186 var matchedSorting = sorting.find(function (sortItem) {
187 var measureSortItem = get_1.default(sortItem, ["measureSortItem"]);
188 if (measureSortItem) {
189 // only one item now, we support only 2d data
190 var identifier = get_1.default(measureSortItem, [
191 "locators",
192 0,
193 "measureLocatorItem",
194 "measureIdentifier",
195 ]);
196 return identifier === get_1.default(measure, "localIdentifier");
197 }
198 return false;
199 });
200 if (matchedSorting) {
201 return get_1.default(matchedSorting, ["measureSortItem", "direction"], null);
202 }
203 return null;
204}
205function getCategorySorting(category, mdObj) {
206 var sorting = get_1.default(mdObj, ["properties", "sortItems"], []);
207 var matchedSorting = sorting.find(function (sortItem) {
208 var attributeSortItem = get_1.default(sortItem, ["attributeSortItem"]);
209 if (attributeSortItem) {
210 var identifier = get_1.default(attributeSortItem, ["attributeIdentifier"]);
211 return identifier === get_1.default(category, "localIdentifier");
212 }
213 return false;
214 });
215 if (matchedSorting) {
216 return get_1.default(matchedSorting, ["attributeSortItem", "direction"], null);
217 }
218 return null;
219}
220var createPureMetric = function (measure, mdObj, measureIndex) { return ({
221 element: get_1.default(measure, ["definition", "measureDefinition", "item", "uri"]),
222 sort: getMeasureSorting(measure, mdObj),
223 meta: { measureIndex: measureIndex },
224}); };
225function createDerivedMetric(measure, mdObj, measureIndex, attributesMap) {
226 var format = measure.format;
227 var sort = getMeasureSorting(measure, mdObj);
228 var title = getBaseMetricTitle(measure.title);
229 var hasher = partial_1.default(getGeneratedMetricHash, title, format);
230 var aggregation = getAggregation(measure);
231 var element = getGeneratedMetricIdentifier(measure, aggregation.length ? aggregation : "base", getGeneratedMetricExpression, hasher, attributesMap);
232 var definition = {
233 metricDefinition: {
234 identifier: element,
235 expression: getGeneratedMetricExpression(measure, attributesMap),
236 title: title,
237 format: format,
238 },
239 };
240 return {
241 element: element,
242 definition: definition,
243 sort: sort,
244 meta: {
245 measureIndex: measureIndex,
246 },
247 };
248}
249function createContributionMetric(measure, mdObj, measureIndex, attributesMap) {
250 var attribute = first_1.default(visualizationObjectHelper_1.getAttributes(mdObj));
251 var getMetricExpression = partial_1.default(getPercentMetricExpression, attribute, attributesMap);
252 var title = getBaseMetricTitle(get_1.default(measure, "title"));
253 var hasher = partial_1.default(getGeneratedMetricHash, title, CONTRIBUTION_METRIC_FORMAT);
254 var identifier = getGeneratedMetricIdentifier(measure, "percent", getMetricExpression, hasher, attributesMap);
255 return {
256 element: identifier,
257 definition: {
258 metricDefinition: {
259 identifier: identifier,
260 expression: getMetricExpression(measure),
261 title: title,
262 format: CONTRIBUTION_METRIC_FORMAT,
263 },
264 },
265 sort: getMeasureSorting(measure, mdObj),
266 meta: {
267 measureIndex: measureIndex,
268 },
269 };
270}
271function getOriginalMeasureForPoP(popMeasure, mdObj) {
272 return visualizationObjectHelper_1.getMeasures(mdObj).find(function (measure) {
273 return get_1.default(measure, "localIdentifier") === get_1.default(getPoPDefinition(popMeasure), ["measureIdentifier"]);
274 });
275}
276function createPoPMetric(popMeasure, mdObj, measureIndex, attributesMap) {
277 var title = getBaseMetricTitle(get_1.default(popMeasure, "title"));
278 var format = get_1.default(popMeasure, "format");
279 var hasher = partial_1.default(getGeneratedMetricHash, title, format);
280 var attributeUri = get_1.default(popMeasure, "definition.popMeasureDefinition.popAttribute.uri");
281 var originalMeasure = getOriginalMeasureForPoP(popMeasure, mdObj);
282 var originalMeasureExpression = "[" + get_1.default(visualizationObjectHelper_1.getDefinition(originalMeasure), ["item", "uri"]) + "]";
283 var metricExpression = getPoPExpression(attributeUri, originalMeasureExpression);
284 if (isDerived(originalMeasure)) {
285 var generated = createDerivedMetric(originalMeasure, mdObj, measureIndex, attributesMap);
286 var generatedMeasureExpression = "(" + get_1.default(generated, [
287 "definition",
288 "metricDefinition",
289 "expression",
290 ]) + ")";
291 metricExpression = getPoPExpression(attributeUri, generatedMeasureExpression);
292 }
293 var identifier = getGeneratedMetricIdentifier(originalMeasure, "pop", function () { return metricExpression; }, hasher, attributesMap);
294 return {
295 element: identifier,
296 definition: {
297 metricDefinition: {
298 identifier: identifier,
299 expression: metricExpression,
300 title: title,
301 format: format,
302 },
303 },
304 sort: getMeasureSorting(popMeasure, mdObj),
305 meta: {
306 measureIndex: measureIndex,
307 isPoP: true,
308 },
309 };
310}
311function createContributionPoPMetric(popMeasure, mdObj, measureIndex, attributesMap) {
312 var attributeUri = get_1.default(popMeasure, ["definition", "popMeasureDefinition", "popAttribute", "uri"]);
313 var originalMeasure = getOriginalMeasureForPoP(popMeasure, mdObj);
314 var generated = createContributionMetric(originalMeasure, mdObj, measureIndex, attributesMap);
315 var title = getBaseMetricTitle(get_1.default(popMeasure, "title"));
316 var format = CONTRIBUTION_METRIC_FORMAT;
317 var hasher = partial_1.default(getGeneratedMetricHash, title, format);
318 var generatedMeasureExpression = "(" + get_1.default(generated, [
319 "definition",
320 "metricDefinition",
321 "expression",
322 ]) + ")";
323 var metricExpression = getPoPExpression(attributeUri, generatedMeasureExpression);
324 var identifier = getGeneratedMetricIdentifier(originalMeasure, "pop", function () { return metricExpression; }, hasher, attributesMap);
325 return {
326 element: identifier,
327 definition: {
328 metricDefinition: {
329 identifier: identifier,
330 expression: metricExpression,
331 title: title,
332 format: format,
333 },
334 },
335 sort: getMeasureSorting(),
336 meta: {
337 measureIndex: measureIndex,
338 isPoP: true,
339 },
340 };
341}
342function categoryToElement(attributesMap, mdObj, category) {
343 var element = getAttrUriFromMap(get_1.default(category, ["displayForm", "uri"]), attributesMap);
344 return {
345 element: element,
346 sort: getCategorySorting(category, mdObj),
347 };
348}
349function isPoP(_a) {
350 var definition = _a.definition;
351 return get_1.default(definition, "popMeasureDefinition") !== undefined;
352}
353function isContribution(_a) {
354 var definition = _a.definition;
355 return get_1.default(definition, ["measureDefinition", "computeRatio"]);
356}
357function isPoPContribution(popMeasure, mdObj) {
358 if (isPoP(popMeasure)) {
359 var originalMeasure = getOriginalMeasureForPoP(popMeasure, mdObj);
360 return isContribution(originalMeasure);
361 }
362 return false;
363}
364function isCalculatedMeasure(_a) {
365 var definition = _a.definition;
366 return get_1.default(definition, ["measureDefinition", "aggregation"]) === undefined;
367}
368var rules = new rules_1.Rules();
369rules.addRule([isPoPContribution], createContributionPoPMetric);
370rules.addRule([isPoP], createPoPMetric);
371rules.addRule([isContribution], createContributionMetric);
372rules.addRule([isDerived], createDerivedMetric);
373rules.addRule([isCalculatedMeasure], createPureMetric);
374function getMetricFactory(measure, mdObj) {
375 var factory = rules.match(measure, mdObj);
376 invariant_1.default(factory, "Unknown factory for: " + measure);
377 return factory;
378}
379function getExecutionDefinitionsAndColumns(mdObj, options, attributesMap) {
380 var measures = visualizationObjectHelper_1.getMeasures(mdObj);
381 var attributes = visualizationObjectHelper_1.getAttributes(mdObj);
382 var metrics = flatten_1.default(map_1.default(measures, function (measure, index) {
383 return getMetricFactory(measure, mdObj)(measure, mdObj, index, attributesMap);
384 }));
385 if (options.removeDateItems) {
386 attributes = filter_1.default(attributes, function (attribute) { return !isDateAttribute(attribute, attributesMap); });
387 }
388 attributes = map_1.default(attributes, partial_1.default(categoryToElement, attributesMap, mdObj));
389 var columns = compact_1.default(map_1.default(attributes.concat(metrics), "element"));
390 return {
391 columns: columns,
392 definitions: definitions_1.sortDefinitions(compact_1.default(map_1.default(metrics, "definition"))),
393 };
394}
395/**
396 * Module for execution on experimental execution resource
397 *
398 * @class execution
399 * @module execution
400 * @deprecated The module is in maintenance mode only (just the the compilation issues are being fixed when
401 * referenced utilities and interfaces are being changed) and is not being extended when AFM executor
402 * have new functionality added.
403 */
404var ExperimentalExecutionsModule = /** @class */ (function () {
405 function ExperimentalExecutionsModule(xhr, loadAttributesMap) {
406 this.xhr = xhr;
407 this.loadAttributesMap = loadAttributesMap;
408 }
409 /**
410 * For the given projectId it returns table structure with the given
411 * elements in column headers.
412 *
413 * @method getData
414 * @param {String} projectId - GD project identifier
415 * @param {Array} columns - An array of attribute or metric identifiers.
416 * @param {Object} executionConfiguration - Execution configuration - can contain for example
417 * property "where" containing query-like filters
418 * property "orderBy" contains array of sorted properties to order in form
419 * [{column: 'identifier', direction: 'asc|desc'}]
420 * @param {Object} settings - Supports additional settings accepted by the underlying
421 * xhr.ajax() calls
422 *
423 * @return {Object} Structure with `headers` and `rawData` keys filled with values from execution.
424 */
425 ExperimentalExecutionsModule.prototype.getData = function (projectId, columns, executionConfiguration, settings) {
426 var _this = this;
427 if (executionConfiguration === void 0) { executionConfiguration = {}; }
428 if (settings === void 0) { settings = {}; }
429 if (process.env.NODE_ENV !== "test") {
430 // tslint:disable-next-line:no-console
431 console.warn("ExperimentalExecutionsModule is deprecated and is no longer being maintained. " +
432 "Please migrate to the ExecuteAfmModule.");
433 }
434 var executedReport = {
435 isLoaded: false,
436 };
437 // Create request and result structures
438 var request = {
439 execution: { columns: columns },
440 };
441 // enrich configuration with supported properties such as
442 // where clause with query-like filters
443 ["where", "orderBy", "definitions"].forEach(function (property) {
444 if (executionConfiguration[property]) {
445 request.execution[property] = executionConfiguration[property];
446 }
447 });
448 // Execute request
449 return this.xhr
450 .post("/gdc/internal/projects/" + projectId + "/experimental/executions", __assign({}, settings, { body: JSON.stringify(request) }))
451 .then(function (r) { return r.getData(); })
452 .then(function (response) {
453 executedReport.headers = wrapMeasureIndexesFromMappings(get_1.default(executionConfiguration, "metricMappings"), get_1.default(response, ["executionResult", "headers"], []));
454 // Start polling on url returned in the executionResult for tabularData
455 return _this.loadExtendedDataResults(response.executionResult.extendedTabularDataResult, settings);
456 })
457 .then(function (r) {
458 var result = r.result, status = r.status;
459 return __assign({}, executedReport, { rawData: get_1.default(result, "extendedTabularDataResult.values", []), warnings: get_1.default(result, "extendedTabularDataResult.warnings", []), isLoaded: true, isEmpty: status === 204 });
460 });
461 };
462 ExperimentalExecutionsModule.prototype.mdToExecutionDefinitionsAndColumns = function (projectId, mdObj, options) {
463 if (options === void 0) { options = {}; }
464 var allDfUris = visualizationObjectHelper_1.getAttributesDisplayForms(mdObj);
465 var attributesMapPromise = this.getAttributesMap(options, allDfUris, projectId);
466 return attributesMapPromise.then(function (attributesMap) {
467 return getExecutionDefinitionsAndColumns(mdObj, options, attributesMap);
468 });
469 };
470 ExperimentalExecutionsModule.prototype.getAttributesMap = function (options, displayFormUris, projectId) {
471 var attributesMap = get_1.default(options, "attributesMap", {});
472 var missingUris = attributesMapLoader_1.getMissingUrisInAttributesMap(displayFormUris, attributesMap);
473 return this.loadAttributesMap(projectId, missingUris).then(function (result) {
474 return __assign({}, attributesMap, result);
475 });
476 };
477 ExperimentalExecutionsModule.prototype.loadExtendedDataResults = function (uri, settings, prevResult) {
478 var _this = this;
479 if (prevResult === void 0) { prevResult = emptyResult; }
480 return new Promise(function (resolve, reject) {
481 _this.xhr
482 .ajax(uri, settings)
483 .then(function (r) {
484 var response = r.response;
485 if (response.status === 204) {
486 return {
487 status: response.status,
488 result: "",
489 };
490 }
491 return {
492 status: response.status,
493 result: r.getData(),
494 };
495 })
496 .then(function (_a) {
497 var status = _a.status, result = _a.result;
498 var values = get_1.default(prevResult, "extendedTabularDataResult.values", []).concat(get_1.default(result, "extendedTabularDataResult.values", []));
499 var warnings = get_1.default(prevResult, "extendedTabularDataResult.warnings", []).concat(get_1.default(result, "extendedTabularDataResult.warnings", []));
500 var updatedResult = merge_1.default({}, prevResult, {
501 extendedTabularDataResult: {
502 values: values,
503 warnings: warnings,
504 },
505 });
506 var nextUri = get_1.default(result, "extendedTabularDataResult.paging.next");
507 if (nextUri) {
508 resolve(_this.loadExtendedDataResults(nextUri, settings, updatedResult));
509 }
510 else {
511 resolve({ status: status, result: updatedResult });
512 }
513 }, reject);
514 });
515 };
516 return ExperimentalExecutionsModule;
517}());
518exports.ExperimentalExecutionsModule = ExperimentalExecutionsModule;