From a46e317a758fd119aba35d418edda3403ae4ef1e Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Sat, 18 Jun 2022 13:26:23 -0500 Subject: [PATCH 1/3] Added support for custom time format in header clocks Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/silver-needles-unite.md | 26 +++++++++++++++++++ packages/app/src/components/home/HomePage.tsx | 11 +++++++- plugins/home/api-report.md | 1 + .../HeaderWorldClock/HeaderWorldClock.tsx | 20 +++++++++----- 4 files changed, 50 insertions(+), 8 deletions(-) create mode 100644 .changeset/silver-needles-unite.md diff --git a/.changeset/silver-needles-unite.md b/.changeset/silver-needles-unite.md new file mode 100644 index 0000000000..bd65f4d253 --- /dev/null +++ b/.changeset/silver-needles-unite.md @@ -0,0 +1,26 @@ +--- +'@backstage/plugin-home': patch +--- + +Added support for customizing the time format used in the `HeaderWorlClock` component + +Here's an example of how this can be used in the `HomePage.tsx` found in `\packages\app\src\components\home` to change the clock to be in the 24hr time format: + +```diff ++const timeFormat: Intl.DateTimeFormatOptions = { ++ hour: '2-digit', ++ minute: '2-digit', ++ hour12: false, ++}; + +export const homePage = ( + +
} pageTitleOverride="Home"> ++ +
+ + + + + +``` diff --git a/packages/app/src/components/home/HomePage.tsx b/packages/app/src/components/home/HomePage.tsx index 2cd5481c91..e432e1a00e 100644 --- a/packages/app/src/components/home/HomePage.tsx +++ b/packages/app/src/components/home/HomePage.tsx @@ -49,10 +49,19 @@ const clockConfigs: ClockConfig[] = [ }, ]; +const timeFormat: Intl.DateTimeFormatOptions = { + hour: '2-digit', + minute: '2-digit', + hour12: false, +}; + export const homePage = (
} pageTitleOverride="Home"> - +
diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index a65f8cda5c..fff7e6c28b 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -62,6 +62,7 @@ export function createCardExtension(options: { // @public (undocumented) export const HeaderWorldClock: (props: { clockConfigs: ClockConfig[]; + customTimeFormat?: Intl.DateTimeFormatOptions; }) => JSX.Element | null; // @public diff --git a/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.tsx b/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.tsx index 7e3065cc7a..c536457ad9 100644 --- a/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.tsx +++ b/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.tsx @@ -32,7 +32,10 @@ export type ClockConfig = { timeZone: string; }; -function getTimes(clockConfigs: ClockConfig[]) { +function getTimes( + clockConfigs: ClockConfig[], + customTimeFormat?: Intl.DateTimeFormatOptions, +) { const d = new Date(); const lang = window.navigator.language; @@ -47,7 +50,7 @@ function getTimes(clockConfigs: ClockConfig[]) { const options: Intl.DateTimeFormatOptions = { timeZone: clockConfig.timeZone, - ...timeFormat, + ...(customTimeFormat ?? timeFormat), }; try { @@ -69,23 +72,26 @@ function getTimes(clockConfigs: ClockConfig[]) { } /** @public */ -export const HeaderWorldClock = (props: { clockConfigs: ClockConfig[] }) => { - const { clockConfigs } = props; +export const HeaderWorldClock = (props: { + clockConfigs: ClockConfig[]; + customTimeFormat?: Intl.DateTimeFormatOptions; +}) => { + const { clockConfigs, customTimeFormat } = props; const defaultTimes: TimeObj[] = []; const [clocks, setTimes] = React.useState(defaultTimes); React.useEffect(() => { - setTimes(getTimes(clockConfigs)); + setTimes(getTimes(clockConfigs, customTimeFormat)); const intervalId = setInterval(() => { - setTimes(getTimes(clockConfigs)); + setTimes(getTimes(clockConfigs, customTimeFormat)); }, 1000); return () => { clearInterval(intervalId); }; - }, [clockConfigs]); + }, [clockConfigs, customTimeFormat]); if (clocks.length !== 0) { return ( From cec13be485b452346b93fc2dfc74b0c905b5fc81 Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Mon, 20 Jun 2022 13:01:20 -0500 Subject: [PATCH 2/3] Fixed typo and added test Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- .changeset/silver-needles-unite.md | 2 +- .../HeaderWorldClock.test.tsx | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/.changeset/silver-needles-unite.md b/.changeset/silver-needles-unite.md index bd65f4d253..b5fed7e615 100644 --- a/.changeset/silver-needles-unite.md +++ b/.changeset/silver-needles-unite.md @@ -2,7 +2,7 @@ '@backstage/plugin-home': patch --- -Added support for customizing the time format used in the `HeaderWorlClock` component +Added support for customizing the time format used in the `HeaderWorldClock` component Here's an example of how this can be used in the `HomePage.tsx` found in `\packages\app\src\components\home` to change the clock to be in the 24hr time format: diff --git a/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.test.tsx b/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.test.tsx index 9dbfceac81..3611f47787 100644 --- a/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.test.tsx +++ b/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.test.tsx @@ -86,3 +86,32 @@ describe('HeaderWorldClock with invalid Time Zone', () => { expect(rendered.getByText('GMT')).toBeInTheDocument(); }); }); + +describe('HeaderWorldClock with custom Time Format', () => { + it('uses 24hr clock from custom Time Format', async () => { + const clockConfigs: ClockConfig[] = [ + { + label: 'UTC', + timeZone: 'UTC', + }, + ]; + + const timeFormat: Intl.DateTimeFormatOptions = { + hour: '2-digit', + minute: '2-digit', + hour12: false, + }; + + const rendered = await renderInTestApp( + + + , + ); + + const currentTime = `${new Date().getHours()}:${new Date().getMinutes()}`; + expect(rendered.getByText(currentTime)).toBeInTheDocument(); + }); +}); From 144879af16d71d7187b490d985835903c38ed5fe Mon Sep 17 00:00:00 2001 From: Andre Wanlin <67169551+awanlin@users.noreply.github.com> Date: Thu, 23 Jun 2022 12:17:55 -0500 Subject: [PATCH 3/3] Refactored to include stories and examples Signed-off-by: Andre Wanlin <67169551+awanlin@users.noreply.github.com> --- plugins/home/api-report.md | 4 +- plugins/home/src/components/index.ts | 2 - .../HeaderWorldClock.stories.tsx | 97 +++++++++++++++++++ .../HeaderWorldClock.test.tsx | 0 .../HeaderWorldClock/HeaderWorldClock.tsx | 32 +++++- .../HeaderWorldClock/index.ts | 0 plugins/home/src/homePageComponents/index.ts | 1 + plugins/home/src/index.ts | 5 +- plugins/home/src/plugin.ts | 17 ++++ 9 files changed, 151 insertions(+), 7 deletions(-) create mode 100644 plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.stories.tsx rename plugins/home/src/{components => homePageComponents}/HeaderWorldClock/HeaderWorldClock.test.tsx (100%) rename plugins/home/src/{components => homePageComponents}/HeaderWorldClock/HeaderWorldClock.tsx (77%) rename plugins/home/src/{components => homePageComponents}/HeaderWorldClock/index.ts (100%) diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index fff7e6c28b..452b3e1685 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -59,10 +59,10 @@ export function createCardExtension(options: { name?: string; }): Extension<(props: CardExtensionProps) => JSX.Element>; -// @public (undocumented) +// @public export const HeaderWorldClock: (props: { clockConfigs: ClockConfig[]; - customTimeFormat?: Intl.DateTimeFormatOptions; + customTimeFormat?: Intl.DateTimeFormatOptions | undefined; }) => JSX.Element | null; // @public diff --git a/plugins/home/src/components/index.ts b/plugins/home/src/components/index.ts index 1408853f5f..aae0cbe26d 100644 --- a/plugins/home/src/components/index.ts +++ b/plugins/home/src/components/index.ts @@ -16,5 +16,3 @@ export { HomepageCompositionRoot } from './HomepageCompositionRoot'; export { SettingsModal } from './SettingsModal'; -export { HeaderWorldClock } from './HeaderWorldClock'; -export type { ClockConfig } from './HeaderWorldClock'; diff --git a/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.stories.tsx b/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.stories.tsx new file mode 100644 index 0000000000..706dfa06ce --- /dev/null +++ b/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.stories.tsx @@ -0,0 +1,97 @@ +/* + * Copyright 2021 The Backstage Authors + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +import { Header } from '@backstage/core-components'; +import { wrapInTestApp } from '@backstage/test-utils'; +import React, { ComponentType } from 'react'; +import { ClockConfig, HeaderWorldClock } from './HeaderWorldClock'; + +export default { + title: 'Plugins/Home/Components/HeaderWorldClock', + decorators: [(Story: ComponentType<{}>) => wrapInTestApp()], +}; + +export const Default = () => { + const clockConfigs: ClockConfig[] = [ + { + label: 'NYC', + timeZone: 'America/New_York', + }, + { + label: 'UTC', + timeZone: 'UTC', + }, + { + label: 'STO', + timeZone: 'Europe/Stockholm', + }, + { + label: 'TYO', + timeZone: 'Asia/Tokyo', + }, + ]; + + const timeFormat: Intl.DateTimeFormatOptions = { + hour: '2-digit', + minute: '2-digit', + hour12: true, + }; + + return ( +
+ +
+ ); +}; + +export const TwentyFourHourClocks = () => { + const clockConfigs: ClockConfig[] = [ + { + label: 'NYC', + timeZone: 'America/New_York', + }, + { + label: 'UTC', + timeZone: 'UTC', + }, + { + label: 'STO', + timeZone: 'Europe/Stockholm', + }, + { + label: 'TYO', + timeZone: 'Asia/Tokyo', + }, + ]; + + const timeFormat: Intl.DateTimeFormatOptions = { + hour: '2-digit', + minute: '2-digit', + hour12: false, + }; + + return ( +
+ +
+ ); +}; diff --git a/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.test.tsx b/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.test.tsx similarity index 100% rename from plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.test.tsx rename to plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.test.tsx diff --git a/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.tsx b/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.tsx similarity index 77% rename from plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.tsx rename to plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.tsx index c536457ad9..6672fe6a22 100644 --- a/plugins/home/src/components/HeaderWorldClock/HeaderWorldClock.tsx +++ b/plugins/home/src/homePageComponents/HeaderWorldClock/HeaderWorldClock.tsx @@ -71,7 +71,37 @@ function getTimes( return clocks; } -/** @public */ +/** + * A component to display a configurable list of clocks for various time zones. + * + * @example + * Here's a simple example: + * ``` + * // This will give you a clock for the time zone that Stockholm is in + * // you can add more than one but keep in mind space may be limited + * const clockConfigs: ClockConfig[] = [ + * { + * label: 'STO', + * timeZone: 'Europe/Stockholm', + * }, + * ]; + * + * // Setting hour12 to false will make all the clocks show in the 24hr format + * const timeFormat: Intl.DateTimeFormatOptions = { + * hour: '2-digit', + * minute: '2-digit', + * hour12: false, + * }; + * + * // Here is the component in use: + * + * ``` + * + * @public + */ export const HeaderWorldClock = (props: { clockConfigs: ClockConfig[]; customTimeFormat?: Intl.DateTimeFormatOptions; diff --git a/plugins/home/src/components/HeaderWorldClock/index.ts b/plugins/home/src/homePageComponents/HeaderWorldClock/index.ts similarity index 100% rename from plugins/home/src/components/HeaderWorldClock/index.ts rename to plugins/home/src/homePageComponents/HeaderWorldClock/index.ts diff --git a/plugins/home/src/homePageComponents/index.ts b/plugins/home/src/homePageComponents/index.ts index 4d2802fb98..d318226dbd 100644 --- a/plugins/home/src/homePageComponents/index.ts +++ b/plugins/home/src/homePageComponents/index.ts @@ -16,3 +16,4 @@ export * from './CompanyLogo'; export * from './Toolkit'; +export type { ClockConfig } from './HeaderWorldClock'; diff --git a/plugins/home/src/index.ts b/plugins/home/src/index.ts index 8f137d589b..1776b5aa9c 100644 --- a/plugins/home/src/index.ts +++ b/plugins/home/src/index.ts @@ -31,9 +31,10 @@ export { ComponentTabs, ComponentTab, WelcomeTitle, + HeaderWorldClock, } from './plugin'; -export { SettingsModal, HeaderWorldClock } from './components'; +export { SettingsModal } from './components'; export * from './assets'; -export type { ClockConfig } from './components'; +export type { ClockConfig } from './homePageComponents'; export { createCardExtension } from './extensions'; export type { ComponentRenderer } from './extensions'; diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index 93110faffb..9b221ad8dc 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -136,3 +136,20 @@ export const HomePageStarredEntities = homePlugin.provide( components: () => import('./homePageComponents/StarredEntities'), }), ); + +/** + * A component to display a configurable list of clocks for various time zones. + * + * @public + */ +export const HeaderWorldClock = homePlugin.provide( + createComponentExtension({ + name: 'HeaderWorldClock', + component: { + lazy: () => + import('./homePageComponents/HeaderWorldClock').then( + m => m.HeaderWorldClock, + ), + }, + }), +);