hectorruiz9 commited on
Commit
5d31219
·
verified ·
1 Parent(s): 93f7d96

Update Dockerfile

Browse files
Files changed (1) hide show
  1. Dockerfile +285 -20
Dockerfile CHANGED
@@ -1,27 +1,292 @@
1
- FROM python:3.13-slim
 
 
 
 
 
 
2
 
3
- # 1. Instalamos dependencias y el binario de uv
4
- RUN apt-get update && apt-get install -y \
5
- curl \
6
- build-essential \
7
- && curl -LsSf https://astral.sh | sh \
8
- && rm -rf /var/lib/apt/lists/*
9
 
10
- # Aseguramos que uv esté en el PATH para el resto del build
11
- ENV PATH="/root/.local/bin/:$PATH"
 
 
 
 
12
 
13
- RUN useradd -m -u 1000 user
14
- # Añadimos el path del usuario para el runtime
15
- ENV PATH="/home/user/.local/bin:$PATH"
16
- ENV UV_SYSTEM_PYTHON=1
 
 
 
 
 
17
 
18
- WORKDIR /app
 
 
 
19
 
20
- # 2. Copiamos e instalamos dependencias
21
- COPY --chown=user ./requirements.txt requirements.txt
22
- RUN uv pip install -r requirements.txt
23
 
24
- COPY --chown=user . /app
25
- USER user
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
 
27
- CMD ["python", "app.py"]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import React, { useState, useEffect } from 'react';
2
+ import axios from 'axios';
3
+ import Toggler from './components/Toggler';
4
+ import Dashboard from './screens/Dashboard';
5
+ import Login from './screens/Login';
6
+ import Reportes from './screens/Reportes';
7
+ import MonitoreoGnosis from './screens/MonitoreoGnosis';
8
 
9
+ function HectronApp() {
10
+ const [logged, setLogged] = useState(false);
11
+ const [sintonizado, setSintonizado] = useState(false);
 
 
 
12
 
13
+ useEffect(() => {
14
+ const token = localStorage.getItem('token');
15
+ if (token) {
16
+ setLogged(true);
17
+ }
18
+ }, []);
19
 
20
+ const handleLogin = async (email, password) => {
21
+ try {
22
+ const response = await axios.post('/login', { email, password });
23
+ localStorage.setItem('token', response.data.token);
24
+ setLogged(true);
25
+ } catch (error) {
26
+ console.error(error);
27
+ }
28
+ };
29
 
30
+ const handleLogout = () => {
31
+ localStorage.removeItem('token');
32
+ setLogged(false);
33
+ };
34
 
35
+ const handleSintonizar = () => {
36
+ setSintonizado(!sintonizado);
37
+ };
38
 
39
+ return (
40
+ <div className="flex h-screen justify-center items-center overflow-hidden">
41
+ {logged ? (
42
+ <div className="relative flex w-full items-center justify-between py-4">
43
+ <div className="hidden lg:block">
44
+ <img src="/hectron-logo.png" alt="Hectron logo" className="w-32" />
45
+ </div>
46
+ <div className="lg:hidden">
47
+ <Toggler
48
+ checked={sintonizado}
49
+ onChange={handleSintonizar}
50
+ label="Sintonizar"
51
+ />
52
+ </div>
53
+ <div className="hidden lg:flex">
54
+ <Toggler
55
+ checked={sintonizado}
56
+ onChange={handleSintonizar}
57
+ label="Sintonizar"
58
+ className="ml-auto"
59
+ />
60
+ </div>
61
+ <div className="lg:hidden">
62
+ <button
63
+ onClick={handleLogout}
64
+ className="bg-red-500 hover:bg-red-700 text-white py-2 px-4 rounded"
65
+ >
66
+ Desconectar
67
+ </button>
68
+ </div>
69
+ </div>
70
+ ) : (
71
+ <Login onLogin={handleLogin} />
72
+ )}
73
+ {logged && (
74
+ <main className="flex-1 max-w-7xl mx-auto p-4">
75
+ <div className="flex w-full lg:h-screen">
76
+ <div className="w-24 lg:w-64 fixed top-24 hidden lg:block left-4 bg-white shadow-md rounded p-4">
77
+ <ul>
78
+ <li>
79
+ <a
80
+ href="#"
81
+ className="flex justify-between items-center py-2 text-gray-600 hover:text-gray-900"
82
+ >
83
+ <span>Monitoreo de Gnosis</span>
84
+ <span className="ml-2">
85
+ <i className="fas fa-tachometer-alt" />
86
+ </span>
87
+ </a>
88
+ </li>
89
+ <li>
90
+ <a
91
+ href="#"
92
+ className="flex justify-between items-center py-2 text-gray-600 hover:text-gray-900"
93
+ >
94
+ <span>Configuración de alertas</span>
95
+ <span className="ml-2">
96
+ <i className="fas fa-bell" />
97
+ </span>
98
+ </a>
99
+ </li>
100
+ <li>
101
+ <a
102
+ href="#"
103
+ className="flex justify-between items-center py-2 text-gray-600 hover:text-gray-900"
104
+ >
105
+ <span>Acceso a reportes</span>
106
+ <span className="ml-2">
107
+ <i className="fas fa-file" />
108
+ </span>
109
+ </a>
110
+ </li>
111
+ <li>
112
+ <a
113
+ href="#"
114
+ className="flex justify-between items-center py-2 text-gray-600 hover:text-gray-900"
115
+ >
116
+ <span>Desplegar agentes y ejecutar tareas</span>
117
+ <span className="ml-2">
118
+ <i className="fas fa-robot" />
119
+ </span>
120
+ </a>
121
+ </li>
122
+ </ul>
123
+ </div>
124
+ <div className="w-full lg:w-7xl mx-auto p-4">
125
+ {sintonizado && <Dashboard />}
126
+ {!sintonizado && (
127
+ <div className="text-center">
128
+ <h2 className="text-2xl font-bold mb-4">Dashboard</h2>
129
+ <p>Pulse el botón para sintonizar</p>
130
+ <button
131
+ onClick={handleSintonizar}
132
+ className="bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded"
133
+ >
134
+ Sintonizar
135
+ </button>
136
+ </div>
137
+ )}
138
+ {!logged && <Reportes />}
139
+ {logged && !sintonizado && (
140
+ <MonitoreoGnosis />
141
+ )}
142
+ </div>
143
+ </div>
144
+ </main>
145
+ )}
146
+ </div>
147
+ );
148
+ }
149
 
150
+ export default HectronApp;
151
+ ```
152
+ **Login.js**
153
+ ```jsx
154
+ import React, { useState } from 'react';
155
+ import axios from 'axios';
156
+
157
+ const Login = ({ onLogin }) => {
158
+ const [email, setEmail] = useState('');
159
+ const [password, setPassword] = useState('');
160
+ const [error, setError] = useState(null);
161
+
162
+ const handleLogin = async () => {
163
+ if (!email || !password) {
164
+ return setError('Correo electrónico y contraseña son obligatorios');
165
+ }
166
+ try {
167
+ const response = await axios.post('/login', { email, password });
168
+ onLogin(email, password);
169
+ } catch (error) {
170
+ console.error(error);
171
+ setError('Error de autenticación');
172
+ }
173
+ };
174
+
175
+ return (
176
+ <div className="flex h-screen justify-center items-center overflow-hidden bg-gray-100">
177
+ <div className="max-w-md p-8 bg-white rounded-lg shadow-lg">
178
+ <h2 className="text-2xl font-bold mb-4">Inicio de sesión</h2>
179
+ {error && <p className="text-red-500 mb-4">{error}</p>}
180
+ <form>
181
+ <div className="mb-4">
182
+ <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="email">
183
+ Correo electrónico
184
+ </label>
185
+ <input
186
+ className="shadow appearance-none border rounded py-2 px-3 w-full justify-center items-center"
187
+ id="email"
188
+ type="email"
189
+ value={email}
190
+ onChange={(e) => setEmail(e.target.value)}
191
+ />
192
+ </div>
193
+ <div className="mb-4">
194
+ <label className="block text-gray-700 text-sm font-bold mb-2" htmlFor="password">
195
+ Contraseña
196
+ </label>
197
+ <input
198
+ className="shadow appearance-none border rounded py-2 px-3 w-full justify-center items-center"
199
+ id="password"
200
+ type="password"
201
+ value={password}
202
+ onChange={(e) => setPassword(e.target.value)}
203
+ />
204
+ </div>
205
+ <button
206
+ className="bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded"
207
+ onClick={handleLogin}
208
+ >
209
+ Iniciar sesión
210
+ </button>
211
+ </form>
212
+ </div>
213
+ </div>
214
+ );
215
+ };
216
+
217
+ export default Login;
218
+ ```
219
+ **Dashboard.js**
220
+ ```jsx
221
+ import React from 'react';
222
+ import axios from 'axios';
223
+
224
+ const Dashboard = () => {
225
+ const [data, setData] = React.useState({});
226
+
227
+ React.useEffect(() => {
228
+ const fetchDashboardData = async () => {
229
+ try {
230
+ const response = await axios.get('/dashboard');
231
+ setData(response.data);
232
+ } catch (error) {
233
+ console.error(error);
234
+ }
235
+ };
236
+ fetchDashboardData();
237
+ }, []);
238
+
239
+ return (
240
+ <div className="max-w-md p-8 bg-white rounded-lg shadow-lg">
241
+ <h2 className="text-2xl font-bold mb-4">Dashboard</h2>
242
+ <ul>
243
+ <li>
244
+ <span className="text-gray-700 text-sm font-bold mb-2">Monitoreo de Gnosis</span>
245
+ <span className="ml-2">{data.monitoreoGnosis}</span>
246
+ </li>
247
+ <li>
248
+ <span className="text-gray-700 text-sm font-bold mb-2">Configuración de alertas</span>
249
+ <span className="ml-2">{data.configuracionAlertas}</span>
250
+ </li>
251
+ <li>
252
+ <span className="text-gray-700 text-sm font-bold mb-2">Acceso a reportes</span>
253
+ <span className="ml-2">{data.accesoReportes}</span>
254
+ </li>
255
+ </ul>
256
+ </div>
257
+ );
258
+ };
259
+
260
+ export default Dashboard;
261
+ ```
262
+ **Reportes.js**
263
+ ```jsx
264
+ import React from 'react';
265
+
266
+ const Reportes = () => {
267
+ return (
268
+ <div className="max-w-md p-8 bg-white rounded-lg shadow-lg">
269
+ <h2 className="text-2xl font-bold mb-4">Reportes</h2>
270
+ <p>Este es un lugar donde se podrán ver reportes de la aplicación.</p>
271
+ </div>
272
+ );
273
+ };
274
+
275
+ export default Reportes;
276
+ ```
277
+ **MonitoreoGnosis.js**
278
+ ```jsx
279
+ import React from 'react';
280
+
281
+ const MonitoreoGnosis = () => {
282
+ return (
283
+ <div className="max-w-md p-8 bg-white rounded-lg shadow-lg">
284
+ <h2 className="text-2xl font-bold mb-4">Monitoreo de Gnosis</h2>
285
+ <p>Este es un lugar donde se puede monitorear la salud y el estado del sistema.</p>
286
+ </div>
287
+ );
288
+ };
289
+
290
+ export default MonitoreoGnosis;
291
+ ```
292
+ Estos componentes principales están implementados con Tailwind y se pueden personalizar de acuerdo a las necesidades específicas de HECTRON.