Skip to content

Commit

Permalink
Add toggle 'Treat as end of fiscal year'
Browse files Browse the repository at this point in the history
  • Loading branch information
adiletelf committed May 22, 2024
1 parent 7ffc991 commit 0c671db
Show file tree
Hide file tree
Showing 12 changed files with 81 additions and 35 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
## 2.5.5
* Add toggle 'Treat as end of fiscal year'

## 2.5.4
* Disable "Calendar" and "First day of week" settings when WeekStandard is set to IS0 860
* Fix uninitialized start date when date from filters is less than date from DataView
Expand Down
5 changes: 5 additions & 0 deletions capabilities.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@
},
"calendar": {
"properties": {
"treatAsEndOfFiscalYear": {
"type": {
"bool": true
}
},
"month": {
"type": {
"enumeration": [
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

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-timeline",
"version": "2.5.4.0",
"version": "2.5.5.0",
"description": "Timeline slicer is a graphical date range selector used as a filtering component in the report canvas",
"repository": {
"type": "git",
Expand Down
4 changes: 2 additions & 2 deletions pbiviz.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"visual": {
"name": "Timeline",
"displayName": "Timeline 2.5.4.0",
"displayName": "Timeline 2.5.5.0",
"guid": "Timeline1447991079100",
"visualClassName": "Timeline",
"version": "2.5.4.0",
"version": "2.5.5.0",
"description": "Timeline slicer is a graphical date range selector used as a filtering component in the report canvas",
"supportUrl": "https://community.powerbi.com",
"gitHubUrl": "https://github.com/Microsoft/powerbi-visuals-timeline"
Expand Down
36 changes: 30 additions & 6 deletions src/calendars/calendar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,13 @@ export interface WeekdayFormat {
day: number;
}

export interface CalendarFormattingSettings {
treatAsEndOfFiscalYear: boolean;
}

export class Calendar {
private static QuarterFirstMonths: number[] = [0, 3, 6, 9];
private settings: CalendarFormattingSettings;

protected firstDayOfWeek: number;
protected firstMonthOfYear: number;
Expand All @@ -60,7 +65,8 @@ export class Calendar {
protected EmptyYearOffset: number = 0;
protected YearOffset: number = 1;

constructor(calendarFormat: CalendarFormat, weekDaySettings: WeekdayFormat) {
constructor(calendarFormat: CalendarFormat, weekDaySettings: WeekdayFormat, settings: CalendarFormattingSettings) {
this.settings = settings;
this.isDaySelection = weekDaySettings.daySelection;
this.firstDayOfWeek = weekDaySettings.day;
this.firstMonthOfYear = calendarFormat.month;
Expand All @@ -78,7 +84,11 @@ export class Calendar {
const firstMonthOfYear = this.getFirstMonthOfYear();
const firstDayOfYear = this.getFirstDayOfYear();

return ((firstMonthOfYear === 0 && firstDayOfYear === 1) ? 0 : 1);
if (firstMonthOfYear === 0 && firstDayOfYear === 1) {
return 0;
}

return this.settings.treatAsEndOfFiscalYear ? 1 : -1;
}

public determineYear(date: Date): number {
Expand All @@ -91,17 +101,31 @@ export class Calendar {
firstDayOfYear,
);

return date.getFullYear() + this.getFiscalYearAdjustment() - ((firstDate <= date)
? this.EmptyYearOffset
: this.YearOffset);
let adjustment: number = this.getFiscalYearAdjustment();

if (adjustment === 0) {
return date.getFullYear();
}
else if (this.settings.treatAsEndOfFiscalYear) {
adjustment -= ((firstDate <= date) ? this.EmptyYearOffset : this.YearOffset);
} else {
adjustment += ((firstDate > date) ? this.EmptyYearOffset : this.YearOffset);
}

return date.getFullYear() + adjustment;
}

public determineWeek(date: Date): number[] {
// For fiscal calendar case that started not from the 1st January a year may be greater on 1.
// It's Ok until this year is used to calculate date of first week.
// So, here is some adjustment was applied.
const year: number = this.determineYear(date);
const fiscalYearAdjustment = this.getFiscalYearAdjustment();
let fiscalYearAdjustment = this.getFiscalYearAdjustment();

// fiscal year starts with W1 (week 1), meaning previous week should be W52-53
if (fiscalYearAdjustment === -1) {
fiscalYearAdjustment = 0;
}

const dateOfFirstWeek: Date = this.getDateOfFirstWeek(year - fiscalYearAdjustment);
const dateOfFirstFullWeek: Date = this.getDateOfFirstFullWeek(year - fiscalYearAdjustment);
Expand Down
9 changes: 5 additions & 4 deletions src/calendars/calendarFactory.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
import {Calendar, CalendarFormat, WeekdayFormat} from "./calendar";
import {Calendar, CalendarFormat, CalendarFormattingSettings, WeekdayFormat} from "./calendar";
import { WeekStandard } from "./weekStandard";
import { CalendarISO8061 } from "./calendarISO8061";

export class CalendarFactory {
public create(
weekStandard: WeekStandard,
calendarSettings: CalendarFormat,
weekDaySettings: WeekdayFormat) : Calendar {
weekDaySettings: WeekdayFormat,
settings: CalendarFormattingSettings) : Calendar {

let calendar: Calendar;

switch (weekStandard) {
case WeekStandard.ISO8061:
calendar = new CalendarISO8061();
calendar = new CalendarISO8061(settings);
break;
default:
calendar = new Calendar(calendarSettings, weekDaySettings)
calendar = new Calendar(calendarSettings, weekDaySettings, settings)
}

return calendar;
Expand Down
6 changes: 3 additions & 3 deletions src/calendars/calendarISO8061.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import {Calendar, CalendarFormat, WeekdayFormat} from "./calendar";
import {Calendar, CalendarFormat, CalendarFormattingSettings, WeekdayFormat} from "./calendar";
import { WeekStandard } from "./weekStandard";
import { Utils } from "../utils";
import {CalendarSettingsCard} from "../timeLineSettingsModel";

export class CalendarISO8061 extends Calendar {

constructor() {
constructor(settings: CalendarFormattingSettings) {
const isoCalendarSettings: CalendarFormat = {
month: CalendarSettingsCard.DefaultMonth,
day: CalendarSettingsCard.DefaultDay,
Expand All @@ -16,7 +16,7 @@ export class CalendarISO8061 extends Calendar {
day: 1,
};

super(isoCalendarSettings, isoWeekDaySettings);
super(isoCalendarSettings, isoWeekDaySettings, settings);

//this.firstDayOfYear = calendarFormat.day;
}
Expand Down
9 changes: 6 additions & 3 deletions src/timeLine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ import {ITimelineDatePeriod, ITimelineDatePeriodBase,} from "./datePeriod/datePe

import {DatePeriodBase} from "./datePeriod/datePeriodBase";

import {Calendar, CalendarFormat, WeekdayFormat} from "./calendars/calendar";
import {Calendar, CalendarFormat, CalendarFormattingSettings, WeekdayFormat} from "./calendars/calendar";
import {Utils} from "./utils";
import {WeekStandard} from "./calendars/weekStandard";
import {CalendarFactory} from "./calendars/calendarFactory";
Expand Down Expand Up @@ -150,7 +150,9 @@ export class Timeline implements powerbiVisualsApi.extensibility.visual.IVisual
}

if (!initialized || isCalendarChanged) {
calendar = new CalendarFactory().create(weekStandard, calendarFormat, weekDayFormat);
const calendarFormattingSettings: CalendarFormattingSettings = { treatAsEndOfFiscalYear: this.visualSettings.calendar.treatAsEndOfFiscalYear.value };

calendar = new CalendarFactory().create(weekStandard, calendarFormat, weekDayFormat, calendarFormattingSettings);
const granularity: GranularityType = this.visualSettings.granularity.granularity.value
? <GranularityType>this.visualSettings.granularity.granularity.value.value
: GranularityType.month;
Expand Down Expand Up @@ -1234,7 +1236,8 @@ export class Timeline implements powerbiVisualsApi.extensibility.visual.IVisual
) {
const { weekStandard, calendarFormat, weekDayFormat } = Timeline.computeCalendarFormat(timelineSettings);

const calendar: Calendar = this.calendarFactory.create(weekStandard, calendarFormat, weekDayFormat);
const calendarFormattingSettings: CalendarFormattingSettings = { treatAsEndOfFiscalYear: timelineSettings.calendar.treatAsEndOfFiscalYear.value };
const calendar: Calendar = this.calendarFactory.create(weekStandard, calendarFormat, weekDayFormat, calendarFormattingSettings);

timelineGranularityData.createGranularities(calendar, locale, localizationManager);
timelineGranularityData.createLabels();
Expand Down
9 changes: 8 additions & 1 deletion src/timeLineSettingsModel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,13 @@ export class CalendarSettingsCard extends Card {
public static readonly DefaultMonth: number = 0;
public static readonly DefaultDay: number = 1;

treatAsEndOfFiscalYear = new formattingSettings.ToggleSwitch({
name: "treatAsEndOfFiscalYear",
displayName: "Treat as end of fiscal year",
displayNameKey: "Visual_TreatAsEndOfFiscalYear",
value: true,
});

month = new formattingSettings.ItemDropdown({
name: "month",
displayName: "Month",
Expand All @@ -141,7 +148,7 @@ export class CalendarSettingsCard extends Card {
displayName: string = "Fiscal Year";
displayNameKey: string = "Visual_FiscalYear";
descriptionKey: string = "Visual_FiscalYear_Description";
slices = [this.month, this.day];
slices = [this.treatAsEndOfFiscalYear, this.month, this.day];
}

class WeekDaySettingsCard extends Card {
Expand Down
1 change: 1 addition & 0 deletions stringResources/en-US/resources.resjson
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
"Visual_FiscalYearStart": "Fiscal Year Start",
"Visual_FiscalYear": "Fiscal Year",
"Visual_FiscalYear_Description": "This option have no sense if ISO 8601 standard was picked",
"Visual_TreatAsEndOfFiscalYear": "Treat as end of fiscal year",
"Visual_Month": "Month",
"Visual_Month_January": "January",
"Visual_Month_February": "February",
Expand Down
28 changes: 15 additions & 13 deletions test/visual.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import {select as d3Select} from "d3-selection";
import powerbiVisualsApi from "powerbi-visuals-api";
import {assertColorsMatch, d3Click, parseColorString, renderTimeout,} from "powerbi-visuals-utils-testutils";

import {Calendar, CalendarFormat, WeekdayFormat} from "../src/calendars/calendar";
import {Calendar, CalendarFormat, CalendarFormattingSettings, WeekdayFormat} from "../src/calendars/calendar";
import {ITimelineCursorOverElement, ITimelineData} from "../src/dataInterfaces";
import {ITimelineDatePeriod, ITimelineDatePeriodBase} from "../src/datePeriod/datePeriod";
import {DatePeriodBase} from "../src/datePeriod/datePeriodBase";
Expand Down Expand Up @@ -1029,11 +1029,11 @@ describe("Timeline - Granularity - 1 Jan (Regular Calendar)", () => {
calendar = createCalendar();

granularities = [
new YearGranularity(calendar, null, null),
new QuarterGranularity(calendar, null),
new WeekGranularity(calendar, null, null),
new MonthGranularity(calendar, null),
new DayGranularity(calendar, null),
new YearGranularity(calendar, "en-US", null),
new QuarterGranularity(calendar, "en-US"),
new WeekGranularity(calendar, "en-US", null),
new MonthGranularity(calendar, "en-US"),
new DayGranularity(calendar, "en-US"),
];
});

Expand Down Expand Up @@ -1075,11 +1075,11 @@ describe("Timeline - Granularity - 1 Apr (Fiscal Calendar)", () => {
calendar = createCalendar(3);

granularities = [
new YearGranularity(calendar, null, null),
new QuarterGranularity(calendar, null),
new WeekGranularity(calendar, null, null),
new MonthGranularity(calendar, null),
new DayGranularity(calendar, null),
new YearGranularity(calendar, "en-US", null),
new QuarterGranularity(calendar, "en-US"),
new WeekGranularity(calendar, "en-US", null),
new MonthGranularity(calendar, "en-US"),
new DayGranularity(calendar, "en-US"),
];
});

Expand Down Expand Up @@ -1157,7 +1157,8 @@ describe("Timeline - Granularity - ISO 8601 Week numbering", () => {
let calendar: Calendar;

beforeEach(() => {
calendar = new CalendarISO8061();
const calendarFormattingSettings: CalendarFormattingSettings = { treatAsEndOfFiscalYear: true };
calendar = new CalendarISO8061(calendarFormattingSettings);
});

describe("ISO Calendar Methods", () => {
Expand Down Expand Up @@ -1723,6 +1724,7 @@ function createCalendar(
day: number = 1,
week: number = 1,
dayOfWeekSelectionOn: boolean = false,
treatAsEndOfFiscalYear: boolean = true,
): Calendar {

const calendarSettings: CalendarFormat = {
Expand All @@ -1735,7 +1737,7 @@ function createCalendar(
daySelection: dayOfWeekSelectionOn,
};

return new Calendar(calendarSettings, weekDaySettings);
return new Calendar(calendarSettings, weekDaySettings, { treatAsEndOfFiscalYear });
}

function createDatePeriod(dates: Date[]): ITimelineDatePeriod[] {
Expand Down

0 comments on commit 0c671db

Please sign in to comment.