Skip to content

Commit

Permalink
refactor(ui): use a shared layout across the pages (#40)
Browse files Browse the repository at this point in the history
* feat: working on the basic restructure

* feat: workspace pages

* feat: better failed middleware redirection

* feat: more consistency stuff

* feat: service pages

* feat: let the aside not be ugly when in light mode

* feat: breakpoint on mobile

* feat: some mobile relevant fixes

* chore: stuff for the vscode config

* chore: one more item for the vscode config

* chore: bump package.json version
  • Loading branch information
SeanCassiere authored Jul 1, 2024
1 parent 65625e1 commit 6bfafd5
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 147 deletions.
3 changes: 2 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@
"editor.codeActionsOnSave": {
"source.organizeImports": "explicit"
}
}
},
"conventionalCommits.scopes": ["auth", "ui", "api-v2"]
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "simple-logging-server",
"license": "MIT",
"version": "2.3.2",
"version": "2.3.3",
"description": "This is a simple API for logging messages",
"author": "Sean Cassiere",
"keywords": [],
Expand Down
4 changes: 3 additions & 1 deletion src/routers/app/ui/components/card.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ import type { FC, PropsWithChildren } from "hono/jsx";

export const Card: FC<PropsWithChildren<{ class?: string }>> = ({ class: className, children }) => {
return (
<div class={["rounded-lg border bg-white shadow overflow-hidden", className].filter(Boolean).join(" ")}>
<div
class={["rounded-lg border bg-white text-gray-950 shadow overflow-hidden", className].filter(Boolean).join(" ")}
>
{children}
</div>
);
Expand Down
52 changes: 42 additions & 10 deletions src/routers/app/ui/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@ import { Hono } from "hono";

import { db } from "@/config/db/index.mjs";

import { DashboardLandingPage } from "./pages/dashboard-landing.js";
import { LoginPage } from "./pages/login.js";
import { WorkspaceLandingPage } from "./pages/workspace-landing.js";
import { WorkspaceEditPage } from "./pages/workspace-edit.js";
import { ServiceLandingPage } from "./pages/service-landing.js";
import { ServiceEditPage } from "./pages/service-edit.js";
import { DashboardLandingPage } from "./pages/app.index.js";
import { LoginPage } from "./pages/app.login.js";
import { WorkspaceLandingPage } from "./pages/app.$workspace.index.js";
import { WorkspaceEditPage } from "./pages/app.$workspace.edit.js";
import { ServiceLandingPage } from "./pages/app.$workspace.$serviceId.index.js";
import { ServiceEditPage } from "./pages/app.$workspace.$serviceId.edit.js";

import { checkTenantMembership, checkUserAuthed, checkServiceTenantMembership } from "./utils/middleware.mjs";

Expand Down Expand Up @@ -46,25 +46,49 @@ app.get("/login", async (c) => {

app.get("/:workspace", checkUserAuthed, checkTenantMembership, async (c) => {
const tenant = c.var.tenant!;
const user = c.var.user!;

const relationships = await db.query.usersToTenants.findMany({
where: (fields, { eq }) => eq(fields.userId, user.id),
with: { tenant: true },
});

const tenants = relationships.map((r) => r.tenant);

const services = await db.query.services.findMany({
where: (fields, { eq }) => eq(fields.tenantId, tenant.id),
});

return c.html(<WorkspaceLandingPage tenant={tenant} services={services} />);
return c.html(<WorkspaceLandingPage user={user} tenants={tenants} tenant={tenant} services={services} />);
});

app.get("/:workspace/edit", checkUserAuthed, checkTenantMembership, async (c) => {
const tenant = c.var.tenant!;
const user = c.var.user!;

const relationships = await db.query.usersToTenants.findMany({
where: (fields, { eq }) => eq(fields.userId, user.id),
with: { tenant: true },
});

const tenants = relationships.map((r) => r.tenant);

return c.html(<WorkspaceEditPage tenant={tenant} />);
return c.html(<WorkspaceEditPage user={user} tenants={tenants} tenant={tenant} />);
});

app.get("/:workspace/:service_id", checkUserAuthed, checkTenantMembership, checkServiceTenantMembership, async (c) => {
const tenant = c.var.tenant!;
const service = c.var.service!;
const user = c.var.user!;

return c.html(<ServiceLandingPage tenant={tenant} service={service} />);
const relationships = await db.query.usersToTenants.findMany({
where: (fields, { eq }) => eq(fields.userId, user.id),
with: { tenant: true },
});

const tenants = relationships.map((r) => r.tenant);

return c.html(<ServiceLandingPage user={user} tenant={tenant} tenants={tenants} service={service} />);
});

app.get(
Expand All @@ -75,8 +99,16 @@ app.get(
async (c) => {
const tenant = c.var.tenant!;
const service = c.var.service!;
const user = c.var.user!;

const relationships = await db.query.usersToTenants.findMany({
where: (fields, { eq }) => eq(fields.userId, user.id),
with: { tenant: true },
});

const tenants = relationships.map((r) => r.tenant);

return c.html(<ServiceEditPage tenant={tenant} service={service} />);
return c.html(<ServiceEditPage user={user} tenant={tenant} tenants={tenants} service={service} />);
},
);

Expand Down
52 changes: 52 additions & 0 deletions src/routers/app/ui/layouts/app-container.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import type { FC, PropsWithChildren } from "hono/jsx";
import { User } from "lucia";

import type { TenantRecord } from "@/types/db.mjs";

export interface AppContainerProps {
user: User;
tenant: TenantRecord | null;
tenants: Array<TenantRecord>;
mainClass?: string;
}

export const AppContainer: FC<PropsWithChildren<AppContainerProps>> = ({
user,
tenant,
tenants,
children,
mainClass,
}) => {
return (
<div className="flex flex-col md:grid md:grid-cols-4 lg:grid-cols-5 min-h-full">
<aside class="h-[250px] border-b flex flex-col bg-gray-100 dark:bg-gray-800 md:h-auto md:col-span-1 md:border-r md:border-b-none">
<div class="flex-grow p-2">
<p class="pb-2">Hello {user.username}!</p>
<p class="pb-2 border-b">Your organizations</p>
{tenants.length > 0 ? (
<ul>
{tenants.map((item) => (
<li>
<a
href={`/app/${item.workspace}`}
class='block py-1 data-[active-tenant="true"]:text-blue-500'
data-active-tenant={tenant ? item.id === tenant.id : false}
>
{item.name}
</a>
</li>
))}
</ul>
) : (
<p>😞 You have no organizations.</p>
)}
<span class="border-t" />
</div>
<div class="p-2">
<a href="/app/logout">👋🏼 Logout</a>
</div>
</aside>
<main className={["md:col-span-3 lg:col-span-4", mainClass].filter(Boolean).join(" ")}>{children}</main>
</div>
);
};
2 changes: 1 addition & 1 deletion src/routers/app/ui/layouts/root-document.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ export const RootDocument: FC<PropsWithChildren<{ title: string }>> = ({ title,
<title>{title}</title>
<script src="https://cdn.tailwindcss.com"></script>
</head>
<body class="bg-gray-50 dark:bg-gray-950">{children}</body>
<body class="bg-gray-50 text-gray-950 dark:bg-gray-950 dark:text-gray-50">{children}</body>
</html>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,31 @@ import type { FC } from "hono/jsx";
import { RootDocument } from "../layouts/root-document.js";
import { Card } from "../components/card.js";
import { getButtonStyles } from "../components/button.js";
import { AppContainer, type AppContainerProps } from "../layouts/app-container.js";

import type { ServiceRecord, TenantRecord } from "@/types/db.mjs";
import type { ServiceRecord } from "@/types/db.mjs";

export const ServiceEditPage: FC<{ tenant: TenantRecord; service: ServiceRecord }> = ({ tenant, service }) => {
export const ServiceEditPage: FC<{ service: ServiceRecord } & AppContainerProps> = ({
user,
tenant,
tenants,
service,
}) => {
return (
<RootDocument title={`${tenant.name} edit`}>
<section class="mx-auto max-w-7xl h-full grid place-items-center">
<Card class="max-w-md">
<RootDocument title={`${tenant?.name} edit`}>
<AppContainer user={user} tenant={tenant} tenants={tenants} mainClass="grid place-items-center p-2 md:p-4">
<Card class="max-w-2xl w-full">
<div class="p-4 grid gap-2">
<h2 class="text-2xl lg:text-3xl font-semibold pb-2 text-gray-900">"{service.name}" Service Edit</h2>
<p class="text-gray-700 lg:text-sm">You can edit the service here.</p>
<div class="flex gap-1">
<a class={getButtonStyles("secondary", "xs")} href={`/app/${tenant.workspace}/${service.id}`}>
<a class={getButtonStyles("secondary", "xs")} href={`/app/${tenant?.workspace}/${service.id}`}>
Back ⬅️
</a>
</div>
<h2 class="text-2xl lg:text-3xl font-semibold pb-2 text-gray-900">"{service.name}" Service Edit</h2>
<p class="text-gray-700 lg:text-sm">You can edit the service here.</p>
</div>
</Card>
</section>
</AppContainer>
</RootDocument>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,34 +3,33 @@ import type { FC } from "hono/jsx";
import { RootDocument } from "../layouts/root-document.js";
import { Card } from "../components/card.js";
import { getButtonStyles } from "../components/button.js";
import { AppContainer, type AppContainerProps } from "../layouts/app-container.js";

import type { ServiceRecord, TenantRecord } from "@/types/db.mjs";
import type { ServiceRecord } from "@/types/db.mjs";

export const ServiceLandingPage: FC<{
tenant: TenantRecord;
service: ServiceRecord;
}> = ({ service, tenant }) => {
export const ServiceLandingPage: FC<
{
service: ServiceRecord;
} & AppContainerProps
> = ({ user, tenant, tenants, service }) => {
return (
<RootDocument title="Simple Logging Server">
<section class="mx-auto max-w-7xl h-full grid place-items-center px-2">
<Card class="lg:max-w-2xl w-full">
<AppContainer user={user} tenant={tenant} tenants={tenants} mainClass="grid place-items-center p-2 md:p-4">
<Card class="max-w-2xl w-full">
<div class="p-4 grid gap-2">
<h2 class="text-2xl lg:text-3xl font-semibold pb-2 text-gray-900">Service: {service.name}</h2>
<p class="lg:text-sm text-gray-700">Service landing page.</p>
<div class="flex gap-1">
<a class={getButtonStyles("secondary", "xs")} href="/app/logout">
Logout 👋🏼
</a>
<a class={getButtonStyles("secondary", "xs")} href={`/app/${tenant.workspace}`}>
Back ⬅️
<a class={getButtonStyles("secondary", "xs")} href={`/app/${tenant?.workspace}`}>
⬅️ Back
</a>
<a class={getButtonStyles("secondary", "xs")} href={`/app/${tenant.workspace}/${service.id}/edit`}>
Edit ✏️
<a class={getButtonStyles("secondary", "xs")} href={`/app/${tenant?.workspace}/${service.id}/edit`}>
✏️ Edit service
</a>
</div>
<h2 class="text-2xl lg:text-3xl font-semibold pb-2 text-gray-900">Service: {service.name}</h2>
<p class="lg:text-sm text-gray-700">Service landing page.</p>
</div>
</Card>
</section>
</AppContainer>
</RootDocument>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,26 @@ import type { FC } from "hono/jsx";
import { RootDocument } from "../layouts/root-document.js";
import { Card } from "../components/card.js";
import { getButtonStyles } from "../components/button.js";
import { AppContainer, type AppContainerProps } from "../layouts/app-container.js";

import type { TenantRecord } from "@/types/db.mjs";

export const WorkspaceEditPage: FC<{ tenant: TenantRecord }> = ({ tenant }) => {
export const WorkspaceEditPage: FC<{ tenant: TenantRecord } & AppContainerProps> = ({ user, tenants, tenant }) => {
return (
<RootDocument title={`${tenant.name} edit`}>
<section class="mx-auto max-w-7xl h-full grid place-items-center">
<Card class="max-w-md">
<AppContainer user={user} tenants={tenants} tenant={tenant} mainClass="grid place-items-center p-2 md:p-4">
<Card class="max-w-2xl w-full">
<div class="p-4 grid gap-2">
<h2 class="text-2xl lg:text-3xl font-semibold pb-2 text-gray-900">"{tenant.name}" Workspace Edit</h2>
<p class="text-gray-700 lg:text-sm">You can edit the workspace here.</p>
<div class="flex gap-1">
<a class={getButtonStyles("secondary", "xs")} href={`/app/${tenant.workspace}`}>
Back ⬅️
⬅️ Back
</a>
</div>
<h2 class="text-2xl lg:text-3xl font-semibold pb-2 text-gray-900">Edit the "{tenant.name}" organization</h2>
<p class="text-gray-700 lg:text-sm">You can edit the organization here.</p>
</div>
</Card>
</section>
</AppContainer>
</RootDocument>
);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,37 +4,34 @@ import { RootDocument } from "../layouts/root-document.js";
import { Card } from "../components/card.js";
import { getButtonStyles } from "../components/button.js";
import { dateFormatter } from "../utils/date.mjs";
import { AppContainer, type AppContainerProps } from "../layouts/app-container.js";

import type { ServiceRecord, TenantRecord } from "@/types/db.mjs";

export const WorkspaceLandingPage: FC<{
tenant: TenantRecord;
services: Array<ServiceRecord>;
}> = ({ tenant, services }) => {
export const WorkspaceLandingPage: FC<
{
tenant: TenantRecord;
services: Array<ServiceRecord>;
} & AppContainerProps
> = ({ user, tenants, tenant, services }) => {
return (
<RootDocument title="Simple Logging Server">
<section class="mx-auto max-w-7xl h-full grid place-items-center px-2">
<Card class="lg:max-w-2xl w-full">
<RootDocument title={`${tenant.name}`}>
<AppContainer user={user} tenant={tenant} tenants={tenants} mainClass="grid place-items-center p-2 md:p-4">
<Card class="max-w-4xl w-full">
<div class="p-4 grid gap-2">
<h2 class="text-2xl lg:text-3xl font-semibold pb-2 text-gray-900">Services</h2>
<p class="lg:text-sm text-gray-700">These are the services managed by this organization ({tenant.name}).</p>
<div class="flex gap-1">
<a class={getButtonStyles("secondary", "xs")} href="/app/logout">
Logout 👋🏼
</a>
<a class={getButtonStyles("secondary", "xs")} href={`/app?view_all=true`}>
Organizations ⬅️
</a>
<a class={getButtonStyles("secondary", "xs")} href={`/app/${tenant.workspace}/edit`}>
Edit ✏️
✏️ Edit organization
</a>
</div>
<h2 class="text-2xl lg:text-3xl font-semibold pb-2 text-gray-900">Services</h2>
<p class="lg:text-sm text-gray-700">These are the services managed by this organization ({tenant.name}).</p>
<p class="lg:text-sm text-gray-700">
You can view and edit the services managed by this organization here.
</p>
</div>
<div class="border-t overflow-hidden">
<table class="min-w-full divide-y divide-gray-300">
<div class="border-t overflow-x-auto">
<table class="min-w-full divide-y divide-gray-300 overflow-auto">
<thead class="bg-gray-50">
<tr>
<th
Expand Down Expand Up @@ -68,7 +65,7 @@ export const WorkspaceLandingPage: FC<{
</table>
</div>
</Card>
</section>
</AppContainer>
</RootDocument>
);
};
14 changes: 14 additions & 0 deletions src/routers/app/ui/pages/app.index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { FC } from "hono/jsx";

import { RootDocument } from "../layouts/root-document.js";
import { AppContainer, type AppContainerProps } from "../layouts/app-container.js";

export const DashboardLandingPage: FC<{} & Omit<AppContainerProps, "tenant">> = ({ user, tenants }) => {
return (
<RootDocument title="Simple Logging Server">
<AppContainer user={user} tenants={tenants} tenant={null} mainClass="p-2 md:p-4">
<p>There is no content on this page</p>
</AppContainer>
</RootDocument>
);
};
File renamed without changes.
Loading

0 comments on commit 6bfafd5

Please sign in to comment.