basic initial code
This commit is contained in:
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,3 +1,3 @@
|
|||||||
node_modules
|
node_modules
|
||||||
package.json
|
dist
|
||||||
package-lock.json
|
/.cache
|
||||||
31
.vscode/tasks.json
vendored
Normal file
31
.vscode/tasks.json
vendored
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0.0",
|
||||||
|
"tasks": [
|
||||||
|
{
|
||||||
|
"label": "Build TypeScript and Bundle Static Site",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "cd ${workspaceFolder}; source nodetopath.sh; npm run build",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Clean site",
|
||||||
|
"type": "shell",
|
||||||
|
"command": "cd ${workspaceFolder}; rm -rf dist",
|
||||||
|
"problemMatcher": [],
|
||||||
|
"group": {
|
||||||
|
"kind": "build",
|
||||||
|
"isDefault": true
|
||||||
|
},
|
||||||
|
"presentation": {
|
||||||
|
"reveal": "always"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
3
init.sh
3
init.sh
@@ -3,5 +3,8 @@
|
|||||||
#source node binaries
|
#source node binaries
|
||||||
. nodetopath.sh
|
. nodetopath.sh
|
||||||
npm install -g typescript
|
npm install -g typescript
|
||||||
|
npm install -g ts-node
|
||||||
|
npm install --save-dev @types/node
|
||||||
|
npm install --save-dev typescript parcel-bundler
|
||||||
npm install chart.js@4.4.1
|
npm install chart.js@4.4.1
|
||||||
npm install chartjs-plugin-annotation@3.1.0
|
npm install chartjs-plugin-annotation@3.1.0
|
||||||
10834
package-lock.json
generated
Normal file
10834
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
14
package.json
Normal file
14
package.json
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"chart.js": "^4.4.1",
|
||||||
|
"chartjs-plugin-annotation": "^3.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^22.15.30",
|
||||||
|
"parcel-bundler": "^1.12.5",
|
||||||
|
"typescript": "^5.8.3"
|
||||||
|
},
|
||||||
|
"scripts": {
|
||||||
|
"build": "parcel build src/roast.html --public-url=./ --out-dir dist"
|
||||||
|
}
|
||||||
|
}
|
||||||
19
postcss.config.js
Normal file
19
postcss.config.js
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
module.exports = {
|
||||||
|
plugins: [
|
||||||
|
// Other PostCSS plugins can be listed here if you use them.
|
||||||
|
],
|
||||||
|
minify: true, // Ensure this is set to true so Parcel uses the provided options
|
||||||
|
terserOptions: {
|
||||||
|
mangle: {
|
||||||
|
// Specify functions that should not be mangled by their names
|
||||||
|
reserved: [
|
||||||
|
"setPlan",
|
||||||
|
"logEvent",
|
||||||
|
"exportCSV",
|
||||||
|
"resetSystem",
|
||||||
|
"navigateTemp",
|
||||||
|
"logTemp"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
124
src/roast.css
Normal file
124
src/roast.css
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
body {
|
||||||
|
background-color: #e6ccff;
|
||||||
|
font-family: Arial, sans-serif;
|
||||||
|
color: #333;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
#timer {
|
||||||
|
font-size: 48px;
|
||||||
|
text-align: center;
|
||||||
|
padding: 20px;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 2px solid #666;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
#create-plan {
|
||||||
|
padding: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#create-plan input {
|
||||||
|
width: 80%;
|
||||||
|
padding: 10px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
#create-plan button {
|
||||||
|
margin-top: 10px;
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 18px;
|
||||||
|
}
|
||||||
|
#controls {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
padding: 20px;
|
||||||
|
}
|
||||||
|
.button-group {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin: 10px;
|
||||||
|
}
|
||||||
|
.button-group button:not(.nav-btn) {
|
||||||
|
font-size: 20px;
|
||||||
|
border: 2px solid #666;
|
||||||
|
background-color: #fff;
|
||||||
|
color: #333;
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.button-group .nav-btn {
|
||||||
|
padding: 15px 25px;
|
||||||
|
font-size: 20px;
|
||||||
|
border: 2px solid #666;
|
||||||
|
background-color: #E8E;
|
||||||
|
color: #333;
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.button-group button:active {
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
#event-buttons {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
gap: 10px;
|
||||||
|
margin: 20px;
|
||||||
|
}
|
||||||
|
#event-buttons button {
|
||||||
|
padding: 15px 25px;
|
||||||
|
font-size: 20px;
|
||||||
|
border: 2px solid #666;
|
||||||
|
background-color: #afa;
|
||||||
|
color: #333;
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#event-buttons button:active {
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
#log-table {
|
||||||
|
width: 100%;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
#log-table table {
|
||||||
|
table-layout: fixed;
|
||||||
|
width: 90%;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
#log-table th, #log-table td {
|
||||||
|
border: 1px solid #666;
|
||||||
|
padding: 10px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#log-table th {
|
||||||
|
background-color: #f0e6ff;
|
||||||
|
}
|
||||||
|
#export-csv {
|
||||||
|
margin: 20px;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
#export-csv button {
|
||||||
|
padding: 10px 20px;
|
||||||
|
font-size: 18px;
|
||||||
|
border: 2px solid #666;
|
||||||
|
background-color: #fff;
|
||||||
|
color: #333;
|
||||||
|
border-radius: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
#export-csv button:active {
|
||||||
|
background-color: #ddd;
|
||||||
|
}
|
||||||
|
.hidden {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
#temp-buttons {
|
||||||
|
margin: 8px;
|
||||||
|
}
|
||||||
|
#temp-buttons button {
|
||||||
|
text-align: center;
|
||||||
|
width: 3.5em;
|
||||||
|
}
|
||||||
44
src/roast.html
Normal file
44
src/roast.html
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8">
|
||||||
|
<title>Stovetop Coffee Roast Logger</title>
|
||||||
|
<link rel="stylesheet" href="./roast.css">
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="timer">0:00</div>
|
||||||
|
<div id="create-plan">
|
||||||
|
<input type="text" id="plan-input" placeholder="Enter temperatures (comma separated)">
|
||||||
|
<button onclick="setPlan()">Set Plan</button>
|
||||||
|
</div>
|
||||||
|
<div id="controls" class="hidden">
|
||||||
|
<div id="temp-buttons" class="button-group"></div>
|
||||||
|
<div id="event-buttons" class="button-group">
|
||||||
|
<button onclick="logEvent('Charge')">Charge</button>
|
||||||
|
<button onclick="logEvent('Yellow')">Yellow</button>
|
||||||
|
<button onclick="logEvent('First Crack')">First Crack</button>
|
||||||
|
<button onclick="logEvent('Second Crack')">Second Crack</button>
|
||||||
|
<button onclick="logEvent('Drop')">Drop</button>
|
||||||
|
</div>
|
||||||
|
<div id="export-csv">
|
||||||
|
<button onclick="exportCSV()">Export CSV</button>
|
||||||
|
<button onclick="resetSystem()">Reset</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="log-table">
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Time</th>
|
||||||
|
<th>Event</th>
|
||||||
|
<th>Temperature</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody id="log-body">
|
||||||
|
<!-- Log entries will be inserted here -->
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<script src="./roast.ts"></script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
23
src/roast.ts
23
src/roast.ts
@@ -5,6 +5,7 @@ let targets: number[] = [];
|
|||||||
let currentTargetIndex = 0;
|
let currentTargetIndex = 0;
|
||||||
let interval: NodeJS.Timeout | null = null;
|
let interval: NodeJS.Timeout | null = null;
|
||||||
|
|
||||||
|
|
||||||
function startTimer(): void {
|
function startTimer(): void {
|
||||||
if (isRunning) {
|
if (isRunning) {
|
||||||
alert("Timer is already running. Click again to reset.");
|
alert("Timer is already running. Click again to reset.");
|
||||||
@@ -36,20 +37,20 @@ function logEvent(eventName: string): void {
|
|||||||
isRunning = false;
|
isRunning = false;
|
||||||
}
|
}
|
||||||
startTimer();
|
startTimer();
|
||||||
log.push({ time: formatTime(timer), event: eventName, temp: null });
|
log.push({ time: formatTime(timer), event: eventName });
|
||||||
updateLog();
|
updateLog();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (eventName === "Drop") {
|
if (eventName === "Drop") {
|
||||||
stopTimer();
|
stopTimer();
|
||||||
log.push({ time: formatTime(timer), event: eventName, temp: null });
|
log.push({ time: formatTime(timer), event: eventName });
|
||||||
updateLog();
|
updateLog();
|
||||||
document.getElementById("create-plan")!.classList.add("hidden");
|
document.getElementById("create-plan")!.classList.remove("hidden");
|
||||||
const tempButtons = document.getElementById("temp-buttons")!;
|
const tempButtons = document.getElementById("temp-buttons")!;
|
||||||
tempButtons.innerHTML = "";
|
tempButtons.innerHTML = "";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
log.push({ time: formatTime(timer), event: eventName, temp: null });
|
log.push({ time: formatTime(timer), event: eventName });
|
||||||
updateLog();
|
updateLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -57,7 +58,7 @@ function resetSystem(): void {
|
|||||||
stopTimer();
|
stopTimer();
|
||||||
log = [];
|
log = [];
|
||||||
updateLog();
|
updateLog();
|
||||||
document.getElementById("create-plan")!.classList.add("hidden");
|
document.getElementById("create-plan")!.classList.remove("hidden");
|
||||||
const tempButtons = document.getElementById("temp-buttons")!;
|
const tempButtons = document.getElementById("temp-buttons")!;
|
||||||
tempButtons.innerHTML = "";
|
tempButtons.innerHTML = "";
|
||||||
}
|
}
|
||||||
@@ -137,3 +138,15 @@ function exportCSV(): void {
|
|||||||
link.click();
|
link.click();
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Expose functions to the global scope
|
||||||
|
if (typeof window !== 'undefined') {
|
||||||
|
window.startTimer = startTimer;
|
||||||
|
window.stopTimer = stopTimer;
|
||||||
|
window.logEvent = logEvent;
|
||||||
|
window.resetSystem = resetSystem;
|
||||||
|
window.setPlan = setPlan;
|
||||||
|
window.navigateTemp = navigateTemp;
|
||||||
|
window.logTemp = logTemp;
|
||||||
|
window.exportCSV = exportCSV;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user