forked from github/plane
Feat: Github importer to sync issues, users, and labels with workspace projects. (#509)
* Dev: Github integration with issues and layout integration * dev: Github Integration route and UI configuration
This commit is contained in:
parent
7892a563b7
commit
2f2caaaf6e
24
apps/app/components/icons/arrow-right.tsx
Normal file
24
apps/app/components/icons/arrow-right.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const ArrowRightIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
color = "#858E96",
|
||||
className,
|
||||
}) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
className={className}
|
||||
viewBox="0 0 16 10"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M10.9583 0.500103L15.0625 4.58344C15.1319 4.65288 15.1806 4.72232 15.2083 4.79177C15.2361 4.86121 15.25 4.9376 15.25 5.02094C15.25 5.10427 15.2361 5.18066 15.2083 5.2501C15.1806 5.31955 15.1319 5.38899 15.0625 5.45844L10.9583 9.5626C10.8472 9.67371 10.7014 9.73274 10.5208 9.73969C10.3403 9.74663 10.1875 9.6876 10.0625 9.5626C9.9375 9.4376 9.875 9.2883 9.875 9.11469C9.875 8.94108 9.9375 8.79177 10.0625 8.66677L13.0833 5.64594L1.125 5.64594C0.944443 5.64594 0.795138 5.58691 0.677083 5.46885C0.559026 5.3508 0.5 5.20149 0.5 5.02094C0.5 4.84038 0.559026 4.69108 0.677083 4.57302C0.795138 4.45496 0.944443 4.39594 1.125 4.39594L13.0833 4.39594L10.0625 1.3751C9.95139 1.26399 9.89236 1.12163 9.88542 0.94802C9.87847 0.774409 9.9375 0.625103 10.0625 0.500103C10.1875 0.375103 10.3368 0.312602 10.5104 0.312602C10.684 0.312602 10.8333 0.375103 10.9583 0.500103Z"
|
||||
fill={color}
|
||||
/>
|
||||
</svg>
|
||||
);
|
24
apps/app/components/icons/check.tsx
Normal file
24
apps/app/components/icons/check.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const CheckIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
color = "#858E96",
|
||||
className,
|
||||
}) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
className={className}
|
||||
viewBox="0 0 16 12"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill={color}
|
||||
d="M5.45005 11.5504C5.35005 11.5504 5.25838 11.5337 5.17505 11.5004C5.09172 11.4671 5.00838 11.4087 4.92505 11.3254L0.400049 6.80039C0.250049 6.65039 0.175049 6.46706 0.175049 6.25039C0.175049 6.03372 0.250049 5.85039 0.400049 5.70039C0.550049 5.55039 0.725049 5.47539 0.925049 5.47539C1.12505 5.47539 1.30005 5.55039 1.45005 5.70039L5.45005 9.70039L14.525 0.625391C14.675 0.475391 14.8542 0.400391 15.0625 0.400391C15.2709 0.400391 15.45 0.475391 15.6 0.625391C15.75 0.775391 15.825 0.954557 15.825 1.16289C15.825 1.37122 15.75 1.55039 15.6 1.70039L5.97505 11.3254C5.89172 11.4087 5.80838 11.4671 5.72505 11.5004C5.64172 11.5337 5.55005 11.5504 5.45005 11.5504Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
24
apps/app/components/icons/cloud-upload.tsx
Normal file
24
apps/app/components/icons/cloud-upload.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const CloudUploadIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
color = "#858E96",
|
||||
className,
|
||||
}) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
className={className}
|
||||
viewBox="0 0 22 16"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill={color}
|
||||
d="M5.25 16.0004C3.81667 16.0004 2.58333 15.4837 1.55 14.4504C0.516667 13.4171 0 12.1837 0 10.7504C0 9.45039 0.4125 8.30456 1.2375 7.31289C2.0625 6.32122 3.125 5.72539 4.425 5.52539C4.75833 3.90872 5.54167 2.58789 6.775 1.56289C8.00833 0.537891 9.43333 0.0253906 11.05 0.0253906C12.9333 0.0253906 14.5125 0.704557 15.7875 2.06289C17.0625 3.42122 17.7 5.05039 17.7 6.95039V7.55039C18.9 7.51706 19.9167 7.90456 20.75 8.71289C21.5833 9.52122 22 10.5421 22 11.7754C22 12.9254 21.5833 13.9171 20.75 14.7504C19.9167 15.5837 18.925 16.0004 17.775 16.0004H11.75C11.35 16.0004 11 15.8504 10.7 15.5504C10.4 15.2504 10.25 14.9004 10.25 14.5004V8.05039L8.7 9.60039C8.55 9.75039 8.375 9.82122 8.175 9.81289C7.975 9.80456 7.8 9.72539 7.65 9.57539C7.5 9.42539 7.425 9.24622 7.425 9.03789C7.425 8.82956 7.5 8.65039 7.65 8.50039L10.475 5.67539C10.5583 5.59206 10.6417 5.53372 10.725 5.50039C10.8083 5.46706 10.9 5.45039 11 5.45039C11.1 5.45039 11.1917 5.46706 11.275 5.50039C11.3583 5.53372 11.4417 5.59206 11.525 5.67539L14.375 8.52539C14.525 8.67539 14.6 8.85039 14.6 9.05039C14.6 9.25039 14.525 9.42539 14.375 9.57539C14.225 9.72539 14.0458 9.80039 13.8375 9.80039C13.6292 9.80039 13.45 9.72539 13.3 9.57539L11.75 8.05039V14.5004H17.775C18.525 14.5004 19.1667 14.2337 19.7 13.7004C20.2333 13.1671 20.5 12.5254 20.5 11.7754C20.5 11.0254 20.2333 10.3837 19.7 9.85039C19.1667 9.31706 18.525 9.05039 17.775 9.05039H16.2V6.95039C16.2 5.46706 15.6958 4.19206 14.6875 3.12539C13.6792 2.05872 12.4333 1.52539 10.95 1.52539C9.46667 1.52539 8.21667 2.05872 7.2 3.12539C6.18333 4.19206 5.675 5.46706 5.675 6.95039H5.2C4.16667 6.95039 3.29167 7.31289 2.575 8.03789C1.85833 8.76289 1.5 9.65872 1.5 10.7254C1.5 11.7587 1.86667 12.6462 2.6 13.3879C3.33333 14.1296 4.21667 14.5004 5.25 14.5004H8C8.21667 14.5004 8.39583 14.5712 8.5375 14.7129C8.67917 14.8546 8.75 15.0337 8.75 15.2504C8.75 15.4671 8.67917 15.6462 8.5375 15.7879C8.39583 15.9296 8.21667 16.0004 8 16.0004H5.25Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
24
apps/app/components/icons/cog.tsx
Normal file
24
apps/app/components/icons/cog.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const CogIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
color = "#858E96",
|
||||
className,
|
||||
}) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
className={className}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill={color}
|
||||
d="M11.65 20H8.34998C8.16664 20 8.00414 19.9417 7.86248 19.825C7.72081 19.7083 7.63331 19.5583 7.59998 19.375L7.19998 16.85C6.88331 16.7333 6.54998 16.575 6.19998 16.375C5.84998 16.175 5.54164 15.9667 5.27498 15.75L2.94998 16.825C2.76664 16.9083 2.58331 16.9208 2.39998 16.8625C2.21664 16.8042 2.07498 16.6833 1.97498 16.5L0.324976 13.575C0.224976 13.4083 0.199976 13.2333 0.249976 13.05C0.299976 12.8667 0.399976 12.7167 0.549976 12.6L2.69998 11.025C2.66664 10.875 2.64581 10.7042 2.63748 10.5125C2.62914 10.3208 2.62498 10.15 2.62498 10C2.62498 9.85 2.62914 9.67917 2.63748 9.4875C2.64581 9.29583 2.66664 9.125 2.69998 8.975L0.549976 7.4C0.399976 7.28333 0.299976 7.13333 0.249976 6.95C0.199976 6.76667 0.224976 6.59167 0.324976 6.425L1.97498 3.5C2.07498 3.31667 2.21664 3.19583 2.39998 3.1375C2.58331 3.07917 2.76664 3.09167 2.94998 3.175L5.27498 4.25C5.54164 4.03333 5.84998 3.825 6.19998 3.625C6.54998 3.425 6.88331 3.275 7.19998 3.175L7.59998 0.625C7.63331 0.441667 7.72081 0.291667 7.86248 0.175C8.00414 0.0583333 8.16664 0 8.34998 0H11.65C11.8333 0 11.9958 0.0583333 12.1375 0.175C12.2791 0.291667 12.3666 0.441667 12.4 0.625L12.8 3.15C13.1166 3.26667 13.4541 3.42083 13.8125 3.6125C14.1708 3.80417 14.475 4.01667 14.725 4.25L17.05 3.175C17.2333 3.09167 17.4166 3.07917 17.6 3.1375C17.7833 3.19583 17.925 3.31667 18.025 3.5L19.675 6.4C19.775 6.56667 19.8041 6.74583 19.7625 6.9375C19.7208 7.12917 19.6166 7.28333 19.45 7.4L17.3 8.925C17.3333 9.09167 17.3541 9.27083 17.3625 9.4625C17.3708 9.65417 17.375 9.83333 17.375 10C17.375 10.1667 17.3708 10.3417 17.3625 10.525C17.3541 10.7083 17.3333 10.8833 17.3 11.05L19.45 12.6C19.6 12.7167 19.7 12.8667 19.75 13.05C19.8 13.2333 19.775 13.4083 19.675 13.575L18.025 16.5C17.925 16.6833 17.7833 16.8042 17.6 16.8625C17.4166 16.9208 17.2333 16.9083 17.05 16.825L14.725 15.75C14.4583 15.9667 14.1541 16.1792 13.8125 16.3875C13.4708 16.5958 13.1333 16.75 12.8 16.85L12.4 19.375C12.3666 19.5583 12.2791 19.7083 12.1375 19.825C11.9958 19.9417 11.8333 20 11.65 20ZM9.99998 13.25C10.9 13.25 11.6666 12.9333 12.3 12.3C12.9333 11.6667 13.25 10.9 13.25 10C13.25 9.1 12.9333 8.33333 12.3 7.7C11.6666 7.06667 10.9 6.75 9.99998 6.75C9.09998 6.75 8.33331 7.06667 7.69998 7.7C7.06664 8.33333 6.74998 9.1 6.74998 10C6.74998 10.9 7.06664 11.6667 7.69998 12.3C8.33331 12.9333 9.09998 13.25 9.99998 13.25ZM9.99998 11.75C9.51664 11.75 9.10414 11.5792 8.76248 11.2375C8.42081 10.8958 8.24998 10.4833 8.24998 10C8.24998 9.51667 8.42081 9.10417 8.76248 8.7625C9.10414 8.42083 9.51664 8.25 9.99998 8.25C10.4833 8.25 10.8958 8.42083 11.2375 8.7625C11.5791 9.10417 11.75 9.51667 11.75 10C11.75 10.4833 11.5791 10.8958 11.2375 11.2375C10.8958 11.5792 10.4833 11.75 9.99998 11.75ZM8.89997 18.5H11.1L11.45 15.7C12 15.5667 12.5208 15.3583 13.0125 15.075C13.5041 14.7917 13.95 14.45 14.35 14.05L17 15.2L18 13.4L15.65 11.675C15.7166 11.3917 15.7708 11.1125 15.8125 10.8375C15.8541 10.5625 15.875 10.2833 15.875 10C15.875 9.71667 15.8583 9.4375 15.825 9.1625C15.7916 8.8875 15.7333 8.60833 15.65 8.325L18 6.6L17 4.8L14.35 5.95C13.9666 5.51667 13.5333 5.15417 13.05 4.8625C12.5666 4.57083 12.0333 4.38333 11.45 4.3L11.1 1.5H8.89997L8.54998 4.3C7.98331 4.41667 7.45414 4.61667 6.96248 4.9C6.47081 5.18333 6.03331 5.53333 5.64998 5.95L2.99998 4.8L1.99998 6.6L4.34998 8.325C4.28331 8.60833 4.22914 8.8875 4.18748 9.1625C4.14581 9.4375 4.12498 9.71667 4.12498 10C4.12498 10.2833 4.14581 10.5625 4.18748 10.8375C4.22914 11.1125 4.28331 11.3917 4.34998 11.675L1.99998 13.4L2.99998 15.2L5.64998 14.05C6.04998 14.45 6.49581 14.7917 6.98748 15.075C7.47914 15.3583 7.99998 15.5667 8.54998 15.7L8.89997 18.5Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
@ -2,27 +2,27 @@ import React from "react";
|
||||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const GithubIcon: React.FC<Props> = ({ width = "24", height = "24", className }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
className={className}
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g clipPath="url(#clip0_282_232)">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M10 0C4.475 0 0 4.475 0 10C0 14.425 2.8625 18.1625 6.8375 19.4875C7.3375 19.575 7.525 19.275 7.525 19.0125C7.525 18.775 7.5125 17.9875 7.5125 17.15C5 17.6125 4.35 16.5375 4.15 15.975C4.0375 15.6875 3.55 14.8 3.125 14.5625C2.775 14.375 2.275 13.9125 3.1125 13.9C3.9 13.8875 4.4625 14.625 4.65 14.925C5.55 16.4375 6.9875 16.0125 7.5625 15.75C7.65 15.1 7.9125 14.6625 8.2 14.4125C5.975 14.1625 3.65 13.3 3.65 9.475C3.65 8.3875 4.0375 7.4875 4.675 6.7875C4.575 6.5375 4.225 5.5125 4.775 4.1375C4.775 4.1375 5.6125 3.875 7.525 5.1625C8.325 4.9375 9.175 4.825 10.025 4.825C10.875 4.825 11.725 4.9375 12.525 5.1625C14.4375 3.8625 15.275 4.1375 15.275 4.1375C15.825 5.5125 15.475 6.5375 15.375 6.7875C16.0125 7.4875 16.4 8.375 16.4 9.475C16.4 13.3125 14.0625 14.1625 11.8375 14.4125C12.2 14.725 12.5125 15.325 12.5125 16.2625C12.5125 17.6 12.5 18.675 12.5 19.0125C12.5 19.275 12.6875 19.5875 13.1875 19.4875C15.1726 18.8173 16.8976 17.5414 18.1197 15.8395C19.3418 14.1375 19.9994 12.0952 20 10C20 4.475 15.525 0 10 0Z"
|
||||
fill="#858E96"
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_282_232">
|
||||
<rect width={width} height={height} />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
export const GithubIcon: React.FC<Props> = ({ width = "24", height = "24", className, color }) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
className={className}
|
||||
viewBox="0 0 24 24"
|
||||
fill="currentColor"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<g clipPath="url(#clip0_282_232)">
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M10 0C4.475 0 0 4.475 0 10C0 14.425 2.8625 18.1625 6.8375 19.4875C7.3375 19.575 7.525 19.275 7.525 19.0125C7.525 18.775 7.5125 17.9875 7.5125 17.15C5 17.6125 4.35 16.5375 4.15 15.975C4.0375 15.6875 3.55 14.8 3.125 14.5625C2.775 14.375 2.275 13.9125 3.1125 13.9C3.9 13.8875 4.4625 14.625 4.65 14.925C5.55 16.4375 6.9875 16.0125 7.5625 15.75C7.65 15.1 7.9125 14.6625 8.2 14.4125C5.975 14.1625 3.65 13.3 3.65 9.475C3.65 8.3875 4.0375 7.4875 4.675 6.7875C4.575 6.5375 4.225 5.5125 4.775 4.1375C4.775 4.1375 5.6125 3.875 7.525 5.1625C8.325 4.9375 9.175 4.825 10.025 4.825C10.875 4.825 11.725 4.9375 12.525 5.1625C14.4375 3.8625 15.275 4.1375 15.275 4.1375C15.825 5.5125 15.475 6.5375 15.375 6.7875C16.0125 7.4875 16.4 8.375 16.4 9.475C16.4 13.3125 14.0625 14.1625 11.8375 14.4125C12.2 14.725 12.5125 15.325 12.5125 16.2625C12.5125 17.6 12.5 18.675 12.5 19.0125C12.5 19.275 12.6875 19.5875 13.1875 19.4875C15.1726 18.8173 16.8976 17.5414 18.1197 15.8395C19.3418 14.1375 19.9994 12.0952 20 10C20 4.475 15.525 0 10 0Z"
|
||||
fill={color ? color : "#858E96"}
|
||||
/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_282_232">
|
||||
<rect width={width} height={height} />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
|
26
apps/app/components/icons/import-layers.tsx
Normal file
26
apps/app/components/icons/import-layers.tsx
Normal file
@ -0,0 +1,26 @@
|
||||
import React from "react";
|
||||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const ImportLayersIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
color = "#858E96",
|
||||
className,
|
||||
}) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
className={className}
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill={color}
|
||||
d="M10.6004 2.20111C10.6005 2.10308 10.5766 2.00653 10.5307 1.91989C10.4849 1.83325 10.4185 1.75916 10.3374 1.7041C10.2563 1.64905 10.1629 1.6147 10.0655 1.60407C9.96803 1.59343 9.86946 1.60684 9.77839 1.64311L2.73799 4.43191C2.4024 4.56473 2.11449 4.79536 1.91163 5.09387C1.70877 5.39239 1.60033 5.74499 1.60039 6.10591V12.9963C1.60037 13.0942 1.6243 13.1906 1.67009 13.2771C1.71587 13.3636 1.78212 13.4376 1.86306 13.4926C1.94401 13.5476 2.03718 13.582 2.13446 13.5928C2.23175 13.6035 2.33018 13.5903 2.42119 13.5543L2.80039 13.4043V14.6943C2.52882 14.7903 2.23817 14.8198 1.95286 14.7802C1.66756 14.7405 1.39592 14.633 1.16078 14.4667C0.925631 14.3003 0.733846 14.0799 0.601533 13.8241C0.469219 13.5682 0.40024 13.2844 0.400391 12.9963V6.10591C0.400286 5.50438 0.581015 4.91671 0.919115 4.41919C1.25722 3.92166 1.73707 3.53727 2.29639 3.31591L9.33679 0.527108C9.60109 0.42232 9.88645 0.38163 10.1695 0.40837C10.4526 0.435109 10.7252 0.528518 10.9652 0.680946C11.2052 0.833374 11.4057 1.04049 11.5503 1.28532C11.6948 1.53015 11.7793 1.80574 11.7968 2.08951L10.5992 2.56231V2.20111H10.6004ZM14.2004 4.60111C14.2003 4.50318 14.1762 4.40677 14.1303 4.32029C14.0844 4.23381 14.018 4.15988 13.9369 4.10496C13.8558 4.05005 13.7625 4.01581 13.6652 4.00523C13.5678 3.99466 13.4694 4.00808 13.3784 4.04431L5.95879 6.98311C5.73506 7.07165 5.54312 7.22541 5.40788 7.42442C5.27264 7.62343 5.20035 7.8585 5.20039 8.09911V15.3975C5.20037 15.4954 5.2243 15.5918 5.27009 15.6783C5.31587 15.7648 5.38212 15.8388 5.46307 15.8938C5.54401 15.9488 5.63718 15.9832 5.73447 15.994C5.83175 16.0047 5.93018 15.9915 6.02119 15.9555L7.60039 15.3279V16.6191L6.46399 17.0691C6.1911 17.1773 5.89587 17.2172 5.60405 17.1852C5.31223 17.1531 5.03267 17.0502 4.78974 16.8854C4.54681 16.7206 4.34788 16.4988 4.2103 16.2395C4.07272 15.9801 4.00065 15.6911 4.00039 15.3975V8.09791C4.00031 7.61668 4.14489 7.14655 4.41537 6.74853C4.68585 6.35051 5.06974 6.043 5.51719 5.86591L12.9368 2.92831C13.2096 2.82033 13.5047 2.78068 13.7964 2.81283C14.088 2.84497 14.3674 2.94793 14.6102 3.11273C14.853 3.27753 15.0518 3.49919 15.1893 3.75839C15.3268 4.01759 15.3989 4.30648 15.3992 4.59991V4.72351L14.2004 5.19991V4.59991V4.60111ZM17.5796 6.44311C17.6705 6.40713 17.7688 6.39391 17.866 6.4046C17.9632 6.4153 18.0563 6.44958 18.1372 6.50447C18.2181 6.55936 18.2844 6.63319 18.3303 6.71954C18.3761 6.80589 18.4002 6.90213 18.4004 6.99991V14.9487C18.4002 15.0688 18.3639 15.1861 18.2963 15.2853C18.2287 15.3846 18.1329 15.4613 18.0212 15.5055L10.8212 18.3579C10.7302 18.3939 10.6318 18.4071 10.5345 18.3964C10.4372 18.3856 10.344 18.3512 10.2631 18.2962C10.1821 18.2412 10.1159 18.1672 10.0701 18.0807C10.0243 17.9942 10.0004 17.8978 10.0004 17.7999V9.85231C10.0004 9.732 10.0365 9.61447 10.1041 9.51496C10.1718 9.41546 10.2677 9.33858 10.3796 9.29431L17.5796 6.44311ZM19.6004 6.99991C19.6003 6.70638 19.5283 6.41735 19.3909 6.15799C19.2535 5.89863 19.0547 5.67681 18.8119 5.51187C18.5691 5.34693 18.2896 5.24386 17.9979 5.21166C17.7061 5.17946 17.4109 5.21909 17.138 5.32711L9.93799 8.17831C9.6024 8.31113 9.31449 8.54176 9.11163 8.84028C8.90877 9.13879 8.80033 9.49139 8.80039 9.85231V17.7999C8.80034 18.0935 8.87212 18.3827 9.00948 18.6422C9.14683 18.9018 9.34559 19.1237 9.58841 19.2888C9.83124 19.4539 10.1108 19.5571 10.4026 19.5893C10.6945 19.6216 10.9898 19.582 11.2628 19.4739L18.4628 16.6215C18.7982 16.4888 19.086 16.2583 19.2888 15.96C19.4917 15.6618 19.6002 15.3094 19.6004 14.9487V6.99991Z"
|
||||
stroke={color}
|
||||
strokeWidth="0.25"
|
||||
/>
|
||||
</svg>
|
||||
);
|
@ -45,3 +45,9 @@ export * from "./people-group-icon";
|
||||
export * from "./cmd-icon";
|
||||
export * from "./view-list-icon";
|
||||
export * from "./exclamation-icon";
|
||||
export * from "./arrow-right";
|
||||
export * from "./cog";
|
||||
export * from "./cloud-upload";
|
||||
export * from "./users";
|
||||
export * from "./import-layers";
|
||||
export * from "./check";
|
||||
|
24
apps/app/components/icons/users.tsx
Normal file
24
apps/app/components/icons/users.tsx
Normal file
@ -0,0 +1,24 @@
|
||||
import React from "react";
|
||||
|
||||
import type { Props } from "./types";
|
||||
|
||||
export const UsersIcon: React.FC<Props> = ({
|
||||
width = "24",
|
||||
height = "24",
|
||||
color = "#858E96",
|
||||
className,
|
||||
}) => (
|
||||
<svg
|
||||
width={width}
|
||||
height={height}
|
||||
className={className}
|
||||
viewBox="0 0 20 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
fill={color}
|
||||
d="M12.754 7C13.72 7 14.504 7.784 14.504 8.75V13.499C14.504 14.6927 14.0298 15.8376 13.1857 16.6817C12.3416 17.5258 11.1967 18 10.003 18C8.80926 18 7.66441 17.5258 6.82031 16.6817C5.97621 15.8376 5.502 14.6927 5.502 13.499V8.75C5.502 7.784 6.285 7 7.252 7H12.754ZM12.754 8.5H7.252C7.1857 8.5 7.12211 8.52634 7.07522 8.57322C7.02834 8.62011 7.002 8.6837 7.002 8.75V13.499C7.002 14.2949 7.31818 15.0582 7.88097 15.621C8.44377 16.1838 9.20709 16.5 10.003 16.5C10.7989 16.5 11.5622 16.1838 12.125 15.621C12.6878 15.0582 13.004 14.2949 13.004 13.499V8.75C13.004 8.6837 12.9777 8.62011 12.9308 8.57322C12.8839 8.52634 12.8203 8.5 12.754 8.5ZM1.75 7H5.131C4.7782 7.42609 4.56274 7.94905 4.513 8.5H1.75C1.6837 8.5 1.62011 8.52634 1.57322 8.57322C1.52634 8.62011 1.5 8.6837 1.5 8.75V11.999C1.49994 12.3769 1.5855 12.7499 1.75027 13.0899C1.91504 13.43 2.15473 13.7283 2.45133 13.9625C2.74793 14.1966 3.09374 14.3605 3.46277 14.4418C3.83179 14.5231 4.21445 14.5198 4.582 14.432C4.667 14.936 4.822 15.417 5.035 15.864C4.44228 16.0226 3.82103 16.0427 3.21929 15.9228C2.61756 15.8029 2.05145 15.5463 1.56475 15.1727C1.07805 14.7991 0.683789 14.3185 0.412463 13.7682C0.141138 13.2179 1.22998e-05 12.6126 0 11.999V8.75C0 7.784 0.784 7 1.75 7ZM14.875 7H18.25C19.216 7 20 7.784 20 8.75V12C20.0001 12.6132 19.8593 13.2182 19.5884 13.7682C19.3175 14.3183 18.9237 14.7987 18.4376 15.1724C17.9514 15.546 17.3858 15.8029 16.7846 15.9232C16.1833 16.0435 15.5625 16.0239 14.97 15.866C15.184 15.418 15.339 14.937 15.425 14.433C15.7921 14.5198 16.174 14.5223 16.5423 14.4405C16.9105 14.3587 17.2554 14.1946 17.5512 13.9606C17.847 13.7265 18.086 13.4286 18.2503 13.089C18.4147 12.7495 18.5 12.3772 18.5 12V8.75C18.5 8.6837 18.4737 8.62011 18.4268 8.57322C18.3799 8.52634 18.3163 8.5 18.25 8.5H15.493C15.4433 7.94905 15.2278 7.42609 14.875 7ZM10 0C10.7956 0 11.5587 0.316071 12.1213 0.87868C12.6839 1.44129 13 2.20435 13 3C13 3.79565 12.6839 4.55871 12.1213 5.12132C11.5587 5.68393 10.7956 6 10 6C9.20435 6 8.44129 5.68393 7.87868 5.12132C7.31607 4.55871 7 3.79565 7 3C7 2.20435 7.31607 1.44129 7.87868 0.87868C8.44129 0.316071 9.20435 0 10 0ZM16.5 1C17.163 1 17.7989 1.26339 18.2678 1.73223C18.7366 2.20107 19 2.83696 19 3.5C19 4.16304 18.7366 4.79893 18.2678 5.26777C17.7989 5.73661 17.163 6 16.5 6C15.837 6 15.2011 5.73661 14.7322 5.26777C14.2634 4.79893 14 4.16304 14 3.5C14 2.83696 14.2634 2.20107 14.7322 1.73223C15.2011 1.26339 15.837 1 16.5 1ZM3.5 1C4.16304 1 4.79893 1.26339 5.26777 1.73223C5.73661 2.20107 6 2.83696 6 3.5C6 4.16304 5.73661 4.79893 5.26777 5.26777C4.79893 5.73661 4.16304 6 3.5 6C2.83696 6 2.20107 5.73661 1.73223 5.26777C1.26339 4.79893 1 4.16304 1 3.5C1 2.83696 1.26339 2.20107 1.73223 1.73223C2.20107 1.26339 2.83696 1 3.5 1ZM10 1.5C9.60218 1.5 9.22064 1.65804 8.93934 1.93934C8.65804 2.22064 8.5 2.60218 8.5 3C8.5 3.39782 8.65804 3.77936 8.93934 4.06066C9.22064 4.34196 9.60218 4.5 10 4.5C10.3978 4.5 10.7794 4.34196 11.0607 4.06066C11.342 3.77936 11.5 3.39782 11.5 3C11.5 2.60218 11.342 2.22064 11.0607 1.93934C10.7794 1.65804 10.3978 1.5 10 1.5ZM16.5 2.5C16.2348 2.5 15.9804 2.60536 15.7929 2.79289C15.6054 2.98043 15.5 3.23478 15.5 3.5C15.5 3.76522 15.6054 4.01957 15.7929 4.20711C15.9804 4.39464 16.2348 4.5 16.5 4.5C16.7652 4.5 17.0196 4.39464 17.2071 4.20711C17.3946 4.01957 17.5 3.76522 17.5 3.5C17.5 3.23478 17.3946 2.98043 17.2071 2.79289C17.0196 2.60536 16.7652 2.5 16.5 2.5ZM3.5 2.5C3.23478 2.5 2.98043 2.60536 2.79289 2.79289C2.60536 2.98043 2.5 3.23478 2.5 3.5C2.5 3.76522 2.60536 4.01957 2.79289 4.20711C2.98043 4.39464 3.23478 4.5 3.5 4.5C3.76522 4.5 4.01957 4.39464 4.20711 4.20711C4.39464 4.01957 4.5 3.76522 4.5 3.5C4.5 3.23478 4.39464 2.98043 4.20711 2.79289C4.01957 2.60536 3.76522 2.5 3.5 2.5Z"
|
||||
/>
|
||||
</svg>
|
||||
);
|
60
apps/app/components/integration/github/auth.tsx
Normal file
60
apps/app/components/integration/github/auth.tsx
Normal file
@ -0,0 +1,60 @@
|
||||
import { FC, useRef, useState } from "react";
|
||||
|
||||
type Props = {
|
||||
workspaceSlug: string | undefined;
|
||||
workspaceIntegration: any;
|
||||
};
|
||||
|
||||
export const GithubAuth: FC<Props> = ({ workspaceSlug, workspaceIntegration }) => {
|
||||
const popup = useRef<any>();
|
||||
const [authLoader, setAuthLoader] = useState(false);
|
||||
|
||||
const checkPopup = () => {
|
||||
const check = setInterval(() => {
|
||||
if (!popup || popup.current.closed || popup.current.closed === undefined) {
|
||||
clearInterval(check);
|
||||
setAuthLoader(false);
|
||||
}
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
const openPopup = () => {
|
||||
const width = 600,
|
||||
height = 600;
|
||||
const left = window.innerWidth / 2 - width / 2;
|
||||
const top = window.innerHeight / 2 - height / 2;
|
||||
const url = `https://github.com/apps/${
|
||||
process.env.NEXT_PUBLIC_GITHUB_APP_NAME
|
||||
}/installations/new?state=${workspaceSlug as string}`;
|
||||
|
||||
return window.open(url, "", `width=${width}, height=${height}, top=${top}, left=${left}`);
|
||||
};
|
||||
|
||||
const startAuth = () => {
|
||||
popup.current = openPopup();
|
||||
checkPopup();
|
||||
setAuthLoader(true);
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
{workspaceIntegration && workspaceIntegration?.id ? (
|
||||
<button
|
||||
type="button"
|
||||
className={`cursor-not-allowed rounded-sm bg-theme bg-opacity-80 px-3 py-1.5 text-sm text-white transition-colors`}
|
||||
>
|
||||
Successfully Connected
|
||||
</button>
|
||||
) : (
|
||||
<button
|
||||
onClick={startAuth}
|
||||
type="button"
|
||||
className={`rounded-sm bg-theme px-3 py-1.5 text-sm text-white transition-colors hover:bg-opacity-80`}
|
||||
disabled={authLoader}
|
||||
>
|
||||
{authLoader ? "Connecting..." : "Connect"}
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
};
|
74
apps/app/components/integration/github/configure.tsx
Normal file
74
apps/app/components/integration/github/configure.tsx
Normal file
@ -0,0 +1,74 @@
|
||||
import { FC } from "react";
|
||||
// components
|
||||
import { IIntegrationData, GithubAuth } from "components/integration";
|
||||
// types
|
||||
import { IAppIntegrations } from "types";
|
||||
|
||||
type Props = {
|
||||
state: IIntegrationData;
|
||||
provider: string | undefined;
|
||||
handleState: (key: string, valve: any) => void;
|
||||
workspaceSlug: string | undefined;
|
||||
allIntegrations: IAppIntegrations[] | undefined;
|
||||
allIntegrationsError: Error | undefined;
|
||||
allWorkspaceIntegrations: any | undefined;
|
||||
allWorkspaceIntegrationsError: Error | undefined;
|
||||
};
|
||||
|
||||
export const GithubConfigure: FC<Props> = ({
|
||||
state,
|
||||
handleState,
|
||||
workspaceSlug,
|
||||
provider,
|
||||
allIntegrations,
|
||||
allIntegrationsError,
|
||||
allWorkspaceIntegrations,
|
||||
allWorkspaceIntegrationsError,
|
||||
}) => {
|
||||
// current integration from all the integrations available
|
||||
const integration =
|
||||
allIntegrations &&
|
||||
allIntegrations.length > 0 &&
|
||||
allIntegrations.find((_integration) => _integration.provider === provider);
|
||||
|
||||
// current integration from workspace integrations
|
||||
const workspaceIntegration =
|
||||
integration &&
|
||||
allWorkspaceIntegrations &&
|
||||
allWorkspaceIntegrations.length > 0 &&
|
||||
allWorkspaceIntegrations.find(
|
||||
(_integration: any) => _integration.integration_detail.id === integration.id
|
||||
);
|
||||
|
||||
console.log("integration", integration);
|
||||
console.log("workspaceIntegration", workspaceIntegration);
|
||||
|
||||
return (
|
||||
<div className="space-y-5">
|
||||
<div className="flex items-center gap-2 py-5">
|
||||
<div className="w-full">
|
||||
<div className="font-medium">Configure</div>
|
||||
<div className="text-sm text-gray-600">Set up your Github import</div>
|
||||
</div>
|
||||
<div className="flex-shrink-0">
|
||||
<GithubAuth workspaceSlug={workspaceSlug} workspaceIntegration={workspaceIntegration} />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex items-center justify-end">
|
||||
<button
|
||||
type="button"
|
||||
className={`rounded-sm bg-theme px-3 py-1.5 text-sm text-white transition-colors hover:bg-opacity-80 ${
|
||||
workspaceIntegration && workspaceIntegration?.id
|
||||
? `bg-opacity-100`
|
||||
: `cursor-not-allowed bg-opacity-80`
|
||||
}`}
|
||||
onClick={() => handleState("state", "import-import-data")}
|
||||
disabled={workspaceIntegration && workspaceIntegration?.id ? false : true}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
27
apps/app/components/integration/github/confirm.tsx
Normal file
27
apps/app/components/integration/github/confirm.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import { FC } from "react";
|
||||
// types
|
||||
import { IIntegrationData } from "components/integration";
|
||||
|
||||
type Props = { state: IIntegrationData; handleState: (key: string, valve: any) => void };
|
||||
|
||||
export const GithubConfirm: FC<Props> = ({ state, handleState }) => (
|
||||
<>
|
||||
<div>Confirm</div>
|
||||
<div className="mt-5 flex items-center justify-between">
|
||||
<button
|
||||
type="button"
|
||||
className={`rounded-sm bg-gray-300 px-3 py-1.5 text-sm transition-colors hover:bg-opacity-80`}
|
||||
onClick={() => handleState("state", "migrate-users")}
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`rounded-sm bg-theme px-3 py-1.5 text-sm text-white transition-colors hover:bg-opacity-80`}
|
||||
onClick={() => handleState("state", "migrate-confirm")}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</>
|
||||
);
|
27
apps/app/components/integration/github/import-data.tsx
Normal file
27
apps/app/components/integration/github/import-data.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import { FC } from "react";
|
||||
// types
|
||||
import { IIntegrationData } from "components/integration";
|
||||
|
||||
type Props = { state: IIntegrationData; handleState: (key: string, valve: any) => void };
|
||||
|
||||
export const GithubImportData: FC<Props> = ({ state, handleState }) => (
|
||||
<div>
|
||||
<div>Import Data</div>
|
||||
<div className="mt-5 flex items-center justify-between">
|
||||
<button
|
||||
type="button"
|
||||
className={`rounded-sm bg-gray-300 px-3 py-1.5 text-sm transition-colors hover:bg-opacity-80`}
|
||||
onClick={() => handleState("state", "import-configure")}
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`rounded-sm bg-theme px-3 py-1.5 text-sm text-white transition-colors hover:bg-opacity-80`}
|
||||
onClick={() => handleState("state", "migrate-issues")}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
27
apps/app/components/integration/github/issues-select.tsx
Normal file
27
apps/app/components/integration/github/issues-select.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import { FC } from "react";
|
||||
// types
|
||||
import { IIntegrationData } from "components/integration";
|
||||
|
||||
type Props = { state: IIntegrationData; handleState: (key: string, valve: any) => void };
|
||||
|
||||
export const GithubIssuesSelect: FC<Props> = ({ state, handleState }) => (
|
||||
<div>
|
||||
<div>Issues Select</div>
|
||||
<div className="mt-5 flex items-center justify-between">
|
||||
<button
|
||||
type="button"
|
||||
className={`rounded-sm bg-gray-300 px-3 py-1.5 text-sm transition-colors hover:bg-opacity-80`}
|
||||
onClick={() => handleState("state", "import-import-data")}
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`rounded-sm bg-theme px-3 py-1.5 text-sm text-white transition-colors hover:bg-opacity-80`}
|
||||
onClick={() => handleState("state", "migrate-users")}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
168
apps/app/components/integration/github/root.tsx
Normal file
168
apps/app/components/integration/github/root.tsx
Normal file
@ -0,0 +1,168 @@
|
||||
import { FC, useState } from "react";
|
||||
// next imports
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
// icons
|
||||
import GithubLogo from "public/logos/github-square.png";
|
||||
import { CogIcon, CloudUploadIcon, UsersIcon, ImportLayersIcon, CheckIcon } from "components/icons";
|
||||
import { ArrowLeftIcon } from "@heroicons/react/24/outline";
|
||||
// components
|
||||
import {
|
||||
GithubConfigure,
|
||||
GithubImportData,
|
||||
GithubIssuesSelect,
|
||||
GithubUsersSelect,
|
||||
GithubConfirm,
|
||||
} from "components/integration";
|
||||
// types
|
||||
import { IAppIntegrations } from "types";
|
||||
|
||||
type Props = {
|
||||
workspaceSlug: string | undefined;
|
||||
provider: string | undefined;
|
||||
allIntegrations: IAppIntegrations[] | undefined;
|
||||
allIntegrationsError: Error | undefined;
|
||||
allWorkspaceIntegrations: any | undefined;
|
||||
allWorkspaceIntegrationsError: Error | undefined;
|
||||
allIntegrationImporters: any | undefined;
|
||||
allIntegrationImportersError: Error | undefined;
|
||||
};
|
||||
|
||||
export interface IIntegrationData {
|
||||
state: string;
|
||||
}
|
||||
|
||||
export const GithubIntegrationRoot: FC<Props> = ({
|
||||
workspaceSlug,
|
||||
provider,
|
||||
allIntegrations,
|
||||
allIntegrationsError,
|
||||
allWorkspaceIntegrations,
|
||||
allWorkspaceIntegrationsError,
|
||||
allIntegrationImporters,
|
||||
allIntegrationImportersError,
|
||||
}) => {
|
||||
const integrationWorkflowData = [
|
||||
{
|
||||
title: "Configure",
|
||||
key: "import-configure",
|
||||
icon: CogIcon,
|
||||
},
|
||||
{
|
||||
title: "Import Data",
|
||||
key: "import-import-data",
|
||||
icon: CloudUploadIcon,
|
||||
},
|
||||
{ title: "Issues", key: "migrate-issues", icon: UsersIcon },
|
||||
{
|
||||
title: "Users",
|
||||
key: "migrate-users",
|
||||
icon: ImportLayersIcon,
|
||||
},
|
||||
{
|
||||
title: "Confirm",
|
||||
key: "migrate-confirm",
|
||||
icon: CheckIcon,
|
||||
},
|
||||
];
|
||||
const activeIntegrationState = () => {
|
||||
const currentElementIndex = integrationWorkflowData.findIndex(
|
||||
(_item) => _item?.key === integrationData?.state
|
||||
);
|
||||
|
||||
return currentElementIndex;
|
||||
};
|
||||
|
||||
const [integrationData, setIntegrationData] = useState<IIntegrationData>({
|
||||
state: "import-configure",
|
||||
});
|
||||
const handleIntegrationData = (key: string = "state", value: string) => {
|
||||
setIntegrationData((previousData) => ({ ...previousData, [key]: value }));
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="space-y-4">
|
||||
<Link href={`/${workspaceSlug}/settings/import-export`}>
|
||||
<div className="inline-flex cursor-pointer items-center gap-2 text-sm font-medium text-gray-600 hover:text-gray-900">
|
||||
<div>
|
||||
<ArrowLeftIcon className="h-3 w-3" />
|
||||
</div>
|
||||
<div>Back</div>
|
||||
</div>
|
||||
</Link>
|
||||
|
||||
<div className="space-y-4 rounded border border-gray-200 bg-white p-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-10 w-10 flex-shrink-0">
|
||||
<Image src={GithubLogo} alt="GithubLogo" />
|
||||
</div>
|
||||
<div className="flex h-full w-full items-center justify-center">
|
||||
{integrationWorkflowData.map((_integration, _idx) => (
|
||||
<>
|
||||
<div
|
||||
key={_integration?.key}
|
||||
className={`flex h-10 w-10 flex-shrink-0 items-center justify-center rounded-full border
|
||||
${
|
||||
_idx <= activeIntegrationState()
|
||||
? `border-[#3F76FF] bg-[#3F76FF] text-white ${
|
||||
_idx === activeIntegrationState()
|
||||
? `border-opacity-100 bg-opacity-100`
|
||||
: `border-opacity-80 bg-opacity-80`
|
||||
}`
|
||||
: `border-gray-300`
|
||||
}
|
||||
`}
|
||||
>
|
||||
<_integration.icon
|
||||
width={`18px`}
|
||||
height={`18px`}
|
||||
color={_idx <= activeIntegrationState() ? "#ffffff" : "#d1d5db"}
|
||||
/>
|
||||
</div>
|
||||
{_idx < integrationWorkflowData.length - 1 && (
|
||||
<div
|
||||
key={_idx}
|
||||
className={`border-b px-7 ${
|
||||
_idx <= activeIntegrationState() - 1 ? `border-[#3F76FF]` : `border-gray-300`
|
||||
}`}
|
||||
>
|
||||
{" "}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="relative w-full space-y-4 overflow-hidden">
|
||||
<div className="w-full">
|
||||
{integrationData?.state === "import-configure" && (
|
||||
<GithubConfigure
|
||||
state={integrationData}
|
||||
handleState={handleIntegrationData}
|
||||
workspaceSlug={workspaceSlug}
|
||||
provider={provider}
|
||||
allIntegrations={allIntegrations}
|
||||
allIntegrationsError={allIntegrationsError}
|
||||
allWorkspaceIntegrations={allWorkspaceIntegrations}
|
||||
allWorkspaceIntegrationsError={allWorkspaceIntegrationsError}
|
||||
/>
|
||||
)}
|
||||
{integrationData?.state === "import-import-data" && (
|
||||
<GithubImportData state={integrationData} handleState={handleIntegrationData} />
|
||||
)}
|
||||
{integrationData?.state === "migrate-issues" && (
|
||||
<GithubIssuesSelect state={integrationData} handleState={handleIntegrationData} />
|
||||
)}
|
||||
{integrationData?.state === "migrate-users" && (
|
||||
<GithubUsersSelect state={integrationData} handleState={handleIntegrationData} />
|
||||
)}
|
||||
{integrationData?.state === "migrate-confirm" && (
|
||||
<GithubConfirm state={integrationData} handleState={handleIntegrationData} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
27
apps/app/components/integration/github/users-select.tsx
Normal file
27
apps/app/components/integration/github/users-select.tsx
Normal file
@ -0,0 +1,27 @@
|
||||
import { FC } from "react";
|
||||
// types
|
||||
import { IIntegrationData } from "components/integration";
|
||||
|
||||
type Props = { state: IIntegrationData; handleState: (key: string, valve: any) => void };
|
||||
|
||||
export const GithubUsersSelect: FC<Props> = ({ state, handleState }) => (
|
||||
<div>
|
||||
<div>Users Select</div>
|
||||
<div className="mt-5 flex items-center justify-between">
|
||||
<button
|
||||
type="button"
|
||||
className={`rounded-sm bg-gray-300 px-3 py-1.5 text-sm transition-colors hover:bg-opacity-80`}
|
||||
onClick={() => handleState("state", "migrate-issues")}
|
||||
>
|
||||
Back
|
||||
</button>
|
||||
<button
|
||||
type="button"
|
||||
className={`rounded-sm bg-theme px-3 py-1.5 text-sm text-white transition-colors hover:bg-opacity-80`}
|
||||
onClick={() => handleState("state", "migrate-confirm")}
|
||||
>
|
||||
Next
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
162
apps/app/components/integration/guide.tsx
Normal file
162
apps/app/components/integration/guide.tsx
Normal file
@ -0,0 +1,162 @@
|
||||
import { FC } from "react";
|
||||
// next imports
|
||||
import Link from "next/link";
|
||||
import Image from "next/image";
|
||||
// icons
|
||||
import { ArrowRightIcon } from "components/icons";
|
||||
import GithubLogo from "public/logos/github-square.png";
|
||||
import { ChevronDownIcon } from "@heroicons/react/24/outline";
|
||||
// components
|
||||
import { Loader } from "components/ui";
|
||||
import { GithubIntegrationRoot } from "components/integration";
|
||||
// types
|
||||
import { IAppIntegrations } from "types";
|
||||
|
||||
type Props = {
|
||||
workspaceSlug: string | undefined;
|
||||
provider: string | undefined;
|
||||
allIntegrations: IAppIntegrations[] | undefined;
|
||||
allIntegrationsError: Error | undefined;
|
||||
allWorkspaceIntegrations: any | undefined;
|
||||
allWorkspaceIntegrationsError: Error | undefined;
|
||||
allIntegrationImporters: any | undefined;
|
||||
allIntegrationImportersError: Error | undefined;
|
||||
};
|
||||
|
||||
const IntegrationGuide: FC<Props> = ({
|
||||
workspaceSlug,
|
||||
provider,
|
||||
allIntegrations,
|
||||
allIntegrationsError,
|
||||
allWorkspaceIntegrations,
|
||||
allWorkspaceIntegrationsError,
|
||||
allIntegrationImporters,
|
||||
allIntegrationImportersError,
|
||||
}) => (
|
||||
<div className="space-y-5">
|
||||
{!provider && (
|
||||
<>
|
||||
<div className="text-2xl font-semibold">Import</div>
|
||||
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="h-full w-full space-y-1">
|
||||
<div className="text-lg font-medium">Relocation Guide</div>
|
||||
<div className="text-sm">
|
||||
You can now transfer all the issues that you’ve created in other tracking services.
|
||||
This tool will guide you to relocate the issue to Plane.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex flex-shrink-0 cursor-pointer items-center gap-2 text-sm font-medium text-[#3F76FF] hover:text-opacity-80">
|
||||
<div>Read More</div>
|
||||
<div>
|
||||
<ArrowRightIcon width={"18px"} color={"#3F76FF"} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{allIntegrations && !allIntegrationsError ? (
|
||||
<>
|
||||
{allIntegrations && allIntegrations.length > 0 ? (
|
||||
<>
|
||||
{allIntegrations.map((_integration, _idx) => (
|
||||
<div
|
||||
key={_idx}
|
||||
className="space-y-4 rounded border border-gray-200 bg-white p-4"
|
||||
>
|
||||
<div className="flex items-center gap-4 whitespace-nowrap">
|
||||
<div className="h-[40px] w-[40px] flex-shrink-0">
|
||||
{_integration?.provider === "github" && (
|
||||
<Image src={GithubLogo} alt="GithubLogo" />
|
||||
)}
|
||||
</div>
|
||||
<div className="w-full space-y-1">
|
||||
<div className="flex items-center gap-2 font-medium">
|
||||
<div>{_integration?.title}</div>
|
||||
<div className="rounded-full border border-gray-200 bg-gray-200 px-3 text-[12px]">
|
||||
0
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm text-gray-500">
|
||||
Activate GitHub integrations on individual projects to sync with
|
||||
specific repositories.
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-shrink-0">
|
||||
<Link href={`/${workspaceSlug}/settings/import-export?provider=github`}>
|
||||
<button
|
||||
type="button"
|
||||
className="w-full rounded bg-[#3F76FF] py-1.5 px-4 text-center text-sm text-white hover:bg-opacity-90"
|
||||
>
|
||||
Integrate Now
|
||||
</button>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="flex h-[24px] w-[24px] flex-shrink-0 cursor-pointer items-center justify-center rounded-sm bg-gray-100 hover:bg-gray-200">
|
||||
<ChevronDownIcon className="h-4 w-4" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
{allIntegrationImporters && !allIntegrationImportersError ? (
|
||||
<>
|
||||
{allIntegrationImporters && allIntegrationImporters.length > 0 ? (
|
||||
<></>
|
||||
) : (
|
||||
<div className="py-2 text-sm text-gray-800">
|
||||
Previous Imports not available.
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div>
|
||||
<Loader className="grid grid-cols-1 gap-3">
|
||||
{["", ""].map((_integration, _idx) => (
|
||||
<Loader.Item height="40px" width="100%" />
|
||||
))}
|
||||
</Loader>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</>
|
||||
) : (
|
||||
<div className="py-5 text-center text-sm text-gray-800">
|
||||
Integrations not available.
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<div>
|
||||
<Loader className="grid grid-cols-1 gap-3">
|
||||
{["", ""].map((_integration, _idx) => (
|
||||
<Loader.Item height="34px" width="100%" />
|
||||
))}
|
||||
</Loader>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
|
||||
{provider && (
|
||||
<>
|
||||
{provider === "github" && (
|
||||
<GithubIntegrationRoot
|
||||
workspaceSlug={workspaceSlug}
|
||||
provider={provider}
|
||||
allIntegrations={allIntegrations}
|
||||
allIntegrationsError={allIntegrationsError}
|
||||
allWorkspaceIntegrations={allWorkspaceIntegrations}
|
||||
allWorkspaceIntegrationsError={allWorkspaceIntegrationsError}
|
||||
allIntegrationImporters={allIntegrationImporters}
|
||||
allIntegrationImportersError={allIntegrationImportersError}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
|
||||
export default IntegrationGuide;
|
14
apps/app/components/integration/index.ts
Normal file
14
apps/app/components/integration/index.ts
Normal file
@ -0,0 +1,14 @@
|
||||
// layout
|
||||
export * from "./guide";
|
||||
|
||||
// github integration
|
||||
// authenticate
|
||||
export * from "./github/auth";
|
||||
// layout
|
||||
export * from "./github/root";
|
||||
// components
|
||||
export * from "./github/configure";
|
||||
export * from "./github/import-data";
|
||||
export * from "./github/issues-select";
|
||||
export * from "./github/users-select";
|
||||
export * from "./github/confirm";
|
@ -102,8 +102,10 @@ export const VIEW_DETAILS = (viewId: string) => `VIEW_DETAILS_${viewId}`;
|
||||
export const ISSUE_DETAILS = (issueId: string) => `ISSUE_DETAILS_${issueId}`;
|
||||
export const SUB_ISSUES = (issueId: string) => `SUB_ISSUES_${issueId}`;
|
||||
|
||||
// integrations
|
||||
|
||||
// Pages
|
||||
export const PAGE_LIST = (pageId: string) => `PAGE_LIST_${pageId}`;
|
||||
export const PAGE_DETAILS = (pageId: string) => `PAGE_DETAILS_${pageId}`;
|
||||
export const PAGE_BLOCK_LIST = (pageId: string) => `PAGE_BLOCK_LIST_${pageId}`;
|
||||
export const PAGE_BLOCK_DETAILS = (pageId: string) => `PAGE_BLOCK_DETAILS_${pageId}`;
|
||||
export const PAGE_BLOCK_DETAILS = (pageId: string) => `PAGE_BLOCK_DETAILS_${pageId}`;
|
||||
|
@ -25,6 +25,10 @@ const SettingsNavbar: React.FC = () => {
|
||||
label: "Integrations",
|
||||
href: `/${workspaceSlug}/settings/integrations`,
|
||||
},
|
||||
{
|
||||
label: "Import/Export",
|
||||
href: `/${workspaceSlug}/settings/import-export`,
|
||||
},
|
||||
];
|
||||
|
||||
const projectLinks: Array<{
|
||||
|
113
apps/app/pages/[workspaceSlug]/settings/import-export.tsx
Normal file
113
apps/app/pages/[workspaceSlug]/settings/import-export.tsx
Normal file
@ -0,0 +1,113 @@
|
||||
// next imports
|
||||
import type { GetServerSideProps, NextPage } from "next";
|
||||
import { useRouter } from "next/router";
|
||||
// swr
|
||||
import useSWR from "swr";
|
||||
// lib
|
||||
import { requiredWorkspaceAdmin } from "lib/auth";
|
||||
// hooks
|
||||
import useToast from "hooks/use-toast";
|
||||
// layouts
|
||||
import AppLayout from "layouts/app-layout";
|
||||
import IntegrationGuide from "components/integration/guide";
|
||||
// ui
|
||||
import { BreadcrumbItem, Breadcrumbs } from "components/breadcrumbs";
|
||||
// types
|
||||
import { UserAuth, IAppIntegrations } from "types";
|
||||
// api services
|
||||
import WorkspaceIntegrationService from "services/integration";
|
||||
|
||||
const ImportExport: NextPage<UserAuth> = (props) => {
|
||||
const { setToastAlert } = useToast();
|
||||
|
||||
const router = useRouter();
|
||||
const { workspaceSlug, provider } = router.query as {
|
||||
workspaceSlug: string;
|
||||
provider: string;
|
||||
};
|
||||
|
||||
// fetching all the integrations available
|
||||
const { data: allIntegrations, error: allIntegrationsError } = useSWR<
|
||||
IAppIntegrations[] | undefined,
|
||||
Error
|
||||
>(
|
||||
workspaceSlug ? `ALL_INTEGRATIONS_${workspaceSlug.toUpperCase()}` : null,
|
||||
workspaceSlug ? () => WorkspaceIntegrationService.listAllIntegrations() : null
|
||||
);
|
||||
|
||||
// fetching all the integrations available
|
||||
const { data: allWorkspaceIntegrations, error: allWorkspaceIntegrationsError } = useSWR<
|
||||
any | undefined,
|
||||
Error
|
||||
>(
|
||||
workspaceSlug ? `WORKSPACE_INTEGRATIONS_${workspaceSlug.toUpperCase()}` : null,
|
||||
workspaceSlug
|
||||
? () => WorkspaceIntegrationService.listWorkspaceIntegrations(workspaceSlug)
|
||||
: null
|
||||
);
|
||||
|
||||
// fetching list of importers that already initialized
|
||||
const { data: allIntegrationImporters, error: allIntegrationImportersError } = useSWR<
|
||||
any | undefined,
|
||||
Error
|
||||
>(
|
||||
workspaceSlug ? `INTEGRATION_IMPORTERS_${workspaceSlug.toUpperCase()}` : null,
|
||||
workspaceSlug
|
||||
? () => WorkspaceIntegrationService.fetchImportExportIntegrationStatus(workspaceSlug)
|
||||
: null
|
||||
);
|
||||
|
||||
return (
|
||||
<>
|
||||
<AppLayout
|
||||
memberType={props}
|
||||
breadcrumbs={
|
||||
<Breadcrumbs>
|
||||
<BreadcrumbItem title={`${workspaceSlug ?? "Workspace"}`} link={`/${workspaceSlug}`} />
|
||||
<BreadcrumbItem title="Members Settings" />
|
||||
</Breadcrumbs>
|
||||
}
|
||||
settingsLayout
|
||||
>
|
||||
<section className="space-y-5">
|
||||
<IntegrationGuide
|
||||
workspaceSlug={workspaceSlug}
|
||||
provider={provider}
|
||||
allIntegrations={allIntegrations}
|
||||
allIntegrationsError={allIntegrationsError}
|
||||
allWorkspaceIntegrations={allWorkspaceIntegrations}
|
||||
allWorkspaceIntegrationsError={allWorkspaceIntegrationsError}
|
||||
allIntegrationImporters={allIntegrationImporters}
|
||||
allIntegrationImportersError={allIntegrationImportersError}
|
||||
/>
|
||||
</section>
|
||||
</AppLayout>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export const getServerSideProps: GetServerSideProps = async (ctx) => {
|
||||
const workspaceSlug = ctx.params?.workspaceSlug as string;
|
||||
|
||||
const memberDetail = await requiredWorkspaceAdmin(workspaceSlug, ctx.req.headers.cookie);
|
||||
|
||||
if (memberDetail === null) {
|
||||
return {
|
||||
redirect: {
|
||||
destination: "/",
|
||||
permanent: false,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
props: {
|
||||
isOwner: memberDetail?.role === 20,
|
||||
isMember: memberDetail?.role === 15,
|
||||
isViewer: memberDetail?.role === 10,
|
||||
isGuest: memberDetail?.role === 5,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
||||
export default ImportExport;
|
45
apps/app/services/integration/github.service.ts
Normal file
45
apps/app/services/integration/github.service.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import APIService from "services/api.service";
|
||||
|
||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||
|
||||
const integrationServiceType: string = "github";
|
||||
|
||||
class GithubIntegrationService extends APIService {
|
||||
constructor() {
|
||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||
}
|
||||
|
||||
// fetching all the repositories under the github
|
||||
async listAllRepositories(workspaceSlug: string, integrationSlug: string): Promise<any> {
|
||||
return this.get(
|
||||
`/api/workspaces/${workspaceSlug}/workspace-integrations/${integrationSlug}/github-repositories`
|
||||
)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
// fetching repository stats under the repository eg: users, labels and issues
|
||||
async fetchRepositoryStats(workspaceSlug: string): Promise<any> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/importers/${integrationServiceType}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
// migrating repository data in workspace project
|
||||
async migrateRepositoryStatToProject(
|
||||
workspaceSlug: string,
|
||||
integrationSlug: string
|
||||
): Promise<any> {
|
||||
return this.post(`/api/workspaces/${workspaceSlug}/importers/${integrationServiceType}/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new GithubIntegrationService();
|
49
apps/app/services/integration/index.ts
Normal file
49
apps/app/services/integration/index.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import APIService from "services/api.service";
|
||||
// types
|
||||
import { IAppIntegrations, IWorkspaceIntegrations, IProject } from "types";
|
||||
|
||||
const { NEXT_PUBLIC_API_BASE_URL } = process.env;
|
||||
|
||||
class WorkspaceIntegrationService extends APIService {
|
||||
constructor() {
|
||||
super(NEXT_PUBLIC_API_BASE_URL || "http://localhost:8000");
|
||||
}
|
||||
|
||||
// integration available and integration validation starts
|
||||
async listAllIntegrations(): Promise<IAppIntegrations[]> {
|
||||
return this.get(`/api/integrations/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
async listWorkspaceIntegrations(workspaceSlug: string): Promise<IWorkspaceIntegrations[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/workspace-integrations/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
// integration available and integration validation ends
|
||||
|
||||
// listing all the projects under the workspace
|
||||
async listWorkspaceProjects(workspaceSlug: string): Promise<IProject[]> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/projects/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
|
||||
// fetching the status of all the importers that initiated eg: GitHub...
|
||||
async fetchImportExportIntegrationStatus(workspaceSlug: string): Promise<any> {
|
||||
return this.get(`/api/workspaces/${workspaceSlug}/importers/`)
|
||||
.then((response) => response?.data)
|
||||
.catch((error) => {
|
||||
throw error?.response?.data;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default new WorkspaceIntegrationService();
|
1
apps/app/types/index.d.ts
vendored
1
apps/app/types/index.d.ts
vendored
@ -7,6 +7,7 @@ export * from "./invitation";
|
||||
export * from "./issues";
|
||||
export * from "./modules";
|
||||
export * from "./views";
|
||||
export * from "./integration";
|
||||
export * from "./pages";
|
||||
|
||||
export type NestedKeyOf<ObjectType extends object> = {
|
||||
|
35
apps/app/types/integration.d.ts
vendored
Normal file
35
apps/app/types/integration.d.ts
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
// All the app integrations that are available
|
||||
export interface IAppIntegrations {
|
||||
author: string;
|
||||
author: "";
|
||||
avatar_url: string | null;
|
||||
created_at: string;
|
||||
created_by: string | null;
|
||||
description: any;
|
||||
id: string;
|
||||
metadata: any;
|
||||
network: number;
|
||||
provider: string;
|
||||
redirect_url: string;
|
||||
title: string;
|
||||
updated_at: string;
|
||||
updated_by: string | null;
|
||||
verified: boolean;
|
||||
webhook_secret: string;
|
||||
webhook_url: string;
|
||||
}
|
||||
|
||||
export interface IWorkspaceIntegrations {
|
||||
actor: string;
|
||||
api_token: string;
|
||||
config: any;
|
||||
created_at: string;
|
||||
created_by: string;
|
||||
id: string;
|
||||
integration: string;
|
||||
integration_detail: IIntegrations;
|
||||
metadata: any;
|
||||
updated_at: string;
|
||||
updated_by: string;
|
||||
workspace: string;
|
||||
}
|
35
apps/app/types/workspace.d.ts
vendored
35
apps/app/types/workspace.d.ts
vendored
@ -44,38 +44,3 @@ export interface ILastActiveWorkspaceDetails {
|
||||
workspace_details: IWorkspace;
|
||||
project_details?: IProjectMember[];
|
||||
}
|
||||
|
||||
export interface IAppIntegrations {
|
||||
author: string;
|
||||
author: "";
|
||||
avatar_url: string | null;
|
||||
created_at: string;
|
||||
created_by: string | null;
|
||||
description: any;
|
||||
id: string;
|
||||
metadata: any;
|
||||
network: number;
|
||||
provider: string;
|
||||
redirect_url: string;
|
||||
title: string;
|
||||
updated_at: string;
|
||||
updated_by: string | null;
|
||||
verified: boolean;
|
||||
webhook_secret: string;
|
||||
webhook_url: string;
|
||||
}
|
||||
|
||||
export interface IWorkspaceIntegrations {
|
||||
actor: string;
|
||||
api_token: string;
|
||||
config: any;
|
||||
created_at: string;
|
||||
created_by: string;
|
||||
id: string;
|
||||
integration: string;
|
||||
integration_detail: IIntegrations;
|
||||
metadata: any;
|
||||
updated_at: string;
|
||||
updated_by: string;
|
||||
workspace: string;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user