Files
harmony/examples/compose_java_react/app/frontend/src/App.jsx
Jean-Gabriel Gill-Couture 9605892aba feat(examples): deploy a java+react app by importing its docker-compose
Demonstrates the compose-as-source-of-truth path (ADR-026): import an
existing docker-compose.yml into typed Scores, then build/publish/deploy
with the fleet pattern (no ApplicationScore, no ArgoCD).

- compose.rs: docker-compose-types → typed ComposeApp; loud on bind
  mounts / unparseable ports, warns on depends_on/command/restart.
- chart.rs: per-service Deployment+Service (unique filenames), RWX PVC
  per mounted named volume, RollingUpdate/Recreate strategy. Deploy-only
  knobs live here, never in compose or Harmony.toml.
- score.rs: ComposeAppScore = helm upgrade --install + public Ingress.
- publish.rs: docker build/push each built service + helm package/push.
- app/: minimal real Java(SQLite)+React(nginx) compose stack.
- 16 unit tests over import + chart generation.
2026-06-18 17:00:19 -04:00

49 lines
1.1 KiB
JavaScript

import { useEffect, useState } from "react";
export default function App() {
const [entries, setEntries] = useState([]);
const [note, setNote] = useState("");
const load = () =>
fetch("/api/entries")
.then((r) => r.json())
.then(setEntries);
useEffect(() => {
load();
}, []);
const submit = async (e) => {
e.preventDefault();
if (!note.trim()) return;
await fetch("/api/entries", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ note }),
});
setNote("");
load();
};
return (
<main style={{ fontFamily: "sans-serif", maxWidth: 600, margin: "2rem auto" }}>
<h1>Timesheet</h1>
<form onSubmit={submit}>
<input
value={note}
onChange={(e) => setNote(e.target.value)}
placeholder="What did you work on?"
/>
<button type="submit">Add</button>
</form>
<ul>
{entries.map((e) => (
<li key={e.id}>
{e.note} <small>({e.created_at})</small>
</li>
))}
</ul>
</main>
);
}