Skip to content

Commit

Permalink
feat(configure-node): add a button for node creation
Browse files Browse the repository at this point in the history
  • Loading branch information
kunish committed Jul 1, 2023
1 parent 08298ed commit c8a36e6
Show file tree
Hide file tree
Showing 11 changed files with 120 additions and 77 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { FormActions } from '~/components/FormActions'
import { DEFAULT_HTTP_FORM_VALUES, httpSchema } from '~/constants'
import { GenerateURLParams, generateURL } from '~/utils'

export const HTTPForm = () => {
export const HTTPForm = ({ onLinkGeneration }: { onLinkGeneration: (link: string) => void }) => {
const { t } = useTranslation()
const { onSubmit, getInputProps, reset } = useForm<z.infer<typeof httpSchema> & { protocol: 'http' | 'https' }>({
initialValues: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { z } from 'zod'
import { FormActions } from '~/components/FormActions'
import { DEFAULT_SS_FORM_VALUES, ssSchema } from '~/constants'

export const SSForm = () => {
export const SSForm = ({ onLinkGeneration }: { onLinkGeneration: (link: string) => void }) => {
const { t } = useTranslation()
const { values, onSubmit, getInputProps, reset } = useForm<z.infer<typeof ssSchema>>({
initialValues: DEFAULT_SS_FORM_VALUES,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { z } from 'zod'
import { FormActions } from '~/components/FormActions'
import { DEFAULT_SSR_FORM_VALUES, ssrSchema } from '~/constants'

export const SSRForm = () => {
export const SSRForm = ({ onLinkGeneration }: { onLinkGeneration: (link: string) => void }) => {
const { t } = useTranslation()
const { values, onSubmit, getInputProps, reset } = useForm<z.infer<typeof ssrSchema>>({
initialValues: DEFAULT_SSR_FORM_VALUES,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { FormActions } from '~/components/FormActions'
import { DEFAULT_SOCKS5_FORM_VALUES, socks5Schema } from '~/constants'
import { GenerateURLParams, generateURL } from '~/utils'

export const Socks5Form = () => {
export const Socks5Form = ({ onLinkGeneration }: { onLinkGeneration: (link: string) => void }) => {
const { t } = useTranslation()
const { onSubmit, getInputProps, reset } = useForm<z.infer<typeof socks5Schema>>({
initialValues: DEFAULT_SOCKS5_FORM_VALUES,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { FormActions } from '~/components/FormActions'
import { DEFAULT_TROJAN_FORM_VALUES, trojanSchema } from '~/constants'
import { generateURL } from '~/utils'

export const TrojanForm = () => {
export const TrojanForm = ({ onLinkGeneration }: { onLinkGeneration: (link: string) => void }) => {
const { t } = useTranslation()
const { values, onSubmit, getInputProps, reset } = useForm<z.infer<typeof trojanSchema>>({
initialValues: DEFAULT_TROJAN_FORM_VALUES,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import { FormActions } from '~/components/FormActions'
import { DEFAULT_V2RAY_FORM_VALUES, v2raySchema } from '~/constants'
import { generateURL } from '~/utils'

export const V2rayForm = () => {
export const V2rayForm = ({ onLinkGeneration }: { onLinkGeneration: (link: string) => void }) => {
const { t } = useTranslation()
const { values, onSubmit, getInputProps, reset } = useForm<
z.infer<typeof v2raySchema> & { protocol: 'vless' | 'vmess' }
Expand Down Expand Up @@ -38,14 +38,16 @@ export const V2rayForm = () => {

if (net === 'kcp') params.seed = path

return generateURL({
protocol,
username: id,
host: add,
port,
hash: ps,
params,
})
return onLinkGeneration(
generateURL({
protocol,
username: id,
host: add,
port,
hash: ps,
params,
})
)
}

if (protocol === 'vmess') {
Expand Down Expand Up @@ -75,7 +77,7 @@ export const V2rayForm = () => {
delete body.flow
}

return 'vmess://' + Base64.encode(JSON.stringify(body))
return onLinkGeneration('vmess://' + Base64.encode(JSON.stringify(body)))
}
})

Expand Down Expand Up @@ -145,7 +147,6 @@ export const V2rayForm = () => {

<Select
label={t('configureNode.network')}
withAsterisk
data={[
{ label: 'TCP', value: 'tcp' },
{ label: 'mKCP', value: 'kcp' },
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { MantineProvider, Modal, Stack, Tabs } from '@mantine/core'
import { Divider, MantineProvider, Modal, Stack, Tabs, TextInput } from '@mantine/core'
import { useForm, zodResolver } from '@mantine/form'
import { useTranslation } from 'react-i18next'
import { z } from 'zod'

import { useImportNodesMutation } from '~/apis'

import { HTTPForm } from './HTTPForm'
import { SSForm } from './SSForm'
Expand All @@ -8,11 +12,39 @@ import { Socks5Form } from './Socks5Form'
import { TrojanForm } from './TrojanForm'
import { V2rayForm } from './V2rayForm'

export const NodeModal = ({ opened, onClose }: { opened: boolean; onClose: () => void }) => {
const schema = z.object({
tag: z.string().nonempty(),
})

export const ConfigureNodeFormModal = ({ opened, onClose }: { opened: boolean; onClose: () => void }) => {
const { t } = useTranslation()
const importNodesMutation = useImportNodesMutation()
const form = useForm<z.infer<typeof schema>>({
initialValues: { tag: '' },
validate: zodResolver(schema),
})

const onLinkGeneration = async (link: string) => {
const { hasErrors } = form.validate()

if (hasErrors) return

await importNodesMutation.mutateAsync([
{
link,
tag: form.values.tag,
},
])

onClose()
}

return (
<Modal opened={opened} onClose={onClose} title={t('configureNode.title')} size="md">
<TextInput label={t('tag')} withAsterisk {...form.getInputProps('tag')} />

<Divider />

<MantineProvider
theme={{
components: { TabsPanel: { defaultProps: { pt: 'md' } }, Stack: { defaultProps: { spacing: 'sm' } } },
Expand All @@ -31,37 +63,37 @@ export const NodeModal = ({ opened, onClose }: { opened: boolean; onClose: () =>

<Tabs.Panel value="v2ray">
<Stack>
<V2rayForm />
<V2rayForm onLinkGeneration={onLinkGeneration} />
</Stack>
</Tabs.Panel>

<Tabs.Panel value="ss">
<Stack>
<SSForm />
<SSForm onLinkGeneration={onLinkGeneration} />
</Stack>
</Tabs.Panel>

<Tabs.Panel value="ssr">
<Stack>
<SSRForm />
<SSRForm onLinkGeneration={onLinkGeneration} />
</Stack>
</Tabs.Panel>

<Tabs.Panel value="trojan">
<Stack>
<TrojanForm />
<TrojanForm onLinkGeneration={onLinkGeneration} />
</Stack>
</Tabs.Panel>

<Tabs.Panel value="http">
<Stack>
<HTTPForm />
<HTTPForm onLinkGeneration={onLinkGeneration} />
</Stack>
</Tabs.Panel>

<Tabs.Panel value="socks5">
<Stack>
<Socks5Form />
<Socks5Form onLinkGeneration={onLinkGeneration} />
</Stack>
</Tabs.Panel>
</Tabs>
Expand Down
24 changes: 0 additions & 24 deletions src/components/CreateNodeFormModal.tsx

This file was deleted.

18 changes: 18 additions & 0 deletions src/components/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export * from './ConfigFormModal'
export * from './ConfigureNodeFormModal'
export * from './DraggableResourceBadge'
export * from './DraggableResourceCard'
export * from './DroppableGroupCard'
export * from './ExpandedTableRow'
export * from './FormActions'
export * from './GroupFormModal'
export * from './Header'
export * from './ImportResourceFormModal'
export * from './PlainTextFormModal'
export * from './QRCodeModal'
export * from './RenameFormModal'
export * from './Section'
export * from './SelectItemWithDescription'
export * from './SimpleCard'
export * from './Table'
export * from './UpdateSubscriptionAction'
55 changes: 28 additions & 27 deletions src/pages/Experiment.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import {
import { useDisclosure } from '@mantine/hooks'
import { Prism } from '@mantine/prism'
import Editor from '@monaco-editor/react'
import { IconForms } from '@tabler/icons-react'
import { IconFileImport, IconForms } from '@tabler/icons-react'
import dayjs from 'dayjs'
import { produce } from 'immer'
import { useRef, useState } from 'react'
Expand All @@ -33,18 +33,20 @@ import {
useImportNodesMutation,
useImportSubscriptionsMutation,
} from '~/apis'
import { ConfigFormDrawer } from '~/components/ConfigFormModal'
import { CreateNodeFormModal } from '~/components/CreateNodeFormModal'
import { DraggableResourceBadge } from '~/components/DraggableResourceBadge'
import { DraggableResourceCard } from '~/components/DraggableResourceCard'
import { DroppableGroupCard } from '~/components/DroppableGroupCard'
import { GroupFormModal } from '~/components/GroupFormModal'
import { ImportResourceFormModal } from '~/components/ImportResourceFormModal'
import { NodeModal } from '~/components/NodeModal'
import { PlainTextFormModal } from '~/components/PlainTextFormModal'
import { RenameFormModal, RenameFormModalRef } from '~/components/RenameFormModal'
import { Section } from '~/components/Section'
import { SimpleCard } from '~/components/SimpleCard'
import {
ConfigFormDrawer,
ConfigureNodeFormModal,
DraggableResourceBadge,
DraggableResourceCard,
DroppableGroupCard,
GroupFormModal,
ImportResourceFormModal,
PlainTextFormModal,
RenameFormModal,
RenameFormModalRef,
Section,
SimpleCard,
} from '~/components'
import { DialMode, DraggableResourceType, EDITOR_OPTIONS, LogLevel, RuleType } from '~/constants'
import { Policy } from '~/schemas/gql/graphql'

Expand Down Expand Up @@ -217,6 +219,8 @@ export const ExperimentPage = () => {
useDisclosure(false)
const [openedCreateGroupModal, { open: openCreateGroupModal, close: closeCreateGroupModal }] = useDisclosure(false)
const [openedImportNodeModal, { open: openImportNodeModal, close: closeImportNodeModal }] = useDisclosure(false)
const [openedConfigureNodeFormModal, { open: openConfigureNodeFormModal, close: closeConfigureNodeFormModal }] =
useDisclosure(false)
const [openedImportSubscriptionModal, { open: openImportSubscriptionModal, close: closeImportSubscriptionModal }] =
useDisclosure(false)

Expand Down Expand Up @@ -504,7 +508,16 @@ export const ExperimentPage = () => {
</Stack>
</Section>

<Section title={t('node')} onCreate={openImportNodeModal} bordered>
<Section
title={t('node')}
onCreate={openConfigureNodeFormModal}
actions={
<ActionIcon onClick={openImportNodeModal}>
<IconFileImport />
</ActionIcon>
}
bordered
>
<Stack>
{fakeNodes.map(({ id, name, tag, protocol, link }) => (
<DraggableResourceCard
Expand Down Expand Up @@ -632,21 +645,9 @@ export const ExperimentPage = () => {
}}
/>

<CreateNodeFormModal
opened={false}
onClose={() => {
//
}}
/>

<RenameFormModal ref={renameModalRef} opened={openedRenameModal} onClose={closeRenameModal} />

<NodeModal
opened
onClose={() => {
//
}}
/>
<ConfigureNodeFormModal opened={openedConfigureNodeFormModal} onClose={closeConfigureNodeFormModal} />
</Stack>
)
}
19 changes: 17 additions & 2 deletions src/pages/Orchestrate/Node.tsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { ActionIcon, Spoiler, Text, useMantineTheme } from '@mantine/core'
import { useDisclosure } from '@mantine/hooks'
import { IconCloud, IconDetails } from '@tabler/icons-react'
import { IconCloud, IconDetails, IconFileImport } from '@tabler/icons-react'
import { useRef } from 'react'
import { useTranslation } from 'react-i18next'

import { useImportNodesMutation, useNodesQuery, useRemoveNodesMutation } from '~/apis'
import { ConfigureNodeFormModal } from '~/components'
import { DraggableResourceCard } from '~/components/DraggableResourceCard'
import { ImportResourceFormModal } from '~/components/ImportResourceFormModal'
import { QRCodeModal, QRCodeModalRef } from '~/components/QRCodeModal'
Expand All @@ -18,13 +19,25 @@ export const NodeResource = () => {
const [openedQRCodeModal, { open: openQRCodeModal, close: closeQRCodeModal }] = useDisclosure(false)
const [openedImportNodeFormModal, { open: openImportNodeFormModal, close: closeImportNodeFormModal }] =
useDisclosure(false)
const [openedConfigureNodeFormModal, { open: openConfigureNodeFormModal, close: closeConfigureNodeFormModal }] =
useDisclosure(false)
const qrCodeModalRef = useRef<QRCodeModalRef>(null)
const { data: nodesQuery } = useNodesQuery()
const removeNodesMutation = useRemoveNodesMutation()
const importNodesMutation = useImportNodesMutation()

return (
<Section title={t('node')} icon={<IconCloud />} onCreate={openImportNodeFormModal} bordered>
<Section
title={t('node')}
icon={<IconCloud />}
onCreate={openConfigureNodeFormModal}
actions={
<ActionIcon onClick={openImportNodeFormModal}>
<IconFileImport />
</ActionIcon>
}
bordered
>
{nodesQuery?.nodes.edges.map(({ id, name, tag, protocol, link }) => (
<DraggableResourceCard
key={id}
Expand Down Expand Up @@ -84,6 +97,8 @@ export const NodeResource = () => {
await importNodesMutation.mutateAsync(values.resources.map(({ link, tag }) => ({ link, tag })))
}}
/>

<ConfigureNodeFormModal opened={openedConfigureNodeFormModal} onClose={closeConfigureNodeFormModal} />
</Section>
)
}

0 comments on commit c8a36e6

Please sign in to comment.