feat: promote seatmap and organization updates
This commit is contained in:
@@ -982,7 +982,7 @@ def parse_fixed_office_template(office_key: str = FIXED_OFFICE_SOURCE_KEY) -> di
|
||||
raise HTTPException(status_code=500, detail=f"Fixed office viewer data not found: {office_key}")
|
||||
|
||||
html = re.sub(
|
||||
r'<script\s+src="\./[^"]+payload[^"]*\.js"></script>',
|
||||
r'<script\s+src="\./[^"]+payload[^"]*\.js(?:\?[^"]*)?"></script>',
|
||||
f"<script>{payload_js}</script>",
|
||||
html,
|
||||
count=1,
|
||||
@@ -1582,6 +1582,10 @@ def fetch_seat_layout(seat_map_id: int, as_of: datetime | None = None) -> dict[s
|
||||
(as_of, as_of, seat_map_id, as_of, as_of),
|
||||
)
|
||||
placements = cur.fetchall()
|
||||
cur.execute("SELECT name FROM member_retirements")
|
||||
retired_names = {str(row["name"] or "").strip() for row in cur.fetchall() if str(row["name"] or "").strip()}
|
||||
for member in members:
|
||||
member["is_retired"] = str(member.get("name") or "").strip() in retired_names
|
||||
viewer_data: dict[str, object] | None = None
|
||||
office_key = str(seat_map.get("source_url") or FIXED_OFFICE_SOURCE_KEY)
|
||||
fixed_office = FIXED_OFFICE_CONFIGS.get(office_key)
|
||||
@@ -1807,6 +1811,8 @@ def build_center_chair_viewer_html(layout: dict[str, object]) -> str:
|
||||
<script>
|
||||
const seatAssignments = new Map();
|
||||
let selectedChairKey = null;
|
||||
let focusedChairKey = null;
|
||||
let focusedChairPulseUntil = 0;
|
||||
let viewerMode = "default";
|
||||
const popup = document.createElement("div");
|
||||
popup.className = "seat-popup";
|
||||
@@ -1854,6 +1860,9 @@ def build_center_chair_viewer_html(layout: dict[str, object]) -> str:
|
||||
function focusChair(chairKey, padding = 2200) {
|
||||
const chair = chairGeometry.find((item) => String(item.key) === String(chairKey));
|
||||
if (!chair) return;
|
||||
selectedChairKey = String(chairKey);
|
||||
focusedChairKey = String(chairKey);
|
||||
focusedChairPulseUntil = Date.now() + 2600;
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const pad = 24;
|
||||
const minX = chair.minX - padding;
|
||||
@@ -1919,8 +1928,31 @@ def build_center_chair_viewer_html(layout: dict[str, object]) -> str:
|
||||
const originalDraw = draw;
|
||||
draw = function drawWithAssignments() {
|
||||
originalDraw();
|
||||
if (!seatAssignments.size) return;
|
||||
const rect = canvas.getBoundingClientRect();
|
||||
const now = Date.now();
|
||||
const focusedChair = focusedChairKey
|
||||
? chairGeometry.find((item) => String(item.key) === String(focusedChairKey))
|
||||
: null;
|
||||
if (focusedChair && now <= focusedChairPulseUntil) {
|
||||
const pulse = (Math.sin(now / 180) + 1) / 2;
|
||||
const center = worldToScreen((focusedChair.minX + focusedChair.maxX) / 2, (focusedChair.minY + focusedChair.maxY) / 2);
|
||||
const width = Math.max(34, (focusedChair.maxX - focusedChair.minX) * camera.scale + 20 + pulse * 18);
|
||||
const height = Math.max(34, (focusedChair.maxY - focusedChair.minY) * camera.scale + 20 + pulse * 18);
|
||||
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
|
||||
ctx.save();
|
||||
ctx.strokeStyle = `rgba(245, 158, 11, ${0.38 + pulse * 0.32})`;
|
||||
ctx.lineWidth = 3 + pulse * 2;
|
||||
ctx.shadowColor = "rgba(245, 158, 11, 0.35)";
|
||||
ctx.shadowBlur = 16 + pulse * 10;
|
||||
ctx.beginPath();
|
||||
ctx.roundRect(center.x - width / 2, center.y - height / 2, width, height, 16);
|
||||
ctx.stroke();
|
||||
ctx.restore();
|
||||
if (typeof requestDraw === "function") requestDraw();
|
||||
} else if (focusedChair && now > focusedChairPulseUntil) {
|
||||
focusedChairPulseUntil = 0;
|
||||
}
|
||||
if (!seatAssignments.size) return;
|
||||
ctx.setTransform(pixelRatio, 0, 0, pixelRatio, 0, 0);
|
||||
ctx.textBaseline = "middle";
|
||||
for (const chair of chairGeometry) {
|
||||
|
||||
Reference in New Issue
Block a user