@yuuvis/app-invoice 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +63 -0
- package/extensions/README.md +3 -0
- package/extensions/index.d.ts +4 -0
- package/extensions/lib/actions/open-email/open-email.action.d.ts +18 -0
- package/extensions/lib/actions/retention/manage-retention/manage-retention.component.d.ts +26 -0
- package/extensions/lib/actions/retention/retention.action.d.ts +17 -0
- package/extensions/lib/assets/i18n/de.json +42 -0
- package/extensions/lib/assets/i18n/en.json +42 -0
- package/extensions/lib/components/apply-create-flavor/apply-create-flavor.component.d.ts +12 -0
- package/extensions/lib/components/apply-flavor/apply-flavor.component.d.ts +25 -0
- package/extensions/lib/components/form-extensions/ai-extracted-property/ai-extracted-property.component.d.ts +28 -0
- package/extensions/lib/invoice.flavor.create.d.ts +2 -0
- package/extensions/lib/invoice.schema.d.ts +6 -0
- package/extensions/lib/services/apply-flavor.service.d.ts +11 -0
- package/extensions/lib/services/extensions.service.d.ts +8 -0
- package/fesm2022/yuuvis-app-invoice-extensions.mjs +455 -0
- package/fesm2022/yuuvis-app-invoice-extensions.mjs.map +1 -0
- package/fesm2022/yuuvis-app-invoice.mjs +8 -0
- package/fesm2022/yuuvis-app-invoice.mjs.map +1 -0
- package/index.d.ts +1 -0
- package/lib/assets/i18n/de.json +1 -0
- package/lib/assets/i18n/en.json +1 -0
- package/lib/lib.routes.d.ts +2 -0
- package/package.json +31 -0
- package/yuv-manifest.json +5 -0
package/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# AppInvoice
|
|
2
|
+
|
|
3
|
+
This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 19.2.0.
|
|
4
|
+
|
|
5
|
+
## Code scaffolding
|
|
6
|
+
|
|
7
|
+
Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
ng generate component component-name
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
ng generate --help
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Building
|
|
20
|
+
|
|
21
|
+
To build the library, run:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
ng build app-invoice
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
This command will compile your project, and the build artifacts will be placed in the `dist/` directory.
|
|
28
|
+
|
|
29
|
+
### Publishing the Library
|
|
30
|
+
|
|
31
|
+
Once the project is built, you can publish your library by following these steps:
|
|
32
|
+
|
|
33
|
+
1. Navigate to the `dist` directory:
|
|
34
|
+
```bash
|
|
35
|
+
cd dist/app-invoice
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
2. Run the `npm publish` command to publish your library to the npm registry:
|
|
39
|
+
```bash
|
|
40
|
+
npm publish
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Running unit tests
|
|
44
|
+
|
|
45
|
+
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
ng test
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Running end-to-end tests
|
|
52
|
+
|
|
53
|
+
For end-to-end (e2e) testing, run:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
ng e2e
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
|
|
60
|
+
|
|
61
|
+
## Additional Resources
|
|
62
|
+
|
|
63
|
+
For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export * from './lib/services/extensions.service';
|
|
2
|
+
export * from './lib/components/apply-flavor/apply-flavor.component';
|
|
3
|
+
export * from './lib/components/form-extensions/ai-extracted-property/ai-extracted-property.component';
|
|
4
|
+
export * from './lib/components/apply-create-flavor/apply-create-flavor.component';
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { DmsObject } from '@yuuvis/client-core';
|
|
2
|
+
import { AbstractContextAction, Action, ActionSupport, SelectionRange } from '@yuuvis/client-framework/actions';
|
|
3
|
+
import { Observable } from 'rxjs';
|
|
4
|
+
export declare class OpenEmailAction extends AbstractContextAction implements Action {
|
|
5
|
+
#private;
|
|
6
|
+
private translate;
|
|
7
|
+
private router;
|
|
8
|
+
id: string;
|
|
9
|
+
label: any;
|
|
10
|
+
description: any;
|
|
11
|
+
priority: number;
|
|
12
|
+
icon: string;
|
|
13
|
+
group: string;
|
|
14
|
+
range: SelectionRange;
|
|
15
|
+
supports: ActionSupport;
|
|
16
|
+
isExecutable(selection: DmsObject[]): Observable<boolean>;
|
|
17
|
+
run(selection: DmsObject[]): Observable<boolean>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { DmsObject, RetentionState } from '@yuuvis/client-core';
|
|
2
|
+
import { ActionContext } from '@yuuvis/client-framework/actions';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
interface RetentionGroupEntry {
|
|
5
|
+
object: DmsObject;
|
|
6
|
+
objectLabel: string;
|
|
7
|
+
state: RetentionState;
|
|
8
|
+
}
|
|
9
|
+
export declare class ManageRetentionComponent {
|
|
10
|
+
#private;
|
|
11
|
+
private translate;
|
|
12
|
+
actionContext: ActionContext;
|
|
13
|
+
retentionPeriod: import("@angular/core").InputSignal<number>;
|
|
14
|
+
objects: import("@angular/core").InputSignal<DmsObject[]>;
|
|
15
|
+
objectGroups: import("@angular/core").Signal<{
|
|
16
|
+
underRetention: RetentionGroupEntry[];
|
|
17
|
+
notUnderRetention: RetentionGroupEntry[];
|
|
18
|
+
}>;
|
|
19
|
+
busySettingRetention: import("@angular/core").WritableSignal<boolean>;
|
|
20
|
+
error?: string;
|
|
21
|
+
setRetention(): void;
|
|
22
|
+
cancel(): void;
|
|
23
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ManageRetentionComponent, never>;
|
|
24
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ManageRetentionComponent, "ymxi-manage-retention", never, { "retentionPeriod": { "alias": "retentionPeriod"; "required": false; "isSignal": true; }; "objects": { "alias": "objects"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
25
|
+
}
|
|
26
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { DmsObject } from '@yuuvis/client-core';
|
|
2
|
+
import { AbstractContextAction, Action, ActionSupport, SelectionRange } from '@yuuvis/client-framework/actions';
|
|
3
|
+
import { Observable } from 'rxjs';
|
|
4
|
+
export declare class InvoiceRetentionAction extends AbstractContextAction implements Action {
|
|
5
|
+
#private;
|
|
6
|
+
private translate;
|
|
7
|
+
id: string;
|
|
8
|
+
label: any;
|
|
9
|
+
description: any;
|
|
10
|
+
priority: number;
|
|
11
|
+
icon: string;
|
|
12
|
+
group: string;
|
|
13
|
+
range: SelectionRange;
|
|
14
|
+
supports: ActionSupport;
|
|
15
|
+
isExecutable(selection: DmsObject[]): Observable<boolean>;
|
|
16
|
+
run(selection: DmsObject[]): Observable<boolean>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"io.yuuvis.app.invoice.flavor.create.with-ai": "KI: Hochladen und erkennen",
|
|
3
|
+
"io.yuuvis.app.invoice.flavor.create.with-ai.description": "",
|
|
4
|
+
"io.yuuvis.app.invoice.flavor.declarationOfConformity": "Konformitätserklärung",
|
|
5
|
+
"io.yuuvis.app.invoice.flavor.declarationOfConformity.description": " Ein Dokument, das bescheinigt, dass ein Produkt die erforderlichen Standards und Vorschriften erfüllt.",
|
|
6
|
+
"io.yuuvis.app.invoice.flavor.invoice": "Rechnung",
|
|
7
|
+
"io.yuuvis.app.invoice.flavor.invoice.description": "Ein Dokument, das eine Transaktion detailliert beschreibt, einschließlich Waren, Dienstleistungen und fälliger Zahlungen.",
|
|
8
|
+
"io.yuuvis.app.invoice.flavor.offer": "Angebot",
|
|
9
|
+
"io.yuuvis.app.invoice.flavor.offer.description": "Ein Dokument, das Bedingungen für ein Produkt oder eine Dienstleistung vorschlägt.",
|
|
10
|
+
"io.yuuvis.app.invoice.flavor.recognize-by-ai": "Mit KI erkennen ",
|
|
11
|
+
"io.yuuvis.app.invoice.flavor.recognize-by-ai.description": "Erkennen des Dokumenttyps mithilfe von KI.",
|
|
12
|
+
"yuv.app.invoice.action.classify.description": "",
|
|
13
|
+
"yuv.app.invoice.action.classify.label": "KI: Erkennen",
|
|
14
|
+
"yuv.app.invoice.ai-classify.already-classified.button.classify-again": "Erneut erkennen",
|
|
15
|
+
"yuv.app.invoice.ai-classify.already-classified.button.extract": "Daten für Typ '{{flavor}}' extrahieren",
|
|
16
|
+
"yuv.app.invoice.ai-classify.already-classified.text": "Dieses Dokument wurde bereits verarbeitet. Was möchten Sie tun?",
|
|
17
|
+
"yuv.app.invoice.ai-classify.button.cancel": "Abbrechen",
|
|
18
|
+
"yuv.app.invoice.ai-classify.error": "Erkennung nicht verfügbar",
|
|
19
|
+
"yuv.app.invoice.ai-classify.headline": "KI: Erkennen",
|
|
20
|
+
"yuv.app.invoice.apply-flavor.button.apply": "Anwenden",
|
|
21
|
+
"yuv.app.invoice.apply-flavor.button.cancel": "Abbrechen",
|
|
22
|
+
"yuv.app.invoice.apply-flavor.button.extract": "Daten mit KI extrahieren",
|
|
23
|
+
"yuv.app.invoice.apply-flavor.button.extract.error": "KI-Extraktion aktuell nicht verfügbar",
|
|
24
|
+
"yuv.app.invoice.apply-flavor.headline": "Typ '{{name}}' hinzufügen",
|
|
25
|
+
"io.yuuvis.app.invoice.apply-flavor.button.apply": "Anwenden",
|
|
26
|
+
"io.yuuvis.app.invoice.apply-flavor.button.cancel": "Abbrechen",
|
|
27
|
+
"io.yuuvis.app.invoice.apply-flavor.headline": "Typ '{{name}}' hinzufügen",
|
|
28
|
+
"yuv.app.invoice.action.retention.action.cancel": "Abbrechen",
|
|
29
|
+
"yuv.app.invoice.action.retention.confirm.title": "Revisionssichere Archivierung",
|
|
30
|
+
"yuv.app.invoice.action.retention.description": "Aktiviert unveränderbare Langzeitarchivierung",
|
|
31
|
+
"yuv.app.invoice.action.retention.error.retention.set": "Der Archivierungsstatus konnte nicht gesetzt werden.",
|
|
32
|
+
"yuv.app.invoice.action.retention.label": "Revisionssichere Archivierung",
|
|
33
|
+
"yuv.app.invoice.action.retention.notUnderRetention.action.confirm": "Revisionssicher archivieren",
|
|
34
|
+
"yuv.app.invoice.action.retention.notUnderRetention.message": "Starten der gesetzlich vorgeschriebenen Aufbewahrungsfrist von {{years}} Jahren. Beachten Sie:",
|
|
35
|
+
"yuv.app.invoice.action.retention.notUnderRetention.message.bullet.1": "Der Inhalt des Dokuments kann während der Aufbewahrungsfrist nicht mehr verändert werden.",
|
|
36
|
+
"yuv.app.invoice.action.retention.notUnderRetention.message.bullet.2": "Das Dokument kann nicht gelöscht werden.",
|
|
37
|
+
"yuv.app.invoice.action.retention.notUnderRetention.message.bullet.3": "Die Aufbewahrungsfrist kann nicht verkürzt oder abgebrochen werden.",
|
|
38
|
+
"yuv.app.invoice.action.retention.notUnderRetention.message.bullet.4": "Das Starten der Aufbewahrung ist endgültig und kann nicht rückgängig gemacht werden.",
|
|
39
|
+
"yuv.app.invoice.action.retention.underRetention.message": "Die folgenden Dokumente sind bereits revisionssicher archiviert.",
|
|
40
|
+
"yuv.app.invoice.action.open-email.label": "Zugehörige E-Mail öffnen",
|
|
41
|
+
"yuv.app.invoice.action.open-email.description": "Öffne E-Mail-Objekt, das die aktuelle Rechnung enthält."
|
|
42
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"io.yuuvis.app.invoice.flavor.create.with-ai": "AI: Upload and identify",
|
|
3
|
+
"io.yuuvis.app.invoice.flavor.create.with-ai.description": "",
|
|
4
|
+
"io.yuuvis.app.invoice.flavor.declarationOfConformity": "Declaration of conformity",
|
|
5
|
+
"io.yuuvis.app.invoice.flavor.declarationOfConformity.description": "A document certifying that a product meets the required standards and regulations.",
|
|
6
|
+
"io.yuuvis.app.invoice.flavor.invoice": "Invoice",
|
|
7
|
+
"io.yuuvis.app.invoice.flavor.invoice.description": "A document that describes a transaction in detail, including goods, services, and payments due.",
|
|
8
|
+
"io.yuuvis.app.invoice.flavor.offer": "Offer",
|
|
9
|
+
"io.yuuvis.app.invoice.flavor.offer.description": "A document that proposes conditions for a product or service.",
|
|
10
|
+
"io.yuuvis.app.invoice.flavor.recognize-by-ai": "Identify using AI",
|
|
11
|
+
"io.yuuvis.app.invoice.flavor.recognize-by-ai.description": "Identify the document type using AI.",
|
|
12
|
+
"yuv.app.invoice.action.classify.description": "",
|
|
13
|
+
"yuv.app.invoice.action.classify.label": "AI: Identify",
|
|
14
|
+
"yuv.app.invoice.ai-classify.already-classified.button.classify-again": "Identify again",
|
|
15
|
+
"yuv.app.invoice.ai-classify.already-classified.button.extract": "Extract data for type '{{flavor}}'",
|
|
16
|
+
"yuv.app.invoice.ai-classify.already-classified.text": "This document has already been processed. What do you want to do?",
|
|
17
|
+
"yuv.app.invoice.ai-classify.button.cancel": "Cancel",
|
|
18
|
+
"yuv.app.invoice.ai-classify.error": "Identification not available",
|
|
19
|
+
"yuv.app.invoice.ai-classify.headline": "AI: Identify",
|
|
20
|
+
"yuv.app.invoice.apply-flavor.button.apply": "Apply",
|
|
21
|
+
"yuv.app.invoice.apply-flavor.button.cancel": "Cancel",
|
|
22
|
+
"yuv.app.invoice.apply-flavor.button.extract": "Extract data using AI",
|
|
23
|
+
"yuv.app.invoice.apply-flavor.button.extract.error": "AI extraction currently not available",
|
|
24
|
+
"yuv.app.invoice.apply-flavor.headline": "Add type '{{name}}'",
|
|
25
|
+
"io.yuuvis.app.invoice.apply-flavor.button.apply": "Apply",
|
|
26
|
+
"io.yuuvis.app.invoice.apply-flavor.button.cancel": "Cancel",
|
|
27
|
+
"io.yuuvis.app.invoice.apply-flavor.headline": "Add type '{{name}}'",
|
|
28
|
+
"yuv.app.invoice.action.retention.action.cancel": "Cancel",
|
|
29
|
+
"yuv.app.invoice.action.retention.confirm.title": "Audit-proof archiving",
|
|
30
|
+
"yuv.app.invoice.action.retention.description": "Activates unalterable long-term archiving",
|
|
31
|
+
"yuv.app.invoice.action.retention.error.retention.set": "Unable to set archiving status.",
|
|
32
|
+
"yuv.app.invoice.action.retention.label": "Audit-proof archiving",
|
|
33
|
+
"yuv.app.invoice.action.retention.notUnderRetention.action.confirm": "Archiving in an audit-proof manner",
|
|
34
|
+
"yuv.app.invoice.action.retention.notUnderRetention.message": "Start the retention period of {{years}} years, which is prescribed by law. Note:",
|
|
35
|
+
"yuv.app.invoice.action.retention.notUnderRetention.message.bullet.1": "The document’s content cannot be changed during the retention period.",
|
|
36
|
+
"yuv.app.invoice.action.retention.notUnderRetention.message.bullet.2": "Unable to delete the document.",
|
|
37
|
+
"yuv.app.invoice.action.retention.notUnderRetention.message.bullet.3": "Unable to shorten or cancel the retention period.",
|
|
38
|
+
"yuv.app.invoice.action.retention.notUnderRetention.message.bullet.4": "Once retention has started, it is final and cannot be reversed.",
|
|
39
|
+
"yuv.app.invoice.action.retention.underRetention.message": "The following documents are already archived in an audit-proof manner.",
|
|
40
|
+
"yuv.app.invoice.action.open-email.label": "Open associated email",
|
|
41
|
+
"yuv.app.invoice.action.open-email.description": "Open email object that contains the current invoice."
|
|
42
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Type } from '@angular/core';
|
|
2
|
+
import { AbstractApplyCreateFlavorComponent } from '@yuuvis/client-framework/object-flavor';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export declare class ApplyCreateFlavorComponent extends AbstractApplyCreateFlavorComponent {
|
|
5
|
+
#private;
|
|
6
|
+
sc?: {
|
|
7
|
+
cmp: Type<any>;
|
|
8
|
+
inputs: any;
|
|
9
|
+
};
|
|
10
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ApplyCreateFlavorComponent, never>;
|
|
11
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ApplyCreateFlavorComponent, "yin-apply-create-flavor", never, {}, {}, never, never, true, never>;
|
|
12
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { AbstractApplyObjectFlavorComponent } from '@yuuvis/client-framework/object-flavor';
|
|
2
|
+
import { FormStatusChangedEvent, IObjectFormElementExtension, ObjectFormComponent, ObjectFormOptions } from '@yuuvis/client-framework/object-form';
|
|
3
|
+
import * as i0 from "@angular/core";
|
|
4
|
+
export declare class ApplyFlavorComponent extends AbstractApplyObjectFlavorComponent {
|
|
5
|
+
#private;
|
|
6
|
+
private translate;
|
|
7
|
+
objectForm: import("@angular/core").Signal<ObjectFormComponent | undefined>;
|
|
8
|
+
flavorLabel: import("@angular/core").Signal<any>;
|
|
9
|
+
error: import("@angular/core").WritableSignal<boolean>;
|
|
10
|
+
applyDisabled: import("@angular/core").WritableSignal<boolean>;
|
|
11
|
+
supportsExtraction: import("@angular/core").WritableSignal<boolean>;
|
|
12
|
+
busyLoading: import("@angular/core").WritableSignal<boolean>;
|
|
13
|
+
busySaving: import("@angular/core").WritableSignal<boolean>;
|
|
14
|
+
busyExtracting: import("@angular/core").WritableSignal<boolean>;
|
|
15
|
+
formOptions: import("@angular/core").WritableSignal<ObjectFormOptions | null>;
|
|
16
|
+
extensions: import("@angular/core").WritableSignal<IObjectFormElementExtension[]>;
|
|
17
|
+
immediateExtract: any;
|
|
18
|
+
headline?: string;
|
|
19
|
+
extract(): void;
|
|
20
|
+
onFormStatusChanged(status: FormStatusChangedEvent): void;
|
|
21
|
+
applyFlavor(): void;
|
|
22
|
+
close(): void;
|
|
23
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ApplyFlavorComponent, never>;
|
|
24
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<ApplyFlavorComponent, "yin-apply-flavor", never, {}, {}, never, never, true, never>;
|
|
25
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { OnInit } from '@angular/core';
|
|
2
|
+
import { PredictionExtractResultItem } from '@yuuvis/client-core';
|
|
3
|
+
import { ObjectFormElementExtension } from '@yuuvis/client-framework/object-form';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
/**
|
|
6
|
+
* This object form field extension inserts AI-extracted values into an
|
|
7
|
+
* object-form. Once the AI service has extracted a value, this extension
|
|
8
|
+
* will change the form field to display the extracted value and show the
|
|
9
|
+
* value for the probability of the extraction right next to the field.
|
|
10
|
+
*
|
|
11
|
+
* If there are multiple extractions, the extension will insert the value
|
|
12
|
+
* with the highest probability and provide a picker for the other values.
|
|
13
|
+
*
|
|
14
|
+
* This way the user can easily accept the extracted value or choose a
|
|
15
|
+
* different one from the list of extracted values.
|
|
16
|
+
*/
|
|
17
|
+
export declare class AiExtractedPropertyComponent extends ObjectFormElementExtension implements OnInit {
|
|
18
|
+
#private;
|
|
19
|
+
predictionValues: PredictionExtractResultItem[];
|
|
20
|
+
currentValueProbability: import("@angular/core").WritableSignal<number | undefined>;
|
|
21
|
+
extractedData: import("@angular/core").Signal<Record<string, PredictionExtractResultItem[]> | null>;
|
|
22
|
+
extractedDataEffect: import("@angular/core").EffectRef;
|
|
23
|
+
selectOptionByIndex(idx: number): void;
|
|
24
|
+
selectOption(pr: PredictionExtractResultItem): void;
|
|
25
|
+
ngOnInit(): void;
|
|
26
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AiExtractedPropertyComponent, never>;
|
|
27
|
+
static ɵcmp: i0.ɵɵComponentDeclaration<AiExtractedPropertyComponent, "yin-ai-extracted-property", never, {}, {}, never, never, true, never>;
|
|
28
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { AppSchemaFlavor } from '@yuuvis/client-shell-core';
|
|
2
|
+
export declare const APP_ROLE = "YM_APP_INVOICE";
|
|
3
|
+
export declare const APP_PREFIX = "appSysteminvoice:";
|
|
4
|
+
export declare const APP_ID = "io.yuuvis.app.invoice";
|
|
5
|
+
export declare const RETENTION_PERIOD = 10;
|
|
6
|
+
export declare const APP_FLAVORS: AppSchemaFlavor[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Signal } from '@angular/core';
|
|
2
|
+
import { PredictionExtractResultItem } from '@yuuvis/client-core';
|
|
3
|
+
import { Observable } from 'rxjs';
|
|
4
|
+
import * as i0 from "@angular/core";
|
|
5
|
+
export declare class ApplyFlavorService {
|
|
6
|
+
#private;
|
|
7
|
+
extractedData: Signal<Record<string, PredictionExtractResultItem[]> | null>;
|
|
8
|
+
extract(schemaObjectTypeId: string, objectID: string): Observable<any>;
|
|
9
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<ApplyFlavorService, never>;
|
|
10
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<ApplyFlavorService>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ClientShellExtension } from '@yuuvis/client-shell-core';
|
|
2
|
+
import * as i0 from "@angular/core";
|
|
3
|
+
export declare class AppInvoiceExtension implements ClientShellExtension {
|
|
4
|
+
#private;
|
|
5
|
+
init(): Promise<any>;
|
|
6
|
+
static ɵfac: i0.ɵɵFactoryDeclaration<AppInvoiceExtension, never>;
|
|
7
|
+
static ɵprov: i0.ɵɵInjectableDeclaration<AppInvoiceExtension>;
|
|
8
|
+
}
|
|
@@ -0,0 +1,455 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, signal, Injectable, DestroyRef, ElementRef, effect, untracked, Component, viewChild, computed, input } from '@angular/core';
|
|
3
|
+
import { AbstractContextAction, SelectionRange, ActionsService } from '@yuuvis/client-framework/actions';
|
|
4
|
+
import { ShellService } from '@yuuvis/client-shell-core';
|
|
5
|
+
import { Router } from '@angular/router';
|
|
6
|
+
import { TranslateService } from '@ngx-translate/core';
|
|
7
|
+
import { APP_ID as APP_ID$1 } from '@yuuvis/app-drive';
|
|
8
|
+
import { of, tap, finalize } from 'rxjs';
|
|
9
|
+
import * as i4 from '@angular/material/dialog';
|
|
10
|
+
import { MatDialogModule, MAT_DIALOG_DATA, MatDialogRef, MatDialog } from '@angular/material/dialog';
|
|
11
|
+
import { marker } from '@colsen1991/ngx-translate-extract-marker';
|
|
12
|
+
import * as i3 from '@yuuvis/client-core';
|
|
13
|
+
import { PredictionService, SystemService, TranslateModule, TranslateService as TranslateService$1, Situation, SystemType, RetentionService, BaseObjectTypeField, LocaleDatePipe, DmsService } from '@yuuvis/client-core';
|
|
14
|
+
import * as i1$1 from '@angular/common';
|
|
15
|
+
import { CommonModule } from '@angular/common';
|
|
16
|
+
import { MatButtonModule } from '@angular/material/button';
|
|
17
|
+
import { BusyOverlayDirective, DialogComponent } from '@yuuvis/client-framework/common';
|
|
18
|
+
import { AbstractApplyObjectFlavorComponent, AbstractApplyCreateFlavorComponent } from '@yuuvis/client-framework/object-flavor';
|
|
19
|
+
import { ObjectFormElementExtension, ObjectFormComponent } from '@yuuvis/client-framework/object-form';
|
|
20
|
+
import { ObjectPreviewComponent } from '@yuuvis/client-framework/object-preview';
|
|
21
|
+
import * as i2$1 from '@yuuvis/client-framework/split-view';
|
|
22
|
+
import { YuvSplitViewModule } from '@yuuvis/client-framework/split-view';
|
|
23
|
+
import * as i2 from '@angular/material/icon';
|
|
24
|
+
import { MatIconModule } from '@angular/material/icon';
|
|
25
|
+
import * as i1 from '@angular/material/menu';
|
|
26
|
+
import { MatMenuModule } from '@angular/material/menu';
|
|
27
|
+
import { YmtButtonDirective } from '@yuuvis/material';
|
|
28
|
+
import * as i5 from '@angular/material/tooltip';
|
|
29
|
+
import { MatTooltipModule } from '@angular/material/tooltip';
|
|
30
|
+
import { finalize as finalize$1 } from 'rxjs/operators';
|
|
31
|
+
|
|
32
|
+
class OpenEmailAction extends AbstractContextAction {
|
|
33
|
+
translate = inject(TranslateService);
|
|
34
|
+
router = inject(Router);
|
|
35
|
+
#shell = inject(ShellService);
|
|
36
|
+
id = 'app.invoice.open-email';
|
|
37
|
+
label = this.translate.instant('yuv.app.invoice.action.open-email.label');
|
|
38
|
+
description = this.translate.instant('yuv.app.invoice.action.open-email.description');
|
|
39
|
+
priority = 3;
|
|
40
|
+
icon = 'mail';
|
|
41
|
+
group = 'common';
|
|
42
|
+
range = SelectionRange.SINGLE_SELECT;
|
|
43
|
+
supports = {};
|
|
44
|
+
#app = this.#shell.getApp(APP_ID$1);
|
|
45
|
+
isExecutable(selection) {
|
|
46
|
+
const o = selection[0];
|
|
47
|
+
return of(o &&
|
|
48
|
+
o.sots.includes('appSysteminvoice:invoice') &&
|
|
49
|
+
!!o.data['appClassifypro:emailReference']);
|
|
50
|
+
}
|
|
51
|
+
run(selection) {
|
|
52
|
+
const o = selection[0];
|
|
53
|
+
const emailReference = o.data['appClassifypro:emailReference'];
|
|
54
|
+
this.router.navigateByUrl(`/${this.#app ? this.#app.path : 'drive'}/object/${emailReference}`);
|
|
55
|
+
return of(true);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
class ApplyFlavorService {
|
|
60
|
+
#predict = inject(PredictionService);
|
|
61
|
+
#extractedDataSource = signal(null);
|
|
62
|
+
extractedData = this.#extractedDataSource.asReadonly();
|
|
63
|
+
extract(schemaObjectTypeId, objectID) {
|
|
64
|
+
return this.#predict
|
|
65
|
+
.extract(schemaObjectTypeId, [objectID])
|
|
66
|
+
.pipe(tap((res) => this.#extractedDataSource.set(res[objectID].properties)));
|
|
67
|
+
}
|
|
68
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ApplyFlavorService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
69
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ApplyFlavorService });
|
|
70
|
+
}
|
|
71
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ApplyFlavorService, decorators: [{
|
|
72
|
+
type: Injectable
|
|
73
|
+
}] });
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* This object form field extension inserts AI-extracted values into an
|
|
77
|
+
* object-form. Once the AI service has extracted a value, this extension
|
|
78
|
+
* will change the form field to display the extracted value and show the
|
|
79
|
+
* value for the probability of the extraction right next to the field.
|
|
80
|
+
*
|
|
81
|
+
* If there are multiple extractions, the extension will insert the value
|
|
82
|
+
* with the highest probability and provide a picker for the other values.
|
|
83
|
+
*
|
|
84
|
+
* This way the user can easily accept the extracted value or choose a
|
|
85
|
+
* different one from the list of extracted values.
|
|
86
|
+
*/
|
|
87
|
+
class AiExtractedPropertyComponent extends ObjectFormElementExtension {
|
|
88
|
+
#applyFlavorService = inject(ApplyFlavorService);
|
|
89
|
+
#destroyRef = inject(DestroyRef);
|
|
90
|
+
#system = inject(SystemService);
|
|
91
|
+
#elRef = inject(ElementRef);
|
|
92
|
+
predictionValues = [];
|
|
93
|
+
currentValueProbability = signal(undefined);
|
|
94
|
+
#currentValueProbabilityEffect = effect(() => {
|
|
95
|
+
const cp = this.currentValueProbability();
|
|
96
|
+
if (!cp)
|
|
97
|
+
return;
|
|
98
|
+
// set the probability color
|
|
99
|
+
const color = cp < 30 ? '--ymt-danger' : cp < 60 ? '--ymt-warning' : '--ymt-success';
|
|
100
|
+
this.#elRef.nativeElement.style.setProperty('--current-value-probability-color', `var(${color})`);
|
|
101
|
+
});
|
|
102
|
+
extractedData = this.#applyFlavorService.extractedData;
|
|
103
|
+
extractedDataEffect = effect(() => {
|
|
104
|
+
const extData = this.extractedData();
|
|
105
|
+
if (extData) {
|
|
106
|
+
untracked(() => {
|
|
107
|
+
const fcn = this.input().formControlName;
|
|
108
|
+
this.predictionValues = extData[fcn] || [];
|
|
109
|
+
this.#applyPredictionValues();
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
#internalFieldType;
|
|
114
|
+
#applyPredictionValues() {
|
|
115
|
+
// set the value of the form field to the extracted value with
|
|
116
|
+
// the highest probability
|
|
117
|
+
const pv = this.predictionValues;
|
|
118
|
+
if (pv.length) {
|
|
119
|
+
pv.sort((a, b) => b.probability - a.probability);
|
|
120
|
+
this.selectOption(pv[0]);
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
this.currentValueProbability.set(undefined);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// map extracted string to a proper format to be used
|
|
127
|
+
// within the form elements
|
|
128
|
+
#mapValueToType(value) {
|
|
129
|
+
if (this.#internalFieldType === 'datetime') {
|
|
130
|
+
// dates will always be returned as german formatted strings (24.12.2024)
|
|
131
|
+
// no matter what the locale of the processed document is. So we need to
|
|
132
|
+
// convert the string to a proper date object
|
|
133
|
+
const dateParts = value.split('.');
|
|
134
|
+
return dateParts.length === 3 ? new Date(+dateParts[2], +dateParts[1] - 1, +dateParts[0]) : value;
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
return value;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
selectOptionByIndex(idx) {
|
|
141
|
+
this.selectOption(this.predictionValues[idx]);
|
|
142
|
+
}
|
|
143
|
+
selectOption(pr) {
|
|
144
|
+
this.setValue(this.#mapValueToType(pr.value));
|
|
145
|
+
this.currentValueProbability.set(pr.probability);
|
|
146
|
+
}
|
|
147
|
+
ngOnInit() {
|
|
148
|
+
this.#internalFieldType = this.#system.getObjectTypeField(this.input().formControlName)?._internalType;
|
|
149
|
+
}
|
|
150
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AiExtractedPropertyComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
151
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: AiExtractedPropertyComponent, isStandalone: true, selector: "yin-ai-extracted-property", usesInheritance: true, ngImport: i0, template: "@if (predictionValues.length === 1) {\n <span class=\"probability\">\n <mat-icon class=\"ymt-icon--size-s\">robot_2</mat-icon>\n {{ currentValueProbability() }}%</span\n >\n} @else if (predictionValues.length > 1) {\n <button class=\"probability\" [matMenuTriggerFor]=\"menu\">\n <!-- (click)=\"openValueOptions(options, $event)\"> -->\n <mat-icon class=\"ymt-icon--size-s\">robot_2</mat-icon>\n {{ currentValueProbability() }}%\n <mat-icon class=\"ymt-icon--size-s\">arrow_drop_down</mat-icon>\n </button>\n\n <mat-menu #menu=\"matMenu\">\n @for (pv of predictionValues; track $index) {\n <button mat-menu-item (click)=\"selectOptionByIndex($index)\">{{ pv.value }}<span>{{ pv.probability }}%</span></button> \n }\n </mat-menu>\n} \n", styles: [":host{--current-value-probability-color: var(--ymt-success)}:host .probability{padding:2px;background-color:rgb(from var(--current-value-probability-color) r g b/.1);border:1px solid rgb(from var(--current-value-probability-color) r g b/.3);color:var(--current-value-probability-color);display:flex;border-radius:.25em;gap:var(--ymt-spacing-2xs);font:var(--ymt-font-body-subtle);align-items:center;line-height:1em;--icon-size: 14px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: MatMenuModule }, { kind: "component", type: i1.MatMenu, selector: "mat-menu", inputs: ["backdropClass", "aria-label", "aria-labelledby", "aria-describedby", "xPosition", "yPosition", "overlapTrigger", "hasBackdrop", "class", "classList"], outputs: ["closed", "close"], exportAs: ["matMenu"] }, { kind: "component", type: i1.MatMenuItem, selector: "[mat-menu-item]", inputs: ["role", "disabled", "disableRipple"], exportAs: ["matMenuItem"] }, { kind: "directive", type: i1.MatMenuTrigger, selector: "[mat-menu-trigger-for], [matMenuTriggerFor]", inputs: ["mat-menu-trigger-for", "matMenuTriggerFor", "matMenuTriggerData", "matMenuTriggerRestoreFocus"], outputs: ["menuOpened", "onMenuOpen", "menuClosed", "onMenuClose"], exportAs: ["matMenuTrigger"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
152
|
+
}
|
|
153
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AiExtractedPropertyComponent, decorators: [{
|
|
154
|
+
type: Component,
|
|
155
|
+
args: [{ selector: 'yin-ai-extracted-property', standalone: true, imports: [CommonModule, MatMenuModule, MatIconModule], template: "@if (predictionValues.length === 1) {\n <span class=\"probability\">\n <mat-icon class=\"ymt-icon--size-s\">robot_2</mat-icon>\n {{ currentValueProbability() }}%</span\n >\n} @else if (predictionValues.length > 1) {\n <button class=\"probability\" [matMenuTriggerFor]=\"menu\">\n <!-- (click)=\"openValueOptions(options, $event)\"> -->\n <mat-icon class=\"ymt-icon--size-s\">robot_2</mat-icon>\n {{ currentValueProbability() }}%\n <mat-icon class=\"ymt-icon--size-s\">arrow_drop_down</mat-icon>\n </button>\n\n <mat-menu #menu=\"matMenu\">\n @for (pv of predictionValues; track $index) {\n <button mat-menu-item (click)=\"selectOptionByIndex($index)\">{{ pv.value }}<span>{{ pv.probability }}%</span></button> \n }\n </mat-menu>\n} \n", styles: [":host{--current-value-probability-color: var(--ymt-success)}:host .probability{padding:2px;background-color:rgb(from var(--current-value-probability-color) r g b/.1);border:1px solid rgb(from var(--current-value-probability-color) r g b/.3);color:var(--current-value-probability-color);display:flex;border-radius:.25em;gap:var(--ymt-spacing-2xs);font:var(--ymt-font-body-subtle);align-items:center;line-height:1em;--icon-size: 14px}\n"] }]
|
|
156
|
+
}] });
|
|
157
|
+
|
|
158
|
+
const COMPONENTS = [
|
|
159
|
+
YuvSplitViewModule,
|
|
160
|
+
TranslateModule,
|
|
161
|
+
BusyOverlayDirective,
|
|
162
|
+
ObjectFormComponent,
|
|
163
|
+
ObjectPreviewComponent,
|
|
164
|
+
DialogComponent,
|
|
165
|
+
YmtButtonDirective
|
|
166
|
+
];
|
|
167
|
+
const MATERIAL = [MatButtonModule, MatDialogModule, MatTooltipModule];
|
|
168
|
+
class ApplyFlavorComponent extends AbstractApplyObjectFlavorComponent {
|
|
169
|
+
#system = inject(SystemService);
|
|
170
|
+
#shell = inject(ShellService);
|
|
171
|
+
#applyFlavorService = inject(ApplyFlavorService);
|
|
172
|
+
translate = inject(TranslateService$1);
|
|
173
|
+
objectForm = viewChild(ObjectFormComponent);
|
|
174
|
+
flavorLabel = computed(() => this.#shell.getFlavorLabel(this.flavor().id));
|
|
175
|
+
#flavorEffect = effect(() => {
|
|
176
|
+
const f = this.flavor();
|
|
177
|
+
untracked(() => {
|
|
178
|
+
if (f)
|
|
179
|
+
this.#loadForm(f);
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
#dmsObjectEffect = effect(() => {
|
|
183
|
+
const o = this.dmsObject();
|
|
184
|
+
untracked(() => {
|
|
185
|
+
this.supportsExtraction.set(!!o.content && o.content.mimeType === 'application/pdf');
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
error = signal(false);
|
|
189
|
+
applyDisabled = signal(true);
|
|
190
|
+
supportsExtraction = signal(true);
|
|
191
|
+
busyLoading = signal(false);
|
|
192
|
+
busySaving = signal(false);
|
|
193
|
+
busyExtracting = signal(false);
|
|
194
|
+
formOptions = signal(null);
|
|
195
|
+
extensions = signal([]);
|
|
196
|
+
immediateExtract = (this.data() && this.data().immediateExtract) || false;
|
|
197
|
+
headline = this.data() && this.data().headline;
|
|
198
|
+
#loadForm(f) {
|
|
199
|
+
this.busyLoading.set(true);
|
|
200
|
+
const sot = this.#system.getSecondaryObjectType(f.sot);
|
|
201
|
+
this.extensions.set((sot?.fields || []).map((field) => ({
|
|
202
|
+
property: field.id,
|
|
203
|
+
cmp: AiExtractedPropertyComponent
|
|
204
|
+
})));
|
|
205
|
+
this.#system
|
|
206
|
+
.getObjectTypeForm(f.sot, Situation.EDIT)
|
|
207
|
+
.pipe(finalize(() => this.busyLoading.set(false)))
|
|
208
|
+
.subscribe({
|
|
209
|
+
next: (form) => {
|
|
210
|
+
this.formOptions.set({
|
|
211
|
+
formModel: form,
|
|
212
|
+
data: {}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
extract() {
|
|
218
|
+
this.busyExtracting.set(true);
|
|
219
|
+
this.#applyFlavorService
|
|
220
|
+
.extract(this.flavor().sot, this.dmsObject().id)
|
|
221
|
+
.pipe(finalize(() => this.busyExtracting.set(false)))
|
|
222
|
+
.subscribe({
|
|
223
|
+
next: () => {
|
|
224
|
+
this.error.set(false);
|
|
225
|
+
},
|
|
226
|
+
error: () => {
|
|
227
|
+
this.error.set(true);
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
onFormStatusChanged(status) {
|
|
232
|
+
this.applyDisabled.set(status.invalid);
|
|
233
|
+
}
|
|
234
|
+
applyFlavor() {
|
|
235
|
+
const of = this.objectForm();
|
|
236
|
+
const data = of ? of.getFormData() : {};
|
|
237
|
+
this.busySaving.set(true);
|
|
238
|
+
this.#shell
|
|
239
|
+
.applyObjectFlavor(this.dmsObject(), this.flavor(), data)
|
|
240
|
+
.pipe(finalize(() => this.busySaving.set(false)))
|
|
241
|
+
.subscribe({
|
|
242
|
+
next: () => this.close()
|
|
243
|
+
// TODO: handle error
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
close() {
|
|
247
|
+
this.dialogRef.close();
|
|
248
|
+
}
|
|
249
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ApplyFlavorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
250
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ApplyFlavorComponent, isStandalone: true, selector: "yin-apply-flavor", providers: [ApplyFlavorService], viewQueries: [{ propertyName: "objectForm", first: true, predicate: ObjectFormComponent, descendants: true, isSignal: true }], usesInheritance: true, ngImport: i0, template: "<yuv-dialog [headertitel]=\"headline || ('yuv.app.invoice.apply-flavor.headline' | translate: { name: flavorLabel() })\">\n <main>\n <yuv-split-view [gutterSize]=\"1\">\n <ng-template yuvSplitArea [size]=\"60\">\n @if (dmsObject() && dmsObject().content) {\n <yuv-object-preview [objectId]=\"dmsObject().id\"></yuv-object-preview>\n }\n </ng-template>\n\n <ng-template yuvSplitArea [size]=\"40\">\n <div class=\"metadata\" [yuvBusyOverlay]=\"busyLoading()\">\n <div class=\"ai\">\n @if (supportsExtraction()) {\n @if (error()) {\n <mat-icon class=\"warning\" [matTooltip]=\"'yuv.app.invoice.apply-flavor.button.extract.error' | translate\">warning</mat-icon>\n }\n @if (busyExtracting()) {\n <div class=\"spinner\"></div>\n }\n <button ymtButton=\"secondary\" class=\"ai-extract\" [ngClass]=\"{ spinning: busyExtracting() }\" (click)=\"extract()\">\n <mat-icon>robot_2</mat-icon>\n {{ 'yuv.app.invoice.apply-flavor.button.extract' | translate }}\n </button>\n }\n </div>\n\n @let fo = formOptions();\n @if (fo) {\n <yuv-object-form\n [elementExtensions]=\"extensions()\"\n [inert]=\"busySaving() || busyExtracting()\"\n [formOptions]=\"fo\"\n (statusChanged)=\"onFormStatusChanged($event)\"\n ></yuv-object-form>\n }\n </div>\n </ng-template>\n </yuv-split-view>\n </main>\n\n <footer>\n <button ymtButton=\"secondary\" mat-dialog-close [disabled]=\"busySaving() || busyExtracting()\">\n {{ 'yuv.app.invoice.apply-flavor.button.cancel' | translate }}\n </button>\n <button\n ymtButton=\"primary\"\n mat-dialog-close\n cdkFocusInitial\n class=\"primary\"\n [ngClass]=\"{ spinning: busySaving() }\"\n [disabled]=\"applyDisabled() || busyExtracting()\"\n (click)=\"applyFlavor()\"\n >\n {{ 'yuv.app.invoice.apply-flavor.button.apply' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{width:90vw;--ymt-dialog-content-display: block}:host .spinning{opacity:.5;pointer-events:none}:host main{height:65vh}:host yuv-split-view{--split-gutter-background-color: var(--ymt-outline-variant);flex:1}:host .metadata{display:flex;flex-flow:column;height:100%;overflow:hidden}:host .metadata .ai{display:flex;flex:0 0 auto;justify-content:end;padding:0 var(--ymt-spacing-m);border-block-end:1px solid var(--ymt-outline-variant);align-items:center;gap:1em}:host .metadata .ai mat-icon.warning{--icon-size: 18px;color:var(--ymt-warning)}:host .metadata .ai button{display:flex;margin-block:var(--ymt-spacing-2xs);padding:.25em 1.5em}:host .metadata .ai button mat-icon{--icon-size: 18px;color:var(--ymt-text-color-subtle)}:host .metadata yuv-object-form{display:block;background-color:var(--ymt-surface-panel);border:1px solid var(--ymt-outline-variant);max-width:100%;margin-inline:auto;box-sizing:border-box;overflow:auto}:host .spinner{color:var(--mat-sys-primary)}:host .spinner,:host .spinner:after{box-sizing:border-box}:host .spinner{display:inline-block;width:40px;height:40px}:host .spinner:after{content:\" \";display:block;width:32px;height:32px;margin:4px;border-radius:50%;border:6.4px solid currentColor;border-color:currentColor transparent currentColor transparent;animation:spinner 1.2s linear infinite}@keyframes spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}::ng-deep .cdk-overlay-pane.mat-mdc-dialog-panel{max-width:unset!important}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: YuvSplitViewModule }, { kind: "directive", type: i2$1.SplitAreaDirective, selector: "[yuvSplitArea]", inputs: ["size", "minSize", "maxSize", "panelClass", "visible"] }, { kind: "component", type: i2$1.SplitViewComponent, selector: "yuv-split-view", inputs: ["direction", "gutterSize", "restrictMove", "disabled", "layoutSettingsID"], outputs: ["layoutSettingsChange", "dragStart", "dragEnd", "gutterClick", "gutterDblClick"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "directive", type: BusyOverlayDirective, selector: "[yuvBusyOverlay]", inputs: ["yuvBusyOverlay"] }, { kind: "component", type: ObjectFormComponent, selector: "yuv-object-form", inputs: ["formOptions", "inert", "elementExtensions", "isInnerTableForm"], outputs: ["statusChanged", "onFormReady"] }, { kind: "component", type: ObjectPreviewComponent, selector: "yuv-object-preview", inputs: ["objectId", "dmsObject", "version"] }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitel"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatDialogModule }, { kind: "directive", type: i4.MatDialogClose, selector: "[mat-dialog-close], [matDialogClose]", inputs: ["aria-label", "type", "mat-dialog-close", "matDialogClose"], exportAs: ["matDialogClose"] }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "ngmodule", type: MatIconModule }, { kind: "component", type: i2.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }] });
|
|
251
|
+
}
|
|
252
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ApplyFlavorComponent, decorators: [{
|
|
253
|
+
type: Component,
|
|
254
|
+
args: [{ selector: 'yin-apply-flavor', standalone: true, providers: [ApplyFlavorService], imports: [CommonModule, ...COMPONENTS, ...MATERIAL, MatIconModule], template: "<yuv-dialog [headertitel]=\"headline || ('yuv.app.invoice.apply-flavor.headline' | translate: { name: flavorLabel() })\">\n <main>\n <yuv-split-view [gutterSize]=\"1\">\n <ng-template yuvSplitArea [size]=\"60\">\n @if (dmsObject() && dmsObject().content) {\n <yuv-object-preview [objectId]=\"dmsObject().id\"></yuv-object-preview>\n }\n </ng-template>\n\n <ng-template yuvSplitArea [size]=\"40\">\n <div class=\"metadata\" [yuvBusyOverlay]=\"busyLoading()\">\n <div class=\"ai\">\n @if (supportsExtraction()) {\n @if (error()) {\n <mat-icon class=\"warning\" [matTooltip]=\"'yuv.app.invoice.apply-flavor.button.extract.error' | translate\">warning</mat-icon>\n }\n @if (busyExtracting()) {\n <div class=\"spinner\"></div>\n }\n <button ymtButton=\"secondary\" class=\"ai-extract\" [ngClass]=\"{ spinning: busyExtracting() }\" (click)=\"extract()\">\n <mat-icon>robot_2</mat-icon>\n {{ 'yuv.app.invoice.apply-flavor.button.extract' | translate }}\n </button>\n }\n </div>\n\n @let fo = formOptions();\n @if (fo) {\n <yuv-object-form\n [elementExtensions]=\"extensions()\"\n [inert]=\"busySaving() || busyExtracting()\"\n [formOptions]=\"fo\"\n (statusChanged)=\"onFormStatusChanged($event)\"\n ></yuv-object-form>\n }\n </div>\n </ng-template>\n </yuv-split-view>\n </main>\n\n <footer>\n <button ymtButton=\"secondary\" mat-dialog-close [disabled]=\"busySaving() || busyExtracting()\">\n {{ 'yuv.app.invoice.apply-flavor.button.cancel' | translate }}\n </button>\n <button\n ymtButton=\"primary\"\n mat-dialog-close\n cdkFocusInitial\n class=\"primary\"\n [ngClass]=\"{ spinning: busySaving() }\"\n [disabled]=\"applyDisabled() || busyExtracting()\"\n (click)=\"applyFlavor()\"\n >\n {{ 'yuv.app.invoice.apply-flavor.button.apply' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n", styles: [":host{width:90vw;--ymt-dialog-content-display: block}:host .spinning{opacity:.5;pointer-events:none}:host main{height:65vh}:host yuv-split-view{--split-gutter-background-color: var(--ymt-outline-variant);flex:1}:host .metadata{display:flex;flex-flow:column;height:100%;overflow:hidden}:host .metadata .ai{display:flex;flex:0 0 auto;justify-content:end;padding:0 var(--ymt-spacing-m);border-block-end:1px solid var(--ymt-outline-variant);align-items:center;gap:1em}:host .metadata .ai mat-icon.warning{--icon-size: 18px;color:var(--ymt-warning)}:host .metadata .ai button{display:flex;margin-block:var(--ymt-spacing-2xs);padding:.25em 1.5em}:host .metadata .ai button mat-icon{--icon-size: 18px;color:var(--ymt-text-color-subtle)}:host .metadata yuv-object-form{display:block;background-color:var(--ymt-surface-panel);border:1px solid var(--ymt-outline-variant);max-width:100%;margin-inline:auto;box-sizing:border-box;overflow:auto}:host .spinner{color:var(--mat-sys-primary)}:host .spinner,:host .spinner:after{box-sizing:border-box}:host .spinner{display:inline-block;width:40px;height:40px}:host .spinner:after{content:\" \";display:block;width:32px;height:32px;margin:4px;border-radius:50%;border:6.4px solid currentColor;border-color:currentColor transparent currentColor transparent;animation:spinner 1.2s linear infinite}@keyframes spinner{0%{transform:rotate(0)}to{transform:rotate(360deg)}}::ng-deep .cdk-overlay-pane.mat-mdc-dialog-panel{max-width:unset!important}\n"] }]
|
|
255
|
+
}] });
|
|
256
|
+
|
|
257
|
+
// use marker to extract the labels for the app schema types
|
|
258
|
+
// make sure to provide a marker for each type/flavor ID
|
|
259
|
+
marker('io.yuuvis.app.invoice.flavor.invoice');
|
|
260
|
+
marker('io.yuuvis.app.invoice.flavor.invoice.description');
|
|
261
|
+
const APP_ROLE = 'YM_APP_INVOICE';
|
|
262
|
+
const APP_PREFIX = 'appSysteminvoice:';
|
|
263
|
+
const APP_ID = 'io.yuuvis.app.invoice';
|
|
264
|
+
const RETENTION_PERIOD = 10;
|
|
265
|
+
const APP_FLAVORS = [
|
|
266
|
+
{
|
|
267
|
+
id: 'io.yuuvis.app.invoice.flavor.invoice',
|
|
268
|
+
descriptionKey: 'io.yuuvis.app.invoice.flavor.invoice.description',
|
|
269
|
+
icon: 'local_atm',
|
|
270
|
+
objectTypeID: SystemType.DOCUMENT,
|
|
271
|
+
sot: `${APP_PREFIX}invoice`,
|
|
272
|
+
applicableTo: {
|
|
273
|
+
mimeTypes: ['*/*']
|
|
274
|
+
},
|
|
275
|
+
applyComponent: ApplyFlavorComponent
|
|
276
|
+
}
|
|
277
|
+
];
|
|
278
|
+
|
|
279
|
+
class ManageRetentionComponent {
|
|
280
|
+
#dialogData = inject(MAT_DIALOG_DATA);
|
|
281
|
+
#dialogRef = inject((MatDialogRef));
|
|
282
|
+
#retention = inject(RetentionService);
|
|
283
|
+
translate = inject(TranslateService$1);
|
|
284
|
+
#DEFAULT_RETENTION_PERIOD = 10; // years
|
|
285
|
+
actionContext = this.#dialogData.context;
|
|
286
|
+
// in years
|
|
287
|
+
retentionPeriod = input(this.#dialogData.retentionPeriod || this.#DEFAULT_RETENTION_PERIOD);
|
|
288
|
+
objects = input(this.#dialogData.selection);
|
|
289
|
+
#objectsEffect = effect(() => {
|
|
290
|
+
const objects = this.objects();
|
|
291
|
+
untracked(() => {
|
|
292
|
+
this.#objects.set(objects);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
#objects = signal([]);
|
|
296
|
+
objectGroups = computed(() => {
|
|
297
|
+
// group given objects by their retention state
|
|
298
|
+
const groups = { underRetention: [], notUnderRetention: [] };
|
|
299
|
+
this.#objects().forEach((o) => {
|
|
300
|
+
const state = this.#retention.getRetentionState(o);
|
|
301
|
+
if (state.underRetention) {
|
|
302
|
+
groups.underRetention.push(this.#toRetentionGroupEntry(o, state));
|
|
303
|
+
}
|
|
304
|
+
else {
|
|
305
|
+
groups.notUnderRetention.push(this.#toRetentionGroupEntry(o, state));
|
|
306
|
+
}
|
|
307
|
+
});
|
|
308
|
+
return groups;
|
|
309
|
+
});
|
|
310
|
+
busySettingRetention = signal(false);
|
|
311
|
+
#toRetentionGroupEntry(object, state) {
|
|
312
|
+
const labelProperty = this.actionContext.subjectProperty || BaseObjectTypeField.OBJECT_ID;
|
|
313
|
+
return {
|
|
314
|
+
object,
|
|
315
|
+
objectLabel: object.data[labelProperty],
|
|
316
|
+
state
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
error;
|
|
320
|
+
setRetention() {
|
|
321
|
+
this.error = undefined;
|
|
322
|
+
this.busySettingRetention.set(true);
|
|
323
|
+
const retentionStart = new Date();
|
|
324
|
+
const retentionStartClone = new Date(retentionStart);
|
|
325
|
+
const retentionEnd = new Date(retentionStartClone.setFullYear(retentionStart.getFullYear() + this.retentionPeriod()));
|
|
326
|
+
this.#retention
|
|
327
|
+
.setRetention(this.objectGroups().notUnderRetention.map((o) => o.object), retentionStart, retentionEnd)
|
|
328
|
+
.pipe(finalize$1(() => this.busySettingRetention.set(false)))
|
|
329
|
+
.subscribe({
|
|
330
|
+
next: () => {
|
|
331
|
+
this.#dialogRef.close(true);
|
|
332
|
+
},
|
|
333
|
+
error: (e) => {
|
|
334
|
+
console.error('Error setting retention', e);
|
|
335
|
+
this.error = this.translate.instant('yuv.app.invoice.action.retention.error.retention.set');
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
cancel() {
|
|
340
|
+
this.#dialogRef.close(false);
|
|
341
|
+
}
|
|
342
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ManageRetentionComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
343
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ManageRetentionComponent, isStandalone: true, selector: "ymxi-manage-retention", inputs: { retentionPeriod: { classPropertyName: "retentionPeriod", publicName: "retentionPeriod", isSignal: true, isRequired: false, transformFunction: null }, objects: { classPropertyName: "objects", publicName: "objects", isSignal: true, isRequired: false, transformFunction: null } }, ngImport: i0, template: "<yuv-dialog [headertitel]=\"'yuv.app.invoice.action.retention.confirm.title' | translate\">\n <main>\n @if (error) {\n <p class=\"error\">{{ error }}</p>\n }\n\n @if (objectGroups().underRetention.length) {\n <section>\n <p>{{ 'yuv.app.invoice.action.retention.underRetention.message' | translate }}</p>\n <ul class=\"files\">\n @for (o of objectGroups().underRetention; track $index) {\n <li\n matTooltip=\"{{ o.objectLabel }} ( {{ o.state.start | localeDate: 'shortDate' }} - {{ o.state.end | localeDate: 'shortDate' }} )\"\n [attr.aria-label]=\"o.objectLabel + ' (' + (o.state.start | localeDate: 'shortDate') + ' - ' + (o.state.end | localeDate: 'shortDate') + ')'\"\n >\n {{ o.objectLabel }} <time class=\"date\"> {{ o.state.start | localeDate: 'shortDate' }} - {{ o.state.end | localeDate: 'shortDate' }} </time>\n </li>\n }\n </ul>\n </section>\n }\n @if (objectGroups().notUnderRetention.length) {\n <section class=\"warning\">\n <p>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message' | translate: { years: retentionPeriod() } }}</p>\n <ul class=\"bullets\">\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.1' | translate }}</li>\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.2' | translate }}</li>\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.3' | translate }}</li>\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.4' | translate }}</li>\n </ul>\n </section>\n\n <ul class=\"files\">\n @for (o of objectGroups().notUnderRetention; track $index) {\n <li matTooltip=\"{{ o.objectLabel }}\" [attr.aria-label]=\"o.objectLabel\">{{ o.objectLabel }}</li>\n }\n </ul>\n }\n </main>\n <footer>\n <button ymtButton=\"secondary\" (click)=\"cancel()\">{{ 'yuv.app.invoice.action.retention.action.cancel' | translate }}</button>\n @if (objectGroups().notUnderRetention.length) {\n <button ymtButton=\"primary\" [ngClass]=\"{ spinning: busySettingRetention() }\" (click)=\"setRetention()\">\n {{ 'yuv.app.invoice.action.retention.notUnderRetention.action.confirm' | translate }}\n </button>\n }\n </footer>\n</yuv-dialog>\n", styles: [":host{display:contents}:host main{padding:0 var(--ymt-spacing-m);--ymt-dialog-content-display: block}:host .error{background-color:var(--ymt-danger-container);color:var(--ymt-on-danger-container);border:var(--ymt-danger);padding:var(--ymt-spacing-xs);border-radius:var(--ymt-corner-xs)}:host section{padding:var(--ymt-spacing-xs);border:1px solid var(--ymt-outline-variant);margin-block:var(--ymt-spacing-m);border-radius:4px;background-color:var(--ymt-surface-panel)}:host section.warning{background-color:var(--ymt-danger-container);border:var(--ymt-danger);color:var(--ymt-on-danger-container)}:host section p{margin-block-start:0}:host section ul:not(.bullets){background-color:var(--ymt-surface-panel)}:host section .actions{display:flex;justify-content:end;margin-block-start:var(--ymt-spacing-xs)}:host p{line-height:1.5em}:host ul.bullets li{line-height:1.5em;margin-inline-end:.5em}:host ul.files{list-style-type:none;padding:0;margin:0;border:1px solid var(--ymt-outline-variant);border-radius:var(--ymt-corner-xs);margin-block:var(--ymt-spacing-m)}:host ul.files li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:var(--ymt-spacing-xs);display:flex;justify-content:space-between;align-items:center;gap:var(--ymt-spacing-m);overflow:auto;scrollbar-width:none;-ms-overflow-style:none}:host ul.files li::-webkit-scrollbar{display:none}:host ul.files li:not(:last-child){border-block-end:1px solid var(--ymt-outline-variant)}:host ul.files li .date{font:var(--ymt-font-body-subtle);background-color:var(--ymt-surface);border:1px solid var(--ymt-outline-variant);line-height:1em;padding:.1em .25em;border-radius:var(--ymt-corner-xs)}:host .actions{display:flex;justify-content:space-between;gap:var(--ymt-spacing-2xs);margin-block-start:var(--ymt-spacing-m)}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: TranslateModule }, { kind: "pipe", type: i3.TranslatePipe, name: "translate" }, { kind: "ngmodule", type: MatDialogModule }, { kind: "ngmodule", type: MatButtonModule }, { kind: "ngmodule", type: MatTooltipModule }, { kind: "directive", type: i5.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "pipe", type: LocaleDatePipe, name: "localeDate" }, { kind: "component", type: DialogComponent, selector: "yuv-dialog", inputs: ["headertitel"] }, { kind: "directive", type: YmtButtonDirective, selector: "button[ymtButton], a[ymtButton]", inputs: ["ymtButton", "disabled", "aria-disabled", "disableRipple", "disabledInteractive", "button-size"] }] });
|
|
344
|
+
}
|
|
345
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ManageRetentionComponent, decorators: [{
|
|
346
|
+
type: Component,
|
|
347
|
+
args: [{ selector: 'ymxi-manage-retention', standalone: true, imports: [CommonModule, TranslateModule, MatDialogModule, MatButtonModule, MatTooltipModule, LocaleDatePipe, DialogComponent, YmtButtonDirective], template: "<yuv-dialog [headertitel]=\"'yuv.app.invoice.action.retention.confirm.title' | translate\">\n <main>\n @if (error) {\n <p class=\"error\">{{ error }}</p>\n }\n\n @if (objectGroups().underRetention.length) {\n <section>\n <p>{{ 'yuv.app.invoice.action.retention.underRetention.message' | translate }}</p>\n <ul class=\"files\">\n @for (o of objectGroups().underRetention; track $index) {\n <li\n matTooltip=\"{{ o.objectLabel }} ( {{ o.state.start | localeDate: 'shortDate' }} - {{ o.state.end | localeDate: 'shortDate' }} )\"\n [attr.aria-label]=\"o.objectLabel + ' (' + (o.state.start | localeDate: 'shortDate') + ' - ' + (o.state.end | localeDate: 'shortDate') + ')'\"\n >\n {{ o.objectLabel }} <time class=\"date\"> {{ o.state.start | localeDate: 'shortDate' }} - {{ o.state.end | localeDate: 'shortDate' }} </time>\n </li>\n }\n </ul>\n </section>\n }\n @if (objectGroups().notUnderRetention.length) {\n <section class=\"warning\">\n <p>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message' | translate: { years: retentionPeriod() } }}</p>\n <ul class=\"bullets\">\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.1' | translate }}</li>\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.2' | translate }}</li>\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.3' | translate }}</li>\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.4' | translate }}</li>\n </ul>\n </section>\n\n <ul class=\"files\">\n @for (o of objectGroups().notUnderRetention; track $index) {\n <li matTooltip=\"{{ o.objectLabel }}\" [attr.aria-label]=\"o.objectLabel\">{{ o.objectLabel }}</li>\n }\n </ul>\n }\n </main>\n <footer>\n <button ymtButton=\"secondary\" (click)=\"cancel()\">{{ 'yuv.app.invoice.action.retention.action.cancel' | translate }}</button>\n @if (objectGroups().notUnderRetention.length) {\n <button ymtButton=\"primary\" [ngClass]=\"{ spinning: busySettingRetention() }\" (click)=\"setRetention()\">\n {{ 'yuv.app.invoice.action.retention.notUnderRetention.action.confirm' | translate }}\n </button>\n }\n </footer>\n</yuv-dialog>\n", styles: [":host{display:contents}:host main{padding:0 var(--ymt-spacing-m);--ymt-dialog-content-display: block}:host .error{background-color:var(--ymt-danger-container);color:var(--ymt-on-danger-container);border:var(--ymt-danger);padding:var(--ymt-spacing-xs);border-radius:var(--ymt-corner-xs)}:host section{padding:var(--ymt-spacing-xs);border:1px solid var(--ymt-outline-variant);margin-block:var(--ymt-spacing-m);border-radius:4px;background-color:var(--ymt-surface-panel)}:host section.warning{background-color:var(--ymt-danger-container);border:var(--ymt-danger);color:var(--ymt-on-danger-container)}:host section p{margin-block-start:0}:host section ul:not(.bullets){background-color:var(--ymt-surface-panel)}:host section .actions{display:flex;justify-content:end;margin-block-start:var(--ymt-spacing-xs)}:host p{line-height:1.5em}:host ul.bullets li{line-height:1.5em;margin-inline-end:.5em}:host ul.files{list-style-type:none;padding:0;margin:0;border:1px solid var(--ymt-outline-variant);border-radius:var(--ymt-corner-xs);margin-block:var(--ymt-spacing-m)}:host ul.files li{overflow:hidden;text-overflow:ellipsis;white-space:nowrap;padding:var(--ymt-spacing-xs);display:flex;justify-content:space-between;align-items:center;gap:var(--ymt-spacing-m);overflow:auto;scrollbar-width:none;-ms-overflow-style:none}:host ul.files li::-webkit-scrollbar{display:none}:host ul.files li:not(:last-child){border-block-end:1px solid var(--ymt-outline-variant)}:host ul.files li .date{font:var(--ymt-font-body-subtle);background-color:var(--ymt-surface);border:1px solid var(--ymt-outline-variant);line-height:1em;padding:.1em .25em;border-radius:var(--ymt-corner-xs)}:host .actions{display:flex;justify-content:space-between;gap:var(--ymt-spacing-2xs);margin-block-start:var(--ymt-spacing-m)}\n"] }]
|
|
348
|
+
}] });
|
|
349
|
+
|
|
350
|
+
class InvoiceRetentionAction extends AbstractContextAction {
|
|
351
|
+
translate = inject(TranslateService);
|
|
352
|
+
#dialog = inject(MatDialog);
|
|
353
|
+
id = 'app.invoice.retention';
|
|
354
|
+
label = this.translate.instant('yuv.app.invoice.action.retention.label');
|
|
355
|
+
description = this.translate.instant('yuv.app.invoice.action.retention.description');
|
|
356
|
+
priority = 2;
|
|
357
|
+
icon = 'lock_clock';
|
|
358
|
+
group = 'common';
|
|
359
|
+
range = SelectionRange.SINGLE_SELECT;
|
|
360
|
+
supports = {};
|
|
361
|
+
isExecutable(selection) {
|
|
362
|
+
const o = selection[0];
|
|
363
|
+
return of(o && o.sots.includes('appSysteminvoice:invoice'));
|
|
364
|
+
}
|
|
365
|
+
run(selection) {
|
|
366
|
+
this.#dialog.open(ManageRetentionComponent, {
|
|
367
|
+
maxWidth: '90vw',
|
|
368
|
+
data: {
|
|
369
|
+
context: this.context,
|
|
370
|
+
selection,
|
|
371
|
+
retentionPeriod: RETENTION_PERIOD
|
|
372
|
+
}
|
|
373
|
+
});
|
|
374
|
+
return of(true);
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
class ApplyCreateFlavorComponent extends AbstractApplyCreateFlavorComponent {
|
|
379
|
+
#dms = inject(DmsService);
|
|
380
|
+
#dialogRef = inject((MatDialogRef));
|
|
381
|
+
#dataEffect = effect(() => {
|
|
382
|
+
untracked(() => {
|
|
383
|
+
this.#setupApplyComponent();
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
sc;
|
|
387
|
+
#setupApplyComponent() {
|
|
388
|
+
const flavor = APP_FLAVORS.find((f) => f.id === 'io.yuuvis.app.invoice.flavor.invoice');
|
|
389
|
+
this.#dms.getDmsObject(this.createdObjectIDs()[0]).subscribe((dmsObject) => {
|
|
390
|
+
this.sc = {
|
|
391
|
+
inputs: {
|
|
392
|
+
dmsObject,
|
|
393
|
+
flavor: flavor
|
|
394
|
+
},
|
|
395
|
+
cmp: flavor.applyComponent
|
|
396
|
+
};
|
|
397
|
+
if (dmsObject.content?.mimeType === 'application/x-os-invoice-xml') {
|
|
398
|
+
this.#dialogRef.close();
|
|
399
|
+
}
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ApplyCreateFlavorComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
403
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.2.14", type: ApplyCreateFlavorComponent, isStandalone: true, selector: "yin-apply-create-flavor", usesInheritance: true, ngImport: i0, template: "@if (sc && sc.cmp) {\n <ng-container *ngComponentOutlet=\"sc.cmp; inputs: sc.inputs\"></ng-container>\n}\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgComponentOutlet, selector: "[ngComponentOutlet]", inputs: ["ngComponentOutlet", "ngComponentOutletInputs", "ngComponentOutletInjector", "ngComponentOutletContent", "ngComponentOutletNgModule", "ngComponentOutletNgModuleFactory"], exportAs: ["ngComponentOutlet"] }] });
|
|
404
|
+
}
|
|
405
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: ApplyCreateFlavorComponent, decorators: [{
|
|
406
|
+
type: Component,
|
|
407
|
+
args: [{ selector: 'yin-apply-create-flavor', standalone: true, imports: [CommonModule], template: "@if (sc && sc.cmp) {\n <ng-container *ngComponentOutlet=\"sc.cmp; inputs: sc.inputs\"></ng-container>\n}\n" }]
|
|
408
|
+
}] });
|
|
409
|
+
|
|
410
|
+
const APP_CREATE_FLAVORS = [
|
|
411
|
+
{
|
|
412
|
+
id: 'io.yuuvis.app.invoice.flavor.invoice',
|
|
413
|
+
descriptionKey: 'io.yuuvis.app.invoice.flavor.invoice.description',
|
|
414
|
+
icon: 'local_atm',
|
|
415
|
+
withFileUpload: {
|
|
416
|
+
applicableTo: {
|
|
417
|
+
mimeTypes: ['application/pdf']
|
|
418
|
+
}
|
|
419
|
+
},
|
|
420
|
+
sot: `${APP_PREFIX}invoice`,
|
|
421
|
+
applyComponent: ApplyCreateFlavorComponent
|
|
422
|
+
}
|
|
423
|
+
];
|
|
424
|
+
|
|
425
|
+
class AppInvoiceExtension {
|
|
426
|
+
#shell = inject(ShellService);
|
|
427
|
+
#actionsService = inject(ActionsService);
|
|
428
|
+
#actions = [
|
|
429
|
+
{ id: 'app.invoice.retention', action: InvoiceRetentionAction },
|
|
430
|
+
{ id: 'app.invoice.open-email', action: OpenEmailAction },
|
|
431
|
+
];
|
|
432
|
+
init() {
|
|
433
|
+
this.#enableExtension();
|
|
434
|
+
return Promise.resolve();
|
|
435
|
+
}
|
|
436
|
+
#enableExtension() {
|
|
437
|
+
// expose flavors
|
|
438
|
+
this.#shell.exposeObjectFlavors(APP_FLAVORS);
|
|
439
|
+
this.#shell.exposeObjectCreateFlavors(APP_CREATE_FLAVORS);
|
|
440
|
+
// register actions
|
|
441
|
+
this.#actionsService.registerActions(this.#actions);
|
|
442
|
+
}
|
|
443
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AppInvoiceExtension, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
444
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AppInvoiceExtension });
|
|
445
|
+
}
|
|
446
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.14", ngImport: i0, type: AppInvoiceExtension, decorators: [{
|
|
447
|
+
type: Injectable
|
|
448
|
+
}] });
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Generated bundle index. Do not edit.
|
|
452
|
+
*/
|
|
453
|
+
|
|
454
|
+
export { AiExtractedPropertyComponent, AppInvoiceExtension, ApplyCreateFlavorComponent, ApplyFlavorComponent };
|
|
455
|
+
//# sourceMappingURL=yuuvis-app-invoice-extensions.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yuuvis-app-invoice-extensions.mjs","sources":["../../../../projects/yuuvis/app-invoice/extensions/src/lib/actions/open-email/open-email.action.ts","../../../../projects/yuuvis/app-invoice/extensions/src/lib/services/apply-flavor.service.ts","../../../../projects/yuuvis/app-invoice/extensions/src/lib/components/form-extensions/ai-extracted-property/ai-extracted-property.component.ts","../../../../projects/yuuvis/app-invoice/extensions/src/lib/components/form-extensions/ai-extracted-property/ai-extracted-property.component.html","../../../../projects/yuuvis/app-invoice/extensions/src/lib/components/apply-flavor/apply-flavor.component.ts","../../../../projects/yuuvis/app-invoice/extensions/src/lib/components/apply-flavor/apply-flavor.component.html","../../../../projects/yuuvis/app-invoice/extensions/src/lib/invoice.schema.ts","../../../../projects/yuuvis/app-invoice/extensions/src/lib/actions/retention/manage-retention/manage-retention.component.ts","../../../../projects/yuuvis/app-invoice/extensions/src/lib/actions/retention/manage-retention/manage-retention.component.html","../../../../projects/yuuvis/app-invoice/extensions/src/lib/actions/retention/retention.action.ts","../../../../projects/yuuvis/app-invoice/extensions/src/lib/components/apply-create-flavor/apply-create-flavor.component.ts","../../../../projects/yuuvis/app-invoice/extensions/src/lib/components/apply-create-flavor/apply-create-flavor.component.html","../../../../projects/yuuvis/app-invoice/extensions/src/lib/invoice.flavor.create.ts","../../../../projects/yuuvis/app-invoice/extensions/src/lib/services/extensions.service.ts","../../../../projects/yuuvis/app-invoice/extensions/src/yuuvis-app-invoice-extensions.ts"],"sourcesContent":["import { inject } from '@angular/core';\nimport { Router } from '@angular/router';\nimport { TranslateService } from '@ngx-translate/core';\nimport { APP_ID } from '@yuuvis/app-drive';\nimport { DmsObject } from '@yuuvis/client-core';\nimport {\n AbstractContextAction,\n Action,\n ActionSupport,\n SelectionRange,\n} from '@yuuvis/client-framework/actions';\nimport { ShellService } from '@yuuvis/client-shell-core';\nimport { Observable, of } from 'rxjs';\n\nexport class OpenEmailAction extends AbstractContextAction implements Action {\n private translate = inject(TranslateService);\n private router = inject(Router);\n #shell = inject(ShellService);\n\n id = 'app.invoice.open-email';\n label = this.translate.instant('yuv.app.invoice.action.open-email.label');\n description = this.translate.instant(\n 'yuv.app.invoice.action.open-email.description'\n );\n priority = 3;\n icon = 'mail';\n group = 'common';\n range = SelectionRange.SINGLE_SELECT;\n supports: ActionSupport = {};\n\n #app = this.#shell.getApp(APP_ID);\n\n isExecutable(selection: DmsObject[]) {\n const o = selection[0];\n return of(\n o &&\n o.sots.includes('appSysteminvoice:invoice') &&\n !!o.data['appClassifypro:emailReference']\n );\n }\n\n run(selection: DmsObject[]): Observable<boolean> {\n const o = selection[0];\n const emailReference = o.data['appClassifypro:emailReference'];\n this.router.navigateByUrl(\n `/${this.#app ? this.#app.path : 'drive'}/object/${emailReference}`\n );\n return of(true);\n }\n}\n","import { inject, Injectable, Signal, signal } from '@angular/core';\nimport { PredictionExtractResult, PredictionExtractResultItem, PredictionService } from '@yuuvis/client-core';\nimport { Observable, tap } from 'rxjs';\n\n@Injectable()\nexport class ApplyFlavorService {\n #predict = inject(PredictionService);\n\n #extractedDataSource = signal<Record<string, PredictionExtractResultItem[]> | null>(null);\n extractedData: Signal<Record<string, PredictionExtractResultItem[]> | null> = this.#extractedDataSource.asReadonly();\n\n extract(schemaObjectTypeId: string, objectID: string): Observable<any> {\n return this.#predict\n .extract(schemaObjectTypeId, [objectID])\n .pipe(tap((res: Record<string, PredictionExtractResult>) => this.#extractedDataSource.set(res[objectID].properties)));\n }\n}\n","import { CommonModule } from '@angular/common';\nimport { Component, DestroyRef, effect, ElementRef, inject, OnInit, signal, TemplateRef, untracked } from '@angular/core';\nimport { MatIconModule } from '@angular/material/icon';\nimport { MatMenuModule } from '@angular/material/menu';\nimport { PredictionExtractResultItem, SystemService } from '@yuuvis/client-core';\nimport { ObjectFormElementExtension } from '@yuuvis/client-framework/object-form';\nimport { ApplyFlavorService } from '../../../services/apply-flavor.service';\n\n/**\n * This object form field extension inserts AI-extracted values into an\n * object-form. Once the AI service has extracted a value, this extension\n * will change the form field to display the extracted value and show the\n * value for the probability of the extraction right next to the field.\n *\n * If there are multiple extractions, the extension will insert the value\n * with the highest probability and provide a picker for the other values.\n *\n * This way the user can easily accept the extracted value or choose a\n * different one from the list of extracted values.\n */\n@Component({\n selector: 'yin-ai-extracted-property',\n standalone: true,\n imports: [CommonModule, MatMenuModule, MatIconModule],\n templateUrl: './ai-extracted-property.component.html',\n styleUrl: './ai-extracted-property.component.scss'\n})\nexport class AiExtractedPropertyComponent extends ObjectFormElementExtension implements OnInit {\n #applyFlavorService = inject(ApplyFlavorService);\n #destroyRef = inject(DestroyRef);\n #system = inject(SystemService);\n #elRef = inject(ElementRef);\n\n predictionValues: PredictionExtractResultItem[] = [];\n currentValueProbability = signal<number | undefined>(undefined);\n #currentValueProbabilityEffect = effect(() => {\n const cp = this.currentValueProbability();\n if (!cp) return;\n // set the probability color\n const color = cp < 30 ? '--ymt-danger' : cp < 60 ? '--ymt-warning' : '--ymt-success';\n (this.#elRef.nativeElement as HTMLElement).style.setProperty('--current-value-probability-color', `var(${color})`);\n });\n\n extractedData = this.#applyFlavorService.extractedData;\n extractedDataEffect = effect(() => {\n const extData = this.extractedData();\n if (extData) {\n untracked(() => {\n const fcn = this.input().formControlName;\n this.predictionValues = extData[fcn] || [];\n this.#applyPredictionValues();\n });\n }\n });\n\n #internalFieldType?: string;\n\n #applyPredictionValues() {\n // set the value of the form field to the extracted value with\n // the highest probability\n const pv = this.predictionValues;\n if (pv.length) {\n pv.sort((a, b) => b.probability - a.probability);\n this.selectOption(pv[0]);\n } else {\n this.currentValueProbability.set(undefined);\n }\n }\n\n // map extracted string to a proper format to be used\n // within the form elements\n #mapValueToType(value: any): unknown {\n if (this.#internalFieldType === 'datetime') {\n // dates will always be returned as german formatted strings (24.12.2024)\n // no matter what the locale of the processed document is. So we need to\n // convert the string to a proper date object\n const dateParts = value.split('.');\n return dateParts.length === 3 ? new Date(+dateParts[2], +dateParts[1] - 1, +dateParts[0]) : value;\n } else {\n return value;\n }\n }\n\n selectOptionByIndex(idx: number) {\n this.selectOption(this.predictionValues[idx]);\n }\n\n selectOption(pr: PredictionExtractResultItem) {\n this.setValue(this.#mapValueToType(pr.value));\n this.currentValueProbability.set(pr.probability);\n }\n\n ngOnInit() {\n this.#internalFieldType = this.#system.getObjectTypeField(this.input().formControlName)?._internalType;\n }\n}\n","@if (predictionValues.length === 1) {\n <span class=\"probability\">\n <mat-icon class=\"ymt-icon--size-s\">robot_2</mat-icon>\n {{ currentValueProbability() }}%</span\n >\n} @else if (predictionValues.length > 1) {\n <button class=\"probability\" [matMenuTriggerFor]=\"menu\">\n <!-- (click)=\"openValueOptions(options, $event)\"> -->\n <mat-icon class=\"ymt-icon--size-s\">robot_2</mat-icon>\n {{ currentValueProbability() }}%\n <mat-icon class=\"ymt-icon--size-s\">arrow_drop_down</mat-icon>\n </button>\n\n <mat-menu #menu=\"matMenu\">\n @for (pv of predictionValues; track $index) {\n <button mat-menu-item (click)=\"selectOptionByIndex($index)\">{{ pv.value }}<span>{{ pv.probability }}%</span></button> \n }\n </mat-menu>\n} \n","import { CommonModule } from '@angular/common';\nimport { Component, computed, effect, inject, signal, untracked, viewChild } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MatDialogModule } from '@angular/material/dialog';\nimport { Situation, SystemService, TranslateModule, TranslateService } from '@yuuvis/client-core';\nimport { BusyOverlayDirective, DialogComponent } from '@yuuvis/client-framework/common';\nimport { AbstractApplyObjectFlavorComponent } from '@yuuvis/client-framework/object-flavor';\nimport { FormStatusChangedEvent, IObjectFormElementExtension, ObjectFormComponent, ObjectFormOptions } from '@yuuvis/client-framework/object-form';\nimport { ObjectPreviewComponent } from '@yuuvis/client-framework/object-preview';\nimport { YuvSplitViewModule } from '@yuuvis/client-framework/split-view';\nimport { ObjectFlavor, ShellService } from '@yuuvis/client-shell-core';\nimport { finalize } from 'rxjs';\nimport { ApplyFlavorService } from '../../services/apply-flavor.service';\nimport { AiExtractedPropertyComponent } from '../form-extensions/ai-extracted-property/ai-extracted-property.component';\nimport { YmtButtonDirective } from '@yuuvis/material';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { MatIconModule } from '@angular/material/icon';\n\nconst COMPONENTS = [\n YuvSplitViewModule,\n TranslateModule,\n BusyOverlayDirective,\n ObjectFormComponent,\n ObjectPreviewComponent,\n DialogComponent,\n YmtButtonDirective\n];\nconst MATERIAL = [MatButtonModule, MatDialogModule, MatTooltipModule];\n\n@Component({\n selector: 'yin-apply-flavor',\n standalone: true,\n providers: [ApplyFlavorService],\n imports: [CommonModule, ...COMPONENTS, ...MATERIAL, MatIconModule],\n templateUrl: './apply-flavor.component.html',\n styleUrl: './apply-flavor.component.scss'\n})\nexport class ApplyFlavorComponent extends AbstractApplyObjectFlavorComponent {\n #system = inject(SystemService);\n #shell = inject(ShellService);\n #applyFlavorService = inject(ApplyFlavorService);\n private translate = inject(TranslateService);\n\n objectForm = viewChild(ObjectFormComponent);\n flavorLabel = computed(() => this.#shell.getFlavorLabel(this.flavor().id));\n #flavorEffect = effect(() => {\n const f = this.flavor();\n untracked(() => {\n if (f) this.#loadForm(f);\n });\n });\n #dmsObjectEffect = effect(() => {\n const o = this.dmsObject();\n untracked(() => {\n this.supportsExtraction.set(!!o.content && o.content.mimeType === 'application/pdf');\n });\n });\n\n error = signal<boolean>(false);\n\n applyDisabled = signal<boolean>(true);\n supportsExtraction = signal<boolean>(true);\n busyLoading = signal<boolean>(false);\n busySaving = signal<boolean>(false);\n busyExtracting = signal<boolean>(false);\n formOptions = signal<ObjectFormOptions | null>(null);\n extensions = signal<IObjectFormElementExtension[]>([]);\n immediateExtract = (this.data() && this.data().immediateExtract) || false;\n headline?: string = this.data() && this.data().headline;\n\n #loadForm(f: ObjectFlavor) {\n this.busyLoading.set(true);\n\n const sot = this.#system.getSecondaryObjectType(f.sot);\n this.extensions.set(\n (sot?.fields || []).map((field) => ({\n property: field.id,\n cmp: AiExtractedPropertyComponent\n }))\n );\n\n this.#system\n .getObjectTypeForm(f.sot, Situation.EDIT)\n .pipe(finalize(() => this.busyLoading.set(false)))\n .subscribe({\n next: (form) => {\n this.formOptions.set({\n formModel: form,\n data: {}\n });\n }\n });\n }\n\n extract() {\n this.busyExtracting.set(true);\n this.#applyFlavorService\n .extract(this.flavor().sot, this.dmsObject().id)\n .pipe(finalize(() => this.busyExtracting.set(false)))\n .subscribe({\n next: () => {\n this.error.set(false);\n },\n error: () => {\n this.error.set(true);\n }\n });\n }\n\n onFormStatusChanged(status: FormStatusChangedEvent) {\n this.applyDisabled.set(status.invalid);\n }\n\n applyFlavor() {\n const of = this.objectForm();\n const data: Record<string, unknown> = of ? of.getFormData() : {};\n this.busySaving.set(true);\n this.#shell\n .applyObjectFlavor(this.dmsObject(), this.flavor(), data)\n .pipe(finalize(() => this.busySaving.set(false)))\n .subscribe({\n next: () => this.close()\n // TODO: handle error\n });\n }\n\n close() {\n this.dialogRef.close();\n }\n}\n","<yuv-dialog [headertitel]=\"headline || ('yuv.app.invoice.apply-flavor.headline' | translate: { name: flavorLabel() })\">\n <main>\n <yuv-split-view [gutterSize]=\"1\">\n <ng-template yuvSplitArea [size]=\"60\">\n @if (dmsObject() && dmsObject().content) {\n <yuv-object-preview [objectId]=\"dmsObject().id\"></yuv-object-preview>\n }\n </ng-template>\n\n <ng-template yuvSplitArea [size]=\"40\">\n <div class=\"metadata\" [yuvBusyOverlay]=\"busyLoading()\">\n <div class=\"ai\">\n @if (supportsExtraction()) {\n @if (error()) {\n <mat-icon class=\"warning\" [matTooltip]=\"'yuv.app.invoice.apply-flavor.button.extract.error' | translate\">warning</mat-icon>\n }\n @if (busyExtracting()) {\n <div class=\"spinner\"></div>\n }\n <button ymtButton=\"secondary\" class=\"ai-extract\" [ngClass]=\"{ spinning: busyExtracting() }\" (click)=\"extract()\">\n <mat-icon>robot_2</mat-icon>\n {{ 'yuv.app.invoice.apply-flavor.button.extract' | translate }}\n </button>\n }\n </div>\n\n @let fo = formOptions();\n @if (fo) {\n <yuv-object-form\n [elementExtensions]=\"extensions()\"\n [inert]=\"busySaving() || busyExtracting()\"\n [formOptions]=\"fo\"\n (statusChanged)=\"onFormStatusChanged($event)\"\n ></yuv-object-form>\n }\n </div>\n </ng-template>\n </yuv-split-view>\n </main>\n\n <footer>\n <button ymtButton=\"secondary\" mat-dialog-close [disabled]=\"busySaving() || busyExtracting()\">\n {{ 'yuv.app.invoice.apply-flavor.button.cancel' | translate }}\n </button>\n <button\n ymtButton=\"primary\"\n mat-dialog-close\n cdkFocusInitial\n class=\"primary\"\n [ngClass]=\"{ spinning: busySaving() }\"\n [disabled]=\"applyDisabled() || busyExtracting()\"\n (click)=\"applyFlavor()\"\n >\n {{ 'yuv.app.invoice.apply-flavor.button.apply' | translate }}\n </button>\n </footer>\n</yuv-dialog>\n","import { marker } from '@colsen1991/ngx-translate-extract-marker';\nimport { SystemType } from '@yuuvis/client-core';\nimport { AppSchemaFlavor } from '@yuuvis/client-shell-core';\nimport { ApplyFlavorComponent } from './components/apply-flavor/apply-flavor.component';\n\n// use marker to extract the labels for the app schema types\n// make sure to provide a marker for each type/flavor ID\nmarker('io.yuuvis.app.invoice.flavor.invoice');\nmarker('io.yuuvis.app.invoice.flavor.invoice.description');\n\nexport const APP_ROLE = 'YM_APP_INVOICE';\nexport const APP_PREFIX = 'appSysteminvoice:';\nexport const APP_ID = 'io.yuuvis.app.invoice';\nexport const RETENTION_PERIOD = 10;\n\nexport const APP_FLAVORS: AppSchemaFlavor[] = [\n {\n id: 'io.yuuvis.app.invoice.flavor.invoice',\n descriptionKey: 'io.yuuvis.app.invoice.flavor.invoice.description',\n icon: 'local_atm',\n objectTypeID: SystemType.DOCUMENT,\n sot: `${APP_PREFIX}invoice`,\n applicableTo: {\n mimeTypes: ['*/*']\n },\n applyComponent: ApplyFlavorComponent\n }\n];\n","import { CommonModule } from '@angular/common';\nimport { Component, computed, effect, inject, input, signal, untracked } from '@angular/core';\nimport { MatButtonModule } from '@angular/material/button';\nimport { MAT_DIALOG_DATA, MatDialogModule, MatDialogRef } from '@angular/material/dialog';\nimport { MatTooltipModule } from '@angular/material/tooltip';\nimport { BaseObjectTypeField, DmsObject, LocaleDatePipe, RetentionService, RetentionState, TranslateModule, TranslateService } from '@yuuvis/client-core';\nimport { ActionContext } from '@yuuvis/client-framework/actions';\nimport { DialogComponent } from '@yuuvis/client-framework/common';\nimport { finalize } from 'rxjs/operators';\nimport { YmtButtonDirective } from '@yuuvis/material';\n\ninterface RetentionGroupEntry {\n object: DmsObject;\n objectLabel: string;\n state: RetentionState;\n}\n\n@Component({\n selector: 'ymxi-manage-retention',\n standalone: true,\n imports: [CommonModule, TranslateModule, MatDialogModule, MatButtonModule, MatTooltipModule, LocaleDatePipe, DialogComponent, YmtButtonDirective],\n templateUrl: './manage-retention.component.html',\n styleUrl: './manage-retention.component.scss'\n})\nexport class ManageRetentionComponent {\n #dialogData = inject<any>(MAT_DIALOG_DATA);\n readonly #dialogRef = inject(MatDialogRef<ManageRetentionComponent>);\n #retention = inject(RetentionService);\n private translate = inject(TranslateService);\n\n #DEFAULT_RETENTION_PERIOD = 10; // years\n\n actionContext: ActionContext = this.#dialogData.context;\n // in years\n retentionPeriod = input<number>(this.#dialogData.retentionPeriod || this.#DEFAULT_RETENTION_PERIOD);\n objects = input<DmsObject[]>(this.#dialogData.selection);\n #objectsEffect = effect(() => {\n const objects = this.objects();\n untracked(() => {\n this.#objects.set(objects);\n });\n });\n #objects = signal<DmsObject[]>([]);\n objectGroups = computed(() => {\n // group given objects by their retention state\n const groups: {\n underRetention: RetentionGroupEntry[];\n notUnderRetention: RetentionGroupEntry[];\n } = { underRetention: [], notUnderRetention: [] };\n\n this.#objects().forEach((o) => {\n const state = this.#retention.getRetentionState(o);\n if (state.underRetention) {\n groups.underRetention.push(this.#toRetentionGroupEntry(o, state));\n } else {\n groups.notUnderRetention.push(this.#toRetentionGroupEntry(o, state));\n }\n });\n return groups;\n });\n\n busySettingRetention = signal<boolean>(false);\n\n #toRetentionGroupEntry(object: DmsObject, state: RetentionState): RetentionGroupEntry {\n const labelProperty = this.actionContext.subjectProperty || BaseObjectTypeField.OBJECT_ID;\n return {\n object,\n objectLabel: object.data[labelProperty] as string,\n state\n };\n }\n\n error?: string;\n\n setRetention() {\n this.error = undefined;\n this.busySettingRetention.set(true);\n const retentionStart = new Date();\n const retentionStartClone = new Date(retentionStart);\n const retentionEnd = new Date(retentionStartClone.setFullYear(retentionStart.getFullYear() + this.retentionPeriod()));\n\n this.#retention\n .setRetention(\n this.objectGroups().notUnderRetention.map((o) => o.object),\n retentionStart,\n retentionEnd\n )\n .pipe(finalize(() => this.busySettingRetention.set(false)))\n .subscribe({\n next: () => {\n this.#dialogRef.close(true);\n },\n error: (e) => {\n console.error('Error setting retention', e);\n this.error = this.translate.instant('yuv.app.invoice.action.retention.error.retention.set');\n }\n });\n }\n\n cancel() {\n this.#dialogRef.close(false);\n }\n}\n","<yuv-dialog [headertitel]=\"'yuv.app.invoice.action.retention.confirm.title' | translate\">\n <main>\n @if (error) {\n <p class=\"error\">{{ error }}</p>\n }\n\n @if (objectGroups().underRetention.length) {\n <section>\n <p>{{ 'yuv.app.invoice.action.retention.underRetention.message' | translate }}</p>\n <ul class=\"files\">\n @for (o of objectGroups().underRetention; track $index) {\n <li\n matTooltip=\"{{ o.objectLabel }} ( {{ o.state.start | localeDate: 'shortDate' }} - {{ o.state.end | localeDate: 'shortDate' }} )\"\n [attr.aria-label]=\"o.objectLabel + ' (' + (o.state.start | localeDate: 'shortDate') + ' - ' + (o.state.end | localeDate: 'shortDate') + ')'\"\n >\n {{ o.objectLabel }} <time class=\"date\"> {{ o.state.start | localeDate: 'shortDate' }} - {{ o.state.end | localeDate: 'shortDate' }} </time>\n </li>\n }\n </ul>\n </section>\n }\n @if (objectGroups().notUnderRetention.length) {\n <section class=\"warning\">\n <p>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message' | translate: { years: retentionPeriod() } }}</p>\n <ul class=\"bullets\">\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.1' | translate }}</li>\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.2' | translate }}</li>\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.3' | translate }}</li>\n <li>{{ 'yuv.app.invoice.action.retention.notUnderRetention.message.bullet.4' | translate }}</li>\n </ul>\n </section>\n\n <ul class=\"files\">\n @for (o of objectGroups().notUnderRetention; track $index) {\n <li matTooltip=\"{{ o.objectLabel }}\" [attr.aria-label]=\"o.objectLabel\">{{ o.objectLabel }}</li>\n }\n </ul>\n }\n </main>\n <footer>\n <button ymtButton=\"secondary\" (click)=\"cancel()\">{{ 'yuv.app.invoice.action.retention.action.cancel' | translate }}</button>\n @if (objectGroups().notUnderRetention.length) {\n <button ymtButton=\"primary\" [ngClass]=\"{ spinning: busySettingRetention() }\" (click)=\"setRetention()\">\n {{ 'yuv.app.invoice.action.retention.notUnderRetention.action.confirm' | translate }}\n </button>\n }\n </footer>\n</yuv-dialog>\n","import { inject } from '@angular/core';\nimport { MatDialog } from '@angular/material/dialog';\nimport { TranslateService } from '@ngx-translate/core';\nimport { DmsObject } from '@yuuvis/client-core';\nimport { AbstractContextAction, Action, ActionSupport, SelectionRange } from '@yuuvis/client-framework/actions';\nimport { Observable, of } from 'rxjs';\nimport { RETENTION_PERIOD } from '../../invoice.schema';\nimport { ManageRetentionComponent } from './manage-retention/manage-retention.component';\n\nexport class InvoiceRetentionAction extends AbstractContextAction implements Action {\n private translate = inject(TranslateService);\n #dialog = inject(MatDialog);\n\n id = 'app.invoice.retention';\n label = this.translate.instant('yuv.app.invoice.action.retention.label');\n description = this.translate.instant('yuv.app.invoice.action.retention.description');\n priority = 2;\n icon = 'lock_clock';\n group = 'common';\n range = SelectionRange.SINGLE_SELECT;\n supports: ActionSupport = {};\n\n isExecutable(selection: DmsObject[]) {\n const o = selection[0];\n return of(o && o.sots.includes('appSysteminvoice:invoice'));\n }\n\n run(selection: DmsObject[]): Observable<boolean> {\n this.#dialog.open(ManageRetentionComponent, {\n maxWidth: '90vw',\n data: {\n context: this.context,\n selection,\n retentionPeriod: RETENTION_PERIOD\n }\n });\n return of(true);\n }\n}\n","import { CommonModule } from '@angular/common';\nimport { Component, effect, inject, Type, untracked } from '@angular/core';\nimport { DmsService } from '@yuuvis/client-core';\nimport { MatDialogRef } from '@angular/material/dialog';\nimport { APP_FLAVORS } from '../../invoice.schema';\nimport { AbstractApplyCreateFlavorComponent } from '@yuuvis/client-framework/object-flavor';\n\n@Component({\n selector: 'yin-apply-create-flavor',\n standalone: true,\n imports: [CommonModule],\n templateUrl: './apply-create-flavor.component.html',\n styleUrl: './apply-create-flavor.component.scss'\n})\nexport class ApplyCreateFlavorComponent extends AbstractApplyCreateFlavorComponent {\n #dms = inject(DmsService);\n readonly #dialogRef = inject(MatDialogRef<ApplyCreateFlavorComponent>);\n\n #dataEffect = effect(() => {\n untracked(() => {\n this.#setupApplyComponent();\n });\n });\n\n sc?: { cmp: Type<any>; inputs: any };\n\n #setupApplyComponent() {\n const flavor = APP_FLAVORS.find((f) => f.id === 'io.yuuvis.app.invoice.flavor.invoice')!\n\n this.#dms.getDmsObject(this.createdObjectIDs()[0]).subscribe((dmsObject) => {\n this.sc = {\n inputs: {\n dmsObject,\n flavor: flavor\n },\n cmp: flavor.applyComponent!\n };\n\n if (dmsObject.content?.mimeType === 'application/x-os-invoice-xml') {\n this.#dialogRef.close();\n }\n });\n }\n}\n\n","@if (sc && sc.cmp) {\n <ng-container *ngComponentOutlet=\"sc.cmp; inputs: sc.inputs\"></ng-container>\n}\n","import { ObjectCreateFlavor } from \"@yuuvis/client-core\";\nimport { APP_PREFIX } from \"./invoice.schema\";\nimport { ApplyCreateFlavorComponent } from './components/apply-create-flavor/apply-create-flavor.component';\n\nexport const APP_CREATE_FLAVORS: ObjectCreateFlavor[] = [\n {\n id: 'io.yuuvis.app.invoice.flavor.invoice',\n descriptionKey: 'io.yuuvis.app.invoice.flavor.invoice.description',\n icon: 'local_atm',\n withFileUpload: {\n applicableTo: {\n mimeTypes: ['application/pdf']\n }\n },\n sot: `${APP_PREFIX}invoice`,\n applyComponent: ApplyCreateFlavorComponent\n }\n];\n","import { Injectable, inject } from '@angular/core';\nimport { ActionsService } from '@yuuvis/client-framework/actions';\nimport { ClientShellExtension, ShellService } from '@yuuvis/client-shell-core';\nimport { OpenEmailAction } from '../actions/open-email/open-email.action';\nimport { InvoiceRetentionAction } from '../actions/retention/retention.action';\nimport { APP_CREATE_FLAVORS } from '../invoice.flavor.create';\nimport { APP_FLAVORS } from '../invoice.schema';\n\n@Injectable()\nexport class AppInvoiceExtension implements ClientShellExtension {\n #shell = inject(ShellService);\n #actionsService = inject(ActionsService);\n\n #actions = [\n { id: 'app.invoice.retention', action: InvoiceRetentionAction },\n { id: 'app.invoice.open-email', action: OpenEmailAction },\n ];\n\n init(): Promise<any> {\n this.#enableExtension();\n return Promise.resolve();\n }\n\n #enableExtension() {\n // expose flavors\n this.#shell.exposeObjectFlavors(APP_FLAVORS);\n this.#shell.exposeObjectCreateFlavors(APP_CREATE_FLAVORS);\n // register actions\n this.#actionsService.registerActions(this.#actions);\n }\n}\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":["APP_ID","TranslateService","i1","i6","finalize","i2","i3"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"yuuvis-app-invoice.mjs","sources":["../../../../projects/yuuvis/app-invoice/src/lib/lib.routes.ts","../../../../projects/yuuvis/app-invoice/src/yuuvis-app-invoice.ts"],"sourcesContent":["import { Route } from '@angular/router';\n\nexport const invoiceRoutes: Route[] = [];\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"AAEO,MAAM,aAAa,GAAY;;ACFtC;;AAEG;;;;"}
|
package/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './lib/lib.routes';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{}
|
package/package.json
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yuuvis/app-invoice",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"author": "OPTIMAL SYSTEMS GmbH <npm@optimal-systems.de>",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"peerDependencies": {
|
|
7
|
+
"@angular/common": "^19.2.0",
|
|
8
|
+
"@angular/core": "^19.2.0",
|
|
9
|
+
"@yuuvis/client-shell": "^2.0.0",
|
|
10
|
+
"@yuuvis/material": "^2.0.0"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"tslib": "^2.3.0"
|
|
14
|
+
},
|
|
15
|
+
"sideEffects": false,
|
|
16
|
+
"module": "fesm2022/yuuvis-app-invoice.mjs",
|
|
17
|
+
"typings": "index.d.ts",
|
|
18
|
+
"exports": {
|
|
19
|
+
"./package.json": {
|
|
20
|
+
"default": "./package.json"
|
|
21
|
+
},
|
|
22
|
+
".": {
|
|
23
|
+
"types": "./index.d.ts",
|
|
24
|
+
"default": "./fesm2022/yuuvis-app-invoice.mjs"
|
|
25
|
+
},
|
|
26
|
+
"./extensions": {
|
|
27
|
+
"types": "./extensions/index.d.ts",
|
|
28
|
+
"default": "./fesm2022/yuuvis-app-invoice-extensions.mjs"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|