Skip to content

Commit

Permalink
Merge pull request #99 from napse-invest/feature/server
Browse files Browse the repository at this point in the history
Feature/server
  • Loading branch information
tomjeannesson authored Oct 14, 2023
2 parents e4caba6 + 1309bb4 commit 80dac4d
Show file tree
Hide file tree
Showing 27 changed files with 1,167 additions and 171 deletions.
3 changes: 3 additions & 0 deletions desktop-app/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@
"dependencies": {
"@hookform/resolvers": "^3.3.0",
"@radix-ui/react-accordion": "^1.1.2",
"@radix-ui/react-checkbox": "^1.0.4",
"@radix-ui/react-dialog": "^1.0.5",
"@radix-ui/react-dropdown-menu": "^2.0.5",
"@radix-ui/react-hover-card": "^1.0.7",
"@radix-ui/react-icons": "^1.3.0",
"@radix-ui/react-label": "^2.0.2",
"@radix-ui/react-popover": "^1.0.6",
Expand All @@ -25,6 +27,7 @@
"@radix-ui/react-select": "^2.0.0",
"@radix-ui/react-separator": "^1.0.3",
"@radix-ui/react-slot": "^1.0.2",
"@radix-ui/react-switch": "^1.0.3",
"@radix-ui/react-tabs": "^1.0.4",
"@radix-ui/react-toast": "^1.1.4",
"@radix-ui/react-tooltip": "^1.0.6",
Expand Down
4 changes: 2 additions & 2 deletions desktop-app/renderer/api/exchangeAccounts/exchangeAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,14 @@ export interface ExchangeAccount {
testing: boolean
}

export async function list(
export async function listExchangeAccount(
searchParams: ReturnType<typeof useSearchParams>
): Promise<AxiosResponse<ExchangeAccount[]>> {
const response = await request(searchParams, 'GET', '/api/exchange_account/')
return response as AxiosResponse<ExchangeAccount[]>
}

export async function get(
export async function getExchangeAccount(
searchParams: ReturnType<typeof useSearchParams>,
id: string
): Promise<AxiosResponse<ExchangeAccount>> {
Expand Down
43 changes: 43 additions & 0 deletions desktop-app/renderer/api/key/key.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { request } from 'api/request'
import { AxiosResponse } from 'axios'
import { useSearchParams } from 'next/navigation'

export interface Key {
name: string
prefix: string
permissions: string[]
is_master_key: boolean
revoked: boolean
description: string
}

export async function getKey(
searchParams: ReturnType<typeof useSearchParams>,
id: string
): Promise<AxiosResponse<Key>> {
const response = await request(searchParams, 'GET', `/api/key/${id}/`)
return response as AxiosResponse<Key>
}
export async function listKey(
searchParams: ReturnType<typeof useSearchParams>,
space: string | null = null
): Promise<AxiosResponse<Key[]>> {
const response = await request(
searchParams,
'GET',
space ? `/api/key/?space=${space}` : '/api/key/'
)
return response as AxiosResponse<Key[]>
}

export async function createKey(
searchParams: ReturnType<typeof useSearchParams>,
name: string,
description: string
): Promise<AxiosResponse<{ key: string }>> {
const response = await request(searchParams, 'POST', '/api/key/', {
name,
description
})
return response as AxiosResponse<{ key: string }>
}
15 changes: 11 additions & 4 deletions desktop-app/renderer/api/request.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import { getServer } from '@/lib/localStorage'
import axios from 'axios'
import axios, { AxiosHeaders } from 'axios'
import { useSearchParams } from 'next/navigation'

export function request(
searchParams: ReturnType<typeof useSearchParams>,
method: string,
url: string,
...args: any[]
data: Object | null = null,
headers: AxiosHeaders | null = null
) {
const serverID = searchParams.get('server')
if (!serverID) {
throw new Error('No server selected')
}
const serverUrl = getServer(serverID).url
const server = getServer(serverID)
const serverUrl = server.url
const token = server.token
return axios({
method: method,
url: url,
baseURL: serverUrl,
...args
headers: {
Authorization: 'Api-Key ' + token,
...headers
},
data: data || {}
})
}
27 changes: 27 additions & 0 deletions desktop-app/renderer/api/spaces/spaces.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import { request } from 'api/request'
import { AxiosResponse } from 'axios'
import { useSearchParams } from 'next/navigation'

export interface NapseSpace {
name: string
uuid: string
value: number
fleet_count: number
exchange_account: string
delta?: number
}

export async function listSpace(
searchParams: ReturnType<typeof useSearchParams>
): Promise<AxiosResponse<NapseSpace[]>> {
const response = await request(searchParams, 'GET', '/api/space/')
return response as AxiosResponse<NapseSpace[]>
}

export async function getSpace(
searchParams: ReturnType<typeof useSearchParams>,
id: string
): Promise<AxiosResponse<NapseSpace>> {
const response = await request(searchParams, 'GET', `/api/space/${id}/`)
return response as AxiosResponse<NapseSpace>
}
52 changes: 52 additions & 0 deletions desktop-app/renderer/components/custom/copyButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { CheckIcon, CopyIcon } from '@radix-ui/react-icons'
import * as React from 'react'

import { Button } from '@/components/ui/button'
import { cn } from '@/lib/utils'

interface CopyButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
value: string
src?: string
}

export async function copyToClipboardWithMeta(value: string, event?: Event) {
navigator.clipboard.writeText(value)
}

export default function CopyButton({
value,
className,
src,
...props
}: CopyButtonProps) {
const [hasCopied, setHasCopied] = React.useState(false)

React.useEffect(() => {
setTimeout(() => {
setHasCopied(false)
}, 2000)
}, [hasCopied])

return (
<Button
size="icon"
variant="ghost"
className={cn(
'bg-foreground relative z-10 h-6 w-6 text-zinc-50',
className
)}
onClick={() => {
copyToClipboardWithMeta(value)
setHasCopied(true)
}}
{...props}
>
<span className="sr-only">Copy</span>
{hasCopied ? (
<CheckIcon className="h-3 w-3" />
) : (
<CopyIcon className="h-3 w-3" />
)}
</Button>
)
}
117 changes: 89 additions & 28 deletions desktop-app/renderer/components/custom/headerPopover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,8 @@ import { ToastAction } from '@/components/ui/toast'
import { useToast } from '@/components/ui/use-toast'
import { addServer, getServers, removeServer } from '@/lib/localStorage'
import { standardUrlPartial } from '@/lib/queryParams'
import { PlusCircledIcon } from '@radix-ui/react-icons'
import { PlusIcon } from '@radix-ui/react-icons'
import { Settings } from 'lucide-react'
import { useSearchParams } from 'next/navigation'
import { useRouter } from 'next/router'
import { useState } from 'react'
Expand All @@ -28,11 +29,16 @@ export default function ServerPopover(): JSX.Element {
const { toast } = useToast()
const defaultServerName = 'Localhost'
const defaultServerURL = 'http://localhost:8000'
const defaulAPIToken = 'xxxxxxxx.xxxxxx.xxxxxxxxx'
const [newServerName, setNewServerName] = useState(defaultServerName)
const [newServerURL, setNewServerURL] = useState(defaultServerURL)
const [newServerToken, setNewServerToken] = useState(defaulAPIToken)
const [servers, setServers] = useState(getServers())
const router = useRouter()
const searchParams = useSearchParams()
const currentURL = router.asPath
const urlBase = currentURL.split('?')[0].split('/')[1]
const urlId = currentURL.split('?')[0].split('/')[2]
return (
<>
<Popover>
Expand All @@ -43,48 +49,86 @@ export default function ServerPopover(): JSX.Element {
<div className="flex flex-col items-stretch space-y-3">
{Object.entries(servers).map(([key, server], index) => {
return (
<div key={index + 1} className="flex flex-row space-x-5">
<div key={index + 1} className="flex flex-row space-x-1">
<Button
onClick={() => {
router.push(
standardUrlPartial(
'/servers/',
server.id,
{
server: server.id,
exchangeAccount: '',
space: '',
fleet: '',
bot: ''
},
searchParams
)
)
if (currentURL === '/') {
router
.push(
standardUrlPartial(
'/exchangeAccounts/',
null,
{
server: server.id,
exchangeAccount: '',
space: '',
fleet: '',
bot: ''
},
searchParams
)
)
.catch((err) => {
console.error(err)
})
} else {
router
.push(
standardUrlPartial(
`/${urlBase}/`,
urlId,
{
server: server.id,
exchangeAccount: '',
space: '',
fleet: '',
bot: ''
},
searchParams
)
)
.catch((err) => {
console.error(err)
})
}
}}
variant="ghost"
className="w-full"
className="w-full space-x-5"
>
{server.name}
</Button>
<Button
onClick={() => {
removeServer(key)
setServers(getServers())
router
.push(
standardUrlPartial(
'/servers/',
server.id,
{
server: server.id,
exchangeAccount: '',
space: '',
fleet: '',
bot: ''
},
searchParams
)
)
.catch((err) => {
console.error(err)
})
}}
variant="default"
variant="outline"
>
<div className="flex flex-row ">
{/* <MinusCircledIcon className="mr-2 h-5 w-5" /> */}
<div>Remove</div>
</div>
<Settings className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all " />
</Button>
</div>
)
})}
<Dialog key={0}>
<DialogTrigger asChild>
<Button variant="outline" className="">
<PlusCircledIcon className="mr-2 h-5 w-5" />
<PlusIcon className="mr-2 h-5 w-5" />
Add new
</Button>
</DialogTrigger>
Expand All @@ -111,24 +155,41 @@ export default function ServerPopover(): JSX.Element {
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="username" className="text-right">
<Label htmlFor="url" className="text-right">
URL
</Label>
<Input
id="username"
id="url"
defaultValue={defaultServerURL}
className="col-span-3"
onChange={(e) => {
setNewServerURL(e.currentTarget.value)
}}
/>
</div>
<div className="grid grid-cols-4 items-center gap-4">
<Label htmlFor="token" className="text-right">
API Token
</Label>
<Input
id="token"
defaultValue={defaulAPIToken}
className="col-span-3"
onChange={(e) => {
setNewServerToken(e.currentTarget.value)
}}
/>
</div>
</div>
<DialogFooter>
<Button
type="submit"
onClick={() => {
const id = addServer(newServerName, newServerURL)
const id = addServer(
newServerName,
newServerURL,
newServerToken
)
setServers(getServers())
setNewServerName(defaultServerName)
setNewServerURL(defaultServerURL)
Expand Down
21 changes: 21 additions & 0 deletions desktop-app/renderer/components/custom/settingsButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { Button } from '@/components/ui/button'
import { Settings } from 'lucide-react'
import { useRouter } from 'next/router'

export function SettingsButton(): JSX.Element {
const router = useRouter()

return (
<Button
variant="outline"
size="icon"
onClick={() => {
router.push('/settings').catch((err) => {
console.error(err)
})
}}
>
<Settings className="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all " />
</Button>
)
}
Loading

0 comments on commit 80dac4d

Please sign in to comment.