Unverified Commit 804459c0 authored by Lemon-miaow's avatar Lemon-miaow
Browse files

feat(panel): implement admin maintenance window settings page

parent 55592ed1
Loading
Loading
Loading
Loading
+36 −0
Changes for panel/dev/mockApi.ts: 36 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -55,6 +55,7 @@ interface MockState {
  builds: Build[];
  passkeys: Record<AccountID, { id: string; name: string; created_at: string }[]>;
  submissions: Submission[];
  updateWindow: { start: string | null; end: string | null };
}

// PLAYER_NAME mirrors the backend's mcNameRe (handlers_access.go) so the mock
@@ -333,6 +334,7 @@ function initialState(): MockState {
        reviewed_at: new Date(Date.now() - 10700000).toISOString(),
      },
    ],
    updateWindow: { start: null, end: null },
  };
}

@@ -630,6 +632,40 @@ async function handlePublic(ctx: RequestContext): Promise<boolean> {

async function handleSession(ctx: SessionContext): Promise<boolean> {
  switch (route(ctx)) {
    case "GET updates/window":
      if (ctx.account.role !== "admin") {
        sendError(ctx.res, 403, "forbidden", "admin account required");
        return true;
      }
      sendJSON(ctx.res, 200, ctx.state.updateWindow);
      return true;
    case "PUT updates/window": {
      if (ctx.account.role !== "admin") {
        sendError(ctx.res, 403, "forbidden", "admin account required");
        return true;
      }
      const body = await readJSON<{ start: string | null; end: string | null }>(ctx.req);
      if (body.start === null && body.end === null) {
        ctx.state.updateWindow = { start: null, end: null };
      } else if (body.start === null || body.end === null) {
        sendError(ctx.res, 400, "bad_request", "start and end must both be set or both be null");
        return true;
      } else {
        const start = new Date(body.start);
        const end = new Date(body.end);
        if (isNaN(start.getTime()) || isNaN(end.getTime())) {
          sendError(ctx.res, 400, "bad_request", "invalid start or end time format");
          return true;
        }
        if (end <= start) {
          sendError(ctx.res, 400, "bad_request", "end must be after start");
          return true;
        }
        ctx.state.updateWindow = { start: body.start, end: body.end };
      }
      sendJSON(ctx.res, 200, ctx.state.updateWindow);
      return true;
    }
    case "GET me/servers":
      sendJSON(ctx.res, 200, { servers: visibleServers(ctx.state, ctx.account) });
      return true;
+2 −0
Changes for panel/src/App.tsx: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@ import { ImageAdmin } from "@/pages/admin/ImageAdmin";
import { ImageBuildPage } from "@/pages/admin/ImageBuildPage";
import { SubmissionsPage } from "@/pages/admin/SubmissionsPage";
import { MySubmissionsPage } from "@/pages/MySubmissionsPage";
import { UpdatesPage } from "@/pages/admin/UpdatesPage";

// Three UX surfaces over two Zero-Trust tiers (DESIGN-WEB-3SIDES):
//   /        User-Side    — app-tier, every authenticated principal
@@ -57,6 +58,7 @@ export default function App() {
                <Route path="images" element={<ImageAdmin />} />
                <Route path="builds" element={<ImageBuildPage />} />
                <Route path="submissions" element={<SubmissionsPage />} />
                <Route path="updates" element={<UpdatesPage />} />
              </Route>

              <Route path="*" element={<Navigate to="/" replace />} />
+24 −1
Changes for panel/src/i18n/resources/en-US/admin.json: 24 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -71,5 +71,28 @@
  "no_submissions_hint": "There are currently no pending or reviewed modpack submissions.",
  "reviewer": "Reviewer",
  "reviewed_at": "Reviewed At",
  "reject_reason": "Rejection Reason"
  "reject_reason": "Rejection Reason",
  "updates_title": "Maintenance Window",
  "updates_subtitle": "Configure the platform-wide maintenance window. A Scheduled auto-update component may only be applied by Felis within this window; outside it, updates are notify-only.",
  "updates_current_title": "Current Setting",
  "updates_current_unset": "No maintenance window set. Scheduled updates will degrade to notify-only and will not be applied automatically.",
  "updates_current_set": "Felis may apply auto-updates between the following period:",
  "updates_start_label": "Start Time",
  "updates_end_label": "End Time",
  "updates_set_title": "Configure Maintenance Window",
  "updates_submit_btn": "Save Maintenance Window",
  "updates_clear_btn": "Clear Maintenance Window",
  "updates_save_success": "Maintenance window updated successfully.",
  "updates_clear_success": "Maintenance window cleared successfully.",
  "updates_validation_both": "Both start and end times must be set, or both cleared.",
  "updates_validation_order": "End time must be strictly after start time.",
  "updates_status_active": "Currently Active",
  "updates_status_pending": "Scheduled (Future)",
  "updates_status_expired": "Expired (Past)",
  "updates_status_unset": "Unset",
  "updates_timezone_hint": "Times are selected and displayed in your browser's local time zone ({{tz}}).",
  "updates_stat_status": "System Status",
  "updates_stat_start": "Start Time",
  "updates_stat_end": "End Time",
  "updates_stat_timezone": "Local Timezone"
}
 No newline at end of file
+2 −1
Changes for panel/src/i18n/resources/en-US/navigation.json: 2 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -6,5 +6,6 @@
  "admin_section": "Admin",
  "admin_images": "Images",
  "admin_builds": "Build Pipeline",
  "admin_submissions": "Submissions"
  "admin_submissions": "Submissions",
  "admin_updates": "Maintenance Window"
}
+24 −1
Changes for panel/src/i18n/resources/zh-CN/admin.json: 24 added lines, 1 removed line.
Original line number Diff line number Diff line
@@ -71,5 +71,28 @@
  "no_submissions_hint": "当前没有待审核或已审核的模组包提交。",
  "reviewer": "审核人",
  "reviewed_at": "审核时间",
  "reject_reason": "驳回理由"
  "reject_reason": "驳回理由",
  "updates_title": "维护窗口",
  "updates_subtitle": "配置全局系统维护窗口。在此窗口内,Felis 可以自动应用系统更新;在窗口外,更新将降级为仅通知,不会自动执行。",
  "updates_current_title": "当前设置",
  "updates_current_unset": "当前未设置维护窗口。自动更新将降级为仅通知,不会自动执行。",
  "updates_current_set": "Felis 可在以下时间段内自动执行更新:",
  "updates_start_label": "开始时间",
  "updates_end_label": "结束时间",
  "updates_set_title": "配置维护窗口",
  "updates_submit_btn": "保存维护窗口",
  "updates_clear_btn": "清除维护窗口",
  "updates_save_success": "维护窗口更新成功。",
  "updates_clear_success": "维护窗口已清除。",
  "updates_validation_both": "开始时间和结束时间必须同时设置,或同时清空。",
  "updates_validation_order": "结束时间必须在开始时间之后。",
  "updates_status_active": "当前生效中",
  "updates_status_pending": "已计划(未来)",
  "updates_status_expired": "已过期(过去)",
  "updates_status_unset": "未设置",
  "updates_timezone_hint": "时间以您的浏览器本地时区 ({{tz}}) 选择和显示。",
  "updates_stat_status": "系统状态",
  "updates_stat_start": "维护开始时间",
  "updates_stat_end": "维护结束时间",
  "updates_stat_timezone": "本地时区"
}
 No newline at end of file
Loading