diff --git a/frontend/eslintrc.json b/frontend/eslintrc.json
index cdc243a37..3bd6d3171 100644
--- a/frontend/eslintrc.json
+++ b/frontend/eslintrc.json
@@ -28,9 +28,7 @@
"plugins": [
"import",
"node",
- "react",
- "jest",
- "@typescript-eslint"
+ "react"
],
"rules": {
"consistent-this": [
diff --git a/frontend/src/component/input-field/input-field.scss b/frontend/src/component/input-field/input-field.scss
index 6d2ccd555..1d2b41710 100644
--- a/frontend/src/component/input-field/input-field.scss
+++ b/frontend/src/component/input-field/input-field.scss
@@ -31,7 +31,6 @@
input {
color: var(--text-color);
- font-size: 1.2rem;
padding: 0.5rem;
border: none;
flex: 1 1 auto;
diff --git a/frontend/src/component/preferences/preferences.scss b/frontend/src/component/preferences/preferences.scss
index ffb286729..3942c9db0 100644
--- a/frontend/src/component/preferences/preferences.scss
+++ b/frontend/src/component/preferences/preferences.scss
@@ -9,6 +9,9 @@
@media (max-width:980px) {
flex-flow: row wrap;
overflow: auto;
+ > * {
+ flex-grow: 1;
+ }
}
diff --git a/frontend/src/component/server-info-view/server-info-view.tsx b/frontend/src/component/server-info-view/server-info-view.tsx
index fd35bb488..5c57113f4 100644
--- a/frontend/src/component/server-info-view/server-info-view.tsx
+++ b/frontend/src/component/server-info-view/server-info-view.tsx
@@ -1,4 +1,4 @@
-import React, {useCallback, useEffect, useMemo, useState} from "react";
+import React, {useCallback, useMemo} from "react";
import './server-info-view.scss';
import ServerConfig, {ServerInfo} from "../../model/server-config";
import {useSnackbar} from "notistack";
@@ -43,7 +43,7 @@ export default function ServerInfoView(props: ServerInfoViewProps) {
error: (err) => enqueueSnackbar("Failed to save server info!", {variant: 'error'})
});
}
- }, [services, enqueueSnackbar]);
+ }, [services, serverInfo, enqueueSnackbar]);
return
@@ -53,12 +53,12 @@ export default function ServerInfoView(props: ServerInfoViewProps) {
{
SERVER_INFO_FIELDS.map(field =>
-
+
diff --git a/frontend/src/component/tab-set/tab-set.scss b/frontend/src/component/tab-set/tab-set.scss
new file mode 100644
index 000000000..f031db307
--- /dev/null
+++ b/frontend/src/component/tab-set/tab-set.scss
@@ -0,0 +1,38 @@
+
+.tab-set {
+ display: flex;
+ flex-flow: row wrap;
+ gap: 2px;
+ background-color: var(--tabset-background-color);
+ border-bottom: 1px solid var(--tabset-border-color);
+
+ list-style-type: none;
+ padding: 0;
+ margin: 0;
+
+ &__tab {
+ cursor: pointer;
+ user-select: none;
+ box-sizing: border-box;
+ background-color: var(--tab-background-color);
+ color: var(--tab-color);
+ padding: 4px 8px;
+ border-top-left-radius: var(--border-radius);
+ border-top-right-radius: var(--border-radius);
+
+ &:active {
+ transform: scale(0.9);
+ }
+
+ &:focus, &:hover {
+ background-color: var(--tab-hover-background-color);
+ color: var(--tab-hover-color);
+ }
+
+ &-active {
+ border-bottom: 3px solid var(--tab-avtive-indicator-color);
+ background-color: var(--tab-active-background-color);
+ color: var(--tab-active-color);
+ }
+ }
+}
\ No newline at end of file
diff --git a/frontend/src/component/tab-set/tab-set.tsx b/frontend/src/component/tab-set/tab-set.tsx
new file mode 100644
index 000000000..cdee3947a
--- /dev/null
+++ b/frontend/src/component/tab-set/tab-set.tsx
@@ -0,0 +1,29 @@
+import React, {useCallback} from "react";
+
+import './tab-set.scss';
+
+export interface TabSetTab {
+ label: string;
+ key: string;
+}
+
+interface TabSetProps {
+ tabs: TabSetTab[];
+ active: string;
+ onTabChange: (key: string) => void;
+}
+
+export default function TabSet(props: TabSetProps) {
+ const {tabs, active, onTabChange} = props;
+
+ const handleTabClick = useCallback((evt: any) => {
+ const key = evt.target.dataset.key;
+ onTabChange(key);
+ }, [onTabChange]);
+
+ return
+ {tabs?.map(tab =>
+ - {tab.label}
)}
+
+
+}
\ No newline at end of file
diff --git a/frontend/src/component/user-view/user-view.scss b/frontend/src/component/user-view/user-view.scss
index d5b33079c..0de179f6e 100644
--- a/frontend/src/component/user-view/user-view.scss
+++ b/frontend/src/component/user-view/user-view.scss
@@ -120,7 +120,7 @@
display: none;
}
- @media (max-width: 750px) {
+ @media (max-width: 980px) {
&-table {
display: flex;
flex-flow: column;
@@ -140,6 +140,7 @@
&-col-label {
display: block;
+ padding: 4px;
}
&-col {
@@ -148,7 +149,8 @@
gap: 4px;
input {
- border: 1px solid var(--table-border-color);
+ border-top: 1px solid var(--table-border-color) !important;
+ border-bottom: 1px solid var(--table-border-color) !important;
}
}
}
diff --git a/frontend/src/component/user-view/user-view.tsx b/frontend/src/component/user-view/user-view.tsx
index 3acae2cee..5c5ca60a7 100644
--- a/frontend/src/component/user-view/user-view.tsx
+++ b/frontend/src/component/user-view/user-view.tsx
@@ -6,6 +6,7 @@ import TextGenerator from "../../utils/text-generator";
import {useSnackbar} from "notistack";
import {useServices} from "../../provider/service-provider";
import ConfigUtils from "../../utils/config-utils";
+import TabSet, {TabSetTab} from "../tab-set/tab-set";
interface UserViewProps {
config: ServerConfig;
@@ -17,6 +18,7 @@ export default function UserView(props: UserViewProps) {
const {enqueueSnackbar/*, closeSnackbar*/} = useSnackbar();
const [targets, setTargets] = useState
([]);
const [activeTarget, setActiveTarget] = useState(undefined);
+ const [tabs, setTabs] = useState([]);
useEffect(() => {
if (config) {
@@ -30,19 +32,15 @@ export default function UserView(props: UserViewProps) {
missing?.forEach(target => {
result.push({src: false, target: target.target, credentials: target.credentials} as any);
});
- setTargets(result || []);
- if (result?.length) {
- setActiveTarget(result[0].target);
+ const targets = result || [];
+ setTargets(targets);
+ if (targets?.length) {
+ setActiveTarget(targets[0].target);
}
+ setTabs(targets.map(target => ({key: target.target, label: target.target})));
}
}, [config])
-
- const handleTabClick = useCallback((evt: any) => {
- const target_name = evt.target.dataset.target;
- setActiveTarget(target_name);
- }, []);
-
const handleUserAdd = useCallback((evt: any) => {
const target_name = evt.target.dataset.target;
const target = targets.find(target => target.target === target_name);
@@ -129,14 +127,16 @@ export default function UserView(props: UserViewProps) {
});
}, [targets, services, enqueueSnackbar]);
+ const handleTabChange = useCallback((target: string) => {
+ setActiveTarget(target);
+ }, []);
+
return
-
- {targets?.map(target => {target.target})}
-
+
{
diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx
index b1507cb6c..28bdf192c 100755
--- a/frontend/src/index.tsx
+++ b/frontend/src/index.tsx
@@ -1,14 +1,23 @@
import React from 'react';
-import ReactDOM from 'react-dom';
+import { createRoot } from 'react-dom/client';
import './index.scss';
import App from './app/app';
import {SnackbarProvider} from 'notistack';
import {ServiceProvider} from "./provider/service-provider";
-ReactDOM.render(
-
+const container = document.getElementById('root');
+const root = createRoot(container);
+root.render(
- , document.getElementById('root'));
\ No newline at end of file
+);
+
+// ReactDOM.render(
+//
+//
+//
+//
+//
+// , document.getElementById('root'));
\ No newline at end of file
diff --git a/frontend/src/scss/_default.scss b/frontend/src/scss/_default.scss
index 06350111a..af2cef7e5 100644
--- a/frontend/src/scss/_default.scss
+++ b/frontend/src/scss/_default.scss
@@ -59,38 +59,6 @@ button {
padding: 0 4px 4px 0;
}
-.tabset {
- display: flex;
- flex-flow: row;
- gap: 2px;
- background-color: var(--tabset-background-color);
- border-bottom: 1px solid var(--tabset-border-color);
- &__tab {
- cursor: pointer;
- user-select: none;
- box-sizing: border-box;
- background-color: var(--tab-background-color);
- color: var(--tab-color);
- padding: 4px 8px;
- border-top-left-radius: var(--border-radius);
- border-top-right-radius: var(--border-radius);
-
- &:active {
- transform: scale(0.9);
- }
-
- &:focus, &:hover {
- background-color: var(--tab-hover-background-color);
- color: var(--tab-hover-color);
- }
-
- &-active {
- border-bottom: 3px solid var(--tab-avtive-indicator-color);
- background-color: var(--tab-active-background-color);
- color: var(--tab-active-color);
- }
- }
-}
input {
background-color: transparent;