Spaces:
Runtime error
Runtime error
space: fix blank override popup and disable image/model preview modals
Browse files- app.py +7 -4
- core/theme.py +15 -10
- record-beat.sh +41 -3
app.py
CHANGED
|
@@ -941,7 +941,7 @@ def build() -> gr.Blocks:
|
|
| 941 |
|
| 942 |
# OVERRIDE ENVIRONMENT popup (hidden by default; toggled via JS)
|
| 943 |
gr.HTML("<div class='ce-popup-backdrop' data-popup-backdrop='override'></div>")
|
| 944 |
-
with gr.Group(elem_classes=["ce-popup"
|
| 945 |
gr.HTML("<div class='ce-popup-title'>OVERRIDE ENVIRONMENT"
|
| 946 |
"<span class='ce-popup-close'>✕</span></div>")
|
| 947 |
with gr.Row():
|
|
@@ -958,7 +958,8 @@ def build() -> gr.Blocks:
|
|
| 958 |
# LEFT: 3D viewer with intro + job-log copy below it (moved from top)
|
| 959 |
with gr.Column(scale=3, elem_classes=["ce-part-viewer-col"]):
|
| 960 |
part_placeholder = gr.HTML(_viewer_placeholder())
|
| 961 |
-
model3d = gr.Model3D(value=None, label="", height=360, visible=False
|
|
|
|
| 962 |
# intro + job log moved DOWN into the part area
|
| 963 |
gr.HTML(tab_intro("Load the part, set the material and the room, then "
|
| 964 |
"<b>SLICE</b> to read the engineer's pre-flight check. "
|
|
@@ -995,7 +996,9 @@ def build() -> gr.Blocks:
|
|
| 995 |
gr.HTML(rule("SLICE · CROSS-SECTION + MOTION PREVIEW"))
|
| 996 |
with gr.Row(equal_height=False, elem_classes=["ce-part-row", "ce-slice-viz"]):
|
| 997 |
with gr.Column(scale=1, elem_classes=["ce-slice-col"]):
|
| 998 |
-
vp_layer = gr.Image(label="", height=360, show_label=False
|
|
|
|
|
|
|
| 999 |
with gr.Column(scale=1, elem_classes=["ce-slice-col", "ce-vp"]):
|
| 1000 |
vprint = gr.HTML()
|
| 1001 |
with gr.Column(elem_classes=["ce-hslider"]):
|
|
@@ -1077,7 +1080,7 @@ def build() -> gr.Blocks:
|
|
| 1077 |
|
| 1078 |
# OVERRIDE PLAN popup — same component as OVERRIDE ENVIRONMENT on the BUILD tab
|
| 1079 |
gr.HTML("<div class='ce-popup-backdrop' data-popup-backdrop='plan'></div>")
|
| 1080 |
-
with gr.Group(elem_classes=["ce-popup"
|
| 1081 |
gr.HTML("<div class='ce-popup-title'>OVERRIDE THE ENGINEER'S PLAN"
|
| 1082 |
"<span class='ce-popup-close'>✕</span></div>")
|
| 1083 |
gr.HTML("<div class='ce-sub' style='border-left:3px solid var(--ao-red);"
|
|
|
|
| 941 |
|
| 942 |
# OVERRIDE ENVIRONMENT popup (hidden by default; toggled via JS)
|
| 943 |
gr.HTML("<div class='ce-popup-backdrop' data-popup-backdrop='override'></div>")
|
| 944 |
+
with gr.Group(elem_classes=["ce-popup", "ce-popup-override"]):
|
| 945 |
gr.HTML("<div class='ce-popup-title'>OVERRIDE ENVIRONMENT"
|
| 946 |
"<span class='ce-popup-close'>✕</span></div>")
|
| 947 |
with gr.Row():
|
|
|
|
| 958 |
# LEFT: 3D viewer with intro + job-log copy below it (moved from top)
|
| 959 |
with gr.Column(scale=3, elem_classes=["ce-part-viewer-col"]):
|
| 960 |
part_placeholder = gr.HTML(_viewer_placeholder())
|
| 961 |
+
model3d = gr.Model3D(value=None, label="", height=360, visible=False,
|
| 962 |
+
interactive=False)
|
| 963 |
# intro + job log moved DOWN into the part area
|
| 964 |
gr.HTML(tab_intro("Load the part, set the material and the room, then "
|
| 965 |
"<b>SLICE</b> to read the engineer's pre-flight check. "
|
|
|
|
| 996 |
gr.HTML(rule("SLICE · CROSS-SECTION + MOTION PREVIEW"))
|
| 997 |
with gr.Row(equal_height=False, elem_classes=["ce-part-row", "ce-slice-viz"]):
|
| 998 |
with gr.Column(scale=1, elem_classes=["ce-slice-col"]):
|
| 999 |
+
vp_layer = gr.Image(label="", height=360, show_label=False,
|
| 1000 |
+
interactive=False, show_download_button=False,
|
| 1001 |
+
show_share_button=False)
|
| 1002 |
with gr.Column(scale=1, elem_classes=["ce-slice-col", "ce-vp"]):
|
| 1003 |
vprint = gr.HTML()
|
| 1004 |
with gr.Column(elem_classes=["ce-hslider"]):
|
|
|
|
| 1080 |
|
| 1081 |
# OVERRIDE PLAN popup — same component as OVERRIDE ENVIRONMENT on the BUILD tab
|
| 1082 |
gr.HTML("<div class='ce-popup-backdrop' data-popup-backdrop='plan'></div>")
|
| 1083 |
+
with gr.Group(elem_classes=["ce-popup", "ce-popup-plan"]):
|
| 1084 |
gr.HTML("<div class='ce-popup-title'>OVERRIDE THE ENGINEER'S PLAN"
|
| 1085 |
"<span class='ce-popup-close'>✕</span></div>")
|
| 1086 |
gr.HTML("<div class='ce-sub' style='border-left:3px solid var(--ao-red);"
|
core/theme.py
CHANGED
|
@@ -348,15 +348,16 @@ textarea:focus, input:focus {{ border-color:var(--ao-orange) !important; box-sha
|
|
| 348 |
/* ── OVERRIDE ENVIRONMENT POPUP ──
|
| 349 |
Hidden by default; toggled via JS clicking the OVERRIDE button.
|
| 350 |
Modal-style overlay with the override fields inside. */
|
| 351 |
-
.ce-popup {{ display:none; position:fixed; top:50%; left:50%;
|
| 352 |
transform:translate(-50%,-50%); z-index:1000;
|
| 353 |
background:var(--ao-surface-hi); border:2px solid var(--ao-orange);
|
| 354 |
padding:18px 22px; min-width:420px; max-width:520px;
|
| 355 |
box-shadow:0 20px 60px rgba(0,0,0,0.7); }}
|
| 356 |
-
.ce-popup.open {{ display:block; }}
|
| 357 |
-
.ce-popup-
|
|
|
|
| 358 |
background:rgba(0,0,0,0.6); }}
|
| 359 |
-
.ce-popup-backdrop.open {{ display:block; }}
|
| 360 |
.ce-popup-title {{ color:var(--ao-orange); letter-spacing:3px;
|
| 361 |
text-transform:uppercase; font-size:13px; font-weight:800;
|
| 362 |
margin-bottom:10px; display:flex; align-items:center; justify-content:space-between; }}
|
|
@@ -702,8 +703,8 @@ CLOCK_JS = """
|
|
| 702 |
};
|
| 703 |
tick(); setInterval(tick, 1000);
|
| 704 |
|
| 705 |
-
// Popup wiring: any [data-popup-trigger="X"] toggles
|
| 706 |
-
//
|
| 707 |
const wirePopups = () => {
|
| 708 |
document.querySelectorAll('[data-popup-trigger]').forEach(btn => {
|
| 709 |
if (btn.dataset._wired) return;
|
|
@@ -711,11 +712,15 @@ CLOCK_JS = """
|
|
| 711 |
btn.addEventListener('click', (e) => {
|
| 712 |
e.preventDefault(); e.stopPropagation();
|
| 713 |
const id = btn.dataset.popupTrigger;
|
| 714 |
-
const
|
| 715 |
-
|| document.querySelector('#ce-popup-' + id);
|
| 716 |
const bd = document.querySelector('[data-popup-backdrop="' + id + '"]');
|
| 717 |
-
|
| 718 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 719 |
});
|
| 720 |
});
|
| 721 |
document.querySelectorAll('.ce-popup-close, [data-popup-backdrop]').forEach(el => {
|
|
|
|
| 348 |
/* ── OVERRIDE ENVIRONMENT POPUP ──
|
| 349 |
Hidden by default; toggled via JS clicking the OVERRIDE button.
|
| 350 |
Modal-style overlay with the override fields inside. */
|
| 351 |
+
.ce-popup {{ display:none !important; position:fixed; top:50%; left:50%;
|
| 352 |
transform:translate(-50%,-50%); z-index:1000;
|
| 353 |
background:var(--ao-surface-hi); border:2px solid var(--ao-orange);
|
| 354 |
padding:18px 22px; min-width:420px; max-width:520px;
|
| 355 |
box-shadow:0 20px 60px rgba(0,0,0,0.7); }}
|
| 356 |
+
.ce-popup.open {{ display:block !important; }}
|
| 357 |
+
.ce-popup.open .ce-popup {{ display:block !important; }}
|
| 358 |
+
.ce-popup-backdrop {{ display:none !important; position:fixed; inset:0; z-index:999;
|
| 359 |
background:rgba(0,0,0,0.6); }}
|
| 360 |
+
.ce-popup-backdrop.open {{ display:block !important; }}
|
| 361 |
.ce-popup-title {{ color:var(--ao-orange); letter-spacing:3px;
|
| 362 |
text-transform:uppercase; font-size:13px; font-weight:800;
|
| 363 |
margin-bottom:10px; display:flex; align-items:center; justify-content:space-between; }}
|
|
|
|
| 703 |
};
|
| 704 |
tick(); setInterval(tick, 1000);
|
| 705 |
|
| 706 |
+
// Popup wiring: any [data-popup-trigger="X"] toggles all .ce-popup-X (and backdrop).
|
| 707 |
+
// Click outside or on .ce-popup-close to dismiss. Re-runs in case popups are added later.
|
| 708 |
const wirePopups = () => {
|
| 709 |
document.querySelectorAll('[data-popup-trigger]').forEach(btn => {
|
| 710 |
if (btn.dataset._wired) return;
|
|
|
|
| 712 |
btn.addEventListener('click', (e) => {
|
| 713 |
e.preventDefault(); e.stopPropagation();
|
| 714 |
const id = btn.dataset.popupTrigger;
|
| 715 |
+
const pops = document.querySelectorAll('.ce-popup-' + id);
|
|
|
|
| 716 |
const bd = document.querySelector('[data-popup-backdrop="' + id + '"]');
|
| 717 |
+
const isOpening = pops.length && !pops[0].classList.contains('open');
|
| 718 |
+
document.querySelectorAll('.ce-popup.open, .ce-popup-backdrop.open')
|
| 719 |
+
.forEach(x => x.classList.remove('open'));
|
| 720 |
+
if (isOpening) {
|
| 721 |
+
pops.forEach(p => p.classList.add('open'));
|
| 722 |
+
if (bd) bd.classList.add('open');
|
| 723 |
+
}
|
| 724 |
});
|
| 725 |
});
|
| 726 |
document.querySelectorAll('.ce-popup-close, [data-popup-backdrop]').forEach(el => {
|
record-beat.sh
CHANGED
|
@@ -60,10 +60,48 @@ case "$BEAT" in
|
|
| 60 |
review) BEAT_ARG="loop" ;;
|
| 61 |
esac
|
| 62 |
|
| 63 |
-
|
|
|
|
|
|
|
|
|
|
| 64 |
echo "Starting Cap recording..."
|
| 65 |
-
|
| 66 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 67 |
echo " ✓ Cap recording started (${REC_ID})"
|
| 68 |
|
| 69 |
echo "Driving beat..."
|
|
|
|
| 60 |
review) BEAT_ARG="loop" ;;
|
| 61 |
esac
|
| 62 |
|
| 63 |
+
SCREEN_ID=$(cap targets screens --json | python3 -c 'import sys,json; d=json.load(sys.stdin); print([s for s in d if s.get("primary")][0]["id"])')
|
| 64 |
+
echo "Recording beat: ${BEAT} (driver=${BEAT_ARG}) (screen=${SCREEN_ID})"
|
| 65 |
+
|
| 66 |
+
CAP_START_TMP="/tmp/cap-beat-start-$(date +%s).txt"
|
| 67 |
echo "Starting Cap recording..."
|
| 68 |
+
rm -f "$CAP_START_TMP"
|
| 69 |
+
nohup /mnt/c/Users/kyleb/AppData/Local/Cap/cap-cli.exe record start --screen "$SCREEN_ID" --fps 60 --detach --json > "$CAP_START_TMP" 2>&1 &
|
| 70 |
+
CAP_PID=$!
|
| 71 |
+
sleep 3
|
| 72 |
+
|
| 73 |
+
# Parse the JSON Cap emitted
|
| 74 |
+
REC_ID=""
|
| 75 |
+
if [[ -s "$CAP_START_TMP" ]]; then
|
| 76 |
+
REC_ID=$(python3 -c '
|
| 77 |
+
import sys, json, re
|
| 78 |
+
with open(sys.argv[1]) as f:
|
| 79 |
+
data = f.read()
|
| 80 |
+
# Single-line JSON object
|
| 81 |
+
for line in data.splitlines():
|
| 82 |
+
line = line.strip()
|
| 83 |
+
if line.startswith("{") and line.endswith("}"):
|
| 84 |
+
try:
|
| 85 |
+
d = json.loads(line)
|
| 86 |
+
if "recordingId" in d:
|
| 87 |
+
print(d["recordingId"])
|
| 88 |
+
sys.exit(0)
|
| 89 |
+
except:
|
| 90 |
+
pass
|
| 91 |
+
# Pretty-printed JSON
|
| 92 |
+
m = re.search(r"\"recordingId\"\s*:\s*\"([^\"]+)\"", data)
|
| 93 |
+
if m:
|
| 94 |
+
print(m.group(1))
|
| 95 |
+
' "$CAP_START_TMP")
|
| 96 |
+
fi
|
| 97 |
+
|
| 98 |
+
if [[ -z "$REC_ID" ]]; then
|
| 99 |
+
echo " ✗ could not parse Cap recording ID; output was:"
|
| 100 |
+
cat "$CAP_START_TMP" || true
|
| 101 |
+
wait "$CAP_PID" 2>/dev/null || true
|
| 102 |
+
exit 1
|
| 103 |
+
fi
|
| 104 |
+
|
| 105 |
echo " ✓ Cap recording started (${REC_ID})"
|
| 106 |
|
| 107 |
echo "Driving beat..."
|