feat(app): implement cli page with download and example
This commit is contained in:
parent
d2d65027f7
commit
d72f5c2111
12
apps/app/public/apple.svg
Normal file
12
apps/app/public/apple.svg
Normal file
@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
|
||||
<svg width="80px" height="80px" viewBox="-1.5 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g id="Dribbble-Light-Preview" transform="translate(-102.000000, -7439.000000)" fill="#71717a">
|
||||
<g id="icons" transform="translate(56.000000, 160.000000)">
|
||||
<path d="M57.5708873,7282.19296 C58.2999598,7281.34797 58.7914012,7280.17098 58.6569121,7279 C57.6062792,7279.04 56.3352055,7279.67099 55.5818643,7280.51498 C54.905374,7281.26397 54.3148354,7282.46095 54.4735932,7283.60894 C55.6455696,7283.69593 56.8418148,7283.03894 57.5708873,7282.19296 M60.1989864,7289.62485 C60.2283111,7292.65181 62.9696641,7293.65879 63,7293.67179 C62.9777537,7293.74279 62.562152,7295.10677 61.5560117,7296.51675 C60.6853718,7297.73474 59.7823735,7298.94772 58.3596204,7298.97372 C56.9621472,7298.99872 56.5121648,7298.17973 54.9134635,7298.17973 C53.3157735,7298.17973 52.8162425,7298.94772 51.4935978,7298.99872 C50.1203933,7299.04772 49.0738052,7297.68074 48.197098,7296.46676 C46.4032359,7293.98379 45.0330649,7289.44985 46.8734421,7286.3899 C47.7875635,7284.87092 49.4206455,7283.90793 51.1942837,7283.88393 C52.5422083,7283.85893 53.8153044,7284.75292 54.6394294,7284.75292 C55.4635543,7284.75292 57.0106846,7283.67793 58.6366882,7283.83593 C59.3172232,7283.86293 61.2283842,7284.09893 62.4549652,7285.8199 C62.355868,7285.8789 60.1747177,7287.09489 60.1989864,7289.62485" id="apple-[#173]">
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.7 KiB |
6
apps/app/public/linux.svg
Normal file
6
apps/app/public/linux.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 10 KiB |
11
apps/app/public/windows.svg
Normal file
11
apps/app/public/windows.svg
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="80px" height="80px" viewBox="0 0 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||
<g transform="translate(-60.000000, -7439.000000)" fill="#71717a">
|
||||
<g transform="translate(56.000000, 160.000000)">
|
||||
<path d="M13.1458647,7289.43426 C13.1508772,7291.43316 13.1568922,7294.82929 13.1619048,7297.46884 C16.7759398,7297.95757 20.3899749,7298.4613 23.997995,7299 C23.997995,7295.84873 24.002005,7292.71146 23.997995,7289.71311 C20.3809524,7289.71311 16.7649123,7289.43426 13.1458647,7289.43426 M4,7289.43526 L4,7296.22153 C6.72581454,7296.58933 9.45162907,7296.94113 12.1724311,7297.34291 C12.1774436,7294.71736 12.1704261,7292.0908 12.1704261,7289.46524 C9.44661654,7289.47024 6.72380952,7289.42627 4,7289.43526 M4,7281.84344 L4,7288.61071 C6.72581454,7288.61771 9.45162907,7288.57673 12.1774436,7288.57973 C12.1754386,7285.96017 12.1754386,7283.34361 12.1724311,7280.72405 C9.44461153,7281.06486 6.71679198,7281.42567 4,7281.84344 M24,7288.47179 C20.3879699,7288.48578 16.7759398,7288.54075 13.1619048,7288.55175 C13.1598997,7285.88921 13.1598997,7283.22967 13.1619048,7280.56914 C16.7689223,7280.01844 20.3839599,7279.50072 23.997995,7279 C24,7282.15826 23.997995,7285.31353 24,7288.47179">
|
||||
</path>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 1.5 KiB |
@ -29,7 +29,8 @@ export const AccessTokenColumns: ColumnDef<
|
||||
{
|
||||
accessorKey: 'id',
|
||||
header: '',
|
||||
size: 10,
|
||||
size: 20,
|
||||
maxSize: 20,
|
||||
cell: (props) => <AccessTokenDelete id={props.row.original.id} />,
|
||||
},
|
||||
]
|
||||
|
@ -63,7 +63,10 @@ export function DataTable<TData, TValue>({
|
||||
data-state={row.getIsSelected() && 'selected'}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell key={cell.id}>
|
||||
<TableCell
|
||||
key={cell.id}
|
||||
style={{ width: cell.column.getSize() }}
|
||||
>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
|
@ -1,96 +0,0 @@
|
||||
import { ChevronsUpDown } from 'lucide-react'
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
AvatarFallback,
|
||||
AvatarImage,
|
||||
DropdownMenu,
|
||||
DropdownMenuContent,
|
||||
DropdownMenuGroup,
|
||||
DropdownMenuItem,
|
||||
DropdownMenuLabel,
|
||||
DropdownMenuSeparator,
|
||||
DropdownMenuTrigger,
|
||||
SidebarMenu,
|
||||
SidebarMenuButton,
|
||||
SidebarMenuItem,
|
||||
useSidebar,
|
||||
} from '@boring.tools/ui'
|
||||
import { SignOutButton, useUser } from '@clerk/clerk-react'
|
||||
import { Link } from '@tanstack/react-router'
|
||||
|
||||
export function SidebarUser() {
|
||||
const { isMobile } = useSidebar()
|
||||
const { user } = useUser()
|
||||
|
||||
return (
|
||||
<SidebarMenu>
|
||||
<SidebarMenuItem>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<SidebarMenuButton
|
||||
size="lg"
|
||||
className="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
|
||||
>
|
||||
<Avatar className="h-8 w-8 rounded-lg">
|
||||
<AvatarImage
|
||||
src={user?.imageUrl}
|
||||
alt={user?.fullName ?? 'Avatar'}
|
||||
/>
|
||||
<AvatarFallback className="rounded-lg">CN</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="grid flex-1 text-left text-sm leading-tight">
|
||||
<span className="truncate font-semibold">{user?.fullName}</span>
|
||||
<span className="truncate text-xs">
|
||||
{user?.primaryEmailAddress?.emailAddress}
|
||||
</span>
|
||||
</div>
|
||||
<ChevronsUpDown className="ml-auto size-4" />
|
||||
</SidebarMenuButton>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent
|
||||
className="w-[--radix-dropdown-menu-trigger-width] min-w-56 rounded-lg"
|
||||
side={isMobile ? 'bottom' : 'right'}
|
||||
align="end"
|
||||
sideOffset={4}
|
||||
>
|
||||
<DropdownMenuLabel className="p-0 font-normal">
|
||||
<div className="flex items-center gap-2 px-1 py-1.5 text-left text-sm">
|
||||
<Avatar className="h-8 w-8 rounded-lg">
|
||||
<AvatarImage
|
||||
src={user?.imageUrl}
|
||||
alt={user?.fullName ?? 'Avatar'}
|
||||
/>
|
||||
<AvatarFallback className="rounded-lg">
|
||||
{user?.firstName?.substring(0, 1)}
|
||||
{user?.lastName?.substring(0, 1)}
|
||||
</AvatarFallback>
|
||||
</Avatar>
|
||||
<div className="grid flex-1 text-left text-sm leading-tight">
|
||||
<span className="truncate font-semibold">
|
||||
{user?.fullName}
|
||||
</span>
|
||||
<span className="truncate text-xs">
|
||||
{user?.primaryEmailAddress?.emailAddress}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</DropdownMenuLabel>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuGroup>
|
||||
<DropdownMenuItem>
|
||||
<Link to="/user">Profile</Link>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuGroup>
|
||||
<DropdownMenuSeparator />
|
||||
<DropdownMenuItem>
|
||||
<SignOutButton>
|
||||
<button type="button">Sign out</button>
|
||||
</SignOutButton>
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
</SidebarMenuItem>
|
||||
</SidebarMenu>
|
||||
)
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { ChevronsUpDown, KeyRoundIcon } from 'lucide-react'
|
||||
import { ChevronsUpDown, KeyRoundIcon, TerminalIcon } from 'lucide-react'
|
||||
|
||||
import {
|
||||
Avatar,
|
||||
@ -37,6 +37,14 @@ export function SidebarUser() {
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
<SidebarMenuItem>
|
||||
<SidebarMenuButton asChild tooltip="Access Tokens">
|
||||
<Link to="/cli" activeProps={{ className: 'bg-sidebar-accent' }}>
|
||||
<TerminalIcon />
|
||||
<span>CLI</span>
|
||||
</Link>
|
||||
</SidebarMenuButton>
|
||||
</SidebarMenuItem>
|
||||
<SidebarSeparator />
|
||||
<SidebarMenuItem>
|
||||
<DropdownMenu>
|
||||
|
@ -17,6 +17,7 @@ import { Route as ChangelogIdVersionVersionIdImport } from './routes/changelog.$
|
||||
|
||||
// Create Virtual Routes
|
||||
|
||||
const CliLazyImport = createFileRoute('/cli')()
|
||||
const IndexLazyImport = createFileRoute('/')()
|
||||
const UserIndexLazyImport = createFileRoute('/user/')()
|
||||
const PageIndexLazyImport = createFileRoute('/page/')()
|
||||
@ -37,6 +38,11 @@ const ChangelogIdEditLazyImport = createFileRoute('/changelog/$id/edit')()
|
||||
|
||||
// Create/Update Routes
|
||||
|
||||
const CliLazyRoute = CliLazyImport.update({
|
||||
path: '/cli',
|
||||
getParentRoute: () => rootRoute,
|
||||
} as any).lazy(() => import('./routes/cli.lazy').then((d) => d.Route))
|
||||
|
||||
const IndexLazyRoute = IndexLazyImport.update({
|
||||
path: '/',
|
||||
getParentRoute: () => rootRoute,
|
||||
@ -146,6 +152,13 @@ declare module '@tanstack/react-router' {
|
||||
preLoaderRoute: typeof IndexLazyImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/cli': {
|
||||
id: '/cli'
|
||||
path: '/cli'
|
||||
fullPath: '/cli'
|
||||
preLoaderRoute: typeof CliLazyImport
|
||||
parentRoute: typeof rootRoute
|
||||
}
|
||||
'/access-tokens/new': {
|
||||
id: '/access-tokens/new'
|
||||
path: '/access-tokens/new'
|
||||
@ -290,6 +303,7 @@ const PageIdLazyRouteWithChildren = PageIdLazyRoute._addFileChildren(
|
||||
|
||||
export interface FileRoutesByFullPath {
|
||||
'/': typeof IndexLazyRoute
|
||||
'/cli': typeof CliLazyRoute
|
||||
'/access-tokens/new': typeof AccessTokensNewLazyRoute
|
||||
'/changelog/$id': typeof ChangelogIdLazyRouteWithChildren
|
||||
'/changelog/create': typeof ChangelogCreateLazyRoute
|
||||
@ -309,6 +323,7 @@ export interface FileRoutesByFullPath {
|
||||
|
||||
export interface FileRoutesByTo {
|
||||
'/': typeof IndexLazyRoute
|
||||
'/cli': typeof CliLazyRoute
|
||||
'/access-tokens/new': typeof AccessTokensNewLazyRoute
|
||||
'/changelog/create': typeof ChangelogCreateLazyRoute
|
||||
'/page/create': typeof PageCreateLazyRoute
|
||||
@ -327,6 +342,7 @@ export interface FileRoutesByTo {
|
||||
export interface FileRoutesById {
|
||||
__root__: typeof rootRoute
|
||||
'/': typeof IndexLazyRoute
|
||||
'/cli': typeof CliLazyRoute
|
||||
'/access-tokens/new': typeof AccessTokensNewLazyRoute
|
||||
'/changelog/$id': typeof ChangelogIdLazyRouteWithChildren
|
||||
'/changelog/create': typeof ChangelogCreateLazyRoute
|
||||
@ -348,6 +364,7 @@ export interface FileRouteTypes {
|
||||
fileRoutesByFullPath: FileRoutesByFullPath
|
||||
fullPaths:
|
||||
| '/'
|
||||
| '/cli'
|
||||
| '/access-tokens/new'
|
||||
| '/changelog/$id'
|
||||
| '/changelog/create'
|
||||
@ -366,6 +383,7 @@ export interface FileRouteTypes {
|
||||
fileRoutesByTo: FileRoutesByTo
|
||||
to:
|
||||
| '/'
|
||||
| '/cli'
|
||||
| '/access-tokens/new'
|
||||
| '/changelog/create'
|
||||
| '/page/create'
|
||||
@ -382,6 +400,7 @@ export interface FileRouteTypes {
|
||||
id:
|
||||
| '__root__'
|
||||
| '/'
|
||||
| '/cli'
|
||||
| '/access-tokens/new'
|
||||
| '/changelog/$id'
|
||||
| '/changelog/create'
|
||||
@ -402,6 +421,7 @@ export interface FileRouteTypes {
|
||||
|
||||
export interface RootRouteChildren {
|
||||
IndexLazyRoute: typeof IndexLazyRoute
|
||||
CliLazyRoute: typeof CliLazyRoute
|
||||
AccessTokensNewLazyRoute: typeof AccessTokensNewLazyRoute
|
||||
ChangelogIdLazyRoute: typeof ChangelogIdLazyRouteWithChildren
|
||||
ChangelogCreateLazyRoute: typeof ChangelogCreateLazyRoute
|
||||
@ -415,6 +435,7 @@ export interface RootRouteChildren {
|
||||
|
||||
const rootRouteChildren: RootRouteChildren = {
|
||||
IndexLazyRoute: IndexLazyRoute,
|
||||
CliLazyRoute: CliLazyRoute,
|
||||
AccessTokensNewLazyRoute: AccessTokensNewLazyRoute,
|
||||
ChangelogIdLazyRoute: ChangelogIdLazyRouteWithChildren,
|
||||
ChangelogCreateLazyRoute: ChangelogCreateLazyRoute,
|
||||
@ -439,6 +460,7 @@ export const routeTree = rootRoute
|
||||
"filePath": "__root.tsx",
|
||||
"children": [
|
||||
"/",
|
||||
"/cli",
|
||||
"/access-tokens/new",
|
||||
"/changelog/$id",
|
||||
"/changelog/create",
|
||||
@ -453,6 +475,9 @@ export const routeTree = rootRoute
|
||||
"/": {
|
||||
"filePath": "index.lazy.tsx"
|
||||
},
|
||||
"/cli": {
|
||||
"filePath": "cli.lazy.tsx"
|
||||
},
|
||||
"/access-tokens/new": {
|
||||
"filePath": "access-tokens.new.lazy.tsx"
|
||||
},
|
||||
|
107
apps/app/src/routes/cli.lazy.tsx
Normal file
107
apps/app/src/routes/cli.lazy.tsx
Normal file
@ -0,0 +1,107 @@
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from '@boring.tools/ui'
|
||||
import { Link, createLazyFileRoute } from '@tanstack/react-router'
|
||||
import { CopyIcon } from 'lucide-react'
|
||||
import { PageWrapper } from '../components/PageWrapper'
|
||||
|
||||
const Platforms = [
|
||||
{
|
||||
name: 'Linux',
|
||||
arch: 'x86',
|
||||
svg: '/linux.svg',
|
||||
path: '/cli/linux/bt',
|
||||
filename: 'bt',
|
||||
},
|
||||
{
|
||||
name: 'Apple Intel',
|
||||
arch: 'Intel',
|
||||
svg: '/apple.svg',
|
||||
path: '/cli/mac-intel/bt',
|
||||
filename: 'bt',
|
||||
},
|
||||
{
|
||||
name: 'Apple ARM',
|
||||
arch: 'ARM',
|
||||
svg: '/apple.svg',
|
||||
path: '/cli/mac-arm/bt',
|
||||
filename: 'bt',
|
||||
},
|
||||
{
|
||||
name: 'Windows',
|
||||
arch: 'x86',
|
||||
svg: '/windows.svg',
|
||||
path: '/cli/windows/bt.exe',
|
||||
filename: 'bt.exe',
|
||||
},
|
||||
]
|
||||
|
||||
const Component = () => {
|
||||
return (
|
||||
<PageWrapper breadcrumbs={[{ name: 'CLI', to: '/cli' }]}>
|
||||
<div className="flex flex-col gap-5 w-full max-w-screen-lg">
|
||||
<h1 className="text-3xl">CLI</h1>
|
||||
<p className="text-muted-foreground">
|
||||
With our CLI you can upload your commits for your changelog in just a
|
||||
few seconds.
|
||||
</p>
|
||||
<h2 className="text-xl">Download</h2>
|
||||
<div className="grid grid-cols-4 gap-10">
|
||||
{Platforms.map((platform) => {
|
||||
return (
|
||||
<a
|
||||
href={`https://cdn.boring.tools${platform.path}`}
|
||||
key={`${platform.arch}-${platform.name}`}
|
||||
download={platform.filename}
|
||||
>
|
||||
<Card className="hover:border-accent transition">
|
||||
<CardHeader>
|
||||
<img
|
||||
src={platform.svg}
|
||||
alt={platform.name}
|
||||
className="h-20"
|
||||
/>
|
||||
</CardHeader>
|
||||
<CardContent className="text-center">
|
||||
{platform.arch}
|
||||
</CardContent>
|
||||
</Card>
|
||||
</a>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
|
||||
<h2 className="text-xl">Usage</h2>
|
||||
<pre className="bg-muted text-xl p-3 rounded text-center flex justify-between items-center">
|
||||
bt --changelogId=... --token=bt_...
|
||||
</pre>
|
||||
|
||||
<p className="text-muted-foreground">
|
||||
Alternatively, you can use an .env file:
|
||||
</p>
|
||||
|
||||
<pre className="bg-muted text-xl p-3 rounded text-center flex justify-between items-center">
|
||||
BT_CHANGELOG_ID=...
|
||||
<br />
|
||||
BT_AUTH_TOKEN=bt_...
|
||||
</pre>
|
||||
|
||||
<p className="text-muted-foreground">
|
||||
If you have not yet created an Access Token, you can do so{' '}
|
||||
<Link to="/access-tokens/new" className="text-accent font-bold">
|
||||
here
|
||||
</Link>
|
||||
.
|
||||
</p>
|
||||
</div>
|
||||
</PageWrapper>
|
||||
)
|
||||
}
|
||||
|
||||
export const Route = createLazyFileRoute('/cli')({
|
||||
component: Component,
|
||||
})
|
@ -1,8 +1,8 @@
|
||||
import { parseArgs } from 'node:util'
|
||||
import { z } from 'zod'
|
||||
|
||||
const ENV_ID = Bun.env.CHANGELOG_ID
|
||||
const ENV_TOKEN = Bun.env.AUTH_TOKEN
|
||||
const ENV_ID = Bun.env.BT_CHANGELOG_ID
|
||||
const ENV_TOKEN = Bun.env.BT_AUTH_TOKEN
|
||||
|
||||
const schema = z.object({
|
||||
token: z.string(),
|
||||
|
Loading…
Reference in New Issue
Block a user