diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json index 6a862fa016..c1097000c1 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ar.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "عرض 0 الي 0 من 0 إدخالات", "PagerInfoFiltered": "(تمت تصفيته من _MAX_ مجموع الإدخالات)", "NoDataAvailableInDatatable": "لا توجد بيانات متاحة في الجدول", + "ErrorLoadingDatatable": "حدث خطأ أثناء الطلب. تحقق من الرسالة للتفاصيل.", "Total": "مجموع", "Selected": "مختارة", "PagerShowMenuEntries": "عرض _MENU_ إدخالات", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json index 46de32b3e6..710a57a2a9 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/cs.json @@ -39,6 +39,7 @@ "PagerInfoFiltered": "(filtrováno ze všech _MAX_ záznamů)", "NoDataAvailableInDatatable": "Nejsou žádná data", "Total": "celkem", + "ErrorLoadingDatatable": "Došlo k chybě během požadavku. Zkontrolujte zprávu pro podrobnosti.", "Selected": "vybráno", "PagerShowMenuEntries": "Zobrazit _MENU_ záznamů", "DatatableActionDropdownDefaultText": "Akce", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json index 3d5a4f3bf3..a955a9066d 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/de.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "0 bis 0 von 0 Einträgen anzeigen", "PagerInfoFiltered": "(gefiltert aus _MAX_ Einträgen)", "NoDataAvailableInDatatable": "Keine Daten verfügbar", + "ErrorLoadingDatatable": "Ein Fehler ist während der Anfrage aufgetreten. Überprüfen Sie die Nachricht auf Details.", "Total": "gesamt", "Selected": "ausgewählt", "PagerShowMenuEntries": "_MENU_ Einträge anzeigen", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json index ede2ca211a..2abb92eab7 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/el.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Εμφάνιση 0 έως 0 από 0 εγγραφές", "PagerInfoFiltered": "(φιλτραρισμένο από _MAX_ συνολικές εγγραφές)", "NoDataAvailableInDatatable": "Δεν υπάρχουν διαθέσιμα δεδομένα", + "ErrorLoadingDatatable": "Παρουσιάστηκε σφάλμα κατά τη διάρκεια του αιτήματος. Ελέγξτε το μήνυμα για λεπτομέρειες.", "Total": "Σύνολο", "Selected": "Έχει γίνει επιλογή", "PagerShowMenuEntries": "Εμφάνιση στοιχείων _MENU_", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json index 44913c3b1e..7bbcc9d82f 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en-GB.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Showing 0 to 0 of 0 entries", "PagerInfoFiltered": "(filtered from _MAX_ total entries)", "NoDataAvailableInDatatable": "No data available", + "ErrorLoadingDatatable": "An error occurred during the request. Check the message for details.", "Total": "total", "Selected": "selected", "PagerShowMenuEntries": "Show _MENU_ entries", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json index 5c2810f555..8ea53bba77 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/en.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Showing 0 to 0 of 0 entries", "PagerInfoFiltered": "(filtered from _MAX_ total entries)", "NoDataAvailableInDatatable": "No data available", + "ErrorLoadingDatatable": "An error occurred during the request. Check the message for details.", "Total": "total", "Selected": "selected", "PagerShowMenuEntries": "Show _MENU_ entries", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json index 9d8578bc94..df75ed8799 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/es.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Mostrando de 0 a 0 de 0 entradas", "PagerInfoFiltered": "(filtrado desde _MAX_ entradas totales)", "NoDataAvailableInDatatable": "No hay datos disponibles", + "ErrorLoadingDatatable": "Se produjo un error durante la solicitud. Consulte el mensaje para más detalles.", "Total": "Total", "Selected": "Seleccionado", "PagerShowMenuEntries": "Mostrar _MENU_ registros", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json index 017f97ccb2..c5cb5960bd 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fa.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "نمایش از 0 تا 0 از مجموع 0 مورد", "PagerInfoFiltered": "(فیلتر شده از مجموع _MAX_ مورد)", "NoDataAvailableInDatatable": "داده ای وجود ندارد", + "ErrorLoadingDatatable": "در طول درخواست خطایی رخ داد. برای جزئیات پیام را بررسی کنید.", "Total": "مجموع", "Selected": "انتخاب شده", "PagerShowMenuEntries": "نمایش _MENU_ مورد", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json index 481ac49158..d2b5018e73 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fi.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Näytetään 0 - 0/0 tietueesta", "PagerInfoFiltered": "(suodatettu _MAX_ tietueen kokonaismäärästä)", "NoDataAvailableInDatatable": "Tietoja ei löydy", + "ErrorLoadingDatatable": "Pyynnön aikana tapahtui virhe. Tarkista viesti yksityiskohtia varten.", "Total": "kaikki yhteensä", "Selected": "valittu", "PagerShowMenuEntries": "Näytä _MENU_ tietueet", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json index ecef824b2a..66e37491fb 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/fr.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Affichage de 0 à 0 sur 0 entrées", "PagerInfoFiltered": "(filtré à partir des entrées _MAX_ totale)", "NoDataAvailableInDatatable": "Aucune donnée disponible", + "ErrorLoadingDatatable": "Une erreur est survenue lors de la requête. Vérifiez le message pour plus de détails.", "Total": "Total", "Selected": "Sélectionné", "PagerShowMenuEntries": "Afficher les entrées _MENU_", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json index a21b9e3443..7da0065d95 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hi.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "0 से 0 प्रविष्टियों को दिखा रहा है", "PagerInfoFiltered": "(_MAX_ कुल प्रविष्टियों से फ़िल्टर किया गया)", "NoDataAvailableInDatatable": "कोई डेटा उपलब्ध नहीं है", + "ErrorLoadingDatatable": "अनुरोध के दौरान एक त्रुटि हुई। विवरण के लिए संदेश देखें।", "Total": "संपूर्ण", "Selected": "चयनित", "PagerShowMenuEntries": "_MENU_ प्रविष्टियाँ दिखाएँ", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json index e3c7ebf295..b1073d62e7 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hr.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Prikazano 0 do 0 od 0 zapisa", "PagerInfoFiltered": "(filtrirano od _MAX_ ukupnih zapisa)", "NoDataAvailableInDatatable": "Nema dostupnih podataka", + "ErrorLoadingDatatable": "Došlo je do pogreške tijekom zahtjeva. Provjerite poruku za detalje.", "Total": "ukupno", "Selected": "odabrano", "PagerShowMenuEntries": "Pokaži _MENU_ zapise", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json index bf54087eba..3df6177a9f 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/hu.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Látható 0-tól 0-ig 0 elemből", "PagerInfoFiltered": "(szűrve _MAX_ elemből)", "NoDataAvailableInDatatable": "Nem elérhető adat", + "ErrorLoadingDatatable": "Hiba történt a kérés során. Ellenőrizze az üzenetet a részletekért.", "Total": "összesen", "Selected": "kiválasztott", "PagerShowMenuEntries": "Megjelenítve _MENU_ elem", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json index 93d0d8a161..d2eba16bd8 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/is.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Sýnir 0 til 0 af 0 færslum", "PagerInfoFiltered": "(síað úr _MAX_ heildar færslum)", "NoDataAvailableInDatatable": "Engar upplýsingar fáanlegar", + "ErrorLoadingDatatable": "Villa kom upp við beiðni. Athugaðu skilaboðin til að fá frekari upplýsingar.", "Total": "Samtals", "Selected": "valið", "PagerShowMenuEntries": "Sýna færslur _MENU_", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json index 852ce0d3e2..ef255274df 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/it.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Risultati da 0 a 0 di 0 elementi", "PagerInfoFiltered": "(filtrati da _MAX_ elementi totali)", "NoDataAvailableInDatatable": "Nessun dato disponibile", + "ErrorLoadingDatatable": "Si è verificato un errore durante la richiesta. Controlla il messaggio per i dettagli.", "Total": "Totale", "Selected": "Selezionato", "PagerShowMenuEntries": "Righe per pagina _MENU_", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json index 2ac54e4341..85b8b4f88b 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/nl.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Toont 0 tot 0 van 0 vermeldingen", "PagerInfoFiltered": "(gefilterd uit in totaal _MAX_ vermeldingen)", "NoDataAvailableInDatatable": "Geen gegevens beschikbaar", + "ErrorLoadingDatatable": "Er is een fout opgetreden tijdens het verzoek. Controleer het bericht voor details.", "Total": "totaal", "Selected": "geselecteed", "PagerShowMenuEntries": "Toon _MENU_-vermeldingen", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json index 596f816b4f..6739b673d7 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pl-PL.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Pokaż od 0 do 0 z 0 rekordów", "PagerInfoFiltered": "(filtruj od _MAX_ wszystkich rekordów)", "NoDataAvailableInDatatable": "Nie znaleziono danych w tabeli", + "ErrorLoadingDatatable": "Wystąpił błąd podczas żądania. Sprawdź wiadomość, aby uzyskać szczegóły.", "Total": "całkowity", "Selected": "wybrany", "PagerShowMenuEntries": "Pokaż _MENU_ rekordów", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json index 73ec4120ce..5c4a6790f7 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/pt-BR.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Mostrando 0 até 0 de 0 registros", "PagerInfoFiltered": "(filtrado de um total de _MAX_ registros)", "NoDataAvailableInDatatable": "Nenhum dado disponível", + "ErrorLoadingDatatable": "Ocorreu um erro durante a solicitação. Verifique a mensagem para mais detalhes.", "Total": "total", "Selected": "selecionado", "PagerShowMenuEntries": "Mostrando _MENU_ registros", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json index bf83b4e89a..c5850bef00 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ro-RO.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Afişate 0 din 0 înregistrări", "PagerInfoFiltered": "(filtrate de la _MAX_ înregistrări totale)", "NoDataAvailableInDatatable": "Nicio informaţie disponibilă", + "ErrorLoadingDatatable": "A apărut o eroare în timpul solicitării. Verificați mesajul pentru detalii.", "Total": "total", "Selected": "selectate", "PagerShowMenuEntries": "Afişează _MENU_ intrări", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json index c7e6cc5439..f329315488 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/ru.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Записи с 0 до 0 из 0 записей.", "PagerInfoFiltered": "(отфильтровано из _MAX_ записей)", "NoDataAvailableInDatatable": "Данные в таблице отсутствуют", + "ErrorLoadingDatatable": "Произошла ошибка во время запроса. Проверьте сообщение для получения деталей.", "Total": "общий", "Selected": "выбранный", "PagerShowMenuEntries": "Показать _MENU_ записей", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json index eb06cdf1d0..6cc73f0cc6 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sk.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Zobrazených 0 až 0 z 0 záznamov", "PagerInfoFiltered": "(filtrované z celkom _MAX_ záznamov)", "NoDataAvailableInDatatable": "Nie sú k dispozícii žiadne údaje", + "ErrorLoadingDatatable": "Počas žiadosti došlo k chybe. Skontrolujte správu pre podrobnosti.", "Total": "celkom", "Selected": "vybrané", "PagerShowMenuEntries": "Zobraziť _MENU_ záznamov", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json index 3516ba5499..36d1bb14a6 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/sl.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Prikazanih 0 do 0 od 0 zapisov", "PagerInfoFiltered": "(filtrirano od vseh _MAX_ zapisov)", "NoDataAvailableInDatatable": "V tabeli ni na voljo podatkov", + "ErrorLoadingDatatable": "Pri zahtevi je prišlo do napake. Preverite sporočilo za podrobnosti.", "Total": "skupaj", "Selected": "izbrani", "PagerShowMenuEntries": "Prikaži _MENU_ zapise", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json index 1278ee2375..2636d1087a 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/tr.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "0 kayıttan 0 ile 0 arası gösteriliyor.", "PagerInfoFiltered": "(_MAX_ kayıt arasından filtrelendi)", "NoDataAvailableInDatatable": "Tabloda kayıt mevcut değil.", + "ErrorLoadingDatatable": "İstek sırasında bir hata oluştu. Detaylar için mesajı kontrol edin.", "Total": "toplam", "Selected": "seçilen", "PagerShowMenuEntries": "Sayfada _MENU_ kayıt göster.", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json index e807f851a1..fca1f0954c 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/vi.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "Hiển thị từ 0 đến 0 trong 0 mục", "PagerInfoFiltered": "(được lọc từ tổng số _MAX_ mục)", "NoDataAvailableInDatatable": "Không có dữ liệu trong bảng", + "ErrorLoadingDatatable": "Đã xảy ra lỗi trong quá trình yêu cầu. Kiểm tra tin nhắn để biết chi tiết.", "Total": "toàn bộ", "Selected": "đã chọn", "PagerShowMenuEntries": "Hiển thị _MENU_ mục", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json index 9a2ab1091b..2824c1bbbc 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hans.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "显示0个条目中的0到0", "PagerInfoFiltered": "(从 _MAX_ 总条目中过滤掉)", "NoDataAvailableInDatatable": "表中没有数据", + "ErrorLoadingDatatable": " 请求过程中发生错误。检查消息以获取详细信息", "Total": "总计", "Selected": "已选", "PagerShowMenuEntries": "显示 _MENU_ 条数据", diff --git a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json index 897356e3b7..17dac54739 100644 --- a/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json +++ b/framework/src/Volo.Abp.UI/Localization/Resources/AbpUi/zh-Hant.json @@ -38,6 +38,7 @@ "PagerInfoEmpty": "顯示0個紀錄中的0到0", "PagerInfoFiltered": "(從 _MAX_ 所有紀錄中過濾掉)", "NoDataAvailableInDatatable": "資料表中沒有資料", + "ErrorLoadingDatatable": "請求過程中發生錯誤。檢查消息以獲取詳細信息。", "Total": "總共", "Selected": "已選擇", "PagerShowMenuEntries": "顯示 _MENU_ 實體", diff --git a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts index e7b8371240..9d4a7be83f 100644 --- a/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts +++ b/npm/ng-packs/packages/components/extensible/src/lib/components/extensible-table/extensible-table.component.ts @@ -1,5 +1,7 @@ import { + AfterViewInit, ChangeDetectionStrategy, + ChangeDetectorRef, Component, EventEmitter, inject, @@ -14,8 +16,7 @@ import { } from '@angular/core'; import { AsyncPipe, formatDate, NgComponentOutlet, NgTemplateOutlet } from '@angular/common'; -import { Observable } from 'rxjs'; -import { map } from 'rxjs/operators'; +import { Observable, filter, map } from 'rxjs'; import { NgbTooltip } from '@ng-bootstrap/ng-bootstrap'; import { NgxDatatableModule } from '@swimlane/ngx-datatable'; @@ -71,7 +72,15 @@ const DEFAULT_ACTIONS_COLUMN_WIDTH = 150; templateUrl: './extensible-table.component.html', changeDetection: ChangeDetectionStrategy.OnPush, }) -export class ExtensibleTableComponent implements OnChanges { +export class ExtensibleTableComponent implements OnChanges, AfterViewInit { + readonly #injector = inject(Injector); + readonly getInjected = this.#injector.get.bind(this.#injector); + protected readonly cdr = inject(ChangeDetectorRef); + protected readonly locale = inject(LOCALE_ID); + protected readonly config = inject(ConfigStateService); + protected readonly entityPropTypeClasses = inject(ENTITY_PROP_TYPE_CLASSES); + protected readonly permissionService = inject(PermissionService); + protected _actionsText!: string; @Input() set actionsText(value: string) { @@ -104,13 +113,6 @@ export class ExtensibleTableComponent implements OnChanges { readonly trackByFn: TrackByFunction> = (_, item) => item.name; - locale = inject(LOCALE_ID); - private config = inject(ConfigStateService); - entityPropTypeClasses = inject(ENTITY_PROP_TYPE_CLASSES); - #injector = inject(Injector); - getInjected = this.#injector.get.bind(this.#injector); - permissionService = this.#injector.get(PermissionService); - constructor() { const extensions = this.#injector.get(ExtensionsService); const name = this.#injector.get(EXTENSIONS_IDENTIFIER); @@ -227,4 +229,11 @@ export class ExtensibleTableComponent implements OnChanges { return visibleActions.length > 0; } + + ngAfterViewInit(): void { + this.list?.requestStatus$?.pipe(filter(status => status === 'loading')).subscribe(() => { + this.data = []; + this.cdr.markForCheck(); + }); + } } diff --git a/npm/ng-packs/packages/core/src/lib/services/list.service.ts b/npm/ng-packs/packages/core/src/lib/services/list.service.ts index ef835e9fcd..027624ef88 100644 --- a/npm/ng-packs/packages/core/src/lib/services/list.service.ts +++ b/npm/ng-packs/packages/core/src/lib/services/list.service.ts @@ -1,9 +1,9 @@ import { Injectable, Injector, OnDestroy } from '@angular/core'; import { + EMPTY, BehaviorSubject, MonoTypeOperatorFunction, Observable, - of, ReplaySubject, Subject, } from 'rxjs'; @@ -11,6 +11,7 @@ import { catchError, debounceTime, filter, + finalize, shareReplay, switchMap, takeUntil, @@ -20,6 +21,8 @@ import { ABP } from '../models/common'; import { PagedResultDto } from '../models/dtos'; import { LIST_QUERY_DEBOUNCE_TIME } from '../tokens/list.token'; +export type RequestStatus = 'idle' | 'loading' | 'success' | 'error'; + @Injectable() export class ListService implements OnDestroy { private _filter = ''; @@ -40,7 +43,6 @@ export class ListService implements return this._maxResultCount; } - private _skipCount = 0; private _page = 0; set page(value: number) { if (value === this._page) return; @@ -91,12 +93,21 @@ export class ListService implements private _isLoading$ = new BehaviorSubject(false); + private _requestStatus = new BehaviorSubject('idle'); + private destroy$ = new Subject(); private delay: MonoTypeOperatorFunction; + /** + * @deprecated Use `requestStatus$` instead. + */ get isLoading$(): Observable { - return this._isLoading$.asObservable(); + return this._isLoading$.asObservable().pipe(takeUntil(this.destroy$)); + } + + get requestStatus$(): Observable { + return this._requestStatus.asObservable().pipe(takeUntil(this.destroy$)); } get = () => { @@ -119,9 +130,21 @@ export class ListService implements ): Observable> { return this.query$.pipe( tap(() => this._isLoading$.next(true)), - switchMap(query => streamCreatorCallback(query).pipe(catchError(() => of(null)))), + tap(() => this._requestStatus.next('loading')), + switchMap(query => + streamCreatorCallback(query).pipe( + catchError(() => { + this._requestStatus.next('error'); + return EMPTY; + }), + tap(() => this._requestStatus.next('success')), + finalize(() => { + this._isLoading$.next(false); + this._requestStatus.next('idle'); + }), + ), + ), filter(Boolean), - tap(() => this._isLoading$.next(false)), shareReplay({ bufferSize: 1, refCount: true }), takeUntil(this.destroy$), ); @@ -130,18 +153,15 @@ export class ListService implements ngOnDestroy() { this.destroy$.next(); } - private resetPageWhenUnchanged() { const maxPage = Number(Number(this.totalCount / this._maxResultCount).toFixed()); const skipCount = this._page * this._maxResultCount; if (skipCount !== this._totalCount) { - this._skipCount = skipCount; return; } if (this.page === maxPage && this.page > 0) { - this._skipCount = skipCount - this._maxResultCount; this.page = this.page - 1; } } diff --git a/npm/ng-packs/packages/core/src/lib/tests/list.service.spec.ts b/npm/ng-packs/packages/core/src/lib/tests/list.service.spec.ts index f26c39d4ad..d81091b2f7 100644 --- a/npm/ng-packs/packages/core/src/lib/tests/list.service.spec.ts +++ b/npm/ng-packs/packages/core/src/lib/tests/list.service.spec.ts @@ -149,5 +149,37 @@ describe('ListService', () => { service.hookToQuery(callback).subscribe(); }); + + it('should emit requestStatus as side effect', done => { + const callback: QueryStreamCreatorCallback = query => + of({ items: [query], totalCount: 1 }); + + service.requestStatus$.pipe(bufferCount(3)).subscribe(([idle, init, end]) => { + expect(idle).toBe('idle'); + expect(init).toBe('loading'); + expect(end).toBe('success'); + + done(); + }); + + service.hookToQuery(callback).subscribe(); + }); + + it('should emit error requestStatus as side effect and stop processing', done => { + const errCallback: QueryStreamCreatorCallback = query => { + throw Error('A server error occurred'); + }; + + service.requestStatus$.pipe(bufferCount(3)).subscribe(([idle, loading, error]) => { + expect(idle).toBe('idle'); + expect(loading).toBe('loading'); + expect(error).toBe('error'); + done(); + }); + + service.hookToQuery(errCallback).subscribe({ + error: () => done(), + }); + }); }); }); diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts index 3adc055b8c..8eded1d615 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/index.ts @@ -14,4 +14,5 @@ export * from './password/password.component'; export * from './card/index'; export * from './checkbox/checkbox.component'; export * from './form-input/form-input.component'; -export * from './internet-connection-status/internet-connection-status.component' +export * from './internet-connection-status/internet-connection-status.component'; +export * from './spinner/spinner.component'; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/components/spinner/spinner.component.ts b/npm/ng-packs/packages/theme-shared/src/lib/components/spinner/spinner.component.ts new file mode 100644 index 0000000000..e1d3493261 --- /dev/null +++ b/npm/ng-packs/packages/theme-shared/src/lib/components/spinner/spinner.component.ts @@ -0,0 +1,14 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'abp-spinner', + standalone: true, + template: ` +
+
+ Loading... +
+
+ `, +}) +export class SpinnerComponent {} diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts index eb781666c1..359ca72b59 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-default.directive.ts @@ -7,12 +7,11 @@ import { debounceTime } from 'rxjs/operators'; @Directive({ // eslint-disable-next-line @angular-eslint/directive-selector selector: 'ngx-datatable[default]', - standalone:true, + standalone: true, exportAs: 'ngxDatatableDefault', }) -export class NgxDatatableDefaultDirective implements AfterViewInit, OnDestroy { +export class NgxDatatableDefaultDirective implements AfterViewInit, OnDestroy { private subscription = new Subscription(); - private resizeDiff = 0; @Input() class = 'material bordered'; @@ -22,7 +21,10 @@ export class NgxDatatableDefaultDirective implements AfterViewInit, OnDestroy { return `ngx-datatable ${this.class}`; } - constructor(private table: DatatableComponent, @Inject(DOCUMENT) private document: MockDocument) { + constructor( + private table: DatatableComponent, + @Inject(DOCUMENT) private document: MockDocument, + ) { this.table.columnMode = ColumnMode.force; this.table.footerHeight = 50; this.table.headerHeight = 50; diff --git a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts index b946ba2639..d50038b1b7 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/directives/ngx-datatable-list.directive.ts @@ -7,15 +7,19 @@ import { DoCheck, SimpleChanges, inject, - DestroyRef + DestroyRef, + ViewContainerRef, + Renderer2, } from '@angular/core'; import { takeUntilDestroyed } from '@angular/core/rxjs-interop'; +import { distinctUntilChanged } from 'rxjs'; import { DatatableComponent } from '@swimlane/ngx-datatable'; import { ListService, LocalizationService } from '@abp/ng.core'; import { defaultNgxDatatableMessages, NGX_DATATABLE_MESSAGES, } from '../tokens/ngx-datatable-messages.token'; +import { SpinnerComponent } from '../components'; @Directive({ // eslint-disable-next-line @angular-eslint/directive-selector @@ -24,13 +28,15 @@ import { exportAs: 'ngxDatatableList', }) export class NgxDatatableListDirective implements OnChanges, OnInit, DoCheck { - @Input() list!: ListService; - protected readonly table = inject(DatatableComponent); protected readonly cdRef = inject(ChangeDetectorRef); protected readonly destroyRef = inject(DestroyRef); protected readonly localizationService = inject(LocalizationService); protected readonly ngxDatatableMessages = inject(NGX_DATATABLE_MESSAGES, { optional: true }); + protected readonly viewContainerRef = inject(ViewContainerRef); + protected readonly renderer = inject(Renderer2); + + @Input() list!: ListService; constructor() { this.setInitialValues(); @@ -43,6 +49,7 @@ export class NgxDatatableListDirective implements OnChanges, OnInit, DoCheck { ngOnInit() { this.subscribeToPage(); this.subscribeToSort(); + this.subscribeToRequestStatus(); } ngOnChanges({ list }: SimpleChanges) { @@ -55,32 +62,88 @@ export class NgxDatatableListDirective implements OnChanges, OnInit, DoCheck { this.table.offset = page; } + protected subscribeToRequestStatus() { + const requestStatus$ = this.list.requestStatus$.pipe(distinctUntilChanged()); + const { emptyMessage, errorMessage } = this.ngxDatatableMessages || defaultNgxDatatableMessages; + + requestStatus$.subscribe(status => { + this.table.loadingIndicator = false; + + if (status === 'idle') { + return; + } + + if (status === 'loading') { + this.table.messages.emptyMessage = undefined; + this.table.loadingIndicator = true; + this.cdRef.detectChanges(); + this.updateLoadingIndicator(); + return; + } + + if (status === 'error') { + this.table.messages.emptyMessage = this.localizationService.instant(errorMessage); + this.viewContainerRef.clear(); + this.cdRef.markForCheck(); + } + + if (status === 'success') { + this.table.messages.emptyMessage = this.localizationService.instant(emptyMessage); + this.viewContainerRef.clear(); + } + }); + } + + protected updateLoadingIndicator() { + const body = this.table.element.querySelector('datatable-body'); + const progress = this.table.element.querySelector('datatable-progress'); + + if (!body) { + return; + } + + if (progress) { + this.replaceLoadingIndicator(body, progress); + } + } + + protected replaceLoadingIndicator(parent: Element, placeholder: Element) { + this.viewContainerRef.clear(); + + const spinnerRef = this.viewContainerRef.createComponent(SpinnerComponent); + const spinnerElement = spinnerRef.location.nativeElement; + + this.renderer.insertBefore(parent, spinnerElement, placeholder); + this.renderer.removeChild(parent, placeholder); + } + protected setInitialValues() { this.table.externalPaging = true; this.table.externalSorting = true; - const { emptyMessage, selectedMessage, totalMessage } = + const { selectedMessage, totalMessage } = this.ngxDatatableMessages || defaultNgxDatatableMessages; this.table.messages = { - emptyMessage: this.localizationService.instant(emptyMessage), totalMessage: this.localizationService.instant(totalMessage), selectedMessage: this.localizationService.instant(selectedMessage), }; } protected subscribeToSort() { - this.table.sort.pipe(takeUntilDestroyed(this.destroyRef)).subscribe(({ sorts: [{ prop, dir }] }) => { - if (prop === this.list.sortKey && this.list.sortOrder === 'desc') { - this.list.sortKey = ''; - this.list.sortOrder = ''; - this.table.sorts = []; - this.cdRef.detectChanges(); - } else { - this.list.sortKey = prop; - this.list.sortOrder = dir; - } - }); + this.table.sort + .pipe(takeUntilDestroyed(this.destroyRef)) + .subscribe(({ sorts: [{ prop, dir }] }) => { + if (prop === this.list.sortKey && this.list.sortOrder === 'desc') { + this.list.sortKey = ''; + this.list.sortOrder = ''; + this.table.sorts = []; + this.cdRef.detectChanges(); + } else { + this.list.sortKey = prop; + this.list.sortOrder = dir; + } + }); } protected subscribeToPage() { diff --git a/npm/ng-packs/packages/theme-shared/src/lib/tokens/ngx-datatable-messages.token.ts b/npm/ng-packs/packages/theme-shared/src/lib/tokens/ngx-datatable-messages.token.ts index bf1a73ab09..07b4157a37 100644 --- a/npm/ng-packs/packages/theme-shared/src/lib/tokens/ngx-datatable-messages.token.ts +++ b/npm/ng-packs/packages/theme-shared/src/lib/tokens/ngx-datatable-messages.token.ts @@ -2,12 +2,14 @@ import { InjectionToken } from '@angular/core'; export interface NgxDatatableMessages { emptyMessage: string; + errorMessage: string; totalMessage: string; selectedMessage: string; } export const defaultNgxDatatableMessages = { emptyMessage: 'AbpUi::NoDataAvailableInDatatable', + errorMessage: 'AbpUi::ErrorLoadingDatatable', totalMessage: 'AbpUi::Total', selectedMessage: 'AbpUi::Selected', }; diff --git a/templates/app/angular/src/app/home/home.component.html b/templates/app/angular/src/app/home/home.component.html index c4149e6905..c80dd1724e 100644 --- a/templates/app/angular/src/app/home/home.component.html +++ b/templates/app/angular/src/app/home/home.component.html @@ -1,120 +1,309 @@ -
-

Let's improve your application!

-

Here are some links to help you get started:

-
-
-
-
- +
+
+
+
+
+ @if(!hasLoggedIn){ +

Welcome

+

+ {{ '::LongWelcomeMessage' | abpLocalization }} +

+ {{ 'AbpAccount::Login' | abpLocalization }} + } - + " + > - + +

Customize Lepton Theme

+

Learn how to customize LeptonX Theme as you wish.

+ Customize Lepton +
+ + +
+
+
+
+
+ + +
+
+
+
+
+ +

+ A unique community platform for + ABP Lovers! +

+

+ Explore all ABP users' experiences with the ABP Framework, discover articles and videos on + how to use ABP, and join raffles for a chance to win surprise gifts! +

+ Join ABP Community +
+ +
+
+
+
+ +
+
+
+
+
+

THE OFFICIAL GUIDE

+

Mastering ABP Framework

+

+ Written by the creator of the ABP Framework, this book will help you gain a complete + understanding of the framework and modern web application development techniques. +

+ +
+
+ +
+
+
+
+
+ + ] + } + } + " + > +
+ + +

+ {{ context.label }} +
+ + +
+
+ +
+
+
+ + +
+
+
+
{{ context.title }}
-
- +
+ + + @for(item of context.items; track $index; let last = $last){ + + + + } - } - " - > - - -

- - - - -

-
+ +
+ @if(item.icon){ +
+ @if(item.iconType === 'image'){ + + }@else if(item.iconType === 'icon'){ + + }@else{ +
+ } +
} - ] +
{{ item.title }}
+
+ + + +
+
+