websocket & Datatable modified

This commit is contained in:
sumedh
2024-09-12 22:50:35 +05:30
parent 24e4d3093e
commit 8802adef07
10 changed files with 658 additions and 47 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 72 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 218 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 341 KiB

View File

@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="494px" height="455px" viewBox="0 0 494 455" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.2 (9983) - http://www.bohemiancoding.com/sketch -->
<title>logo</title>
<desc>Created with Sketch.</desc>
<defs>
<path id="path-1" d="M0,1173.3333 L1999.99995,1173.3333 L1999.99995,0 L0,0 L0,1173.3333 L0,1173.3333 Z"></path>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="gitlab_logo" sketch:type="MSLayerGroup" transform="translate(-359.000000, -360.000000)">
<g id="g10" transform="translate(999.999975, 587.666648) scale(1, -1) translate(-999.999975, -587.666648) translate(0.000000, 0.999996)">
<g id="g16">
<g id="g18-Clipped">
<mask id="mask-2" sketch:name="path22" fill="white">
<use xlink:href="#path-1"></use>
</mask>
<g id="path22"></g>
<g id="g18" mask="url(#mask-2)">
<g transform="translate(358.666658, 358.666658)">
<g id="g44" transform="translate(0.532000, 0.774933)">
<path d="M491.999988,194.666662 L464.441322,279.481326 L409.82399,447.578655 C407.014656,456.226655 394.778657,456.226655 391.96799,447.578655 L337.349325,279.481326 L155.982663,279.481326 L101.362664,447.578655 C98.5533309,456.226655 86.3173312,456.226655 83.5066646,447.578655 L28.8893326,279.481326 L1.33199997,194.666662 C-1.18266664,186.930662 1.57199996,178.455996 8.1519998,173.674662 L246.665327,0.385333324 L485.179988,173.674662 C491.759988,178.455996 494.513321,186.930662 491.999988,194.666662" id="path46" fill="#FC6D26" sketch:type="MSShapeGroup"></path>
</g>
<g id="g48" transform="translate(155.197863, 1.160267)">
<path d="M91.9999977,0 L91.9999977,0 L182.683995,279.095993 L1.31599997,279.095993 L91.9999977,0 L91.9999977,0 Z" id="path50" fill="#E24329" sketch:type="MSShapeGroup"></path>
</g>
<g id="g52" transform="translate(247.197860, 1.160267)">
<g id="path54"></g>
</g>
<g id="g56" transform="translate(28.531199, 1.160800)">
<path d="M218.666661,0 L127.982663,279.09466 L0.890666644,279.09466 L218.666661,0 L218.666661,0 Z" id="path58" fill="#FC6D26" sketch:type="MSShapeGroup"></path>
</g>
<g id="g60" transform="translate(247.197860, 1.160800)">
<g id="path62"></g>
</g>
<g id="g64" transform="translate(0.088533, 0.255867)">
<path d="M29.3333326,279.999993 L29.3333326,279.999993 L1.77466662,195.185328 C-0.738666648,187.449329 2.01466662,178.974662 8.59599979,174.194662 L247.109327,0.905333311 L29.3333326,279.999993 L29.3333326,279.999993 Z" id="path66" fill="#FCA326" sketch:type="MSShapeGroup"></path>
</g>
<g id="g68" transform="translate(247.197860, 1.160267)">
<g id="path70"></g>
</g>
<g id="g72" transform="translate(29.421866, 280.255593)">
<path d="M0,0 L127.091997,0 L72.4733315,168.097329 C69.6626649,176.746662 57.4266652,176.746662 54.617332,168.097329 L0,0 L0,0 Z" id="path74" fill="#E24329" sketch:type="MSShapeGroup"></path>
</g>
<g id="g76" transform="translate(247.197860, 1.160800)">
<path d="M0,0 L90.6839977,279.09466 L217.775995,279.09466 L0,0 L0,0 Z" id="path78" fill="#FC6D26" sketch:type="MSShapeGroup"></path>
</g>
<g id="g80" transform="translate(246.307061, 0.255867)">
<path d="M218.666661,279.999993 L218.666661,279.999993 L246.225327,195.185328 C248.73866,187.449329 245.985327,178.974662 239.403994,174.194662 L0.890666644,0.905333311 L218.666661,279.999993 L218.666661,279.999993 Z" id="path82" fill="#FCA326" sketch:type="MSShapeGroup"></path>
</g>
<g id="g84" transform="translate(336.973725, 280.255593)">
<path d="M127.999997,0 L0.907999977,0 L55.5266653,168.097329 C58.3373319,176.746662 70.5733316,176.746662 73.3826648,168.097329 L127.999997,0 L127.999997,0 Z" id="path86" fill="#E24329" sketch:type="MSShapeGroup"></path>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

@@ -0,0 +1,72 @@
<template>
<div>
</div>
</template>
<script setup>
import { ref, onMounted, onBeforeUnmount, defineProps, defineEmits } from 'vue';
import { Stomp } from "@stomp/stompjs";
import SockJS from 'sockjs-client/dist/sockjs';
// Define props
const props = defineProps(['topic', 'subtopic']);
const emit = defineEmits(['update']);
// Reactive state
const lastMessage = ref({ message: "" });
let stompClient = null;
let messageHandler = null;
//Function to connect to websocket
const connectWebSocket = (onMessageReceived) => {
messageHandler = onMessageReceived; // Store the message handler
if (stompClient !== null){
console.warn('Websocket is already Connected.');
return;
}
const socket = new SockJS(`http://localhost:8082/ws/endpoint`);
stompClient = Stomp.over(socket);
stompClient.reconnect_delay = 5000;
stompClient.connect({},(frame) => {
//console.log('Connected: '+frame);
// Correctly use props.topic and props.subtopic
const subscriptionTopic = `/${props.topic}/${props.subtopic}`;
console.log('Subscribing to: ' + subscriptionTopic);
stompClient.subscribe(subscriptionTopic, (message) => {
if(messageHandler){
messageHandler(JSON.parse(message.body));
}
});
}, (error) => {
console.warn('WebSocket Error: '+error);
});
};
onMounted(() => {
console.log("Created notification component");
connectWebSocket(handleWebSocketMessage)
});
onBeforeUnmount(() => {
if(stompClient !== null){
stompClient.disconnect(() => {
console.log('Disconnected');
})
stompClient = null;
}
});
const handleWebSocketMessage = (data) =>{
console.log('Received WebSocket message: ',data)
lastMessage.value = data;
emit('update', data);
}
</script>

View File

@@ -15,6 +15,9 @@ const logoSrc = ref(logo);
<template>
<div class="layout-topbar">
<div class="layout-topbar-logo-container">
<button class="layout-topbar-action" @click="onMenuToggle"> <!--class layout-menu-button -->
<i class="pi pi-bars"></i>
</button>
<router-link to="/" class="layout-topbar-logo">
<!--svg width="85" height="63" viewBox="0 0 85 63" fill="none" xmlns="http://www.w3.org/2000/svg">
@@ -33,9 +36,7 @@ const logoSrc = ref(logo);
<span>APOLLO</span>
</router-link>
<button class="layout-topbar-action" @click="onMenuToggle"> <!--class layout-menu-button -->
<i class="pi pi-bars"></i>
</button>
</div>
@@ -45,14 +46,14 @@ const logoSrc = ref(logo);
<button type="button" class="layout-topbar-action" @click="toggleDarkMode">
<i :class="['pi', { 'pi-moon': isDarkTheme, 'pi-sun': !isDarkTheme }]"></i>
</button>
<div class="relative">
<!--div class="relative">
<button
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
type="button" class="layout-topbar-action layout-topbar-action-highlight">
<i class="pi pi-palette"></i>
</button>
<AppConfigurator />
</div>
</div-->
</div>
<button class="layout-topbar-menu-button layout-topbar-action"

View File

@@ -0,0 +1,106 @@
<template>
<form @submit.prevent="submitForm" class="p-fluid">
<div class="flex flex-col gap-4">
<div class="flex flex-col gap-2">
<label for="repoName">Repo Name</label>
<InputText id="repoName" v-model="formData.repoName" placeholder="Enter Repo Name" required class="w-full" />
</div>
<div class="flex flex-col gap-2">
<label for="group">Group Name</label>
<InputText id="group" v-model="formData.group" placeholder="Enter Group Name" required class="w-full" />
</div>
<div class="flex flex-col gap-2">
<label for="source">Source Name</label>
<InputText id="source" v-model="formData.source" placeholder="Enter Source base URL" required class="w-full" />
</div>
<div class="flex flex-col gap-2">
<label for="branch">Branch</label>
<InputText id="branch" v-model="formData.branch" placeholder="Enter Branch" required class="w-full" />
</div>
<div class="flex flex-col gap-2">
<label for="commitId">CommitID</label>
<InputText id="commitId" type="text" v-model="formData.commitId" required class="w-full" />
</div>
<div class="flex flex-col gap-2">
<label for="tokenType">Git Token Type</label>
<InputText id="tokenType" type="text" v-model="formData.tokenType" required class="w-full" />
</div>
<!--div class="col-12 mb-4">
<span class="p-float-label">
<label for="repoPath">Repo Path</label>
<InputText id="repoPath" v-model="formData.repoPath" required class="w-full" />
</span>
</div-->
<div class="flex flex-col gap-2">
<label for="defaultChunkSize">Default Chunk Size</label>
<InputNumber id="defaultChunkSize" v-model="formData.defaultChunkSize" required class="w-full" />
</div>
<div class="flex flex-col gap-2">
<label for="minChunkSize">Min Chunk Size</label>
<InputNumber id="minChunkSize" v-model="formData.minChunkSize" required class="w-full" />
</div>
<div class="flex flex-col gap-2">
<label for="maxNumberOfChunks">Max Number of Chunks</label>
<InputNumber id="maxNumberOfChunks" v-model="formData.maxNumberOfChunks" required class="w-full" />
</div>
<div class="flex flex-col gap-2">
<label for="minChunkSizeToEmbed">Min Chunk Size to Embed</label>
<InputNumber id="minChunkSizeToEmbed" v-model="formData.minChunkSizeToEmbed" required class="w-full" />
</div>
</div>
<Button type="submit" label="Submit" text rounded raised :disabled="isSubmitting" :fluid="false" class="p-button-rounded p-button-lg mt-4" />
</form>
</template>
<script setup>
import { ref, defineProps, defineEmits } from 'vue';
const formData = ref({
repoName: 'shellExecutionThroughAPI',
group: 'automationtester23',
source:'https://github.com',
branch: 'master',
commitId: 'latest',
tokenType:'github',
repoPath: 'C:\\repos\\olympus_ai\\gitClone',
defaultChunkSize: 1988,
minChunkSize: 200,
maxNumberOfChunks: 1988,
minChunkSizeToEmbed: 20
});
const isSubmitting = ref(false);
const emit = defineEmits(['submitForm'])
const submitForm = () => {
if (isSubmitting.value) return; // Prevent duplicate submissions
isSubmitting.value = true;
const formDataToSend = new FormData();
formDataToSend.append('repoName', formData.value.repoName);
formDataToSend.append('group', formData.value.group);
formDataToSend.append('source', formData.value.source);
formDataToSend.append('branch', formData.value.branch);
formDataToSend.append('commitId', formData.value.commitId);
formDataToSend.append('tokenType', formData.value.tokenType);
//formDataToSend.append('repoPath', formData.value.repoPath);
formDataToSend.append('defaultChunkSize', formData.value.defaultChunkSize);
formDataToSend.append('minChunkSize', formData.value.minChunkSize);
formDataToSend.append('maxNumberOfChunks', formData.value.maxNumberOfChunks);
formDataToSend.append('minChunkSizeToEmbed', formData.value.minChunkSizeToEmbed);
//console.log(formData);
const json = formDatatoJson(formDataToSend);
console.log(json)
emit('submitForm',json)
};
function formDatatoJson(formData){
const jsonObject ={};
formData.forEach((value,key) => {
jsonObject[key] = value;
})
return jsonObject;
}
</script>

View File

@@ -8,45 +8,80 @@
<p class="loading-text">Loading data...</p>
</div>
</div>
<Toolbar class="mb-6">
<template #start>
<Button label="Refresh" icon="pi pi-refresh" severity="secondary" class="mr-2" rounded @click="fetchCodeRepoInfo" />
</template>
<template #end>
<Button label="Expand All" icon="pi pi-plus" severity="secondary" class="mr-3" rounded @click="expandAll" />
<Button label="Collapse All" icon="pi pi-minus" severity="secondary" class="mr-3" rounded @click="collapseAll"/>
<!--Button label="Add New Git Repo" icon="pi pi-plus" severity="secondary" rounded class="mr-3" @click="newCodeRepoForm()" v-tooltip="'Add New Git Repo'" class="mr-2" /-->
<!--Button label="Add Git Repo" icon="pi pi-bolt" severity="secondary" rounded @click="cloneRepoForm()" v-tooltip="'Add New Git Repo'" /-->
<Button label="Add Git Repo" icon="pi pi-bolt" severity="secondary" rounded @click="showDialog = true" v-tooltip="'Add New Git Repo using Dialog'"/>
<Dialog v-model:visible="showDialog" :style="{ width: '600px' }" header="Repository Details" :modal="true">
<div>
<cloneForm @submitForm="cloneRepo"/>
</div>
</Dialog>
</template>
</Toolbar>
<DataTable
v-else
v-model:filters="filters"
v-model:expandedRows="expandedRows"
@rowExpand="onRowExpand"
@rowCollapse="onRowCollapse"
:value="codeRepoInfo"
:paginator="true"
:rows="10"
dataKey="repoName"
paginatorTemplate="FirstPageLink PrevPageLink PageLinks NextPageLink LastPageLink CurrentPageReport RowsPerPageDropdown"
currentPageReportTemplate="Showing {first} to {last} of {totalRecords} records"
:rowsPerPageOptions="[ 10,15, 20, 50, 100]"
dataKey="id"
:rowHover="true"
showGridlines
rowGroupMode="subheader"
groupRowsBy="repoName"
filterDisplay="menu"
:loading="loading"
:globalFilterFields="['repoName', 'branch', 'ingestionStatus', 'ingestionDateFormat']"
tableStyle="min-width: 60rem"
tableStyle="min-width: 70rem"
removableSort
>
<template #header>
<div class="flex items-center justify-between gap-4 p-4">
<span class="text-xl font-bold">Knowledge Source Git Code Repository</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>
<!--Button icon="pi pi-plus" rounded raised @click="newCodeRepoForm()" v-tooltip="'Add New Git Repo'" class="mr-2" /-->
<Button icon="pi pi-bolt" rounded raised @click="cloneRepoForm()" v-tooltip="'Clone New Git Repo'" class="mr-2" />
<template #header>
<div class="flex flex-wrap gap-2 items-center justify-between">
<h4 class="m-0">Manage Repositories</h4>
<IconField>
<InputIcon>
<i class="pi pi-search" />
</InputIcon>
<InputText v-model="filters['global'].value" placeholder="Search..." />
</IconField>
</div>
</template>
<template #groupheader="slotProps">
<div class="flex items-center gap-2">
<img :alt="slotProps.data.repoName" :src="logoSrc" width="32" style="vertical-align: middle" />
<span>{{ slotProps.data.repoName }}</span>
</div>
</template>
<Column expander style="width: 5rem" />
<template #empty>No Records found</template>
<template #loading>Loading Data... </template>
<socketManager @update="handleCloneRepoWebSocketMessage" topic="topic" subtopic="clone-status"></socketManager>
<socketManager @update="handleCloneRepoWebSocketMessage" topic="topic" subtopic="deletion-status"></socketManager>
<!--Column field="id" header="KSGitInfoID" sortable /-->
<Column/>
<Column/>
<!--Column field="ksGitIngestionInfo.id" header="ksGitIngestionInfo" sortable> </Column-->
<Column field="repoName" header="Repo Name" sortable>
<Column field="repoName" header="Repo Name">
<template #body="{ data }">
{{ data.repoName }}
</template>
@@ -55,7 +90,7 @@
</template>
</Column>
<Column field="branch" header="Branch" sortable>
<Column field="branch" header="Branch">
<template #body="{ data }">
{{ data.branch }}
</template>
@@ -86,53 +121,73 @@
</template>
</Column>
<Column header="Actions" headerStyle="width: 5rem; text-align: center" bodyStyle="text-align: center; overflow: visible">
<!--Column header="Actions" headerStyle="width: 5rem; text-align: center" bodyStyle="text-align: center; overflow: visible"-->
<Column :exportable="false" style="min-width: 12rem">
<template #body="slotProps">
<div class="flex justify-center items-center space-x-3" >
<Button
type="button"
text raised rounded
severity="info"
type="button"
class="mr-2"
icon="pi pi-play"
class="p-button-rounded p-button-success p-mr-2"
@click="ingestGitRepo(slotProps.data)"
v-tooltip="'Start Ingestion of Repo'"
:disabled="slotProps.data.ingestionStatus === 'INGESTED'"
:disabled="isButtonDisabled(slotProps.data)"
/>
<Button
type="button"
text raised rounded
severity="warn"
type="button"
class="mr-2"
icon="pi pi-forward"
class="p-button-rounded p-button-success p-mr-2"
@click="reIngestWithPullChanges(slotProps.data)"
v-tooltip="'Ingest Repo with latest changes from master branch'"
/>
<Button
text raised rounded
severity="danger"
type="button"
icon="pi pi-trash"
class="p-button-rounded p-button-success p-mr-2"
@click="deleteRecordsFromVectorStore(slotProps.data)"
v-tooltip="'Delete the Records'"
/>
</div>
</template>
</Column>
<template #expansion="slotProps">
<div class="p-4">
<h5>Records of {{ slotProps.data }}</h5>
<VueJsonView :src="slotProps.data"
:collapsed="collapsed"
:theme="theme"
:sort-keys="sortKeys"
:enable-clipboard="enableClipboard"
class="vue-json-view"
/>
</div>
</template>
<template #groupfooter="slotProps">
<div class="flex justify-end font-bold w-full">Total Count: {{ calculateCustomerTotal(slotProps.data.repoName) }}</div>
</template>
</DataTable>
</div>
</template>
<script setup>
import { FilterMatchMode, FilterOperator } from '@primevue/core/api';
import { computed, onMounted, ref } from 'vue';
import { computed, onMounted, onUnmounted, ref } from 'vue';
import { useRouter } from 'vue-router';
import { useToast } from 'primevue/usetoast';
import axios from 'axios';
import moment from 'moment';
import {setWebSocketMessageHandler} from '/src/service/websocketService.js';
import VueJsonView from '@matpool/vue-json-view'
import logo from '@/assets/gitlab-logo.svg';
import Button from 'primevue/button';
import Column from 'primevue/column';
@@ -146,6 +201,28 @@ import Tooltip from 'primevue/tooltip';
import ProgressSpinner from 'primevue/progressspinner';
import { useConfirm } from "primevue/useconfirm";
import socketManager from '/src/components/SocketManager.vue'
//dialog
import cloneForm from './KsGitCloneRepoFormDialog.vue'
const showDialog = ref(false);
const cloneRepo = (formData) => {
try {
const response = axios.post('/fe-api/ks_git_repos/clone', formData, {
headers: {
'Content-Type': 'application/json'
}
});
console.log('Submit successful:', response.data);
toast.add({ severity: 'success', summary: 'Success', detail: 'Repository Download is IN-PROGRESS', life: 3000 });
} catch (error) {
console.error('Submit failed:', error);
toast.add({ severity: 'error', summary: 'Error', detail: 'Repository Submission failed', life: 3000 });
}
showDialog.value = false; // Close the dialog after form submission
};
const router = useRouter();
const codeRepoInfo = ref(null);
const loading = ref(true);
@@ -157,12 +234,34 @@ const ingestionResult = ref('');
const popupTitle = ref('');
const popupMessage = ref('');
const filters = ref();
const statuses = ref(['NEW', 'INGESTED', 'FAILED', 'INPROGRESS']);
const statuses = ref(['INGESTION-ERROR','INGESTION-IN-PROGRESS', 'INGESTED', 'REPO-NEW', 'REPO-CLONE-IN-PROGRESS','REPO-CLONE-COMPLETED','REPO-CLONE-FAILED']);
const collapsed = ref(1)
const theme = ref('bright:inverted')
const sortKeys = ref(true)
const enableClipboard = ref(true)
const logoSrc = ref(logo);
onMounted(() => {
fetchCodeRepoInfo();
});
//websocket
const handleCloneRepoWebSocketMessage = (data) => {
console.log('Update received in parent component:', data);
const { success, message } = data;
if (success) {
toast.add({ severity: 'success', summary: 'Success', detail: message , life: 10000 });
fetchCodeRepoInfo();
} else {
toast.add({ severity: 'error', summary: 'Error', detail: message, life: 10000 });
fetchCodeRepoInfo();
}
};
//websocket end
const initFilters = () => {
filters.value = {
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
@@ -174,6 +273,20 @@ const initFilters = () => {
};
};
function calculateCustomerTotal(name) {
let total = 0;
if(codeRepoInfo.value){
for(let RepoInfo of codeRepoInfo.value){
if (RepoInfo.repoName === name) {
total++;
}
}
}
return total;
}
initFilters();
const fetchCodeRepoInfo = async () => {
@@ -345,11 +458,29 @@ const reIngestWithPullChanges = (data) =>{
//expand
const onRowExpand = (event) => {
toast.add({ severity: 'info', summary: 'Product Expanded', detail: event.data, life: 3000 });
console.log('Row Expanded:', event.data);
toast.add({ severity: 'info', summary: event.data.repoName +' Expanded', life: 3000 });
};
const onRowCollapse = (event) => {
toast.add({ severity: 'success', summary: 'Product Collapsed', detail: event.data, life: 3000 });
console.log('Row Expanded:', event.data);
toast.add({ severity: 'success', summary: event.data.repoName +' Collapsed', life: 3000 });
};
const expandAll = () => {
expandedRows.value = codeRepoInfo.value.reduce((acc, item) => {
(acc[item.id] = true);
return acc;
}, {});
};
const collapseAll = () => {
expandedRows.value = {};
};
//disable button
function isButtonDisabled(data) {
return data.ingestionStatus !== 'REPO-CLONE-COMPLETED';
}
</script>
<style scoped>
@@ -434,4 +565,8 @@ const onRowCollapse = (event) => {
.card {
margin: 2rem;
}
.vue-json-view {
font-size: 15px; /* Change this value to your desired font size */
}
</style>