Improve change request previews: consistency and toolbar (#2487)

This commit is contained in:
Samy Pessé
2024-09-25 12:54:15 +02:00
committed by GitHub
parent 5096f7fbc5
commit f885e887ea
5 changed files with 108 additions and 17 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': patch
---
Improve consistency of change request preview by removing cache-control on response
+5
View File
@@ -0,0 +1,5 @@
---
'gitbook': minor
---
Improve the toolbar for change-requests and revisions to show more actions
@@ -1,9 +1,12 @@
import { Space } from '@gitbook/api';
import { Icon } from '@gitbook/icons';
import React from 'react';
import { ContentPointer, getChangeRequest, getRevision } from '@/lib/api';
import { tcls } from '@/lib/tailwind';
import { DateRelative } from '../primitives';
interface AdminToolbarProps {
content: ContentPointer;
space: Space;
@@ -67,9 +70,27 @@ async function ChangeRequestToolbar(props: { spaceId: string; changeRequestId: s
const changeRequest = await getChangeRequest(spaceId, changeRequestId);
return (
<ToolbarButton href={changeRequest.urls.app}>
Change request #{changeRequest.number}: {changeRequest.subject ?? 'No subject'}
</ToolbarButton>
<Toolbar>
<ToolbarButton title="Open in application" href={changeRequest.urls.app}>
<Icon icon="code-branch" className="size-4" />
</ToolbarButton>
<ToolbarBody>
<p>
#{changeRequest.number}: {changeRequest.subject ?? 'No subject'}
</p>
<p className="text-xs text-light/8 dark:text-light/8">
Change request updated <DateRelative value={changeRequest.updatedAt} />
</p>
</ToolbarBody>
<ToolbarButtonGroups>
<ToolbarButton title="Open in application" href={changeRequest.urls.app}>
<Icon icon="arrow-up-right-from-square" className="size-4" />
</ToolbarButton>
<ToolbarButton title="Refresh" href={'?'}>
<Icon icon="rotate-right" className="size-4" />
</ToolbarButton>
</ToolbarButtonGroups>
</Toolbar>
);
}
@@ -77,34 +98,93 @@ async function RevisionToolbar(props: { spaceId: string; revisionId: string }) {
const { spaceId, revisionId } = props;
const revision = await getRevision(spaceId, revisionId, {
metadata: false,
metadata: true,
});
return (
<ToolbarButton href={revision.urls.app}>
Revision created on {new Date(revision.createdAt).toLocaleDateString()}
</ToolbarButton>
<Toolbar>
<ToolbarButton title="Open in application" href={revision.urls.app}>
<Icon icon="code-commit" className="size-4" />
</ToolbarButton>
<ToolbarBody>
<p>
Revision created <DateRelative value={revision.createdAt} />
</p>
{revision.git ? (
<p className="text-xs text-light/8 dark:text-light/8">{revision.git.message}</p>
) : null}
</ToolbarBody>
<ToolbarButtonGroups>
<ToolbarButton title="Open in application" href={revision.urls.app}>
<Icon icon="arrow-up-right-from-square" className="size-4" />
</ToolbarButton>
{revision.git?.url ? (
<ToolbarButton title="Open git commit" href={revision.git.url}>
<Icon
icon={revision.git.url.includes('github.com') ? 'github' : 'gitlab'}
className="size-4"
/>
</ToolbarButton>
) : null}
</ToolbarButtonGroups>
</Toolbar>
);
}
function ToolbarButton(props: { href: string; children: React.ReactNode }) {
const { href, children } = props;
function Toolbar(props: { children: React.ReactNode }) {
const { children } = props;
return (
<a
href={href}
<div
className={tcls(
'block',
'flex',
'flex-row',
'items-center',
'gap-4',
'text-sm',
'px-4',
'py-1',
'rounded-full',
'truncate',
'text-light',
'dark:text-light',
)}
>
{children}
</div>
);
}
function ToolbarBody(props: { children: React.ReactNode }) {
return <div className="flex flex-col gap-1">{props.children}</div>;
}
function ToolbarButtonGroups(props: { children: React.ReactNode }) {
return <div className="flex flex-row gap-2">{props.children}</div>;
}
function ToolbarButton(props: { title: string; href: string; children: React.ReactNode }) {
const { title, href, children } = props;
return (
<a
title={title}
href={href}
className={tcls(
'flex',
'flex-col',
'items-center',
'justify-center',
'size-11',
'gap-1',
'text-sm',
'rounded-full',
'hover:bg-dark-1',
'hover:text-white',
'truncate',
'text-light',
'dark:text-light',
'dark:hover:bg-dark-2',
'hover:shadow-lg',
)}
>
{children}
-2
View File
@@ -306,8 +306,6 @@ export const getChangeRequest = cache({
signal: options.signal,
});
return cacheResponse(response, {
// We don't cache for long as we currently don't invalidate change-request cache
// and it's only used for preview where perfs are not critical
ttl: 60 * 60,
revalidateBefore: 10 * 60,
});
+6 -3
View File
@@ -276,7 +276,7 @@ export async function middleware(request: NextRequest) {
'private, no-cache, no-store, max-age=0, must-revalidate',
);
} else {
if (resolved.cacheMaxAge) {
if (typeof resolved.cacheMaxAge === 'number') {
const cacheControl = `public, max-age=0, s-maxage=${resolved.cacheMaxAge}, stale-if-error=0`;
if (
@@ -666,14 +666,17 @@ async function lookupSpaceByAPI(
return null;
}
const changeRequest = data.changeRequest ?? lookup.changeRequest;
return {
space: data.space,
changeRequest: data.changeRequest ?? lookup.changeRequest,
changeRequest,
revision: data.revision ?? lookup.revision,
basePath: joinPath(data.basePath, lookup.basePath ?? ''),
pathname: joinPath(data.pathname, alternative.extraPath),
apiToken: data.apiToken,
cacheMaxAge: data.cacheMaxAge,
// We don't cache change requests as they often change and we want to have consistent previews
// Purging the CDN cache will not be efficient enough.
cacheMaxAge: changeRequest ? 0 : data.cacheMaxAge,
cacheTags: data.cacheTags,
...('site' in data
? {