Compare commits

...

153 Commits

Author SHA1 Message Date
Developer 02
891f6368f1 refactor(card.css): CSS der footer für Reaktionsfähigkeit bearbeitet 2024-10-16 02:11:07 +02:00
Developer 02
e6011b6201 refactor(card.css): CSS des Kopfbereichs für Reaktionsfähigkeit bearbeitet 2024-10-16 01:54:02 +02:00
Developer 02
8b86114998 refactor (card.css): unnötiges CSS entfernt 2024-10-16 00:31:32 +02:00
Developer 02
c20b115faf feat(logo): minimiertes Logo hinzugefügt 2024-10-16 00:11:14 +02:00
Developer 02
2c8ccd3e7c feat: signFlow-Logo hinzufügen 2024-10-14 19:18:40 +02:00
Developer 02
b1f771c320 feat: Kopierschaltfläche von der linken Navigationsleiste in die pspdf-kit Symbolleiste verschoben. 2024-10-14 18:54:29 +02:00
Developer 02
425645a610 feat: neue Klasse für Desktop-Schaltflächen mit dem Namen 'btn-desktop' erstellt
- CSS hinzugefügt, um die Klasse btn-desktop auszublenden, wenn die Breite weniger als 1024px beträgt.
2024-10-14 17:41:51 +02:00
Developer 02
24e6ffc5ef feat: CSS mit Bootstrap für mobil beschreibbare Toolbar-Elemente anordnen 2024-10-14 17:24:49 +02:00
Developer 02
1dd9ce6bbc feat: Aktivieren Sie die Schaltfläche für die mobile Ablehnung.
- Ereignis hinzugefügt.
 - In die Mitte der Schaltflächenleiste verschoben
2024-10-14 17:06:01 +02:00
Developer 02
e528fa6409 feat: getMobileItems umbenennen in getMobileWritableItems 2024-10-14 16:05:27 +02:00
Developer 02
6440dd09d1 feat: Erstellung der konstanten Variablen DEVICE_TYPE und IS_DESKTOP.
- Aufteilung der benutzerdefinierten Symbolleistenelemente in writableItems und mobileItems
 - beide werden abhängig von der jeweiligen Bedingung hinzugefügt
2024-10-14 15:44:21 +02:00
Developer 02
869493bd97 feat: Globale Konstante isReadOnly-Wert erstellt.
- Constraint für ReadOnly-Schaltfläche mit isReadOnly-Wert hinzugefügt
2024-10-14 14:02:02 +02:00
Developer 02
1cb9042736 feat(ui.js): Freigabe-Schaltfläche als Symbolleisten-Schaltfläche hinzugefügt.
- Share-Button auf der linken Seite der Kopfzeile entfernt
2024-10-14 11:27:41 +02:00
Developer 02
c9410a1e2e feat(ReadOnlyController): Try-Catch zur 'CreateAsync'-Methode hinzugefügt.
- Unnötige Testmethoden wurden aus dem Controller entfernt.
2024-10-14 09:38:16 +02:00
Developer 02
c4f0ce7d4b feat: bsNotify-Methode und Benachrichtigung für Clipboard-Kopie hinzufügen
- Implementierung der bsNotify-Methode für benutzerdefinierte Benachrichtigungen mit alertify.
- Hinzufügen von benutzerdefinierten Styles für den benutzerdefinierten Benachrichtigungstyp von alertify.
- Hinzufügen der Clipboard-Kopie-Funktionalität mit Erfolgs- und Fehlerbenachrichtigungen.
2024-10-11 14:15:06 +02:00
Developer 02
dc83486032 feat(ShowEnvelope): Nachricht auf Popup-Seite zum Teilen hinzugefügt 2024-10-11 09:51:02 +02:00
Developer 02
2a64091c87 feat: Funktionalität des Datumsauswählers zum Eingabefeld hinzufügen
- Einen Datumsauswähler implementiert, der beim Fokussieren des Eingabefeldes und beim Klicken auf das Kalendersymbol geöffnet wird.
- Sicherstellt, dass das Eingabefeld keine manuelle Dateneingabe zulässt, während der Kalender weiterhin angezeigt werden kann.
- Das `onkeydown`-Ereignis verwendet, um manuelle Eingaben zu verhindern und die Datenauswahl ausschließlich über den Datumsauswähler zu ermöglichen.
2024-10-11 00:59:00 +02:00
Developer 02
f65f749208 feat(ShowEnvelope): Der Rücksetzwert des Verfallsdatums der Briefumschlag-Aktie wird auf das Datum eine Woche später statt auf den leeren String gesetzt. 2024-10-11 00:45:37 +02:00
Developer 02
0b6ed00062 feat(EnvelopeReceiverReadOnlyCreateDto): EmailAddress und Required Attribute zu ReceiverMail hinzugefügt. 2024-10-11 00:36:18 +02:00
Developer 02
e87c976e19 fix(ShowEnvelope): Logik der E-Mail-Formatprüfung korrigiert 2024-10-10 22:00:52 +02:00
Developer 02
f31ece3a59 feat(ShowEnvelope): Logik zur Überprüfung des E-Mail-Formats hinzugefügt. Zeigt eine Fehlermeldung, wenn das Format falsch ist. 2024-10-10 21:56:32 +02:00
Developer 02
cfd08602ab feat(ShowEnvelope): Logik zur Überprüfung des Datums hinzugefügt. Wenn es weniger als einen Tag beträgt, wird eine Fehlermeldung angezeigt. 2024-10-10 21:46:06 +02:00
Developer 02
4b7152b272 feat(ShowEnvelope): Die Attribute min, max und value wurden zu readonly-date-valid hinzugefügt. 2024-10-10 20:47:55 +02:00
Developer 02
5117a66c81 feat(ShowEnvelope): Standarddatum nach 3 Tagen setzen 2024-10-10 19:30:19 +02:00
Developer 02
83794d4bbc feat: add email validation and toggle 'is-invalid' class for inputs with 'email-input' class 2024-10-10 19:21:15 +02:00
Developer 02
76f74778b4 feat(ShowEnvelope): Swal-Nachrichten zur Umschlagfreigabe-Anforderung hinzugefügt 2024-10-10 18:53:35 +02:00
Developer 02
ded3425e31 feat: Funktion hinzugefügt, um aktuelle URL beim Klicken auf den Button in die Zwischenablage zu kopieren 2024-10-09 16:53:44 +02:00
Developer 02
738b379fe5 feat(UI.js): PDF-Export-Symbolleiste zur pspdf-Instanz hinzugefügt 2024-10-09 16:50:01 +02:00
Developer 02
cf8b28441f feat(ShowEnvelope): Bedingung hinzugefügt, die auf Nur-Lesen basiert, um den Share-Button zu sehen.
- Wenn es schreibgeschützt ist, erscheint die Schaltfläche Kopie zur Zwischenablage hinzufügen.
2024-10-09 16:49:07 +02:00
Developer 02
0eb5897185 feat(share pop-up): Post-Request-Prozess hinzugefügt. 2024-10-09 15:03:54 +02:00
Developer 02
25cd1601a6 feat(share pop-up): Datumswähler hinzugefügt. 2024-10-09 13:54:16 +02:00
Developer 02
42e4d110ad refactor(wwwroot\lib): MDB und bootstrap-cookie-consent-settings-main entfernt 2024-10-09 12:43:18 +02:00
Developer 02
2538f34892 feat(ShowEnvelope). erstellt Basis-Popup-Menü, um das Dokument zu senden 2024-10-09 12:37:36 +02:00
Developer 02
3ce11f4cc7 feat(api-service): Methode für Share-Request erstellt. 2024-10-09 11:00:21 +02:00
Developer 02
f2cd34a79e feat(share-button): Basisstruktur der Klick-Aktion hinzugefügt 2024-10-09 10:50:26 +02:00
Developer 02
5f923ad485 feat(ShowEnvelope): Share-Button hinzugefügt
- CSS einstellen.
2024-10-09 10:46:18 +02:00
Developer 02
8f70f085d3 feat(HomeController): Historischer Prozess zum Speichern von Umschlägen hinzugefügt, die unter dem Endpunkt EnvelopeReceiverReadOnly angezeigt werden. 2024-10-09 09:58:20 +02:00
Developer 02
d6c09ed31a feat(ReadOnlyController): Speichern der EnvelopeShared-History zur CreateAsync-Methode hinzugefügt. 2024-10-09 09:37:02 +02:00
Developer 02
7d3ee1331d feat(EnvelopeStatus): Status „EnvelopeViewed“ hinzugefügt 2024-10-09 02:11:51 +02:00
Developer 02
cd5b90a1e2 feat(ReadOnlyControler): History-Dienst hinzugefügt, um envelope-shared-process zu speichern 2024-10-09 02:10:08 +02:00
Developer 02
ac861f5fa0 fix(DIExtensions): arrangierte Mail- und Dispatcher-Konfigurationen 2024-10-09 02:05:21 +02:00
Developer 02
c1d8f817bb feat(ReadOnlyController): envelope-id von create DTO automatisch aus envelope-id claim hinzugefügt. 2024-10-09 01:16:06 +02:00
Developer 02
da28a7332b feat(EnvelopeClaimTypes): „envelope ID“ als Auth-Claim hinzugefügt. 2024-10-09 00:51:59 +02:00
Developer 02
bfd4e6a8ed feat(MailConfig): Schnittstelle zur Mail-Konfiguration über appsettings erstellt. 2024-10-09 00:22:23 +02:00
Developer 02
b4e0e4b6b2 feat(EnvelopeMailService): Arrangiert den Mailservice für read-only Umschläge zum Versenden als E-Mail 2024-10-08 15:56:34 +02:00
Developer 02
e37caf5c8f refactor(ShowEnvelopeView): Kurzzeitanteil der Verfallszeit für schreibgeschützten Umschlag entfernen 2024-10-07 10:08:10 +02:00
Developer 02
e95cf24af7 feat(EnvelopeExpired-View): Erstellt eine Ansicht, die anzeigt, wenn der Umschlag abgelaufen ist 2024-10-05 04:19:52 +02:00
Developer 02
524a72caa0 feat(ShowEnvelope-View): Flex-Action-Panel ausblenden, wenn schreibgeschützt 2024-10-05 03:22:37 +02:00
Developer 02
1919c562cc feat(ShowEnvelope-View): ReadOnlyMessage wurde für verschiedene Kulturen erstellt. Zu View hinzugefügt.
- View-Benutzernachrichten sind so organisiert, dass sie davon abhängen, ob der Umschlag schreibgeschützt ist oder nicht.
2024-10-05 03:20:39 +02:00
Developer 02
62b54d6e75 feat(HomeController): Sanizer hinzugefügt 2024-10-05 02:16:14 +02:00
Developer 02
efa9160c04 feat(EnvelopeReceiverReadOnly): Modelldaten und Dokument im Endpunkt sind so eingestellt, dass sie als Bytes geladen werden. 2024-10-05 02:04:57 +02:00
Developer 02
bc6955055a feat(EnvelopeReceiverReadOnly): Created endpoint for ShowEnvelope view 2024-10-04 11:28:52 +02:00
Developer 02
dc997d5ff2 refactor(.Extensions): Extensions nach Gruppen aufgeteilt.
- erstellt dekodierende Erweiterungen.
 - Kodierungserweiterungen erstellt.
 - XSS-Erweiterungen in das Extensions-Paket verschoben.
 - EncodeTypes vom Paket Common in das Paket Constants verschoben.
2024-10-02 13:33:11 +02:00
Developer 02
a32f495038 refactor(HomeController): EnvelopeReceiverReadOnly-Endpunkt initialisiert.
- injiziert EnvelopeReceiverReadOnlyService
2024-10-01 18:14:59 +02:00
Developer 02
210466883c refactor(SendAccessCode): Prüfung hinzugefügt, ob die envelope-id schreibgeschützt ist. Wenn ja, Umleitung zu /ReadOnly
- Umbenannt in MainAsync
2024-10-01 17:51:31 +02:00
Developer 02
728385b70a feat(extensions): created extensions project.
- Moved encoding extensions from application to extensions project to increase the abstraction
2024-10-01 17:25:50 +02:00
Developer 02
792aa0b922 feat(decode): Methoden zur Konvertierung des dekodierten Arrays in eine Umschlag-Empfänger-ID und eine Nur-Lese-ID mit Ausnahmewirkung hinzugefügt. 2024-10-01 16:44:46 +02:00
Developer 02
6847b74095 feat(EncodeType): Enum zur Klassifizierung von Kodierungstypen erstellt.
- Erweiterungsmethoden hinzugefügt, um zu versuchen, String mit out-keyworld zu dekodieren.

- Erweiterungsmethode hinzugefügt, um den Typ des Kodierungstyps des dekodierten String-Arrays zu finden.
2024-10-01 16:04:44 +02:00
Developer 02
54e86b421c feat(EnvelopeReceiverReadOnly): Erweiterungsmethode zum Kodieren und Dekodieren von Envelope-Receiver ReadOnly Id hinzugefügt 2024-10-01 15:26:06 +02:00
Developer 02
370666cb0e refactor: EnvelopeReceiverReadOnlyRepository so angepasst, dass die Einbindung von Envelope bis zur Klärung des ID-Typs verschoben wird
- Konstruktor von EnvelopeReceiverReadOnlyRepository angepasst, um IEnvelopeRepository zu akzeptieren.
 - Die Zeile Include(erro => erro.Envelope) in der Methode ReadOnly auskommentiert, bis der EnvelopeId-Typ standardisiert ist.
 - Methoden IncludeEnvelope hinzugefügt, um Envelope manuell für jedes EnvelopeReceiverReadOnly einzubinden.
 - Markierte manuelle Einbindungs-Methoden als veraltet, um durch IQueryable.Include ersetzt zu werden, sobald der EnvelopeId-Typ geklärt ist.
2024-10-01 12:54:27 +02:00
Developer 02
e17f7df930 feat(EnvelopeReceiverReadOnly): Controller initialisieren
- Join mit Receiver und Read
 - DI-Konfiguration hinzufügen
 - Auslöser hinzufügen (TBSIG_ENVELOPE_RECEIVER_READ_ONLY_UPD)
2024-10-01 11:17:30 +02:00
Developer 02
0e91df7acc feat (Constants.EmailTemplateType): Einen neuen Typ namens „DocumentShared“ erstellt 2024-09-30 15:14:01 +02:00
Developer 02
ad26230da5 feat (EnvelopeReceiverReadOnly): Erstellt „EnvelopeReceiverReadOnlyService“ als Implementierung von „CRUDService“ und „IEnvelopeReceiverReadOnlyService-interface“ 2024-09-30 15:02:52 +02:00
Developer 02
a103f34230 feat (EnvelopeReceiverReadOnly): Erstellt „mapping-profiles“ für Auto-Mapper.
- EnvelopeReceiverReadOnly zu EnvelopeReceiverReadOnlyDto
 - EnvelopeReceiverReadOnlyCreateDto zu EnvelopeReceiverReadOnly
 - EnvelopeReceiverReadOnlyUpdateDto zu EnvelopeReceiverReadOnly
2024-09-30 14:43:30 +02:00
Developer 02
806bd3b248 feat (EnvelopeReceiverReadOnly): Erstellt „data-transfer-objects“.
- Erstellt „Read-DTO“
 - Erstellt „Create-DTO
 - Erstellt „Update-DTO“ um nur „DateValid“ zu aktualisieren.
2024-09-30 14:39:22 +02:00
Developer 02
c69c39fa44 refactor(EnvelopeReceiverReadOnly): ChangedWho Eigenschaft „nullable“ gemacht 2024-09-30 14:00:40 +02:00
Developer 02
b6badb44af feat(EnvelopeReceiverReadOnly): Erstellte Repository-Klasse mit der Interface-Implementierung 2024-09-30 13:54:39 +02:00
Developer 02
b2195ce13f feat(EnvelopeReceiverReadOnly): Entität erstellt 2024-09-30 13:43:57 +02:00
Developer 02
f3cb9b8510 feat(EnvelopeStatus): Neuer Status für die gemeinsame Nutzung von Umschlägen mit Code 2008 hinzugefügt. 2024-09-30 11:49:08 +02:00
Developer 02
8edfecb9dc refactor (privacy-policy): Fehlende Informationen und CSS aktualisieren 2024-09-30 11:32:14 +02:00
Developer 02
c123d103bb chore Upgrade auf 2.1.1.0 2024-09-25 16:09:01 +02:00
Developer 02
b92d9da387 refactor(envelope-locked): konvertiere submit-button bootstrap Klasse von btn-outline-primary zu btn-primary 2024-09-25 16:07:54 +02:00
Developer 02
8841698aab chore(web): Version auf 2.0.0.0 aktualisieren und Copyrights schreiben 2024-09-25 15:52:09 +02:00
Developer 02
6f140f16cd fix(footer): Entferne den Ursprung der Datenschutzrichtlinien-URL, um auf den aktuellen Ursprung umzuleiten 2024-09-25 15:49:38 +02:00
Developer 02
8bfd31997b Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2024-09-25 14:46:14 +02:00
Developer 02
4a1459d708 feat: add smooth width transition to progress bar with 1s ease animation 2024-09-25 14:46:08 +02:00
Developer 02
361bdeb2b2 feat(event-binder.js): Es wurde der Effekt hinzugefügt, dass die Breite des Fortschrittsbalkens nach dem Signaturprozess um einen bestimmten Anteil erhöht wird. 2024-09-25 14:41:30 +02:00
Developer 02
9ce5af7cd0 feat(event-binder.js): Signaturkomponente hinzugefügt, um die Animationen in der Fortschrittsleiste der Signatur zu behandeln
- Befehl zum Erhöhen der Anzahl von Signaturen unter der createAnnotationFrameBlob-Methode in annotation.js hinzugefügt

- Vorzeichenbehafteter Befehl zum Nullsetzen der Zählung unter RESET-case der handleClick-Methode in app.js hinzugefügt
2024-09-25 14:03:05 +02:00
Developer 02
84fa9e6e7c refactor(envelope-locked): Zugriffscode-Panel einrichten 2024-09-25 13:28:47 +02:00
Developer 02
36916ed5c8 refactor(envelope-lcoked): Konvertierung von 'access-code' Floating Input 2024-09-25 11:01:54 +02:00
Developer 02
fb366d3e0b refactor: Umschlag nav-menu bearbeiten. minfied card.css 2024-09-25 09:21:55 +02:00
Developer01
e82be8b6a5 Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2024-09-24 17:26:19 +02:00
Developer01
07320af4ee MS GPicture 2024-09-24 17:26:11 +02:00
Developer 02
73eb270237 refactor(privacy-policy.css); minified 2024-09-23 09:20:38 +02:00
Developer 02
222684cfc8 feat(footer): Zu _Layout.cshtml hinzugefügt. CSS-Trennungen bearbeitet. 2024-09-21 00:10:50 +02:00
Developer 02
3974d2123e refactor(privacy-policy): Umbenennung zur Berücksichtigung von Kulturinformationen. 2024-09-20 17:09:44 +02:00
Developer 02
b837a63b34 refactor(cookie-policy): Unnötiges html entfernen. 2024-09-20 17:02:23 +02:00
Developer 02
461316713a feat(privacy-policy): erstellt in html mit einem separaten css in Deutsch und Englisch 2024-09-20 17:01:00 +02:00
Developer 02
185af3210b core(EnvelopeGenerator.Web): Paket-, Assembly- und Dateiversionen wurden auf 2.0.0.0 aktualisiert. 2024-09-20 15:33:29 +02:00
Developer 02
e4620b5469 refactor (_CookieConsentPartial): Mit Bootstrap bearbeiten:
- Aktualisierte Cookie-Zustimmungsmeldung hinzugefügt
2024-09-20 15:30:14 +02:00
Developer 02
5c4acd17a0 fix(cookie): Fehlerhaften Consent-Cookie-Button entfernt und durch von Microsoft empfohlene Struktur ersetzt
- Den fehlerhaften Consent-Cookie-Button entfernt und die von Microsoft empfohlene Struktur integriert, um die Compliance und Funktionalität zu verbessern.
2024-09-20 13:07:32 +02:00
Developer 02
fc171e5b89 fix(html): Ungültige <div>-Tags aus cshtml entfernt
- Überflüssige <div>-Tags, die während des Merge-Prozesses entstanden sind, entfernt, um die korrekte HTML-Struktur sicherzustellen.
2024-09-20 11:24:59 +02:00
Developer 02
662faf2512 merge: feat/signFlow-gen in Master zusammenführen 2024-09-20 11:16:08 +02:00
Developer 02
2fb8af9a4f chore(api): Core-Bibliotheken und UserManager.Infrastructure auf 2.0.0.0 aktualisiert
- Core-Bibliotheken und UserManager.Infrastructure in den API-Schichten auf Version 2.0.0.0 erhöht.
2024-09-20 11:05:00 +02:00
Developer 02
017d03713b refactor(dbcontext): DbContext aktualisiert, um IUserManagerDbContext zu implementieren und neue DbSets hinzuzufügen
- Implementierung des `IUserManagerDbContext` Interface in `EGDbContext`.
- Neue `DbSet`-Eigenschaften für `GroupOfUser`, `Group`, `ModuleOfUser`, `Module`, `User` und `UserRep` hinzugefügt.
- Neue DbSets im Konstruktor injiziert.
- Namespace-Importe aktualisiert, um zusätzliche Entitäten für die neuen DbSets einzubeziehen.
2024-09-20 09:46:21 +02:00
Developer 02
5f5180d937 chore(application): Core-Bibliotheken und UserManager.Infrastructure auf 2.0.0.0 aktualisiert
- Core-Bibliotheken und `UserManager.Infrastructure` in der Application-Schicht auf Version 2.0.0.0 erhöht.
- DbSet-Eigenschaften aus dem DbContext injiziert.
2024-09-20 09:39:14 +02:00
Developer 02
6b3e6cd6f5 chore(infrastructure): Core-Bibliotheken und UserManager.Infrastructure auf 2.0.0.0 aktualisiert
- Core-Bibliotheken und UserManager.Infrastructure im Infrastructure-Layer auf Version 2.0.0.0 erhöht.
- DbSet-Eigenschaften aus DbContext injiziert.
2024-09-20 01:16:47 +02:00
Developer 02
f95f3c7b1b refactor(dbcontext): DbSet-Erstellung in DbContext verschieben und DbSet-Eigenschaften hinzufügen
- Ersetzt die Erstellung von DbSet pro Entität durch DbSet-Eigenschaften in `EGDbContext`.
- Hinzugefügt DbSet-Eigenschaften für `UserReceiver`, `Config`, `EnvelopeReceiver` und `Envelope`.
- Aktualisierter `EGDbContext`-Konstruktor zur Initialisierung der DbSet-Eigenschaften mittels der `Set<T>`-Methode.
2024-09-19 15:06:33 +02:00
Developer 02
316b62083c feat(core): IUnique-Schnittstelle hinzufügen und Core.Infrastructure aktualisieren
- `IUnique`-Schnittstelle zu allen Entitäten im Domain-Projekt hinzugefügt.
- `Core.Infrastructure` auf Version 2.0.0.0 im Infrastructure-Layer aktualisiert.
- Domain-Projekt mit `Core.Abstraction` für verbesserte Abstraktion erweitert.
2024-09-19 14:48:34 +02:00
Developer 02
530b63f299 fix: Logo korrigiert 2024-09-19 11:27:17 +02:00
Developer 02
2f228de163 feat: Annotationen für Unterschrift, Ort und Datum neu angeordnet 2024-09-19 10:42:25 +02:00
Developer 02
e5e64b25fe merge 2024-09-19 10:38:39 +02:00
Developer 02
2d5dde177c feat: Anordnung der Annotationen für Unterschrift, Stadt und Datum 2024-09-18 00:10:16 +02:00
Developer 02
ce0ad4ba61 fix: Fix bug where access code wasn't requested when flag was false
- Modified logic to ensure a new access code is requested only if it hasn't been previously requested for the specific envelope and receiver combination.
- Prevents unnecessary access code requests, improving system efficiency.
2024-09-17 16:42:45 +02:00
Developer 02
ebd7c5d6a4 feat: Logo-Modell in den App-Einstellungen für CURSOR-AG konfiguriert 2024-09-17 15:47:44 +02:00
Developer 02
341da273c9 feat: Logo-Konfiguration und -Stile für digitale Daten aktualisiert
- `appsettings` mit neuen Logo-Klassen `dd-show-logo` und `dd-locked-logo` aktualisiert.
- `logo.css` angepasst, um die neuen Logo-Dimensionen und responsive Stile hinzuzufügen.
- Alte Klassen `cursor-logo` und `cursor-img` wurden durch `dd-locked-logo` und `dd-show-logo` ersetzt.
2024-09-17 15:36:05 +02:00
Developer 02
73d2a43a95 fix: CSSPath aus Logo entfernt, um CSS-Injection-Sicherheitslücke zu vermeiden
- Die Eigenschaft `CSSPath` wurde aus der `Logo`-Klasse entfernt, um potenzielle CSS-Injection-Risiken zu verhindern.
- Alle logo-bezogenen Stile in einer einheitlichen `logo.css` Datei standardisiert.
2024-09-17 15:01:58 +02:00
Developer 02
eee18889d6 feat: Logo-Bild in EnvelopeLocked.cshtml über Appsettings und Logo-Modell konfiguriert 2024-09-17 14:55:17 +02:00
Developer 02
590d7fb717 feat: Logo-Bild in ShowEnvelope.cshtml über appsettings konfiguriert 2024-09-17 14:50:23 +02:00
Developer 02
dd28ef7ab6 feat: Logo-Konfiguration zu Program.cs und _ViewImports.cshtml hinzugefügt 2024-09-17 14:41:31 +02:00
Developer 02
36fb033adc feat: Hinzugefügt Logo-Konfiguration für verschiedene Kunden 2024-09-17 14:10:27 +02:00
Developer 02
4275f25f4a fix: Logo auf "Digital Data" aktualisieren 2024-09-17 13:52:52 +02:00
Developer 02
b66c2f67da feat: Hinzufügen einer erweiterten Ansicht für die Tabelle im Envelope Generator
- In der Tabelle für Umschläge wurde ein versteckter Abschnitt unter den Zeilen hinzugefügt.
- Beim Klicken auf eine Zeile wird nun ein Detailbereich angezeigt, der Informationen zu Empfänger und Historie des Umschlags zeigt.
2024-09-09 17:30:36 +02:00
Developer 02
d084a4cd81 feat(component): initialisieren des HistoryTableComponent 2024-09-07 01:48:04 +02:00
Developer 02
5d2bf56493 feat(service): Unterstützung von Query-Parametern im HistoryService hinzugefügt
- Methode `getHistory` hinzugefügt, um das Abrufen von History-Daten mit optionalen Query-Parametern wie `envelopeId`, `referenceType`, `userReference`, `withSender` und `withReceiver` zu ermöglichen.
- Methode `getHistoryAsync` implementiert, um History-Daten mit async/await abzurufen.
- `Options`-Interface eingeführt, um optionale Query-Parameter für History-Anfragen zu definieren.
2024-09-07 01:41:19 +02:00
Developer 02
cd88f5c833 refactor(controller): Optimierung der Handhabung von Referenztypen im HistoryController
- `GetAllAsync`-Methode angepasst, um `withSender` oder `withReceiver` automatisch basierend auf dem `ReferenceType` zu setzen.
- Unnötigen `status`-Query-Parameter entfernt, um die API zu vereinfachen.
2024-09-07 01:32:09 +02:00
Developer 02
ab41e25071 feat: Referenztypen zwischen Backend und Frontend standardisieren
- `GetReferenceTypes`-Endpunkt im `HistoryController` hinzugefügt, um Key-Value-Paare des `ReferenceType`-Enums im camelCase-Format bereitzustellen.
- `ConfigurationService` in Angular erweitert, um die `ReferenceType`-Werte vom neuen API-Endpunkt abzurufen und zu speichern.
2024-09-07 01:12:50 +02:00
Developer 02
eb775da7d4 feat(service): HistoryService für API-Interaktionen erstellen 2024-09-07 00:37:54 +02:00
Developer 02
7bc2695da4 feat(controller): add GetAllAsync endpoint to HistoryController
- Added a new `GetAllAsync` method to HistoryController to retrieve envelope histories.
- Included query parameters for filtering by envelopeId, userReference, referenceType, status, and boolean flags for sender and receiver.
- Implemented validation of `referenceType` with `ReferenceType` enum, throwing an error for invalid values.
2024-09-07 00:08:55 +02:00
Developer 02
75fff426bc feat(HistoryController): HistoryController mit Logging und Envelope History Service Integration hinzugefügt 2024-09-06 16:43:42 +02:00
Developer 02
4172df4d78 refactor(EnvelopeTableComponent): onToggleExpandedRow Methode asynchron gemacht, um die Daten mit async/await zu handhaben 2024-09-06 16:38:15 +02:00
Developer 02
01856b61ef feat(EnvelopeReceiverService): Status-Filteroption zu ReadByUserAsync hinzugefügt, um die Ergebnisse nach Status zu filtern 2024-09-06 16:31:49 +02:00
Developer 02
2e32559132 feat(ReceiverStatusTableComponent): Schema für die Tabellenansicht hinzugefügt, einschließlich Name, Email und Zugangscode 2024-09-06 15:42:03 +02:00
Developer 02
9adb49df78 Refaktorisierung von EnvelopeReceiverService und EnvelopeReceiverController
- Methode `ReadSecretByUuidAsync` zu `EnvelopeReceiverService` hinzugefügt, um Geheimnisse anhand der UUID abzurufen.
- Fehlerbehandlung und Protokollierung in den Methoden von `EnvelopeReceiverService` verbessert, einschließlich besserer Handhabung von Sicherheitsvorfällen und Datenintegritätsproblemen.
- `VerifyAccessCodeAsync` aktualisiert, um explizite Nachrichten für Sicherheitsvorfälle und Datenintegritätsprobleme zu enthalten.
- `EnvelopeReceiverController` aktualisiert, um einen neuen Endpunkt `GetSecretAsync` zum Abrufen von Geheimnissen anhand der UUID einzuführen.
- Fehlerbehandlung und Protokollierung in den Methoden von `EnvelopeReceiverController` verbessert.
- Endpunkte angepasst, um die neue Methode `ReadSecretByUuidAsync` in der Servicelogik zu nutzen.
2024-09-06 15:19:18 +02:00
Developer 02
18e21b0a8e feat: Füge EnvelopeReceiverSecretDto zur Handhabung von Zugangscodes hinzu 2024-09-06 14:06:03 +02:00
Developer 02
e1d7d0e141 feat(EnvelopeTableComponent): Methode onToggleExpandedRow hinzugefügt, um Empfänger anhand der Umschlag-UUID abzurufen und anzuzeigen 2024-09-06 13:52:47 +02:00
Developer 02
cfa40e640b feat(EnvelopeReceiverService): Methode getReceiverByEnvelope hinzugefügt, um Empfänger nach Umschlag-UUID abzurufen 2024-09-06 13:11:53 +02:00
Developer 02
cb0a45bc17 feat(EnvelopeReceiverController): füge Methode GetReceiverByEnvelopeAsync hinzu 2024-09-06 13:00:13 +02:00
Developer 02
c7b6e5bf24 feat(EnvelopeReceiverService): füge Methode ReadReceiverByEnvelopeAsync hinzu
- Neue Methode `ReadReceiverByEnvelopeAsync` zur `EnvelopeReceiverService`-Klasse hinzugefügt, um Empfänger anhand der Umschlag-UUID abzurufen.
- Die `EnvelopeReceiverService`-Klasse wurde angepasst, um das Mapping auf `ReceiverReadDto` für die neue Methode zu ermöglichen.
- Die Using-Anweisungen wurden aktualisiert, um das erforderliche DTO (`EnvelopeGenerator.Application.DTOs.Receiver`) für die neue Funktionalität einzubinden.
2024-09-06 12:45:03 +02:00
Developer 02
a9ca1b71eb feat(repository): ReadReceiverByEnvelope Methode zum EnvelopeReceiverRepository hinzugefügt
- Neue Methode ReadReceiverByEnvelope hinzugefügt, um Empfänger zu ermitteln, die mit einem bestimmten Umschlag (identifiziert durch UUID) verknüpft sind.
2024-09-06 12:08:42 +02:00
Developer 02
97f07bc72d feat(envelope): ReceiverStatusTable-Komponente unter Envelope-Tabelle hinzugefügt und Backend-Unterstützung integriert
- ReceiverStatusTableComponent als Unterkomponente der EnvelopeTable erstellt, um Empfängerstatus anzuzeigen.
- ReceiverStatusTable in EnvelopeTable mit Tabs und dynamischem Datenladen integriert.
- EnvelopeTable angepasst, um Empfängerdaten über den EnvelopeReceiverService abzurufen und in ReceiverStatusTable anzuzeigen.
- Backend aktualisiert, um das Abrufen von Umschlägen nach Benutzer zu unterstützen:
  - `ReadByUserAsync`-Methode im Envelope-Repository hinzugefügt, um Umschläge für einen bestimmten Benutzer abzufragen.
  - Servicemethode implementiert, um die abgefragten Umschläge in DTOs zu konvertieren und das Ergebnis zurückzugeben.
2024-09-06 11:32:39 +02:00
Developer 02
8753875d93 chore(envelope): ReceiverStatusTableComponent entfernt 2024-09-06 11:32:22 +02:00
Developer 02
3692aa80a4 feat(services): Hinzufügen des EnvelopeService zur Verarbeitung von API-Anfragen 2024-09-05 11:53:22 +02:00
Developer 02
b8b09ded5d refactor(api): Vereinfachung der GetCurrentAsync-Methode im EnvelopeController 2024-09-05 10:35:35 +02:00
Developer 02
5b8d8b9e55 refactor(api): Aktualisierung von ControllerExtensions zur Nutzung von ClaimsPrincipal anstelle von ControllerBase
- Refactoring der Erweiterungsmethoden, sodass sie auf `ClaimsPrincipal` anstatt auf `ControllerBase` basieren.
- Alle Verweise und Verwendungen dieser Erweiterungsmethoden im gesamten Code aktualisiert.
- Dies verbessert die Flexibilität und entkoppelt das Abrufen von Benutzeransprüchen von den Controllern.
2024-09-05 10:24:00 +02:00
Developer 02
e3fbf4fc77 feat(api): Hinzufügen des EnvelopeControllers mit GetCurrentAsync-Methode zur Umschlagabfrage
- Implementierung des `EnvelopeController` in der Route `api/envelope` mit der Methode `GetCurrentAsync`, um Umschläge basierend auf der Benutzer-ID abzurufen.
- Fehlerbehandlung hinzugefügt, wenn die Benutzer-ID keine Ganzzahl ist, mit einem möglichen Problem bei der Erstellung der Claims-Liste.
2024-09-05 10:15:36 +02:00
Developer 02
8d680992b7 refactor: Selector von EnvelopeTableComponent umbenannt und ReceiverStatusTable integriert
- Selector von `EnvelopeTableComponent` von `app-envelope-table` auf `envelope-table` umbenannt für Konsistenz.
- `<receiver-status-table>` in die `EnvelopeTableComponent` integriert, um Empfängerstatusdaten anzuzeigen.
2024-09-04 16:55:58 +02:00
Developer 02
01247f73f4 refactor: Bibliotheksreferenzen nach Umstrukturierung der Tabellenkomponenten aktualisiert 2024-09-04 16:34:39 +02:00
Developer 02
6a7a3dcb90 refactor: Bibliotheksreferenzen nach Umstrukturierung der Tabellenkomponenten aktualisiert
- Referenzen für einige Bibliotheken angepasst, um die neue Verzeichnisstruktur unter `/tables` zu unterstützen.
- Importpfade entsprechend der Verschiebung der Tabellenkomponenten aktualisiert.
2024-09-04 16:20:06 +02:00
Developer 02
2fbfbb4eb6 feat: ReceiverStatusTable erstellt und Tabellen unter /tables organisiert
- Neue `ReceiverStatusTable`-Komponente zur Anzeige von Empfängerstatus-Daten erstellt.
- Alle bestehenden Tabellenkomponenten unter das Verzeichnis `/tables` verschoben, um die Projektstruktur zu verbessern und die Wartbarkeit zu erhöhen.
2024-09-04 16:16:50 +02:00
Developer 02
f88b5d2733 feat: Erweiterbare Zeilen in EnvelopeTableComponent aktiviert und mat-tab-Komponente integriert
- Aktiviert die Unterstützung für erweiterbare Zeilen in der `EnvelopeTableComponent` durch Setzen der `isExpandable`-Option auf `true`.
- Integriert die `mat-tab-group`-Komponente innerhalb der erweiterten Zeilen für eine bessere Darstellung von Tab-Inhalten.
- Hinzugefügt: Zwei Tabs ("Emfänger" und "History") für die Anzeige von zusätzlichen Informationen in den erweiterten Zeilen.
2024-09-04 15:14:10 +02:00
Developer 02
363358aaa1 feat: Implementieren und integrieren von wiederverwendbaren Angular Material-Tabellenkomponenten
- Erstellen der `DDTable`-Komponente für dynamische Angular Material-Tabellen mit Unterstützung für erweiterbare Zeilen, Filterung, Sortierung und Pagination.
- Ersetzen der bestehenden Tabellenimplementierung in `EnvelopeTableComponent` durch die `DDTable`-Komponente für verbesserte Funktionalität und Wartbarkeit.
- Aktualisieren der `EnvelopeTableComponent`, um `DDTable` für die Anzeige von Umschlagdaten zu verwenden, einschließlich Filter- und Paginierungsoptionen.
- Implementieren von `ClearableInputComponent` für eine verbesserte Filtererfahrung.
- Anpassen des Datenabrufs und -handlings, um die Integration von `DDTable` zu berücksichtigen.
- Verbessern der `EnvelopeTableComponent` mit ordnungsgemäßen Animationstriggern für erweiterbare Zeilen.
2024-09-04 14:58:48 +02:00
Developer 02
7444eeba2a feat(envelope): Envelopes-Datenquelle und Initialisierung angepasst
- `EnvelopeTypeService` und `EnvelopeTypeController` hinzugefügt, um Envelope-Typen im Cache zu speichern und bereitzustellen.
- `ConfigurationService` erstellt und mit `APP_INITIALIZER` konfiguriert, um Envelope-Typen bei der Anwendungserstellung zu laden.
- `EnvelopeTableComponent` aktualisiert, um Envelope-Typen aus der Konfiguration zu verwenden, anstatt hartkodierte Werte zu nutzen.
2024-09-02 14:48:20 +02:00
Developer 02
e9d686a4c1 fix(receiver-table): Problem mit automatischer Anredezuweisung für den ersten hinzugefügten Empfänger behoben
- Bedingung in der Funktion `receiver_filter` aktualisiert, um den Indexwert korrekt zu überprüfen.
2024-09-02 10:48:24 +02:00
Developer 02
939ba1bb47 feat: Sortierung der Tabelle hinzugefügt 2024-08-30 23:38:02 +02:00
Developer 02
d5de868eb9 feat: added filter and paginator 2024-08-30 23:25:22 +02:00
Developer 02
6e3bb6c3a0 feat: Enhance receiver input and table components
- Updated `ReceiverInputComponent` to support optional index parameter in the `filter` function to manage email input logic more effectively.
- Added `last_used_name` functionality in `ReceiverTableComponent` to auto-fill names based on the last used email name.
- Implemented email duplication prevention logic in `ReceiverTableComponent` to ensure unique email inputs.
- Refactored component lifecycle methods and data handling for improved performance and user experience.
2024-08-30 22:25:13 +02:00
Developer 02
d347ec420c feat: ReadAllAsync-Methode zur ReceiverRepository hinzugefügt
- `ReadAllAsync`-Methode hinzugefügt, um alle `Receiver`-Entitäten asynchron zurückzugeben.
- Stellt sicher, dass alle Empfänger abgerufen werden, während die vorhandene Abfragelogik mit `ReadBy` erhalten bleibt.
2024-08-30 11:58:00 +02:00
Developer 02
a011b677ea refactor: EnvelopeReceiver-Klasse refaktoriert, um eine Endlosschleife zu verhindern und die Datenabfrage zu verbessern
- `EnvelopeReceiver` in `EnvelopeReceiver` und `EnvelopeReceiverBase` aufgeteilt, um zirkuläre Abhängigkeiten zu vermeiden.
- `EnvelopeReceiverBasicDto` für vereinfachte Datenübertragungsobjekte erstellt.
- `ReceiverRepository` aktualisiert, um den zuletzt verwendeten Empfängernamen durch das Laden aktueller `EnvelopeReceiver`-Daten einzubeziehen.
- `ReceiverReadDto` angepasst, um `LastUsedName` zu erhalten und `EnvelopeReceivers` für die JSON-Serialisierung zu ignorieren.
2024-08-30 11:27:36 +02:00
Developer 02
8831436809 feat(controller): add endpoint to retrieve last used receiver name by email
- Implemented `Get` endpoint in `EnvelopeReceiverController` to fetch the last used receiver's name by email.
- Added handling for successful and failed responses, including proper status codes and logging.
2024-08-29 17:15:00 +02:00
Developer 02
1ededc1f64 feat(service): add ReadLastUsedReceiverNameByMail method to IEnvelopeReceiverService and EnvelopeReceiverService
- Added `ReadLastUsedReceiverNameByMail` method to `IEnvelopeReceiverService` interface.
- Implemented `ReadLastUsedReceiverNameByMail` method in `EnvelopeReceiverService` to retrieve the last used receiver's name by email and handle results with `DataResult`.
2024-08-29 16:57:45 +02:00
Developer 02
183c94fd0a Merge branch 'master' into feat/signFlow-gen 2024-08-29 16:49:30 +02:00
Developer 02
a0a5568d93 feat(repository): Methode ReadLastByReceiver zu IEnvelopeReceiverRepository und EnvelopeReceiverRepository hinzugefügt
- Methode `ReadLastByReceiver` zum Interface `IEnvelopeReceiverRepository` hinzugefügt.
- Methode `ReadLastByReceiver` in `EnvelopeReceiverRepository` implementiert, um den letzten `EnvelopeReceiver` anhand der E-Mail-Adresse abzurufen.
2024-08-29 16:04:19 +02:00
581 changed files with 3791 additions and 59678 deletions

View File

@@ -0,0 +1,13 @@
namespace EnvelopeGenerator.Application.Configurations
{
public class DispatcherConfig
{
public int SendingProfile { get; init; } = 1;
public string AddedWho { get; init; } = "DDEnvelopGenerator";
public int ReminderTypeId { get; init; } = 202377;
public string EmailAttmt1 { get; init; } = string.Empty;
}
}

View File

@@ -0,0 +1,7 @@
namespace EnvelopeGenerator.Application.Configurations
{
public class MailConfig
{
public required Dictionary<string, string> Placeholders { get; init; }
}
}

View File

@@ -5,7 +5,7 @@ using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts namespace EnvelopeGenerator.Application.Contracts
{ {
public interface IConfigService : IBasicCRUDService<ConfigDto, Config, int> public interface IConfigService : IReadService<ConfigDto, Config, int>
{ {
Task<DataResult<ConfigDto>> ReadFirstAsync(); Task<DataResult<ConfigDto>> ReadFirstAsync();

View File

@@ -3,7 +3,6 @@ using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory; using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.Receiver; using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using static EnvelopeGenerator.Common.Constants; using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Application.Contracts namespace EnvelopeGenerator.Application.Contracts

View File

@@ -1,6 +1,7 @@
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts; using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
using EnvelopeGenerator.Common; using EnvelopeGenerator.Common;
namespace EnvelopeGenerator.Application.Contracts namespace EnvelopeGenerator.Application.Contracts
@@ -8,6 +9,9 @@ namespace EnvelopeGenerator.Application.Contracts
public interface IEnvelopeMailService : IEmailOutService public interface IEnvelopeMailService : IEmailOutService
{ {
Task<DataResult<int>> SendAsync(EnvelopeReceiverDto envelopeReceiverDto, Constants.EmailTemplateType tempType); Task<DataResult<int>> SendAsync(EnvelopeReceiverDto envelopeReceiverDto, Constants.EmailTemplateType tempType);
Task<DataResult<int>> SendAsync(EnvelopeReceiverReadOnlyDto dto);
Task<DataResult<int>> SendAccessCodeAsync(EnvelopeReceiverDto envelopeReceiverDto); Task<DataResult<int>> SendAccessCodeAsync(EnvelopeReceiverDto envelopeReceiverDto);
} }
} }

View File

@@ -0,0 +1,10 @@
using DigitalData.Core.Abstractions.Application;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts
{
public interface IEnvelopeReceiverReadOnlyService : ICRUDService<EnvelopeReceiverReadOnlyCreateDto, EnvelopeReceiverReadOnlyDto, EnvelopeReceiverReadOnlyUpdateDto, EnvelopeReceiverReadOnly, long>
{
}
}

View File

@@ -1,15 +1,18 @@
using DigitalData.Core.Abstractions.Application; using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts namespace EnvelopeGenerator.Application.Contracts
{ {
public interface IEnvelopeReceiverService : IBasicCRUDService<EnvelopeReceiverDto, EnvelopeReceiver, object> public interface IEnvelopeReceiverService : IBasicCRUDService<EnvelopeReceiverDto, EnvelopeReceiver, (int Envelope, int Receiver)>
{ {
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false); Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false);
Task<DataResult<IEnumerable<EnvelopeReceiverSecretDto>>> ReadSecretByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true);
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true); Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true);
Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true); Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true);
@@ -25,5 +28,7 @@ namespace EnvelopeGenerator.Application.Contracts
Task<DataResult<bool>> IsExisting(string envelopeReceiverId); Task<DataResult<bool>> IsExisting(string envelopeReceiverId);
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses); Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
Task<DataResult<string?>> ReadLastUsedReceiverNameByMail(string mail);
} }
} }

View File

@@ -2,7 +2,6 @@
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Application.Contracts namespace EnvelopeGenerator.Application.Contracts
{ {
@@ -11,5 +10,7 @@ namespace EnvelopeGenerator.Application.Contracts
Task<DataResult<IEnumerable<EnvelopeDto>>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false); Task<DataResult<IEnumerable<EnvelopeDto>>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false);
Task<DataResult<EnvelopeDto>> ReadByUuidAsync(string uuid, bool withDocuments = false, bool withHistory = false, bool withDocumentReceiverElement = false, bool withUser = false, bool withAll = false); Task<DataResult<EnvelopeDto>> ReadByUuidAsync(string uuid, bool withDocuments = false, bool withHistory = false, bool withDocumentReceiverElement = false, bool withUser = false, bool withAll = false);
Task<DataResult<IEnumerable<EnvelopeDto>>> ReadByUserAsync(int userId, int? min_status = null, int? max_status = null, params int[]ignore_statuses);
} }
} }

View File

@@ -1,7 +1,6 @@
using DigitalData.Core.Abstractions.Application; using DigitalData.Core.Abstractions.Application;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Application.Contracts namespace EnvelopeGenerator.Application.Contracts
{ {

View File

@@ -1,21 +1,18 @@
using DigitalData.UserManager.Application.MappingProfiles; using DigitalData.UserManager.Application.MappingProfiles;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.MappingProfiles; using EnvelopeGenerator.Application.MappingProfiles;
using EnvelopeGenerator.Application.Configurations;
using EnvelopeGenerator.Application.Services; using EnvelopeGenerator.Application.Services;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Infrastructure.Repositories; using EnvelopeGenerator.Infrastructure.Repositories;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace EnvelopeGenerator.Application namespace EnvelopeGenerator.Application
{ {
public static class DIExtensions public static class DIExtensions
{ {
public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services) public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfiguration dispatcherConfigSection, IConfiguration mailConfigSection)
{ {
//Inject CRUD Service and repositoriesad //Inject CRUD Service and repositoriesad
services.AddScoped<IConfigRepository, ConfigRepository>(); services.AddScoped<IConfigRepository, ConfigRepository>();
@@ -33,6 +30,7 @@ namespace EnvelopeGenerator.Application
services.AddScoped<IEnvelopeTypeRepository, EnvelopeTypeRepository>(); services.AddScoped<IEnvelopeTypeRepository, EnvelopeTypeRepository>();
services.AddScoped<IReceiverRepository, ReceiverRepository>(); services.AddScoped<IReceiverRepository, ReceiverRepository>();
services.AddScoped<IUserReceiverRepository, UserReceiverRepository>(); services.AddScoped<IUserReceiverRepository, UserReceiverRepository>();
services.AddScoped<IEnvelopeReceiverReadOnlyRepository, EnvelopeReceiverReadOnlyRepository>();
services.AddScoped<IConfigService, ConfigService>(); services.AddScoped<IConfigService, ConfigService>();
services.AddScoped<IDocumentReceiverElementService, DocumentReceiverElementService>(); services.AddScoped<IDocumentReceiverElementService, DocumentReceiverElementService>();
services.AddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>(); services.AddScoped<IEnvelopeDocumentService, EnvelopeDocumentService>();
@@ -46,12 +44,20 @@ namespace EnvelopeGenerator.Application
services.AddScoped<IEnvelopeTypeService, EnvelopeTypeService>(); services.AddScoped<IEnvelopeTypeService, EnvelopeTypeService>();
services.AddScoped<IReceiverService, ReceiverService>(); services.AddScoped<IReceiverService, ReceiverService>();
services.AddScoped<IUserReceiverService, UserReceiverService>(); services.AddScoped<IUserReceiverService, UserReceiverService>();
services.AddScoped<IEnvelopeReceiverReadOnlyService, EnvelopeReceiverReadOnlyService>();
//Auto mapping profiles //Auto mapping profiles
services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly); services.AddAutoMapper(typeof(BasicDtoMappingProfile).Assembly);
services.AddAutoMapper(typeof(UserMappingProfile).Assembly); services.AddAutoMapper(typeof(UserMappingProfile).Assembly);
services.Configure<DispatcherConfig>(dispatcherConfigSection);
services.Configure<MailConfig>(mailConfigSection);
return services; return services;
} }
public static IServiceCollection AddEnvelopeGenerator(this IServiceCollection services, IConfiguration config) => services.AddEnvelopeGenerator(
dispatcherConfigSection: config.GetSection("DispatcherConfig"),
mailConfigSection: config.GetSection("MailConfig"));
} }
} }

View File

@@ -1,4 +1,7 @@
namespace EnvelopeGenerator.Application.DTOs using DigitalData.Core.Abstractions;
using System.Text.Json.Serialization;
namespace EnvelopeGenerator.Application.DTOs
{ {
public record ConfigDto( public record ConfigDto(
string DocumentPath, string DocumentPath,
@@ -8,5 +11,10 @@
string ExportPath, string ExportPath,
string DocumentPathDmz, string DocumentPathDmz,
string ExportPathDmz, string ExportPathDmz,
string DocumentPathMoveAftsend); string DocumentPathMoveAftsend) : IUnique<int>
{
[JsonIgnore]
[Obsolete("Configuration does not have an ID; it represents a single table in the database.")]
public int Id => throw new InvalidOperationException("This configuration does not support an ID as it represents a single row in the database.");
};
} }

View File

@@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{ {
public record DocumentReceiverElementDto( public record DocumentReceiverElementDto(
int Id, int Id,
@@ -18,5 +20,5 @@
DateTime? ChangedWhen, DateTime? ChangedWhen,
double Top, double Top,
double Left double Left
); ): IUnique<int>;
} }

View File

@@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{ {
public record DocumentStatusDto( public record DocumentStatusDto(
int Id, int Id,
@@ -8,5 +10,5 @@
DateTime? StatusChangedWhen, DateTime? StatusChangedWhen,
string Value, string Value,
DateTime AddedWhen, DateTime AddedWhen,
DateTime? ChangedWhen); DateTime? ChangedWhen) : IUnique<int>;
} }

View File

@@ -1,8 +1,10 @@
namespace EnvelopeGenerator.Application.DTOs using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{ {
public record EmailTemplateDto( public record EmailTemplateDto(
int Id, int Id,
string Name, string Name,
string Body, string Body,
string Subject); string Subject) : IUnique<int>;
} }

View File

@@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{ {
public record EnvelopeCertificateDto( public record EnvelopeCertificateDto(
int Id, int Id,
@@ -8,5 +10,5 @@
int CreatorId, int CreatorId,
string CreatorName, string CreatorName,
string CreatorEmail, string CreatorEmail,
int EnvelopeStatus); int EnvelopeStatus) : IUnique<int>;
} }

View File

@@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{ {
public record EnvelopeDocumentDto public record EnvelopeDocumentDto
( (
@@ -6,5 +8,5 @@
int EnvelopeId, int EnvelopeId,
DateTime AddedWhen, DateTime AddedWhen,
IEnumerable<DocumentReceiverElementDto>? Elements IEnumerable<DocumentReceiverElementDto>? Elements
); ) : IUnique<int>;
} }

View File

@@ -1,10 +1,11 @@
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes; using DigitalData.Core.Abstractions;
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using DigitalData.UserManager.Application.DTOs.User; using DigitalData.UserManager.Application.DTOs.User;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.DTOs namespace EnvelopeGenerator.Application.DTOs
{ {
public record EnvelopeDto() public record EnvelopeDto() : IUnique<int>
{ {
public int Id { get; set; } public int Id { get; set; }

View File

@@ -1,4 +1,5 @@
using DigitalData.Core.DTO; using DigitalData.Core.Abstractions;
using DigitalData.Core.DTO;
using DigitalData.UserManager.Application.DTOs.User; using DigitalData.UserManager.Application.DTOs.User;
using EnvelopeGenerator.Application.DTOs.Receiver; using EnvelopeGenerator.Application.DTOs.Receiver;
using static EnvelopeGenerator.Common.Constants; using static EnvelopeGenerator.Common.Constants;
@@ -10,10 +11,11 @@ namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
int EnvelopeId, int EnvelopeId,
string UserReference, string UserReference,
int Status, int Status,
string? StatusName,
DateTime AddedWhen, DateTime AddedWhen,
DateTime? ActionDate, DateTime? ActionDate,
UserCreateDto? Sender, UserCreateDto? Sender,
ReceiverReadDto? Receiver, ReceiverReadDto? Receiver,
ReferenceType ReferenceType, ReferenceType ReferenceType,
string? Comment = null) : BaseDTO<long>(Id); string? Comment = null) : BaseDTO<long>(Id), IUnique<long>;
} }

View File

@@ -0,0 +1,29 @@
using DigitalData.Core.Abstractions;
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
{
public record EnvelopeReceiverBasicDto() : IUnique<(int Envelope, int Receiver)>
{
public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId);
public int EnvelopeId { get; init; }
public int ReceiverId { get; init; }
public int Sequence { get; init; }
[TemplatePlaceholder("[NAME_RECEIVER]")]
public string? Name { get; init; }
public string? JobTitle { get; init; }
public string? CompanyName { get; init; }
public string? PrivateMessage { get; init; }
public DateTime AddedWhen { get; init; }
public DateTime? ChangedWhen { get; init; }
}
}

View File

@@ -0,0 +1,11 @@
using EnvelopeGenerator.Application.DTOs.Receiver;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
{
public record EnvelopeReceiverDto() : EnvelopeReceiverBasicDto()
{
public EnvelopeDto? Envelope { get; set; }
public ReceiverReadDto? Receiver { get; set; }
}
}

View File

@@ -0,0 +1,4 @@
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiver
{
public record EnvelopeReceiverSecretDto(string? AccessCode) : EnvelopeReceiverDto;
}

View File

@@ -1,31 +0,0 @@
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using EnvelopeGenerator.Application.DTOs.Receiver;
namespace EnvelopeGenerator.Application.DTOs
{
public record EnvelopeReceiverDto()
{
public int EnvelopeId { get; set; }
public int ReceiverId { get; set; }
public int Sequence { get; set; }
[TemplatePlaceholder("[NAME_RECEIVER]")]
public string? Name { get; set; }
public string? JobTitle { get; set; }
public string? CompanyName { get; set; }
public string? PrivateMessage { get; set; }
public DateTime AddedWhen { get; set; }
public DateTime? ChangedWhen { get; set; }
public EnvelopeDto? Envelope { get; set; }
public ReceiverReadDto? Receiver { get; set; }
}
}

View File

@@ -0,0 +1,22 @@
using System.ComponentModel.DataAnnotations;
using System.Text.Json.Serialization;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
{
public record EnvelopeReceiverReadOnlyCreateDto(
DateTime DateValid)
{
[EmailAddress]
[Required]
public required string ReceiverMail { get; init; }
[JsonIgnore]
public long? EnvelopeId { get; set; } = null;
[JsonIgnore]
public string? AddedWho { get; set; }
[JsonIgnore]
public DateTime AddedWhen { get; } = DateTime.Now;
};
}

View File

@@ -0,0 +1,16 @@
using EnvelopeGenerator.Application.DTOs.Receiver;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
{
public record EnvelopeReceiverReadOnlyDto(
long Id,
long EnvelopeId,
string ReceiverMail,
DateTime DateValid,
DateTime AddedWhen,
string AddedWho,
EnvelopeDto? Envelope = null,
string? ChangedWho = null,
DateTime? ChangedWhen = null,
ReceiverReadDto? Receiver = null);
}

View File

@@ -0,0 +1,12 @@
using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly
{
public record EnvelopeReceiverReadOnlyUpdateDto(
long Id,
DateTime DateValid,
string ChangedWho) : IUnique<long>
{
public DateTime ChangedWhen { get; } = DateTime.Now;
};
}

View File

@@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{ {
public record EnvelopeTypeDto( public record EnvelopeTypeDto(
int Id, int Id,
@@ -15,5 +17,5 @@
bool? SendReminderEmails, bool? SendReminderEmails,
int? FirstReminderDays, int? FirstReminderDays,
int? ReminderIntervalDays, int? ReminderIntervalDays,
int? ContractType); int? ContractType) : IUnique<int>;
} }

View File

@@ -1,4 +1,6 @@
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using System.Text.Json.Serialization;
namespace EnvelopeGenerator.Application.DTOs.Receiver namespace EnvelopeGenerator.Application.DTOs.Receiver
{ {
@@ -6,6 +8,12 @@ namespace EnvelopeGenerator.Application.DTOs.Receiver
int Id, int Id,
string EmailAddress, string EmailAddress,
string Signature, string Signature,
DateTime AddedWhen DateTime AddedWhen
) : BaseDTO<int>(Id); ) : BaseDTO<int>(Id)
{
[JsonIgnore]
public IEnumerable<EnvelopeReceiverBasicDto>? EnvelopeReceivers { get; init; }
public string? LastUsedName => EnvelopeReceivers?.LastOrDefault()?.Name;
};
} }

View File

@@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs.Receiver using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs.Receiver
{ {
public record ReceiverUpdateDto(); public record ReceiverUpdateDto(int Id) : IUnique<int>;
} }

View File

@@ -1,4 +1,6 @@
namespace EnvelopeGenerator.Application.DTOs using DigitalData.Core.Abstractions;
namespace EnvelopeGenerator.Application.DTOs
{ {
public record UserReceiverDto( public record UserReceiverDto(
int Id, int Id,
@@ -7,5 +9,5 @@
string Name, string Name,
string CompanyName, string CompanyName,
string JobTitle, string JobTitle,
DateTime AddedWhen); DateTime AddedWhen) : IUnique<int>;
} }

View File

@@ -1,13 +0,0 @@
namespace EnvelopeGenerator.Application
{
public class DispatcherConfig
{
public int SendingProfile { get; init; } = 1;
public string AddedWho { get; init; } = "DDEnvelopGenerator";
public int ReminderTypeId { get; init; } = 202377;
public string EmailAttmt1 { get; init; } = string.Empty;
}
}

View File

@@ -12,16 +12,17 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" /> <PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="1.0.1.1" /> <PackageReference Include="DigitalData.Core.Abstractions" Version="2.0.0" />
<PackageReference Include="DigitalData.Core.Application" Version="1.0.0" /> <PackageReference Include="DigitalData.Core.Application" Version="2.0.0" />
<PackageReference Include="DigitalData.Core.DTO" Version="1.0.0" /> <PackageReference Include="DigitalData.Core.DTO" Version="2.0.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="1.0.0" /> <PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="2.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" /> <PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" />
<PackageReference Include="UserManager.Application" Version="1.0.0" /> <PackageReference Include="UserManager.Application" Version="2.0.0" />
<PackageReference Include="UserManager.Infrastructure" Version="1.0.0" /> <PackageReference Include="UserManager.Infrastructure" Version="2.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Extensions\EnvelopeGenerator.Extensions.csproj" />
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" /> <ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
</ItemGroup> </ItemGroup>

View File

@@ -1,6 +1,8 @@
using AutoMapper; using AutoMapper;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory; using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
using EnvelopeGenerator.Application.DTOs.Receiver; using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
@@ -21,11 +23,13 @@ namespace EnvelopeGenerator.Application.MappingProfiles
CreateMap<EnvelopeHistory, EnvelopeHistoryDto>(); CreateMap<EnvelopeHistory, EnvelopeHistoryDto>();
CreateMap<EnvelopeHistory, EnvelopeHistoryCreateDto>(); CreateMap<EnvelopeHistory, EnvelopeHistoryCreateDto>();
CreateMap<EnvelopeReceiver, EnvelopeReceiverDto>(); CreateMap<EnvelopeReceiver, EnvelopeReceiverDto>();
CreateMap<EnvelopeReceiver, EnvelopeReceiverSecretDto>();
CreateMap<EnvelopeType, EnvelopeTypeDto>(); CreateMap<EnvelopeType, EnvelopeTypeDto>();
CreateMap<Receiver, ReceiverReadDto>(); CreateMap<Receiver, ReceiverReadDto>();
CreateMap<Receiver, ReceiverCreateDto>(); CreateMap<Receiver, ReceiverCreateDto>();
CreateMap<Receiver, ReceiverUpdateDto>(); CreateMap<Receiver, ReceiverUpdateDto>();
CreateMap<UserReceiver, UserReceiverDto>(); CreateMap<UserReceiver, UserReceiverDto>();
CreateMap<EnvelopeReceiverReadOnly, EnvelopeReceiverReadOnlyDto>();
// DTO to Entity mappings // DTO to Entity mappings
CreateMap<ConfigDto, Config>(); CreateMap<ConfigDto, Config>();
@@ -43,6 +47,9 @@ namespace EnvelopeGenerator.Application.MappingProfiles
CreateMap<ReceiverCreateDto, Receiver>(); CreateMap<ReceiverCreateDto, Receiver>();
CreateMap<ReceiverUpdateDto, Receiver>(); CreateMap<ReceiverUpdateDto, Receiver>();
CreateMap<UserReceiverDto, UserReceiver>(); CreateMap<UserReceiverDto, UserReceiver>();
CreateMap<EnvelopeReceiverBase, EnvelopeReceiverBasicDto>();
CreateMap<EnvelopeReceiverReadOnlyCreateDto, EnvelopeReceiverReadOnly>();
CreateMap<EnvelopeReceiverReadOnlyUpdateDto, EnvelopeReceiverReadOnly>();
} }
} }
} }

View File

@@ -177,6 +177,9 @@
<data name="LockedTitle" xml:space="preserve"> <data name="LockedTitle" xml:space="preserve">
<value>Dokument erfordert einen Zugriffscode</value> <value>Dokument erfordert einen Zugriffscode</value>
</data> </data>
<data name="ReadOnlyMessage" xml:space="preserve">
<value>Weitergeleitet von {0}. Gültig bis {1}.</value>
</data>
<data name="Reject" xml:space="preserve"> <data name="Reject" xml:space="preserve">
<value>Ablehnen</value> <value>Ablehnen</value>
</data> </data>

View File

@@ -177,6 +177,9 @@
<data name="LockedTitle" xml:space="preserve"> <data name="LockedTitle" xml:space="preserve">
<value>Document requires an access code</value> <value>Document requires an access code</value>
</data> </data>
<data name="ReadOnlyMessage" xml:space="preserve">
<value>Forwarded by {0}. Valid until {1}.</value>
</data>
<data name="Reject" xml:space="preserve"> <data name="Reject" xml:space="preserve">
<value>Reject</value> <value>Reject</value>
</data> </data>

View File

@@ -3,15 +3,13 @@ using DigitalData.Core.Application;
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.Extensions.Caching.Memory; using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.Services namespace EnvelopeGenerator.Application.Services
{ {
public class ConfigService : BasicCRUDService<IConfigRepository, ConfigDto, Config, int>, IConfigService public class ConfigService : ReadService<IConfigRepository, ConfigDto, Config, int>, IConfigService
{ {
private static readonly Guid DefaultConfigCacheId = Guid.NewGuid(); private static readonly Guid DefaultConfigCacheId = Guid.NewGuid();
@@ -28,7 +26,7 @@ namespace EnvelopeGenerator.Application.Services
var config = await _repository.ReadFirstAsync(); var config = await _repository.ReadFirstAsync();
return config is null return config is null
? Result.Fail<ConfigDto>().Notice(LogLevel.Error, Flag.DataIntegrityIssue, "There is no configuration in DB.") ? Result.Fail<ConfigDto>().Notice(LogLevel.Error, Flag.DataIntegrityIssue, "There is no configuration in DB.")
: Result.Success(_mapper.MapOrThrow<ConfigDto>(config)); : Result.Success(_mapper.Map<ConfigDto>(config));
} }
/// <summary> /// <summary>

View File

@@ -2,10 +2,8 @@
using DigitalData.Core.Application; using DigitalData.Core.Application;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.Extensions.Localization;
namespace EnvelopeGenerator.Application.Services namespace EnvelopeGenerator.Application.Services
{ {

View File

@@ -2,10 +2,8 @@
using DigitalData.Core.Application; using DigitalData.Core.Application;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.Extensions.Localization;
namespace EnvelopeGenerator.Application.Services namespace EnvelopeGenerator.Application.Services
{ {

View File

@@ -1,11 +1,9 @@
using AutoMapper; using AutoMapper;
using DigitalData.Core.Application; using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Application.Resources;
using static EnvelopeGenerator.Common.Constants; using static EnvelopeGenerator.Common.Constants;
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
@@ -26,7 +24,7 @@ namespace EnvelopeGenerator.Application.Services
? Result.Fail<EmailTemplateDto>() ? Result.Fail<EmailTemplateDto>()
.Message(Key.InnerServiceError) .Message(Key.InnerServiceError)
.Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"EmailTemplateType '{type}' is not found in DB. Please, define required e-mail template.") .Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"EmailTemplateType '{type}' is not found in DB. Please, define required e-mail template.")
: Result.Success(_mapper.MapOrThrow<EmailTemplateDto>(temp)); : Result.Success(_mapper.Map<EmailTemplateDto>(temp));
} }
} }
} }

View File

@@ -1,11 +1,9 @@
using AutoMapper; using AutoMapper;
using DigitalData.Core.Application; using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
using static EnvelopeGenerator.Common.Constants; using static EnvelopeGenerator.Common.Constants;
using EnvelopeGenerator.Application.Resources;
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory; using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.Receiver; using EnvelopeGenerator.Application.DTOs.Receiver;
@@ -14,7 +12,7 @@ namespace EnvelopeGenerator.Application.Services
{ {
public class EnvelopeHistoryService : CRUDService<IEnvelopeHistoryRepository, EnvelopeHistoryCreateDto, EnvelopeHistoryDto, EnvelopeHistoryDto, EnvelopeHistory, long>, IEnvelopeHistoryService public class EnvelopeHistoryService : CRUDService<IEnvelopeHistoryRepository, EnvelopeHistoryCreateDto, EnvelopeHistoryDto, EnvelopeHistoryDto, EnvelopeHistory, long>, IEnvelopeHistoryService
{ {
public EnvelopeHistoryService(IEnvelopeHistoryRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper) public EnvelopeHistoryService(IEnvelopeHistoryRepository repository, IMapper mapper)
: base(repository, mapper) : base(repository, mapper)
{ {
} }
@@ -53,7 +51,7 @@ namespace EnvelopeGenerator.Application.Services
public async Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null, bool withSender = false, bool withReceiver = false) public async Task<IEnumerable<EnvelopeHistoryDto>> ReadAsync(int? envelopeId = null, string? userReference = null, ReferenceType? referenceType = null, int? status = null, bool withSender = false, bool withReceiver = false)
{ {
var histDTOs = _mapper.MapOrThrow<IEnumerable<EnvelopeHistoryDto>>( var histDTOs = _mapper.Map<IEnumerable<EnvelopeHistoryDto>>(
await _repository.ReadAsync( await _repository.ReadAsync(
envelopeId: envelopeId, envelopeId: envelopeId,
userReference: userReference, userReference: userReference,

View File

@@ -3,56 +3,68 @@ using DigitalData.Core.DTO;
using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts; using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts;
using DigitalData.EmailProfilerDispatcher.Abstraction.DTOs.EmailOut; using DigitalData.EmailProfilerDispatcher.Abstraction.DTOs.EmailOut;
using DigitalData.EmailProfilerDispatcher.Abstraction.Services; using DigitalData.EmailProfilerDispatcher.Abstraction.Services;
using DigitalData.UserManager.Application;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Common; using EnvelopeGenerator.Common;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using static EnvelopeGenerator.Common.Constants; using static EnvelopeGenerator.Common.Constants;
using EnvelopeGenerator.Extensions;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
using EnvelopeGenerator.Application.Configurations;
namespace EnvelopeGenerator.Application.Services namespace EnvelopeGenerator.Application.Services
{ {
public class EnvelopeMailService : EmailOutService, IEnvelopeMailService public class EnvelopeMailService : EmailOutService, IEnvelopeMailService
{ {
private readonly IEmailTemplateService _tempService; private readonly IEmailTemplateService _tempService;
private readonly IEnvelopeReceiverService _envRcvService; private readonly IEnvelopeReceiverService _envRcvService;
private readonly DispatcherConfig _dConfig; private readonly DispatcherConfig _dConfig;
private readonly IConfigService _configService; private readonly IConfigService _configService;
private readonly Dictionary<string, string> _placeholders;
public EnvelopeMailService(IEmailOutRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper, IEmailTemplateService tempService, IEnvelopeReceiverService envelopeReceiverService, IOptions<DispatcherConfig> dispatcherConfigOptions, IConfigService configService) : base(repository, mapper) public EnvelopeMailService(IEmailOutRepository repository, IMapper mapper, IEmailTemplateService tempService, IEnvelopeReceiverService envelopeReceiverService, IOptions<DispatcherConfig> dispatcherConfigOptions, IConfigService configService, IOptions<MailConfig> mailConfig) : base(repository, mapper)
{ {
_tempService = tempService; _tempService = tempService;
_envRcvService = envelopeReceiverService; _envRcvService = envelopeReceiverService;
_dConfig = dispatcherConfigOptions.Value; _dConfig = dispatcherConfigOptions.Value;
_configService = configService; _configService = configService;
_placeholders = mailConfig.Value.Placeholders;
} }
//TODO: create ioptions and implement TemplatePlaceHolderAttribute instead of this method private async Task<Dictionary<string, string>> CreatePlaceholders(string? accessCode = null, EnvelopeReceiverDto? envelopeReceiverDto = null, EnvelopeReceiverReadOnlyDto? readOnlyDto = null)
private async Task<Dictionary<string, string>> CreatePlaceholders(string? accessCode = null, EnvelopeReceiverDto? envelopeReceiverDto = null)
{ {
Dictionary<string, string> placeholders = new() {
{ "[NAME_PORTAL]", "signFlow" },
{ "[SIGNATURE_TYPE]" , "signieren"},
{ "[REASON]", string.Empty } };
if (accessCode is not null) if (accessCode is not null)
placeholders["[DOCUMENT_ACCESS_CODE]"] = accessCode; _placeholders["[DOCUMENT_ACCESS_CODE]"] = accessCode;
if(envelopeReceiverDto is not null && envelopeReceiverDto.Envelope is not null && envelopeReceiverDto.Receiver is not null) if(envelopeReceiverDto?.Envelope is not null && envelopeReceiverDto.Receiver is not null)
{ {
var erId = (envelopeReceiverDto.Envelope.Uuid, envelopeReceiverDto.Receiver.Signature).EncodeEnvelopeReceiverId(); var erId = (envelopeReceiverDto.Envelope.Uuid, envelopeReceiverDto.Receiver.Signature).EncodeEnvelopeReceiverId();
var sigHost = await _configService.ReadDefaultSignatureHost(); var sigHost = await _configService.ReadDefaultSignatureHost();
var linkToDoc = $"{sigHost}/envelope/{erId}"; var linkToDoc = $"{sigHost}/EnvelopeKey/{erId}";
placeholders["[LINK_TO_DOCUMENT]"] = linkToDoc; _placeholders["[LINK_TO_DOCUMENT]"] = linkToDoc;
placeholders["[LINK_TO_DOCUMENT_TEXT]"] = linkToDoc[..Math.Min(40, linkToDoc.Length)]; _placeholders["[LINK_TO_DOCUMENT_TEXT]"] = linkToDoc[..Math.Min(40, linkToDoc.Length)] + "..";
} }
return placeholders; return _placeholders;
} }
public async Task<DataResult<int>> SendAccessCodeAsync(EnvelopeReceiverDto dto) => await SendAsync(dto: dto, tempType: Constants.EmailTemplateType.DocumentAccessCodeReceived); private async Task<Dictionary<string, string>> CreatePlaceholders(EnvelopeReceiverReadOnlyDto? readOnlyDto = null)
{
if (readOnlyDto?.Envelope is not null && readOnlyDto.Receiver is not null)
{
_placeholders["[NAME_RECEIVER]"] = await _envRcvService.ReadLastUsedReceiverNameByMail(readOnlyDto.AddedWho).ThenAsync(res => res, (msg, ntc) => string.Empty) ?? string.Empty;
var erReadOnlyId = (readOnlyDto.Id).EncodeEnvelopeReceiverId();
var sigHost = await _configService.ReadDefaultSignatureHost();
var linkToDoc = $"{sigHost}/EnvelopeKey/{erReadOnlyId}";
_placeholders["[LINK_TO_DOCUMENT]"] = linkToDoc;
_placeholders["[LINK_TO_DOCUMENT_TEXT]"] = linkToDoc[..Math.Min(40, linkToDoc.Length)] + "..";
}
return _placeholders;
}
public async Task<DataResult<int>> SendAccessCodeAsync(EnvelopeReceiverDto dto) => await SendAsync(dto: dto, tempType: Constants.EmailTemplateType.DocumentAccessCodeReceived);
public async Task<DataResult<int>> SendAsync(EnvelopeReceiverDto dto, Constants.EmailTemplateType tempType) public async Task<DataResult<int>> SendAsync(EnvelopeReceiverDto dto, Constants.EmailTemplateType tempType)
{ {
@@ -92,8 +104,43 @@ namespace EnvelopeGenerator.Application.Services
var placeholders = await CreatePlaceholders(accessCode: accessCode, envelopeReceiverDto: dto); var placeholders = await CreatePlaceholders(accessCode: accessCode, envelopeReceiverDto: dto);
//TODO: remove the requirement to add the models using reflections
return await CreateWithTemplateAsync(createDto: mail,placeholders: placeholders, return await CreateWithTemplateAsync(createDto: mail,placeholders: placeholders,
dto, dto.Envelope.User!, dto.Envelope); dto, dto.Envelope.User!, dto.Envelope);
} }
}
public async Task<DataResult<int>> SendAsync(EnvelopeReceiverReadOnlyDto dto)
{
var tempSerResult = await _tempService.ReadByNameAsync(Constants.EmailTemplateType.DocumentShared);
if (tempSerResult.IsFailed)
return tempSerResult.ToFail<int>().Notice(LogLevel.Error, Flag.DataIntegrityIssue, $"The email cannot send because '{Constants.EmailTemplateType.DocumentShared}' template cannot found.");
var temp = tempSerResult.Data;
var mail = new EmailOutCreateDto()
{
EmailAddress = dto.ReceiverMail,
EmailSubj = temp.Subject,
EmailBody = temp.Body,
//TODO: remove int casting when all
ReferenceId = (int) dto.EnvelopeId, //REFERENCE_ID = ENVELOPE_ID
ReferenceString = dto.Envelope!.Uuid, //REFERENCE_STRING = ENVELOPE_UUID
//receiver_name = receiver.name,
//receiver_access_code = receiver.access_code,
//sender_adress = envelope.user.email,
//sender_name = envelope.user.full_name,
//envelope_title = envelope.title,
ReminderTypeId = _dConfig.ReminderTypeId,
SendingProfile = _dConfig.SendingProfile,
EntityId = null,
WfId = (int)EnvelopeStatus.EnvelopeShared,
WfReference = null,
AddedWho = _dConfig.AddedWho,
EmailAttmt1 = _dConfig.EmailAttmt1
};
var placeholders = await CreatePlaceholders(readOnlyDto: dto);
return await CreateWithTemplateAsync(createDto: mail, placeholders: placeholders, dto.Envelope);
}
}
} }

View File

@@ -0,0 +1,16 @@
using AutoMapper;
using DigitalData.Core.Application;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs.EnvelopeReceiverReadOnly;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
namespace EnvelopeGenerator.Application.Services
{
public class EnvelopeReceiverReadOnlyService : CRUDService<IEnvelopeReceiverReadOnlyRepository, EnvelopeReceiverReadOnlyCreateDto, EnvelopeReceiverReadOnlyDto, EnvelopeReceiverReadOnlyUpdateDto, EnvelopeReceiverReadOnly, long>, IEnvelopeReceiverReadOnlyService
{
public EnvelopeReceiverReadOnlyService(IEnvelopeReceiverReadOnlyRepository repository, IMapper mapper) : base(repository, mapper)
{
}
}
}

View File

@@ -2,16 +2,17 @@
using DigitalData.Core.Application; using DigitalData.Core.Application;
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs.EnvelopeReceiver;
using EnvelopeGenerator.Application.Resources; using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging; using Microsoft.Extensions.Logging;
using EnvelopeGenerator.Extensions;
namespace EnvelopeGenerator.Application.Services namespace EnvelopeGenerator.Application.Services
{ {
public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverRepository, EnvelopeReceiverDto, EnvelopeReceiver, object>, IEnvelopeReceiverService public class EnvelopeReceiverService : BasicCRUDService<IEnvelopeReceiverRepository, EnvelopeReceiverDto, EnvelopeReceiver, (int Envelope, int Receiver)>, IEnvelopeReceiverService
{ {
private readonly IStringLocalizer<Resource> _localizer; private readonly IStringLocalizer<Resource> _localizer;
@@ -24,13 +25,19 @@ namespace EnvelopeGenerator.Application.Services
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true) public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadBySignatureAsync(string signature, bool withEnvelope = false, bool withReceiver = true)
{ {
var env_rcvs = await _repository.ReadBySignatureAsync(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver); var env_rcvs = await _repository.ReadBySignatureAsync(signature: signature, withEnvelope: withEnvelope, withReceiver: withReceiver);
return Result.Success(_mapper.MapOrThrow<IEnumerable<EnvelopeReceiverDto>>(env_rcvs)); return Result.Success(_mapper.Map<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
} }
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false) public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUuidAsync(string uuid, bool withEnvelope = true, bool withReceiver = false)
{ {
var env_rcvs = await _repository.ReadByUuidAsync(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver); var env_rcvs = await _repository.ReadByUuidAsync(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver);
return Result.Success(_mapper.MapOrThrow<IEnumerable<EnvelopeReceiverDto>>(env_rcvs)); return Result.Success(_mapper.Map<IEnumerable<EnvelopeReceiverDto>>(env_rcvs));
}
public async Task<DataResult<IEnumerable<EnvelopeReceiverSecretDto>>> ReadSecretByUuidAsync(string uuid, bool withEnvelope = false, bool withReceiver = true)
{
var env_rcvs = await _repository.ReadByUuidAsync(uuid: uuid, withEnvelope: withEnvelope, withReceiver: withReceiver);
return Result.Success(_mapper.Map<IEnumerable<EnvelopeReceiverSecretDto>>(env_rcvs));
} }
public async Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true) public async Task<DataResult<EnvelopeReceiverDto>> ReadByUuidSignatureAsync(string uuid, string signature, bool withEnvelope = true, bool withReceiver = true)
@@ -40,7 +47,7 @@ namespace EnvelopeGenerator.Application.Services
return Result.Fail<EnvelopeReceiverDto>() return Result.Fail<EnvelopeReceiverDto>()
.Message(Key.EnvelopeReceiverNotFound); .Message(Key.EnvelopeReceiverNotFound);
return Result.Success(_mapper.MapOrThrow<EnvelopeReceiverDto>(env_rcv)); return Result.Success(_mapper.Map<EnvelopeReceiverDto>(env_rcv));
} }
public async Task<DataResult<EnvelopeReceiverDto>> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true) public async Task<DataResult<EnvelopeReceiverDto>> ReadByEnvelopeReceiverIdAsync(string envelopeReceiverId, bool withEnvelope = true, bool withReceiver = true)
@@ -119,8 +126,14 @@ namespace EnvelopeGenerator.Application.Services
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses) public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses)
{ {
var er_list = await _repository.ReadByUsernameAsync(username: username, min_status: min_status, max_status: max_status, ignore_statuses: ignore_statuses); var er_list = await _repository.ReadByUsernameAsync(username: username, min_status: min_status, max_status: max_status, ignore_statuses: ignore_statuses);
var dto_list = _mapper.MapOrThrow<IEnumerable<EnvelopeReceiverDto>>(er_list); var dto_list = _mapper.Map<IEnumerable<EnvelopeReceiverDto>>(er_list);
return Result.Success(dto_list); return Result.Success(dto_list);
} }
public async Task<DataResult<string?>> ReadLastUsedReceiverNameByMail(string mail)
{
var er = await _repository.ReadLastByReceiver(mail);
return er is null ? Result.Fail<string?>().Notice(LogLevel.None, Flag.NotFound) : Result.Success(er.Name);
}
} }
} }

View File

@@ -3,27 +3,22 @@ using DigitalData.Core.Application;
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
using Microsoft.Extensions.Localization;
using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.Services namespace EnvelopeGenerator.Application.Services
{ {
public class EnvelopeService : BasicCRUDService<IEnvelopeRepository, EnvelopeDto, Envelope, int>, IEnvelopeService public class EnvelopeService : BasicCRUDService<IEnvelopeRepository, EnvelopeDto, Envelope, int>, IEnvelopeService
{ {
private readonly ILogger _logger; public EnvelopeService(IEnvelopeRepository repository, IMapper mapper)
public EnvelopeService(IEnvelopeRepository repository, IMapper mapper, ILogger<EnvelopeService> logger)
: base(repository, mapper) : base(repository, mapper)
{ {
_logger = logger;
} }
public async Task<DataResult<IEnumerable<EnvelopeDto>>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false) public async Task<DataResult<IEnumerable<EnvelopeDto>>> ReadAllWithAsync(bool documents = false, bool history = false, bool documentReceiverElement = false)
{ {
var envelopes = await _repository.ReadAllWithAsync(documents: documents, history: history, documentReceiverElement: documentReceiverElement); var envelopes = await _repository.ReadAllWithAsync(documents: documents, history: history, documentReceiverElement: documentReceiverElement);
var readDto = _mapper.MapOrThrow<IEnumerable<EnvelopeDto>>(envelopes); var readDto = _mapper.Map<IEnumerable<EnvelopeDto>>(envelopes);
return Result.Success(readDto); return Result.Success(readDto);
} }
@@ -34,7 +29,14 @@ namespace EnvelopeGenerator.Application.Services
if (envelope is null) if (envelope is null)
return Result.Fail<EnvelopeDto>(); return Result.Fail<EnvelopeDto>();
var readDto = _mapper.MapOrThrow<EnvelopeDto>(envelope); var readDto = _mapper.Map<EnvelopeDto>(envelope);
return Result.Success(readDto);
}
public async Task<DataResult<IEnumerable<EnvelopeDto>>> ReadByUserAsync(int userId, int? min_status = null, int? max_status = null, params int[] ignore_statuses)
{
var users = await _repository.ReadByUserAsync(userId: userId, min_status: min_status, max_status: max_status, ignore_statuses: ignore_statuses);
var readDto = _mapper.Map<IEnumerable<EnvelopeDto>>(users);
return Result.Success(readDto); return Result.Success(readDto);
} }
} }

View File

@@ -1,19 +1,30 @@
using AutoMapper; using AutoMapper;
using DigitalData.Core.Application; using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Application.Resources; using Microsoft.Extensions.Caching.Memory;
using DigitalData.Core.DTO;
using Microsoft.Extensions.Logging;
namespace EnvelopeGenerator.Application.Services namespace EnvelopeGenerator.Application.Services
{ {
public class EnvelopeTypeService : BasicCRUDService<IEnvelopeTypeRepository, EnvelopeTypeDto, EnvelopeType, int>, IEnvelopeTypeService public class EnvelopeTypeService : BasicCRUDService<IEnvelopeTypeRepository, EnvelopeTypeDto, EnvelopeType, int>, IEnvelopeTypeService
{ {
public EnvelopeTypeService(IEnvelopeTypeRepository repository, IMapper mapper) private static readonly Guid CacheKey = Guid.NewGuid();
private readonly IMemoryCache _cache;
public EnvelopeTypeService(IEnvelopeTypeRepository repository, IMapper mapper, IMemoryCache cache)
: base(repository, mapper) : base(repository, mapper)
{ {
_cache = cache;
} }
public override async Task<DataResult<IEnumerable<EnvelopeTypeDto>>> ReadAllAsync()
=> await _cache.GetOrCreateAsync(CacheKey, async entry => await base.ReadAllAsync())
?? Result.Fail<IEnumerable<EnvelopeTypeDto>>().Notice(LogLevel.Error, Flag.NotFound, "No cached envelope types are available in the database. If you have added any envelope types after the server started, please restart the server.");
} }
} }

View File

@@ -1,10 +1,8 @@
using AutoMapper; using AutoMapper;
using DigitalData.Core.Application; using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Application.DTOs.Receiver; using EnvelopeGenerator.Application.DTOs.Receiver;
using DigitalData.Core.DTO; using DigitalData.Core.DTO;
@@ -12,7 +10,7 @@ namespace EnvelopeGenerator.Application.Services
{ {
public class ReceiverService : CRUDService<IReceiverRepository, ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>, IReceiverService public class ReceiverService : CRUDService<IReceiverRepository, ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>, IReceiverService
{ {
public ReceiverService(IReceiverRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper) public ReceiverService(IReceiverRepository repository, IMapper mapper)
: base(repository, mapper) : base(repository, mapper)
{ {
} }
@@ -24,7 +22,7 @@ namespace EnvelopeGenerator.Application.Services
if (rcv is null) if (rcv is null)
return Result.Fail<ReceiverReadDto>(); return Result.Fail<ReceiverReadDto>();
return Result.Success(_mapper.MapOrThrow<ReceiverReadDto>(rcv)); return Result.Success(_mapper.Map<ReceiverReadDto>(rcv));
} }
public async Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null) public async Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null)

View File

@@ -1,17 +1,15 @@
using AutoMapper; using AutoMapper;
using DigitalData.Core.Application; using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts; using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs; using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities; using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts; using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Application.Resources;
namespace EnvelopeGenerator.Application.Services namespace EnvelopeGenerator.Application.Services
{ {
public class UserReceiverService : BasicCRUDService<IUserReceiverRepository, UserReceiverDto, UserReceiver, int>, IUserReceiverService public class UserReceiverService : BasicCRUDService<IUserReceiverRepository, UserReceiverDto, UserReceiver, int>, IUserReceiverService
{ {
public UserReceiverService(IUserReceiverRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper) public UserReceiverService(IUserReceiverRepository repository, IMapper mapper)
: base(repository, mapper) : base(repository, mapper)
{ {
} }

View File

@@ -1,6 +1,7 @@
Public Class Constants Public Class Constants
#Region "Status Fields" #Region "Status Fields"
'http://wiki.dd/xwiki13/bin/view/Anwendungen/Produkt-Handbuch/Sonstiges/SignFlow/Envelope%20Status/
Public Enum EnvelopeStatus Public Enum EnvelopeStatus
Invalid = 0 Invalid = 0
EnvelopeCreated = 1001 EnvelopeCreated = 1001
@@ -19,6 +20,8 @@
DocumentSigned = 2005 DocumentSigned = 2005
SignatureConfirmed = 2006 SignatureConfirmed = 2006
DocumentRejected = 2007 DocumentRejected = 2007
EnvelopeShared = 2008
EnvelopeViewed = 2009
MessageInvitationSent = 3001 ' Wird von Trigger verwendet MessageInvitationSent = 3001 ' Wird von Trigger verwendet
MessageAccessCodeSent = 3002 MessageAccessCodeSent = 3002
MessageConfirmationSent = 3003 MessageConfirmationSent = 3003
@@ -26,6 +29,7 @@
MessageCompletionSent = 3005 MessageCompletionSent = 3005
End Enum End Enum
'TODO: standardize in xwiki
Public Enum ReferenceType Public Enum ReferenceType
Receiver Receiver
Sender Sender
@@ -93,6 +97,13 @@
DocumentDeleted DocumentDeleted
DocumentCompleted DocumentCompleted
DocumentAccessCodeReceived DocumentAccessCodeReceived
DocumentShared
End Enum
Public Enum EncodeType
EnvelopeReceiver
EnvelopeReceiverReadOnly
Undefined
End Enum End Enum
#End Region #End Region

View File

@@ -13,6 +13,8 @@
<TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6.2</TargetFrameworkVersion>
<Deterministic>true</Deterministic> <Deterministic>true</Deterministic>
<TargetFrameworkProfile /> <TargetFrameworkProfile />
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@@ -75,8 +77,8 @@
<Reference Include="DigitalData.Modules.Logging"> <Reference Include="DigitalData.Modules.Logging">
<HintPath>..\..\2_DLL Projekte\DDModules\Logging\bin\Debug\DigitalData.Modules.Logging.dll</HintPath> <HintPath>..\..\2_DLL Projekte\DDModules\Logging\bin\Debug\DigitalData.Modules.Logging.dll</HintPath>
</Reference> </Reference>
<Reference Include="GdPicture.NET.14"> <Reference Include="GdPicture.NET.14, Version=14.2.89.0, Culture=neutral, PublicKeyToken=f52a2e60ad468dbb, processorArchitecture=MSIL">
<HintPath>D:\ProgramFiles\GdPicture.NET 14\Redist\GdPicture.NET (.NET Framework 4.5)\GdPicture.NET.14.dll</HintPath> <HintPath>..\packages\GdPicture.14.2.89\lib\net462\GdPicture.NET.14.dll</HintPath>
</Reference> </Reference>
<Reference Include="Microsoft.CSharp" /> <Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL"> <Reference Include="Microsoft.Extensions.Logging.Abstractions, Version=2.1.1.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
@@ -287,4 +289,11 @@
</ItemGroup> </ItemGroup>
<ItemGroup /> <ItemGroup />
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
<Import Project="..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets" Condition="Exists('..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}".</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets'))" />
</Target>
</Project> </Project>

View File

@@ -31,5 +31,5 @@ Imports System.Runtime.InteropServices
' indem Sie "*" wie unten gezeigt eingeben: ' indem Sie "*" wie unten gezeigt eingeben:
' <Assembly: AssemblyVersion("1.0.*")> ' <Assembly: AssemblyVersion("1.0.*")>
<Assembly: AssemblyVersion("1.9.2.0")> <Assembly: AssemblyVersion("1.9.3.0")>
<Assembly: AssemblyFileVersion("1.9.2.0")> <Assembly: AssemblyFileVersion("1.9.3.0")>

View File

@@ -1,5 +1,7 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="GdPicture" version="14.2.89" targetFramework="net462" />
<package id="GdPicture.runtimes.windows" version="14.2.89" targetFramework="net462" />
<package id="Microsoft.Extensions.Logging.Abstractions" version="2.1.1" targetFramework="net462" /> <package id="Microsoft.Extensions.Logging.Abstractions" version="2.1.1" targetFramework="net462" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net462" /> <package id="Newtonsoft.Json" version="13.0.3" targetFramework="net462" />
<package id="Quartz" version="3.8.0" targetFramework="net462" /> <package id="Quartz" version="3.8.0" targetFramework="net462" />

View File

@@ -1,43 +1,41 @@
using System.ComponentModel; using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_CONFIG", Schema = "dbo")] [Table("TBSIG_CONFIG", Schema = "dbo")]
public class Config public class Config : IUnique<int>
{ {
[Column("DOCUMENT_PATH", TypeName = "nvarchar(256)")] [Column("DOCUMENT_PATH", TypeName = "nvarchar(256)")]
public string DocumentPath { get; set; } public string? DocumentPath { get; init; }
[Column("SENDING_PROFILE", TypeName = "int")] [Column("SENDING_PROFILE", TypeName = "int")]
[Required] [Required]
[DatabaseGenerated(DatabaseGeneratedOption.None)] // Assuming SENDING_PROFILE is manually entered or controlled by the application logic public required int SendingProfile { get; init; }
[DefaultValue(0)] // This sets the default value for SENDING_PROFILE
public int SendingProfile { get; set; }
[Column("SIGNATURE_HOST", TypeName = "nvarchar(128)")] [Column("SIGNATURE_HOST", TypeName = "nvarchar(128)")]
public string SignatureHost { get; set; } public string? SignatureHost { get; init; }
[Column("EXTERNAL_PROGRAM_NAME", TypeName = "nvarchar(30)")] [Column("EXTERNAL_PROGRAM_NAME", TypeName = "nvarchar(30)")]
public string ExternalProgramName { get; set; } public string? ExternalProgramName { get; init; }
[Column("EXPORT_PATH", TypeName = "nvarchar(256)")] [Column("EXPORT_PATH", TypeName = "nvarchar(256)")]
public string ExportPath { get; set; } public string? ExportPath { get; init; }
[Column("DOCUMENT_PATH_DMZ", TypeName = "nvarchar(512)")] [Column("DOCUMENT_PATH_DMZ", TypeName = "nvarchar(512)")]
[Required] [Required]
[DefaultValue("")] // This sets the default value for DOCUMENT_PATH_DMZ public string? DocumentPathDmz { get; init; }
public string DocumentPathDmz { get; set; }
[Column("EXPORT_PATH_DMZ", TypeName = "nvarchar(512)")] [Column("EXPORT_PATH_DMZ", TypeName = "nvarchar(512)")]
[Required] [Required]
[DefaultValue("")] // This sets the default value for EXPORT_PATH_DMZ public required string ExportPathDmz { get; init; }
public string ExportPathDmz { get; set; }
[Column("DOCUMENT_PATH_MOVE_AFTSEND", TypeName = "nvarchar(512)")] [Column("DOCUMENT_PATH_MOVE_AFTSEND", TypeName = "nvarchar(512)")]
[Required] [Required]
[DefaultValue("")] // This sets the default value for DOCUMENT_PATH_MOVE_AFTSEND public required string DocumentPathMoveAftsend { get; init; }
public string DocumentPathMoveAftsend { get; set; }
[Obsolete("Configuration does not have an ID; it represents a single table in the database.")]
public int Id => throw new InvalidOperationException("This configuration does not support an ID as it represents a single table in the database.");
} }
} }

View File

@@ -1,11 +1,12 @@
using System.ComponentModel; using DigitalData.Core.Abstractions;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_DOCUMENT_RECEIVER_ELEMENT", Schema = "dbo")] [Table("TBSIG_DOCUMENT_RECEIVER_ELEMENT", Schema = "dbo")]
public class DocumentReceiverElement public class DocumentReceiverElement : IUnique<int>
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]

View File

@@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations; using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_DOCUMENT_STATUS", Schema = "dbo")] [Table("TBSIG_DOCUMENT_STATUS", Schema = "dbo")]
public class DocumentStatus public class DocumentStatus : IUnique<int>
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -27,7 +28,7 @@ namespace EnvelopeGenerator.Domain.Entities
public DateTime? StatusChangedWhen { get; set; } public DateTime? StatusChangedWhen { get; set; }
[Column("VALUE", TypeName = "nvarchar(max)")] [Column("VALUE", TypeName = "nvarchar(max)")]
public string Value { get; set; } public string? Value { get; set; }
[Required] [Required]
[Column("ADDED_WHEN", TypeName = "datetime")] [Column("ADDED_WHEN", TypeName = "datetime")]
@@ -42,4 +43,4 @@ namespace EnvelopeGenerator.Domain.Entities
[ForeignKey("ReceiverId")] [ForeignKey("ReceiverId")]
public virtual Receiver? Receiver { get; set; } public virtual Receiver? Receiver { get; set; }
} }
} }

View File

@@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations; using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_EMAIL_TEMPLATE", Schema = "dbo")] [Table("TBSIG_EMAIL_TEMPLATE", Schema = "dbo")]
public class EmailTemplate public class EmailTemplate : IUnique<int>
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -12,12 +13,12 @@ namespace EnvelopeGenerator.Domain.Entities
public int Id { get; set; } public int Id { get; set; }
[Column("NAME", TypeName = "nvarchar(64)")] [Column("NAME", TypeName = "nvarchar(64)")]
public string Name { get; set; } public string? Name { get; set; }
[Column("BODY", TypeName = "nvarchar(max)")] [Column("BODY", TypeName = "nvarchar(max)")]
public string Body { get; set; } public string? Body { get; set; }
[Column("SUBJECT", TypeName = "nvarchar(512)")] [Column("SUBJECT", TypeName = "nvarchar(512)")]
public string Subject { get; set; } public string? Subject { get; set; }
} }
} }

View File

@@ -1,12 +1,12 @@
using EnvelopeGenerator.Common; using DigitalData.Core.Abstractions;
using EnvelopeGenerator.Common.My.Resources; using EnvelopeGenerator.Common;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_ENVELOPE", Schema = "dbo")] [Table("TBSIG_ENVELOPE", Schema = "dbo")]
public class Envelope public class Envelope : IUnique<int>
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -26,11 +26,11 @@ namespace EnvelopeGenerator.Domain.Entities
[Required] [Required]
[Column("ENVELOPE_UUID", TypeName = "nvarchar(36)")] [Column("ENVELOPE_UUID", TypeName = "nvarchar(36)")]
public string Uuid { get; set; } public required string Uuid { get; init; }
[Required] [Required]
[Column("MESSAGE", TypeName = "nvarchar(max)")] [Column("MESSAGE", TypeName = "nvarchar(max)")]
public string Message { get; set; } public string? Message { get; set; }
[Column("EXPIRES_WHEN", TypeName = "datetime")] [Column("EXPIRES_WHEN", TypeName = "datetime")]
public DateTime? ExpiresWhen { get; set; } public DateTime? ExpiresWhen { get; set; }
@@ -46,13 +46,13 @@ namespace EnvelopeGenerator.Domain.Entities
public DateTime? ChangedWhen { get; set; } public DateTime? ChangedWhen { get; set; }
[Column("TITLE", TypeName = "nvarchar(128)")] [Column("TITLE", TypeName = "nvarchar(128)")]
public string Title { get; set; } public string? Title { get; set; }
[Column("CONTRACT_TYPE")] [Column("CONTRACT_TYPE")]
public int? ContractType { get; set; } public int? ContractType { get; set; }
[Column("LANGUAGE", TypeName = "nvarchar(5)")] [Column("LANGUAGE", TypeName = "nvarchar(5)")]
public string Language { get; set; } public required string Language { get; set; }
[Column("SEND_REMINDER_EMAILS")] [Column("SEND_REMINDER_EMAILS")]
public bool? SendReminderEmails { get; set; } public bool? SendReminderEmails { get; set; }

View File

@@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations; using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_ENVELOPE_CERTIFICATE", Schema = "dbo")] [Table("TBSIG_ENVELOPE_CERTIFICATE", Schema = "dbo")]
public class EnvelopeCertificate public class EnvelopeCertificate : IUnique<int>
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -17,11 +18,11 @@ namespace EnvelopeGenerator.Domain.Entities
[Required] [Required]
[Column("ENVELOPE_UUID", TypeName = "nvarchar(36)")] [Column("ENVELOPE_UUID", TypeName = "nvarchar(36)")]
public string EnvelopeUuid { get; set; } public required string EnvelopeUuid { get; set; }
[Required] [Required]
[Column("ENVELOPE_SUBJECT", TypeName = "nvarchar(512)")] [Column("ENVELOPE_SUBJECT", TypeName = "nvarchar(512)")]
public string EnvelopeSubject { get; set; } public required string EnvelopeSubject { get; set; }
[Required] [Required]
[Column("CREATOR_ID")] [Column("CREATOR_ID")]
@@ -29,11 +30,11 @@ namespace EnvelopeGenerator.Domain.Entities
[Required] [Required]
[Column("CREATOR_NAME", TypeName = "nvarchar(128)")] [Column("CREATOR_NAME", TypeName = "nvarchar(128)")]
public string CreatorName { get; set; } public required string CreatorName { get; set; }
[Required] [Required]
[Column("CREATOR_EMAIL", TypeName = "nvarchar(128)")] [Column("CREATOR_EMAIL", TypeName = "nvarchar(128)")]
public string CreatorEmail { get; set; } public required string CreatorEmail { get; set; }
[Required] [Required]
[Column("ENVELOPE_STATUS")] [Column("ENVELOPE_STATUS")]

View File

@@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations; using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_ENVELOPE_DOCUMENT", Schema = "dbo")] [Table("TBSIG_ENVELOPE_DOCUMENT", Schema = "dbo")]
public class EnvelopeDocument public class EnvelopeDocument : IUnique<int>
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -17,18 +18,18 @@ namespace EnvelopeGenerator.Domain.Entities
[Required] [Required]
[Column("FILENAME", TypeName = "nvarchar(256)")] [Column("FILENAME", TypeName = "nvarchar(256)")]
public string Filename { get; set; } public required string Filename { get; set; }
[Required] [Required]
[Column("FILEPATH", TypeName = "nvarchar(256)")] [Column("FILEPATH", TypeName = "nvarchar(256)")]
public string Filepath { get; set; } public required string Filepath { get; set; }
[Required] [Required]
[Column("ADDED_WHEN", TypeName = "datetime")] [Column("ADDED_WHEN", TypeName = "datetime")]
public DateTime AddedWhen { get; set; } public required DateTime AddedWhen { get; set; }
[Column("FILENAME_ORIGINAL", TypeName = "nvarchar(256)")] [Column("FILENAME_ORIGINAL", TypeName = "nvarchar(256)")]
public string FilenameOriginal { get; set; } public required string FilenameOriginal { get; set; }
public IEnumerable<DocumentReceiverElement>? Elements { get; set; } public IEnumerable<DocumentReceiverElement>? Elements { get; set; }
} }

View File

@@ -1,4 +1,5 @@
using DigitalData.UserManager.Domain.Entities; using DigitalData.Core.Abstractions;
using DigitalData.UserManager.Domain.Entities;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using static EnvelopeGenerator.Common.Constants; using static EnvelopeGenerator.Common.Constants;
@@ -6,7 +7,7 @@ using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_ENVELOPE_HISTORY", Schema = "dbo")] [Table("TBSIG_ENVELOPE_HISTORY", Schema = "dbo")]
public class EnvelopeHistory public class EnvelopeHistory : IUnique<long>
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -19,7 +20,7 @@ namespace EnvelopeGenerator.Domain.Entities
[Required] [Required]
[Column("USER_REFERENCE", TypeName = "nvarchar(128)")] [Column("USER_REFERENCE", TypeName = "nvarchar(128)")]
public string UserReference { get; set; } public required string UserReference { get; init; }
[Required] [Required]
[Column("STATUS")] [Column("STATUS")]
@@ -43,11 +44,17 @@ namespace EnvelopeGenerator.Domain.Entities
public virtual Receiver? Receiver { get; set; } public virtual Receiver? Receiver { get; set; }
[NotMapped] [NotMapped]
public ReferenceType ReferenceType => (Status / 3) switch public ReferenceType ReferenceType => (Status / 1000) switch
{ {
1 => ReferenceType.Sender, 1 => ReferenceType.Sender,
2 or 3 => ReferenceType.Receiver, 2 or 3 => ReferenceType.Receiver,
_ => ReferenceType.Unknown, _ => ReferenceType.Unknown,
}; };
[NotMapped]
public string? StatusName
=> (Enum.IsDefined(typeof(EnvelopeStatus), Status))
? Enum.GetName(typeof(EnvelopeStatus), Status)
: null;
} }
} }

View File

@@ -1,45 +1,10 @@
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_ENVELOPE_RECEIVER", Schema = "dbo")] [Table("TBSIG_ENVELOPE_RECEIVER", Schema = "dbo")]
public class EnvelopeReceiver public class EnvelopeReceiver : EnvelopeReceiverBase
{ {
[Key]
[Column("ENVELOPE_ID")]
public int EnvelopeId { get; set; }
[Key]
[Column("RECEIVER_ID")]
public int ReceiverId { get; set; }
[Required]
[Column("SEQUENCE")]
public int Sequence { get; set; }
[Column("NAME", TypeName = "nvarchar(128)")]
public string? Name { get; set; }
[Column("JOB_TITLE", TypeName = "nvarchar(128)")]
public string? JobTitle { get; set; }
[Column("COMPANY_NAME", TypeName = "nvarchar(128)")]
public string? CompanyName { get; set; }
[Column("PRIVATE_MESSAGE", TypeName = "nvarchar(max)")]
public string? PrivateMessage { get; set; }
[Column("ACCESS_CODE", TypeName = "nvarchar(64)")]
public string? AccessCode { get; set; }
[Required]
[Column("ADDED_WHEN", TypeName = "datetime")]
public DateTime AddedWhen { get; set; }
[Column("CHANGED_WHEN", TypeName = "datetime")]
public DateTime? ChangedWhen { get; set; }
[ForeignKey("EnvelopeId")] [ForeignKey("EnvelopeId")]
public Envelope? Envelope { get; set; } public Envelope? Envelope { get; set; }

View File

@@ -0,0 +1,46 @@
using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_ENVELOPE_RECEIVER", Schema = "dbo")]
public class EnvelopeReceiverBase : IUnique<(int Envelope, int Receiver)>
{
[Key]
[Column("ENVELOPE_ID")]
public int EnvelopeId { get; set; }
[Key]
[Column("RECEIVER_ID")]
public int ReceiverId { get; set; }
[Required]
[Column("SEQUENCE")]
public int Sequence { get; set; }
[Column("NAME", TypeName = "nvarchar(128)")]
public string? Name { get; set; }
[Column("JOB_TITLE", TypeName = "nvarchar(128)")]
public string? JobTitle { get; set; }
[Column("COMPANY_NAME", TypeName = "nvarchar(128)")]
public string? CompanyName { get; set; }
[Column("PRIVATE_MESSAGE", TypeName = "nvarchar(max)")]
public string? PrivateMessage { get; set; }
[Column("ACCESS_CODE", TypeName = "nvarchar(64)")]
public string? AccessCode { get; set; }
[Required]
[Column("ADDED_WHEN", TypeName = "datetime")]
public DateTime AddedWhen { get; set; }
[Column("CHANGED_WHEN", TypeName = "datetime")]
public DateTime? ChangedWhen { get; set; }
public (int Envelope, int Receiver) Id => (Envelope: EnvelopeId, Receiver: ReceiverId);
}
}

View File

@@ -0,0 +1,52 @@
using System.ComponentModel.DataAnnotations.Schema;
using System.ComponentModel.DataAnnotations;
using DigitalData.Core.Abstractions;
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
namespace EnvelopeGenerator.Domain.Entities
{
[Table("TBSIG_ENVELOPE_RECEIVER_READ_ONLY")]
public class EnvelopeReceiverReadOnly : IUnique<long>
{
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("GUID")]
public long Id { get; init; }
[Column("ENVELOPE_ID")]
[Required]
public long EnvelopeId { get; init; }
//TODO: remove NotMapped attribute when EnvelopeId data type is standardized
[NotMapped]
public Envelope? Envelope { get; set; }
[Column("RECEIVER_MAIL")]
[Required]
[StringLength(250)]
[TemplatePlaceholder("NAME_RECEIVER")]
public required string ReceiverMail { get; init; }
[Column("DATE_VALID")]
[Required]
public DateTime DateValid { get; init; }
[Column("ADDED_WHO")]
[Required]
[StringLength(100)]
public required string AddedWho { get; init; }
public Receiver? Receiver { get; init; }
[Column("ADDED_WHEN")]
[Required]
public DateTime AddedWhen { get; init; }
[Column("CHANGED_WHO")]
[StringLength(100)]
public string? ChangedWho { get; init; }
[Column("CHANGED_WHEN")]
public DateTime? ChangedWhen { get; init; }
}
}

View File

@@ -1,12 +1,11 @@
using System; using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations; using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_ENVELOPE_TYPE", Schema = "dbo")] [Table("TBSIG_ENVELOPE_TYPE", Schema = "dbo")]
public class EnvelopeType public class EnvelopeType : IUnique<int>
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -15,10 +14,10 @@ namespace EnvelopeGenerator.Domain.Entities
[Required] [Required]
[Column("TITLE", TypeName = "nvarchar(128)")] [Column("TITLE", TypeName = "nvarchar(128)")]
public string Title { get; set; } public required string Title { get; set; }
[Column("LANGUAGE", TypeName = "nvarchar(5)")] [Column("LANGUAGE", TypeName = "nvarchar(5)")]
public string Language { get; set; } public string? Language { get; set; }
[Column("EXPIRES_DAYS")] [Column("EXPIRES_DAYS")]
public int? ExpiresDays { get; set; } public int? ExpiresDays { get; set; }

View File

@@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations; using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_RECEIVER", Schema = "dbo")] [Table("TBSIG_RECEIVER", Schema = "dbo")]
public class Receiver public class Receiver : IUnique<int>
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -22,5 +23,7 @@ namespace EnvelopeGenerator.Domain.Entities
[Required] [Required]
[Column("ADDED_WHEN", TypeName = "datetime")] [Column("ADDED_WHEN", TypeName = "datetime")]
public DateTime AddedWhen { get; set; } public DateTime AddedWhen { get; set; }
public IEnumerable<EnvelopeReceiver>? EnvelopeReceivers { get; init; }
} }
} }

View File

@@ -1,10 +1,11 @@
using System.ComponentModel.DataAnnotations; using DigitalData.Core.Abstractions;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema; using System.ComponentModel.DataAnnotations.Schema;
namespace EnvelopeGenerator.Domain.Entities namespace EnvelopeGenerator.Domain.Entities
{ {
[Table("TBSIG_USER_RECEIVER", Schema = "dbo")] [Table("TBSIG_USER_RECEIVER", Schema = "dbo")]
public class UserReceiver public class UserReceiver : IUnique<int>
{ {
[Key] [Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)] [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -21,16 +22,16 @@ namespace EnvelopeGenerator.Domain.Entities
[Required] [Required]
[Column("NAME", TypeName = "nvarchar(128)")] [Column("NAME", TypeName = "nvarchar(128)")]
public string Name { get; set; } public required string Name { get; set; }
[Column("COMPANY_NAME", TypeName = "nvarchar(128)")] [Column("COMPANY_NAME", TypeName = "nvarchar(128)")]
public string CompanyName { get; set; } public string? CompanyName { get; set; }
[Column("JOB_TITLE", TypeName = "nvarchar(128)")] [Column("JOB_TITLE", TypeName = "nvarchar(128)")]
public string JobTitle { get; set; } public string? JobTitle { get; set; }
[Required] [Required]
[Column("ADDED_WHEN", TypeName = "datetime")] [Column("ADDED_WHEN", TypeName = "datetime")]
public DateTime AddedWhen { get; set; } public required DateTime AddedWhen { get; init; }
} }
} }

View File

@@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="2.0.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="1.0.0" /> <PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="1.0.0" />
<PackageReference Include="UserManager.Domain" Version="1.0.0" /> <PackageReference Include="UserManager.Domain" Version="1.0.0" />
</ItemGroup> </ItemGroup>

View File

@@ -1,12 +1,9 @@
using Microsoft.Extensions.Logging; using System.Text;
using System.Text; using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Application namespace EnvelopeGenerator.Extensions
{ {
/// <summary> public static class DecodingExtensions
/// Provides extension methods for decoding and extracting information from an envelope receiver ID.
/// </summary>
public static class EnvelopeGeneratorExtensions
{ {
/// <summary> /// <summary>
/// Validates whether a given string is a correctly formatted Base-64 encoded string. /// Validates whether a given string is a correctly formatted Base-64 encoded string.
@@ -67,6 +64,40 @@ namespace EnvelopeGenerator.Application
return input.IndexOf('=') == -1; // No padding allowed except at the end return input.IndexOf('=') == -1; // No padding allowed except at the end
} }
public static bool TryDecode(this string encodedKey, out string[] decodedKeys)
{
try
{
byte[] bytes = Convert.FromBase64String(encodedKey);
string decodedString = Encoding.UTF8.GetString(bytes);
decodedKeys = decodedString.Split(new string[] { "::" }, StringSplitOptions.None);
return true;
}
catch(ArgumentNullException) { }
catch (FormatException) { }
catch(ArgumentException) { }
decodedKeys = Array.Empty<string>();
return false;
}
public static EncodeType GetEncodeType(this string[] decodedKeys) => decodedKeys.Length switch
{
2 => EncodeType.EnvelopeReceiver,
3 => long.TryParse(decodedKeys[1], out var _) ? EncodeType.EnvelopeReceiverReadOnly : EncodeType.Undefined,
_ => EncodeType.Undefined,
};
public static (string? EnvelopeUuid, string? ReceiverSignature) ParseEnvelopeReceiverId(this string[] decodedKeys)
=> decodedKeys.GetEncodeType() == EncodeType.EnvelopeReceiver
? (EnvelopeUuid: decodedKeys[0], ReceiverSignature: decodedKeys[1])
: throw new InvalidOperationException("Attempted to convert a decoded other than type EnvelopeReceiver to EnvelopeReceiver.");
public static long ParseReadOnlyId(this string[] decodedKeys)
=> decodedKeys.GetEncodeType() == EncodeType.EnvelopeReceiverReadOnly
? long.Parse(decodedKeys[1])
: throw new InvalidOperationException("Attempted to convert a decoded other than type EnvelopeReceiver to EnvelopeReceiver. ");
/// <summary> /// <summary>
/// Decodes the envelope receiver ID and extracts the envelope UUID and receiver signature. /// Decodes the envelope receiver ID and extracts the envelope UUID and receiver signature.
/// </summary> /// </summary>
@@ -79,7 +110,7 @@ namespace EnvelopeGenerator.Application
return (null, null); return (null, null);
} }
byte[] bytes = Convert.FromBase64String(envelopeReceiverId); byte[] bytes = Convert.FromBase64String(envelopeReceiverId);
string decodedString = System.Text.Encoding.UTF8.GetString(bytes); string decodedString = Encoding.UTF8.GetString(bytes);
string[] parts = decodedString.Split(new string[] { "::" }, StringSplitOptions.None); string[] parts = decodedString.Split(new string[] { "::" }, StringSplitOptions.None);
if (parts.Length > 1) if (parts.Length > 1)
@@ -88,6 +119,22 @@ namespace EnvelopeGenerator.Application
return (string.Empty, string.Empty); return (string.Empty, string.Empty);
} }
public static long? DecodeEnvelopeReceiverReadOnlyId(this string envelopeReceiverReadOnlyId)
{
if (!envelopeReceiverReadOnlyId.IsBase64String())
{
return null;
}
byte[] bytes = Convert.FromBase64String(envelopeReceiverReadOnlyId);
string decodedString = System.Text.Encoding.UTF8.GetString(bytes);
string[] parts = decodedString.Split(new string[] { "::" }, StringSplitOptions.None);
if (parts.Length > 2)
return long.TryParse(parts[1], out long readOnlyId) ? readOnlyId : null;
else
return null;
}
/// <summary> /// <summary>
/// Gets the envelope UUID from the decoded envelope receiver ID. /// Gets the envelope UUID from the decoded envelope receiver ID.
/// </summary> /// </summary>
@@ -101,48 +148,5 @@ namespace EnvelopeGenerator.Application
/// <param name="envelopeReceiverId">The base64 encoded string to decode.</param> /// <param name="envelopeReceiverId">The base64 encoded string to decode.</param>
/// <returns>The receiver signature.</returns> /// <returns>The receiver signature.</returns>
public static string? GetReceiverSignature(this string envelopeReceiverId) => envelopeReceiverId.DecodeEnvelopeReceiverId().ReceiverSignature; public static string? GetReceiverSignature(this string envelopeReceiverId) => envelopeReceiverId.DecodeEnvelopeReceiverId().ReceiverSignature;
public static string EncodeEnvelopeReceiverId(this (string envelopeUuid, string receiverSignature) input)
{
string combinedString = $"{input.envelopeUuid}::{input.receiverSignature}";
byte[] bytes = Encoding.UTF8.GetBytes(combinedString);
string base64String = Convert.ToBase64String(bytes);
return base64String;
}
public static void LogEnvelopeError(this ILogger logger, string envelopeReceiverId, Exception? exception = null, string? message = null, params object?[] args)
{
var sb = new StringBuilder().AppendLine(envelopeReceiverId.DecodeEnvelopeReceiverId().ToTitle());
if (message is not null)
sb.AppendLine(message);
if(exception is null)
logger.Log(LogLevel.Error, sb.ToString(), args);
else
logger.Log(LogLevel.Error, exception, sb.AppendLine(exception.Message).ToString(), args);
}
public static void LogEnvelopeError(this ILogger logger, string? uuid, string? signature = null, Exception? exception = null, string? message = null, params object?[] args)
{
var sb = new StringBuilder($"Envelope Uuid: {uuid}");
if(signature is not null)
sb.AppendLine().Append($"Receiver Signature: {signature}");
if (message is not null)
sb.AppendLine().Append(message);
if (exception is null)
logger.Log(LogLevel.Error, sb.ToString(), args);
else
logger.Log(LogLevel.Error, exception, sb.ToString(), args);
}
public static string ToTitle(this (string? UUID, string? Signature) envelopeReceiverTuple)
{
return $"UUID is {envelopeReceiverTuple.UUID} and signature is {envelopeReceiverTuple.Signature}";
}
} }
} }

View File

@@ -0,0 +1,30 @@
using Microsoft.Extensions.Logging;
using System.Text;
namespace EnvelopeGenerator.Extensions
{
/// <summary>
/// Provides extension methods for decoding and extracting information from an envelope receiver ID.
/// </summary>
public static class EncodingExtensions
{
public static string EncodeEnvelopeReceiverId(this long readOnlyId)
{
//The random number is used as a salt to increase security but it is not saved in the database.
string combinedString = $"{Random.Shared.Next()}::{readOnlyId}::{Random.Shared.Next()}";
byte[] bytes = Encoding.UTF8.GetBytes(combinedString);
string base64String = Convert.ToBase64String(bytes);
return base64String;
}
public static string EncodeEnvelopeReceiverId(this (string envelopeUuid, string receiverSignature) input)
{
string combinedString = $"{input.envelopeUuid}::{input.receiverSignature}";
byte[] bytes = Encoding.UTF8.GetBytes(combinedString);
string base64String = Convert.ToBase64String(bytes);
return base64String;
}
}
}

View File

@@ -0,0 +1,19 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="HtmlSanitizer" Version="8.0.865" />
<PackageReference Include="Microsoft.Extensions.Localization.Abstractions" Version="7.0.19" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="8.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Common\EnvelopeGenerator.Common.vbproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,42 @@
using Microsoft.Extensions.Logging;
using System.Text;
namespace EnvelopeGenerator.Extensions
{
public static class LoggerExtensions
{
public static void LogEnvelopeError(this ILogger logger, string envelopeReceiverId, Exception? exception = null, string? message = null, params object?[] args)
{
var sb = new StringBuilder().AppendLine(envelopeReceiverId.DecodeEnvelopeReceiverId().ToTitle());
if (message is not null)
sb.AppendLine(message);
if (exception is null)
logger.Log(LogLevel.Error, sb.ToString(), args);
else
logger.Log(LogLevel.Error, exception, sb.AppendLine(exception.Message).ToString(), args);
}
public static void LogEnvelopeError(this ILogger logger, string? uuid, string? signature = null, Exception? exception = null, string? message = null, params object?[] args)
{
var sb = new StringBuilder($"Envelope Uuid: {uuid}");
if (signature is not null)
sb.AppendLine().Append($"Receiver Signature: {signature}");
if (message is not null)
sb.AppendLine().Append(message);
if (exception is null)
logger.Log(LogLevel.Error, sb.ToString(), args);
else
logger.Log(LogLevel.Error, exception, sb.ToString(), args);
}
public static string ToTitle(this (string? UUID, string? Signature) envelopeReceiverTuple)
{
return $"UUID is {envelopeReceiverTuple.UUID} and signature is {envelopeReceiverTuple.Signature}";
}
}
}

View File

@@ -2,7 +2,7 @@
using Microsoft.Extensions.Localization; using Microsoft.Extensions.Localization;
using System.Text.Encodings.Web; using System.Text.Encodings.Web;
namespace EnvelopeGenerator.Web namespace EnvelopeGenerator.Extensions
{ {
public static class XSSExtensions public static class XSSExtensions
{ {

View File

@@ -14,6 +14,8 @@
<OptionCompare>Binary</OptionCompare> <OptionCompare>Binary</OptionCompare>
<OptionStrict>Off</OptionStrict> <OptionStrict>Off</OptionStrict>
<OptionInfer>On</OptionInfer> <OptionInfer>On</OptionInfer>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget> <PlatformTarget>AnyCPU</PlatformTarget>
@@ -97,8 +99,8 @@
<SpecificVersion>False</SpecificVersion> <SpecificVersion>False</SpecificVersion>
<HintPath>..\EnvelopeGenerator.Common\bin\Debug\EnvelopeGenerator.Common.dll</HintPath> <HintPath>..\EnvelopeGenerator.Common\bin\Debug\EnvelopeGenerator.Common.dll</HintPath>
</Reference> </Reference>
<Reference Include="GdPicture.NET.14"> <Reference Include="GdPicture.NET.14, Version=14.2.89.0, Culture=neutral, PublicKeyToken=f52a2e60ad468dbb, processorArchitecture=MSIL">
<HintPath>D:\ProgramFiles\GdPicture.NET 14\Redist\GdPicture.NET (.NET Framework 4.5)\GdPicture.NET.14.dll</HintPath> <HintPath>..\packages\GdPicture.14.2.89\lib\net462\GdPicture.NET.14.dll</HintPath>
</Reference> </Reference>
<Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL"> <Reference Include="NLog, Version=5.0.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c, processorArchitecture=MSIL">
<HintPath>..\packages\NLog.5.0.5\lib\net46\NLog.dll</HintPath> <HintPath>..\packages\NLog.5.0.5\lib\net46\NLog.dll</HintPath>
@@ -269,6 +271,13 @@
</ProjectReference> </ProjectReference>
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" /> <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />
<Import Project="..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets" Condition="Exists('..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets')" />
<Target Name="EnsureNuGetPackageBuildImports" BeforeTargets="PrepareForBuild">
<PropertyGroup>
<ErrorText>Dieses Projekt verweist auf mindestens ein NuGet-Paket, das auf diesem Computer fehlt. Verwenden Sie die Wiederherstellung von NuGet-Paketen, um die fehlenden Dateien herunterzuladen. Weitere Informationen finden Sie unter "http://go.microsoft.com/fwlink/?LinkID=322105". Die fehlende Datei ist "{0}".</ErrorText>
</PropertyGroup>
<Error Condition="!Exists('..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets')" Text="$([System.String]::Format('$(ErrorText)', '..\packages\GdPicture.runtimes.windows.14.2.89\build\net462\GdPicture.runtimes.windows.targets'))" />
</Target>
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild"> <Target Name="BeforeBuild">

View File

@@ -68,4 +68,12 @@
<!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> --> <!--<add name="EventLog" type="System.Diagnostics.EventLogTraceListener" initializeData="APPLICATION_NAME"/> -->
</sharedListeners> </sharedListeners>
</system.diagnostics> </system.diagnostics>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="GdPicture.NET.14" publicKeyToken="f52a2e60ad468dbb" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-14.2.89.0" newVersion="14.2.89.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration> </configuration>

View File

@@ -1,4 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="GdPicture" version="14.2.89" targetFramework="net462" />
<package id="GdPicture.runtimes.windows" version="14.2.89" targetFramework="net462" />
<package id="NLog" version="5.0.5" targetFramework="net462" /> <package id="NLog" version="5.0.5" targetFramework="net462" />
</packages> </packages>

View File

@@ -1,4 +1,4 @@
import { ApplicationConfig } from '@angular/core'; import { ApplicationConfig, APP_INITIALIZER } from '@angular/core';
import { provideRouter } from '@angular/router'; import { provideRouter } from '@angular/router';
import { routes } from './app.routes'; import { routes } from './app.routes';
import { provideClientHydration } from '@angular/platform-browser'; import { provideClientHydration } from '@angular/platform-browser';
@@ -8,6 +8,7 @@ import { UrlService } from './services/url.service';
import { API_URL } from './tokens/index' import { API_URL } from './tokens/index'
import { HTTP_INTERCEPTORS, provideHttpClient, withFetch } from '@angular/common/http'; import { HTTP_INTERCEPTORS, provideHttpClient, withFetch } from '@angular/common/http';
import { HttpRequestInterceptor } from './http.interceptor'; import { HttpRequestInterceptor } from './http.interceptor';
import { ConfigurationService } from './services/configuration.service';
export const appConfig: ApplicationConfig = { export const appConfig: ApplicationConfig = {
providers: [ providers: [
@@ -29,6 +30,12 @@ export const appConfig: ApplicationConfig = {
provide: HTTP_INTERCEPTORS, provide: HTTP_INTERCEPTORS,
useClass: HttpRequestInterceptor, useClass: HttpRequestInterceptor,
multi: true multi: true
},
{
provide: APP_INITIALIZER,
useFactory: (configService: ConfigurationService) => async () => await configService.ngOnInit(),
deps: [ConfigurationService],
multi: true
} }
] ]
}; };

View File

@@ -1,48 +0,0 @@
<table #table mat-table [dataSource]="data" class="mat-elevation-z8">
@for (colId of displayedColumns; track colId) {
<ng-container matColumnDef="{{colId}}">
<th mat-header-cell *matHeaderCellDef> {{schema[colId].header}} </th>
<td mat-cell *matCellDef="let element"> {{schema[colId].field(element)}} </td>
</ng-container>
}
<ng-container matColumnDef="expand">
<th mat-header-cell *matHeaderCellDef aria-label="row actions">&nbsp;</th>
<td mat-cell *matCellDef="let element">
<button mat-icon-button aria-label="expand row"
(click)="(expandedElement = expandedElement === element ? null : element); $event.stopPropagation()">
@if (expandedElement === element) {
<mat-icon>keyboard_arrow_up</mat-icon>
} @else {
<mat-icon>keyboard_arrow_down</mat-icon>
}
</button>
</td>
</ng-container>
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element" [attr.colspan]="columnsToDisplayWithExpand.length">
<div class="example-element-detail" [@detailExpand]="element == expandedElement ? 'expanded' : 'collapsed'">
<div class="example-element-diagram">
<div class="example-element-position"> {{"element.position"}} </div>
<div class="example-element-symbol"> {{"element.symbol"}} </div>
<div class="example-element-name"> {{"element.name"}} </div>
<div class="example-element-weight"> {{"element.weight"}} </div>
</div>
<div class="example-element-description">
{{"element.description"}}
<span class="example-element-description-attribution"> -- Wikipedia </span>
</div>
</div>
</td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="columnsToDisplayWithExpand"></tr>
<tr mat-row *matRowDef="let element; columns: columnsToDisplayWithExpand;" class="example-element-row"
[class.example-expanded-row]="expandedElement === element"
(click)="expandedElement = expandedElement === element ? null : element">
</tr>
<!--<tr mat-row *matRowDef="let row; columns: ['expandedDetail']; when: isExpandedRow" class="example-detail-row"></tr>-->
</table>

View File

@@ -1,31 +0,0 @@
.example-element-row td {
border-bottom-width: 0;
}
.example-element-detail {
overflow: hidden;
display: flex;
}
.example-element-diagram {
min-width: 80px;
border: 2px solid black;
padding: 8px;
font-weight: lighter;
margin: 8px 0;
height: 104px;
}
.example-element-symbol {
font-weight: bold;
font-size: 40px;
line-height: normal;
}
.example-element-description {
padding: 16px;
}
.example-element-description-attribution {
opacity: 0.5;
}

View File

@@ -1,74 +0,0 @@
import { Component, Input, ViewChild } from '@angular/core';
import { EnvelopeReceiverService } from '../../services/envelope-receiver.service';
import { MatTable, MatTableModule } from '@angular/material/table';
import { CommonModule } from '@angular/common'
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { animate, state, style, transition, trigger } from '@angular/animations';
@Component({
selector: 'app-envelope-table',
standalone: true,
imports: [MatTableModule, CommonModule, MatTableModule, MatButtonModule, MatIconModule],
templateUrl: './envelope-table.component.html',
animations: [
trigger('detailExpand', [
state('collapsed,void', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
]),
],
styleUrl: './envelope-table.component.scss'
})
export class EnvelopeTableComponent {
@Input() data: Array<any> = []
@Input() options?: { min_status?: number; max_status?: number; ignore_status?: number[] }
@Input() displayedColumns: string[] = ['title', 'status', 'type', 'privateMessage', 'addedWhen'];
@Input() schema: Record<string, { header: string; field: (element: any) => any; }> = {
'title': {
header: 'Title',
field: (element: any) => element.envelope.title
},
'status': {
header: 'Status',
field: (element: any) => element.envelope.statusName
},
'type': {
header: 'Type',
field: (element: any) => element.envelope.contractType
},
'privateMessage': {
header: 'Private Message',
field: (element: any) => element.privateMessage
},
'addedWhen': {
header: 'Added When',
field: (element: any) => element.addedWhen
},
}
columnsToDisplayWithExpand = [...this.displayedColumns, 'expand'];
expandedElement: any | null;
@ViewChild(MatTable) table!: MatTable<any>;
constructor(private erService: EnvelopeReceiverService) { }
async ngOnInit() {
if (this.data.length === 0)
this.data = await this.erService.getEnvelopeReceiverAsync(this.options);
}
public updateTable() {
this.table.renderRows();
}
isExpandedRow(index: number, row: any): boolean {
return (row?.envelopeId === this.expandedElement?.envelopeId) && (row?.receiverId === this.expandedElement?.receiverId);
}
}

View File

@@ -37,19 +37,19 @@ export class ReceiverInputComponent implements OnInit, OnChanges {
private setupFiltering(): void { private setupFiltering(): void {
this.filteredOptions = this.control.valueChanges.pipe( this.filteredOptions = this.control.valueChanges.pipe(
startWith(''), startWith(''),
map(value => this.filter(value || '', this.options)), map(value => this.filter(value || '', this.options, this.index)),
); );
} }
control = new FormControl(''); control = new FormControl('');
filteredOptions!: Observable<string[]>; filteredOptions!: Observable<string[]>;
@Input() options: string[] = []; @Input() options: string[] = [];
@Input() filter: (value: string, options: string[]) => string[] = value => { @Input() filter: (value: string, options: string[], index?: number) => string[] = value => {
const filterValue = value.toLowerCase(); const filterValue = value.toLowerCase();
return this.options.filter(option => option.toLowerCase().includes(filterValue)); return this.options.filter(option => option.toLowerCase().includes(filterValue));
} }
@Input() index?: number;
public get text(): string { public get text(): string {
return this.control.value || ''; return this.control.value || '';

View File

@@ -1,7 +1,7 @@
<table mat-table [dataSource]="receiverData" class="mat-elevation-z8"> <table mat-table [dataSource]="receiverData" class="mat-elevation-z8">
<ng-container matColumnDef="email"> <ng-container matColumnDef="email">
<th mat-header-cell *matHeaderCellDef> Email </th> <th mat-header-cell *matHeaderCellDef> Email </th>
<td mat-cell *matCellDef="let element"> <td mat-cell *matCellDef="let element; let i = index">
<receiver-input [options]="receiver_mails" [filter]="receiver_filter"></receiver-input> <receiver-input [options]="receiver_mails" [filter]="receiver_filter"></receiver-input>
</td> </td>
</ng-container> </ng-container>

View File

@@ -0,0 +1,59 @@
@if(isFilterable) {
<mat-form-field>
<mat-label>{{filter.label}}</mat-label>
<input matInput (keyup)="applyFilter($event)" [placeholder]="filter.placeholder" #input>
</mat-form-field>
}
<table mat-table [dataSource]="dataSource" multiTemplateDataRows class="mat-elevation-z8" matSort>
@for (column of __columnsToDisplay; track column) {
<ng-container matColumnDef="{{column}}">
@if(isSortable) {
<th mat-header-cell *matHeaderCellDef mat-sort-header> {{schema[column].header}} </th>
}
@else {
<th mat-header-cell *matHeaderCellDef> {{schema[column].header}} </th>
}
<td mat-cell *matCellDef="let element"> {{schema[column].field(element)}} </td>
</ng-container>
}
<!-- Expanded Content Column - The detail row is made up of this one column that spans across all columns -->
@if(isExpandable) {
<ng-container matColumnDef="expand">
<th mat-header-cell *matHeaderCellDef aria-label="row actions">&nbsp;</th>
<td mat-cell *matCellDef="let element">
<button mat-icon-button aria-label="expand row" (click)="toggleExpandedRow(element, $event)">
@if (__expandedElement === element) {
<mat-icon>keyboard_arrow_up</mat-icon>
} @else {
<mat-icon>keyboard_arrow_down</mat-icon>
}
</button>
</td>
</ng-container>
<ng-container matColumnDef="expandedDetail">
<td mat-cell *matCellDef="let element" [attr.colspan]="__columnsToDisplayWithExpand.length">
<div class="example-element-detail" [@detailExpand]="element == __expandedElement ? 'expanded' : 'collapsed'">
@if(__expandedElement === element){
<ng-content select="[expanded]" detailed></ng-content>
}
</div>
</td>
</ng-container>
}
@if(isExpandable) {
<tr mat-header-row *matHeaderRowDef="__columnsToDisplayWithExpand"></tr>
<tr mat-row *matRowDef="let element; columns: __columnsToDisplayWithExpand;" class="example-element-row"
[class.example-expanded-row]="__expandedElement === element" (click)="toggleExpandedRow(element, $event)">
</tr>
<tr mat-row *matRowDef="let row; columns: ['expandedDetail']" class="example-detail-row"></tr>
}
@else {
<tr mat-header-row *matHeaderRowDef="__columnsToDisplay"></tr>
<tr mat-row *matRowDef="let row; columns: __columnsToDisplay;"></tr>
}
</table>
@if(paginatorSizeOptions && paginatorSizeOptions.length > 0) {
<mat-paginator [pageSizeOptions]="paginatorSizeOptions" aria-label="Select page of users"></mat-paginator>
}

View File

@@ -0,0 +1,52 @@
table {
width: 100%;
}
tr.example-detail-row {
height: 0;
}
tr.example-element-row:not(.example-expanded-row):hover {
background: whitesmoke;
}
tr.example-element-row:not(.example-expanded-row):active {
background: #efefef;
}
.example-element-row td {
border-bottom-width: 0;
}
.example-element-detail {
overflow: hidden;
display: flex;
}
.example-element-diagram {
min-width: 80px;
border: 2px solid black;
padding: 8px;
font-weight: lighter;
margin: 8px 0;
height: 104px;
}
.example-element-symbol {
font-weight: bold;
font-size: 40px;
line-height: normal;
}
.example-element-description {
padding: 16px;
}
.example-element-description-attribution {
opacity: 0.5;
}
.mat-mdc-form-field {
font-size: 14px;
width: 100%;
}

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { DDTable } from './dd-table.component';
describe('TableExpandableRowsExampleComponent', () => {
let component: DDTable;
let fixture: ComponentFixture<DDTable>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [DDTable]
})
.compileComponents();
fixture = TestBed.createComponent(DDTable);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,103 @@
import { AfterViewInit, Component, Input, ViewChild, inject } from '@angular/core';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { MatTable, MatTableDataSource, MatTableModule } from '@angular/material/table';
import { ConfigurationService } from '../../../services/configuration.service';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatSort, MatSortModule } from '@angular/material/sort';
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
/**
* @title Table with expandable rows
*/
@Component({
selector: 'dd-table',
styleUrl: 'dd-table.component.scss',
templateUrl: 'dd-table.component.html',
animations: [
trigger('detailExpand', [
state('collapsed,void', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
]),
],
standalone: true,
imports: [
MatTableModule,
MatButtonModule,
MatIconModule,
MatFormFieldModule,
MatInputModule,
MatTableModule,
MatSort,
MatSortModule,
MatPaginator,
MatPaginatorModule
],
})
export class DDTable implements AfterViewInit {
public readonly dataSource: any = new MatTableDataSource();
@Input() public set columnsToDisplay(value: string[]) {
this.__columnsToDisplay = value;
this.__columnsToDisplayWithExpand = [...value, 'expand'];
}
@Input() public set data(value: any[]) {
this.dataSource.data = value;
}
@Input() schema: Record<string, { header: string; field: (element: any) => any; }> = {}
@Input() paginatorSizeOptions?: number[];
@Input() filter: { label: string, placeholder: string } = { label: '', placeholder: '' }
@Input() isFilterable: boolean = false;
@Input() isExpandable: boolean = false;
@Input() isSortable: boolean = false;
@Input() onToggleExpandedRow: (element: any, event: Event) => Promise<void> = async (element: any, event: Event) => { }
public get data(): any[] {
return this.dataSource.data;
}
__columnsToDisplay: string[] = [];
__columnsToDisplayWithExpand: string[] = [];
__expandedElement!: any;
config: ConfigurationService = inject(ConfigurationService);
@ViewChild(MatSort) sort!: MatSort;
@ViewChild(MatPaginator) paginator!: MatPaginator;
@ViewChild(MatTable) table!: MatTable<any>;
ngAfterViewInit(): void {
if (this.isSortable)
this.dataSource.sort = this.sort;
if (this.paginatorSizeOptions && this.paginatorSizeOptions.length > 0)
this.dataSource.paginator = this.paginator;
}
applyFilter(event: Event) {
const filterValue = (event.target as HTMLInputElement).value;
this.dataSource.filter = filterValue.trim().toLowerCase();
}
update() {
this.table.renderRows();
}
async toggleExpandedRow(element: any, event: Event): Promise<void> {
// first determine the new expanded element, thus it would be possible to use up-to-date
const newExpandedElement = this.__expandedElement === element ? null : element;
// before update the expanded element call the call-back method to show up-to-date component
await this.onToggleExpandedRow(newExpandedElement, event);
// assign expanded element
this.__expandedElement = newExpandedElement;
event.stopPropagation();
}
}

View File

@@ -0,0 +1,12 @@
<dd-table [data]="data" [columnsToDisplay]="displayedColumns" [schema]="schema"
[paginatorSizeOptions]="[5, 10, 25, 100]" [filter]="{label: 'Filter', placeholder: ''}"
[onToggleExpandedRow]="onToggleExpandedRow" [isSortable]="true" [isExpandable]="true" [isFilterable]="true">
<mat-tab-group expanded>
<mat-tab label="Emfänger">
<receiver-status-table></receiver-status-table>
</mat-tab>
<mat-tab label="History">
<history-table></history-table>
</mat-tab>
</mat-tab-group>
</dd-table>

View File

@@ -0,0 +1,59 @@
/* Structure */
table {
width: 100%;
}
.mat-mdc-form-field {
font-size: 14px;
width: 100%;
margin-top: 10px;
}
/* For expanding table */
table {
width: 100%;
}
tr.example-detail-row {
height: 0;
}
tr.example-element-row:not(.example-expanded-row):hover {
background: whitesmoke;
}
tr.example-element-row:not(.example-expanded-row):active {
background: #efefef;
}
.example-element-row td {
border-bottom-width: 0;
}
.example-element-detail {
overflow: hidden;
display: flex;
}
.example-element-diagram {
min-width: 80px;
border: 2px solid black;
padding: 8px;
font-weight: lighter;
margin: 8px 0;
height: 104px;
}
.example-element-symbol {
font-weight: bold;
font-size: 40px;
line-height: normal;
}
.example-element-description {
padding: 16px;
}
.example-element-description-attribution {
opacity: 0.5;
}

View File

@@ -0,0 +1,82 @@
import { AfterViewInit, Component, Input, ViewChild, inject, viewChild } from '@angular/core';
import { EnvelopeService } from '../../../services/envelope.service';
import { animate, state, style, transition, trigger } from '@angular/animations';
import { ConfigurationService } from '../../../services/configuration.service';
import { DDTable } from "../dd-table/dd-table.component";
import { ClearableInputComponent } from '../../clearable-input/clearable-input.component'
import { MatTabsModule } from '@angular/material/tabs';
import { ReceiverStatusTableComponent } from "../receiver-status-table/receiver-status-table.component";
import { HistoryTableComponent } from "../history-table/history-table.component";
import { EnvelopeReceiverService } from '../../../services/envelope-receiver.service';
import { HistoryService } from '../../../services/history.service';
@Component({
selector: 'envelope-table',
standalone: true,
imports: [DDTable, ClearableInputComponent, MatTabsModule, ReceiverStatusTableComponent, HistoryTableComponent],
templateUrl: './envelope-table.component.html',
animations: [
trigger('detailExpand', [
state('collapsed,void', style({ height: '0px', minHeight: '0' })),
state('expanded', style({ height: '*' })),
transition('expanded <=> collapsed', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)')),
]),
],
styleUrl: './envelope-table.component.scss'
})
export class EnvelopeTableComponent implements AfterViewInit {
@Input() options?: { min_status?: number; max_status?: number; ignore_status?: number[] }
displayedColumns: string[] = ['title', 'status', 'type', 'addedWhen'];
schema: Record<string, { header: string; field: (element: any) => any; }> = {
'title': {
header: 'Title',
field: (element: any) => element.title
},
'status': {
header: 'Status',
field: (element: any) => element.statusName
},
'type': {
header: 'Type',
field: (element: any) => this.config.envelopeTypeTitles[element.contractType - 1]
},
'addedWhen': {
header: 'Added When',
field: (element: any) => element.addedWhen
}
}
data: any[] = [];
@ViewChild(ReceiverStatusTableComponent) rsTable!: ReceiverStatusTableComponent
@ViewChild(HistoryTableComponent) histTable!: HistoryTableComponent
onToggleExpandedRow: (envelope: any, event: Event) => Promise<void> = async (envelope, event) => {
if (envelope === null || envelope === undefined)
return;
var uuid: string = envelope.uuid;
this.rsTable.data = await this.erService.getSecretAsync(uuid);
var id: number = envelope.id;
var refType: number = this.config.referenceType.receiver;
const histories = await this.histService.getHistoryAsync({ envelopeId: id, referenceType: refType, withReceiver: true })
this.histTable.data = histories;
}
private eService: EnvelopeService = inject(EnvelopeService);
private config: ConfigurationService = inject(ConfigurationService);
private readonly erService: EnvelopeReceiverService = inject(EnvelopeReceiverService);
private readonly histService: HistoryService = inject(HistoryService);
async ngAfterViewInit() {
this.data = await this.eService.getEnvelopeAsync(this.options);
}
}

View File

@@ -0,0 +1 @@
<dd-table [data]="data" [columnsToDisplay]="columnsToDisplay" [schema]="schema" [isSortable]="true"></dd-table>

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { HistoryTableComponent } from './history-table.component';
describe('HistoryTableComponent', () => {
let component: HistoryTableComponent;
let fixture: ComponentFixture<HistoryTableComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [HistoryTableComponent]
})
.compileComponents();
fixture = TestBed.createComponent(HistoryTableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,30 @@
import { Component } from '@angular/core';
import { DDTable } from '../dd-table/dd-table.component'
@Component({
selector: 'history-table',
standalone: true,
imports: [DDTable],
templateUrl: './history-table.component.html',
styleUrl: './history-table.component.scss'
})
export class HistoryTableComponent {
data: any[] = [];
schema: Record<string, { header: string; field: (element: any) => any; }> = {
"status": {
"header": "Status",
"field": hist => hist.statusName
},
"user": {
"header": "Benutzer",
"field": hist => hist.userReference
},
"date": {
"header": "Datum",
"field": hist => hist.actionDate
}
}
columnsToDisplay: string[] = ["status", "user", "date"];
}

View File

@@ -0,0 +1 @@
<dd-table [data]="data" [columnsToDisplay]="columnsToDisplay" [schema]="schema" [isSortable]="true"></dd-table>

View File

@@ -0,0 +1,23 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { ReceiverStatusTableComponent } from './receiver-status-table.component';
describe('ReceiverStatusTableComponent', () => {
let component: ReceiverStatusTableComponent;
let fixture: ComponentFixture<ReceiverStatusTableComponent>;
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [ReceiverStatusTableComponent]
})
.compileComponents();
fixture = TestBed.createComponent(ReceiverStatusTableComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@@ -0,0 +1,30 @@
import { Component } from '@angular/core';
import { DDTable } from '../dd-table/dd-table.component'
@Component({
selector: 'receiver-status-table',
standalone: true,
imports: [DDTable],
templateUrl: './receiver-status-table.component.html',
styleUrl: './receiver-status-table.component.scss'
})
export class ReceiverStatusTableComponent {
data: any[] = [];
schema: Record<string, { header: string; field: (element: any) => any; }> = {
"name": {
"header": "Email Anrede",
"field": (er) => er.name
},
"email": {
"header": "Email",
"field": (er) => er.receiver.emailAddress
},
"access_code": {
"header": "Email",
"field": (er) => er.accessCode
},
}
columnsToDisplay: string[] = ["name", "email", "access_code"];
}

View File

@@ -0,0 +1,23 @@
<table mat-table [dataSource]="receiverData" class="mat-elevation-z8">
<ng-container matColumnDef="email">
<th mat-header-cell *matHeaderCellDef> Email </th>
<td mat-cell *matCellDef="let element; let i = index">
<receiver-input [options]="receiver_mails" [filter]="receiver_filter" [index]="i"></receiver-input>
</td>
</ng-container>
<ng-container matColumnDef="name">
<th mat-header-cell *matHeaderCellDef> Anrede Email </th>
<td mat-cell *matCellDef="let element">
<clearable-input [label]="'Anrede Email'" [value]="element.name"></clearable-input>
</td>
</ng-container>
<ng-container matColumnDef="accessCode">
<th mat-header-cell *matHeaderCellDef> Zugriffscode </th>
<td mat-cell *matCellDef="let element"> {{element.accessCode}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="displayedColumns"></tr>
<tr mat-row *matRowDef="let row; columns: displayedColumns;"></tr>
</table>

View File

@@ -1,15 +1,15 @@
import { Component, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core'; import { Component, OnInit, QueryList, ViewChildren } from '@angular/core';
import { FormsModule, ReactiveFormsModule, FormControl } from '@angular/forms'; import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { MatInputModule } from '@angular/material/input'; import { MatInputModule } from '@angular/material/input';
import { MatTableModule } from '@angular/material/table'; import { MatTableModule } from '@angular/material/table';
import { AsyncPipe } from '@angular/common'; import { AsyncPipe } from '@angular/common';
import { MatAutocompleteModule } from '@angular/material/autocomplete'; import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatFormFieldModule } from '@angular/material/form-field'; import { MatFormFieldModule } from '@angular/material/form-field';
import { ReceiverService } from '../../services/receiver.service' import { ReceiverService } from '../../../services/receiver.service'
import { ReceiverInputComponent } from '../receiver-input/receiver-input.component'; import { ReceiverInputComponent } from '../../receiver-input/receiver-input.component';
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { ClearableInputComponent } from '../clearable-input/clearable-input.component' import { ClearableInputComponent } from '../../clearable-input/clearable-input.component'
import { v4 as uuidv4 } from 'uuid'; import { v4 as uuidv4 } from 'uuid';
@Component({ @Component({
@@ -34,24 +34,41 @@ export class ReceiverTableComponent implements OnInit {
constructor(private receiverService: ReceiverService) { } constructor(private receiverService: ReceiverService) { }
async ngOnInit() { async ngOnInit() {
this.receiver_mails = await this.receiverService.getReceiverAsync().then((receivers: any[]) => receivers.map(r => r.emailAddress)); const receivers = await this.receiverService.getReceiverAsync();
this.receiver_mails = receivers.map((r: any) => r.emailAddress);
this.last_used_name = receivers.reduce((acc: any, r: any) => {
acc[r.emailAddress] = r.lastUsedName;
return acc;
}, {} as { [key: string]: string | null });
} }
receiver_filter: (value: string, options: string[]) => string[] = (value, options) => { receiver_filter: (value: string, options: string[], index?: number) => string[] = (value, options, index) => {
const filterValue = value.toLowerCase(); const filterValue = value.toLowerCase();
// set the name if it is used before
const name = this.last_used_name[value];
if (name && index != null && index != undefined) {
this.receiverData.at(index)!.name = name
}
// !!! do not allow email duplication !!!
var similarMails = this.receiver_mails.filter(m => m.toLocaleLowerCase() === value.toLocaleLowerCase() && m !== value)
if (similarMails.length > 0 && index != undefined) {
this.receiverInputs[index].text = similarMails[0];
}
// if added into last row // if added into last row
if (value.length > 0 && (this.receiverInputs.at(-1)?.lenght ?? 0) > 0) { if (value.length > 0 && (this.receiverInputs.at(-1)?.lenght ?? 0) > 0) {
this.receiverData.at(-1)!.accessCode = generateAccessCode(); this.receiverData.at(-1)!.accessCode = generateAccessCode();
this.receiverData.push({ email: "", name: "", accessCode: "" }); this.receiverData.push({ email: "", name: "", accessCode: "" });
this.update(); this.update();
} }
else if (value.length == 0) { // delete the row with out mail
for (var i = 0; i < this.receiverInputs.length - 1; i++) { else if (value.length === 0 && this.receiverInputs.length - 1 !== index) {
if (this.receiverInputs[i].lenght === 0) { if (this.receiverInputs.length > 1 && this.receiverInputs[index!]?.lenght === 0) {
this.receiverData.splice(i, 1); this.receiverData.splice(index!, 1);
this.update(); this.update();
}
} }
} }
@@ -59,6 +76,7 @@ export class ReceiverTableComponent implements OnInit {
} }
receiver_mails: string[] = []; receiver_mails: string[] = [];
last_used_name: { [key: string]: string | null } = {};
@ViewChildren(ReceiverInputComponent) receiverInputsQueryList!: QueryList<ReceiverInputComponent>; @ViewChildren(ReceiverInputComponent) receiverInputsQueryList!: QueryList<ReceiverInputComponent>;
get receiverInputs(): ReceiverInputComponent[] { get receiverInputs(): ReceiverInputComponent[] {

View File

@@ -5,7 +5,7 @@ import { MatFormFieldModule } from '@angular/material/form-field';
import { MatStepperModule } from '@angular/material/stepper'; import { MatStepperModule } from '@angular/material/stepper';
import { MatButtonModule } from '@angular/material/button'; import { MatButtonModule } from '@angular/material/button';
import { MatSelectModule } from '@angular/material/select'; import { MatSelectModule } from '@angular/material/select';
import { ReceiverTableComponent } from "../../components/receiver-table/receiver-table.component"; import { ReceiverTableComponent } from "../../components/tables/receiver-table/receiver-table.component";
import { MatIconModule } from '@angular/material/icon'; import { MatIconModule } from '@angular/material/icon';
@Component({ @Component({

Some files were not shown because too many files have changed in this diff Show More