diff --git a/migrations/0005_place_name.sql b/migrations/0005_place_name.sql new file mode 100644 index 0000000..ebc9fa4 --- /dev/null +++ b/migrations/0005_place_name.sql @@ -0,0 +1 @@ +ALTER TABLE places ADD COLUMN name TEXT; diff --git a/public/dashboard/index.html b/public/dashboard/index.html index dea4ded..da596b9 100644 --- a/public/dashboard/index.html +++ b/public/dashboard/index.html @@ -19,6 +19,8 @@

Add place

+ + +
+

Name

+ +
+ + +
+ + +
+

API Key

+
+ + +
diff --git a/public/js/dashboard.js b/public/js/dashboard.js index 201455a..7f26033 100644 --- a/public/js/dashboard.js +++ b/public/js/dashboard.js @@ -56,7 +56,7 @@ function renderPlaceList() { const idSpan = document.createElement('span'); idSpan.className = 'place-list-id'; - idSpan.textContent = place.id; + idSpan.textContent = place.name || place.id; li.appendChild(idSpan); if (place.ownerUsername) { @@ -82,7 +82,10 @@ async function selectPlace(placeId) { document.getElementById('no-place').classList.add('hidden'); document.getElementById('place-view').classList.remove('hidden'); - document.getElementById('place-title').textContent = placeId; + document.getElementById('place-title').textContent = data.place.name || placeId; + + document.getElementById('place-id-display').value = placeId; + document.getElementById('place-name-custom').value = data.place.name || ''; const apiKeyInput = document.getElementById('place-api-key-display'); apiKeyInput.value = data.place.apiKey || ''; @@ -177,10 +180,12 @@ document.getElementById('add-place-form').addEventListener('submit', async (e) = e.preventDefault(); const id = document.getElementById('place-id').value.trim(); const apiKey = document.getElementById('place-api-key').value.trim(); + const name = document.getElementById('place-name').value.trim(); const body = {}; if (id) body.id = id; if (apiKey) body.apiKey = apiKey; + if (name) body.name = name; const data = await api('/dashboard/places', { method: 'POST', @@ -190,6 +195,7 @@ document.getElementById('add-place-form').addEventListener('submit', async (e) = if (data.success) { document.getElementById('place-id').value = ''; document.getElementById('place-api-key').value = ''; + document.getElementById('place-name').value = ''; await loadPlaces(); selectPlace(data.place.id); } else { @@ -265,6 +271,24 @@ document.getElementById('regenerate-api-key-btn').addEventListener('click', asyn } }); +document.getElementById('set-place-name-form').addEventListener('submit', async (e) => { + e.preventDefault(); + if (!currentPlaceId) return; + + const name = document.getElementById('place-name-custom').value.trim(); + const data = await api(`/dashboard/places/${encodeURIComponent(currentPlaceId)}`, { + method: 'PUT', + body: JSON.stringify({ name }) + }); + + if (data.success) { + await loadPlaces(); + selectPlace(currentPlaceId); + } else { + alert(data.message || 'Failed to set place name'); + } +}); + document.getElementById('set-api-key-form').addEventListener('submit', async (e) => { e.preventDefault(); if (!currentPlaceId) return; diff --git a/routes/dashboard.js b/routes/dashboard.js index 430c066..96cccef 100644 --- a/routes/dashboard.js +++ b/routes/dashboard.js @@ -97,7 +97,7 @@ router.get('/places', (req, res) => { router.post('/places', (req, res) => { const canSetCustomValues = req.user.role >= ROLES.ADMIN; const { settings } = req.body || {}; - let { id, apiKey } = req.body || {}; + let { id, apiKey, name } = req.body || {}; if (!canSetCustomValues && (id || apiKey)) { return res.status(403).json({ success: false, message: "Only admins can set a custom place id or API key" }); @@ -106,6 +106,7 @@ router.post('/places', (req, res) => { // If we reach here, either the caller is an admin, or both id and apiKey were already falsy. id = id ? String(id).trim() : ''; apiKey = apiKey ? String(apiKey).trim() : ''; + name = name ? String(name).trim() : ''; if (!id) id = generatePlaceId(); if (!apiKey) apiKey = generateApiKey(); @@ -119,12 +120,12 @@ router.post('/places', (req, res) => { return res.status(409).json({ success: false, message: "A place with that id already exists" }); } - db.run(`INSERT INTO places (id, apiKey, settings, ownerId) VALUES (?, ?, ?, ?)`, [id, apiKey, settings || '{}', req.user.id], (err) => { + db.run(`INSERT INTO places (id, apiKey, settings, ownerId, name) VALUES (?, ?, ?, ?, ?)`, [id, apiKey, settings || '{}', req.user.id, name || null], (err) => { if (err) { console.error('Failed to create place:', err.message); return res.status(500).json({ success: false, message: "Internal server error" }); } - res.json({ success: true, place: { id, apiKey, settings: settings || '{}', ownerId: req.user.id } }); + res.json({ success: true, place: { id, apiKey, settings: settings || '{}', ownerId: req.user.id, name: name || null } }); }); }); }); @@ -155,8 +156,9 @@ router.put('/places/:placeId', loadPlace, (req, res) => { apiKey = String(req.body.apiKey).trim() || generateApiKey(); } const settings = req.body.settings !== undefined ? req.body.settings : req.place.settings; + const name = req.body.name !== undefined ? (String(req.body.name).trim() || null) : req.place.name; - db.run(`UPDATE places SET apiKey = ?, settings = ? WHERE id = ?`, [apiKey, settings, req.place.id], (err) => { + db.run(`UPDATE places SET apiKey = ?, settings = ?, name = ? WHERE id = ?`, [apiKey, settings, name, req.place.id], (err) => { if (err) { console.error('Failed to update place:', err.message); return res.status(500).json({ success: false, message: "Internal server error" });