Rémy commited on
Commit
d45df14
1 Parent(s): a978cdf

Update to serve static files and fix API endpoint

Browse files
Files changed (3) hide show
  1. Dockerfile +2 -0
  2. app.py +6 -1
  3. static/index.html +147 -0
Dockerfile CHANGED
@@ -10,4 +10,6 @@ COPY --chown=user ./requirements.txt requirements.txt
10
  RUN pip install --no-cache-dir --upgrade -r requirements.txt
11
 
12
  COPY --chown=user . /app
 
 
13
  CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
 
10
  RUN pip install --no-cache-dir --upgrade -r requirements.txt
11
 
12
  COPY --chown=user . /app
13
+ COPY --chown=user ./static /app/static
14
+
15
  CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
app.py CHANGED
@@ -1,5 +1,7 @@
1
  from fastapi import FastAPI, HTTPException
2
  from fastapi.middleware.cors import CORSMiddleware
 
 
3
  from pydantic import BaseModel
4
  import subprocess
5
  import shlex
@@ -15,6 +17,9 @@ app.add_middleware(
15
  allow_headers=["*"], # Allows all headers
16
  )
17
 
 
 
 
18
  ALLOWED_COMMANDS = {
19
  'ls', 'cd', 'pwd', 'echo', 'cat', 'grep', 'find', 'touch', 'mkdir', 'rm', 'cp', 'mv'
20
  }
@@ -46,4 +51,4 @@ async def execute_command(command: Command):
46
 
47
  @app.get("/")
48
  async def root():
49
- return {"message": "Welcome to the Linux Practice Tool API"}
 
1
  from fastapi import FastAPI, HTTPException
2
  from fastapi.middleware.cors import CORSMiddleware
3
+ from fastapi.staticfiles import StaticFiles
4
+ from fastapi.responses import FileResponse
5
  from pydantic import BaseModel
6
  import subprocess
7
  import shlex
 
17
  allow_headers=["*"], # Allows all headers
18
  )
19
 
20
+ # Mount the static files directory
21
+ app.mount("/static", StaticFiles(directory="static"), name="static")
22
+
23
  ALLOWED_COMMANDS = {
24
  'ls', 'cd', 'pwd', 'echo', 'cat', 'grep', 'find', 'touch', 'mkdir', 'rm', 'cp', 'mv'
25
  }
 
51
 
52
  @app.get("/")
53
  async def root():
54
+ return FileResponse('static/index.html')
static/index.html ADDED
@@ -0,0 +1,147 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Linux Practice Tool</title>
7
+ <style>
8
+ body {
9
+ font-family: monospace;
10
+ background-color: #000;
11
+ color: #0f0;
12
+ margin: 0;
13
+ padding: 20px;
14
+ }
15
+ #terminal {
16
+ width: 100%;
17
+ height: 100vh;
18
+ overflow-y: auto;
19
+ }
20
+ #output {
21
+ white-space: pre-wrap;
22
+ }
23
+ #input-line {
24
+ display: flex;
25
+ margin-top: 10px;
26
+ }
27
+ #prompt {
28
+ margin-right: 5px;
29
+ }
30
+ #command-input {
31
+ flex-grow: 1;
32
+ background-color: transparent;
33
+ border: none;
34
+ color: #0f0;
35
+ font-family: inherit;
36
+ font-size: inherit;
37
+ outline: none;
38
+ }
39
+ </style>
40
+ </head>
41
+ <body>
42
+ <div id="terminal">
43
+ <div id="output"></div>
44
+ <div id="input-line">
45
+ <span id="prompt">$</span>
46
+ <input type="text" id="command-input" autofocus>
47
+ </div>
48
+ </div>
49
+ <script>
50
+ const output = document.getElementById('output');
51
+ const input = document.getElementById('command-input');
52
+
53
+ let commandHistory = [];
54
+ let historyIndex = -1;
55
+
56
+ input.addEventListener('keydown', async (event) => {
57
+ if (event.key === 'Enter') {
58
+ event.preventDefault();
59
+ const command = input.value.trim();
60
+ if (command) {
61
+ commandHistory.push(command);
62
+ historyIndex = commandHistory.length;
63
+ await executeCommand(command);
64
+ }
65
+ input.value = '';
66
+ } else if (event.key === 'ArrowUp') {
67
+ event.preventDefault();
68
+ if (historyIndex > 0) {
69
+ historyIndex--;
70
+ input.value = commandHistory[historyIndex];
71
+ }
72
+ } else if (event.key === 'ArrowDown') {
73
+ event.preventDefault();
74
+ if (historyIndex < commandHistory.length - 1) {
75
+ historyIndex++;
76
+ input.value = commandHistory[historyIndex];
77
+ } else {
78
+ historyIndex = commandHistory.length;
79
+ input.value = '';
80
+ }
81
+ }
82
+ });
83
+
84
+ async function executeCommand(command) {
85
+ if (command.toLowerCase() === 'help') {
86
+ displayHelp();
87
+ } else {
88
+ output.innerHTML += `$ ${command}\n`;
89
+
90
+ try {
91
+ const response = await fetch('/execute', {
92
+ method: 'POST',
93
+ headers: {
94
+ 'Content-Type': 'application/json',
95
+ },
96
+ body: JSON.stringify({ command }),
97
+ });
98
+
99
+ const data = await response.json();
100
+
101
+ if (response.ok) {
102
+ output.innerHTML += data.output;
103
+ if (data.error) {
104
+ output.innerHTML += `Error: ${data.error}\n`;
105
+ }
106
+ } else {
107
+ output.innerHTML += `Error: ${data.detail}\n`;
108
+ }
109
+ } catch (error) {
110
+ output.innerHTML += `Error: ${error.message}\n`;
111
+ }
112
+ }
113
+
114
+ output.scrollTop = output.scrollHeight;
115
+ }
116
+
117
+ function displayHelp() {
118
+ const helpText = `
119
+ Available commands:
120
+ - ls: List directory contents
121
+ - cd: Change directory
122
+ - pwd: Print working directory
123
+ - echo: Display a line of text
124
+ - cat: Concatenate files and print on the standard output
125
+ - grep: Print lines that match patterns
126
+ - find: Search for files in a directory hierarchy
127
+ - touch: Change file timestamps
128
+ - mkdir: Make directories
129
+ - rm: Remove files or directories
130
+ - cp: Copy files and directories
131
+ - mv: Move (rename) files
132
+
133
+ Type 'help' to see this message again.
134
+ `;
135
+ output.innerHTML += helpText;
136
+ }
137
+
138
+ // Focus on input when clicking anywhere in the terminal
139
+ document.getElementById('terminal').addEventListener('click', () => {
140
+ input.focus();
141
+ });
142
+
143
+ // Initial welcome message
144
+ output.innerHTML = "Welcome to the Linux Practice Tool!\nType 'help' for a list of available commands.\n\n";
145
+ </script>
146
+ </body>
147
+ </html>