feat: integrate firebase for github login (#132)
* wip: form for mint * style: change bgcolor for disabled button * fix: add key to list items * styles: add some spacings and border radius * refactor: change type file and move file validation to form * feat: add minted nft card. add wallet step * refactor: add mint card header to not repeat code * styles: add border radius to svg * styles: fix styles on mint view * style: fix height mint view * fix: fix save repository config * chore: changes based on PR review * wip: connecting with gh login * chore: add env variables * wip: gh login wiht auth0 * feat: add gh login integration * chore: remove web3auth packages * doc: add info on readme to know how to get firebase credentials * feat: add spinner component (#133) * fix: fix for polyfills * refactor: remove loading state cause it was causing a loop * chore: change placeholder * feat: add constants env file * fix: fix polyfills * refactor: implement async thunk for github login * wip: add async thunk for github api calls * feat: implemented async thunk for github api calls * chore: add promise.all to improve api call performance * fix: fix console log error
This commit is contained in:
parent
cfea9a90ea
commit
964c1a651f
|
|
@ -8,6 +8,7 @@ module.exports = {
|
||||||
'plugin:react/recommended',
|
'plugin:react/recommended',
|
||||||
'plugin:@typescript-eslint/recommended',
|
'plugin:@typescript-eslint/recommended',
|
||||||
'plugin:prettier/recommended',
|
'plugin:prettier/recommended',
|
||||||
|
'plugin:react-hooks/recommended',
|
||||||
],
|
],
|
||||||
overrides: [],
|
overrides: [],
|
||||||
parser: '@typescript-eslint/parser',
|
parser: '@typescript-eslint/parser',
|
||||||
|
|
@ -27,5 +28,6 @@ module.exports = {
|
||||||
'simple-import-sort/imports': 2,
|
'simple-import-sort/imports': 2,
|
||||||
'@typescript-eslint/explicit-function-return-type': 'off',
|
'@typescript-eslint/explicit-function-return-type': 'off',
|
||||||
'no-console': 'error',
|
'no-console': 'error',
|
||||||
|
'unused-imports/no-unused-imports-ts': 'error',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
15
ui/README.md
15
ui/README.md
|
|
@ -23,8 +23,21 @@ To run the UI localy follow the steps:
|
||||||
```bash
|
```bash
|
||||||
$ yarn
|
$ yarn
|
||||||
```
|
```
|
||||||
|
3. You'll need to set up your firebase cretendials to make work the github login. Set the .env file with the following variables
|
||||||
|
|
||||||
3. Start the local server running the app:
|
```bash
|
||||||
|
VITE_FIREBASE_API_KEY
|
||||||
|
VITE_FIREBASE_AUTH_DOMAIN
|
||||||
|
VITE_FIREBASE_PROJECT_ID
|
||||||
|
VITE_FIREBASE_STORAGE_BUCKET
|
||||||
|
VITE_FIREBASE_MESSAGING_SENDER_ID
|
||||||
|
VITE_FIREBASE_APP_ID
|
||||||
|
VITE_FIREBASE_MEASUREMENT_ID
|
||||||
|
```
|
||||||
|
|
||||||
|
Get them from the project settings on the firebase dashboard. Read [this article](https://support.google.com/firebase/answer/7015592?hl=en#zippy=%2Cin-this-article) to know how to get your porject config
|
||||||
|
|
||||||
|
4. Start the local server running the app:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
$ yarn dev
|
$ yarn dev
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
<script type="module">
|
||||||
|
import { Buffer } from 'buffer';
|
||||||
|
import process from 'process';
|
||||||
|
window.Buffer = Buffer;
|
||||||
|
window.process = process;
|
||||||
|
</script>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<link
|
<link
|
||||||
rel="icon"
|
rel="icon"
|
||||||
|
|
|
||||||
|
|
@ -16,11 +16,14 @@
|
||||||
"@ethersproject/providers": "^5.7.2",
|
"@ethersproject/providers": "^5.7.2",
|
||||||
"@headlessui/react": "^1.7.8",
|
"@headlessui/react": "^1.7.8",
|
||||||
"@radix-ui/colors": "^0.1.8",
|
"@radix-ui/colors": "^0.1.8",
|
||||||
|
"@radix-ui/react-avatar": "^1.0.1",
|
||||||
"@react-icons/all-files": "^4.1.0",
|
"@react-icons/all-files": "^4.1.0",
|
||||||
"@reduxjs/toolkit": "^1.9.1",
|
"@reduxjs/toolkit": "^1.9.1",
|
||||||
"@stitches/react": "^1.2.8",
|
"@stitches/react": "^1.2.8",
|
||||||
"colorthief": "^2.3.2",
|
"colorthief": "^2.3.2",
|
||||||
|
"firebase": "^9.17.1",
|
||||||
"formik": "^2.2.9",
|
"formik": "^2.2.9",
|
||||||
|
"octokit": "^2.0.14",
|
||||||
"path": "^0.12.7",
|
"path": "^0.12.7",
|
||||||
"react": "^18.2.0",
|
"react": "^18.2.0",
|
||||||
"react-dom": "^18.2.0",
|
"react-dom": "^18.2.0",
|
||||||
|
|
@ -29,6 +32,8 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.20.12",
|
"@babel/core": "^7.20.12",
|
||||||
|
"@esbuild-plugins/node-globals-polyfill": "^0.2.3",
|
||||||
|
"@esbuild-plugins/node-modules-polyfill": "^0.2.2",
|
||||||
"@storybook/addon-actions": "^6.5.15",
|
"@storybook/addon-actions": "^6.5.15",
|
||||||
"@storybook/addon-essentials": "^6.5.15",
|
"@storybook/addon-essentials": "^6.5.15",
|
||||||
"@storybook/addon-interactions": "^6.5.15",
|
"@storybook/addon-interactions": "^6.5.15",
|
||||||
|
|
@ -44,18 +49,23 @@
|
||||||
"@types/react-dom": "^18.0.9",
|
"@types/react-dom": "^18.0.9",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
"@typescript-eslint/eslint-plugin": "^5.45.0",
|
||||||
"@typescript-eslint/parser": "^5.45.0",
|
"@typescript-eslint/parser": "^5.45.0",
|
||||||
"@vitejs/plugin-react": "^2.2.0",
|
"@vitejs/plugin-react": "2.2.0",
|
||||||
"autoprefixer": "^10.4.13",
|
"autoprefixer": "^10.4.13",
|
||||||
"babel-loader": "^8.3.0",
|
"babel-loader": "^8.3.0",
|
||||||
|
"buffer": "^6.0.3",
|
||||||
"eslint": "^8.28.0",
|
"eslint": "^8.28.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-jest": "^27.1.6",
|
"eslint-plugin-jest": "^27.1.6",
|
||||||
"eslint-plugin-prettier": "^4.2.1",
|
"eslint-plugin-prettier": "^4.2.1",
|
||||||
"eslint-plugin-react": "^7.31.11",
|
"eslint-plugin-react": "^7.31.11",
|
||||||
|
"eslint-plugin-react-hooks": "^4.6.0",
|
||||||
"ethers": "^5.7.2",
|
"ethers": "^5.7.2",
|
||||||
"postcss": "^8.4.21",
|
"postcss": "^8.4.21",
|
||||||
"prettier": "^2.8.0",
|
"prettier": "^2.8.0",
|
||||||
|
"process": "^0.11.10",
|
||||||
"react-query": "^3.39.2",
|
"react-query": "^3.39.2",
|
||||||
|
"rollup-plugin-node-builtins": "^2.1.2",
|
||||||
|
"rollup-plugin-node-polyfills": "^0.2.1",
|
||||||
"storybook-dark-mode": "^2.0.5",
|
"storybook-dark-mode": "^2.0.5",
|
||||||
"tailwindcss": "^3.2.4",
|
"tailwindcss": "^3.2.4",
|
||||||
"ts-loader": "^9.4.1",
|
"ts-loader": "^9.4.1",
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,7 @@
|
||||||
import { BrowserRouter, Route, Routes, Navigate } from 'react-router-dom';
|
import { BrowserRouter, Route, Routes, Navigate } from 'react-router-dom';
|
||||||
import { initializeWallet } from './store';
|
import { initializeWallet } from './store';
|
||||||
import { themeGlobals } from '@/theme/globals';
|
import { themeGlobals } from '@/theme/globals';
|
||||||
import { Home } from './views';
|
import { Home, Mint } from './views';
|
||||||
import { Mint } from './views/mint';
|
|
||||||
import { SVGTestScreen } from './views/svg-test'; // TODO: remove when done
|
import { SVGTestScreen } from './views/svg-test'; // TODO: remove when done
|
||||||
|
|
||||||
initializeWallet();
|
initializeWallet();
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,4 @@
|
||||||
|
import { Octokit } from 'octokit';
|
||||||
import React, { forwardRef } from 'react';
|
import React, { forwardRef } from 'react';
|
||||||
import { Flex } from '../layout';
|
import { Flex } from '../layout';
|
||||||
import { CardStyles } from './card.styles';
|
import { CardStyles } from './card.styles';
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { dripStitches } from '@/theme';
|
||||||
|
import * as Avatar from '@radix-ui/react-avatar';
|
||||||
|
|
||||||
|
const { styled } = dripStitches;
|
||||||
|
|
||||||
|
export abstract class AvatarStyles {
|
||||||
|
static readonly Root = styled(Avatar.Root, {
|
||||||
|
display: 'inline-flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
verticalAlign: 'middle',
|
||||||
|
overflow: 'hidden',
|
||||||
|
userSelect: 'none',
|
||||||
|
width: '$5',
|
||||||
|
height: '$5',
|
||||||
|
borderRadius: '100%',
|
||||||
|
backgroundColor: '$slate2',
|
||||||
|
mr: '$2',
|
||||||
|
});
|
||||||
|
|
||||||
|
static readonly Image = styled(Avatar.Image, {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
objectFit: 'cover',
|
||||||
|
borderRadius: 'inherit',
|
||||||
|
});
|
||||||
|
|
||||||
|
static readonly Fallback = styled(Avatar.Fallback, {
|
||||||
|
width: '100%',
|
||||||
|
height: '100%',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: '$slate2',
|
||||||
|
color: '$slate12',
|
||||||
|
fontSize: '$sm',
|
||||||
|
fontWeight: '$medium',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export type AvatarProps = React.ComponentProps<typeof AvatarStyles.Root> & {
|
||||||
|
/**
|
||||||
|
* Fallback node.
|
||||||
|
* In case of string, transformed to upper case and sliced to second letter.
|
||||||
|
*/
|
||||||
|
fallback?: React.ReactNode;
|
||||||
|
/**
|
||||||
|
* Source of the image.
|
||||||
|
* If not provided, fallback will be used.
|
||||||
|
*/
|
||||||
|
src?: AvatarImageProps['src'];
|
||||||
|
/**
|
||||||
|
* Alt text of the image.
|
||||||
|
*/
|
||||||
|
alt?: AvatarImageProps['alt'];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Props of the image tag.
|
||||||
|
* @see {@link AvatarImageProps}
|
||||||
|
* @default {}
|
||||||
|
*/
|
||||||
|
imageProps?: AvatarImageProps;
|
||||||
|
/**
|
||||||
|
* Props of the fallback tag.
|
||||||
|
* @see {@link AvatarFallbackProps}
|
||||||
|
* @default {}
|
||||||
|
*/
|
||||||
|
fallbackProps?: AvatarFallbackProps;
|
||||||
|
};
|
||||||
|
export type AvatarImageProps = React.ComponentProps<typeof AvatarStyles.Image>;
|
||||||
|
export type AvatarFallbackProps = React.ComponentProps<
|
||||||
|
typeof AvatarStyles.Fallback
|
||||||
|
>;
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
import { forwardRef } from 'react';
|
||||||
|
import { AvatarProps, AvatarStyles } from './avatar.styles';
|
||||||
|
|
||||||
|
export const Avatar = forwardRef<HTMLDivElement, AvatarProps>(
|
||||||
|
(
|
||||||
|
{ fallback, fallbackProps, imageProps = {}, src, alt, css, ...rootProps },
|
||||||
|
ref
|
||||||
|
) => {
|
||||||
|
return (
|
||||||
|
<AvatarStyles.Root {...rootProps} ref={ref} css={css}>
|
||||||
|
<AvatarStyles.Image src={src} alt={alt} {...imageProps} />
|
||||||
|
</AvatarStyles.Root>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './avatar';
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import { Fragment, useRef, useState } from 'react';
|
import React, { Fragment, useRef, useState } from 'react';
|
||||||
import { Combobox as ComboboxLib, Transition } from '@headlessui/react';
|
import { Combobox as ComboboxLib, Transition } from '@headlessui/react';
|
||||||
import { Icon, IconName } from '@/components/core/icon';
|
import { Icon } from '@/components/core/icon';
|
||||||
import { Flex } from '@/components/layout';
|
import { Flex } from '@/components/layout';
|
||||||
|
|
||||||
type ComboboxInputProps = {
|
type ComboboxInputProps = {
|
||||||
|
|
@ -53,7 +53,7 @@ const ComboboxOption = ({ option }: ComboboxOptionProps) => (
|
||||||
{({ selected, active }) => (
|
{({ selected, active }) => (
|
||||||
<Flex css={{ justifyContent: 'space-between' }}>
|
<Flex css={{ justifyContent: 'space-between' }}>
|
||||||
<Flex css={{ flexDirection: 'row' }}>
|
<Flex css={{ flexDirection: 'row' }}>
|
||||||
{option.icon && <Icon name={option.icon} css={{ mr: '$2' }} />}
|
{option.icon}
|
||||||
<span className={`${active ? 'text-slate12' : 'text-slate11'}`}>
|
<span className={`${active ? 'text-slate12' : 'text-slate11'}`}>
|
||||||
{option.label}
|
{option.label}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -75,7 +75,7 @@ export const NoResults = ({ css }: { css?: string }) => (
|
||||||
export type ComboboxItem = {
|
export type ComboboxItem = {
|
||||||
value: string;
|
value: string;
|
||||||
label: string;
|
label: string;
|
||||||
icon?: IconName;
|
icon?: React.ReactNode;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type ComboboxProps = {
|
export type ComboboxProps = {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ type DropdownOptionProps = {
|
||||||
const DropdownOption = ({ option }: DropdownOptionProps) => (
|
const DropdownOption = ({ option }: DropdownOptionProps) => (
|
||||||
<Listbox.Option
|
<Listbox.Option
|
||||||
className={({ active }) =>
|
className={({ active }) =>
|
||||||
`relative cursor-default select-none py-2 px-3.5 text-slate11 rounded-xl mb-2 text-sm ${
|
`relative cursor-default select-none py-2 px-3.5 text-slate11 rounded-xl mb-2 text-sm max-w-full ${
|
||||||
active ? 'bg-slate5 text-slate12' : 'bg-transparent'
|
active ? 'bg-slate5 text-slate12' : 'bg-transparent'
|
||||||
}`
|
}`
|
||||||
}
|
}
|
||||||
|
|
@ -18,10 +18,28 @@ const DropdownOption = ({ option }: DropdownOptionProps) => (
|
||||||
>
|
>
|
||||||
{({ selected, active }) => (
|
{({ selected, active }) => (
|
||||||
<Flex css={{ justifyContent: 'space-between' }}>
|
<Flex css={{ justifyContent: 'space-between' }}>
|
||||||
<span className={`${active ? 'text-slate12' : 'text-slate11'}`}>
|
<span
|
||||||
|
className={`${
|
||||||
|
active ? 'text-slate12' : 'text-slate11'
|
||||||
|
} max-w-full break-words pr-5`}
|
||||||
|
>
|
||||||
{option.label}
|
{option.label}
|
||||||
</span>
|
</span>
|
||||||
{selected && <Icon name="check" color="white" />}
|
{selected && (
|
||||||
|
<Icon
|
||||||
|
name="check"
|
||||||
|
color="white"
|
||||||
|
css={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: '$0',
|
||||||
|
bottom: '$0',
|
||||||
|
right: '$0',
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
pr: '$4',
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
</Flex>
|
</Flex>
|
||||||
)}
|
)}
|
||||||
</Listbox.Option>
|
</Listbox.Option>
|
||||||
|
|
@ -41,7 +59,7 @@ const DropdownButton = ({ selectedValue, open }: DropdownButtonProps) => (
|
||||||
<span
|
<span
|
||||||
className={`block truncate ${
|
className={`block truncate ${
|
||||||
selectedValue && selectedValue.label ? 'text-slate12' : 'text-slate11'
|
selectedValue && selectedValue.label ? 'text-slate12' : 'text-slate11'
|
||||||
}`}
|
} break-words`}
|
||||||
>
|
>
|
||||||
{selectedValue && selectedValue.label ? selectedValue.label : 'Select'}
|
{selectedValue && selectedValue.label ? selectedValue.label : 'Select'}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -74,7 +92,7 @@ export const Dropdown: React.FC<DropdownProps> = ({
|
||||||
return (
|
return (
|
||||||
<Listbox value={selectedValue} by="value" onChange={handleDropdownChange}>
|
<Listbox value={selectedValue} by="value" onChange={handleDropdownChange}>
|
||||||
{({ open }) => (
|
{({ open }) => (
|
||||||
<div className="relative">
|
<div className="relative max-w-full">
|
||||||
<DropdownButton selectedValue={selectedValue} open={open} />
|
<DropdownButton selectedValue={selectedValue} open={open} />
|
||||||
<Transition
|
<Transition
|
||||||
as={Fragment}
|
as={Fragment}
|
||||||
|
|
@ -82,7 +100,7 @@ export const Dropdown: React.FC<DropdownProps> = ({
|
||||||
leaveFrom="opacity-100"
|
leaveFrom="opacity-100"
|
||||||
leaveTo="opacity-0"
|
leaveTo="opacity-0"
|
||||||
>
|
>
|
||||||
<Listbox.Options className="absolute max-h-fit w-full z-10 overflow-auto rounded-b-xl bg-black px-3 pt-2 border-solid border-slate6 border text-base focus:outline-none sm:text-sm">
|
<Listbox.Options className="absolute max-h-32 w-full z-10 overflow-auto rounded-b-xl bg-black px-3 pt-2 border-solid border-slate6 border text-base focus:outline-none sm:text-sm">
|
||||||
{items.map((option: DropdownItem) => (
|
{items.map((option: DropdownItem) => (
|
||||||
<DropdownOption key={option.value} option={option} />
|
<DropdownOption key={option.value} option={option} />
|
||||||
))}
|
))}
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,5 @@ export * from './button';
|
||||||
export * from './combobox';
|
export * from './combobox';
|
||||||
export * from './icon';
|
export * from './icon';
|
||||||
export * from './input';
|
export * from './input';
|
||||||
|
export * from './avatar';
|
||||||
|
export * from './separator.styles';
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ const { styled } = dripStitches;
|
||||||
export abstract class FormStyles {
|
export abstract class FormStyles {
|
||||||
static readonly Field = styled(Flex, {
|
static readonly Field = styled(Flex, {
|
||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
|
maxWidth: '100%',
|
||||||
});
|
});
|
||||||
|
|
||||||
static readonly Label = styled('label', {
|
static readonly Label = styled('label', {
|
||||||
|
|
|
||||||
|
|
@ -2,3 +2,4 @@ export * from './core';
|
||||||
export * from './layout';
|
export * from './layout';
|
||||||
export * from './form';
|
export * from './form';
|
||||||
export * from './card';
|
export * from './card';
|
||||||
|
export * from './spinner';
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './spinner';
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
import { dripStitches } from '@/theme';
|
||||||
|
|
||||||
|
const { styled } = dripStitches;
|
||||||
|
|
||||||
|
export abstract class SpinnerStyles {
|
||||||
|
static readonly Container = styled('svg', {
|
||||||
|
fontSize: '1.5rem',
|
||||||
|
width: '1em',
|
||||||
|
height: '1em',
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace SpinnerStyles {
|
||||||
|
export type ContainerProps = React.ComponentProps<
|
||||||
|
typeof SpinnerStyles.Container
|
||||||
|
>;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
/* eslint-disable react/no-unknown-property */
|
||||||
|
|
||||||
|
import { SpinnerStyles } from './spinner.styles';
|
||||||
|
|
||||||
|
export const Spinner: React.FC<SpinnerStyles.ContainerProps> = (props) => (
|
||||||
|
<SpinnerStyles.Container
|
||||||
|
{...props}
|
||||||
|
viewBox="0 0 40 40"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<circle
|
||||||
|
cx="20"
|
||||||
|
cy="20"
|
||||||
|
r="17"
|
||||||
|
stroke="currentColor"
|
||||||
|
strokeWidth="5"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeDasharray="125.6"
|
||||||
|
>
|
||||||
|
<animate
|
||||||
|
attributeName="stroke-dashoffset"
|
||||||
|
values="26.4;125.6;26.4"
|
||||||
|
dur="4s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
keyTimes="0;0.5;1"
|
||||||
|
/>
|
||||||
|
<animateTransform
|
||||||
|
attributeName="transform"
|
||||||
|
type="rotate"
|
||||||
|
from="0 20 20"
|
||||||
|
to="1080 20 20"
|
||||||
|
dur="2s"
|
||||||
|
repeatCount="indefinite"
|
||||||
|
/>
|
||||||
|
</circle>
|
||||||
|
</SpinnerStyles.Container>
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
export const env = Object.freeze({
|
||||||
|
firebase: {
|
||||||
|
apiKey: import.meta.env.VITE_FIREBASE_API_KEY || '',
|
||||||
|
authDomain: import.meta.env.VITE_FIREBASE_AUTH_DOMAIN || '',
|
||||||
|
projectId: import.meta.env.VITE_FIREBASE_PROJECT_ID || '',
|
||||||
|
storageBucket: import.meta.env.VITE_FIREBASE_STORAGE_BUCKET || '',
|
||||||
|
messagingSenderId: import.meta.env.VITE_FIREBASE_MESSAGING_SENDER_ID || '',
|
||||||
|
appId: import.meta.env.VITE_FIREBASE_APP_ID || '',
|
||||||
|
measurementId: import.meta.env.VITE_FIREBASE_MEASUREMENT_ID || '',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './env';
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { DropdownItem } from '@/components';
|
||||||
|
import { githubActions, RootState } from '@/store';
|
||||||
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||||
|
import { GithubClient } from '../github-client';
|
||||||
|
|
||||||
|
type FetchBranches = {
|
||||||
|
owner: string;
|
||||||
|
repository: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const fetchBranchesThunk = createAsyncThunk<void, FetchBranches>(
|
||||||
|
'github/fetchBranches',
|
||||||
|
async ({ owner, repository }, { dispatch, getState }) => {
|
||||||
|
const { token, queryLoading } = (getState() as RootState).github;
|
||||||
|
|
||||||
|
if (queryLoading === 'loading') return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
dispatch(githubActions.setQueryState('loading'));
|
||||||
|
|
||||||
|
const githubClient = new GithubClient(token);
|
||||||
|
|
||||||
|
const branches = await githubClient.fetchBranches(owner, repository);
|
||||||
|
|
||||||
|
dispatch(githubActions.setBranches(branches as DropdownItem[]));
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
dispatch(githubActions.setQueryState('failed'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
import { githubActions, Repository, RootState } from '@/store';
|
||||||
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||||
|
import { GithubClient } from '../github-client';
|
||||||
|
|
||||||
|
export const fetchRepositoriesThunk = createAsyncThunk(
|
||||||
|
'github/fetchRepositories',
|
||||||
|
async (url: string, { dispatch, getState }) => {
|
||||||
|
if ((getState() as RootState).github.queryLoading === 'loading') return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
dispatch(githubActions.setQueryState('loading'));
|
||||||
|
|
||||||
|
const githubClient = new GithubClient(
|
||||||
|
(getState() as RootState).github.token
|
||||||
|
);
|
||||||
|
|
||||||
|
const repositories = await githubClient.fetchRepos(url);
|
||||||
|
|
||||||
|
dispatch(
|
||||||
|
githubActions.setRepositoires(
|
||||||
|
repositories.map(
|
||||||
|
(repo: any) => ({ name: repo.name, url: repo.url } as Repository)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
dispatch(githubActions.setQueryState('failed'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { ComboboxItem } from '@/components';
|
||||||
|
import { RootState } from '@/store';
|
||||||
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||||
|
import { GithubClient, UserData } from '../github-client';
|
||||||
|
import { githubActions } from '../github-slice';
|
||||||
|
|
||||||
|
export const fetchUserAndOrgsThunk = createAsyncThunk(
|
||||||
|
'github/fetchUserAndOrgs',
|
||||||
|
async (_, { dispatch, getState }) => {
|
||||||
|
const { token, queryUserAndOrganizations } = (getState() as RootState)
|
||||||
|
.github;
|
||||||
|
|
||||||
|
if (queryUserAndOrganizations === 'loading') return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
dispatch(githubActions.setQueryUserState('loading'));
|
||||||
|
|
||||||
|
const githubClient = new GithubClient(token);
|
||||||
|
|
||||||
|
const response = await Promise.all([
|
||||||
|
githubClient.fetchUser(),
|
||||||
|
githubClient.fetchOrgs(),
|
||||||
|
]);
|
||||||
|
const userResponse = response[0];
|
||||||
|
const orgsResponse = response[1];
|
||||||
|
|
||||||
|
let comboboxItems: UserData[] = [];
|
||||||
|
|
||||||
|
if (userResponse) {
|
||||||
|
comboboxItems.push(userResponse);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orgsResponse) {
|
||||||
|
comboboxItems = [...comboboxItems, ...orgsResponse];
|
||||||
|
}
|
||||||
|
|
||||||
|
dispatch(githubActions.setUserAndOrgs(comboboxItems));
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
dispatch(githubActions.setQueryState('failed'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
export * from './login';
|
||||||
|
export * from './fetch-repositories';
|
||||||
|
export * from './fetch-branches';
|
||||||
|
export * from './fetch-user-organizations';
|
||||||
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { createAsyncThunk } from '@reduxjs/toolkit';
|
||||||
|
import { env } from '@/constants';
|
||||||
|
import { initializeApp } from 'firebase/app';
|
||||||
|
import { getAuth, signInWithPopup, GithubAuthProvider } from 'firebase/auth';
|
||||||
|
import { githubActions, RootState } from '@/store';
|
||||||
|
|
||||||
|
const GithubScopes = ['repo', 'read:org', 'read:user', 'public_repo', 'user'];
|
||||||
|
|
||||||
|
const firebaseConfig = {
|
||||||
|
apiKey: env.firebase.apiKey,
|
||||||
|
authDomain: env.firebase.authDomain,
|
||||||
|
projectId: env.firebase.projectId,
|
||||||
|
storageBucket: env.firebase.storageBucket,
|
||||||
|
messagingSenderId: env.firebase.messagingSenderId,
|
||||||
|
appId: env.firebase.appId,
|
||||||
|
measurementId: env.firebase.measurementId,
|
||||||
|
};
|
||||||
|
// Initialize Firebase
|
||||||
|
const app = initializeApp(firebaseConfig);
|
||||||
|
|
||||||
|
const provider = new GithubAuthProvider();
|
||||||
|
GithubScopes.forEach((scope) => provider.addScope(scope));
|
||||||
|
|
||||||
|
const auth = getAuth(app);
|
||||||
|
|
||||||
|
export const login = createAsyncThunk(
|
||||||
|
'github/login',
|
||||||
|
async (_, { dispatch, getState }) => {
|
||||||
|
if ((getState() as RootState).github.state === 'loading') return;
|
||||||
|
|
||||||
|
try {
|
||||||
|
dispatch(githubActions.setState('loading'));
|
||||||
|
|
||||||
|
const response = await signInWithPopup(auth, provider);
|
||||||
|
|
||||||
|
// This gives you a GitHub Access Token. You can use it to access the GitHub API.
|
||||||
|
const credential = GithubAuthProvider.credentialFromResult(response);
|
||||||
|
|
||||||
|
if (credential && credential.accessToken) {
|
||||||
|
dispatch(githubActions.setToken(credential.accessToken));
|
||||||
|
} else {
|
||||||
|
//something went wrong and have no token
|
||||||
|
throw Error('Invalid response type');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log('Could not connect to GitHub', error);
|
||||||
|
dispatch(githubActions.setState('disconnected'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
import { DropdownItem } from '@/components';
|
||||||
|
import { Octokit } from 'octokit';
|
||||||
|
|
||||||
|
export type UserData = {
|
||||||
|
value: string;
|
||||||
|
label: string;
|
||||||
|
avatar: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class GithubClient {
|
||||||
|
octokit: Octokit;
|
||||||
|
token: string;
|
||||||
|
|
||||||
|
constructor(token: string) {
|
||||||
|
(this.token = token),
|
||||||
|
(this.octokit = new Octokit({
|
||||||
|
auth: token,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchUser(): Promise<UserData> {
|
||||||
|
const { data: userData } = await this.octokit.request('GET /user');
|
||||||
|
|
||||||
|
return {
|
||||||
|
value: userData.repos_url,
|
||||||
|
label: userData.login,
|
||||||
|
avatar: userData.avatar_url,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchOrgs(): Promise<UserData[]> {
|
||||||
|
const { data: organizationsData } = await this.octokit.request(
|
||||||
|
'GET /user/orgs'
|
||||||
|
);
|
||||||
|
|
||||||
|
return organizationsData.map((org) => {
|
||||||
|
return {
|
||||||
|
label: org.login,
|
||||||
|
value: org.repos_url,
|
||||||
|
avatar: org.avatar_url,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchRepos(url: string) {
|
||||||
|
try {
|
||||||
|
const repos = await fetch(url, {
|
||||||
|
headers: {
|
||||||
|
Authorization: `Bearer ${this.token}`,
|
||||||
|
},
|
||||||
|
}).then((res) => res.json());
|
||||||
|
|
||||||
|
return repos;
|
||||||
|
} catch (error) {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async fetchBranches(owner: string, repo: string): Promise<DropdownItem[]> {
|
||||||
|
const branches = await this.octokit
|
||||||
|
.request('GET /repos/{owner}/{repo}/branches', {
|
||||||
|
owner,
|
||||||
|
repo,
|
||||||
|
})
|
||||||
|
.then((res) =>
|
||||||
|
res.data.map((branch) => {
|
||||||
|
return {
|
||||||
|
label: branch.name,
|
||||||
|
value: branch.commit.sha,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
return branches;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,115 @@
|
||||||
|
import { createSlice, PayloadAction } from '@reduxjs/toolkit';
|
||||||
|
import { RootState } from '@/store';
|
||||||
|
import { useAppSelector } from '@/store/hooks';
|
||||||
|
import * as asyncThunk from './async-thunk';
|
||||||
|
import { ComboboxItem, DropdownItem } from '@/components';
|
||||||
|
import { UserData } from './github-client';
|
||||||
|
|
||||||
|
export type Repository = {
|
||||||
|
name: string;
|
||||||
|
url: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export namespace GithubState {
|
||||||
|
export type Token = string;
|
||||||
|
|
||||||
|
export type State = 'disconnected' | 'loading' | 'connected';
|
||||||
|
|
||||||
|
export type QueryUserAndOrganizations =
|
||||||
|
| 'idle'
|
||||||
|
| 'loading'
|
||||||
|
| 'failed'
|
||||||
|
| 'success';
|
||||||
|
|
||||||
|
export type QueryLoading = 'idle' | 'loading' | 'failed' | 'success';
|
||||||
|
|
||||||
|
export type UserAndOrganizations = Array<UserData>;
|
||||||
|
|
||||||
|
export type Repositories = Array<Repository>;
|
||||||
|
|
||||||
|
export type Branches = Array<DropdownItem>;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface GithubState {
|
||||||
|
token: GithubState.Token;
|
||||||
|
state: GithubState.State;
|
||||||
|
userAndOrganizations: GithubState.UserAndOrganizations;
|
||||||
|
queryUserAndOrganizations: GithubState.QueryUserAndOrganizations;
|
||||||
|
queryLoading: GithubState.QueryLoading;
|
||||||
|
repositories: GithubState.Repositories;
|
||||||
|
branches: GithubState.Branches;
|
||||||
|
}
|
||||||
|
|
||||||
|
const initialState: GithubState = {
|
||||||
|
token: '',
|
||||||
|
state: 'disconnected',
|
||||||
|
queryUserAndOrganizations: 'idle',
|
||||||
|
queryLoading: 'idle',
|
||||||
|
userAndOrganizations: [],
|
||||||
|
repositories: [],
|
||||||
|
branches: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
export const githubSlice = createSlice({
|
||||||
|
name: 'github',
|
||||||
|
initialState,
|
||||||
|
reducers: {
|
||||||
|
setToken: (state, action: PayloadAction<GithubState.Token>) => {
|
||||||
|
state.token = action.payload;
|
||||||
|
state.state = 'connected';
|
||||||
|
},
|
||||||
|
setState: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<Exclude<GithubState.State, 'connected'>>
|
||||||
|
) => {
|
||||||
|
state.token = '';
|
||||||
|
state.state = action.payload;
|
||||||
|
},
|
||||||
|
setRepositoires: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<GithubState.Repositoires>
|
||||||
|
) => {
|
||||||
|
state.repositories = action.payload;
|
||||||
|
state.queryLoading = 'success';
|
||||||
|
},
|
||||||
|
setBranches: (state, action: PayloadAction<GithubState.Branches>) => {
|
||||||
|
state.branches = action.payload;
|
||||||
|
state.queryLoading = 'success';
|
||||||
|
},
|
||||||
|
setUserAndOrgs: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<GithubState.UserAndOrganizations>
|
||||||
|
) => {
|
||||||
|
state.userAndOrganizations = action.payload;
|
||||||
|
state.queryUserAndOrganizations = 'success';
|
||||||
|
},
|
||||||
|
setQueryUserState: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<Exclude<GithubState.QueryLoading, 'success'>>
|
||||||
|
) => {
|
||||||
|
state.queryUserAndOrganizations = action.payload;
|
||||||
|
},
|
||||||
|
setQueryState: (
|
||||||
|
state,
|
||||||
|
action: PayloadAction<Exclude<GithubState.QueryLoading, 'success'>>
|
||||||
|
) => {
|
||||||
|
state.queryLoading = action.payload;
|
||||||
|
},
|
||||||
|
disconnect: (state) => {
|
||||||
|
state.token = '';
|
||||||
|
state.state = 'disconnected';
|
||||||
|
},
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
export const githubActions = {
|
||||||
|
...githubSlice.actions,
|
||||||
|
...asyncThunk,
|
||||||
|
};
|
||||||
|
|
||||||
|
const selectGithubState = (state: RootState): GithubState => state.github;
|
||||||
|
|
||||||
|
export const useGithubStore = (): GithubState =>
|
||||||
|
useAppSelector(selectGithubState);
|
||||||
|
|
||||||
|
export default githubSlice.reducer;
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
export * from './github-slice';
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
export * from './wallet';
|
export * from './wallet';
|
||||||
|
export * from './github';
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
import { configureStore } from '@reduxjs/toolkit';
|
import { configureStore } from '@reduxjs/toolkit';
|
||||||
import walletReducer from './features/wallet/wallet-slice';
|
import walletReducer from './features/wallet/wallet-slice';
|
||||||
|
import githubReducer from './features/github/github-slice';
|
||||||
|
|
||||||
export const store = configureStore({
|
export const store = configureStore({
|
||||||
reducer: {
|
reducer: {
|
||||||
wallet: walletReducer,
|
wallet: walletReducer,
|
||||||
|
github: githubReducer,
|
||||||
},
|
},
|
||||||
middleware: (getDefaultMiddleware) =>
|
middleware: (getDefaultMiddleware) =>
|
||||||
getDefaultMiddleware({
|
getDefaultMiddleware({
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
import { Button, Icon } from '@/components';
|
||||||
|
import { githubActions, useAppDispatch, useGithubStore } from '@/store';
|
||||||
|
import { Mint } from '@/views/mint/mint.context';
|
||||||
|
import { useCallback } from 'react';
|
||||||
|
|
||||||
|
export const GithubButton = () => {
|
||||||
|
const { state } = useGithubStore();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
const { setGithubStep } = Mint.useContext();
|
||||||
|
|
||||||
|
const handleGithubLogin = useCallback(() => {
|
||||||
|
dispatch(githubActions.login())
|
||||||
|
.then(() => setGithubStep(2))
|
||||||
|
.catch((error) => {
|
||||||
|
//TODO show toast with error message
|
||||||
|
console.log(error);
|
||||||
|
});
|
||||||
|
}, [dispatch]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button
|
||||||
|
iconSpacing="59"
|
||||||
|
size="lg"
|
||||||
|
variant="ghost"
|
||||||
|
css={{
|
||||||
|
backgroundColor: '$slate4',
|
||||||
|
color: '$slate12',
|
||||||
|
py: '$2h',
|
||||||
|
}}
|
||||||
|
onClick={handleGithubLogin}
|
||||||
|
disabled={state === 'loading'}
|
||||||
|
rightIcon={
|
||||||
|
<Icon name="github" css={{ color: 'white', fontSize: '$4xl' }} />
|
||||||
|
}
|
||||||
|
>
|
||||||
|
GitHub
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,14 +1,7 @@
|
||||||
import { Button, Card, Grid, Icon, IconButton } from '@/components';
|
import { Card, Grid, Icon, IconButton } from '@/components';
|
||||||
import { Mint } from '../../../mint.context';
|
import { GithubButton } from './github-button';
|
||||||
|
|
||||||
export const GithubConnect: React.FC = () => {
|
export const GithubConnect: React.FC = () => (
|
||||||
const { setGithubStep } = Mint.useContext();
|
|
||||||
|
|
||||||
const handleNextStep = () => {
|
|
||||||
//TODO when we integrate GH login, we'll need to set the step to 2 after login
|
|
||||||
setGithubStep(2);
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<Card.Container>
|
<Card.Container>
|
||||||
<Card.Heading
|
<Card.Heading
|
||||||
title="Connect GitHub"
|
title="Connect GitHub"
|
||||||
|
|
@ -23,22 +16,7 @@ export const GithubConnect: React.FC = () => {
|
||||||
/>
|
/>
|
||||||
<Card.Body>
|
<Card.Body>
|
||||||
<Grid css={{ rowGap: '$6' }}>
|
<Grid css={{ rowGap: '$6' }}>
|
||||||
<Button
|
<GithubButton />
|
||||||
iconSpacing="59"
|
|
||||||
size="lg"
|
|
||||||
variant="ghost"
|
|
||||||
css={{
|
|
||||||
backgroundColor: '$slate4',
|
|
||||||
color: '$slate12',
|
|
||||||
py: '$2h',
|
|
||||||
}}
|
|
||||||
onClick={handleNextStep}
|
|
||||||
rightIcon={
|
|
||||||
<Icon name="github" css={{ color: 'white', fontSize: '$4xl' }} />
|
|
||||||
}
|
|
||||||
>
|
|
||||||
GitHub
|
|
||||||
</Button>
|
|
||||||
<Card.Text
|
<Card.Text
|
||||||
css={{ height: '$46h', width: '$95', fontSize: '$md', px: '$12' }}
|
css={{ height: '$46h', width: '$95', fontSize: '$md', px: '$12' }}
|
||||||
>
|
>
|
||||||
|
|
@ -49,5 +27,4 @@ export const GithubConnect: React.FC = () => {
|
||||||
</Grid>
|
</Grid>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
</Card.Container>
|
</Card.Container>
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
import { Dropdown, DropdownItem, Flex, Form, Spinner } from '@/components';
|
||||||
|
import { githubActions, useAppDispatch, useGithubStore } from '@/store';
|
||||||
|
import { Mint } from '@/views/mint/mint.context';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
export const RepoBranchCommitFields = () => {
|
||||||
|
const { queryLoading, branches } = useGithubStore();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const {
|
||||||
|
repositoryName,
|
||||||
|
selectedUserOrg,
|
||||||
|
branchName,
|
||||||
|
commitHash,
|
||||||
|
setBranchName,
|
||||||
|
setCommitHash,
|
||||||
|
} = Mint.useContext();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (queryLoading === 'idle') {
|
||||||
|
dispatch(
|
||||||
|
githubActions.fetchBranchesThunk({
|
||||||
|
owner: selectedUserOrg.label,
|
||||||
|
repository: repositoryName.name,
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}, [queryLoading, dispatch]);
|
||||||
|
|
||||||
|
const handleBranchChange = (dorpdownOption: DropdownItem) => {
|
||||||
|
setBranchName(dorpdownOption);
|
||||||
|
setCommitHash(dorpdownOption.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleCommitHashChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
||||||
|
setCommitHash(e.target.value);
|
||||||
|
};
|
||||||
|
|
||||||
|
if (queryLoading === 'loading') {
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
css={{
|
||||||
|
height: '9.75rem',
|
||||||
|
justifyContent: 'center',
|
||||||
|
alignItems: 'center',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Spinner />
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Form.Field>
|
||||||
|
<Form.Label>Git Branch</Form.Label>
|
||||||
|
<Dropdown
|
||||||
|
items={branches}
|
||||||
|
selectedValue={branchName}
|
||||||
|
onChange={handleBranchChange}
|
||||||
|
/>
|
||||||
|
</Form.Field>
|
||||||
|
<Form.Field>
|
||||||
|
<Form.Label>Git Commit</Form.Label>
|
||||||
|
<Form.Input
|
||||||
|
placeholder="Select branch to get last commit"
|
||||||
|
value={commitHash}
|
||||||
|
onChange={handleCommitHashChange}
|
||||||
|
/>
|
||||||
|
</Form.Field>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,60 +1,22 @@
|
||||||
import {
|
import { Button, Card, Flex, Stepper } from '@/components';
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Dropdown,
|
|
||||||
DropdownItem,
|
|
||||||
Form,
|
|
||||||
Grid,
|
|
||||||
Stepper,
|
|
||||||
} from '@/components';
|
|
||||||
import { Mint } from '@/views/mint/mint.context';
|
import { Mint } from '@/views/mint/mint.context';
|
||||||
import { useState } from 'react';
|
|
||||||
import { RepoRow } from '../github-repository-selection';
|
import { RepoRow } from '../github-repository-selection';
|
||||||
|
import { RepoBranchCommitFields } from './repo-branch-commit-fields';
|
||||||
//TODO remove once it's integrated with GH login
|
|
||||||
const branches: DropdownItem[] = [
|
|
||||||
{
|
|
||||||
label: 'master',
|
|
||||||
value: 'master',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'develop',
|
|
||||||
value: 'develop',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
label: 'feature/branch',
|
|
||||||
value: 'feature/branch',
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
export const RepoConfigurationBody = () => {
|
export const RepoConfigurationBody = () => {
|
||||||
const { repositoryName, branchName, commitHash, setRepositoryConfig } =
|
const { repositoryName, branchName, commitHash } = Mint.useContext();
|
||||||
Mint.useContext();
|
|
||||||
|
|
||||||
const { nextStep } = Stepper.useContext();
|
const { nextStep } = Stepper.useContext();
|
||||||
const [branchSelected, setBranchSelected] = useState(branchName);
|
|
||||||
const [commitHashSelected, setCommitHashSelected] = useState(commitHash);
|
|
||||||
console.log(branchSelected);
|
|
||||||
const handleBranchChange = (dorpdownOption: DropdownItem) => {
|
|
||||||
//TODO we'll have to check the data that GH API returns
|
|
||||||
console.log(dorpdownOption);
|
|
||||||
setBranchSelected(dorpdownOption);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCommitHashChange = (e: React.ChangeEvent<HTMLInputElement>) => {
|
|
||||||
setCommitHashSelected(e.target.value);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleContinueClick = () => {
|
const handleContinueClick = () => {
|
||||||
setRepositoryConfig(branchSelected, commitHashSelected);
|
|
||||||
nextStep();
|
nextStep();
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card.Body css={{ pt: '$2' }}>
|
<Card.Body css={{ pt: '$2' }}>
|
||||||
<Grid css={{ rowGap: '$6' }}>
|
<Flex css={{ rowGap: '$6', flexDirection: 'column' }}>
|
||||||
<RepoRow
|
<RepoRow
|
||||||
repo={repositoryName}
|
repo={repositoryName.name}
|
||||||
css={{ mb: '0' }}
|
css={{ mb: '0' }}
|
||||||
button={
|
button={
|
||||||
<Button
|
<Button
|
||||||
|
|
@ -67,31 +29,16 @@ export const RepoConfigurationBody = () => {
|
||||||
</Button>
|
</Button>
|
||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<Form.Field>
|
<RepoBranchCommitFields />
|
||||||
<Form.Label>Git Branch</Form.Label>
|
|
||||||
<Dropdown
|
|
||||||
items={branches}
|
|
||||||
selectedValue={branchSelected}
|
|
||||||
onChange={handleBranchChange}
|
|
||||||
/>
|
|
||||||
</Form.Field>
|
|
||||||
<Form.Field>
|
|
||||||
<Form.Label>Git Commit</Form.Label>
|
|
||||||
<Form.Input
|
|
||||||
placeholder="693f89763dbb7a6c9ce0711cc34591a4c8c77198"
|
|
||||||
value={commitHashSelected}
|
|
||||||
onChange={handleCommitHashChange}
|
|
||||||
/>
|
|
||||||
</Form.Field>
|
|
||||||
<Button
|
<Button
|
||||||
disabled={!branchSelected || !commitHashSelected}
|
disabled={!branchName.value || !commitHash}
|
||||||
colorScheme="blue"
|
colorScheme="blue"
|
||||||
variant="solid"
|
variant="solid"
|
||||||
onClick={handleContinueClick}
|
onClick={handleContinueClick}
|
||||||
>
|
>
|
||||||
Continue
|
Continue
|
||||||
</Button>
|
</Button>
|
||||||
</Grid>
|
</Flex>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -3,11 +3,12 @@ import { MintCardHeader } from '@/views/mint/mint-card';
|
||||||
import { Mint } from '@/views/mint/mint.context';
|
import { Mint } from '@/views/mint/mint.context';
|
||||||
|
|
||||||
export const RepoConfigurationHeader = () => {
|
export const RepoConfigurationHeader = () => {
|
||||||
const { setGithubStep, setRepositoryConfig } = Mint.useContext();
|
const { setGithubStep, setBranchName, setCommitHash } = Mint.useContext();
|
||||||
|
|
||||||
const handlePrevStepClick = () => {
|
const handlePrevStepClick = () => {
|
||||||
setGithubStep(2);
|
setGithubStep(2);
|
||||||
setRepositoryConfig({} as DropdownItem, '');
|
setBranchName({} as DropdownItem);
|
||||||
|
setCommitHash('');
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|
|
||||||
|
|
@ -1,42 +1,23 @@
|
||||||
import {
|
import { Card, ComboboxItem, Flex, Grid, Icon, Spinner } from '@/components';
|
||||||
Button,
|
|
||||||
Card,
|
|
||||||
Combobox,
|
|
||||||
ComboboxItem,
|
|
||||||
DropdownItem,
|
|
||||||
Flex,
|
|
||||||
Grid,
|
|
||||||
Icon,
|
|
||||||
IconButton,
|
|
||||||
NoResults,
|
|
||||||
} from '@/components';
|
|
||||||
import { Input } from '@/components/core/input';
|
import { Input } from '@/components/core/input';
|
||||||
import { Separator } from '@/components/core/separator.styles';
|
import { useGithubStore } from '@/store';
|
||||||
import { MintCardHeader } from '@/views/mint/mint-card';
|
import { MintCardHeader } from '@/views/mint/mint-card';
|
||||||
import { Mint } from '@/views/mint/mint.context';
|
import { Mint } from '@/views/mint/mint.context';
|
||||||
import React, { forwardRef, useRef, useState } from 'react';
|
import React, { forwardRef, useRef, useState } from 'react';
|
||||||
|
import { RepositoriesList } from './repositories-list';
|
||||||
|
import { UserOrgsCombobox } from './users-orgs-combobox';
|
||||||
|
|
||||||
//TODO remove once it's integrated with GH login
|
export const Loading = () => (
|
||||||
const repos = [
|
<Flex
|
||||||
'DyDx',
|
css={{
|
||||||
'Testing',
|
justifyContent: 'center',
|
||||||
'Hello World',
|
alignItems: 'center',
|
||||||
'Portofolio',
|
height: '$60',
|
||||||
'NFA',
|
}}
|
||||||
'NFT',
|
>
|
||||||
'NFTs',
|
<Spinner />
|
||||||
];
|
</Flex>
|
||||||
|
);
|
||||||
//TODO remove once it's integrated with GH login
|
|
||||||
const users: ComboboxItem[] = [
|
|
||||||
{ label: 'DyDx', value: 'DyDx', icon: 'github' },
|
|
||||||
{ label: 'Testing', value: 'Testing', icon: 'github' },
|
|
||||||
{ label: 'Hello World', value: 'Hello World', icon: 'github' },
|
|
||||||
{ label: 'Portofolio', value: 'Portofolio', icon: 'github' },
|
|
||||||
{ label: 'NFA', value: 'NFA', icon: 'github' },
|
|
||||||
{ label: 'NFT', value: 'NFT', icon: 'github' },
|
|
||||||
{ label: 'NFTs', value: 'NFTs', icon: 'github' },
|
|
||||||
];
|
|
||||||
|
|
||||||
type RepoRowProps = {
|
type RepoRowProps = {
|
||||||
repo: string;
|
repo: string;
|
||||||
|
|
@ -60,10 +41,10 @@ export const RepoRow = forwardRef<HTMLDivElement, RepoRowProps>(
|
||||||
);
|
);
|
||||||
|
|
||||||
export const GithubRepositoryConnection: React.FC = () => {
|
export const GithubRepositoryConnection: React.FC = () => {
|
||||||
|
const { queryLoading, queryUserAndOrganizations } = useGithubStore();
|
||||||
const [searchValue, setSearchValue] = useState('');
|
const [searchValue, setSearchValue] = useState('');
|
||||||
const [selectedUser, setSelectedUser] = useState<ComboboxItem | undefined>();
|
|
||||||
const { setGithubStep, setRepositoryName, setRepositoryConfig } =
|
const { setGithubStep, setSelectedUserOrg } = Mint.useContext();
|
||||||
Mint.useContext();
|
|
||||||
|
|
||||||
const timeOutRef = useRef<NodeJS.Timeout>();
|
const timeOutRef = useRef<NodeJS.Timeout>();
|
||||||
|
|
||||||
|
|
@ -77,21 +58,9 @@ export const GithubRepositoryConnection: React.FC = () => {
|
||||||
|
|
||||||
const handlePrevStepClick = () => {
|
const handlePrevStepClick = () => {
|
||||||
setGithubStep(1);
|
setGithubStep(1);
|
||||||
|
setSelectedUserOrg({} as ComboboxItem);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleSelectRepo = (repo: string) => {
|
|
||||||
setRepositoryName(repo);
|
|
||||||
setGithubStep(3);
|
|
||||||
setRepositoryConfig({} as DropdownItem, '');
|
|
||||||
};
|
|
||||||
|
|
||||||
const filteredRepositories =
|
|
||||||
searchValue === ''
|
|
||||||
? repos
|
|
||||||
: repos.filter(
|
|
||||||
(item) => item.toUpperCase().indexOf(searchValue.toUpperCase()) != -1
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Card.Container css={{ maxWidth: '$107h', maxHeight: '$95h', pb: '$0h' }}>
|
<Card.Container css={{ maxWidth: '$107h', maxHeight: '$95h', pb: '$0h' }}>
|
||||||
<MintCardHeader
|
<MintCardHeader
|
||||||
|
|
@ -101,49 +70,19 @@ export const GithubRepositoryConnection: React.FC = () => {
|
||||||
<Card.Body css={{ pt: '$4' }}>
|
<Card.Body css={{ pt: '$4' }}>
|
||||||
<Grid css={{ rowGap: '$2' }}>
|
<Grid css={{ rowGap: '$2' }}>
|
||||||
<Flex css={{ gap: '$4' }}>
|
<Flex css={{ gap: '$4' }}>
|
||||||
<Combobox
|
<UserOrgsCombobox />
|
||||||
items={users}
|
|
||||||
selectedValue={selectedUser}
|
|
||||||
onChange={setSelectedUser}
|
|
||||||
/>
|
|
||||||
<Input
|
<Input
|
||||||
leftIcon="search"
|
leftIcon="search"
|
||||||
placeholder="Search"
|
placeholder="Search"
|
||||||
onChange={handleSearchChange}
|
onChange={handleSearchChange}
|
||||||
/>
|
/>
|
||||||
</Flex>
|
</Flex>
|
||||||
<Flex
|
{queryLoading === 'loading' ||
|
||||||
css={{
|
queryUserAndOrganizations === 'loading' ? (
|
||||||
minHeight: '$40',
|
<Loading />
|
||||||
maxHeight: '$60',
|
) : (
|
||||||
overflowX: 'hidden',
|
<RepositoriesList searchValue={searchValue} />
|
||||||
overflowY: 'scroll',
|
)}
|
||||||
flexDirection: 'column',
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
{filteredRepositories.length > 0 ? (
|
|
||||||
filteredRepositories.map((repo, index, { length }) => (
|
|
||||||
<React.Fragment key={repo}>
|
|
||||||
<RepoRow
|
|
||||||
repo={repo}
|
|
||||||
button={
|
|
||||||
<Button
|
|
||||||
colorScheme="blue"
|
|
||||||
variant="outline"
|
|
||||||
css={{ py: '$1', height: '$5', borderRadius: '$md' }}
|
|
||||||
onClick={() => handleSelectRepo(repo)}
|
|
||||||
>
|
|
||||||
Use for NFA
|
|
||||||
</Button>
|
|
||||||
}
|
|
||||||
/>
|
|
||||||
{index < length - 1 && <Separator />}
|
|
||||||
</React.Fragment>
|
|
||||||
))
|
|
||||||
) : (
|
|
||||||
<NoResults css="text-center" />
|
|
||||||
)}
|
|
||||||
</Flex>
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</Card.Body>
|
</Card.Body>
|
||||||
</Card.Container>
|
</Card.Container>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,58 @@
|
||||||
|
import { useEffect, useMemo } from 'react';
|
||||||
|
import { Flex, NoResults } from '@/components';
|
||||||
|
import { Mint } from '@/views/mint/mint.context';
|
||||||
|
import { githubActions, useAppDispatch, useGithubStore } from '@/store';
|
||||||
|
import { Repository } from './repository';
|
||||||
|
|
||||||
|
type RepositoriesListProps = {
|
||||||
|
searchValue: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const RepositoriesList = ({ searchValue }: RepositoriesListProps) => {
|
||||||
|
const { selectedUserOrg } = Mint.useContext();
|
||||||
|
const { queryLoading, repositories } = useGithubStore();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const filteredRepositories = useMemo(() => {
|
||||||
|
return searchValue === ''
|
||||||
|
? repositories
|
||||||
|
: repositories.filter(
|
||||||
|
(item) =>
|
||||||
|
item.name.toUpperCase().indexOf(searchValue.toUpperCase()) != -1
|
||||||
|
);
|
||||||
|
}, [searchValue, repositories]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (queryLoading === 'idle' && selectedUserOrg.value) {
|
||||||
|
dispatch(githubActions.fetchRepositoriesThunk(selectedUserOrg.value));
|
||||||
|
}
|
||||||
|
}, [queryLoading, dispatch, selectedUserOrg]);
|
||||||
|
|
||||||
|
if (queryLoading === 'failed') {
|
||||||
|
return <span>Error</span>;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Flex
|
||||||
|
css={{
|
||||||
|
height: '$60',
|
||||||
|
overflowX: 'hidden',
|
||||||
|
overflowY: 'scroll',
|
||||||
|
flexDirection: 'column',
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{filteredRepositories.length > 0 ? (
|
||||||
|
filteredRepositories.map((repo, index, { length }) => (
|
||||||
|
<Repository
|
||||||
|
key={repo.name}
|
||||||
|
repository={repo}
|
||||||
|
index={index}
|
||||||
|
length={length}
|
||||||
|
/>
|
||||||
|
))
|
||||||
|
) : (
|
||||||
|
<NoResults css="text-center" />
|
||||||
|
)}
|
||||||
|
</Flex>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
import { Button, Separator } from '@/components';
|
||||||
|
import {
|
||||||
|
githubActions,
|
||||||
|
Repository as RepositoryType,
|
||||||
|
useAppDispatch,
|
||||||
|
} from '@/store';
|
||||||
|
import { Mint } from '@/views/mint/mint.context';
|
||||||
|
import { RepoRow } from './github-repository-selection';
|
||||||
|
|
||||||
|
type RepositoryProps = {
|
||||||
|
repository: RepositoryType;
|
||||||
|
index: number;
|
||||||
|
length: number;
|
||||||
|
};
|
||||||
|
export const Repository = ({ repository, index, length }: RepositoryProps) => {
|
||||||
|
const { setGithubStep, setRepositoryName } = Mint.useContext();
|
||||||
|
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const handleSelectRepo = () => {
|
||||||
|
setRepositoryName(repository);
|
||||||
|
setGithubStep(3);
|
||||||
|
dispatch(githubActions.setQueryState('idle'));
|
||||||
|
};
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<RepoRow
|
||||||
|
repo={repository.name}
|
||||||
|
button={
|
||||||
|
<Button
|
||||||
|
colorScheme="blue"
|
||||||
|
variant="outline"
|
||||||
|
css={{ py: '$1', height: '$5', borderRadius: '$md' }}
|
||||||
|
onClick={handleSelectRepo}
|
||||||
|
>
|
||||||
|
Use for NFA
|
||||||
|
</Button>
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
{index < length - 1 && <Separator />}
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
import { Avatar, Combobox, ComboboxItem } from '@/components';
|
||||||
|
import { githubActions, useAppDispatch, useGithubStore } from '@/store';
|
||||||
|
import { Mint } from '@/views/mint/mint.context';
|
||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
export const UserOrgsCombobox = () => {
|
||||||
|
const { queryUserAndOrganizations, userAndOrganizations } = useGithubStore();
|
||||||
|
const dispatch = useAppDispatch();
|
||||||
|
|
||||||
|
const { selectedUserOrg, setSelectedUserOrg } = Mint.useContext();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (queryUserAndOrganizations === 'idle') {
|
||||||
|
dispatch(githubActions.fetchUserAndOrgsThunk());
|
||||||
|
}
|
||||||
|
}, [dispatch, queryUserAndOrganizations]);
|
||||||
|
|
||||||
|
const handleUserOrgChange = (item: ComboboxItem) => {
|
||||||
|
dispatch(githubActions.fetchRepositoriesThunk(item.value));
|
||||||
|
setSelectedUserOrg(item);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (
|
||||||
|
queryUserAndOrganizations === 'success' &&
|
||||||
|
selectedUserOrg.value === undefined &&
|
||||||
|
userAndOrganizations.length > 0
|
||||||
|
) {
|
||||||
|
//SET first user
|
||||||
|
setSelectedUserOrg(userAndOrganizations[0]);
|
||||||
|
}
|
||||||
|
}, [queryUserAndOrganizations]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Combobox
|
||||||
|
items={userAndOrganizations.map(
|
||||||
|
(item) =>
|
||||||
|
({
|
||||||
|
label: item.label,
|
||||||
|
value: item.value,
|
||||||
|
icon: <Avatar src={item.avatar} />,
|
||||||
|
} as ComboboxItem)
|
||||||
|
)}
|
||||||
|
selectedValue={selectedUserOrg}
|
||||||
|
onChange={handleUserOrgChange}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
@ -1,9 +1,11 @@
|
||||||
import { DropdownItem } from '@/components';
|
import { ComboboxItem, DropdownItem } from '@/components';
|
||||||
|
import { Repository } from '@/store';
|
||||||
import { createContext } from '@/utils';
|
import { createContext } from '@/utils';
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
|
|
||||||
export type MintContext = {
|
export type MintContext = {
|
||||||
repositoryName: string;
|
selectedUserOrg: ComboboxItem;
|
||||||
|
repositoryName: Repository;
|
||||||
branchName: DropdownItem; //get value from DropdownItem to mint
|
branchName: DropdownItem; //get value from DropdownItem to mint
|
||||||
commitHash: string;
|
commitHash: string;
|
||||||
githubStep: number;
|
githubStep: number;
|
||||||
|
|
@ -11,13 +13,15 @@ export type MintContext = {
|
||||||
appDescription: string;
|
appDescription: string;
|
||||||
appLogo: string;
|
appLogo: string;
|
||||||
logoColor: string;
|
logoColor: string;
|
||||||
ens: DropdownItem; //maybe it would be a DropdownItem
|
ens: DropdownItem;
|
||||||
domain: string;
|
domain: string;
|
||||||
verifyNFA: boolean;
|
verifyNFA: boolean;
|
||||||
sucessMint: boolean | undefined;
|
sucessMint: boolean | undefined;
|
||||||
setGithubStep: (step: number) => void;
|
setGithubStep: (step: number) => void;
|
||||||
setRepositoryName: (repo: string) => void;
|
setSelectedUserOrg: (userOrg: ComboboxItem) => void;
|
||||||
setRepositoryConfig: (branch: DropdownItem, hash: string) => void;
|
setRepositoryName: (repo: Repository) => void;
|
||||||
|
setBranchName: (branch: DropdownItem) => void;
|
||||||
|
setCommitHash: (hash: string) => void;
|
||||||
setAppName: (name: string) => void;
|
setAppName: (name: string) => void;
|
||||||
setAppDescription: (description: string) => void;
|
setAppDescription: (description: string) => void;
|
||||||
setAppLogo: (logo: string) => void;
|
setAppLogo: (logo: string) => void;
|
||||||
|
|
@ -39,7 +43,10 @@ export abstract class Mint {
|
||||||
|
|
||||||
static readonly Provider: React.FC<Mint.ProviderProps> = ({ children }) => {
|
static readonly Provider: React.FC<Mint.ProviderProps> = ({ children }) => {
|
||||||
//Github Connection
|
//Github Connection
|
||||||
const [repositoryName, setRepositoryName] = useState('');
|
const [selectedUserOrg, setSelectedUserOrg] = useState({} as ComboboxItem);
|
||||||
|
const [repositoryName, setRepositoryName] = useState<Repository>(
|
||||||
|
{} as Repository
|
||||||
|
);
|
||||||
const [branchName, setBranchName] = useState({} as DropdownItem);
|
const [branchName, setBranchName] = useState({} as DropdownItem);
|
||||||
const [commitHash, setCommitHash] = useState('');
|
const [commitHash, setCommitHash] = useState('');
|
||||||
const [githubStep, setGithubStepContext] = useState(1);
|
const [githubStep, setGithubStepContext] = useState(1);
|
||||||
|
|
@ -64,14 +71,10 @@ export abstract class Mint {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setRepositoryConfig = (branch: DropdownItem, hash: string) => {
|
|
||||||
setBranchName(branch);
|
|
||||||
setCommitHash(hash);
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MintProvider
|
<MintProvider
|
||||||
value={{
|
value={{
|
||||||
|
selectedUserOrg,
|
||||||
repositoryName,
|
repositoryName,
|
||||||
branchName,
|
branchName,
|
||||||
commitHash,
|
commitHash,
|
||||||
|
|
@ -84,9 +87,11 @@ export abstract class Mint {
|
||||||
domain,
|
domain,
|
||||||
verifyNFA,
|
verifyNFA,
|
||||||
sucessMint,
|
sucessMint,
|
||||||
|
setSelectedUserOrg,
|
||||||
setGithubStep,
|
setGithubStep,
|
||||||
setRepositoryConfig,
|
|
||||||
setRepositoryName,
|
setRepositoryName,
|
||||||
|
setBranchName,
|
||||||
|
setCommitHash,
|
||||||
setAppName,
|
setAppName,
|
||||||
setAppDescription,
|
setAppDescription,
|
||||||
setAppLogo,
|
setAppLogo,
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,68 @@ import { defineConfig } from 'vite';
|
||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
import tsconfigPaths from 'vite-tsconfig-paths';
|
import tsconfigPaths from 'vite-tsconfig-paths';
|
||||||
|
|
||||||
|
import { NodeGlobalsPolyfillPlugin } from '@esbuild-plugins/node-globals-polyfill';
|
||||||
|
import { NodeModulesPolyfillPlugin } from '@esbuild-plugins/node-modules-polyfill';
|
||||||
|
import rollupNodePolyFill from 'rollup-plugin-node-polyfills';
|
||||||
|
import builtins from 'rollup-plugin-node-builtins';
|
||||||
|
|
||||||
// https://vitejs.dev/config/
|
// https://vitejs.dev/config/
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
plugins: [react(), tsconfigPaths()],
|
plugins: [react(), tsconfigPaths()],
|
||||||
|
resolve: {
|
||||||
|
alias: {
|
||||||
|
// This Rollup aliases are extracted from @esbuild-plugins/node-modules-polyfill,
|
||||||
|
// see https://github.com/remorses/esbuild-plugins/blob/master/node-modules-polyfill/src/polyfills.ts
|
||||||
|
// process and buffer are excluded because already managed
|
||||||
|
// by node-globals-polyfill
|
||||||
|
util: 'rollup-plugin-node-polyfills/polyfills/util',
|
||||||
|
sys: 'util',
|
||||||
|
events: 'rollup-plugin-node-polyfills/polyfills/events',
|
||||||
|
stream: 'rollup-plugin-node-polyfills/polyfills/stream',
|
||||||
|
path: 'rollup-plugin-node-polyfills/polyfills/path',
|
||||||
|
querystring: 'rollup-plugin-node-polyfills/polyfills/qs',
|
||||||
|
punycode: 'rollup-plugin-node-polyfills/polyfills/punycode',
|
||||||
|
url: 'rollup-plugin-node-polyfills/polyfills/url',
|
||||||
|
string_decoder: 'rollup-plugin-node-polyfills/polyfills/string-decoder',
|
||||||
|
http: 'rollup-plugin-node-polyfills/polyfills/http',
|
||||||
|
https: 'rollup-plugin-node-polyfills/polyfills/http',
|
||||||
|
os: 'rollup-plugin-node-polyfills/polyfills/os',
|
||||||
|
assert: 'rollup-plugin-node-polyfills/polyfills/assert',
|
||||||
|
constants: 'rollup-plugin-node-polyfills/polyfills/constants',
|
||||||
|
_stream_duplex:
|
||||||
|
'rollup-plugin-node-polyfills/polyfills/readable-stream/duplex',
|
||||||
|
_stream_passthrough:
|
||||||
|
'rollup-plugin-node-polyfills/polyfills/readable-stream/passthrough',
|
||||||
|
_stream_readable:
|
||||||
|
'rollup-plugin-node-polyfills/polyfills/readable-stream/readable',
|
||||||
|
_stream_writable:
|
||||||
|
'rollup-plugin-node-polyfills/polyfills/readable-stream/writable',
|
||||||
|
_stream_transform:
|
||||||
|
'rollup-plugin-node-polyfills/polyfills/readable-stream/transform',
|
||||||
|
timers: 'rollup-plugin-node-polyfills/polyfills/timers',
|
||||||
|
console: 'rollup-plugin-node-polyfills/polyfills/console',
|
||||||
|
vm: 'rollup-plugin-node-polyfills/polyfills/vm',
|
||||||
|
zlib: 'rollup-plugin-node-polyfills/polyfills/zlib',
|
||||||
|
tty: 'rollup-plugin-node-polyfills/polyfills/tty',
|
||||||
|
domain: 'rollup-plugin-node-polyfills/polyfills/domain',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
optimizeDeps: {
|
||||||
|
esbuildOptions: {
|
||||||
|
target: 'es2020',
|
||||||
|
supported: { bigint: true },
|
||||||
|
plugins: [NodeModulesPolyfillPlugin()],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
build: {
|
||||||
|
target: 'es2020',
|
||||||
|
rollupOptions: {
|
||||||
|
plugins: [
|
||||||
|
// Enable rollup polyfills plugin
|
||||||
|
// used during production bundling
|
||||||
|
builtins(),
|
||||||
|
rollupNodePolyFill(),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
});
|
});
|
||||||
|
|
|
||||||
1339
ui/yarn.lock
1339
ui/yarn.lock
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue