Fixed web-ui problems

This commit is contained in:
euzu
2023-11-01 09:51:36 +01:00
parent f5e79607c0
commit df16677e7c
10 changed files with 104 additions and 58 deletions
+1 -3
View File
@@ -28,9 +28,7 @@
"plugins": [
"import",
"node",
"react",
"jest",
"@typescript-eslint"
"react"
],
"rules": {
"consistent-this": [
@@ -31,7 +31,6 @@
input {
color: var(--text-color);
font-size: 1.2rem;
padding: 0.5rem;
border: none;
flex: 1 1 auto;
@@ -9,6 +9,9 @@
@media (max-width:980px) {
flex-flow: row wrap;
overflow: auto;
> * {
flex-grow: 1;
}
}
@@ -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 <div className={'server-info'}>
<div className={'server-info__toolbar'}><label>Server</label>
@@ -53,12 +53,12 @@ export default function ServerInfoView(props: ServerInfoViewProps) {
<div className={'server-info__content-table'}>
{
SERVER_INFO_FIELDS.map(field =>
<div className={'server-info__content-row'}>
<div key={'server_info_field_' + field.name} className={'server-info__content-row'}>
<div className={'server-info__content-col'}>
<label>{field.caption}</label>
</div>
<div className={'server-info__content-table-col'}>
<input value={(serverInfo as any)?.[field.name]} data-field={field.name}
<input defaultValue={(serverInfo as any)?.[field.name]} data-field={field.name}
onChange={handleValueChange}></input>
</div>
</div>
@@ -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);
}
}
}
@@ -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 <ul className={'tab-set'}>
{tabs?.map(tab =>
<li className={'tab-set__tab' + (tab.key === active ? ' tab-set__tab-active' : '')} key={'tab_' + tab.key} data-key={tab.key} onClick={handleTabClick}>{tab.label}</li>)}
</ul>
}
@@ -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;
}
}
}
+12 -12
View File
@@ -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<TargetUser[]>([]);
const [activeTarget, setActiveTarget] = useState<string>(undefined);
const [tabs, setTabs] = useState<TabSetTab[]>([]);
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 <div className={'user'}>
<div className={'user__toolbar'}><label>User</label>
<button onClick={handleSave}>Save</button>
</div>
<div className={'tabset'}>
{targets?.map(target => <span className={'tabset__tab' + (target.target === activeTarget ? ' tabset__tab-active' : '')} key={'tab_' + target.target} data-target={target.target} onClick={handleTabClick}>{target.target}</span>)}
</div>
<TabSet tabs={tabs} active={activeTarget} onTabChange={handleTabChange}></TabSet>
<div className={'user__content'}>
<div className={'user__content-targets'}>
{
+13 -4
View File
@@ -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(
<SnackbarProvider maxSnack={3} autoHideDuration={1500}>
const container = document.getElementById('root');
const root = createRoot(container);
root.render( <SnackbarProvider maxSnack={3} autoHideDuration={1500}>
<ServiceProvider>
<App/>
</ServiceProvider>
</SnackbarProvider>
, document.getElementById('root'));
);
// ReactDOM.render(
// <SnackbarProvider maxSnack={3} autoHideDuration={1500}>
// <ServiceProvider>
// <App/>
// </ServiceProvider>
// </SnackbarProvider>
// , document.getElementById('root'));
-32
View File
@@ -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;