Github integration (#6414)

Co-authored-by: Tom Moor <tom.moor@gmail.com>
This commit is contained in:
Apoorv Mishra
2024-03-23 19:39:28 +05:30
committed by GitHub
parent a648625700
commit 450d0d9355
47 changed files with 1710 additions and 93 deletions

View File

@@ -0,0 +1,26 @@
import * as React from "react";
type Props = {
/** The size of the icon, 24px is default to match standard icons */
size?: number;
/** The color of the icon, defaults to the current text color */
fill?: string;
};
export default function Icon({ size = 24, fill = "currentColor" }: Props) {
return (
<svg
fill={fill}
width={size}
height={size}
viewBox="0 0 24 24"
version="1.1"
>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M11.9762 4C7.56555 4 4 7.59184 4 12.0354C4 15.5874 6.28457 18.5941 9.45388 19.6583C9.85012 19.7383 9.99527 19.4854 9.99527 19.2727C9.99527 19.0864 9.9822 18.4478 9.9822 17.7825C7.76343 18.2616 7.30139 16.8247 7.30139 16.8247C6.94482 15.8934 6.41649 15.654 6.41649 15.654C5.69029 15.1618 6.46939 15.1618 6.46939 15.1618C7.27494 15.215 7.69763 15.9866 7.69763 15.9866C8.41061 17.2104 9.55951 16.8647 10.0217 16.6518C10.0877 16.1329 10.2991 15.7737 10.5236 15.5742C8.75396 15.3879 6.89208 14.6962 6.89208 11.6096C6.89208 10.7316 7.20882 10.0132 7.71069 9.45453C7.63151 9.25502 7.35412 8.43004 7.79004 7.32588C7.79004 7.32588 8.46351 7.11298 9.98204 8.15069C10.6322 7.9748 11.3027 7.88532 11.9762 7.88457C12.6496 7.88457 13.3362 7.9778 13.9701 8.15069C15.4888 7.11298 16.1623 7.32588 16.1623 7.32588C16.5982 8.43004 16.3207 9.25502 16.2415 9.45453C16.7566 10.0132 17.0602 10.7316 17.0602 11.6096C17.0602 14.6962 15.1984 15.3745 13.4155 15.5742C13.7061 15.8269 13.9569 16.3058 13.9569 17.0642C13.9569 18.1417 13.9438 19.0065 13.9438 19.2725C13.9438 19.4854 14.0891 19.7383 14.4852 19.6584C17.6545 18.594 19.9391 15.5874 19.9391 12.0354C19.9522 7.59184 16.3736 4 11.9762 4Z"
/>
</svg>
);
}

View File

@@ -0,0 +1,154 @@
import { observer } from "mobx-react";
import { PlusIcon } from "outline-icons";
import * as React from "react";
import { useTranslation, Trans } from "react-i18next";
import { IntegrationService } from "@shared/types";
import { ConnectedButton } from "~/scenes/Settings/components/ConnectedButton";
import { AvatarSize } from "~/components/Avatar/Avatar";
import Flex from "~/components/Flex";
import Heading from "~/components/Heading";
import List from "~/components/List";
import ListItem from "~/components/List/Item";
import Notice from "~/components/Notice";
import PlaceholderText from "~/components/PlaceholderText";
import Scene from "~/components/Scene";
import TeamLogo from "~/components/TeamLogo";
import Text from "~/components/Text";
import Time from "~/components/Time";
import env from "~/env";
import useQuery from "~/hooks/useQuery";
import useStores from "~/hooks/useStores";
import GitHubIcon from "./Icon";
import { GitHubConnectButton } from "./components/GitHubButton";
function GitHub() {
const { integrations } = useStores();
const { t } = useTranslation();
const query = useQuery();
const error = query.get("error");
const installRequest = query.get("install_request");
const appName = env.APP_NAME;
const githubAppName = env.GITHUB_APP_NAME;
React.useEffect(() => {
void integrations.fetchAll({
service: IntegrationService.GitHub,
withRelations: true,
});
}, [integrations]);
return (
<Scene title="GitHub" icon={<GitHubIcon />}>
<Heading>GitHub</Heading>
{error === "access_denied" && (
<Notice>
<Trans>
Whoops, you need to accept the permissions in GitHub to connect{" "}
{{ appName }} to your workspace. Try again?
</Trans>
</Notice>
)}
{error === "unauthenticated" && (
<Notice>
<Trans>
Something went wrong while authenticating your request. Please try
logging in again.
</Trans>
</Notice>
)}
{installRequest === "true" && (
<Notice>
<Trans>
The owner of GitHub account has been requested to install the{" "}
{{ githubAppName }} GitHub app. Once approved, previews will be
shown for respective links.
</Trans>
</Notice>
)}
{env.GITHUB_CLIENT_ID ? (
<>
<Text as="p">
<Trans>
Enable previews of GitHub issues and pull requests in documents by
connecting a GitHub organization or specific repositories to{" "}
{appName}.
</Trans>
</Text>
{integrations.github.length ? (
<>
<Heading as="h2">
<Flex justify="space-between" auto>
{t("Connected")}
<GitHubConnectButton icon={<PlusIcon />} />
</Flex>
</Heading>
<List>
{integrations.github.map((integration) => {
const githubAccount =
integration.settings?.github?.installation.account;
const integrationCreatedBy = integration.user
? integration.user.name
: undefined;
return (
<ListItem
key={githubAccount?.id}
small
title={githubAccount?.name}
subtitle={
integrationCreatedBy ? (
<>
<Trans>Enabled by {{ integrationCreatedBy }}</Trans>{" "}
&middot;{" "}
<Time
dateTime={integration.createdAt}
relative={false}
format={{ en_US: "MMMM d, y" }}
/>
</>
) : (
<PlaceholderText />
)
}
image={
<TeamLogo
src={githubAccount?.avatarUrl}
size={AvatarSize.Large}
showBorder={false}
/>
}
actions={
<ConnectedButton
onClick={integration.delete}
confirmationMessage={t(
"Disconnecting will prevent previewing GitHub links from this organization in documents. Are you sure?"
)}
/>
}
/>
);
})}
</List>
</>
) : (
<p>
<GitHubConnectButton icon={<GitHubIcon />} />
</p>
)}
</>
) : (
<Notice>
<Trans>
The GitHub integration is currently disabled. Please set the
associated environment variables and restart the server to enable
the integration.
</Trans>
</Notice>
)}
</Scene>
);
}
export default observer(GitHub);

View File

@@ -0,0 +1,21 @@
import * as React from "react";
import { useTranslation } from "react-i18next";
import Button, { type Props } from "~/components/Button";
import useCurrentTeam from "~/hooks/useCurrentTeam";
import { redirectTo } from "~/utils/urls";
import { GitHubUtils } from "../../shared/GitHubUtils";
export function GitHubConnectButton(props: Props<HTMLButtonElement>) {
const { t } = useTranslation();
const team = useCurrentTeam();
return (
<Button
onClick={() => redirectTo(GitHubUtils.authUrl(team.id))}
neutral
{...props}
>
{t("Connect")}
</Button>
);
}