Skip to content

Commit

Permalink
Added an ability to use hours, minutes and seconds (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
savvinsergey authored and ignatvilesov committed Jul 28, 2017
1 parent a78e87a commit 683ff83
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 13 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
## 1.1.0
* Added ability to use hours, minutes and seconds in a 'duration'
## 1.0.2
* Fixed tooltip date format not respected
## 1.0.1
* Fixed start date calculation
* Fixed start date calculation
28 changes: 28 additions & 0 deletions capabilities.json
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,34 @@
"type": {
"bool": true
}
},
"durationUnit": {
"displayName": "Duration unit",
"displayNameKey": "Visual_DurationUnit",
"type": {
"enumeration": [
{
"value": "day",
"displayName": "Days",
"displayNameKey": "Visual_DurationUnit_Days"
},
{
"value": "hour",
"displayName": "Hours",
"displayNameKey": "Visual_DurationUnit_Hours"
},
{
"value": "minute",
"displayName": "Minutes",
"displayNameKey": "Visual_DurationUnit_Minutes"
},
{
"value": "second",
"displayName": "Seconds",
"displayNameKey": "Visual_DurationUnit_Seconds"
}
]
}
}
}
},
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "powerbi-visuals-gantt",
"version": "1.0.2",
"version": "1.1.0",
"description": "A Gantt chart is a type of bar chart which illustrates a project timeline or schedule. The Gantt Chart visual shows the Tasks, Start Dates, Durations, % Complete, and Resources for a project. The Gantt Chart visual can be used to show current schedule status using percent-complete shadings and a vertical \"TODAY\" line. The Legend may be used to group or filter tasks based upon data values.",
"repository": {
"type": "git",
Expand Down
2 changes: 1 addition & 1 deletion pbiviz.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"displayName": "Gantt",
"guid": "Gantt1448688115699",
"visualClassName": "Gantt",
"version": "1.0.2",
"version": "1.1.0",
"description": "A Gantt chart is a type of bar chart which illustrates a project timeline or schedule. The Gantt Chart visual shows the Tasks, Start Dates, Durations, % Complete, and Resources for a project. The Gantt Chart visual can be used to show current schedule status using percent-complete shadings and a vertical \"TODAY\" line. The Legend may be used to group or filter tasks based upon data values.",
"supportUrl": "http://community.powerbi.com",
"gitHubUrl": "https://github.com/Microsoft/powerbi-visuals-gantt"
Expand Down
67 changes: 58 additions & 9 deletions src/gantt.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,13 @@ module powerbi.extensibility.visual {
const MillisecondsInAYear: number = 365 * MillisecondsInADay;
const ChartLineHeight: number = 40;
const PaddingTasks: number = 5;
const numberFormat = "#";

const GanttDurationUnitType = [
"day",
"hour",
"minute",
"second"
];

export interface Task extends SelectableDataPoint {
id: number;
Expand All @@ -131,7 +137,6 @@ module powerbi.extensibility.visual {
export interface GanttChartFormatters {
startDateFormatter: IValueFormatter;
completionFormatter: IValueFormatter;
durationFormatter: IValueFormatter;
}

export interface GanttViewModel {
Expand Down Expand Up @@ -428,7 +433,7 @@ module powerbi.extensibility.visual {
* @param task All task attributes.
* @param formatters Formatting options for gantt attributes.
*/
private static getTooltipInfo(task: Task, locale: string, formatters: GanttChartFormatters, timeInterval: string = "Days"): VisualTooltipDataItem[] {
private static getTooltipInfo(task: Task, locale: string, formatters: GanttChartFormatters, durationUnit: string): VisualTooltipDataItem[] {
let tooltipDataArray: VisualTooltipDataItem[] = [];

if (task.taskType) {
Expand All @@ -440,7 +445,9 @@ module powerbi.extensibility.visual {
tooltipDataArray.push({ displayName: "Start Date", value: formatters.startDateFormatter.format(task.start) });
}

tooltipDataArray.push({ displayName: "Duration", value: `${formatters.durationFormatter.format(task.duration)} ${timeInterval}` });
const durationLabel: string = this.generateLabelForDuration(task.duration, durationUnit);

tooltipDataArray.push({ displayName: "Duration", value: durationLabel });
tooltipDataArray.push({ displayName: "Completion", value: formatters.completionFormatter.format(task.completion) });

if (task.resource) {
Expand Down Expand Up @@ -491,7 +498,6 @@ module powerbi.extensibility.visual {

return <GanttChartFormatters>{
startDateFormatter: ValueFormatter.create({ format: dateFormat, cultureSelector }),
durationFormatter: ValueFormatter.create({ format: numberFormat }),
completionFormatter: ValueFormatter.create({ format: PercentFormat, value: 1, allowFormatBeautification: true })
};
}
Expand Down Expand Up @@ -530,7 +536,8 @@ module powerbi.extensibility.visual {
taskTypes: TaskTypes,
host: IVisualHost,
formatters: GanttChartFormatters,
colors: IColorPalette
colors: IColorPalette,
settings: GanttSettings
): Task[] {
const tasks: Task[] = [];
const colorHelper: ColorHelper = new ColorHelper(
Expand Down Expand Up @@ -589,8 +596,11 @@ module powerbi.extensibility.visual {
identity: selectionId
};

task.end = d3.time.day.offset(task.start, task.duration);
task.tooltipInfo = Gantt.getTooltipInfo(task, host.locale, formatters);
let durationUnit = settings.general.durationUnit;
durationUnit = (GanttDurationUnitType.indexOf(durationUnit) !== -1 && durationUnit) || "day";

task.end = d3.time[durationUnit].offset(task.start, task.duration);
task.tooltipInfo = Gantt.getTooltipInfo(task, host.locale, formatters, settings.general.durationUnit);

tasks.push(task);
}
Expand All @@ -601,6 +611,45 @@ module powerbi.extensibility.visual {
return tasks;
}

/**
* Generate 'Duration' label for tooltip
* @param duration The duration of task
* @param durationUnit The duration unit for chart
*/
private static generateLabelForDuration(duration: number, durationUnit: string): string {
let label: string = "";

const days: number = Math.floor(duration / 24);
label += days ? `${days} Days ` : ``;
if (durationUnit === "day") {
return `${duration} Days `;
}

const hours: number = duration - (days * 24);
label += hours ? `${hours} Hours ` : ``;
if (durationUnit === "hour") {
return duration >= 24
? label
: `${duration} Hours`;
}

const minutes: number = duration - ((days * 24) + (hours * 60));
label += minutes ? `${minutes} Minutes ` : ``;
if (durationUnit === "minute") {
return duration >= 60
? label
: `${duration} Minutes `;
}

const seconds: number = duration - (days * 24 + hours * 60 + minutes * 60);
label += seconds ? `${seconds} Seconds ` : ``;
if (durationUnit === "second") {
return duration >= 60
? label
: `${duration} Seconds `;
}
}

/**
* Convert the dataView to view model
* @param dataView The data Model
Expand All @@ -617,7 +666,7 @@ module powerbi.extensibility.visual {

const taskTypes: TaskTypes = Gantt.getAllTasksTypes(dataView)
, formatters: GanttChartFormatters = this.getFormatters(dataView, host.locale || null)
, tasks: Task[] = Gantt.createTasks(dataView, taskTypes, host, formatters, colors);
, tasks: Task[] = Gantt.createTasks(dataView, taskTypes, host, formatters, colors, settings);

return {
dataView,
Expand Down
1 change: 1 addition & 0 deletions src/settings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ module powerbi.extensibility.visual {

export class GeneralSettings {
groupTasks: boolean = false;
durationUnit: string = "day";
}

export class LegendSettings {
Expand Down
2 changes: 1 addition & 1 deletion test/visualData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ module powerbi.extensibility.visual.test {
public static getRandomUniqueNumbers(count: number, min: number = 0, max: number = 1): number[] {
let result: number[] = [];
for (let i: number = 0; i < count; i++) {
result.push(getRandomNumber(min, max, result));
result.push(Math.floor(getRandomNumber(min, max, result)));
}

return result;
Expand Down
68 changes: 68 additions & 0 deletions test/visualTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,74 @@ module powerbi.extensibility.visual.test {
});

describe("Format settings test", () => {
describe("General", () => {
describe("Duration units", () => {

function checkDurationUnit(durationUnit: string) {
const tasks: Task[] = d3
.select(visualBuilder.element.get(0))
.selectAll(".task")
.data();

tasks.forEach(task => {
const dates: Date[] = d3
.time[durationUnit]
.range(task.start, task.end);
expect(dates.length).toEqual(task.duration);
});
}

function setDurationUnit(durationUnit) {
dataView.metadata.objects = {
general: {
durationUnit: durationUnit
}
};
}

it("days", (done) => {
let durationUnit: string = "day";
setDurationUnit(durationUnit);

visualBuilder.updateRenderTimeout(dataView, () => {
checkDurationUnit(durationUnit);
done();
});
});

it("hours", (done) => {
let durationUnit: string = "hour";
setDurationUnit(durationUnit);

visualBuilder.updateRenderTimeout(dataView, () => {
checkDurationUnit(durationUnit);
done();
});
});

it("minutes", (done) => {
let durationUnit: string = "minute";
setDurationUnit(durationUnit);

visualBuilder.updateRenderTimeout(dataView, () => {
checkDurationUnit(durationUnit);
done();
});
});

it("seconds", (done) => {
let durationUnit: string = "second";
setDurationUnit(durationUnit);

visualBuilder.updateRenderTimeout(dataView, () => {
checkDurationUnit(durationUnit);
done();
});
});

});
});

describe("Data labels", () => {
beforeEach(() => {
dataView.metadata.objects = {
Expand Down

0 comments on commit 683ff83

Please sign in to comment.