mirror of
https://github.com/coder/coder.git
synced 2025-07-15 22:20:27 +00:00
chore(site): remove template version machine (#10315)
This commit is contained in:
@ -1,15 +0,0 @@
|
||||
import * as API from "api/api";
|
||||
|
||||
export const templateVersionLogs = (versionId: string) => {
|
||||
return {
|
||||
queryKey: ["templateVersion", versionId, "logs"],
|
||||
queryFn: () => API.getTemplateVersionLogs(versionId),
|
||||
};
|
||||
};
|
||||
|
||||
export const richParameters = (versionId: string) => {
|
||||
return {
|
||||
queryKey: ["templateVersion", versionId, "richParameters"],
|
||||
queryFn: () => API.getTemplateVersionRichParameters(versionId),
|
||||
};
|
||||
};
|
@ -50,6 +50,18 @@ export const templateVersion = (versionId: string) => {
|
||||
};
|
||||
};
|
||||
|
||||
export const templateVersionByName = (
|
||||
orgId: string,
|
||||
templateName: string,
|
||||
versionName: string,
|
||||
) => {
|
||||
return {
|
||||
queryKey: ["templateVersion", orgId, templateName, versionName],
|
||||
queryFn: () =>
|
||||
API.getTemplateVersionByName(orgId, templateName, versionName),
|
||||
};
|
||||
};
|
||||
|
||||
export const templateVersions = (templateId: string) => {
|
||||
return {
|
||||
queryKey: ["templateVersions", templateId],
|
||||
@ -127,6 +139,20 @@ const createTemplateFn = async (options: {
|
||||
});
|
||||
};
|
||||
|
||||
export const templateVersionLogs = (versionId: string) => {
|
||||
return {
|
||||
queryKey: ["templateVersion", versionId, "logs"],
|
||||
queryFn: () => API.getTemplateVersionLogs(versionId),
|
||||
};
|
||||
};
|
||||
|
||||
export const richParameters = (versionId: string) => {
|
||||
return {
|
||||
queryKey: ["templateVersion", versionId, "richParameters"],
|
||||
queryFn: () => API.getTemplateVersionRichParameters(versionId),
|
||||
};
|
||||
};
|
||||
|
||||
const waitBuildToBeFinished = async (version: TemplateVersion) => {
|
||||
let data: TemplateVersion;
|
||||
let jobStatus: ProvisionerJobStatus;
|
||||
|
68
site/src/components/TemplateFiles/hooks.ts
Normal file
68
site/src/components/TemplateFiles/hooks.ts
Normal file
@ -0,0 +1,68 @@
|
||||
import { TemplateVersion } from "api/typesGenerated";
|
||||
import { useTab } from "hooks/useTab";
|
||||
import { useEffect } from "react";
|
||||
import { useQuery } from "react-query";
|
||||
import {
|
||||
TemplateVersionFiles,
|
||||
getTemplateVersionFiles,
|
||||
} from "utils/templateVersion";
|
||||
import * as API from "api/api";
|
||||
|
||||
export const useFileTab = (templateFiles: TemplateVersionFiles | undefined) => {
|
||||
// Tabs The default tab is the tab that has main.tf but until we loads the
|
||||
// files and check if main.tf exists we don't know which tab is the default
|
||||
// one so we just use empty string
|
||||
const tab = useTab("file", "");
|
||||
const isLoaded = tab.value !== "";
|
||||
useEffect(() => {
|
||||
if (templateFiles && !isLoaded) {
|
||||
const terraformFileIndex = Object.keys(templateFiles).indexOf("main.tf");
|
||||
// If main.tf exists use the index if not just use the first tab
|
||||
tab.set(terraformFileIndex !== -1 ? terraformFileIndex.toString() : "0");
|
||||
}
|
||||
}, [isLoaded, tab, templateFiles]);
|
||||
|
||||
return {
|
||||
...tab,
|
||||
isLoaded,
|
||||
};
|
||||
};
|
||||
|
||||
export const useTemplateFiles = (
|
||||
templateName: string,
|
||||
version: TemplateVersion | undefined,
|
||||
) => {
|
||||
return useQuery({
|
||||
queryKey: ["templateFiles", templateName, version],
|
||||
queryFn: () => {
|
||||
if (!version) {
|
||||
return;
|
||||
}
|
||||
return getTemplateFilesWithDiff(templateName, version);
|
||||
},
|
||||
enabled: version !== undefined,
|
||||
});
|
||||
};
|
||||
|
||||
const getTemplateFilesWithDiff = async (
|
||||
templateName: string,
|
||||
version: TemplateVersion,
|
||||
) => {
|
||||
const previousVersion = await API.getPreviousTemplateVersionByName(
|
||||
version.organization_id!,
|
||||
templateName,
|
||||
version.name,
|
||||
);
|
||||
const loadFilesPromises: ReturnType<typeof getTemplateVersionFiles>[] = [];
|
||||
loadFilesPromises.push(getTemplateVersionFiles(version.job.file_id));
|
||||
if (previousVersion) {
|
||||
loadFilesPromises.push(
|
||||
getTemplateVersionFiles(previousVersion.job.file_id),
|
||||
);
|
||||
}
|
||||
const [currentFiles, previousFiles] = await Promise.all(loadFilesPromises);
|
||||
return {
|
||||
currentFiles,
|
||||
previousFiles,
|
||||
};
|
||||
};
|
@ -1,6 +1,6 @@
|
||||
import { useQuery, useMutation } from "react-query";
|
||||
import { templateVersionLogs } from "api/queries/templateVersions";
|
||||
import {
|
||||
templateVersionLogs,
|
||||
templateByName,
|
||||
templateVersion,
|
||||
templateVersionVariables,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useQuery, useMutation } from "react-query";
|
||||
import { templateVersionLogs } from "api/queries/templateVersions";
|
||||
import {
|
||||
templateVersionLogs,
|
||||
JobError,
|
||||
createTemplate,
|
||||
templateExamples,
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { useQuery, useMutation } from "react-query";
|
||||
import { templateVersionLogs } from "api/queries/templateVersions";
|
||||
import {
|
||||
templateVersionLogs,
|
||||
JobError,
|
||||
createTemplate,
|
||||
templateVersionVariables,
|
||||
|
@ -22,11 +22,11 @@ import { useMutation, useQuery, useQueryClient } from "react-query";
|
||||
import {
|
||||
templateByName,
|
||||
templateVersionExternalAuth,
|
||||
richParameters,
|
||||
} from "api/queries/templates";
|
||||
import { autoCreateWorkspace, createWorkspace } from "api/queries/workspaces";
|
||||
import { checkAuthorization } from "api/queries/authCheck";
|
||||
import { CreateWSPermissions, createWorkspaceChecks } from "./permissions";
|
||||
import { richParameters } from "api/queries/templateVersions";
|
||||
import { paramsUsedToCreateWorkspace } from "utils/workspace";
|
||||
import { useEffectEvent } from "hooks/hookPolyfills";
|
||||
|
||||
|
@ -1,77 +1,14 @@
|
||||
import { useQuery } from "react-query";
|
||||
import { getPreviousTemplateVersionByName } from "api/api";
|
||||
import { TemplateVersion } from "api/typesGenerated";
|
||||
import { Loader } from "components/Loader/Loader";
|
||||
import { TemplateFiles } from "components/TemplateFiles/TemplateFiles";
|
||||
import { useTemplateLayoutContext } from "pages/TemplatePage/TemplateLayout";
|
||||
import { useOrganizationId } from "hooks/useOrganizationId";
|
||||
import { useTab } from "hooks/useTab";
|
||||
import { FC, useEffect } from "react";
|
||||
import { FC } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import {
|
||||
getTemplateVersionFiles,
|
||||
TemplateVersionFiles,
|
||||
} from "utils/templateVersion";
|
||||
import { getTemplatePageTitle } from "../utils";
|
||||
|
||||
const fetchTemplateFiles = async (
|
||||
organizationId: string,
|
||||
templateName: string,
|
||||
activeVersion: TemplateVersion,
|
||||
) => {
|
||||
const previousVersion = await getPreviousTemplateVersionByName(
|
||||
organizationId,
|
||||
templateName,
|
||||
activeVersion.name,
|
||||
);
|
||||
const loadFilesPromises: ReturnType<typeof getTemplateVersionFiles>[] = [];
|
||||
loadFilesPromises.push(getTemplateVersionFiles(activeVersion));
|
||||
if (previousVersion) {
|
||||
loadFilesPromises.push(getTemplateVersionFiles(previousVersion));
|
||||
}
|
||||
const [currentFiles, previousFiles] = await Promise.all(loadFilesPromises);
|
||||
return {
|
||||
currentFiles,
|
||||
previousFiles,
|
||||
};
|
||||
};
|
||||
|
||||
const useTemplateFiles = (
|
||||
organizationId: string,
|
||||
templateName: string,
|
||||
activeVersion: TemplateVersion,
|
||||
) =>
|
||||
useQuery({
|
||||
queryKey: ["templateFiles", templateName],
|
||||
queryFn: () =>
|
||||
fetchTemplateFiles(organizationId, templateName, activeVersion),
|
||||
});
|
||||
|
||||
const useFileTab = (templateFiles: TemplateVersionFiles | undefined) => {
|
||||
// Tabs The default tab is the tab that has main.tf but until we loads the
|
||||
// files and check if main.tf exists we don't know which tab is the default
|
||||
// one so we just use empty string
|
||||
const tab = useTab("file", "");
|
||||
const isLoaded = tab.value !== "";
|
||||
useEffect(() => {
|
||||
if (templateFiles && !isLoaded) {
|
||||
const terraformFileIndex = Object.keys(templateFiles).indexOf("main.tf");
|
||||
// If main.tf exists use the index if not just use the first tab
|
||||
tab.set(terraformFileIndex !== -1 ? terraformFileIndex.toString() : "0");
|
||||
}
|
||||
}, [isLoaded, tab, templateFiles]);
|
||||
|
||||
return {
|
||||
...tab,
|
||||
isLoaded,
|
||||
};
|
||||
};
|
||||
import { useFileTab, useTemplateFiles } from "components/TemplateFiles/hooks";
|
||||
|
||||
const TemplateFilesPage: FC = () => {
|
||||
const { template, activeVersion } = useTemplateLayoutContext();
|
||||
const orgId = useOrganizationId();
|
||||
const { data: templateFiles } = useTemplateFiles(
|
||||
orgId,
|
||||
template.name,
|
||||
activeVersion,
|
||||
);
|
||||
|
@ -1,13 +1,13 @@
|
||||
import { useMachine } from "@xstate/react";
|
||||
import { usePermissions } from "hooks/usePermissions";
|
||||
import { useOrganizationId } from "hooks/useOrganizationId";
|
||||
import { useTab } from "hooks/useTab";
|
||||
import { type FC, useMemo } from "react";
|
||||
import { Helmet } from "react-helmet-async";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { pageTitle } from "utils/page";
|
||||
import { templateVersionMachine } from "xServices/templateVersion/templateVersionXService";
|
||||
import TemplateVersionPageView from "./TemplateVersionPageView";
|
||||
import { useQuery } from "react-query";
|
||||
import { templateVersionByName } from "api/queries/templates";
|
||||
import { useFileTab, useTemplateFiles } from "components/TemplateFiles/hooks";
|
||||
|
||||
type Params = {
|
||||
version: string;
|
||||
@ -18,13 +18,16 @@ export const TemplateVersionPage: FC = () => {
|
||||
const { version: versionName, template: templateName } =
|
||||
useParams() as Params;
|
||||
const orgId = useOrganizationId();
|
||||
const [state] = useMachine(templateVersionMachine, {
|
||||
context: { templateName, versionName, orgId },
|
||||
});
|
||||
const tab = useTab("file", "0");
|
||||
const templateVersionQuery = useQuery(
|
||||
templateVersionByName(orgId, templateName, versionName),
|
||||
);
|
||||
const { data: templateFiles, error: templateFilesError } = useTemplateFiles(
|
||||
templateName,
|
||||
templateVersionQuery.data,
|
||||
);
|
||||
const tab = useFileTab(templateFiles?.currentFiles);
|
||||
const permissions = usePermissions();
|
||||
|
||||
const versionId = state.context.currentVersion?.id;
|
||||
const versionId = templateVersionQuery.data?.id;
|
||||
const createWorkspaceUrl = useMemo(() => {
|
||||
const params = new URLSearchParams();
|
||||
if (versionId) {
|
||||
@ -41,7 +44,10 @@ export const TemplateVersionPage: FC = () => {
|
||||
</Helmet>
|
||||
|
||||
<TemplateVersionPageView
|
||||
context={state.context}
|
||||
error={templateVersionQuery.error || templateFilesError}
|
||||
currentVersion={templateVersionQuery.data}
|
||||
currentFiles={templateFiles?.currentFiles}
|
||||
previousFiles={templateFiles?.previousFiles}
|
||||
versionName={versionName}
|
||||
templateName={templateName}
|
||||
tab={tab}
|
||||
|
@ -2,7 +2,6 @@ import { action } from "@storybook/addon-actions";
|
||||
import { UseTabResult } from "hooks/useTab";
|
||||
import {
|
||||
mockApiError,
|
||||
MockOrganization,
|
||||
MockTemplate,
|
||||
MockTemplateVersion,
|
||||
} from "testHelpers/entities";
|
||||
@ -32,18 +31,15 @@ const defaultArgs: TemplateVersionPageViewProps = {
|
||||
tab,
|
||||
templateName: MockTemplate.name,
|
||||
versionName: MockTemplateVersion.name,
|
||||
context: {
|
||||
templateName: MockTemplate.name,
|
||||
orgId: MockOrganization.id,
|
||||
versionName: MockTemplateVersion.name,
|
||||
currentVersion: MockTemplateVersion,
|
||||
currentFiles: {
|
||||
"README.md": readmeContent,
|
||||
"main.tf": `{}`,
|
||||
"some.tpl": `{{.Name}}`,
|
||||
"some.sh": `echo "Hello world"`,
|
||||
},
|
||||
currentVersion: MockTemplateVersion,
|
||||
currentFiles: {
|
||||
"README.md": readmeContent,
|
||||
"main.tf": `{}`,
|
||||
"some.tpl": `{{.Name}}`,
|
||||
"some.sh": `echo "Hello world"`,
|
||||
},
|
||||
previousFiles: undefined,
|
||||
error: undefined,
|
||||
};
|
||||
|
||||
const meta: Meta<typeof TemplateVersionPageView> = {
|
||||
@ -59,13 +55,11 @@ export const Default: Story = {};
|
||||
|
||||
export const Error: Story = {
|
||||
args: {
|
||||
context: {
|
||||
...defaultArgs.context,
|
||||
currentVersion: undefined,
|
||||
currentFiles: undefined,
|
||||
error: mockApiError({
|
||||
message: "Error on loading the template version",
|
||||
}),
|
||||
},
|
||||
...defaultArgs,
|
||||
currentVersion: undefined,
|
||||
currentFiles: undefined,
|
||||
error: mockApiError({
|
||||
message: "Error on loading the template version",
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
@ -16,29 +16,31 @@ import { UseTabResult } from "hooks/useTab";
|
||||
import { type FC } from "react";
|
||||
import { Link as RouterLink } from "react-router-dom";
|
||||
import { createDayString } from "utils/createDayString";
|
||||
import { TemplateVersionMachineContext } from "xServices/templateVersion/templateVersionXService";
|
||||
import { ErrorAlert } from "components/Alert/ErrorAlert";
|
||||
import { TemplateVersion } from "api/typesGenerated";
|
||||
import { TemplateVersionFiles } from "utils/templateVersion";
|
||||
|
||||
export interface TemplateVersionPageViewProps {
|
||||
/**
|
||||
* Used to display the version name before loading the version in the API
|
||||
*/
|
||||
versionName: string;
|
||||
templateName: string;
|
||||
tab: UseTabResult;
|
||||
context: TemplateVersionMachineContext;
|
||||
createWorkspaceUrl?: string;
|
||||
error: unknown;
|
||||
currentVersion: TemplateVersion | undefined;
|
||||
currentFiles: TemplateVersionFiles | undefined;
|
||||
previousFiles: TemplateVersionFiles | undefined;
|
||||
}
|
||||
|
||||
export const TemplateVersionPageView: FC<TemplateVersionPageViewProps> = ({
|
||||
context,
|
||||
tab,
|
||||
versionName,
|
||||
templateName,
|
||||
createWorkspaceUrl,
|
||||
currentVersion,
|
||||
currentFiles,
|
||||
previousFiles,
|
||||
error,
|
||||
}) => {
|
||||
const { currentFiles, error, currentVersion, previousFiles } = context;
|
||||
|
||||
return (
|
||||
<Margins>
|
||||
<PageHeader
|
||||
|
@ -1,18 +1,15 @@
|
||||
import * as API from "api/api";
|
||||
import { TemplateVersion } from "api/typesGenerated";
|
||||
import { FileTree, createFile } from "./filetree";
|
||||
import { TarReader } from "./tar";
|
||||
|
||||
/**
|
||||
* Content by filename
|
||||
*/
|
||||
// Content by filename
|
||||
export type TemplateVersionFiles = Record<string, string>;
|
||||
|
||||
export const getTemplateVersionFiles = async (
|
||||
version: TemplateVersion,
|
||||
fileId: string,
|
||||
): Promise<TemplateVersionFiles> => {
|
||||
const files: TemplateVersionFiles = {};
|
||||
const tarFile = await API.getFile(version.job.file_id);
|
||||
const tarFile = await API.getFile(fileId);
|
||||
const tarReader = new TarReader();
|
||||
await tarReader.readFile(tarFile);
|
||||
for (const file of tarReader.fileInfo) {
|
||||
|
@ -1,179 +0,0 @@
|
||||
import {
|
||||
getPreviousTemplateVersionByName,
|
||||
GetPreviousTemplateVersionByNameResponse,
|
||||
getTemplateByName,
|
||||
getTemplateVersionByName,
|
||||
} from "api/api";
|
||||
import { Template, TemplateVersion } from "api/typesGenerated";
|
||||
import {
|
||||
getTemplateVersionFiles,
|
||||
TemplateVersionFiles,
|
||||
} from "utils/templateVersion";
|
||||
import { assign, createMachine } from "xstate";
|
||||
|
||||
export interface TemplateVersionMachineContext {
|
||||
orgId: string;
|
||||
templateName: string;
|
||||
versionName: string;
|
||||
template?: Template;
|
||||
currentVersion?: TemplateVersion;
|
||||
currentFiles?: TemplateVersionFiles;
|
||||
error?: unknown;
|
||||
// Get file diffs
|
||||
previousVersion?: TemplateVersion;
|
||||
previousFiles?: TemplateVersionFiles;
|
||||
}
|
||||
|
||||
export const templateVersionMachine = createMachine(
|
||||
{
|
||||
predictableActionArguments: true,
|
||||
id: "templateVersion",
|
||||
schema: {
|
||||
context: {} as TemplateVersionMachineContext,
|
||||
services: {} as {
|
||||
loadVersions: {
|
||||
data: {
|
||||
currentVersion: GetPreviousTemplateVersionByNameResponse;
|
||||
previousVersion: GetPreviousTemplateVersionByNameResponse;
|
||||
};
|
||||
};
|
||||
loadTemplate: {
|
||||
data: {
|
||||
template: Template;
|
||||
};
|
||||
};
|
||||
loadFiles: {
|
||||
data: {
|
||||
currentFiles: TemplateVersionFiles;
|
||||
previousFiles: TemplateVersionFiles;
|
||||
};
|
||||
};
|
||||
},
|
||||
},
|
||||
tsTypes: {} as import("./templateVersionXService.typegen").Typegen0,
|
||||
initial: "initialInfo",
|
||||
states: {
|
||||
initialInfo: {
|
||||
type: "parallel",
|
||||
states: {
|
||||
versions: {
|
||||
initial: "loadingVersions",
|
||||
states: {
|
||||
loadingVersions: {
|
||||
invoke: {
|
||||
src: "loadVersions",
|
||||
onDone: [
|
||||
{
|
||||
actions: "assignVersions",
|
||||
target: "success",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
success: {
|
||||
type: "final",
|
||||
},
|
||||
},
|
||||
},
|
||||
template: {
|
||||
initial: "loadingTemplate",
|
||||
states: {
|
||||
loadingTemplate: {
|
||||
invoke: {
|
||||
src: "loadTemplate",
|
||||
onDone: [
|
||||
{
|
||||
actions: "assignTemplate",
|
||||
target: "success",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
success: {
|
||||
type: "final",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
onDone: {
|
||||
target: "loadingFiles",
|
||||
},
|
||||
},
|
||||
loadingFiles: {
|
||||
invoke: {
|
||||
src: "loadFiles",
|
||||
onDone: {
|
||||
target: "done.ok",
|
||||
actions: ["assignFiles"],
|
||||
},
|
||||
onError: {
|
||||
target: "done.error",
|
||||
actions: ["assignError"],
|
||||
},
|
||||
},
|
||||
},
|
||||
done: {
|
||||
states: {
|
||||
ok: { type: "final" },
|
||||
error: { type: "final" },
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
actions: {
|
||||
assignError: assign({
|
||||
error: (_, { data }) => data,
|
||||
}),
|
||||
assignTemplate: assign({
|
||||
template: (_, { data }) => data.template,
|
||||
}),
|
||||
assignVersions: assign({
|
||||
currentVersion: (_, { data }) => data.currentVersion,
|
||||
previousVersion: (_, { data }) => data.previousVersion,
|
||||
}),
|
||||
assignFiles: assign({
|
||||
currentFiles: (_, { data }) => data.currentFiles,
|
||||
previousFiles: (_, { data }) => data.previousFiles,
|
||||
}),
|
||||
},
|
||||
services: {
|
||||
loadVersions: async ({ orgId, templateName, versionName }) => {
|
||||
const [currentVersion, previousVersion] = await Promise.all([
|
||||
getTemplateVersionByName(orgId, templateName, versionName),
|
||||
getPreviousTemplateVersionByName(orgId, templateName, versionName),
|
||||
]);
|
||||
|
||||
return {
|
||||
currentVersion,
|
||||
previousVersion,
|
||||
};
|
||||
},
|
||||
loadTemplate: async ({ orgId, templateName }) => {
|
||||
const template = await getTemplateByName(orgId, templateName);
|
||||
|
||||
return {
|
||||
template,
|
||||
};
|
||||
},
|
||||
loadFiles: async ({ currentVersion, previousVersion }) => {
|
||||
if (!currentVersion) {
|
||||
throw new Error("Version is not defined");
|
||||
}
|
||||
const loadFilesPromises: ReturnType<typeof getTemplateVersionFiles>[] =
|
||||
[];
|
||||
loadFilesPromises.push(getTemplateVersionFiles(currentVersion));
|
||||
if (previousVersion) {
|
||||
loadFilesPromises.push(getTemplateVersionFiles(previousVersion));
|
||||
}
|
||||
const [currentFiles, previousFiles] = await Promise.all(
|
||||
loadFilesPromises,
|
||||
);
|
||||
return {
|
||||
currentFiles,
|
||||
previousFiles,
|
||||
};
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
Reference in New Issue
Block a user