disappearing interface after link safe
This commit is contained in:
@@ -861,6 +861,18 @@ When the plugin is activated and the link already exists, show “This link alre
|
||||
### Assistant outcome
|
||||
Added an authenticated duplicate-check request when the popup opens after loading the active page. Existing links now show the requested warning before submission; comment and tag editing plus plugin retriggering remain available.
|
||||
|
||||
### User
|
||||
Display any errors that occur during posting.
|
||||
|
||||
### Assistant outcome
|
||||
Save responses now include sanitized plugin failure details, and the popup displays publishing errors alongside the save confirmation, including Mastodon HTTP or connection failures.
|
||||
|
||||
### User
|
||||
When pressing Save link, display “Link saved to <LinkLog server URL>” and hide all other information. Refresh only when the plugin is opened again.
|
||||
|
||||
### Assistant outcome
|
||||
Added a terminal save state to the popup. After a successful save it displays the localized LinkLog server URL, hides the form, session, warnings, and header information, and performs no refresh until the popup is opened again.
|
||||
|
||||
### User
|
||||
The plugin settings still show `emailLabel`; make that `email` as the title for the email field.
|
||||
|
||||
|
||||
@@ -149,7 +149,9 @@
|
||||
140. Change the title of the field "One-time password" to "One-time password (when configured)".
|
||||
157. The plugin settings still show 'emailLabel'; make that 'email' as title for the email field.
|
||||
163. When a URL with the same title is already in the database, warn the user, allow comment and hashtag changes, and retrigger plugins such as Mastodon reposting.
|
||||
166. Display any errors that occur during posting.
|
||||
164. When the plugin is activated and the link already exists, show "This link already exists. Comment and tags can be updated, and by submitting publishing will be retriggered."
|
||||
165. When pressing save link the plugin should display "Link saved to <url of linklog server>" and hide all other information. It should only refresh when the plugin is opened again
|
||||
141. Remove any leading and trailing spaces when entering fields in the settings page of the plugin.
|
||||
142. Do a full security audit document in what you have done in detail in Security-audit.md
|
||||
143. Address issue 1. and improve password storage
|
||||
|
||||
Binary file not shown.
@@ -76,7 +76,12 @@ def create_link_endpoint(payload: LinkCreate, response: Response, authorization:
|
||||
mark_mastodon_posted(record['id'], info['user_id'], mastodon_result.get('post_id'))
|
||||
if any(result.get('status') == 'failed' for result in plugin_results):
|
||||
logger.warning('One or more plugins failed for link_id=%s results=%s', record['id'], plugin_results)
|
||||
return {**record, 'duplicate': duplicate}
|
||||
plugin_errors = [
|
||||
{'plugin': result.get('plugin', 'unknown'), 'reason': result.get('reason', 'Plugin failed')}
|
||||
for result in plugin_results
|
||||
if result.get('status') == 'failed'
|
||||
]
|
||||
return {**record, 'duplicate': duplicate, 'plugin_errors': plugin_errors}
|
||||
|
||||
|
||||
@router.put('/links/{link_id}')
|
||||
|
||||
@@ -454,6 +454,18 @@ def test_duplicate_link_check_is_authenticated_and_detects_existing_entry():
|
||||
assert check.json()['exists'] is True
|
||||
|
||||
|
||||
def test_link_save_reports_plugin_posting_errors():
|
||||
with patch('backend.app.api.links.plugin_manager.dispatch', return_value=[
|
||||
{'status': 'failed', 'plugin': 'mastodon', 'reason': 'HTTP 503: unavailable'},
|
||||
]):
|
||||
response = client.post('/api/links', headers=login_headers(), json={
|
||||
'title': 'Plugin error report',
|
||||
'url': 'https://example.com/plugin-error-report',
|
||||
})
|
||||
assert response.status_code == 201
|
||||
assert response.json()['plugin_errors'] == [{'plugin': 'mastodon', 'reason': 'HTTP 503: unavailable'}]
|
||||
|
||||
|
||||
def test_links_support_tags_and_tag_filtering():
|
||||
headers = login_headers()
|
||||
response = client.post('/api/links', headers=headers, json={
|
||||
|
||||
@@ -40,9 +40,10 @@
|
||||
"configureAndLogIn": {"message": "Konfiguriere die Backend-URL und melde dich zuerst an."},
|
||||
"sessionExpired": {"message": "Sitzung abgelaufen. Authentifiziere dich in den Einstellungen erneut."},
|
||||
"submissionFailed": {"message": "Senden fehlgeschlagen"},
|
||||
"linkSaved": {"message": "Link erfolgreich gespeichert"},
|
||||
"linkSaved": {"message": "Link auf $URL$ gespeichert.", "placeholders": {"url": {"content": "$1"}}},
|
||||
"linkAlreadyExists": {"message": "Dieser Link existiert bereits. Kommentar und Tags wurden aktualisiert und die Veröffentlichung erneut ausgelöst."},
|
||||
"duplicateLinkWarning": {"message": "Dieser Link existiert bereits. Kommentar und Tags können aktualisiert werden; beim Absenden wird die Veröffentlichung erneut ausgelöst."},
|
||||
"publishingErrors": {"message": "Fehler bei der Veröffentlichung: $ERRORS$", "placeholders": {"errors": {"content": "$1"}}},
|
||||
"submissionFailedConnection": {"message": "Senden fehlgeschlagen. Überprüfe die Verbindung zum Backend."},
|
||||
"loggedInAt": {"message": "$USERNAME$ ist bei $BACKEND$ angemeldet", "placeholders": {"username": {"content": "$1"}, "backend": {"content": "$2"}}},
|
||||
"fillAllFields": {"message": "Fülle alle Felder aus"},
|
||||
|
||||
@@ -123,7 +123,12 @@
|
||||
"message": "Submission failed"
|
||||
},
|
||||
"linkSaved": {
|
||||
"message": "Link saved successfully"
|
||||
"message": "Link saved to $URL$.",
|
||||
"placeholders": {
|
||||
"url": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"linkAlreadyExists": {
|
||||
"message": "This link already exists. Comment and tags were updated, and publishing was retriggered."
|
||||
@@ -131,6 +136,14 @@
|
||||
"duplicateLinkWarning": {
|
||||
"message": "This link already exists. Comment and tags can be updated, and by submitting publishing will be retriggered."
|
||||
},
|
||||
"publishingErrors": {
|
||||
"message": "Publishing errors: $ERRORS$",
|
||||
"placeholders": {
|
||||
"errors": {
|
||||
"content": "$1"
|
||||
}
|
||||
}
|
||||
},
|
||||
"submissionFailedConnection": {
|
||||
"message": "Submission failed. Check your backend connection."
|
||||
},
|
||||
|
||||
@@ -40,9 +40,10 @@
|
||||
"configureAndLogIn": {"message": "Configura la URL del servidor e inicia sesión primero."},
|
||||
"sessionExpired": {"message": "La sesión ha caducado. Vuelve a autenticarte en la configuración."},
|
||||
"submissionFailed": {"message": "Error al enviar"},
|
||||
"linkSaved": {"message": "Enlace guardado correctamente"},
|
||||
"linkSaved": {"message": "Enlace guardado en $URL$.", "placeholders": {"url": {"content": "$1"}}},
|
||||
"linkAlreadyExists": {"message": "Este enlace ya existe. Se actualizaron el comentario y las etiquetas, y se volvió a activar la publicación."},
|
||||
"duplicateLinkWarning": {"message": "Este enlace ya existe. Puedes actualizar el comentario y las etiquetas; al enviarlo se volverá a activar la publicación."},
|
||||
"publishingErrors": {"message": "Errores de publicación: $ERRORS$", "placeholders": {"errors": {"content": "$1"}}},
|
||||
"submissionFailedConnection": {"message": "Error al enviar. Comprueba la conexión con el servidor."},
|
||||
"loggedInAt": {"message": "$USERNAME$ ha iniciado sesión en $BACKEND$", "placeholders": {"username": {"content": "$1"}, "backend": {"content": "$2"}}},
|
||||
"fillAllFields": {"message": "Rellena todos los campos"},
|
||||
|
||||
@@ -40,9 +40,10 @@
|
||||
"configureAndLogIn": {"message": "Configurez l’URL du serveur et connectez-vous d’abord."},
|
||||
"sessionExpired": {"message": "Session expirée. Reconnectez-vous dans les paramètres."},
|
||||
"submissionFailed": {"message": "Échec de l’envoi"},
|
||||
"linkSaved": {"message": "Lien enregistré"},
|
||||
"linkSaved": {"message": "Lien enregistré sur $URL$.", "placeholders": {"url": {"content": "$1"}}},
|
||||
"linkAlreadyExists": {"message": "Ce lien existe déjà. Le commentaire et les étiquettes ont été mis à jour et la publication a été relancée."},
|
||||
"duplicateLinkWarning": {"message": "Ce lien existe déjà. Le commentaire et les étiquettes peuvent être mis à jour ; l’envoi relancera la publication."},
|
||||
"publishingErrors": {"message": "Erreurs de publication : $ERRORS$", "placeholders": {"errors": {"content": "$1"}}},
|
||||
"submissionFailedConnection": {"message": "Échec de l’envoi. Vérifiez la connexion au serveur."},
|
||||
"loggedInAt": {"message": "$USERNAME$ est connecté à $BACKEND$", "placeholders": {"username": {"content": "$1"}, "backend": {"content": "$2"}}},
|
||||
"fillAllFields": {"message": "Veuillez remplir tous les champs"},
|
||||
|
||||
@@ -40,9 +40,10 @@
|
||||
"configureAndLogIn": {"message": "Configureer de backend-URL en log eerst in."},
|
||||
"sessionExpired": {"message": "Sessie verlopen. Verifieer opnieuw in de instellingen."},
|
||||
"submissionFailed": {"message": "Verzenden mislukt"},
|
||||
"linkSaved": {"message": "Koppeling opgeslagen"},
|
||||
"linkSaved": {"message": "Koppeling opgeslagen op $URL$.", "placeholders": {"url": {"content": "$1"}}},
|
||||
"linkAlreadyExists": {"message": "Deze koppeling bestaat al. De opmerking en tags zijn bijgewerkt en publiceren is opnieuw gestart."},
|
||||
"duplicateLinkWarning": {"message": "Deze koppeling bestaat al. De opmerking en tags kunnen worden bijgewerkt; na verzenden wordt publiceren opnieuw gestart."},
|
||||
"publishingErrors": {"message": "Publicatiefouten: $ERRORS$", "placeholders": {"errors": {"content": "$1"}}},
|
||||
"submissionFailedConnection": {"message": "Verzenden mislukt. Controleer de verbinding met de backend."},
|
||||
"loggedInAt": {"message": "$USERNAME$ is ingelogd op $BACKEND$", "placeholders": {"username": {"content": "$1"}, "backend": {"content": "$2"}}},
|
||||
"fillAllFields": {"message": "Vul alle velden in"},
|
||||
|
||||
+20
-1
@@ -65,6 +65,19 @@ function showSignedInState(user, backendUrl) {
|
||||
form.classList.remove('hidden');
|
||||
}
|
||||
|
||||
function showSavedState(message) {
|
||||
document.querySelector('header').classList.add('hidden');
|
||||
document.querySelector('.extension-footer').classList.add('hidden');
|
||||
authSession.hidden = true;
|
||||
authSession.classList.add('hidden');
|
||||
authWarning.hidden = true;
|
||||
authWarning.classList.add('hidden');
|
||||
form.classList.add('hidden');
|
||||
statusEl.textContent = message;
|
||||
statusEl.classList.remove('hidden', 'error');
|
||||
statusEl.classList.add('success');
|
||||
}
|
||||
|
||||
async function updateFeedLink() {
|
||||
const settings = await browser.storage.local.get(['backendUrl', 'username', 'accessToken']);
|
||||
if (!settings.backendUrl || !settings.username || !settings.accessToken) return;
|
||||
@@ -209,7 +222,13 @@ async function handleSubmit(event) {
|
||||
}
|
||||
|
||||
const result = await response.json();
|
||||
setStatus(result.duplicate ? t('linkAlreadyExists') : t('linkSaved'), Boolean(result.duplicate));
|
||||
const saveMessage = result.duplicate ? t('linkAlreadyExists') : t('linkSaved', backendUrl);
|
||||
if (result.plugin_errors?.length) {
|
||||
const errors = result.plugin_errors.map((error) => `${error.plugin}: ${error.reason}`).join(' ');
|
||||
showSavedState(`${saveMessage} ${t('publishingErrors', errors)}`);
|
||||
return;
|
||||
}
|
||||
showSavedState(saveMessage);
|
||||
} catch (error) {
|
||||
setStatus(t('submissionFailedConnection'), true);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user