frontend tweaks

This commit is contained in:
Pagwin 2026-06-17 16:23:09 -04:00
parent 9866af07d3
commit 751a0e2525
3 changed files with 119 additions and 14 deletions

23
Dockerfile Normal file
View file

@ -0,0 +1,23 @@
FROM python:3.13-slim
WORKDIR /app
# Install uv
RUN pip install --no-cache-dir uv
# Copy project files
COPY pyproject.toml uv.lock ./
# Install dependencies with uv
RUN uv sync --no-editable
# Copy source code
COPY solve.py web_solve.py ./
COPY templates/ templates/
# Set environment variables
ENV FLASK_APP=web_solve.py
ENV PYTHONUNBUFFERED=1
# Run Flask app
CMD ["uv", "run", "python", "web_solve.py"]

14
docker-compose.yml Normal file
View file

@ -0,0 +1,14 @@
version: '3.8'
services:
web:
build: .
ports:
- "5555:5000"
environment:
- FLASK_ENV=development
- FLASK_DEBUG=1
volumes:
- .:/app
command: uv run python web_solve.py
restart: unless-stopped

View file

@ -129,10 +129,21 @@
padding: .55rem .7rem;
display: grid;
gap: .45rem .8rem;
align-items: end;
align-items: start;
grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
}
/* Top-align cells but keep every field's input on a common baseline by
reserving a uniform (two-line) label height — so a wrapping label no
longer drops its input below the others, and a stacked cell (Type +
"Can renovate") can hang its extra control underneath while its primary
input still lines up with the rest. */
.card .field:not(.check):not(.vat-row)>span {
min-height: 2.8em;
display: flex;
align-items: flex-end;
}
.card input,
.card select,
.card textarea {
@ -149,17 +160,70 @@
gap: .35rem;
}
/* Stack two controls vertically inside a single grid cell (e.g. the city
Type field with its "Can renovate" checkbox tucked underneath). Top-align
so the Type input stays on the same row as the card's other inputs while
the checkbox hangs below. */
.card .stack {
display: flex;
flex-direction: column;
gap: .45rem;
min-width: 0;
align-self: start;
}
/* Vat amounts: stacked rows, each with its label to the left of the input. */
.card .vat-group {
display: flex;
flex-direction: column;
gap: .3rem;
min-width: 0;
}
.card .vat-head {
font-size: .8rem;
opacity: .8;
}
.card .vat-row {
flex-direction: row;
align-items: center;
gap: .4rem;
}
.card .vat-row>span {
flex: 0 0 4rem;
}
.card .vat-row input {
width: auto;
flex: 1;
min-width: 0;
}
.card-actions {
align-self: start;
justify-self: end;
}
/* Keep the "Log" checkbox and its JS-function field together in one cell
and reserve the space up front, so enabling the field only fills the
already-allotted room instead of reflowing the whole card. */
.card .log-group {
grid-column: span 2;
display: flex;
align-items: start;
gap: .5rem;
min-width: 0;
}
.log-cell {
display: none;
}
.card.log-on .log-cell {
display: flex;
flex: 1;
}
/* Output tables: a CSS grid kept inside a scroll container so it never
@ -466,15 +530,18 @@
}
}
// Vat amounts only matter for Foundries; hide them otherwise and keep
// them as the card's last fields (before the actions).
const vatFields = [
field("Vat steel", vs),
field("Vat brass", vb),
field("Vat electrum", ve),
];
// them as the card's last field (before the actions). They stack in a
// single cell, each input labeled on its left.
const vatRow = (label, input) =>
el("label", {class: "field vat-row"}, [el("span", {}, label), input]);
const vatGroup = el("div", {class: "vat-group"}, [
el("span", {class: "vat-head"}, "Vat amounts"),
vatRow("steel", vs),
vatRow("brass", vb),
vatRow("electrum", ve),
]);
function renderVats() {
const show = type.value === "foundry";
for (const f of vatFields) f.style.display = show ? "" : "none";
vatGroup.style.display = type.value === "foundry" ? "" : "none";
}
type.onchange = () => {renderUpgrades(); renderVats();};
renderUpgrades();
@ -499,14 +566,16 @@
};
card.append(
field("Name", name),
field("Type", type),
el("div", {class: "stack"}, [
field("Type", type),
checkField("Can renovate", reno),
]),
field("Renown", renown),
field("Upgrades (already installed)", upWrap),
checkField("Can renovate", reno),
field("Adjacent cities (csv of names)", adjacent),
field("Forced actions (turn:action, csv)", forced),
field("Avail turns (csv, blank=all)", avail),
...vatFields,
vatGroup,
el("div", {class: "card-actions"}, removeBtn(card)));
document.getElementById("cities").append(card);
}
@ -584,8 +653,7 @@
resF,
field("Scalar", scalar),
turnF,
checkField("Log?", isLog),
exprF,
el("div", {class: "log-group"}, [field("Log", isLog), exprF]),
el("div", {class: "card-actions"}, removeBtn(card)));
document.getElementById("terms").append(card);
toggle();