vectore datatable and few modifications

This commit is contained in:
sumedh
2024-08-07 12:10:50 +05:30
parent 55a547d573
commit ec5c382c3d
8 changed files with 281 additions and 172 deletions

View File

@@ -9,7 +9,7 @@
"editor.formatOnSave": true "editor.formatOnSave": true
}, },
"[vue]": { "[vue]": {
"editor.defaultFormatter": "esbenp.prettier-vscode", "editor.defaultFormatter": "Vue.volar",
"editor.formatOnSave": true "editor.formatOnSave": true
}, },
"[typescript]": { "[typescript]": {

View File

@@ -5,7 +5,7 @@
<meta charset="UTF-8"> <meta charset="UTF-8">
<link rel="icon" href="/favicon.ico"> <link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Sakai Vue</title> <title>Apollo</title>
<link href="https://cdn.jsdelivr.net/npm/@vetixy/circular-std@1.0.0/dist/index.min.css" rel="stylesheet"> <link href="https://cdn.jsdelivr.net/npm/@vetixy/circular-std@1.0.0/dist/index.min.css" rel="stylesheet">
</head> </head>

View File

@@ -1,8 +1,8 @@
<template> <template>
<div class="code-snippet-container"> <div class="code-snippet-container">
<div class="button-container h-8 w-8 p-0 inline-flex items-center justify-center"> <div class="button-container h-8 w-8 p-0 inline-flex items-center justify-center">
<!-- Button to copy code to clipboard --> <!-- Button to copy code to clipboard -->
<Button icon="pi pi-copy" @click="copyToClipboard" class="p-mt-2" /> <Button icon="pi pi-copy" @click="copyToClipboard" class="p-mt-2" />
</div> </div>
<!-- Code display area with syntax highlighting --> <!-- Code display area with syntax highlighting -->
<pre v-html="highlightedCode"></pre> <pre v-html="highlightedCode"></pre>
@@ -51,14 +51,17 @@ function copyToClipboard() {
<style scoped> <style scoped>
.code-snippet-container { .code-snippet-container {
position: relative; /* Enable positioning of child elements */ position: relative;
/* Enable positioning of child elements */
} }
.class="button-container" { .class="button-container" {
position: sticky; position: sticky;
top: 10px; /* Adjust as needed */ top: 10px;
right: 10px; /* Adjust as needed */ /* Adjust as needed */
z-index: 1000; right: 10px;
/* Adjust as needed */
z-index: 1000;
} }
pre { pre {
@@ -72,8 +75,10 @@ pre {
.button-container { .button-container {
position: absolute; position: absolute;
top: 10px; /* Adjust as needed */ top: 10px;
right: 10px; /* Adjust as needed */ /* Adjust as needed */
right: 10px;
/* Adjust as needed */
} }
.p-mt-2 { .p-mt-2 {

View File

@@ -13,7 +13,8 @@ const model = ref([
{ {
label: 'Vector Database', label: 'Vector Database',
items: [{ label: 'Dashboard', icon: 'pi pi-fw pi-home', to: '/' }, items: [{ label: 'Dashboard', icon: 'pi pi-fw pi-home', to: '/' },
{ label: 'Similarity Search', icon: 'pi pi-fw pi-search', to: '/ks_similarity_search' } { label: 'Similarity Search', icon: 'pi pi-fw pi-search', to: '/ks_similarity_search' },
{ label: 'Vector Database Search', icon: 'pi pi-fw pi-search', to: '/ks_vector_data' }
] ]
}, },
]); ]);

View File

@@ -20,6 +20,7 @@ const router = createRouter({
{path: 'new', name: 'ks-document-new', component: () => import('@/views/pages/KsNewDocumentForm.vue')}, {path: 'new', name: 'ks-document-new', component: () => import('@/views/pages/KsNewDocumentForm.vue')},
//{path: ':id', name: 'ks-document-edit', component: () => import('@/views/pages/KsEditDocumentForm.vue')}, //{path: ':id', name: 'ks-document-edit', component: () => import('@/views/pages/KsEditDocumentForm.vue')},
{path: '/ks_similarity_search', name: 'ks_similarity_search', component: () => import('@/views/pages/KsSimilaritySearch.vue')}, {path: '/ks_similarity_search', name: 'ks_similarity_search', component: () => import('@/views/pages/KsSimilaritySearch.vue')},
{path: '/ks_vector_data', name: 'ks_vector_data', component: () => import('@/views/pages/KsVectorData.vue')}
] ]

View File

@@ -1,87 +1,90 @@
<template> <template>
<div className="card"> <div className="card">
<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" :globalFilterFields="['name', 'fileName', 'ingestionStatus', 'ingestionDateFormat']"> filterDisplay="menu" :loading="loading"
<template #header> :globalFilterFields="['name', 'fileName', 'ingestionStatus', 'ingestionDateFormat']">
<div class="flex items-center justify-between gap-4 p-4 "> <template #header>
<span class="text-xl font-bold">KS Documents</span> <div class="flex items-center justify-between gap-4 p-4 ">
<div class="flex items-center gap-2 flex-grow"> <span class="text-xl font-bold">KS Documents</span>
<IconField class="flex-grow"> <div class="flex items-center gap-2 flex-grow">
<InputIcon> <IconField class="flex-grow">
<i class="pi pi-search" /> <InputIcon>
</InputIcon> <i class="pi pi-search" />
<InputText v-model="filters['global'].value" placeholder="Keyword Search" /> </InputIcon>
</IconField> <InputText v-model="filters['global'].value" placeholder="Keyword Search" />
</div> </IconField>
<Button icon="pi pi-plus" rounded raised @click="newKsDocument()" v-tooltip="'Create New Document'" class="mr-2" /> </div>
<Button icon="pi pi-check-circle" rounded raised @click="startlngestion()" v-tooltip="'Start All documents Ingestion'" class="mr-8" :disabled="allDocumentsIngested" :class="{ 'p-button-danger': allDocumentsIngested }"/> <Button icon="pi pi-plus" rounded raised @click="newKsDocument()" v-tooltip="'Create New Document'"
</div> class="mr-2" />
</template> <Button icon="pi pi-check-circle" rounded raised @click="startlngestion()"
<template #empty>No Records found</template> v-tooltip="'Start All documents Ingestion'" class="mr-8" :disabled="allDocumentsIngested"
<template #loading>Loading Data. Please wait....</template> :class="{ 'p-button-danger': allDocumentsIngested }" />
<Column field="id" header="ksdocuments id" sortable style="min-width: 12rem"/> </div>
<Column field="ingestionInfo.id" header="ksingestioninfo id" sortable style="min-width: 12rem"/> </template>
<Column field="name" header="Name" sortable style="min-width: 12rem"> <template #empty>No Records found</template>
<template #body="{ data }"> <template #loading>Loading Data. Please wait....</template>
{{ data.name }} <Column field="id" header="ksdocuments id" sortable style="min-width: 12rem" />
</template> <Column field="ingestionInfo.id" header="ksingestioninfo id" sortable style="min-width: 12rem" />
<template #filter="{ filterModel, filterCallback }"> <Column field="name" header="Name" sortable style="min-width: 12rem">
<InputText v-model="filterModel.value" type="text" @input="filterCallback()" placeholder="Search by File" /> <template #body="{ data }">
</template> {{ data.name }}
</Column> </template>
<Column field="fileName" header="File Name" sortable > <template #filter="{ filterModel, filterCallback }">
<template #body="{ data }"> <InputText v-model="filterModel.value" type="text" @input="filterCallback()" placeholder="Search by File" />
{{ data.fileName }} </template>
</template> </Column>
<template #filter="{ filterModel, filterCallback }"> <Column field="fileName" header="File Name" sortable>
<InputText v-model="filterModel.value" type="text" @input="filterCallback()" placeholder="Search by File Name" /> <template #body="{ data }">
</template> {{ data.fileName }}
</Column> </template>
<Column field="ingestionStatus" header="Status" sortable > <template #filter="{ filterModel, filterCallback }">
<template #body="slotProps"> <InputText v-model="filterModel.value" type="text" @input="filterCallback()"
<Tag :value="slotProps.data.ingestionStatus" :severity="getStatus(slotProps.data)" /> placeholder="Search by File Name" />
</template> </template>
<template #filter="{ filterModel, filterCallback }"> </Column>
<Select v-model="filterModel.value" @change="filterCallback()" :options="statuses" placeholder="Select One" style="min-width: 12rem" :showClear="true"> <Column field="ingestionStatus" header="Status" sortable>
<template #option="{ option }"> <template #body="slotProps">
<Tag :value="option" :severity="getStatus({ ingestionStatus: option })" /> <Tag :value="slotProps.data.ingestionStatus" :severity="getStatus(slotProps.data)" />
</template> </template>
</Select> <template #filter="{ filterModel, filterCallback }">
</template> <Select v-model="filterModel.value" @change="filterCallback()" :options="statuses" placeholder="Select One"
</Column> style="min-width: 12rem" :showClear="true">
<Column header="Ingestion Date" filterField="ingestionDateFormat" dataType="date" style="min-width: 10rem"> <template #option="{ option }">
<template #body="{ data }"> <Tag :value="option" :severity="getStatus({ ingestionStatus: option })" />
{{ formatDate(data.ingestionDate) }} </template>
</template> </Select>
<template #filter="{ filterModel }"> </template>
<DatePicker v-model="filterModel.value" dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy" @change="updateFilterModel"/> </Column>
</template> <Column header="Ingestion Date" filterField="ingestionDateFormat" dataType="date" style="min-width: 10rem">
</Column> <template #body="{ data }">
<Column headerStyle="width: 5rem; text-align: center" bodyStyle="text-align: center; overflow: visible"> {{ formatDate(data.ingestionDate) }}
<template #body="slotProps"> </template>
<div class="flex justify-center items-center"> <template #filter="{ filterModel }">
<Button type="button" icon="pi pi-pencil" rounded @click="editKsDocument(slotProps.data)" v-tooltip="'Edit the information of document'" class="mr-4" /> <DatePicker v-model="filterModel.value" dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy"
<!--Tag :value="slotProps.data.id" /--> @change="updateFilterModel" />
<!--Tag :value="slotProps.data.ingestionInfo.id" /--> </template>
<!--Button type="button" v-if="slotProps.data.ingestionStatus === 'NEW'" icon="pi pi-play" rounded </Column>
<Column headerStyle="width: 5rem; text-align: center" bodyStyle="text-align: center; overflow: visible">
<template #body="slotProps">
<div class="flex justify-center items-center">
<Button type="button" icon="pi pi-pencil" rounded @click="editKsDocument(slotProps.data)"
v-tooltip="'Edit the information of document'" class="mr-4" />
<!--Tag :value="slotProps.data.id" /-->
<!--Tag :value="slotProps.data.ingestionInfo.id" /-->
<!--Button type="button" v-if="slotProps.data.ingestionStatus === 'NEW'" icon="pi pi-play" rounded
@click="startIndividualngestion(slotProps.data.id)" v-tooltip="'Start Ingestion of document'" class="mr-4" /--> @click="startIndividualngestion(slotProps.data.id)" v-tooltip="'Start Ingestion of document'" class="mr-4" /-->
<Button type="button" <Button type="button" icon="pi pi-play" rounded @click="startIndividualngestion(slotProps.data.id)"
icon="pi pi-play" v-tooltip="'Start Ingestion of document'" :disabled="slotProps.data.ingestionStatus === 'INGESTED'"
rounded :class="{ 'p-button-danger': slotProps.data.ingestionStatus === 'INGESTED' }" class="mr-7" />
@click="startIndividualngestion(slotProps.data.id)" </div>
v-tooltip="'Start Ingestion of document'" </template>
:disabled="slotProps.data.ingestionStatus === 'INGESTED'" </Column>
:class="{ 'p-button-danger': slotProps.data.ingestionStatus === 'INGESTED' }" </DataTable>
class="mr-7" /> <Dialog header="Ingestion Result" v-model:visible="ingestionDialogVisible" :modal="true" :closable="false">
</div> <p>{{ ingestionResult }}</p>
</template> <Button label="OK" icon="pi pi-check" @click="ingestionDialogVisible = false" />
</Column> </Dialog>
</DataTable> </div>
<Dialog header="Ingestion Result" v-model:visible="ingestionDialogVisible" :modal="true" :closable="false">
<p>{{ ingestionResult }}</p>
<Button label="OK" icon="pi pi-check" @click="ingestionDialogVisible = false" />
</Dialog>
</div>
</template> </template>
<script setup> <script setup>
@@ -111,14 +114,14 @@ const ingestionResult = ref('');
const filters = ref(); const filters = ref();
const initFilters = () => { const initFilters = () => {
filters.value = { filters.value = {
global: { value: null, matchMode: FilterMatchMode.CONTAINS }, global: { value: null, matchMode: FilterMatchMode.CONTAINS },
id: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] }, id: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
name: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] }, name: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
fileName: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] }, fileName: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
ingestionDateFormat: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] }, ingestionDateFormat: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] },
ingestionStatus: { operator: FilterOperator.OR, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] } ingestionStatus: { operator: FilterOperator.OR, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] }
}; };
}; };
initFilters(); initFilters();
@@ -126,99 +129,99 @@ initFilters();
const statuses = ref(['NEW', 'INGESTED', 'FAILED']); // Add your statuses here const statuses = ref(['NEW', 'INGESTED', 'FAILED']); // Add your statuses here
onMounted(() => { onMounted(() => {
axios.get('http://localhost:8082/fe-api/ksdocuments') axios.get('http://localhost:8082/fe-api/ksdocuments')
.then(response => { .then(response => {
ksdocuments.value = getCustomDatewithAllResponse(response.data); ksdocuments.value = getCustomDatewithAllResponse(response.data);
console.log(ksdocuments.value); console.log(ksdocuments.value);
loading.value = false; loading.value = false;
}); });
}); });
// Computed property to check if all documents are ingested // Computed property to check if all documents are ingested
const allDocumentsIngested = computed(() => { const allDocumentsIngested = computed(() => {
return ksdocuments.value && ksdocuments.value.every(doc => doc.ingestionStatus === 'INGESTED'); return ksdocuments.value && ksdocuments.value.every(doc => doc.ingestionStatus === 'INGESTED');
}); });
const getStatus = (data) => { const getStatus = (data) => {
if (data.ingestionStatus === 'INGESTED') { if (data.ingestionStatus === 'INGESTED') {
return 'success'; return 'success';
} else if (data.ingestionStatus === 'NEW') { } else if (data.ingestionStatus === 'NEW') {
return 'danger'; return 'danger';
} else { } else {
return 'warn'; return 'warn';
} }
} }
const getCustomDatewithAllResponse = (data) => { const getCustomDatewithAllResponse = (data) => {
return [...(data || [])].map((d) => { return [...(data || [])].map((d) => {
d.ingestionDateFormat = new Date(d.ingestionDateFormat); d.ingestionDateFormat = new Date(d.ingestionDateFormat);
return d; return d;
}); });
}; };
const updateFilterModel = () => { const updateFilterModel = () => {
console.log("updateFilterModel") console.log("updateFilterModel")
} }
const editKsDocument = (data) => { const editKsDocument = (data) => {
console.log(data); console.log(data);
router.push({ name: 'ks-document-edit', params: { id: data.id } }); router.push({ name: 'ks-document-edit', params: { id: data.id } });
} }
const startIndividualngestion = (id) => { const startIndividualngestion = (id) => {
axios.get(`http://localhost:8082/test/ingest_document/${id}`) axios.get(`http://localhost:8082/test/ingest_document/${id}`)
//axios.get('http://localhost:8082/test/ingestion_loop') //axios.get('http://localhost:8082/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") {
ksdocuments.value.forEach(element => { ksdocuments.value.forEach(element => {
if (response.data.ingestedDocumentId.includes(element.id)) { if (response.data.ingestedDocumentId.includes(element.id)) {
element.status = "INGESTED" element.status = "INGESTED"
} }
}); });
} else { } else {
ingestionResult.value = `Error: ${response.data.message}`; ingestionResult.value = `Error: ${response.data.message}`;
} }
ingestionDialogVisible.value = true; ingestionDialogVisible.value = true;
}) })
.catch(error => { .catch(error => {
ingestionDialogVisible.value = true; ingestionDialogVisible.value = true;
}); });
}; };
const startlngestion = () => { const startlngestion = () => {
axios.get('http://localhost:8082/test/ingestion_loop') axios.get('http://localhost:8082/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") {
ksdocuments.value.forEach(element => { ksdocuments.value.forEach(element => {
if (response.data.ingestedDocumentId.includes(element.id)) { if (response.data.ingestedDocumentId.includes(element.id)) {
element.status = "INGESTED" element.status = "INGESTED"
} }
}); });
} else { } else {
ingestionResult.value = `Error: ${response.data.message}`; ingestionResult.value = `Error: ${response.data.message}`;
} }
ingestionDialogVisible.value = true; ingestionDialogVisible.value = true;
}) })
.catch(error => { .catch(error => {
ingestionDialogVisible.value = true; ingestionDialogVisible.value = true;
}); });
}; };
const newKsDocument = () => { const newKsDocument = () => {
console.log('new'); console.log('new');
router.push({ name: 'ks-document-new' }); router.push({ name: 'ks-document-new' });
} }
// Function to format date string // Function to format date string
function formatDate(dateString) { function formatDate(dateString) {
// Parse the date string using moment // Parse the date string using moment
return moment(dateString).format('MM/DD/YYYY'); return moment(dateString).format('MM/DD/YYYY');
} }
</script> </script>
@@ -226,15 +229,15 @@ function formatDate(dateString) {
<style scoped> <style scoped>
/* Custom styling for disabled red button */ /* Custom styling for disabled red button */
.p-button-danger { .p-button-danger {
background-color: red; background-color: red;
border-color: red; border-color: red;
color: white; color: white;
} }
.p-button-danger:disabled { .p-button-danger:disabled {
background-color: red; background-color: red;
border-color: red; border-color: red;
color: white; color: white;
cursor: not-allowed; cursor: not-allowed;
} }
</style> </style>

View File

@@ -38,7 +38,7 @@ import ScrollPanel from 'primevue/scrollpanel';
import SelectButton from 'primevue/selectbutton'; // Import SelectButton import SelectButton from 'primevue/selectbutton'; // Import SelectButton
import { useToast } from 'primevue/usetoast'; import { useToast } from 'primevue/usetoast';
import { watch, ref } from 'vue'; import { watch, ref } from 'vue';
import CodeSnippet from './CodeSnippet.vue'; import CodeSnippet from '@/components/CodeSnippet.vue';
const query = ref(''); const query = ref('');
const dropdownItem = ref(null); const dropdownItem = ref(null);
@@ -48,7 +48,8 @@ const dynamicCode = ref('');
const dropdownItems = [ const dropdownItems = [
{ name: 'Documentation', code: 'setup-documentation' }, { name: 'Documentation', code: 'setup-documentation' },
{ name: 'Deploy Documentation', code: 'deploy-documentation' } { name: 'Deploy Documentation', code: 'deploy-documentation' },
{ name: 'SourceCode', code: 'sourcecode' }
]; ];
const sendQuery = async () => { const sendQuery = async () => {

View File

@@ -0,0 +1,98 @@
<template>
<div className="card">
<DataTable v-model:filters="filters" :value="vectorDetails" dataKey="id" :loading="loading" paginator showGridlines
:rows="10" filterDisplay="menu"
:globalFilterFields="['id', 'metadata.ksApplicationName', 'metadata.ksDocSource', 'metadata.ksDoctype', 'metadata.source']">
<template #header>
<div class="flex items-center justify-between gap-4 p-4 ">
<span class="text-xl font-bold">Vector Data</span>
<div class="flex items-center gap-2 flex-grow">
<IconField class="flex-grow">
<InputIcon>
<i class="pi pi-search" />
</InputIcon>
<InputText v-model="filters['global'].value" placeholder="Keyword Search" />
</IconField>
</div>
</div>
</template>
<template #empty>No Records found</template>
<template #loading>Loading Data. Please wait.....</template>
<Column field="id" header="Id" sortable>
<template #body="{ data }">
{{ data.id }}
</template>
<template #filter="{ filterModel, filterCallback }">
<InputText v-model="filterModel.value" type="text" @input="filterCallback()" placeholder="Search By id" />
</template>
</Column>
<Column field="metadata.ksApplicationName" header="ksApplicationName" sortable>
<template #body="{ data }">
{{ data.metadata.ksApplicationName }}
</template>
<template #filter="{ filterModel, filterCallback }">
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
placeholder="Search By Application name" />
</template>
</Column>
<Column field="metadata.ksDocSource" header="ksDocSource" sortable>
<template #body="{ data }">
{{ data.metadata.ksDocSource }}
</template>
<template #filter="{ filterModel, filterCallback }">
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
placeholder="Search By Document/Repo source" />
</template>
</Column>
<Column field="metadata.ksDoctype" header="ksDoctype" sortable>
<template #body="{ data }">
{{ data.metadata.ksDoctype }}
</template>
<template #filter="{ filterModel, filterCallback }">
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
placeholder="Search By Document/Source type" />
</template>
</Column>
<Column field="metadata.source" header="source" sortable>
<template #body="{ data }">
{{ data.metadata.source }}
</template>
<template #filter="{ filterModel, filterCallback }">
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
placeholder="Search By Source/Path" />
</template>
</Column>
</DataTable>
</div>
</template>
<script setup>
import { onMounted, ref } from 'vue';
import { FilterMatchMode, FilterOperator } from '@primevue/core/api'
import axios from 'axios';
const vectorDetails = ref(null);
const loading = ref(true);
const filters = ref();
onMounted(() => {
axios.get('http://localhost:8082/fe-api/vector-store/details')
.then(response => {
vectorDetails.value = response.data;
console.log(vectorDetails.value)
loading.value = false;
});
});
const initFilters = () => {
filters.value = {
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
id: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
'metadata.ksApplicationName': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
'metadata.ksDocSource': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
'metadata.ksDoctype': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
'metadata.source': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] }
};
};
initFilters();
</script>