Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ ones are marked like "v1.0.0-fork".

### Fixed in Unreleased

* The unsaved-changes prompt in the term dialogs is now an in-app dialog that
follows the theme and the interface language, instead of the browser's.

* The "Email not verified" banner no longer follows accounts that have no
email address.

Expand Down
6 changes: 5 additions & 1 deletion locale/ar/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"status_learned": "مُتعلَّم",
"status_well_known": "معروف جيدًا",
"status_ignored": "متجاهَل",
"status_unknown": "غير معروف"
"status_unknown": "غير معروف",
"dialog.discard_title": "هل تريد تجاهل التغييرات؟",
"dialog.discard_message": "لم تُحفظ تغييراتك على هذا المصطلح.",
"dialog.discard": "تجاهل",
"dialog.keep_editing": "متابعة التعديل"
}
6 changes: 5 additions & 1 deletion locale/de/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"status_learned": "Gelernt",
"status_well_known": "Bekannt",
"status_ignored": "Ignoriert",
"status_unknown": "Unbekannt"
"status_unknown": "Unbekannt",
"dialog.discard_title": "Änderungen verwerfen?",
"dialog.discard_message": "Ihre Änderungen an diesem Begriff wurden nicht gespeichert.",
"dialog.discard": "Verwerfen",
"dialog.keep_editing": "Weiter bearbeiten"
}
6 changes: 5 additions & 1 deletion locale/en/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"status_learned": "Learned",
"status_well_known": "Well Known",
"status_ignored": "Ignored",
"status_unknown": "Unknown"
"status_unknown": "Unknown",
"dialog.discard_title": "Discard your changes?",
"dialog.discard_message": "Your changes to this term have not been saved.",
"dialog.discard": "Discard",
"dialog.keep_editing": "Keep editing"
}
6 changes: 5 additions & 1 deletion locale/es/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"status_learned": "Aprendida",
"status_well_known": "Bien conocida",
"status_ignored": "Ignorada",
"status_unknown": "Desconocida"
"status_unknown": "Desconocida",
"dialog.discard_title": "¿Descartar los cambios?",
"dialog.discard_message": "Los cambios en este término no se han guardado.",
"dialog.discard": "Descartar",
"dialog.keep_editing": "Seguir editando"
}
6 changes: 5 additions & 1 deletion locale/fa/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"status_learned": "یادگرفته",
"status_well_known": "کاملاً شناخته‌شده",
"status_ignored": "نادیده‌گرفته",
"status_unknown": "ناشناخته"
"status_unknown": "ناشناخته",
"dialog.discard_title": "تغییرات کنار گذاشته شوند؟",
"dialog.discard_message": "تغییرات شما در این واژه ذخیره نشده است.",
"dialog.discard": "کنار گذاشتن",
"dialog.keep_editing": "ادامهٔ ویرایش"
}
6 changes: 5 additions & 1 deletion locale/fr/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"status_learned": "Apprise",
"status_well_known": "Bien connue",
"status_ignored": "Ignorée",
"status_unknown": "Inconnue"
"status_unknown": "Inconnue",
"dialog.discard_title": "Abandonner vos modifications ?",
"dialog.discard_message": "Vos modifications de ce terme n'ont pas été enregistrées.",
"dialog.discard": "Abandonner",
"dialog.keep_editing": "Continuer à modifier"
}
6 changes: 5 additions & 1 deletion locale/it/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"status_learned": "Appresa",
"status_well_known": "Ben conosciuta",
"status_ignored": "Ignorata",
"status_unknown": "Sconosciuta"
"status_unknown": "Sconosciuta",
"dialog.discard_title": "Annullare le modifiche?",
"dialog.discard_message": "Le modifiche a questo termine non sono state salvate.",
"dialog.discard": "Annulla modifiche",
"dialog.keep_editing": "Continua a modificare"
}
6 changes: 5 additions & 1 deletion locale/ja/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"status_learned": "習得済み",
"status_well_known": "熟知",
"status_ignored": "無視",
"status_unknown": "不明"
"status_unknown": "不明",
"dialog.discard_title": "変更を破棄しますか?",
"dialog.discard_message": "この用語への変更は保存されていません。",
"dialog.discard": "破棄",
"dialog.keep_editing": "編集を続ける"
}
6 changes: 5 additions & 1 deletion locale/pt/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"status_learned": "Aprendida",
"status_well_known": "Bem conhecida",
"status_ignored": "Ignorada",
"status_unknown": "Desconhecida"
"status_unknown": "Desconhecida",
"dialog.discard_title": "Descartar as alterações?",
"dialog.discard_message": "As alterações neste termo não foram guardadas.",
"dialog.discard": "Descartar",
"dialog.keep_editing": "Continuar a editar"
}
6 changes: 5 additions & 1 deletion locale/ru/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"status_learned": "Изучено",
"status_well_known": "Хорошо известно",
"status_ignored": "Игнорируется",
"status_unknown": "Неизвестно"
"status_unknown": "Неизвестно",
"dialog.discard_title": "Отменить изменения?",
"dialog.discard_message": "Изменения этого термина не сохранены.",
"dialog.discard": "Отменить изменения",
"dialog.keep_editing": "Продолжить редактирование"
}
6 changes: 5 additions & 1 deletion locale/zh/common.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,9 @@
"status_learned": "已学会",
"status_well_known": "熟知",
"status_ignored": "已忽略",
"status_unknown": "未知"
"status_unknown": "未知",
"dialog.discard_title": "放弃更改?",
"dialog.discard_message": "您对此词条的更改尚未保存。",
"dialog.discard": "放弃",
"dialog.keep_editing": "继续编辑"
}
21 changes: 21 additions & 0 deletions src/frontend/css/base/styles.css
Original file line number Diff line number Diff line change
Expand Up @@ -3353,3 +3353,24 @@ Searchable Select Component (Alpine.js)
border-bottom: none;
padding-bottom: 0;
}

/* In-app confirmation, above the term dialogs and .lwt-modal */
.confirm-dialog {
z-index: 10001;
}

.confirm-dialog .modal-background {
background-color: rgba(10, 10, 10, 0.6);
}

.confirm-dialog .modal-card {
border-radius: 0.75rem;
max-width: 28rem;
overflow: hidden;
width: calc(100% - 2rem);
}

.confirm-dialog__actions {
gap: 0.5rem;
justify-content: flex-end;
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export interface MultiWordModalData {
init(): void;

// Methods
close(): void;
close(): Promise<void>;
save(): Promise<void>;
setStatus(status: number): void;
clearGeneralError(): void;
Expand Down Expand Up @@ -224,9 +224,11 @@ export function multiWordModalData(): MultiWordModalData {
/**
* Close the modal.
*/
close(): void {
releaseFocus();
this.store.close();
async close(): Promise<void> {
// Only once it has closed: the user may choose to keep editing.
if (await this.store.close()) {
releaseFocus();
}
},

/**
Expand Down
11 changes: 5 additions & 6 deletions src/frontend/js/modules/vocabulary/components/word_edit_form.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* @since 3.0.0
*/

import { confirmDiscardChanges } from '@shared/components/confirm_dialog';
import Alpine from 'alpinejs';
import type { WordFormStoreState, SaveResult } from '../stores/word_form_store';
import type { WordStoreState } from '../stores/word_store';
Expand Down Expand Up @@ -110,7 +111,7 @@ export interface WordEditFormData {
hasFieldError(field: FormDataField): boolean;
getFieldError(field: FormDataField): string | null;
save(): Promise<void>;
cancel(): void;
cancel(): Promise<void>;
addTag(tag: string): void;
removeTag(tag: string): void;
filterTags(): void;
Expand Down Expand Up @@ -323,11 +324,9 @@ export function wordEditFormData(): WordEditFormData {
}
},

cancel(): void {
if (this.isDirty) {
if (!confirm('You have unsaved changes. Are you sure you want to cancel?')) {
return;
}
async cancel(): Promise<void> {
if (this.isDirty && !await confirmDiscardChanges()) {
return;
}

// Call the onCancelled callback if set, otherwise signal to return to info view
Expand Down
7 changes: 4 additions & 3 deletions src/frontend/js/modules/vocabulary/components/word_modal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
* @since 3.0.0
*/

import { confirmDiscardChanges } from '@shared/components/confirm_dialog';
import Alpine from 'alpinejs';
import type { WordStoreState, WordData } from '../stores/word_store';
import type { WordFormStoreState } from '../stores/word_form_store';
Expand Down Expand Up @@ -100,7 +101,7 @@ export interface WordModalData {
init(): void;

// Methods
close(): void;
close(): Promise<void>;
speakWord(): void;
setStatus(status: number): Promise<void>;
markWellKnown(): Promise<void>;
Expand Down Expand Up @@ -276,10 +277,10 @@ export function wordModalData(): WordModalData {
return !!this.word?.wordId;
},

close(): void {
async close(): Promise<void> {
// Check for unsaved changes
if (this.formStore.isDirty) {
if (!confirm('You have unsaved changes. Are you sure you want to close?')) {
if (!await confirmDiscardChanges()) {
return;
}
this.formStore.reset();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* @since 3.0.0
*/

import { confirmDiscardChanges } from '@shared/components/confirm_dialog';
import Alpine from 'alpinejs';
import { TermsApi, type MultiWordData, type MultiWordInput } from '@modules/vocabulary/api/terms_api';
import { updateWordStatusInDOM } from '@modules/text/pages/reading/text_renderer';
Expand Down Expand Up @@ -80,7 +81,7 @@ export interface MultiWordFormStoreState {
// Methods
loadForEdit(textId: number, position: number, text: string, wordCount: number, wordId?: number): Promise<void>;
reset(): void;
close(): void;
close(): Promise<boolean>;
validate(): boolean;
validateField(field: keyof MultiWordFormData): void;
save(): Promise<SaveResult>;
Expand Down Expand Up @@ -296,15 +297,16 @@ function createMultiWordFormStore(): MultiWordFormStoreState {
},

/**
* Close the modal.
* Close the modal, unless the user chooses to keep their changes.
*
* @returns Whether it closed
*/
close(): void {
if (this.isDirty) {
if (!confirm('You have unsaved changes. Are you sure you want to close?')) {
return;
}
async close(): Promise<boolean> {
if (this.isDirty && !await confirmDiscardChanges()) {
return false;
}
this.reset();
return true;
},

/**
Expand Down
Loading
Loading