UNPKG

@immobiliarelabs/backstage-plugin-gitlab

Version:

<p align="center"> <img src="https://avatars.githubusercontent.com/u/10090828?s=200&v=4" width="200px" alt="logo"/> </p> <h1 align="center">Backstage Plugin GitLab</h1>

197 lines (194 loc) 6.66 kB
import React from 'react'; import { makeStyles } from '@material-ui/core/styles'; import { Typography, Grid, Link } from '@material-ui/core'; import LocalOfferOutlinedIcon from '@material-ui/icons/LocalOfferOutlined'; import Alert from '@material-ui/lab/Alert'; import { Progress, InfoCard } from '@backstage/core-components'; import { GitlabCIApiRef } from '../../../api/GitlabCIApi.esm.js'; import '../../utils.esm.js'; import '@gitbeaker/rest'; import 'dayjs'; import { useApi } from '@backstage/core-plugin-api'; import { useAsync } from 'react-use'; import { gitlabProjectId, gitlabProjectSlug, gitlabInstance } from '../../gitlabAppData.esm.js'; import { valid, rcompare, prerelease } from 'semver'; import Select from '@material-ui/core/Select'; import MenuItem from '@material-ui/core/MenuItem'; import SortIcon from '@material-ui/icons/Sort'; import { useTranslationRef } from '@backstage/core-plugin-api/alpha'; import { gitlabTranslationRef } from '../../../translation.esm.js'; const useStyles = makeStyles((theme) => ({ infoCard: { marginBottom: theme.spacing(3), "& + .MuiAlert-root": { marginTop: theme.spacing(3) } }, releaseTitle: { ...theme.typography.h6, margin: 0, marginRight: "0.5rem" }, releaseTagIcon: { verticalAlign: "middle" }, sortSelector: { display: "flex", width: "100%", justifyContent: "flex-end", alignItems: "center" } })); const sortFunctions = { // sort (e.g. v1.2.3 comes before v1.2.3-alpha-4.5) and walk through list of releases // NOTE: rcompare sorts descending, but full release comes before release candidates (v1.2.3 before v1.2.3-alpha-4.5) // use string comparison for non-compliant tags releasedVersion: (a, b) => { try { return rcompare(a.tag_name, b.tag_name); } catch (error) { return a.tag_name > b.tag_name ? 1 : -1; } }, // sort by released date releasedDate: (a, b) => { const d1 = new Date(a.released_at || a.created_at); const d2 = new Date(b.released_at || b.created_at); return d1.getTime() > d2.getTime() ? -1 : 1; } }; function makeFilter(show) { switch (show) { case "patch": return (value) => { try { return prerelease(value.tag_name) === null; } catch (error) { return true; } }; case "all": default: return () => true; } } const ReleasesCard = (props) => { const { t } = useTranslationRef(gitlabTranslationRef); const { title = t("releasesCard.title"), show = "all", limit = 6, sort = "releasedDate", showSortSelector = true } = props; const classes = useStyles(); const project_id = gitlabProjectId(); const project_slug = gitlabProjectSlug(); const gitlab_instance = gitlabInstance(); const [currentSortRule, setCurrentSortRule] = React.useState(sort); const GitlabCIAPI = useApi(GitlabCIApiRef).build( gitlab_instance || "gitlab.com" ); const { value, loading, error } = useAsync(async () => { const projectDetails = await GitlabCIAPI.getProjectDetails( project_slug || project_id ); if (!projectDetails) throw new Error("wrong project_slug or project_id"); const releaseData = await GitlabCIAPI.getReleasesSummary( projectDetails.id ); if (!releaseData) throw new Error("Release data are undefined!"); return { releases: releaseData, projectDetails }; }, []); const project_web_url = value?.projectDetails.web_url; if (loading) { return /* @__PURE__ */ React.createElement(Progress, null); } else if (error) { return /* @__PURE__ */ React.createElement(Alert, { severity: "error", className: classes.infoCard }, error.message); } let releases = []; if (value?.releases != null) { value?.releases.filter(makeFilter(show)).sort(sortFunctions[currentSortRule]).forEach((release) => { if (!valid(release.tag_name)) { releases.push(release); return; } const idx = releases.findIndex((value2) => { return release.tag_name.startsWith(value2.tag_name); }); if (idx < 0) releases.push(release); }); } releases = releases.slice(0, limit); if (releases.length === 0) { return /* @__PURE__ */ React.createElement( InfoCard, { title, deepLink: { link: `${project_web_url}/-/releases`, title: t("releasesCard.deepLinkTitle"), onClick: (e) => { e.preventDefault(); window.open(`${project_web_url}/-/releases`); } }, variant: props.variant, className: classes.infoCard }, /* @__PURE__ */ React.createElement(Typography, { variant: "body2" }, t("releasesCard.noReleases")) ); } const handleSortChange = (event) => { setCurrentSortRule(event.target.value); }; return /* @__PURE__ */ React.createElement( InfoCard, { title, deepLink: { link: `${project_web_url}/-/releases`, title: t("releasesCard.deepLinkTitle"), onClick: (e) => { e.preventDefault(); window.open(`${project_web_url}/-/releases`); } }, variant: props.variant, className: classes.infoCard }, /* @__PURE__ */ React.createElement(Grid, { container: true, spacing: 2, justifyContent: "flex-start" }, showSortSelector && /* @__PURE__ */ React.createElement("div", { className: classes.sortSelector }, /* @__PURE__ */ React.createElement( Select, { id: "release-sort-selector", value: currentSortRule, onChange: handleSortChange }, /* @__PURE__ */ React.createElement(MenuItem, { value: "releasedDate" }, t("releasesCard.releasedDate")), /* @__PURE__ */ React.createElement(MenuItem, { value: "releasedVersion" }, t("releasesCard.releasedVersion")) ), /* @__PURE__ */ React.createElement(SortIcon, null)), releases.map((release) => /* @__PURE__ */ React.createElement(Grid, { item: true, key: release.tag_name }, /* @__PURE__ */ React.createElement( Link, { href: project_web_url + "/-/releases/" + encodeURIComponent(release.tag_name), color: "inherit", target: "_blank", rel: "noopener noreferrer" }, /* @__PURE__ */ React.createElement("div", { className: classes.releaseTitle }, release.name), /* @__PURE__ */ React.createElement( LocalOfferOutlinedIcon, { fontSize: "inherit", className: classes.releaseTagIcon } ), release.tag_name )))) ); }; export { ReleasesCard }; //# sourceMappingURL=ReleasesCard.esm.js.map