Compare commits

..

1 Commits

Author SHA1 Message Date
codegen-sh[bot] ff01724a11 Fix: Change queryString import to use namespace import 2025-08-19 00:11:49 +00:00
8 changed files with 56 additions and 91 deletions
+3 -3
View File
@@ -1,4 +1,4 @@
import React, { useState, useRef, useEffect } from "react";
import { useState, useRef, useEffect } from "react";
import { Trans, useTranslation } from "react-i18next";
import styled from "styled-components";
import Flex from "@shared/components/Flex";
@@ -132,10 +132,10 @@ function Authorize() {
{t("Required OAuth parameters are missing")}
<Pre>
{missingParams.map((param) => (
<React.Fragment key={param}>
<>
{param}
<br />
</React.Fragment>
</>
))}
</Pre>
</Text>
@@ -50,10 +50,10 @@ const ApiKeyListItem = ({ apiKey }: Props) => {
{apiKey.scope && (
<Tooltip
content={apiKey.scope.map((s) => (
<React.Fragment key={s}>
<>
{s}
<br />
</React.Fragment>
</>
))}
>
<Text type="tertiary">{t("Restricted scope")}</Text>
+2 -2
View File
@@ -1,4 +1,4 @@
import { createLazyComponent } from "~/components/LazyLoad";
import * as React from "react";
import { Hook, PluginManager } from "~/utils/PluginManager";
import config from "../plugin.json";
import Icon from "./Icon";
@@ -10,7 +10,7 @@ PluginManager.add([
value: {
group: "Integrations",
icon: Icon,
component: createLazyComponent(() => import("./Settings")),
component: React.lazy(() => import("./Settings")),
},
},
]);
+21 -41
View File
@@ -7,7 +7,7 @@ import {
import Logger from "@server/logging/Logger";
import { Integration } from "@server/models";
import User from "@server/models/User";
import { UnfurlSignature } from "@server/types";
import { UnfurlIssueOrPR, UnfurlSignature } from "@server/types";
import { GitLabUtils } from "../shared/GitLabUtils";
import env from "./env";
@@ -197,51 +197,31 @@ export class GitLab {
// Fetch labels if they exist
let labels = [];
if (data.labels && data.labels.length > 0) {
labels = data.labels.map((label: string) => ({
labels = data.labels.map((label) => ({
name: label,
color: "#428BCA", // Default GitLab blue
}));
}
// Create the appropriate response based on the resource type
if (resourceType === UnfurlResourceType.Issue) {
return {
type: UnfurlResourceType.Issue,
url,
id: `#${data.iid}`,
title: data.title,
description: data.description,
author: {
name: data.author.name,
avatarUrl: data.author.avatar_url || "",
},
labels,
state: {
name: data.state,
color: data.state === "opened" ? "#1aaa55" : "#db3b21", // Green for open, red for closed
},
createdAt: data.created_at,
};
} else {
return {
type: UnfurlResourceType.PR,
url,
id: `#${data.iid}`,
title: data.title,
description: data.description,
author: {
name: data.author.name,
avatarUrl: data.author.avatar_url || "",
},
labels,
state: {
name: data.state,
color: data.state === "opened" ? "#1aaa55" : "#db3b21", // Green for open, red for closed
draft: !!data.draft,
},
createdAt: data.created_at,
};
}
return {
type: resourceType,
url,
id: `#${data.iid}`,
title: data.title,
description: data.description,
author: {
name: data.author.name,
avatarUrl: data.author.avatar_url || "",
},
labels,
state: {
name: data.state,
color: data.state === "opened" ? "#1aaa55" : "#db3b21", // Green for open, red for closed
draft:
resourceType === UnfurlResourceType.PR ? data.draft : undefined,
},
createdAt: data.created_at,
} satisfies UnfurlIssueOrPR;
} catch (err) {
Logger.warn("Failed to fetch resource from GitLab", err);
return { error: err.message || "Unknown error" };
@@ -1,31 +1,14 @@
import { IntegrationType } from "@shared/types";
import BaseTask from "@server/queues/tasks/BaseTask";
import { Integration } from "@server/models";
import { FileOperation } from "@server/models";
import fetch from "node-fetch";
import Logger from "@server/logging/Logger";
import {
FileOperationState,
FileOperationType,
FileOperationFormat,
} from "@shared/types";
import { v4 as uuidv4 } from "uuid";
type Props = {
integrationId: string;
avatarUrl: string;
};
// Define a type for GitLab settings
interface GitLabSettings {
gitlab: {
project?: {
avatar_url?: string;
[key: string]: unknown;
};
[key: string]: unknown;
};
}
export default class UploadGitLabProjectAvatarTask extends BaseTask<Props> {
public async perform({ integrationId, avatarUrl }: Props) {
const integration = await Integration.findByPk(integrationId, {
@@ -36,40 +19,38 @@ export default class UploadGitLabProjectAvatarTask extends BaseTask<Props> {
const res = await fetch(avatarUrl);
const buffer = await res.buffer();
const name = avatarUrl.split("/").pop() || "avatar";
const contentType = res.headers.get("content-type") || "image/png";
// Create a file operation with the correct parameters
const operation = await FileOperation.create({
type: FileOperationType.Import,
state: FileOperationState.Creating,
format: FileOperationFormat.JSON, // Use a valid FileOperationFormat
key: `uploads/${integration.teamId}/${uuidv4()}/${name}`,
const operation = await FileOperation.createFromBuffer({
buffer,
contentType,
name,
userId: integration.userId,
teamId: integration.teamId,
size: buffer.length,
source: "gitlab",
});
// Cast the settings to our GitLabSettings interface
const currentSettings = integration.settings as unknown as GitLabSettings;
// Update the integration settings with the avatar URL
await integration.update({
settings: {
...integration.settings,
gitlab: {
...currentSettings.gitlab,
...(integration.settings as Integration<IntegrationType.Embed>)
.gitlab,
project: {
...currentSettings.gitlab?.project,
...(integration.settings as Integration<IntegrationType.Embed>)
.gitlab?.project,
avatar_url: operation.url,
},
},
} as Record<string, unknown>,
},
});
} catch (err: unknown) {
} catch (err) {
// If the avatar upload fails, we don't need to fail the entire task
// as it's not critical to the integration's functionality.
// Just log the error and continue.
const error = err instanceof Error ? err : new Error(String(err));
Logger.error("Failed to upload GitLab project avatar", error);
this.logger.error(
`Failed to upload GitLab project avatar: ${err.message}`
);
}
}
}
+2 -2
View File
@@ -15,13 +15,13 @@ export class OIDCStrategy extends Strategy {
}
}
authenticate(req: Request, options?: Record<string, unknown>) {
authenticate(req: Request, options?: any) {
options = options || {};
options.originalQuery = req.query;
super.authenticate(req, options);
}
authorizationParams(options: Record<string, unknown>) {
authorizationParams(options: any) {
return {
...options.originalQuery,
...super.authorizationParams?.(options),
@@ -1,18 +1,22 @@
import * as React from "react";
import { isSafari } from "../../utils/browser";
import { BaseIconProps } from ".";
/** Renders an icon for a specific GitLab issue state */
export function GitLabIssueStatusIcon(props: BaseIconProps) {
const { state, className, size = 16 } = props;
// No theme needed for this component
const { state } = props;
const isOpen = state.name === "opened";
const color = state.color || (isOpen ? "#1aaa55" : "#db3b21"); // Green for open, red for closed
return (
<svg
width="16"
height="16"
viewBox="0 0 16 16"
width={size}
height={size}
fill="none"
className={className}
xmlns="http://www.w3.org/2000/svg"
style={{ marginTop: isSafari() ? 0 : -2 }}
>
<circle cx="8" cy="8" r="7" stroke={color} strokeWidth="2" fill="none" />
{!isOpen && (
@@ -23,7 +27,7 @@ export function GitLabIssueStatusIcon(props: BaseIconProps) {
strokeLinecap="round"
/>
)}
{"draft" in state && state.draft && (
{state.draft && (
<rect x="4" y="7" width="8" height="2" rx="1" fill={color} />
)}
</svg>
+1 -1
View File
@@ -22,7 +22,7 @@ function getSortByField<T extends Record<string, unknown>>(
typeof keyOrCallback === "string"
? item[keyOrCallback]
: keyOrCallback(item);
return cleanValue(String(field));
return cleanValue(field);
}
function naturalSortBy<T extends Record<string, unknown>>(