Skip to content

Commit

Permalink
feat: Bind data to TenantTable infiniflow#2846 (infiniflow#2883)
Browse files Browse the repository at this point in the history
### What problem does this PR solve?

feat: Bind data to TenantTable infiniflow#2846
feat: Add TenantTable

### Type of change

- [x] New Feature (non-breaking change which adds functionality)
  • Loading branch information
cike8899 authored Oct 18, 2024
1 parent cf8bab8 commit e0d7442
Show file tree
Hide file tree
Showing 15 changed files with 548 additions and 11 deletions.
137 changes: 135 additions & 2 deletions web/src/hooks/user-setting-hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,19 @@ import { LanguageTranslationMap } from '@/constants/common';
import { ResponseGetType } from '@/interfaces/database/base';
import { IToken } from '@/interfaces/database/chat';
import { ITenantInfo } from '@/interfaces/database/knowledge';
import { ISystemStatus, IUserInfo } from '@/interfaces/database/user-setting';
import userService from '@/services/user-service';
import {
ISystemStatus,
ITenant,
ITenantUser,
IUserInfo,
} from '@/interfaces/database/user-setting';
import userService, {
addTenantUser,
agreeTenant,
deleteTenantUser,
listTenant,
listTenantUser,
} from '@/services/user-service';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { Modal, message } from 'antd';
import DOMPurify from 'dompurify';
Expand Down Expand Up @@ -215,3 +226,125 @@ export const useCreateSystemToken = () => {

return { data, loading, createToken: mutateAsync };
};

export const useListTenantUser = () => {
const { data: tenantInfo } = useFetchTenantInfo();
const tenantId = tenantInfo.tenant_id;
const {
data,
isFetching: loading,
refetch,
} = useQuery<ITenantUser[]>({
queryKey: ['listTenantUser', tenantId],
initialData: [],
gcTime: 0,
enabled: !!tenantId,
queryFn: async () => {
const { data } = await listTenantUser(tenantId);

return data?.data ?? [];
},
});

return { data, loading, refetch };
};

export const useAddTenantUser = () => {
const { data: tenantInfo } = useFetchTenantInfo();
const queryClient = useQueryClient();
const {
data,
isPending: loading,
mutateAsync,
} = useMutation({
mutationKey: ['addTenantUser'],
mutationFn: async (email: string) => {
const { data } = await addTenantUser(tenantInfo.tenant_id, email);
if (data.retcode === 0) {
queryClient.invalidateQueries({ queryKey: ['listTenantUser'] });
}
return data?.retcode;
},
});

return { data, loading, addTenantUser: mutateAsync };
};

export const useDeleteTenantUser = () => {
const { data: tenantInfo } = useFetchTenantInfo();
const queryClient = useQueryClient();
const { t } = useTranslation();

const {
data,
isPending: loading,
mutateAsync,
} = useMutation({
mutationKey: ['deleteTenantUser'],
mutationFn: async ({
userId,
tenantId,
}: {
userId: string;
tenantId?: string;
}) => {
const { data } = await deleteTenantUser({
tenantId: tenantId ?? tenantInfo.tenant_id,
userId,
});
if (data.retcode === 0) {
message.success(t('message.deleted'));
queryClient.invalidateQueries({ queryKey: ['listTenantUser'] });
queryClient.invalidateQueries({ queryKey: ['listTenant'] });
}
return data?.data ?? [];
},
});

return { data, loading, deleteTenantUser: mutateAsync };
};

export const useListTenant = () => {
const { data: tenantInfo } = useFetchTenantInfo();
const tenantId = tenantInfo.tenant_id;
const {
data,
isFetching: loading,
refetch,
} = useQuery<ITenant[]>({
queryKey: ['listTenant', tenantId],
initialData: [],
gcTime: 0,
enabled: !!tenantId,
queryFn: async () => {
const { data } = await listTenant();

return data?.data ?? [];
},
});

return { data, loading, refetch };
};

export const useAgreeTenant = () => {
const queryClient = useQueryClient();
const { t } = useTranslation();

const {
data,
isPending: loading,
mutateAsync,
} = useMutation({
mutationKey: ['agreeTenant'],
mutationFn: async (tenantId: string) => {
const { data } = await agreeTenant(tenantId);
if (data.retcode === 0) {
message.success(t('message.operated'));
queryClient.invalidateQueries({ queryKey: ['listTenant'] });
}
return data?.data ?? [];
},
});

return { data, loading, agreeTenant: mutateAsync };
};
25 changes: 25 additions & 0 deletions web/src/interfaces/database/user-setting.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,3 +60,28 @@ interface Es {
number_of_nodes: number;
active_shards: number;
}

export interface ITenantUser {
avatar: null;
delta_seconds: number;
email: string;
is_active: string;
is_anonymous: string;
is_authenticated: string;
is_superuser: boolean;
nickname: string;
role: string;
status: string;
update_date: string;
user_id: string;
}

export interface ITenant {
avatar: string;
delta_seconds: number;
email: string;
nickname: string;
role: string;
tenant_id: string;
update_date: string;
}
11 changes: 10 additions & 1 deletion web/src/locales/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ export default {
close: 'Close',
preview: 'Preview',
move: 'Move',
warn: '提醒',
warn: 'Warn',
action: 'Action',
},
login: {
login: 'Sign in',
Expand Down Expand Up @@ -584,6 +585,14 @@ The above is the content you need to summarize.`,
'Please add both embedding model and LLM in <b>Settings > Model providers</b> firstly.',
apiVersion: 'API-Version',
apiVersionMessage: 'Please input API version',
add: 'Add',
updateDate: 'Update Date',
role: 'Role',
invite: 'Invite',
agree: 'Agree',
refuse: 'Refuse',
teamMembers: 'Team Members',
joinedTeams: 'Joined Teams',
},
message: {
registered: 'Registered!',
Expand Down
9 changes: 9 additions & 0 deletions web/src/locales/zh-traditional.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default {
preview: '預覽',
move: '移動',
warn: '提醒',
action: '操作',
},
login: {
login: '登入',
Expand Down Expand Up @@ -540,6 +541,14 @@ export default {
GoogleRegionMessage: '請輸入 Google Cloud 區域',
modelProvidersWarn:
'請先在 <b>「設定」>「模型提供者」</b> 中新增嵌入模型和LLM。',
add: '添加',
updateDate: '更新日期',
role: '角色',
invite: '邀請',
agree: '同意',
refuse: '拒絕',
teamMembers: '團隊成員',
joinedTeams: '加入的團隊',
},
message: {
registered: '註冊成功',
Expand Down
9 changes: 9 additions & 0 deletions web/src/locales/zh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ export default {
preview: '预览',
move: '移动',
warn: '提醒',
action: '操作',
},
login: {
login: '登录',
Expand Down Expand Up @@ -559,6 +560,14 @@ export default {
'请首先在 <b>设置 > 模型提供商</b> 中添加嵌入模型和 LLM。',
apiVersion: 'API版本',
apiVersionMessage: '请输入API版本!',
add: '添加',
updateDate: '更新日期',
role: '角色',
invite: '邀请',
agree: '同意',
refuse: '拒绝',
teamMembers: '团队成员',
joinedTeams: '加入的团队',
},
message: {
registered: '注册成功',
Expand Down
6 changes: 6 additions & 0 deletions web/src/pages/user-setting/constants.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,9 @@ export const LocalLlmFactories = [
'OpenRouter',
'HuggingFace',
];

export enum TenantRole {
Owner = 'owner',
Invite = 'invite',
Normal = 'normal',
}
52 changes: 52 additions & 0 deletions web/src/pages/user-setting/setting-team/add-user-modal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { IModalProps } from '@/interfaces/common';
import { Form, Input, Modal } from 'antd';
import { useTranslation } from 'react-i18next';

const AddingUserModal = ({
visible,
hideModal,
loading,
onOk,
}: IModalProps<string>) => {
const [form] = Form.useForm();
const { t } = useTranslation();

type FieldType = {
email?: string;
};

const handleOk = async () => {
const ret = await form.validateFields();

return onOk?.(ret.email);
};

return (
<Modal
title={t('setting.add')}
open={visible}
onOk={handleOk}
onCancel={hideModal}
okButtonProps={{ loading }}
confirmLoading={loading}
>
<Form
name="basic"
labelCol={{ span: 6 }}
wrapperCol={{ span: 18 }}
autoComplete="off"
form={form}
>
<Form.Item<FieldType>
label={t('setting.email')}
name="email"
rules={[{ required: true, message: t('namePlaceholder') }]}
>
<Input />
</Form.Item>
</Form>
</Modal>
);
};

export default AddingUserModal;
68 changes: 68 additions & 0 deletions web/src/pages/user-setting/setting-team/hooks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import { useSetModalState, useShowDeleteConfirm } from '@/hooks/common-hooks';
import {
useAddTenantUser,
useAgreeTenant,
useDeleteTenantUser,
useFetchUserInfo,
} from '@/hooks/user-setting-hooks';
import { useCallback } from 'react';

export const useAddUser = () => {
const { addTenantUser } = useAddTenantUser();
const {
visible: addingTenantModalVisible,
hideModal: hideAddingTenantModal,
showModal: showAddingTenantModal,
} = useSetModalState();

const handleAddUserOk = useCallback(
async (email: string) => {
const retcode = await addTenantUser(email);
if (retcode === 0) {
hideAddingTenantModal();
}
},
[addTenantUser, hideAddingTenantModal],
);

return {
addingTenantModalVisible,
hideAddingTenantModal,
showAddingTenantModal,
handleAddUserOk,
};
};

export const useHandleDeleteUser = () => {
const { deleteTenantUser, loading } = useDeleteTenantUser();
const showDeleteConfirm = useShowDeleteConfirm();

const handleDeleteTenantUser = (userId: string) => () => {
showDeleteConfirm({
onOk: async () => {
const retcode = await deleteTenantUser({ userId });
if (retcode === 0) {
}
return;
},
});
};

return { handleDeleteTenantUser, loading };
};

export const useHandleAgreeTenant = () => {
const { agreeTenant } = useAgreeTenant();
const { deleteTenantUser } = useDeleteTenantUser();
const { data: user } = useFetchUserInfo();

const handleAgree = (tenantId: string, isAgree: boolean) => () => {
if (isAgree) {
agreeTenant(tenantId);
} else {
deleteTenantUser({ tenantId, userId: user.id });
}
};

return { handleAgree };
};
3 changes: 3 additions & 0 deletions web/src/pages/user-setting/setting-team/index.less
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
.teamWrapper {
width: 100%;
display: flex;
flex-direction: column;
gap: 20px;
.teamCard {
// width: 100%;
}
Expand Down
Loading

0 comments on commit e0d7442

Please sign in to comment.