Files
projectsend/resources/js/pages/api/docs.tsx
T
ignacionelson 6e47d76ba6 ProjectSend 2.0.0
Client file sharing, rebuilt from the ground up: a private area per
client, resumable uploads, folders, groups and categories, sharing with
expiry dates and download limits, comments, file versions, an activity
log, a REST API, and sixteen languages.

This repository begins here. ProjectSend 2 was developed privately, and
that development history is not published — the previous generation
remains available, with its own history, at projectsend/legacy.

Free software under the GNU General Public License v2, or (at your
option) any later version.
2026-08-14 01:38:12 -03:00

97 lines
4.4 KiB
TypeScript

import { Head, Link } from '@inertiajs/react';
import Heading from '@/components/heading';
import { Badge } from '@/components/ui/badge';
import { Button } from '@/components/ui/button';
import { useTranslation } from '@/hooks/use-translation';
import AppLayout from '@/layouts/app-layout';
import { type BreadcrumbItem } from '@/types';
interface Endpoint {
method: string;
path: string;
summary: string;
abilities: string[];
}
interface Props {
guide_html: string;
endpoints: Endpoint[];
spec_url: string;
version: string | null;
}
const METHOD_TONE: Record<string, string> = {
GET: 'text-emerald-700 dark:text-emerald-400',
POST: 'text-violet-700 dark:text-violet-400',
PATCH: 'text-amber-700 dark:text-amber-400',
PUT: 'text-amber-700 dark:text-amber-400',
DELETE: 'text-red-700 dark:text-red-400',
};
export default function ApiDocs({ guide_html, endpoints, spec_url, version }: Props) {
const { t } = useTranslation();
const breadcrumbs: BreadcrumbItem[] = [{ title: t('API'), href: '/api/docs' }];
return (
<AppLayout breadcrumbs={breadcrumbs}>
<Head title={t('API')} />
<div className="px-4 py-6">
<div className="flex flex-wrap items-start justify-between gap-4">
<Heading title={t('API')} description={t('How external tools can act on this installation on your behalf.')} />
<div className="flex items-center gap-2">
{version && <Badge variant="secondary">v{version}</Badge>}
<Button variant="outline" size="sm" asChild>
<a href={spec_url} target="_blank" rel="noreferrer">
{t('OpenAPI specification')}
</a>
</Button>
<Button size="sm" asChild>
<Link href={route('api-tokens.index')}>{t('API tokens')}</Link>
</Button>
</div>
</div>
<section className="mb-10">
<h2 className="mb-3 text-base font-semibold">{t('Endpoints')}</h2>
<div className="overflow-x-auto rounded-md border">
<table className="w-full text-sm">
<thead className="bg-muted/50">
<tr className="text-left">
<th className="px-4 py-2 font-medium">{t('Method')}</th>
<th className="px-4 py-2 font-medium">{t('Path')}</th>
<th className="px-4 py-2 font-medium">{t('Description')}</th>
<th className="px-4 py-2 font-medium">{t('Permissions')}</th>
</tr>
</thead>
<tbody>
{endpoints.map((endpoint) => (
<tr key={`${endpoint.method} ${endpoint.path}`} className="border-t">
<td className={`px-4 py-2 font-mono text-xs font-semibold ${METHOD_TONE[endpoint.method] ?? ''}`}>
{endpoint.method}
</td>
<td className="px-4 py-2 font-mono text-xs whitespace-nowrap">{endpoint.path}</td>
<td className="text-muted-foreground px-4 py-2">{endpoint.summary}</td>
<td className="px-4 py-2">
<span className="text-muted-foreground font-mono text-xs">{endpoint.abilities.join(', ') || '—'}</span>
</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
{/*
* Rendered server-side from docs/api-guide.md, a file that
* ships with the application — see ApiDocsController, which
* converts it with HTML input escaped.
*/}
<section className="api-guide max-w-3xl" dangerouslySetInnerHTML={{ __html: guide_html }} />
</div>
</AppLayout>
);
}