Skip to content

Commit 6b92c6c

Browse files
chore: code refactored
1 parent 7fafd2c commit 6b92c6c

23 files changed

Lines changed: 411 additions & 144 deletions

app.py

Lines changed: 56 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,31 @@
1414
# Initialize the database
1515
db = SQLAlchemy(app)
1616

17+
# config
18+
SPEEDTEST_COOLDOWN_IN_HOURS = 1 # in hours
19+
TIMEZONE = 'Asia/Kolkata'
20+
NUMBER_OF_SPEEDTESTS = 3
21+
1722
# Define the model for storing speed test results
1823
class SpeedTestResult(db.Model):
1924
id = db.Column(db.Integer, primary_key=True)
2025
download_speed = db.Column(db.String(50))
2126
upload_speed = db.Column(db.String(50))
2227
ping = db.Column(db.String(50))
23-
timestamp = db.Column(db.DateTime, default=datetime.datetime.now(datetime.UTC))
28+
timestamp = db.Column(db.DateTime, default=datetime.datetime.now())
2429

2530
def __repr__(self):
2631
return f'<SpeedTestResult {self.download_speed}, {self.upload_speed}, {self.ping}>'
2732

33+
# class DashoardSettings(db.Model):
34+
# id = db.Column(db.Integer, primary_key=True)
35+
# speedtest_cooldown = db.Column(db.Integer)
36+
# timezone = db.Column(db.String(50))
37+
# number_of_speedtests = db.Column(db.Integer)
38+
39+
# def __repr__(self):
40+
# return f'<DashboardSettings {self.speedtest_cooldown}, {self.timezone}, {self.number_of_speedtests}>'
41+
2842
def change_up_time_format(uptime):
2943
uptime_seconds = uptime.total_seconds()
3044
days = int(uptime_seconds // (24 * 3600))
@@ -48,23 +62,27 @@ def run_speedtest():
4862
elif "Ping:" in line:
4963
ping = line.split("Ping: ")[1]
5064

51-
return {"download_speed": download_speed, "upload_speed": upload_speed, "ping": ping}
65+
return {"download_speed": download_speed, "upload_speed": upload_speed, "ping": ping,
66+
"status": "Success"}
5267

5368
except subprocess.CalledProcessError as e:
54-
print(f"Speedtest failed with error: {e.stderr}")
55-
return None
69+
error = {"status": "Error", "message": e.stderr}
70+
return error
5671

5772
except Exception as e:
58-
print(f"Error occurred while running speed test: {e}")
59-
return None
73+
error = {"status": "Error", "message": str(e)}
74+
return error
6075

6176
@app.route('/speedtest')
6277
def speedtest():
63-
one_hour_ago = datetime.datetime.now(datetime.UTC) - datetime.timedelta(hours=1)
64-
recent_results = SpeedTestResult.query.filter(SpeedTestResult.timestamp > one_hour_ago).all()
78+
n_hour_ago = datetime.datetime.now() - datetime.timedelta(hours=SPEEDTEST_COOLDOWN_IN_HOURS)
79+
recent_results = SpeedTestResult.query.filter(SpeedTestResult.timestamp > n_hour_ago).all()
6580

66-
if len(recent_results) < 3:
81+
if len(recent_results) < NUMBER_OF_SPEEDTESTS:
6782
speedtest_result = run_speedtest()
83+
if speedtest_result['status'] == "Error":
84+
return render_template('error/speedtest_error.html', error=speedtest_result['message'])
85+
6886
if speedtest_result:
6987
new_result = SpeedTestResult(
7088
download_speed=speedtest_result['download_speed'],
@@ -121,7 +139,35 @@ def get_established_connections():
121139
@app.route('/')
122140
def dashboard():
123141
system_info = get_system_info()
124-
return render_template('dashboard.html', system_info=system_info)
142+
143+
# Fetch the last speedtest result
144+
n_hour_ago = datetime.datetime.now() - datetime.timedelta(hours=SPEEDTEST_COOLDOWN_IN_HOURS)
145+
recent_results = SpeedTestResult.query.filter(SpeedTestResult.timestamp > n_hour_ago).all()
146+
147+
if recent_results:
148+
# Display the most recent result from the database
149+
latest_result = recent_results[-1]
150+
speedtest_result = {
151+
'download_speed': latest_result.download_speed,
152+
'upload_speed': latest_result.upload_speed,
153+
'ping': latest_result.ping
154+
}
155+
source = "Database"
156+
next_test_time = latest_result.timestamp + datetime.timedelta(hours=1)
157+
show_prompt = False
158+
remaining_time_for_next_test = round((next_test_time - datetime.datetime.now()).total_seconds() / 60)
159+
else:
160+
# No recent results, prompt to perform a test
161+
speedtest_result = None
162+
source = None
163+
show_prompt = True
164+
remaining_time_for_next_test = None
165+
166+
return render_template('dashboard.html', system_info=system_info,
167+
speedtest_result=speedtest_result,
168+
source=source,
169+
next_test_time=remaining_time_for_next_test,
170+
show_prompt=show_prompt)
125171

126172
@app.route('/cpu_usage')
127173
def cpu_usage():

dashboard.sh

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,9 @@ export FLASK_ENV=development # or production
5454

5555
# Check if Flask app is running
5656
if ! pgrep -f "flask run --host=0.0.0.0 --port=$FLASK_PORT" > /dev/null; then
57+
# check for the latest version of the code and do a git pull
58+
git stash
59+
git pull
5760
echo "Flask app is not running. Starting..." >> "$LOG_FILE"
5861
flask run --host=0.0.0.0 --port="$FLASK_PORT" &
5962
else

static/css/speedtest_error.css

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
2+
.error-container {
3+
background-color: #f8d7da;
4+
border: 1px solid #f5c6cb;
5+
padding: 20px;
6+
border-radius: 10px;
7+
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
8+
text-align: center;
9+
}
10+
11+
.error-title {
12+
font-size: 2rem;
13+
margin-bottom: 10px;
14+
font-weight: bold;
15+
}
16+
17+
.error-message {
18+
font-size: 1.25rem;
19+
margin-bottom: 20px;
20+
}
21+
22+
.retry-button {
23+
background-color: #dc3545;
24+
color: white;
25+
padding: 10px 20px;
26+
text-decoration: none;
27+
border-radius: 5px;
28+
transition: background-color 0.3s ease;
29+
}
30+
31+
.retry-button:hover {
32+
background-color: #c82333;
33+
}

static/css/style.css

Lines changed: 172 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,40 @@
1+
/* Primary Colors */
2+
:root {
3+
--color-primary: #007bff; /* Bright blue for primary elements */
4+
--color-secondary: #6c757d; /* Gray for secondary elements */
5+
--color-success: #28a745; /* Green for success */
6+
--color-danger: #dc3545; /* Red for danger */
7+
--color-warning: #ffc107; /* Yellow for warning */
8+
--color-info: #17a2b8; /* Cyan for info */
9+
--color-light: #f8f9fa; /* Light gray for backgrounds */
10+
--color-dark: #343a40; /* Dark gray for text */
11+
--color-white: #ffffff; /* White for text */
12+
--color-black: #000000; /* Black for text */
13+
14+
/* card colors */
15+
--color-username: #007bff; /* Bright blue for username */
16+
--color-boot: #28a745; /* Green for boot time */
17+
--color-cpu: #af13e3; /* Red for CPU */
18+
--color-ip: #03e77c; /* Bright blue for IP address */
19+
--color-cpu-usage: #ffc107; /* Yellow for CPU usage */
20+
--color-memory: #6f42c1; /* Purple for memory */
21+
--color-disk: #6c757d; /* Gray for disk */
22+
--color-uptime: #17a2b8; /* Cyan for uptime */
23+
--color-network: #11eeee; /* Bright blue for network */
24+
--color-speedtest: #c9ef4b; /* Bright blue for speedtest */
25+
--color-battery: #007bff; /* Bright blue for battery */
26+
27+
/* shadow colors */
28+
--color-shadow: #f80000; /* Red shadow for username */
29+
30+
/* Battery colors */
31+
--color-battery-100: linear-gradient(135deg, #76c7c0, #4caf50); /* Green gradient for 100% battery */
32+
--color-battery-75: linear-gradient(135deg, #76c7c0, #ffeb3b); /* Yellow gradient for 75% battery */
33+
--color-battery-50: linear-gradient(135deg, #38322a, #3a3732); /* Orange gradient for 50% battery */
34+
--color-battery-25: linear-gradient(135deg, #58382f, #483b3a); /* Red gradient for 25% battery */
35+
--color-battery-0: linear-gradient(135deg, #f44336, #d32f2f); /* Dark red gradient for 0% battery */
36+
}
37+
138
/* General Styles */
239
body {
340
font-family: 'Arial', sans-serif;
@@ -89,50 +126,54 @@ body {
89126
border-radius: 10px; /* Rounded corners */
90127
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.1); /* Box shadow for depth */
91128
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition for hover effect */
129+
position: relative; /* Allows positioning for the pseudo-element */
92130
}
93131

94132
/* Specific Background Colors */
133+
.card.bg-basic {
134+
background-color: var(--color-primary); /* Bright blue for basic info */
135+
}
136+
95137
.card.bg-username {
96-
background-color: #007bff; /* Bright blue for user-related info */
138+
background-color: var(--color-username); /* Bright blue for username */
97139
}
98140

99141
.card.bg-ipv4 {
100-
background-color: #ff5722; /* Warm orange for network info */
142+
background-color: var(--color-ip); /* Bright blue for IP address */
101143
}
102144

103145
.card.bg-cpu {
104-
background-color: #f44336; /* Red for CPU-related info */
146+
background-color: var(--color-cpu); /* Red for CPU */
105147
}
106148

107149
.card.bg-boot {
108-
background-color: #9c27b0; /* Purple for boot time */
150+
background-color: var(--color-boot); /* Green for boot time */
109151
}
110152

111153
.card.bg-cpu-usage {
112-
background-color: #ff9800; /* Orange for CPU usage */
154+
background-color: var(--color-cpu-usage); /* Yellow for CPU usage */
113155
}
114156

115157
.card.bg-memory {
116-
background-color: #3f51b5; /* Deep blue for memory usage */
158+
background-color: var(--color-memory); /* Purple for memory usage */
117159
}
118160

119161
.card.bg-disk {
120-
background-color: #607d8b; /* Blue-gray for disk usage */
162+
background-color: var(--color-disk); /* Gray for disk usage */
121163
}
122164

123165
.card.bg-uptime {
124-
background-color: #8bc34a; /* Light green for uptime */
166+
background-color: var(--color-uptime); /* Cyan for uptime */
125167
}
126168

127169
.card.bg-network {
128-
background-color: #00bcd4; /* Teal for network statistics */
170+
background-color: var(--color-network); /* Bright blue for network */
129171
}
130172

131173
.card.bg-speedtest {
132-
background-color: #ff9800; /* Orange for CPU usage */
174+
background-color: var(--color-speedtest); /* Bright blue for speedtest */
133175
}
134176

135-
136177
.card-body {
137178
display: flex;
138179
flex-direction: column;
@@ -197,3 +238,123 @@ body {
197238
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2);
198239
color: #fff;
199240
}
241+
242+
/* Card containing CPU core visualization */
243+
.card.bg-cpu {
244+
position: relative;
245+
}
246+
247+
.cpu-core-visualization {
248+
display: flex;
249+
gap: 0.5rem; /* Space between bars */
250+
margin-top: 1rem;
251+
justify-content: center; /* Center-align bars */
252+
}
253+
254+
/* Individual bar representing a CPU core */
255+
.cpu-core-bar {
256+
width: 10px; /* Width of each bar */
257+
height: 10px; /* Height of each bar */
258+
background-color: #ffffff; /* Bar color */
259+
border-radius: 5px; /* Rounded corners */
260+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2); /* Shadow for depth */
261+
transition: background-color 0.3s ease; /* Smooth transition on hover */
262+
}
263+
264+
/* General Card Hover Effect */
265+
.card:hover {
266+
transform: translateY(-8px); /* Slight lift effect */
267+
box-shadow: 0 10px 20px rgba(0, 0, 0, 0.2); /* Subtle shadow for depth */
268+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
269+
}
270+
271+
/* Specific Background Colors with Hover Effects */
272+
273+
/* User-related info */
274+
.card.bg-username:hover {
275+
transform: translateY(-8px); /* Slight lift effect */
276+
box-shadow: 0 10px 20px var(--color-shadow);
277+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
278+
}
279+
280+
/* Network info */
281+
.card.bg-ipv4:hover {
282+
transform: translateY(-8px); /* Slight lift effect */
283+
box-shadow: 0 10px 20px var(--color-shadow);
284+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
285+
}
286+
287+
/* CPU-related info */
288+
.card.bg-cpu:hover {
289+
transform: translateY(-8px); /* Slight lift effect */
290+
box-shadow: 0 10px 20px var(--color-shadow);
291+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
292+
}
293+
294+
/* Boot time */
295+
.card.bg-boot:hover {
296+
transform: translateY(-8px); /* Slight lift effect */
297+
box-shadow: 0 10px 20px var(--color-shadow);
298+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
299+
}
300+
301+
/* CPU usage */
302+
.card.bg-cpu-usage:hover {
303+
transform: translateY(-8px); /* Slight lift effect */
304+
box-shadow: 0 10px 20px var(--color-shadow);
305+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
306+
}
307+
308+
/* Memory usage */
309+
.card.bg-memory:hover {
310+
transform: translateY(-8px); /* Slight lift effect */
311+
box-shadow: 0 10px 20px var(--color-shadow);
312+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
313+
}
314+
315+
/* Disk usage */
316+
.card.bg-disk:hover {
317+
transform: translateY(-8px); /* Slight lift effect */
318+
box-shadow: 0 10px 20px var(--color-shadow);
319+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
320+
}
321+
322+
/* Uptime */
323+
.card.bg-uptime:hover {
324+
transform: translateY(-8px); /* Slight lift effect */
325+
box-shadow: 0 10px 20px var(--color-shadow);
326+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
327+
}
328+
329+
/* Network statistics */
330+
.card.bg-network:hover {
331+
transform: translateY(-8px); /* Slight lift effect */
332+
box-shadow: 0 10px 20px var(--color-shadow);
333+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
334+
}
335+
336+
/* Speedtest */
337+
.card.bg-speedtest:hover {
338+
transform: translateY(-8px); /* Slight lift effect */
339+
box-shadow: 0 10px 20px var(--color-shadow);
340+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
341+
}
342+
343+
/* Battery Card Styles */
344+
.battery-card:hover {
345+
transform: translateY(-8px); /* Slight lift effect */
346+
box-shadow: 0 10px 20px var(--color-shadow);
347+
transition: transform 0.3s ease, box-shadow 0.3s ease; /* Smooth transition */
348+
}
349+
350+
/* Card Red Bottom Effect */
351+
.card::before {
352+
content: "";
353+
position: absolute;
354+
bottom: 0;
355+
left: 0;
356+
width: 100%;
357+
height: 10px; /* Height of the red effect */
358+
border-radius: 0 0 10px 10px; /* Match the card's border radius */
359+
z-index: 1; /* Ensure it's on top of the card content */
360+
}

templates/base.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
99
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.0.0/css/all.min.css" rel="stylesheet">
1010
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
11+
1112
{% block extra_head %}{% endblock %}
1213
</head>
1314

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<div class="col-md-6 col-lg-4 mb-4">
2+
<div class="card battery-card" data-battery="{{ system_info['battery_percent'] }}">
3+
<div class="card-body">
4+
<h5 class="card-title">Battery Percentage <i class="fas fa-battery-three-quarters"></i></h5>
5+
<p class="card-text fs-4">{{ system_info['battery_percent'] }}%</p>
6+
</div>
7+
</div>
8+
</div>

0 commit comments

Comments
 (0)