/** * sharing.js – File sharing management UI. * * Renders the current shares for a document and lets the file owner * add new shares, change roles, or revoke access. * * Usage: * initSharing(fileId, i18n) * * The i18n object is expected to contain all keys used below. */ /* global fetch */ (function () { 'use strict'; var _fileId = null; var _i18n = {}; // ── DOM helpers ────────────────────────────────────────────────────────── function _el(id) { return document.getElementById(id); } function _esc(str) { return String(str) .replace(/&/g, '&') .replace(//g, '>') .replace(/"/g, '"') .replace(/'/g, '''); } function _t(key) { return _i18n[key] || key; } // ── API helpers ────────────────────────────────────────────────────────── function _apiUrl(suffix) { return '/api/files/' + _fileId + suffix; } function _fetchShares() { return fetch(_apiUrl('/shares'), { credentials: 'same-origin' }) .then(function (r) { return r.json(); }); } function _addShare(userId, role) { return fetch(_apiUrl('/shares'), { method: 'POST', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ shared_with_user_id: userId, role: role }), }).then(function (r) { return r.json().then(function (body) { if (!r.ok) throw new Error((body && body.detail) || r.statusText); return body; }); }); } function _updateRole(shareId, role) { return fetch(_apiUrl('/shares/' + shareId), { method: 'PUT', credentials: 'same-origin', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ role: role }), }).then(function (r) { return r.json().then(function (body) { if (!r.ok) throw new Error((body && body.detail) || r.statusText); return body; }); }); } function _revokeShare(shareId) { return fetch(_apiUrl('/shares/' + shareId), { method: 'DELETE', credentials: 'same-origin', }).then(function (r) { return r.json().then(function (body) { if (!r.ok) throw new Error((body && body.detail) || r.statusText); return body; }); }); } // ── Render ─────────────────────────────────────────────────────────────── function _renderShares(shares) { var list = _el('sharing-list'); if (!list) return; if (!shares || shares.length === 0) { list.innerHTML = '
' + _esc(_t('no_shares')) + '
'; return; } var rows = shares.map(function (s) { var roleLabel = s.role === 'editor' ? _t('role_editor') : _t('role_viewer'); return ( '' + _esc(_t('loading')) + '
'; _fetchShares() .then(function (data) { // GET /files/{id}/shares returns an array; /files/{id}/shared-with also returns array var shares = Array.isArray(data) ? data : (data.shares || []); // Normalise keys: shares list uses share_id, but the shares endpoint returns id shares = shares.map(function (s) { return { share_id: s.share_id || s.id, user_id: s.user_id || s.shared_with_user_id, display_name: s.display_name || s.shared_with_user_id || s.user_id, role: s.role, }; }); _renderShares(shares); }) .catch(function (err) { if (list) list.innerHTML = '' + _esc(err.message) + '
'; }); } function _showError(msg) { var el = _el('sharing-form-error'); if (!el) return; el.textContent = msg; el.style.display = 'block'; setTimeout(function () { el.style.display = 'none'; }, 5000); } // ── Init ───────────────────────────────────────────────────────────────── function initSharing(fileId, i18n) { _fileId = fileId; _i18n = i18n || {}; _loadAndRender(); var form = _el('sharing-form'); if (!form) return; form.addEventListener('submit', function (e) { e.preventDefault(); var userInput = _el('share-user-input'); var roleInput = _el('share-role-input'); var userId = userInput ? userInput.value.trim() : ''; var role = roleInput ? roleInput.value : 'viewer'; if (!userId) { _showError(_t('error_empty_user')); return; } _addShare(userId, role) .then(function () { if (userInput) userInput.value = ''; _loadAndRender(); }) .catch(function (err) { _showError(err.message); }); }); } // Expose window.initSharing = initSharing; })();