From c93fe8ddbe7efecd45f45a648fc949446b0f766e Mon Sep 17 00:00:00 2001 From: Bruno Quaresma Date: Wed, 18 Oct 2023 09:18:03 -0300 Subject: [PATCH] chore(site): remove template version machine (#10315) --- site/src/api/queries/templateVersions.ts | 15 -- site/src/api/queries/templates.ts | 26 +++ site/src/components/TemplateFiles/hooks.ts | 68 +++++++ .../DuplicateTemplateView.tsx | 2 +- .../ImportStarterTemplateView.tsx | 2 +- .../CreateTemplatePage/UploadTemplateView.tsx | 2 +- .../CreateWorkspacePage.tsx | 2 +- .../TemplateFilesPage/TemplateFilesPage.tsx | 67 +------ .../TemplateVersionPage.tsx | 26 ++- .../TemplateVersionPageView.stories.tsx | 34 ++-- .../TemplateVersionPageView.tsx | 18 +- site/src/utils/templateVersion.ts | 9 +- .../templateVersionXService.ts | 179 ------------------ 13 files changed, 143 insertions(+), 307 deletions(-) delete mode 100644 site/src/api/queries/templateVersions.ts create mode 100644 site/src/components/TemplateFiles/hooks.ts delete mode 100644 site/src/xServices/templateVersion/templateVersionXService.ts diff --git a/site/src/api/queries/templateVersions.ts b/site/src/api/queries/templateVersions.ts deleted file mode 100644 index e90e762e81..0000000000 --- a/site/src/api/queries/templateVersions.ts +++ /dev/null @@ -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), - }; -}; diff --git a/site/src/api/queries/templates.ts b/site/src/api/queries/templates.ts index f4082e362f..e5a39a015b 100644 --- a/site/src/api/queries/templates.ts +++ b/site/src/api/queries/templates.ts @@ -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; diff --git a/site/src/components/TemplateFiles/hooks.ts b/site/src/components/TemplateFiles/hooks.ts new file mode 100644 index 0000000000..6d21538f8c --- /dev/null +++ b/site/src/components/TemplateFiles/hooks.ts @@ -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[] = []; + 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, + }; +}; diff --git a/site/src/pages/CreateTemplatePage/DuplicateTemplateView.tsx b/site/src/pages/CreateTemplatePage/DuplicateTemplateView.tsx index 96567948d9..3fcdb59498 100644 --- a/site/src/pages/CreateTemplatePage/DuplicateTemplateView.tsx +++ b/site/src/pages/CreateTemplatePage/DuplicateTemplateView.tsx @@ -1,6 +1,6 @@ import { useQuery, useMutation } from "react-query"; -import { templateVersionLogs } from "api/queries/templateVersions"; import { + templateVersionLogs, templateByName, templateVersion, templateVersionVariables, diff --git a/site/src/pages/CreateTemplatePage/ImportStarterTemplateView.tsx b/site/src/pages/CreateTemplatePage/ImportStarterTemplateView.tsx index 9854a62cae..38e596b908 100644 --- a/site/src/pages/CreateTemplatePage/ImportStarterTemplateView.tsx +++ b/site/src/pages/CreateTemplatePage/ImportStarterTemplateView.tsx @@ -1,6 +1,6 @@ import { useQuery, useMutation } from "react-query"; -import { templateVersionLogs } from "api/queries/templateVersions"; import { + templateVersionLogs, JobError, createTemplate, templateExamples, diff --git a/site/src/pages/CreateTemplatePage/UploadTemplateView.tsx b/site/src/pages/CreateTemplatePage/UploadTemplateView.tsx index a337b82a12..b3eb11a7c1 100644 --- a/site/src/pages/CreateTemplatePage/UploadTemplateView.tsx +++ b/site/src/pages/CreateTemplatePage/UploadTemplateView.tsx @@ -1,6 +1,6 @@ import { useQuery, useMutation } from "react-query"; -import { templateVersionLogs } from "api/queries/templateVersions"; import { + templateVersionLogs, JobError, createTemplate, templateVersionVariables, diff --git a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx index 94e8a55f16..2c6cff4807 100644 --- a/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx +++ b/site/src/pages/CreateWorkspacePage/CreateWorkspacePage.tsx @@ -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"; diff --git a/site/src/pages/TemplatePage/TemplateFilesPage/TemplateFilesPage.tsx b/site/src/pages/TemplatePage/TemplateFilesPage/TemplateFilesPage.tsx index d5398d7bc3..1a1cd9b244 100644 --- a/site/src/pages/TemplatePage/TemplateFilesPage/TemplateFilesPage.tsx +++ b/site/src/pages/TemplatePage/TemplateFilesPage/TemplateFilesPage.tsx @@ -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[] = []; - 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, ); diff --git a/site/src/pages/TemplateVersionPage/TemplateVersionPage.tsx b/site/src/pages/TemplateVersionPage/TemplateVersionPage.tsx index 7567efd502..491e57a576 100644 --- a/site/src/pages/TemplateVersionPage/TemplateVersionPage.tsx +++ b/site/src/pages/TemplateVersionPage/TemplateVersionPage.tsx @@ -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 = () => { = { @@ -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", + }), }, }; diff --git a/site/src/pages/TemplateVersionPage/TemplateVersionPageView.tsx b/site/src/pages/TemplateVersionPage/TemplateVersionPageView.tsx index 2238f9ccdd..44107caffe 100644 --- a/site/src/pages/TemplateVersionPage/TemplateVersionPageView.tsx +++ b/site/src/pages/TemplateVersionPage/TemplateVersionPageView.tsx @@ -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 = ({ - context, tab, versionName, templateName, createWorkspaceUrl, + currentVersion, + currentFiles, + previousFiles, + error, }) => { - const { currentFiles, error, currentVersion, previousFiles } = context; - return ( ; export const getTemplateVersionFiles = async ( - version: TemplateVersion, + fileId: string, ): Promise => { 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) { diff --git a/site/src/xServices/templateVersion/templateVersionXService.ts b/site/src/xServices/templateVersion/templateVersionXService.ts deleted file mode 100644 index 4cad1e061c..0000000000 --- a/site/src/xServices/templateVersion/templateVersionXService.ts +++ /dev/null @@ -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[] = - []; - loadFilesPromises.push(getTemplateVersionFiles(currentVersion)); - if (previousVersion) { - loadFilesPromises.push(getTemplateVersionFiles(previousVersion)); - } - const [currentFiles, previousFiles] = await Promise.all( - loadFilesPromises, - ); - return { - currentFiles, - previousFiles, - }; - }, - }, - }, -);