mirror of
https://github.com/langgenius/dify.git
synced 2026-04-05 10:12:43 +08:00
Signed-off-by: yyh <yuanyouhuilyz@gmail.com> Signed-off-by: dependabot[bot] <support@github.com> Co-authored-by: CodingOnStar <hanxujiang@dify.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Coding On Star <447357187@qq.com> Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: -LAN- <laipz8200@outlook.com> Co-authored-by: statxc <tyleradams93226@gmail.com>
153 lines
4.9 KiB
TypeScript
153 lines
4.9 KiB
TypeScript
'use client'
|
|
import { useId, useMemo, useState } from 'react'
|
|
import { useTranslation } from 'react-i18next'
|
|
import { useContext } from 'use-context-selector'
|
|
import Button from '@/app/components/base/button'
|
|
import Input from '@/app/components/base/input'
|
|
import { ToastContext } from '@/app/components/base/toast/context'
|
|
import { Dialog, DialogCloseButton, DialogContent, DialogTitle } from '@/app/components/base/ui/dialog'
|
|
import { useAppContext } from '@/context/app-context'
|
|
import { updateWorkspaceInfo } from '@/service/common'
|
|
import { cn } from '@/utils/classnames'
|
|
|
|
type IEditWorkspaceModalProps = {
|
|
onCancel: () => void
|
|
}
|
|
|
|
const EditWorkspaceModal = ({
|
|
onCancel,
|
|
}: IEditWorkspaceModalProps) => {
|
|
const { t } = useTranslation()
|
|
const { notify } = useContext(ToastContext)
|
|
const { currentWorkspace, isCurrentWorkspaceOwner } = useAppContext()
|
|
const [name, setName] = useState<string>(currentWorkspace.name)
|
|
const [isSubmitting, setIsSubmitting] = useState(false)
|
|
const inputId = useId()
|
|
const errorId = useId()
|
|
const normalizedName = name.trim()
|
|
const hasChanges = normalizedName !== currentWorkspace.name
|
|
const hasError = normalizedName.length === 0
|
|
const isSaveDisabled = !isCurrentWorkspaceOwner || !hasChanges || hasError || isSubmitting
|
|
const nameErrorMessage = useMemo(() => {
|
|
if (!hasError)
|
|
return ''
|
|
|
|
return t('errorMsg.fieldRequired', {
|
|
ns: 'common',
|
|
field: t('account.workspaceName', { ns: 'common' }),
|
|
})
|
|
}, [hasError, t])
|
|
|
|
const changeWorkspaceInfo = async () => {
|
|
if (isSaveDisabled)
|
|
return
|
|
|
|
setIsSubmitting(true)
|
|
try {
|
|
await updateWorkspaceInfo({
|
|
url: '/workspaces/info',
|
|
body: {
|
|
name: normalizedName,
|
|
},
|
|
})
|
|
notify({ type: 'success', message: t('actionMsg.modifiedSuccessfully', { ns: 'common' }) })
|
|
location.assign(`${location.origin}`)
|
|
}
|
|
catch {
|
|
notify({ type: 'error', message: t('actionMsg.modifiedUnsuccessfully', { ns: 'common' }) })
|
|
}
|
|
finally {
|
|
setIsSubmitting(false)
|
|
}
|
|
}
|
|
|
|
return (
|
|
<Dialog
|
|
open
|
|
onOpenChange={(open) => {
|
|
if (!open)
|
|
onCancel()
|
|
}}
|
|
>
|
|
<DialogContent
|
|
backdropProps={{ forceRender: true }}
|
|
className="overflow-visible"
|
|
>
|
|
<DialogCloseButton data-testid="edit-workspace-close" />
|
|
|
|
<form
|
|
className="flex flex-col"
|
|
onSubmit={(e) => {
|
|
e.preventDefault()
|
|
void changeWorkspaceInfo()
|
|
}}
|
|
>
|
|
<div className="mb-4 pr-8">
|
|
<DialogTitle className="text-xl font-semibold text-text-primary" data-testid="edit-workspace-title">
|
|
{t('account.editWorkspaceInfo', { ns: 'common' })}
|
|
</DialogTitle>
|
|
</div>
|
|
|
|
<div className="space-y-2">
|
|
<label htmlFor={inputId} className="block text-sm font-medium text-text-primary">
|
|
{t('account.workspaceName', { ns: 'common' })}
|
|
</label>
|
|
<Input
|
|
id={inputId}
|
|
autoFocus
|
|
value={name}
|
|
placeholder={t('account.workspaceNamePlaceholder', { ns: 'common' })}
|
|
onChange={(e) => {
|
|
setName(e.target.value)
|
|
}}
|
|
aria-invalid={hasError}
|
|
aria-describedby={hasError ? errorId : undefined}
|
|
className={cn(
|
|
hasError && 'border-components-input-border-destructive bg-components-input-bg-destructive hover:border-components-input-border-destructive hover:bg-components-input-bg-destructive focus:border-components-input-border-destructive focus:bg-components-input-bg-destructive',
|
|
)}
|
|
/>
|
|
<div className="min-h-6">
|
|
{hasError && (
|
|
<p
|
|
id={errorId}
|
|
data-testid="edit-workspace-error"
|
|
className="text-text-destructive system-xs-regular"
|
|
role="alert"
|
|
>
|
|
{nameErrorMessage}
|
|
</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
<div className="sticky bottom-0 -mx-2 mt-2 flex flex-wrap items-center justify-end gap-x-2 bg-components-panel-bg px-2 pt-4">
|
|
<Button
|
|
size="large"
|
|
type="button"
|
|
data-testid="edit-workspace-cancel"
|
|
onClick={onCancel}
|
|
>
|
|
{t('operation.cancel', { ns: 'common' })}
|
|
</Button>
|
|
<Button
|
|
size="large"
|
|
type="submit"
|
|
variant="primary"
|
|
data-testid="edit-workspace-save"
|
|
disabled={isSaveDisabled}
|
|
loading={isSubmitting}
|
|
>
|
|
{t(
|
|
isSubmitting ? 'operation.saving' : 'operation.save',
|
|
{ ns: 'common' },
|
|
)}
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</DialogContent>
|
|
</Dialog>
|
|
)
|
|
}
|
|
|
|
export default EditWorkspaceModal
|