feat: allow rename workspace
This commit is contained in:
parent
7c271dc3c1
commit
63e6bfe0d1
@ -3,7 +3,11 @@ import { createFileRoute } from '@tanstack/react-router';
|
|||||||
import { useTranslation } from '@i18next-toolkit/react';
|
import { useTranslation } from '@i18next-toolkit/react';
|
||||||
import { CommonWrapper } from '@/components/CommonWrapper';
|
import { CommonWrapper } from '@/components/CommonWrapper';
|
||||||
import { ScrollArea } from '@/components/ui/scroll-area';
|
import { ScrollArea } from '@/components/ui/scroll-area';
|
||||||
import { useCurrentWorkspace, useHasAdminPermission } from '../../store/user';
|
import {
|
||||||
|
useCurrentWorkspace,
|
||||||
|
useHasAdminPermission,
|
||||||
|
useUserStore,
|
||||||
|
} from '../../store/user';
|
||||||
import { CommonHeader } from '@/components/CommonHeader';
|
import { CommonHeader } from '@/components/CommonHeader';
|
||||||
import {
|
import {
|
||||||
Card,
|
Card,
|
||||||
@ -40,6 +44,7 @@ import { z } from 'zod';
|
|||||||
import { AlertConfirm } from '@/components/AlertConfirm';
|
import { AlertConfirm } from '@/components/AlertConfirm';
|
||||||
import { ROLES } from '@tianji/shared';
|
import { ROLES } from '@tianji/shared';
|
||||||
import { cn } from '@/utils/style';
|
import { cn } from '@/utils/style';
|
||||||
|
import { Separator } from '@/components/ui/separator';
|
||||||
|
|
||||||
export const Route = createFileRoute('/settings/workspace')({
|
export const Route = createFileRoute('/settings/workspace')({
|
||||||
beforeLoad: routeAuthBeforeLoad,
|
beforeLoad: routeAuthBeforeLoad,
|
||||||
@ -63,6 +68,9 @@ function PageComponent() {
|
|||||||
trpc.workspace.members.useQuery({
|
trpc.workspace.members.useQuery({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
});
|
});
|
||||||
|
const updateCurrentWorkspaceName = useUserStore(
|
||||||
|
(state) => state.updateCurrentWorkspaceName
|
||||||
|
);
|
||||||
const form = useForm<InviteFormValues>({
|
const form = useForm<InviteFormValues>({
|
||||||
resolver: zodResolver(inviteFormSchema),
|
resolver: zodResolver(inviteFormSchema),
|
||||||
defaultValues: {
|
defaultValues: {
|
||||||
@ -73,12 +81,26 @@ function PageComponent() {
|
|||||||
onSuccess: defaultSuccessHandler,
|
onSuccess: defaultSuccessHandler,
|
||||||
onError: defaultErrorHandler,
|
onError: defaultErrorHandler,
|
||||||
});
|
});
|
||||||
|
const renameWorkspaceMutation = trpc.workspace.rename.useMutation({
|
||||||
|
onSuccess: defaultSuccessHandler,
|
||||||
|
onError: defaultErrorHandler,
|
||||||
|
});
|
||||||
const deleteWorkspaceMutation = trpc.workspace.delete.useMutation({
|
const deleteWorkspaceMutation = trpc.workspace.delete.useMutation({
|
||||||
onSuccess: defaultSuccessHandler,
|
onSuccess: defaultSuccessHandler,
|
||||||
onError: defaultErrorHandler,
|
onError: defaultErrorHandler,
|
||||||
});
|
});
|
||||||
|
|
||||||
const [handleInvite, isLoading] = useEventWithLoading(
|
const [renameWorkspaceName, setRenameWorkspaceName] = useState('');
|
||||||
|
const [handleRename, isRenameLoading] = useEventWithLoading(async () => {
|
||||||
|
await renameWorkspaceMutation.mutateAsync({
|
||||||
|
workspaceId,
|
||||||
|
name: renameWorkspaceName,
|
||||||
|
});
|
||||||
|
|
||||||
|
updateCurrentWorkspaceName(renameWorkspaceName);
|
||||||
|
});
|
||||||
|
|
||||||
|
const [handleInvite, isInviteLoading] = useEventWithLoading(
|
||||||
async (values: InviteFormValues) => {
|
async (values: InviteFormValues) => {
|
||||||
await inviteMutation.mutateAsync({
|
await inviteMutation.mutateAsync({
|
||||||
workspaceId,
|
workspaceId,
|
||||||
@ -177,7 +199,7 @@ function PageComponent() {
|
|||||||
<CardFooter>
|
<CardFooter>
|
||||||
<Button
|
<Button
|
||||||
type="submit"
|
type="submit"
|
||||||
loading={isLoading}
|
loading={isInviteLoading}
|
||||||
disabled={!hasAdminPermission}
|
disabled={!hasAdminPermission}
|
||||||
>
|
>
|
||||||
{t('Invite')}
|
{t('Invite')}
|
||||||
@ -203,6 +225,33 @@ function PageComponent() {
|
|||||||
</CardHeader>
|
</CardHeader>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<div>
|
<div>
|
||||||
|
<div className="flex items-center gap-2 text-left">
|
||||||
|
<Input
|
||||||
|
className="w-60"
|
||||||
|
placeholder={t('New Workspace Name')}
|
||||||
|
value={renameWorkspaceName}
|
||||||
|
onChange={(e) => setRenameWorkspaceName(e.target.value)}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<AlertConfirm
|
||||||
|
title={'Confirm to rename this workspace?'}
|
||||||
|
description={`${name} => ${renameWorkspaceName}`}
|
||||||
|
onConfirm={handleRename}
|
||||||
|
>
|
||||||
|
<Button
|
||||||
|
type="button"
|
||||||
|
loading={isRenameLoading}
|
||||||
|
disabled={
|
||||||
|
!renameWorkspaceName || name === renameWorkspaceName
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{t('Rename')}
|
||||||
|
</Button>
|
||||||
|
</AlertConfirm>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<Separator className="my-4" />
|
||||||
|
|
||||||
<AlertConfirm
|
<AlertConfirm
|
||||||
title={'Confirm to delete this workspace'}
|
title={'Confirm to delete this workspace'}
|
||||||
description={t(
|
description={t(
|
||||||
|
@ -3,17 +3,31 @@ import { createWithEqualityFn } from 'zustand/traditional';
|
|||||||
import { createSocketIOClient } from '../api/socketio';
|
import { createSocketIOClient } from '../api/socketio';
|
||||||
import { AppRouterOutput } from '../api/trpc';
|
import { AppRouterOutput } from '../api/trpc';
|
||||||
import { ROLES } from '@tianji/shared';
|
import { ROLES } from '@tianji/shared';
|
||||||
|
import { immer } from 'zustand/middleware/immer';
|
||||||
|
|
||||||
export type UserLoginInfo = NonNullable<AppRouterOutput['user']['info']>;
|
export type UserLoginInfo = NonNullable<AppRouterOutput['user']['info']>;
|
||||||
|
|
||||||
interface UserState {
|
interface UserState {
|
||||||
info: UserLoginInfo | null;
|
info: UserLoginInfo | null;
|
||||||
|
updateCurrentWorkspaceName: (name: string) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const useUserStore = createWithEqualityFn<UserState>(
|
export const useUserStore = createWithEqualityFn<UserState>()(
|
||||||
() => ({
|
immer((set) => ({
|
||||||
info: null,
|
info: null,
|
||||||
}),
|
updateCurrentWorkspaceName: (name) => {
|
||||||
|
const currentUserInfo = useUserStore.getState().info;
|
||||||
|
if (!currentUserInfo) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
set((state) => {
|
||||||
|
for (const workspace of state.info?.workspaces ?? []) {
|
||||||
|
workspace.workspace.name = name;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
})),
|
||||||
shallow
|
shallow
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@ import { prisma } from '../../model/_client.js';
|
|||||||
import {
|
import {
|
||||||
userInfoSchema,
|
userInfoSchema,
|
||||||
workspaceDashboardLayoutSchema,
|
workspaceDashboardLayoutSchema,
|
||||||
|
workspaceSchema,
|
||||||
} from '../../model/_schema/index.js';
|
} from '../../model/_schema/index.js';
|
||||||
import { Prisma } from '@prisma/client';
|
import { Prisma } from '@prisma/client';
|
||||||
import { OPENAPI_TAG } from '../../utils/const.js';
|
import { OPENAPI_TAG } from '../../utils/const.js';
|
||||||
@ -124,6 +125,33 @@ export const workspaceRouter = router({
|
|||||||
|
|
||||||
return userInfo;
|
return userInfo;
|
||||||
}),
|
}),
|
||||||
|
rename: workspaceOwnerProcedure
|
||||||
|
.meta(
|
||||||
|
buildWorkspaceOpenapi({
|
||||||
|
method: 'PATCH',
|
||||||
|
path: '/rename',
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.input(
|
||||||
|
z.object({
|
||||||
|
name: z.string().max(60).min(4),
|
||||||
|
})
|
||||||
|
)
|
||||||
|
.output(workspaceSchema)
|
||||||
|
.mutation(async ({ input }) => {
|
||||||
|
const { workspaceId, name } = input;
|
||||||
|
|
||||||
|
const workspace = await prisma.workspace.update({
|
||||||
|
where: {
|
||||||
|
id: workspaceId,
|
||||||
|
},
|
||||||
|
data: {
|
||||||
|
name,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
return workspace;
|
||||||
|
}),
|
||||||
delete: workspaceOwnerProcedure
|
delete: workspaceOwnerProcedure
|
||||||
.meta(
|
.meta(
|
||||||
buildWorkspaceOpenapi({
|
buildWorkspaceOpenapi({
|
||||||
|
Loading…
Reference in New Issue
Block a user