diff --git a/docker-compose.yaml b/docker-compose.yaml
index cf0d0282..880c8675 100644
--- a/docker-compose.yaml
+++ b/docker-compose.yaml
@@ -153,7 +153,7 @@ services:
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- server
- - frontend
+# - frontend
redis:
hostname: redis
@@ -175,23 +175,23 @@ services:
volumes:
- workspaces:/workspaces
- frontend:
- container_name: frontend
- build:
- context: ./gui
- dockerfile: Dockerfile
- ports:
- - 3000:3000
- volumes:
- - ./gui:/app
- - /app/node_modules/
- - /app/.next/
- depends_on:
- - server
- environment:
- - NEXT_PUBLIC_DOCKER=true
- restart: always
- command: [ "yarn", "dev" ]
+# frontend:
+# container_name: frontend
+# build:
+# context: ./gui
+# dockerfile: Dockerfile
+# ports:
+# - 3000:3000
+# volumes:
+# - ./gui:/app
+# - /app/node_modules/
+# - /app/.next/
+# depends_on:
+# - server
+# environment:
+# - NEXT_PUBLIC_DOCKER=true
+# restart: always
+# command: [ "yarn", "dev" ]
gitness:
container_name: gitness
diff --git a/gui/package.json b/gui/package.json
index 2aa1006d..e68d58c1 100644
--- a/gui/package.json
+++ b/gui/package.json
@@ -12,6 +12,8 @@
"dependencies": {
"@monaco-editor/react": "^4.6.0",
"@nextui-org/react": "^2.3.6",
+ "@xterm/addon-fit": "^0.10.0",
+ "@xterm/xterm": "^5.5.0",
"axios": "^1.7.2",
"babel-plugin-styled-components": "^2.1.4",
"cookie": "^0.6.0",
@@ -33,7 +35,8 @@
"react-transition-group": "^4.4.5",
"sharp": "^0.33.4",
"socket.io-client": "^2.5.0",
- "styled-components": "^6.1.11"
+ "styled-components": "^6.1.11",
+ "xterm": "^5.3.0"
},
"devDependencies": {
"@types/cookie": "^0.6.0",
@@ -45,6 +48,7 @@
"@types/react-transition-group": "^4.4.10",
"@types/socket.io-client": "^3.0.0",
"@types/styled-components": "^5.1.34",
+ "@types/xterm": "^3.0.0",
"@typescript-eslint/eslint-plugin": "^6",
"@typescript-eslint/parser": "^6",
"eslint": "^8",
diff --git a/gui/src/app/(programmer)/board/page.tsx b/gui/src/app/(programmer)/board/page.tsx
index 18028c6b..fb2b1e4d 100644
--- a/gui/src/app/(programmer)/board/page.tsx
+++ b/gui/src/app/(programmer)/board/page.tsx
@@ -14,6 +14,7 @@ import SetupModelModal from '@/components/StoryComponents/SetupModelModal';
import CustomLoaders from '@/components/CustomLoaders/CustomLoaders';
import { SkeletonTypes } from '@/app/constants/SkeletonConstants';
import CustomInput from '@/components/CustomInput/CustomInput';
+import TerminalComponent from '@/components/Terminal/Terminal';
const TaskItem = ({ task, handleStoryClick }) => (
{
- toGetAllStoriesOfProject();
- };
-
useEffect(() => {
toGetAllStoriesOfProject();
}, [searchValue]);
@@ -125,7 +122,6 @@ export default function Board() {
toGetAllStoriesOfProject={toGetAllStoriesOfProject}
/>
-
setOpenStoryDetailsModal(false)}
@@ -151,7 +147,6 @@ export default function Board() {
openModal={openSetupModelModal}
setOpenModel={setOpenSetupModelModal}
/>
-
+
+
{
+ const terminalRef = useTerminal(commands);
+
+ return (
+
+ );
+};
+
+export default TerminalComponent;
diff --git a/gui/src/components/Terminal/terminal.module.css b/gui/src/components/Terminal/terminal.module.css
new file mode 100644
index 00000000..a525d8d7
--- /dev/null
+++ b/gui/src/components/Terminal/terminal.module.css
@@ -0,0 +1,9 @@
+.terminal {
+ height: 100%;
+ width: 100%;
+ border: 1px solid var(--white-opacity-8);
+ background: var(--layout-bg-color);
+ color: #ffffff;
+ padding: 10px;
+ border-radius: 8px;
+}
diff --git a/gui/src/hooks/useTerminal.tsx b/gui/src/hooks/useTerminal.tsx
new file mode 100644
index 00000000..09b69f40
--- /dev/null
+++ b/gui/src/hooks/useTerminal.tsx
@@ -0,0 +1,66 @@
+import { useEffect, useRef } from 'react';
+import { Terminal } from '@xterm/xterm';
+import '@xterm/xterm/css/xterm.css';
+
+export const useTerminal = (commands: { [key: string]: string }) => {
+ const terminalRef = useRef
(null);
+ const xtermRef = useRef(null);
+
+ useEffect(() => {
+ if (terminalRef.current && !xtermRef.current) {
+ const xterm = new Terminal({
+ cursorBlink: true,
+ theme: {
+ background: '#1e1e1e', // Dark background
+ foreground: '#ffffff', // Light text
+ },
+ });
+ xterm.open(terminalRef.current);
+ xtermRef.current = xterm;
+
+ xterm.onKey(({ key, domEvent }) => {
+ const printable =
+ !domEvent.altKey && !domEvent.ctrlKey && !domEvent.metaKey;
+
+ if (domEvent.keyCode === 13) {
+ handleCommand(xterm);
+ } else if (domEvent.keyCode === 8) {
+ // Do not delete the prompt
+ if (xterm.buffer.active.cursorX > 2) {
+ xterm.write('\b \b');
+ }
+ } else if (printable) {
+ xterm.write(key);
+ }
+ });
+
+ xterm.prompt = () => {
+ xterm.write('\r\n$ ');
+ };
+
+ xterm.prompt();
+ }
+
+ return () => {
+ xtermRef.current?.dispose();
+ };
+ }, []);
+
+ const handleCommand = (xterm: Terminal) => {
+ const input = xterm.buffer.active
+ .getLine(xterm.buffer.active.cursorY)
+ ?.translateToString()
+ .trim();
+ const command = input?.split('$ ')[1];
+
+ if (command && commands[command]) {
+ xterm.write(`\r\n${commands[command]}`);
+ } else {
+ xterm.write('\r\nCommand not found');
+ }
+
+ xterm.prompt();
+ };
+
+ return terminalRef;
+};
diff --git a/gui/yarn.lock b/gui/yarn.lock
index 5ac0734e..05bf7b87 100644
--- a/gui/yarn.lock
+++ b/gui/yarn.lock
@@ -2500,6 +2500,13 @@
resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.10.tgz#04ffa7f406ab628f7f7e97ca23e290cd8ab15efc"
integrity sha512-IfYcSBWE3hLpBg8+X2SEa8LVkJdJEkT2Ese2aaLs3ptGdVtABxndrMaxuFlQ1qdFf9Q5rDvDpxI3WwgvKFAsQA==
+"@types/xterm@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/xterm/-/xterm-3.0.0.tgz#5b177010903ee1dc26fdc25d6e4e1f2490d44ce6"
+ integrity sha512-+VaAJQmE7E1d1ebkIh/Zdc2mbXBVwxZGGSgqwzDPpk/HKo0mNT+iX5ZrnswztHSV+CDV+bURl7Yg7PWF7IZfXQ==
+ dependencies:
+ xterm "*"
+
"@typescript-eslint/eslint-plugin@^6":
version "6.21.0"
resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz#30830c1ca81fd5f3c2714e524c4303e0194f9cd3"
@@ -2637,6 +2644,16 @@
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==
+"@xterm/addon-fit@^0.10.0":
+ version "0.10.0"
+ resolved "https://registry.yarnpkg.com/@xterm/addon-fit/-/addon-fit-0.10.0.tgz#bebf87fadd74e3af30fdcdeef47030e2592c6f55"
+ integrity sha512-UFYkDm4HUahf2lnEyHvio51TNGiLK66mqP2JoATy7hRZeXaGMRDr00JiSF7m63vR5WKATF605yEggJKsw0JpMQ==
+
+"@xterm/xterm@^5.5.0":
+ version "5.5.0"
+ resolved "https://registry.yarnpkg.com/@xterm/xterm/-/xterm-5.5.0.tgz#275fb8f6e14afa6e8a0c05d4ebc94523ff775396"
+ integrity sha512-hqJHYaQb5OptNunnyAnkHyM8aCjZ1MEIDTQu1iIbbTD/xops91NB5yq1ZK/dC2JDbVWtF23zUtl9JE2NqwT87A==
+
abbrev@1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
@@ -6922,6 +6939,11 @@ xtend@^4.0.0:
resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54"
integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==
+xterm@*, xterm@^5.3.0:
+ version "5.3.0"
+ resolved "https://registry.yarnpkg.com/xterm/-/xterm-5.3.0.tgz#867daf9cc826f3d45b5377320aabd996cb0fce46"
+ integrity sha512-8QqjlekLUFTrU6x7xck1MsPzPA571K5zNqWm0M0oroYEWVOptZ0+ubQSkQ3uxIEhcIHRujJy6emDWX4A7qyFzg==
+
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"