Skip to content

Commit 156aaba

Browse files
feat(site): show version files diff based on active version (#11686)
1 parent 6bb1a34 commit 156aaba

File tree

9 files changed

+130
-106
lines changed

9 files changed

+130
-106
lines changed

site/src/api/queries/templates.ts

+33
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import {
1515
type QueryOptions,
1616
} from "react-query";
1717
import { delay } from "utils/delay";
18+
import { getTemplateVersionFiles } from "utils/templateVersion";
1819

1920
export const templateByNameKey = (orgId: string, name: string) => [
2021
orgId,
@@ -236,6 +237,38 @@ export const resources = (versionId: string) => {
236237
};
237238
};
238239

240+
export const templateFiles = (fileId: string) => {
241+
return {
242+
queryKey: ["templateFiles", fileId],
243+
queryFn: async () => {
244+
const tarFile = await API.getFile(fileId);
245+
return getTemplateVersionFiles(tarFile);
246+
},
247+
};
248+
};
249+
250+
export const previousTemplateVersion = (
251+
organizationId: string,
252+
templateName: string,
253+
versionName: string,
254+
) => {
255+
return {
256+
queryKey: [
257+
"templateVersion",
258+
organizationId,
259+
templateName,
260+
versionName,
261+
"previous",
262+
],
263+
queryFn: () =>
264+
API.getPreviousTemplateVersionByName(
265+
organizationId,
266+
templateName,
267+
versionName,
268+
),
269+
};
270+
};
271+
239272
const waitBuildToBeFinished = async (version: TemplateVersion) => {
240273
let data: TemplateVersion;
241274
let jobStatus: ProvisionerJobStatus;

site/src/components/TemplateFiles/TemplateFiles.stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ const meta: Meta<typeof TemplateFiles> = {
1818
component: TemplateFiles,
1919
args: {
2020
currentFiles: exampleFiles,
21-
previousFiles: exampleFiles,
21+
baseFiles: exampleFiles,
2222
tab: { value: "0", set: action("change tab") },
2323
},
2424
};

site/src/components/TemplateFiles/TemplateFiles.tsx

+32-8
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import { type Interpolation, type Theme } from "@emotion/react";
2-
import { type FC } from "react";
2+
import { useEffect, type FC } from "react";
33
import { DockerIcon } from "components/Icons/DockerIcon";
44
import { MarkdownIcon } from "components/Icons/MarkdownIcon";
55
import { TerraformIcon } from "components/Icons/TerraformIcon";
66
import { SyntaxHighlighter } from "components/SyntaxHighlighter/SyntaxHighlighter";
7-
import { UseTabResult } from "hooks/useTab";
7+
import { UseTabResult, useTab } from "hooks/useTab";
88
import { AllowedExtension, TemplateVersionFiles } from "utils/templateVersion";
99
import InsertDriveFileOutlined from "@mui/icons-material/InsertDriveFileOutlined";
1010

@@ -39,19 +39,22 @@ const languageByExtension: Record<AllowedExtension, string> = {
3939

4040
interface TemplateFilesProps {
4141
currentFiles: TemplateVersionFiles;
42-
previousFiles?: TemplateVersionFiles;
42+
/**
43+
* Files used to compare with current files
44+
*/
45+
baseFiles?: TemplateVersionFiles;
4346
tab: UseTabResult;
4447
}
4548

4649
export const TemplateFiles: FC<TemplateFilesProps> = ({
4750
currentFiles,
48-
previousFiles,
51+
baseFiles,
4952
tab,
5053
}) => {
5154
const filenames = Object.keys(currentFiles);
5255
const selectedFilename = filenames[Number(tab.value)];
5356
const currentFile = currentFiles[selectedFilename];
54-
const previousFile = previousFiles && previousFiles[selectedFilename];
57+
const previousFile = baseFiles && baseFiles[selectedFilename];
5558

5659
return (
5760
<div css={styles.files}>
@@ -61,9 +64,9 @@ export const TemplateFiles: FC<TemplateFilesProps> = ({
6164
const extension = getExtension(filename) as AllowedExtension;
6265
const icon = iconByExtension[extension];
6366
const hasDiff =
64-
previousFiles &&
65-
previousFiles[filename] &&
66-
currentFiles[filename] !== previousFiles[filename];
67+
baseFiles &&
68+
baseFiles[filename] &&
69+
currentFiles[filename] !== baseFiles[filename];
6770

6871
return (
6972
<button
@@ -93,6 +96,27 @@ export const TemplateFiles: FC<TemplateFilesProps> = ({
9396
</div>
9497
);
9598
};
99+
100+
export const useFileTab = (templateFiles: TemplateVersionFiles | undefined) => {
101+
// Tabs The default tab is the tab that has main.tf but until we loads the
102+
// files and check if main.tf exists we don't know which tab is the default
103+
// one so we just use empty string
104+
const tab = useTab("file", "");
105+
const isLoaded = tab.value !== "";
106+
useEffect(() => {
107+
if (templateFiles && !isLoaded) {
108+
const terraformFileIndex = Object.keys(templateFiles).indexOf("main.tf");
109+
// If main.tf exists use the index if not just use the first tab
110+
tab.set(terraformFileIndex !== -1 ? terraformFileIndex.toString() : "0");
111+
}
112+
}, [isLoaded, tab, templateFiles]);
113+
114+
return {
115+
...tab,
116+
isLoaded,
117+
};
118+
};
119+
96120
const styles = {
97121
tabs: (theme) => ({
98122
display: "flex",

site/src/components/TemplateFiles/hooks.ts

-68
This file was deleted.

site/src/pages/TemplatePage/TemplateFilesPage/TemplateFilesPage.tsx

+21-9
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,41 @@
11
import { type FC } from "react";
22
import { Helmet } from "react-helmet-async";
33
import { Loader } from "components/Loader/Loader";
4-
import { TemplateFiles } from "components/TemplateFiles/TemplateFiles";
5-
import { useFileTab, useTemplateFiles } from "components/TemplateFiles/hooks";
4+
import {
5+
TemplateFiles,
6+
useFileTab,
7+
} from "components/TemplateFiles/TemplateFiles";
68
import { useTemplateLayoutContext } from "pages/TemplatePage/TemplateLayout";
79
import { getTemplatePageTitle } from "../utils";
10+
import { useQuery } from "react-query";
11+
import { previousTemplateVersion, templateFiles } from "api/queries/templates";
12+
import { useOrganizationId } from "hooks";
813

914
const TemplateFilesPage: FC = () => {
15+
const orgId = useOrganizationId();
1016
const { template, activeVersion } = useTemplateLayoutContext();
11-
const { data: templateFiles } = useTemplateFiles(
12-
template.name,
13-
activeVersion,
17+
const { data: currentFiles } = useQuery(
18+
templateFiles(activeVersion.job.file_id),
1419
);
15-
const tab = useFileTab(templateFiles?.currentFiles);
20+
const { data: previousTemplate } = useQuery(
21+
previousTemplateVersion(orgId, template.name, activeVersion.name),
22+
);
23+
const { data: previousFiles } = useQuery({
24+
...templateFiles(previousTemplate?.job.file_id ?? ""),
25+
enabled: Boolean(previousTemplate),
26+
});
27+
const tab = useFileTab(currentFiles);
1628

1729
return (
1830
<>
1931
<Helmet>
2032
<title>{getTemplatePageTitle("Source Code", template)}</title>
2133
</Helmet>
2234

23-
{templateFiles && tab.isLoaded ? (
35+
{previousFiles && currentFiles && tab.isLoaded ? (
2436
<TemplateFiles
25-
currentFiles={templateFiles.currentFiles}
26-
previousFiles={templateFiles.previousFiles}
37+
currentFiles={currentFiles}
38+
baseFiles={previousFiles}
2739
tab={tab}
2840
/>
2941
) : (

site/src/pages/TemplateVersionPage/TemplateVersionPage.tsx

+38-13
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,13 @@ import { useParams } from "react-router-dom";
66
import { pageTitle } from "utils/page";
77
import TemplateVersionPageView from "./TemplateVersionPageView";
88
import { useQuery } from "react-query";
9-
import { templateVersionByName } from "api/queries/templates";
10-
import { useFileTab, useTemplateFiles } from "components/TemplateFiles/hooks";
9+
import {
10+
templateByName,
11+
templateFiles,
12+
templateVersion,
13+
templateVersionByName,
14+
} from "api/queries/templates";
15+
import { useFileTab } from "components/TemplateFiles/TemplateFiles";
1116

1217
type Params = {
1318
version: string;
@@ -18,16 +23,30 @@ export const TemplateVersionPage: FC = () => {
1823
const { version: versionName, template: templateName } =
1924
useParams() as Params;
2025
const orgId = useOrganizationId();
21-
const templateVersionQuery = useQuery(
26+
27+
/**
28+
* Template version files
29+
*/
30+
const templateQuery = useQuery(templateByName(orgId, templateName));
31+
const selectedVersionQuery = useQuery(
2232
templateVersionByName(orgId, templateName, versionName),
2333
);
24-
const { data: templateFiles, error: templateFilesError } = useTemplateFiles(
25-
templateName,
26-
templateVersionQuery.data,
27-
);
28-
const tab = useFileTab(templateFiles?.currentFiles);
34+
const selectedVersionFilesQuery = useQuery({
35+
...templateFiles(selectedVersionQuery.data?.job.file_id ?? ""),
36+
enabled: Boolean(selectedVersionQuery.data),
37+
});
38+
const activeVersionQuery = useQuery({
39+
...templateVersion(templateQuery.data?.active_version_id ?? ""),
40+
enabled: Boolean(templateQuery.data),
41+
});
42+
const activeVersionFilesQuery = useQuery({
43+
...templateFiles(activeVersionQuery.data?.job.file_id ?? ""),
44+
enabled: Boolean(activeVersionQuery.data),
45+
});
46+
const tab = useFileTab(selectedVersionFilesQuery.data);
47+
2948
const permissions = usePermissions();
30-
const versionId = templateVersionQuery.data?.id;
49+
const versionId = selectedVersionQuery.data?.id;
3150
const createWorkspaceUrl = useMemo(() => {
3251
const params = new URLSearchParams();
3352
if (versionId) {
@@ -44,10 +63,16 @@ export const TemplateVersionPage: FC = () => {
4463
</Helmet>
4564

4665
<TemplateVersionPageView
47-
error={templateVersionQuery.error || templateFilesError}
48-
currentVersion={templateVersionQuery.data}
49-
currentFiles={templateFiles?.currentFiles}
50-
previousFiles={templateFiles?.previousFiles}
66+
error={
67+
templateQuery.error ||
68+
selectedVersionQuery.error ||
69+
selectedVersionFilesQuery.error ||
70+
activeVersionQuery.error ||
71+
activeVersionFilesQuery.error
72+
}
73+
currentVersion={selectedVersionQuery.data}
74+
currentFiles={selectedVersionFilesQuery.data}
75+
baseFiles={activeVersionFilesQuery.data}
5176
versionName={versionName}
5277
templateName={templateName}
5378
tab={tab}

site/src/pages/TemplateVersionPage/TemplateVersionPageView.stories.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ const defaultArgs: TemplateVersionPageViewProps = {
3838
"some.tpl": `{{.Name}}`,
3939
"some.sh": `echo "Hello world"`,
4040
},
41-
previousFiles: undefined,
41+
baseFiles: undefined,
4242
error: undefined,
4343
};
4444

site/src/pages/TemplateVersionPage/TemplateVersionPageView.tsx

+3-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ export interface TemplateVersionPageViewProps {
2828
error: unknown;
2929
currentVersion: TemplateVersion | undefined;
3030
currentFiles: TemplateVersionFiles | undefined;
31-
previousFiles: TemplateVersionFiles | undefined;
31+
baseFiles: TemplateVersionFiles | undefined;
3232
}
3333

3434
export const TemplateVersionPageView: FC<TemplateVersionPageViewProps> = ({
@@ -38,7 +38,7 @@ export const TemplateVersionPageView: FC<TemplateVersionPageViewProps> = ({
3838
createWorkspaceUrl,
3939
currentVersion,
4040
currentFiles,
41-
previousFiles,
41+
baseFiles,
4242
error,
4343
}) => {
4444
return (
@@ -103,7 +103,7 @@ export const TemplateVersionPageView: FC<TemplateVersionPageViewProps> = ({
103103
<TemplateFiles
104104
tab={tab}
105105
currentFiles={currentFiles}
106-
previousFiles={previousFiles}
106+
baseFiles={baseFiles}
107107
/>
108108
</>
109109
)}

site/src/utils/templateVersion.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,13 @@
1-
import * as API from "api/api";
21
import { FileTree, createFile } from "./filetree";
32
import { TarReader } from "./tar";
43

54
// Content by filename
65
export type TemplateVersionFiles = Record<string, string>;
76

87
export const getTemplateVersionFiles = async (
9-
fileId: string,
8+
tarFile: ArrayBuffer,
109
): Promise<TemplateVersionFiles> => {
1110
const files: TemplateVersionFiles = {};
12-
const tarFile = await API.getFile(fileId);
1311
const tarReader = new TarReader();
1412
await tarReader.readFile(tarFile);
1513
for (const file of tarReader.fileInfo) {

0 commit comments

Comments
 (0)