helpers/barType.js

import constants, { COLORS } from "./constants";
import styles from "./styles";
import utils from "./utils";

/**
 * @module barType
 * @alias module:barType
 */

/**
 * @typedef d3
 */

/**
 * Returns the appropriate bar based on the bar style settings.
 * For Bar, we apply the settings below in the
 * `rect` element style attribute.
 *
 * @private
 * @param {object} style - data associated to the task
 * @param {object} dataTarget - input data object
 * @returns {string} A style constant
 */
const getBarStyle = (style = {}, dataTarget) => {
    const color = dataTarget.color || constants.DEFAULT_BAR_COLOR;
    let currentStyle = `fill: ${color}; stroke: ${color};`;

    // If style property is not provided then we use treat it as filled.
    if (utils.isEmpty(style)) {
        return currentStyle;
    }
    if (style.isDotted === true) {
        currentStyle = `${currentStyle}; stroke-width: 1; stroke-dasharray: 2, 2;`;
    }
    if (style.isHollow === true) {
        currentStyle = `${currentStyle} fill: ${COLORS.WHITE}; stroke-width: 1;`;
    }
    if (style.isHashed === true) {
        currentStyle = `${currentStyle} stroke-width: 1;`;
    }
    return currentStyle;
};

/**
 * Creates a SVG rect and appends to the d3 element provided
 *
 * @private
 * @param {Selection} path - d3 selection path for the SVG group element
 * @param {number} x - Scaled x co-ordinate
 * @param {number} y - Scaled y co-ordinate
 * @param {number} width - width in scaled pixels
 * @param {number} height - fixed pixel height as a number
 * @returns {Selection} d3 selection path after appending rect
 */
const getRect = (path, x, y, width, height) =>
    path
        .append("rect")
        .attr("x", x)
        .attr("y", y)
        .attr("width", width)
        .attr("height", height);
/**
 * Creates a rect and appends it to the d3 selection element provided in the argument
 *
 * @private
 * @param {Selection} path - d3 selection path for the SVG group element
 * @param {number} x - Scaled x co-ordinate
 * @param {number} y - Scaled y co-ordinate
 * @param {number} width - width in scaled pixels
 * @param {number} height - fixed pixel height as a number
 * @param {string} style - inline styling for the bar
 * @returns {Selection} d3 selection path
 */
const getBar = (path, x, y, width, height, style) => {
    getRect(path, x, y, width, height)
        .classed(styles.taskBar, true)
        .attr("style", style);
    return path;
};

/**
 * Creates a rect and appends it to the d3 selection element provided in the argument.
 * A chunk is a bar with fixed width. Uses: DEFAULT_GANTT_TASK_CHUNK_WIDTH
 *
 * @private
 * @param {Selection} path - d3 selection path for the SVG group element
 * @param {number} x - Scaled x co-ordinate
 * @param {number} y - Scaled y co-ordinate
 * @param {number} width - width in scaled pixels
 * @param {number} height - fixed pixel height as a number
 * @param {string} style - inline styling for the bar
 * @returns {Selection} d3 selection path
 */
const getChunk = (path, x, y, width, height, style) => {
    getBar(path, x, y, constants.DEFAULT_GANTT_TASK_CHUNK_WIDTH, height, style);
    return path;
};
/**
 * Creates 2 rect:
 * * Full width bar
 * * Completion bar with width as much as the percentage provided
 * We render the Completion bar on top of the Full width bar to give an illusion of
 * a percentage bar. If percentage is 100 then the Completion bar will overlap the Full width bar
 *
 * @private
 * @param {Selection} path - d3 selection path for the SVG group element
 * @param {number} x - Scaled x co-ordinate
 * @param {number} y - Scaled y co-ordinate
 * @param {number} width - width in scaled pixels
 * @param {number} height - fixed pixel height as a number
 * @param {number} percent - percent value for percentage completion
 * @param {string} color - hexa value denoting the color of the bar
 * @returns {Selection} d3 selection path
 */
const getPercentageBar = (path, x, y, width, height, percent, color) => {
    getRect(path, x, y, width, height)
        .classed(styles.taskBar, true)
        .attr(
            "style",
            `fill: ${COLORS.WHITE}; stroke: ${color}; stroke-width: 1;`
        );
    getRect(path, x, y, percent, height)
        .classed(styles.taskBarCompletion, true)
        .attr("style", `fill: ${color};`);
    return path;
};
/**
 * Creates a patterned bar with forward backslashes
 *
 * @private
 * @param {d3.selection} canvasSVG - d3 selection node of canvas svg
 * @param {Selection} defs - d3 selection path for defs element in the graph
 * @param {Selection} path - d3 selection path for the SVG group element
 * @param {number} x - Scaled x co-ordinate
 * @param {number} y - Scaled y co-ordinate
 * @param {number} width - width in scaled pixels
 * @param {number} height - fixed pixel height as a number
 * @param {string} style - style you want to apply for bar
 * @returns {Selection} d3 selection path
 */
const getHashedBar = (canvasSVG, defs, path, x, y, width, height, style) => {
    const patternId = "pattern-stripe";
    if (utils.isEmpty(defs) || defs.empty()) {
        canvasSVG.append("defs");
    }
    if (canvasSVG.select(`#${patternId}`).empty()) {
        defs.append("pattern")
            .attr("id", patternId)
            .attr("patternUnits", "userSpaceOnUse")
            .attr("patternTransform", "rotate(45)")
            .attr("width", constants.DEFAULT_GANTT_TASK_STRIPE_WIDTH)
            .attr("height", height)
            .attr("style", `fill: ${constants.DEFAULT_BAR_STRIPE_COLOR};`)
            .append("rect")
            .attr("width", constants.DEFAULT_GANTT_TASK_STRIPE_DISTANCE)
            .attr("height", height);
    }
    getRect(path, x, y, width, height)
        .classed(styles.taskBar, true)
        .attr(
            "style",
            style || `fill: ${constants.DEFAULT_TASK_BAR_HASH_COLOR};`
        );
    getRect(path, x, y, width, height)
        .classed(styles.taskBar, true)
        .attr("style", `fill: url(#${patternId});`);
    return path;
};

export {
    getRect,
    getBar,
    getChunk,
    getPercentageBar,
    getHashedBar,
    getBarStyle
};