@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
import {
|
||||
Accordion,
|
||||
AccordionDetails,
|
||||
AccordionSummary,
|
||||
Typography,
|
||||
IconButton,
|
||||
Theme,
|
||||
} from '@material-ui/core';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
||||
import SettingsIcon from '@material-ui/icons/Settings';
|
||||
|
||||
import { SettingsModal } from '../components';
|
||||
|
||||
const useStyles = makeStyles((theme: Theme) => ({
|
||||
settingsIconButton: {
|
||||
padding: theme.spacing(0, 1, 0, 0),
|
||||
},
|
||||
}));
|
||||
|
||||
export const ComponentAccordion = ({
|
||||
title,
|
||||
Content,
|
||||
Actions,
|
||||
Settings,
|
||||
ContextProvider,
|
||||
...childProps
|
||||
}: {
|
||||
title: string;
|
||||
Content: () => JSX.Element;
|
||||
Actions?: () => JSX.Element;
|
||||
Settings?: () => JSX.Element;
|
||||
ContextProvider?: (props: any) => JSX.Element;
|
||||
}) => {
|
||||
const classes = useStyles();
|
||||
const [settingsIsExpanded, setSettingsIsExpanded] = React.useState(false);
|
||||
const [isExpanded, setIsExpanded] = React.useState(false);
|
||||
|
||||
const handleOpenSettings = (e: any) => {
|
||||
e.stopPropagation();
|
||||
setSettingsIsExpanded(prevState => !prevState);
|
||||
};
|
||||
|
||||
const innerContent = (
|
||||
<>
|
||||
{Settings && (
|
||||
<SettingsModal
|
||||
open={settingsIsExpanded}
|
||||
close={() => setSettingsIsExpanded(false)}
|
||||
componentName={title}
|
||||
>
|
||||
<Settings />
|
||||
</SettingsModal>
|
||||
)}
|
||||
<Accordion
|
||||
expanded={isExpanded}
|
||||
onChange={(_e: any, expanded: boolean) => setIsExpanded(expanded)}
|
||||
>
|
||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||
{Settings && (
|
||||
<IconButton
|
||||
onClick={handleOpenSettings}
|
||||
className={classes.settingsIconButton}
|
||||
>
|
||||
<SettingsIcon />
|
||||
</IconButton>
|
||||
)}
|
||||
<Typography>{title}</Typography>
|
||||
</AccordionSummary>
|
||||
<AccordionDetails>
|
||||
<div>
|
||||
<Content />
|
||||
{Actions && <Actions />}
|
||||
</div>
|
||||
</AccordionDetails>
|
||||
</Accordion>
|
||||
</>
|
||||
);
|
||||
|
||||
return ContextProvider ? (
|
||||
<ContextProvider {...childProps}>{innerContent}</ContextProvider>
|
||||
) : (
|
||||
innerContent
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
export const ComponentTab = ({
|
||||
title,
|
||||
Content,
|
||||
ContextProvider,
|
||||
...childProps
|
||||
}: {
|
||||
title: string;
|
||||
Content: () => JSX.Element;
|
||||
ContextProvider?: (props: any) => JSX.Element;
|
||||
}) => {
|
||||
return ContextProvider ? (
|
||||
<ContextProvider {...childProps}>
|
||||
<Content />
|
||||
</ContextProvider>
|
||||
) : (
|
||||
<Content />
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
import { Tabs, Tab } from '@material-ui/core';
|
||||
import { InfoCard } from '@backstage/core-components';
|
||||
|
||||
type TabType = {
|
||||
label: string;
|
||||
Component: () => JSX.Element;
|
||||
};
|
||||
|
||||
export const ComponentTabs = ({
|
||||
title,
|
||||
tabs,
|
||||
}: {
|
||||
title: string;
|
||||
tabs: TabType[];
|
||||
}) => {
|
||||
const [value, setValue] = React.useState(0);
|
||||
|
||||
const handleChange = (_event: any, newValue: number) => {
|
||||
setValue(newValue);
|
||||
};
|
||||
|
||||
return (
|
||||
<InfoCard title={title}>
|
||||
<Tabs value={value} onChange={handleChange}>
|
||||
{tabs.map(t => (
|
||||
<Tab key={t.label} label={t.label} />
|
||||
))}
|
||||
</Tabs>
|
||||
{tabs.map(({ Component }, idx) => (
|
||||
<div {...(idx === value ? { style: { display: 'none' } } : {})}>
|
||||
<Component />
|
||||
</div>
|
||||
))}
|
||||
</InfoCard>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { ComponentTabs } from './ComponentTabs';
|
||||
export { ComponentTab } from './ComponentTab';
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { ComponentAccordion } from './ComponentAccordion';
|
||||
export { ComponentTabs, ComponentTab } from './ComponentTabs';
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 React, { ReactNode } from 'react';
|
||||
import { useOutlet } from 'react-router';
|
||||
import { Content, Header, Page } from '@backstage/core-components';
|
||||
|
||||
export const HomepageCompositionRoot = (props: {
|
||||
title?: string;
|
||||
children?: ReactNode;
|
||||
}) => {
|
||||
const outlet = useOutlet();
|
||||
const children = props.children ?? outlet;
|
||||
return (
|
||||
<Page themeId="home">
|
||||
<Header title={props.title ?? 'Home'} />
|
||||
<Content>{children}</Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
import {
|
||||
Button,
|
||||
Dialog,
|
||||
DialogActions,
|
||||
DialogContent,
|
||||
DialogTitle,
|
||||
} from '@material-ui/core';
|
||||
|
||||
export const SettingsModal = ({
|
||||
open,
|
||||
close,
|
||||
componentName,
|
||||
children,
|
||||
}: {
|
||||
open: boolean;
|
||||
close: Function;
|
||||
componentName: string;
|
||||
children: JSX.Element;
|
||||
}) => {
|
||||
return (
|
||||
<Dialog open={open} onClose={() => close()}>
|
||||
<DialogTitle>Settings - {componentName}</DialogTitle>
|
||||
<DialogContent>{children}</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={() => close()} color="primary" variant="contained">
|
||||
Close
|
||||
</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* 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 { HomepageCompositionRoot } from './HomepageCompositionRoot';
|
||||
export { SettingsModal } from './SettingsModal';
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* 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 React, { Suspense } from 'react';
|
||||
import { IconButton } from '@material-ui/core';
|
||||
import SettingsIcon from '@material-ui/icons/Settings';
|
||||
import { InfoCard } from '@backstage/core-components';
|
||||
import { SettingsModal } from './components';
|
||||
import { createReactExtension, useApp } from '@backstage/core-plugin-api';
|
||||
|
||||
export type ComponentRenderer = {
|
||||
Renderer?: (props: RendererProps) => JSX.Element;
|
||||
};
|
||||
|
||||
type ComponentParts = {
|
||||
Content: () => JSX.Element;
|
||||
Actions?: () => JSX.Element;
|
||||
Settings?: () => JSX.Element;
|
||||
ContextProvider?: (props: any) => JSX.Element;
|
||||
};
|
||||
|
||||
type RendererProps = { title: string } & ComponentParts;
|
||||
|
||||
export function createCardExtension<T>({
|
||||
title,
|
||||
components,
|
||||
}: {
|
||||
title: string;
|
||||
components: () => Promise<ComponentParts>;
|
||||
}) {
|
||||
return createReactExtension({
|
||||
component: {
|
||||
lazy: () =>
|
||||
components().then(({ Content, Actions, Settings, ContextProvider }) => {
|
||||
const CardExtension = ({
|
||||
Renderer,
|
||||
title: overrideTitle,
|
||||
...childProps
|
||||
}: ComponentRenderer & { title?: string } & T) => {
|
||||
const app = useApp();
|
||||
const { Progress } = app.getComponents();
|
||||
const [settingsOpen, setSettingsOpen] = React.useState(false);
|
||||
|
||||
if (Renderer) {
|
||||
return (
|
||||
<Suspense fallback={<Progress />}>
|
||||
<Renderer
|
||||
title={overrideTitle || title}
|
||||
{...{
|
||||
Content,
|
||||
...(Actions ? { Actions } : {}),
|
||||
...(Settings ? { Settings } : {}),
|
||||
...(ContextProvider ? { ContextProvider } : {}),
|
||||
...childProps,
|
||||
}}
|
||||
/>
|
||||
</Suspense>
|
||||
);
|
||||
}
|
||||
|
||||
const cardProps = {
|
||||
title: overrideTitle ?? title,
|
||||
...(Settings
|
||||
? {
|
||||
action: (
|
||||
<IconButton onClick={() => setSettingsOpen(true)}>
|
||||
<SettingsIcon>Settings</SettingsIcon>
|
||||
</IconButton>
|
||||
),
|
||||
}
|
||||
: {}),
|
||||
...(Actions
|
||||
? {
|
||||
actions: <Actions />,
|
||||
}
|
||||
: {}),
|
||||
};
|
||||
|
||||
const innerContent = (
|
||||
<InfoCard {...cardProps}>
|
||||
{Settings && (
|
||||
<SettingsModal
|
||||
open={settingsOpen}
|
||||
componentName={title}
|
||||
close={() => setSettingsOpen(false)}
|
||||
>
|
||||
<Settings />
|
||||
</SettingsModal>
|
||||
)}
|
||||
<Content />
|
||||
</InfoCard>
|
||||
);
|
||||
|
||||
return (
|
||||
<Suspense fallback={<Progress />}>
|
||||
{ContextProvider ? (
|
||||
<ContextProvider {...childProps}>
|
||||
{innerContent}
|
||||
</ContextProvider>
|
||||
) : (
|
||||
innerContent
|
||||
)}
|
||||
</Suspense>
|
||||
);
|
||||
};
|
||||
return CardExtension;
|
||||
}),
|
||||
},
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
|
||||
import { Button } from '@material-ui/core';
|
||||
import { useRandomJoke } from './Context';
|
||||
|
||||
export const Actions = () => {
|
||||
const { rerollJoke } = useRandomJoke();
|
||||
return (
|
||||
<Button variant="contained" color="primary" onClick={() => rerollJoke()}>
|
||||
Reroll
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* 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 React from 'react';
|
||||
import { useRandomJoke } from './Context';
|
||||
|
||||
export const Content = () => {
|
||||
const { joke, loading } = useRandomJoke();
|
||||
|
||||
if (loading) return <p>Loading...</p>;
|
||||
|
||||
return (
|
||||
<div>
|
||||
<p>{joke.setup}</p>
|
||||
<p>{joke.punchline}</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* 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 React, { createContext } from 'react';
|
||||
|
||||
export type JokeType = 'any' | 'programming';
|
||||
|
||||
type Joke = {
|
||||
setup: string;
|
||||
punchline: string;
|
||||
};
|
||||
|
||||
type RandomJokeContextValue = {
|
||||
loading: boolean;
|
||||
joke: Joke;
|
||||
type: JokeType;
|
||||
rerollJoke: Function;
|
||||
handleChangeType: Function;
|
||||
};
|
||||
|
||||
const Context = createContext<RandomJokeContextValue | undefined>(undefined);
|
||||
|
||||
const getNewJoke = (type: string): Promise<Joke> =>
|
||||
fetch(
|
||||
`https://official-joke-api.appspot.com/jokes${
|
||||
type !== 'any' ? `/${type}` : ''
|
||||
}/random`,
|
||||
)
|
||||
.then(res => res.json())
|
||||
.then(data => (Array.isArray(data) ? data[0] : data));
|
||||
|
||||
export const ContextProvider = ({
|
||||
children,
|
||||
defaultCategory,
|
||||
}: {
|
||||
children: JSX.Element;
|
||||
defaultCategory?: JokeType;
|
||||
}) => {
|
||||
const [loading, setLoading] = React.useState(true);
|
||||
const [joke, setJoke] = React.useState<Joke>({
|
||||
setup: '',
|
||||
punchline: '',
|
||||
});
|
||||
const [type, setType] = React.useState<JokeType>(
|
||||
defaultCategory || ('programming' as JokeType),
|
||||
);
|
||||
|
||||
const rerollJoke = React.useCallback(() => {
|
||||
setLoading(true);
|
||||
getNewJoke(type).then(newJoke => setJoke(newJoke));
|
||||
}, [type]);
|
||||
|
||||
const handleChangeType = (newType: JokeType) => {
|
||||
setType(newType);
|
||||
};
|
||||
|
||||
React.useEffect(() => {
|
||||
setLoading(false);
|
||||
}, [joke]);
|
||||
|
||||
React.useEffect(() => {
|
||||
rerollJoke();
|
||||
}, [rerollJoke]);
|
||||
|
||||
const value: RandomJokeContextValue = {
|
||||
loading,
|
||||
joke,
|
||||
type,
|
||||
rerollJoke,
|
||||
handleChangeType,
|
||||
};
|
||||
|
||||
return <Context.Provider value={value}>{children}</Context.Provider>;
|
||||
};
|
||||
|
||||
export const useRandomJoke = () => {
|
||||
const value = React.useContext(Context);
|
||||
|
||||
if (value === undefined) {
|
||||
throw new Error('useRandomJoke must be used within a RandomJokeProvider');
|
||||
}
|
||||
|
||||
return value;
|
||||
};
|
||||
|
||||
export default Context;
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 {
|
||||
FormControl,
|
||||
FormLabel,
|
||||
RadioGroup,
|
||||
FormControlLabel,
|
||||
Radio,
|
||||
} from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { useRandomJoke, JokeType } from './Context';
|
||||
|
||||
export const Settings = () => {
|
||||
const { type, handleChangeType } = useRandomJoke();
|
||||
const JOKE_TYPES: JokeType[] = ['any' as JokeType, 'programming' as JokeType];
|
||||
return (
|
||||
<FormControl component="fieldset">
|
||||
<FormLabel component="legend">Joke Type</FormLabel>
|
||||
<RadioGroup
|
||||
aria-label="joke type"
|
||||
value={type}
|
||||
onChange={e => handleChangeType(e.target.value)}
|
||||
>
|
||||
{JOKE_TYPES.map(t => (
|
||||
<FormControlLabel
|
||||
key={t}
|
||||
value={t}
|
||||
control={<Radio />}
|
||||
label={`${t.slice(0, 1).toUpperCase()}${t.slice(1)}`}
|
||||
/>
|
||||
))}
|
||||
</RadioGroup>
|
||||
</FormControl>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export { Actions } from './Actions';
|
||||
export { Content } from './Content';
|
||||
export { Settings } from './Settings';
|
||||
export { ContextProvider } from './Context';
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
export {
|
||||
homePlugin,
|
||||
HomepageCompositionRoot,
|
||||
RandomJokeHomePageComponent,
|
||||
ComponentAccordion,
|
||||
ComponentTabs,
|
||||
ComponentTab,
|
||||
} from './plugin';
|
||||
export { SettingsModal } from './components';
|
||||
export { createCardExtension } from './extensions';
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* 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 { homePlugin } from './plugin';
|
||||
|
||||
describe('home', () => {
|
||||
it('should export plugin', () => {
|
||||
expect(homePlugin).toBeDefined();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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 {
|
||||
createComponentExtension,
|
||||
createPlugin,
|
||||
createRoutableExtension,
|
||||
} from '@backstage/core-plugin-api';
|
||||
import { createCardExtension } from './extensions';
|
||||
|
||||
import { rootRouteRef } from './routes';
|
||||
|
||||
export const homePlugin = createPlugin({
|
||||
id: 'home',
|
||||
routes: {
|
||||
root: rootRouteRef,
|
||||
},
|
||||
});
|
||||
|
||||
export const HomepageCompositionRoot = homePlugin.provide(
|
||||
createRoutableExtension({
|
||||
component: () =>
|
||||
import('./components').then(m => m.HomepageCompositionRoot),
|
||||
mountPoint: rootRouteRef,
|
||||
}),
|
||||
);
|
||||
|
||||
export const ComponentAccordion = homePlugin.provide(
|
||||
createComponentExtension({
|
||||
component: {
|
||||
lazy: () =>
|
||||
import('./componentRenderers').then(m => m.ComponentAccordion),
|
||||
},
|
||||
}),
|
||||
);
|
||||
export const ComponentTabs = homePlugin.provide(
|
||||
createComponentExtension({
|
||||
component: {
|
||||
lazy: () => import('./componentRenderers').then(m => m.ComponentTabs),
|
||||
},
|
||||
}),
|
||||
);
|
||||
export const ComponentTab = homePlugin.provide(
|
||||
createComponentExtension({
|
||||
component: {
|
||||
lazy: () => import('./componentRenderers').then(m => m.ComponentTab),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export const RandomJokeHomePageComponent = homePlugin.provide(
|
||||
createCardExtension<{ defaultCategory?: 'any' | 'programming' }>({
|
||||
title: 'Random Joke',
|
||||
components: () => import('./homePageComponents/RandomJoke'),
|
||||
}),
|
||||
);
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* 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 { createRouteRef } from '@backstage/core-plugin-api';
|
||||
|
||||
export const rootRouteRef = createRouteRef({
|
||||
title: 'home',
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
/*
|
||||
* 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 '@testing-library/jest-dom';
|
||||
import 'cross-fetch/polyfill';
|
||||
Reference in New Issue
Block a user