stackviz/app/js/services/dataset.js

267 lines
7.4 KiB
JavaScript

'use strict';
var servicesModule = require('./_index.js');
/**
* @ngInject
*/
function DatasetService($q, $http, $window) {
var service = {};
var config = null;
var datasets = null;
var artifacts = new Map();
var deployer = false;
/**
* Return a promise to fetch the dataset associated with the current URL path.
* This is only valid when in deployer mode.
* @return {Promise} an $http promise for the current deployer dataset
*/
var fetchDeployerDataset = function() {
// get uuid from first segment of url, but remove any defined config root
var path = $window.location.pathname;
if (config.root && path.startsWith(config.root)) {
path = path.replace(config.root, '');
}
// remove leading '/' (if any)
if (path.startsWith('/')) {
path = path.substr(1, path.length - 1);
}
// trim to first segment if necessary
if (path.includes('/')) {
path = path.substring(0, path.indexOf('/'));
}
return $http({
cache: true,
url: config.apiRoot + '/task',
method: 'POST',
data: { q: path }
});
};
/**
* Adds the given list of artifacts to the global artifact map, based on their
* `artifact_name` fields.
* @param {object[]} artifacts a list of artifacts
*/
var initArtifacts = function(list) {
list.forEach(function(artifact) {
if (artifacts.has(artifact.artifact_name)) {
artifacts.get(artifact.artifact_name).push(artifact);
} else {
artifacts.set(artifact.artifact_name, [artifact]);
}
});
};
service.config = function() {
return $q(function(resolve, reject) {
if (config) {
resolve({ config: config, datasets: datasets, artifacts: artifacts });
return;
}
$http({
cache: true,
url: 'data/config.json',
method: 'GET'
}).then(function(response) {
config = response.data;
if (config.deployer === true) {
deployer = true;
fetchDeployerDataset().then(function(apiResponse) {
datasets = [ apiResponse.data ];
initArtifacts(apiResponse.data.artifacts);
resolve({
config: config,
datasets: datasets,
artifacts: artifacts
});
}, function(reason) {
reject(reason);
});
} else {
datasets = config.datasets;
// merge all datasets into a 1-level grouping for now
config.datasets.forEach(function(dataset) {
initArtifacts(dataset.artifacts);
});
resolve({
config: config,
datasets: datasets,
artifacts: artifacts
});
}
}, function(reason) {
reject(reason);
});
});
};
/**
* Lists all datasets.
* @return {Promise} a Promise for the global list of datasets
*/
service.list = function() {
return $q(function(resolve, reject) {
/* eslint-disable angular/di */
service.config().then(function(config) {
resolve(config.datasets);
}, reject);
/* eslint-enable angular/di */
});
};
/**
* Lists all artifact groups that contain at least one artifact. If `primary`
* is true (default), only groups with at least one primary artifact are
* returned.
* @return {Promise} a Promise for the global list of datasets
*/
service.groups = function(primary) {
if (typeof primary === 'undefined') {
primary = true;
}
return $q(function(resolve, reject) {
/* eslint-disable angular/di */
service.config().then(function(config) {
var ret = [];
config.artifacts.forEach(function(entries, name) {
if (primary) {
entries = entries.filter(function(artifact) {
return artifact.primary;
});
}
if (entries.length > 0) {
ret.push(name);
}
});
resolve(ret);
}, reject);
/* eslint-enable angular/di */
});
};
/**
* Gets the dataset with the given ID. Note that for deployer instances, there
* will only ever be a single dataset (id #0). In most cases, dataset #0
* should be treated as the 'primary' dataset (and should almost always be the
* only one configured).
* @param {number} id the index of the dataset to get
* @return {Promise} a Promise to retreive the specified dataset
*/
service.get = function(id) {
return $q(function(resolve, reject) {
/* eslint-disable angular/di */
service.config().then(function(config) {
var dataset = config.datasets[id];
if (dataset) {
resolve(dataset);
} else {
reject("Dataset not found with ID: " + id);
}
}, function(reason) {
reject(reason);
});
/* eslint-enable angular/di */
});
};
/**
* Fetch all artifacts with the given `artifact_name` field. This should be
* the primary method for differentiating between artifacts. If no artifact
* name is given, this returns a flat list of all artifacts (via a Promise).
* @param {string} [name] an `artifact_name` field value
* @return {Promise} a promise for a list of matching artifacts
*/
service.artifacts = function(name) {
return $q(function(resolve, reject) {
/* eslint-disable angular/di */
service.config().then(function(config) {
if (typeof name === 'undefined') {
var ret = [];
config.datasets.forEach(function(dataset) {
ret.push.apply(ret, dataset.artifacts);
});
resolve(ret);
} else {
var group = config.artifacts.get(name);
if (group && group.length > 0) {
resolve(group);
} else {
reject('No artifacts found with name: ' + name);
}
}
}, reject);
/* eslint-enable angular/di */
});
};
var _loadArtifact = function(artifact, resolve, reject, message) {
if (artifact) {
var url = null;
if (deployer) {
url = config.apiRoot + '/blob/' + artifact.id;
} else {
url = 'data/' + artifact.path;
}
resolve($http({
cache: true,
url: url,
method: 'GET'
}));
} else {
reject('No artifact found matching ' + message);
}
};
/**
* Fetch the artifact with the given `artifact_name` and `artifact_type`
* fields. If only one parameter is provided, only `artifact_type` is
* considered.
* @param {string} [name] an `artifact_name` field value
* @param {string} type an `artifact_type` field value (e.g. 'subunit')
* @return {Promise} a Promise for the actual data associated with the
* artifact
*/
service.artifact = function(name, type) {
if (arguments.length === 1) {
type = arguments[0];
return $q(function(resolve, reject) {
service.artifacts().then(function(all) {
_loadArtifact(all.find(function(a) {
return a.artifact_type === type;
}), resolve, reject, 'type=' + type);
});
});
} else {
return $q(function(resolve, reject) {
service.artifacts(name).then(function(group) {
_loadArtifact(group.find(function(a) {
return a.artifact_type === type;
}), resolve, reject, 'name=' + name + ', type=' + type);
}, reject);
});
}
};
return service;
}
servicesModule.service('datasetService', DatasetService);