diff --git a/web/src/components/FileTree.vue b/web/src/components/FileTree.vue
new file mode 100644
index 000000000..6a5da3956
--- /dev/null
+++ b/web/src/components/FileTree.vue
@@ -0,0 +1,70 @@
+
+
+
+
+
+
+
+
+
+
+ {{ node.name }}
+
+
+
+
+
+
+
+
+
+
diff --git a/web/src/components/atomic/Icon.vue b/web/src/components/atomic/Icon.vue
index 371bdcd97..c8c5e2a99 100644
--- a/web/src/components/atomic/Icon.vue
+++ b/web/src/components/atomic/Icon.vue
@@ -61,6 +61,9 @@
+
+
+
@@ -124,6 +127,9 @@ import {
mdiEyeOutline,
mdiFileCogOutline,
mdiFileEditOutline,
+ mdiFileOutline,
+ mdiFolderOpenOutline,
+ mdiFolderOutline,
mdiFormatListBulleted,
mdiFormatListGroup,
mdiGestureTap,
@@ -230,7 +236,10 @@ export type IconNames =
| 'org'
| 'cron'
| 'toolbox'
- | 'forge';
+ | 'forge'
+ | 'folder'
+ | 'folder-open'
+ | 'file';
const props = defineProps<{
name: IconNames;
diff --git a/web/src/views/repo/pipeline/PipelineChangedFiles.vue b/web/src/views/repo/pipeline/PipelineChangedFiles.vue
index 5d67da7d7..be3d0b136 100644
--- a/web/src/views/repo/pipeline/PipelineChangedFiles.vue
+++ b/web/src/views/repo/pipeline/PipelineChangedFiles.vue
@@ -1,8 +1,8 @@
-
+
+
+
@@ -10,6 +10,8 @@
import { computed } from 'vue';
import { useI18n } from 'vue-i18n';
+import FileTree from '~/components/FileTree.vue';
+import type { TreeNode } from '~/components/FileTree.vue';
import Panel from '~/components/layout/Panel.vue';
import { requiredInject } from '~/compositions/useInjectProvide';
import { useWPTitle } from '~/compositions/useWPTitle';
@@ -25,4 +27,29 @@ useWPTitle(
repo.value.full_name,
]),
);
+
+const fileTree = computed(() =>
+ (pipeline.value.changed_files ?? []).reduce((acc, file) => {
+ const parts = file.split('/');
+ let currentLevel = acc;
+
+ parts.forEach((part, index) => {
+ const existingNode = currentLevel.find((node) => node.name === part);
+ if (existingNode) {
+ currentLevel = existingNode.children;
+ } else {
+ const newNode = {
+ name: part,
+ path: parts.slice(0, index + 1).join('/'),
+ isDirectory: index < parts.length - 1,
+ children: [],
+ };
+ currentLevel.push(newNode);
+ currentLevel = newNode.children;
+ }
+ });
+
+ return acc;
+ }, [] as TreeNode[]),
+);