synapse-react-client
Version:
[](https://travis-ci.com/Sage-Bionetworks/Synapse-React-Client) [](https://badge.fury.io/js/synaps
229 lines • 13.5 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.NEXT_CLICK = exports.PREVIOUS_ITEM_CLICK = void 0;
var tslib_1 = require("tslib");
var fontawesome_svg_core_1 = require("@fortawesome/fontawesome-svg-core");
var free_solid_svg_icons_1 = require("@fortawesome/free-solid-svg-icons");
var react_fontawesome_1 = require("@fortawesome/react-fontawesome");
var React = (0, tslib_1.__importStar)(require("react"));
var react_measure_1 = (0, tslib_1.__importDefault)(require("react-measure"));
var react_tooltip_1 = (0, tslib_1.__importDefault)(require("react-tooltip"));
var ColorGradient_1 = require("./ColorGradient");
var facetUtils_1 = require("../utils/functions/facetUtils");
var unCamelCase_1 = require("../utils/functions/unCamelCase");
var LoadingScreen_1 = (0, tslib_1.__importDefault)(require("./LoadingScreen"));
var utils_1 = require("../utils");
fontawesome_svg_core_1.library.add(free_solid_svg_icons_1.faAngleLeft);
fontawesome_svg_core_1.library.add(free_solid_svg_icons_1.faAngleRight);
exports.PREVIOUS_ITEM_CLICK = 'left click';
exports.NEXT_CLICK = 'right click';
/**
* Make a simple stacked bar chart
*
* @class StackedBarChart
* @extends {React.Component}
*/
var StackedBarChart = /** @class */ (function (_super) {
(0, tslib_1.__extends)(StackedBarChart, _super);
function StackedBarChart(props) {
var _this = _super.call(this, props) || this;
/**
* Handle column click event
*/
_this.handleClick = function (dict) { return function (_event) {
// https://medium.freecodecamp.org/reactjs-pass-parameters-to-event-handlers-ca1f5c422b9
_this.props.updateParentState({ chartSelectionIndex: dict.index });
}; };
_this.handleArrowClick = function (direction) { return function (_event) {
var _a = _this.props.chartSelectionIndex, chartSelectionIndex = _a === void 0 ? 0 : _a;
var dict = _this.extractPropsData(_this.props.data);
var length = Object.keys(dict).length;
if (direction === exports.PREVIOUS_ITEM_CLICK) {
chartSelectionIndex -= 1;
// if its at zero then we want to wrap around to the end
chartSelectionIndex =
chartSelectionIndex < 0 ? length - 1 : chartSelectionIndex;
}
else {
chartSelectionIndex += 1;
}
chartSelectionIndex = chartSelectionIndex % length;
dict = dict[chartSelectionIndex];
_this.props.updateParentState({ chartSelectionIndex: chartSelectionIndex });
// return is only for testing purposes
return chartSelectionIndex;
}; };
_this.handleHover = _this.handleHover.bind(_this);
_this.handleExit = _this.handleExit.bind(_this);
_this.handleClick = _this.handleClick.bind(_this);
_this.handleArrowClick = _this.handleArrowClick.bind(_this);
_this.getTextForChartSelection = _this.getTextForChartSelection.bind(_this);
_this.onMeasureResize = _this.onMeasureResize.bind(_this);
// the text currently under the cursor
_this.state = {
// the dimensions of the bar chart itself
dimensions: {
bounds: { height: 1, width: 1, top: 0, left: 0, right: 0, bottom: 0 },
},
// the text of the current slice
// the count of this facet value occurence
selectedFacets: {},
};
_this.extractPropsData = _this.extractPropsData.bind(_this);
return _this;
}
/**
* Updates the hover text and update the view
*
* @memberof StackedBarChart
*/
StackedBarChart.prototype.handleHover = function (event) {
// add box shadow
event.currentTarget.style.boxShadow = '25px 20px';
};
/**
* Update the hover text and the view
*
* @param {*} event
* @memberof StackedBarChart
*/
StackedBarChart.prototype.handleExit = function (event) {
// remove box shadow
event.currentTarget.style.boxShadow = '';
};
StackedBarChart.prototype.getTextForChartSelection = function (xData) {
var _a = this.props.chartSelectionIndex, chartSelectionIndex = _a === void 0 ? 0 : _a;
var _b = this.props, _c = _b.facetAliases, facetAliases = _c === void 0 ? {} : _c, facet = _b.facet;
var facetValueDisplay = xData[chartSelectionIndex] && xData[chartSelectionIndex].value;
var filterDisplay = facetAliases[facet] || (0, unCamelCase_1.unCamelCase)(facet);
return (React.createElement("span", null,
React.createElement("span", { className: "SRC-text-title SRC-filter-display" }, filterDisplay),
":",
React.createElement("span", { className: "SRC-facet-view SRC-text-title" }, facetValueDisplay === utils_1.SynapseConstants.VALUE_NOT_SET
? utils_1.SynapseConstants.FRIENDLY_VALUE_NOT_SET
: facetValueDisplay)));
};
StackedBarChart.prototype.getFileCount = function (xData) {
var _a = this.props.chartSelectionIndex, chartSelectionIndex = _a === void 0 ? 1 : _a;
return xData[chartSelectionIndex] && xData[chartSelectionIndex].count;
};
StackedBarChart.prototype.render = function () {
var _this = this;
var _a = this.props, data = _a.data, isLoadingNewData = _a.isLoadingNewData, rgbIndex = _a.rgbIndex, _b = _a.facet, facet = _b === void 0 ? '' : _b, unitDescription = _a.unitDescription, isLoading = _a.isLoading, lastFacetSelection = _a.lastFacetSelection, isAllFilterSelectedForFacet = _a.isAllFilterSelectedForFacet, chartSelectionIndex = _a.chartSelectionIndex, asyncJobStatus = _a.asyncJobStatus;
// while loading
if (isLoadingNewData) {
return (React.createElement("div", { className: "SRC-loadingContainer SRC-centerContentColumn" },
LoadingScreen_1.default,
React.createElement("div", null, asyncJobStatus && asyncJobStatus.progressMessage)));
}
var xData = this.extractPropsData(data);
var total = 0;
var width = this.state.dimensions.bounds.width;
// sum up the counts of data
for (var key in xData) {
if (xData.hasOwnProperty(key)) {
total += xData[key].count;
}
}
var _c = (0, ColorGradient_1.getColorPalette)(rgbIndex, xData.length), colorPalette = _c.colorPalette, textColors = _c.textColors;
var originalColor = colorPalette[0];
return (React.createElement(React.Fragment, null,
React.createElement("div", { className: "SRC-bar-border SRC-bar-marginTop SRC-bar-border-top", "data-testid": 'StackedBarChart' },
React.createElement(react_measure_1.default, { bounds: true, onResize: function (contentRect) {
_this.setState({ dimensions: contentRect });
} }, function (_a) {
var measureRef = _a.measureRef;
return (React.createElement("div", { className: "SRC-flex", ref: measureRef }, xData.map(function (obj, index) {
var textColor = textColors[index];
var rgbColor = colorPalette[index];
var rectStyle;
var isValueSelected = isAllFilterSelectedForFacet[facet]
? true
: (0, facetUtils_1.getIsValueSelected)({
isLoading: isLoading,
lastFacetSelection: lastFacetSelection,
columnName: facet,
curFacetSelection: obj,
});
if (isValueSelected) {
rectStyle = {
fill: rgbColor,
};
}
else {
rectStyle = {
fill: '#C4C4C4',
};
}
var svgHeight = 80;
var svgWidth = (obj.count / total) * width;
var style = {};
if (chartSelectionIndex === index) {
style.filter = 'drop-shadow(5px 5px 5px rgba(0,0,0,0.5))';
}
var label = facet + ": " + obj.value + " - " + obj.count + " " + unitDescription;
// there was one bug where a new line character was in the obj.value, making data-for
// break because its a special character, below we remove that
var tooltipId = obj.value.replace(/(\r\n|\n|\r)/gm, '');
// basic heuristic to calculate the number of pixels needed to show the value on the bar chart
var value = obj.count;
var numCharsInValue = value.toString().length * 4.5; // represents width of a character
return (
// each svg represents one of the bars
// will need to change this to be responsive
React.createElement(React.Fragment, { key: label },
React.createElement("span", { "data-for": tooltipId, "data-tip": label },
React.createElement("svg", { className: "SRC-hoverBox", height: svgHeight + 15, width: svgWidth, style: style, onClick: _this.handleClick((0, tslib_1.__assign)((0, tslib_1.__assign)({}, obj), { index: index })) },
React.createElement("rect", { onMouseEnter: _this.handleHover, onMouseLeave: _this.handleExit, height: svgHeight, width: svgWidth, className: "SRC-chart-rect-style",
// can't remove inline style due to dynamic fill
style: rectStyle }),
index < 3 && svgWidth > numCharsInValue && (React.createElement("text", { textAnchor: "middle", className: "SRC-text-title", fontFamily: 'bold sans-serif', fill: textColor, x: '50%', y: '50%' }, obj.count)),
chartSelectionIndex === index && (React.createElement("text", { fill: originalColor, x: 0, y: svgHeight + 15, className: "SRC-text-shadow SRC-text-large" }, '\u25CF')))),
React.createElement(react_tooltip_1.default, { delayShow: 1000, id: tooltipId })));
})));
})),
React.createElement("div", { className: "SRC-bar-border SRC-bar-border-bottom" },
React.createElement("p", { className: "SRC-noMargin SRC-padding-chart SRC-text-title" },
React.createElement("strong", null, this.getTextForChartSelection(xData))),
React.createElement("p", { id: "fileCount", className: "SRC-noMargin SRC-padding-chart SRC-text-chart" },
this.getFileCount(xData),
" ",
unitDescription),
this.props.link && (React.createElement("div", { className: "SRC-chart-link" },
React.createElement("a", { href: "/" + this.props.link },
" ",
this.props.linkText,
" ")))),
React.createElement("div", { className: "SRC-chart-nav SRC-center-text" },
React.createElement("button", { className: "SRC-chart-btn SRC-floatRight", type: "button", onClick: this.handleArrowClick(exports.NEXT_CLICK) },
React.createElement(react_fontawesome_1.FontAwesomeIcon, { style: { fontSize: '11px' }, className: "SRC-primary-text-color", icon: "angle-right" })),
React.createElement("button", { className: "SRC-chart-btn SRC-floatRight", type: "button", onClick: this.handleArrowClick(exports.PREVIOUS_ITEM_CLICK) },
React.createElement(react_fontawesome_1.FontAwesomeIcon, { style: { fontSize: '11px' }, className: "SRC-primary-text-color", icon: "angle-left" })))));
};
StackedBarChart.prototype.extractPropsData = function (data) {
var _a;
var xData = [];
var facet = this.props.facet;
// pull out the data corresponding to the filter in question
(_a = data === null || data === void 0 ? void 0 : data.facets) === null || _a === void 0 ? void 0 : _a.forEach(function (item) {
if (item.facetType === 'enumeration' && item.columnName === facet) {
item.facetValues.forEach(function (facetValue) {
if (item.columnName) {
xData.push((0, tslib_1.__assign)({ columnName: item.columnName }, facetValue));
}
});
}
});
// sort the data so that the largest bars are at the front
xData.sort(function (a, b) {
return b.count - a.count;
});
return xData;
};
StackedBarChart.prototype.onMeasureResize = function (contentRect) {
this.setState({ dimensions: contentRect });
};
return StackedBarChart;
}(React.Component));
exports.default = StackedBarChart;
//# sourceMappingURL=StackedBarChart.js.map