Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat(site): allow any file extension on template editor#12000

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
BrunoQuaresma merged 20 commits intomainfrombq/template-editor
Feb 7, 2024
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
20 commits
Select commitHold shift + click to select a range
4635cbd
Display all files in the editor
BrunoQuaresmaFeb 2, 2024
541c953
Adjust group padding
BrunoQuaresmaFeb 2, 2024
1785b90
Show error for unsupported files
BrunoQuaresmaFeb 2, 2024
9653fc7
Save version on URL even when building
BrunoQuaresmaFeb 2, 2024
ce75edd
Remove unecessary state
BrunoQuaresmaFeb 2, 2024
4403a18
Keep user navigation from URL
BrunoQuaresmaFeb 2, 2024
3957240
Merge branch 'main' of https://github.com/coder/coder into bq/templat…
BrunoQuaresmaFeb 5, 2024
a418467
Show stack files
BrunoQuaresmaFeb 5, 2024
0c72ecc
Remove unecessary imports
BrunoQuaresmaFeb 5, 2024
2353ea9
Add file tree on template files
BrunoQuaresmaFeb 5, 2024
0c2ffc9
Add edit button
BrunoQuaresmaFeb 5, 2024
98aa054
Use same editor bg
BrunoQuaresmaFeb 5, 2024
8508e69
Add storybook for visual testing
BrunoQuaresmaFeb 6, 2024
94775b1
Fix tests
BrunoQuaresmaFeb 6, 2024
4593f0e
Fix test
BrunoQuaresmaFeb 6, 2024
1a7ef6d
Merge branch 'main' of https://github.com/coder/coder into bq/templat…
BrunoQuaresmaFeb 7, 2024
955bced
wip: group empty folders
BrunoQuaresmaFeb 7, 2024
bfdabb3
Group empty folders + remove contextual actions if there is any
BrunoQuaresmaFeb 7, 2024
469a35c
Grey out hidden files
BrunoQuaresmaFeb 7, 2024
9a95846
Fix storybook
BrunoQuaresmaFeb 7, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -2,12 +2,13 @@ import { type ComponentProps, type FC } from "react";
import Editor, { DiffEditor, loader } from "@monaco-editor/react";
import * as monaco from "monaco-editor";
import { useCoderTheme } from "./coderTheme";
import { useTheme } from "@emotion/react";

loader.config({ monaco });

interface SyntaxHighlighterProps {
value: string;
language: string;
language?: string;
editorProps?: ComponentProps<typeof Editor> &
ComponentProps<typeof DiffEditor>;
compareWith?: string;
Expand All@@ -20,6 +21,7 @@ export const SyntaxHighlighter: FC<SyntaxHighlighterProps> = ({
editorProps,
}) => {
const hasDiff = compareWith && value !== compareWith;
const theme = useTheme();
const coderTheme = useCoderTheme();
const commonProps = {
language,
Expand All@@ -45,6 +47,7 @@ export const SyntaxHighlighter: FC<SyntaxHighlighterProps> = ({
css={{
padding: "8px 0",
height: "100%",
backgroundColor: theme.monaco.colors["editor.background"],
}}
>
{hasDiff ? (
Expand Down
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
import type { Meta, StoryObj } from "@storybook/react";
import { chromatic } from "testHelpers/chromatic";
import { TemplateFileTree } from "./TemplateFileTree";
import { FileTree } from "utils/filetree";
import { useTheme } from "@emotion/react";

const fileTree: FileTree = {
"main.tf": "resource aws_instance my_instance {}",
"variables.tf": "variable my_var {}",
"outputs.tf": "output my_output {}",
folder: {
"nested.tf": "resource aws_instance my_instance {}",
},
};

const meta: Meta<typeof TemplateFileTree> = {
title: "modules/templates/TemplateFileTree",
parameters: { chromatic },
component: TemplateFileTree,
args: {
fileTree,
activePath: "main.tf",
},
decorators: [
(Story) => {
const theme = useTheme();
return (
<div
css={{
maxWidth: 260,
borderRadius: 8,
border: `1px solid ${theme.palette.divider}`,
}}
>
<Story />
</div>
);
},
],
};

export default meta;
type Story = StoryObj<typeof TemplateFileTree>;

export const Example: Story = {};

export const NestedOpen: Story = {
args: {
activePath: "folder/nested.tf",
},
};

export const GroupEmptyFolders: Story = {
args: {
activePath: "folder/other-folder/another/nested.tf",
fileTree: {
"main.tf": "resource aws_instance my_instance {}",
"variables.tf": "variable my_var {}",
"outputs.tf": "output my_output {}",
folder: {
"other-folder": {
another: {
"nested.tf": "resource aws_instance my_instance {}",
},
},
},
},
},
};

export const GreyOutHiddenFiles: Story = {
args: {
fileTree: {
".vite": {
"config.json": "resource aws_instance my_instance {}",
},
".nextjs": {
"nested.tf": "resource aws_instance my_instance {}",
},
".terraform.lock.hcl": "{}",
"main.tf": "resource aws_instance my_instance {}",
"variables.tf": "variable my_var {}",
"outputs.tf": "output my_output {}",
},
},
};
Original file line numberDiff line numberDiff line change
Expand Up@@ -28,30 +28,59 @@ type ContextMenu = {
clientY: number;
};

interfaceFileTreeViewProps {
interfaceTemplateFilesTreeProps {
onSelect: (path: string) => void;
onDelete: (path: string) => void;
onRename: (path: string) => void;
onDelete?: (path: string) => void;
onRename?: (path: string) => void;
fileTree: FileTree;
activePath?: string;
Label?: FC<{
path: string;
filename: string;
label: string;
isFolder: boolean;
}>;
}

export constFileTreeView: FC<FileTreeViewProps> = ({
export constTemplateFileTree: FC<TemplateFilesTreeProps> = ({
fileTree,
activePath,
onDelete,
onRename,
onSelect,
Label,
}) => {
const [contextMenu, setContextMenu] = useState<ContextMenu | undefined>();

const isFolder = (content?: FileTree | string): content is FileTree =>
typeof content === "object";

const buildTreeItems = (
label: string,
filename: string,
content?: FileTree | string,
parentPath?: string,
): JSX.Element => {
const currentPath = parentPath ? `${parentPath}/${filename}` : filename;
const isFolder = typeof content === "object";
let icon: JSX.Element | null = isFolder ? null : (
// Used to group empty folders in one single label like VSCode does
const shouldGroupFolder =
isFolder(content) &&
Object.keys(content).length === 1 &&
isFolder(Object.values(content)[0]);
const isHiddenFile = currentPath.startsWith(".");

if (shouldGroupFolder) {
const firstChildFileName = Object.keys(content)[0];
const child = content[firstChildFileName];
return buildTreeItems(
`${label} / ${firstChildFileName}`,
firstChildFileName,
child,
currentPath,
);
}

let icon: JSX.Element | null = isFolder(content) ? null : (
<FormatAlignLeftOutlined />
);

Expand All@@ -69,26 +98,40 @@ export const FileTreeView: FC<FileTreeViewProps> = ({
<TreeItem
nodeId={currentPath}
key={currentPath}
label={filename}
label={
Label ? (
<Label
path={currentPath}
label={label}
filename={filename}
isFolder={isFolder(content)}
/>
) : (
label
)
}
css={(theme) => css`
overflow: hidden;
user-select: none;

& > .MuiTreeItem-content {
padding: 2px 16px;
color: ${theme.palette.text.secondary};
color: ${isHiddenFile
? theme.palette.text.disabled
: theme.palette.text.secondary};
height: 32px;

& svg {
width: 12px;
height: 12px;
color:${theme.palette.text.secondary};
color:currentColor;
}

& > .MuiTreeItem-label {
margin-left: 4px;
font-size: 13px;
color: inherit;
white-space: nowrap;
}

&.Mui-selected {
Expand All@@ -103,17 +146,22 @@ export const FileTreeView: FC<FileTreeViewProps> = ({

& .MuiTreeItem-group {
margin-left: 0;
position: relative;

// We need to find a better way to recursive padding here
& .MuiTreeItem-content {
padding-left: calc(var(--level)* 40px);
padding-left: calc(8px + (var(--level)+ 1) * 8px);
}
}
`}
onClick={() => {
onSelect(currentPath);
}}
onContextMenu={(event) => {
const hasContextActions = onRename || onDelete;
if (!hasContextActions) {
return;
}
event.preventDefault(); // Avoid default browser behavior
event.stopPropagation(); // Avoid trigger parent context menu
setContextMenu(
Expand All@@ -133,12 +181,12 @@ export const FileTreeView: FC<FileTreeViewProps> = ({
} as CSSProperties
}
>
{isFolder &&
{isFolder(content) &&
Object.keys(content)
.sort(sortFileTree(content))
.map((filename) => {
const child = content[filename];
return buildTreeItems(filename, child, currentPath);
return buildTreeItems(filename,filename,child, currentPath);
})}
</TreeItem>
);
Expand All@@ -149,13 +197,14 @@ export const FileTreeView: FC<FileTreeViewProps> = ({
defaultCollapseIcon={<ExpandMoreIcon />}
defaultExpandIcon={<ChevronRightIcon />}
aria-label="Files"
defaultExpanded={activePath ? expandablePaths(activePath) : []}
defaultSelected={activePath}
>
{Object.keys(fileTree)
.sort(sortFileTree(fileTree))
.map((filename) => {
const child = fileTree[filename];
return buildTreeItems(filename, child);
return buildTreeItems(filename,filename,child);
})}

<Menu
Expand DownExpand Up@@ -184,7 +233,7 @@ export const FileTreeView: FC<FileTreeViewProps> = ({
if (!contextMenu) {
return;
}
onRename(contextMenu.path);
onRename && onRename(contextMenu.path);
setContextMenu(undefined);
}}
>
Expand All@@ -195,7 +244,7 @@ export const FileTreeView: FC<FileTreeViewProps> = ({
if (!contextMenu) {
return;
}
onDelete(contextMenu.path);
onDelete && onDelete(contextMenu.path);
setContextMenu(undefined);
}}
>
Expand DownExpand Up@@ -232,3 +281,12 @@ const FileTypeMarkdown: FC = () => (
<polygon points="22.955 20.636 18.864 16.136 21.591 16.136 21.591 11.364 24.318 11.364 24.318 16.136 27.045 16.136 22.955 20.636" />
</svg>
);

const expandablePaths = (path: string) => {
const paths = path.split("/");
const result = [];
for (let i = 1; i < paths.length; i++) {
result.push(paths.slice(0, i).join("/"));
}
return result;
};
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
import { action } from "@storybook/addon-actions";
import type { Meta, StoryObj } from "@storybook/react";
import { chromatic } from "testHelpers/chromatic";
import { TemplateFiles } from "./TemplateFiles";
Expand All@@ -19,7 +18,6 @@ const meta: Meta<typeof TemplateFiles> = {
args: {
currentFiles: exampleFiles,
baseFiles: exampleFiles,
tab: { value: "0", set: action("change tab") },
},
};

Expand All@@ -28,4 +26,14 @@ type Story = StoryObj<typeof TemplateFiles>;

const Example: Story = {};

export const WithDiff: Story = {
args: {
currentFiles: {
...exampleFiles,
"main.tf": `${exampleFiles["main.tf"]} - with changes`,
},
baseFiles: exampleFiles,
},
};

export { Example as TemplateFiles };
Loading

[8]ページ先頭

©2009-2025 Movatter.jp