Merge remote-tracking branch 'jannaahs/rework-ui' into rework-ui-cleanup-mod-portal

# Conflicts:
#	src/handlers.go
#	src/mods_handler.go
#	src/routes.go
#	ui/App/views/Controls.jsx
#	ui/App/views/Saves/Saves.jsx
This commit is contained in:
knoxfighter
2020-09-10 03:34:30 +02:00
11 changed files with 192 additions and 149 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 910 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 190 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

View File

@ -4,7 +4,6 @@
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>Factorio Server Manager</title>
<link rel="icon" type="image/png" href="./images/favicon.ico">
<!-- Tell the browser to be responsive to screen width -->
<meta content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no" name="viewport">

View File

@ -5,7 +5,18 @@ module.exports = {
purge: [],
theme: {
extend: {
width: {
72: "18rem",
80: "20rem",
88: "22rem",
96: "24rem",
},
margin: {
72: "18rem",
80: "20rem",
88: "22rem",
96: "24rem",
}
},
colors: {
"gray": {

View File

@ -1,10 +1,13 @@
import React, {useEffect} from "react";
import server from "../../api/resources/server";
import React, {useEffect, useState} from "react";
import {NavLink} from "react-router-dom";
import Button from "./Button";
import {FontAwesomeIcon} from "@fortawesome/react-fontawesome";
import {faBars} from "@fortawesome/free-solid-svg-icons";
const Layout = ({children, handleLogout, serverStatus, updateServerStatus}) => {
const [isNavCollapsed, setIsNavCollapsed] = useState(true);
useEffect(() => {
(async () => {
updateServerStatus()
@ -34,6 +37,7 @@ const Layout = ({children, handleLogout, serverStatus, updateServerStatus}) => {
const Link = ({children, to, last}) => {
return (
<NavLink
onClick={() => setIsNavCollapsed(true)}
exact={true}
to={to}
activeClassName="bg-orange"
@ -42,22 +46,21 @@ const Layout = ({children, handleLogout, serverStatus, updateServerStatus}) => {
}
return (
<div className="flex md:flex-row-reverse flex-wrap">
{/*Main*/}
<div className="w-full md:w-5/6 bg-gray-100 bg-banner bg-fixed min-h-screen">
<div className="container mx-auto bg-gray-100 pt-16 px-6">
{children}
</div>
</div>
<>
{/*Sidebar*/}
<div
className="w-full md:w-1/6 bg-gray-dark fixed bottom-0 md:top-0 md:left-0 h-16 md:h-screen">
<div className="py-4 px-2 accentuated items-center text-center">
<img src="/images/factorio.jpg" className="inline h-8" alt="Factorio Logo"/>
<span className="text-dirty-white pl-2 text-xl">Factorio Server Manager</span>
<div className="w-full md:w-88 md:fixed md:top-0 md:left-0 bg-gray-dark md:h-screen">
<div className="py-4 px-2 accentuated">
<div className="mx-4 justify-between flex text-center">
<span className="text-dirty-white text-xl">Factorio Server Manager</span>
<button
className="md:hidden cursor-pointer text-white hover:text-dirty-white"
onClick={() => setIsNavCollapsed(!isNavCollapsed)}
>
<FontAwesomeIcon icon={faBars}/>
</button>
</div>
</div>
<div className={isNavCollapsed ? "hidden md:block" : "block"}>
<div className="py-4 px-2 accentuated">
<h1 className="text-dirty-white text-lg mb-2 mx-4">Server Status</h1>
<div className="mx-4 mb-4 text-center">
@ -88,9 +91,17 @@ const Layout = ({children, handleLogout, serverStatus, updateServerStatus}) => {
<Button type="danger" className="w-full" onClick={handleLogout}>Logout</Button>
</div>
</div>
<div className="accentuated h-full"/>
<div className="accentuated-t accentuated-x md:block hidden"/>
</div>
</div>
{/*Main*/}
<div className="md:ml-88 bg-gray-100 bg-black min-h-screen">
<div className="container mx-auto bg-gray-100 pt-16 px-6">
{children}
</div>
</div>
</>
);
}

View File

@ -50,39 +50,48 @@ const Controls = ({serverStatus, updateServerStatus}) => {
<Panel
title="Server Status"
content={
<div className="flex">
<table className="w-full">
<thead>
<tr className="text-left py-1">
<th>Status</th>
<th>IP</th>
<th>Port</th>
<th>Factorio Version</th>
<th>Save File</th>
</tr>
</thead>
<tbody>
<div className="lg:flex">
{ isRunning
? <tr className="py-1">
<td className="pr-4 py-2">{serverStatus.status}</td>
<td className="pr-4 py-2">{serverStatus.address}</td>
<td className="pr-4 py-2">{serverStatus.port}</td>
<td className="pr-4 py-2">{factorioVersion}</td>
<td className="pr-4 py-2">{serverStatus.savefile}</td>
</tr>
: <tr className="py-1">
<td className="pr-4 py-2">{serverStatus.status}</td>
<td className="pr-4">
? <>
<div className="lg:w-1/5 mb-2">
<div className="font-bold">Status</div>
<div>{serverStatus.status}</div>
</div>
<div className="lg:w-1/5 mb-2">
<div className="font-bold">IP</div>
<div>{serverStatus.address}</div>
</div>
<div className="lg:w-1/5 mb-2">
<div className="font-bold">Port</div>
<div>{serverStatus.port}</div>
</div>
<div className="lg:w-1/5 mb-2">
<div className="font-bold">Factorio Version</div>
<div>{factorioVersion}</div>
</div>
<div className="lg:w-1/5 mb-2">
<div className="font-bold">Save</div>
<div>{serverStatus.savefile}</div>
</div>
</>
: <>
<div className="lg:w-1/5 mb-2">
<div className="font-bold">Status</div>
<div>{serverStatus.status}</div>
</div>
<div className="lg:w-1/5 mb-2 mr-0 lg:mr-4">
<div className="font-bold">IP</div>
<input
name="ip"
className="shadow appearance-none w-full py-2 px-3 text-black"
className="shadow appearance-none w-full mr-2 py-2 px-3 text-black"
type="text"
defaultValue={"0.0.0.0"}
ref={register({required: true, pattern: '^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'})}
/>
{errors.ip && <span className="block text-red">IP is required and must be valid.</span>}
</td>
<td className="pr-4">
</div>
<div className="lg:w-1/5 mb-2 mr-0 lg:mr-4">
<div className="font-bold">Port</div>
<input
name="port"
className="shadow appearance-none w-full py-2 px-3 text-black"
@ -92,9 +101,13 @@ const Controls = ({serverStatus, updateServerStatus}) => {
ref={register({required: true})}
/>
{errors.port && <span className="block text-red">Port is required</span>}
</td>
<td className="pr-4 py-2">{factorioVersion}</td>
<td className="pr-4 py-2">
</div>
<div className="lg:w-1/5 mb-2 mr-0 lg:mr-4">
<div className="font-bold">Factorio Version</div>
<div>{factorioVersion}</div>
</div>
<div className="lg:w-1/5 mb-2">
<div className="font-bold">Save</div>
<div className="relative">
<Select
name="save"
@ -104,21 +117,19 @@ const Controls = ({serverStatus, updateServerStatus}) => {
<option value={save.name} key={save.name}>{save.name}</option>))}
</Select>
</div>
</td>
</tr>
</div>
</>
}
</tbody>
</table>
</div>
}
actions={
<div className="flex">
<div className="md:flex">
{isRunning
? <>
<Button onClick={stopServer} size="sm" className="mr-2" type="default">Save & Stop Server</Button>
<Button onClick={killServer} size="sm" type="danger">Kill Server</Button>
<Button onClick={stopServer} size="sm" className="w-full md:w-auto mb-2 md:mb-0 md:mr-2" type="default">Save & Stop Server</Button>
<Button onClick={killServer} size="sm" type="danger" className="w-full md:w-auto">Kill Server</Button>
</>
: <Button isSubmit={true} size="sm" type="success">Start Server</Button>
: <Button isSubmit={true} size="sm" type="success" className="w-full md:w-auto">Start Server</Button>
}
</div>
}

View File

@ -6,6 +6,7 @@ import {useHistory, useLocation} from "react-router";
import Panel from "../components/Panel";
import Input from "../components/Input";
import Label from "../components/Label";
import {Flash} from "../components/Flash";
const Login = ({handleLogin}) => {
const {register, handleSubmit, errors} = useForm();
@ -32,7 +33,7 @@ const Login = ({handleLogin}) => {
}, [])
return (
<div className="h-screen overflow-hidden flex items-center justify-center bg-banner">
<div className="h-screen overflow-hidden flex items-center justify-center bg-black">
<Panel
title="Login"
content={
@ -58,6 +59,7 @@ const Login = ({handleLogin}) => {
</form>
}
/>
<Flash/>
</div>
);
};

View File

@ -33,10 +33,10 @@ const Saves = ({serverStatus}) => {
return (
<>
<div className="flex mb-6">
<div className="lg:flex mb-6">
<Panel
title="Create Save"
className="w-1/2 mr-3"
className="lg:w-1/2 lg:mr-3 mb-6 lg:mb-0"
content={
serverStatus.status === "running"
? <p className="text-red-light pt-4 pb-24">
@ -48,7 +48,7 @@ const Saves = ({serverStatus}) => {
/>
<Panel
title="Upload Save"
className="w-1/2 ml-3"
className="lg:w-1/2 lg:ml-3"
content={<UploadSaveForm onSuccess={updateList}/>}
/>
</div>
@ -57,7 +57,8 @@ const Saves = ({serverStatus}) => {
className="mb-4"
title="Saves"
content={
<table className="w-full">
<div className="overflow-x-auto">
<table style={{"width" : "max-content"}}>
<thead>
<tr className="text-left py-1">
<th>Name</th>
@ -68,20 +69,24 @@ const Saves = ({serverStatus}) => {
</thead>
<tbody>
{saves.map(save =>
<tr className="py-1" key={save.name}>
<tr className="py-2 md:py-1" key={save.name}>
<td className="pr-4">{save.name}</td>
<td className="pr-4">{(new Date(save.last_mod)).toISOString().replace('T', ' ').split('.')[0]}</td>
<td>{parseFloat(save.size / 1024 / 1024).toFixed(3)} MB</td>
<td className="pr-4">{parseFloat(save.size / 1024 / 1024).toFixed(3)} MB</td>
<td>
<a href={`/api/saves/dl/${save.name}`} className="mr-2">
<FontAwesomeIcon className="text-gray-light cursor-pointer hover:text-orange" icon={faDownload}/>
<FontAwesomeIcon
className="text-gray-light cursor-pointer hover:text-orange"
icon={faDownload}/>
</a>
<FontAwesomeIcon className="text-red cursor-pointer hover:text-red-light mr-2" onClick={() => deleteSave(save)} icon={faTrashAlt}/>
<FontAwesomeIcon className="text-red cursor-pointer hover:text-red-light mr-2"
onClick={() => deleteSave(save)} icon={faTrashAlt}/>
</td>
</tr>
)}
</tbody>
</table>
</div>
}
/>
</>

View File

@ -7,4 +7,13 @@ const client = Axios.create({
}
});
client.interceptors.response.use(res => res, err => {
if(err.response.status === 502) {
window.flash("Service not available", "red");
} else if (err.response.status !== 401) {
window.flash(err.response.data, "red");
}
return Promise.reject(err);
});
export default client;

View File

@ -2,11 +2,6 @@
@import "tailwindcss/utilities";
@import "tailwindcss/components";
.bg-banner {
background-image: url("/images/factorio-main-banner.jpg");
background-position: center center;
}
.accentuated-t {
border-top: 2px solid rgba(255, 255, 255, 0.1);
}