This commit is contained in:
2022-11-29 14:17:11 +01:00
parent c9a7da688f
commit 25ef07b0b7
32 changed files with 1275 additions and 507 deletions

View File

@@ -0,0 +1,47 @@
import React from "react";
import clsx from "clsx";
export default function Dialog(props) {
const show = props.show;
const classes = ["modal", "fade"];
const style = { paddingRight: "12px", display: (show ? "block" : "none") };
const onClose = props.onClose || function() { };
const onOption = props.onOption || function() { };
const options = props.options || ["Close"];
let buttons = [];
for (let name of options) {
let type = "default";
if (name === "Yes") type = "warning";
else if(name === "No") type = "danger";
buttons.push(
<button type="button" key={"button-" + name} className={"btn btn-" + type}
data-dismiss={"modal"} onClick={() => { onClose(); onOption(name); }}>
{name}
</button>
)
}
return (
<div className={clsx(classes, show && "show")} style={style} aria-modal={"true"} onClick={() => onClose()}>
<div className="modal-dialog" onClick={(e) => e.stopPropagation()}>
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title">{props.title}</h4>
<button type="button" className="close" data-dismiss="modal" aria-label="Close" onClick={() => onClose()}>
<span aria-hidden="true">×</span>
</button>
</div>
<div className="modal-body">
<p>{props.message}</p>
</div>
<div className="modal-footer">
{ buttons }
</div>
</div>
</div>
</div>
);
}

View File

@@ -0,0 +1,11 @@
import React from "react";
export default function Footer() {
return (
<footer className={"main-footer"}>
Theme: <strong>Copyright © 2014-2019 <a href={"https://adminlte.io"}>AdminLTE.io</a>. <b>Version</b> 3.0.3</strong>&nbsp;
CMS: <strong><a href={"https://git.romanh.de/Projekte/web-base"}>WebBase</a></strong>. <b>Version</b> 1.2.6
</footer>
)
}

View File

@@ -0,0 +1,57 @@
import * as React from "react";
import {Link} from "react-router-dom";
import Icon from "shared/elements/icon";
export default function Header(props) {
const parent = {
api: props.api
};
function onToggleSidebar() {
let classes = document.body.classList;
if (classes.contains("sidebar-collapse")) {
classes.remove("sidebar-collapse");
classes.add("sidebar-open");
} else {
classes.add("sidebar-collapse");
classes.remove("sidebar-add");
}
}
return (
<nav className={"main-header navbar navbar-expand navbar-white navbar-light"}>
{/*Left navbar links */}
<ul className={"navbar-nav"}>
<li className={"nav-item"}>
<a href={"#"} className={"nav-link"} role={"button"} onClick={onToggleSidebar}>
<Icon icon={"bars"}/>
</a>
</li>
<li className={"nav-item d-none d-sm-inline-block"}>
<Link to={"/admin/dashboard"} className={"nav-link"}>
Home
</Link>
</li>
</ul>
{/* SEARCH FORM */}
<form className={"form-inline ml-3"}>
<div className={"input-group input-group-sm"}>
<input className={"form-control form-control-navbar"} type={"search"} placeholder={"Search"} aria-label={"Search"} />
<div className={"input-group-append"}>
<button className={"btn btn-navbar"} type={"submit"}>
<Icon icon={"search"}/>
</button>
</div>
</div>
</form>
{/* Right navbar links */}
<ul className={"navbar-nav ml-auto"}>
</ul>
</nav>
)
}

View File

@@ -0,0 +1,47 @@
import React, {useState} from 'react';
import {initLocale, L} from "shared/locale/locale";
import {Box} from "@material-ui/core";
import {makeStyles} from "@material-ui/core/styles";
const useStyles = makeStyles((theme) => ({
languageFlag: {
margin: theme.spacing(0.2),
cursor: "pointer",
border: 0,
}
}));
export default function LanguageSelection(props) {
const api = props.api;
const classes = useStyles();
let [languages, setLanguages] = useState(null);
const onSetLanguage = (code) => {
api.setLanguageByCode(code).then((res) => {
if (res.success) {
initLocale(code);
props.onUpdateLocale();
}
});
};
let flags = [];
if (languages === null) {
api.getLanguages().then((res) => {
setLanguages(res.languages);
});
} else {
for (const language of Object.values(languages)) {
let key = `lang-${language.code}`;
flags.push(<button type={"button"} title={language.name} onClick={() => onSetLanguage(language.code)}
key={key} className={classes.languageFlag} >
<img alt={key} src={`/img/icons/lang/${language.code}.gif`} />
</button>);
}
}
return <Box mt={1}>
{L("Language") + ": "} { flags }
</Box>
}

View File

@@ -0,0 +1,113 @@
import React from 'react';
import {Link, NavLink} from "react-router-dom";
import Icon from "shared/elements/icon";
export default function Sidebar(props) {
let parent = {
showDialog: props.showDialog || function() {},
api: props.api,
};
function onLogout() {
parent.api.logout().then(obj => {
if (obj.success) {
document.location = "/admin";
} else {
parent.showDialog("Error logging out: " + obj.msg, "Error logging out");
}
});
}
const menuItems = {
"dashboard": {
"name": "Dashboard",
"icon": "tachometer-alt"
},
"visitors": {
"name": "Visitor Statistics",
"icon": "chart-bar",
},
"users": {
"name": "Users & Groups",
"icon": "users"
},
"pages": {
"name": "Pages & Routes",
"icon": "copy",
},
"settings": {
"name": "Settings",
"icon": "tools"
},
"logs": {
"name": "Logs & Notifications",
"icon": "file-medical-alt"
},
"contact": {
"name": "Contact Requests",
"icon": "comments"
},
"help": {
"name": "Help",
"icon": "question-circle"
},
};
let li = [];
for (let id in menuItems) {
let obj = menuItems[id];
const badge = (obj.badge ? <span className={"right badge badge-" + obj.badge.type}>{obj.badge.value}</span> : <></>);
li.push(
<li key={id} className={"nav-item"}>
<NavLink to={"/admin/" + id} className={"nav-link"} activeClassName={"active"}>
<Icon icon={obj.icon} className={"nav-icon"} /><p>{obj.name}{badge}</p>
</NavLink>
</li>
);
}
li.push(<li className={"nav-item"} key={"logout"}>
<a href={"#"} onClick={() => onLogout()} className={"nav-link"}>
<Icon icon={"arrow-left"} className={"nav-icon"} />
<p>Logout</p>
</a>
</li>);
return (
<aside className={"main-sidebar sidebar-dark-primary elevation-4"}>
<Link href={"#"} className={"brand-link"} to={"/admin/dashboard"}>
<img src={"/img/icons/logo.png"} alt={"Logo"} className={"brand-image img-circle elevation-3"} style={{opacity: ".8"}} />
<span className={"brand-text font-weight-light ml-2"}>WebBase</span>
</Link>
<div className={"sidebar os-host os-theme-light os-host-overflow os-host-overflow-y os-host-resize-disabled os-host-scrollbar-horizontal-hidden os-host-transition"}>
{/* IDK what this is */}
<div className={"os-resize-observer-host"}>
<div className={"os-resize-observer observed"} style={{left: "0px", right: "auto"}}/>
</div>
<div className={"os-size-auto-observer"} style={{height: "calc(100% + 1px)", float: "left"}}>
<div className={"os-resize-observer observed"}/>
</div>
<div className={"os-content-glue"} style={{margin: "0px -8px"}}/>
<div className={"os-padding"}>
<div className={"os-viewport os-viewport-native-scrollbars-invisible"} style={{right: "0px", bottom: "0px"}}>
<div className={"os-content"} style={{padding: "0px 0px", height: "100%", width: "100%"}}>
<div className="user-panel mt-3 pb-3 mb-3 d-flex">
<div className="info">
<a href="#" className="d-block">Logged in as: {parent.api.user.name}</a>
</div>
</div>
<nav className={"mt-2"}>
<ul className={"nav nav-pills nav-sidebar flex-column"} data-widget={"treeview"} role={"menu"} data-accordion={"false"}>
{li}
</ul>
</nav>
</div>
</div>
</div>
</div>
</aside>
)
}