-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
(ui): create views for server list / new server form
- Loading branch information
Showing
8 changed files
with
288 additions
and
20 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<?php | ||
|
||
namespace Influx\Http\Controllers; | ||
|
||
use Inertia\Inertia; | ||
use Inertia\Response; | ||
use Influx\Models\Server; | ||
use Illuminate\Http\Request; | ||
|
||
class ServersController extends Controller | ||
{ | ||
/** | ||
* ServersController constructor. | ||
*/ | ||
public function __construct() | ||
{ | ||
} | ||
|
||
/** | ||
* Display the table holding all servers. | ||
*/ | ||
public function index(Request $request): Response | ||
{ | ||
return Inertia::render('Servers/Index', [ | ||
'servers' => Server::all(), | ||
]); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
import PrimaryButton from '@/Components/PrimaryButton'; | ||
import { Body, Head } from '@/Components/Table'; | ||
import Authenticated from '@/Layouts/AuthenticatedLayout'; | ||
import { PageProps, Server } from '@/types'; | ||
import { MagnifyingGlassIcon } from '@heroicons/react/24/outline'; | ||
import { Link } from '@inertiajs/react'; | ||
import Avatar from 'boring-avatars'; | ||
import { useState } from 'react'; | ||
import New from './New'; | ||
|
||
export default function Index({ servers }: PageProps<{ servers: Server[] }>) { | ||
const [filter, setFilter] = useState<string>(''); | ||
const [showForm, setShowForm] = useState(false); | ||
|
||
if (showForm) { | ||
return <New />; | ||
}; | ||
|
||
return ( | ||
<Authenticated title={'All Servers'}> | ||
<div className={'mb-4 flex justify-between'}> | ||
<div className="relative"> | ||
<div className="pointer-events-none absolute inset-y-0 start-0 flex items-center ps-3"> | ||
<MagnifyingGlassIcon className={'h-5 text-white'} /> | ||
</div> | ||
<input | ||
type="text" | ||
className="block w-full rounded-lg border border-zinc-700 bg-zinc-800 p-2.5 ps-10 text-sm text-white focus:border-green-500 focus:ring-green-500 dark:placeholder-gray-400 dark:focus:border-green-500 dark:focus:ring-green-500" | ||
placeholder="Search servers" | ||
onChange={(e) => { | ||
if (e.currentTarget.value.length > 2) { | ||
setFilter(e.currentTarget.value); | ||
} else { | ||
setFilter(''); | ||
} | ||
}} | ||
required | ||
/> | ||
</div> | ||
<div className={'ml-auto'}> | ||
<PrimaryButton onClick={() => setShowForm(true)}>New Server</PrimaryButton> | ||
</div> | ||
</div> | ||
<table className="w-full text-left text-sm text-gray-400"> | ||
<Head columns={['Name', 'Position', 'Status', 'Action']} /> | ||
<Body> | ||
{servers | ||
.filter((x) => x.name.startsWith(filter)) | ||
.map((server) => ( | ||
<tr | ||
className="duration-250 border-b border-gray-800 bg-zinc-800 transition dark:hover:bg-zinc-800/80" | ||
key={server.name} | ||
> | ||
<th | ||
scope="row" | ||
className="flex items-center whitespace-nowrap px-6 py-4" | ||
> | ||
<Avatar | ||
variant={'beam'} | ||
name={server.name} | ||
className={'h-10 w-10'} | ||
/> | ||
<div className="ps-3"> | ||
<div className="text-base font-semibold"> | ||
{server.name} | ||
</div> | ||
<div className="font-normal text-gray-500"> | ||
{server.address} | ||
</div> | ||
</div> | ||
</th> | ||
<td className="px-6 py-4"> | ||
{server.public ? 'Public' : 'Private'} | ||
</td> | ||
<td className="px-6 py-4"> | ||
<div className="flex items-center"> | ||
<div className="me-2 h-2.5 w-2.5 rounded-full bg-green-500"></div>{' '} | ||
Online | ||
</div> | ||
</td> | ||
<td className="px-6 py-4"> | ||
<Link | ||
href={`/servers/${server.id}`} | ||
className="font-medium text-green-600 hover:underline dark:text-green-500" | ||
> | ||
Edit | ||
</Link> | ||
</td> | ||
</tr> | ||
))} | ||
</Body> | ||
</table> | ||
</Authenticated> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import Card from '@/Components/Card'; | ||
import Authenticated from '@/Layouts/AuthenticatedLayout'; | ||
import { ServerStackIcon } from '@heroicons/react/24/outline'; | ||
import ServerForm from './ServerForm'; | ||
|
||
export default function New() { | ||
return ( | ||
<Authenticated title={'New Server'}> | ||
<Card | ||
header={'Create new server'} | ||
description={'Add a new server to the management interface.'} | ||
> | ||
<div className={'grid gap-6 lg:grid-cols-3'}> | ||
<div className={'grid items-center justify-center'}> | ||
<div> | ||
<ServerStackIcon className={'h-24 text-green-600'} /> | ||
</div> | ||
</div> | ||
<ServerForm /> | ||
</div> | ||
</Card> | ||
</Authenticated> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
import PrimaryButton from '@/Components/PrimaryButton'; | ||
import { Server } from '@/types'; | ||
import { router } from '@inertiajs/react'; | ||
import { useState } from 'react'; | ||
|
||
export default function ServerForm({ server }: { server?: Server }) { | ||
const [values, setValues] = useState({ | ||
name: server?.name ?? '', | ||
address: server?.address ?? '', | ||
}); | ||
|
||
function handleChange(e: { | ||
target: { id: string; value: string | boolean }; | ||
}) { | ||
const key = e.target.id; | ||
const value = e.target.value; | ||
setValues((values) => ({ | ||
...values, | ||
[key]: value, | ||
})); | ||
} | ||
|
||
function handleSubmit(e: { preventDefault: () => void }) { | ||
e.preventDefault(); | ||
|
||
if (server) { | ||
router.put(`/servers/${server!.id}`, values); | ||
} else { | ||
router.post('/servers/new', values); | ||
} | ||
} | ||
|
||
return ( | ||
<form | ||
className="lg:col-span-2" | ||
autoComplete={'off'} | ||
onSubmit={handleSubmit} | ||
> | ||
<div className="group relative z-0 mb-5 w-full"> | ||
<input | ||
type="text" | ||
name="name" | ||
id="name" | ||
onChange={handleChange} | ||
className="peer block w-full appearance-none border-0 border-b-2 border-gray-300 bg-transparent px-0 py-2.5 text-sm text-gray-900 focus:border-green-600 focus:outline-none focus:ring-0 dark:border-gray-600 dark:text-white dark:focus:border-green-500" | ||
placeholder=" " | ||
defaultValue={server?.name} | ||
required | ||
/> | ||
<label className="absolute top-3 -z-10 origin-[0] -translate-y-6 scale-75 transform text-sm text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:start-0 peer-focus:-translate-y-6 peer-focus:scale-75 peer-focus:font-medium peer-focus:text-green-600 dark:text-gray-400 peer-focus:dark:text-green-500"> | ||
Server name | ||
</label> | ||
</div> | ||
<div className="group relative z-0 mb-5 w-full"> | ||
<input | ||
type="text" | ||
name="address" | ||
id="address" | ||
onChange={handleChange} | ||
className="peer block w-full appearance-none border-0 border-b-2 border-gray-300 bg-transparent px-0 py-2.5 text-sm text-gray-900 focus:border-green-600 focus:outline-none focus:ring-0 dark:border-gray-600 dark:text-white dark:focus:border-green-500" | ||
placeholder=" " | ||
defaultValue={server?.address} | ||
required | ||
/> | ||
<label className="absolute top-3 -z-10 origin-[0] -translate-y-6 scale-75 transform text-sm text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:start-0 peer-focus:-translate-y-6 peer-focus:scale-75 peer-focus:font-medium peer-focus:text-green-600 dark:text-gray-400 peer-focus:dark:text-green-500"> | ||
Server IP/FQDN Address | ||
</label> | ||
</div> | ||
<div className="grid md:grid-cols-2 md:gap-6"> | ||
<div className="group relative z-0 mb-5 w-full"> | ||
<input | ||
type="text" | ||
name="owner_id" | ||
id="owner_id" | ||
defaultValue={server?.ownerId} | ||
className="peer block w-full appearance-none border-0 border-b-2 border-gray-300 bg-transparent px-0 py-2.5 text-sm text-gray-900 focus:border-green-600 focus:outline-none focus:ring-0 dark:border-gray-600 dark:text-white dark:focus:border-green-500" | ||
placeholder=" " | ||
onChange={handleChange} | ||
required | ||
/> | ||
<label | ||
htmlFor="name" | ||
className="absolute top-3 -z-10 origin-[0] -translate-y-6 scale-75 transform text-sm text-gray-500 duration-300 peer-placeholder-shown:translate-y-0 peer-placeholder-shown:scale-100 peer-focus:start-0 peer-focus:-translate-y-6 peer-focus:scale-75 peer-focus:font-medium peer-focus:text-green-600 rtl:peer-focus:translate-x-1/4 dark:text-gray-400 peer-focus:dark:text-green-500" | ||
> | ||
Server Owner | ||
</label> | ||
</div> | ||
<div className="mb-4 flex items-center"> | ||
<input | ||
id="public" | ||
type="checkbox" | ||
defaultChecked={server?.public} | ||
onChange={handleChange} | ||
className="h-4 w-4 rounded border-gray-300 bg-gray-100 text-green-600 focus:ring-2 focus:ring-green-500 dark:border-gray-600 dark:bg-gray-700 dark:ring-offset-gray-800 dark:focus:ring-green-600 dark:focus:ring-offset-gray-800" | ||
/> | ||
<label | ||
htmlFor="superuser" | ||
className="ms-2 text-sm font-medium text-gray-900 dark:text-gray-300" | ||
> | ||
Allow this server to be viewed publicly | ||
</label> | ||
</div> | ||
</div> | ||
<div className={'text-right'}> | ||
<PrimaryButton type={'submit'}>{server ? 'Update' : 'Create'} Server</PrimaryButton> | ||
</div> | ||
</form> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters