Skip to content

Commit

Permalink
Add date range picker to energy period selector (#14337)
Browse files Browse the repository at this point in the history
  • Loading branch information
TillFleisch authored Oct 12, 2023
1 parent f8966a2 commit 6071757
Show file tree
Hide file tree
Showing 16 changed files with 785 additions and 331 deletions.
1 change: 0 additions & 1 deletion cast/src/receiver/layout/hc-main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,7 +260,6 @@ export class HcMain extends HassElement {
{
strategy: {
type: "energy",
show_date_selection: true,
},
},
],
Expand Down
20 changes: 17 additions & 3 deletions src/common/datetime/calc_date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@ import { FrontendLocaleData, TimeZone } from "../../data/translation";
const calcZonedDate = (
date: Date,
tz: string,
fn: (date: Date, options?: any) => Date,
fn: (date: Date, options?: any) => Date | number | boolean,
options?
) => {
const inputZoned = utcToZonedTime(date, tz);
const fnZoned = fn(inputZoned, options);
return zonedTimeToUtc(fnZoned, tz);
if (fnZoned instanceof Date) {
return zonedTimeToUtc(fnZoned, tz) as Date;
}
return fnZoned;
};

export const calcDate = (
Expand All @@ -21,5 +24,16 @@ export const calcDate = (
options?
) =>
locale.time_zone === TimeZone.server
? calcZonedDate(date, config.time_zone, fn, options)
? (calcZonedDate(date, config.time_zone, fn, options) as Date)
: fn(date, options);

export const calcDateProperty = (
date: Date,
fn: (date: Date, options?: any) => boolean | number,
locale: FrontendLocaleData,
config: HassConfig,
options?
) =>
locale.time_zone === TimeZone.server
? (calcZonedDate(date, config.time_zone, fn, options) as number | boolean)
: fn(date, options);
23 changes: 20 additions & 3 deletions src/common/datetime/format_date.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ const formatDateMem = memoizeOne(
})
);

// Aug 10, 2021
export const formatDateShort = (
dateObj: Date,
locale: FrontendLocaleData,
config: HassConfig
) => formatDateShortMem(locale, config.time_zone).format(dateObj);

const formatDateShortMem = memoizeOne(
(locale: FrontendLocaleData, serverTimeZone: string) =>
new Intl.DateTimeFormat(locale.language, {
year: "numeric",
month: "short",
day: "numeric",
timeZone: locale.time_zone === "server" ? serverTimeZone : undefined,
})
);

// 10/08/2021
export const formatDateNumeric = (
dateObj: Date,
Expand Down Expand Up @@ -102,13 +119,13 @@ const formatDateNumericMem = memoizeOne(
);

// Aug 10
export const formatDateShort = (
export const formatDateVeryShort = (
dateObj: Date,
locale: FrontendLocaleData,
config: HassConfig
) => formatDateShortMem(locale, config.time_zone).format(dateObj);
) => formatDateVeryShortMem(locale, config.time_zone).format(dateObj);

const formatDateShortMem = memoizeOne(
const formatDateVeryShortMem = memoizeOne(
(locale: FrontendLocaleData, serverTimeZone: string) =>
new Intl.DateTimeFormat(locale.language, {
day: "numeric",
Expand Down
4 changes: 2 additions & 2 deletions src/components/chart/chart-date-adapter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ import {
formatDate,
formatDateMonth,
formatDateMonthYear,
formatDateShort,
formatDateVeryShort,
formatDateWeekdayDay,
formatDateYear,
} from "../../common/datetime/format_date";
Expand Down Expand Up @@ -128,7 +128,7 @@ _adapters._date.override({
this.options.config
);
case "day":
return formatDateShort(
return formatDateVeryShort(
new Date(time),
this.options.locale,
this.options.config
Expand Down
12 changes: 10 additions & 2 deletions src/components/date-range-picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ const Component = Vue.extend({
type: Boolean,
default: true,
},
openingDirection: {
type: String,
default: "right",
},
disabled: {
type: Boolean,
default: false,
Expand Down Expand Up @@ -66,7 +70,7 @@ const Component = Vue.extend({
props: {
"time-picker": this.timePicker,
"auto-apply": this.autoApply,
opens: "right",
opens: this.openingDirection,
"show-dropdowns": false,
"time-picker24-hour": this.twentyfourHours,
disabled: this.disabled,
Expand Down Expand Up @@ -126,9 +130,9 @@ class DateRangePickerElement extends WrappedElement {
${dateRangePickerStyles}
.calendars {
display: flex;
flex-wrap: nowrap !important;
}
.daterangepicker {
left: 0px !important;
top: auto;
box-shadow: var(--ha-card-box-shadow, none);
background-color: var(--card-background-color);
Expand Down Expand Up @@ -252,6 +256,10 @@ class DateRangePickerElement extends WrappedElement {
direction: ltr;
text-align: left;
}
.vue-daterange-picker{
min-width: unset !important;
display: block !important;
}
`;
const shadowRoot = this.shadowRoot!;
shadowRoot.appendChild(style);
Expand Down
98 changes: 69 additions & 29 deletions src/components/ha-date-range-picker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import {
CSSResultGroup,
html,
LitElement,
nothing,
PropertyValues,
TemplateResult,
} from "lit";
Expand All @@ -29,6 +30,7 @@ import { HomeAssistant } from "../types";
import "./date-range-picker";
import "./ha-svg-icon";
import "./ha-textfield";
import "./ha-icon-button";

export interface DateRangePickerRanges {
[key: string]: [Date, Date];
Expand All @@ -54,7 +56,21 @@ export class HaDateRangePicker extends LitElement {

@property({ type: String }) private _rtlDirection = "ltr";

@property({ type: Boolean }) private minimal = false;

@property() private _openingDirection = "right";

protected willUpdate() {
// set dialog opening direction based on position
const datePickerPosition = this.getBoundingClientRect().x;
if (datePickerPosition > (2 * window.innerWidth) / 3) {
this._openingDirection = "left";
} else if (datePickerPosition < window.innerWidth / 3) {
this._openingDirection = "right";
} else {
this._openingDirection = "center";
}

if (!this.hasUpdated && this.ranges === undefined) {
const today = new Date();
const weekStartsOn = firstWeekdayIndex(this.hass.locale);
Expand Down Expand Up @@ -133,41 +149,61 @@ export class HaDateRangePicker extends LitElement {
<date-range-picker
?disabled=${this.disabled}
?auto-apply=${this.autoApply}
?time-picker=${this.timePicker}
time-picker=${this.timePicker}
twentyfour-hours=${this._hour24format}
start-date=${this.startDate}
end-date=${this.endDate}
?ranges=${this.ranges !== false}
opening-direction=${this._openingDirection}
first-day=${firstWeekdayIndex(this.hass.locale)}
>
<div slot="input" class="date-range-inputs">
<ha-svg-icon .path=${mdiCalendar}></ha-svg-icon>
<ha-textfield
.value=${this.timePicker
? formatDateTime(
this.startDate,
this.hass.locale,
this.hass.config
)
: formatDate(this.startDate, this.hass.locale, this.hass.config)}
.label=${this.hass.localize(
"ui.components.date-range-picker.start_date"
)}
.disabled=${this.disabled}
@click=${this._handleInputClick}
readonly
></ha-textfield>
<ha-textfield
.value=${this.timePicker
? formatDateTime(this.endDate, this.hass.locale, this.hass.config)
: formatDate(this.endDate, this.hass.locale, this.hass.config)}
.label=${this.hass.localize(
"ui.components.date-range-picker.end_date"
)}
.disabled=${this.disabled}
@click=${this._handleInputClick}
readonly
></ha-textfield>
${!this.minimal
? html`<ha-svg-icon .path=${mdiCalendar}></ha-svg-icon>
<ha-textfield
.value=${this.timePicker
? formatDateTime(
this.startDate,
this.hass.locale,
this.hass.config
)
: formatDate(
this.startDate,
this.hass.locale,
this.hass.config
)}
.label=${this.hass.localize(
"ui.components.date-range-picker.start_date"
)}
.disabled=${this.disabled}
@click=${this._handleInputClick}
readonly
></ha-textfield>
<ha-textfield
.value=${this.timePicker
? formatDateTime(
this.endDate,
this.hass.locale,
this.hass.config
)
: formatDate(
this.endDate,
this.hass.locale,
this.hass.config
)}
.label=${this.hass.localize(
"ui.components.date-range-picker.end_date"
)}
.disabled=${this.disabled}
@click=${this._handleInputClick}
readonly
></ha-textfield>`
: html`<ha-icon-button
.label=${this.hass.localize(
"ui.components.date-range-picker.select_date_range"
)}
.path=${mdiCalendar}
></ha-icon-button>`}
</div>
${this.ranges
? html`<div
Expand All @@ -181,7 +217,7 @@ export class HaDateRangePicker extends LitElement {
)}
</mwc-list>
</div>`
: ""}
: nothing}
<div slot="footer" class="date-range-footer">
<mwc-button @click=${this._cancelDateRange}
>${this.hass.localize("ui.common.cancel")}</mwc-button
Expand Down Expand Up @@ -234,6 +270,10 @@ export class HaDateRangePicker extends LitElement {
direction: var(--direction);
}
ha-icon-button {
direction: var(--direction);
}
.date-range-inputs {
display: flex;
align-items: center;
Expand Down
44 changes: 39 additions & 5 deletions src/data/energy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ import {
addMilliseconds,
addMonths,
differenceInDays,
differenceInMonths,
endOfDay,
startOfDay,
isFirstDayOfMonth,
isLastDayOfMonth,
} from "date-fns/esm";
import { Collection, getCollection } from "home-assistant-js-websocket";
import { calcDate } from "../common/datetime/calc_date";
import { calcDate, calcDateProperty } from "../common/datetime/calc_date";
import { formatTime24h } from "../common/datetime/format_time";
import { groupBy } from "../common/util/group-by";
import { HomeAssistant } from "../types";
Expand Down Expand Up @@ -416,11 +419,42 @@ const getEnergyData = async (
let _waterStatsCompare: Statistics | Promise<Statistics> = {};

if (compare) {
if (dayDifference > 27 && dayDifference < 32) {
// When comparing a month, we want to start at the begining of the month
startCompare = addMonths(start, -1);
if (
(calcDateProperty(
start,
isFirstDayOfMonth,
hass.locale,
hass.config
) as boolean) &&
(calcDateProperty(
end || new Date(),
isLastDayOfMonth,
hass.locale,
hass.config
) as boolean)
) {
// When comparing a month (or multiple), we want to start at the begining of the month
startCompare = calcDate(
start,
addMonths,
hass.locale,
hass.config,
-(calcDateProperty(
end || new Date(),
differenceInMonths,
hass.locale,
hass.config,
start
) as number) - 1
);
} else {
startCompare = addDays(start, (dayDifference + 1) * -1);
startCompare = calcDate(
start,
addDays,
hass.locale,
hass.config,
(dayDifference + 1) * -1
);
}
endCompare = addMilliseconds(start, -1);
if (energyStatIds.length) {
Expand Down
Loading

0 comments on commit 6071757

Please sign in to comment.