chore: update notice instead of using a custom one on acls

This commit is contained in:
Aarnav Tale 2025-04-05 18:54:30 -04:00
parent e8059ca6fd
commit 0e49ccef8e
No known key found for this signature in database
3 changed files with 45 additions and 57 deletions

View File

@ -1,16 +1,45 @@
import { CircleSlash2 } from 'lucide-react'; import {
CircleAlert,
CircleSlash2,
LucideProps,
TriangleAlert,
} from 'lucide-react';
import React from 'react'; import React from 'react';
import Card from '~/components/Card'; import Card from '~/components/Card';
export interface NoticeProps { export interface NoticeProps {
children: React.ReactNode; children: React.ReactNode;
title?: string;
variant?: 'default' | 'error' | 'warning';
icon?: React.ReactElement<LucideProps>;
} }
export default function Notice({ children }: NoticeProps) { export default function Notice({
children,
title,
variant,
icon,
}: NoticeProps) {
return ( return (
<Card className="flex w-full max-w-full gap-4 font-semibold"> <Card variant="flat" className="max-w-2xl my-6">
<CircleSlash2 /> <div className="flex items-center justify-between">
{children} {title ? (
<Card.Title className="text-xl mb-0">{title}</Card.Title>
) : undefined}
{!variant && icon ? icon : iconForVariant(variant)}
</div>
<Card.Text className="mt-4">{children}</Card.Text>
</Card> </Card>
); );
} }
function iconForVariant(variant?: 'default' | 'error' | 'warning') {
switch (variant) {
case 'error':
return <TriangleAlert className="text-red-500" />;
case 'warning':
return <CircleAlert className="text-yellow-500" />;
default:
return <CircleSlash2 />;
}
}

View File

@ -1,45 +0,0 @@
import { AlertIcon } from '@primer/octicons-react';
import React from 'react';
import Card from '~/components/Card';
interface NoticeViewProps {
title: string;
children: React.ReactNode;
}
export function NoticeView({ children, title }: NoticeViewProps) {
return (
<Card variant="flat" className="max-w-2xl my-8">
<div className="flex items-center justify-between">
<Card.Title className="text-xl mb-0">{title}</Card.Title>
<AlertIcon className="w-8 h-8 text-yellow-500" />
</div>
<Card.Text className="mt-4">{children}</Card.Text>
</Card>
);
}
interface ErrorViewProps {
children: string;
}
export function ErrorView({ children }: ErrorViewProps) {
const [title, ...rest] = children.split(':');
const formattedMessage = rest.length > 0 ? rest.join(':').trim() : children;
return (
<Card variant="flat" className="max-w-2xl mb-4">
<div className="flex items-center justify-between">
<Card.Title className="text-xl mb-0">
{title.trim() ?? 'Error'}
</Card.Title>
<AlertIcon className="w-8 h-8 text-red-500" />
</div>
<Card.Text className="mt-4">
Could not apply changes to the ACL policy:
<br />
<span className="font-mono">{formattedMessage}</span>
</Card.Text>
</Card>
);
}

View File

@ -17,7 +17,6 @@ import toast from '~/utils/toast';
import { aclAction } from './acl-action'; import { aclAction } from './acl-action';
import { aclLoader } from './acl-loader'; import { aclLoader } from './acl-loader';
import { Differ, Editor } from './components/cm.client'; import { Differ, Editor } from './components/cm.client';
import { ErrorView, NoticeView } from './components/error';
export async function loader(request: LoaderFunctionArgs<LoadContext>) { export async function loader(request: LoaderFunctionArgs<LoadContext>) {
return aclLoader(request); return aclLoader(request);
@ -57,19 +56,19 @@ export default function Page() {
return ( return (
<div> <div>
{!access ? ( {!access ? (
<NoticeView title="ACL Policy restricted"> <Notice title="ACL Policy restricted" variant="warning">
You do not have the necessary permissions to edit the Access Control You do not have the necessary permissions to edit the Access Control
List policy. Please contact your administrator to request access or to List policy. Please contact your administrator to request access or to
make changes to the ACL policy. make changes to the ACL policy.
</NoticeView> </Notice>
) : !writable ? ( ) : !writable ? (
<NoticeView title="Read-only ACL Policy"> <Notice title="Read-only ACL Policy" variant="error">
The ACL policy mode is most likely set to <Code>file</Code> in your The ACL policy mode is most likely set to <Code>file</Code> in your
Headscale configuration. This means that the ACL file cannot be edited Headscale configuration. This means that the ACL file cannot be edited
through the web interface. In order to resolve this, you'll need to through the web interface. In order to resolve this, you'll need to
set <Code>acl.mode</Code> to <Code>database</Code> in your Headscale set <Code>acl.mode</Code> to <Code>database</Code> in your Headscale
configuration. configuration.
</NoticeView> </Notice>
) : undefined} ) : undefined}
<h1 className="text-2xl font-medium mb-4">Access Control List (ACL)</h1> <h1 className="text-2xl font-medium mb-4">Access Control List (ACL)</h1>
<p className="mb-4 max-w-prose"> <p className="mb-4 max-w-prose">
@ -91,7 +90,13 @@ export default function Page() {
. .
</p> </p>
{fetcher.data?.error !== undefined ? ( {fetcher.data?.error !== undefined ? (
<ErrorView>{fetcher.data.error}</ErrorView> <Notice
variant="error"
title={fetcher.data.error.split(':')[0] ?? 'Error'}
>
{fetcher.data.error.split(':').slice(1).join(': ') ??
'An unknown error occurred while trying to update the ACL policy.'}
</Notice>
) : undefined} ) : undefined}
<Tabs label="ACL Editor" className="mb-4"> <Tabs label="ACL Editor" className="mb-4">
<Tabs.Item <Tabs.Item
@ -150,7 +155,6 @@ export default function Page() {
} }
onPress={() => { onPress={() => {
const formData = new FormData(); const formData = new FormData();
console.log(codePolicy);
formData.append('policy', codePolicy); formData.append('policy', codePolicy);
fetcher.submit(formData, { method: 'PATCH' }); fetcher.submit(formData, { method: 'PATCH' });
}} }}