+
+ Action Output
+
+
+
+ Action Input
+
+
+
+
+
+
+
+ );
+};
+
+export const ExecutionPanel = ({ id }: { id: string }) => {
+ const st2 = useApi(stackStormApiRef);
+
+ const { value, loading, error } = useAsync(async (): Promise => {
+ const data = await st2.getExecution(id);
+ return data;
+ }, []);
+
+ if (loading) {
+ return ;
+ } else if (error) {
+ return {error.message};
+ }
+
+ return ;
+};
diff --git a/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx
new file mode 100644
index 0000000000..4dbd64399f
--- /dev/null
+++ b/plugins/stackstorm/src/components/ExecutionsTable/ExecutionsTable.tsx
@@ -0,0 +1,130 @@
+/*
+ * Copyright 2023 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, { useEffect, useState } from 'react';
+import { Link, Table, TableColumn } from '@backstage/core-components';
+import { useApi, configApiRef, errorApiRef } from '@backstage/core-plugin-api';
+import { Execution, stackStormApiRef } from '../../api';
+import { Status } from './Status';
+import { ExecutionPanel } from './ExecutionPanel';
+
+type DenseTableProps = {
+ executions: Execution[];
+ loading: boolean;
+ page: number;
+ pageSize: number;
+ onPageChange: (page: number) => void;
+ onRowsPerPageChange: (rows: number) => void;
+};
+
+export const DenseTable = ({
+ executions,
+ loading,
+ page,
+ pageSize,
+ onPageChange,
+ onRowsPerPageChange,
+}: DenseTableProps) => {
+ const config = useApi(configApiRef);
+
+ const columns: TableColumn[] = [
+ {
+ title: 'Status',
+ field: 'status',
+ render: e => ,
+ },
+ {
+ title: 'Time',
+ field: 'start_timestamp',
+ render: e => `${new Date(e.start_timestamp).toUTCString()}`,
+ },
+ { title: 'Name', field: 'action.ref' },
+ {
+ title: 'Execution ID',
+ field: 'id',
+ render: e => (
+
+ {e.id}
+
+ ),
+ },
+ ];
+
+ const count =
+ pageSize > executions.length
+ ? (page + 1) * pageSize + executions.length - pageSize
+ : (page + 1) * pageSize + 1;
+
+ return (
+
{
+ return ;
+ }}
+ />
+ );
+};
+
+export const ExecutionsTable = () => {
+ const st2 = useApi(stackStormApiRef);
+ const errorApi = useApi(errorApiRef);
+ const [page, setPage] = useState(0);
+ const [rowsPerPage, setRowsPerPage] = useState(10);
+ const [data, setData] = useState([]);
+ const [loading, setLoading] = useState(false);
+
+ useEffect(() => {
+ const getData = async () => {
+ setLoading(true);
+ await st2
+ .getExecutions(rowsPerPage, page * rowsPerPage)
+ .then(d => {
+ setData(d);
+ })
+ .catch(err => {
+ errorApi.post(err);
+ });
+ setLoading(false);
+ };
+ getData();
+ }, [errorApi, page, rowsPerPage, st2]);
+
+ return (
+
+ );
+};
diff --git a/plugins/stackstorm/src/components/ExecutionsTable/Status.tsx b/plugins/stackstorm/src/components/ExecutionsTable/Status.tsx
new file mode 100644
index 0000000000..99a94df2c8
--- /dev/null
+++ b/plugins/stackstorm/src/components/ExecutionsTable/Status.tsx
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2023 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 {
+ StatusOK,
+ StatusError,
+ StatusRunning,
+ StatusWarning,
+} from '@backstage/core-components';
+import React from 'react';
+
+export const Status = ({ status }: { status: string | undefined }) => {
+ if (status === undefined) return null;
+ const st = status.toLocaleLowerCase('en-US');
+ switch (status) {
+ case 'succeeded':
+ case 'enabled':
+ case 'complete':
+ return (
+ <>
+ {st}
+ >
+ );
+ case 'scheduled':
+ case 'running':
+ return (
+ <>
+ {st}
+ >
+ );
+ case 'failed':
+ case 'error':
+ return (
+ <>
+ {st}
+ >
+ );
+ default:
+ return (
+ <>
+ {st}
+ >
+ );
+ }
+};
diff --git a/plugins/stackstorm/src/components/ExecutionsTable/index.ts b/plugins/stackstorm/src/components/ExecutionsTable/index.ts
new file mode 100644
index 0000000000..402d8e557d
--- /dev/null
+++ b/plugins/stackstorm/src/components/ExecutionsTable/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2023 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 { ExecutionsTable } from './ExecutionsTable';
diff --git a/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx b/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx
new file mode 100644
index 0000000000..b150aeec4d
--- /dev/null
+++ b/plugins/stackstorm/src/components/PacksTable/PacksTable.tsx
@@ -0,0 +1,59 @@
+/*
+ * Copyright 2023 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 { Progress, Table, TableColumn } from '@backstage/core-components';
+import { Alert } from '@material-ui/lab';
+import useAsync from 'react-use/lib/useAsync';
+import { useApi } from '@backstage/core-plugin-api';
+import { Pack, stackStormApiRef } from '../../api';
+
+type DenseTableProps = {
+ packs: Pack[];
+};
+
+export const DenseTable = ({ packs }: DenseTableProps) => {
+ const columns: TableColumn[] = [
+ { title: 'Name', field: 'ref' },
+ { title: 'Description', field: 'description' },
+ { title: 'Version', field: 'version' },
+ ];
+
+ return (
+
+ );
+};
+
+export const PacksTable = () => {
+ const st2 = useApi(stackStormApiRef);
+
+ const { value, loading, error } = useAsync(async (): Promise => {
+ const data = await st2.getPacks();
+ return data;
+ }, []);
+
+ if (loading) {
+ return ;
+ } else if (error) {
+ return {error.message};
+ }
+
+ return ;
+};
diff --git a/plugins/stackstorm/src/components/PacksTable/index.ts b/plugins/stackstorm/src/components/PacksTable/index.ts
new file mode 100644
index 0000000000..378e32a5d5
--- /dev/null
+++ b/plugins/stackstorm/src/components/PacksTable/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2023 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 { PacksTable } from './PacksTable';
diff --git a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx
new file mode 100644
index 0000000000..6249fa71e8
--- /dev/null
+++ b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.test.tsx
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2023 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 { StackStormHome } from './StackStormHome';
+import { screen } from '@testing-library/react';
+import { renderInTestApp, TestApiProvider } from '@backstage/test-utils';
+import { StackStormApi, stackStormApiRef } from '../../api';
+
+describe('StackStormHome', () => {
+ const mockApi: jest.Mocked = {
+ getExecutions: jest.fn().mockResolvedValue([]),
+ getExecution: jest.fn().mockResolvedValue({}),
+ getPacks: jest.fn().mockResolvedValue([]),
+ getActions: jest.fn().mockResolvedValue([]),
+ } as any;
+
+ it('should render', async () => {
+ await renderInTestApp(
+
+
+ ,
+ );
+ expect(screen.getByText('Welcome to StackStorm!')).toBeInTheDocument();
+ });
+});
diff --git a/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx
new file mode 100644
index 0000000000..a059505c2b
--- /dev/null
+++ b/plugins/stackstorm/src/components/StackStormHome/StackStormHome.tsx
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2023 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 { Grid, IconButton } from '@material-ui/core';
+import {
+ Header,
+ Page,
+ HeaderLabel,
+ TabbedLayout,
+ Content,
+} from '@backstage/core-components';
+import LibraryBooks from '@material-ui/icons/LibraryBooks';
+import { ExecutionsTable } from '../ExecutionsTable';
+import { PacksTable } from '../PacksTable/PacksTable';
+import { ActionsList } from '../ActionsList';
+
+export const StackStormHome = () => (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+);
diff --git a/plugins/stackstorm/src/components/StackStormHome/index.ts b/plugins/stackstorm/src/components/StackStormHome/index.ts
new file mode 100644
index 0000000000..27c6db48ab
--- /dev/null
+++ b/plugins/stackstorm/src/components/StackStormHome/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2023 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 { StackStormHome } from './StackStormHome';
diff --git a/plugins/stackstorm/src/index.ts b/plugins/stackstorm/src/index.ts
new file mode 100644
index 0000000000..aff9e2d78a
--- /dev/null
+++ b/plugins/stackstorm/src/index.ts
@@ -0,0 +1,16 @@
+/*
+ * Copyright 2023 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 { stackstormPlugin, StackstormPage } from './plugin';
diff --git a/plugins/stackstorm/src/plugin.test.ts b/plugins/stackstorm/src/plugin.test.ts
new file mode 100644
index 0000000000..9ef2f438c1
--- /dev/null
+++ b/plugins/stackstorm/src/plugin.test.ts
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2023 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 { stackstormPlugin } from './plugin';
+
+describe('stackstorm', () => {
+ it('should export plugin', () => {
+ expect(stackstormPlugin).toBeDefined();
+ });
+});
diff --git a/plugins/stackstorm/src/plugin.ts b/plugins/stackstorm/src/plugin.ts
new file mode 100644
index 0000000000..012c78372b
--- /dev/null
+++ b/plugins/stackstorm/src/plugin.ts
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2023 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 {
+ createApiFactory,
+ createPlugin,
+ createRoutableExtension,
+ discoveryApiRef,
+ identityApiRef,
+} from '@backstage/core-plugin-api';
+import { stackStormApiRef, StackStormClient } from './api';
+
+import { rootRouteRef } from './routes';
+
+export const stackstormPlugin = createPlugin({
+ id: 'stackstorm',
+ apis: [
+ createApiFactory({
+ api: stackStormApiRef,
+ deps: {
+ discoveryApi: discoveryApiRef,
+ identityApi: identityApiRef,
+ },
+ factory: ({ discoveryApi, identityApi }) =>
+ new StackStormClient({
+ discoveryApi,
+ identityApi,
+ }),
+ }),
+ ],
+ routes: {
+ root: rootRouteRef,
+ },
+});
+
+export const StackstormPage = stackstormPlugin.provide(
+ createRoutableExtension({
+ name: 'StackstormPage',
+ component: () =>
+ import('./components/StackStormHome').then(m => m.StackStormHome),
+ mountPoint: rootRouteRef,
+ }),
+);
diff --git a/plugins/stackstorm/src/routes.ts b/plugins/stackstorm/src/routes.ts
new file mode 100644
index 0000000000..90cf7760bc
--- /dev/null
+++ b/plugins/stackstorm/src/routes.ts
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2023 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({
+ id: 'stackstorm',
+});
diff --git a/plugins/stackstorm/src/setupTests.ts b/plugins/stackstorm/src/setupTests.ts
new file mode 100644
index 0000000000..73dd8dce47
--- /dev/null
+++ b/plugins/stackstorm/src/setupTests.ts
@@ -0,0 +1,17 @@
+/*
+ * Copyright 2023 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';
diff --git a/yarn.lock b/yarn.lock
index 4e56cb9839..5c8cdcad98 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -7955,6 +7955,32 @@ __metadata:
languageName: unknown
linkType: soft
+"@backstage/plugin-stackstorm@workspace:^, @backstage/plugin-stackstorm@workspace:plugins/stackstorm":
+ version: 0.0.0-use.local
+ resolution: "@backstage/plugin-stackstorm@workspace:plugins/stackstorm"
+ dependencies:
+ "@backstage/cli": "workspace:^"
+ "@backstage/core-app-api": "workspace:^"
+ "@backstage/core-components": "workspace:^"
+ "@backstage/core-plugin-api": "workspace:^"
+ "@backstage/dev-utils": "workspace:^"
+ "@backstage/test-utils": "workspace:^"
+ "@backstage/theme": "workspace:^"
+ "@material-ui/core": ^4.12.2
+ "@material-ui/icons": ^4.9.1
+ "@material-ui/lab": ^4.0.0-alpha.57
+ "@testing-library/jest-dom": ^5.10.1
+ "@testing-library/react": ^12.1.3
+ "@testing-library/user-event": ^14.0.0
+ "@types/node": "*"
+ cross-fetch: ^3.1.5
+ msw: ^0.49.0
+ react-use: ^17.2.4
+ peerDependencies:
+ react: ^16.13.1 || ^17.0.0
+ languageName: unknown
+ linkType: soft
+
"@backstage/plugin-tech-insights-backend-module-jsonfc@workspace:^, @backstage/plugin-tech-insights-backend-module-jsonfc@workspace:plugins/tech-insights-backend-module-jsonfc":
version: 0.0.0-use.local
resolution: "@backstage/plugin-tech-insights-backend-module-jsonfc@workspace:plugins/tech-insights-backend-module-jsonfc"
@@ -22492,6 +22518,7 @@ __metadata:
"@backstage/plugin-sentry": "workspace:^"
"@backstage/plugin-shortcuts": "workspace:^"
"@backstage/plugin-stack-overflow": "workspace:^"
+ "@backstage/plugin-stackstorm": "workspace:^"
"@backstage/plugin-tech-insights": "workspace:^"
"@backstage/plugin-tech-radar": "workspace:^"
"@backstage/plugin-techdocs": "workspace:^"