Move HomepageTimer and use props over config (#7533)
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
---
|
||||
'@backstage/plugin-home': patch
|
||||
---
|
||||
|
||||
Added HeaderWorldClock to the Home plugin which is a copy of the HomepageTimer from core-components that has been updated to use props over static config from app-config.yaml. To use HeaderWorldClock you'll need to create an array of ClockConfig like this:
|
||||
|
||||
```ts
|
||||
const clockConfigs: ClockConfig[] = [
|
||||
{
|
||||
label: 'NYC',
|
||||
timeZone: 'America/New_York',
|
||||
},
|
||||
{
|
||||
label: 'UTC',
|
||||
timeZone: 'UTC',
|
||||
},
|
||||
{
|
||||
label: 'STO',
|
||||
timeZone: 'Europe/Stockholm',
|
||||
},
|
||||
{
|
||||
label: 'TYO',
|
||||
timeZone: 'Asia/Tokyo',
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
Then you can pass `clockConfigs` into the HeaderWorldClock like this:
|
||||
|
||||
```ts
|
||||
<Page themeId="home">
|
||||
<Header title="Home">
|
||||
<HeaderWorldClock clockConfigs={clockConfigs} />
|
||||
</Header>
|
||||
<Content>...</Content>
|
||||
</Page>
|
||||
```
|
||||
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'@backstage/core-components': patch
|
||||
---
|
||||
|
||||
Deprecated HomepageTimer in favor of HeaderWorldClock which is found in the [home plugin](https://github.com/backstage/backstage/tree/master/plugins/home)
|
||||
@@ -15,26 +15,42 @@
|
||||
*/
|
||||
|
||||
import {
|
||||
Content,
|
||||
Header,
|
||||
HomepageTimer,
|
||||
Page,
|
||||
} from '@backstage/core-components';
|
||||
import {
|
||||
ComponentAccordion,
|
||||
ComponentTab,
|
||||
ComponentTabs,
|
||||
HomePageRandomJoke,
|
||||
ComponentAccordion,
|
||||
ComponentTabs,
|
||||
ComponentTab,
|
||||
WelcomeTitle,
|
||||
HeaderWorldClock,
|
||||
ClockConfig,
|
||||
} from '@backstage/plugin-home';
|
||||
import { Content, Header, Page } from '@backstage/core-components';
|
||||
import { HomePageSearchBar } from '@backstage/plugin-search';
|
||||
import Grid from '@material-ui/core/Grid';
|
||||
import React from 'react';
|
||||
|
||||
const clockConfigs: ClockConfig[] = [
|
||||
{
|
||||
label: 'NYC',
|
||||
timeZone: 'America/New_York',
|
||||
},
|
||||
{
|
||||
label: 'UTC',
|
||||
timeZone: 'UTC',
|
||||
},
|
||||
{
|
||||
label: 'STO',
|
||||
timeZone: 'Europe/Stockholm',
|
||||
},
|
||||
{
|
||||
label: 'TYO',
|
||||
timeZone: 'Asia/Tokyo',
|
||||
},
|
||||
];
|
||||
|
||||
export const HomePage = () => (
|
||||
<Page themeId="home">
|
||||
<Header title={<WelcomeTitle />} pageTitleOverride="Home">
|
||||
<HomepageTimer />
|
||||
<HeaderWorldClock clockConfigs={clockConfigs} />
|
||||
</Header>
|
||||
<Content>
|
||||
<Grid container spacing={3}>
|
||||
|
||||
@@ -569,7 +569,7 @@ export function HelpIcon(props: IconComponentProps): JSX.Element;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "HomepageTimer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
// @public @deprecated
|
||||
export function HomepageTimer(_props: {}): JSX.Element | null;
|
||||
|
||||
// Warning: (ae-forgotten-export) The symbol "Props" needs to be exported by the entry point index.d.ts
|
||||
|
||||
@@ -67,6 +67,10 @@ function getTimes(configApi: ConfigApi) {
|
||||
return clocks;
|
||||
}
|
||||
|
||||
/**
|
||||
* Please use the HeaderWorldClock in the home plugin
|
||||
* @deprecated in favor of the HeaderWorldClock which is found in the to home plugin
|
||||
*/
|
||||
export function HomepageTimer(_props: {}) {
|
||||
const configApi = useApi(configApiRef);
|
||||
|
||||
|
||||
@@ -10,6 +10,14 @@ import { Extension } from '@backstage/core-plugin-api';
|
||||
import { ReactNode } from 'react';
|
||||
import { RouteRef } from '@backstage/core-plugin-api';
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ClockConfig" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export type ClockConfig = {
|
||||
label: string;
|
||||
timeZone: string;
|
||||
};
|
||||
|
||||
// Warning: (ae-missing-release-tag) "ComponentAccordion" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
@@ -76,6 +84,15 @@ export function createCardExtension<T>({
|
||||
} & T) => JSX.Element
|
||||
>;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "HeaderWorldClock" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
export const HeaderWorldClock: ({
|
||||
clockConfigs,
|
||||
}: {
|
||||
clockConfigs: ClockConfig[];
|
||||
}) => JSX.Element | null;
|
||||
|
||||
// Warning: (ae-missing-release-tag) "HomepageCompositionRoot" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal)
|
||||
//
|
||||
// @public (undocumented)
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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 { renderInTestApp } from '@backstage/test-utils';
|
||||
import { HeaderWorldClock, ClockConfig } from './HeaderWorldClock';
|
||||
import React from 'react';
|
||||
import { lightTheme } from '@backstage/theme';
|
||||
import { ThemeProvider } from '@material-ui/core';
|
||||
|
||||
describe('HeaderWorldClock with valid Time Zones', () => {
|
||||
it('displays Time Zones as expected', async () => {
|
||||
const clockConfigs: ClockConfig[] = [
|
||||
{
|
||||
label: 'NYC',
|
||||
timeZone: 'America/New_York',
|
||||
},
|
||||
{
|
||||
label: 'UTC',
|
||||
timeZone: 'UTC',
|
||||
},
|
||||
{
|
||||
label: 'STO',
|
||||
timeZone: 'Europe/Stockholm',
|
||||
},
|
||||
{
|
||||
label: 'TYO',
|
||||
timeZone: 'Asia/Tokyo',
|
||||
},
|
||||
];
|
||||
|
||||
const rendered = await renderInTestApp(
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<HeaderWorldClock clockConfigs={clockConfigs} />
|
||||
</ThemeProvider>,
|
||||
);
|
||||
|
||||
expect(rendered.getByText('NYC')).toBeInTheDocument();
|
||||
expect(rendered.getByText('UTC')).toBeInTheDocument();
|
||||
expect(rendered.getByText('STO')).toBeInTheDocument();
|
||||
expect(rendered.getByText('TYO')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
|
||||
describe('HeaderWorldClock with no Time Zones provided', () => {
|
||||
it('should not appear in output', async () => {
|
||||
const clockConfigs: ClockConfig[] = [];
|
||||
|
||||
const rendered = await renderInTestApp(
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<HeaderWorldClock clockConfigs={clockConfigs} />
|
||||
</ThemeProvider>,
|
||||
);
|
||||
|
||||
expect(rendered.container).toBeEmptyDOMElement();
|
||||
});
|
||||
});
|
||||
|
||||
describe('HeaderWorldClock with invalid Time Zone', () => {
|
||||
it('uses GMT as fallback Time Zone', async () => {
|
||||
const clockConfigs: ClockConfig[] = [
|
||||
{
|
||||
label: 'New York',
|
||||
timeZone: 'America/New_Pork',
|
||||
},
|
||||
];
|
||||
|
||||
const rendered = await renderInTestApp(
|
||||
<ThemeProvider theme={lightTheme}>
|
||||
<HeaderWorldClock clockConfigs={clockConfigs} />
|
||||
</ThemeProvider>,
|
||||
);
|
||||
|
||||
expect(rendered.getByText('GMT')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 2020 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 React from 'react';
|
||||
import { HeaderLabel } from '@backstage/core-components';
|
||||
|
||||
const timeFormat: Intl.DateTimeFormatOptions = {
|
||||
hour: '2-digit',
|
||||
minute: '2-digit',
|
||||
};
|
||||
|
||||
type TimeObj = {
|
||||
time: string;
|
||||
label: string;
|
||||
};
|
||||
|
||||
export type ClockConfig = {
|
||||
label: string;
|
||||
timeZone: string;
|
||||
};
|
||||
|
||||
function getTimes(clockConfigs: ClockConfig[]) {
|
||||
const d = new Date();
|
||||
const lang = window.navigator.language;
|
||||
|
||||
const clocks: TimeObj[] = [];
|
||||
|
||||
if (!clockConfigs) {
|
||||
return clocks;
|
||||
}
|
||||
|
||||
for (const clockConfig of clockConfigs) {
|
||||
let label = clockConfig.label;
|
||||
|
||||
const options: Intl.DateTimeFormatOptions = {
|
||||
timeZone: clockConfig.timeZone,
|
||||
...timeFormat,
|
||||
};
|
||||
|
||||
try {
|
||||
new Date().toLocaleString(lang, options);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
`The timezone ${options.timeZone} is invalid. Defaulting to GMT`,
|
||||
);
|
||||
options.timeZone = 'GMT';
|
||||
label = 'GMT';
|
||||
}
|
||||
|
||||
const time = d.toLocaleTimeString(lang, options);
|
||||
clocks.push({ time, label });
|
||||
}
|
||||
|
||||
return clocks;
|
||||
}
|
||||
|
||||
export const HeaderWorldClock = ({
|
||||
clockConfigs,
|
||||
}: {
|
||||
clockConfigs: ClockConfig[];
|
||||
}) => {
|
||||
const defaultTimes: TimeObj[] = [];
|
||||
const [clocks, setTimes] = React.useState(defaultTimes);
|
||||
|
||||
React.useEffect(() => {
|
||||
setTimes(getTimes(clockConfigs));
|
||||
|
||||
const intervalId = setInterval(() => {
|
||||
setTimes(getTimes(clockConfigs));
|
||||
}, 1000);
|
||||
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
}, [clockConfigs]);
|
||||
|
||||
if (clocks.length !== 0) {
|
||||
return (
|
||||
<>
|
||||
{clocks.map(clock => (
|
||||
<HeaderLabel
|
||||
label={clock.label}
|
||||
value={clock.time}
|
||||
key={clock.label}
|
||||
/>
|
||||
))}
|
||||
</>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* Copyright 2020 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.
|
||||
*/
|
||||
export { HeaderWorldClock } from './HeaderWorldClock';
|
||||
export type { ClockConfig } from './HeaderWorldClock';
|
||||
@@ -16,3 +16,5 @@
|
||||
|
||||
export { HomepageCompositionRoot } from './HomepageCompositionRoot';
|
||||
export { SettingsModal } from './SettingsModal';
|
||||
export { HeaderWorldClock } from './HeaderWorldClock';
|
||||
export type { ClockConfig } from './HeaderWorldClock';
|
||||
|
||||
@@ -29,5 +29,6 @@ export {
|
||||
ComponentTab,
|
||||
WelcomeTitle,
|
||||
} from './plugin';
|
||||
export { SettingsModal } from './components';
|
||||
export { SettingsModal, HeaderWorldClock } from './components';
|
||||
export type { ClockConfig } from './components';
|
||||
export { createCardExtension } from './extensions';
|
||||
|
||||
Reference in New Issue
Block a user