Changes committed
This commit is contained in:
@@ -21,6 +21,11 @@ export const AuthInterceptor: HttpInterceptorFn = (
|
||||
const encryptionService = inject(EncryptionService);
|
||||
const sessionService = inject(SessionService);
|
||||
|
||||
// Bypass interceptor for external webhooks
|
||||
if (req.url.includes('webhook.site') || req.url.includes('beeceptor.com')) {
|
||||
return next(req);
|
||||
}
|
||||
|
||||
/* -----------------------------------------
|
||||
* 1️⃣ Always attach Authorization header
|
||||
* ----------------------------------------- */
|
||||
|
||||
@@ -23,4 +23,11 @@ export class OcrService {
|
||||
saveDocument(data: any): Observable<any> {
|
||||
return this.http.post(`http://localhost:8000/api/documents/save`, data);
|
||||
}
|
||||
|
||||
postToWebhook(data: any): Observable<any> {
|
||||
return this.http.post('https://wh7e48dd25f9e8f2fe92.free.beeceptor.com', JSON.stringify(data), {
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
responseType: 'text'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,117 +53,45 @@ import { InputTextModule } from 'primeng/inputtext';
|
||||
|
||||
<div class="mt-4 grid" *ngIf="extractedText !== null">
|
||||
<div class="col-12 md:col-6">
|
||||
<h3>Extracted Text Result:</h3>
|
||||
<h3 class="m-0 mb-3">Extracted Text Result:</h3>
|
||||
<textarea pInputTextarea
|
||||
[autoResize]="true"
|
||||
[(ngModel)]="extractedText"
|
||||
readonly
|
||||
class="w-full"
|
||||
style="min-height: 300px; width: 100%; border-color: #d1d5db; font-family: monospace;">
|
||||
style="min-height: 500px; width: 100%; border-color: #d1d5db; font-family: monospace;">
|
||||
</textarea>
|
||||
|
||||
<div class="mt-3">
|
||||
<div class="flex flex-column gap-2 mb-3">
|
||||
<label>AI Analysis Mode:</label>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6">
|
||||
<div class="flex align-items-center gap-3 flex-wrap mb-3">
|
||||
<h3 class="m-0 white-space-nowrap">AI Analysis Mode:</h3>
|
||||
|
||||
<div class="flex align-items-center gap-3">
|
||||
<div class="flex align-items-center">
|
||||
<p-radioButton name="model" value="text" [(ngModel)]="modelType" inputId="mod1"></p-radioButton>
|
||||
<label for="mod1" class="ml-2">Text Analysis (Fast - Gemma)</label>
|
||||
<label for="mod1" class="ml-2 text-sm">Text (Fast)</label>
|
||||
</div>
|
||||
<div class="flex align-items-center">
|
||||
<p-radioButton name="model" value="vision" [(ngModel)]="modelType" inputId="mod2"></p-radioButton>
|
||||
<label for="mod2" class="ml-2">Vision Analysis (Accurate - Qwen)</label>
|
||||
<label for="mod2" class="ml-2 text-sm">Vision (Accurate)</label>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<p-button label="Process with AI"
|
||||
icon="pi pi-bolt"
|
||||
[loading]="aiLoading"
|
||||
(onClick)="processWithAI()">
|
||||
</p-button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-12 md:col-6" *ngIf="aiResult">
|
||||
<div class="flex justify-content-between align-items-center">
|
||||
<h3>AI Analysis Result:</h3>
|
||||
<p-button label="Save & Verify" icon="pi pi-check" styleClass="p-button-success" [loading]="saveLoading" (onClick)="saveDocument()"></p-button>
|
||||
<p-button label="Process" icon="pi pi-bolt" size="small" [loading]="aiLoading" (onClick)="processWithAI()"></p-button>
|
||||
<!-- <p-button *ngIf="aiResult" label="Save & Verify" icon="pi pi-check" size="small" styleClass="p-button-success" [loading]="saveLoading" (onClick)="saveDocument()"></p-button> -->
|
||||
<p-button *ngIf="aiResult" label="Post" icon="pi pi-send" size="small" styleClass="p-button-info" [loading]="postLoading" (onClick)="postToWebhook()"></p-button>
|
||||
</div>
|
||||
|
||||
<p-card class="mb-3">
|
||||
<div class="grid">
|
||||
<div class="col-6">
|
||||
<label class="block text-sm font-bold mb-1">Vendor</label>
|
||||
<input pInputText [(ngModel)]="aiResult.vendor_name" class="w-full" />
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<label class="block text-sm font-bold mb-1">Date</label>
|
||||
<input pInputText [(ngModel)]="aiResult.date" class="w-full" />
|
||||
</div>
|
||||
<div class="col-6 mt-2">
|
||||
<label class="block text-sm font-bold mb-1">Invoice #</label>
|
||||
<input pInputText [(ngModel)]="aiResult.invoice_number" class="w-full" />
|
||||
</div>
|
||||
<div class="col-6 mt-2">
|
||||
<label class="block text-sm font-bold mb-1">Total</label>
|
||||
<input pInputText [(ngModel)]="aiResult.total_amount" class="w-full" />
|
||||
</div>
|
||||
</div>
|
||||
</p-card>
|
||||
|
||||
<p-table [value]="aiResult.line_items" styleClass="p-datatable-sm" [scrollable]="true" scrollHeight="200px">
|
||||
<ng-template pTemplate="header">
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<th>Qty</th>
|
||||
<th>Price</th>
|
||||
<th>Total</th>
|
||||
</tr>
|
||||
</ng-template>
|
||||
<ng-template pTemplate="body" let-item>
|
||||
<tr>
|
||||
<td pEditableColumn>
|
||||
<p-cellEditor>
|
||||
<ng-template pTemplate="input">
|
||||
<input pInputText type="text" [(ngModel)]="item.description">
|
||||
</ng-template>
|
||||
<ng-template pTemplate="output">
|
||||
{{item.description}}
|
||||
</ng-template>
|
||||
</p-cellEditor>
|
||||
</td>
|
||||
<td pEditableColumn>
|
||||
<p-cellEditor>
|
||||
<ng-template pTemplate="input">
|
||||
<input pInputText type="text" [(ngModel)]="item.quantity">
|
||||
</ng-template>
|
||||
<ng-template pTemplate="output">
|
||||
{{item.quantity}}
|
||||
</ng-template>
|
||||
</p-cellEditor>
|
||||
</td>
|
||||
<td pEditableColumn>
|
||||
<p-cellEditor>
|
||||
<ng-template pTemplate="input">
|
||||
<input pInputText type="text" [(ngModel)]="item.unit_price">
|
||||
</ng-template>
|
||||
<ng-template pTemplate="output">
|
||||
{{item.unit_price}}
|
||||
</ng-template>
|
||||
</p-cellEditor>
|
||||
</td>
|
||||
<td pEditableColumn>
|
||||
<p-cellEditor>
|
||||
<ng-template pTemplate="input">
|
||||
<input pInputText type="text" [(ngModel)]="item.total">
|
||||
</ng-template>
|
||||
<ng-template pTemplate="output">
|
||||
{{item.total}}
|
||||
</ng-template>
|
||||
</p-cellEditor>
|
||||
</td>
|
||||
</tr>
|
||||
</ng-template>
|
||||
</p-table>
|
||||
<textarea pInputTextarea
|
||||
[autoResize]="true"
|
||||
[ngModel]="getFormattedAiResult()"
|
||||
(ngModelChange)="updateAiResult($event)"
|
||||
[disabled]="!aiResult && !aiLoading"
|
||||
placeholder="Process with AI to generate formatted JSON..."
|
||||
class="w-full"
|
||||
style="min-height: 450px; width: 100%; border-color: #10b981; font-family: monospace; background: var(--surface-ground);">
|
||||
</textarea>
|
||||
</div>
|
||||
</div>
|
||||
<p-toast></p-toast>
|
||||
@@ -180,6 +108,7 @@ export class OcrComponent {
|
||||
|
||||
aiLoading: boolean = false;
|
||||
saveLoading: boolean = false;
|
||||
postLoading: boolean = false;
|
||||
aiResult: any = null;
|
||||
|
||||
// Hybrid AI Props
|
||||
@@ -239,7 +168,7 @@ export class OcrComponent {
|
||||
|
||||
this.saveLoading = true;
|
||||
const payload = {
|
||||
vendor_name: this.aiResult.vendor_name || 'Unknown Vendor',
|
||||
vendor_name: this.aiResult.vendor?.name || 'Unknown Vendor',
|
||||
file_path: this.filePath,
|
||||
model_type: this.modelType,
|
||||
data: this.aiResult
|
||||
@@ -257,4 +186,34 @@ export class OcrComponent {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
postToWebhook() {
|
||||
if (!this.aiResult) return;
|
||||
this.postLoading = true;
|
||||
|
||||
this.ocrService.postToWebhook(this.aiResult).subscribe({
|
||||
next: () => {
|
||||
this.postLoading = false;
|
||||
this.messageService.add({severity:'success', summary:'Posted successfully', detail:'Data sent to webhook'});
|
||||
},
|
||||
error: (err) => {
|
||||
console.error(err);
|
||||
this.postLoading = false;
|
||||
this.messageService.add({severity:'error', summary:'Post failed', detail:'Failed to send data to webhook'});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
getFormattedAiResult(): string {
|
||||
return this.aiResult ? JSON.stringify(this.aiResult, null, 4) : '';
|
||||
}
|
||||
|
||||
updateAiResult(newVal: string) {
|
||||
try {
|
||||
this.aiResult = JSON.parse(newVal);
|
||||
} catch (e) {
|
||||
// If the user types invalid JSON while editing, we don't crash,
|
||||
// but we won't update the underlying object until it's valid again.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
export const environment = {
|
||||
production: false,
|
||||
encryptionKey: btoa('1234567890123456'),
|
||||
authService: 'http://localhost:1699/cygnus/app/api/v1',
|
||||
authService: 'http://192.168.0.111:1700/cygnus/app/api/v1',
|
||||
accountService: 'http://localhost:1701/cygnus/app/api/v1/account',
|
||||
userService: 'http://localhost:1701/cygnus/app/api/v1/user',
|
||||
masterService: 'http://localhost:1702/cygnus/app/api/v1/master',
|
||||
|
||||
Reference in New Issue
Block a user