Skip to content

Commit d06088f

Browse files
authored
feat: add uplot chart (#11)
1 parent 2a3eace commit d06088f

5 files changed

Lines changed: 712 additions & 168 deletions

File tree

‎web/package-lock.json‎

Lines changed: 8 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎web/package.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@
1111
},
1212
"dependencies": {
1313
"react": "^18.2.0",
14-
"react-dom": "^18.2.0"
14+
"react-dom": "^18.2.0",
15+
"uplot": "^1.6.32"
1516
},
1617
"devDependencies": {
1718
"@types/react": "^18.2.43",

‎web/src/App.css‎

Lines changed: 83 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ body {
150150
.value-success {
151151
font-weight: 600;
152152
color: var(--color-success);
153-
font-size: 0.875rem;
153+
font-size: 0.65rem;
154154
}
155155

156156
.value-warning {
@@ -162,7 +162,7 @@ body {
162162
.value-error {
163163
font-weight: 600;
164164
color: var(--color-error);
165-
font-size: 0.875rem;
165+
font-size: 0.65rem;
166166
}
167167

168168
.miners-list {
@@ -239,7 +239,7 @@ body {
239239
right: 0;
240240
bottom: 0;
241241
background-image: url("../assets/ems.png");
242-
background-size: cover;
242+
background-size: contain;
243243
background-position: center;
244244
background-repeat: no-repeat;
245245
z-index: 0;
@@ -252,6 +252,8 @@ body {
252252
justify-content: center;
253253
align-items: center;
254254
min-height: 250px;
255+
width: 100%;
256+
height: 100%;
255257
}
256258

257259
.pv-power-display {
@@ -392,26 +394,38 @@ body {
392394
.mpc-table {
393395
width: 100%;
394396
border-collapse: collapse;
395-
font-size: 0.875rem;
397+
font-size: 0.7rem;
398+
table-layout: fixed;
396399
}
397400

398401
.mpc-table thead {
399402
background-color: rgba(51, 65, 85, 0.7);
400403
}
401404

402405
.mpc-table th {
403-
padding: 0.75rem 1rem;
406+
padding: 0.4rem 0.5rem;
404407
text-align: left;
405408
font-weight: 600;
406409
color: var(--color-text);
407410
border-bottom: 2px solid var(--color-border);
408411
text-transform: uppercase;
409-
font-size: 0.75rem;
410-
letter-spacing: 0.05em;
412+
font-size: 0.65rem;
413+
letter-spacing: 0.03em;
414+
}
415+
416+
.mpc-table th:first-child,
417+
.mpc-table td:first-child {
418+
width: 120px;
419+
}
420+
421+
.mpc-table th:not(:first-child),
422+
.mpc-table td:not(:first-child) {
423+
width: 25px;
424+
text-align: center;
411425
}
412426

413427
.mpc-table td {
414-
padding: 0.75rem 1rem;
428+
padding: 0.4rem 0.5rem;
415429
border-bottom: 1px solid var(--color-border);
416430
color: var(--color-text);
417431
}
@@ -428,29 +442,15 @@ body {
428442
border-bottom: none;
429443
}
430444

431-
/* Prevent wrapping in forecast and profit columns */
432-
.mpc-table th:nth-child(5),
433-
.mpc-table th:nth-child(6),
434-
.mpc-table th:nth-child(7),
435-
.mpc-table th:nth-child(8),
436-
.mpc-table th:nth-child(9),
437-
.mpc-table td:nth-child(5),
438-
.mpc-table td:nth-child(6),
439-
.mpc-table td:nth-child(7),
440-
.mpc-table td:nth-child(8),
441-
.mpc-table td:nth-child(9) {
442-
white-space: nowrap;
443-
}
444-
445445
/* Forecast data header styling */
446446
.mpc-table thead tr:first-child th {
447447
vertical-align: middle;
448448
}
449449

450450
.mpc-table thead tr:nth-child(2) th {
451-
padding-top: 0.5rem;
452-
padding-bottom: 0.75rem;
453-
font-size: 0.7rem;
451+
padding-top: 0.3rem;
452+
padding-bottom: 0.4rem;
453+
font-size: 0.6rem;
454454
}
455455

456456
.action-charge,
@@ -513,19 +513,72 @@ body {
513513
}
514514

515515
.devices-section {
516-
min-height: 200px;
516+
min-height: auto;
517+
padding: 1rem;
518+
}
519+
520+
.devices-section::before {
521+
/* Hide background image on mobile */
522+
display: none;
517523
}
518524

519525
.devices-content {
520-
min-height: 150px;
526+
min-height: auto;
527+
flex-direction: column;
528+
gap: 1rem;
529+
padding: 0;
530+
position: static !important;
531+
}
532+
533+
/* Wrapper for power displays with mobile labels */
534+
.devices-content .power-display-wrapper {
535+
position: static !important;
536+
margin: 0 auto;
537+
width: 100%;
538+
max-width: 280px;
539+
display: flex;
540+
flex-direction: column;
541+
align-items: center;
542+
}
543+
544+
/* Show label from data attribute on mobile */
545+
.devices-content .power-display-wrapper::before {
546+
content: attr(data-mobile-label);
547+
font-size: 0.875rem;
548+
font-weight: 600;
549+
color: var(--color-text-secondary);
550+
text-transform: uppercase;
551+
letter-spacing: 0.05em;
552+
margin-bottom: 0.5rem;
553+
text-align: center;
554+
}
555+
556+
/* Convert absolute positioned PowerDisplay components to static flow on mobile */
557+
.devices-content .power-display-wrapper .pv-power-display {
558+
position: static !important;
559+
margin: 0 auto;
560+
width: 100%;
561+
padding: 1rem 1.5rem;
562+
display: flex;
563+
flex-direction: column;
564+
align-items: center;
521565
}
522566

523-
.pv-power-display {
524-
padding: 1.5rem 2rem;
567+
.devices-content .solar-info {
568+
position: static !important;
569+
width: 100% !important;
570+
max-width: 280px;
571+
margin: 0 auto;
525572
}
526573

527574
.pv-power-value {
528-
font-size: 2rem;
575+
font-size: 1.5rem;
576+
}
577+
578+
.pv-power-label {
579+
font-size: 0.875rem;
580+
margin-bottom: 0.5rem;
581+
margin-top: 0 !important;
529582
}
530583

531584
.mpc-summary {

‎web/src/App.tsx‎

Lines changed: 67 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -129,48 +129,81 @@ function App() {
129129
<section className="card devices-section">
130130
<h2>Devices</h2>
131131
<div className="devices-content" style={{ position: "relative" }}>
132-
<PowerDisplay
133-
value={health?.ems?.current_pv_power}
134-
style={{ position: "absolute", top: "202px", right: "170px" }}
135-
/>
132+
<div
133+
className="power-display-wrapper"
134+
data-mobile-label="Solar Power"
135+
>
136+
<PowerDisplay
137+
value={health?.ems?.current_pv_power}
138+
style={{ position: "absolute", top: "202px", right: "170px" }}
139+
/>
140+
</div>
136141

137-
<PowerDisplay
138-
value={health?.ems?.ess_power}
139-
invertColors={true}
140-
label={
142+
<div
143+
className="power-display-wrapper"
144+
data-mobile-label={
141145
health?.ems?.ess_soc !== undefined
142-
? `${health.ems.ess_soc.toFixed(1)}%`
143-
: "N/A"
146+
? `Battery (${health.ems.ess_soc.toFixed(1)}%)`
147+
: "Battery"
144148
}
145-
style={{ position: "absolute", top: "643px", right: "622px" }}
146-
/>
149+
>
150+
<PowerDisplay
151+
value={health?.ems?.ess_power}
152+
invertColors={true}
153+
label={
154+
health?.ems?.ess_soc !== undefined
155+
? `${health.ems.ess_soc.toFixed(1)}%`
156+
: "N/A"
157+
}
158+
style={{ position: "absolute", top: "643px", right: "622px" }}
159+
/>
160+
</div>
147161

148-
<PowerDisplay
149-
value={
150-
health?.ems?.grid_sensor_status === 1
151-
? health?.ems?.grid_sensor_active_power
152-
: undefined
153-
}
154-
style={{ position: "absolute", top: "556px", left: "220px" }}
155-
/>
162+
<div
163+
className="power-display-wrapper"
164+
data-mobile-label="Grid Power"
165+
>
166+
<PowerDisplay
167+
value={
168+
health?.ems?.grid_sensor_status === 1
169+
? health?.ems?.grid_sensor_active_power
170+
: undefined
171+
}
172+
style={{ position: "absolute", top: "556px", left: "220px" }}
173+
/>
174+
</div>
156175

157-
<PowerDisplay
158-
value={health?.ems?.plant_active_power}
159-
label="Active Power"
160-
invertColors={true}
161-
showLabel={true}
162-
style={{ position: "absolute", top: "194px", left: "223px" }}
163-
/>
176+
<div
177+
className="power-display-wrapper"
178+
data-mobile-label="Plant Active Power"
179+
>
180+
<PowerDisplay
181+
value={health?.ems?.plant_active_power}
182+
label="Active Power"
183+
invertColors={true}
184+
showLabel={true}
185+
style={{ position: "absolute", top: "194px", left: "223px" }}
186+
/>
187+
</div>
164188

165-
<PowerDisplay
166-
value={health?.ems?.dc_charger_output_power}
167-
label={
189+
<div
190+
className="power-display-wrapper"
191+
data-mobile-label={
168192
health?.ems?.dc_charger_vehicle_soc !== undefined
169-
? `${health.ems.dc_charger_vehicle_soc.toFixed(1)}%`
170-
: "N/A"
193+
? `EV Charger (${health.ems.dc_charger_vehicle_soc.toFixed(1)}%)`
194+
: "EV Charger"
171195
}
172-
style={{ position: "absolute", top: "428px", right: "162px" }}
173-
/>
196+
>
197+
<PowerDisplay
198+
value={health?.ems?.dc_charger_output_power}
199+
label={
200+
health?.ems?.dc_charger_vehicle_soc !== undefined
201+
? `${health.ems.dc_charger_vehicle_soc.toFixed(1)}%`
202+
: "N/A"
203+
}
204+
style={{ position: "absolute", top: "428px", right: "162px" }}
205+
/>
206+
</div>
174207

175208
<SolarInfo
176209
solarAngle={health?.sun?.solar_angle}

0 commit comments

Comments
 (0)