implemented user rights

master
Tudor Stanciu 2023-04-04 18:28:01 +03:00
parent 6bad079252
commit b9726950cc
14 changed files with 137 additions and 21 deletions

14
package-lock.json generated
View File

@ -1316,21 +1316,21 @@
"integrity": "sha512-6NBXdZgRrHbLXw4EMgyqCIzOVAlUgr1+8QGHjlA+n5Iw2Lp/+dP3FTgAfPW/cHR/PBI3cj7gUDVUf/zD/qTPOQ=="
},
"@flare/tuitio-client": {
"version": "1.2.3",
"resolved": "https://lab.code-rove.com/public-node-registry/@flare/tuitio-client/-/tuitio-client-1.2.3.tgz",
"integrity": "sha512-m1cJZNTLNXwviD2hkeAvs6I/jlC17GHkUraExfaEaYOUrmDpovE64sg6Xheb01mXnDADCdA2MYxdJgxODNJAqw==",
"version": "1.2.4",
"resolved": "https://lab.code-rove.com/public-node-registry/@flare/tuitio-client/-/tuitio-client-1.2.4.tgz",
"integrity": "sha512-qLVneFf/uACqnr6fIDceVXvIHDmE1y7z6S/sVUPAPHipXmVq8bCiqvCeyGb+If0Mjj16WexedF+FNBltg5UYCA==",
"requires": {
"@flare/js-utils": "^1.1.0",
"axios": "^1.3.2"
}
},
"@flare/tuitio-client-react": {
"version": "1.2.3",
"resolved": "https://lab.code-rove.com/public-node-registry/@flare/tuitio-client-react/-/tuitio-client-react-1.2.3.tgz",
"integrity": "sha512-ry8eiNJh+TrAVu+PN/vuZ6MJXVMDDEBixz+X37rPOKzY283FhiLSJt76l0rBjfSKuFHyqE8Bx5g4mJ0XgutjMg==",
"version": "1.2.4",
"resolved": "https://lab.code-rove.com/public-node-registry/@flare/tuitio-client-react/-/tuitio-client-react-1.2.4.tgz",
"integrity": "sha512-AM/TXHI8J9YxBMS8P6YHJANYRwVGGNsssR7HU3Mo+EgkTxwImOgT1nkKNZEEQmx1O/KlOxYz58VD3YyDzA0RCQ==",
"requires": {
"@flare/js-utils": "^1.1.0",
"@flare/tuitio-client": "^1.2.3"
"@flare/tuitio-client": "^1.2.4"
}
},
"@gar/promisify": {

View File

@ -14,7 +14,7 @@
"private": true,
"dependencies": {
"@flare/js-utils": "^1.1.0",
"@flare/tuitio-client-react": "^1.2.3",
"@flare/tuitio-client-react": "^1.2.4",
"@material-ui/core": "^4.11.2",
"@material-ui/icons": "^4.11.2",
"@material-ui/lab": "^4.0.0-alpha.61",

View File

@ -36,6 +36,18 @@
"Label": "Login",
"IncorrectCredentials": "Incorrect credentials."
},
"Dashboard": {
"Announcements": {
"Guest": {
"Title": "Hello there! I'm glad you're here!",
"Message": "You are currently browsing my application as a guest. Keep in mind that you cannot perform actions, and most of the data you see is fake. The purpose of the application in this state is for presentation."
},
"User": {
"Title": "Welcome back, {{userName}}",
"Message": "The application is in continuous development, so if you identify a problem, please report it. Thank you!"
}
}
},
"User": {
"Profile": {
"Label": "Profile",

View File

@ -27,6 +27,18 @@
"Label": "Autentificare",
"IncorrectCredentials": "Credențiale incorecte."
},
"Dashboard": {
"Announcements": {
"Guest": {
"Title": "Salutare! Sunt bucuros ca ești aici!",
"Message": "În acest moment, răsfoiești aplicația mea că invitat. Reține că nu poți efectua acțiuni, iar majoritatea datelor pe care le vezi sunt false. Scopul aplicației în această stare este de prezentare."
},
"User": {
"Title": "Bine ai revenit, {{userName}}",
"Message": "Aplicația este în continuă dezvoltare, așa că dacă identifici o problemă, te rog să o raportezi. Mulțumesc!"
}
}
},
"User": {
"Profile": {
"Label": "Profil",

View File

@ -4,7 +4,7 @@ import PageNotFound from "./PageNotFound";
import NetworkContainer from "../../features/network/components/NetworkContainer";
import SystemContainer from "../../features/system/SystemContainer";
import SettingsContainer from "../../features/settings/SettingsContainer";
import DashboardContainer from "../../features/dashboard/components/DashboardContainer";
import DashboardContainer from "../../features/dashboard/DashboardContainer";
import UserProfileContainer from "../../features/user/profile/card/UserProfileContainer";
import AboutContainer from "../../features/about/AboutContainer";

View File

@ -0,0 +1,10 @@
import React from "react";
import AnnouncementsSection from "./announcements/AnnouncementsSection";
const DashboardContainer = () => (
<>
<AnnouncementsSection />
</>
);
export default DashboardContainer;

View File

@ -0,0 +1,19 @@
import React from "react";
import GuestAnnouncement from "./GuestAnnouncement";
import UserAnnouncement from "./UserAnnouncement";
import { useTuitioUserInfo } from "@flare/tuitio-client-react";
const AnnouncementsSection = () => {
const { userInfo, isGuest } = useTuitioUserInfo();
const loading = !userInfo;
if (loading) return "";
return (
<>
{isGuest && <GuestAnnouncement />}
{!isGuest && <UserAnnouncement userData={userInfo} />}
</>
);
};
export default AnnouncementsSection;

View File

@ -0,0 +1,21 @@
import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import { Alert, AlertTitle } from "@material-ui/lab";
import styles from "../styles";
import { useTranslation } from "react-i18next";
const useStyles = makeStyles(styles);
export default function GuestAnnouncement() {
const classes = useStyles();
const { t } = useTranslation();
return (
<div className={classes.alert}>
<Alert variant="outlined" severity="warning">
<AlertTitle>{t("Dashboard.Announcements.Guest.Title")}</AlertTitle>
{t("Dashboard.Announcements.Guest.Message")}
</Alert>
</div>
);
}

View File

@ -0,0 +1,30 @@
import React from "react";
import PropTypes from "prop-types";
import { makeStyles } from "@material-ui/core/styles";
import { Alert, AlertTitle } from "@material-ui/lab";
import styles from "../styles";
import { useTranslation } from "react-i18next";
const useStyles = makeStyles(styles);
export default function UserAnnouncement({ userData }) {
const classes = useStyles();
const { t } = useTranslation();
return (
<div className={classes.alert}>
<Alert variant="outlined" severity="info">
<AlertTitle>
{t("Dashboard.Announcements.User.Title", {
userName: userData.firstName
})}
</AlertTitle>
{t("Dashboard.Announcements.User.Message")}
</Alert>
</div>
);
}
UserAnnouncement.propTypes = {
userData: PropTypes.object.isRequired
};

View File

@ -1,5 +0,0 @@
import React from "react";
const DashboardContainer = () => <h2>In development...</h2>;
export default DashboardContainer;

View File

@ -0,0 +1,10 @@
const styles = theme => ({
alert: {
width: "100%",
"& > * + *": {
marginTop: theme.spacing(1)
}
}
});
export default styles;

View File

@ -3,7 +3,7 @@ import PropTypes from "prop-types";
import { IconButton, Tooltip } from "@material-ui/core";
const ActionButton = React.forwardRef((props, _ref) => {
const { action, machine, callback } = props;
const { action, machine, callback, disabled } = props;
const id = `machine-item-${machine.machineId}-${action.code}`;
const handleActionClick = event => {
action.effect(machine, event);
@ -22,6 +22,7 @@ const ActionButton = React.forwardRef((props, _ref) => {
size={"small"}
onFocus={event => event.stopPropagation()}
onClick={handleActionClick}
disabled={disabled}
>
<action.icon />
</IconButton>
@ -39,7 +40,8 @@ ActionButton.propTypes = {
tooltip: PropTypes.string.isRequired,
effect: PropTypes.func.isRequired
}).isRequired,
callback: PropTypes.func
callback: PropTypes.func,
disabled: PropTypes.bool
};
export default ActionButton;

View File

@ -5,11 +5,13 @@ import ActionButton from "./ActionButton";
import { Menu } from "@material-ui/core";
import { MoreHoriz } from "@material-ui/icons";
import { useTranslation } from "react-i18next";
import { useTuitioUserInfo } from "@flare/tuitio-client-react";
const ActionsGroup = ({ machine, actions, addLog }) => {
const [menuAnchor, setMenuAnchor] = useState(null);
const { t } = useTranslation();
const { isSysAdmin } = useTuitioUserInfo();
const mainActions = useMemo(
() => actions.filter(a => a.main === true),
@ -31,12 +33,13 @@ const ActionsGroup = ({ machine, actions, addLog }) => {
return (
<>
<WakeComponent machine={machine} addLog={addLog} />
<WakeComponent machine={machine} addLog={addLog} disabled={!isSysAdmin} />
{mainActions.map(action => (
<ActionButton
key={`machine-item-${machine.machineId}-${action.code}`}
action={action}
machine={machine}
disabled={!isSysAdmin}
/>
))}
<ActionButton
@ -62,6 +65,7 @@ const ActionsGroup = ({ machine, actions, addLog }) => {
action={action}
machine={machine}
callback={handleMenuClose}
disabled={!isSysAdmin}
/>
))}
</Menu>

View File

@ -11,7 +11,7 @@ const initialState = { on: false };
const defaultPingInterval = 1200000; //20 minutes
const defaultStartingTime = 300000; //5 minutes
const WakeComponent = ({ machine, addLog }) => {
const WakeComponent = ({ machine, addLog, disabled }) => {
const [state, setState] = useState(initialState);
const [trigger, setTrigger] = useState(false);
@ -91,9 +91,9 @@ const WakeComponent = ({ machine, addLog }) => {
<IconButton
id={`machine-${machine.machineId}-wake`}
size={"small"}
disabled={state.on}
disabled={disabled || state.on}
onClick={handleWakeClick}
style={state.on ? { color: "#33cc33" } : {}}
style={state.on ? { color: "#33cc33" } : undefined}
onFocus={event => event.stopPropagation()}
>
<PowerSettingsNew />
@ -105,7 +105,8 @@ const WakeComponent = ({ machine, addLog }) => {
WakeComponent.propTypes = {
machine: PropTypes.object.isRequired,
addLog: PropTypes.func.isRequired
addLog: PropTypes.func.isRequired,
disabled: PropTypes.bool
};
export default WakeComponent;