From 2b8647b2ef61d6eab8cfc34a629506131ca9df44 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Urs=20Kr=C3=B6ll?=
<109229014+UrsKroell@users.noreply.github.com>
Date: Fri, 22 Nov 2024 16:07:17 +0100
Subject: [PATCH] Feature: gitlab service widget (#4317)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
---
docs/widgets/services/gitlab.md | 20 +++++++++++++
docs/widgets/services/index.md | 1 +
mkdocs.yml | 1 +
public/locales/en/common.json | 6 ++++
src/utils/proxy/handlers/credentialed.js | 2 ++
src/widgets/components.js | 1 +
src/widgets/gitlab/component.jsx | 36 ++++++++++++++++++++++++
src/widgets/gitlab/widget.js | 13 +++++++++
src/widgets/widgets.js | 2 ++
9 files changed, 82 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 000000000..a92434d83
--- /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.
+
+Your Gitlab user ID can be found on [your profile page](https://support.circleci.com/hc/en-us/articles/20761157174043-How-to-find-your-GitLab-User-ID).
+
+Allowed fields: `["events", "issues", "merges", "projects"]`.
+
+```yaml
+widget:
+ type: gitlab
+ url: http://gitlab.host.or.ip:port
+ key: personal-access-token
+ user_id: 123456
+```
diff --git a/docs/widgets/services/index.md b/docs/widgets/services/index.md
index ae506f086..894a31f6e 100644
--- a/docs/widgets/services/index.md
+++ b/docs/widgets/services/index.md
@@ -41,6 +41,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 5b350d717..a19d3b839 100644
--- a/mkdocs.yml
+++ b/mkdocs.yml
@@ -64,6 +64,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 5abb9a4b9..484f76b5c 100644
--- a/public/locales/en/common.json
+++ b/public/locales/en/common.json
@@ -1001,5 +1001,11 @@
},
"spoolman": {
"loading": "Loading"
+ },
+ "gitlab": {
+ "groups": "Groups",
+ "issues": "Issues",
+ "merges": "Merge Requests",
+ "projects": "Projects"
}
}
diff --git a/src/utils/proxy/handlers/credentialed.js b/src/utils/proxy/handlers/credentialed.js
index 8d4340c2a..cbe0422ae 100644
--- a/src/utils/proxy/handlers/credentialed.js
+++ b/src/utils/proxy/handlers/credentialed.js
@@ -94,6 +94,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 bea37cf2e..19f41d4ae 100644
--- a/src/widgets/components.js
+++ b/src/widgets/components.js
@@ -38,6 +38,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 000000000..fb6f898f7
--- /dev/null
+++ b/src/widgets/gitlab/component.jsx
@@ -0,0 +1,36 @@
+import { useTranslation } from "next-i18next";
+
+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 { t } = useTranslation();
+ const { widget } = service;
+
+ const { data: gitlabCounts, error: gitlabCountsError } = useWidgetAPI(widget, "counts");
+
+ if (gitlabCountsError) {
+ return ;
+ }
+
+ if (!gitlabCounts) {
+ return (
+
+
+
+
+
+
+ );
+ }
+
+ return (
+
+
+
+
+
+
+ );
+}
diff --git a/src/widgets/gitlab/widget.js b/src/widgets/gitlab/widget.js
new file mode 100644
index 000000000..26f77a777
--- /dev/null
+++ b/src/widgets/gitlab/widget.js
@@ -0,0 +1,13 @@
+import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
+
+const widget = {
+ api: "{url}/api/v4/{endpoint}",
+ proxyHandler: credentialedProxyHandler,
+ mappings: {
+ counts: {
+ endpoint: "users/{user_id}/associations_count",
+ },
+ },
+};
+
+export default widget;
diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js
index 8eb3f51fc..9d4bb935d 100644
--- a/src/widgets/widgets.js
+++ b/src/widgets/widgets.js
@@ -32,6 +32,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";
@@ -164,6 +165,7 @@ const widgets = {
gatus,
ghostfolio,
gitea,
+ gitlab,
glances,
gluetun,
gotify,