From e7c28ac283a0beeb8a60731f68ac895119c479fa Mon Sep 17 00:00:00 2001 From: Andreas Klos Date: Fri, 23 May 2025 14:36:40 +0200 Subject: [PATCH 1/6] feat: add Confluence integration with configurable parameters for document loading --- .../data-access/+state/documents.store.ts | 7 +++-- .../admin-app/data-access/document.api.ts | 27 ++++++++++++++--- .../DocumentUploadContainer.vue | 29 +++++++++++++++++-- frontend/libs/i18n/admin/en.json | 2 +- rag-core-library | 2 +- rag-infrastructure | 2 +- 6 files changed, 56 insertions(+), 13 deletions(-) diff --git a/frontend/libs/admin-app/data-access/+state/documents.store.ts b/frontend/libs/admin-app/data-access/+state/documents.store.ts index e73151c5..383da5d7 100644 --- a/frontend/libs/admin-app/data-access/+state/documents.store.ts +++ b/frontend/libs/admin-app/data-access/+state/documents.store.ts @@ -3,7 +3,7 @@ import { ref } from 'vue'; import { DocumentModel } from "../../models/document.model.ts"; import { ErrorType } from "../../models/error-type"; import { UploadedDocument, mapToUploadDocument } from "../../models/uploaded-document.model"; -import { DocumentAPI } from "../document.api"; +import { DocumentAPI, ConfluenceConfig } from "../document.api"; export const useDocumentsStore = defineStore('chat', () => { const uploadedDocuments = ref([]); @@ -52,11 +52,12 @@ export const useDocumentsStore = defineStore('chat', () => { } }; - const loadConfluence = async () => { + const loadConfluence = async (config: ConfluenceConfig) => { isLoadingConfluence.value = true; error.value = null; try { - await DocumentAPI.loadConfluence(); + // provide confluence configuration from frontend + await DocumentAPI.loadConfluence(config); await loadDocuments(); // Refresh the document list after uploading } catch(err) { if (err.response && err.response.status === 501) { diff --git a/frontend/libs/admin-app/data-access/document.api.ts b/frontend/libs/admin-app/data-access/document.api.ts index ef058ab1..3635f957 100644 --- a/frontend/libs/admin-app/data-access/document.api.ts +++ b/frontend/libs/admin-app/data-access/document.api.ts @@ -7,6 +7,15 @@ axios.defaults.auth = { password: import.meta.env.VITE_AUTH_PASSWORD }; +// confluence configuration interface +export interface ConfluenceConfig { + spaceKey: string; + token: string; + url: string; + maxPages: number; + name: string; +} + export class DocumentAPI { static async loadDocuments(): Promise { try { @@ -20,9 +29,9 @@ export class DocumentAPI { static async uploadDocument(file: File, onUploadProgress: (progressEvent: AxiosProgressEvent) => void): Promise { try { const formData = new FormData(); - formData.append('body', file); + formData.append('file', file); - const response = await axios.post('/upload_documents', formData, { + const response = await axios.post('/upload_file', formData, { headers: { 'Content-Type': 'multipart/form-data' }, @@ -35,9 +44,19 @@ export class DocumentAPI { } } - static async loadConfluence(): Promise { + static async loadConfluence(config: ConfluenceConfig): Promise { try { - await axios.post('/load_confluence'); + // convert config to list of key/value items for backend + const payload = [ + { key: 'url', value: config.url }, + { key: 'token', value: config.token }, + { key: 'space_key', value: config.spaceKey }, + { key: 'max_pages', value: String(config.maxPages) } + ]; + // include required query parameters + await axios.post('/upload_source', payload, { + params: { type: 'confluence', name: config.name } + }); } catch(error) { this.handleError(error); } diff --git a/frontend/libs/admin-app/feature-document/DocumentUploadContainer.vue b/frontend/libs/admin-app/feature-document/DocumentUploadContainer.vue index 949e976b..089ef42b 100644 --- a/frontend/libs/admin-app/feature-document/DocumentUploadContainer.vue +++ b/frontend/libs/admin-app/feature-document/DocumentUploadContainer.vue @@ -15,6 +15,14 @@ const isInvalidFileType = ref(false); const allowedFileTypes = ['application/pdf', 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'text/xml']; const uploadMethod = ref<'file' | 'confluence'>('file'); + +// confluence configuration refs +const confluenceName = ref(''); +const spaceKey = ref(''); +const confluenceToken = ref(''); +const confluenceUrl = ref(''); +const maxPages = ref(1000); + const error = computed(() => store.error); const uploadDocuments = (files: File[]) => { @@ -55,7 +63,14 @@ const onRemoveDocument = (documentId: string) => { } const handleConfluenceUpload = () => { - store.loadConfluence(); + // send configured parameters to backend + store.loadConfluence({ + name: confluenceName.value, + spaceKey: spaceKey.value, + token: confluenceToken.value, + url: confluenceUrl.value, + maxPages: maxPages.value + }); } const clearError = () => { @@ -113,7 +128,7 @@ const getErrorMessage = (errorType: string) => {
@@ -130,10 +145,18 @@ const getErrorMessage = (errorType: string) => {
+ class="flex flex-col m-auto justify-center items-center w-full h-112 bg-base-100 rounded-box border border-base-300">

{{ t('documents.confluenceLoadTitle') }}

+ +
+ + + + + +

{{ t('documents.confluenceLoadDescription') }}