multiple branches repository clone functionality implemented

This commit is contained in:
sumedh
2024-08-29 22:58:42 +05:30
parent 9a6d807054
commit 5318441cd9
3 changed files with 73 additions and 79 deletions

View File

@@ -1,17 +1,20 @@
<template> <template>
<div class="card"> <div class="card">
<Toast/>
<ConfirmPopup></ConfirmPopup>
<div v-if="loading" class="loading-container"> <div v-if="loading" class="loading-container">
<div class="spinner-container"> <div class="spinner-container">
<ProgressSpinner class="spinner" /> <ProgressSpinner class="spinner" />
<p class="loading-text">Loading data...</p> <p class="loading-text">Loading data...</p>
</div> </div>
</div> </div>
<DataTable v-model:filters="filters" :value="ksdocuments" paginator showGridlines :rows="10" dataKey="id" <DataTable v-model:filters="filters" :value="ksdocuments" paginator showGridlines :rows="10" dataKey="id"
filterDisplay="menu" :loading="loading" filterDisplay="menu" :loading="loading"
:globalFilterFields="['ingestionInfo.metadata.KsApplicationName', 'ingestionInfo.metadata.KsFileSources', 'ingestionInfo.metadata.KsDocSource', 'ingestionStatus', 'ingestionDateFormat']"> :globalFilterFields="['ingestionInfo.metadata.KsApplicationName', 'ingestionInfo.metadata.KsFileSources', 'ingestionInfo.metadata.KsDocSource', 'ingestionStatus', 'ingestionDateFormat']">
<template #header> <template #header>
<div class="flex items-center justify-between gap-4 p-4 "> <div class="flex items-center justify-between gap-4 p-4 ">
<span class="text-xl font-bold">KS Documents</span> <span class="text-xl font-bold">Knowledge Source Documents</span>
<div class="flex items-center gap-2 flex-grow"> <div class="flex items-center gap-2 flex-grow">
<IconField class="flex-grow"> <IconField class="flex-grow">
<InputIcon> <InputIcon>
@@ -29,14 +32,7 @@
</template> </template>
<template #empty>No Records found</template> <template #empty>No Records found</template>
<!--Column field="id" header="id" sortable style="min-width: 12rem"> <Column field="ingestionInfo.metadata.KsApplicationName" header="ApplicationName" sortable
<template #body="slotProps">
<Tag>ksdocuments: {{ slotProps.data.id }}</Tag>
<Tag>ksingestioninfo: {{ slotProps.data.ingestionInfo.id }}</Tag>
</template>
</Column-->
<!--Column field="ingestionInfo.id" header="ksingestioninfo id" sortable style="min-width: 12rem" /-->
<Column field="ingestionInfo.metadata.KsApplicationName" header="KSApplicationName" sortable
style="min-width: 12rem"> style="min-width: 12rem">
<template #body="{ data }"> <template #body="{ data }">
{{ data.ingestionInfo.metadata.KsApplicationName }} {{ data.ingestionInfo.metadata.KsApplicationName }}
@@ -45,7 +41,7 @@
<InputText v-model="filterModel.value" type="text" @input="filterCallback()" placeholder="Search by File" /> <InputText v-model="filterModel.value" type="text" @input="filterCallback()" placeholder="Search by File" />
</template> </template>
</Column> </Column>
<Column field="ingestionInfo.metadata.KsFileSource" header="KsFileSource" sortable> <Column field="ingestionInfo.metadata.KsFileSource" header="FileSource" sortable>
<template #body="{ data }"> <template #body="{ data }">
{{ data.ingestionInfo.metadata.KsFileSource }} {{ data.ingestionInfo.metadata.KsFileSource }}
</template> </template>
@@ -54,7 +50,7 @@
placeholder="Search by File Name" /> placeholder="Search by File Name" />
</template> </template>
</Column> </Column>
<Column field="ingestionInfo.metadata.KsDocSource" header="KsDocSource" sortable style="min-width: 12rem"> <Column field="ingestionInfo.metadata.KsDocSource" header="DocSource" sortable style="min-width: 12rem">
<template #body="{ data }"> <template #body="{ data }">
{{ data.ingestionInfo.metadata.KsDocSource }} {{ data.ingestionInfo.metadata.KsDocSource }}
</template> </template>
@@ -75,7 +71,7 @@
</Select> </Select>
</template> </template>
</Column> </Column>
<Column header="Ingestion Date" filterField="ingestionDateFormat" dataType="date" style="min-width: 10rem"> <Column header="Date" filterField="ingestionDateFormat" dataType="date" style="min-width: 10rem">
<template #body="{ data }"> <template #body="{ data }">
{{ formatDate(data.ingestionDate) }} {{ formatDate(data.ingestionDate) }}
</template> </template>
@@ -92,18 +88,9 @@
<Button type="button" icon="pi pi-play" rounded @click="startIndividualngestion(slotProps.data.id)" <Button type="button" icon="pi pi-play" rounded @click="startIndividualngestion(slotProps.data.id)"
v-tooltip="'Start Ingestion of document'" :disabled="slotProps.data.ingestionStatus === 'INGESTED'" v-tooltip="'Start Ingestion of document'" :disabled="slotProps.data.ingestionStatus === 'INGESTED'"
:class="{ 'p-button-danger': slotProps.data.ingestionStatus === 'INGESTED' }" /> :class="{ 'p-button-danger': slotProps.data.ingestionStatus === 'INGESTED' }" />
<Button type="button" icon="pi pi-trash" rounded @click="showConfirmDialog(slotProps.data.id)" <Button type="button" icon="pi pi-trash" rounded @click="confirmDelete(slotProps.data.id)"
v-tooltip="'Delete the ingested Record'" :disabled="slotProps.data.ingestionStatus === 'NEW'" v-tooltip="'Delete the ingested Record'" :disabled="slotProps.data.ingestionStatus === 'NEW'"
:class="{ 'p-button-danger': slotProps.data.ingestionStatus === 'NEW' }" /> :class="{ 'p-button-danger': slotProps.data.ingestionStatus === 'NEW' }" />
<Dialog header="Confirm Deletion" :visible="confirmDialogVisible" modal @hide="resetConfirmDialog"
:style="{ width: '300px' }">
<p>Are you sure you want to delete this record?</p>
<template #footer>
<Button label="No" icon="pi pi-times" @click="confirmDialogVisible = false"/>
<Button label="Yes" icon="pi pi-check" @click="confirmDelete" class="p-button-danger" />
</template>
</Dialog>
</div> </div>
</template> </template>
</Column> </Column>
@@ -120,6 +107,8 @@ import { FilterMatchMode, FilterOperator } from '@primevue/core/api';
import axios from 'axios'; import axios from 'axios';
import { computed, onMounted, ref } from 'vue'; import { computed, onMounted, ref } from 'vue';
import { useRouter } from 'vue-router'; import { useRouter } from 'vue-router';
import { useToast } from 'primevue/usetoast';
import { useConfirm } from "primevue/useconfirm";
import moment from 'moment'; import moment from 'moment';
import Button from 'primevue/button'; import Button from 'primevue/button';
@@ -137,14 +126,13 @@ import ProgressSpinner from 'primevue/progressspinner';
const router = useRouter() const router = useRouter()
const ksdocuments = ref(null); const ksdocuments = ref(null);
const loading = ref(true); const loading = ref(true);
const toast = useToast();
const confirm = useConfirm();
const ingestionDialogVisible = ref(false); const ingestionDialogVisible = ref(false);
const ingestionResult = ref(''); const ingestionResult = ref('');
const filters = ref(); const filters = ref();
const confirmDialogVisible = ref(false);
const recordToDelete = ref(null);
const initFilters = () => { const initFilters = () => {
filters.value = { filters.value = {
global: { value: null, matchMode: FilterMatchMode.CONTAINS }, global: { value: null, matchMode: FilterMatchMode.CONTAINS },
@@ -202,56 +190,61 @@ const editKsDocument = (data) => {
router.push({ name: 'ks-document-edit', params: { id: data.id } }); router.push({ name: 'ks-document-edit', params: { id: data.id } });
} }
//delete functionality const confirmDelete = (id) =>{
function showConfirmDialog(id) { console.log("id",id);
recordToDelete.value = id;
confirmDialogVisible.value = true;
}
function confirmDelete() { confirm.require({
if (recordToDelete.value !== null) { target: event.currentTarget,
deleteRecordsFromVectorStore(recordToDelete.value); message: 'Are you sure you want to proceed?',
recordToDelete.value = null; icon: 'pi pi-exclamation-triangle',
} rejectProps: {
confirmDialogVisible.value = false; label: 'Cancel',
} severity: 'secondary',
outlined: true
},
acceptProps: {
label: 'Delete',
severity: 'danger',
},
accept: () => {
const documentToDelete = ksdocuments.value.find(doc => doc.id === id);
console.log("documentToDelete",documentToDelete)
if (!documentToDelete) {
console.error('Document not found');
return;
}
function resetConfirmDialog() { const requestPayload = {
recordToDelete.value = null; ksDocumentId: id,
} ksIngestionInfoId: documentToDelete.ingestionInfo.id,
ksDoctype: documentToDelete.ingestionInfo.metadata.KsDoctype,
ksDocSource: documentToDelete.ingestionInfo.metadata.KsDocSource,
ksFileSource: documentToDelete.ingestionInfo.metadata.KsFileSource,
ksApplicationName: documentToDelete.ingestionInfo.metadata.KsApplicationName,
};
console.log("requestPayload",requestPayload)
axios.post('/fe-api/vector-store/deleteRecords', requestPayload)
const deleteRecordsFromVectorStore = (id) => { .then(response => {
const documentToDelete = ksdocuments.value.find(doc => doc.id === id); console.log('Delete resource:', response.data)
ksdocuments.value = ksdocuments.value.filter(doc => doc.id !== id);
if (!documentToDelete) { console.log('ksdocuments.value',ksdocuments.value)
console.error('Document not found'); toast.add({ severity: 'info', summary: 'Confirmed', detail: 'deletion is in PROGRESS', life: 3000 });
return; })
} .catch(error => {
console.error('Error deleting records: ', error)
const requestPayload = { toast.add({ severity: 'error', summary: 'Error', detail: 'Error in Deletion', life: 3000 });
ksDocumentId: id, });
ksIngestionInfoId: documentToDelete.ingestionInfo.id, },
ksDoctype: documentToDelete.ingestionInfo.metadata.KsDoctype, reject: () => {
ksDocSource: documentToDelete.ingestionInfo.metadata.KsDocSource, toast.add({severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000})
ksFileSource: documentToDelete.ingestionInfo.metadata.KsFileSource, }
ksApplicationName: documentToDelete.ingestionInfo.metadata.KsApplicationName, })
}; };
axios.post('/fe-api/vector-store/deleteRecords', requestPayload)
.then(response => {
console.log('Delete resource:', response.data)
ksdocuments.value = ksdocuments.value.filter(doc => doc.id !== id);
})
.catch(error => {
console.error('Error deleting records: ', error)
});
}
//ingestion //ingestion
const startIndividualngestion = (id) => { const startIndividualngestion = (id) => {
axios.get(`/test/ingest_document/${id}`) axios.get(`/test/ingest_document/${id}`)
//axios.get('/test/ingestion_loop')
.then(response => { .then(response => {
ingestionResult.value = response.data; ingestionResult.value = response.data;
if (response.data.status == "OK") { if (response.data.status == "OK") {

View File

@@ -31,12 +31,12 @@
<label for="tokenType">Git Token Type</label> <label for="tokenType">Git Token Type</label>
<InputText id="tokenType" type="text" v-model="formData.tokenType" required class="w-full" /> <InputText id="tokenType" type="text" v-model="formData.tokenType" required class="w-full" />
</div> </div>
<div class="col-12 mb-4"> <!--div class="col-12 mb-4">
<span class="p-float-label"> <span class="p-float-label">
<label for="repoPath">Repo Path</label> <label for="repoPath">Repo Path</label>
<InputText id="repoPath" v-model="formData.repoPath" required class="w-full" /> <InputText id="repoPath" v-model="formData.repoPath" required class="w-full" />
</span> </span>
</div> </div-->
<div class="flex flex-col gap-2"> <div class="flex flex-col gap-2">
<label for="defaultChunkSize">Default Chunk Size</label> <label for="defaultChunkSize">Default Chunk Size</label>
<InputNumber id="defaultChunkSize" v-model="formData.defaultChunkSize" required class="w-full" /> <InputNumber id="defaultChunkSize" v-model="formData.defaultChunkSize" required class="w-full" />
@@ -100,7 +100,7 @@ const submitForm = async () => {
formDataToSend.append('branch', formData.value.branch); formDataToSend.append('branch', formData.value.branch);
formDataToSend.append('commitId', formData.value.commitId); formDataToSend.append('commitId', formData.value.commitId);
formDataToSend.append('tokenType', formData.value.tokenType); formDataToSend.append('tokenType', formData.value.tokenType);
formDataToSend.append('repoPath', formData.value.repoPath); //formDataToSend.append('repoPath', formData.value.repoPath);
formDataToSend.append('defaultChunkSize', formData.value.defaultChunkSize); formDataToSend.append('defaultChunkSize', formData.value.defaultChunkSize);
formDataToSend.append('minChunkSize', formData.value.minChunkSize); formDataToSend.append('minChunkSize', formData.value.minChunkSize);
formDataToSend.append('maxNumberOfChunks', formData.value.maxNumberOfChunks); formDataToSend.append('maxNumberOfChunks', formData.value.maxNumberOfChunks);

View File

@@ -201,31 +201,31 @@ const getCustomDatewithAllResponse = (data) => {
const ingestGitRepo = (repo) => { const ingestGitRepo = (repo) => {
axios axios
.get(`/test/ingest_repo/${repo.repoName}`) .get(`/test/ingest_repo?repoName=${repo.repoName}&branchName=${repo.branch}`)
.then((response) => { .then((response) => {
showPopup('Ingestion started', 'info'); showPopup('Ingestion started', 'info');
toast.add({ severity: 'success', summary: 'Ingestion Summary', detail: 'Repository Ingestion Started', life: 3000 }); toast.add({ severity: 'success', summary: 'Ingestion Summary', detail: 'Repository Ingestion Started', life: 3000 });
startPollingStatus(repo.repoName); startPollingStatus(repo);
}) })
.catch((error) => { .catch((error) => {
showPopup('Error starting ingestion', 'error'); showPopup('Error starting ingestion', 'error');
}); });
}; };
const startPollingStatus = (repoName) => { const startPollingStatus = (repo) => {
if (checkStatusInterval) { if (checkStatusInterval) {
// Prevent starting multiple intervals if there's already one running // Prevent starting multiple intervals if there's already one running
clearInterval(checkStatusInterval); clearInterval(checkStatusInterval);
} }
checkStatusInterval = setInterval(() => { checkStatusInterval = setInterval(() => {
checkIngestionStatus(repoName); checkIngestionStatus(repo);
}, 100000); // Poll every 1 minute }, 100000); // Poll every 1 minute
}; };
const checkIngestionStatus = (repoName) => { const checkIngestionStatus = (repo) => {
axios axios
.get(`/test/check_ingestion_status/${repoName}`) .get(`/test/check_ingestion_status?repoName=${repo.repoName}&branchName=${repo.branch}`)
.then((response) => { .then((response) => {
const data = response.data; const data = response.data;
if (data.status === 'INGESTED') { if (data.status === 'INGESTED') {
@@ -329,7 +329,8 @@ const deleteRecordsFromVectorStore = (id) => {
ksDoctype: ksGitInfoToDelete.ksGitIngestionInfo.metadata.KsDoctype, ksDoctype: ksGitInfoToDelete.ksGitIngestionInfo.metadata.KsDoctype,
ksDocSource: ksGitInfoToDelete.ksGitIngestionInfo.metadata.KsDocSource, ksDocSource: ksGitInfoToDelete.ksGitIngestionInfo.metadata.KsDocSource,
ksFileSource: ksGitInfoToDelete.ksGitIngestionInfo.metadata.KsFileSource, ksFileSource: ksGitInfoToDelete.ksGitIngestionInfo.metadata.KsFileSource,
ksApplicationName: ksGitInfoToDelete.ksGitIngestionInfo.metadata.KsApplicationName ksApplicationName: ksGitInfoToDelete.ksGitIngestionInfo.metadata.KsApplicationName,
ksBranch: ksGitInfoToDelete.ksGitIngestionInfo.metadata.KsBranch
}; };
axios.post('/fe-api/vector-store/deleteGitRecords', requestPayload) axios.post('/fe-api/vector-store/deleteGitRecords', requestPayload)
@@ -360,7 +361,7 @@ const reIngestWithPullChanges = (data) =>{
severity: 'danger', severity: 'danger',
}, },
accept: () => { accept: () => {
axios.get('/test/reingest_repo/'+data.repoName) axios.get('/test/reingest_repo?repoName=${data.repoName}&branchName=${data.branch}')
.then(response => { .then(response => {
console.log(response.data); console.log(response.data);
toast.add({ severity: 'info', summary: 'Confirmed', detail: 'ReIngestion with latest pull from master started', life: 3000 }); toast.add({ severity: 'info', summary: 'Confirmed', detail: 'ReIngestion with latest pull from master started', life: 3000 });