forked from cerc-io/snowballtools-base
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
30357672ef | ||
|
|
2457d5a095 | ||
|
|
234803e313 | ||
|
|
1fbaf6fdf0 | ||
|
|
66277d6c3b | ||
|
|
3215a19141 | ||
|
|
282001c317 | ||
|
|
2f62d086de | ||
|
|
4c544e8d15 | ||
|
|
a02ee13f9d | ||
|
|
e32a51a771 | ||
|
|
513ca69d01 | ||
|
|
e34b8d6a2e | ||
|
|
f4d5b77784 | ||
|
|
399b80ce3b | ||
|
|
fdaec2da94 | ||
|
|
13fc92bf0e | ||
|
|
8a8ee1d6ae | ||
|
|
5680961964 | ||
|
|
aa0ca8dd21 | ||
|
|
8280f4c7f7 | ||
|
|
ab72bbb03f | ||
|
|
195471b888 | ||
|
|
8ce531274d | ||
|
|
6c38094093 | ||
|
|
95285d30dd | ||
|
|
61c8846400 | ||
|
|
d73c3c7daf |
@@ -4,9 +4,18 @@
|
||||
```bash
|
||||
yarn
|
||||
```
|
||||
```bash
|
||||
brew install jq # if you do not have jq installed already
|
||||
```
|
||||
|
||||
|
||||
|
||||
|
||||
Example of how to make the necessary deploy edits [here](https://github.com/snowball-tools/snowballtools-base/pull/131/files).
|
||||
|
||||
- Replace variables in the following files
|
||||
- [records/application-deployment-request.yml](records/application-deployment-request.yml)
|
||||
- update the name & application version numbers
|
||||
- `<CURRENT_DATE_TIME>`: Replace with current time which can be generated by command `date -u`
|
||||
```yml
|
||||
# Example
|
||||
@@ -42,9 +51,10 @@
|
||||
repository_ref: <COMMIT_HASH>
|
||||
```
|
||||
- [deploy-frontend.sh](deploy-frontend.sh)
|
||||
Also be sure to update the app version
|
||||
```bash
|
||||
...
|
||||
RCD_APP_VERSION="0.1.0"
|
||||
RCD_APP_VERSION="<NEW_VERSION>"
|
||||
REPO_REF="<COMMIT_HASH>"
|
||||
...
|
||||
```
|
||||
@@ -71,6 +81,9 @@
|
||||
|
||||
## Troubleshoot
|
||||
|
||||
- Check deployment status [here](https://console.laconic.com/deployer).
|
||||
- Check records [here](https://console.laconic.com/#/registry).
|
||||
|
||||
- If deployment fails due to low bond balance
|
||||
- Check balances
|
||||
```bash
|
||||
@@ -83,4 +96,4 @@
|
||||
- Command to refill bond
|
||||
```bash
|
||||
yarn laconic cns bond refill --id 8fcf44b2f326b4b63ac57547777f1c78b7d494e5966e508f09001af53cb440ac --type aphoton --quantity 10000000
|
||||
```
|
||||
```
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
RECORD_FILE=records/application-record.yml
|
||||
CONFIG_FILE=config.yml
|
||||
RCD_APP_VERSION="0.1.0"
|
||||
REPO_REF="353fd0f6219a955be186b5914e93baa9058b4473"
|
||||
RCD_APP_VERSION="0.1.3"
|
||||
REPO_REF="513ca69d01bee857cf207a0605483205b384e218"
|
||||
|
||||
# Publish ApplicationRecord
|
||||
RECORD_ID=$(yarn --silent laconic -c $CONFIG_FILE cns record publish --filename $RECORD_FILE | jq -r '.id')
|
||||
|
||||
@@ -1,21 +1,21 @@
|
||||
record:
|
||||
type: ApplicationDeploymentRequest
|
||||
version: '1.0.0'
|
||||
name: snowballtools-base-frontend@0.1.0
|
||||
application: crn://snowballtools/applications/snowballtools-base-frontend@0.1.0
|
||||
name: snowballtools-base-frontend@0.1.3
|
||||
application: crn://snowballtools/applications/snowballtools-base-frontend@0.1.3
|
||||
dns: dashboard
|
||||
config:
|
||||
env:
|
||||
LACONIC_HOSTED_CONFIG_app_server_url: https://snowballtools-base-api-001.apps.snowballtools.com
|
||||
# If GitHub client ID is changed, same ID and corresponding secret has to be set in backend config
|
||||
LACONIC_HOSTED_CONFIG_app_github_clientid: 1ed99146e0d07aa62d44
|
||||
LACONIC_HOSTED_CONFIG_app_github_templaterepo: deep-stack/test-progressive-web-app
|
||||
LACONIC_HOSTED_CONFIG_app_github_clientid: b7c63b235ca1dd5639ab
|
||||
LACONIC_HOSTED_CONFIG_app_github_templaterepo: snowball-tools-platform/test-progressive-web-app
|
||||
# New config env after changes for image upload PWA
|
||||
LACONIC_HOSTED_CONFIG_app_github_pwa_templaterepo: deep-stack/test-progressive-web-app
|
||||
LACONIC_HOSTED_CONFIG_app_github_image_upload_templaterepo: deep-stack/image-upload-pwa-example
|
||||
LACONIC_HOSTED_CONFIG_app_github_pwa_templaterepo: snowball-tools-platform/test-progressive-web-app
|
||||
LACONIC_HOSTED_CONFIG_app_github_image_upload_templaterepo: snowball-tools-platform/image-upload-pwa-example
|
||||
LACONIC_HOSTED_CONFIG_app_wallet_connect_id: eda9ba18042a5ea500f358194611ece2
|
||||
meta:
|
||||
# Set CURRENT_DATE_TIME; Use command date -u
|
||||
note: Added by Snowball @ <CURRENT_DATE_TIME>
|
||||
note: Added by Snowball @ Tue Feb 27 17:24:06 UTC 2024
|
||||
repository: "https://git.vdb.to/cerc-io/snowballtools-base"
|
||||
repository_ref: 353fd0f6219a955be186b5914e93baa9058b4473
|
||||
repository_ref: 513ca69d01bee857cf207a0605483205b384e218
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
record:
|
||||
type: ApplicationRecord
|
||||
version: 0.0.5
|
||||
repository_ref: 353fd0f6219a955be186b5914e93baa9058b4473
|
||||
version: 0.0.11
|
||||
repository_ref: 513ca69d01bee857cf207a0605483205b384e218
|
||||
repository: ["https://git.vdb.to/cerc-io/snowballtools-base"]
|
||||
app_type: webapp
|
||||
# name is set to repo name
|
||||
name: snowballtools-base-frontend
|
||||
# app_version is set from package.json
|
||||
app_version: 0.1.0
|
||||
app_version: 0.1.3
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
REACT_APP_SERVER_URL = 'http://localhost:8000'
|
||||
|
||||
REACT_APP_GITHUB_CLIENT_ID =
|
||||
REACT_APP_GITHUB_PWA_TEMPLATE_REPO =
|
||||
REACT_APP_GITHUB_IMAGE_UPLOAD_PWA_TEMPLATE_REPO =
|
||||
|
||||
REACT_APP_WALLET_CONNECT_ID =
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "frontend",
|
||||
"version": "0.1.0",
|
||||
"version": "0.1.3",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@fontsource-variable/jetbrains-mono": "^5.0.19",
|
||||
|
||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -7,6 +7,7 @@ import { Chip, IconButton, Spinner } from '@material-tailwind/react';
|
||||
import { relativeTimeISO } from '../../../utils/time';
|
||||
import { GitRepositoryDetails } from '../../../types';
|
||||
import { useGQLClient } from '../../../context/GQLClientContext';
|
||||
import { GithubIcon, LockIcon } from 'components/shared/CustomIcon';
|
||||
|
||||
interface ProjectRepoCardProps {
|
||||
repository: GitRepositoryDetails;
|
||||
@@ -47,16 +48,18 @@ const ProjectRepoCard: React.FC<ProjectRepoCardProps> = ({ repository }) => {
|
||||
className="group flex items-center gap-4 text-gray-500 text-xs hover:bg-gray-100 p-2 cursor-pointer"
|
||||
onClick={createProject}
|
||||
>
|
||||
<div>^</div>
|
||||
<div className="w-10 h-10 bg-white rounded-md justify-center items-center gap-1.5 inline-flex">
|
||||
<GithubIcon />
|
||||
</div>
|
||||
<div className="grow">
|
||||
<div>
|
||||
<span className="text-black">{repository.full_name}</span>
|
||||
{repository.visibility === 'private' && (
|
||||
<Chip
|
||||
className="normal-case inline ml-6 font-normal"
|
||||
className="normal-case inline ml-6 font-normal text-xs text-xs bg-orange-50 border border-orange-200 text-orange-600 items-center gap-1 inline-flex"
|
||||
size="sm"
|
||||
value="Private"
|
||||
icon={'^'}
|
||||
icon={<LockIcon />}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -9,6 +9,7 @@ import SearchBar from '../../SearchBar';
|
||||
import ProjectRepoCard from './ProjectRepoCard';
|
||||
import { GitOrgDetails, GitRepositoryDetails } from '../../../types';
|
||||
import AsyncSelect from '../../shared/AsyncSelect';
|
||||
import { GithubIcon } from 'components/shared/CustomIcon';
|
||||
|
||||
const DEFAULT_SEARCHED_REPO = '';
|
||||
const REPOS_PER_PAGE = 5;
|
||||
@@ -108,7 +109,7 @@ const RepositoryList = ({ octokit }: RepositoryListProps) => {
|
||||
|
||||
return (
|
||||
<div className="p-4">
|
||||
<div className="flex gap-2 mb-2">
|
||||
<div className="flex gap-2 mb-2 items-center">
|
||||
<div className="basis-1/3">
|
||||
<AsyncSelect
|
||||
value={selectedAccount}
|
||||
@@ -116,12 +117,14 @@ const RepositoryList = ({ octokit }: RepositoryListProps) => {
|
||||
>
|
||||
{accounts.map((account) => (
|
||||
<Option key={account.id} value={account.login}>
|
||||
^ {account.login}
|
||||
<div className="flex items-center gap-2 justify-start">
|
||||
<GithubIcon /> {account.login}
|
||||
</div>
|
||||
</Option>
|
||||
))}
|
||||
</AsyncSelect>
|
||||
</div>
|
||||
<div className="basis-2/3">
|
||||
<div className="basis-2/3 flex-grow flex items-center">
|
||||
<SearchBar
|
||||
value={searchedRepo}
|
||||
onChange={(event) => setSearchedRepo(event.target.value)}
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import { CustomIcon, CustomIconProps } from './CustomIcon';
|
||||
|
||||
export const GithubIcon: React.FC<CustomIconProps> = (props) => {
|
||||
return (
|
||||
<CustomIcon
|
||||
width="20"
|
||||
height="20"
|
||||
viewBox="0 0 20 20"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M9.9702 0.206024C4.45694 0.206024 0 4.69582 0 10.2503C0 14.6903 2.85571 18.4487 6.81735 19.7789C7.31265 19.8789 7.49408 19.5628 7.49408 19.2968C7.49408 19.064 7.47776 18.2658 7.47776 17.4342C4.70429 18.033 4.12674 16.2368 4.12674 16.2368C3.68102 15.0728 3.02061 14.7736 3.02061 14.7736C2.11286 14.1583 3.08673 14.1583 3.08673 14.1583C4.09367 14.2248 4.62204 15.1893 4.62204 15.1893C5.51327 16.7191 6.94939 16.2868 7.52714 16.0207C7.60959 15.3721 7.87388 14.9232 8.15449 14.6738C5.94245 14.4409 3.6151 13.5762 3.6151 9.71807C3.6151 8.62051 4.01102 7.72256 4.63837 7.02419C4.53939 6.7748 4.19265 5.74358 4.73755 4.36337C4.73755 4.36337 5.57939 4.09725 7.47755 5.39439C8.29022 5.17453 9.12832 5.06268 9.9702 5.06174C10.812 5.06174 11.6702 5.17827 12.4627 5.39439C14.361 4.09725 15.2029 4.36337 15.2029 4.36337C15.7478 5.74358 15.4008 6.7748 15.3018 7.02419C15.9457 7.72256 16.3253 8.62051 16.3253 9.71807C16.3253 13.5762 13.998 14.4242 11.7694 14.6738C12.1327 14.9897 12.4461 15.5883 12.4461 16.5362C12.4461 17.8832 12.4298 18.9642 12.4298 19.2966C12.4298 19.5628 12.6114 19.8789 13.1065 19.7791C17.0682 18.4485 19.9239 14.6903 19.9239 10.2503C19.9402 4.69582 15.4669 0.206024 9.9702 0.206024Z"
|
||||
fill="#0B1D2E"
|
||||
/>
|
||||
</CustomIcon>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
import React from 'react';
|
||||
import { CustomIcon, CustomIconProps } from './CustomIcon';
|
||||
|
||||
export const LockIcon: React.FC<CustomIconProps> = (props) => {
|
||||
return (
|
||||
<CustomIcon
|
||||
width="16"
|
||||
height="16"
|
||||
viewBox="0 0 16 16"
|
||||
fill="none"
|
||||
{...props}
|
||||
>
|
||||
<path
|
||||
fillRule="evenodd"
|
||||
clipRule="evenodd"
|
||||
d="M7.99984 1.5C6.15889 1.5 4.6665 2.99238 4.6665 4.83333V6H4.49984C3.48732 6 2.6665 6.82081 2.6665 7.83333V12.8333C2.6665 13.8459 3.48732 14.6667 4.49984 14.6667H11.4998C12.5124 14.6667 13.3332 13.8459 13.3332 12.8333V7.83333C13.3332 6.82081 12.5124 6 11.4998 6H11.3332V4.83333C11.3332 2.99238 9.84079 1.5 7.99984 1.5ZM10.3332 6V4.83333C10.3332 3.54467 9.2885 2.5 7.99984 2.5C6.71117 2.5 5.6665 3.54467 5.6665 4.83333V6H10.3332ZM7.99984 8.83333C8.27598 8.83333 8.49984 9.05719 8.49984 9.33333V11.3333C8.49984 11.6095 8.27598 11.8333 7.99984 11.8333C7.72369 11.8333 7.49984 11.6095 7.49984 11.3333V9.33333C7.49984 9.05719 7.72369 8.83333 7.99984 8.83333Z"
|
||||
fill="#EA580C"
|
||||
/>
|
||||
</CustomIcon>
|
||||
);
|
||||
};
|
||||
@@ -22,6 +22,8 @@ export * from './EllipseIcon';
|
||||
export * from './EllipsesIcon';
|
||||
export * from './SnowballIcon';
|
||||
export * from './NotificationBellIcon';
|
||||
export * from './GithubIcon';
|
||||
export * from './LockIcon';
|
||||
export * from './PencilIcon';
|
||||
export * from './CheckRadioIcon';
|
||||
export * from './ChevronDownIcon';
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { tv, type VariantProps } from 'tailwind-variants';
|
||||
|
||||
export const headingTheme = tv({
|
||||
base: ['text-elements-high-em', 'font-display', 'font-normal'],
|
||||
});
|
||||
|
||||
export type HeadingVariants = VariantProps<typeof headingTheme>;
|
||||
@@ -0,0 +1,30 @@
|
||||
import React, { type PropsWithChildren } from 'react';
|
||||
|
||||
import { headingTheme, type HeadingVariants } from './Heading.theme';
|
||||
import { PolymorphicProps } from 'types/common';
|
||||
|
||||
export type HeadingElementType = 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6';
|
||||
|
||||
export type HeadingProps<Element extends HeadingElementType> =
|
||||
PropsWithChildren<PolymorphicProps<Element, HeadingVariants>>;
|
||||
|
||||
export const Heading = <Element extends HeadingElementType>({
|
||||
children,
|
||||
as,
|
||||
className,
|
||||
...props
|
||||
}: HeadingProps<Element>) => {
|
||||
// Component is the element that will be rendered
|
||||
const Component = as ?? 'h1';
|
||||
|
||||
return (
|
||||
<Component
|
||||
{...props}
|
||||
className={headingTheme({
|
||||
className,
|
||||
})}
|
||||
>
|
||||
{children}
|
||||
</Component>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export * from './Heading';
|
||||
+32
-28
@@ -5,8 +5,8 @@ import { Organization } from 'gql-client';
|
||||
import { Option } from '@material-tailwind/react';
|
||||
import { useDisconnect } from 'wagmi';
|
||||
|
||||
import { useGQLClient } from '../context/GQLClientContext';
|
||||
import AsyncSelect from './shared/AsyncSelect';
|
||||
import { useGQLClient } from 'context/GQLClientContext';
|
||||
import AsyncSelect from 'components/shared/AsyncSelect';
|
||||
import {
|
||||
ChevronGrabberHorizontal,
|
||||
FolderIcon,
|
||||
@@ -14,10 +14,11 @@ import {
|
||||
LifeBuoyIcon,
|
||||
QuestionMarkRoundIcon,
|
||||
SettingsSlidersIcon,
|
||||
} from './shared/CustomIcon';
|
||||
} from 'components/shared/CustomIcon';
|
||||
import { Tabs } from 'components/shared/Tabs';
|
||||
import { Heading } from 'components/shared/Heading';
|
||||
|
||||
const Sidebar = () => {
|
||||
export const Sidebar = () => {
|
||||
const { orgSlug } = useParams();
|
||||
const navigate = useNavigate();
|
||||
const client = useGQLClient();
|
||||
@@ -42,20 +43,20 @@ const Sidebar = () => {
|
||||
}, [disconnect, navigate]);
|
||||
|
||||
return (
|
||||
<div className="flex flex-col h-full p-4 pt-10">
|
||||
<div className="grow">
|
||||
<Link to={`/${orgSlug}`}>
|
||||
<div className="flex items-center space-x-3 mb-10 ml-2">
|
||||
<img
|
||||
src="/logo.svg"
|
||||
alt="Snowball Logo"
|
||||
className="h-8 w-8 rounded-lg"
|
||||
/>
|
||||
<span className="text-2xl font-bold text-snowball-900">
|
||||
Snowball
|
||||
</span>
|
||||
</div>
|
||||
</Link>
|
||||
<div className="flex flex-col h-full px-6 py-8 gap-9">
|
||||
{/* Logo */}
|
||||
<Link to={`/${orgSlug}`}>
|
||||
<div className="flex items-center gap-3 px-2">
|
||||
<img
|
||||
src="/logo.svg"
|
||||
alt="Snowball Logo"
|
||||
className="h-10 w-10 rounded-lg"
|
||||
/>
|
||||
<Heading className="text-[24px] font-semibold">Snowball</Heading>
|
||||
</div>
|
||||
</Link>
|
||||
{/* Switch organization */}
|
||||
<div className="flex flex-1 flex-col gap-4">
|
||||
<AsyncSelect
|
||||
containerProps={{ className: 'h-14 border-none' }}
|
||||
labelProps={{ className: 'before:border-none after:border-none' }}
|
||||
@@ -82,7 +83,7 @@ const Sidebar = () => {
|
||||
)}
|
||||
arrow={<ChevronGrabberHorizontal className="h-4 w-4 text-gray-500" />}
|
||||
>
|
||||
{/* TODO: Show label organization and manage in option */}
|
||||
{/* // TODO: Show label organization and manage in option */}
|
||||
{organizations.map((org) => (
|
||||
<Option key={org.id} value={org.slug}>
|
||||
<div className="flex items-center space-x-3">
|
||||
@@ -99,13 +100,17 @@ const Sidebar = () => {
|
||||
</Option>
|
||||
))}
|
||||
</AsyncSelect>
|
||||
<Tabs defaultValue="Projects" orientation="vertical" className="mt-10">
|
||||
<Tabs defaultValue="Projects" orientation="vertical">
|
||||
<Tabs.List>
|
||||
{[
|
||||
{ title: 'Projects', icon: <FolderIcon /> },
|
||||
{ title: 'Settings', icon: <SettingsSlidersIcon /> },
|
||||
].map(({ title, icon }, index) => (
|
||||
<NavLink to={`/${orgSlug}/${title}`} key={index}>
|
||||
{ title: 'Projects', url: `/${orgSlug}/`, icon: <FolderIcon /> },
|
||||
{
|
||||
title: 'Settings',
|
||||
url: `/${orgSlug}/settings`,
|
||||
icon: <SettingsSlidersIcon />,
|
||||
},
|
||||
].map(({ title, icon, url }, index) => (
|
||||
<NavLink to={url} key={index}>
|
||||
<Tabs.Trigger icon={icon} value={title}>
|
||||
{title}
|
||||
</Tabs.Trigger>
|
||||
@@ -114,9 +119,10 @@ const Sidebar = () => {
|
||||
</Tabs.List>
|
||||
</Tabs>
|
||||
</div>
|
||||
<div className="grow flex flex-col justify-end mb-8">
|
||||
{/* Bottom navigation */}
|
||||
<div className="flex flex-col justify-end">
|
||||
<Tabs defaultValue="Projects" orientation="vertical">
|
||||
{/* TODO: use proper link buttons */}
|
||||
{/* // TODO: use proper link buttons */}
|
||||
<Tabs.List>
|
||||
<Tabs.Trigger icon={<GlobeIcon />} value="">
|
||||
<a className="cursor-pointer" onClick={handleLogOut}>
|
||||
@@ -135,5 +141,3 @@ const Sidebar = () => {
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default Sidebar;
|
||||
@@ -0,0 +1 @@
|
||||
export * from './Sidebar';
|
||||
@@ -23,7 +23,6 @@ export const tabsTheme = tv({
|
||||
// Vertical
|
||||
'data-[orientation=vertical]:px-3',
|
||||
'data-[orientation=vertical]:py-3',
|
||||
'data-[orientation=vertical]:min-w-[240px]',
|
||||
'data-[orientation=vertical]:w-full',
|
||||
'data-[orientation=vertical]:focus-ring',
|
||||
'data-[orientation=vertical]:rounded-xl',
|
||||
|
||||
@@ -2,6 +2,153 @@
|
||||
@tailwind components;
|
||||
@tailwind utilities;
|
||||
|
||||
@layer base {
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: normal;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-Thin.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: italic;
|
||||
font-weight: 100;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-ThinItalic.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: normal;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-ExtraLight.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: italic;
|
||||
font-weight: 200;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-ExtraLightItalic.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-Light.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: italic;
|
||||
font-weight: 300;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-LightItalic.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-Regular.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-Italic.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-Medium.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: italic;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-MediumItalic.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-SemiBold.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: italic;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-SemiBoldItalic.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-Bold.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: italic;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-BoldItalic.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: normal;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-ExtraBold.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: italic;
|
||||
font-weight: 800;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-ExtraBoldItalic.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: normal;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-Black.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
@font-face {
|
||||
font-family: 'Inter Display';
|
||||
font-style: italic;
|
||||
font-weight: 900;
|
||||
font-display: swap;
|
||||
src: url('../public/fonts/InterDisplay/InterDisplay-BlackItalic.woff2')
|
||||
format('woff2');
|
||||
}
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
.focus-ring {
|
||||
@apply focus-visible:ring-[3px] focus-visible:ring-snowball-200 focus-visible:ring-offset-1 focus-visible:ring-offset-snowball-500 focus-visible:outline-none;
|
||||
|
||||
@@ -25,6 +25,12 @@ const ProjectSearch = () => {
|
||||
fetchUser();
|
||||
}, []);
|
||||
|
||||
const fetchOrgSlug = useCallback(async () => {
|
||||
const { organizations } = await client.getOrganizations();
|
||||
// TODO: Get the selected organization. This is temp
|
||||
return organizations[0].slug;
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="sticky top-0 bg-white z-30">
|
||||
@@ -38,7 +44,15 @@ const ProjectSearch = () => {
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
<Button variant={'secondary'} iconOnly>
|
||||
<Button
|
||||
variant={'secondary'}
|
||||
iconOnly
|
||||
onClick={() => {
|
||||
fetchOrgSlug().then((organizationSlug) => {
|
||||
navigate(`/${organizationSlug}/projects/create`);
|
||||
});
|
||||
}}
|
||||
>
|
||||
<PlusIcon />
|
||||
</Button>
|
||||
<Button variant={'ghost'} iconOnly>
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
import React from 'react';
|
||||
import './Snow.css';
|
||||
|
||||
const Login = () => {
|
||||
return (
|
||||
<div className="grid grid-cols-5 h-screen bg-light-blue-50 py-10">
|
||||
<div className="col-span-2"></div>
|
||||
<div className="col-span-1">
|
||||
<div className="flex items-center justify-center h-screen bg-snowball-900 snow">
|
||||
<div className="flex flex-col items-center justify-center">
|
||||
<img
|
||||
src="/logo.svg"
|
||||
alt="snowball logo"
|
||||
className="w-32 h-32 rounded-full mb-4"
|
||||
/>
|
||||
<w3m-button />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import React from 'react';
|
||||
import { Outlet } from 'react-router-dom';
|
||||
|
||||
import Sidebar from '../components/Sidebar';
|
||||
import { OctokitProvider } from '../context/OctokitContext';
|
||||
import { OctokitProvider } from 'context/OctokitContext';
|
||||
import { Sidebar } from 'components/shared/Sidebar';
|
||||
|
||||
const OrgSlug = () => {
|
||||
return (
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
.snow {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||
background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 50 50' style='enable-background:new 0 0 50 50%3B' xml:space='preserve'%3E%3Cstyle type='text/css'%3E.st1%7Bopacity:0.3%3Bfill:%23FFFFFF%3B%7D.st3%7Bopacity:0.1%3Bfill:%23FFFFFF%3B%7D%3C/style%3E%3Ccircle class='st1' cx='5' cy='8' r='1'/%3E%3Ccircle class='st1' cx='38' cy='3' r='1'/%3E%3Ccircle class='st1' cx='12' cy='4' r='1'/%3E%3Ccircle class='st1' cx='16' cy='16' r='1'/%3E%3Ccircle class='st1' cx='47' cy='46' r='1'/%3E%3Ccircle class='st1' cx='32' cy='10' r='1'/%3E%3Ccircle class='st1' cx='3' cy='46' r='1'/%3E%3Ccircle class='st1' cx='45' cy='13' r='1'/%3E%3Ccircle class='st1' cx='10' cy='28' r='1'/%3E%3Ccircle class='st1' cx='22' cy='35' r='1'/%3E%3Ccircle class='st1' cx='3' cy='21' r='1'/%3E%3Ccircle class='st1' cx='26' cy='20' r='1'/%3E%3Ccircle class='st1' cx='30' cy='45' r='1'/%3E%3Ccircle class='st1' cx='15' cy='45' r='1'/%3E%3Ccircle class='st1' cx='34' cy='36' r='1'/%3E%3Ccircle class='st1' cx='41' cy='32' r='1'/%3E%3C/svg%3E");
|
||||
background-position: 0px 0px;
|
||||
animation: animatedBackground 230s linear infinite;
|
||||
}
|
||||
|
||||
.snow div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background-image: url("data:image/svg+xml,%3Csvg version='1.1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 50 50' style='enable-background:new 0 0 50 50%3B' xml:space='preserve'%3E%3Cstyle type='text/css'%3E.st1%7Bopacity:0.7%3Bfill:%23FFFFFF%3B%7D.st3%7Bopacity:0.1%3Bfill:%23FFFFFF%3B%7D%3C/style%3E%3Ccircle class='st3' cx='4' cy='14' r='1'/%3E%3Ccircle class='st3' cx='43' cy='3' r='1'/%3E%3Ccircle class='st3' cx='31' cy='30' r='2'/%3E%3Ccircle class='st3' cx='19' cy='23' r='1'/%3E%3Ccircle class='st3' cx='37' cy='22' r='1'/%3E%3Ccircle class='st3' cx='43' cy='16' r='1'/%3E%3Ccircle class='st3' cx='8' cy='45' r='1'/%3E%3Ccircle class='st3' cx='29' cy='39' r='1'/%3E%3Ccircle class='st3' cx='13' cy='37' r='1'/%3E%3Ccircle class='st3' cx='47' cy='32' r='1'/%3E%3Ccircle class='st3' cx='15' cy='4' r='2'/%3E%3Ccircle class='st3' cx='9' cy='27' r='1'/%3E%3Ccircle class='st3' cx='30' cy='9' r='1'/%3E%3Ccircle class='st3' cx='25' cy='15' r='1'/%3E%3Ccircle class='st3' cx='21' cy='45' r='2'/%3E%3Ccircle class='st3' cx='42' cy='45' r='1'/%3E%3C/svg%3E");
|
||||
background-position: 0px 0px;
|
||||
animation: animatedBackground 260s linear infinite;
|
||||
}
|
||||
|
||||
@keyframes animatedBackground {
|
||||
0% {
|
||||
background-position: 0 0;
|
||||
}
|
||||
100% {
|
||||
background-position: 0px 11600px;
|
||||
}
|
||||
}
|
||||
@@ -3,11 +3,11 @@ import { Link, useParams } from 'react-router-dom';
|
||||
import { Project } from 'gql-client';
|
||||
import { Button } from 'components/shared/Button';
|
||||
|
||||
import { Typography, Chip } from '@material-tailwind/react';
|
||||
|
||||
import { useGQLClient } from '../../context/GQLClientContext';
|
||||
import { PlusIcon } from 'components/shared/CustomIcon';
|
||||
import { ProjectCard } from 'components/projects/ProjectCard';
|
||||
import { Heading } from 'components/shared/Heading';
|
||||
import { Badge } from 'components/shared/Badge';
|
||||
import { useGQLClient } from 'context/GQLClientContext';
|
||||
|
||||
const Projects = () => {
|
||||
const client = useGQLClient();
|
||||
@@ -26,33 +26,31 @@ const Projects = () => {
|
||||
}, [orgSlug]);
|
||||
|
||||
return (
|
||||
<div>
|
||||
<div className="flex p-5">
|
||||
<section className="px-6 py-6 flex flex-col gap-6">
|
||||
{/* Header */}
|
||||
<div className="flex items-center">
|
||||
<div className="grow">
|
||||
<div className="flex gap-2 items-center">
|
||||
<Typography variant="h4" placeholder={''}>
|
||||
<div className="flex gap-4 items-center">
|
||||
<Heading as="h2" className="text-[24px]">
|
||||
Projects
|
||||
</Typography>
|
||||
<Chip
|
||||
className="bg-gray-300 rounded-full static"
|
||||
value={projects.length}
|
||||
size="sm"
|
||||
/>
|
||||
</Heading>
|
||||
<Badge className="bg-base-bg-alternate text-elements-mid-em h-7 w-7">
|
||||
{projects.length}
|
||||
</Badge>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<Link to="projects/create">
|
||||
<Button leftIcon={<PlusIcon />}>Create project</Button>
|
||||
</Link>
|
||||
</div>
|
||||
<Link to="projects/create">
|
||||
<Button leftIcon={<PlusIcon />}>Create project</Button>
|
||||
</Link>
|
||||
</div>
|
||||
<div className="grid grid-cols-3 gap-5 p-5">
|
||||
{projects.length !== 0 &&
|
||||
{/* List of projects */}
|
||||
<div className="grid grid-cols-3 gap-4">
|
||||
{projects.length > 0 &&
|
||||
projects.map((project, key) => {
|
||||
return <ProjectCard project={project} key={key} />;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,3 +1,9 @@
|
||||
import {
|
||||
type ElementType,
|
||||
type ComponentPropsWithoutRef,
|
||||
forwardRef,
|
||||
} from 'react';
|
||||
|
||||
/**
|
||||
* Construct a type by excluding common keys from one type to another.
|
||||
* @template T - The type from which to omit properties.
|
||||
@@ -7,3 +13,15 @@
|
||||
* @returns A new type that includes all properties from T except those that are common with U.
|
||||
*/
|
||||
export type OmitCommon<T, U> = Pick<T, Exclude<keyof T, keyof U>>;
|
||||
|
||||
export type PolymorphicProps<Element extends ElementType, Props> = Props &
|
||||
Omit<ComponentPropsWithoutRef<Element>, 'as'> & {
|
||||
as?: Element;
|
||||
};
|
||||
|
||||
// taken from : https://github.com/total-typescript/react-typescript-tutorial/blob/main/src/08-advanced-patterns/72-as-prop-with-forward-ref.solution.tsx
|
||||
type FixedForwardRef = <T, P = object>(
|
||||
render: (props: P, ref: React.Ref<T>) => React.ReactNode,
|
||||
) => (props: P & React.RefAttributes<T>) => JSX.Element;
|
||||
|
||||
export const fixedForwardRef = forwardRef as FixedForwardRef;
|
||||
|
||||
@@ -14,6 +14,7 @@ export default withMT({
|
||||
},
|
||||
fontFamily: {
|
||||
sans: ['Inter', 'sans-serif'],
|
||||
display: ['Inter Display', 'sans-serif'],
|
||||
mono: ['JetBrains Mono', 'monospace'],
|
||||
},
|
||||
fontSize: {
|
||||
|
||||
Reference in New Issue
Block a user