diff --git a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.de.resx b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.de.resx index 202abded..12366fca 100644 --- a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.de.resx +++ b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.de.resx @@ -248,6 +248,30 @@ Flag Call Note + + Anrufbild markieren + + + Anrufdatei markieren + + + Bild hinzugefügt von + + + Bildzeitstempel + + + Datei hinzugefügt von + + + Dateizeitstempel + + + Bild markieren + + + Datei markieren + Flagged Reason diff --git a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.en.resx b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.en.resx index a641af4c..30e59a0b 100644 --- a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.en.resx +++ b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.en.resx @@ -297,6 +297,30 @@ Flag Call Note + + Flag Call Image + + + Flag Call File + + + Image Added By + + + Image Timestamp + + + File Added By + + + File Timestamp + + + Flag Image + + + Flag File + Flagged Reason @@ -483,4 +507,4 @@ This is a what3words address. - \ No newline at end of file + diff --git a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.es.resx b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.es.resx index 2207305c..7b2db68b 100644 --- a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.es.resx +++ b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.es.resx @@ -297,6 +297,30 @@ Marcar nota de llamada + + Marcar imagen del incidente + + + Marcar archivo del incidente + + + Imagen añadida por + + + Marca de tiempo de imagen + + + Archivo añadido por + + + Marca de tiempo de archivo + + + Marcar imagen + + + Marcar archivo + Motivo marcado @@ -483,4 +507,4 @@ Esta es una dirección de what3words. - \ No newline at end of file + diff --git a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.fr.resx b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.fr.resx index b9dc96ed..aa590699 100644 --- a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.fr.resx +++ b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.fr.resx @@ -248,6 +248,30 @@ Flag Call Note + + Signaler l'image de l'appel + + + Signaler le fichier de l'appel + + + Image ajoutée par + + + Horodatage de l'image + + + Fichier ajouté par + + + Horodatage du fichier + + + Signaler l'image + + + Signaler le fichier + Flagged Reason diff --git a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.it.resx b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.it.resx index 5b65dc1b..a990af88 100644 --- a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.it.resx +++ b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.it.resx @@ -248,6 +248,30 @@ Flag Call Note + + Segnala immagine chiamata + + + Segnala file chiamata + + + Immagine aggiunta da + + + Timestamp immagine + + + File aggiunto da + + + Timestamp file + + + Segnala immagine + + + Segnala file + Flagged Reason diff --git a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.pl.resx b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.pl.resx index 2ec64bcf..03880aa1 100644 --- a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.pl.resx +++ b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.pl.resx @@ -248,6 +248,30 @@ Flag Call Note + + Oznacz obraz zgłoszenia + + + Oznacz plik zgłoszenia + + + Obraz dodany przez + + + Znacznik czasu obrazu + + + Plik dodany przez + + + Znacznik czasu pliku + + + Oznacz obraz + + + Oznacz plik + Flagged Reason diff --git a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.sv.resx b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.sv.resx index d0906da3..abc0b7e9 100644 --- a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.sv.resx +++ b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.sv.resx @@ -248,6 +248,30 @@ Flag Call Note + + Flagga samtalsbild + + + Flagga samtalsfil + + + Bild tillagd av + + + Bildtidsstämpel + + + Fil tillagd av + + + Filtidsstämpel + + + Flagga bild + + + Flagga fil + Flagged Reason diff --git a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.uk.resx b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.uk.resx index aa69686a..e1e4dbce 100644 --- a/Core/Resgrid.Localization/Areas/User/Dispatch/Call.uk.resx +++ b/Core/Resgrid.Localization/Areas/User/Dispatch/Call.uk.resx @@ -248,6 +248,30 @@ Flag Call Note + + Позначити зображення виклику + + + Позначити файл виклику + + + Зображення додав + + + Мітка часу зображення + + + Файл додав + + + Мітка часу файлу + + + Позначити зображення + + + Позначити файл + Flagged Reason diff --git a/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.cs b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.cs new file mode 100644 index 00000000..52ebe994 --- /dev/null +++ b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.cs @@ -0,0 +1,11 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Resgrid.Localization.Areas.User.Reports +{ + public class FlaggedReport + { + } +} + diff --git a/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.de.resx b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.de.resx new file mode 100644 index 00000000..6c487a1c --- /dev/null +++ b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.de.resx @@ -0,0 +1,108 @@ + + + text/microsoft-resx + 2.0 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Bericht über markierte Anrufnotizen, Bilder und Dateien + + + Dieser Bericht zeigt alle markierten Anrufnotizen, Bilder und Dateien der Abteilung, einschließlich der zugehörigen Anrufinformationen, Inhalte, Dateinamen, Markierungsdetails und des Grundes für die Markierung. + + + Berichtsstartdatum + + + Berichtsenddatum + + + Bericht ausführen + + + Datumsfilter angewendet + + + Markierte Notizen + + + Markierte Bilder + + + Markierte Dateien + + + markiert + + + Keine markierten Anrufnotizen für diese Abteilung gefunden. + + + Keine markierten Anrufbilder für diese Abteilung gefunden. + + + Keine markierten Anrufdateien für diese Abteilung gefunden. + + + Anruf-Nr. + + + Anrufname + + + Typ + + + Adresse + + + Anruf protokolliert am + + + Notiz + + + Notiz von + + + Notiz-Zeitstempel + + + Markierungsinfo + + + Dateiname + + + Bild von + + + Bild-Zeitstempel + + + Dateityp + + + Datei von + + + Datei-Zeitstempel + + + Markiert von + + + Markiert am + + + Grund + + + Datumsbereich + + + Bericht erstellt + + + + diff --git a/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.en.resx b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.en.resx new file mode 100644 index 00000000..48a3db2f --- /dev/null +++ b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.en.resx @@ -0,0 +1,162 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + Flagged Call Notes, Images & Files Report + + + This report shows all flagged call notes, flagged call images, and flagged call files for the department, including the associated call information, content or file name, flag details, and the reason each item was flagged. + + + Report Start Date + + + Report End Date + + + Run Report + + + Date Filter Applied + + + Flagged Notes + + + Flagged Images + + + Flagged Files + + + flagged + + + No flagged call notes were found for this department. + + + No flagged call images were found for this department. + + + No flagged call files were found for this department. + + + Call # + + + Call Name + + + Type + + + Address + + + Call Logged On + + + Note + + + Note By + + + Note Timestamp + + + Flag Info + + + File Name + + + Image By + + + Image Timestamp + + + File Type + + + File By + + + File Timestamp + + + Flagged By + + + Flagged On + + + Reason + + + Date range + + + Report generated + + + + diff --git a/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.es.resx b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.es.resx new file mode 100644 index 00000000..40d994c1 --- /dev/null +++ b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.es.resx @@ -0,0 +1,108 @@ + + + text/microsoft-resx + 2.0 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Informe de notas, imágenes y archivos de llamadas marcadas + + + Este informe muestra todas las notas de llamada, imágenes y archivos marcados del departamento, incluida la información de llamada asociada, el contenido o nombre de archivo, los detalles de la marca y el motivo por el que se marcó cada elemento. + + + Fecha de inicio del informe + + + Fecha de fin del informe + + + Ejecutar informe + + + Filtro de fecha aplicado + + + Notas marcadas + + + Imágenes marcadas + + + Archivos marcados + + + marcado(s) + + + No se encontraron notas de llamada marcadas para este departamento. + + + No se encontraron imágenes de llamada marcadas para este departamento. + + + No se encontraron archivos de llamada marcados para este departamento. + + + Llamada # + + + Nombre de llamada + + + Tipo + + + Dirección + + + Llamada registrada el + + + Nota + + + Nota de + + + Marca de tiempo de nota + + + Info de marca + + + Nombre de archivo + + + Imagen de + + + Marca de tiempo de imagen + + + Tipo de archivo + + + Archivo de + + + Marca de tiempo de archivo + + + Marcado por + + + Marcado el + + + Motivo + + + Rango de fechas + + + Informe generado + + + + diff --git a/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.fr.resx b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.fr.resx new file mode 100644 index 00000000..01ded64c --- /dev/null +++ b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.fr.resx @@ -0,0 +1,108 @@ + + + text/microsoft-resx + 2.0 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Rapport des notes, images et fichiers d'appel signalés + + + Ce rapport affiche toutes les notes d'appel, images et fichiers signalés du département, y compris les informations d'appel associées, le contenu ou le nom du fichier, les détails du signalement et la raison pour laquelle chaque élément a été signalé. + + + Date de début du rapport + + + Date de fin du rapport + + + Exécuter le rapport + + + Filtre de date appliqué + + + Notes signalées + + + Images signalées + + + Fichiers signalés + + + signalé(s) + + + Aucune note d'appel signalée trouvée pour ce département. + + + Aucune image d'appel signalée trouvée pour ce département. + + + Aucun fichier d'appel signalé trouvé pour ce département. + + + Appel n° + + + Nom de l'appel + + + Type + + + Adresse + + + Appel enregistré le + + + Note + + + Note de + + + Horodatage de la note + + + Info signalement + + + Nom de fichier + + + Image de + + + Horodatage de l'image + + + Type de fichier + + + Fichier de + + + Horodatage du fichier + + + Signalé par + + + Signalé le + + + Raison + + + Plage de dates + + + Rapport généré + + + + diff --git a/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.it.resx b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.it.resx new file mode 100644 index 00000000..e6edcea1 --- /dev/null +++ b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.it.resx @@ -0,0 +1,108 @@ + + + text/microsoft-resx + 2.0 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Rapporto di note, immagini e file di chiamata segnalati + + + Questo rapporto mostra tutte le note di chiamata, le immagini e i file segnalati del dipartimento, incluse le informazioni sulla chiamata associata, il contenuto o il nome del file, i dettagli della segnalazione e il motivo per cui ogni elemento è stato segnalato. + + + Data inizio rapporto + + + Data fine rapporto + + + Esegui rapporto + + + Filtro data applicato + + + Note segnalate + + + Immagini segnalate + + + File segnalati + + + segnalato/i + + + Nessuna nota di chiamata segnalata trovata per questo dipartimento. + + + Nessuna immagine di chiamata segnalata trovata per questo dipartimento. + + + Nessun file di chiamata segnalato trovato per questo dipartimento. + + + Chiamata # + + + Nome chiamata + + + Tipo + + + Indirizzo + + + Chiamata registrata il + + + Nota + + + Nota di + + + Timestamp nota + + + Info segnalazione + + + Nome file + + + Immagine di + + + Timestamp immagine + + + Tipo file + + + File di + + + Timestamp file + + + Segnalato da + + + Segnalato il + + + Motivo + + + Intervallo date + + + Rapporto generato + + + + diff --git a/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.pl.resx b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.pl.resx new file mode 100644 index 00000000..4c959a63 --- /dev/null +++ b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.pl.resx @@ -0,0 +1,108 @@ + + + text/microsoft-resx + 2.0 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Raport oznaczonych notatek, obrazów i plików zgłoszeń + + + Raport pokazuje wszystkie oznaczone notatki, obrazy i pliki zgłoszeń w dziale, w tym powiązane informacje o zgłoszeniu, treść lub nazwę pliku, szczegóły oznaczenia oraz powód oznaczenia każdego elementu. + + + Data rozpoczęcia raportu + + + Data zakończenia raportu + + + Uruchom raport + + + Zastosowano filtr dat + + + Oznaczone notatki + + + Oznaczone obrazy + + + Oznaczone pliki + + + oznaczono + + + Nie znaleziono oznaczonych notatek zgłoszeń dla tego działu. + + + Nie znaleziono oznaczonych obrazów zgłoszeń dla tego działu. + + + Nie znaleziono oznaczonych plików zgłoszeń dla tego działu. + + + Zgłoszenie # + + + Nazwa zgłoszenia + + + Typ + + + Adres + + + Zgłoszenie zarejestrowane + + + Notatka + + + Notatka od + + + Znacznik czasu notatki + + + Info oznaczenia + + + Nazwa pliku + + + Obraz od + + + Znacznik czasu obrazu + + + Typ pliku + + + Plik od + + + Znacznik czasu pliku + + + Oznaczono przez + + + Oznaczono dnia + + + Powód + + + Zakres dat + + + Raport wygenerowany + + + + diff --git a/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.sv.resx b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.sv.resx new file mode 100644 index 00000000..196df2ad --- /dev/null +++ b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.sv.resx @@ -0,0 +1,108 @@ + + + text/microsoft-resx + 2.0 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Rapport över flaggade samtalnoteringar, bilder och filer + + + Den här rapporten visar alla flaggade samtalsnoteringar, bilder och filer för avdelningen, inklusive tillhörande samtalsinformation, innehåll eller filnamn, flaggningsdetaljer och anledningen till att varje objekt flaggades. + + + Rapportens startdatum + + + Rapportens slutdatum + + + Kör rapport + + + Datumfilter tillämpat + + + Flaggade noteringar + + + Flaggade bilder + + + Flaggade filer + + + flaggad(e) + + + Inga flaggade samtalsnoteringar hittades för denna avdelning. + + + Inga flaggade samtalsbilder hittades för denna avdelning. + + + Inga flaggade samtalsfiler hittades för denna avdelning. + + + Samtal # + + + Samtalsnamn + + + Typ + + + Adress + + + Samtal loggat + + + Notering + + + Notering av + + + Noteringens tidsstämpel + + + Flagginfo + + + Filnamn + + + Bild av + + + Bildens tidsstämpel + + + Filtyp + + + Fil av + + + Filens tidsstämpel + + + Flaggad av + + + Flaggad den + + + Anledning + + + Datumintervall + + + Rapport genererad + + + + diff --git a/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.uk.resx b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.uk.resx new file mode 100644 index 00000000..bd03d9d2 --- /dev/null +++ b/Core/Resgrid.Localization/Areas/User/Reports/FlaggedReport.uk.resx @@ -0,0 +1,108 @@ + + + text/microsoft-resx + 2.0 + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Звіт про позначені нотатки, зображення та файли викликів + + + Цей звіт показує всі позначені нотатки, зображення та файли викликів підрозділу, включаючи пов'язану інформацію про виклик, вміст або ім'я файлу, деталі позначки та причину позначення кожного елемента. + + + Дата початку звіту + + + Дата завершення звіту + + + Запустити звіт + + + Застосовано фільтр дати + + + Позначені нотатки + + + Позначені зображення + + + Позначені файли + + + позначено + + + Не знайдено позначених нотаток викликів для цього підрозділу. + + + Не знайдено позначених зображень викликів для цього підрозділу. + + + Не знайдено позначених файлів викликів для цього підрозділу. + + + Виклик # + + + Назва виклику + + + Тип + + + Адреса + + + Виклик зареєстровано + + + Нотатка + + + Нотатка від + + + Мітка часу нотатки + + + Інфо позначки + + + Ім'я файлу + + + Зображення від + + + Мітка часу зображення + + + Тип файлу + + + Файл від + + + Мітка часу файлу + + + Позначено ким + + + Позначено коли + + + Причина + + + Діапазон дат + + + Звіт сформовано + + + + diff --git a/Core/Resgrid.Model/Repositories/ICallAttachmentRepository.cs b/Core/Resgrid.Model/Repositories/ICallAttachmentRepository.cs index df2e86ea..a293aa8b 100644 --- a/Core/Resgrid.Model/Repositories/ICallAttachmentRepository.cs +++ b/Core/Resgrid.Model/Repositories/ICallAttachmentRepository.cs @@ -24,5 +24,19 @@ public interface ICallAttachmentRepository: IRepository /// The call identifier. /// Task<IEnumerable<CallAttachment>>. Task> GetCallDispatchesByCallIdAsync(int callId); + + /// + /// Gets all flagged call images for a department asynchronous. + /// + /// The department identifier. + /// Task<IEnumerable<CallAttachment>>. + Task> GetFlaggedCallImagesByDepartmentIdAsync(int departmentId); + + /// + /// Gets all flagged call files (audio, files, video) for a department asynchronous. + /// + /// The department identifier. + /// Task<IEnumerable<CallAttachment>>. + Task> GetFlaggedCallFilesByDepartmentIdAsync(int departmentId); } } diff --git a/Core/Resgrid.Model/Repositories/ICallNotesRepository.cs b/Core/Resgrid.Model/Repositories/ICallNotesRepository.cs index 583da47e..024cf5f0 100644 --- a/Core/Resgrid.Model/Repositories/ICallNotesRepository.cs +++ b/Core/Resgrid.Model/Repositories/ICallNotesRepository.cs @@ -16,5 +16,12 @@ public interface ICallNotesRepository: IRepository /// The call identifier. /// Task<IEnumerable<CallNote>>. Task> GetCallNotesByCallIdAsync(int callId); + + /// + /// Gets all flagged call notes for a department asynchronous. + /// + /// The department identifier. + /// Task<IEnumerable<CallNote>>. + Task> GetFlaggedCallNotesByDepartmentIdAsync(int departmentId); } } diff --git a/Core/Resgrid.Model/Services/ICallsService.cs b/Core/Resgrid.Model/Services/ICallsService.cs index 249b27b0..b47154b2 100644 --- a/Core/Resgrid.Model/Services/ICallsService.cs +++ b/Core/Resgrid.Model/Services/ICallsService.cs @@ -218,6 +218,27 @@ Task GenerateCallFromEmail(int type, CallEmail email, string managingUser, /// Task<CallNote>. Task SaveCallNoteAsync(CallNote note, CancellationToken cancellationToken = default(CancellationToken)); + /// + /// Gets all flagged call notes for a department asynchronous. + /// + /// The department identifier. + /// Task<List<CallNote>>. + Task> GetFlaggedCallNotesByDepartmentIdAsync(int departmentId); + + /// + /// Gets all flagged call images for a department asynchronous. + /// + /// The department identifier. + /// Task<List<CallAttachment>>. + Task> GetFlaggedCallImagesByDepartmentIdAsync(int departmentId); + + /// + /// Gets all flagged call files (audio, files, video) for a department asynchronous. + /// + /// The department identifier. + /// Task<List<CallAttachment>>. + Task> GetFlaggedCallFilesByDepartmentIdAsync(int departmentId); + /// /// Gets the call attachment asynchronous. /// diff --git a/Core/Resgrid.Services/CallsService.cs b/Core/Resgrid.Services/CallsService.cs index bf4d7b17..6f4a0fa5 100644 --- a/Core/Resgrid.Services/CallsService.cs +++ b/Core/Resgrid.Services/CallsService.cs @@ -368,6 +368,36 @@ public async Task GenerateCallFromEmail(int type, CallEmail email, string return await _callNotesRepository.SaveOrUpdateAsync(note, cancellationToken); } + public async Task> GetFlaggedCallNotesByDepartmentIdAsync(int departmentId) + { + var notes = await _callNotesRepository.GetFlaggedCallNotesByDepartmentIdAsync(departmentId); + + if (notes != null && notes.Any()) + return notes.ToList(); + + return new List(); + } + + public async Task> GetFlaggedCallImagesByDepartmentIdAsync(int departmentId) + { + var images = await _callAttachmentRepository.GetFlaggedCallImagesByDepartmentIdAsync(departmentId); + + if (images != null && images.Any()) + return images.ToList(); + + return new List(); + } + + public async Task> GetFlaggedCallFilesByDepartmentIdAsync(int departmentId) + { + var files = await _callAttachmentRepository.GetFlaggedCallFilesByDepartmentIdAsync(departmentId); + + if (files != null && files.Any()) + return files.ToList(); + + return new List(); + } + public async Task GetCallAttachmentAsync(int callAttachmentId) { var attachment = await _callAttachmentRepository.GetByIdAsync(callAttachmentId); diff --git a/Repositories/Resgrid.Repositories.DataRepository/CallAttachmentRepository.cs b/Repositories/Resgrid.Repositories.DataRepository/CallAttachmentRepository.cs index 38cea416..8f0f5623 100644 --- a/Repositories/Resgrid.Repositories.DataRepository/CallAttachmentRepository.cs +++ b/Repositories/Resgrid.Repositories.DataRepository/CallAttachmentRepository.cs @@ -111,5 +111,87 @@ public async Task> GetCallDispatchesByCallIdAsync(in throw; } } + + public async Task> GetFlaggedCallImagesByDepartmentIdAsync(int departmentId) + { + try + { + var selectFunction = new Func>>(async x => + { + var dynamicParameters = new DynamicParametersExtension(); + dynamicParameters.Add("DepartmentId", departmentId); + + var query = _queryFactory.GetQuery(); + + return await x.QueryAsync(sql: query, + param: dynamicParameters, + transaction: _unitOfWork.Transaction); + }); + + DbConnection conn = null; + if (_unitOfWork?.Connection == null) + { + using (conn = _connectionProvider.Create()) + { + await conn.OpenAsync(); + + return await selectFunction(conn); + } + } + else + { + conn = _unitOfWork.CreateOrGetConnection(); + + return await selectFunction(conn); + } + } + catch (Exception ex) + { + Logging.LogException(ex); + + throw; + } + } + + public async Task> GetFlaggedCallFilesByDepartmentIdAsync(int departmentId) + { + try + { + var selectFunction = new Func>>(async x => + { + var dynamicParameters = new DynamicParametersExtension(); + dynamicParameters.Add("DepartmentId", departmentId); + + var query = _queryFactory.GetQuery(); + + return await x.QueryAsync(sql: query, + param: dynamicParameters, + transaction: _unitOfWork.Transaction); + }); + + DbConnection conn = null; + if (_unitOfWork?.Connection == null) + { + using (conn = _connectionProvider.Create()) + { + await conn.OpenAsync(); + + return await selectFunction(conn); + } + } + else + { + conn = _unitOfWork.CreateOrGetConnection(); + + return await selectFunction(conn); + } + } + catch (Exception ex) + { + Logging.LogException(ex); + + throw; + } + } } } diff --git a/Repositories/Resgrid.Repositories.DataRepository/CallNotesRepository.cs b/Repositories/Resgrid.Repositories.DataRepository/CallNotesRepository.cs index a75b1c0d..e2af3b0c 100644 --- a/Repositories/Resgrid.Repositories.DataRepository/CallNotesRepository.cs +++ b/Repositories/Resgrid.Repositories.DataRepository/CallNotesRepository.cs @@ -51,21 +51,56 @@ public async Task> GetCallNotesByCallIdAsync(int callId) using (conn = _connectionProvider.Create()) { await conn.OpenAsync(); - return await selectFunction(conn); } } else { conn = _unitOfWork.CreateOrGetConnection(); - return await selectFunction(conn); } } catch (Exception ex) { Logging.LogException(ex); + throw; + } + } + + public async Task> GetFlaggedCallNotesByDepartmentIdAsync(int departmentId) + { + try + { + var selectFunction = new Func>>(async x => + { + var dynamicParameters = new DynamicParametersExtension(); + dynamicParameters.Add("DepartmentId", departmentId); + + var query = _queryFactory.GetQuery(); + + return await x.QueryAsync(sql: query, + param: dynamicParameters, + transaction: _unitOfWork.Transaction); + }); + DbConnection conn = null; + if (_unitOfWork?.Connection == null) + { + using (conn = _connectionProvider.Create()) + { + await conn.OpenAsync(); + return await selectFunction(conn); + } + } + else + { + conn = _unitOfWork.CreateOrGetConnection(); + return await selectFunction(conn); + } + } + catch (Exception ex) + { + Logging.LogException(ex); throw; } } diff --git a/Repositories/Resgrid.Repositories.DataRepository/Configs/SqlConfiguration.cs b/Repositories/Resgrid.Repositories.DataRepository/Configs/SqlConfiguration.cs index a8ba1d6e..5052655c 100644 --- a/Repositories/Resgrid.Repositories.DataRepository/Configs/SqlConfiguration.cs +++ b/Repositories/Resgrid.Repositories.DataRepository/Configs/SqlConfiguration.cs @@ -327,6 +327,9 @@ protected SqlConfiguration() { } public string SelectNonDispatchedScheduledCallsByDateQuery { get; set; } public string SelectNonDispatchedScheduledCallsByDidQuery { get; set; } public string SelectCallsByContactQuery { get; set; } + public string SelectFlaggedCallNotesByDepartmentIdQuery { get; set; } + public string SelectFlaggedCallImagesByDepartmentIdQuery { get; set; } + public string SelectFlaggedCallFilesByDepartmentIdQuery { get; set; } #endregion Calls #region Dispatch Protocols diff --git a/Repositories/Resgrid.Repositories.DataRepository/Queries/Calls/SelectFlaggedCallFilesByDepartmentIdQuery.cs b/Repositories/Resgrid.Repositories.DataRepository/Queries/Calls/SelectFlaggedCallFilesByDepartmentIdQuery.cs new file mode 100644 index 00000000..f62fb857 --- /dev/null +++ b/Repositories/Resgrid.Repositories.DataRepository/Queries/Calls/SelectFlaggedCallFilesByDepartmentIdQuery.cs @@ -0,0 +1,41 @@ +using Resgrid.Model; +using Resgrid.Model.Repositories.Queries.Contracts; +using Resgrid.Repositories.DataRepository.Configs; +using Resgrid.Repositories.DataRepository.Extensions; + +namespace Resgrid.Repositories.DataRepository.Queries.Calls +{ + public class SelectFlaggedCallFilesByDepartmentIdQuery : ISelectQuery + { + private readonly SqlConfiguration _sqlConfiguration; + + public SelectFlaggedCallFilesByDepartmentIdQuery(SqlConfiguration sqlConfiguration) + { + _sqlConfiguration = sqlConfiguration; + } + + public string GetQuery() + { + var query = _sqlConfiguration.SelectFlaggedCallFilesByDepartmentIdQuery + .ReplaceQueryParameters(_sqlConfiguration, _sqlConfiguration.SchemaName, + string.Empty, + _sqlConfiguration.ParameterNotation, + new string[] { "%DID%" }, + new string[] { "DepartmentId" }, + new string[] { "%CALLATTACHMENTSTABLE%", "%CALLSTABLE%" }, + new string[] + { + _sqlConfiguration.CallAttachmentsTable, + _sqlConfiguration.CallsTable + }); + + return query; + } + + public string GetQuery() where TEntity : class, IEntity + { + throw new System.NotImplementedException(); + } + } +} + diff --git a/Repositories/Resgrid.Repositories.DataRepository/Queries/Calls/SelectFlaggedCallImagesByDepartmentIdQuery.cs b/Repositories/Resgrid.Repositories.DataRepository/Queries/Calls/SelectFlaggedCallImagesByDepartmentIdQuery.cs new file mode 100644 index 00000000..ca7f8456 --- /dev/null +++ b/Repositories/Resgrid.Repositories.DataRepository/Queries/Calls/SelectFlaggedCallImagesByDepartmentIdQuery.cs @@ -0,0 +1,41 @@ +using Resgrid.Model; +using Resgrid.Model.Repositories.Queries.Contracts; +using Resgrid.Repositories.DataRepository.Configs; +using Resgrid.Repositories.DataRepository.Extensions; + +namespace Resgrid.Repositories.DataRepository.Queries.Calls +{ + public class SelectFlaggedCallImagesByDepartmentIdQuery : ISelectQuery + { + private readonly SqlConfiguration _sqlConfiguration; + + public SelectFlaggedCallImagesByDepartmentIdQuery(SqlConfiguration sqlConfiguration) + { + _sqlConfiguration = sqlConfiguration; + } + + public string GetQuery() + { + var query = _sqlConfiguration.SelectFlaggedCallImagesByDepartmentIdQuery + .ReplaceQueryParameters(_sqlConfiguration, _sqlConfiguration.SchemaName, + string.Empty, + _sqlConfiguration.ParameterNotation, + new string[] { "%DID%" }, + new string[] { "DepartmentId" }, + new string[] { "%CALLATTACHMENTSTABLE%", "%CALLSTABLE%" }, + new string[] + { + _sqlConfiguration.CallAttachmentsTable, + _sqlConfiguration.CallsTable + }); + + return query; + } + + public string GetQuery() where TEntity : class, IEntity + { + throw new System.NotImplementedException(); + } + } +} + diff --git a/Repositories/Resgrid.Repositories.DataRepository/Queries/Calls/SelectFlaggedCallNotesByDepartmentIdQuery.cs b/Repositories/Resgrid.Repositories.DataRepository/Queries/Calls/SelectFlaggedCallNotesByDepartmentIdQuery.cs new file mode 100644 index 00000000..7fc71f08 --- /dev/null +++ b/Repositories/Resgrid.Repositories.DataRepository/Queries/Calls/SelectFlaggedCallNotesByDepartmentIdQuery.cs @@ -0,0 +1,41 @@ +using Resgrid.Model; +using Resgrid.Model.Repositories.Queries.Contracts; +using Resgrid.Repositories.DataRepository.Configs; +using Resgrid.Repositories.DataRepository.Extensions; + +namespace Resgrid.Repositories.DataRepository.Queries.Calls +{ + public class SelectFlaggedCallNotesByDepartmentIdQuery : ISelectQuery + { + private readonly SqlConfiguration _sqlConfiguration; + + public SelectFlaggedCallNotesByDepartmentIdQuery(SqlConfiguration sqlConfiguration) + { + _sqlConfiguration = sqlConfiguration; + } + + public string GetQuery() + { + var query = _sqlConfiguration.SelectFlaggedCallNotesByDepartmentIdQuery + .ReplaceQueryParameters(_sqlConfiguration, _sqlConfiguration.SchemaName, + string.Empty, + _sqlConfiguration.ParameterNotation, + new string[] { "%DID%" }, + new string[] { "DepartmentId" }, + new string[] { "%CALLNOTESTABLE%", "%CALLSTABLE%" }, + new string[] + { + _sqlConfiguration.CallNotesTable, + _sqlConfiguration.CallsTable + }); + + return query; + } + + public string GetQuery() where TEntity : class, IEntity + { + throw new System.NotImplementedException(); + } + } +} + diff --git a/Repositories/Resgrid.Repositories.DataRepository/Servers/PostgreSql/PostgreSqlConfiguration.cs b/Repositories/Resgrid.Repositories.DataRepository/Servers/PostgreSql/PostgreSqlConfiguration.cs index 5fc7ffbd..2eeaa7af 100644 --- a/Repositories/Resgrid.Repositories.DataRepository/Servers/PostgreSql/PostgreSqlConfiguration.cs +++ b/Repositories/Resgrid.Repositories.DataRepository/Servers/PostgreSql/PostgreSqlConfiguration.cs @@ -1136,6 +1136,24 @@ group by 1 FROM %SCHEMA%.%CALLSTABLE% INNER JOIN %SCHEMA%.%CALLCONTACTSTABLE% ON %SCHEMA%.%CALLCONTACTSTABLE%.CallId = %SCHEMA%.%CALLSTABLE%.CallId WHERE %SCHEMA%.%CALLCONTACTSTABLE%.ContactId = %CONTACTID% AND %SCHEMA%.%CALLSTABLE%.IsDeleted = false AND %SCHEMA%.%CALLSTABLE%.DepartmentId = %DID%"; + SelectFlaggedCallNotesByDepartmentIdQuery = @" + SELECT cn.* + FROM %SCHEMA%.%CALLNOTESTABLE% cn + INNER JOIN %SCHEMA%.%CALLSTABLE% c ON c.CallId = cn.CallId + WHERE cn.IsFlagged = true AND c.DepartmentId = %DID% + ORDER BY cn.FlaggedOn DESC"; + SelectFlaggedCallImagesByDepartmentIdQuery = @" + SELECT ca.* + FROM %SCHEMA%.%CALLATTACHMENTSTABLE% ca + INNER JOIN %SCHEMA%.%CALLSTABLE% c ON c.CallId = ca.CallId + WHERE ca.IsFlagged = true AND ca.CallAttachmentType = 2 AND c.DepartmentId = %DID% + ORDER BY ca.FlaggedOn DESC"; + SelectFlaggedCallFilesByDepartmentIdQuery = @" + SELECT ca.* + FROM %SCHEMA%.%CALLATTACHMENTSTABLE% ca + INNER JOIN %SCHEMA%.%CALLSTABLE% c ON c.CallId = ca.CallId + WHERE ca.IsFlagged = true AND ca.CallAttachmentType IN (1, 3, 4) AND c.DepartmentId = %DID% + ORDER BY ca.FlaggedOn DESC"; #endregion Calls #region Department Groups diff --git a/Repositories/Resgrid.Repositories.DataRepository/Servers/SqlServer/SqlServerConfiguration.cs b/Repositories/Resgrid.Repositories.DataRepository/Servers/SqlServer/SqlServerConfiguration.cs index 9724bc25..64393956 100644 --- a/Repositories/Resgrid.Repositories.DataRepository/Servers/SqlServer/SqlServerConfiguration.cs +++ b/Repositories/Resgrid.Repositories.DataRepository/Servers/SqlServer/SqlServerConfiguration.cs @@ -1099,6 +1099,24 @@ SELECT c.* FROM %SCHEMA%.%CALLSTABLE% c INNER JOIN %SCHEMA%.%CALLCONTACTSTABLE% cc ON cc.CallId = c.CallId WHERE cc.ContactId = %CONTACTID% AND c.IsDeleted = 0 AND c.DepartmentId = %DID%"; + SelectFlaggedCallNotesByDepartmentIdQuery = @" + SELECT cn.* + FROM %SCHEMA%.%CALLNOTESTABLE% cn + INNER JOIN %SCHEMA%.%CALLSTABLE% c ON c.[CallId] = cn.[CallId] + WHERE cn.[IsFlagged] = 1 AND c.[DepartmentId] = %DID% + ORDER BY cn.[FlaggedOn] DESC"; + SelectFlaggedCallImagesByDepartmentIdQuery = @" + SELECT ca.* + FROM %SCHEMA%.%CALLATTACHMENTSTABLE% ca + INNER JOIN %SCHEMA%.%CALLSTABLE% c ON c.[CallId] = ca.[CallId] + WHERE ca.[IsFlagged] = 1 AND ca.[CallAttachmentType] = 2 AND c.[DepartmentId] = %DID% + ORDER BY ca.[FlaggedOn] DESC"; + SelectFlaggedCallFilesByDepartmentIdQuery = @" + SELECT ca.* + FROM %SCHEMA%.%CALLATTACHMENTSTABLE% ca + INNER JOIN %SCHEMA%.%CALLSTABLE% c ON c.[CallId] = ca.[CallId] + WHERE ca.[IsFlagged] = 1 AND ca.[CallAttachmentType] IN (1, 3, 4) AND c.[DepartmentId] = %DID% + ORDER BY ca.[FlaggedOn] DESC"; #endregion Calls diff --git a/Web/Resgrid.Web/Areas/User/Controllers/DispatchController.cs b/Web/Resgrid.Web/Areas/User/Controllers/DispatchController.cs index 9d775ee7..186777f2 100644 --- a/Web/Resgrid.Web/Areas/User/Controllers/DispatchController.cs +++ b/Web/Resgrid.Web/Areas/User/Controllers/DispatchController.cs @@ -1324,11 +1324,13 @@ public async Task FlagCallNote(FlagCallNoteView model, Cancellati { note.FlaggedReason = model.FlagNote; note.FlaggedOn = DateTime.UtcNow; + note.FlaggedByUserId = UserId; } else { note.FlaggedReason = null; note.FlaggedOn = null; + note.FlaggedByUserId = null; } await _callsService.SaveCallNoteAsync(note, cancellationToken); @@ -1339,6 +1341,195 @@ public async Task FlagCallNote(FlagCallNoteView model, Cancellati return View(model); } + [HttpGet] + [Authorize(Policy = ResgridResources.Call_Update)] + public async Task FlagCallImage(int callId, int callAttachmentId) + { + if (!await _authorizationService.CanUserEditCallAsync(UserId, callId)) + return Unauthorized(); + + var call = await _callsService.GetCallByIdAsync(callId); + + if (call == null) + return Unauthorized(); + + call = await _callsService.PopulateCallData(call, false, true, false, false, false, false, false, false, false); + var department = await _departmentsService.GetDepartmentByIdAsync(call.DepartmentId); + + if (call.Attachments == null || !call.Attachments.Any()) + return Unauthorized(); + + var attachment = call.Attachments.FirstOrDefault(x => x.CallAttachmentId == callAttachmentId); + + if (attachment == null) + return Unauthorized(); + + var names = await _usersService.GetUserGroupAndRolesByDepartmentIdAsync(DepartmentId, false, false, false); + + var model = new FlagCallImageView(); + model.CallId = call.CallId; + model.CallAttachmentId = attachment.CallAttachmentId; + model.FileName = attachment.FileName; + model.IsFlagged = attachment.IsFlagged; + model.FlagNote = attachment.FlaggedReason; + model.AddedOn = attachment.Timestamp.HasValue + ? attachment.Timestamp.Value.FormatForDepartment(department) + : string.Empty; + model.AddedBy = names.FirstOrDefault(x => x.UserId == attachment.UserId)?.Name; + + if (attachment.IsFlagged) + { + model.FlaggedOn = attachment.FlaggedOn.HasValue + ? attachment.FlaggedOn.Value.FormatForDepartment(department) + : string.Empty; + model.FlaggedBy = names.FirstOrDefault(x => x.UserId == attachment.FlaggedByUserId)?.Name; + } + + return View(model); + } + + [HttpPost] + [Authorize(Policy = ResgridResources.Call_Update)] + public async Task FlagCallImage(FlagCallImageView model, CancellationToken cancellationToken) + { + if (!await _authorizationService.CanUserEditCallAsync(UserId, model.CallId)) + return Unauthorized(); + + var call = await _callsService.GetCallByIdAsync(model.CallId); + + if (call == null) + return Unauthorized(); + + call = await _callsService.PopulateCallData(call, false, true, false, false, false, false, false, false, false); + + if (call.Attachments == null || !call.Attachments.Any()) + return Unauthorized(); + + var attachment = call.Attachments.FirstOrDefault(x => x.CallAttachmentId == model.CallAttachmentId); + + if (attachment == null) + return Unauthorized(); + + if (ModelState.IsValid) + { + attachment.IsFlagged = model.IsFlagged; + + if (attachment.IsFlagged) + { + attachment.FlaggedReason = model.FlagNote; + attachment.FlaggedOn = DateTime.UtcNow; + attachment.FlaggedByUserId = UserId; + } + else + { + attachment.FlaggedReason = null; + attachment.FlaggedOn = null; + attachment.FlaggedByUserId = null; + } + + await _callsService.SaveCallAttachmentAsync(attachment, cancellationToken); + + return RedirectToAction("ViewCall", "Dispatch", new { Area = "User", callId = model.CallId }); + } + + return View(model); + } + + [HttpGet] + [Authorize(Policy = ResgridResources.Call_Update)] + public async Task FlagCallFile(int callId, int callAttachmentId) + { + if (!await _authorizationService.CanUserEditCallAsync(UserId, callId)) + return Unauthorized(); + + var call = await _callsService.GetCallByIdAsync(callId); + + if (call == null) + return Unauthorized(); + + call = await _callsService.PopulateCallData(call, false, true, false, false, false, false, false, false, false); + var department = await _departmentsService.GetDepartmentByIdAsync(call.DepartmentId); + + if (call.Attachments == null || !call.Attachments.Any()) + return Unauthorized(); + + var attachment = call.Attachments.FirstOrDefault(x => x.CallAttachmentId == callAttachmentId && (x.CallAttachmentType == 1 || x.CallAttachmentType == 3 || x.CallAttachmentType == 4)); + + if (attachment == null) + return Unauthorized(); + + var names = await _usersService.GetUserGroupAndRolesByDepartmentIdAsync(DepartmentId, false, false, false); + + var model = new FlagCallFileView(); + model.CallId = call.CallId; + model.CallAttachmentId = attachment.CallAttachmentId; + model.FileName = attachment.FileName; + model.FileType = attachment.CallAttachmentType; + model.IsFlagged = attachment.IsFlagged; + model.FlagNote = attachment.FlaggedReason; + model.AddedOn = attachment.Timestamp.HasValue + ? attachment.Timestamp.Value.FormatForDepartment(department) + : string.Empty; + model.AddedBy = names.FirstOrDefault(x => x.UserId == attachment.UserId)?.Name; + + if (attachment.IsFlagged) + { + model.FlaggedOn = attachment.FlaggedOn.HasValue + ? attachment.FlaggedOn.Value.FormatForDepartment(department) + : string.Empty; + model.FlaggedBy = names.FirstOrDefault(x => x.UserId == attachment.FlaggedByUserId)?.Name; + } + + return View(model); + } + + [HttpPost] + [Authorize(Policy = ResgridResources.Call_Update)] + public async Task FlagCallFile(FlagCallFileView model, CancellationToken cancellationToken) + { + if (!await _authorizationService.CanUserEditCallAsync(UserId, model.CallId)) + return Unauthorized(); + + var call = await _callsService.GetCallByIdAsync(model.CallId); + + if (call == null) + return Unauthorized(); + + call = await _callsService.PopulateCallData(call, false, true, false, false, false, false, false, false, false); + + if (call.Attachments == null || !call.Attachments.Any()) + return Unauthorized(); + + var attachment = call.Attachments.FirstOrDefault(x => x.CallAttachmentId == model.CallAttachmentId && (x.CallAttachmentType == 1 || x.CallAttachmentType == 3 || x.CallAttachmentType == 4)); + + if (attachment == null) + return Unauthorized(); + + if (ModelState.IsValid) + { + attachment.IsFlagged = model.IsFlagged; + + if (attachment.IsFlagged) + { + attachment.FlaggedReason = model.FlagNote; + attachment.FlaggedOn = DateTime.UtcNow; + attachment.FlaggedByUserId = UserId; + } + else + { + attachment.FlaggedReason = null; + attachment.FlaggedOn = null; + attachment.FlaggedByUserId = null; + } + + await _callsService.SaveCallAttachmentAsync(attachment, cancellationToken); + + return RedirectToAction("ViewCall", "Dispatch", new { Area = "User", callId = model.CallId }); + } + + return View(model); + } + [HttpPost] [Authorize(Policy = ResgridResources.Call_View)] public async Task AddCallNote([FromBody] AddCallNoteInput model, CancellationToken cancellationToken) diff --git a/Web/Resgrid.Web/Areas/User/Controllers/ReportsController.cs b/Web/Resgrid.Web/Areas/User/Controllers/ReportsController.cs index 7c8c6e76..c3f6bff8 100644 --- a/Web/Resgrid.Web/Areas/User/Controllers/ReportsController.cs +++ b/Web/Resgrid.Web/Areas/User/Controllers/ReportsController.cs @@ -503,6 +503,41 @@ public async Task ActiveCallsResourcesReport() { return View(await ActiveCallsResourcesReportModel(DepartmentId)); } + + [HttpGet] + [Authorize(Policy = ResgridResources.Reports_View)] + public async Task FlaggedCallNotesReport(DateTime? start, DateTime? end) + { + if (!ClaimsAuthorizationHelper.IsUserDepartmentAdmin()) + return Unauthorized(); + + return View(await FlaggedCallNotesReportModel(DepartmentId, start, end)); + } + + [HttpGet] + [Authorize(Policy = ResgridResources.Reports_View)] + public async Task FlaggedCallNotesReportParams() + { + if (!ClaimsAuthorizationHelper.IsUserDepartmentAdmin()) + return Unauthorized(); + + var department = await _departmentsService.GetDepartmentByIdAsync(DepartmentId); + + var model = new FlaggedCallNotesReportParams + { + Start = TimeConverterHelper.TimeConverter(new DateTime(DateTime.UtcNow.Year, 1, 1, 0, 0, 1), department), + End = TimeConverterHelper.TimeConverter(new DateTime(DateTime.UtcNow.Year, 12, 31, 23, 59, 59), department) + }; + + return View(model); + } + + [HttpPost] + [Authorize(Policy = ResgridResources.Reports_View)] + public IActionResult FlaggedCallNotesReportParams(FlaggedCallNotesReportParams model) + { + return RedirectToAction("FlaggedCallNotesReport", new { start = model.Start, end = model.End }); + } #endregion Views [HttpGet] @@ -1761,7 +1796,7 @@ private async Task ActiveCallsResourcesReportModel(int dep var personnel = await _usersService.GetUserGroupAndRolesByDepartmentIdAsync(DepartmentId, false, false, false); var units = await _unitsService.GetUnitsForDepartmentAsync(DepartmentId); var activeRoles = await _unitsService.GetAllActiveRolesForUnitsByDepartmentIdAsync(DepartmentId); - + foreach (var call in calls) { var summary = new OpenCallResource(); @@ -1839,5 +1874,175 @@ private async Task ActiveCallsResourcesReportModel(int dep return model; } + + private async Task FlaggedCallNotesReportModel(int departmentId, DateTime? start = null, DateTime? end = null) + { + var model = new FlaggedCallNotesReportView(); + model.Department = await _departmentsService.GetDepartmentByIdAsync(departmentId, false); + model.RunOn = DateTime.UtcNow.TimeConverter(model.Department); + + if (start.HasValue && end.HasValue) + { + model.Start = start.Value; + model.End = end.Value; + } + + var flaggedNotes = await _callsService.GetFlaggedCallNotesByDepartmentIdAsync(departmentId); + var flaggedImages = await _callsService.GetFlaggedCallImagesByDepartmentIdAsync(departmentId); + var flaggedFiles = await _callsService.GetFlaggedCallFilesByDepartmentIdAsync(departmentId); + + if (start.HasValue && end.HasValue) + { + flaggedNotes = flaggedNotes + .Where(n => n.FlaggedOn.HasValue && + n.FlaggedOn.Value.TimeConverter(model.Department) >= start.Value && + n.FlaggedOn.Value.TimeConverter(model.Department) <= end.Value) + .ToList(); + flaggedImages = flaggedImages + .Where(i => i.FlaggedOn.HasValue && + i.FlaggedOn.Value.TimeConverter(model.Department) >= start.Value && + i.FlaggedOn.Value.TimeConverter(model.Department) <= end.Value) + .ToList(); + flaggedFiles = flaggedFiles + .Where(f => f.FlaggedOn.HasValue && + f.FlaggedOn.Value.TimeConverter(model.Department) >= start.Value && + f.FlaggedOn.Value.TimeConverter(model.Department) <= end.Value) + .ToList(); + } + + var allCallIds = flaggedNotes.Select(n => n.CallId) + .Concat(flaggedImages.Select(i => i.CallId)) + .Concat(flaggedFiles.Select(f => f.CallId)) + .Distinct() + .ToList(); + + var calls = new Dictionary(); + foreach (var callId in allCallIds) + { + var call = await _callsService.GetCallByIdAsync(callId); + if (call != null) + calls[callId] = call; + } + + var profiles = await _userProfileService.GetAllProfilesForDepartmentAsync(departmentId); + + foreach (var note in flaggedNotes) + { + var row = new FlaggedCallNoteRow(); + + if (calls.TryGetValue(note.CallId, out var call)) + { + row.CallNumber = call.Number; + row.CallName = call.Name; + row.CallType = string.IsNullOrWhiteSpace(call.Type) ? "None" : call.Type; + row.CallAddress = call.Address; + row.CallLoggedOn = call.LoggedOn.TimeConverter(model.Department); + } + + row.CallNoteId = note.CallNoteId; + row.NoteText = note.Note; + row.NoteTimestamp = note.Timestamp.TimeConverter(model.Department); + + if (!string.IsNullOrWhiteSpace(note.UserId) && profiles.TryGetValue(note.UserId, out var authorProfile)) + row.NoteAuthorName = authorProfile.FullName.AsFirstNameLastName; + else + row.NoteAuthorName = "Unknown"; + + row.FlaggedOn = note.FlaggedOn.HasValue + ? note.FlaggedOn.Value.TimeConverter(model.Department) + : null; + row.FlaggedReason = note.FlaggedReason; + + if (!string.IsNullOrWhiteSpace(note.FlaggedByUserId) && profiles.TryGetValue(note.FlaggedByUserId, out var flaggedByProfile)) + row.FlaggedByName = flaggedByProfile.FullName.AsFirstNameLastName; + else + row.FlaggedByName = "Unknown"; + + model.Notes.Add(row); + } + + foreach (var image in flaggedImages) + { + var row = new FlaggedCallImageRow(); + + if (calls.TryGetValue(image.CallId, out var call)) + { + row.CallNumber = call.Number; + row.CallName = call.Name; + row.CallType = string.IsNullOrWhiteSpace(call.Type) ? "None" : call.Type; + row.CallAddress = call.Address; + row.CallLoggedOn = call.LoggedOn.TimeConverter(model.Department); + } + + row.CallAttachmentId = image.CallAttachmentId; + row.FileName = image.FileName; + row.ImageTimestamp = image.Timestamp.HasValue + ? image.Timestamp.Value.TimeConverter(model.Department) + : null; + + if (!string.IsNullOrWhiteSpace(image.UserId) && profiles.TryGetValue(image.UserId, out var authorProfile)) + row.ImageAuthorName = authorProfile.FullName.AsFirstNameLastName; + else + row.ImageAuthorName = "Unknown"; + + row.FlaggedOn = image.FlaggedOn.HasValue + ? image.FlaggedOn.Value.TimeConverter(model.Department) + : null; + row.FlaggedReason = image.FlaggedReason; + + if (!string.IsNullOrWhiteSpace(image.FlaggedByUserId) && profiles.TryGetValue(image.FlaggedByUserId, out var flaggedByProfile)) + row.FlaggedByName = flaggedByProfile.FullName.AsFirstNameLastName; + else + row.FlaggedByName = "Unknown"; + + model.Images.Add(row); + } + + foreach (var file in flaggedFiles) + { + var row = new FlaggedCallFileRow(); + + if (calls.TryGetValue(file.CallId, out var call)) + { + row.CallNumber = call.Number; + row.CallName = call.Name; + row.CallType = string.IsNullOrWhiteSpace(call.Type) ? "None" : call.Type; + row.CallAddress = call.Address; + row.CallLoggedOn = call.LoggedOn.TimeConverter(model.Department); + } + + row.CallAttachmentId = file.CallAttachmentId; + row.FileName = file.FileName; + row.FileTypeName = file.CallAttachmentType switch + { + 1 => "Dispatch Audio", + 3 => "File", + 4 => "Video", + _ => "Unknown" + }; + row.FileTimestamp = file.Timestamp.HasValue + ? file.Timestamp.Value.TimeConverter(model.Department) + : null; + + if (!string.IsNullOrWhiteSpace(file.UserId) && profiles.TryGetValue(file.UserId, out var fileAuthorProfile)) + row.FileAuthorName = fileAuthorProfile.FullName.AsFirstNameLastName; + else + row.FileAuthorName = "Unknown"; + + row.FlaggedOn = file.FlaggedOn.HasValue + ? file.FlaggedOn.Value.TimeConverter(model.Department) + : null; + row.FlaggedReason = file.FlaggedReason; + + if (!string.IsNullOrWhiteSpace(file.FlaggedByUserId) && profiles.TryGetValue(file.FlaggedByUserId, out var flaggedByFileProfile)) + row.FlaggedByName = flaggedByFileProfile.FullName.AsFirstNameLastName; + else + row.FlaggedByName = "Unknown"; + + model.Files.Add(row); + } + + return model; + } } } diff --git a/Web/Resgrid.Web/Areas/User/Models/Dispatch/FlagCallFileView.cs b/Web/Resgrid.Web/Areas/User/Models/Dispatch/FlagCallFileView.cs new file mode 100644 index 00000000..63b5b7cc --- /dev/null +++ b/Web/Resgrid.Web/Areas/User/Models/Dispatch/FlagCallFileView.cs @@ -0,0 +1,18 @@ +namespace Resgrid.WebCore.Areas.User.Models.Dispatch +{ + public class FlagCallFileView + { + public string Message { get; set; } + public int CallId { get; set; } + public int CallAttachmentId { get; set; } + public string FileName { get; set; } + public int FileType { get; set; } + public string AddedOn { get; set; } + public string AddedBy { get; set; } + public bool IsFlagged { get; set; } + public string FlagNote { get; set; } + public string FlaggedOn { get; set; } + public string FlaggedBy { get; set; } + } +} + diff --git a/Web/Resgrid.Web/Areas/User/Models/Dispatch/FlagCallImageView.cs b/Web/Resgrid.Web/Areas/User/Models/Dispatch/FlagCallImageView.cs new file mode 100644 index 00000000..8cbc355d --- /dev/null +++ b/Web/Resgrid.Web/Areas/User/Models/Dispatch/FlagCallImageView.cs @@ -0,0 +1,17 @@ +namespace Resgrid.WebCore.Areas.User.Models.Dispatch +{ + public class FlagCallImageView + { + public string Message { get; set; } + public int CallId { get; set; } + public int CallAttachmentId { get; set; } + public string FileName { get; set; } + public string AddedOn { get; set; } + public string AddedBy { get; set; } + public bool IsFlagged { get; set; } + public string FlagNote { get; set; } + public string FlaggedOn { get; set; } + public string FlaggedBy { get; set; } + } +} + diff --git a/Web/Resgrid.Web/Areas/User/Models/Reports/Calls/FlaggedCallNotesReportView.cs b/Web/Resgrid.Web/Areas/User/Models/Reports/Calls/FlaggedCallNotesReportView.cs new file mode 100644 index 00000000..3aba05a1 --- /dev/null +++ b/Web/Resgrid.Web/Areas/User/Models/Reports/Calls/FlaggedCallNotesReportView.cs @@ -0,0 +1,73 @@ +using System; +using System.Collections.Generic; +using Resgrid.Model; + +namespace Resgrid.Web.Areas.User.Models.Reports.Calls +{ + public class FlaggedCallNotesReportView + { + public DateTime RunOn { get; set; } + public Department Department { get; set; } + public DateTime? Start { get; set; } + public DateTime? End { get; set; } + public List Notes { get; set; } + public List Images { get; set; } + public List Files { get; set; } + + public FlaggedCallNotesReportView() + { + Notes = new List(); + Images = new List(); + Files = new List(); + } + } + + public class FlaggedCallNoteRow + { + public int CallNoteId { get; set; } + public string CallNumber { get; set; } + public string CallName { get; set; } + public string CallType { get; set; } + public string CallAddress { get; set; } + public DateTime CallLoggedOn { get; set; } + public string NoteText { get; set; } + public DateTime NoteTimestamp { get; set; } + public string NoteAuthorName { get; set; } + public DateTime? FlaggedOn { get; set; } + public string FlaggedReason { get; set; } + public string FlaggedByName { get; set; } + } + + public class FlaggedCallImageRow + { + public int CallAttachmentId { get; set; } + public string CallNumber { get; set; } + public string CallName { get; set; } + public string CallType { get; set; } + public string CallAddress { get; set; } + public DateTime CallLoggedOn { get; set; } + public string FileName { get; set; } + public DateTime? ImageTimestamp { get; set; } + public string ImageAuthorName { get; set; } + public DateTime? FlaggedOn { get; set; } + public string FlaggedReason { get; set; } + public string FlaggedByName { get; set; } + } + + public class FlaggedCallFileRow + { + public int CallAttachmentId { get; set; } + public string CallNumber { get; set; } + public string CallName { get; set; } + public string CallType { get; set; } + public string CallAddress { get; set; } + public DateTime CallLoggedOn { get; set; } + public string FileName { get; set; } + public string FileTypeName { get; set; } + public DateTime? FileTimestamp { get; set; } + public string FileAuthorName { get; set; } + public DateTime? FlaggedOn { get; set; } + public string FlaggedReason { get; set; } + public string FlaggedByName { get; set; } + } +} diff --git a/Web/Resgrid.Web/Areas/User/Models/Reports/Params/FlaggedCallNotesReportParams.cs b/Web/Resgrid.Web/Areas/User/Models/Reports/Params/FlaggedCallNotesReportParams.cs new file mode 100644 index 00000000..0dcffae3 --- /dev/null +++ b/Web/Resgrid.Web/Areas/User/Models/Reports/Params/FlaggedCallNotesReportParams.cs @@ -0,0 +1,11 @@ +using System; + +namespace Resgrid.Web.Areas.User.Models.Reports.Params +{ + public class FlaggedCallNotesReportParams + { + public DateTime Start { get; set; } + public DateTime End { get; set; } + } +} + diff --git a/Web/Resgrid.Web/Areas/User/Views/Dispatch/FlagCallFile.cshtml b/Web/Resgrid.Web/Areas/User/Views/Dispatch/FlagCallFile.cshtml new file mode 100644 index 00000000..94b0a4d2 --- /dev/null +++ b/Web/Resgrid.Web/Areas/User/Views/Dispatch/FlagCallFile.cshtml @@ -0,0 +1,94 @@ +@using Resgrid.Model +@model Resgrid.WebCore.Areas.User.Models.Dispatch.FlagCallFileView +@inject IStringLocalizer localizer +@{ + ViewBag.Title = "Resgrid | " + @localizer["FlagCallFileHeader"]; +} + +
+
+

@localizer["FlagCallFileHeader"]

+ +
+
+ +
+
+
+
+
+
+ +
+
+ @if (!String.IsNullOrEmpty(Model.Message)) + { +
+ @Model.Message +
+ } +
+ @Html.AntiForgeryToken() + @Html.HiddenFor(m => m.CallId) + @Html.HiddenFor(m => m.CallAttachmentId) + @Html.HiddenFor(m => m.FileType) +
+
+ +
+ +
@Html.Raw(Model.FileName)
+
+ +
+ +
@Html.Raw(Model.AddedOn)
+
+ +
+ +
@Html.Raw(Model.AddedBy)
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+ @commonLocalizer["Cancel"] + +
+
+
+
+
+
+
+
+ +@section Scripts + { + +} + diff --git a/Web/Resgrid.Web/Areas/User/Views/Dispatch/FlagCallImage.cshtml b/Web/Resgrid.Web/Areas/User/Views/Dispatch/FlagCallImage.cshtml new file mode 100644 index 00000000..30855465 --- /dev/null +++ b/Web/Resgrid.Web/Areas/User/Views/Dispatch/FlagCallImage.cshtml @@ -0,0 +1,93 @@ +@using Resgrid.Model +@model Resgrid.WebCore.Areas.User.Models.Dispatch.FlagCallImageView +@inject IStringLocalizer localizer +@{ + ViewBag.Title = "Resgrid | " + @localizer["FlagCallImageHeader"]; +} + +
+
+

@localizer["FlagCallImageHeader"]

+ +
+
+ +
+
+
+
+
+
+ +
+
+ @if (!String.IsNullOrEmpty(Model.Message)) + { +
+ @Model.Message +
+ } +
+ @Html.AntiForgeryToken() + @Html.HiddenFor(m => m.CallId) + @Html.HiddenFor(m => m.CallAttachmentId) +
+
+ +
+ +
@Html.Raw(Model.FileName)
+
+ +
+ +
@Html.Raw(Model.AddedOn)
+
+ +
+ +
@Html.Raw(Model.AddedBy)
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+ @commonLocalizer["Cancel"] + +
+
+
+
+
+
+
+
+ +@section Scripts + { + +} + diff --git a/Web/Resgrid.Web/Areas/User/Views/Dispatch/ViewCall.cshtml b/Web/Resgrid.Web/Areas/User/Views/Dispatch/ViewCall.cshtml index 3b67663d..4ffd43f5 100644 --- a/Web/Resgrid.Web/Areas/User/Views/Dispatch/ViewCall.cshtml +++ b/Web/Resgrid.Web/Areas/User/Views/Dispatch/ViewCall.cshtml @@ -470,6 +470,20 @@ @commonLocalizer["Download"] } + + @if (file.IsFlagged) + { + + @localizer["FlagFile"] + + } + else + { + + @localizer["FlagFile"] + + } + } @@ -482,8 +496,8 @@ {
-
-
+
+
@commonLocalizer["Name"]:
@image.Name
@commonLocalizer["Timestamp"]:
@@ -498,7 +512,20 @@
@commonLocalizer["Location"]:
@commonLocalizer["Unknown"]
- +
+ @if (image.IsFlagged) + { + + @localizer["FlagImage"] + + } + else + { + + @localizer["FlagImage"] + + } +
diff --git a/Web/Resgrid.Web/Areas/User/Views/Logs/NewLog.cshtml b/Web/Resgrid.Web/Areas/User/Views/Logs/NewLog.cshtml index 04405042..574e23ca 100644 --- a/Web/Resgrid.Web/Areas/User/Views/Logs/NewLog.cshtml +++ b/Web/Resgrid.Web/Areas/User/Views/Logs/NewLog.cshtml @@ -509,7 +509,7 @@
- +
@@ -597,8 +597,37 @@ } -
-
+ + + @section Scripts { diff --git a/Web/Resgrid.Web/Areas/User/Views/Reports/FlaggedCallNotesReport.cshtml b/Web/Resgrid.Web/Areas/User/Views/Reports/FlaggedCallNotesReport.cshtml new file mode 100644 index 00000000..69bbd2ff --- /dev/null +++ b/Web/Resgrid.Web/Areas/User/Views/Reports/FlaggedCallNotesReport.cshtml @@ -0,0 +1,319 @@ +@using Resgrid.Model.Helpers +@using Resgrid.Web +@using Resgrid.Web.Helpers +@using Microsoft.Extensions.Localization +@model Resgrid.Web.Areas.User.Models.Reports.Calls.FlaggedCallNotesReportView +@inject IStringLocalizer localizer +@{ + Layout = null; +} + + + + + + @localizer["ReportTitle"] + + + + + + + + + + + + + + + + + +
+
+
+ +
+
+

@localizer["ReportTitle"]

+ @Model.Department.Name +
+
+ + @* ===== DATE RANGE FILTER BANNER ===== *@ + @if (Model.Start.HasValue && Model.End.HasValue) + { +
+
+
+ @localizer["DateFilterApplied"]: + @Model.Start.Value.FormatForDepartment(Model.Department) – @Model.End.Value.FormatForDepartment(Model.Department) +
+
+
+ } + + @* ===== FLAGGED NOTES SECTION ===== *@ +
+
+

@localizer["FlaggedNotesSection"] @Model.Notes.Count @localizer["FlaggedCountSuffix"]

+
+
+
+ + @if (!Model.Notes.Any()) + { +
+
+
+ @localizer["NoFlaggedNotesFound"] +
+
+
+ } + else + { +
+
+ + + + + + + + + + + + + + + + @foreach (var row in Model.Notes) + { + + + + + + + + + + + + } + +
@localizer["CallNumberHeader"]@localizer["CallNameHeader"]@localizer["CallTypeHeader"]@localizer["CallAddressHeader"]@localizer["CallLoggedOnHeader"]@localizer["NoteHeader"]@localizer["NoteByHeader"]@localizer["NoteTimestampHeader"]@localizer["FlagInfoHeader"]
@row.CallNumber@row.CallName@row.CallType@row.CallAddress@row.CallLoggedOn.FormatForDepartment(Model.Department)@row.NoteText@row.NoteAuthorName@row.NoteTimestamp.FormatForDepartment(Model.Department) + @localizer["FlaggedByLabel"]: @row.FlaggedByName
+ @if (row.FlaggedOn.HasValue) + { + @localizer["FlaggedOnLabel"]: + @row.FlaggedOn.Value.FormatForDepartment(Model.Department)
+ } + @if (!string.IsNullOrWhiteSpace(row.FlaggedReason)) + { + @localizer["ReasonLabel"]: @row.FlaggedReason + } +
+
+
+ } + + @* ===== FLAGGED IMAGES SECTION ===== *@ +
+
+

@localizer["FlaggedImagesSection"] @Model.Images.Count @localizer["FlaggedCountSuffix"]

+
+
+
+ + @if (!Model.Images.Any()) + { +
+
+
+ @localizer["NoFlaggedImagesFound"] +
+
+
+ } + else + { +
+
+ + + + + + + + + + + + + + + + @foreach (var row in Model.Images) + { + + + + + + + + + + + + } + +
@localizer["CallNumberHeader"]@localizer["CallNameHeader"]@localizer["CallTypeHeader"]@localizer["CallAddressHeader"]@localizer["CallLoggedOnHeader"]@localizer["FileNameHeader"]@localizer["ImageByHeader"]@localizer["ImageTimestampHeader"]@localizer["FlagInfoHeader"]
@row.CallNumber@row.CallName@row.CallType@row.CallAddress@row.CallLoggedOn.FormatForDepartment(Model.Department)@row.FileName@row.ImageAuthorName + @if (row.ImageTimestamp.HasValue) + { + @row.ImageTimestamp.Value.FormatForDepartment(Model.Department) + } + + @localizer["FlaggedByLabel"]: @row.FlaggedByName
+ @if (row.FlaggedOn.HasValue) + { + @localizer["FlaggedOnLabel"]: + @row.FlaggedOn.Value.FormatForDepartment(Model.Department)
+ } + @if (!string.IsNullOrWhiteSpace(row.FlaggedReason)) + { + @localizer["ReasonLabel"]: @row.FlaggedReason + } +
+
+
+ } + + @* ===== FLAGGED FILES SECTION ===== *@ +
+
+

@localizer["FlaggedFilesSection"] @Model.Files.Count @localizer["FlaggedCountSuffix"]

+
+
+
+ + @if (!Model.Files.Any()) + { +
+
+
+ @localizer["NoFlaggedFilesFound"] +
+
+
+ } + else + { +
+
+ + + + + + + + + + + + + + + + + @foreach (var row in Model.Files) + { + + + + + + + + + + + + + } + +
@localizer["CallNumberHeader"]@localizer["CallNameHeader"]@localizer["CallTypeHeader"]@localizer["CallAddressHeader"]@localizer["CallLoggedOnHeader"]@localizer["FileNameHeader"]@localizer["FileTypeHeader"]@localizer["FileByHeader"]@localizer["FileTimestampHeader"]@localizer["FlagInfoHeader"]
@row.CallNumber@row.CallName@row.CallType@row.CallAddress@row.CallLoggedOn.FormatForDepartment(Model.Department)@row.FileName@row.FileTypeName@row.FileAuthorName + @if (row.FileTimestamp.HasValue) + { + @row.FileTimestamp.Value.FormatForDepartment(Model.Department) + } + + @localizer["FlaggedByLabel"]: @row.FlaggedByName
+ @if (row.FlaggedOn.HasValue) + { + @localizer["FlaggedOnLabel"]: + @row.FlaggedOn.Value.FormatForDepartment(Model.Department)
+ } + @if (!string.IsNullOrWhiteSpace(row.FlaggedReason)) + { + @localizer["ReasonLabel"]: @row.FlaggedReason + } +
+
+
+ } + +
+
+ @if (Model.Start.HasValue && Model.End.HasValue) + { + @localizer["DateRangeLabel"]: @Model.Start.Value.FormatForDepartment(Model.Department) – @Model.End.Value.FormatForDepartment(Model.Department)  |  + } + @localizer["ReportGeneratedLabel"]: @Model.RunOn.FormatForDepartment(Model.Department) +
+
+
+ + + + + + diff --git a/Web/Resgrid.Web/Areas/User/Views/Reports/FlaggedCallNotesReportParams.cshtml b/Web/Resgrid.Web/Areas/User/Views/Reports/FlaggedCallNotesReportParams.cshtml new file mode 100644 index 00000000..bf3e99d4 --- /dev/null +++ b/Web/Resgrid.Web/Areas/User/Views/Reports/FlaggedCallNotesReportParams.cshtml @@ -0,0 +1,81 @@ +@using Resgrid.Framework +@using Resgrid.Model +@using Resgrid.Web.Helpers +@using Microsoft.Extensions.Localization +@model Resgrid.Web.Areas.User.Models.Reports.Params.FlaggedCallNotesReportParams +@inject IStringLocalizer localizer +@{ + ViewBag.Title = "Resgrid | " + localizer["ReportTitle"]; +} + +
+
+

@localizer["ReportTitle"]

+ +
+
+ +
+
+
+
+
+
+ +
+
+ @Html.AntiForgeryToken() +
+
+
+ +
+ +
+ @Html.TextBoxFor(m => m.Start, new { style = "width:250px;", onkeydown = "javascript:return false;" }) +
+
+ +
+ +
+ @Html.TextBoxFor(m => m.End, new { style = "width:250px;", onkeydown = "javascript:return false;" }) +
+
+ +
+
+ @commonLocalizer["Cancel"] + +
+
+
+
+
+
+
+
+ +@section Scripts +{ + +} diff --git a/Web/Resgrid.Web/Areas/User/Views/Reports/Index.cshtml b/Web/Resgrid.Web/Areas/User/Views/Reports/Index.cshtml index 7f070604..0f13455f 100644 --- a/Web/Resgrid.Web/Areas/User/Views/Reports/Index.cshtml +++ b/Web/Resgrid.Web/Areas/User/Views/Reports/Index.cshtml @@ -1,7 +1,9 @@ @using Resgrid.Framework @using Resgrid.Model @using Resgrid.Web.Helpers +@using Microsoft.Extensions.Localization @model Resgrid.Web.Areas.User.Models.Logs.LogsIndexView +@inject IStringLocalizer flaggedReportLocalizer @{ ViewBag.Title = "Resgrid | Reports"; } @@ -159,6 +161,20 @@ View Report + @if (ClaimsAuthorizationHelper.IsUserDepartmentAdmin()) + { + + + @flaggedReportLocalizer["ReportTitle"] + + + @flaggedReportLocalizer["ReportIndexDescription"] + + + View Report + + + }
diff --git a/Web/Resgrid.Web/wwwroot/js/app/internal/logs/resgrid.logs.newlog.js b/Web/Resgrid.Web/wwwroot/js/app/internal/logs/resgrid.logs.newlog.js index 64c06199..c5e8c15d 100644 --- a/Web/Resgrid.Web/wwwroot/js/app/internal/logs/resgrid.logs.newlog.js +++ b/Web/Resgrid.Web/wwwroot/js/app/internal/logs/resgrid.logs.newlog.js @@ -72,11 +72,11 @@ var resgrid; // Bootstrap modal wrappers replacing kendoWindow $('#callsWindow').on('show.bs.modal', function () { var $b = $(this).find('.modal-body'); - if ($b.is(':empty')) { $b.load('/User/Dispatch/SmallCallGrid'); } + if ($.trim($b.html()) === '') { $b.load(resgrid.absoluteBaseUrl + '/User/Dispatch/SmallCallGrid'); } }); $('#unitsWindow').on('show.bs.modal', function () { var $b = $(this).find('.modal-body'); - if ($b.is(':empty')) { $b.load('/User/Units/SmallUnitsGrid'); } + if ($.trim($b.html()) === '') { $b.load(resgrid.absoluteBaseUrl + '/User/Units/SmallUnitsGrid'); } }); newlog.wndCalls = { center: function() { return this; }, open: function() { $('#callsWindow').modal('show'); }, close: function() { $('#callsWindow').modal('hide'); } }; newlog.wndUnits = { center: function() { return this; }, open: function() { $('#unitsWindow').modal('show'); }, close: function() { $('#unitsWindow').modal('hide'); } };