diff --git a/plugins/circleci/src/api/index.ts b/plugins/circleci/src/api/index.ts index afbd74f28f..d1eabbe2d6 100644 --- a/plugins/circleci/src/api/index.ts +++ b/plugins/circleci/src/api/index.ts @@ -31,6 +31,7 @@ export const circleCIApiRef = new ApiRef({ }); export class CircleCIApi { + private token: string = ''; options: Partial; @@ -104,4 +105,8 @@ export class CircleCIApi { async getUser() { return this.api.me(); } + + async getBuild(buildId: string) { + return this.api.build(parseInt(buildId, 10)); + } } diff --git a/plugins/circleci/src/components/ActionOutput/ActionOutput.tsx b/plugins/circleci/src/components/ActionOutput/ActionOutput.tsx new file mode 100644 index 0000000000..b8d1564040 --- /dev/null +++ b/plugins/circleci/src/components/ActionOutput/ActionOutput.tsx @@ -0,0 +1,47 @@ +import React, { useEffect, useState, FC } from 'react'; +import { + ExpansionPanel, + ExpansionPanelSummary, + Typography, + ExpansionPanelDetails, +} from '@material-ui/core'; + +import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; +import { BuildStepAction } from 'circleci-api'; + +export const ActionOutput: FC<{ + url: string; + name: string; + action: BuildStepAction; +}> = ({ url, name }) => { + const [messages, setMessages] = useState([]); + useEffect(() => { + fetch(url) + .then(res => res.json()) + .then(actionOutput => { + actionOutput && + setMessages( + actionOutput.map(({ message }: { message: string }) => message), + ); + }); + }, [url]); + console.log(messages); + return ( + + } + aria-controls="panel1a-content" + id="panel1a-header" + > + {name} + + + {messages.length === 0 + ? 'Nothing here...' + : messages.map(message => ( +

{message}

+ ))} +
+
+ ); +}; diff --git a/plugins/circleci/src/components/ActionOutput/index.ts b/plugins/circleci/src/components/ActionOutput/index.ts new file mode 100644 index 0000000000..1e4fd5dfac --- /dev/null +++ b/plugins/circleci/src/components/ActionOutput/index.ts @@ -0,0 +1 @@ +export { ActionOutput } from './ActionOutput'; diff --git a/plugins/circleci/src/components/CITable/CITable.tsx b/plugins/circleci/src/components/CITable/CITable.tsx index 5efb0edb9f..465fae24e0 100644 --- a/plugins/circleci/src/components/CITable/CITable.tsx +++ b/plugins/circleci/src/components/CITable/CITable.tsx @@ -9,10 +9,10 @@ import { TableHead, TableContainer, TableRow, - Link, CircularProgress, } from '@material-ui/core'; import { Replay as RetryIcon } from '@material-ui/icons'; +import { Link } from 'react-router-dom'; import { StatusFailed, StatusOK, @@ -94,7 +94,7 @@ export const CITable: FC<{ {build.id} - + {build.buildName} diff --git a/plugins/circleci/src/components/CircleCIPage/CircleCIPage.tsx b/plugins/circleci/src/components/CircleCIPage/CircleCIPage.tsx deleted file mode 100644 index 32812b1ade..0000000000 --- a/plugins/circleci/src/components/CircleCIPage/CircleCIPage.tsx +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2020 Spotify AB - * - * 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, { FC } from 'react'; -import { Route } from 'react-router'; -import { Link as RouterLink } from 'react-router-dom'; -import { Grid, Button } from '@material-ui/core'; -import { Settings as SettingsIcon } from '@material-ui/icons'; -import { - InfoCard, - Header, - Page, - pageTheme, - Content, - ContentHeader, - HeaderLabel, - SupportButton, -} from '@backstage/core'; -import { CircleCIFetch } from '../CircleCIFetch'; -import { SettingsPage } from '../SettingsPage'; -export const CircleCIPage: FC<{}> = () => { - return ( - <> - - -
- - -
- - - - - A description of your plugin goes here. - - - - - - - - - - -
- - ); -}; - -export default CircleCIPage; diff --git a/plugins/circleci/src/components/CircleCIPage/index.ts b/plugins/circleci/src/components/CircleCIPage/index.ts deleted file mode 100644 index 188ed6d61f..0000000000 --- a/plugins/circleci/src/components/CircleCIPage/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { CircleCIPage } from './CircleCIPage'; diff --git a/plugins/circleci/src/components/Layout/Layout.tsx b/plugins/circleci/src/components/Layout/Layout.tsx new file mode 100644 index 0000000000..fe82bf90e8 --- /dev/null +++ b/plugins/circleci/src/components/Layout/Layout.tsx @@ -0,0 +1,12 @@ +import React from 'react'; +import { Header, Page, pageTheme, HeaderLabel } from '@backstage/core'; + +export const Layout: React.FC = ({ children }) => ( + +
+ + +
+ {children} +
+); diff --git a/plugins/circleci/src/components/Layout/index.ts b/plugins/circleci/src/components/Layout/index.ts new file mode 100644 index 0000000000..9877e7f4ae --- /dev/null +++ b/plugins/circleci/src/components/Layout/index.ts @@ -0,0 +1 @@ +export * from './Layout'; diff --git a/plugins/circleci/src/components/PluginHeader/PluginHeader.tsx b/plugins/circleci/src/components/PluginHeader/PluginHeader.tsx new file mode 100644 index 0000000000..f725a979a9 --- /dev/null +++ b/plugins/circleci/src/components/PluginHeader/PluginHeader.tsx @@ -0,0 +1,18 @@ +import React from 'react'; +import { Link as RouterLink } from 'react-router-dom'; +import { ContentHeader, SupportButton } from '@backstage/core'; +import { Button } from '@material-ui/core'; +import { Settings as SettingsIcon } from '@material-ui/icons'; + +export const PluginHeader = () => ( + + + A description of your plugin goes here. + +); diff --git a/plugins/circleci/src/components/PluginHeader/index.ts b/plugins/circleci/src/components/PluginHeader/index.ts new file mode 100644 index 0000000000..e9231f1318 --- /dev/null +++ b/plugins/circleci/src/components/PluginHeader/index.ts @@ -0,0 +1 @@ +export * from './PluginHeader'; diff --git a/plugins/circleci/src/pages/BuildsPage/BuildsPage.tsx b/plugins/circleci/src/pages/BuildsPage/BuildsPage.tsx new file mode 100644 index 0000000000..98e634d4c0 --- /dev/null +++ b/plugins/circleci/src/pages/BuildsPage/BuildsPage.tsx @@ -0,0 +1,36 @@ +import React, { FC } from 'react'; +import { Link as RouterLink } from 'react-router-dom'; +import { + Content, + ContentHeader, + SupportButton, + InfoCard, +} from '@backstage/core'; +import { Button, Grid } from '@material-ui/core'; +import { CircleCIFetch } from 'components/CircleCIFetch'; +import { Settings as SettingsIcon } from '@material-ui/icons'; +import { Layout } from 'components/Layout'; + +export const BuildsPage: FC<{}> = () => ( + + + + + A description of your plugin goes here. + + + + + + + + + + +); diff --git a/plugins/circleci/src/pages/BuildsPage/index.ts b/plugins/circleci/src/pages/BuildsPage/index.ts new file mode 100644 index 0000000000..94086cd569 --- /dev/null +++ b/plugins/circleci/src/pages/BuildsPage/index.ts @@ -0,0 +1 @@ +export * from './BuildsPage'; diff --git a/plugins/circleci/src/pages/DetailedViewPage/DetailedViewPage.tsx b/plugins/circleci/src/pages/DetailedViewPage/DetailedViewPage.tsx new file mode 100644 index 0000000000..3d5d7b575b --- /dev/null +++ b/plugins/circleci/src/pages/DetailedViewPage/DetailedViewPage.tsx @@ -0,0 +1,78 @@ +import React, { FC } from 'react'; +import { Content, InfoCard, useApi } from '@backstage/core'; +import { Grid, Box } from '@material-ui/core'; +import { PluginHeader } from 'components/PluginHeader'; +import { BuildWithSteps, BuildStepAction } from 'circleci-api'; +import { circleCIApiRef } from 'api'; +import { useParams } from 'react-router-dom'; +import { ActionOutput } from '../../components/ActionOutput/ActionOutput'; +import { Layout } from 'components/Layout'; + +export const DetailedViewPage: FC<{}> = () => { + let { buildId = '' } = useParams(); + + const [authed, setAuthed] = React.useState(false); + const [build, setBuild] = React.useState(null); + const api = useApi(circleCIApiRef); + + React.useEffect(() => { + const getBuildAsync = async () => { + if (!authed) { + await api.restorePersistedSettings(); + await api + .validateToken() + .then(() => { + setAuthed(true); + }) + .catch(() => setAuthed(false)); + } + api.getBuild(buildId).then(setBuild); + }; + getBuildAsync(); + }, [authed, buildId]); + return ( + + + + {!api.authed ? ( +
Not authenticated
+ ) : ( + + + + + + + + )} +
+
+ ); +}; + +const BuildsList: FC<{ build: BuildWithSteps | null }> = ({ build }) => ( + + {build && + build.steps && + build.steps.map( + ({ name, actions }: { name: string; actions: BuildStepAction[] }) => ( + + ), + )} + +); + +const ActionsList: FC<{ actions: BuildStepAction[]; name: string }> = ({ + actions, + name, +}) => ( + + {actions.map((action: BuildStepAction) => ( + + ))} + +); diff --git a/plugins/circleci/src/pages/DetailedViewPage/index.ts b/plugins/circleci/src/pages/DetailedViewPage/index.ts new file mode 100644 index 0000000000..578eec4e64 --- /dev/null +++ b/plugins/circleci/src/pages/DetailedViewPage/index.ts @@ -0,0 +1 @@ +export * from './DetailedViewPage'; diff --git a/plugins/circleci/src/components/SettingsPage/SettingsPage.tsx b/plugins/circleci/src/pages/SettingsPage/SettingsPage.tsx similarity index 90% rename from plugins/circleci/src/components/SettingsPage/SettingsPage.tsx rename to plugins/circleci/src/pages/SettingsPage/SettingsPage.tsx index 8a0ba78118..af380509d1 100644 --- a/plugins/circleci/src/components/SettingsPage/SettingsPage.tsx +++ b/plugins/circleci/src/pages/SettingsPage/SettingsPage.tsx @@ -4,16 +4,13 @@ import { circleCIApiRef } from 'api'; import { InfoCard, useApi, - Header, - Page, - pageTheme, Content, ContentHeader, - HeaderLabel, SupportButton, } from '@backstage/core'; import { ProjectInput } from 'components/ProjectInput/ProjectInput'; import { Link as RouterLink } from 'react-router-dom'; +import { Layout } from 'components/Layout'; export const SettingsPage = () => { const api = useApi(circleCIApiRef); @@ -29,11 +26,7 @@ export const SettingsPage = () => { }, []); return ( - -
- - -
+