Commit 076fe8ca authored by Joel's avatar Joel

feat: auth struct

parent b08327cb
'use client'
import type { FC } from 'react'
import React, { useCallback } from 'react'
import produce from 'immer'
import type { Authorization as AuthorizationPayloadType } from '../../types'
import { APIType, AuthorizationType } from '../../types'
import RadioGroup from './radio-group'
import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button'
type Props = {
payload: AuthorizationPayloadType
onChange: (newPayload: AuthorizationPayloadType) => void
isShow: boolean
onHide: () => void
}
const Field = ({ title, children }: { title: string; children: JSX.Element }) => {
return (
<div>
<div className='leading-8 text-[13px] font-medium text-gray-700'>{title}</div>
<div>{children}</div>
</div>
)
}
const Authorization: FC<Props> = ({
payload,
onChange,
isShow,
onHide,
}) => {
const [tempPayload, setTempPayload] = React.useState<AuthorizationPayloadType>(payload)
const handleAuthTypeChange = useCallback((type: string) => {
const newPayload = produce(tempPayload, (draft: AuthorizationPayloadType) => {
draft.type = type as AuthorizationType
if (draft.type === AuthorizationType.apiKey && !draft.config) {
draft.config = {
type: APIType.basic,
api_key: '',
}
}
})
setTempPayload(newPayload)
}, [tempPayload, setTempPayload])
const handleAuthAPITypeChange = useCallback((type: string) => {
const newPayload = produce(tempPayload, (draft: AuthorizationPayloadType) => {
if (!draft.config) {
draft.config = {
type: APIType.basic,
api_key: '',
}
}
draft.config.type = type as APIType
})
setTempPayload(newPayload)
}, [tempPayload, setTempPayload])
const handleAPIKeyOrHeaderChange = useCallback((type: 'api_key' | 'header') => {
return (e: React.ChangeEvent<HTMLInputElement>) => {
const newPayload = produce(tempPayload, (draft: AuthorizationPayloadType) => {
if (!draft.config) {
draft.config = {
type: APIType.basic,
api_key: '',
}
}
draft.config[type] = e.target.value
})
setTempPayload(newPayload)
}
}, [tempPayload, setTempPayload])
const handleConfirm = useCallback(() => {
onChange(tempPayload)
onHide()
}, [tempPayload, onChange, onHide])
return (
<Modal
title='Authorization'
wrapperClassName='z-50 w-400'
isShow={isShow}
onClose={onHide}
>
<div>
<div className='space-y-2'>
<Field title='Type'>
<RadioGroup
options={[
{ value: AuthorizationType.none, label: 'Basic' },
{ value: AuthorizationType.apiKey, label: 'Bearer' },
]}
value={tempPayload.type}
onChange={handleAuthTypeChange}
/>
</Field>
{tempPayload.type === AuthorizationType.apiKey && (
<>
<Field title='Auth type'>
<RadioGroup
options={[
{ value: APIType.basic, label: 'Basic' },
{ value: APIType.bearer, label: 'Bearer' },
{ value: APIType.custom, label: 'Custom' },
]}
value={tempPayload.config?.type || APIType.basic}
onChange={handleAuthAPITypeChange}
/>
</Field>
{tempPayload.config?.type === APIType.custom && (
<Field title='header'>
<input
type='text'
className='w-full h-8 leading-8 px-2.5 rounded-lg border-0 bg-gray-100 text-gray-900 text-[13px] placeholder:text-gray-400 focus:outline-none focus:ring-1 focus:ring-inset focus:ring-gray-200'
value={tempPayload.config?.header || ''}
onChange={handleAPIKeyOrHeaderChange('header')}
/>
</Field>
)}
<Field title='API Key'>
<input
type='text'
className='w-full h-8 leading-8 px-2.5 rounded-lg border-0 bg-gray-100 text-gray-900 text-[13px] placeholder:text-gray-400 focus:outline-none focus:ring-1 focus:ring-inset focus:ring-gray-200'
value={tempPayload.config?.api_key || ''}
onChange={handleAPIKeyOrHeaderChange('api_key')}
/>
</Field>
</>
)}
</div>
<div className='mt-6 flex justify-end space-x-2'>
<Button onClick={onHide} className='flex items-center !h-8 leading-[18px] !text-[13px] !font-medium'>Cancel</Button>
<Button type='primary' onClick={handleConfirm} className='flex items-center !h-8 leading-[18px] !text-[13px] !font-medium'>Confirm</Button>
</div>
</div>
</Modal>
)
}
export default React.memo(Authorization)
'use client'
import type { FC } from 'react'
import React, { useCallback } from 'react'
import cn from 'classnames'
type Option = {
value: string
label: string
}
type ItemProps = {
title: string
onClick: () => void
isSelected: boolean
}
const Item: FC<ItemProps> = ({
title,
onClick,
isSelected,
}) => {
return (
<div
className={cn(
isSelected ? 'border-[2px] border-primary-400 bg-white shadow-xs' : 'border border-gray-100 bg-gray-25',
'w-0 grow flex items-center justify-center h-8 cursor-pointer rounded-lg text-[13px] font-normal text-gray-900')
}
onClick={onClick}
>
{title}
</div>
)
}
type Props = {
options: Option[]
value: string
onChange: (value: string) => void
}
const RadioGroup: FC<Props> = ({
options,
value,
onChange,
}) => {
const handleChange = useCallback((value: string) => {
return () => onChange(value)
}, [onChange])
return (
<div className='flex space-x-2'>
{options.map(option => (
<Item
key={option.value}
title={option.label}
onClick={handleChange(option.value)}
isSelected={option.value === value}
/>
))}
</div>
)
}
export default React.memo(RadioGroup)
import { BlockEnum } from '../../types'
import { BodyType, Method } from './types'
import { APIType, AuthorizationType, BodyType, Method } from './types'
import type { HttpNodeType } from './types'
export const mockData: HttpNodeType = {
......@@ -24,4 +24,12 @@ export const mockData: HttpNodeType = {
type: BodyType.none,
data: '',
},
authorization: {
type: AuthorizationType.apiKey,
config: {
type: APIType.custom,
api_key: 'abc',
header: 'x-Authorization',
},
},
}
......@@ -5,6 +5,7 @@ import { mockData } from './mock'
import ApiInput from './components/api-input'
import KeyValue from './components/key-value'
import EditBody from './components/edit-body'
import AuthorizationModal from './components/authorization'
import VarList from '@/app/components/workflow/nodes/_base/components/variable/var-list'
import Field from '@/app/components/workflow/nodes/_base/components/field'
import AddButton from '@/app/components/base/button/add-button'
......@@ -33,6 +34,10 @@ const Panel: FC = () => {
isParamKeyValueEdit,
toggleIsParamKeyValueEdit,
setBody,
isShowAuthorization,
showAuthorization,
hideAuthorization,
setAuthorization,
} = useConfig(mockData)
return (
......@@ -52,6 +57,14 @@ const Panel: FC = () => {
</Field>
<Field
title={t(`${i18nPrefix}.api`)}
operations={
<div
onClick={showAuthorization}
className='flex '
>
API-KEY
</div>
}
>
<ApiInput
readonly={readOnly}
......@@ -95,6 +108,14 @@ const Panel: FC = () => {
/>
</Field>
</div>
{isShowAuthorization && (
<AuthorizationModal
isShow
onHide={hideAuthorization}
payload={inputs.authorization}
onChange={setAuthorization}
/>
)}
<Split />
<div className='px-4 pt-4 pb-2'>
<OutputVars>
......
......@@ -27,6 +27,26 @@ export type Body = {
data: string
}
export enum AuthorizationType {
none = 'no-auth',
apiKey = 'api-key',
}
export enum APIType {
basic = 'basic',
bearer = 'bearer',
custom = 'custom',
}
export type Authorization = {
type: AuthorizationType
config?: {
type: APIType
api_key: string
header?: string
}
}
export type HttpNodeType = CommonNodeType & {
variables: Variable[]
method: Method
......@@ -34,4 +54,5 @@ export type HttpNodeType = CommonNodeType & {
headers: string
params: string
body: Body
authorization: Authorization
}
import { useCallback, useState } from 'react'
import produce from 'immer'
import { useBoolean } from 'ahooks'
import useVarList from '../_base/hooks/use-var-list'
import type { Body, HttpNodeType, Method } from './types'
import type { Authorization, Body, HttpNodeType, Method } from './types'
import useKeyValueList from './hooks/use-key-value-list'
const useConfig = (initInputs: HttpNodeType) => {
const [inputs, setInputs] = useState<HttpNodeType>(initInputs)
......@@ -48,6 +49,19 @@ const useConfig = (initInputs: HttpNodeType) => {
setInputs(newInputs)
}, [inputs, setInputs])
// authorization
const [isShowAuthorization, {
setTrue: showAuthorization,
setFalse: hideAuthorization,
}] = useBoolean(true)
const setAuthorization = useCallback((authorization: Authorization) => {
const newInputs = produce(inputs, (draft: HttpNodeType) => {
draft.authorization = authorization
})
setInputs(newInputs)
}, [inputs, setInputs])
return {
inputs,
handleVarListChange,
......@@ -68,6 +82,11 @@ const useConfig = (initInputs: HttpNodeType) => {
toggleIsParamKeyValueEdit,
// body
setBody,
// authorization
isShowAuthorization,
showAuthorization,
hideAuthorization,
setAuthorization,
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment