mirror of
https://github.com/GitbookIO/gitbook.git
synced 2026-09-23 02:53:29 +00:00
Improve change request previews: consistency and toolbar (#2487)
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'gitbook': patch
|
||||
---
|
||||
|
||||
Improve consistency of change request preview by removing cache-control on response
|
||||
@@ -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}
|
||||
|
||||
@@ -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,
|
||||
});
|
||||
|
||||
@@ -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
|
||||
? {
|
||||
|
||||
Reference in New Issue
Block a user