From 26e2e152018039e4227198f305fd5372014a5e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Urs=20Kr=C3=B6ll?= Date: Sat, 16 Nov 2024 02:18:07 +0100 Subject: [PATCH] Add gitlab widget --- docs/widgets/services/gitlab.md | 20 ++++++++++ docs/widgets/services/index.md | 1 + mkdocs.yml | 1 + public/locales/en/common.json | 9 +++++ src/utils/proxy/handlers/credentialed.js | 2 + src/widgets/components.js | 1 + src/widgets/gitlab/component.jsx | 51 ++++++++++++++++++++++++ src/widgets/gitlab/widget.js | 39 ++++++++++++++++++ src/widgets/widgets.js | 2 + 9 files changed, 126 insertions(+) create mode 100644 docs/widgets/services/gitlab.md create mode 100644 src/widgets/gitlab/component.jsx create mode 100644 src/widgets/gitlab/widget.js diff --git a/docs/widgets/services/gitlab.md b/docs/widgets/services/gitlab.md new file mode 100644 index 00000000..32712963 --- /dev/null +++ b/docs/widgets/services/gitlab.md @@ -0,0 +1,20 @@ +--- +title: Gitlab +description: Gitlab Widget Configuration +--- + +Learn more about [Gitlab](https://gitlab.com). + +API requires a personal access token with either `read_api` or `api` permission. See the [gitlab documentation](https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html#create-a-personal-access-token) for details on generating one. + +Allowed fields: `["events", "issues", "openIssues", "closedIssues", "mergeRequests", "openMergeRequests", +"closedMergeRequests"]`. + +```yaml +widget: + type: gitlab + url: http://gitlab.host.or.ip:port + key: personal-access-token + issueState: all # supports "opened", "closed" and defaults to "all" + mergeRequestState: all # supports "opened", "closed", "locked" and defaults to "all" +``` diff --git a/docs/widgets/services/index.md b/docs/widgets/services/index.md index 8ea2e933..1de62be4 100644 --- a/docs/widgets/services/index.md +++ b/docs/widgets/services/index.md @@ -40,6 +40,7 @@ You can also find a list of all available service widgets in the sidebar navigat - [Gatus](gatus.md) - [Ghostfolio](ghostfolio.md) - [Gitea](gitea.md) +- [Gitlab](gitlab.md) - [Glances](glances.md) - [Gluetun](gluetun.md) - [Gotify](gotify.md) diff --git a/mkdocs.yml b/mkdocs.yml index 42abce30..58e54f49 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -63,6 +63,7 @@ nav: - widgets/services/gatus.md - widgets/services/ghostfolio.md - widgets/services/gitea.md + - widgets/services/gitlab.md - widgets/services/glances.md - widgets/services/gluetun.md - widgets/services/gotify.md diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 81576984..d219bcc3 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -988,5 +988,14 @@ "memory": "MEM", "disk": "Disk", "network": "NET" + }, + "gitlab": { + "events": "Events", + "issues": "Issues", + "issuesOpen": "Open Issues", + "issuesClosed": "Closed Issues", + "merges": "Merge Requests", + "mergesOpen": "Open Merge Requests", + "mergesClosed": "Closed Merge Requests" } } diff --git a/src/utils/proxy/handlers/credentialed.js b/src/utils/proxy/handlers/credentialed.js index eb2aab69..19185063 100644 --- a/src/utils/proxy/handlers/credentialed.js +++ b/src/utils/proxy/handlers/credentialed.js @@ -93,6 +93,8 @@ export default async function credentialedProxyHandler(req, res, map) { } } else if (widget.type === "wgeasy") { headers.Authorization = widget.password; + } else if (widget.type === "gitlab") { + headers["PRIVATE-TOKEN"] = widget.key } else { headers["X-API-Key"] = `${widget.key}`; } diff --git a/src/widgets/components.js b/src/widgets/components.js index 3cba84d2..4daa0c83 100644 --- a/src/widgets/components.js +++ b/src/widgets/components.js @@ -37,6 +37,7 @@ const components = { gatus: dynamic(() => import("./gatus/component")), ghostfolio: dynamic(() => import("./ghostfolio/component")), gitea: dynamic(() => import("./gitea/component")), + gitlab: dynamic(() => import("./gitlab/component")), glances: dynamic(() => import("./glances/component")), gluetun: dynamic(() => import("./gluetun/component")), gotify: dynamic(() => import("./gotify/component")), diff --git a/src/widgets/gitlab/component.jsx b/src/widgets/gitlab/component.jsx new file mode 100644 index 00000000..b6d3004d --- /dev/null +++ b/src/widgets/gitlab/component.jsx @@ -0,0 +1,51 @@ +import Container from "components/services/widget/container"; +import Block from "components/services/widget/block"; +import useWidgetAPI from "utils/proxy/use-widget-api"; + +export default function Component({ service }) { + const { widget } = service; + + const { data: gitlabEvents, error: gitlabEventsError } = useWidgetAPI(widget, "events"); + + if (gitlabEventsError) { + return ; + } + + if (!gitlabEvents) { + return ( + + + + + + + + + + ); + } + + const issues = { + open: gitlabEvents.issues.filter(event => event.action_name.toLowerCase() === "opened").length, + closed: gitlabEvents.issues.filter(event => event.action_name.toLowerCase() === "closed").length, + count: gitlabEvents.issues.length + }; + + const merges = { + open: gitlabEvents.merges.filter(event => event.action_name.toLowerCase() === "opened").length, + closed: gitlabEvents.merges.filter(event => event.action_name.toLowerCase() === "closed").length, + count: gitlabEvents.merges.length + }; + + return ( + + + + + + + + + + ); +} diff --git a/src/widgets/gitlab/widget.js b/src/widgets/gitlab/widget.js new file mode 100644 index 00000000..90d7336b --- /dev/null +++ b/src/widgets/gitlab/widget.js @@ -0,0 +1,39 @@ +import { asJson } from "utils/proxy/api-helpers"; +import credentialedProxyHandler from "utils/proxy/handlers/credentialed"; + +const widget = { + api: "{url}/api/v1/{endpoint}", + proxyHandler: credentialedProxyHandler, + mappings: { + events: { + endpoint: "events", + map: (data) => ({ + merges: asJson(data).filter((event) => event.target_type?.toLowerCase() === "merge_request"), + issues: asJson(data).filter((event) => event.target_type?.toLowerCase() === "issue"), + events: asJson(data).length + }) + }, + issues: { + endpoint: "issues", + params: ["state"] + }, + openIssues: { + endpoint: "issues?state=opened" + }, + closedIssues: { + endpoint: "issues?state=closed" + }, + mergeRequests: { + endpoint: "merge_requests", + params: ["state"] + }, + openMergeRequests: { + endpoint: "merge_requests?state=opened" + }, + closedMergeRequests: { + endpoint: "merge_requests?state=closed" + } + } +}; + +export default widget; diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js index 79110378..412f4cda 100644 --- a/src/widgets/widgets.js +++ b/src/widgets/widgets.js @@ -31,6 +31,7 @@ import gamedig from "./gamedig/widget"; import gatus from "./gatus/widget"; import ghostfolio from "./ghostfolio/widget"; import gitea from "./gitea/widget"; +import gitlab from "./gitlab/widget"; import glances from "./glances/widget"; import gluetun from "./gluetun/widget"; import gotify from "./gotify/widget"; @@ -161,6 +162,7 @@ const widgets = { gatus, ghostfolio, gitea, + gitlab, glances, gluetun, gotify,