mirror of
https://github.com/aykhans/slash-e.git
synced 2025-07-03 20:21:40 +00:00
feat: impl grpcweb in frontend
This commit is contained in:
@ -19,6 +19,7 @@
|
||||
"i18next": "^23.5.1",
|
||||
"lodash-es": "^4.17.21",
|
||||
"lucide-react": "^0.263.1",
|
||||
"nice-grpc-web": "^3.3.1",
|
||||
"qrcode.react": "^3.1.0",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
|
53
frontend/web/pnpm-lock.yaml
generated
53
frontend/web/pnpm-lock.yaml
generated
@ -38,6 +38,9 @@ dependencies:
|
||||
lucide-react:
|
||||
specifier: ^0.263.1
|
||||
version: 0.263.1(react@18.2.0)
|
||||
nice-grpc-web:
|
||||
specifier: ^3.3.1
|
||||
version: 3.3.1(ws@8.14.2)
|
||||
qrcode.react:
|
||||
specifier: ^3.1.0
|
||||
version: 3.1.0(react@18.2.0)
|
||||
@ -1259,6 +1262,10 @@ packages:
|
||||
resolution: {integrity: sha512-N8tkAACJx2ww8vFMneJmaAgmjAG1tnVBZJRLRcx061tmsLRZHSEZSLuGWnwPtunsSLvSqXQ2wfp7Mgqg1I+2dQ==}
|
||||
dev: false
|
||||
|
||||
/abort-controller-x@0.4.3:
|
||||
resolution: {integrity: sha512-VtUwTNU8fpMwvWGn4xE93ywbogTYsuT+AUxAXOeelbXuQVIwNmC5YLeho9sH4vZ4ITW8414TTAOG1nW6uIVHCA==}
|
||||
dev: false
|
||||
|
||||
/acorn-jsx@5.3.2(acorn@8.10.0):
|
||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||
peerDependencies:
|
||||
@ -2490,6 +2497,14 @@ packages:
|
||||
resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==}
|
||||
dev: true
|
||||
|
||||
/isomorphic-ws@5.0.0(ws@8.14.2):
|
||||
resolution: {integrity: sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==}
|
||||
peerDependencies:
|
||||
ws: '*'
|
||||
dependencies:
|
||||
ws: 8.14.2
|
||||
dev: false
|
||||
|
||||
/iterator.prototype@1.1.2:
|
||||
resolution: {integrity: sha512-DR33HMMr8EzwuRL8Y9D3u2BMj8+RqSE850jfGu59kS7tbmPLzGkZmVSfyCFSDxuZiEY6Rzt3T2NA/qU+NwVj1w==}
|
||||
dependencies:
|
||||
@ -2509,6 +2524,10 @@ packages:
|
||||
hasBin: true
|
||||
dev: false
|
||||
|
||||
/js-base64@3.7.5:
|
||||
resolution: {integrity: sha512-3MEt5DTINKqfScXKfJFrRbxkrnk2AxPWGBL/ycjz4dK8iqiSJ06UxD8jh8xuh6p10TX4t2+7FsBYVxxQbMg+qA==}
|
||||
dev: false
|
||||
|
||||
/js-cookie@2.2.1:
|
||||
resolution: {integrity: sha512-HvdH2LzI/EAZcUwA8+0nKNtWHqS+ZmijLA30RwZA0bo7ToCckjK5MkGhjED9KoRcXO6BaGI3I9UIzSA1FKFPOQ==}
|
||||
dev: false
|
||||
@ -2693,6 +2712,23 @@ packages:
|
||||
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}
|
||||
dev: true
|
||||
|
||||
/nice-grpc-common@2.0.2:
|
||||
resolution: {integrity: sha512-7RNWbls5kAL1QVUOXvBsv1uO0wPQK3lHv+cY1gwkTzirnG1Nop4cBJZubpgziNbaVc/bl9QJcyvsf/NQxa3rjQ==}
|
||||
dependencies:
|
||||
ts-error: 1.0.6
|
||||
dev: false
|
||||
|
||||
/nice-grpc-web@3.3.1(ws@8.14.2):
|
||||
resolution: {integrity: sha512-KXListAFLjJ7L/GsrRW5YWT+2oZDaF8Lu19ms7+HMykDGtIksqvZwR6+EzVmunFJciiNDShJ4EXr1W6eaiZoDQ==}
|
||||
dependencies:
|
||||
abort-controller-x: 0.4.3
|
||||
isomorphic-ws: 5.0.0(ws@8.14.2)
|
||||
js-base64: 3.7.5
|
||||
nice-grpc-common: 2.0.2
|
||||
transitivePeerDependencies:
|
||||
- ws
|
||||
dev: false
|
||||
|
||||
/node-releases@2.0.13:
|
||||
resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==}
|
||||
dev: true
|
||||
@ -3542,6 +3578,10 @@ packages:
|
||||
resolution: {integrity: sha512-Z86EW+fFFh/IFB1fqQ3/+7Zpf9t2ebOAxNI/V6Wo7r5gqiqtxmgTlQ1qbqQcjLKYeSHPTsEmvlJUDg/EuL0uHQ==}
|
||||
dev: false
|
||||
|
||||
/ts-error@1.0.6:
|
||||
resolution: {integrity: sha512-tLJxacIQUM82IR7JO1UUkKlYuUTmoY9HBJAmNWFzheSlDS5SPMcNIepejHJa4BpPQLAcbRhRf3GDJzyj6rbKvA==}
|
||||
dev: false
|
||||
|
||||
/ts-interface-checker@0.1.13:
|
||||
resolution: {integrity: sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==}
|
||||
dev: false
|
||||
@ -3743,6 +3783,19 @@ packages:
|
||||
/wrappy@1.0.2:
|
||||
resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==}
|
||||
|
||||
/ws@8.14.2:
|
||||
resolution: {integrity: sha512-wEBG1ftX4jcglPxgFCMJmZ2PLtSbJ2Peg6TmpJFTbe9GZYOQCDPdMYu/Tm0/bGZkw8paZnJY45J4K2PZrLYq8g==}
|
||||
engines: {node: '>=10.0.0'}
|
||||
peerDependencies:
|
||||
bufferutil: ^4.0.1
|
||||
utf-8-validate: '>=5.0.2'
|
||||
peerDependenciesMeta:
|
||||
bufferutil:
|
||||
optional: true
|
||||
utf-8-validate:
|
||||
optional: true
|
||||
dev: false
|
||||
|
||||
/yallist@4.0.0:
|
||||
resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==}
|
||||
dev: true
|
||||
|
@ -1,8 +1,8 @@
|
||||
import { Button, Input, Modal, ModalDialog, Radio, RadioGroup } from "@mui/joy";
|
||||
import axios from "axios";
|
||||
import { useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { userServiceClient } from "@/grpcweb";
|
||||
import useLoading from "../hooks/useLoading";
|
||||
import useUserStore from "../stores/v1/user";
|
||||
import Icon from "./Icon";
|
||||
@ -68,9 +68,12 @@ const CreateAccessTokenDialog: React.FC<Props> = (props: Props) => {
|
||||
}
|
||||
|
||||
try {
|
||||
await axios.post(`/api/v2/users/${currentUser.id}/access_tokens`, {
|
||||
description: state.description,
|
||||
expiresAt: new Date(Date.now() + state.expiration * 1000),
|
||||
await userServiceClient.createUserAccessToken({
|
||||
id: currentUser.id,
|
||||
userAccessToken: {
|
||||
description: state.description,
|
||||
expiresAt: new Date(Date.now() + state.expiration * 1000),
|
||||
},
|
||||
});
|
||||
|
||||
if (onConfirm) {
|
||||
|
@ -1,18 +1,20 @@
|
||||
import { Button, IconButton } from "@mui/joy";
|
||||
import axios from "axios";
|
||||
import copy from "copy-to-clipboard";
|
||||
import { useEffect, useState } from "react";
|
||||
import { toast } from "react-hot-toast";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { ListUserAccessTokensResponse, UserAccessToken } from "@/types/proto/api/v2/user_service";
|
||||
import { userServiceClient } from "@/grpcweb";
|
||||
import { UserAccessToken } from "@/types/proto/api/v2/user_service";
|
||||
import useUserStore from "../../stores/v1/user";
|
||||
import { showCommonDialog } from "../Alert";
|
||||
import CreateAccessTokenDialog from "../CreateAccessTokenDialog";
|
||||
import Icon from "../Icon";
|
||||
|
||||
const listAccessTokens = async (userId: number) => {
|
||||
const { data } = await axios.get<ListUserAccessTokensResponse>(`/api/v2/users/${userId}/access_tokens`);
|
||||
return data.accessTokens;
|
||||
const { accessTokens } = await userServiceClient.listUserAccessTokens({
|
||||
id: userId,
|
||||
});
|
||||
return accessTokens;
|
||||
};
|
||||
|
||||
const AccessTokenSection = () => {
|
||||
@ -43,7 +45,10 @@ const AccessTokenSection = () => {
|
||||
content: `Are you sure to delete access token \`${getFormatedAccessToken(accessToken)}\`? You cannot undo this action.`,
|
||||
style: "danger",
|
||||
onConfirm: async () => {
|
||||
await axios.delete(`/api/v2/users/${currentUser.id}/access_tokens/${accessToken}`);
|
||||
await userServiceClient.deleteUserAccessToken({
|
||||
id: currentUser.id,
|
||||
accessToken: accessToken,
|
||||
});
|
||||
setUserAccessTokens(userAccessTokens.filter((token) => token.accessToken !== accessToken));
|
||||
},
|
||||
});
|
||||
|
@ -7,20 +7,20 @@ const WorkspaceSection: React.FC = () => {
|
||||
const [workspaceSetting, setWorkspaceSetting] = useState<WorkspaceSetting>();
|
||||
|
||||
useEffect(() => {
|
||||
getWorkspaceSetting().then(({ data }) => {
|
||||
setWorkspaceSetting(data.setting);
|
||||
getWorkspaceSetting().then(({ setting }) => {
|
||||
setWorkspaceSetting(setting);
|
||||
});
|
||||
}, []);
|
||||
|
||||
const handleDisallowSignUpChange = async (value: boolean) => {
|
||||
const { data } = await updateWorkspaceSetting(
|
||||
const { setting } = await updateWorkspaceSetting(
|
||||
{
|
||||
...workspaceSetting,
|
||||
enableSignup: value,
|
||||
} as WorkspaceSetting,
|
||||
["enable_signup"]
|
||||
);
|
||||
setWorkspaceSetting(data.setting);
|
||||
setWorkspaceSetting(setting);
|
||||
};
|
||||
|
||||
if (!workspaceSetting) return <></>;
|
||||
|
18
frontend/web/src/grpcweb.ts
Normal file
18
frontend/web/src/grpcweb.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { createChannel, createClientFactory, FetchTransport } from "nice-grpc-web";
|
||||
import { UserServiceDefinition } from "./types/proto/api/v2/user_service";
|
||||
import { WorkspaceSettingServiceDefinition } from "./types/proto/api/v2/workspace_setting_service";
|
||||
|
||||
const address = import.meta.env.MODE === "development" ? "http://localhost:8082" : window.location.origin;
|
||||
|
||||
const channel = createChannel(
|
||||
address,
|
||||
FetchTransport({
|
||||
credentials: "include",
|
||||
})
|
||||
);
|
||||
|
||||
const clientFactory = createClientFactory();
|
||||
|
||||
export const userServiceClient = clientFactory.create(UserServiceDefinition, channel);
|
||||
|
||||
export const workspaceSettingServiceClient = clientFactory.create(WorkspaceSettingServiceDefinition, channel);
|
@ -1,9 +1,6 @@
|
||||
import axios from "axios";
|
||||
import {
|
||||
GetWorkspaceSettingResponse,
|
||||
UpdateWorkspaceSettingResponse,
|
||||
WorkspaceSetting,
|
||||
} from "@/types/proto/api/v2/workspace_setting_service";
|
||||
import { userServiceClient, workspaceSettingServiceClient } from "@/grpcweb";
|
||||
import { WorkspaceSetting } from "@/types/proto/api/v2/workspace_setting_service";
|
||||
|
||||
export function getWorkspaceProfile() {
|
||||
return axios.get<WorkspaceProfile>("/api/v1/workspace/profile");
|
||||
@ -49,7 +46,7 @@ export function patchUser(userPatch: UserPatch) {
|
||||
}
|
||||
|
||||
export function deleteUser(userId: UserId) {
|
||||
return axios.delete(`/api/v2/users/${userId}`);
|
||||
return userServiceClient.deleteUser({ id: userId });
|
||||
}
|
||||
|
||||
export function getShortcutList(shortcutFind?: ShortcutFind) {
|
||||
@ -81,11 +78,11 @@ export function deleteShortcutById(shortcutId: ShortcutId) {
|
||||
}
|
||||
|
||||
export function getWorkspaceSetting() {
|
||||
return axios.get<GetWorkspaceSettingResponse>(`/api/v2/workspace/settings`);
|
||||
return workspaceSettingServiceClient.getWorkspaceSetting({});
|
||||
}
|
||||
|
||||
export function updateWorkspaceSetting(setting: WorkspaceSetting, updateMask: string[]) {
|
||||
return axios.post<UpdateWorkspaceSettingResponse>(`/api/v2/workspace/settings`, {
|
||||
return workspaceSettingServiceClient.updateWorkspaceSetting({
|
||||
setting,
|
||||
updateMask,
|
||||
});
|
||||
|
Reference in New Issue
Block a user