HIGH fixes (7): - H1: VNCdirectory admin i18n — 30+ translation keys added - H2: handleSave try/catch with error toast - H3: Free/busy accountId scoping - H4: cancelEventBookings filter by eventId - H5: Resource picker static apiFetch import - H6: Sharing-store toast messages via lastMessage state - H7: roleLabel for all resource types MEDIUM fixes (11): - M1: identitySignatureMap cleanup on delete - M2: Now-line relative positioning - M3: Radial menu disabled item keyboard nav - M4: Radial menu stable event listener via refs - M5: cancelBooking error on missing booking - M6: PasswordRow isMasked state flag - M7: Extract shared rights into lib/sharing-rights.ts - M8: VNCtalk client server-side guard - M9: Collabora configManager instead of process.env - M10: CONFIG_ENV_MAP VNCdirectory fields - M11: SENSITIVE_CONFIG_KEYS field name unification LOW fixes (7): - L1-L3: Unused imports removed - L4: aria-labels on close, clear, search, spinner - L5-L7: Comments for intentional patterns, null guard
63 lines
1.7 KiB
TypeScript
63 lines
1.7 KiB
TypeScript
// Server-side only — imported exclusively from API route handlers.
|
|
// configManager reads from node:fs/promises and cannot run in the browser.
|
|
if (typeof window !== "undefined") {
|
|
throw new Error("lib/vnctalk/client.ts is server-only");
|
|
}
|
|
|
|
import { configManager } from "@/lib/admin/config-manager";
|
|
|
|
export interface CreateVncMeetingParams {
|
|
name: string;
|
|
start: string;
|
|
end: string;
|
|
invitees: string[];
|
|
password?: string;
|
|
description?: string;
|
|
}
|
|
|
|
export interface CreateVncMeetingResult {
|
|
meetingUrl: string;
|
|
meetingId: string;
|
|
}
|
|
|
|
export async function createVncMeeting(
|
|
params: CreateVncMeetingParams
|
|
): Promise<CreateVncMeetingResult> {
|
|
const serverUrl = configManager.get<string>("vnctalkServerUrl") || process.env.VNCTALK_SERVER_URL || "";
|
|
|
|
if (!serverUrl) {
|
|
throw new Error("VNCTALK_SERVER_URL is not configured");
|
|
}
|
|
|
|
const endpoint = `${serverUrl.replace(/\/+$/, "")}/api/createnewmeeting`;
|
|
|
|
const response = await fetch(endpoint, {
|
|
method: "POST",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({
|
|
name: params.name,
|
|
start: params.start,
|
|
end: params.end,
|
|
invitees: params.invitees,
|
|
password: params.password,
|
|
description: params.description,
|
|
}),
|
|
});
|
|
|
|
if (!response.ok) {
|
|
const text = await response.text().catch(() => "");
|
|
throw new Error(`VNCtalk API error ${response.status}: ${text}`);
|
|
}
|
|
|
|
const data = await response.json();
|
|
|
|
const meetingUrl: string = data.meetingUrl || data.meeting_url || data.url || "";
|
|
const meetingId: string = data.meetingId || data.meeting_id || data.id || "";
|
|
|
|
if (!meetingUrl) {
|
|
throw new Error("VNCtalk API did not return a meeting URL");
|
|
}
|
|
|
|
return { meetingUrl, meetingId };
|
|
}
|