Codex commited on
Commit ·
9d12b14
1
Parent(s): d3b98cb
Fix admin alignment and refine UI
Browse files- static/admin-v020.js +32 -8
- static/v020.css +88 -2
static/admin-v020.js
CHANGED
|
@@ -221,16 +221,40 @@
|
|
| 221 |
const startMinutes = segments[0].startMinutes;
|
| 222 |
const endMinutes = segments[segments.length - 1].endMinutes;
|
| 223 |
const totalMinutes = Math.max(endMinutes - startMinutes, 1);
|
| 224 |
-
const
|
|
|
|
|
|
|
| 225 |
|
| 226 |
scheduleEditorAxis.innerHTML = "";
|
| 227 |
scheduleEditorTrack.innerHTML = "";
|
| 228 |
scheduleEditorAxis.style.height = `${height}px`;
|
| 229 |
scheduleEditorTrack.style.height = `${height}px`;
|
| 230 |
|
| 231 |
-
|
|
|
|
|
|
|
| 232 |
const top = Math.round((minute - startMinutes) * getEditorPixelsPerMinute());
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 233 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 234 |
const tick = document.createElement("div");
|
| 235 |
tick.className = "schedule-editor-tick";
|
| 236 |
if (index === 0) {
|
|
@@ -241,18 +265,16 @@
|
|
| 241 |
tick.style.top = `${top}px`;
|
| 242 |
tick.textContent = minutesToTime(minute);
|
| 243 |
scheduleEditorAxis.appendChild(tick);
|
| 244 |
-
|
| 245 |
-
const line = document.createElement("div");
|
| 246 |
-
line.className = "schedule-editor-line";
|
| 247 |
-
line.style.top = `${top}px`;
|
| 248 |
-
scheduleEditorTrack.appendChild(line);
|
| 249 |
});
|
| 250 |
|
| 251 |
segments.forEach((segment, index) => {
|
| 252 |
const block = document.createElement("article");
|
|
|
|
| 253 |
block.className = `schedule-editor-segment ${segment.kind}`;
|
| 254 |
block.style.top = `${Math.round((segment.startMinutes - startMinutes) * getEditorPixelsPerMinute())}px`;
|
| 255 |
-
block.style.height = `${
|
|
|
|
|
|
|
| 256 |
block.innerHTML = `
|
| 257 |
<div class="schedule-editor-segment-copy">
|
| 258 |
<strong>${segment.label}</strong>
|
|
@@ -265,6 +287,8 @@
|
|
| 265 |
scheduleEditorTrack.appendChild(block);
|
| 266 |
});
|
| 267 |
|
|
|
|
|
|
|
| 268 |
scheduleEditorTrack.appendChild(scheduleEditorDropzone);
|
| 269 |
if (scheduleSegmentCount) {
|
| 270 |
scheduleSegmentCount.textContent = `${segments.length} 段`;
|
|
|
|
| 221 |
const startMinutes = segments[0].startMinutes;
|
| 222 |
const endMinutes = segments[segments.length - 1].endMinutes;
|
| 223 |
const totalMinutes = Math.max(endMinutes - startMinutes, 1);
|
| 224 |
+
const contentHeight = Math.max(Math.round(totalMinutes * getEditorPixelsPerMinute()), 980);
|
| 225 |
+
const dropzoneTop = contentHeight + 20;
|
| 226 |
+
const height = dropzoneTop + 96;
|
| 227 |
|
| 228 |
scheduleEditorAxis.innerHTML = "";
|
| 229 |
scheduleEditorTrack.innerHTML = "";
|
| 230 |
scheduleEditorAxis.style.height = `${height}px`;
|
| 231 |
scheduleEditorTrack.style.height = `${height}px`;
|
| 232 |
|
| 233 |
+
const marks = buildScheduleAxisMarks();
|
| 234 |
+
const visibleMarks = [];
|
| 235 |
+
marks.forEach((minute, index) => {
|
| 236 |
const top = Math.round((minute - startMinutes) * getEditorPixelsPerMinute());
|
| 237 |
+
const line = document.createElement("div");
|
| 238 |
+
line.className = "schedule-editor-line";
|
| 239 |
+
line.style.top = `${top}px`;
|
| 240 |
+
scheduleEditorTrack.appendChild(line);
|
| 241 |
+
});
|
| 242 |
+
|
| 243 |
+
marks.forEach((minute, index) => {
|
| 244 |
+
const top = Math.round((minute - startMinutes) * getEditorPixelsPerMinute());
|
| 245 |
+
const isEdge = index === 0 || index === marks.length - 1;
|
| 246 |
+
const previous = visibleMarks[visibleMarks.length - 1];
|
| 247 |
+
|
| 248 |
+
if (isEdge && previous && top - previous.top < 30) {
|
| 249 |
+
visibleMarks.pop();
|
| 250 |
+
}
|
| 251 |
|
| 252 |
+
if (!previous || isEdge || top - (visibleMarks[visibleMarks.length - 1]?.top ?? -Infinity) >= 30) {
|
| 253 |
+
visibleMarks.push({ minute, top, index });
|
| 254 |
+
}
|
| 255 |
+
});
|
| 256 |
+
|
| 257 |
+
visibleMarks.forEach(({ minute, top, index }) => {
|
| 258 |
const tick = document.createElement("div");
|
| 259 |
tick.className = "schedule-editor-tick";
|
| 260 |
if (index === 0) {
|
|
|
|
| 265 |
tick.style.top = `${top}px`;
|
| 266 |
tick.textContent = minutesToTime(minute);
|
| 267 |
scheduleEditorAxis.appendChild(tick);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 268 |
});
|
| 269 |
|
| 270 |
segments.forEach((segment, index) => {
|
| 271 |
const block = document.createElement("article");
|
| 272 |
+
const height = Math.max(Math.round(segment.durationMinutes * getEditorPixelsPerMinute()), 36);
|
| 273 |
block.className = `schedule-editor-segment ${segment.kind}`;
|
| 274 |
block.style.top = `${Math.round((segment.startMinutes - startMinutes) * getEditorPixelsPerMinute())}px`;
|
| 275 |
+
block.style.height = `${height}px`;
|
| 276 |
+
block.classList.toggle("is-compact", height < 88);
|
| 277 |
+
block.classList.toggle("is-tight", height < 56);
|
| 278 |
block.innerHTML = `
|
| 279 |
<div class="schedule-editor-segment-copy">
|
| 280 |
<strong>${segment.label}</strong>
|
|
|
|
| 287 |
scheduleEditorTrack.appendChild(block);
|
| 288 |
});
|
| 289 |
|
| 290 |
+
scheduleEditorDropzone.style.top = `${dropzoneTop}px`;
|
| 291 |
+
scheduleEditorDropzone.style.bottom = "auto";
|
| 292 |
scheduleEditorTrack.appendChild(scheduleEditorDropzone);
|
| 293 |
if (scheduleSegmentCount) {
|
| 294 |
scheduleSegmentCount.textContent = `${segments.length} 段`;
|
static/v020.css
CHANGED
|
@@ -978,12 +978,29 @@ body.planner-interacting .page-planner {
|
|
| 978 |
width: min(1480px, calc(100% - 28px));
|
| 979 |
}
|
| 980 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 981 |
.admin-page-nav {
|
| 982 |
display: inline-flex;
|
| 983 |
gap: 8px;
|
| 984 |
padding: 6px;
|
| 985 |
border-radius: 999px;
|
| 986 |
background: rgba(255, 255, 255, 0.05);
|
|
|
|
| 987 |
}
|
| 988 |
|
| 989 |
.admin-page-tab {
|
|
@@ -1057,6 +1074,7 @@ body.planner-interacting .page-planner {
|
|
| 1057 |
|
| 1058 |
.course-row-head {
|
| 1059 |
align-items: start;
|
|
|
|
| 1060 |
}
|
| 1061 |
|
| 1062 |
.course-row-actions {
|
|
@@ -1072,11 +1090,26 @@ body.planner-interacting .page-planner {
|
|
| 1072 |
}
|
| 1073 |
|
| 1074 |
.course-card {
|
| 1075 |
-
padding:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1076 |
}
|
| 1077 |
|
| 1078 |
.course-card .admin-card-copy {
|
| 1079 |
-
margin:
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1080 |
}
|
| 1081 |
|
| 1082 |
.admin-schedule-grid {
|
|
@@ -1218,6 +1251,50 @@ body.planner-interacting .page-planner {
|
|
| 1218 |
right: 14px;
|
| 1219 |
}
|
| 1220 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1221 |
.schedule-editor-delete {
|
| 1222 |
position: absolute;
|
| 1223 |
right: 14px;
|
|
@@ -1313,6 +1390,15 @@ body.planner-interacting .page-planner {
|
|
| 1313 |
flex-wrap: wrap;
|
| 1314 |
}
|
| 1315 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1316 |
.page-viewport,
|
| 1317 |
.page-track,
|
| 1318 |
.page-slide,
|
|
|
|
| 978 |
width: min(1480px, calc(100% - 28px));
|
| 979 |
}
|
| 980 |
|
| 981 |
+
.admin-layout-v2 .admin-hero {
|
| 982 |
+
display: grid;
|
| 983 |
+
grid-template-columns: minmax(0, 1fr) auto;
|
| 984 |
+
align-items: start;
|
| 985 |
+
gap: 18px 24px;
|
| 986 |
+
}
|
| 987 |
+
|
| 988 |
+
.admin-layout-v2 .admin-hero > div:first-child {
|
| 989 |
+
max-width: 760px;
|
| 990 |
+
}
|
| 991 |
+
|
| 992 |
+
.admin-layout-v2 .action-group {
|
| 993 |
+
justify-self: end;
|
| 994 |
+
align-self: start;
|
| 995 |
+
}
|
| 996 |
+
|
| 997 |
.admin-page-nav {
|
| 998 |
display: inline-flex;
|
| 999 |
gap: 8px;
|
| 1000 |
padding: 6px;
|
| 1001 |
border-radius: 999px;
|
| 1002 |
background: rgba(255, 255, 255, 0.05);
|
| 1003 |
+
justify-self: end;
|
| 1004 |
}
|
| 1005 |
|
| 1006 |
.admin-page-tab {
|
|
|
|
| 1074 |
|
| 1075 |
.course-row-head {
|
| 1076 |
align-items: start;
|
| 1077 |
+
margin-bottom: 2px;
|
| 1078 |
}
|
| 1079 |
|
| 1080 |
.course-row-actions {
|
|
|
|
| 1090 |
}
|
| 1091 |
|
| 1092 |
.course-card {
|
| 1093 |
+
padding: 10px 12px;
|
| 1094 |
+
border-radius: 20px;
|
| 1095 |
+
}
|
| 1096 |
+
|
| 1097 |
+
.course-card h2 {
|
| 1098 |
+
font-size: 1.12rem;
|
| 1099 |
}
|
| 1100 |
|
| 1101 |
.course-card .admin-card-copy {
|
| 1102 |
+
margin: 1px 0 0;
|
| 1103 |
+
font-size: 0.78rem;
|
| 1104 |
+
line-height: 1.18;
|
| 1105 |
+
}
|
| 1106 |
+
|
| 1107 |
+
.course-row-actions .secondary-button,
|
| 1108 |
+
.course-row-actions .danger-button,
|
| 1109 |
+
.course-row-actions .task-count {
|
| 1110 |
+
min-height: 34px;
|
| 1111 |
+
padding: 0 10px;
|
| 1112 |
+
font-size: 0.82rem;
|
| 1113 |
}
|
| 1114 |
|
| 1115 |
.admin-schedule-grid {
|
|
|
|
| 1251 |
right: 14px;
|
| 1252 |
}
|
| 1253 |
|
| 1254 |
+
.schedule-editor-segment.is-compact .schedule-editor-segment-copy {
|
| 1255 |
+
padding: 9px 12px 15px;
|
| 1256 |
+
gap: 4px;
|
| 1257 |
+
}
|
| 1258 |
+
|
| 1259 |
+
.schedule-editor-segment.is-compact .schedule-editor-segment-copy strong {
|
| 1260 |
+
font-size: 0.88rem;
|
| 1261 |
+
}
|
| 1262 |
+
|
| 1263 |
+
.schedule-editor-segment.is-compact .schedule-editor-segment-kind {
|
| 1264 |
+
font-size: 0.72rem;
|
| 1265 |
+
}
|
| 1266 |
+
|
| 1267 |
+
.schedule-editor-segment.is-compact .schedule-editor-delete {
|
| 1268 |
+
top: 10px;
|
| 1269 |
+
bottom: auto;
|
| 1270 |
+
}
|
| 1271 |
+
|
| 1272 |
+
.schedule-editor-segment.is-tight .schedule-editor-segment-copy {
|
| 1273 |
+
padding: 7px 10px 12px;
|
| 1274 |
+
gap: 2px;
|
| 1275 |
+
}
|
| 1276 |
+
|
| 1277 |
+
.schedule-editor-segment.is-tight .schedule-editor-segment-copy strong {
|
| 1278 |
+
font-size: 0.8rem;
|
| 1279 |
+
}
|
| 1280 |
+
|
| 1281 |
+
.schedule-editor-segment.is-tight .schedule-editor-segment-copy span {
|
| 1282 |
+
font-size: 0.7rem;
|
| 1283 |
+
}
|
| 1284 |
+
|
| 1285 |
+
.schedule-editor-segment.is-tight .schedule-editor-segment-kind,
|
| 1286 |
+
.schedule-editor-segment.is-tight .schedule-editor-delete {
|
| 1287 |
+
display: none;
|
| 1288 |
+
}
|
| 1289 |
+
|
| 1290 |
+
.schedule-editor-segment.break.is-tight .schedule-editor-segment-copy span {
|
| 1291 |
+
display: none;
|
| 1292 |
+
}
|
| 1293 |
+
|
| 1294 |
+
.schedule-editor-segment.break.is-tight .schedule-editor-segment-copy strong {
|
| 1295 |
+
display: none;
|
| 1296 |
+
}
|
| 1297 |
+
|
| 1298 |
.schedule-editor-delete {
|
| 1299 |
position: absolute;
|
| 1300 |
right: 14px;
|
|
|
|
| 1390 |
flex-wrap: wrap;
|
| 1391 |
}
|
| 1392 |
|
| 1393 |
+
.admin-layout-v2 .admin-hero {
|
| 1394 |
+
grid-template-columns: 1fr;
|
| 1395 |
+
}
|
| 1396 |
+
|
| 1397 |
+
.admin-layout-v2 .action-group,
|
| 1398 |
+
.admin-page-nav {
|
| 1399 |
+
justify-self: stretch;
|
| 1400 |
+
}
|
| 1401 |
+
|
| 1402 |
.page-viewport,
|
| 1403 |
.page-track,
|
| 1404 |
.page-slide,
|