Skip to content

Commit c9d8a8d

Browse files
authored
feat: github importer (#722)
* chore: github importer first step completed * refactor: github importer code refactored * chore: github importer functionality completed * fix: import data step saved data
1 parent 6b8b981 commit c9d8a8d

31 files changed

+1207
-714
lines changed

apps/app/components/core/board-view/board-header.tsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,9 @@ export const BoardHeader: React.FC<Props> = ({
142142
>
143143
{getGroupTitle()}
144144
</h2>
145-
<span className="ml-0.5 rounded-full bg-gray-100 py-1 px-3 text-sm">
145+
<span
146+
className={`${isCollapsed ? "ml-0.5" : ""} rounded-full bg-gray-100 py-1 px-3 text-sm`}
147+
>
146148
{groupedByIssues?.[groupTitle].length ?? 0}
147149
</span>
148150
</div>

apps/app/components/integration/github/auth.tsx

Lines changed: 6 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
11
import { FC, useRef, useState } from "react";
22

3+
// ui
4+
import { PrimaryButton } from "components/ui";
5+
36
type Props = {
47
workspaceSlug: string | undefined;
58
workspaceIntegration: any;
@@ -39,21 +42,11 @@ export const GithubAuth: FC<Props> = ({ workspaceSlug, workspaceIntegration }) =
3942
return (
4043
<div>
4144
{workspaceIntegration && workspaceIntegration?.id ? (
42-
<button
43-
type="button"
44-
className={`cursor-not-allowed rounded-sm bg-theme bg-opacity-80 px-3 py-1.5 text-sm text-white transition-colors`}
45-
>
46-
Successfully Connected
47-
</button>
45+
<PrimaryButton disabled>Successfully Connected</PrimaryButton>
4846
) : (
49-
<button
50-
onClick={startAuth}
51-
type="button"
52-
className={`rounded-sm bg-theme px-3 py-1.5 text-sm text-white transition-colors hover:bg-opacity-80`}
53-
disabled={authLoader}
54-
>
47+
<PrimaryButton onClick={startAuth} loading={authLoader}>
5548
{authLoader ? "Connecting..." : "Connect"}
56-
</button>
49+
</PrimaryButton>
5750
)}
5851
</div>
5952
);

apps/app/components/integration/github/configure.tsx

Lines changed: 0 additions & 74 deletions
This file was deleted.

apps/app/components/integration/github/confirm.tsx

Lines changed: 0 additions & 27 deletions
This file was deleted.
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
import { FC } from "react";
2+
3+
import { useRouter } from "next/router";
4+
5+
// components
6+
import { GithubAuth, TIntegrationSteps } from "components/integration";
7+
// ui
8+
import { PrimaryButton } from "components/ui";
9+
// types
10+
import { IAppIntegrations, IWorkspaceIntegrations } from "types";
11+
12+
type Props = {
13+
provider: string | undefined;
14+
handleStepChange: (value: TIntegrationSteps) => void;
15+
appIntegrations: IAppIntegrations[] | undefined;
16+
workspaceIntegrations: IWorkspaceIntegrations[] | undefined;
17+
};
18+
19+
export const GithubImportConfigure: FC<Props> = ({
20+
handleStepChange,
21+
provider,
22+
appIntegrations,
23+
workspaceIntegrations,
24+
}) => {
25+
const router = useRouter();
26+
const { workspaceSlug } = router.query;
27+
28+
// current integration from all the integrations available
29+
const integration =
30+
appIntegrations &&
31+
appIntegrations.length > 0 &&
32+
appIntegrations.find((i) => i.provider === provider);
33+
34+
// current integration from workspace integrations
35+
const workspaceIntegration =
36+
integration &&
37+
workspaceIntegrations &&
38+
workspaceIntegrations.length > 0 &&
39+
workspaceIntegrations.find((i: any) => i.integration_detail.id === integration.id);
40+
41+
return (
42+
<div className="space-y-6">
43+
<div className="flex items-center gap-2 py-5">
44+
<div className="w-full">
45+
<div className="font-medium">Configure</div>
46+
<div className="text-sm text-gray-600">Set up your GitHub import.</div>
47+
</div>
48+
<div className="flex-shrink-0">
49+
<GithubAuth
50+
workspaceSlug={workspaceSlug as string}
51+
workspaceIntegration={workspaceIntegration}
52+
/>
53+
</div>
54+
</div>
55+
56+
<div className="flex items-center justify-end">
57+
<PrimaryButton
58+
onClick={() => handleStepChange("import-data")}
59+
disabled={workspaceIntegration && workspaceIntegration?.id ? false : true}
60+
>
61+
Next
62+
</PrimaryButton>
63+
</div>
64+
</div>
65+
);
66+
};
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
import { FC } from "react";
2+
3+
// react-hook-form
4+
import { UseFormWatch } from "react-hook-form";
5+
// ui
6+
import { PrimaryButton, SecondaryButton } from "components/ui";
7+
// types
8+
import { TFormValues, TIntegrationSteps } from "components/integration";
9+
10+
type Props = {
11+
handleStepChange: (value: TIntegrationSteps) => void;
12+
watch: UseFormWatch<TFormValues>;
13+
};
14+
15+
export const GithubImportConfirm: FC<Props> = ({ handleStepChange, watch }) => (
16+
<div className="mt-6">
17+
<h4 className="font-medium">
18+
You are about to import issues from {watch("github").full_name}. Click on {'"'}Confirm &
19+
Import{'" '}
20+
to complete the process.
21+
</h4>
22+
<div className="mt-6 flex items-center justify-between">
23+
<SecondaryButton onClick={() => handleStepChange("import-users")}>Back</SecondaryButton>
24+
<PrimaryButton type="submit">Confirm & Import</PrimaryButton>
25+
</div>
26+
</div>
27+
);
Lines changed: 123 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,127 @@
1-
import { FC } from "react";
1+
import { FC, useState } from "react";
2+
3+
// react-hook-form
4+
import { Control, Controller, UseFormWatch } from "react-hook-form";
5+
// hooks
6+
import useProjects from "hooks/use-projects";
7+
// components
8+
import { SelectRepository, TFormValues, TIntegrationSteps } from "components/integration";
9+
// ui
10+
import { CustomSearchSelect, PrimaryButton, SecondaryButton } from "components/ui";
11+
// helpers
12+
import { truncateText } from "helpers/string.helper";
213
// types
3-
import { IIntegrationData } from "components/integration";
14+
import { IWorkspaceIntegrations } from "types";
15+
16+
type Props = {
17+
handleStepChange: (value: TIntegrationSteps) => void;
18+
integration: IWorkspaceIntegrations | false | undefined;
19+
control: Control<TFormValues, any>;
20+
watch: UseFormWatch<TFormValues>;
21+
};
22+
23+
export const GithubImportData: FC<Props> = ({ handleStepChange, integration, control, watch }) => {
24+
const { projects } = useProjects();
425

5-
type Props = { state: IIntegrationData; handleState: (key: string, valve: any) => void };
26+
const options =
27+
projects.map((project) => ({
28+
value: project.id,
29+
query: project.name,
30+
content: <p>{truncateText(project.name, 25)}</p>,
31+
})) ?? [];
632

7-
export const GithubImportData: FC<Props> = ({ state, handleState }) => (
8-
<div>
9-
<div>Import Data</div>
10-
<div className="mt-5 flex items-center justify-between">
11-
<button
12-
type="button"
13-
className={`rounded-sm bg-gray-300 px-3 py-1.5 text-sm transition-colors hover:bg-opacity-80`}
14-
onClick={() => handleState("state", "import-configure")}
15-
>
16-
Back
17-
</button>
18-
<button
19-
type="button"
20-
className={`rounded-sm bg-theme px-3 py-1.5 text-sm text-white transition-colors hover:bg-opacity-80`}
21-
onClick={() => handleState("state", "migrate-issues")}
22-
>
23-
Next
24-
</button>
33+
return (
34+
<div className="mt-6">
35+
<div className="space-y-8">
36+
<div className="grid grid-cols-12 gap-4 sm:gap-16">
37+
<div className="col-span-12 sm:col-span-8">
38+
<h4 className="font-semibold">Select Repository</h4>
39+
<p className="text-gray-500 text-xs">
40+
Select the repository that you want the issues to be imported from.
41+
</p>
42+
</div>
43+
<div className="col-span-12 sm:col-span-4">
44+
{integration && (
45+
<Controller
46+
control={control}
47+
name="github"
48+
render={({ field: { value, onChange } }) => (
49+
<SelectRepository
50+
integration={integration}
51+
value={value ? value.id : null}
52+
label={value ? `${value.full_name}` : "Select Repository"}
53+
onChange={onChange}
54+
characterLimit={50}
55+
/>
56+
)}
57+
/>
58+
)}
59+
</div>
60+
</div>
61+
<div className="grid grid-cols-12 gap-4 sm:gap-16">
62+
<div className="col-span-12 sm:col-span-8">
63+
<h4 className="font-semibold">Select Project</h4>
64+
<p className="text-gray-500 text-xs">Select the project to import the issues to.</p>
65+
</div>
66+
<div className="col-span-12 sm:col-span-4">
67+
{projects && (
68+
<Controller
69+
control={control}
70+
name="project"
71+
render={({ field: { value, onChange } }) => (
72+
<CustomSearchSelect
73+
value={value}
74+
label={value ? projects.find((p) => p.id === value)?.name : "Select Project"}
75+
onChange={onChange}
76+
options={options}
77+
optionsClassName="w-full"
78+
/>
79+
)}
80+
/>
81+
)}
82+
</div>
83+
</div>
84+
<div className="grid grid-cols-12 gap-4 sm:gap-16">
85+
<div className="col-span-12 sm:col-span-8">
86+
<h4 className="font-semibold">Sync Issues</h4>
87+
<p className="text-gray-500 text-xs">Set whether you want to sync the issues or not.</p>
88+
</div>
89+
<div className="col-span-12 sm:col-span-4">
90+
<Controller
91+
control={control}
92+
name="sync"
93+
render={({ field: { value, onChange } }) => (
94+
<button
95+
type="button"
96+
className={`relative inline-flex h-3.5 w-6 flex-shrink-0 cursor-pointer rounded-full border-2 border-transparent transition-colors duration-200 ease-in-out focus:outline-none ${
97+
value ? "bg-green-500" : "bg-gray-200"
98+
}`}
99+
role="switch"
100+
aria-checked={value ? true : false}
101+
onClick={() => onChange(!value)}
102+
>
103+
<span className="sr-only">Show empty groups</span>
104+
<span
105+
aria-hidden="true"
106+
className={`inline-block h-2.5 w-2.5 transform rounded-full bg-white shadow ring-0 transition duration-200 ease-in-out ${
107+
value ? "translate-x-2.5" : "translate-x-0"
108+
}`}
109+
/>
110+
</button>
111+
)}
112+
/>
113+
</div>
114+
</div>
115+
</div>
116+
<div className="mt-6 flex items-center justify-end gap-2">
117+
<SecondaryButton onClick={() => handleStepChange("import-configure")}>Back</SecondaryButton>
118+
<PrimaryButton
119+
onClick={() => handleStepChange("repo-details")}
120+
disabled={!watch("github") || !watch("project")}
121+
>
122+
Next
123+
</PrimaryButton>
124+
</div>
25125
</div>
26-
</div>
27-
);
126+
);
127+
};

0 commit comments

Comments
 (0)