Make sure page reloads when version is selected

Signed-off-by: Émile Ré <emile@getprobo.com>
This commit is contained in:
Émile Ré
2026-01-27 16:04:01 +04:00
parent 7c721e5ff7
commit 147ea0f08f
5 changed files with 177 additions and 23 deletions

View File

@@ -1,5 +1,5 @@
/**
* @generated SignedSource<<fbb0d6a61d0aa33c1c114772d54efd2a>>
* @generated SignedSource<<369fa1f3218710cdc3fedb7e161f4e13>>
* @lightSyntaxTransform
* @nogrep
*/
@@ -12,10 +12,19 @@ import { ConcreteRequest } from 'relay-runtime';
import { FragmentRefs } from "relay-runtime";
export type DocumentVersionsDropdownMenuQuery$variables = {
documentId: string;
versionId: string;
versionSpecified: boolean;
};
export type DocumentVersionsDropdownMenuQuery$data = {
readonly document: {
readonly __typename: "Document";
readonly lastVersion?: {
readonly edges: ReadonlyArray<{
readonly node: {
readonly id: string;
};
}>;
};
readonly versions: {
readonly edges: ReadonlyArray<{
readonly node: {
@@ -29,6 +38,14 @@ export type DocumentVersionsDropdownMenuQuery$data = {
// value in case none of the concrete values match.
readonly __typename: "%other";
};
readonly version?: {
readonly __typename: "DocumentVersion";
readonly id: string;
} | {
// This will never be '%other', but we need some
// value in case none of the concrete values match.
readonly __typename: "%other";
};
};
export type DocumentVersionsDropdownMenuQuery = {
response: DocumentVersionsDropdownMenuQuery$data;
@@ -41,6 +58,16 @@ var v0 = [
"defaultValue": null,
"kind": "LocalArgument",
"name": "documentId"
},
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "versionId"
},
{
"defaultValue": null,
"kind": "LocalArgument",
"name": "versionSpecified"
}
],
v1 = [
@@ -70,7 +97,70 @@ v4 = {
"kind": "ScalarField",
"name": "id",
"storageKey": null
};
},
v5 = [
(v4/*: any*/)
],
v6 = {
"condition": "versionSpecified",
"kind": "Condition",
"passingValue": false,
"selections": [
{
"alias": "lastVersion",
"args": [
{
"kind": "Literal",
"name": "first",
"value": 1
},
{
"kind": "Literal",
"name": "orderBy",
"value": {
"direction": "DESC",
"field": "CREATED_AT"
}
}
],
"concreteType": "DocumentVersionConnection",
"kind": "LinkedField",
"name": "versions",
"plural": false,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "DocumentVersionEdge",
"kind": "LinkedField",
"name": "edges",
"plural": true,
"selections": [
{
"alias": null,
"args": null,
"concreteType": "DocumentVersion",
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": (v5/*: any*/),
"storageKey": null
}
],
"storageKey": null
}
],
"storageKey": "versions(first:1,orderBy:{\"direction\":\"DESC\",\"field\":\"CREATED_AT\"})"
}
]
},
v7 = [
{
"kind": "Variable",
"name": "id",
"variableName": "versionId"
}
];
return {
"fragment": {
"argumentDefinitions": (v0/*: any*/),
@@ -128,13 +218,39 @@ return {
}
],
"storageKey": "versions(first:20)"
}
},
(v6/*: any*/)
],
"type": "Document",
"abstractKey": null
}
],
"storageKey": null
},
{
"condition": "versionSpecified",
"kind": "Condition",
"passingValue": true,
"selections": [
{
"alias": "version",
"args": (v7/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v2/*: any*/),
{
"kind": "InlineFragment",
"selections": (v5/*: any*/),
"type": "DocumentVersion",
"abstractKey": null
}
],
"storageKey": null
}
]
}
],
"type": "Query",
@@ -219,7 +335,8 @@ return {
}
],
"storageKey": "versions(first:20)"
}
},
(v6/*: any*/)
],
"type": "Document",
"abstractKey": null
@@ -227,20 +344,40 @@ return {
(v4/*: any*/)
],
"storageKey": null
},
{
"condition": "versionSpecified",
"kind": "Condition",
"passingValue": true,
"selections": [
{
"alias": "version",
"args": (v7/*: any*/),
"concreteType": null,
"kind": "LinkedField",
"name": "node",
"plural": false,
"selections": [
(v2/*: any*/),
(v4/*: any*/)
],
"storageKey": null
}
]
}
]
},
"params": {
"cacheID": "914f2c11640879dfb202ba668fb0bff0",
"cacheID": "f940f62593d1a96d898b128a11e8cf3b",
"id": null,
"metadata": {},
"name": "DocumentVersionsDropdownMenuQuery",
"operationKind": "query",
"text": "query DocumentVersionsDropdownMenuQuery(\n $documentId: ID!\n) {\n document: node(id: $documentId) {\n __typename\n ... on Document {\n versions(first: 20) {\n edges {\n node {\n id\n ...DocumentVersionsDropdownItemFragment\n }\n }\n }\n }\n id\n }\n}\n\nfragment DocumentVersionsDropdownItemFragment on DocumentVersion {\n id\n version\n status\n publishedAt\n updatedAt\n}\n"
"text": "query DocumentVersionsDropdownMenuQuery(\n $documentId: ID!\n $versionId: ID!\n $versionSpecified: Boolean!\n) {\n document: node(id: $documentId) {\n __typename\n ... on Document {\n versions(first: 20) {\n edges {\n node {\n id\n ...DocumentVersionsDropdownItemFragment\n }\n }\n }\n lastVersion: versions(first: 1, orderBy: {field: CREATED_AT, direction: DESC}) @skip(if: $versionSpecified) {\n edges {\n node {\n id\n }\n }\n }\n }\n id\n }\n version: node(id: $versionId) @include(if: $versionSpecified) {\n __typename\n ... on DocumentVersion {\n id\n }\n id\n }\n}\n\nfragment DocumentVersionsDropdownItemFragment on DocumentVersion {\n id\n version\n status\n publishedAt\n updatedAt\n}\n"
}
};
})();
(node as any).hash = "4cc270e68cee032d619dc7a348715d83";
(node as any).hash = "33baa920362db3aef46644b80477d78a";
export default node;

View File

@@ -149,7 +149,7 @@ export function DocumentLayout(props: { queryRef: PreloadedQuery<DocumentLayoutQ
{__("Publish")}
</Button>
)}
<DocumentVersionsDropdown currentVersionId={currentVersion.id} />
<DocumentVersionsDropdown />
<DocumentActionsDropdownn documentFragmentRef={document} versionFragmentRef={currentVersion} />
</div>
</div>

View File

@@ -31,9 +31,11 @@ function DocumentLayoutQueryLoader() {
}
export default function DocumentLayoutLoader() {
const { documentId, versionId } = useParams();
return (
<CoreRelayProvider>
<Suspense fallback={<PageSkeleton />}>
<Suspense key={`${documentId}-${versionId}`} fallback={<PageSkeleton />}>
<DocumentLayoutQueryLoader />
</Suspense>
</CoreRelayProvider>

View File

@@ -8,12 +8,8 @@ import type { DocumentVersionsDropdownMenuQuery } from "#/__generated__/core/Doc
import { DocumentVersionsDropdownMenu, documentVersionsDropdownMenuQuery } from "./DocumentVersionsDropdownMenu";
export function DocumentVersionsDropdown(props: {
currentVersionId: string;
}) {
const { currentVersionId } = props;
const { documentId } = useParams();
export function DocumentVersionsDropdown() {
const { documentId, versionId } = useParams();
if (!documentId) {
throw new Error(":documentId missing in route params");
}
@@ -23,7 +19,7 @@ export function DocumentVersionsDropdown(props: {
return (
<Dropdown
onOpenChange={open => open && !queryRef && loadQuery({ documentId })}
onOpenChange={open => open && !queryRef && loadQuery({ documentId, versionId: versionId ?? "", versionSpecified: !!versionId })}
toggle={(
<Button icon={IconClock} variant="secondary">
{__("Version history")}
@@ -33,7 +29,9 @@ export function DocumentVersionsDropdown(props: {
>
<Suspense>
{queryRef
&& <DocumentVersionsDropdownMenu currentVersionId={currentVersionId} queryRef={queryRef} />}
&& (
<DocumentVersionsDropdownMenu queryRef={queryRef} />
)}
</Suspense>
</Dropdown>
);

View File

@@ -6,7 +6,7 @@ import type { DocumentVersionsDropdownMenuQuery } from "#/__generated__/core/Doc
import { DocumentVersionsDropdownItem } from "./DocumentVersionsDropdownItem";
export const documentVersionsDropdownMenuQuery = graphql`
query DocumentVersionsDropdownMenuQuery($documentId: ID!) {
query DocumentVersionsDropdownMenuQuery($documentId: ID! $versionId: ID! $versionSpecified: Boolean!) {
document: node(id: $documentId) {
__typename
... on Document {
@@ -18,32 +18,49 @@ export const documentVersionsDropdownMenuQuery = graphql`
}
}
}
# We use this on /documents/:documentId
lastVersion: versions(first: 1 orderBy: { field: CREATED_AT, direction: DESC }) @skip(if: $versionSpecified) {
edges {
node {
id
}
}
}
}
}
# We use this on /documents/:documentId/versions/:versionId
version: node(id: $versionId) @include(if: $versionSpecified) {
__typename
... on DocumentVersion {
id
}
}
}
`;
export function DocumentVersionsDropdownMenu(props: {
currentVersionId: string;
queryRef: PreloadedQuery<DocumentVersionsDropdownMenuQuery>;
}) {
const { currentVersionId, queryRef } = props;
const { queryRef } = props;
const { document } = usePreloadedQuery<DocumentVersionsDropdownMenuQuery>(
const { document, version } = usePreloadedQuery<DocumentVersionsDropdownMenuQuery>(
documentVersionsDropdownMenuQuery,
queryRef,
);
if (document.__typename !== "Document") {
if (document.__typename !== "Document" || (version && version.__typename !== "DocumentVersion")) {
throw new Error("invalid type for node");
}
const lastVersion = document.lastVersion?.edges[0].node;
const currentVersion = lastVersion ?? version as NonNullable<typeof lastVersion | typeof version>;
return (
<>
{document.versions.edges.map(({ node: version }) => (
<DocumentVersionsDropdownItem
key={version.id}
fragmentRef={version}
active={version.id === currentVersionId}
active={version.id === currentVersion.id}
/>
))}
</>