Skip to content

Commit 4635cbd

Browse files
committed
Display all files in the editor
1 parent 2e378b4 commit 4635cbd

File tree

6 files changed

+77
-106
lines changed

6 files changed

+77
-106
lines changed

site/src/modules/templates/TemplateFiles/TemplateFiles.tsx

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import { MarkdownIcon } from "components/Icons/MarkdownIcon";
55
import { TerraformIcon } from "components/Icons/TerraformIcon";
66
import { SyntaxHighlighter } from "components/SyntaxHighlighter/SyntaxHighlighter";
77
import { UseTabResult, useTab } from "hooks/useTab";
8-
import { AllowedExtension, TemplateVersionFiles } from "utils/templateVersion";
8+
import { TemplateVersionFiles } from "utils/templateVersion";
99
import InsertDriveFileOutlined from "@mui/icons-material/InsertDriveFileOutlined";
1010

11-
const iconByExtension: Record<AllowedExtension, JSX.Element> = {
11+
const iconByExtension: Record<string, JSX.Element> = {
1212
tf: <TerraformIcon />,
1313
md: <MarkdownIcon />,
1414
mkd: <MarkdownIcon />,
@@ -27,7 +27,7 @@ const getExtension = (filename: string) => {
2727
return filename;
2828
};
2929

30-
const languageByExtension: Record<AllowedExtension, string> = {
30+
const languageByExtension: Record<string, string> = {
3131
tf: "hcl",
3232
md: "markdown",
3333
mkd: "markdown",
@@ -61,7 +61,7 @@ export const TemplateFiles: FC<TemplateFilesProps> = ({
6161
<div css={styles.tabs}>
6262
{filenames.map((filename, index) => {
6363
const tabValue = index.toString();
64-
const extension = getExtension(filename) as AllowedExtension;
64+
const extension = getExtension(filename);
6565
const icon = iconByExtension[extension];
6666
const hasDiff =
6767
baseFiles &&
@@ -87,11 +87,7 @@ export const TemplateFiles: FC<TemplateFilesProps> = ({
8787
<SyntaxHighlighter
8888
value={currentFile}
8989
compareWith={previousFile}
90-
language={
91-
languageByExtension[
92-
getExtension(selectedFilename) as AllowedExtension
93-
]
94-
}
90+
language={languageByExtension[getExtension(selectedFilename)]}
9591
/>
9692
</div>
9793
);

site/src/pages/TemplateVersionEditorPage/FileDialog.tsx

Lines changed: 2 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import TextField from "@mui/material/TextField";
22
import { ConfirmDialog } from "components/Dialogs/ConfirmDialog/ConfirmDialog";
33
import { Stack } from "components/Stack/Stack";
44
import { type ChangeEvent, type FC, useState } from "react";
5-
import { allowedExtensions, isAllowedFile } from "utils/templateVersion";
65
import { type FileTree, isFolder, validatePath } from "utils/filetree";
76

87
interface CreateFileDialogProps {
@@ -34,13 +33,7 @@ export const CreateFileDialog: FC<CreateFileDialogProps> = ({
3433
setError("File already exists");
3534
return;
3635
}
37-
if (!isAllowedFile(pathValue)) {
38-
const extensions = allowedExtensions.join(", ");
39-
setError(
40-
`This extension is not allowed. You only can create files with the following extensions: ${extensions}.`,
41-
);
42-
return;
43-
}
36+
4437
const pathError = validatePath(pathValue, fileTree);
4538
if (pathError) {
4639
setError(pathError);
@@ -155,13 +148,7 @@ export const RenameFileDialog: FC<RenameFileDialogProps> = ({
155148
setError("File already exists");
156149
return;
157150
}
158-
if (!isAllowedFile(pathValue)) {
159-
const extensions = allowedExtensions.join(", ");
160-
setError(
161-
`This extension is not allowed. You only can rename files with the following extensions: ${extensions}.`,
162-
);
163-
return;
164-
}
151+
165152
//Check if a folder is renamed to a file
166153
const [_, extension] = pathValue.split(".");
167154
if (isFolder(filename, fileTree) && extension) {

site/src/pages/TemplateVersionEditorPage/MonacoEditor.tsx

Lines changed: 1 addition & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useTheme } from "@emotion/react";
22
import Editor, { loader } from "@monaco-editor/react";
33
import * as monaco from "monaco-editor";
4-
import { type FC, useEffect, useMemo } from "react";
4+
import { type FC, useEffect } from "react";
55
import { MONOSPACE_FONT_FAMILY } from "theme/constants";
66

77
loader.config({ monaco });
@@ -19,24 +19,6 @@ export const MonacoEditor: FC<MonacoEditorProps> = ({
1919
}) => {
2020
const theme = useTheme();
2121

22-
const language = useMemo(() => {
23-
if (path?.endsWith(".tf")) {
24-
return "hcl";
25-
}
26-
if (path?.endsWith(".md")) {
27-
return "markdown";
28-
}
29-
if (path?.endsWith(".json")) {
30-
return "json";
31-
}
32-
if (path?.endsWith(".yaml")) {
33-
return "yaml";
34-
}
35-
if (path?.endsWith("Dockerfile")) {
36-
return "dockerfile";
37-
}
38-
}, [path]);
39-
4022
useEffect(() => {
4123
document.fonts.ready
4224
.then(() => {
@@ -54,7 +36,6 @@ export const MonacoEditor: FC<MonacoEditorProps> = ({
5436
return (
5537
<Editor
5638
value={value}
57-
language={language}
5839
theme="vs-dark"
5940
options={{
6041
automaticLayout: true,

site/src/pages/TemplateVersionEditorPage/TemplateVersionEditor.tsx

Lines changed: 41 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,7 @@ export const TemplateVersionEditor: FC<TemplateVersionEditorProps> = ({
178178
}, [templateVersion]);
179179

180180
const editorValue = getFileContent(activePath ?? "", fileTree) as string;
181+
const isEditorValueBinary = isBinaryData(editorValue);
181182

182183
// Auto scroll
183184
const buildLogsRef = useRef<HTMLDivElement>(null);
@@ -448,19 +449,23 @@ export const TemplateVersionEditor: FC<TemplateVersionEditorProps> = ({
448449
>
449450
<div css={{ flex: 1, overflowY: "auto" }} data-chromatic="ignore">
450451
{activePath ? (
451-
<MonacoEditor
452-
value={editorValue}
453-
path={activePath}
454-
onChange={(value) => {
455-
if (!activePath) {
456-
return;
457-
}
458-
setFileTree((fileTree) =>
459-
updateFile(activePath, value, fileTree),
460-
);
461-
setDirty(true);
462-
}}
463-
/>
452+
isEditorValueBinary ? (
453+
<p>File type not supported</p>
454+
) : (
455+
<MonacoEditor
456+
value={editorValue}
457+
path={activePath}
458+
onChange={(value) => {
459+
if (!activePath) {
460+
return;
461+
}
462+
setFileTree((fileTree) =>
463+
updateFile(activePath, value, fileTree),
464+
);
465+
setDirty(true);
466+
}}
467+
/>
468+
)
464469
) : (
465470
<div>No file opened</div>
466471
)}
@@ -616,6 +621,29 @@ export const TemplateVersionEditor: FC<TemplateVersionEditorProps> = ({
616621
);
617622
};
618623

624+
function isBinaryData(s: string): boolean {
625+
// Remove unicode characters from the string like emojis.
626+
const asciiString = s.replace(/[\u007F-\uFFFF]/g, "");
627+
628+
// Create a set of all printable ASCII characters (and some control characters).
629+
const textChars = new Set(
630+
[7, 8, 9, 10, 12, 13, 27].concat(
631+
Array.from({ length: 128 }, (_, i) => i + 32),
632+
),
633+
);
634+
635+
const isBinaryString = (str: string): boolean => {
636+
for (let i = 0; i < str.length; i++) {
637+
if (!textChars.has(str.charCodeAt(i))) {
638+
return true;
639+
}
640+
}
641+
return false;
642+
};
643+
644+
return isBinaryString(asciiString);
645+
}
646+
619647
const styles = {
620648
tab: (theme) => ({
621649
"&:not(:disabled)": {

site/src/pages/TemplateVersionEditorPage/TemplateVersionEditorPage.tsx

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@ import {
2525
import { file, uploadFile } from "api/queries/files";
2626
import { TarFileTypeCodes, TarReader, TarWriter } from "utils/tar";
2727
import { FileTree, traverse } from "utils/filetree";
28-
import {
29-
createTemplateVersionFileTree,
30-
isAllowedFile,
31-
} from "utils/templateVersion";
28+
import { createTemplateVersionFileTree } from "utils/templateVersion";
3229
import { displayError } from "components/GlobalSnackbar/utils";
3330
import { FullScreenLoader } from "components/Loader/FullScreenLoader";
3431

@@ -253,7 +250,8 @@ const useFileTree = (templateVersion: TemplateVersion | undefined) => {
253250
};
254251

255252
if (fileQuery.data) {
256-
initializeFileTree(fileQuery.data).catch(() => {
253+
initializeFileTree(fileQuery.data).catch((reason) => {
254+
console.error(reason);
257255
displayError("Error on initializing the editor");
258256
});
259257
}
@@ -332,22 +330,20 @@ const generateVersionFiles = async (
332330

333331
// Add previous non editable files
334332
for (const file of tarReader.fileInfo) {
335-
if (!isAllowedFile(file.name)) {
336-
if (file.type === TarFileTypeCodes.Dir) {
337-
tar.addFolder(file.name, {
338-
mode: file.mode, // https://github.com/beatgammit/tar-js/blob/master/lib/tar.js#L42
339-
mtime: file.mtime,
340-
user: file.user,
341-
group: file.group,
342-
});
343-
} else {
344-
tar.addFile(file.name, tarReader.getTextFile(file.name) as string, {
345-
mode: file.mode, // https://github.com/beatgammit/tar-js/blob/master/lib/tar.js#L42
346-
mtime: file.mtime,
347-
user: file.user,
348-
group: file.group,
349-
});
350-
}
333+
if (file.type === TarFileTypeCodes.Dir) {
334+
tar.addFolder(file.name, {
335+
mode: file.mode, // https://github.com/beatgammit/tar-js/blob/master/lib/tar.js#L42
336+
mtime: file.mtime,
337+
user: file.user,
338+
group: file.group,
339+
});
340+
} else {
341+
tar.addFile(file.name, tarReader.getTextFile(file.name) as string, {
342+
mode: file.mode, // https://github.com/beatgammit/tar-js/blob/master/lib/tar.js#L42
343+
mtime: file.mtime,
344+
user: file.user,
345+
group: file.group,
346+
});
351347
}
352348
}
353349
// Add the editable files

site/src/utils/templateVersion.ts

Lines changed: 11 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
import { FileTree, createFile } from "./filetree";
2-
import { TarReader } from "./tar";
1+
import set from "lodash/set";
2+
import { FileTree } from "./filetree";
3+
import { TarFileTypeCodes, TarReader } from "./tar";
34

45
// Content by filename
56
export type TemplateVersionFiles = Record<string, string>;
@@ -11,41 +12,23 @@ export const getTemplateVersionFiles = async (
1112
const tarReader = new TarReader();
1213
await tarReader.readFile(tarFile);
1314
for (const file of tarReader.fileInfo) {
14-
if (isAllowedFile(file.name)) {
15-
files[file.name] = tarReader.getTextFile(file.name) as string;
16-
}
15+
files[file.name] = tarReader.getTextFile(file.name) as string;
1716
}
1817
return files;
1918
};
2019

21-
export const allowedExtensions = [
22-
"tf",
23-
"md",
24-
"mkd",
25-
"Dockerfile",
26-
"protobuf",
27-
"sh",
28-
"tpl",
29-
] as const;
30-
31-
export type AllowedExtension = (typeof allowedExtensions)[number];
32-
33-
export const isAllowedFile = (name: string) => {
34-
return allowedExtensions.some((ext) => name.endsWith(ext));
35-
};
36-
3720
export const createTemplateVersionFileTree = async (
3821
tarReader: TarReader,
3922
): Promise<FileTree> => {
4023
let fileTree: FileTree = {};
4124
for (const file of tarReader.fileInfo) {
42-
if (isAllowedFile(file.name)) {
43-
fileTree = createFile(
44-
file.name,
45-
fileTree,
46-
tarReader.getTextFile(file.name) as string,
47-
);
48-
}
25+
fileTree = set(
26+
fileTree,
27+
file.name.split("/"),
28+
file.type === TarFileTypeCodes.Dir
29+
? {}
30+
: (tarReader.getTextFile(file.name) as string),
31+
);
4932
}
5033
return fileTree;
5134
};

0 commit comments

Comments
 (0)