@backstage-community/plugin-lighthouse 0.4.20 → 0.4.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +16 -0
- package/dist/Router.esm.js +26 -0
- package/dist/Router.esm.js.map +1 -0
- package/dist/api.esm.js +8 -0
- package/dist/api.esm.js.map +1 -0
- package/dist/components/AuditList/AuditListForEntity.esm.js +43 -0
- package/dist/components/AuditList/AuditListForEntity.esm.js.map +1 -0
- package/dist/components/AuditList/AuditListTable.esm.js +92 -0
- package/dist/components/AuditList/AuditListTable.esm.js.map +1 -0
- package/dist/components/AuditList/index.esm.js +83 -0
- package/dist/components/AuditList/index.esm.js.map +1 -0
- package/dist/components/AuditStatusIcon/index.esm.js +11 -0
- package/dist/components/AuditStatusIcon/index.esm.js.map +1 -0
- package/dist/components/AuditView/index.esm.js +135 -0
- package/dist/components/AuditView/index.esm.js.map +1 -0
- package/dist/components/Cards/LastLighthouseAuditCard.esm.js +57 -0
- package/dist/components/Cards/LastLighthouseAuditCard.esm.js.map +1 -0
- package/dist/components/Cards/index.esm.js +2 -0
- package/dist/components/Cards/index.esm.js.map +1 -0
- package/dist/components/CreateAudit/index.esm.js +152 -0
- package/dist/components/CreateAudit/index.esm.js.map +1 -0
- package/dist/components/Intro/index.esm.js +130 -0
- package/dist/components/Intro/index.esm.js.map +1 -0
- package/dist/components/SupportButton/index.esm.js +9 -0
- package/dist/components/SupportButton/index.esm.js.map +1 -0
- package/dist/constants.esm.js +4 -0
- package/dist/constants.esm.js.map +1 -0
- package/dist/hooks/useWebsiteForEntity.esm.js +23 -0
- package/dist/hooks/useWebsiteForEntity.esm.js.map +1 -0
- package/dist/index.esm.js +4 -770
- package/dist/index.esm.js.map +1 -1
- package/dist/plugin.esm.js +55 -0
- package/dist/plugin.esm.js.map +1 -0
- package/dist/utils.esm.js +44 -0
- package/dist/utils.esm.js.map +1 -0
- package/package.json +17 -11
- package/dist/esm/index-DTZMI_cR.esm.js +0 -26
- package/dist/esm/index-DTZMI_cR.esm.js.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,21 @@
|
|
|
1
1
|
# @backstage-community/plugin-lighthouse
|
|
2
2
|
|
|
3
|
+
## 0.4.22
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 0ba8b43: Backstage version bump to v1.30.2
|
|
8
|
+
- Updated dependencies [0ba8b43]
|
|
9
|
+
- @backstage-community/plugin-lighthouse-common@0.1.8
|
|
10
|
+
|
|
11
|
+
## 0.4.21
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- e71dda0: version:bump to v1.29.1
|
|
16
|
+
- Updated dependencies [e71dda0]
|
|
17
|
+
- @backstage-community/plugin-lighthouse-common@0.1.7
|
|
18
|
+
|
|
3
19
|
## 0.4.20
|
|
4
20
|
|
|
5
21
|
### Patch Changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Routes, Route } from 'react-router-dom';
|
|
3
|
+
import { useEntity, MissingAnnotationEmptyState } from '@backstage/plugin-catalog-react';
|
|
4
|
+
import AuditList from './components/AuditList/index.esm.js';
|
|
5
|
+
import ConnectedAuditView, { AuditViewContent } from './components/AuditView/index.esm.js';
|
|
6
|
+
import CreateAudit, { CreateAuditContent } from './components/CreateAudit/index.esm.js';
|
|
7
|
+
import { LIGHTHOUSE_WEBSITE_URL_ANNOTATION } from './constants.esm.js';
|
|
8
|
+
import { AuditListForEntity } from './components/AuditList/AuditListForEntity.esm.js';
|
|
9
|
+
|
|
10
|
+
const isLighthouseAvailable = (entity) => Boolean(entity.metadata.annotations?.[LIGHTHOUSE_WEBSITE_URL_ANNOTATION]);
|
|
11
|
+
const Router = () => /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, { path: "/", element: /* @__PURE__ */ React.createElement(AuditList, null) }), /* @__PURE__ */ React.createElement(Route, { path: "/audit/:id", element: /* @__PURE__ */ React.createElement(ConnectedAuditView, null) }), /* @__PURE__ */ React.createElement(Route, { path: "/create-audit", element: /* @__PURE__ */ React.createElement(CreateAudit, null) }));
|
|
12
|
+
const EmbeddedRouter = () => {
|
|
13
|
+
const { entity } = useEntity();
|
|
14
|
+
if (!isLighthouseAvailable(entity)) {
|
|
15
|
+
return /* @__PURE__ */ React.createElement(
|
|
16
|
+
MissingAnnotationEmptyState,
|
|
17
|
+
{
|
|
18
|
+
annotation: LIGHTHOUSE_WEBSITE_URL_ANNOTATION
|
|
19
|
+
}
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
return /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, { path: "/", element: /* @__PURE__ */ React.createElement(AuditListForEntity, null) }), /* @__PURE__ */ React.createElement(Route, { path: "/audit/:id", element: /* @__PURE__ */ React.createElement(AuditViewContent, null) }), /* @__PURE__ */ React.createElement(Route, { path: "/create-audit", element: /* @__PURE__ */ React.createElement(CreateAuditContent, null) }));
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export { EmbeddedRouter, Router, isLighthouseAvailable };
|
|
26
|
+
//# sourceMappingURL=Router.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Router.esm.js","sources":["../src/Router.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { Route, Routes } from 'react-router-dom';\nimport {\n useEntity,\n MissingAnnotationEmptyState,\n} from '@backstage/plugin-catalog-react';\nimport AuditList from './components/AuditList';\nimport AuditView, { AuditViewContent } from './components/AuditView';\nimport CreateAudit, { CreateAuditContent } from './components/CreateAudit';\nimport { Entity } from '@backstage/catalog-model';\nimport { LIGHTHOUSE_WEBSITE_URL_ANNOTATION } from '../constants';\nimport { AuditListForEntity } from './components/AuditList/AuditListForEntity';\n\n/** @public */\nexport const isLighthouseAvailable = (entity: Entity) =>\n Boolean(entity.metadata.annotations?.[LIGHTHOUSE_WEBSITE_URL_ANNOTATION]);\n\n/** @public */\nexport const Router = () => (\n <Routes>\n <Route path=\"/\" element={<AuditList />} />\n <Route path=\"/audit/:id\" element={<AuditView />} />\n <Route path=\"/create-audit\" element={<CreateAudit />} />\n </Routes>\n);\n\n/** @public */\nexport const EmbeddedRouter = () => {\n const { entity } = useEntity();\n\n if (!isLighthouseAvailable(entity)) {\n return (\n <MissingAnnotationEmptyState\n annotation={LIGHTHOUSE_WEBSITE_URL_ANNOTATION}\n />\n );\n }\n\n return (\n <Routes>\n <Route path=\"/\" element={<AuditListForEntity />} />\n <Route path=\"/audit/:id\" element={<AuditViewContent />} />\n <Route path=\"/create-audit\" element={<CreateAuditContent />} />\n </Routes>\n );\n};\n"],"names":["AuditView"],"mappings":";;;;;;;;;AA8Ba,MAAA,qBAAA,GAAwB,CAAC,MACpC,KAAA,OAAA,CAAQ,OAAO,QAAS,CAAA,WAAA,GAAc,iCAAiC,CAAC,EAAA;AAGnE,MAAM,MAAS,GAAA,sBACnB,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAM,IAAK,EAAA,GAAA,EAAI,OAAS,kBAAA,KAAA,CAAA,aAAA,CAAC,SAAU,EAAA,IAAA,CAAA,EAAI,mBACvC,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAM,IAAK,EAAA,YAAA,EAAa,OAAS,kBAAA,KAAA,CAAA,aAAA,CAACA,kBAAU,EAAA,IAAA,CAAA,EAAI,CACjD,kBAAA,KAAA,CAAA,aAAA,CAAC,KAAM,EAAA,EAAA,IAAA,EAAK,eAAgB,EAAA,OAAA,kBAAU,KAAA,CAAA,aAAA,CAAA,WAAA,EAAA,IAAY,GAAI,CACxD,EAAA;AAIK,MAAM,iBAAiB,MAAM;AAClC,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA,CAAA;AAE7B,EAAI,IAAA,CAAC,qBAAsB,CAAA,MAAM,CAAG,EAAA;AAClC,IACE,uBAAA,KAAA,CAAA,aAAA;AAAA,MAAC,2BAAA;AAAA,MAAA;AAAA,QACC,UAAY,EAAA,iCAAA;AAAA,OAAA;AAAA,KACd,CAAA;AAAA,GAEJ;AAEA,EAAA,uBACG,KAAA,CAAA,aAAA,CAAA,MAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAM,IAAK,EAAA,GAAA,EAAI,OAAS,kBAAA,KAAA,CAAA,aAAA,CAAC,kBAAmB,EAAA,IAAA,CAAA,EAAI,CACjD,kBAAA,KAAA,CAAA,aAAA,CAAC,KAAM,EAAA,EAAA,IAAA,EAAK,YAAa,EAAA,OAAA,kBAAU,KAAA,CAAA,aAAA,CAAA,gBAAA,EAAA,IAAiB,CAAI,EAAA,CAAA,kBACvD,KAAA,CAAA,aAAA,CAAA,KAAA,EAAA,EAAM,IAAK,EAAA,eAAA,EAAgB,OAAS,kBAAA,KAAA,CAAA,aAAA,CAAC,kBAAmB,EAAA,IAAA,CAAA,EAAI,CAC/D,CAAA,CAAA;AAEJ;;;;"}
|
package/dist/api.esm.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.esm.js","sources":["../src/api.ts"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport { createApiRef } from '@backstage/core-plugin-api';\nimport { LighthouseApi } from '@backstage-community/plugin-lighthouse-common';\n\n/** @public */\nexport const lighthouseApiRef = createApiRef<LighthouseApi>({\n id: 'plugin.lighthouse.service',\n});\n"],"names":[],"mappings":";;AAoBO,MAAM,mBAAmB,YAA4B,CAAA;AAAA,EAC1D,EAAI,EAAA,2BAAA;AACN,CAAC;;;;"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { AuditListTable } from './AuditListTable.esm.js';
|
|
3
|
+
import { useWebsiteForEntity } from '../../hooks/useWebsiteForEntity.esm.js';
|
|
4
|
+
import { LIGHTHOUSE_WEBSITE_URL_ANNOTATION } from '../../constants.esm.js';
|
|
5
|
+
import { WarningPanel, InfoCard, Content, ContentHeader, Progress } from '@backstage/core-components';
|
|
6
|
+
import Button from '@material-ui/core/Button';
|
|
7
|
+
import { useNavigate, resolvePath } from 'react-router-dom';
|
|
8
|
+
import { useEntity } from '@backstage/plugin-catalog-react';
|
|
9
|
+
import { useRouteRef } from '@backstage/core-plugin-api';
|
|
10
|
+
import { rootRouteRef } from '../../plugin.esm.js';
|
|
11
|
+
import LighthouseSupportButton from '../SupportButton/index.esm.js';
|
|
12
|
+
|
|
13
|
+
const AuditListForEntity = () => {
|
|
14
|
+
const { value, loading, error } = useWebsiteForEntity();
|
|
15
|
+
const { entity } = useEntity();
|
|
16
|
+
const navigate = useNavigate();
|
|
17
|
+
const fromPath = useRouteRef(rootRouteRef)?.() ?? "../";
|
|
18
|
+
let createAuditButtonUrl = "create-audit";
|
|
19
|
+
const websiteUrl = entity.metadata.annotations?.[LIGHTHOUSE_WEBSITE_URL_ANNOTATION] ?? "";
|
|
20
|
+
if (websiteUrl) {
|
|
21
|
+
createAuditButtonUrl += `?url=${encodeURIComponent(websiteUrl)}`;
|
|
22
|
+
}
|
|
23
|
+
let content = null;
|
|
24
|
+
content = /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(ContentHeader, { title: "Latest Audit" }, /* @__PURE__ */ React.createElement(
|
|
25
|
+
Button,
|
|
26
|
+
{
|
|
27
|
+
variant: "contained",
|
|
28
|
+
color: "primary",
|
|
29
|
+
onClick: () => navigate(resolvePath(createAuditButtonUrl, fromPath))
|
|
30
|
+
},
|
|
31
|
+
"Create New Audit"
|
|
32
|
+
), /* @__PURE__ */ React.createElement(LighthouseSupportButton, null)), /* @__PURE__ */ React.createElement(AuditListTable, { items: value ? [value] : [] }));
|
|
33
|
+
if (loading) {
|
|
34
|
+
content = /* @__PURE__ */ React.createElement(Progress, null);
|
|
35
|
+
}
|
|
36
|
+
if (error && !error.message.includes("no audited website found for url")) {
|
|
37
|
+
content = /* @__PURE__ */ React.createElement(WarningPanel, { severity: "error", title: "Could not load audit list." }, error.message);
|
|
38
|
+
}
|
|
39
|
+
return /* @__PURE__ */ React.createElement(InfoCard, { noPadding: true }, content);
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export { AuditListForEntity };
|
|
43
|
+
//# sourceMappingURL=AuditListForEntity.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuditListForEntity.esm.js","sources":["../../../src/components/AuditList/AuditListForEntity.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { ReactNode } from 'react';\nimport { AuditListTable } from './AuditListTable';\nimport { useWebsiteForEntity } from '../../hooks/useWebsiteForEntity';\nimport { LIGHTHOUSE_WEBSITE_URL_ANNOTATION } from '../../../constants';\nimport {\n Content,\n ContentHeader,\n InfoCard,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\nimport Button from '@material-ui/core/Button';\nimport { resolvePath, useNavigate } from 'react-router-dom';\nimport { useEntity } from '@backstage/plugin-catalog-react';\nimport { useRouteRef } from '@backstage/core-plugin-api';\nimport { rootRouteRef } from '../../plugin';\nimport LighthouseSupportButton from '../SupportButton';\n\nexport const AuditListForEntity = () => {\n const { value, loading, error } = useWebsiteForEntity();\n const { entity } = useEntity();\n const navigate = useNavigate();\n const fromPath = useRouteRef(rootRouteRef)?.() ?? '../';\n\n let createAuditButtonUrl = 'create-audit';\n const websiteUrl =\n entity.metadata.annotations?.[LIGHTHOUSE_WEBSITE_URL_ANNOTATION] ?? '';\n if (websiteUrl) {\n createAuditButtonUrl += `?url=${encodeURIComponent(websiteUrl)}`;\n }\n\n let content: ReactNode = null;\n content = (\n <Content>\n <ContentHeader title=\"Latest Audit\">\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => navigate(resolvePath(createAuditButtonUrl, fromPath))}\n >\n Create New Audit\n </Button>\n <LighthouseSupportButton />\n </ContentHeader>\n <AuditListTable items={value ? [value] : []} />\n </Content>\n );\n\n if (loading) {\n content = <Progress />;\n }\n if (error && !error.message.includes('no audited website found for url')) {\n // We only want to display this warning panel when its caused by an error other than no audits for the website\n content = (\n <WarningPanel severity=\"error\" title=\"Could not load audit list.\">\n {error.message}\n </WarningPanel>\n );\n }\n\n return <InfoCard noPadding>{content}</InfoCard>;\n};\n"],"names":[],"mappings":";;;;;;;;;;;;AAiCO,MAAM,qBAAqB,MAAM;AACtC,EAAA,MAAM,EAAE,KAAA,EAAO,OAAS,EAAA,KAAA,KAAU,mBAAoB,EAAA,CAAA;AACtD,EAAM,MAAA,EAAE,MAAO,EAAA,GAAI,SAAU,EAAA,CAAA;AAC7B,EAAA,MAAM,WAAW,WAAY,EAAA,CAAA;AAC7B,EAAA,MAAM,QAAW,GAAA,WAAA,CAAY,YAAY,CAAA,IAAS,IAAA,KAAA,CAAA;AAElD,EAAA,IAAI,oBAAuB,GAAA,cAAA,CAAA;AAC3B,EAAA,MAAM,UACJ,GAAA,MAAA,CAAO,QAAS,CAAA,WAAA,GAAc,iCAAiC,CAAK,IAAA,EAAA,CAAA;AACtE,EAAA,IAAI,UAAY,EAAA;AACd,IAAwB,oBAAA,IAAA,CAAA,KAAA,EAAQ,kBAAmB,CAAA,UAAU,CAAC,CAAA,CAAA,CAAA;AAAA,GAChE;AAEA,EAAA,IAAI,OAAqB,GAAA,IAAA,CAAA;AACzB,EAAA,OAAA,mBACG,KAAA,CAAA,aAAA,CAAA,OAAA,EAAA,IAAA,kBACE,KAAA,CAAA,aAAA,CAAA,aAAA,EAAA,EAAc,OAAM,cACnB,EAAA,kBAAA,KAAA,CAAA,aAAA;AAAA,IAAC,MAAA;AAAA,IAAA;AAAA,MACC,OAAQ,EAAA,WAAA;AAAA,MACR,KAAM,EAAA,SAAA;AAAA,MACN,SAAS,MAAM,QAAA,CAAS,WAAY,CAAA,oBAAA,EAAsB,QAAQ,CAAC,CAAA;AAAA,KAAA;AAAA,IACpE,kBAAA;AAAA,GAGD,kBAAA,KAAA,CAAA,aAAA,CAAC,uBAAwB,EAAA,IAAA,CAC3B,mBACC,KAAA,CAAA,aAAA,CAAA,cAAA,EAAA,EAAe,KAAO,EAAA,KAAA,GAAQ,CAAC,KAAK,CAAI,GAAA,IAAI,CAC/C,CAAA,CAAA;AAGF,EAAA,IAAI,OAAS,EAAA;AACX,IAAA,OAAA,uCAAW,QAAS,EAAA,IAAA,CAAA,CAAA;AAAA,GACtB;AACA,EAAA,IAAI,SAAS,CAAC,KAAA,CAAM,OAAQ,CAAA,QAAA,CAAS,kCAAkC,CAAG,EAAA;AAExE,IAAA,OAAA,uCACG,YAAa,EAAA,EAAA,QAAA,EAAS,SAAQ,KAAM,EAAA,4BAAA,EAAA,EAClC,MAAM,OACT,CAAA,CAAA;AAAA,GAEJ;AAEA,EAAA,uBAAQ,KAAA,CAAA,aAAA,CAAA,QAAA,EAAA,EAAS,SAAS,EAAA,IAAA,EAAA,EAAE,OAAQ,CAAA,CAAA;AACtC;;;;"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import React, { useState, useEffect } from 'react';
|
|
2
|
+
import Typography from '@material-ui/core/Typography';
|
|
3
|
+
import { lighthouseApiRef } from '../../api.esm.js';
|
|
4
|
+
import useInterval from 'react-use/esm/useInterval';
|
|
5
|
+
import { buildSparklinesDataForItem, CATEGORIES, CATEGORY_LABELS, formatTime } from '../../utils.esm.js';
|
|
6
|
+
import { generatePath } from 'react-router-dom';
|
|
7
|
+
import AuditStatusIcon from '../AuditStatusIcon/index.esm.js';
|
|
8
|
+
import { TrendLine, Link, Table } from '@backstage/core-components';
|
|
9
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
10
|
+
|
|
11
|
+
const columns = [
|
|
12
|
+
{
|
|
13
|
+
title: "Website URL",
|
|
14
|
+
field: "websiteUrl"
|
|
15
|
+
},
|
|
16
|
+
...CATEGORIES.map((category) => ({
|
|
17
|
+
title: CATEGORY_LABELS[category],
|
|
18
|
+
field: category
|
|
19
|
+
})),
|
|
20
|
+
{
|
|
21
|
+
title: "Last Report",
|
|
22
|
+
field: "lastReport",
|
|
23
|
+
cellStyle: {
|
|
24
|
+
whiteSpace: "nowrap"
|
|
25
|
+
}
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
title: "Last Audit Triggered",
|
|
29
|
+
field: "lastAuditTriggered",
|
|
30
|
+
cellStyle: {
|
|
31
|
+
minWidth: 120
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
];
|
|
35
|
+
const AuditListTable = ({ items }) => {
|
|
36
|
+
const [websiteState, setWebsiteState] = useState(items);
|
|
37
|
+
const lighthouseApi = useApi(lighthouseApiRef);
|
|
38
|
+
useEffect(() => {
|
|
39
|
+
setWebsiteState(items);
|
|
40
|
+
}, [items]);
|
|
41
|
+
const runRefresh = (websites) => {
|
|
42
|
+
websites.forEach(async (website) => {
|
|
43
|
+
const response = await lighthouseApi.getWebsiteForAuditId(
|
|
44
|
+
website.lastAudit.id
|
|
45
|
+
);
|
|
46
|
+
const auditStatus = response.lastAudit.status;
|
|
47
|
+
if (auditStatus === "COMPLETED" || auditStatus === "FAILED") {
|
|
48
|
+
const newWebsiteData = websiteState.slice(0);
|
|
49
|
+
newWebsiteData[newWebsiteData.findIndex((w) => w.url === response.url)] = response;
|
|
50
|
+
setWebsiteState(newWebsiteData);
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
};
|
|
54
|
+
const runningWebsiteAudits = websiteState ? websiteState.filter((website) => website.lastAudit.status === "RUNNING") : [];
|
|
55
|
+
useInterval(
|
|
56
|
+
() => runRefresh(runningWebsiteAudits),
|
|
57
|
+
runningWebsiteAudits.length > 0 ? 5e3 : null
|
|
58
|
+
);
|
|
59
|
+
const data = websiteState.map((website) => {
|
|
60
|
+
const trendlineData = buildSparklinesDataForItem(website);
|
|
61
|
+
const trendlines = {};
|
|
62
|
+
CATEGORIES.forEach((category) => {
|
|
63
|
+
trendlines[category] = /* @__PURE__ */ React.createElement(
|
|
64
|
+
TrendLine,
|
|
65
|
+
{
|
|
66
|
+
title: `trendline for ${CATEGORY_LABELS[category]} category of ${website.url}`,
|
|
67
|
+
data: trendlineData[category] || []
|
|
68
|
+
}
|
|
69
|
+
);
|
|
70
|
+
});
|
|
71
|
+
return {
|
|
72
|
+
websiteUrl: /* @__PURE__ */ React.createElement(Link, { to: generatePath("audit/:id", { id: website.lastAudit.id }) }, website.url),
|
|
73
|
+
...trendlines,
|
|
74
|
+
lastReport: /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(AuditStatusIcon, { audit: website.lastAudit }), " ", /* @__PURE__ */ React.createElement(Typography, { component: "span" }, website.lastAudit.status.toLocaleUpperCase("en-US"))),
|
|
75
|
+
lastAuditTriggered: formatTime(website.lastAudit.timeCreated)
|
|
76
|
+
};
|
|
77
|
+
});
|
|
78
|
+
return /* @__PURE__ */ React.createElement(
|
|
79
|
+
Table,
|
|
80
|
+
{
|
|
81
|
+
options: {
|
|
82
|
+
paging: false,
|
|
83
|
+
toolbar: false
|
|
84
|
+
},
|
|
85
|
+
columns,
|
|
86
|
+
data
|
|
87
|
+
}
|
|
88
|
+
);
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
export { AuditListTable, AuditListTable as default };
|
|
92
|
+
//# sourceMappingURL=AuditListTable.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AuditListTable.esm.js","sources":["../../../src/components/AuditList/AuditListTable.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React, { useState, useEffect } from 'react';\nimport Typography from '@material-ui/core/Typography';\nimport { Website } from '@backstage-community/plugin-lighthouse-common';\nimport { lighthouseApiRef } from '../../api';\nimport useInterval from 'react-use/esm/useInterval';\nimport {\n formatTime,\n CATEGORIES,\n CATEGORY_LABELS,\n buildSparklinesDataForItem,\n} from '../../utils';\nimport { generatePath } from 'react-router-dom';\nimport AuditStatusIcon from '../AuditStatusIcon';\n\nimport {\n Link,\n Table,\n TableColumn,\n TrendLine,\n} from '@backstage/core-components';\nimport { useApi } from '@backstage/core-plugin-api';\n\nconst columns: TableColumn[] = [\n {\n title: 'Website URL',\n field: 'websiteUrl',\n },\n ...CATEGORIES.map(category => ({\n title: CATEGORY_LABELS[category],\n field: category,\n })),\n {\n title: 'Last Report',\n field: 'lastReport',\n cellStyle: {\n whiteSpace: 'nowrap',\n },\n },\n {\n title: 'Last Audit Triggered',\n field: 'lastAuditTriggered',\n cellStyle: {\n minWidth: 120,\n },\n },\n];\n\nexport const AuditListTable = ({ items }: { items: Website[] }) => {\n const [websiteState, setWebsiteState] = useState(items);\n const lighthouseApi = useApi(lighthouseApiRef);\n\n useEffect(() => {\n setWebsiteState(items);\n }, [items]);\n\n const runRefresh = (websites: Website[]) => {\n websites.forEach(async website => {\n const response = await lighthouseApi.getWebsiteForAuditId(\n website.lastAudit.id,\n );\n const auditStatus = response.lastAudit.status;\n if (auditStatus === 'COMPLETED' || auditStatus === 'FAILED') {\n const newWebsiteData = websiteState.slice(0);\n newWebsiteData[newWebsiteData.findIndex(w => w.url === response.url)] =\n response;\n setWebsiteState(newWebsiteData);\n }\n });\n };\n\n const runningWebsiteAudits = websiteState\n ? websiteState.filter(website => website.lastAudit.status === 'RUNNING')\n : [];\n\n useInterval(\n () => runRefresh(runningWebsiteAudits),\n runningWebsiteAudits.length > 0 ? 5000 : null,\n );\n\n const data = websiteState.map(website => {\n const trendlineData = buildSparklinesDataForItem(website);\n const trendlines: any = {};\n CATEGORIES.forEach(category => {\n trendlines[category] = (\n <TrendLine\n title={`trendline for ${CATEGORY_LABELS[category]} category of ${website.url}`}\n data={trendlineData[category] || []}\n />\n );\n });\n\n return {\n websiteUrl: (\n <Link to={generatePath('audit/:id', { id: website.lastAudit.id })}>\n {website.url}\n </Link>\n ),\n ...trendlines,\n lastReport: (\n <>\n <AuditStatusIcon audit={website.lastAudit} />{' '}\n <Typography component=\"span\">\n {website.lastAudit.status.toLocaleUpperCase('en-US')}\n </Typography>\n </>\n ),\n lastAuditTriggered: formatTime(website.lastAudit.timeCreated),\n };\n });\n\n return (\n <Table\n options={{\n paging: false,\n toolbar: false,\n }}\n columns={columns}\n data={data}\n />\n );\n};\n\nexport default AuditListTable;\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import Button from '@material-ui/core/Button';
|
|
2
|
+
import Grid from '@material-ui/core/Grid';
|
|
3
|
+
import Pagination from '@material-ui/lab/Pagination';
|
|
4
|
+
import React, { useState, useMemo } from 'react';
|
|
5
|
+
import { useNavigate } from 'react-router-dom';
|
|
6
|
+
import useAsync from 'react-use/esm/useAsync';
|
|
7
|
+
import useLocalStorage from 'react-use/esm/useLocalStorage';
|
|
8
|
+
import { lighthouseApiRef } from '../../api.esm.js';
|
|
9
|
+
import { useQuery } from '../../utils.esm.js';
|
|
10
|
+
import LighthouseIntro, { LIGHTHOUSE_INTRO_LOCAL_STORAGE } from '../Intro/index.esm.js';
|
|
11
|
+
import LighthouseSupportButton from '../SupportButton/index.esm.js';
|
|
12
|
+
import { AuditListTable } from './AuditListTable.esm.js';
|
|
13
|
+
import { WarningPanel, Page, Header, HeaderLabel, Content, ContentHeader, InfoCard, Progress } from '@backstage/core-components';
|
|
14
|
+
import { useApi } from '@backstage/core-plugin-api';
|
|
15
|
+
|
|
16
|
+
const LIMIT = 10;
|
|
17
|
+
const AuditList = () => {
|
|
18
|
+
const [dismissedStored] = useLocalStorage(
|
|
19
|
+
LIGHTHOUSE_INTRO_LOCAL_STORAGE
|
|
20
|
+
);
|
|
21
|
+
const [dismissed, setDismissed] = useState(dismissedStored);
|
|
22
|
+
const query = useQuery();
|
|
23
|
+
const page = query.get("page") ? parseInt(query.get("page"), 10) || 1 : 1;
|
|
24
|
+
const lighthouseApi = useApi(lighthouseApiRef);
|
|
25
|
+
const { value, loading, error } = useAsync(
|
|
26
|
+
async () => await lighthouseApi.getWebsiteList({
|
|
27
|
+
limit: LIMIT,
|
|
28
|
+
offset: (page - 1) * LIMIT
|
|
29
|
+
}),
|
|
30
|
+
[page]
|
|
31
|
+
);
|
|
32
|
+
const pageCount = useMemo(() => {
|
|
33
|
+
if (value?.total && value?.limit)
|
|
34
|
+
return Math.ceil(value?.total / value?.limit);
|
|
35
|
+
return 0;
|
|
36
|
+
}, [value?.total, value?.limit]);
|
|
37
|
+
const navigate = useNavigate();
|
|
38
|
+
let content = null;
|
|
39
|
+
if (value) {
|
|
40
|
+
content = /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(AuditListTable, { items: value?.items || [] }), pageCount > 1 && /* @__PURE__ */ React.createElement(
|
|
41
|
+
Pagination,
|
|
42
|
+
{
|
|
43
|
+
page,
|
|
44
|
+
count: pageCount,
|
|
45
|
+
onChange: (_event, newPage) => {
|
|
46
|
+
navigate(`?page=${newPage}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
));
|
|
50
|
+
} else if (loading) {
|
|
51
|
+
content = /* @__PURE__ */ React.createElement(Progress, null);
|
|
52
|
+
} else if (error) {
|
|
53
|
+
content = /* @__PURE__ */ React.createElement(WarningPanel, { severity: "error", title: "Could not load audit list." }, error.message);
|
|
54
|
+
}
|
|
55
|
+
return /* @__PURE__ */ React.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React.createElement(
|
|
56
|
+
Header,
|
|
57
|
+
{
|
|
58
|
+
title: "Lighthouse",
|
|
59
|
+
subtitle: "Website audits powered by Lighthouse"
|
|
60
|
+
},
|
|
61
|
+
/* @__PURE__ */ React.createElement(HeaderLabel, { label: "Owner", value: "Spotify" }),
|
|
62
|
+
/* @__PURE__ */ React.createElement(HeaderLabel, { label: "Lifecycle", value: "Alpha" })
|
|
63
|
+
), /* @__PURE__ */ React.createElement(Content, null, /* @__PURE__ */ React.createElement(LighthouseIntro, { onDismiss: () => setDismissed(true) }), /* @__PURE__ */ React.createElement(
|
|
64
|
+
ContentHeader,
|
|
65
|
+
{
|
|
66
|
+
title: "Audits",
|
|
67
|
+
description: "View all audits run for your website through Backstage here. Track the trend of your most recent audits."
|
|
68
|
+
},
|
|
69
|
+
/* @__PURE__ */ React.createElement(
|
|
70
|
+
Button,
|
|
71
|
+
{
|
|
72
|
+
variant: "contained",
|
|
73
|
+
color: "primary",
|
|
74
|
+
onClick: () => navigate("create-audit")
|
|
75
|
+
},
|
|
76
|
+
"Create Audit"
|
|
77
|
+
),
|
|
78
|
+
dismissed && /* @__PURE__ */ React.createElement(LighthouseSupportButton, null)
|
|
79
|
+
), /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 3, direction: "column" }, /* @__PURE__ */ React.createElement(Grid, { item: true }, /* @__PURE__ */ React.createElement(InfoCard, { noPadding: true }, content)))));
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
export { LIMIT, AuditList as default };
|
|
83
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../../src/components/AuditList/index.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Button from '@material-ui/core/Button';\nimport Grid from '@material-ui/core/Grid';\nimport Pagination from '@material-ui/lab/Pagination';\nimport React, { ChangeEvent, ReactNode, useMemo, useState } from 'react';\nimport { useNavigate } from 'react-router-dom';\nimport useAsync from 'react-use/esm/useAsync';\nimport useLocalStorage from 'react-use/esm/useLocalStorage';\nimport { lighthouseApiRef } from '../../api';\nimport { useQuery } from '../../utils';\nimport LighthouseIntro, { LIGHTHOUSE_INTRO_LOCAL_STORAGE } from '../Intro';\nimport LighthouseSupportButton from '../SupportButton';\nimport AuditListTable from './AuditListTable';\n\nimport {\n Content,\n ContentHeader,\n Header,\n HeaderLabel,\n InfoCard,\n Page,\n Progress,\n WarningPanel,\n} from '@backstage/core-components';\n\nimport { useApi } from '@backstage/core-plugin-api';\n\n// TODO(freben): move all of this out of index\n\nexport const LIMIT = 10;\n\nconst AuditList = () => {\n const [dismissedStored] = useLocalStorage<boolean>(\n LIGHTHOUSE_INTRO_LOCAL_STORAGE,\n );\n const [dismissed, setDismissed] = useState(dismissedStored);\n\n const query = useQuery();\n const page = query.get('page')\n ? parseInt(query.get('page') as string, 10) || 1\n : 1;\n\n const lighthouseApi = useApi(lighthouseApiRef);\n const { value, loading, error } = useAsync(\n async () =>\n await lighthouseApi.getWebsiteList({\n limit: LIMIT,\n offset: (page - 1) * LIMIT,\n }),\n [page],\n );\n\n const pageCount: number = useMemo(() => {\n if (value?.total && value?.limit)\n return Math.ceil(value?.total / value?.limit);\n return 0;\n }, [value?.total, value?.limit]);\n\n const navigate = useNavigate();\n\n let content: ReactNode = null;\n if (value) {\n content = (\n <>\n <AuditListTable items={value?.items || []} />\n {pageCount > 1 && (\n <Pagination\n page={page}\n count={pageCount}\n onChange={(_event: ChangeEvent<unknown>, newPage: number) => {\n navigate(`?page=${newPage}`);\n }}\n />\n )}\n </>\n );\n } else if (loading) {\n content = <Progress />;\n } else if (error) {\n content = (\n <WarningPanel severity=\"error\" title=\"Could not load audit list.\">\n {error.message}\n </WarningPanel>\n );\n }\n\n return (\n <Page themeId=\"tool\">\n <Header\n title=\"Lighthouse\"\n subtitle=\"Website audits powered by Lighthouse\"\n >\n <HeaderLabel label=\"Owner\" value=\"Spotify\" />\n <HeaderLabel label=\"Lifecycle\" value=\"Alpha\" />\n </Header>\n <Content>\n <LighthouseIntro onDismiss={() => setDismissed(true)} />\n <ContentHeader\n title=\"Audits\"\n description=\"View all audits run for your website through Backstage here. Track the trend of your most recent audits.\"\n >\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => navigate('create-audit')}\n >\n Create Audit\n </Button>\n {dismissed && <LighthouseSupportButton />}\n </ContentHeader>\n <Grid container spacing={3} direction=\"column\">\n <Grid item>\n <InfoCard noPadding>{content}</InfoCard>\n </Grid>\n </Grid>\n </Content>\n </Page>\n );\n};\n\nexport default AuditList;\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { StatusError, StatusOK, StatusPending } from '@backstage/core-components';
|
|
3
|
+
|
|
4
|
+
const AuditStatusIcon = ({ audit }) => {
|
|
5
|
+
if (audit.status === "FAILED") return /* @__PURE__ */ React.createElement(StatusError, null);
|
|
6
|
+
if (audit.status === "COMPLETED") return /* @__PURE__ */ React.createElement(StatusOK, null);
|
|
7
|
+
return /* @__PURE__ */ React.createElement(StatusPending, null);
|
|
8
|
+
};
|
|
9
|
+
|
|
10
|
+
export { AuditStatusIcon as default };
|
|
11
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../../src/components/AuditStatusIcon/index.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport React from 'react';\nimport { Audit } from '@backstage-community/plugin-lighthouse-common';\nimport {\n StatusError,\n StatusOK,\n StatusPending,\n} from '@backstage/core-components';\n\n// TODO(freben): move all of this out of index\n\nconst AuditStatusIcon = ({ audit }: { audit: Audit }) => {\n if (audit.status === 'FAILED') return <StatusError />;\n if (audit.status === 'COMPLETED') return <StatusOK />;\n return <StatusPending />;\n};\n\nexport default AuditStatusIcon;\n"],"names":[],"mappings":";;;AA0BA,MAAM,eAAkB,GAAA,CAAC,EAAE,KAAA,EAA8B,KAAA;AACvD,EAAA,IAAI,KAAM,CAAA,MAAA,KAAW,QAAU,EAAA,2CAAQ,WAAY,EAAA,IAAA,CAAA,CAAA;AACnD,EAAA,IAAI,KAAM,CAAA,MAAA,KAAW,WAAa,EAAA,2CAAQ,QAAS,EAAA,IAAA,CAAA,CAAA;AACnD,EAAA,2CAAQ,aAAc,EAAA,IAAA,CAAA,CAAA;AACxB;;;;"}
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import Button from '@material-ui/core/Button';
|
|
2
|
+
import Grid from '@material-ui/core/Grid';
|
|
3
|
+
import List from '@material-ui/core/List';
|
|
4
|
+
import ListItem from '@material-ui/core/ListItem';
|
|
5
|
+
import ListItemIcon from '@material-ui/core/ListItemIcon';
|
|
6
|
+
import ListItemText from '@material-ui/core/ListItemText';
|
|
7
|
+
import { makeStyles } from '@material-ui/core/styles';
|
|
8
|
+
import Alert from '@material-ui/lab/Alert';
|
|
9
|
+
import React, { useState, useEffect } from 'react';
|
|
10
|
+
import { useParams, useNavigate, resolvePath, Link, generatePath } from 'react-router-dom';
|
|
11
|
+
import useAsync from 'react-use/esm/useAsync';
|
|
12
|
+
import { lighthouseApiRef } from '../../api.esm.js';
|
|
13
|
+
import { formatTime } from '../../utils.esm.js';
|
|
14
|
+
import AuditStatusIcon from '../AuditStatusIcon/index.esm.js';
|
|
15
|
+
import LighthouseSupportButton from '../SupportButton/index.esm.js';
|
|
16
|
+
import { ContentHeader, Page, Header, HeaderLabel, Content, Progress, InfoCard } from '@backstage/core-components';
|
|
17
|
+
import { useApi, useRouteRef } from '@backstage/core-plugin-api';
|
|
18
|
+
import { rootRouteRef } from '../../plugin.esm.js';
|
|
19
|
+
|
|
20
|
+
const useStyles = makeStyles({
|
|
21
|
+
contentGrid: {
|
|
22
|
+
height: "100%"
|
|
23
|
+
},
|
|
24
|
+
iframe: {
|
|
25
|
+
border: "0",
|
|
26
|
+
width: "100%",
|
|
27
|
+
height: "100%"
|
|
28
|
+
},
|
|
29
|
+
errorOutput: { whiteSpace: "pre" }
|
|
30
|
+
});
|
|
31
|
+
const AuditLinkList = ({ audits = [], selectedId }) => {
|
|
32
|
+
const fromPath = useRouteRef(rootRouteRef)?.() ?? "../";
|
|
33
|
+
return /* @__PURE__ */ React.createElement(
|
|
34
|
+
List,
|
|
35
|
+
{
|
|
36
|
+
"data-testid": "audit-sidebar",
|
|
37
|
+
component: "nav",
|
|
38
|
+
"aria-label": "lighthouse audit history"
|
|
39
|
+
},
|
|
40
|
+
audits.map((audit) => /* @__PURE__ */ React.createElement(
|
|
41
|
+
ListItem,
|
|
42
|
+
{
|
|
43
|
+
key: audit.id,
|
|
44
|
+
selected: audit.id === selectedId,
|
|
45
|
+
button: true,
|
|
46
|
+
component: Link,
|
|
47
|
+
replace: true,
|
|
48
|
+
to: resolvePath(
|
|
49
|
+
generatePath("audit/:id", { id: audit.id }),
|
|
50
|
+
fromPath
|
|
51
|
+
)
|
|
52
|
+
},
|
|
53
|
+
/* @__PURE__ */ React.createElement(ListItemIcon, null, /* @__PURE__ */ React.createElement(AuditStatusIcon, { audit })),
|
|
54
|
+
/* @__PURE__ */ React.createElement(ListItemText, { primary: formatTime(audit.timeCreated) })
|
|
55
|
+
))
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
const AuditView = ({ audit }) => {
|
|
59
|
+
const classes = useStyles();
|
|
60
|
+
const params = useParams();
|
|
61
|
+
const { url: lighthouseUrl } = useApi(lighthouseApiRef);
|
|
62
|
+
if (audit?.status === "RUNNING") return /* @__PURE__ */ React.createElement(Progress, null);
|
|
63
|
+
if (audit?.status === "FAILED")
|
|
64
|
+
return /* @__PURE__ */ React.createElement(Alert, { severity: "error" }, "This audit failed when attempting to run after several retries. Check that your instance of lighthouse-audit-service can successfully connect to your website and try again.");
|
|
65
|
+
return /* @__PURE__ */ React.createElement(InfoCard, { variant: "fullHeight" }, /* @__PURE__ */ React.createElement(
|
|
66
|
+
"iframe",
|
|
67
|
+
{
|
|
68
|
+
className: classes.iframe,
|
|
69
|
+
title: `Lighthouse audit${audit?.url ? ` for ${audit.url}` : ""}`,
|
|
70
|
+
src: `${lighthouseUrl}/v1/audits/${encodeURIComponent(params.id)}`
|
|
71
|
+
}
|
|
72
|
+
));
|
|
73
|
+
};
|
|
74
|
+
const AuditViewContent = () => {
|
|
75
|
+
const lighthouseApi = useApi(lighthouseApiRef);
|
|
76
|
+
const fromPath = useRouteRef(rootRouteRef)?.() ?? "../";
|
|
77
|
+
const params = useParams();
|
|
78
|
+
const classes = useStyles();
|
|
79
|
+
const navigate = useNavigate();
|
|
80
|
+
const {
|
|
81
|
+
loading,
|
|
82
|
+
error,
|
|
83
|
+
value: nextValue
|
|
84
|
+
} = useAsync(
|
|
85
|
+
async () => await lighthouseApi.getWebsiteForAuditId(params.id),
|
|
86
|
+
[params.id]
|
|
87
|
+
);
|
|
88
|
+
const [value, setValue] = useState();
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
if (!!nextValue && nextValue.url !== value?.url) {
|
|
91
|
+
setValue(nextValue);
|
|
92
|
+
}
|
|
93
|
+
}, [value, nextValue, setValue]);
|
|
94
|
+
let content = null;
|
|
95
|
+
if (value) {
|
|
96
|
+
content = /* @__PURE__ */ React.createElement(Grid, { container: true, alignItems: "stretch", className: classes.contentGrid }, /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 3 }, /* @__PURE__ */ React.createElement(AuditLinkList, { audits: value?.audits, selectedId: params.id })), /* @__PURE__ */ React.createElement(Grid, { item: true, xs: 9 }, /* @__PURE__ */ React.createElement(AuditView, { audit: value?.audits.find((a) => a.id === params.id) })));
|
|
97
|
+
} else if (loading) {
|
|
98
|
+
content = /* @__PURE__ */ React.createElement(Progress, null);
|
|
99
|
+
} else if (error) {
|
|
100
|
+
content = /* @__PURE__ */ React.createElement(
|
|
101
|
+
Alert,
|
|
102
|
+
{
|
|
103
|
+
"data-testid": "error-message",
|
|
104
|
+
severity: "error",
|
|
105
|
+
className: classes.errorOutput
|
|
106
|
+
},
|
|
107
|
+
error.message
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
let createAuditButtonUrl = "create-audit";
|
|
111
|
+
if (value?.url) {
|
|
112
|
+
createAuditButtonUrl += `?url=${encodeURIComponent(value.url)}`;
|
|
113
|
+
}
|
|
114
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
115
|
+
ContentHeader,
|
|
116
|
+
{
|
|
117
|
+
title: value?.url || "Audit",
|
|
118
|
+
description: "See a history of all Lighthouse audits for your website run through Backstage."
|
|
119
|
+
},
|
|
120
|
+
/* @__PURE__ */ React.createElement(
|
|
121
|
+
Button,
|
|
122
|
+
{
|
|
123
|
+
variant: "contained",
|
|
124
|
+
color: "primary",
|
|
125
|
+
onClick: () => navigate(resolvePath(createAuditButtonUrl, fromPath))
|
|
126
|
+
},
|
|
127
|
+
"Create New Audit"
|
|
128
|
+
),
|
|
129
|
+
/* @__PURE__ */ React.createElement(LighthouseSupportButton, null)
|
|
130
|
+
), content);
|
|
131
|
+
};
|
|
132
|
+
const ConnectedAuditView = () => /* @__PURE__ */ React.createElement(Page, { themeId: "tool" }, /* @__PURE__ */ React.createElement(Header, { title: "Lighthouse", subtitle: "Website audits powered by Lighthouse" }, /* @__PURE__ */ React.createElement(HeaderLabel, { label: "Owner", value: "Spotify" }), /* @__PURE__ */ React.createElement(HeaderLabel, { label: "Lifecycle", value: "Alpha" })), /* @__PURE__ */ React.createElement(Content, { stretch: true }, /* @__PURE__ */ React.createElement(AuditViewContent, null)));
|
|
133
|
+
|
|
134
|
+
export { AuditViewContent, ConnectedAuditView as default };
|
|
135
|
+
//# sourceMappingURL=index.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":["../../../src/components/AuditView/index.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\n\nimport Button from '@material-ui/core/Button';\nimport Grid from '@material-ui/core/Grid';\nimport List from '@material-ui/core/List';\nimport ListItem from '@material-ui/core/ListItem';\nimport ListItemIcon from '@material-ui/core/ListItemIcon';\nimport ListItemText from '@material-ui/core/ListItemText';\nimport { makeStyles } from '@material-ui/core/styles';\nimport Alert from '@material-ui/lab/Alert';\nimport React, { ReactNode, useEffect, useState } from 'react';\nimport {\n generatePath,\n Link,\n resolvePath,\n useNavigate,\n useParams,\n} from 'react-router-dom';\nimport useAsync from 'react-use/esm/useAsync';\nimport { Audit, Website } from '@backstage-community/plugin-lighthouse-common';\nimport { lighthouseApiRef } from '../../api';\nimport { formatTime } from '../../utils';\nimport AuditStatusIcon from '../AuditStatusIcon';\nimport LighthouseSupportButton from '../SupportButton';\n\nimport {\n Content,\n ContentHeader,\n Header,\n HeaderLabel,\n InfoCard,\n Page,\n Progress,\n} from '@backstage/core-components';\nimport { useApi, useRouteRef } from '@backstage/core-plugin-api';\nimport { rootRouteRef } from '../../plugin';\n\n// TODO(freben): move all of this out of index\n\nconst useStyles = makeStyles({\n contentGrid: {\n height: '100%',\n },\n iframe: {\n border: '0',\n width: '100%',\n height: '100%',\n },\n errorOutput: { whiteSpace: 'pre' },\n});\n\ninterface AuditLinkListProps {\n audits?: Audit[];\n selectedId: string;\n}\nconst AuditLinkList = ({ audits = [], selectedId }: AuditLinkListProps) => {\n const fromPath = useRouteRef(rootRouteRef)?.() ?? '../';\n return (\n <List\n data-testid=\"audit-sidebar\"\n component=\"nav\"\n aria-label=\"lighthouse audit history\"\n >\n {audits.map(audit => (\n <ListItem\n key={audit.id}\n selected={audit.id === selectedId}\n button\n component={Link}\n replace\n to={resolvePath(\n generatePath('audit/:id', { id: audit.id }),\n fromPath,\n )}\n >\n <ListItemIcon>\n <AuditStatusIcon audit={audit} />\n </ListItemIcon>\n <ListItemText primary={formatTime(audit.timeCreated)} />\n </ListItem>\n ))}\n </List>\n );\n};\n\nconst AuditView = ({ audit }: { audit?: Audit }) => {\n const classes = useStyles();\n const params = useParams() as { id: string };\n const { url: lighthouseUrl } = useApi(lighthouseApiRef);\n\n if (audit?.status === 'RUNNING') return <Progress />;\n if (audit?.status === 'FAILED')\n return (\n <Alert severity=\"error\">\n This audit failed when attempting to run after several retries. Check\n that your instance of lighthouse-audit-service can successfully connect\n to your website and try again.\n </Alert>\n );\n\n return (\n <InfoCard variant=\"fullHeight\">\n <iframe\n className={classes.iframe}\n title={`Lighthouse audit${audit?.url ? ` for ${audit.url}` : ''}`}\n src={`${lighthouseUrl}/v1/audits/${encodeURIComponent(params.id)}`}\n />\n </InfoCard>\n );\n};\n\nexport const AuditViewContent = () => {\n const lighthouseApi = useApi(lighthouseApiRef);\n const fromPath = useRouteRef(rootRouteRef)?.() ?? '../';\n const params = useParams() as { id: string };\n const classes = useStyles();\n const navigate = useNavigate();\n\n const {\n loading,\n error,\n value: nextValue,\n } = useAsync(\n async () => await lighthouseApi.getWebsiteForAuditId(params.id),\n [params.id],\n );\n const [value, setValue] = useState<Website>();\n useEffect(() => {\n if (!!nextValue && nextValue.url !== value?.url) {\n setValue(nextValue);\n }\n }, [value, nextValue, setValue]);\n\n let content: ReactNode = null;\n if (value) {\n content = (\n <Grid container alignItems=\"stretch\" className={classes.contentGrid}>\n <Grid item xs={3}>\n <AuditLinkList audits={value?.audits} selectedId={params.id} />\n </Grid>\n <Grid item xs={9}>\n <AuditView audit={value?.audits.find(a => a.id === params.id)} />\n </Grid>\n </Grid>\n );\n } else if (loading) {\n content = <Progress />;\n } else if (error) {\n content = (\n <Alert\n data-testid=\"error-message\"\n severity=\"error\"\n className={classes.errorOutput}\n >\n {error.message}\n </Alert>\n );\n }\n\n let createAuditButtonUrl = 'create-audit';\n if (value?.url) {\n createAuditButtonUrl += `?url=${encodeURIComponent(value.url)}`;\n }\n\n return (\n <>\n <ContentHeader\n title={value?.url || 'Audit'}\n description=\"See a history of all Lighthouse audits for your website run through Backstage.\"\n >\n <Button\n variant=\"contained\"\n color=\"primary\"\n onClick={() => navigate(resolvePath(createAuditButtonUrl, fromPath))}\n >\n Create New Audit\n </Button>\n <LighthouseSupportButton />\n </ContentHeader>\n {content}\n </>\n );\n};\n\nconst ConnectedAuditView = () => (\n <Page themeId=\"tool\">\n <Header title=\"Lighthouse\" subtitle=\"Website audits powered by Lighthouse\">\n <HeaderLabel label=\"Owner\" value=\"Spotify\" />\n <HeaderLabel label=\"Lifecycle\" value=\"Alpha\" />\n </Header>\n <Content stretch>\n <AuditViewContent />\n </Content>\n </Page>\n);\n\nexport default ConnectedAuditView;\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import Typography from '@material-ui/core/Typography';
|
|
3
|
+
import { useWebsiteForEntity } from '../../hooks/useWebsiteForEntity.esm.js';
|
|
4
|
+
import AuditStatusIcon from '../AuditStatusIcon/index.esm.js';
|
|
5
|
+
import { EmptyState, WarningPanel, InfoCard, StructuredMetadataTable, Progress, StatusError, StatusWarning, StatusOK } from '@backstage/core-components';
|
|
6
|
+
|
|
7
|
+
const LighthouseCategoryScoreStatus = (props) => {
|
|
8
|
+
const scoreAsPercentage = Math.round(props.score * 100);
|
|
9
|
+
switch (true) {
|
|
10
|
+
case scoreAsPercentage >= 90:
|
|
11
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(StatusOK, null), scoreAsPercentage, "%");
|
|
12
|
+
case (scoreAsPercentage >= 50 && scoreAsPercentage < 90):
|
|
13
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(StatusWarning, null), scoreAsPercentage, "%");
|
|
14
|
+
case scoreAsPercentage < 50:
|
|
15
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(StatusError, null), scoreAsPercentage, "%");
|
|
16
|
+
default:
|
|
17
|
+
return /* @__PURE__ */ React.createElement(Typography, { component: "span" }, "N/A");
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
const LighthouseAuditStatus = (props) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(AuditStatusIcon, { audit: props.audit }), props.audit.status.toLocaleUpperCase("en-US"));
|
|
21
|
+
const LighthouseAuditSummary = (props) => {
|
|
22
|
+
const { audit, dense = false } = props;
|
|
23
|
+
const { url } = audit;
|
|
24
|
+
const flattenedCategoryData = {};
|
|
25
|
+
if (audit.status === "COMPLETED") {
|
|
26
|
+
const categories = audit.categories;
|
|
27
|
+
const categoryIds = Object.keys(categories);
|
|
28
|
+
categoryIds.forEach((id) => {
|
|
29
|
+
const { title, score } = categories[id];
|
|
30
|
+
flattenedCategoryData[title] = /* @__PURE__ */ React.createElement(LighthouseCategoryScoreStatus, { score });
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
const tableData = {
|
|
34
|
+
url,
|
|
35
|
+
status: /* @__PURE__ */ React.createElement(LighthouseAuditStatus, { audit }),
|
|
36
|
+
...flattenedCategoryData
|
|
37
|
+
};
|
|
38
|
+
return /* @__PURE__ */ React.createElement(StructuredMetadataTable, { metadata: tableData, dense });
|
|
39
|
+
};
|
|
40
|
+
const LastLighthouseAuditCard = (props) => {
|
|
41
|
+
const { dense = false, variant } = props;
|
|
42
|
+
const { value: website, loading, error } = useWebsiteForEntity();
|
|
43
|
+
let content;
|
|
44
|
+
if (loading) {
|
|
45
|
+
content = /* @__PURE__ */ React.createElement(Progress, null);
|
|
46
|
+
}
|
|
47
|
+
if (error) {
|
|
48
|
+
content = error.message.includes("no audited website found for url") ? /* @__PURE__ */ React.createElement(EmptyState, { title: "No Audits Found", missing: "data" }) : /* @__PURE__ */ React.createElement(WarningPanel, { severity: "error", title: "Could not load audit list." }, error.message);
|
|
49
|
+
}
|
|
50
|
+
if (website) {
|
|
51
|
+
content = /* @__PURE__ */ React.createElement(LighthouseAuditSummary, { audit: website.lastAudit, dense });
|
|
52
|
+
}
|
|
53
|
+
return /* @__PURE__ */ React.createElement(InfoCard, { title: "Lighthouse Audit", variant }, content);
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
export { LastLighthouseAuditCard };
|
|
57
|
+
//# sourceMappingURL=LastLighthouseAuditCard.esm.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"LastLighthouseAuditCard.esm.js","sources":["../../../src/components/Cards/LastLighthouseAuditCard.tsx"],"sourcesContent":["/*\n * Copyright 2020 The Backstage Authors\n *\n * Licensed under the Apache License, Version 2.0 (the \"License\");\n * you may not use this file except in compliance with the License.\n * You may obtain a copy of the License at\n *\n * http://www.apache.org/licenses/LICENSE-2.0\n *\n * Unless required by applicable law or agreed to in writing, software\n * distributed under the License is distributed on an \"AS IS\" BASIS,\n * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n * See the License for the specific language governing permissions and\n * limitations under the License.\n */\nimport React from 'react';\nimport Typography from '@material-ui/core/Typography';\nimport {\n Audit,\n AuditCompleted,\n LighthouseCategoryId,\n} from '@backstage-community/plugin-lighthouse-common';\nimport { useWebsiteForEntity } from '../../hooks/useWebsiteForEntity';\nimport AuditStatusIcon from '../AuditStatusIcon';\nimport {\n EmptyState,\n InfoCard,\n InfoCardVariants,\n Progress,\n StatusError,\n StatusOK,\n StatusWarning,\n StructuredMetadataTable,\n WarningPanel,\n} from '@backstage/core-components';\n\nconst LighthouseCategoryScoreStatus = (props: { score: number }) => {\n const scoreAsPercentage = Math.round(props.score * 100);\n switch (true) {\n case scoreAsPercentage >= 90:\n return (\n <>\n <StatusOK />\n {scoreAsPercentage}%\n </>\n );\n case scoreAsPercentage >= 50 && scoreAsPercentage < 90:\n return (\n <>\n <StatusWarning />\n {scoreAsPercentage}%\n </>\n );\n case scoreAsPercentage < 50:\n return (\n <>\n <StatusError />\n {scoreAsPercentage}%\n </>\n );\n default:\n return <Typography component=\"span\">N/A</Typography>;\n }\n};\n\nconst LighthouseAuditStatus = (props: { audit: Audit }) => (\n <>\n <AuditStatusIcon audit={props.audit} />\n {props.audit.status.toLocaleUpperCase('en-US')}\n </>\n);\n\nconst LighthouseAuditSummary = (props: { audit: Audit; dense?: boolean }) => {\n const { audit, dense = false } = props;\n const { url } = audit;\n const flattenedCategoryData: Record<string, React.ReactNode> = {};\n if (audit.status === 'COMPLETED') {\n const categories = (audit as AuditCompleted).categories;\n const categoryIds = Object.keys(categories) as LighthouseCategoryId[];\n categoryIds.forEach((id: LighthouseCategoryId) => {\n const { title, score } = categories[id];\n\n flattenedCategoryData[title] = (\n <LighthouseCategoryScoreStatus score={score} />\n );\n });\n }\n const tableData = {\n url,\n status: <LighthouseAuditStatus audit={audit} />,\n ...flattenedCategoryData,\n };\n\n return <StructuredMetadataTable metadata={tableData} dense={dense} />;\n};\n\n/** @public */\nexport const LastLighthouseAuditCard = (props: {\n dense?: boolean;\n variant?: InfoCardVariants;\n}) => {\n const { dense = false, variant } = props;\n const { value: website, loading, error } = useWebsiteForEntity();\n\n let content;\n if (loading) {\n content = <Progress />;\n }\n if (error) {\n // We only want to display this warning panel when its caused by an error other than no audits being found for the website\n content = error.message.includes('no audited website found for url') ? (\n <EmptyState title=\"No Audits Found\" missing=\"data\" />\n ) : (\n <WarningPanel severity=\"error\" title=\"Could not load audit list.\">\n {error.message}\n </WarningPanel>\n );\n }\n if (website) {\n content = (\n <LighthouseAuditSummary audit={website.lastAudit} dense={dense} />\n );\n }\n return (\n <InfoCard title=\"Lighthouse Audit\" variant={variant}>\n {content}\n </InfoCard>\n );\n};\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
|