-
Notifications
You must be signed in to change notification settings - Fork 15
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(front): improve bin deletion UX
The bin deletion via the interface was completly impratical. From now on, the token storage is done automatically. Indeed, a Service Worker is registered to intercept in particular the request of the form and the request of the final page (redirection). This allows to associate the token with the bin ID, which is not known in advance. In the background, the IndexedDB database is used via the `localforage` abstraction, which allows to easily store key-value in the same way as the `localStorage` (which is not available in a Service Worker). This feature is only available for the clients with JavaScript enabled. Closes: #147.
- Loading branch information
Showing
7 changed files
with
104 additions
and
10 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
const deleteButton = document.getElementById('delete-button'); | ||
const id = location.pathname.slice(1, location.pathname.lastIndexOf('.')); | ||
|
||
const token = await localforage.getItem(id); | ||
|
||
if (token) { | ||
deleteButton.classList.remove('hidden'); | ||
deleteButton.addEventListener('click', async () => { | ||
try { | ||
const response = await fetch(window.location.pathname, { | ||
method: 'DELETE', | ||
headers: { | ||
Authorization: `Token ${token}`, | ||
}, | ||
}); | ||
|
||
if (!response.ok) { | ||
const error = new Error(`${response.status} ${response.statusText}\n${await response.text()}`); | ||
error.response = response; | ||
throw error; | ||
} | ||
|
||
location.href = '/'; | ||
} catch (error) { | ||
console.error(error); | ||
if (error.response.status === 401) { | ||
alert('Le token stocké est très probablement erroné.'); | ||
localforage.removeItem(id); | ||
} else { | ||
console.error("Nous vous recommandons d'ouvrir une issue sur https://github.com/readthedocs-fr/bin-server si le problème persiste."); | ||
alert(`Une erreur est survenue (${error.response?.statusText || error.message}), votre snippet n'a donc pas pu être supprimé. Regardez la console pour plus d'informations.`); | ||
} | ||
} | ||
}); | ||
} else { | ||
deleteButton.remove(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
importScripts('https://cdnjs.cloudflare.com/ajax/libs/localforage/1.10.0/localforage.min.js'); | ||
|
||
const NEW_URL = location.origin + '/new'; | ||
|
||
self.addEventListener('install', () => { | ||
console.log('Installed Service Worker.'); | ||
self.skipWaiting(); | ||
}); | ||
self.addEventListener('activate', () => self.clients.claim()); | ||
|
||
// As the redirection mode of the form POST request | ||
// is 'manual', we cannot get the the redirection URL | ||
// from the request (opaqueredirect). A trick, is to store | ||
// the event.request.resultingClientId, which seems to be | ||
// the same only for the form POST request and the fetch | ||
// of the redirection URL. This allows us to intercept | ||
// the correct redirection URL request and thus obtain | ||
// the ID. | ||
const tokens = new Map(); | ||
self.addEventListener('fetch', (event) => { | ||
let token; | ||
// Intercept the request when the form is submitted | ||
if (event.request.url === NEW_URL && event.request.method === 'POST') { | ||
event.respondWith(fetch(event.request.clone()).then(async (response) => { | ||
// Store the resultingClientId only if the request is successful. | ||
if (response.type === 'opaqueredirect') { | ||
tokens.set(event.request.resultingClientId, | ||
new URLSearchParams(await event.request.text()).get('token')); | ||
} | ||
return response; | ||
})); | ||
|
||
// If the request's resultingClientId is the same as | ||
// the submitted form request's resultingClientId, | ||
// then this request is the fetch of the redirection URL. | ||
} else if (token = tokens.get(event.request.resultingClientId)) { | ||
tokens.delete(event.request.resultingClientId); | ||
localforage.setItem(event.request.url.slice(event.request.url.lastIndexOf('/') + 1, | ||
event.request.url.lastIndexOf('.')), token); | ||
} | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters