Skip to content

Commit 61a9290

Browse files
committed
Notification toasts, nicer loading, add new user support
1 parent fadec97 commit 61a9290

File tree

31 files changed

+399
-213
lines changed

31 files changed

+399
-213
lines changed

backend/internal/token.js

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -134,24 +134,24 @@ export default {
134134
* @param {Object} user
135135
* @returns {Promise}
136136
*/
137-
getTokenFromUser: (user) => {
137+
getTokenFromUser: async (user) => {
138138
const expire = "1d";
139139
const Token = new TokenModel();
140140
const expiry = parseDatePeriod(expire);
141141

142-
return Token.create({
142+
const signed = await Token.create({
143143
iss: "api",
144144
attrs: {
145145
id: user.id,
146146
},
147147
scope: ["user"],
148148
expiresIn: expire,
149-
}).then((signed) => {
150-
return {
151-
token: signed.token,
152-
expires: expiry.toISOString(),
153-
user: user,
154-
};
155149
});
150+
151+
return {
152+
token: signed.token,
153+
expires: expiry.toISOString(),
154+
user: user,
155+
};
156156
},
157157
};

backend/internal/user.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -337,11 +337,11 @@ const internalUser = {
337337
* @param {Integer} [id_requested]
338338
* @returns {[String]}
339339
*/
340-
getUserOmisionsByAccess: (access, id_requested) => {
340+
getUserOmisionsByAccess: (access, idRequested) => {
341341
let response = []; // Admin response
342342

343-
if (!access.token.hasScope("admin") && access.token.getUserId(0) !== id_requested) {
344-
response = ["roles", "is_deleted"]; // Restricted response
343+
if (!access.token.hasScope("admin") && access.token.getUserId(0) !== idRequested) {
344+
response = ["is_deleted"]; // Restricted response
345345
}
346346

347347
return response;

backend/models/token.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,16 +123,16 @@ export default () => {
123123
},
124124

125125
/**
126-
* @param [default_value]
126+
* @param [defaultValue]
127127
* @returns {Integer}
128128
*/
129-
getUserId: (default_value) => {
129+
getUserId: (defaultValue) => {
130130
const attrs = self.get("attrs");
131131
if (attrs && typeof attrs.id !== "undefined" && attrs.id) {
132132
return attrs.id;
133133
}
134134

135-
return default_value || 0;
135+
return defaultValue || 0;
136136
},
137137
};
138138

frontend/src/App.css

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,10 @@
55
.domain-name {
66
font-family: monospace;
77
}
8+
9+
.mr-1 {
10+
margin-right: 0.25rem;
11+
}
12+
.ml-1 {
13+
margin-left: 0.25rem;
14+
}

frontend/src/App.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
22
import { ReactQueryDevtools } from "@tanstack/react-query-devtools";
33
import { RawIntlProvider } from "react-intl";
4+
import { ToastContainer } from "react-toastify";
45
import { AuthProvider, LocaleProvider, ThemeProvider } from "src/context";
56
import { intl } from "src/locale";
67
import Router from "src/Router.tsx";
@@ -16,6 +17,15 @@ function App() {
1617
<QueryClientProvider client={queryClient}>
1718
<AuthProvider>
1819
<Router />
20+
<ToastContainer
21+
position="top-right"
22+
autoClose={5000}
23+
hideProgressBar={true}
24+
newestOnTop={true}
25+
closeOnClick={true}
26+
rtl={false}
27+
closeButton={false}
28+
/>
1929
</AuthProvider>
2030
<ReactQueryDevtools buttonPosition="bottom-right" position="right" />
2131
</QueryClientProvider>

frontend/src/api/backend/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export * from "./createDeadHost";
44
export * from "./createProxyHost";
55
export * from "./createRedirectionHost";
66
export * from "./createStream";
7+
export * from "./createUser";
78
export * from "./deleteAccessList";
89
export * from "./deleteCertificate";
910
export * from "./deleteDeadHost";

frontend/src/components/HasPermission.tsx

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { ReactNode } from "react";
22
import Alert from "react-bootstrap/Alert";
3+
import { Loading, LoadingPage } from "src/components";
34
import { useUser } from "src/hooks";
45
import { intl } from "src/locale";
56

@@ -8,11 +9,30 @@ interface Props {
89
type: "manage" | "view";
910
hideError?: boolean;
1011
children?: ReactNode;
12+
pageLoading?: boolean;
13+
loadingNoLogo?: boolean;
1114
}
12-
function HasPermission({ permission, type, children, hideError = false }: Props) {
13-
const { data } = useUser("me");
15+
function HasPermission({
16+
permission,
17+
type,
18+
children,
19+
hideError = false,
20+
pageLoading = false,
21+
loadingNoLogo = false,
22+
}: Props) {
23+
const { data, isLoading } = useUser("me");
1424
const perms = data?.permissions;
1525

26+
if (isLoading) {
27+
if (hideError) {
28+
return null;
29+
}
30+
if (pageLoading) {
31+
return <LoadingPage noLogo={loadingNoLogo} />;
32+
}
33+
return <Loading noLogo={loadingNoLogo} />;
34+
}
35+
1636
let allowed = permission === "";
1737
const acceptable = ["manage", type];
1838

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { intl } from "src/locale";
2+
import styles from "./Loading.module.css";
3+
4+
interface Props {
5+
label?: string;
6+
noLogo?: boolean;
7+
}
8+
export function Loading({ label, noLogo }: Props) {
9+
return (
10+
<div className="empty text-center">
11+
{noLogo ? null : (
12+
<div className="mb-3">
13+
<img className={styles.logo} src="/images/logo-no-text.svg" alt="" />
14+
</div>
15+
)}
16+
<div className="text-secondary mb-3">{label || intl.formatMessage({ id: "loading" })}</div>
17+
<div className="progress progress-sm">
18+
<div className="progress-bar progress-bar-indeterminate" />
19+
</div>
20+
</div>
21+
);
22+
}

frontend/src/components/LoadingPage.tsx

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
import { Page } from "src/components";
2-
import { intl } from "src/locale";
3-
import styles from "./LoadingPage.module.css";
1+
import { Loading, Page } from "src/components";
42

53
interface Props {
64
label?: string;
@@ -10,17 +8,7 @@ export function LoadingPage({ label, noLogo }: Props) {
108
return (
119
<Page className="page-center">
1210
<div className="container-tight py-4">
13-
<div className="empty text-center">
14-
{noLogo ? null : (
15-
<div className="mb-3">
16-
<img className={styles.logo} src="/images/logo-no-text.svg" alt="" />
17-
</div>
18-
)}
19-
<div className="text-secondary mb-3">{label || intl.formatMessage({ id: "loading" })}</div>
20-
<div className="progress progress-sm">
21-
<div className="progress-bar progress-bar-indeterminate" />
22-
</div>
23-
</div>
11+
<Loading label={label} noLogo={noLogo} />
2412
</div>
2513
</Page>
2614
);

0 commit comments

Comments
 (0)