UNPKG

@atomist/sdm-pack-aspect

Version:

an Atomist SDM Extension Pack for visualizing drift across an organization

185 lines 8.82 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const React = require("react"); const _ = require("lodash"); const api_1 = require("../lib/routes/api"); function displayCurrentIdeal(currentIdeal) { return React.createElement("h2", null, "Current ideal: ", currentIdeal.displayValue); } /* This element will contain the full data value for one level, about the item hovered over. */ function levelDataListItem(item) { return React.createElement("li", { key: "li-" + item.textAreaId }, React.createElement("label", { htmlFor: item.textAreaId }, item.labelText, ": "), React.createElement("div", { className: "unfrozenLevelData", id: item.textAreaId })); } function displayTagGroup(tagGroup) { return React.createElement("div", null, tagGroup.tagSelection.length > 0 && React.createElement("div", { className: "tagGroup" }, "clear:", React.createElement("form", { method: "GET", action: "/explore" }, React.createElement("input", { type: "hidden", name: "explore", value: "true" }), React.createElement("input", { className: "resetTagSelection", type: "submit", value: "CLEAR" }))), tagGroup.allTagNames().map(n => displayTagButtons(tagGroup, n))); } function displayTagButtons(tagGroup, tagName) { const percentageWithTag = tagGroup.getPercentageOfProjects(tagName); const percentageBar = React.createElement("div", { className: "percentageOfProjectWithoutTag" }, React.createElement("div", { className: "percentageOfProjectsWithTag", style: { width: percentageWithTag + "%" } }, percentageWithTag, "%"), 100 - percentageWithTag, "%"); const description = tagGroup.getDescription(tagName) + (tagGroup.isWarning(tagName) ? " - WARN" : "") + (tagGroup.isError(tagName) ? " - ERROR" : ""); return React.createElement("div", { className: "tagGroup " + (tagGroup.isWarning(tagName) ? "warnTagGroup " : "") + (tagGroup.isError(tagName) ? "errorTagGroup " : "") + (tagGroup.isRequired(tagName) ? "requiredTag " : "") + (tagGroup.isExcluded(tagName) ? "excludedTag" : "") }, percentageBar, React.createElement("img", { className: "taggydoober", src: "/taggydoober.png", title: description }), React.createElement("span", { className: "tagDescription", title: description }, tagName), React.createElement("form", { method: "GET", action: "/explore" }, React.createElement("input", { type: "hidden", name: "explore", value: "true" }), React.createElement("input", { type: "hidden", name: "tags", value: tagGroup.tagSelectionForRequire(tagName).join(",") }), React.createElement("input", { className: "requireButton", type: "submit", value: "Yes please", title: tagGroup.describeRequire(tagName) })), React.createElement("form", { method: "GET", action: "/explore" }, React.createElement("input", { type: "hidden", name: "explore", value: "true" }), React.createElement("input", { type: "hidden", name: "tags", value: tagGroup.tagSelectionForExclude(tagName).join(",") }), React.createElement("input", { className: "excludeButton", type: "submit", value: "Please no", alt: "alt text", title: tagGroup.describeExclude(tagName) }))); } /** * Class backing displayTagButtons */ class TagGroup { constructor(tagSelection, treeWithTags) { this.tagSelection = tagSelection; this.tagsInData = treeWithTags && treeWithTags.tags ? treeWithTags.tags : []; this.totalProjectsDisplayed = treeWithTags ? treeWithTags.matchingRepoCount : 0; } allTagNames() { const tagsFromData = this.tagsInData.map(t => t.name); const tagsFromSelection = this.tagSelection.map(this.dontFeelExcluded); return _.uniq([...tagsFromSelection, ...tagsFromData]); } isRequired(tagName) { return this.tagSelection.includes(tagName); } isExcluded(tagName) { return this.tagSelection.includes(this.pleaseExclude(tagName)); } isWarning(tagName) { const tagUsage = this.tagsInData.find(tu => tu.name === tagName); return tagUsage && tagUsage.severity === "warn"; } isError(tagName) { const tagUsage = this.tagsInData.find(tu => tu.name === tagName); return tagUsage && tagUsage.severity === "error"; } getDescription(tagName) { const tagUsage = this.tagsInData.find(tu => tu.name === tagName); return tagUsage ? tagUsage.description : ""; } getPercentageOfProjects(tagName) { if (this.isExcluded(tagName)) { return 0; } if (this.isRequired(tagName)) { return 100; } const data = this.tagsInData.find(t => t.name === tagName); if (!data) { return 0; // whatever } return Math.round(data.count * 100 / this.totalProjectsDisplayed); } describeExclude(tagName) { if (this.isRequired(tagName)) { return `Switch to excluding ${tagName} projects`; } if (this.isExcluded(tagName)) { return `Currently excluding ${tagName} projects`; } return `Exclude ${tagName} projects`; } describeRequire(tagName) { if (this.isRequired(tagName)) { return `Currently showing only ${tagName} projects`; } const dataTag = this.tagsInData.find(t => t.name === tagName); if (dataTag) { return `Show only ${tagName} projects (${dataTag.count})`; } return `Show only ${tagName} projects`; } tagSelectionForRequire(tagName) { if (this.isRequired(tagName)) { // toggle return this.tagSelection.filter(tn => tn !== tagName); } const existingTagsMinusAnyExclusionOfThisTag = this.tagSelection.filter(tn => tn !== this.pleaseExclude(tagName)); return [...existingTagsMinusAnyExclusionOfThisTag, tagName]; } tagSelectionForExclude(tagName) { if (this.isExcluded(tagName)) { // toggle return this.tagSelection.filter(tn => tn !== this.pleaseExclude(tagName)); } const existingTagsMinusAnyRequireOfThisTag = this.tagSelection.filter(tn => tn !== tagName); return [...existingTagsMinusAnyRequireOfThisTag, this.pleaseExclude(tagName)]; } pleaseExclude(tagName) { return "!" + tagName; } dontFeelExcluded(tagName) { return tagName.replace("!", ""); } } exports.TagGroup = TagGroup; function SunburstPage(props) { const perLevelDataItems = !props.tree || !props.tree.circles ? [] : props.tree.circles.map((c, i) => ({ textAreaId: "levelData-" + i, labelText: c.meaning })); const d3ScriptCall = `<script> const data = ${JSON.stringify(props.tree)}; SunburstYo.sunburst("${props.workspaceId}", data, window.innerWidth - 250, window.innerHeight - 100, { perLevelDataElementIds: [${perLevelDataItems.map(p => `"` + p.textAreaId + `"`).join(",")}], fieldsToDisplay: ${JSON.stringify(props.fieldsToDisplay)} }); </script>`; const thingies = !props.tree ? "Hover over a slice to see its details" : React.createElement("ul", null, perLevelDataItems.map(levelDataListItem)); const tagGroup = new TagGroup(props.selectedTags, props.tree); const tagButtons = displayTagGroup(tagGroup); const h2 = props.subheading ? React.createElement("h2", null, props.subheading) : React.createElement("h2", null, api_1.describeSelectedTagsToAnimals(props.selectedTags), " - ", props.tree.matchingRepoCount, " of ", props.tree.repoCount, " repositories"); const idealDisplay = props.currentIdeal ? displayCurrentIdeal(props.currentIdeal) : ""; return React.createElement("div", { className: "sunburst" }, React.createElement("h1", null, props.heading), h2, tagButtons, idealDisplay, React.createElement("div", { className: "wrapper" }, React.createElement("div", { id: "putSvgHere", className: "sunburstSvg" }), React.createElement("div", { id: "dataAboutWhatYouClicked", className: "sunburstData" }, thingies, React.createElement("div", { id: "additionalDataAboutWhatYouClicked" }))), React.createElement("div", { dangerouslySetInnerHTML: { __html: d3ScriptCall } }), React.createElement("a", { href: props.dataUrl, type: "application/json" }, "Raw data")); } exports.SunburstPage = SunburstPage; //# sourceMappingURL=sunburstPage.js.map