feat: connect onboarding to APIs
This commit is contained in:
@@ -4,110 +4,106 @@ import dayjs from "dayjs";
|
||||
import { updateToken, resetAuthData } from "../slices/auth.data";
|
||||
import BASE_URL, { tokenHeader } from "../config";
|
||||
const whiteList = [
|
||||
"login",
|
||||
"register",
|
||||
"sendMagicLink",
|
||||
"checkInviteTokenValid",
|
||||
"getGoogleAuthConfig",
|
||||
"getGithubAuthConfig",
|
||||
"getSMTPStatus",
|
||||
"getLoginConfig",
|
||||
"getServerVersion",
|
||||
"getServer",
|
||||
"getOpenid",
|
||||
"getMetamaskNonce",
|
||||
"renew",
|
||||
"login",
|
||||
"register",
|
||||
"sendMagicLink",
|
||||
"checkInviteTokenValid",
|
||||
"getGoogleAuthConfig",
|
||||
"getGithubAuthConfig",
|
||||
"getSMTPStatus",
|
||||
"getLoginConfig",
|
||||
"getServerVersion",
|
||||
"getServer",
|
||||
"getOpenid",
|
||||
"getMetamaskNonce",
|
||||
"renew",
|
||||
"getInitialized",
|
||||
"createAdmin",
|
||||
"updateLoginConfig"
|
||||
];
|
||||
const baseQuery = fetchBaseQuery({
|
||||
baseUrl: BASE_URL,
|
||||
prepareHeaders: (headers, { getState, endpoint }) => {
|
||||
console.log("req", endpoint);
|
||||
const { token } = getState().authData;
|
||||
if (token && !whiteList.includes(endpoint)) {
|
||||
headers.set(tokenHeader, token);
|
||||
}
|
||||
return headers;
|
||||
},
|
||||
baseUrl: BASE_URL,
|
||||
prepareHeaders: (headers, { getState, endpoint }) => {
|
||||
console.log("req", endpoint);
|
||||
const { token } = getState().authData;
|
||||
if (token && !whiteList.includes(endpoint)) {
|
||||
headers.set(tokenHeader, token);
|
||||
}
|
||||
return headers;
|
||||
}
|
||||
});
|
||||
let waitingForRenew = null;
|
||||
const baseQueryWithTokenCheck = async (args, api, extraOptions) => {
|
||||
if (waitingForRenew) {
|
||||
await waitingForRenew;
|
||||
}
|
||||
// 先检查token是否过期,过期则renew
|
||||
const {
|
||||
token,
|
||||
refreshToken,
|
||||
expireTime = new Date().getTime(),
|
||||
} = api.getState().authData;
|
||||
let result = null;
|
||||
if (
|
||||
!whiteList.includes(api.endpoint) &&
|
||||
dayjs().isAfter(new Date(expireTime - 20 * 1000))
|
||||
) {
|
||||
// 快过期了,renew
|
||||
waitingForRenew = baseQuery(
|
||||
{
|
||||
url: "/token/renew",
|
||||
method: "POST",
|
||||
body: {
|
||||
token,
|
||||
refresh_token: refreshToken,
|
||||
},
|
||||
},
|
||||
api,
|
||||
extraOptions
|
||||
);
|
||||
result = await waitingForRenew;
|
||||
waitingForRenew = null;
|
||||
if (result.data) {
|
||||
// store the new token
|
||||
api.dispatch(updateToken(result.data));
|
||||
// retry the initial query
|
||||
result = await baseQuery(args, api, extraOptions);
|
||||
if (waitingForRenew) {
|
||||
await waitingForRenew;
|
||||
}
|
||||
// 先检查token是否过期,过期则renew
|
||||
const { token, refreshToken, expireTime = new Date().getTime() } = api.getState().authData;
|
||||
let result = null;
|
||||
if (!whiteList.includes(api.endpoint) && dayjs().isAfter(new Date(expireTime - 20 * 1000))) {
|
||||
// 快过期了,renew
|
||||
waitingForRenew = baseQuery(
|
||||
{
|
||||
url: "/token/renew",
|
||||
method: "POST",
|
||||
body: {
|
||||
token,
|
||||
refresh_token: refreshToken
|
||||
}
|
||||
} else {
|
||||
result = await baseQuery(args, api, extraOptions);
|
||||
},
|
||||
api,
|
||||
extraOptions
|
||||
);
|
||||
result = await waitingForRenew;
|
||||
waitingForRenew = null;
|
||||
if (result.data) {
|
||||
// store the new token
|
||||
api.dispatch(updateToken(result.data));
|
||||
// retry the initial query
|
||||
result = await baseQuery(args, api, extraOptions);
|
||||
}
|
||||
if (result?.error) {
|
||||
console.log("api error", result.error, api.endpoint);
|
||||
switch (result.error.originalStatus || result.error.status) {
|
||||
case "FETCH_ERROR":
|
||||
{
|
||||
toast.error(`${api.endpoint}: Failed to fetch`);
|
||||
}
|
||||
break;
|
||||
case 404:
|
||||
{
|
||||
toast.error("Request Not Found");
|
||||
}
|
||||
break;
|
||||
case 500:
|
||||
{
|
||||
toast.error(result.error.data || "server error");
|
||||
}
|
||||
break;
|
||||
case 401:
|
||||
{
|
||||
if (api.endpoint !== "login") {
|
||||
api.dispatch(resetAuthData());
|
||||
location.href = "/#/login";
|
||||
toast.error("API Not Authenticated");
|
||||
}
|
||||
// toast.error("token expired, please login again");
|
||||
// } else {
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
break;
|
||||
case 403:
|
||||
toast.error("Request Not Allowed");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
} else {
|
||||
result = await baseQuery(args, api, extraOptions);
|
||||
}
|
||||
if (result?.error) {
|
||||
console.log("api error", result.error, api.endpoint);
|
||||
switch (result.error.originalStatus || result.error.status) {
|
||||
case "FETCH_ERROR":
|
||||
{
|
||||
toast.error(`${api.endpoint}: Failed to fetch`);
|
||||
}
|
||||
break;
|
||||
case 404:
|
||||
{
|
||||
toast.error("Request Not Found");
|
||||
}
|
||||
break;
|
||||
case 500:
|
||||
{
|
||||
toast.error(result.error.data || "server error");
|
||||
}
|
||||
break;
|
||||
case 401:
|
||||
{
|
||||
if (api.endpoint !== "login") {
|
||||
api.dispatch(resetAuthData());
|
||||
location.href = "/#/login";
|
||||
toast.error("API Not Authenticated");
|
||||
}
|
||||
// toast.error("token expired, please login again");
|
||||
// } else {
|
||||
// return;
|
||||
// }
|
||||
}
|
||||
break;
|
||||
case 403:
|
||||
toast.error("Request Not Allowed");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
export default baseQueryWithTokenCheck;
|
||||
|
||||
+210
-196
@@ -4,204 +4,218 @@ import { updateInfo } from "../slices/server";
|
||||
import baseQuery from "./base.query";
|
||||
const defaultExpireDuration = 7 * 24 * 60 * 60;
|
||||
export const serverApi = createApi({
|
||||
reducerPath: "serverApi",
|
||||
baseQuery,
|
||||
endpoints: (builder) => ({
|
||||
getServer: builder.query({
|
||||
query: () => ({ url: `admin/system/organization` }),
|
||||
transformResponse: (data) => {
|
||||
data.logo = `${BASE_URL}/resource/organization/logo?t=${new Date().getTime()}`;
|
||||
return data;
|
||||
},
|
||||
async onQueryStarted(data, { dispatch, queryFulfilled }) {
|
||||
try {
|
||||
const { data: server } = await queryFulfilled;
|
||||
dispatch(updateInfo(server));
|
||||
} catch {
|
||||
console.log("get server info error");
|
||||
}
|
||||
},
|
||||
}),
|
||||
getThirdPartySecret: builder.query({
|
||||
query: () => ({
|
||||
// headers: {
|
||||
// "content-type": "text/plain",
|
||||
// accept: "text/plain",
|
||||
// },
|
||||
url: `/admin/system/third_party_secret`,
|
||||
responseHandler: (response) => response.text(),
|
||||
}),
|
||||
keepUnusedDataFor: 0,
|
||||
}),
|
||||
updateThirdPartySecret: builder.mutation({
|
||||
query: () => ({
|
||||
url: `/admin/system/third_party_secret`,
|
||||
method: "POST",
|
||||
responseHandler: (response) => response.text(),
|
||||
}),
|
||||
}),
|
||||
getMetrics: builder.query({
|
||||
query: () => ({ url: `/admin/system/metrics` }),
|
||||
}),
|
||||
getServerVersion: builder.query({
|
||||
query: () => ({
|
||||
headers: {
|
||||
// "content-type": "text/plain",
|
||||
accept: "text/plain",
|
||||
},
|
||||
url: `/admin/system/version`,
|
||||
responseHandler: (response) => response.text(),
|
||||
}),
|
||||
}),
|
||||
getFirebaseConfig: builder.query({
|
||||
query: () => ({ url: `admin/fcm/config` }),
|
||||
}),
|
||||
getGoogleAuthConfig: builder.query({
|
||||
query: () => ({ url: `admin/google_auth/config` }),
|
||||
}),
|
||||
updateGoogleAuthConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/google_auth/config`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
}),
|
||||
getGithubAuthConfig: builder.query({
|
||||
query: () => ({ url: `admin/github_auth/config` }),
|
||||
}),
|
||||
updateGithubAuthConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/github_auth/config`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
}),
|
||||
sendTestEmail: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `/admin/system/send_mail`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
}),
|
||||
updateFirebaseConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/fcm/config`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
}),
|
||||
getAgoraConfig: builder.query({
|
||||
query: () => ({ url: `admin/agora/config` }),
|
||||
}),
|
||||
updateAgoraConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/agora/config`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
}),
|
||||
getSMTPConfig: builder.query({
|
||||
query: () => ({ url: `admin/smtp/config` }),
|
||||
}),
|
||||
getSMTPStatus: builder.query({
|
||||
query: () => ({ url: `/admin/smtp/enabled` }),
|
||||
}),
|
||||
updateSMTPConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/smtp/config`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
}),
|
||||
getLoginConfig: builder.query({
|
||||
query: () => ({ url: `admin/login/config` }),
|
||||
}),
|
||||
updateLoginConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/login/config`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
}),
|
||||
updateLogo: builder.mutation({
|
||||
query: (data) => ({
|
||||
headers: {
|
||||
"content-type": "image/png",
|
||||
},
|
||||
url: `admin/system/organization/logo`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
async onQueryStarted(data, { dispatch, queryFulfilled }) {
|
||||
try {
|
||||
await queryFulfilled;
|
||||
dispatch(
|
||||
updateInfo({
|
||||
logo: `${BASE_URL}/resource/organization/logo?t=${new Date().getTime()}`,
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
console.log("update server logo error");
|
||||
}
|
||||
},
|
||||
}),
|
||||
createInviteLink: builder.query({
|
||||
query: (expired_in = defaultExpireDuration) => ({
|
||||
headers: {
|
||||
"content-type": "text/plain",
|
||||
accept: "text/plain",
|
||||
},
|
||||
url: `/admin/system/create_invite_link?expired_in=${expired_in}`,
|
||||
responseHandler: (response) => response.text(),
|
||||
}),
|
||||
transformResponse: (link) => {
|
||||
// 替换掉域名
|
||||
const invite = new URL(link);
|
||||
return `${location.origin}${invite.pathname}${invite.search}${invite.hash}`;
|
||||
},
|
||||
}),
|
||||
updateServer: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/system/organization`,
|
||||
method: "POST",
|
||||
body: data,
|
||||
}),
|
||||
async onQueryStarted(data, { dispatch, queryFulfilled, getState }) {
|
||||
const { name: prevName, description: prevDesc } = getState().server;
|
||||
dispatch(updateInfo(data));
|
||||
try {
|
||||
await queryFulfilled;
|
||||
} catch {
|
||||
dispatch(updateInfo({ name: prevName, description: prevDesc }));
|
||||
}
|
||||
},
|
||||
}),
|
||||
reducerPath: "serverApi",
|
||||
baseQuery,
|
||||
endpoints: (builder) => ({
|
||||
getServer: builder.query({
|
||||
query: () => ({ url: `admin/system/organization` }),
|
||||
transformResponse: (data) => {
|
||||
data.logo = `${BASE_URL}/resource/organization/logo?t=${new Date().getTime()}`;
|
||||
return data;
|
||||
},
|
||||
async onQueryStarted(data, { dispatch, queryFulfilled }) {
|
||||
try {
|
||||
const { data: server } = await queryFulfilled;
|
||||
dispatch(updateInfo(server));
|
||||
} catch {
|
||||
console.log("get server info error");
|
||||
}
|
||||
}
|
||||
}),
|
||||
getThirdPartySecret: builder.query({
|
||||
query: () => ({
|
||||
// headers: {
|
||||
// "content-type": "text/plain",
|
||||
// accept: "text/plain",
|
||||
// },
|
||||
url: `/admin/system/third_party_secret`,
|
||||
responseHandler: (response) => response.text()
|
||||
}),
|
||||
keepUnusedDataFor: 0
|
||||
}),
|
||||
updateThirdPartySecret: builder.mutation({
|
||||
query: () => ({
|
||||
url: `/admin/system/third_party_secret`,
|
||||
method: "POST",
|
||||
responseHandler: (response) => response.text()
|
||||
})
|
||||
}),
|
||||
getMetrics: builder.query({
|
||||
query: () => ({ url: `/admin/system/metrics` })
|
||||
}),
|
||||
getServerVersion: builder.query({
|
||||
query: () => ({
|
||||
headers: {
|
||||
// "content-type": "text/plain",
|
||||
accept: "text/plain"
|
||||
},
|
||||
url: `/admin/system/version`,
|
||||
responseHandler: (response) => response.text()
|
||||
})
|
||||
}),
|
||||
getFirebaseConfig: builder.query({
|
||||
query: () => ({ url: `admin/fcm/config` })
|
||||
}),
|
||||
getGoogleAuthConfig: builder.query({
|
||||
query: () => ({ url: `admin/google_auth/config` })
|
||||
}),
|
||||
updateGoogleAuthConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/google_auth/config`,
|
||||
method: "POST",
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
getGithubAuthConfig: builder.query({
|
||||
query: () => ({ url: `admin/github_auth/config` })
|
||||
}),
|
||||
updateGithubAuthConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/github_auth/config`,
|
||||
method: "POST",
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
sendTestEmail: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `/admin/system/send_mail`,
|
||||
method: "POST",
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
updateFirebaseConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/fcm/config`,
|
||||
method: "POST",
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
getAgoraConfig: builder.query({
|
||||
query: () => ({ url: `admin/agora/config` })
|
||||
}),
|
||||
updateAgoraConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/agora/config`,
|
||||
method: "POST",
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
getSMTPConfig: builder.query({
|
||||
query: () => ({ url: `admin/smtp/config` })
|
||||
}),
|
||||
getSMTPStatus: builder.query({
|
||||
query: () => ({ url: `/admin/smtp/enabled` })
|
||||
}),
|
||||
updateSMTPConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/smtp/config`,
|
||||
method: "POST",
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
getLoginConfig: builder.query({
|
||||
query: () => ({ url: `admin/login/config` })
|
||||
}),
|
||||
updateLoginConfig: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/login/config`,
|
||||
method: "POST",
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
updateLogo: builder.mutation({
|
||||
query: (data) => ({
|
||||
headers: {
|
||||
"content-type": "image/png"
|
||||
},
|
||||
url: `admin/system/organization/logo`,
|
||||
method: "POST",
|
||||
body: data
|
||||
}),
|
||||
async onQueryStarted(data, { dispatch, queryFulfilled }) {
|
||||
try {
|
||||
await queryFulfilled;
|
||||
dispatch(
|
||||
updateInfo({
|
||||
logo: `${BASE_URL}/resource/organization/logo?t=${new Date().getTime()}`
|
||||
})
|
||||
);
|
||||
} catch {
|
||||
console.log("update server logo error");
|
||||
}
|
||||
}
|
||||
}),
|
||||
createInviteLink: builder.query({
|
||||
query: (expired_in = defaultExpireDuration) => ({
|
||||
headers: {
|
||||
"content-type": "text/plain",
|
||||
accept: "text/plain"
|
||||
},
|
||||
url: `/admin/system/create_invite_link?expired_in=${expired_in}`,
|
||||
responseHandler: (response) => response.text()
|
||||
}),
|
||||
transformResponse: (link) => {
|
||||
// 替换掉域名
|
||||
const invite = new URL(link);
|
||||
return `${location.origin}${invite.pathname}${invite.search}${invite.hash}`;
|
||||
}
|
||||
}),
|
||||
updateServer: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `admin/system/organization`,
|
||||
method: "POST",
|
||||
body: data
|
||||
}),
|
||||
async onQueryStarted(data, { dispatch, queryFulfilled, getState }) {
|
||||
const { name: prevName, description: prevDesc } = getState().server;
|
||||
dispatch(updateInfo(data));
|
||||
try {
|
||||
await queryFulfilled;
|
||||
} catch {
|
||||
dispatch(updateInfo({ name: prevName, description: prevDesc }));
|
||||
}
|
||||
}
|
||||
}),
|
||||
createAdmin: builder.mutation({
|
||||
query: (data) => ({
|
||||
url: `/admin/system/createAdmin`,
|
||||
method: "POST",
|
||||
body: data
|
||||
})
|
||||
}),
|
||||
getInitialized: builder.query({
|
||||
query: () => ({
|
||||
url: `/admin/system/initialized`
|
||||
})
|
||||
})
|
||||
})
|
||||
});
|
||||
|
||||
export const {
|
||||
useGetServerVersionQuery,
|
||||
useGetGithubAuthConfigQuery,
|
||||
useUpdateGithubAuthConfigMutation,
|
||||
useGetGoogleAuthConfigQuery,
|
||||
useUpdateGoogleAuthConfigMutation,
|
||||
useGetSMTPStatusQuery,
|
||||
useSendTestEmailMutation,
|
||||
useUpdateFirebaseConfigMutation,
|
||||
useGetFirebaseConfigQuery,
|
||||
useGetLoginConfigQuery,
|
||||
useUpdateLoginConfigMutation,
|
||||
useGetSMTPConfigQuery,
|
||||
useUpdateSMTPConfigMutation,
|
||||
useGetAgoraConfigQuery,
|
||||
useUpdateAgoraConfigMutation,
|
||||
useGetServerQuery,
|
||||
useGetMetricsQuery,
|
||||
useLazyGetServerQuery,
|
||||
useUpdateServerMutation,
|
||||
useUpdateLogoMutation,
|
||||
useCreateInviteLinkQuery,
|
||||
useLazyCreateInviteLinkQuery,
|
||||
useGetThirdPartySecretQuery,
|
||||
useUpdateThirdPartySecretMutation,
|
||||
useGetServerVersionQuery,
|
||||
useGetGithubAuthConfigQuery,
|
||||
useUpdateGithubAuthConfigMutation,
|
||||
useGetGoogleAuthConfigQuery,
|
||||
useUpdateGoogleAuthConfigMutation,
|
||||
useGetSMTPStatusQuery,
|
||||
useSendTestEmailMutation,
|
||||
useUpdateFirebaseConfigMutation,
|
||||
useGetFirebaseConfigQuery,
|
||||
useGetLoginConfigQuery,
|
||||
useUpdateLoginConfigMutation,
|
||||
useGetSMTPConfigQuery,
|
||||
useUpdateSMTPConfigMutation,
|
||||
useGetAgoraConfigQuery,
|
||||
useUpdateAgoraConfigMutation,
|
||||
useGetServerQuery,
|
||||
useGetMetricsQuery,
|
||||
useLazyGetServerQuery,
|
||||
useUpdateServerMutation,
|
||||
useUpdateLogoMutation,
|
||||
useCreateInviteLinkQuery,
|
||||
useLazyCreateInviteLinkQuery,
|
||||
useGetThirdPartySecretQuery,
|
||||
useUpdateThirdPartySecretMutation,
|
||||
useCreateAdminMutation,
|
||||
useGetInitializedQuery
|
||||
} = serverApi;
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
import { Navigate } from "react-router-dom";
|
||||
import { useGetInitializedQuery } from "../../app/services/server";
|
||||
|
||||
export default function RequireInitialized({ children, redirectTo = "/" }) {
|
||||
const { data } = useGetInitializedQuery();
|
||||
console.log("initialized?", data);
|
||||
return data === false ? <Navigate to={redirectTo} replace /> : children;
|
||||
}
|
||||
+11
-6
@@ -24,6 +24,7 @@ import SettingChannelPage from "./settingChannel";
|
||||
import OnboardingPage from "./onboarding";
|
||||
import toast from "react-hot-toast";
|
||||
import ResourceManagement from "./resources";
|
||||
import RequireInitialized from "../common/component/RequireInitialized";
|
||||
|
||||
const PageRoutes = () => {
|
||||
const {
|
||||
@@ -49,9 +50,11 @@ const PageRoutes = () => {
|
||||
<Route
|
||||
path="/login"
|
||||
element={
|
||||
<RequireNoAuth>
|
||||
<LoginPage />
|
||||
</RequireNoAuth>
|
||||
<RequireInitialized>
|
||||
<RequireNoAuth>
|
||||
<LoginPage />
|
||||
</RequireNoAuth>
|
||||
</RequireInitialized>
|
||||
}
|
||||
/>
|
||||
<Route
|
||||
@@ -89,9 +92,11 @@ const PageRoutes = () => {
|
||||
<Route
|
||||
path="/"
|
||||
element={
|
||||
<RequireAuth>
|
||||
<HomePage />
|
||||
</RequireAuth>
|
||||
<RequireInitialized>
|
||||
<RequireAuth>
|
||||
<HomePage />
|
||||
</RequireAuth>
|
||||
</RequireInitialized>
|
||||
}
|
||||
>
|
||||
<Route path="setting">
|
||||
|
||||
@@ -11,11 +11,7 @@ import StyledOnboardingPage from "./styled";
|
||||
export default function OnboardingPage() {
|
||||
const [step, setStep] = useState(0);
|
||||
const [data, setData] = useState({
|
||||
spaceName: "",
|
||||
adminEmail: "",
|
||||
adminPassword: "",
|
||||
adminPassword2: "",
|
||||
inviteRule: null
|
||||
spaceName: ""
|
||||
});
|
||||
const props = { step, setStep, data, setData };
|
||||
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import styled from "styled-components";
|
||||
import toast from "react-hot-toast";
|
||||
import StyledInput from "../../../common/component/styled/Input";
|
||||
import StyledButton from "../../../common/component/styled/Button";
|
||||
import toast from "react-hot-toast";
|
||||
import { useCreateAdminMutation } from "../../../app/services/server";
|
||||
import { useLoginMutation } from "../../../app/services/auth";
|
||||
|
||||
const StyledAdminCredentialsStep = styled.div`
|
||||
height: 100%;
|
||||
@@ -19,7 +22,34 @@ const StyledAdminCredentialsStep = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export default function AdminCredentialsStep({ step, setStep, data, setData }) {
|
||||
export default function AdminCredentialsStep({ step, setStep }) {
|
||||
const [
|
||||
createAdmin,
|
||||
{ isLoading: isSignUpLoading, isSuccess: isSignUpSuccess, error: signUpError }
|
||||
] = useCreateAdminMutation();
|
||||
const [login, { isLoading: isLoginLoading, isSuccess: isLoginSuccess, error: loginError }] =
|
||||
useLoginMutation();
|
||||
|
||||
const [email, setEmail] = useState("");
|
||||
const [password, setPassword] = useState("");
|
||||
const [confirm, setConfirm] = useState("");
|
||||
|
||||
// Display error
|
||||
useEffect(() => {
|
||||
if (signUpError === undefined) return;
|
||||
toast.error(`Failed to sign up: ${signUpError.data}`);
|
||||
}, [signUpError]);
|
||||
|
||||
useEffect(() => {
|
||||
if (loginError === undefined) return;
|
||||
toast.error(`Login failed: ${loginError.data}`);
|
||||
}, [loginError]);
|
||||
|
||||
// Increment `step` when both signing up and logging in have completed
|
||||
useEffect(() => {
|
||||
if (isSignUpSuccess && isLoginSuccess) setStep(step + 1);
|
||||
}, [isSignUpSuccess, isLoginSuccess]);
|
||||
|
||||
return (
|
||||
<StyledAdminCredentialsStep>
|
||||
<span className="primaryText">Now let’s set up your admin account</span>
|
||||
@@ -27,56 +57,51 @@ export default function AdminCredentialsStep({ step, setStep, data, setData }) {
|
||||
<StyledInput
|
||||
className="input"
|
||||
placeholder="Enter your email"
|
||||
value={data.adminEmail}
|
||||
onChange={(e) =>
|
||||
setData({
|
||||
...data,
|
||||
adminEmail: e.target.value
|
||||
})
|
||||
}
|
||||
value={email}
|
||||
onChange={(e) => setEmail(e.target.value)}
|
||||
/>
|
||||
<StyledInput
|
||||
className="input"
|
||||
type="password"
|
||||
placeholder="Enter your password"
|
||||
value={data.adminPassword}
|
||||
onChange={(e) =>
|
||||
setData({
|
||||
...data,
|
||||
adminPassword: e.target.value
|
||||
})
|
||||
}
|
||||
value={password}
|
||||
onChange={(e) => setPassword(e.target.value)}
|
||||
/>
|
||||
<StyledInput
|
||||
className="input"
|
||||
type="password"
|
||||
placeholder="Confirm your password"
|
||||
value={data.adminPassword2}
|
||||
onChange={(e) =>
|
||||
setData({
|
||||
...data,
|
||||
adminPassword2: e.target.value
|
||||
})
|
||||
}
|
||||
value={confirm}
|
||||
onChange={(e) => setConfirm(e.target.value)}
|
||||
/>
|
||||
<StyledButton
|
||||
className="button"
|
||||
onClick={() => {
|
||||
onClick={async () => {
|
||||
// Verification for admin credentials
|
||||
if (data.adminEmail === "") {
|
||||
if (email === "") {
|
||||
toast.error("Please enter admin email!");
|
||||
return;
|
||||
} else if (data.adminPassword === "") {
|
||||
} else if (password === "") {
|
||||
toast.error("Please enter admin password!");
|
||||
return;
|
||||
} else if (data.adminPassword !== data.adminPassword2) {
|
||||
} else if (password !== confirm) {
|
||||
toast.error("Two passwords do not match!");
|
||||
return;
|
||||
}
|
||||
setStep(step + 1);
|
||||
await createAdmin({
|
||||
email,
|
||||
name: "Admin",
|
||||
password,
|
||||
gender: 0
|
||||
});
|
||||
await login({
|
||||
email,
|
||||
password,
|
||||
type: "password"
|
||||
});
|
||||
}}
|
||||
>
|
||||
Sign Up
|
||||
{!(isSignUpLoading || isLoginLoading) ? "Sign Up" : "..."}
|
||||
</StyledButton>
|
||||
</StyledAdminCredentialsStep>
|
||||
);
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import toast from "react-hot-toast";
|
||||
import styled from "styled-components";
|
||||
import StyledRadio from "../../../common/component/styled/Radio";
|
||||
import StyledButton from "../../../common/component/styled/Button";
|
||||
import { useGetLoginConfigQuery, useUpdateLoginConfigMutation } from "../../../app/services/server";
|
||||
|
||||
const StyledInviteRuleStep = styled.div`
|
||||
height: 100%;
|
||||
@@ -14,22 +17,39 @@ const StyledInviteRuleStep = styled.div`
|
||||
}
|
||||
`;
|
||||
|
||||
export default function InviteRuleStep({ step, setStep, data, setData }) {
|
||||
export default function InviteRuleStep({ step, setStep }) {
|
||||
const { data: loginConfig } = useGetLoginConfigQuery();
|
||||
const [updateLoginConfig, { isSuccess, error }] = useUpdateLoginConfigMutation();
|
||||
|
||||
const [value, setValue] = useState(null);
|
||||
|
||||
// Display error
|
||||
useEffect(() => {
|
||||
if (error === undefined) return;
|
||||
toast.error(`Failed to update invitation rule: ${error.data}`);
|
||||
}, [error]);
|
||||
|
||||
// Increment `step` when updating has completed
|
||||
useEffect(() => {
|
||||
if (isSuccess) setStep(step + 1);
|
||||
}, [isSuccess]);
|
||||
|
||||
return (
|
||||
<StyledInviteRuleStep>
|
||||
<span className="primaryText">Last step: invite others!</span>
|
||||
<span className="secondaryText">Firstly, who can sign up to this server?</span>
|
||||
<StyledRadio
|
||||
options={["Everyone", "Invitation link only"]}
|
||||
value={data.inviteRule}
|
||||
value={value}
|
||||
onChange={(v) => {
|
||||
setData({
|
||||
...data,
|
||||
inviteRule: v
|
||||
});
|
||||
setTimeout(() => {
|
||||
setStep(step + 1);
|
||||
}, 750);
|
||||
setValue(v);
|
||||
if (loginConfig !== undefined) {
|
||||
const whoCanSignUp = ["EveryOne", "InvitationOnly"][v];
|
||||
updateLoginConfig({
|
||||
...loginConfig,
|
||||
who_can_sign_up: whoCanSignUp
|
||||
});
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<StyledButton className="button border_less ghost" onClick={() => setStep(step + 1)}>
|
||||
|
||||
Reference in New Issue
Block a user