@atomist/sdm-pack-aspect
Version:
an Atomist SDM Extension Pack for visualizing drift across an organization
205 lines • 8.66 kB
JavaScript
;
/*
* Copyright © 2019 Atomist, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const Ideal_1 = require("@atomist/sdm-pack-fingerprint/lib/machine/Ideal");
const sunburst_1 = require("../tree/sunburst");
const treeUtils_1 = require("../tree/treeUtils");
const _ = require("lodash");
const treeMunging_1 = require("./support/treeMunging");
/**
* Return a tree from fingerprint name -> instances -> repos
* @return {Promise<PlantedTree>}
*/
function buildFingerprintTree(world, params) {
return __awaiter(this, void 0, void 0, function* () {
const { workspaceId, byName, fingerprintName, fingerprintType, otherLabel, byOrg, trim, showProgress } = params;
const showPresence = !!otherLabel;
const { store, aspectRegistry } = world;
// Get the tree and then perform post processing on it
let pt = yield store.fingerprintsToReposTree({
workspaceId,
byName,
otherLabel,
rootName: fingerprintName,
aspectName: fingerprintType,
});
// logger.debug("Returning fingerprint tree '%s': %j", fingerprintName, pt);
yield decorateProblemFingerprints(aspectRegistry, pt);
const aspect = aspectRegistry.aspectOf(fingerprintType);
if (!byName) {
// Show all fingerprints in one aspect, splitting by fingerprint name
pt = treeUtils_1.introduceClassificationLayer(pt, {
descendantClassifier: l => {
if (!l.sha) {
return undefined;
}
const aspect2 = aspectRegistry.aspectOf(l.type);
return !aspect2 || !aspect2.toDisplayableFingerprintName ?
l.name :
aspect2.toDisplayableFingerprintName(l.name);
},
newLayerDepth: 1,
newLayerMeaning: "fingerprint name",
});
if (!!aspect) {
pt.tree.name = aspect.displayName;
}
}
else {
// We are showing a particular fingerprint
if (!!aspect) {
pt.tree.name = aspect.toDisplayableFingerprintName ?
aspect.toDisplayableFingerprintName(fingerprintName) :
fingerprintName;
}
}
resolveAspectNames(aspectRegistry, pt.tree);
// if (!showPresence) {
// // Suppress branches from aspects that use name "None" for not found
// pt.tree = killChildren(pt.tree, c => c.name === "None");
// }
if (byOrg) {
pt = treeMunging_1.splitByOrg(pt);
}
if (showPresence) {
pt.tree = treeUtils_1.groupSiblings(pt.tree, {
parentSelector: parent => parent.children.some(c => c.sha),
childClassifier: kid => kid.sha && kid.name !== "None" ? "Present" : "Absent",
collapseUnderName: name => name === "Absent",
});
}
else if (showProgress) {
const ideal = yield aspectRegistry.idealStore.loadIdeal(workspaceId, fingerprintType, fingerprintName);
if (!ideal || !Ideal_1.isConcreteIdeal(ideal)) {
throw new Error(`No ideal to aspire to for ${fingerprintType}/${fingerprintName} in workspace '${workspaceId}'`);
}
decorateToShowProgressToIdeal(aspectRegistry, pt, ideal);
}
if (!showPresence) {
// Don't do this if we are looking at presence, as sized nodes will swamp absent nodes with default 1
applyTerminalSizing(aspect, pt.tree);
}
pt.tree = treeMunging_1.addRepositoryViewUrl(pt.tree);
// Group all fingerprint nodes by their name at the first level
pt.tree = treeUtils_1.groupSiblings(pt.tree, {
parentSelector: parent => parent.children.some(c => c.sha),
childClassifier: l => l.name,
collapseUnderName: () => true,
});
if (trim) {
pt.tree = treeUtils_1.trimOuterRim(pt.tree);
}
else {
putRepoPathInNameOfRepoLeaves(pt);
}
return pt;
});
}
exports.buildFingerprintTree = buildFingerprintTree;
function resolveAspectNames(aspectRegistry, t) {
treeUtils_1.visit(t, l => {
if (l.sha) {
const fp = l;
// It's a fingerprint name
const aspect = aspectRegistry.aspectOf(fp.type);
if (aspect) {
fp.name = aspect.toDisplayableFingerprint ? aspect.toDisplayableFingerprint(fp) : fp.data;
}
else if (!!fp.data && !!fp.data.displayValue) {
fp.name = fp.data.displayValue;
}
else if (!!fp.displayValue) {
fp.name = fp.displayValue;
}
}
return true;
});
}
/**
* Size terminal nodes by aspect stat if available
*/
function applyTerminalSizing(aspect, t) {
if (aspect && aspect.stats && aspect.stats.basicStatsPath) {
treeUtils_1.visit(t, l => {
if (sunburst_1.isSunburstTree(l) && l.children.every(c => !sunburst_1.isSunburstTree(c) && c.owner)) {
l.children.forEach(c => c.size = _.get(l, "data." + aspect.stats.basicStatsPath, 1));
}
return true;
});
}
}
function decorateProblemFingerprints(aspectRegistry, pt) {
return __awaiter(this, void 0, void 0, function* () {
const usageChecker = yield aspectRegistry.undesirableUsageCheckerFor("local");
// Flag bad fingerprints with a special color
yield treeUtils_1.visitAsync(pt.tree, (l) => __awaiter(this, void 0, void 0, function* () {
if (l.sha) {
const problems = usageChecker ? usageChecker.check(l, "local") : undefined;
if (problems && problems.length > 0) {
l.color = "#810325";
l.problems = problems.map(problem => ({
// Need to dispense with the fingerprint, which would make this circular
description: problem.description,
severity: problem.severity,
authority: problem.authority,
url: problem.url,
}));
}
}
return true;
}));
});
}
function decorateToShowProgressToIdeal(aspectRegistry, pt, ideal) {
pt.tree = treeUtils_1.groupSiblings(pt.tree, {
parentSelector: parent => parent.children.some(c => c.sha),
childClassifier: kid => kid.sha === ideal.ideal.sha ? "Ideal" : "No",
groupLayerDecorator: l => {
if (l.name === "Ideal") {
l.color = "#168115";
}
else {
l.color = "#811824";
}
},
});
}
/**
* Show virtual repos
* @param {PlantedTree} pt
*/
function putRepoPathInNameOfRepoLeaves(pt) {
treeUtils_1.visit(pt.tree, l => {
const en = l;
if (!sunburst_1.isSunburstTree(en) && en.name && en.url && en.path) {
// It's an eligible end node
en.name = en.name + "/" + en.path;
}
return true;
});
}
exports.putRepoPathInNameOfRepoLeaves = putRepoPathInNameOfRepoLeaves;
//# sourceMappingURL=buildFingerprintTree.js.map