feat: auth system — CSS page transitions, API helpers, users/tokens pages
This commit is contained in:
parent
d0f9848717
commit
2d21d4d44d
1 changed files with 71 additions and 38 deletions
|
|
@ -133,7 +133,6 @@ async function deleteProject(projectId) {
|
|||
|
||||
// ============================================================
|
||||
// BIN API CALLS
|
||||
// Bins are mounted at /api/v1/bins with project_id as query param
|
||||
// ============================================================
|
||||
|
||||
async function getBins(projectId) {
|
||||
|
|
@ -166,14 +165,8 @@ async function deleteBin(projectId, binId) {
|
|||
|
||||
// ============================================================
|
||||
// CAPTURE API CALLS
|
||||
// Routes: GET /capture/devices, GET /capture/status,
|
||||
// POST /capture/start, POST /capture/stop
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* Get list of available capture devices.
|
||||
* Normalises capture service response ({index, name}) to {id, name, interface}.
|
||||
*/
|
||||
async function getCaptureDevices() {
|
||||
const result = await captureApi('/devices');
|
||||
if (result.success && result.data) {
|
||||
|
|
@ -189,23 +182,14 @@ async function getCaptureDevices() {
|
|||
return result;
|
||||
}
|
||||
|
||||
/** Get overall capture service status */
|
||||
async function getCaptureStatus() {
|
||||
return captureApi('/status');
|
||||
}
|
||||
|
||||
/** Get current recording state (alias for getCaptureStatus) */
|
||||
async function getRecordingStatus() {
|
||||
return captureApi('/status');
|
||||
}
|
||||
|
||||
/**
|
||||
* Start recording.
|
||||
* @param {number} deviceIndex - Device index from getCaptureDevices
|
||||
* @param {string} projectId
|
||||
* @param {string|null} binId
|
||||
* @param {string} clipName
|
||||
*/
|
||||
async function startRecording(deviceIndex, projectId, binId, clipName) {
|
||||
const result = await captureApi('/start', {
|
||||
method: 'POST',
|
||||
|
|
@ -222,16 +206,10 @@ async function startRecording(deviceIndex, projectId, binId, clipName) {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the active recording.
|
||||
* Uses the session ID stored from the most recent startRecording call,
|
||||
* falling back to the current status if no local state exists.
|
||||
*/
|
||||
async function stopRecording() {
|
||||
let sessionId = _captureSessionId;
|
||||
|
||||
if (!sessionId) {
|
||||
// Try to recover session_id from live status
|
||||
const statusResult = await captureApi('/status');
|
||||
if (statusResult.success && statusResult.data && statusResult.data.sessionId) {
|
||||
sessionId = statusResult.data.sessionId;
|
||||
|
|
@ -249,14 +227,10 @@ async function stopRecording() {
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get recent captures — uses assets API ordered by created_at desc.
|
||||
*/
|
||||
async function getRecentCaptures(limit = 10) {
|
||||
return api(`/assets?limit=${limit}`);
|
||||
}
|
||||
|
||||
/** Not available in current capture service — returns empty */
|
||||
async function getRecordingTimecode() {
|
||||
return { success: true, data: { timecode: null } };
|
||||
}
|
||||
|
|
@ -318,13 +292,8 @@ function throttle(func, limit) {
|
|||
|
||||
// ============================================================
|
||||
// UPLOAD API CALLS
|
||||
// Routes expect camelCase field names
|
||||
// ============================================================
|
||||
|
||||
/**
|
||||
* Initialize a multipart upload.
|
||||
* Returns { assetId, uploadId, key }
|
||||
*/
|
||||
async function initUpload(data) {
|
||||
const body = {
|
||||
filename: data.filename,
|
||||
|
|
@ -337,10 +306,6 @@ async function initUpload(data) {
|
|||
return api('/upload/init', { method: 'POST', body: JSON.stringify(body) });
|
||||
}
|
||||
|
||||
/**
|
||||
* Complete a multipart upload.
|
||||
* @param {object} data - { uploadId, key, assetId, parts: [{partNumber, ETag}] }
|
||||
*/
|
||||
async function completeUpload(data) {
|
||||
const body = {
|
||||
uploadId: data.upload_id || data.uploadId,
|
||||
|
|
@ -354,7 +319,6 @@ async function completeUpload(data) {
|
|||
return api('/upload/complete', { method: 'POST', body: JSON.stringify(body) });
|
||||
}
|
||||
|
||||
/** Abort an ongoing multipart upload */
|
||||
async function abortUpload(data) {
|
||||
const body = {
|
||||
uploadId: data.upload_id || data.uploadId,
|
||||
|
|
@ -364,7 +328,6 @@ async function abortUpload(data) {
|
|||
return api('/upload/abort', { method: 'POST', body: JSON.stringify(body) });
|
||||
}
|
||||
|
||||
/** Upload a file part (FormData, no JSON content-type) */
|
||||
async function uploadPart(formData) {
|
||||
try {
|
||||
const response = await fetch('/api/v1/upload/part', {
|
||||
|
|
@ -380,7 +343,6 @@ async function uploadPart(formData) {
|
|||
}
|
||||
}
|
||||
|
||||
/** Simple upload for small files (under 50MB) */
|
||||
async function simpleUpload(formData) {
|
||||
try {
|
||||
const response = await fetch('/api/v1/upload/simple', {
|
||||
|
|
@ -423,3 +385,74 @@ async function deleteRecorder(id) {
|
|||
async function getRecorderStatus(id) {
|
||||
return api(`/recorders/${id}/status`);
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// USERS API CALLS (admin)
|
||||
// ============================================================
|
||||
|
||||
async function getUsers() {
|
||||
return api('/users');
|
||||
}
|
||||
|
||||
async function createUser(data) {
|
||||
return api('/users', { method: 'POST', body: JSON.stringify(data) });
|
||||
}
|
||||
|
||||
async function updateUser(id, data) {
|
||||
return api(`/users/${id}`, { method: 'PATCH', body: JSON.stringify(data) });
|
||||
}
|
||||
|
||||
async function deleteUser(id) {
|
||||
return api(`/users/${id}`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// GROUPS API CALLS (admin)
|
||||
// ============================================================
|
||||
|
||||
async function getGroups() {
|
||||
return api('/groups');
|
||||
}
|
||||
|
||||
async function createGroup(data) {
|
||||
return api('/groups', { method: 'POST', body: JSON.stringify(data) });
|
||||
}
|
||||
|
||||
async function updateGroup(id, data) {
|
||||
return api(`/groups/${id}`, { method: 'PATCH', body: JSON.stringify(data) });
|
||||
}
|
||||
|
||||
async function deleteGroup(id) {
|
||||
return api(`/groups/${id}`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
async function getGroupMembers(id) {
|
||||
return api(`/groups/${id}/members`);
|
||||
}
|
||||
|
||||
async function addGroupMember(groupId, userId) {
|
||||
return api(`/groups/${groupId}/members`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ user_id: userId }),
|
||||
});
|
||||
}
|
||||
|
||||
async function removeGroupMember(groupId, userId) {
|
||||
return api(`/groups/${groupId}/members/${userId}`, { method: 'DELETE' });
|
||||
}
|
||||
|
||||
// ============================================================
|
||||
// TOKENS API CALLS
|
||||
// ============================================================
|
||||
|
||||
async function getTokens() {
|
||||
return api('/tokens');
|
||||
}
|
||||
|
||||
async function createToken(data) {
|
||||
return api('/tokens', { method: 'POST', body: JSON.stringify(data) });
|
||||
}
|
||||
|
||||
async function revokeToken(id) {
|
||||
return api(`/tokens/${id}`, { method: 'DELETE' });
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue