Skip to content

fix(site): Fix template version editor rename #6251

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Mar 6, 2023
Prev Previous commit
Next Next commit
Fix minor UI issues
  • Loading branch information
BrunoQuaresma committed Mar 2, 2023
commit ab9b8da0594efbb57c06523ebd71dd24f0517f99
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ const useStyles = makeStyles((theme) => ({
color: theme.palette.text.primary,
},

"& p": {
"& p:not(.MuiFormHelperText-root)": {
margin: 0,
},

Expand Down
29 changes: 24 additions & 5 deletions site/src/components/TemplateVersionEditor/FileDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ import { Stack } from "components/Stack/Stack"
import { ChangeEvent, FC, useState } from "react"
import Typography from "@material-ui/core/Typography"
import { allowedExtensions, isAllowedFile } from "util/templateVersion"
import { FileTree, validatePath } from "util/filetree"

export const CreateFileDialog: FC<{
onClose: () => void
checkExists: (path: string) => boolean
onConfirm: (path: string) => void
open: boolean
}> = ({ checkExists, onClose, onConfirm, open }) => {
fileTree: FileTree
}> = ({ checkExists, onClose, onConfirm, open, fileTree }) => {
const [pathValue, setPathValue] = useState("")
const [error, setError] = useState("")
const [error, setError] = useState<string>()
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setPathValue(event.target.value)
}
Expand All @@ -32,7 +34,13 @@ export const CreateFileDialog: FC<{
)
return
}
const pathError = validatePath(pathValue, fileTree)
if (pathError) {
setError(pathError)
return
}
onConfirm(pathValue)
setError(undefined)
setPathValue("")
}

Expand All @@ -41,6 +49,7 @@ export const CreateFileDialog: FC<{
open={open}
onClose={() => {
onClose()
setError(undefined)
setPathValue("")
}}
onConfirm={handleConfirm}
Expand All @@ -62,6 +71,7 @@ export const CreateFileDialog: FC<{
handleConfirm()
}
}}
error={Boolean(error)}
helperText={error}
name="file-path"
autoComplete="off"
Expand Down Expand Up @@ -109,9 +119,10 @@ export const RenameFileDialog: FC<{
checkExists: (path: string) => boolean
open: boolean
filename: string
}> = ({ checkExists, onClose, onConfirm, open, filename }) => {
fileTree: FileTree
}> = ({ checkExists, onClose, onConfirm, open, filename, fileTree }) => {
const [pathValue, setPathValue] = useState(filename)
const [error, setError] = useState("")
const [error, setError] = useState<string>()
const handleChange = (event: ChangeEvent<HTMLInputElement>) => {
setPathValue(event.target.value)
}
Expand All @@ -127,11 +138,17 @@ export const RenameFileDialog: FC<{
if (!isAllowedFile(pathValue)) {
const extensions = allowedExtensions.join(", ")
setError(
`This extension is not allowed. You only can create files with the following extensions: ${extensions}.`,
`This extension is not allowed. You only can rename files with the following extensions: ${extensions}.`,
)
return
}
const pathError = validatePath(pathValue, fileTree)
if (pathError) {
setError(pathError)
return
}
onConfirm(pathValue)
setError(undefined)
setPathValue("")
}

Expand All @@ -140,6 +157,7 @@ export const RenameFileDialog: FC<{
open={open}
onClose={() => {
onClose()
setError(undefined)
setPathValue("")
}}
onConfirm={handleConfirm}
Expand All @@ -161,6 +179,7 @@ export const RenameFileDialog: FC<{
handleConfirm()
}
}}
error={Boolean(error)}
helperText={error}
name="file-path"
autoComplete="off"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,15 @@ import { WorkspaceBuildLogs } from "components/WorkspaceBuildLogs/WorkspaceBuild
import { FC, useCallback, useEffect, useRef, useState } from "react"
import { navHeight, dashboardContentBottomPadding } from "theme/constants"
import {
createFile,
existsFile,
FileTree,
getFileContent,
isFolder,
moveFile,
removeFile,
setFile,
traverse,
updateFile,
} from "util/filetree"
import {
CreateFileDialog,
Expand Down Expand Up @@ -217,13 +218,14 @@ export const TemplateVersionEditor: FC<TemplateVersionEditorProps> = ({
</Tooltip>
</div>
<CreateFileDialog
fileTree={fileTree}
open={createFileOpen}
onClose={() => {
setCreateFileOpen(false)
}}
checkExists={(path) => existsFile(path, fileTree)}
onConfirm={(path) => {
setFileTree((fileTree) => setFile(path, "", fileTree))
setFileTree((fileTree) => createFile(path, fileTree, ""))
setActivePath(path)
setCreateFileOpen(false)
setDirty(true)
Expand All @@ -246,6 +248,7 @@ export const TemplateVersionEditor: FC<TemplateVersionEditorProps> = ({
filename={deleteFileOpen || ""}
/>
<RenameFileDialog
fileTree={fileTree}
open={Boolean(renameFileOpen)}
onClose={() => {
setRenameFileOpen(undefined)
Expand Down Expand Up @@ -289,7 +292,7 @@ export const TemplateVersionEditor: FC<TemplateVersionEditorProps> = ({
return
}
setFileTree((fileTree) =>
setFile(activePath, value, fileTree),
updateFile(activePath, value, fileTree),
)
setDirty(true)
}}
Expand Down
38 changes: 36 additions & 2 deletions site/src/util/filetree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,38 @@ export type FileTree = {
[key: string]: FileTree | string
}

export const setFile = (
export const createFile = (
path: string,
fileTree: FileTree,
value: string,
): FileTree => {
if (existsFile(path, fileTree)) {
throw new Error(`File ${path} already exists`)
}
const pathError = validatePath(path, fileTree)
if (pathError) {
throw new Error(pathError)
}

return set(fileTree, path.split("/"), value)
}

export const validatePath = (
path: string,
fileTree: FileTree,
): string | undefined => {
const paths = path.split("/")
paths.pop() // The last item is the filename
for (let i = 0; i <= paths.length; i++) {
const path = paths.slice(0, i + 1)
const pathStr = path.join("/")
if (existsFile(pathStr, fileTree) && !isFolder(pathStr, fileTree)) {
return `Invalid path. The path ${path} is not a folder`
}
}
}

export const updateFile = (
path: string,
content: FileTree | string,
fileTree: FileTree,
Expand All @@ -31,8 +62,11 @@ export const moveFile = (
fileTree: FileTree,
) => {
const content = getFileContent(currentPath, fileTree)
if (typeof content !== "string") {
throw new Error("Move folders is not allowed")
}
fileTree = removeFile(currentPath, fileTree)
fileTree = setFile(newPath, content, fileTree)
fileTree = createFile(newPath, fileTree, content)
return fileTree
}

Expand Down
6 changes: 3 additions & 3 deletions site/src/util/templateVersion.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import * as API from "api/api"
import { TemplateVersion } from "api/typesGenerated"
import { FileTree, setFile } from "./filetree"
import { FileTree, createFile } from "./filetree"
import { TarReader } from "./tar"

/**
Expand Down Expand Up @@ -35,10 +35,10 @@ export const createTemplateVersionFileTree = async (
let fileTree: FileTree = {}
for (const file of tarReader.fileInfo) {
if (isAllowedFile(file.name)) {
fileTree = setFile(
fileTree = createFile(
file.name,
tarReader.getTextFile(file.name) as string,
fileTree,
tarReader.getTextFile(file.name) as string,
)
}
}
Expand Down