Remove old frontend
Signed-off-by: Sacha Al Himdani <sacha@getprobo.com>
This commit is contained in:
@@ -1,38 +0,0 @@
|
||||
import { Toaster } from "@/components/ui/toaster";
|
||||
import { ReactNode } from "react";
|
||||
|
||||
export default function AuthLayout({ children }: { children: ReactNode }) {
|
||||
return (
|
||||
<div className="flex min-h-screen flex-col">
|
||||
<div className="flex flex-1">
|
||||
<div className="flex flex-1 flex-col bg-subtle-bg/40">
|
||||
<div className="flex flex-1 items-center justify-center">
|
||||
<main className="w-full max-w-md p-6">{children}</main>
|
||||
</div>
|
||||
</div>
|
||||
<div className="hidden flex-1 bg-linear-to-br from-gray-900 to-gray-950 lg:block">
|
||||
<div className="flex h-full items-center justify-center p-8">
|
||||
<div className="relative h-full w-full">
|
||||
<div className="absolute right-0 top-1/4 z-10">
|
||||
<img
|
||||
src="/assets/android-chrome-512x512.png"
|
||||
alt="Probo Mascot"
|
||||
className="h-auto w-96"
|
||||
/>
|
||||
</div>
|
||||
<div className="absolute left-8 top-1/3 z-0 text-white">
|
||||
<h1 className="text-4xl font-bold leading-tight">
|
||||
Navigate compliance with
|
||||
<br />
|
||||
confidence thanks to{" "}
|
||||
<span className="text-accent">probo</span>
|
||||
</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<Toaster />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
217
apps/console/src/layouts/MainLayout.tsx
Normal file
217
apps/console/src/layouts/MainLayout.tsx
Normal file
@@ -0,0 +1,217 @@
|
||||
import { Link, Navigate, Outlet, useParams } from "react-router";
|
||||
import {
|
||||
DropdownSeparator,
|
||||
IconArrowBoxLeft,
|
||||
IconBank,
|
||||
IconCircleQuestionmark,
|
||||
IconFire3,
|
||||
IconGroup1,
|
||||
IconInboxEmpty,
|
||||
IconPageTextLine,
|
||||
IconSettingsGear2,
|
||||
IconStore,
|
||||
IconTodo,
|
||||
IconListStack,
|
||||
IconBox,
|
||||
Layout,
|
||||
SidebarItem,
|
||||
UserDropdown as UserDropdownRoot,
|
||||
UserDropdownItem,
|
||||
Skeleton,
|
||||
Dropdown,
|
||||
Button,
|
||||
DropdownItem,
|
||||
IconChevronGrabberVertical,
|
||||
IconPlusLarge,
|
||||
Avatar,
|
||||
} from "@probo/ui";
|
||||
import { useTranslate } from "@probo/i18n";
|
||||
import { graphql } from "relay-runtime";
|
||||
import { useLazyLoadQuery } from "react-relay";
|
||||
import type { MainLayoutQuery as MainLayoutQueryType } from "./__generated__/MainLayoutQuery.graphql";
|
||||
import { Suspense } from "react";
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
import { PageError } from "/components/PageError";
|
||||
|
||||
const MainLayoutQuery = graphql`
|
||||
query MainLayoutQuery {
|
||||
viewer {
|
||||
id
|
||||
user {
|
||||
fullName
|
||||
email
|
||||
}
|
||||
organizations(first: 25) @connection(key: "MainLayout_organizations") {
|
||||
__id
|
||||
edges {
|
||||
node {
|
||||
id
|
||||
name
|
||||
logoUrl
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* Site layout with a header and a sidebar
|
||||
*/
|
||||
export function MainLayout() {
|
||||
const { organizationId } = useParams();
|
||||
const { __ } = useTranslate();
|
||||
|
||||
const prefix = `/organizations/${organizationId}`;
|
||||
|
||||
if (!organizationId) {
|
||||
return <Navigate to="/" />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Layout
|
||||
header={
|
||||
<>
|
||||
<div className="mr-auto">
|
||||
<Suspense fallback={<Skeleton className="w-20 h-8" />}>
|
||||
<OrganizationSelector organizationId={organizationId} />
|
||||
</Suspense>
|
||||
</div>
|
||||
<Suspense fallback={<Skeleton className="w-32 h-8" />}>
|
||||
<UserDropdown />
|
||||
</Suspense>
|
||||
</>
|
||||
}
|
||||
sidebar={
|
||||
<ul className="space-y-[2px]">
|
||||
<SidebarItem
|
||||
label={__("Tasks")}
|
||||
icon={IconInboxEmpty}
|
||||
to={`${prefix}/tasks`}
|
||||
/>
|
||||
<SidebarItem
|
||||
label={__("Measures")}
|
||||
icon={IconTodo}
|
||||
to={`${prefix}/measures`}
|
||||
/>
|
||||
<SidebarItem
|
||||
label={__("Risks")}
|
||||
icon={IconFire3}
|
||||
to={`${prefix}/risks`}
|
||||
/>
|
||||
<SidebarItem
|
||||
label={__("Frameworks")}
|
||||
icon={IconBank}
|
||||
to={`${prefix}/frameworks`}
|
||||
/>
|
||||
<SidebarItem
|
||||
label={__("People")}
|
||||
icon={IconGroup1}
|
||||
to={`${prefix}/people`}
|
||||
/>
|
||||
<SidebarItem
|
||||
label={__("Vendors")}
|
||||
icon={IconStore}
|
||||
to={`${prefix}/vendors`}
|
||||
/>
|
||||
<SidebarItem
|
||||
label={__("Documents")}
|
||||
icon={IconPageTextLine}
|
||||
to={`${prefix}/documents`}
|
||||
/>
|
||||
<SidebarItem
|
||||
label={__("Assets")}
|
||||
icon={IconBox}
|
||||
to={`${prefix}/assets`}
|
||||
/>
|
||||
<SidebarItem
|
||||
label={__("Data")}
|
||||
icon={IconListStack}
|
||||
to={`${prefix}/data`}
|
||||
/>
|
||||
<SidebarItem
|
||||
label={__("Settings")}
|
||||
icon={IconSettingsGear2}
|
||||
to={`${prefix}/settings`}
|
||||
/>
|
||||
</ul>
|
||||
}
|
||||
>
|
||||
<ErrorBoundary FallbackComponent={PageError}>
|
||||
<Outlet />
|
||||
</ErrorBoundary>
|
||||
</Layout>
|
||||
);
|
||||
}
|
||||
|
||||
function UserDropdown() {
|
||||
const { __ } = useTranslate();
|
||||
const user = useLazyLoadQuery<MainLayoutQueryType>(MainLayoutQuery, {}).viewer
|
||||
.user;
|
||||
return (
|
||||
<UserDropdownRoot fullName={user.fullName} email={user.email}>
|
||||
<UserDropdownItem
|
||||
to="/settings"
|
||||
icon={IconSettingsGear2}
|
||||
label={__("Settings")}
|
||||
/>
|
||||
<UserDropdownItem
|
||||
to="mailto:support@getprobo.com"
|
||||
icon={IconCircleQuestionmark}
|
||||
label={__("Help")}
|
||||
/>
|
||||
<DropdownSeparator />
|
||||
<UserDropdownItem
|
||||
variant="danger"
|
||||
to="/logout"
|
||||
icon={IconArrowBoxLeft}
|
||||
label="Logout"
|
||||
/>
|
||||
</UserDropdownRoot>
|
||||
);
|
||||
}
|
||||
|
||||
function OrganizationSelector({ organizationId }: { organizationId: string }) {
|
||||
const organizations = useLazyLoadQuery<MainLayoutQueryType>(
|
||||
MainLayoutQuery,
|
||||
{}
|
||||
).viewer.organizations.edges.map((edge) => edge.node);
|
||||
const currentOrganization = organizations.find(
|
||||
(organization) => organization.id === organizationId
|
||||
);
|
||||
const { __ } = useTranslate();
|
||||
|
||||
return (
|
||||
<Dropdown
|
||||
toggle={
|
||||
<Button
|
||||
className="-ml-3"
|
||||
variant="tertiary"
|
||||
iconAfter={IconChevronGrabberVertical}
|
||||
>
|
||||
{currentOrganization?.name}
|
||||
</Button>
|
||||
}
|
||||
>
|
||||
{organizations.map((organization) => (
|
||||
<DropdownItem
|
||||
asChild
|
||||
key={organization.id}
|
||||
icon={IconCircleQuestionmark}
|
||||
>
|
||||
<Link to={`/organizations/${organization.id}`}>
|
||||
<Avatar src={organization.logoUrl} name={organization.name} />
|
||||
{organization.name}
|
||||
</Link>
|
||||
</DropdownItem>
|
||||
))}
|
||||
<DropdownSeparator />
|
||||
<DropdownItem asChild icon={IconPlusLarge}>
|
||||
<Link to="/organizations/new">
|
||||
<IconPlusLarge size={16} />
|
||||
{__("Add organization")}
|
||||
</Link>
|
||||
</DropdownItem>
|
||||
</Dropdown>
|
||||
);
|
||||
}
|
||||
280
apps/console/src/layouts/__generated__/MainLayoutQuery.graphql.ts
generated
Normal file
280
apps/console/src/layouts/__generated__/MainLayoutQuery.graphql.ts
generated
Normal file
@@ -0,0 +1,280 @@
|
||||
/**
|
||||
* @generated SignedSource<<d411922830ba632f8c48c98caa435a22>>
|
||||
* @lightSyntaxTransform
|
||||
* @nogrep
|
||||
*/
|
||||
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
// @ts-nocheck
|
||||
|
||||
import { ConcreteRequest } from 'relay-runtime';
|
||||
export type MainLayoutQuery$variables = Record<PropertyKey, never>;
|
||||
export type MainLayoutQuery$data = {
|
||||
readonly viewer: {
|
||||
readonly id: string;
|
||||
readonly organizations: {
|
||||
readonly __id: string;
|
||||
readonly edges: ReadonlyArray<{
|
||||
readonly node: {
|
||||
readonly id: string;
|
||||
readonly logoUrl: string | null | undefined;
|
||||
readonly name: string;
|
||||
};
|
||||
}>;
|
||||
};
|
||||
readonly user: {
|
||||
readonly email: string;
|
||||
readonly fullName: string;
|
||||
};
|
||||
};
|
||||
};
|
||||
export type MainLayoutQuery = {
|
||||
response: MainLayoutQuery$data;
|
||||
variables: MainLayoutQuery$variables;
|
||||
};
|
||||
|
||||
const node: ConcreteRequest = (function(){
|
||||
var v0 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "id",
|
||||
"storageKey": null
|
||||
},
|
||||
v1 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "fullName",
|
||||
"storageKey": null
|
||||
},
|
||||
v2 = {
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "email",
|
||||
"storageKey": null
|
||||
},
|
||||
v3 = [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "OrganizationEdge",
|
||||
"kind": "LinkedField",
|
||||
"name": "edges",
|
||||
"plural": true,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Organization",
|
||||
"kind": "LinkedField",
|
||||
"name": "node",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "name",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "logoUrl",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__typename",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "cursor",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "PageInfo",
|
||||
"kind": "LinkedField",
|
||||
"name": "pageInfo",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "endCursor",
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "hasNextPage",
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"kind": "ClientExtension",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"kind": "ScalarField",
|
||||
"name": "__id",
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
v4 = [
|
||||
{
|
||||
"kind": "Literal",
|
||||
"name": "first",
|
||||
"value": 25
|
||||
}
|
||||
];
|
||||
return {
|
||||
"fragment": {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Fragment",
|
||||
"metadata": null,
|
||||
"name": "MainLayoutQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Viewer",
|
||||
"kind": "LinkedField",
|
||||
"name": "viewer",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "User",
|
||||
"kind": "LinkedField",
|
||||
"name": "user",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": "organizations",
|
||||
"args": null,
|
||||
"concreteType": "OrganizationConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "__MainLayout_organizations_connection",
|
||||
"plural": false,
|
||||
"selections": (v3/*: any*/),
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
],
|
||||
"type": "Query",
|
||||
"abstractKey": null
|
||||
},
|
||||
"kind": "Request",
|
||||
"operation": {
|
||||
"argumentDefinitions": [],
|
||||
"kind": "Operation",
|
||||
"name": "MainLayoutQuery",
|
||||
"selections": [
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "Viewer",
|
||||
"kind": "LinkedField",
|
||||
"name": "viewer",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v0/*: any*/),
|
||||
{
|
||||
"alias": null,
|
||||
"args": null,
|
||||
"concreteType": "User",
|
||||
"kind": "LinkedField",
|
||||
"name": "user",
|
||||
"plural": false,
|
||||
"selections": [
|
||||
(v1/*: any*/),
|
||||
(v2/*: any*/),
|
||||
(v0/*: any*/)
|
||||
],
|
||||
"storageKey": null
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v4/*: any*/),
|
||||
"concreteType": "OrganizationConnection",
|
||||
"kind": "LinkedField",
|
||||
"name": "organizations",
|
||||
"plural": false,
|
||||
"selections": (v3/*: any*/),
|
||||
"storageKey": "organizations(first:25)"
|
||||
},
|
||||
{
|
||||
"alias": null,
|
||||
"args": (v4/*: any*/),
|
||||
"filters": null,
|
||||
"handle": "connection",
|
||||
"key": "MainLayout_organizations",
|
||||
"kind": "LinkedHandle",
|
||||
"name": "organizations"
|
||||
}
|
||||
],
|
||||
"storageKey": null
|
||||
}
|
||||
]
|
||||
},
|
||||
"params": {
|
||||
"cacheID": "9ab80df970b8fa7c4eabff75a6730ec5",
|
||||
"id": null,
|
||||
"metadata": {
|
||||
"connection": [
|
||||
{
|
||||
"count": null,
|
||||
"cursor": null,
|
||||
"direction": "forward",
|
||||
"path": [
|
||||
"viewer",
|
||||
"organizations"
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"name": "MainLayoutQuery",
|
||||
"operationKind": "query",
|
||||
"text": "query MainLayoutQuery {\n viewer {\n id\n user {\n fullName\n email\n id\n }\n organizations(first: 25) {\n edges {\n node {\n id\n name\n logoUrl\n __typename\n }\n cursor\n }\n pageInfo {\n endCursor\n hasNextPage\n }\n }\n }\n}\n"
|
||||
}
|
||||
};
|
||||
})();
|
||||
|
||||
(node as any).hash = "fc37d1b70f1a239abb4c959d47ee28fd";
|
||||
|
||||
export default node;
|
||||
Reference in New Issue
Block a user