feat: date format on weather widget (#1443)
* feat: date format on weather widget * fix: type check error * fix: reviewed changes * fix: reviewed changes
This commit is contained in:
@@ -12,5 +12,15 @@ export type OldmarrWeatherDefinition = CommonOldmarrWidgetDefinition<
|
|||||||
latitude: number;
|
latitude: number;
|
||||||
longitude: number;
|
longitude: number;
|
||||||
};
|
};
|
||||||
|
dateFormat:
|
||||||
|
| "hide"
|
||||||
|
| "dddd, MMMM D"
|
||||||
|
| "dddd, D MMMM"
|
||||||
|
| "MMM D"
|
||||||
|
| "D MMM"
|
||||||
|
| "DD/MM/YYYY"
|
||||||
|
| "MM/DD/YYYY"
|
||||||
|
| "DD/MM"
|
||||||
|
| "MM/DD";
|
||||||
}
|
}
|
||||||
>;
|
>;
|
||||||
|
|||||||
@@ -72,6 +72,7 @@ const optionMapping: OptionMapping = {
|
|||||||
isFormatFahrenheit: (oldOptions) => oldOptions.displayInFahrenheit,
|
isFormatFahrenheit: (oldOptions) => oldOptions.displayInFahrenheit,
|
||||||
location: (oldOptions) => oldOptions.location,
|
location: (oldOptions) => oldOptions.location,
|
||||||
showCity: (oldOptions) => oldOptions.displayCityName,
|
showCity: (oldOptions) => oldOptions.displayCityName,
|
||||||
|
dateFormat: (oldOptions) => (oldOptions.dateFormat === "hide" ? undefined : oldOptions.dateFormat),
|
||||||
},
|
},
|
||||||
iframe: {
|
iframe: {
|
||||||
embedUrl: (oldOptions) => oldOptions.embedUrl,
|
embedUrl: (oldOptions) => oldOptions.embedUrl,
|
||||||
|
|||||||
@@ -1134,6 +1134,10 @@
|
|||||||
"forecastDayCount": {
|
"forecastDayCount": {
|
||||||
"label": "Amount of forecast days",
|
"label": "Amount of forecast days",
|
||||||
"description": "When the widget is not wide enough, less days are shown"
|
"description": "When the widget is not wide enough, less days are shown"
|
||||||
|
},
|
||||||
|
"dateFormat": {
|
||||||
|
"label": "Date Format",
|
||||||
|
"description": "How the date should look like"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"kind": {
|
"kind": {
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ const WeeklyForecast = ({ options, weather }: WeatherProps) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
function Forecast({ weather, options }: WeatherProps) {
|
function Forecast({ weather, options }: WeatherProps) {
|
||||||
|
const dateFormat = options.dateFormat;
|
||||||
return (
|
return (
|
||||||
<Group className="weather-forecast-days-group" w="100%" justify="space-evenly" wrap="nowrap" pb="2.5cqmin">
|
<Group className="weather-forecast-days-group" w="100%" justify="space-evenly" wrap="nowrap" pb="2.5cqmin">
|
||||||
{weather.daily.slice(0, options.forecastDayCount).map((dayWeather, index) => (
|
{weather.daily.slice(0, options.forecastDayCount).map((dayWeather, index) => (
|
||||||
@@ -136,6 +137,7 @@ function Forecast({ weather, options }: WeatherProps) {
|
|||||||
</HoverCard.Target>
|
</HoverCard.Target>
|
||||||
<HoverCard.Dropdown>
|
<HoverCard.Dropdown>
|
||||||
<WeatherDescription
|
<WeatherDescription
|
||||||
|
dateFormat={dateFormat}
|
||||||
time={dayWeather.time}
|
time={dayWeather.time}
|
||||||
weatherCode={dayWeather.weatherCode}
|
weatherCode={dayWeather.weatherCode}
|
||||||
maxTemp={getPreferredUnit(dayWeather.maxTemp, options.isFormatFahrenheit)}
|
maxTemp={getPreferredUnit(dayWeather.maxTemp, options.isFormatFahrenheit)}
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ import type { TranslationObject } from "@homarr/translation";
|
|||||||
import { useScopedI18n } from "@homarr/translation/client";
|
import { useScopedI18n } from "@homarr/translation/client";
|
||||||
import type { TablerIcon } from "@homarr/ui";
|
import type { TablerIcon } from "@homarr/ui";
|
||||||
|
|
||||||
|
import type { WidgetProps } from "../definition";
|
||||||
|
|
||||||
interface WeatherIconProps {
|
interface WeatherIconProps {
|
||||||
code: number;
|
code: number;
|
||||||
size?: string | number;
|
size?: string | number;
|
||||||
@@ -34,6 +36,7 @@ export const WeatherIcon = ({ code, size = 50 }: WeatherIconProps) => {
|
|||||||
|
|
||||||
interface WeatherDescriptionProps {
|
interface WeatherDescriptionProps {
|
||||||
weatherOnly?: boolean;
|
weatherOnly?: boolean;
|
||||||
|
dateFormat?: WidgetProps<"weather">["options"]["dateFormat"];
|
||||||
time?: string;
|
time?: string;
|
||||||
weatherCode: number;
|
weatherCode: number;
|
||||||
maxTemp?: string;
|
maxTemp?: string;
|
||||||
@@ -42,13 +45,21 @@ interface WeatherDescriptionProps {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Description Dropdown for a given set of parameters
|
* Description Dropdown for a given set of parameters
|
||||||
|
* @param dateFormat format of the date that will be displayed on the widget
|
||||||
* @param time date that can be formatted by dayjs
|
* @param time date that can be formatted by dayjs
|
||||||
* @param weatherCode weather code from api
|
* @param weatherCode weather code from api
|
||||||
* @param maxTemp preformatted string for max temperature
|
* @param maxTemp preformatted string for max temperature
|
||||||
* @param minTemp preformatted string for min temperature
|
* @param minTemp preformatted string for min temperature
|
||||||
* @returns Content for a HoverCard dropdown presenting weather information
|
* @returns Content for a HoverCard dropdown presenting weather information
|
||||||
*/
|
*/
|
||||||
export const WeatherDescription = ({ weatherOnly, time, weatherCode, maxTemp, minTemp }: WeatherDescriptionProps) => {
|
export const WeatherDescription = ({
|
||||||
|
weatherOnly,
|
||||||
|
dateFormat,
|
||||||
|
time,
|
||||||
|
weatherCode,
|
||||||
|
maxTemp,
|
||||||
|
minTemp,
|
||||||
|
}: WeatherDescriptionProps) => {
|
||||||
const t = useScopedI18n("widget.weather");
|
const t = useScopedI18n("widget.weather");
|
||||||
const tCommon = useScopedI18n("common");
|
const tCommon = useScopedI18n("common");
|
||||||
|
|
||||||
@@ -60,7 +71,7 @@ export const WeatherDescription = ({ weatherOnly, time, weatherCode, maxTemp, mi
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Stack align="center" gap="0">
|
<Stack align="center" gap="0">
|
||||||
<Text fz="24px">{dayjs(time).format("dddd MMMM D YYYY")}</Text>
|
<Text fz="24px">{dayjs(time).format(dateFormat)}</Text>
|
||||||
<Text fz="16px">{t(`kind.${name}`)}</Text>
|
<Text fz="16px">{t(`kind.${name}`)}</Text>
|
||||||
<Text fz="16px">{`${tCommon("information.max")}: ${maxTemp}`}</Text>
|
<Text fz="16px">{`${tCommon("information.max")}: ${maxTemp}`}</Text>
|
||||||
<Text fz="16px">{`${tCommon("information.min")}: ${minTemp}`}</Text>
|
<Text fz="16px">{`${tCommon("information.min")}: ${minTemp}`}</Text>
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
import { IconCloud } from "@tabler/icons-react";
|
import { IconCloud } from "@tabler/icons-react";
|
||||||
|
import dayjs from "dayjs";
|
||||||
|
|
||||||
import { z } from "@homarr/validation";
|
import { z } from "@homarr/validation";
|
||||||
|
|
||||||
@@ -17,6 +18,20 @@ export const { definition, componentLoader } = createWidgetDefinition("weather",
|
|||||||
longitude: 2.3488,
|
longitude: 2.3488,
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
|
dateFormat: factory.select({
|
||||||
|
options: [
|
||||||
|
{ value: "dddd, MMMM D", label: dayjs().format("dddd, MMMM D") },
|
||||||
|
{ value: "dddd, D MMMM", label: dayjs().format("dddd, D MMMM") },
|
||||||
|
{ value: "MMM D", label: dayjs().format("MMM D") },
|
||||||
|
{ value: "D MMM", label: dayjs().format("D MMM") },
|
||||||
|
{ value: "DD/MM/YYYY", label: dayjs().format("DD/MM/YYYY") },
|
||||||
|
{ value: "MM/DD/YYYY", label: dayjs().format("MM/DD/YYYY") },
|
||||||
|
{ value: "DD/MM", label: dayjs().format("DD/MM") },
|
||||||
|
{ value: "MM/DD", label: dayjs().format("MM/DD") },
|
||||||
|
],
|
||||||
|
defaultValue: "dddd, MMMM D",
|
||||||
|
withDescription: true,
|
||||||
|
}),
|
||||||
showCity: factory.switch(),
|
showCity: factory.switch(),
|
||||||
hasForecast: factory.switch(),
|
hasForecast: factory.switch(),
|
||||||
forecastDayCount: factory.slider({
|
forecastDayCount: factory.slider({
|
||||||
|
|||||||
Reference in New Issue
Block a user