Compare commits

..

120 Commits

Author SHA1 Message Date
Developer 02
dd7454d38e feat: Separate CSS for Cursor company created
Eine separate CSS-Datei für das Unternehmen Cursor wurde erstellt. Die site.css wurde angepasst, um das Layout entsprechend dem Cursor-Logo responsiv zu gestalten.
2024-09-17 10:14:34 +02:00
Developer 02
f7c3ed280a merge: Master-Branch integriert 2024-09-17 00:52:34 +02:00
Developer 02
9ffeb7afe8 feat: UI für die Dokumentenunterzeichnungsseite verbessert
- Layout modernisiert und responsiver gestaltet.
- Button-Stile und Farbschemata aktualisiert.
- Verbesserte Ausrichtung von Text und Symbolen für mehr visuelle Klarheit.
- Fokus auf die Verbesserung der Benutzererfahrung beim Unterzeichnen von Dokumenten.
2024-09-17 00:38:37 +02:00
Developer 02
a83994af43 feat: Google Fonts und Google Icons hinzugefügt; CSP-Anpassungen vorgenommen
- Google Fonts und Google Icons in das Projekt integriert.
- Content Security Policy (CSP) aktualisiert, um die Nutzung von Google Fonts und Google Icons zu ermöglichen.
2024-09-16 15:19:56 +02:00
Developer 02
8345034fcd refactor: Logo aktualisieren 2024-09-16 14:31:18 +02:00
Developer 02
a763d3c353 feat: Mehrsprachige Unterstützung für den Header hinzugefügt 2024-09-16 14:04:34 +02:00
Developer 02
5ba5d2755b feat: EnvelopeLocked Seite anpassen und Stile für Firmenbranding aktualisieren
- Die Datei `EnvelopeLocked.cshtml` wurde aktualisiert, um eine neue Willkommensnachricht, ein Logo und ein benutzerdefiniertes Kopfzeilen-Layout für das eSign-Portal aufzunehmen.
- Aktualisierungen der Lokalisierung hinzugefügt, um die korrekte Anzeige der ausgewählten Sprache und Flagge zu gewährleisten.
- Das Layout und die Abstände wurden angepasst, um besser mit den unternehmensspezifischen Designanforderungen übereinzustimmen.
- Modifizierte `site.css` für benutzerdefinierte Schaltflächenstile, Seitenlayout und fügte unternehmensspezifische Farben für die Markenkonsistenz hinzu.
2024-09-16 13:51:07 +02:00
Developer 02
8629599f86 fix: aktualisiere TestReceiverController zur Verwendung von CRUDControllerBase und entferne unnötige Pakete
- Ersetze TestControllerBase durch CRUDControllerBase im TestReceiverController
- Aktualisiere generische Typen auf ReceiverCreateDto, ReceiverReadDto und ReceiverUpdateDto
- Entferne nicht benötigte Pakete aus dem Projekt
2024-08-29 16:42:48 +02:00
Developer 02
d166ae5a8b Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2024-08-29 15:48:53 +02:00
Developer 02
145d139e3a fix(auth): Aktualisierung der Authentifizierungsstatusbehandlung
- Methode `logInOut` aktualisiert, um nach dem Logout zu `/login` zu navigieren.
- Methoden `login` und `logout` angepasst, um `#IsAuthenticated` basierend auf der Antwort zu aktualisieren.
- Sicherstellung, dass der Authentifizierungsstatus nach Login und Logout korrekt gesetzt wird.
2024-08-29 15:46:20 +02:00
Developer01
d3ce34ee31 MS TryCatchBlock Finalize Documents For Each 2024-08-28 11:14:46 +02:00
Developer01
fd61d4431f Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2024-08-28 11:14:13 +02:00
Developer 02
93417d1b37 fix: Den Text des Navbar-Brand von "SignFlow" auf "signFlow" geändert, um eine konsistente Gestaltung zu gewährleisten. 2024-08-23 10:58:54 +02:00
Developer 02
ca3ea36a83 chore: Favicon aktualisieren 2024-08-23 10:57:23 +02:00
Developer 02
c59d9bbf57 chore: Favicon aktualisieren 2024-08-23 10:54:13 +02:00
Developer 02
0cf1cd10c0 fix: UUID-Generierung und Typdeklarationsprobleme beheben
- `crypto.randomUUID()` durch `uuid.v4()` ersetzt, um die Kompatibilität über verschiedene Node.js-Versionen hinweg zu verbessern.
- Das `uuid`-Paket installiert und Typdeklarationen mit `@types/uuid` hinzugefügt, um TypeScript-Fehler zu beheben.
- Die Funktion `generateAccessCode` aktualisiert, um die `uuid`-Bibliothek zur UUID-Generierung zu verwenden.
2024-08-23 01:21:38 +02:00
Developer 02
1da73d1754 chore: Client-App-Dateien unter wwwroot aktualisiert
- Client-App-Dateien im Verzeichnis `wwwroot` aktualisiert, um die neuesten Änderungen und Verbesserungen widerzuspiegeln.
2024-08-23 00:57:10 +02:00
Developer 02
24037f8366 feat: Navbar mit zusätzlichem Button und Icons aktualisiert
- Neuer "Umschläge"-Button zur Navbar hinzugefügt, um die Navigation zur Startseite zu erleichtern.
- Icon des "Neuer Umschlag"-Buttons zu "forward_to_inbox" geändert für eine bessere visuelle Darstellung.
2024-08-23 00:51:18 +02:00
Developer 02
91b891513f fix: Platzhaltertext für Dateiupload in der Envelopes-Erstellungstabelle aktualisiert
- Platzhaltertext von "No file uploaded yet." zu "Noch keine Datei hochgeladen." für bessere Lokalisierung geändert.
2024-08-23 00:41:22 +02:00
Developer 02
e7d1f1574f refactor: Komponenten-Namen vereinfacht und Envelopes-Seite der '\' Route zugewiesen
- Komponenten-Namen zur besseren Lesbarkeit vereinfacht
- Envelopes-Seite der '\' Route für einfachere Navigation zugewiesen
2024-08-23 00:37:56 +02:00
Developer 02
80a3a26af8 feat: EnvelopeCreationComponent mit neuen Formularelementen und Datei-Upload-Schritt aktualisiert
- `isLinear` und `titelControl` als @Input-Eigenschaften in `EnvelopeCreationComponent` hinzugefügt
- Datei-Upload-Funktionalität mit visueller Rückmeldung für ausgewählte Dateien implementiert
- Mat-stepper refaktoriert, um den neuen Datei-Upload-Schritt einzubeziehen
- Design durch Hinzufügen von Symbolen zu den 'Weiter'-Buttons in jedem Schritt verbessert
2024-08-23 00:26:09 +02:00
Developer 02
9905ea5a12 feat: Symbole zu den Weiter-Buttons in den Envelope Creation Schritten hinzufügen 2024-08-22 23:10:12 +02:00
Developer 02
a7a77cd491 feat: Zugangscode-Generierung zu ReceiverTableComponent hinzufügen
- `generateAccessCode` Funktion implementiert, um einen eindeutigen Zugangscode zu generieren
- Zugangscode-Generierung in die `receiver_filter` Funktion integriert
- `receiver_filter` aktualisiert, um einen generierten Zugangscode der letzten Zeile zuzuweisen, wenn ein neuer Empfänger hinzugefügt wird
- Dynamisches Zeilenmanagement basierend auf Eingabeveränderungen verbessert
2024-08-22 22:53:29 +02:00
Developer 02
f795b1447f feat: ClearableInputComponent hinzufügen und in ReceiverTableComponent integrieren
- `ClearableInputComponent` erstellt mit einer Löschen-Schaltfläche für Texteingaben
- `ClearableInputComponent` in `ReceiverTableComponent` integriert, um dynamische Eingabefelder zu verwalten
- `receiver-table.component.html` aktualisiert, um `ClearableInputComponent` für das Feld 'Anrede Email' zu verwenden
2024-08-22 22:34:07 +02:00
Developer 02
e5e12bfb61 feat: Löschen-Schaltfläche zur ReceiverInputComponent hinzufügen und Verwaltung der Empfängerdaten aktualisieren
- Löschen-Schaltfläche zur `ReceiverInputComponent` hinzugefügt, um den Texteingang zu leeren
- Logik in `receiver_filter` implementiert, um eine leere Zeile hinzuzufügen, wenn ein neuer Empfänger hinzugefügt wird, und Zeilen zu entfernen, wenn Eingaben gelöscht werden
- Verwaltung der `receiverData` aktualisiert, um dynamische Hinzufügung und Entfernung von Zeilen basierend auf Eingaben zu berücksichtigen
2024-08-22 20:15:03 +02:00
Developer 02
6a8baf08ed feat: ReceiverInputComponent zu ReceiverTableComponent hinzufügen
- `ReceiverInputComponent` für E-Mail-Eingabe mit Autocomplete erstellt
- `ReceiverInputComponent` in `ReceiverTableComponent` integriert
- `ReceiverInputComponent` mit Eingabeoptionen für E-Mail-Adressen konfiguriert
2024-08-22 18:24:09 +02:00
Developer 02
10ac34a9f7 refactor: ReceiverInputComponent in ReceiverTableComponent umbenennen und in das Verzeichnis components verschieben 2024-08-22 17:40:14 +02:00
Developer 02
72af1cc2a2 refactor: nicht verwendete Filtermethode aus der Receiver-Input-Komponente entfernen 2024-08-22 17:18:17 +02:00
Developer 02
cd32ae2a35 feat: neuen Receiver-Input-Komponente mit Autocomplete und Tabellenanzeige hinzufügen
- Implementierung der `ReceiverInputComponent` mit Angular Material Autocomplete und Tabelle
- Abruf und Filterung von E-Mail-Adressen aus `ReceiverService`
- Anzeige des E-Mail-Inputs mit Autocomplete-Optionen und einer Datentabelle
- Integration der `ReceiverInputComponent` in den `envelope-creation` Formularschritt
2024-08-22 17:04:46 +02:00
Developer 02
ddc0c9c6f3 feat: DELETE-Anforderungsmethode zu API-Diensten im Angular-Frontend hinzufügen 2024-08-21 18:13:32 +02:00
Developer 02
489c2a2a9f refactor: Receiver-Update-Endpunkt entfernen durch Überschreiben und Hinzufügen des [NonAction]-Attributs 2024-08-21 18:02:09 +02:00
Developer 02
320e81719b feat: HTTP-Anforderungsdienste mit HttpClient im Frontend implementieren 2024-08-21 17:59:55 +02:00
Developer 02
66a8471f05 refactor: Code in Regionen für entfernte Endpunkte organisieren 2024-08-21 17:16:44 +02:00
Developer 02
c7a4ef4722 fix: Füge try-catch-Blöcke zur Fehlerbehandlung in der Delete-Methode und dem Service hinzu 2024-08-21 17:14:06 +02:00
Developer 02
1673ea81df fix: Füge try-catch-Blöcke zur Fehlerbehandlung in der Delete-Methode und dem Service hinzu 2024-08-21 17:09:16 +02:00
Developer 02
306956a7be feat: Löschen nach E-Mail oder Signatur zur Delete-Methode und zum Service hinzugefügt
- Die `Delete`-Methode im Controller aktualisiert, um das Löschen nach `id`, `emailAddress` oder `signature` zu unterstützen.
- `DeleteByAsync`-Methode im Service hinzugefügt, um Datensätze basierend auf `emailAddress` und `signature` zu löschen.
- Fehlerbehandlung mit Protokollierung für fehlgeschlagene Löschversuche verbessert.
2024-08-21 16:37:54 +02:00
Developer 02
bfe3d38ecc fix: E-Mail-Formatvalidierung zu ReceiverCreateDto hinzugefügt und Modellvalidierung im Create-Methoden behandelt
- `[EmailAddress]`-Attribut auf `EmailAddress` in `ReceiverCreateDto` angewendet, um das E-Mail-Format zu validieren.
- `ModelState.IsValid`-Überprüfung zur `Create`-Methode hinzugefügt, um Validierungsfehler vor dem Aufruf der Basis-`Create`-Methode zu behandeln.
2024-08-21 16:19:18 +02:00
Developer 02
6e5bb58f65 feat: E-Mail-Formatvalidierung in der Receiver-Entität mit [EmailAddress]-Attribut hinzugefügt 2024-08-21 15:10:07 +02:00
Developer 02
b96c6c10f8 feat: Filterung nach emailAddress und signature im Receiver-Repository, -Service und -Controller hinzugefügt
- `ReadBy`-Methode im Receiver-Repository implementiert, um nach `emailAddress` und `signature` zu filtern.
- `ReadByAsync`-Methode im Receiver-Service hinzugefügt, um Receiver-Daten abzurufen und zuzuordnen.
- Controller-`Get`-Endpunkt aktualisiert, um optionale `emailAddress` und `signature` Query-Parameter für die Filterung zu unterstützen.
- Fehlerbehandlung mit Protokollierung für fehlgeschlagene Service-Operationen im Controller hinzugefügt.
2024-08-21 15:05:18 +02:00
Developer 02
afedfdd596 refactor: Receiver-Service in CRUD-Service umgewandelt und DTOs aktualisiert
- Receiver-Service von einfachem CRUD zu generischem CRUD-Service umgewandelt.
- `ReceiverDto` in `ReceiverReadDto` umbenannt.
- Neues `ReceiverCreateDto` mit automatischer SHA-256-Signaturerstellung und aktuellem Zeitstempel erstellt.
- Leeres `ReceiverUpdateDto` für zukünftige Updates hinzugefügt.
2024-08-21 14:37:45 +02:00
Developer 02
3a7099feb4 fix: Füge required-Attribut zu Receiver-Eigenschaften hinzu 2024-08-21 11:29:39 +02:00
Developer 02
c704d222f0 fix: Beseitige Duplikation von formControlName="firstCtrl" 2024-08-21 11:27:17 +02:00
Developer 02
83ce528e2f feat: Füge Eingaben für die Umschlagstabelle und Statusfilteroptionen hinzu
- `data`, `displayedColumns` und `schema` wurden als `@Input`-Eigenschaften für die Umschlagstabelle hinzugefügt.
- `min`, `max` und `ignore` Statusfilter wurden als Objekt-Eingaben für Statusbeschränkungen eingeführt.
- Die Methode `getEnvelopeReceiver` wurde aktualisiert, um Statusfilter über Abfrageparameter zu unterstützen.
- `getEnvelopeReceiverAsync` wurde für die Promise-basierte Verarbeitung von Status-gefilterten Anfragen hinzugefügt.
- Die Umschlag-Tab-Konfiguration wurde geändert, um Statusfilter dynamisch anzuwenden.
2024-08-21 11:13:31 +02:00
Developer 02
9cc15f9beb feat: Envelope-Status-Enum erstellt 2024-08-21 09:13:57 +02:00
Developer 02
d323244157 feat: Füge Abfrageparameter zum GetEnvelopeReceiver-Endpunkt hinzu
- Optionale Abfrageparameter hinzugefügt: min_status, max_status und ignore_status.
- ignore_status standardmäßig auf ein leeres Array gesetzt, wenn nicht bereitgestellt.
- Aktualisierte _erService.ReadByUsernameAsync-Methode, um neue Parameter einzuschließen.
- Bestehende Fehlerbehandlung und Protokollierung beibehalten.
2024-08-20 16:15:11 +02:00
Developer 02
56d35c65bb feat: ReadByUsernameAsync-Methode im Service aktualisiert, um Statusfilter zu unterstützen
- `ReadByUsernameAsync` Methode angepasst, um zusätzliche Parameter `min_status`, `max_status` und `ignore_statuses` zu integrieren.
- Die Methode ruft jetzt die aktualisierte Repository-Methode auf, um Umschläge basierend auf Statusfiltern abzurufen.
- DTO-Zuordnung und Erfolgsrückgabe beibehalten.
2024-08-20 12:30:17 +02:00
Developer 02
15eabfc834 feat: ReadByUsernameAsync-Methode erweitert, um Statusfilter hinzuzufügen
- `ReadByUsernameAsync` aktualisiert, um optionale Parameter `min_status`, `max_status` und `ignore_statuses` zu unterstützen.
- Abfrage optimiert, um Umschläge basierend auf Statuswerten zu filtern.
- Ermöglicht das Abrufen von Umschlägen mit spezifischen Statusbereichen oder das Ignorieren bestimmter Status.
2024-08-20 11:28:25 +02:00
Developer 02
11e8c46e44 feat: Umschlag-Erstellungskomponente erstellt und Angular Material Stepper initialisiert 2024-08-20 09:35:00 +02:00
Developer 02
a14bd78415 feat: Navigationsleiste angepasst, Logout- und Neuen-Umschlag-Button hinzugefügt
- Navigationsleiste überarbeitet und das Layout optimiert.
- Logout-Button hinzugefügt, um den Benutzern das Abmelden zu erleichtern.
- Button für das Erstellen eines neuen Umschlags hinzugefügt, um die Benutzerfreundlichkeit zu verbessern.
2024-08-19 16:43:24 +02:00
Developer 02
609f7d09fc feat: Bootstrap zur Projektstruktur hinzugefügt 2024-08-19 13:32:14 +02:00
Developer 02
4c21cb4ba7 feat: Zeilen-Erweiterungsfunktion zur EnvelopeTableComponent hinzugefügt 2024-08-19 11:48:45 +02:00
Developer 02
00ebf45605 refactor: Aktualisierung von EnvelopeTableComponent zur Verwendung der Angular Material Tabelle
- Ersetzte `@generic-ui/ngx-grid` durch Angular Material Tabellenkomponenten.
- Aktualisierte `EnvelopeTableComponent`, um `mat-table` für die Tabellenanzeige zu verwenden.
- Umorganisierte Daten- und Schema-Definitionen zur Kompatibilität mit Angular Material Tabelle.
- Füge `MatTableModule` und `CommonModule` zu den Komponenten-Imports hinzu.
- Implementierte dynamische Spaltenanzeige basierend auf dem Schema.
- Hinzugefügt `updateTable` Methode zur erneuten Darstellung der Tabelle.
2024-08-19 09:41:01 +02:00
Developer 02
387777972b feat: Envelope Status Name geändert in Envelope Name mit contant.Status Enum. Diese Eigenschaft wurde zu envelope entitiy und dto hinzugefügt. Die angular Tabelle wurde entsprechend aktualisiert. 2024-08-15 18:13:51 +02:00
Developer 02
b7569982ff chore: Dateireferenzen durch NuGet-Pakete in der User Manager-Assembly ersetzt 2024-08-15 14:25:16 +02:00
Developer 02
d6be88b61d chore: Content Security Policy (CSP) aktualisiert 2024-08-15 13:06:39 +02:00
Developer01
8e454a0419 MS 2024-07-30 16:24:19 +02:00
Developer 02
f8932e14c0 fix: z-index-Problem für #flex-action-panel, um sicherzustellen, dass es über anderen Elementen angezeigt wird. 2024-07-25 17:19:49 +02:00
Developer 02
812bf9b25a fix: Korrigiere falsche DOM-Element-ID von flex-actio-panel auf flex-action-panel 2024-07-25 17:13:11 +02:00
Developer 02
0d591d5350 chore: PSPDFKit von Version 2023.5.2 auf 2024.3.2 aktualisiert 2024-07-25 17:11:01 +02:00
Developer 02
c9712af73e fix: asp-append-version aus dem PSPDFKit-Skript-Tag entfernt, um Browser-Cache zu ermöglichen; Versionierung im Pfad sorgt für automatische Updates 2024-07-25 16:55:20 +02:00
Developer 02
da483706b1 chore: PSPDFKit Versionen 2023.5.2 und 2024.3.2 separat hinzugefügt, weiterhin 2023.5.2 verwenden 2024-07-25 16:51:20 +02:00
Developer 02
4b600cb190 chore: Initialize versioning for envelope-generator-ui (Angular) 2024-07-25 16:25:47 +02:00
Developer 02
25a56a22fa release: Version 1.0.0.2 auf 1.0.0.3 erhöht 2024-07-22 11:51:02 +02:00
Developer 02
4e81f0949c fix(pspdfkit): Inline-Worker stoppen und aus CSP entfernen 2024-07-22 11:20:38 +02:00
Developer 02
18e79cf516 update(site.css): für eine responsivere Seite px in rem umgewandelt 2024-07-22 10:36:35 +02:00
Developer 02
fad0a6070c refactor(_Layout.cshtml.css): convert px to rem units 2024-07-22 10:07:44 +02:00
Developer 02
755fcfeef2 refactor(site.css): convert px to rem units 2024-07-22 10:01:09 +02:00
Developer01
40739b598b MS SignatureLink 2024-07-22 09:46:48 +02:00
Developer 02
9782503d1d Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2024-07-18 17:23:31 +02:00
Developer 02
35ced9b9ad feat: Hinzufügen der detaillierten aktuellen Uhrzeit mit Zeitzoneninformation im Format "dd.mm.yyyy, hh:mm:ss GMT+X". 2024-07-18 17:21:54 +02:00
Developer 02
9b28c0a1d1 chore: Minifizierte Versionen der JS- und CSS-Dateien hinzugefügt. 2024-07-18 15:50:47 +02:00
Developer 02
fd19c5be58 feat: Minifizierte Versionen aller JS- und CSS-Dateien erstellt. 2024-07-18 15:07:39 +02:00
Developer01
58b13e233c MS 2024-07-18 14:50:20 +02:00
Developer01
ce55066208 Ms Optimierung 2024-07-18 14:49:28 +02:00
Developer 02
7d582d2422 feat: Regulären Ausdruck zur Überprüfung der Stadt im Frontend hinzugefügt. 2024-07-18 14:13:33 +02:00
Developer 02
fe1d553a8d Reapply "Version von 1.0.0.1 auf 1.0.0.2 erhöht."
This reverts commit 9867e81220.
2024-07-18 11:56:42 +02:00
Developer 02
99c05a44f5 fix: CSS-Stil für die mail-link Klasse angepasst: Links sind nun blau und haben keine Unterstreichung. Aktivierung der href-Eigenschaft, die zuvor durch den Sanitizer entfernt wurde. 2024-07-18 11:56:19 +02:00
Developer 02
678360953d Hinzufügen eines neuen Werts für den Titel des Signierungsprozesses zur Ansicht show-envelope. 2024-07-18 11:37:14 +02:00
Developer 02
9867e81220 Revert "Version von 1.0.0.1 auf 1.0.0.2 erhöht."
This reverts commit 49cfc3c044.
2024-07-18 11:17:22 +02:00
Developer 02
49cfc3c044 Version von 1.0.0.1 auf 1.0.0.2 erhöht. 2024-07-18 10:54:20 +02:00
Developer 02
43ae15b71c Refaktorierung für HTML-Sanitization mit neuer Sanitizer-Klasse.
- Bestehende Sanitization überarbeitet.
- Injektionsmethode für flexible Konfiguration implementiert.
- Wichtige Abschnitte in `show-envelope` hervorgehoben.
2024-07-18 10:52:39 +02:00
Developer 02
1c2df71e0f fix: Viewport-Meta-Tag aktualisiert, um Skalierungsoptionen für eine bessere Layout-Kontrolle einzuschränken. 2024-07-17 17:20:41 +02:00
Developer 02
a806ec27db fix: Version updated from 1.1.0 to 1.1.0.1. 2024-07-17 15:57:51 +02:00
Developer 02
14bd2e22fc feat: Developed markFieldAsRequired and isFieldRequired methods to mark and validate required form fields; added user alert if location information is not provided. 2024-07-17 15:52:04 +02:00
Developer 02
f94728bf67 fix: Ort und Datum Informationen wurden horizontal ausgerichtet. 2024-07-17 14:11:20 +02:00
Developer 02
caeaf1774e feat: Alertify hinzugefügt. 2024-07-17 14:04:35 +02:00
Developer 02
1388b40a6b feat: isMobile-Methode mit Lazy Loading implementiert; Standortinformationen für mobile Browser auf readonly gesetzt. 2024-07-17 13:22:43 +02:00
Developer 02
e44d5f644c fix: Breite von City von 0,75 auf 1,2 erhöht. 2024-07-17 12:32:08 +02:00
Developer 02
fe9fd3024e refactor: Datum und Ort vertauscht. 2024-07-17 12:20:26 +02:00
Developer 02
b664e35b11 fix: Postleitzahl entfernt. 2024-07-17 12:00:50 +02:00
Developer 02
a77a31121f fix: Datum als readonly festgelegt. 2024-07-17 11:57:52 +02:00
Developer 02
381de6b554 fix: createText-Variable entfernt. 2024-07-17 11:47:40 +02:00
Developer 02
13bd727b3e feat: Configure project file for versioning and packaging; updated file and assembly versions from 1.0.0.0 to 1.1.0.0. 2024-07-16 15:58:10 +02:00
Developer 02
9021291aef Hinzufügen einer Bedingung zum Entfernen von Komponenten aus der Ignorierliste 2024-07-16 14:26:41 +02:00
Developer 02
8bd7ab13d0 Liste für ignorierte Etiketten erstellt und zu den Diensten hinzugefügt. 2024-07-16 13:55:36 +02:00
Developer 02
8eefd94569 Hinzufügen von Beschriftungen mit schreibgeschütztem PSPDF Kit-Textformularfeld. Statische PSPDF-Kit-Instanz erstellt. 2024-07-05 17:15:51 +02:00
Developer 02
b3b2baf0e4 Revert "PSPDFKit von 2023.5.2 auf 2024.3.2 aktualisiert."
This reverts commit c91446c5ac.
2024-07-05 10:05:28 +02:00
Developer 02
836380048a Reapply "Endpunkt "EncodeEnvelopeReceiverId" zum Test-Controller hinzugefügt."
This reverts commit f105aaa567.
2024-07-05 10:04:49 +02:00
Developer 02
f105aaa567 Revert "Endpunkt "EncodeEnvelopeReceiverId" zum Test-Controller hinzugefügt."
This reverts commit b615446274.
2024-07-05 10:00:54 +02:00
Developer 02
6238d66ca2 Getrennte Datumsauswahl, Postleitzahl und Stadtfelder hinzugefügt. 2024-07-05 01:37:11 +02:00
Developer 02
7e325a7eb6 Proxy-Konfiguration außerhalb von src verschoben. EmailProfilerDispatcher nuget hinzugefügt und Referenzen aktualisiert. 2024-07-04 10:34:46 +02:00
Developer 02
c91446c5ac PSPDFKit von 2023.5.2 auf 2024.3.2 aktualisiert. 2024-06-26 16:18:17 +02:00
eaf4cd773d Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2024-06-26 11:38:02 +02:00
8950482bac MS 2024-06-26 11:37:58 +02:00
Developer 02
b615446274 Endpunkt "EncodeEnvelopeReceiverId" zum Test-Controller hinzugefügt. 2024-06-26 10:47:04 +02:00
Developer 02
f276735b5c Referenzen für Common hinzugefügt. 2024-06-26 10:02:15 +02:00
Developer 02
31aa5829f6 Common-Projekt wurde zum Form-Projekt hinzugefügt. Content-Security-Policy wurde aktualisiert, um nominatim.openstreetmap.org zu erlauben. 2024-06-25 18:03:51 +02:00
27a5538229 Ms logging 2024-06-25 15:45:00 +02:00
322fb2fd7e MS 2024-06-25 13:28:17 +02:00
8e33094806 Merge commit 2024-06-25 13:28:03 +02:00
54b246f8e4 MS Sync Hakan 2024-06-25 13:26:35 +02:00
Developer 02
5c51ea679e Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2024-06-25 13:18:05 +02:00
Developer 02
e264a10a36 String-Lokalisierer für Model.resx im Common-Projekt hinzugefügt. 2024-06-25 13:07:02 +02:00
2f8aed8640 Merge branch 'master' of http://git.dd:3000/AppStd/EnvelopeGenerator 2024-06-25 08:42:49 +02:00
29eac347c3 MS 2024-06-25 08:42:42 +02:00
Developer 02
dd6ab13e6e Hinzugefügt Localizer Dienste für beide api und angular 2024-06-24 15:55:27 +02:00
Developer 02
d94d9f045e Standardthema als FABRIC hinzugefügt 2024-06-24 13:29:58 +02:00
Developer 02
12bfcb1f25 Standard-Lokalisierer für generic-ui hinzugefügt. 2024-06-24 13:11:39 +02:00
Developer 02
63613f2073 Seitenverzeichnis hinzugefügt. Seite 'home' dorthin verschoben und Seite 'envelope' hinzugefügt. 2024-06-24 12:43:30 +02:00
Developer 02
1c11a0e8f0 Http-Interceptor hinzugefügt. 2024-06-24 11:56:49 +02:00
1654 changed files with 14195 additions and 1190 deletions

View File

@@ -1,7 +1,7 @@
using DigitalData.Core.Abstractions.Application;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using static EnvelopeGenerator.Common.Constants;
@@ -22,7 +22,7 @@ namespace EnvelopeGenerator.Application.Contracts
Task<IEnumerable<EnvelopeHistoryDto>> ReadRejectedAsync(int envelopeId, string? userReference = null);
Task<IEnumerable<ReceiverDto>> ReadRejectingReceivers(int envelopeId);
Task<IEnumerable<ReceiverReadDto>> ReadRejectingReceivers(int envelopeId);
Task<DataResult<long>> RecordAsync(int envelopeId, string userReference, EnvelopeStatus status, string? comment = null);
}

View File

@@ -1,5 +1,5 @@
using DigitalData.Core.DTO;
using DigitalData.EmailProfilerDispatcher.Application.Contracts;
using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Common;

View File

@@ -24,6 +24,6 @@ namespace EnvelopeGenerator.Application.Contracts
Task<DataResult<bool>> IsExisting(string envelopeReceiverId);
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username);
Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username, int? min_status = null, int? max_status = null, params int[] ignore_statuses);
}
}

View File

@@ -1,10 +1,14 @@
using DigitalData.Core.Abstractions.Application;
using EnvelopeGenerator.Application.DTOs;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.Contracts
{
public interface IReceiverService : IBasicCRUDService<ReceiverDto, Receiver, int>
public interface IReceiverService : ICRUDService<ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>
{
public Task<DataResult<ReceiverReadDto>> ReadByAsync(string? emailAddress = null, string? signature = null);
public Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null);
}
}

View File

@@ -1,7 +1,5 @@
using DigitalData.EmailProfilerDispatcher.Domain.Attributes;
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using DigitalData.UserManager.Application.DTOs.User;
using DigitalData.UserManager.Domain.Entities;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.DTOs
@@ -14,7 +12,9 @@ namespace EnvelopeGenerator.Application.DTOs
public int Status { get; set; }
public string Uuid { get; set; }
public string StatusName { get; set; }
public string Uuid { get; set; }
[TemplatePlaceholder("[MESSAGE]")]
public string Message { get; set; }

View File

@@ -1,5 +1,6 @@
using DigitalData.Core.DTO;
using DigitalData.UserManager.Application.DTOs.User;
using EnvelopeGenerator.Application.DTOs.Receiver;
using static EnvelopeGenerator.Common.Constants;
namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
@@ -12,7 +13,7 @@ namespace EnvelopeGenerator.Application.DTOs.EnvelopeHistory
DateTime AddedWhen,
DateTime? ActionDate,
UserCreateDto? Sender,
ReceiverDto? Receiver,
ReceiverReadDto? Receiver,
ReferenceType ReferenceType,
string? Comment = null) : BaseDTO<long>(Id);
}

View File

@@ -1,6 +1,5 @@
using DigitalData.EmailProfilerDispatcher.Domain.Attributes;
using System.ComponentModel.DataAnnotations.Schema;
using System.Text.Json.Serialization;
using DigitalData.EmailProfilerDispatcher.Abstraction.Attributes;
using EnvelopeGenerator.Application.DTOs.Receiver;
namespace EnvelopeGenerator.Application.DTOs
{
@@ -27,6 +26,6 @@ namespace EnvelopeGenerator.Application.DTOs
public EnvelopeDto? Envelope { get; set; }
public ReceiverDto? Receiver { get; set; }
public ReceiverReadDto? Receiver { get; set; }
}
}

View File

@@ -0,0 +1,21 @@
using System.ComponentModel.DataAnnotations;
using System.Security.Cryptography;
using System.Text;
namespace EnvelopeGenerator.Application.DTOs.Receiver
{
public record ReceiverCreateDto([EmailAddress] string EmailAddress)
{
public string Signature => sha256HexOfMail.Value;
private readonly Lazy<string> sha256HexOfMail = new(() =>
{
var bytes_arr = Encoding.UTF8.GetBytes(EmailAddress.ToUpper());
var hash_arr = SHA256.HashData(bytes_arr);
var hexa_str = BitConverter.ToString(hash_arr);
return hexa_str.Replace("-", string.Empty);
});
public DateTime AddedWhen { get; } = DateTime.Now;
};
}

View File

@@ -1,8 +1,8 @@
using DigitalData.Core.DTO;
namespace EnvelopeGenerator.Application.DTOs
namespace EnvelopeGenerator.Application.DTOs.Receiver
{
public record ReceiverDto(
public record ReceiverReadDto(
int Id,
string EmailAddress,
string Signature,

View File

@@ -0,0 +1,4 @@
namespace EnvelopeGenerator.Application.DTOs.Receiver
{
public record ReceiverUpdateDto();
}

View File

@@ -6,13 +6,19 @@
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<None Remove="Resources\Model.Designer.vb" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AutoMapper" Version="13.0.1" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="1.0.1.1" />
<PackageReference Include="DigitalData.Core.Application" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.DTO" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.Infrastructure" Version="1.0.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher" Version="1.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="7.0.18" />
<PackageReference Include="UserManager.Application" Version="1.0.0" />
<PackageReference Include="UserManager.Infrastructure" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
@@ -20,27 +26,24 @@
</ItemGroup>
<ItemGroup>
<Reference Include="DigitalData.EmailProfilerDispatcher.Application">
<HintPath>..\..\EmailProfilerDispatcher\DigitalData.EmailProfilerDispatcher.Application\bin\Debug\net7.0\DigitalData.EmailProfilerDispatcher.Application.dll</HintPath>
</Reference>
<Reference Include="DigitalData.EmailProfilerDispatcher.Domain">
<HintPath>..\..\EmailProfilerDispatcher\DigitalData.EmailProfilerDispatcher.Application\bin\Debug\net7.0\DigitalData.EmailProfilerDispatcher.Domain.dll</HintPath>
</Reference>
<Reference Include="DigitalData.EmailProfilerDispatcher.Infrastructure">
<HintPath>..\..\EmailProfilerDispatcher\DigitalData.EmailProfilerDispatcher.Application\bin\Debug\net7.0\DigitalData.EmailProfilerDispatcher.Infrastructure.dll</HintPath>
</Reference>
<Reference Include="DigitalData.UserManager.Application">
<HintPath>..\..\WebUserManager\DigitalData.UserManager.Application\bin\Debug\net7.0\DigitalData.UserManager.Application.dll</HintPath>
</Reference>
<Reference Include="DigitalData.UserManager.Domain">
<HintPath>..\..\WebUserManager\DigitalData.UserManager.Domain\bin\Debug\net7.0\DigitalData.UserManager.Domain.dll</HintPath>
</Reference>
<Reference Include="DigitalData.UserManager.Infrastructure">
<HintPath>..\..\WebUserManager\DigitalData.UserManager.Application\bin\Debug\net7.0\DigitalData.UserManager.Infrastructure.dll</HintPath>
</Reference>
<Compile Update="Resources\Model.Designer.cs">
<DesignTime>True</DesignTime>
<AutoGen>True</AutoGen>
<DependentUpon>Model.resx</DependentUpon>
</Compile>
</ItemGroup>
<ItemGroup>
<EmbeddedResource Update="Resources\Model.en.resx">
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<LastGenOutput>Model.en.Designer.vb</LastGenOutput>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Model.resx">
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<LastGenOutput>Model.Designer.cs</LastGenOutput>
<Generator>PublicResXFileCodeGenerator</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Resources\Resource.de-DE.resx">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>

View File

@@ -1,6 +1,7 @@
using AutoMapper;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
namespace EnvelopeGenerator.Application.MappingProfiles
@@ -21,7 +22,9 @@ namespace EnvelopeGenerator.Application.MappingProfiles
CreateMap<EnvelopeHistory, EnvelopeHistoryCreateDto>();
CreateMap<EnvelopeReceiver, EnvelopeReceiverDto>();
CreateMap<EnvelopeType, EnvelopeTypeDto>();
CreateMap<Receiver, ReceiverDto>();
CreateMap<Receiver, ReceiverReadDto>();
CreateMap<Receiver, ReceiverCreateDto>();
CreateMap<Receiver, ReceiverUpdateDto>();
CreateMap<UserReceiver, UserReceiverDto>();
// DTO to Entity mappings
@@ -36,7 +39,9 @@ namespace EnvelopeGenerator.Application.MappingProfiles
CreateMap<EnvelopeHistoryCreateDto, EnvelopeHistory>();
CreateMap<EnvelopeReceiverDto, EnvelopeReceiver>();
CreateMap<EnvelopeTypeDto, EnvelopeType>();
CreateMap<ReceiverDto, Receiver>();
CreateMap<ReceiverReadDto, Receiver>();
CreateMap<ReceiverCreateDto, Receiver>();
CreateMap<ReceiverUpdateDto, Receiver>();
CreateMap<UserReceiverDto, UserReceiver>();
}
}

View File

@@ -145,10 +145,10 @@
<value>Englisch</value>
</data>
<data name="EnvelopeInfo1" xml:space="preserve">
<value>Sie müssen {0} Vorgang unterzeichen. Bitte prüfen Sie die Seite {1}.</value>
<value>Sie müssen {0} Vorgang unterzeichen. &lt;span class="highlight highlight-envelope-info-1"&gt;Bitte prüfen Sie die Seite {1}&lt;/span&gt;.</value>
</data>
<data name="EnvelopeInfo2" xml:space="preserve">
<value>Erstellt am {0} von {1}. Sie können den Absender über &lt;a href="mailto:{2}?subject={3}&amp;body=Sehr%20geehrter%20{4}%20{5},%0A%0A%0A"&gt;{6}&lt;/a&gt; kontaktieren.</value>
<value>Erstellt am {0} von {1}. Sie können den Absender über &lt;span class="highlight highlight-envelope-info-2"&gt;&lt;a class="mail-link" href="mailto:{2}?subject={3}&amp;body=Sehr%20geehrter%20{4}%20{5},%0A%0A%0A"&gt;{6}&lt;/a&gt;&lt;/span&gt; kontaktieren.</value>
</data>
<data name="Finalize" xml:space="preserve">
<value>Abschließen</value>
@@ -159,6 +159,9 @@
<data name="LocakedOpen" xml:space="preserve">
<value>Öffnen</value>
</data>
<data name="LocationWarning" xml:space="preserve">
<value>Bitte überprüfen Sie die Standortinformationen. Wenn sie falsch sind, korrigieren Sie diese bitte.</value>
</data>
<data name="LockedAccessCode" xml:space="preserve">
<value>Zugriffscode</value>
</data>
@@ -201,9 +204,15 @@
<data name="SignDoc" xml:space="preserve">
<value>Dokument unterschreiben</value>
</data>
<data name="SigningProcessTitle" xml:space="preserve">
<value>Titel des Unterzeichnungs-Vorgangs</value>
</data>
<data name="UnexpectedError" xml:space="preserve">
<value>Ein unerwarteter Fehler ist aufgetreten.</value>
</data>
<data name="WelcomeToTheESignPortal" xml:space="preserve">
<value>Herzlich willkommen im eSign-Portal</value>
</data>
<data name="WrongAccessCode" xml:space="preserve">
<value>Ungültiger Zugangscode.</value>
</data>

View File

@@ -145,10 +145,10 @@
<value>English</value>
</data>
<data name="EnvelopeInfo1" xml:space="preserve">
<value>You have to sign {0} process. Please check page {1}.</value>
<value>You have to sign {0} process. &lt;span class="highlight highlight-envelope-info-1"&gt;Please check page {1}&lt;/span&gt;.</value>
</data>
<data name="EnvelopeInfo2" xml:space="preserve">
<value>Created on {0} by {1}. You can contact the sender via &lt;a href="mailto:{2}?subject={3}&amp;body=Dear%20{4}%20{5},%0A%0A%0A"&gt;{6}&lt;/a&gt;.</value>
<value>Created on {0} by {1}. You can contact the sender via &lt;span class="highlight highlight-envelope-info-2"&gt;&lt;a class="mail-link" href="mailto:{2}?subject={3}&amp;body=Dear%20{4}%20{5},%0A%0A%0A"&gt;{6}&lt;/a&gt;&lt;/span&gt;.</value>
</data>
<data name="Finalize" xml:space="preserve">
<value>Finalize</value>
@@ -159,6 +159,9 @@
<data name="LocakedOpen" xml:space="preserve">
<value>Open</value>
</data>
<data name="LocationWarning" xml:space="preserve">
<value>Please review the location information. If it is incorrect, kindly make the necessary corrections.</value>
</data>
<data name="LockedAccessCode" xml:space="preserve">
<value>Access Code</value>
</data>
@@ -201,9 +204,15 @@
<data name="SignDoc" xml:space="preserve">
<value>Sign document</value>
</data>
<data name="SigningProcessTitle" xml:space="preserve">
<value>Title of the signing process</value>
</data>
<data name="UnexpectedError" xml:space="preserve">
<value>An unexpected error has occurred.</value>
</data>
<data name="WelcomeToTheESignPortal" xml:space="preserve">
<value>Welcome to the eSign portal</value>
</data>
<data name="WrongAccessCode" xml:space="preserve">
<value>Invalid access code.</value>
</data>

View File

@@ -8,7 +8,7 @@ using static EnvelopeGenerator.Common.Constants;
using EnvelopeGenerator.Application.Resources;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.DTOs.EnvelopeHistory;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Application.DTOs.Receiver;
namespace EnvelopeGenerator.Application.Services
{
@@ -67,11 +67,11 @@ namespace EnvelopeGenerator.Application.Services
await ReadAsync(envelopeId: envelopeId, userReference: userReference, status: (int)EnvelopeStatus.DocumentRejected, withReceiver:true);
//TODO: use IQueryable in repository to incerease the performance
public async Task<IEnumerable<ReceiverDto>> ReadRejectingReceivers(int envelopeId)
public async Task<IEnumerable<ReceiverReadDto>> ReadRejectingReceivers(int envelopeId)
{
var envelopes = await ReadRejectedAsync(envelopeId);
return envelopes is null
? Enumerable.Empty<ReceiverDto>()
? Enumerable.Empty<ReceiverReadDto>()
: envelopes
.Where(eh => eh?.Receiver != null)
.Select(eh => eh.Receiver!);

View File

@@ -1,8 +1,8 @@
using AutoMapper;
using DigitalData.Core.DTO;
using DigitalData.EmailProfilerDispatcher.Application.DTOs.EmailOut;
using DigitalData.EmailProfilerDispatcher.Application.Services;
using DigitalData.EmailProfilerDispatcher.Infrastructure.Contracts;
using DigitalData.EmailProfilerDispatcher.Abstraction.Contracts;
using DigitalData.EmailProfilerDispatcher.Abstraction.DTOs.EmailOut;
using DigitalData.EmailProfilerDispatcher.Abstraction.Services;
using DigitalData.UserManager.Application;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;

View File

@@ -116,9 +116,9 @@ namespace EnvelopeGenerator.Application.Services
: Result.Success(code);
}
public async Task<DataResult<IEnumerable<EnvelopeReceiverDto>>> ReadByUsernameAsync(string username)
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);
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);
return Result.Success(dto_list);
}

View File

@@ -2,19 +2,39 @@
using DigitalData.Core.Application;
using Microsoft.Extensions.Localization;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs;
using EnvelopeGenerator.Domain.Entities;
using EnvelopeGenerator.Infrastructure.Contracts;
using EnvelopeGenerator.Application.Resources;
using Microsoft.AspNetCore.Mvc;
using EnvelopeGenerator.Application.DTOs.Receiver;
using DigitalData.Core.DTO;
namespace EnvelopeGenerator.Application.Services
{
public class ReceiverService : BasicCRUDService<IReceiverRepository, ReceiverDto, Receiver, int>, IReceiverService
public class ReceiverService : CRUDService<IReceiverRepository, ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>, IReceiverService
{
public ReceiverService(IReceiverRepository repository, IStringLocalizer<Resource> localizer, IMapper mapper)
: base(repository, mapper)
{
}
public async Task<DataResult<ReceiverReadDto>> ReadByAsync(string? emailAddress = null, string? signature = null)
{
var rcv = await _repository.ReadByAsync(emailAddress: emailAddress, signature: signature);
if (rcv is null)
return Result.Fail<ReceiverReadDto>();
return Result.Success(_mapper.MapOrThrow<ReceiverReadDto>(rcv));
}
public async Task<Result> DeleteByAsync(string? emailAddress = null, string? signature = null)
{
var rcv = await _repository.ReadByAsync(emailAddress: emailAddress, signature: signature);
if (rcv is null)
return Result.Fail();
return await _repository.DeleteAsync(rcv) ? Result.Success() : Result.Fail();
}
}
}

View File

@@ -102,6 +102,7 @@
Public Const DATABASE = "DATABASE"
Public Const LOGCONFIG = "LOGCONFIG"
Public Const GDPICTURE = "GDPICTURE"
Public Const IGNORED_LABELS = "IgnoredLabels"
Public Const GREEN_300 = "#bbf7d0"
Public Const RED_300 = "#fecaca"

View File

@@ -17,6 +17,8 @@ Public Class EmailData
Public Property EnvelopeTitle As String = ""
Public Property EmailAttachment As String = ""
Public Property ATT1_RELATED_ID As Long
Public Property ATT1_REL_TYPE As String = ""
''' <summary>
''' Constructor for sending email to receiver

View File

@@ -32,8 +32,6 @@
Public Property History As New List(Of EnvelopeHistoryEntry)
Public Property EnvelopeType As EnvelopeType
Public Property DOC_RESULT As Byte()
Public Property Doc1 As Byte()
Public ReadOnly Property EnvelopeTypeTitle As String
Get
Return EnvelopeType?.Title

View File

@@ -220,6 +220,8 @@
<DesignTime>True</DesignTime>
<DependentUpon>Model.resx</DependentUpon>
</Compile>
<Compile Include="Strings\Model.vb" />
<Compile Include="TempFiles.vb" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="My Project\licenses.licx" />
@@ -241,11 +243,13 @@
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Envelope.en.Designer.vb</LastGenOutput>
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Strings\Envelope.resx">
<Generator>PublicResXFileCodeGenerator</Generator>
<LastGenOutput>Envelope1.Designer.vb</LastGenOutput>
<CustomToolNamespace>My.Resources</CustomToolNamespace>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="Strings\Email.resx">
<Generator>PublicResXFileCodeGenerator</Generator>

View File

@@ -7,17 +7,9 @@ Imports System.Security.Cryptography
Imports System.IO
Imports EnvelopeGenerator.Common.Jobs.FinalizeDocument.FinalizeDocumentExceptions
Imports EnvelopeGenerator.Common.Jobs.FinalizeDocument
Imports EnvelopeGenerator.Common.My.Resources
Imports EnvelopeGenerator.Common.Constants
Imports DevExpress.XtraBars.Docking
Imports System.ServiceModel
Imports DevExpress.XtraRichEdit.Export
Imports DevExpress.Pdf.Native.BouncyCastle.Asn1.Cms
Imports DevExpress.DataAccess.Sql
Imports DevExpress.DataProcessing
Imports Quartz.Logging.OperationName
Imports System.Data.SqlClient
Imports System.Windows.Forms
Namespace Jobs
Public Class FinalizeDocumentJob
@@ -43,9 +35,11 @@ Namespace Jobs
Private ReadOnly CompleteWaitTime As Integer = 5
Private ParentFolderUID As String = ""
Private myTempFiles As TempFiles
Private Class EnvelopeData
Public EnvelopeId As Integer
Public EnvelopeUUID As String
Public DocumentPath As String
Public AnnotationData As List(Of String)
Public DocAsByte As Byte()
@@ -56,7 +50,8 @@ Namespace Jobs
Dim oGdPictureKey As String = pContext.MergedJobDataMap.Item(Constants.GDPICTURE)
LogConfig = pContext.MergedJobDataMap.Item(Constants.LOGCONFIG)
Logger = LogConfig.GetLogger()
myTempFiles = New TempFiles(LogConfig)
myTempFiles.Create()
Dim JobId = pContext.JobDetail.Key
Logger.Info("Starting job {0}", JobId)
@@ -79,7 +74,8 @@ Namespace Jobs
InitializeServices(oState)
Logger.Debug("Loading PDFBurner..")
PDFBurner = New PDFBurner(LogConfig, oGdPictureKey)
Dim ignoredLabels As List(Of String) = pContext.MergedJobDataMap.Item(Constants.IGNORED_LABELS)
PDFBurner = New PDFBurner(LogConfig, oGdPictureKey, ignoredLabels)
Logger.Debug("Loading PDFMerger..")
PDFMerger = New PDFMerger(LogConfig, oGdPictureKey)
@@ -148,77 +144,81 @@ Namespace Jobs
For Each oId In oEnvelopeIds
Logger.Info("Finalizing Envelope [{0}] ({1}/{2})", oId, oCurrent, oTotal)
Logger.Debug("Loading Envelope..")
Dim oEnvelope = EnvelopeModel.GetById(oId)
If oEnvelope Is Nothing Then
Logger.Warn("Envelope could not be loaded for Id [{0}]!", oId)
Throw New ArgumentNullException("EnvelopeData")
End If
Logger.Debug("Loading Envelope Data..")
Dim oEnvelopeData = GetEnvelopeData(oId)
If oEnvelopeData Is Nothing Then
Logger.Warn("EnvelopeData could not be loaded for Id [{0}]!", oId)
Throw New ArgumentNullException("EnvelopeData")
End If
If Config.DOCUMENT_PATH_MOVE_AFTSEND <> String.Empty Then
oEnvelopeData.DocumentPath.Replace(Config.DocumentPathOrigin, Config.DOCUMENT_PATH_MOVE_AFTSEND)
Logger.Debug("Replaced Path in oEnvelopeData.DocumentPath!")
End If
Logger.Debug("Burning Annotations to pdf ...")
Dim oBurnedDocument As Byte() = BurnAnnotationsToPdf(oEnvelopeData)
If oBurnedDocument Is Nothing Then
Logger.Warn("Document could not be finalized!")
Throw New ApplicationException("Document could not be finalized")
End If
If ActionService.CreateReport(oEnvelope) = False Then
Logger.Warn("Document Report could not be created!")
Throw New ApplicationException("Document Report could not be created")
End If
Logger.Debug("Creating report..")
Dim oReport As Byte() = ReportCreator.CreateReport(oEnvelope)
Logger.Debug("Report created!")
Logger.Debug("Merging documents ...")
Dim oMergedDocument As Byte() = PDFMerger.MergeDocuments(oBurnedDocument, oReport)
Logger.Debug("Documents merged!")
Dim oOutputDirectoryPath = Path.Combine(Config.ExportPath, ParentFolderUID)
If Not Directory.Exists(oOutputDirectoryPath) Then
Directory.CreateDirectory(oOutputDirectoryPath)
End If
Dim oOutputFilePath = Path.Combine(oOutputDirectoryPath, $"{oEnvelope.Uuid}.pdf")
Logger.Info("Writing finalized Pdf to disk..")
Logger.Info("Output path is [{0}]", oOutputFilePath)
Try
File.WriteAllBytes(oOutputFilePath, oMergedDocument)
Catch ex As Exception
Logger.Warn("Could not export final document to disk!")
Throw New ExportDocumentException("Could not export final document to disk!", ex)
End Try
Dim oEnvelope = EnvelopeModel.GetById(oId)
If oEnvelope Is Nothing Then
Logger.Warn("Envelope could not be loaded for Id [{0}]!", oId)
Throw New ArgumentNullException("EnvelopeData")
End If
Logger.Debug("Loading Envelope Data..")
Dim oEnvelopeData = GetEnvelopeData(oId)
If Config.NetUse_Finish = True Then
If Config.FINISHED_PATH_EX_DMZ <> String.Empty Then
If My.Settings.NetUse_PW <> String.Empty And My.Settings.NetUse_Usr <> String.Empty Then
Clean_DNZ_PAth(Config.FINISHED_PATH_EX_DMZ)
If oEnvelopeData Is Nothing Then
Logger.Warn("EnvelopeData could not be loaded for Id [{0}]!", oId)
Throw New ArgumentNullException("EnvelopeData")
End If
If Config.DOCUMENT_PATH_MOVE_AFTSEND <> String.Empty Then
oEnvelopeData.DocumentPath.Replace(Config.DocumentPathOrigin, Config.DOCUMENT_PATH_MOVE_AFTSEND)
Logger.Debug("Replaced Path in oEnvelopeData.DocumentPath!")
End If
Logger.Debug("Burning Annotations to pdf ...")
Dim oBurnedDocument As Byte() = BurnAnnotationsToPdf(oEnvelopeData)
If oBurnedDocument Is Nothing Then
Logger.Warn("Document could not be finalized!")
Throw New ApplicationException("Document could not be finalized")
End If
If ActionService.CreateReport(oEnvelope) = False Then
Logger.Warn("Document Report could not be created!")
Throw New ApplicationException("Document Report could not be created")
End If
Logger.Debug("Creating report..")
Dim oReport As Byte() = ReportCreator.CreateReport(oEnvelope)
Logger.Debug("Report created!")
Logger.Debug("Merging documents ...")
Dim oMergedDocument As Byte() = PDFMerger.MergeDocuments(oBurnedDocument, oReport)
Logger.Debug("Documents merged!")
Dim oOutputDirectoryPath = Path.Combine(Config.ExportPath, ParentFolderUID)
If Not Directory.Exists(oOutputDirectoryPath) Then
Directory.CreateDirectory(oOutputDirectoryPath)
End If
Dim oOutputFilePath = Path.Combine(oOutputDirectoryPath, $"{oEnvelope.Uuid}.pdf")
Logger.Info("Writing finalized Pdf to disk..")
Logger.Info("Output path is [{0}]", oOutputFilePath)
Try
File.WriteAllBytes(oOutputFilePath, oMergedDocument)
Catch ex As Exception
Logger.Warn("Could not export final document to disk!")
Throw New ExportDocumentException("Could not export final document to disk!", ex)
End Try
If Config.NetUse_Finish = True Then
If Config.FINISHED_PATH_EX_DMZ <> String.Empty Then
If My.Settings.NetUse_PW <> String.Empty And My.Settings.NetUse_Usr <> String.Empty Then
Clean_DNZ_PAth(Config.FINISHED_PATH_EX_DMZ)
End If
End If
End If
End If
Logger.Info("Writing EB-bytes to database...")
Update_File_DB(oOutputFilePath, oEnvelope.Id)
Logger.Info("Writing EB-bytes to database...")
Update_File_DB(oOutputFilePath, oEnvelope.Id)
Logger.Info("Sending finalized report-mails..")
If SendFinalEmails(oEnvelope) = False Then ', oOutputFilePath
Throw New ApplicationException("Final emails could not be sent!")
End If
Logger.Debug("Setting envelope status..")
If ActionService.FinalizeEnvelope(oEnvelope) = False Then
Logger.Warn("Envelope could not be finalized!")
Throw New ApplicationException("Envelope could not be finalized")
End If
Catch ex As Exception
Logger.Warn($"Unhandled exception while working envelope [{oId}] - [{ex.Message}]")
End Try
Logger.Info("Sending finalized report-mails..")
If SendFinalEmails(oEnvelope, oOutputFilePath) = False Then
Throw New ApplicationException("Final emails could not be sent!")
End If
Logger.Debug("Setting envelope status..")
If ActionService.FinalizeEnvelope(oEnvelope) = False Then
Logger.Warn("Envelope could not be finalized!")
Throw New ApplicationException("Envelope could not be finalized")
End If
oCurrent += 1
Logger.Info("Envelope finalized!")
@@ -329,35 +329,33 @@ Namespace Jobs
End Function
Private Function SendFinalEmails(pEnvelope As Envelope, pAttachment As String) As Boolean
Private Function SendFinalEmails(pEnvelope As Envelope) As Boolean ', pAttachment As String
Dim oMailToCreator = pEnvelope.FinalEmailToCreator
Dim oMailToReceivers = pEnvelope.FinalEmailToReceivers
If oMailToCreator <> FinalEmailType.No Then
Logger.Debug("Sending email to creator ...")
SendFinalEmailToCreator(pEnvelope, pAttachment)
SendFinalEmailToCreator(pEnvelope) ', pAttachment
End If
If oMailToReceivers <> FinalEmailType.No Then
Logger.Debug("Sending emails to receivers..")
SendFinalEmailToReceivers(pEnvelope, pAttachment)
SendFinalEmailToReceivers(pEnvelope) ', pAttachment
End If
Return True
End Function
Private Function SendFinalEmailToCreator(pEnvelope As Envelope, pAttachment As String) As Boolean
Private Function SendFinalEmailToCreator(pEnvelope As Envelope) As Boolean ', pAttachment As String
Dim oIncludeAttachment = SendFinalEmailWithAttachment(pEnvelope.FinalEmailToCreator)
Dim oAttachment = String.Empty
' Dim oAttachment = String.Empty
Logger.Debug("Attachment included: [{0}]", oIncludeAttachment)
If oIncludeAttachment Then
oAttachment = pAttachment
'oAttachment = pAttachment
End If
If ActionService.CompleteEnvelope(pEnvelope, oAttachment) = False Then
If ActionService.CompleteEnvelope(pEnvelope) = False Then ', oAttachment
Logger.Error("Envelope could not be completed for receiver [{0}]", pEnvelope.User.Email)
Return False
End If
@@ -365,18 +363,18 @@ Namespace Jobs
Return True
End Function
Private Function SendFinalEmailToReceivers(pEnvelope As Envelope, pAttachment As String) As Boolean
Private Function SendFinalEmailToReceivers(pEnvelope As Envelope) As Boolean ', pAttachment As String
Dim oIncludeAttachment = SendFinalEmailWithAttachment(pEnvelope.FinalEmailToReceivers)
Dim oAttachment = String.Empty
'Dim oAttachment = String.Empty
Logger.Debug("Attachment included: [{0}]", oIncludeAttachment)
If oIncludeAttachment Then
oAttachment = pAttachment
' oAttachment = pAttachment
End If
For Each oReceiver In pEnvelope.Receivers
If ActionService.CompleteEnvelope(pEnvelope, oReceiver, oAttachment) = False Then
If ActionService.CompleteEnvelope(pEnvelope, oReceiver) = False Then ', oAttachment
Logger.Error("Envelope could not be completed for receiver [{0}]", oReceiver.Email)
Return False
End If
@@ -399,36 +397,52 @@ Namespace Jobs
Logger.Info($"Burning [{pEnvelopeData.AnnotationData.Count}] signatures")
Dim oAnnotations = pEnvelopeData.AnnotationData
Dim oInputPath = ""
If My.Settings.RuninDMZ Then
Logger.Debug("Replacing Path in pData.DocumentPath ...")
oInputPath = pEnvelopeData.DocumentPath.Replace(Config.DocumentPathOrigin, Config.DocumentPath)
ElseIf Config.DOCUMENT_PATH_MOVE_AFTSEND <> String.Empty Then
Logger.Debug("Replacing Path in pData.DocumentPath ...")
oInputPath = pEnvelopeData.DocumentPath.Replace(Config.DocumentPathOrigin, Config.DOCUMENT_PATH_MOVE_AFTSEND)
If IsNothing(pEnvelopeData.DocAsByte) Then
If My.Settings.RuninDMZ Then
Logger.Debug("Replacing Path in pData.DocumentPath ...")
oInputPath = pEnvelopeData.DocumentPath.Replace(Config.DocumentPathOrigin, Config.DocumentPath)
ElseIf Config.DOCUMENT_PATH_MOVE_AFTSEND <> String.Empty Then
Logger.Debug("Replacing Path in pData.DocumentPath ...")
oInputPath = pEnvelopeData.DocumentPath.Replace(Config.DocumentPathOrigin, Config.DOCUMENT_PATH_MOVE_AFTSEND)
Else
oInputPath = pEnvelopeData.DocumentPath
End If
Logger.Info($"Input path: [{oInputPath}]")
Else
oInputPath = pEnvelopeData.DocumentPath
Logger.Info($"we got bytes..")
oInputPath = Config.DocumentPathOrigin
Logger.Info($"oInputPath: {Config.DocumentPathOrigin}")
End If
If IsNothing(pEnvelopeData.DocAsByte) Then
Dim oDirectorySource As String = Path.GetDirectoryName(oInputPath)
Dim split As String() = oDirectorySource.Split("\")
ParentFolderUID = split(split.Length - 1)
Else
ParentFolderUID = pEnvelopeData.EnvelopeUUID
End If
Logger.Info($"Input path: [{oInputPath}]")
Dim oDirectorySource As String = Path.GetDirectoryName(oInputPath)
Dim split As String() = oDirectorySource.Split("\")
ParentFolderUID = split(split.Length - 1)
Logger.Info("ParentFolderUID: [{0}]", ParentFolderUID)
Dim oInputDocumentBuffer As Byte()
Try
oInputDocumentBuffer = File.ReadAllBytes(oInputPath)
Catch ex As Exception
Logger.Error(ex)
Throw New BurnAnnotationException("Source document could not be read from disk!", ex)
End Try
If Not IsNothing(pEnvelopeData.DocAsByte) Then
oInputDocumentBuffer = pEnvelopeData.DocAsByte
Else
Try
oInputDocumentBuffer = File.ReadAllBytes(oInputPath)
Catch ex As Exception
Logger.Error(ex)
Throw New BurnAnnotationException("Source document could not be read from disk!", ex)
End Try
End If
Return PDFBurner.BurnInstantJSONAnnotationsToPDF(oInputDocumentBuffer, oAnnotations)
End Function
Private Function GetEnvelopeData(pEnvelopeId As Integer) As EnvelopeData
Dim oSql = $"SELECT T.GUID, T2.FILEPATH, T2.BYTE_DATA FROM [dbo].[TBSIG_ENVELOPE] T
Dim oSql = $"SELECT T.GUID, T.ENVELOPE_UUID,T2.FILEPATH, T2.BYTE_DATA FROM [dbo].[TBSIG_ENVELOPE] T
JOIN TBSIG_ENVELOPE_DOCUMENT T2 ON T.GUID = T2.ENVELOPE_ID
WHERE T.GUID = {pEnvelopeId}"
Dim oTable As DataTable = Database.GetDatatable(oSql)
@@ -441,7 +455,9 @@ Namespace Jobs
Dim oData As New EnvelopeData With {
.EnvelopeId = pEnvelopeId,
.DocumentPath = oRow.ItemEx("FILEPATH", ""),
.AnnotationData = oAnnotationData
.AnnotationData = oAnnotationData,
.DocAsByte = DirectCast(oRow.Item("BYTE_DATA"), Byte()),
.EnvelopeUUID = oRow.ItemEx("ENVELOPE_UUID", "")
}
Logger.Debug("Document path: [{0}]", oData.DocumentPath)

View File

@@ -16,14 +16,17 @@ Namespace Jobs.FinalizeDocument
Private Const ANNOTATION_TYPE_IMAGE = "pspdfkit/image"
Private Const ANNOTATION_TYPE_INK = "pspdfkit/ink"
Private Const ANNOTATION_TYPE_WIDGET = "pspdfkit/widget"
Private Property _ignoredLabels As List(Of String)
Public Sub New(pLogConfig As LogConfig, pGDPictureLicenseKey As String)
Public Sub New(pLogConfig As LogConfig, pGDPictureLicenseKey As String, ignoredLabels As List(Of String))
MyBase.New(pLogConfig)
LicenseManager = New LicenseManager()
LicenseManager.RegisterKEY(pGDPictureLicenseKey)
Manager = New AnnotationManager()
_ignoredLabels = ignoredLabels
End Sub
Public Function BurnInstantJSONAnnotationsToPDF(pSourceBuffer As Byte(), pInstantJSONList As List(Of String)) As Byte()
@@ -38,11 +41,11 @@ Namespace Jobs.FinalizeDocument
For Each oJSON In pInstantJSONList
If AddInstantJSONAnnotationToPDF(oJSON) = False Then
Logger.Warn($"Error in AddInstantJSONAnnotationToPDF - oJson: ")
Logger.Warn(oJSON)
Throw New BurnAnnotationException($"Adding Annotation failed")
End If
Next
oResult = Manager.BurnAnnotationsToPage(RemoveInitialAnnots:=True, VectorMode:=True)
If oResult <> GdPictureStatus.OK Then
Throw New BurnAnnotationException($"Could not burn annotations to file: [{oResult}]")
@@ -71,6 +74,7 @@ Namespace Jobs.FinalizeDocument
Dim oAnnotationData = JsonConvert.DeserializeObject(Of AnnotationData)(pInstantJSON)
For Each oAnnotation In oAnnotationData.annotations
Logger.Debug("Adding AnnotationID: " + oAnnotation.id)
Select Case oAnnotation.type
Case ANNOTATION_TYPE_IMAGE
AddImageAnnotation(oAnnotation, oAnnotationData.attachments)
@@ -81,7 +85,7 @@ Namespace Jobs.FinalizeDocument
Case ANNOTATION_TYPE_WIDGET
'Add form field values
Dim formFieldValue = oAnnotationData.formFieldValues.FirstOrDefault(Function(fv) fv.name = oAnnotation.id)
If formFieldValue IsNot Nothing Then
If formFieldValue IsNot Nothing AndAlso Not _ignoredLabels.Contains(formFieldValue.value) Then
AddFormFieldValue(oAnnotation, formFieldValue)
End If
End Select

View File

@@ -12,8 +12,8 @@ Public Class EmailModel
Public Function Insert(pEmail As EmailData) As Boolean
Try
Dim oSql = "INSERT INTO [dbo].[TBEMLP_EMAIL_OUT] "
oSql += " (EMAIL_ADRESS, EMAIL_SUBJ, EMAIL_BODY, ADDED_WHO, SENDING_PROFILE, REFERENCE_ID, REFERENCE_STRING, REMINDER_TYPE_ID, EMAIL_ATTMT1, WF_ID) "
oSql += " VALUES (@EMAIL_ADRESS, @EMAIL_SUBJ, @EMAIL_BODY, @ADDED_WHO, @SENDING_PROFILE, @REFERENCE_ID, @REFERENCE_STRING, @REMINDER_TYPE_ID, @EMAIL_ATTMT1, @WF_ID)"
oSql += " (EMAIL_ADRESS, EMAIL_SUBJ, EMAIL_BODY, ADDED_WHO, SENDING_PROFILE, REFERENCE_ID, REFERENCE_STRING, REMINDER_TYPE_ID, WF_ID,ATT1_RELATED_ID,ATT1_REL_TYPE) "
oSql += " VALUES (@EMAIL_ADRESS, @EMAIL_SUBJ, @EMAIL_BODY, @ADDED_WHO, @SENDING_PROFILE, @REFERENCE_ID, @REFERENCE_STRING, @REMINDER_TYPE_ID, @WF_ID,@ATT1_RELATED_ID,@ATT1_REL_TYPE)"
Dim oCommand As New SqlCommand(oSql)
oCommand.Parameters.Add("EMAIL_ADRESS", SqlDbType.NVarChar).Value = pEmail.EmailAdress
oCommand.Parameters.Add("EMAIL_SUBJ", SqlDbType.NVarChar).Value = pEmail.EmailSubject
@@ -23,8 +23,10 @@ Public Class EmailModel
oCommand.Parameters.Add("REFERENCE_ID", SqlDbType.Int).Value = pEmail.ReferenceID
oCommand.Parameters.Add("REFERENCE_STRING", SqlDbType.NVarChar).Value = pEmail.ReferenceString
oCommand.Parameters.Add("REMINDER_TYPE_ID", SqlDbType.Int).Value = 202377
oCommand.Parameters.Add("EMAIL_ATTMT1", SqlDbType.NVarChar).Value = pEmail.EmailAttachment
'oCommand.Parameters.Add("EMAIL_ATTMT1", SqlDbType.NVarChar).Value = pEmail.EmailAttachment
oCommand.Parameters.Add("WF_ID", SqlDbType.Int).Value = pEmail.EmailType ' Wegen DB-Trigger MUSS dieser Wert gesetzt werden
oCommand.Parameters.Add("ATT1_RELATED_ID", SqlDbType.Int).Value = pEmail.ATT1_RELATED_ID
oCommand.Parameters.Add("ATT1_REL_TYPE", SqlDbType.NVarChar).Value = pEmail.ATT1_REL_TYPE
If Database.ExecuteNonQuery(oCommand) Then
Return True

View File

@@ -47,15 +47,6 @@ Public Class EnvelopeModel
.FinalEmailToCreator = ObjectEx.ToEnum(Of Constants.FinalEmailType)(pRow.ItemEx("FINAL_EMAIL_TO_CREATOR", Constants.FinalEmailType.No.ToString())),
.FinalEmailToReceivers = ObjectEx.ToEnum(Of Constants.FinalEmailType)(pRow.ItemEx("FINAL_EMAIL_TO_RECEIVERS", Constants.FinalEmailType.No.ToString()))
}
Dim oDoc1 = pRow.Item("DOC1")
If Not IsDBNull(oDoc1) Then
Dim oByte As Byte() = DirectCast(pRow.Item("DOC1"), Byte())
If Not IsNothing(oByte) Then
oEnvelope.Doc1 = oByte
End If
Else
oEnvelope.Doc1 = Nothing
End If
Dim oDOC_RESULT = pRow.Item("DOC_RESULT")
If Not IsDBNull(oDOC_RESULT) Then
Dim oByte As Byte() = DirectCast(pRow.Item("DOC_RESULT"), Byte())
@@ -202,6 +193,9 @@ Public Class EnvelopeModel
oCommand.Parameters.Add("TITLE", SqlDbType.NVarChar).Value = pEnvelope.Title
oCommand.Parameters.Add("ENVELOPE_TYPE", SqlDbType.Int).Value = pEnvelope.EnvelopeTypeId
oCommand.Parameters.Add("CONTRACT_TYPE", SqlDbType.Int).Value = pEnvelope.ContractType
If IsNothing(pEnvelope.Language) Then
pEnvelope.Language = "de-DE"
End If
oCommand.Parameters.Add("LANGUAGE", SqlDbType.NVarChar).Value = pEnvelope.Language
oCommand.Parameters.Add("CERTIFICATION_TYPE", SqlDbType.Int).Value = pEnvelope.CertificationType
oCommand.Parameters.Add("EXPIRES_WHEN_DAYS", SqlDbType.Int).Value = pEnvelope.ExpiresWhenDays

View File

@@ -10,7 +10,7 @@ Public Class HistoryModel
Private Function ToEnvelopeHistoryEntry(pRow As DataRow) As EnvelopeHistoryEntry
Return New EnvelopeHistoryEntry() With {
.ActionDate = pRow.Item("ACTION_DATE"),
.ActionDate = pRow.ItemEx(Of Date)("ACTION_DATE", Nothing),
.EnvelopeId = pRow.Item("ENVELOPE_ID"),
.Status = pRow.Item("STATUS"),
.UserReference = pRow.ItemEx("USER_REFERENCE", "")
@@ -18,7 +18,7 @@ Public Class HistoryModel
End Function
Public Function List(pEnvelopeId As Integer) As List(Of EnvelopeHistoryEntry)
Dim oSql = $"SELECT * FROM TBSIG_ENVELOPE_HISTORY WHERE ENVELOPE_ID = {pEnvelopeId} ORDER BY GUID DESC"
Dim oSql = $"SELECT * FROM TBSIG_ENVELOPE_HISTORY WHERE ENVELOPE_ID = {pEnvelopeId} AND ACTION_DATE IS NOT NULL ORDER BY GUID DESC"
Dim oTable = Database.GetDatatable(oSql)
Return oTable?.Rows.
Cast(Of DataRow).

View File

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

View File

@@ -1,5 +1,6 @@
Imports DevExpress.DataAccess.Native.Web
Imports DigitalData.Modules.Base
Imports EnvelopeGenerator.Common.My.Resources
Public Class ActionService
Inherits BaseService
@@ -33,6 +34,10 @@ Public Class ActionService
Return True
End Function
Public Function ResendReceiver(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean
EmailService.SendDocumentReceivedEmail(pEnvelope, pReceiver)
End Function
Public Function DeleteEnvelope(pEnvelope As Envelope, pReason As String) As Boolean
If HistoryService.SetEnvelopeStatus(pEnvelope, Constants.EnvelopeStatus.EnvelopeDeleted, pEnvelope.User.Email) = False Then
@@ -108,20 +113,20 @@ Public Class ActionService
Return True
End Function
Public Function CompleteEnvelope(pEnvelope As Envelope, pReceiver As EnvelopeReceiver, pAttachment As String) As Boolean
Public Function CompleteEnvelope(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean ', pAttachment As String
If HistoryService.SetEnvelopeStatus(pEnvelope, Constants.EnvelopeStatus.MessageCompletionSent, pReceiver.Email) = False Then
Return False
End If
Return EmailService.SendDocumentCompletedEmailToReceiver(pEnvelope, pReceiver, pAttachment)
Return EmailService.SendDocumentCompletedEmailToReceiver(pEnvelope, pReceiver) ', pAttachment
End Function
Public Function CompleteEnvelope(pEnvelope As Envelope, pAttachment As String) As Boolean
Public Function CompleteEnvelope(pEnvelope As Envelope) As Boolean ', pAttachment As String
If HistoryService.SetEnvelopeStatus(pEnvelope, Constants.EnvelopeStatus.MessageCompletionSent, pEnvelope.User.Email) = False Then
Return False
End If
Return EmailService.SendDocumentCompletedEmailToCreator(pEnvelope, pAttachment)
Return EmailService.SendDocumentCompletedEmailToCreator(pEnvelope) ', pAttachment
End Function
Public Function CreateReport(pEnvelope As Envelope) As Boolean

View File

@@ -1,6 +1,7 @@
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Logging
Imports EnvelopeGenerator.Common.My.Resources
Public Class EmailService
Inherits BaseService
@@ -49,6 +50,15 @@ Public Class EmailService
Return True
End Function
Public Function GetReceiverUrl(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As String
Dim oEmailData As New EmailData(pEnvelope, pReceiver, Constants.EnvelopeStatus.MessageInvitationSent) With
{
.SignatureLink = Helpers.GetEnvelopeURL(State.DbConfig.SignatureHost, pEnvelope.Uuid, pReceiver.Signature)
}
Return oEmailData.SignatureLink
End Function
Public Function SendDocumentAccessCodeReceivedEmail(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean
Logger.Debug("Creating email data object.")
Dim oEmailData As New EmailData(pEnvelope, pReceiver, Constants.EnvelopeStatus.MessageAccessCodeSent) With
@@ -83,14 +93,15 @@ Public Class EmailService
Return True
End Function
Public Function SendDocumentCompletedEmailToReceiver(pEnvelope As Envelope, pReceiver As EnvelopeReceiver, pAttachment As String) As Boolean
Public Function SendDocumentCompletedEmailToReceiver(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean ', pAttachment As String
Logger.Debug("Creating email data object.")
Dim oEmailData = New EmailData(pEnvelope, pReceiver, Constants.EnvelopeStatus.MessageCompletionSent) With
{
.SignatureLink = "",
.EmailAttachment = pAttachment
.ATT1_RELATED_ID = pEnvelope.Id,
.ATT1_REL_TYPE = "EnvelopeResult"
}
' .EmailAttachment = pAttachment,
Logger.Debug("Sending mail to receiver: [{0}]", oEmailData.EmailAdress)
EmailTemplate.FillDocumentCompletedEmailBody(oEmailData)
@@ -103,14 +114,15 @@ Public Class EmailService
Return True
End Function
Public Function SendDocumentCompletedEmailToCreator(pEnvelope As Envelope, pAttachment As String) As Boolean
Public Function SendDocumentCompletedEmailToCreator(pEnvelope As Envelope) As Boolean ', pAttachment As String
Logger.Debug("Creating email data object.")
Dim oEmailData = New EmailData(pEnvelope, Constants.EnvelopeStatus.MessageCompletionSent) With
{
.SignatureLink = "",
.EmailAttachment = pAttachment
.ATT1_RELATED_ID = pEnvelope.Id,
.ATT1_REL_TYPE = "EnvelopeResult"
}
'.EmailAttachment = pAttachment,
EmailTemplate.FillDocumentCompletedEmailBody(oEmailData)
If EmailModel.Insert(oEmailData) = False Then

View File

@@ -154,7 +154,7 @@
<value>Envelope could not be sent!</value>
</data>
<data name="Envelope Invitations Sent" xml:space="preserve">
<value>Envelope Invitations Sent</value>
<value>The invitations have been scheduled for dispatch.s</value>
</data>
<data name="Envelope Overview" xml:space="preserve">
<value>Overview</value>

View File

@@ -154,7 +154,7 @@
<value>Umschlag konnte nicht gesendet werden!</value>
</data>
<data name="Envelope Invitations Sent" xml:space="preserve">
<value>Die Einladungen wurden versendet</value>
<value>Die Einladungen zum Signieren wurden zum Versand eingereiht.</value>
</data>
<data name="Envelope Overview" xml:space="preserve">
<value>Übersicht</value>

View File

@@ -182,7 +182,7 @@ Namespace My.Resources
End Property
'''<summary>
''' Sucht eine lokalisierte Zeichenfolge, die Die Einladungen wurden versendet ähnelt.
''' Sucht eine lokalisierte Zeichenfolge, die Die Einladungen zum Signieren wurden zum Versand eingereiht. ähnelt.
'''</summary>
Public Shared ReadOnly Property Envelope_Invitations_Sent() As String
Get

View File

@@ -0,0 +1,3 @@
Public Class Model
End Class

View File

@@ -0,0 +1,60 @@
Imports System.IO
Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Logging
Public Class TempFiles
Inherits BaseClass
Public Property TempPath As String
Public Sub New(pLogConfig As LogConfig)
MyBase.New(pLogConfig)
Dim oTempDirectoryPath = Path.GetTempPath()
TempPath = Path.Combine(oTempDirectoryPath, "EnvelopeGenerator")
End Sub
Public Function Create() As Boolean
Try
If Directory.Exists(TempPath) = False Then
Directory.CreateDirectory(TempPath)
Else
CleanUpFiles()
End If
Return True
Catch ex As Exception
Logger.Error(ex)
Return False
End Try
End Function
Private Function CleanUpFiles() As Boolean
Try
For Each fileItem As String In Directory.GetFiles(TempPath)
Logger.Debug("Deleting tempPath-file: {0} ...", fileItem)
File.Delete(fileItem)
Next
Return True
Catch ex As Exception
Logger.Error(ex)
Return False
End Try
End Function
Public Function CleanUp() As Boolean
Try
Logger.Debug("Deleting tempPath-Data: {0} ...", TempPath)
Directory.Delete(TempPath, True)
Return True
Catch ex As Exception
Logger.Error(ex)
Return False
End Try
End Function
End Class

View File

@@ -21,6 +21,9 @@ namespace EnvelopeGenerator.Domain.Entities
[Column("STATUS")]
public int Status { get; set; }
[NotMapped]
public string StatusName => ((Constants.EnvelopeStatus)Status).ToString();
[Required]
[Column("ENVELOPE_UUID", TypeName = "nvarchar(36)")]
public string Uuid { get; set; }
@@ -100,19 +103,6 @@ namespace EnvelopeGenerator.Domain.Entities
[NotMapped]
public bool IsAlreadySent => Status > (int) Constants.EnvelopeStatus.EnvelopeSaved;
[NotMapped]
public string? StatusTranslated => Model.ResourceManager.GetString(Status.ToString());
[NotMapped]
public string? ContractTypeTranslated
{
get
{
string? oContractType = ContractType.ToString();
return oContractType is null ? default : Model.ResourceManager.GetString(oContractType);
}
}
public IEnumerable<EnvelopeDocument>? Documents { get; set; }
public IEnumerable<EnvelopeHistory>? History { get; set; }

View File

@@ -10,14 +10,14 @@ namespace EnvelopeGenerator.Domain.Entities
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Column("GUID")]
public int Id { get; set; }
[Required]
[Required, EmailAddress]
[Column("EMAIL_ADDRESS", TypeName = "nvarchar(128)")]
public string EmailAddress { get; set; }
public required string EmailAddress { get; set; }
[Required]
[Column("SIGNATURE", TypeName = "nvarchar(64)")]
public string Signature { get; set; }
public required string Signature { get; set; }
[Required]
[Column("ADDED_WHEN", TypeName = "datetime")]

View File

@@ -7,20 +7,12 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.Application" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.DTO" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.Infrastructure" Version="1.0.0" />
<PackageReference Include="DigitalData.EmailProfilerDispatcher.Abstraction" Version="1.0.0" />
<PackageReference Include="UserManager.Domain" Version="1.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Common\EnvelopeGenerator.Common.vbproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="DigitalData.UserManager.Domain">
<HintPath>..\..\WebUserManager\DigitalData.UserManager.Domain\bin\Debug\net7.0\DigitalData.UserManager.Domain.dll</HintPath>
</Reference>
</ItemGroup>
</Project>

View File

@@ -38,6 +38,9 @@ Public Class EnvelopeEditorController
Public Function SendEnvelope() As Boolean
Return ActionService.SendEnvelope(Envelope)
End Function
Public Function ResendReceiverInvitation(pEnvelope As Envelope, pReceiver As EnvelopeReceiver) As Boolean
Return ActionService.ResendReceiver(pEnvelope, pReceiver)
End Function
Public Function ValidateEnvelopeForSending(pErrors As List(Of String)) As List(Of String)
Dim oEnvelopeErrors = pErrors

View File

@@ -84,6 +84,10 @@
<Reference Include="DigitalData.Modules.Logging">
<HintPath>..\..\DDModules\Logging\bin\Debug\DigitalData.Modules.Logging.dll</HintPath>
</Reference>
<Reference Include="EnvelopeGenerator.Common, Version=1.8.0.0, Culture=neutral, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\EnvelopeGenerator.Common\bin\Debug\EnvelopeGenerator.Common.dll</HintPath>
</Reference>
<Reference Include="GdPicture.NET.14">
<HintPath>D:\ProgramFiles\GdPicture.NET 14\Redist\GdPicture.NET (.NET Framework 4.5)\GdPicture.NET.14.dll</HintPath>
</Reference>
@@ -179,6 +183,7 @@
</EmbeddedResource>
<EmbeddedResource Include="frmEnvelopeEditor.resx">
<DependentUpon>frmEnvelopeEditor.vb</DependentUpon>
<SubType>Designer</SubType>
</EmbeddedResource>
<EmbeddedResource Include="frmEnvelopeMainData.en.resx">
<DependentUpon>frmEnvelopeMainData.vb</DependentUpon>
@@ -247,7 +252,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Common\EnvelopeGenerator.Common.vbproj">
<Project>{6ea0c51f-c2b1-4462-8198-3de0b32b74f8}</Project>
<Project>{6EA0C51F-C2B1-4462-8198-3DE0B32B74F8}</Project>
<Name>EnvelopeGenerator.Common</Name>
</ProjectReference>
</ItemGroup>

View File

@@ -37,113 +37,36 @@ Partial Public Class frmEnvelopeEditor
Private Async Sub btnNewFile_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles btnNewFile.ItemClick
Dim oHandle = SplashScreenManager.ShowOverlayForm(Me)
If IsNothing(Envelope) Then
SaveEnvelopeWithValidation()
If IsNothing(Envelope) Then
Exit Sub
End If
End If
'SaveEnvelopeWithValidation()
' If Not IsNothing(Envelope) Then
Try
' prüfen ob es schon eine Datei gibt
If Documents.Count > 0 Then
MsgBox(Resources.Envelope.Only_one_file_is_allowed, MsgBoxStyle.Information, Text)
Return
End If
If OpenFileDialog1.ShowDialog() = DialogResult.OK Then
Dim oDocument = Await Controller.CreateDocument(OpenFileDialog1.FileName)
If oDocument IsNot Nothing Then
Documents.Add(oDocument)
' Update_File_DB(OpenFileDialog1.FileName)
Else
MsgBox(Resources.Envelope.Document_Could_Not_Be_Saved, MsgBoxStyle.Critical, Text)
' prüfen ob es schon eine Datei gibt
If Documents.Count > 0 Then
MsgBox(Resources.Envelope.Only_one_file_is_allowed, MsgBoxStyle.Information, Text)
Return
End If
End If
Catch ex As Exception
Logger.Error(ex)
Finally
SplashScreenManager.CloseOverlayForm(oHandle)
If OpenFileDialog1.ShowDialog() = DialogResult.OK Then
Dim oDocument = Await Controller.CreateDocument(OpenFileDialog1.FileName)
RibbonPageGroupAddSignature_Enabled()
End Try
End Sub
Sub Update_File_DB(pFilePath As String)
Dim SqlCom As SqlCommand
Dim imageData As Byte()
Dim sFileName As String
Dim qry As String
If oDocument IsNot Nothing Then
Documents.Add(oDocument)
' Update_File_DB(OpenFileDialog1.FileName)
Else
MsgBox(Resources.Envelope.Document_Could_Not_Be_Saved, MsgBoxStyle.Critical, Text)
End If
End If
Try
'Read Image Bytes into a byte array
'Initialize SQL Server Connection
Catch ex As Exception
Logger.Error(ex)
Finally
SplashScreenManager.CloseOverlayForm(oHandle)
'Convert File to bytes Array
imageData = ReadFile(pFilePath)
sFileName = System.IO.Path.GetFileName(pFilePath)
'Set insert query
qry = $"UPDATE TBSIG_ENVELOPE SET DOC1 = @ImageData WHERE GUID = {Envelope.Id}"
'Initialize SqlCommand object for insert.
SqlCom = New SqlCommand(qry, DB_DD_ECM.GetConnection)
'We are passing File Name and Image byte data as sql parameters.
SqlCom.Parameters.Add(New SqlParameter("@ImageData", DirectCast(imageData, Object)))
'Execute the Query
SqlCom.ExecuteNonQuery()
Catch ex As Exception
Logger.Error(ex)
MessageBox.Show(ex.ToString())
End Try
End Sub
'Open file in to a filestream and read data in a byte array.
Private Function ReadFile(ByVal sPath As String) As Byte()
'Initialize byte array with a null value initially.
Dim data As Byte() = Nothing
'Use FileInfo object to get file size.
Dim fInfo As New FileInfo(sPath)
Dim numBytes As Long = fInfo.Length
'Open FileStream to read file
Dim fStream As New FileStream(sPath, FileMode.Open, FileAccess.Read)
'Use BinaryReader to read file stream into byte array.
Dim br As New BinaryReader(fStream)
'When you use BinaryReader, you need to supply number of bytes to read from file.
'In this case we want to read entire file. So supplying total number of bytes.
data = br.ReadBytes(CInt(numBytes))
Return data
End Function
Private Sub downLoadFile(ByVal sFileName As String)
Dim strSql As String
'For Document
Try
'Get image data from gridview column.
strSql = "Select [DOC1] from [TBSIG_ENVELOPE] WHERE GUID =" & Envelope.Id
'Get image data from DB
Dim fileData As Byte() = DirectCast(DB_DD_ECM.GetScalarValue(strSql), Byte())
Dim sTempFileName As String = Application.StartupPath & "\" & sFileName
If Not fileData Is Nothing Then
'Read image data into a file stream
Using fs As New FileStream(sFileName, FileMode.OpenOrCreate, FileAccess.Write)
fs.Write(fileData, 0, fileData.Length)
'Set image variable value using memory stream.
fs.Flush()
fs.Close()
End Using
'Open File
Process.Start(sFileName)
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
RibbonPageGroupAddSignature_Enabled()
End Try
' Else
' SplashScreenManager.CloseOverlayForm(oHandle)
' End If
End Sub
Private Sub frmEditor_Load(sender As Object, e As EventArgs) Handles Me.Load

View File

@@ -27,7 +27,7 @@ Partial Class frmMain
Dim GridLevelNode3 As DevExpress.XtraGrid.GridLevelNode = New DevExpress.XtraGrid.GridLevelNode()
Dim GridLevelNode4 As DevExpress.XtraGrid.GridLevelNode = New DevExpress.XtraGrid.GridLevelNode()
Me.SplitContainerControl1 = New DevExpress.XtraEditors.SplitContainerControl()
Me.XtraTabControl1 = New DevExpress.XtraTab.XtraTabControl()
Me.XtraTabControlMain = New DevExpress.XtraTab.XtraTabControl()
Me.XtraTabPage1 = New DevExpress.XtraTab.XtraTabPage()
Me.GridEnvelopes = New DevExpress.XtraGrid.GridControl()
Me.ViewReceivers = New DevExpress.XtraGrid.Views.Grid.GridView()
@@ -59,6 +59,7 @@ Partial Class frmMain
Me.btnOpenLogDirectory = New DevExpress.XtraBars.BarButtonItem()
Me.BarCheckItem1 = New DevExpress.XtraBars.BarCheckItem()
Me.bsitmInfo = New DevExpress.XtraBars.BarStaticItem()
Me.bbtnitmEB = New DevExpress.XtraBars.BarButtonItem()
Me.RibbonPage1 = New DevExpress.XtraBars.Ribbon.RibbonPage()
Me.RibbonPageEnvelopeActions = New DevExpress.XtraBars.Ribbon.RibbonPageGroup()
Me.RibbonPageGroup1 = New DevExpress.XtraBars.Ribbon.RibbonPageGroup()
@@ -84,15 +85,15 @@ Partial Class frmMain
Me.GridColumn7 = New DevExpress.XtraGrid.Columns.GridColumn()
Me.RefreshTimer = New System.Windows.Forms.Timer(Me.components)
Me.SaveFileDialog1 = New System.Windows.Forms.SaveFileDialog()
Me.RibbonPageGroup4 = New DevExpress.XtraBars.Ribbon.RibbonPageGroup()
Me.bbtnitmEB = New DevExpress.XtraBars.BarButtonItem()
Me.bbtnitmInfoMail = New DevExpress.XtraBars.BarButtonItem()
Me.BarButtonItem2 = New DevExpress.XtraBars.BarButtonItem()
CType(Me.SplitContainerControl1, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.SplitContainerControl1.Panel1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SplitContainerControl1.Panel1.SuspendLayout()
CType(Me.SplitContainerControl1.Panel2, System.ComponentModel.ISupportInitialize).BeginInit()
Me.SplitContainerControl1.SuspendLayout()
CType(Me.XtraTabControl1, System.ComponentModel.ISupportInitialize).BeginInit()
Me.XtraTabControl1.SuspendLayout()
CType(Me.XtraTabControlMain, System.ComponentModel.ISupportInitialize).BeginInit()
Me.XtraTabControlMain.SuspendLayout()
Me.XtraTabPage1.SuspendLayout()
CType(Me.GridEnvelopes, System.ComponentModel.ISupportInitialize).BeginInit()
CType(Me.ViewReceivers, System.ComponentModel.ISupportInitialize).BeginInit()
@@ -120,7 +121,7 @@ Partial Class frmMain
'
'SplitContainerControl1.Panel1
'
Me.SplitContainerControl1.Panel1.Controls.Add(Me.XtraTabControl1)
Me.SplitContainerControl1.Panel1.Controls.Add(Me.XtraTabControlMain)
resources.ApplyResources(Me.SplitContainerControl1.Panel1, "SplitContainerControl1.Panel1")
'
'SplitContainerControl1.Panel2
@@ -128,12 +129,12 @@ Partial Class frmMain
resources.ApplyResources(Me.SplitContainerControl1.Panel2, "SplitContainerControl1.Panel2")
Me.SplitContainerControl1.SplitterPosition = 272
'
'XtraTabControl1
'XtraTabControlMain
'
resources.ApplyResources(Me.XtraTabControl1, "XtraTabControl1")
Me.XtraTabControl1.Name = "XtraTabControl1"
Me.XtraTabControl1.SelectedTabPage = Me.XtraTabPage1
Me.XtraTabControl1.TabPages.AddRange(New DevExpress.XtraTab.XtraTabPage() {Me.XtraTabPage1, Me.XtraTabPage2})
resources.ApplyResources(Me.XtraTabControlMain, "XtraTabControlMain")
Me.XtraTabControlMain.Name = "XtraTabControlMain"
Me.XtraTabControlMain.SelectedTabPage = Me.XtraTabPage1
Me.XtraTabControlMain.TabPages.AddRange(New DevExpress.XtraTab.XtraTabPage() {Me.XtraTabPage1, Me.XtraTabPage2})
'
'XtraTabPage1
'
@@ -291,9 +292,9 @@ Partial Class frmMain
Me.RibbonControl.ExpandCollapseItem.Id = 0
Me.RibbonControl.ExpandCollapseItem.ImageOptions.ImageIndex = CType(resources.GetObject("RibbonControl.ExpandCollapseItem.ImageOptions.ImageIndex"), Integer)
Me.RibbonControl.ExpandCollapseItem.ImageOptions.LargeImageIndex = CType(resources.GetObject("RibbonControl.ExpandCollapseItem.ImageOptions.LargeImageIndex"), Integer)
Me.RibbonControl.Items.AddRange(New DevExpress.XtraBars.BarItem() {Me.RibbonControl.ExpandCollapseItem, Me.RibbonControl.SearchEditItem, Me.btnCreateEnvelope, Me.btnEditEnvelope, Me.btnDeleteEnvelope, Me.BarButtonItem1, Me.txtRefreshLabel, Me.btnShowDocument, Me.btnContactReceiver, Me.txtEnvelopeIdLabel, Me.btnOpenLogDirectory, Me.BarCheckItem1, Me.bsitmInfo, Me.bbtnitmEB})
Me.RibbonControl.Items.AddRange(New DevExpress.XtraBars.BarItem() {Me.RibbonControl.ExpandCollapseItem, Me.RibbonControl.SearchEditItem, Me.btnCreateEnvelope, Me.btnEditEnvelope, Me.btnDeleteEnvelope, Me.BarButtonItem1, Me.txtRefreshLabel, Me.btnShowDocument, Me.btnContactReceiver, Me.txtEnvelopeIdLabel, Me.btnOpenLogDirectory, Me.BarCheckItem1, Me.bsitmInfo, Me.bbtnitmEB, Me.bbtnitmInfoMail, Me.BarButtonItem2})
resources.ApplyResources(Me.RibbonControl, "RibbonControl")
Me.RibbonControl.MaxItemId = 15
Me.RibbonControl.MaxItemId = 17
Me.RibbonControl.Name = "RibbonControl"
Me.RibbonControl.Pages.AddRange(New DevExpress.XtraBars.Ribbon.RibbonPage() {Me.RibbonPage1, Me.RibbonPage2})
Me.RibbonControl.ShowApplicationButton = DevExpress.Utils.DefaultBoolean.[False]
@@ -401,9 +402,17 @@ Partial Class frmMain
Me.bsitmInfo.PaintStyle = DevExpress.XtraBars.BarItemPaintStyle.CaptionGlyph
Me.bsitmInfo.Visibility = DevExpress.XtraBars.BarItemVisibility.Never
'
'bbtnitmEB
'
resources.ApplyResources(Me.bbtnitmEB, "bbtnitmEB")
Me.bbtnitmEB.Enabled = False
Me.bbtnitmEB.Id = 14
Me.bbtnitmEB.ImageOptions.SvgImage = CType(resources.GetObject("bbtnitmEB.ImageOptions.SvgImage"), DevExpress.Utils.Svg.SvgImage)
Me.bbtnitmEB.Name = "bbtnitmEB"
'
'RibbonPage1
'
Me.RibbonPage1.Groups.AddRange(New DevExpress.XtraBars.Ribbon.RibbonPageGroup() {Me.RibbonPageEnvelopeActions, Me.RibbonPageGroup1, Me.RibbonPageGroup2, Me.RibbonPageGroup4})
Me.RibbonPage1.Groups.AddRange(New DevExpress.XtraBars.Ribbon.RibbonPageGroup() {Me.RibbonPageEnvelopeActions, Me.RibbonPageGroup1, Me.RibbonPageGroup2})
Me.RibbonPage1.Name = "RibbonPage1"
resources.ApplyResources(Me.RibbonPage1, "RibbonPage1")
'
@@ -426,7 +435,9 @@ Partial Class frmMain
'
Me.RibbonPageGroup2.ItemLinks.Add(Me.btnShowDocument)
Me.RibbonPageGroup2.ItemLinks.Add(Me.btnContactReceiver)
Me.RibbonPageGroup2.ItemLinks.Add(Me.bbtnitmInfoMail)
Me.RibbonPageGroup2.ItemLinks.Add(Me.bbtnitmEB)
Me.RibbonPageGroup2.ItemLinks.Add(Me.BarButtonItem2)
Me.RibbonPageGroup2.Name = "RibbonPageGroup2"
resources.ApplyResources(Me.RibbonPageGroup2, "RibbonPageGroup2")
'
@@ -589,18 +600,19 @@ Partial Class frmMain
'
resources.ApplyResources(Me.SaveFileDialog1, "SaveFileDialog1")
'
'RibbonPageGroup4
'bbtnitmInfoMail
'
Me.RibbonPageGroup4.Name = "RibbonPageGroup4"
resources.ApplyResources(Me.RibbonPageGroup4, "RibbonPageGroup4")
resources.ApplyResources(Me.bbtnitmInfoMail, "bbtnitmInfoMail")
Me.bbtnitmInfoMail.Id = 15
Me.bbtnitmInfoMail.ImageOptions.SvgImage = CType(resources.GetObject("BarButtonItem2.ImageOptions.SvgImage"), DevExpress.Utils.Svg.SvgImage)
Me.bbtnitmInfoMail.Name = "bbtnitmInfoMail"
'
'bbtnitmEB
'BarButtonItem2
'
resources.ApplyResources(Me.bbtnitmEB, "bbtnitmEB")
Me.bbtnitmEB.Enabled = False
Me.bbtnitmEB.Id = 14
Me.bbtnitmEB.ImageOptions.SvgImage = CType(resources.GetObject("BarButtonItem2.ImageOptions.SvgImage"), DevExpress.Utils.Svg.SvgImage)
Me.bbtnitmEB.Name = "bbtnitmEB"
resources.ApplyResources(Me.BarButtonItem2, "BarButtonItem2")
Me.BarButtonItem2.Id = 16
Me.BarButtonItem2.ImageOptions.SvgImage = CType(resources.GetObject("BarButtonItem2.ImageOptions.SvgImage1"), DevExpress.Utils.Svg.SvgImage)
Me.BarButtonItem2.Name = "BarButtonItem2"
'
'frmMain
'
@@ -618,8 +630,8 @@ Partial Class frmMain
CType(Me.SplitContainerControl1.Panel2, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.SplitContainerControl1, System.ComponentModel.ISupportInitialize).EndInit()
Me.SplitContainerControl1.ResumeLayout(False)
CType(Me.XtraTabControl1, System.ComponentModel.ISupportInitialize).EndInit()
Me.XtraTabControl1.ResumeLayout(False)
CType(Me.XtraTabControlMain, System.ComponentModel.ISupportInitialize).EndInit()
Me.XtraTabControlMain.ResumeLayout(False)
Me.XtraTabPage1.ResumeLayout(False)
CType(Me.GridEnvelopes, System.ComponentModel.ISupportInitialize).EndInit()
CType(Me.ViewReceivers, System.ComponentModel.ISupportInitialize).EndInit()
@@ -653,7 +665,7 @@ Partial Class frmMain
Friend WithEvents ColEmail As DevExpress.XtraGrid.Columns.GridColumn
Friend WithEvents ColReceiverStatus As DevExpress.XtraGrid.Columns.GridColumn
Friend WithEvents SplitContainerControl1 As DevExpress.XtraEditors.SplitContainerControl
Friend WithEvents XtraTabControl1 As DevExpress.XtraTab.XtraTabControl
Friend WithEvents XtraTabControlMain As DevExpress.XtraTab.XtraTabControl
Friend WithEvents XtraTabPage1 As DevExpress.XtraTab.XtraTabPage
Friend WithEvents XtraTabPage2 As DevExpress.XtraTab.XtraTabPage
Friend WithEvents GridCompleted As DevExpress.XtraGrid.GridControl
@@ -694,6 +706,7 @@ Partial Class frmMain
Friend WithEvents BarCheckItem1 As DevExpress.XtraBars.BarCheckItem
Friend WithEvents bsitmInfo As DevExpress.XtraBars.BarStaticItem
Friend WithEvents SaveFileDialog1 As SaveFileDialog
Friend WithEvents RibbonPageGroup4 As DevExpress.XtraBars.Ribbon.RibbonPageGroup
Friend WithEvents bbtnitmEB As DevExpress.XtraBars.BarButtonItem
Friend WithEvents bbtnitmInfoMail As DevExpress.XtraBars.BarButtonItem
Friend WithEvents BarButtonItem2 As DevExpress.XtraBars.BarButtonItem
End Class

View File

@@ -125,10 +125,10 @@
<data name="SplitContainerControl1.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 162</value>
</data>
<data name="XtraTabControl1.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<data name="XtraTabControlMain.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
<value>Fill</value>
</data>
<data name="XtraTabControl1.Location" type="System.Drawing.Point, System.Drawing">
<data name="XtraTabControlMain.Location" type="System.Drawing.Point, System.Drawing">
<value>0, 0</value>
</data>
<data name="GridEnvelopes.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
@@ -684,7 +684,7 @@
<data name="bbtnitmEB.Caption" xml:space="preserve">
<value>Ergebnisbericht anzeigen</value>
</data>
<data name="BarButtonItem2.ImageOptions.SvgImage" type="DevExpress.Utils.Svg.SvgImage, DevExpress.Data.v21.2" mimetype="application/x-microsoft.net.object.bytearray.base64">
<data name="bbtnitmEB.ImageOptions.SvgImage" type="DevExpress.Utils.Svg.SvgImage, DevExpress.Data.v21.2" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFlEZXZFeHByZXNzLkRhdGEudjIxLjIsIFZlcnNpb249MjEuMi40
LjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjg4ZDE3NTRkNzAwZTQ5YQUBAAAAHURl
@@ -709,6 +709,50 @@
My40LTMuOWgtMi4xdjhoMi4yYzEuMSwwLDEuOS0wLjQsMi41LTEuMUMyMC45LDIwLjIsMjEuMiwxOS4y
LDIxLjIsMTcuOXogICAgTTI2LDE0aC0zLjd2OGgxLjZ2LTMuMWgydi0xLjNoLTJ2LTIuMkgyNlYxNHoi
IGNsYXNzPSJSZWQiIC8+DQogIDwvZz4NCjwvc3ZnPgs=
</value>
</data>
<data name="bbtnitmInfoMail.Caption" xml:space="preserve">
<value>Support Mail</value>
</data>
<data name="BarButtonItem2.ImageOptions.SvgImage" type="DevExpress.Utils.Svg.SvgImage, DevExpress.Data.v21.2" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFlEZXZFeHByZXNzLkRhdGEudjIxLjIsIFZlcnNpb249MjEuMi40
LjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjg4ZDE3NTRkNzAwZTQ5YQUBAAAAHURl
dkV4cHJlc3MuVXRpbHMuU3ZnLlN2Z0ltYWdlAQAAAAREYXRhBwICAAAACQMAAAAPAwAAAKQCAAAC77u/
PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz4NCjxzdmcgeD0iMHB4IiB5PSIwcHgi
IHZpZXdCb3g9IjAgMCAzMiAzMiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv
MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3Bh
Y2U9InByZXNlcnZlIiBpZD0iTGF5ZXJfMSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAg
MzIgMzIiPg0KICA8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLkJsYWNre2ZpbGw6IzcyNzI3Mjt9Cgku
WWVsbG93e2ZpbGw6I0ZGQjExNTt9CgkuQmx1ZXtmaWxsOiMxMTc3RDc7fQoJLlJlZHtmaWxsOiNEMTFD
MUM7fQoJLldoaXRle2ZpbGw6I0ZGRkZGRjt9CgkuR3JlZW57ZmlsbDojMDM5QzIzO30KCS5zdDB7Zmls
bDojNzI3MjcyO30KCS5zdDF7b3BhY2l0eTowLjU7fQoJLnN0MntvcGFjaXR5OjAuNzU7fQo8L3N0eWxl
Pg0KICA8ZyBpZD0iTWFpbCI+DQogICAgPHBhdGggZD0iTTE2LDE4LjNsMTQtOFYyNWMwLDAuNS0wLjUs
MS0xLDFIM2MtMC41LDAtMS0wLjUtMS0xVjEwLjNMMTYsMTguM3ogTTI5LDZIM0MyLjUsNiwyLDYuNSwy
LDd2MWwxNCw4bDE0LThWNyAgIEMzMCw2LjUsMjkuNSw2LDI5LDZ6IiBjbGFzcz0iQmxhY2siIC8+DQog
IDwvZz4NCjwvc3ZnPgs=
</value>
</data>
<data name="BarButtonItem2.Caption" xml:space="preserve">
<value>BarButtonItem2</value>
</data>
<data name="BarButtonItem2.ImageOptions.SvgImage1" type="DevExpress.Utils.Svg.SvgImage, DevExpress.Data.v21.2" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>
AAEAAAD/////AQAAAAAAAAAMAgAAAFlEZXZFeHByZXNzLkRhdGEudjIxLjIsIFZlcnNpb249MjEuMi40
LjAsIEN1bHR1cmU9bmV1dHJhbCwgUHVibGljS2V5VG9rZW49Yjg4ZDE3NTRkNzAwZTQ5YQUBAAAAHURl
dkV4cHJlc3MuVXRpbHMuU3ZnLlN2Z0ltYWdlAQAAAAREYXRhBwICAAAACQMAAAAPAwAAAKQCAAAC77u/
PD94bWwgdmVyc2lvbj0nMS4wJyBlbmNvZGluZz0nVVRGLTgnPz4NCjxzdmcgeD0iMHB4IiB5PSIwcHgi
IHZpZXdCb3g9IjAgMCAzMiAzMiIgdmVyc2lvbj0iMS4xIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcv
MjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB4bWw6c3Bh
Y2U9InByZXNlcnZlIiBpZD0iTGF5ZXJfMSIgc3R5bGU9ImVuYWJsZS1iYWNrZ3JvdW5kOm5ldyAwIDAg
MzIgMzIiPg0KICA8c3R5bGUgdHlwZT0idGV4dC9jc3MiPgoJLkJsYWNre2ZpbGw6IzcyNzI3Mjt9Cgku
WWVsbG93e2ZpbGw6I0ZGQjExNTt9CgkuQmx1ZXtmaWxsOiMxMTc3RDc7fQoJLlJlZHtmaWxsOiNEMTFD
MUM7fQoJLldoaXRle2ZpbGw6I0ZGRkZGRjt9CgkuR3JlZW57ZmlsbDojMDM5QzIzO30KCS5zdDB7Zmls
bDojNzI3MjcyO30KCS5zdDF7b3BhY2l0eTowLjU7fQoJLnN0MntvcGFjaXR5OjAuNzU7fQo8L3N0eWxl
Pg0KICA8ZyBpZD0iTWFpbCI+DQogICAgPHBhdGggZD0iTTE2LDE4LjNsMTQtOFYyNWMwLDAuNS0wLjUs
MS0xLDFIM2MtMC41LDAtMS0wLjUtMS0xVjEwLjNMMTYsMTguM3ogTTI5LDZIM0MyLjUsNiwyLDYuNSwy
LDd2MWwxNCw4bDE0LThWNyAgIEMzMCw2LjUsMjkuNSw2LDI5LDZ6IiBjbGFzcz0iQmxhY2siIC8+DQog
IDwvZz4NCjwvc3ZnPgs=
</value>
</data>
<data name="RibbonControl.Location" type="System.Drawing.Point, System.Drawing">
@@ -723,9 +767,6 @@
<data name="RibbonPageGroup2.Text" xml:space="preserve">
<value>Funktionen</value>
</data>
<data name="RibbonPageGroup4.Text" xml:space="preserve">
<value>RibbonPageGroup4</value>
</data>
<data name="RibbonPage1.Text" xml:space="preserve">
<value>Start</value>
</data>
@@ -799,15 +840,15 @@
<value>DevExpress.XtraTab.XtraTabPage, DevExpress.XtraEditors.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="&gt;&gt;XtraTabPage1.Parent" xml:space="preserve">
<value>XtraTabControl1</value>
<value>XtraTabControlMain</value>
</data>
<data name="&gt;&gt;XtraTabPage1.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="XtraTabControl1.Size" type="System.Drawing.Size, System.Drawing">
<data name="XtraTabControlMain.Size" type="System.Drawing.Size, System.Drawing">
<value>1090, 484</value>
</data>
<data name="XtraTabControl1.TabIndex" type="System.Int32, mscorlib">
<data name="XtraTabControlMain.TabIndex" type="System.Int32, mscorlib">
<value>3</value>
</data>
<data name="GridCompleted.Dock" type="System.Windows.Forms.DockStyle, System.Windows.Forms">
@@ -979,21 +1020,21 @@
<value>DevExpress.XtraTab.XtraTabPage, DevExpress.XtraEditors.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="&gt;&gt;XtraTabPage2.Parent" xml:space="preserve">
<value>XtraTabControl1</value>
<value>XtraTabControlMain</value>
</data>
<data name="&gt;&gt;XtraTabPage2.ZOrder" xml:space="preserve">
<value>1</value>
</data>
<data name="&gt;&gt;XtraTabControl1.Name" xml:space="preserve">
<value>XtraTabControl1</value>
<data name="&gt;&gt;XtraTabControlMain.Name" xml:space="preserve">
<value>XtraTabControlMain</value>
</data>
<data name="&gt;&gt;XtraTabControl1.Type" xml:space="preserve">
<data name="&gt;&gt;XtraTabControlMain.Type" xml:space="preserve">
<value>DevExpress.XtraTab.XtraTabControl, DevExpress.XtraEditors.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="&gt;&gt;XtraTabControl1.Parent" xml:space="preserve">
<data name="&gt;&gt;XtraTabControlMain.Parent" xml:space="preserve">
<value>SplitContainerControl1.Panel1</value>
</data>
<data name="&gt;&gt;XtraTabControl1.ZOrder" xml:space="preserve">
<data name="&gt;&gt;XtraTabControlMain.ZOrder" xml:space="preserve">
<value>0</value>
</data>
<data name="SplitContainerControl1.Panel1.Text" xml:space="preserve">
@@ -1322,6 +1363,12 @@
<data name="&gt;&gt;bsitmInfo.Type" xml:space="preserve">
<value>DevExpress.XtraBars.BarStaticItem, DevExpress.XtraBars.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="&gt;&gt;bbtnitmEB.Name" xml:space="preserve">
<value>bbtnitmEB</value>
</data>
<data name="&gt;&gt;bbtnitmEB.Type" xml:space="preserve">
<value>DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="&gt;&gt;RibbonPage1.Name" xml:space="preserve">
<value>RibbonPage1</value>
</data>
@@ -1454,16 +1501,16 @@
<data name="&gt;&gt;SaveFileDialog1.Type" xml:space="preserve">
<value>System.Windows.Forms.SaveFileDialog, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</data>
<data name="&gt;&gt;RibbonPageGroup4.Name" xml:space="preserve">
<value>RibbonPageGroup4</value>
<data name="&gt;&gt;bbtnitmInfoMail.Name" xml:space="preserve">
<value>bbtnitmInfoMail</value>
</data>
<data name="&gt;&gt;RibbonPageGroup4.Type" xml:space="preserve">
<value>DevExpress.XtraBars.Ribbon.RibbonPageGroup, DevExpress.XtraBars.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
<data name="&gt;&gt;bbtnitmInfoMail.Type" xml:space="preserve">
<value>DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="&gt;&gt;bbtnitmEB.Name" xml:space="preserve">
<value>bbtnitmEB</value>
<data name="&gt;&gt;BarButtonItem2.Name" xml:space="preserve">
<value>BarButtonItem2</value>
</data>
<data name="&gt;&gt;bbtnitmEB.Type" xml:space="preserve">
<data name="&gt;&gt;BarButtonItem2.Type" xml:space="preserve">
<value>DevExpress.XtraBars.BarButtonItem, DevExpress.XtraBars.v21.2, Version=21.2.4.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a</value>
</data>
<data name="&gt;&gt;$this.Name" xml:space="preserve">

View File

@@ -10,6 +10,7 @@ Imports DigitalData.Modules.Base
Imports DigitalData.Modules.Logging
Imports EnvelopeGenerator.Common
Imports EnvelopeGenerator.Common.My
Imports System.Diagnostics
Public Class frmMain
Private ReadOnly LogConfig As LogConfig
@@ -55,8 +56,12 @@ Public Class frmMain
Private Sub LoadEnvelopeData()
Try
RefreshHelper.SaveViewInfo()
LoadEnvelopes()
LoadCompletedEnvelopes()
If XtraTabControlMain.SelectedTabPageIndex = 0 Then
LoadEnvelopes()
ElseIf XtraTabControlMain.SelectedTabPageIndex = 1 Then
LoadCompletedEnvelopes()
End If
RefreshHelper.LoadViewInfo()
'LoadCharts()
@@ -183,20 +188,22 @@ Public Class frmMain
TempFiles.CleanUp()
End Sub
Private Sub XtraTabControl1_SelectedPageChanged(sender As Object, e As DevExpress.XtraTab.TabPageChangedEventArgs) Handles XtraTabControl1.SelectedPageChanged
Select Case XtraTabControl1.SelectedTabPageIndex
Private Sub XtraTabControl1_SelectedPageChanged(sender As Object, e As DevExpress.XtraTab.TabPageChangedEventArgs) Handles XtraTabControlMain.SelectedPageChanged
Select Case XtraTabControlMain.SelectedTabPageIndex
Case 1
btnEditEnvelope.Enabled = False
btnDeleteEnvelope.Enabled = False
btnContactReceiver.Enabled = False
btnShowDocument.Enabled = False
bbtnitmEB.Enabled = True
LoadEnvelopeData()
Case 0
btnEditEnvelope.Enabled = True
btnDeleteEnvelope.Enabled = True
btnContactReceiver.Enabled = True
btnShowDocument.Enabled = True
bbtnitmEB.Enabled = False
LoadEnvelopeData()
End Select
End Sub
@@ -220,30 +227,43 @@ Public Class frmMain
End If
End Sub
Private Sub bbtnitmEB_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtnitmEB.ItemClick
If ViewEnvelopes.FocusedRowHandle < 0 Then
Exit Sub
End If
Me.Cursor = Cursors.WaitCursor
Dim oEnvelope As Envelope = ViewCompleted.GetRow(ViewCompleted.FocusedRowHandle)
GetResRepFileStreamByte(oEnvelope.Id)
Dim oTempFolder = TempFiles.TempPath
Dim oTempFilename = String.Concat(oTempFolder, "\", $"ViewEnvResReport_{oEnvelope.Id}.pdf")
If File.Exists(oTempFilename) Then
Try
File.OpenWrite(oTempFilename)
Catch ex As Exception
MsgBox("File might already be open?", MsgBoxStyle.Exclamation)
Try
If ViewEnvelopes.FocusedRowHandle < 0 Then
Exit Sub
End Try
End If
Me.Cursor = Cursors.WaitCursor
Dim oEnvelope As Envelope = ViewCompleted.GetRow(ViewCompleted.FocusedRowHandle)
GetResRepFileStreamByte(oEnvelope.Id)
Dim oTempFolder = TempFiles.TempPath
Dim oFilename = "ViewEnvResReport"
Dim oVersion As Integer = 0
Dim oTempFilename = String.Concat(oTempFolder, "\", $"{oFilename}_{oEnvelope.Id}.pdf")
Do While File.Exists(oTempFilename)
oVersion += 1
oTempFilename = String.Concat(oTempFolder, "\", $"{oFilename}_{oEnvelope.Id}_", oVersion.ToString, ".pdf")
Loop
'If File.Exists(oTempFilename) Then
' oVersion += 1
' oTempFilename = String.Concat(oTempFolder, "\", $"ViewEnvResReport_{oEnvelope.Id}_", oVersion.ToString, ".pdf")
' Try
' File.OpenWrite(oTempFilename)
' Catch ex As Exception
' MsgBox("File might already be open?", MsgBoxStyle.Exclamation)
' Exit Sub
' End Try
File.Delete(oTempFilename)
End If
downloadResFile(oTempFilename)
' File.Delete(oTempFilename)
'End If
downloadResFile(oTempFilename)
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Exclamation)
End Try
Me.Cursor = Cursors.Default
End Sub
Private Sub ViewEnvelopes_CustomDrawCell(sender As Object, e As DevExpress.XtraGrid.Views.Base.RowCellCustomDrawEventArgs) Handles ViewEnvelopes.CustomDrawCell
If e.RowHandle < 0 Or XtraTabControl1.SelectedTabPageIndex = 1 Then
If e.RowHandle < 0 Or XtraTabControlMain.SelectedTabPageIndex = 1 Then
Exit Sub
End If
@@ -374,27 +394,6 @@ Public Class frmMain
End Try
Me.Cursor = Cursors.Default
End Sub
'Private Sub GetFileStreamByte(ByVal pEnvID As Long)
' Dim strSql As String
' 'For Document
' Try
' 'Get image data from gridview column.
' strSql = "Select [DOC1] from [TBSIG_ENVELOPE] WHERE GUID =" & pEnvID
' 'Get image data from DB
' Dim fileData As Byte() = DirectCast(DB_DD_ECM.GetScalarValue(strSql), Byte())
' If Not fileData Is Nothing Then
' myFileData = fileData
' Else
' myFileData = Nothing
' End If
' Catch ex As Exception
' MsgBox(ex.Message, MsgBoxStyle.Exclamation, "Error in GetFileStreamByte")
' myFileData = Nothing
' End Try
'End Sub
Private Sub GetResRepFileStreamByte(ByVal pEnvID As Long)
Dim strSql As String
@@ -442,9 +441,6 @@ Public Class frmMain
End Try
End Sub
Private Sub downloadResFile(ByVal sFileName As String)
Dim strSql As String
'For Document
Try
If Not myResFileData Is Nothing Then
'Read image data into a file stream
@@ -504,8 +500,54 @@ Public Class frmMain
Else
BarCheckItem1.Checked = False
End If
bbtnitmEB.Enabled = False
RefreshTimer.Start()
End Sub
Private Sub bbtnitmInfoMail_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles bbtnitmInfoMail.ItemClick
If ViewEnvelopes.FocusedRowHandle < 0 Then
Exit Sub
End If
Try
Dim oEnvelope As Envelope = ViewEnvelopes.GetRow(ViewEnvelopes.FocusedRowHandle)
Dim oView As GridView = GridEnvelopes.FocusedView
If oView.Name = ViewReceivers.Name Then
Dim oReceiver As EnvelopeReceiver = oView.GetRow(oView.FocusedRowHandle)
Dim oEnvelopeTitle As String = Net.WebUtility.UrlEncode(oEnvelope.Title)
Dim oCode = oReceiver.AccessCode
Dim oUID = oEnvelope.Uuid
' E-Mail-Details konfigurieren
Dim mailto As String = "support-flow@digitaldata.works"
Dim subject As String = "signFLOW - Envelope issue"
Dim body As String = $"<html><body>Dear Digital Data Team, <br> There is an error or misbehavin with following envelope and Receiver: <p> Envelope: <b>{oUID}</b> <br> Receiver: <b>{oReceiver.Email}</b>
<p>Issue/Description: Please describe the issue in Your own words...</p></body></html>"
' URL-encoding für Betreff und Inhalt der E-Mail
'Dim encodedSubject As String = Uri.EscapeDataString(subject)
'Dim encodedBody As String = Uri.EscapeDataString(body)
' mailto-Link erstellen
Dim mailtoLink As String = $"{mailto}?subject={subject}&body={body}"
Try
Process.Start(mailtoLink)
Catch ex1 As Exception
MsgBox(ex1.Message, MsgBoxStyle.Critical, Text)
End Try
' E-Mail-Client öffnen
Process.Start($"mailto:{oReceiver.Email}?subject={oEnvelopeTitle}")
Else
MsgBox(Resources.Envelope.Please_select_a_recipient_from_the_Recipients_tab, MsgBoxStyle.Information, Text)
End If
Catch ex As Exception
MsgBox(ex.Message, MsgBoxStyle.Critical, Text)
End Try
End Sub
Private Sub BarButtonItem2_ItemClick(sender As Object, e As DevExpress.XtraBars.ItemClickEventArgs) Handles BarButtonItem2.ItemClick
End Sub
End Class

View File

@@ -31,9 +31,14 @@
],
"styles": [
"@angular/material/prebuilt-themes/indigo-pink.css",
"src/styles.scss"
"src/styles.scss",
"node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/@popperjs/core/dist/umd/popper.min.js",
"node_modules/bootstrap/dist/js/bootstrap.min.js"
],
"scripts": [],
"server": "src/main.server.ts",
"prerender": true,
"ssr": {
@@ -45,8 +50,8 @@
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
"maximumWarning": "1.5mb",
"maximumError": "2mb"
},
{
"type": "anyComponentStyle",
@@ -76,7 +81,7 @@
},
"defaultConfiguration": "development",
"options": {
"proxyConfig": "src/proxy.conf.json"
"proxyConfig": "proxy.conf.json"
}
},
"extract-i18n": {
@@ -106,7 +111,7 @@
],
"scripts": [
"node_modules/jquery/dist/jquery.min.js",
"node_modules/popper.js/dist/umd/popper.min.js",
"node_modules/@popperjs/core/dist/umd/popper.min.js",
"node_modules/bootstrap/dist/js/bootstrap.min.js"
]
}
@@ -114,4 +119,4 @@
}
}
}
}
}

View File

@@ -1,12 +1,12 @@
{
"name": "envelope-generator-ui",
"version": "0.0.0",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "envelope-generator-ui",
"version": "0.0.0",
"version": "1.0.0",
"dependencies": {
"@angular/animations": "^17.3.0",
"@angular/cdk": "^17.3.10",
@@ -24,11 +24,12 @@
"@generic-ui/hermes": "^0.21.0",
"@generic-ui/ngx-grid": "^0.21.0",
"@ng-bootstrap/ng-bootstrap": "^16.0.0",
"@popperjs/core": "^2.11.8",
"bootstrap": "^5.3.3",
"express": "^4.18.2",
"jquery": "^3.7.1",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"uuid": "^10.0.0",
"zone.js": "~0.14.3"
},
"devDependencies": {
@@ -39,6 +40,7 @@
"@types/express": "^4.17.17",
"@types/jasmine": "~5.1.0",
"@types/node": "^18.18.0",
"@types/uuid": "^10.0.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
@@ -4259,6 +4261,7 @@
"version": "2.11.8",
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
"peer": true,
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/popperjs"
@@ -4871,6 +4874,12 @@
"@types/node": "*"
}
},
"node_modules/@types/uuid": {
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-7gqG38EyHgyP1S+7+xomFtL+ZNHcKv6DwNaCZmJmo1vgMugyF3TCnXVg4t1uk89mLNwnLtnY3TpOpCOyp1/xHQ==",
"dev": true
},
"node_modules/@types/ws": {
"version": "8.5.10",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.10.tgz",
@@ -8448,6 +8457,11 @@
"jiti": "bin/jiti.js"
}
},
"node_modules/jquery": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-3.7.1.tgz",
"integrity": "sha512-m4avr8yL8kmFN8psrbFFFmB/If14iN5o9nw/NgnnM+kybDJpRsAynV2BsfpTYrTRysYUdADVD7CkUUizgkpLfg=="
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -11617,6 +11631,15 @@
"websocket-driver": "^0.7.4"
}
},
"node_modules/sockjs/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/socks": {
"version": "2.8.3",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz",
@@ -12396,10 +12419,13 @@
}
},
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"version": "10.0.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-10.0.0.tgz",
"integrity": "sha512-8XkAphELsDnEGrDxUOHB3RGvXz6TeuYSGEZBOjtTtPm2lwhGBjLgOzLHB63IUWfBpNucQjND6d3AOudO+H3RWQ==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"bin": {
"uuid": "dist/bin/uuid"
}

View File

@@ -1,6 +1,6 @@
{
"name": "envelope-generator-ui",
"version": "0.0.0",
"version": "1.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
@@ -27,11 +27,12 @@
"@generic-ui/hermes": "^0.21.0",
"@generic-ui/ngx-grid": "^0.21.0",
"@ng-bootstrap/ng-bootstrap": "^16.0.0",
"@popperjs/core": "^2.11.8",
"bootstrap": "^5.3.3",
"express": "^4.18.2",
"jquery": "^3.7.1",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"uuid": "^10.0.0",
"zone.js": "~0.14.3"
},
"devDependencies": {
@@ -42,6 +43,7 @@
"@types/express": "^4.17.17",
"@types/jasmine": "~5.1.0",
"@types/node": "^18.18.0",
"@types/uuid": "^10.0.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",

View File

@@ -2,7 +2,7 @@ import { Component } from '@angular/core';
import { RouterOutlet } from '@angular/router';
import { NavbarComponent } from "./components/navbar/navbar.component";
import { LoginComponent } from "./components/login/login.component";
import { HomeComponent } from "./components/home/home.component";
import { HomeComponent } from "./pages/home/home.component";
@Component({
selector: 'app-root',

View File

@@ -6,7 +6,8 @@ import { provideAnimationsAsync } from '@angular/platform-browser/animations/asy
import { APP_BASE_HREF } from '@angular/common';
import { UrlService } from './services/url.service';
import { API_URL } from './tokens/index'
import { provideHttpClient, withFetch } from '@angular/common/http';
import { HTTP_INTERCEPTORS, provideHttpClient, withFetch } from '@angular/common/http';
import { HttpRequestInterceptor } from './http.interceptor';
export const appConfig: ApplicationConfig = {
providers: [
@@ -23,6 +24,11 @@ export const appConfig: ApplicationConfig = {
provide: API_URL,
useFactory: (urlService: UrlService) => urlService.getApiUrl(),
deps: [UrlService]
},
{
provide: HTTP_INTERCEPTORS,
useClass: HttpRequestInterceptor,
multi: true
}
]
};

View File

@@ -1,10 +1,12 @@
import { Routes } from '@angular/router';
import { EnvelopeTableComponent } from '../app/components/envelope-table/envelope-table.component'
import { HomeComponent } from '../app/components/home/home.component'
import { HomeComponent } from '../app/pages/home/home.component'
import { authGuard } from './guards/auth.guard'
import { EnvelopeComponent } from './pages/envelope/envelope.component';
import { EnvelopeCreationComponent } from './pages/envelope-creation/envelope-creation.component';
export const routes: Routes = [
{ path: '', component: HomeComponent },
{ path: '', component: EnvelopeComponent, canActivate: [authGuard] },
{ path: 'login', component: HomeComponent },
{ path: 'envelope', component: EnvelopeTableComponent, canActivate: [authGuard] }
{ path: 'envelope', component: EnvelopeComponent, canActivate: [authGuard] },
{ path: 'envelope-creation', component: EnvelopeCreationComponent, canActivate: [authGuard] }
];

View File

@@ -0,0 +1,9 @@
<mat-form-field class="example-form-field">
<mat-label>{{label}}</mat-label>
<input matInput type="text" [(ngModel)]="value">
@if (value) {
<button matSuffix mat-icon-button aria-label="Clear" (click)="value=''">
<mat-icon>close</mat-icon>
</button>
}
</mat-form-field>

View File

@@ -0,0 +1,7 @@
.mat-stepper-vertical {
margin-top: 8px;
}
.mat-mdc-form-field {
margin-top: 16px;
}

View File

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

View File

@@ -0,0 +1,18 @@
import {Component, Input} from '@angular/core';
import {MatIconModule} from '@angular/material/icon';
import {MatButtonModule} from '@angular/material/button';
import {FormsModule} from '@angular/forms';
import {MatInputModule} from '@angular/material/input';
import {MatFormFieldModule} from '@angular/material/form-field';
@Component({
selector: 'clearable-input',
standalone: true,
imports: [MatFormFieldModule, MatInputModule, FormsModule, MatButtonModule, MatIconModule],
templateUrl: './clearable-input.component.html',
styleUrl: './clearable-input.component.scss'
})
export class ClearableInputComponent {
@Input() public value: string = '';
@Input() public label: string = '';
}

View File

@@ -1,12 +1,48 @@
<gui-grid
[columns]="columns"
[source]="source"
[columnMenu]="columnMenu"
[paging]="paging"
[sorting]="sorting"
[searching]="searching"
[summaries]="summaries"
[infoPanel]="infoPanel"
[localization]="localization"
>
</gui-grid>
<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

@@ -0,0 +1,31 @@
.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,91 +1,74 @@
import { Component } from '@angular/core';
import { Component, Input, ViewChild } from '@angular/core';
import { EnvelopeReceiverService } from '../../services/envelope-receiver.service';
import { NgModule } from '@angular/core';
import { GuiColumn, GuiColumnMenu, GuiGridModule, GuiInfoPanel, GuiLocalization, GuiPaging, GuiPagingDisplay, GuiSearching, GuiSorting, GuiSummaries } from '@generic-ui/ngx-grid';
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: [GuiGridModule],
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 {
columnMenu: GuiColumnMenu = {
enabled: true,
sort: true,
columnsManager: true
};
@Input() data: Array<any> = []
sorting: GuiSorting = {
enabled: true,
multiSorting: true
};
@Input() options?: { min_status?: number; max_status?: number; ignore_status?: number[] }
paging: GuiPaging = {
enabled: true,
page: 1,
pageSize: 10,
pageSizes: [10, 25, 50],
pagerTop: true,
pagerBottom: true,
display: GuiPagingDisplay.ADVANCED
};
@Input() displayedColumns: string[] = ['title', 'status', 'type', 'privateMessage', 'addedWhen'];
searching: GuiSearching = {
enabled: true
};
summaries: GuiSummaries = {
enabled: true
};
infoPanel: GuiInfoPanel = {
enabled:true,
infoDialog:false,
columnsManager:false,
schemaManager: true
};
localization: GuiLocalization = {
translationResolver: (key: string, value: string) => {
return '[de-DE]';
}
};
source: Array<any> = []
constructor(private erService: EnvelopeReceiverService) {
}
ngOnInit() {
this.erService.getEnvelopeReceiver().subscribe({
next: res => this.source = res,
error: console.error
});
}
columns: Array<GuiColumn> = [
{
@Input() schema: Record<string, { header: string; field: (element: any) => any; }> = {
'title': {
header: 'Title',
field: er => er.envelope.title
field: (element: any) => element.envelope.title
},
{
header: "Status",
field: er => er.envelope.status
'status': {
header: 'Status',
field: (element: any) => element.envelope.statusName
},
{
'type': {
header: 'Type',
field: er => er.envelope.contractType
field: (element: any) => element.envelope.contractType
},
{
header: 'PrivateMessage',
field: 'privateMessage'
'privateMessage': {
header: 'Private Message',
field: (element: any) => element.privateMessage
},
{
header: 'AddedWhen',
field: 'addedWhen'
}];
'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

@@ -1,23 +1,25 @@
<!-- src/app/components/login/login.component.html -->
<form [formGroup]="loginForm" (ngSubmit)="onSubmit()">
<div class="mb-3">
<mat-form-field>
<mat-label>Username</mat-label>
<input matInput formControlName="username">
</mat-form-field>
</div>
<div class="mb-3">
<mat-form-field>
<mat-label>Enter your password</mat-label>
<input matInput [type]="hide ? 'password' : 'text'" formControlName="password">
<button type="button" mat-icon-button matSuffix (click)="togglePWVisibility($event)" [attr.aria-label]="'Hide password'"
[attr.aria-pressed]="hide">
<mat-icon>{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
</button>
</mat-form-field>
</div>
<div class="mb-3">
<button mat-flat-button color="primary" type="submit">Log In</button>
</div>
</form>
<div class="mb-3">
<mat-form-field>
<mat-label>Username</mat-label>
<input matInput formControlName="username">
</mat-form-field>
</div>
<div class="mb-3">
<mat-form-field>
<mat-label>Enter your password</mat-label>
<input matInput [type]="hide ? 'password' : 'text'" formControlName="password">
<button type="button" mat-icon-button matSuffix (click)="togglePWVisibility($event)"
[attr.aria-label]="'Hide password'" [attr.aria-pressed]="hide">
<mat-icon>{{hide ? 'visibility_off' : 'visibility'}}</mat-icon>
</button>
</mat-form-field>
</div>
<div class="mb-3">
<button type="submit" class="btn" mat-flat-button color="primary">
<span class="me-2">Anmeldung</span>
<span class="p-0 m-0" [class.spinner-border]="wait4waitRes" [class.spinner-border-sm]="wait4waitRes" aria-hidden="true"></span>
</button>
</div>
</form>

View File

@@ -9,7 +9,7 @@ import { Router } from '@angular/router';
import { ReactiveFormsModule } from '@angular/forms';
@Component({
selector: 'app-login',
selector: 'login',
standalone: true,
imports: [MatFormFieldModule, MatInputModule, MatButtonModule, MatIconModule, ReactiveFormsModule],
templateUrl: './login.component.html',
@@ -18,6 +18,7 @@ import { ReactiveFormsModule } from '@angular/forms';
export class LoginComponent {
hide = true;
loginForm: FormGroup;
wait4waitRes: boolean = false;
constructor(private fb: FormBuilder, private authService: AuthService, private router: Router) {
this.loginForm = this.fb.group({
@@ -33,12 +34,14 @@ export class LoginComponent {
onSubmit() {
if (this.loginForm.valid) {
this.wait4waitRes = true;
this.authService.login(this.loginForm.value).subscribe({
next: () => {
this.router.navigate(['/envelope']);
this.wait4waitRes = false;
this.router.navigate(['/envelope']);
},
error: error => {
console.error('Login failed', error);
this.wait4waitRes = false;
}
});
}

View File

@@ -1,6 +1,40 @@
<mat-toolbar color="primary" class="toolbar">
<button mat-icon-button>
<mat-icon>menu</mat-icon>
</button>
<span>signFlow</span>
</mat-toolbar>
<header>
<nav class="navbar navbar-expand-lg bg-body-tertiary fs-5">
<div class="container-fluid">
<a class="navbar-brand fs-2 fw-bold" [routerLink]="['/']">signFlow</a>
<!-- Navbars -->
<div *ngIf="isLogedIn()" class="navbar-collapse collapse d-sm-inline-flex justify-content-center"
[ngClass]="{ show: isExpanded }">
<ul class=" navbar-nav flex-grow">
<li class="nav-item" [routerLinkActive]="['link-active']" [routerLinkActiveOptions]="{exact: true}">
<button class="btn nav-link d-inline-flex flex-column align-items-center justify-content-center mx-2" (click)="router.navigate(['/'])">
<mat-icon>mail</mat-icon>
<span class="fs-6">Umschläge</span>
</button>
<button class="btn nav-link d-inline-flex flex-column align-items-center justify-content-center mx-2" (click)="router.navigate(['/envelope-creation'])">
<mat-icon>forward_to_inbox</mat-icon>
<span class="fs-6">Neuer Umschlag</span>
</button>
</li>
</ul>
</div>
<!-- Right menu -->
<div class="navbar-collapse justify-content-end me-5">
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target=".navbar-collapse"
aria-label="Toggle navigation" [attr.aria-expanded]="isExpanded" (click)="toggle()">
<span class="navbar-toggler-icon"></span>
</button>
<button class="fs-5 btn d-flex align-items-center ms-2 me-0 pe-0" type="button" (click)="logInOut()">
@if(isLogedIn()){
<mat-icon>logout</mat-icon>
<span class="fs-6 ms-1">Abmelden</span>
}
@else {
<mat-icon>login</mat-icon>
<span class="fs-6 ms-1">Anmelden</span>
}
</button>
</div>
</div>
</nav>
</header>

View File

@@ -1,23 +1,55 @@
import { Component } from '@angular/core';
import { MatToolbarModule } from '@angular/material/toolbar';
import { Component, QueryList, ViewChildren } from '@angular/core';
import { Router, RouterModule } from '@angular/router';
import { CommonModule } from '@angular/common';
import { MatBadgeModule } from '@angular/material/badge';
import { MatSlideToggleModule } from '@angular/material/slide-toggle';
import { FormsModule } from '@angular/forms';
import { MatTooltip, MatTooltipModule } from '@angular/material/tooltip';
import { MatButtonModule } from '@angular/material/button';
import { MatIconModule } from '@angular/material/icon';
import { MatSidenavModule } from '@angular/material/sidenav';
import { MatListModule } from '@angular/material/list';
import { AuthService } from '../../services/auth.service'
import { Observable } from 'rxjs';
@Component({
selector: 'app-navbar',
standalone: true,
imports: [
MatToolbarModule,
MatButtonModule,
MatIconModule,
MatSidenavModule,
MatListModule
],
imports: [RouterModule, CommonModule, MatIconModule, MatBadgeModule, MatSlideToggleModule, FormsModule, MatButtonModule, MatTooltipModule],
selector: 'app-navbar',
templateUrl: './navbar.component.html',
styleUrl: './navbar.component.scss'
styleUrls: ['./navbar.component.scss']
})
export class NavbarComponent {
isLogedIn(): boolean {
return this.authService.IsAuthenticated;
}
}
async logInOut(): Promise<void> {
if (this.isLogedIn())
return this.authService.logoutAsync().then(() => {
this.router.navigate(['/login']);
})
else
this.router.navigate(['/login']);
}
isExpanded = false;
isChecked = true;
constructor(public router: Router, public authService: AuthService) {
}
get isDarkTheme(): boolean {
return false;
}
collapse() {
this.isExpanded = false;
}
toggle() {
this.isExpanded = !this.isExpanded;
}
@ViewChildren(MatTooltip) tooltips: QueryList<MatTooltip> | undefined;
}

View File

@@ -0,0 +1,16 @@
<form class="example-form">
<mat-form-field class="example-full-width">
<mat-label>Email</mat-label>
<input type="text" aria-label="Email" matInput [formControl]="control" [matAutocomplete]="auto">
@if (text) {
<button matSuffix mat-icon-button aria-label="Clear" (click)="text=''">
<mat-icon>close</mat-icon>
</button>
}
<mat-autocomplete autoActiveFirstOption #auto="matAutocomplete">
@for (option of filteredOptions | async; track option) {
<mat-option [value]="option">{{option}}</mat-option>
}
</mat-autocomplete>
</mat-form-field>
</form>

View File

@@ -0,0 +1,7 @@
.mat-stepper-vertical {
margin-top: 8px;
}
.mat-mdc-form-field {
margin-top: 16px;
}

View File

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

View File

@@ -0,0 +1,66 @@
import { Component, Input, OnChanges, OnInit, SimpleChanges } from '@angular/core';
import { ReactiveFormsModule, FormControl } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { Observable, map, startWith } from 'rxjs';
import { AsyncPipe } from '@angular/common';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { FormsModule } from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
@Component({
selector: 'receiver-input',
standalone: true,
imports: [
MatInputModule,
MatAutocompleteModule,
ReactiveFormsModule,
AsyncPipe,
MatFormFieldModule, MatInputModule, FormsModule, MatButtonModule, MatIconModule
],
templateUrl: './receiver-input.component.html',
styleUrl: './receiver-input.component.scss'
})
export class ReceiverInputComponent implements OnInit, OnChanges {
ngOnInit(): void {
this.setupFiltering();
}
ngOnChanges(changes: SimpleChanges): void {
if (changes['options']) {
this.setupFiltering();
}
}
private setupFiltering(): void {
this.filteredOptions = this.control.valueChanges.pipe(
startWith(''),
map(value => this.filter(value || '', this.options)),
);
}
control = new FormControl('');
filteredOptions!: Observable<string[]>;
@Input() options: string[] = [];
@Input() filter: (value: string, options: string[]) => string[] = value => {
const filterValue = value.toLowerCase();
return this.options.filter(option => option.toLowerCase().includes(filterValue));
}
public get text(): string {
return this.control.value || '';
}
public set text(value: string) {
this.control.setValue(value)
}
public get lenght(): number {
return this.text.length;
}
}

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">
<receiver-input [options]="receiver_mails" [filter]="receiver_filter"></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

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

View File

@@ -0,0 +1,82 @@
import { Component, OnInit, QueryList, ViewChild, ViewChildren } from '@angular/core';
import { FormsModule, ReactiveFormsModule, FormControl } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { MatTableModule } from '@angular/material/table';
import { AsyncPipe } from '@angular/common';
import { MatAutocompleteModule } from '@angular/material/autocomplete';
import { MatFormFieldModule } from '@angular/material/form-field';
import { ReceiverService } from '../../services/receiver.service'
import { ReceiverInputComponent } from '../receiver-input/receiver-input.component';
import { MatIconModule } from '@angular/material/icon';
import { MatButtonModule } from '@angular/material/button';
import { ClearableInputComponent } from '../clearable-input/clearable-input.component'
import { v4 as uuidv4 } from 'uuid';
@Component({
selector: 'receiver-table',
standalone: true,
imports: [
MatTableModule,
FormsModule,
MatFormFieldModule,
MatInputModule,
MatAutocompleteModule,
ReactiveFormsModule,
AsyncPipe,
ReceiverInputComponent,
MatFormFieldModule, MatInputModule, FormsModule, MatButtonModule, MatIconModule, ClearableInputComponent
],
templateUrl: './receiver-table.component.html',
styleUrl: './receiver-table.component.scss'
})
export class ReceiverTableComponent implements OnInit {
constructor(private receiverService: ReceiverService) { }
async ngOnInit() {
this.receiver_mails = await this.receiverService.getReceiverAsync().then((receivers: any[]) => receivers.map(r => r.emailAddress));
}
receiver_filter: (value: string, options: string[]) => string[] = (value, options) => {
const filterValue = value.toLowerCase();
// if added into last row
if (value.length > 0 && (this.receiverInputs.at(-1)?.lenght ?? 0) > 0) {
this.receiverData.at(-1)!.accessCode = generateAccessCode();
this.receiverData.push({ email: "", name: "", accessCode: "" });
this.update();
}
else if (value.length == 0) {
for (var i = 0; i < this.receiverInputs.length - 1; i++) {
if (this.receiverInputs[i].lenght === 0) {
this.receiverData.splice(i, 1);
this.update();
}
}
}
return options.filter(option => option.toLowerCase().includes(filterValue));
}
receiver_mails: string[] = [];
@ViewChildren(ReceiverInputComponent) receiverInputsQueryList!: QueryList<ReceiverInputComponent>;
get receiverInputs(): ReceiverInputComponent[] {
return this.receiverInputsQueryList?.toArray() ?? [];
}
receiverData: { email: string; name: string; accessCode: string }[] = [
{ email: "", name: "", accessCode: "" }
];
displayedColumns: string[] = ['email', 'name', 'accessCode'];
public update() {
this.receiverData = [...this.receiverData];
}
}
function generateAccessCode(): string {
const uuid = uuidv4();
return uuid.replace(/-/g, '').substring(1, 7).toUpperCase();
}

View File

@@ -0,0 +1,25 @@
enum Status {
Invalid = 0,
EnvelopeCreated = 1001,
EnvelopeSaved = 1002,
EnvelopeQueued = 1003,
EnvelopeSent = 1004,
EnvelopePartlySigned = 1005,
EnvelopeCompletelySigned = 1006,
EnvelopeReportCreated = 1007,
EnvelopeArchived = 1008,
EnvelopeDeleted = 1009,
AccessCodeRequested = 2001,
AccessCodeCorrect = 2002,
AccessCodeIncorrect = 2003,
DocumentOpened = 2004,
DocumentSigned = 2005,
SignatureConfirmed = 2006,
MessageInvitationSent = 3001,
MessageAccessCodeSent = 3002,
MessageConfirmationSent = 3003,
MessageDeletionSent = 3004,
MessageCompletionSent = 3005
}
export { Status }

View File

@@ -3,15 +3,15 @@ import { inject } from '@angular/core';
import { CanActivateFn, Router } from '@angular/router';
import { AuthService } from '../services/auth.service';
import { map } from 'rxjs/operators';
import { Observable } from 'rxjs';
export const authGuard: CanActivateFn = (route, state) => {
const authService = inject(AuthService);
const router = inject(Router);
return authService.isAuthenticated().pipe(
map(isAuthenticated => {
if (!isAuthenticated) {
router.navigate(['/']);
router.navigate(['/login']);
}
return isAuthenticated;
})

View File

@@ -0,0 +1,17 @@
import { TestBed } from '@angular/core/testing';
import { HttpInterceptorFn } from '@angular/common/http';
import { httpInterceptor } from './http.interceptor';
describe('httpInterceptor', () => {
const interceptor: HttpInterceptorFn = (req, next) =>
TestBed.runInInjectionContext(() => httpInterceptor(req, next));
beforeEach(() => {
TestBed.configureTestingModule({});
});
it('should be created', () => {
expect(interceptor).toBeTruthy();
});
});

View File

@@ -0,0 +1,21 @@
import { Injectable } from '@angular/core';
import { HttpEvent, HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http';
import { Observable } from 'rxjs';
@Injectable()
export class HttpRequestInterceptor implements HttpInterceptor {
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const secureReq = req.clone({
withCredentials: true,
setHeaders: {
'X-Insecure-Request': 'true',
'Content-Type': 'application/json',
...req.headers.keys().reduce((headers, key) => {
headers[key] = req.headers.get(key) || '';
return headers;
}, {} as { [name: string]: string })
}
});
return next.handle(secureReq);
}
}

View File

@@ -1,6 +0,0 @@
export interface EnvelopeReceiver {
name: string | null
privateMessage: string | null
addedWhen: Date
changedWhen: Date | null
}

View File

@@ -0,0 +1,56 @@
<mat-stepper orientation="vertical" [linear]="isLinear" #stepper>
<mat-step>
<form>
<ng-template matStepLabel>Titel & Vertragstyp</ng-template>
<mat-form-field>
<mat-label>Titel</mat-label>
<input matInput placeholder="Arbeitsvertrag" [formControl]="titelControl" required>
</mat-form-field>
<mat-form-field class="ms-5">
<mat-label>Vertragstyp</mat-label>
<mat-select [formControl]="typeControl" required>
@for (type of types; track type) {
<mat-option [value]="type.value">{{type.viewValue}}</mat-option>
}
</mat-select>
</mat-form-field>
<div>
<button mat-button matStepperNext>
Next
<mat-icon>arrow_forward_ios</mat-icon>
</button>
</div>
</form>
</mat-step>
<mat-step>
<form>
<ng-template matStepLabel>Empfänger</ng-template>
<receiver-table></receiver-table>
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button matStepperNext>
Next
<mat-icon>arrow_forward_ios</mat-icon>
</button>
</div>
</form>
</mat-step>
<mat-step>
<form>
<ng-template matStepLabel>Neues Dokument</ng-template>
<input type="file" class="file-input" (change)="onFileSelected($event)" #fileUpload>
<div class="file-upload">
{{fileName || "Noch keine Datei hochgeladen."}}
<button mat-mini-fab color="primary" class="upload-btn" (click)="fileUpload.click()">
<mat-icon>attach_file</mat-icon>
</button>
</div>
</form>
<div>
<button mat-button matStepperPrevious>Back</button>
<button mat-button (click)="stepper.reset()">Reset</button>
</div>
</mat-step>
</mat-stepper>

View File

@@ -0,0 +1,11 @@
.mat-stepper-vertical {
margin-top: 8px;
}
.mat-mdc-form-field {
margin-top: 16px;
}
.file-input {
display: none;
}

View File

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

View File

@@ -0,0 +1,53 @@
import { Component, Input, inject } from '@angular/core';
import { FormBuilder, Validators, FormsModule, ReactiveFormsModule, FormControl } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatStepperModule } from '@angular/material/stepper';
import { MatButtonModule } from '@angular/material/button';
import { MatSelectModule } from '@angular/material/select';
import { ReceiverTableComponent } from "../../components/receiver-table/receiver-table.component";
import { MatIconModule } from '@angular/material/icon';
@Component({
selector: 'app-envelope-creation',
standalone: true,
imports: [
MatButtonModule,
MatStepperModule,
FormsModule,
ReactiveFormsModule,
MatFormFieldModule,
MatInputModule,
MatSelectModule,
ReceiverTableComponent,
MatIconModule
],
templateUrl: './envelope-creation.component.html',
styleUrl: './envelope-creation.component.scss'
})
export class EnvelopeCreationComponent {
@Input() isLinear = false;
titelControl = new FormControl('', [Validators.required]);
types: any[] = [
{ value: 0, viewValue: 'Mietvertrag' },
{ value: 1, viewValue: 'Kaufvertrag' }
];
typeControl = new FormControl('Mietvertrag', [Validators.required]);
fileName: string = ''
onFileSelected(event: any) {
const file: File = event.target.files[0];
if (file) {
this.fileName = file.name;
const formData = new FormData();
formData.append("thumbnail", file);
}
}
}

View File

@@ -0,0 +1,10 @@
<div id="table">
<mat-tab-group>
<mat-tab label="Offene Umschläge">
<app-envelope-table [options]="{max_status: Status.EnvelopePartlySigned}"></app-envelope-table>
</mat-tab>
<mat-tab label="Abgeschlossene Umschläge">
<app-envelope-table [options]="{min_status: Status.EnvelopeCompletelySigned, ignore_status: [Status.EnvelopeDeleted]}"></app-envelope-table>
</mat-tab>
</mat-tab-group>
</div>

View File

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

View File

@@ -0,0 +1,25 @@
import { Component } from '@angular/core';
import { EnvelopeTableComponent } from "../../components/envelope-table/envelope-table.component";
import { MatTabsModule } from '@angular/material/tabs';
import { LocalizationService } from '../../services/localization.service';
import { Status } from '../../enums/envelope-const'
@Component({
selector: 'envelope',
standalone: true,
templateUrl: './envelope.component.html',
styleUrl: './envelope.component.scss',
imports: [EnvelopeTableComponent, MatTabsModule]
})
export class EnvelopeComponent {
readonly Status = Status;
private localizer: any = {};
constructor(private localizationService: LocalizationService) {
}
async ngOnInit() {
this.localizer = await this.localizationService.getLocalizer()
}
}

View File

@@ -1,7 +1,7 @@
<div class="main">
<div class="content">
<div class="left-side">
<app-login></app-login>
<login></login>
</div>
<div class="divider" role="separator" aria-label="Divider"></div>
<div class="right-side">

View File

@@ -1,5 +1,5 @@
import { Component } from '@angular/core';
import { LoginComponent } from "../login/login.component";
import { LoginComponent } from "../../components/login/login.component";
@Component({
selector: 'app-home',

View File

@@ -1,6 +1,6 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';
import { Observable, firstValueFrom, tap } from 'rxjs';
import { API_URL } from '../tokens/index';
@Injectable({
@@ -15,14 +15,35 @@ export class AuthService {
}
login(credentials: { username: string; password: string }): Observable<any> {
return this.http.post(`${this.url}/login`, credentials);
return this.http.post(`${this.url}/login`, credentials).pipe(
tap({
next: res => this.#IsAuthenticated = true,
error: () => this.#IsAuthenticated = false
})
)
}
logout(): Observable<any> {
return this.http.post(`${this.url}/logout`, {});
return this.http.post(`${this.url}/logout`, {}).pipe(
tap({
next: res => this.#IsAuthenticated = false,
error: () => this.#IsAuthenticated = true
})
);
}
async logoutAsync(): Promise<void> {
return await firstValueFrom(this.logout());
}
isAuthenticated(): Observable<boolean> {
return this.http.get<boolean>(`${this.url}/check`);
return this.http.get<boolean>(`${this.url}/check`).pipe(
tap(isAuthenticated => this.#IsAuthenticated = isAuthenticated)
);
}
#IsAuthenticated = false;
get IsAuthenticated(): boolean {
return this.#IsAuthenticated;
}
}

View File

@@ -1,24 +1,34 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient, HttpHeaders } from '@angular/common/http';
import { Observable, catchError } from 'rxjs';
import { HttpClient, HttpParams } from '@angular/common/http';
import { Observable, firstValueFrom } from 'rxjs';
import { API_URL } from '../tokens/index';
@Injectable({
providedIn: 'root'
})
export class EnvelopeReceiverService {
private url: string;
protected url: string;
constructor(private http: HttpClient) {
constructor(private http: HttpClient) {
const api_url = inject(API_URL);
this.url = `${api_url}/envelopereceiver`;
}
getEnvelopeReceiver(): Observable<any> {
const headers = new HttpHeaders({
'Content-Type': 'application/json',
});
getEnvelopeReceiver(options?: { min_status?: number; max_status?: number; ignore_status?: number[] }): Observable<any> {
let params = new HttpParams();
if (options) {
if (options.min_status)
params = params.set('min_status', options.min_status.toString());
if (options.max_status)
params = params.set('max_status', options.max_status.toString());
if (options.ignore_status)
params = params.set('ignore_status', options.ignore_status.join(','));
}
return this.http.get<any>(this.url, { params });
}
return this.http.get<any>(this.url, { withCredentials: true , headers });
getEnvelopeReceiverAsync(options?: { min_status?: number; max_status?: number; ignore_status?: number[] }): Promise<any> {
return firstValueFrom(this.getEnvelopeReceiver(options));
}
}

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { LocalizationService } from './localization.service';
describe('LocalizationService', () => {
let service: LocalizationService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(LocalizationService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@@ -0,0 +1,21 @@
import { Injectable, inject } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, firstValueFrom } from 'rxjs';
import { API_URL } from '../tokens/index';
@Injectable({
providedIn: 'root'
})
export class LocalizationService {
private url: string;
constructor(private http: HttpClient) {
const api_url = inject(API_URL);
this.url = `${api_url}/localization`;
}
getLocalizer(): Promise<any> {
return firstValueFrom(this.http.get<any>(this.url));
}
}

View File

@@ -0,0 +1,16 @@
import { TestBed } from '@angular/core/testing';
import { ReceiverService } from './receiver.service';
describe('ReceiverService', () => {
let service: ReceiverService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(ReceiverService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
});

View File

@@ -0,0 +1,58 @@
import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable, inject } from '@angular/core';
import { API_URL } from '../tokens';
import { Observable, firstValueFrom } from 'rxjs';
@Injectable({
providedIn: 'root'
})
export class ReceiverService {
protected url: string;
constructor(private http: HttpClient) {
const api_url = inject(API_URL);
this.url = `${api_url}/receiver`;
}
public getReceiver(options?: { emailAdress?: string; signature?: string; }): Observable<any> {
let params = new HttpParams();
if (options) {
if (options.emailAdress)
params = params.set('emailAdress', options?.emailAdress);
if (options.signature)
params = params.set('signature', options?.signature);
}
return this.http.get<any>(this.url, { params });
}
public async getReceiverAsync(options?: { emailAdress?: string; signature?: string; }): Promise<any> {
return await firstValueFrom(this.getReceiver(options));
}
public createReceiver(emailAddress: string): Observable<any> {
return this.http.post<any>(this.url, { emailAddress: emailAddress });
}
public async createReceiverAsync(emailAddress: string): Promise<any> {
return await firstValueFrom(this.createReceiver(emailAddress));
}
public deleteReceiver(options: { id: number, emailAdress?: string; signature?: string; }): Observable<any> {
let params = new HttpParams();
if (options.emailAdress)
params = params.set('emailAdress', options?.emailAdress);
if (options.signature)
params = params.set('signature', options?.signature);
if (options.id)
params = params.set('id', options?.id.toString());
return this.http.get<any>(this.url, { params });
}
public async deleteReceiverAsync(options: { id: number, emailAdress?: string; signature?: string; }): Promise<any> {
return await firstValueFrom(this.deleteReceiver(options));
}
}

View File

@@ -0,0 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" width="3em" height="2.5em" viewBox="0 0 24 24" style="stroke: #a9a8ad;">
<path opacity="0.5" d="M15.9998 2L14.9998 2C12.1714 2 10.7576 2.00023 9.87891 2.87891C9.00023 3.75759 9.00023 5.1718 9.00023 8.00023L9.00023 16.0002C9.00023 18.8287 9.00023 20.2429 9.87891 21.1215C10.7574 22 12.1706 22 14.9976 22L14.9998 22L15.9998 22C18.8282 22 20.2424 22 21.1211 21.1213C21.9998 20.2426 21.9998 18.8284 21.9998 16L21.9998 8L21.9998 7.99998C21.9998 5.17157 21.9998 3.75736 21.1211 2.87868C20.2424 2 18.8282 2 15.9998 2Z" fill="#1C274C"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.25098 11.999C1.25098 11.5848 1.58676 11.249 2.00098 11.249L13.9735 11.249L12.0129 9.56845C11.6984 9.29889 11.662 8.82541 11.9315 8.51092C12.2011 8.19642 12.6746 8.16 12.9891 8.42957L16.4891 11.4296C16.6553 11.5721 16.751 11.7801 16.751 11.999C16.751 12.218 16.6553 12.426 16.4891 12.5685L12.9891 15.5685C12.6746 15.838 12.2011 15.8016 11.9315 15.4871C11.662 15.1726 11.6984 14.6991 12.0129 14.4296L13.9735 12.749L2.00098 12.749C1.58676 12.749 1.25098 12.4132 1.25098 11.999Z" fill="#1C274C"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 264 KiB

View File

@@ -64,6 +64,7 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
{
IsPersistent = true,
AllowRefresh = true,
ExpiresUtc = DateTime.Now.AddMinutes(180)
};
// Sign in
@@ -72,8 +73,6 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
new ClaimsPrincipal(claimsIdentity),
authProperties);
_dirSearchService.SetSearchRootCache(user.Username, login.Password);
return Ok();
}
catch(Exception ex)

View File

@@ -17,10 +17,10 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
_logger = logger;
_erService = envelopeReceiverService;
}
[Authorize]
[HttpGet]
public async Task<IActionResult> GetEnvelopeReceiver()
public async Task<IActionResult> GetEnvelopeReceiver([FromQuery] int? min_status = null, [FromQuery] int? max_status = null, [FromQuery] int[]? ignore_status = null)
{
try
{
@@ -33,7 +33,9 @@ namespace EnvelopeGenerator.GeneratorAPI.Controllers
return StatusCode(StatusCodes.Status500InternalServerError);
}
return await _erService.ReadByUsernameAsync(username).ThenAsync(
ignore_status ??= Array.Empty<int>();
return await _erService.ReadByUsernameAsync(username: username, min_status: min_status, max_status: max_status, ignore_statuses: ignore_status).ThenAsync(
Success: Ok,
Fail: IActionResult (msg, ntc) =>
{

View File

@@ -0,0 +1,91 @@
using DigitalData.Core.API;
using EnvelopeGenerator.Application.Resources;
using EnvelopeGenerator.Common;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Caching.Memory;
using Microsoft.Extensions.Localization;
namespace EnvelopeGenerator.GeneratorAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class LocalizationController : ControllerBase
{
private static readonly Guid L_KEY = Guid.NewGuid();
private readonly ILogger<LocalizationController> _logger;
private readonly IStringLocalizer<Model> _mLocalizer;
private readonly IStringLocalizer<Resource> _localizer;
private readonly IMemoryCache _cache;
public LocalizationController(
ILogger<LocalizationController> logger,
IStringLocalizer<Resource> localizer,
IMemoryCache memoryCache,
IStringLocalizer<Model> _modelLocalizer)
{
_logger = logger;
_localizer = localizer;
_cache = memoryCache;
_mLocalizer = _modelLocalizer;
}
[HttpGet]
public IActionResult GetAll() => Ok(_cache.GetOrCreate(Language ?? string.Empty + L_KEY, _ => _mLocalizer.ToDictionary()));
[HttpGet("lang")]
public IActionResult GetLanguage() => Language is null ? NotFound() : Ok(Language);
[HttpPost("lang")]
public IActionResult SetLanguage([FromQuery] string language)
{
if (string.IsNullOrEmpty(language))
return BadRequest();
Language = language;
return Ok();
}
[HttpDelete("lang")]
public IActionResult DeleteLanguage()
{
Language = null;
return Ok();
}
private string? Language
{
get
{
var cookieValue = Request.Cookies[CookieRequestCultureProvider.DefaultCookieName];
if (string.IsNullOrEmpty(cookieValue))
return null;
var culture = CookieRequestCultureProvider.ParseCookieValue(cookieValue)?.Cultures[0];
return culture?.Value ?? null;
}
set
{
if (value is null)
Response.Cookies.Delete(CookieRequestCultureProvider.DefaultCookieName);
else
{
var cookieOptions = new CookieOptions()
{
Expires = DateTimeOffset.UtcNow.AddYears(1),
Secure = false,
SameSite = SameSiteMode.Strict,
HttpOnly = true
};
Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(value)),
cookieOptions);
}
}
}
}
}

View File

@@ -0,0 +1,91 @@
using DigitalData.Core.API;
using DigitalData.Core.DTO;
using EnvelopeGenerator.Application.Contracts;
using EnvelopeGenerator.Application.DTOs.Receiver;
using EnvelopeGenerator.Domain.Entities;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
namespace EnvelopeGenerator.GeneratorAPI.Controllers
{
[Route("api/[controller]")]
[ApiController]
[Authorize]
public class ReceiverController : CRUDControllerBaseWithErrorHandling<IReceiverService, ReceiverCreateDto, ReceiverReadDto, ReceiverUpdateDto, Receiver, int>
{
public ReceiverController(ILogger<ReceiverController> logger, IReceiverService service) : base(logger, service)
{
}
[HttpGet]
public async Task<IActionResult> Get([FromQuery] string? emailAddress = null, [FromQuery] string? signature = null)
{
if (emailAddress is null && signature is null)
return await base.GetAll();
try
{
return await _service.ReadByAsync(emailAddress: emailAddress, signature: signature).ThenAsync(
Success: Ok,
Fail: IActionResult (msg, ntc) =>
{
_logger.LogNotice(ntc);
return StatusCode(StatusCodes.Status500InternalServerError);
});
}
catch(Exception ex)
{
_logger.LogError(ex, "{Message}", ex.Message);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
[HttpPost]
public async override Task<IActionResult> Create(ReceiverCreateDto createDto)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
return await base.Create(createDto);
}
[HttpDelete]
public async Task<IActionResult> Delete([FromQuery] int? id = null, [FromQuery]string? emailAddress = null, [FromQuery] string? signature = null)
{
if(id is int id_int)
return await base.Delete(id_int);
try
{
if (emailAddress is not null || signature is not null)
return await _service.DeleteByAsync(emailAddress: emailAddress, signature: signature).ThenAsync(
Success: Ok,
Fail: IActionResult (msg, ntc) =>
{
_logger.LogNotice(ntc);
return StatusCode(StatusCodes.Status500InternalServerError);
});
}
catch(Exception ex)
{
_logger.LogError(ex, "{Message}", ex.Message);
return StatusCode(500);
}
return BadRequest();
}
#region REMOVED ENDPOINTS
[NonAction]
public override Task<IActionResult> GetAll() => base.GetAll();
[NonAction]
public override Task<IActionResult> Delete([FromRoute] int id) => base.Delete(id);
[NonAction]
public override Task<IActionResult> Update(ReceiverUpdateDto updateDto) => base.Update(updateDto);
#endregion
}
}

View File

@@ -7,11 +7,8 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="DigitalData.Core.Abstractions" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.API" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.Application" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.DTO" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.Infrastructure" Version="1.0.0" />
<PackageReference Include="DigitalData.Core.Abstractions" Version="1.0.1.1" />
<PackageReference Include="DigitalData.Core.API" Version="1.0.2.1" />
<PackageReference Include="Microsoft.AspNetCore.OpenApi" Version="7.0.15" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.5.0" />
<PackageReference Include="System.DirectoryServices" Version="7.0.1" />
@@ -25,16 +22,11 @@
<ItemGroup>
<ProjectReference Include="..\EnvelopeGenerator.Application\EnvelopeGenerator.Application.csproj" />
<ProjectReference Include="..\EnvelopeGenerator.Common\EnvelopeGenerator.Common.vbproj" />
<ProjectReference Include="..\EnvelopeGenerator.Domain\EnvelopeGenerator.Domain.csproj" />
<ProjectReference Include="..\EnvelopeGenerator.Infrastructure\EnvelopeGenerator.Infrastructure.csproj" />
</ItemGroup>
<ItemGroup>
<Reference Include="DigitalData.UserManager.Application">
<HintPath>..\..\WebUserManager\DigitalData.UserManager.Application\bin\Debug\net7.0\DigitalData.UserManager.Application.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<None Update="ClientApp\envelope-generator-ui\dist\envelope-generator-ui\browser\chunk-35PBLQEP.js">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>

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