Spaces:
Running
Running
Download public/js/api.js from Tataaicoltd/api: direct link, hf CLI and curl.
- Browser
- Download file 3.39 kB
-
https://huggingface.co/spaces/Tataaicoltd/api/resolve/main/public/js/api.js
- Command line
-
hf download hf://spaces/Tataaicoltd/api/public/js/api.js
-
curl -L -o api.js https://huggingface.co/spaces/Tataaicoltd/api/resolve/main/public/js/api.js
3.39 kB
| // Thin fetch wrapper around the backend API + shared UI helpers. | |
| const API = { | |
| base: '/api', | |
| async request(method, path, body) { | |
| const opts = { method, headers: {} }; | |
| if (body !== undefined) { | |
| opts.headers['Content-Type'] = 'application/json'; | |
| opts.body = JSON.stringify(body); | |
| } | |
| const res = await fetch(this.base + path, opts); | |
| if (res.status === 204) return null; | |
| const data = await res.json().catch(() => ({})); | |
| if (!res.ok) throw new Error(data.error || `Request failed (${res.status})`); | |
| return data; | |
| }, | |
| // Projects | |
| listProjects() { return this.request('GET', '/projects'); }, | |
| getProject(id) { return this.request('GET', `/projects/${id}`); }, | |
| createProject(p) { return this.request('POST', '/projects', p); }, | |
| updateProject(id, p) { return this.request('PUT', `/projects/${id}`, p); }, | |
| deleteProject(id) { return this.request('DELETE', `/projects/${id}`); }, | |
| // Tickets | |
| listTickets(params = {}) { | |
| const qs = new URLSearchParams(params).toString(); | |
| return this.request('GET', `/tickets${qs ? '?' + qs : ''}`); | |
| }, | |
| getTicket(id) { return this.request('GET', `/tickets/${id}`); }, | |
| createTicket(t) { return this.request('POST', '/tickets', t); }, | |
| updateTicket(id, t) { return this.request('PUT', `/tickets/${id}`, t); }, | |
| deleteTicket(id) { return this.request('DELETE', `/tickets/${id}`); }, | |
| deleteTicketImage(id, url) { return this.request('DELETE', `/tickets/${id}/images`, { url }); }, | |
| async uploadImages(id, files) { | |
| const fd = new FormData(); | |
| for (const f of files) fd.append('images', f); | |
| const res = await fetch(`${this.base}/tickets/${id}/images`, { method: 'POST', body: fd }); | |
| const data = await res.json().catch(() => ({})); | |
| if (!res.ok) throw new Error(data.error || 'Upload failed'); | |
| return data; | |
| } | |
| }; | |
| // ---------- UI helpers ---------- | |
| const UI = { | |
| el(html) { | |
| const t = document.createElement('template'); | |
| t.innerHTML = html.trim(); | |
| return t.content.firstElementChild; | |
| }, | |
| esc(s) { | |
| return String(s ?? '').replace(/[&<>"']/g, (c) => ({ | |
| '&': '&', '<': '<', '>': '>', '"': '"', "'": ''' | |
| })[c]); | |
| }, | |
| fmtDate(v) { | |
| if (!v) return '—'; | |
| const d = new Date(v); | |
| if (isNaN(d)) return UI.esc(v); | |
| return d.toLocaleString(); | |
| }, | |
| toast(msg, isError = false) { | |
| const t = document.getElementById('toast'); | |
| t.textContent = msg; | |
| t.className = 'toast' + (isError ? ' error' : ''); | |
| t.hidden = false; | |
| clearTimeout(this._toastTimer); | |
| this._toastTimer = setTimeout(() => (t.hidden = true), 2600); | |
| }, | |
| openModal(html, wide = false) { | |
| const overlay = document.getElementById('modal-overlay'); | |
| const modal = document.getElementById('modal'); | |
| modal.className = 'modal' + (wide ? ' wide' : ''); | |
| modal.innerHTML = ''; | |
| modal.appendChild(typeof html === 'string' ? UI.el(html) : html); | |
| overlay.hidden = false; | |
| return modal; | |
| }, | |
| closeModal() { | |
| document.getElementById('modal-overlay').hidden = true; | |
| }, | |
| lightbox(url) { | |
| const lb = UI.el(`<div class="lightbox"><img src="${UI.esc(url)}" alt="screenshot" /></div>`); | |
| lb.addEventListener('click', () => lb.remove()); | |
| document.body.appendChild(lb); | |
| } | |
| }; | |
| // Close modal on overlay click | |
| document.addEventListener('click', (e) => { | |
| if (e.target.id === 'modal-overlay') UI.closeModal(); | |
| }); | |