Merge branch 'develop' into 'master'
merge develop into master See merge request olympus_ai/apollo-fe!2
This commit is contained in:
47
.gitlab-ci.yml
Normal file
47
.gitlab-ci.yml
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
# This file is a template, and might need editing before it works on your project.
|
||||||
|
# To contribute improvements to CI/CD templates, please follow the Development guide at:
|
||||||
|
# https://docs.gitlab.com/ee/development/cicd/templates.html
|
||||||
|
# This specific template is located at:
|
||||||
|
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Docker.gitlab-ci.yml
|
||||||
|
|
||||||
|
# Build a Docker image with CI/CD and push to the GitLab registry.
|
||||||
|
# Docker-in-Docker documentation: https://docs.gitlab.com/ee/ci/docker/using_docker_build.html
|
||||||
|
#
|
||||||
|
# This template uses one generic job with conditional builds
|
||||||
|
# for the default branch and all other (MR) branches.
|
||||||
|
|
||||||
|
docker-build:
|
||||||
|
# Use the official docker image.
|
||||||
|
image: gcr.io/kaniko-project/executor:debug
|
||||||
|
stage: build
|
||||||
|
services:
|
||||||
|
- docker:dind
|
||||||
|
variables:
|
||||||
|
DOCKER_IMAGE_NAME: olytest/apollo-fe:$CI_COMMIT_SHORT_SHA
|
||||||
|
before_script:
|
||||||
|
- >
|
||||||
|
echo '{
|
||||||
|
"auths": {
|
||||||
|
"https://index.docker.io/v1/": {
|
||||||
|
"auth": "b2x5dGVzdDpkY2tyX3BhdF9ZUFBCa21IVlVkbmx4R3dLT0t1TEtmQ1RTVTg="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} ' >> /kaniko/.docker/config.json
|
||||||
|
|
||||||
|
# All branches are tagged with $DOCKER_IMAGE_NAME (defaults to commit ref slug)
|
||||||
|
# Default branch is also tagged with `latest`
|
||||||
|
script:
|
||||||
|
- /kaniko/executor
|
||||||
|
--context "${CI_PROJECT_DIR}"
|
||||||
|
--dockerfile "${CI_PROJECT_DIR}/Dockerfile"
|
||||||
|
--destination "${DOCKER_IMAGE_NAME}"
|
||||||
|
--build-arg "VITE_BACKEND_URL=http://olympus-api-gateway.olympusai.live/apollo"
|
||||||
|
|
||||||
|
# Run this job in a branch where a Dockerfile exists
|
||||||
|
rules:
|
||||||
|
- if: $CI_COMMIT_BRANCH
|
||||||
|
exists:
|
||||||
|
- Dockerfile
|
||||||
|
#when: manual
|
||||||
|
tags:
|
||||||
|
- OLYMPUS
|
||||||
2
.vscode/settings.json
vendored
2
.vscode/settings.json
vendored
@@ -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]": {
|
||||||
|
|||||||
25
Dockerfile
Normal file
25
Dockerfile
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
FROM node:latest as builder
|
||||||
|
|
||||||
|
# automatically creates the dir and sets it as the current working dir
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
# this will allow us to run vite and other tools directly
|
||||||
|
ENV PATH /usr/src/node_modules/.bin:$PATH
|
||||||
|
|
||||||
|
# inject all environment vars we'll need
|
||||||
|
ARG VITE_BACKEND_URL
|
||||||
|
ENV VITE_BACKEND_URL=$VITE_BACKEND_URL
|
||||||
|
|
||||||
|
COPY package.json ./
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
|
||||||
|
COPY . ./
|
||||||
|
|
||||||
|
RUN npm run build
|
||||||
|
|
||||||
|
FROM nginx:latest as prod
|
||||||
|
|
||||||
|
COPY --from=builder /usr/src/app/dist /usr/share/nginx/html
|
||||||
|
ADD default.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
CMD ["nginx", "-g", "daemon off;"]
|
||||||
@@ -4,6 +4,10 @@ server {
|
|||||||
server_name localhost;
|
server_name localhost;
|
||||||
|
|
||||||
#access_log /var/log/nginx/host.access.log main;
|
#access_log /var/log/nginx/host.access.log main;
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html index.html;
|
||||||
|
|
||||||
|
server_name _;
|
||||||
|
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
|
|||||||
@@ -3,9 +3,10 @@
|
|||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<link rel="icon" href="/favicon.ico">
|
<link rel="icon" href="/src/assets/Apollo_simple_logo.webp">
|
||||||
|
|
||||||
<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>
|
||||||
|
|||||||
695
package-lock.json
generated
695
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@@ -8,13 +8,21 @@
|
|||||||
"lint": "eslint --fix . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
|
"lint": "eslint --fix . --ext .vue,.js,.jsx,.cjs,.mjs --fix --ignore-path .gitignore"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"@matpool/vue-json-view": "^0.1.8",
|
||||||
"@primevue/themes": "^4.0.0",
|
"@primevue/themes": "^4.0.0",
|
||||||
|
"@stomp/stompjs": "^7.0.0",
|
||||||
|
"@websanova/vue-auth": "^4.2.1",
|
||||||
"axios": "^1.7.2",
|
"axios": "^1.7.2",
|
||||||
"chart.js": "3.3.2",
|
"chart.js": "3.3.2",
|
||||||
|
"moment": "^2.30.1",
|
||||||
"primeicons": "^6.0.1",
|
"primeicons": "^6.0.1",
|
||||||
"primevue": "^4.0.0",
|
"primevue": "^4.0.0",
|
||||||
|
"prismjs": "^1.29.0",
|
||||||
|
"sockjs-client": "^1.6.1",
|
||||||
"vue": "^3.4.34",
|
"vue": "^3.4.34",
|
||||||
"vue-router": "^4.4.0"
|
"vue-authenticate-2": "^2.2.0",
|
||||||
|
"vue-router": "^4.4.0",
|
||||||
|
"webstomp-client": "^1.2.6"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@primevue/auto-import-resolver": "^4.0.1",
|
"@primevue/auto-import-resolver": "^4.0.1",
|
||||||
|
|||||||
BIN
src/assets/Apollo_Transparent.png
Normal file
BIN
src/assets/Apollo_Transparent.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 72 KiB |
BIN
src/assets/Apollo_simple_logo.webp
Normal file
BIN
src/assets/Apollo_simple_logo.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 103 KiB |
BIN
src/assets/Logo_Apollo_Transparent-hd.png
Normal file
BIN
src/assets/Logo_Apollo_Transparent-hd.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 218 KiB |
BIN
src/assets/apollo.jpg
Normal file
BIN
src/assets/apollo.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 24 KiB |
60
src/assets/gitlab-logo.svg
Normal file
60
src/assets/gitlab-logo.svg
Normal 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 |
@@ -1,6 +1,6 @@
|
|||||||
html {
|
html {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
font-size: 14px;
|
font-size: 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { ref, reactive } from 'vue';
|
import { reactive, ref } from 'vue';
|
||||||
|
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
header: {
|
header: {
|
||||||
@@ -45,11 +45,14 @@ async function copyCode(event) {
|
|||||||
<span class="badge-free" v-if="free">Free</span>
|
<span class="badge-free" v-if="free">Free</span>
|
||||||
</span>
|
</span>
|
||||||
<div class="block-actions">
|
<div class="block-actions">
|
||||||
<a tabindex="0" :class="{ 'block-action-active': blockView === BlockView.PREVIEW }" @click="activateView($event, BlockView.PREVIEW)"><span>Preview</span></a>
|
<a tabindex="0" :class="{ 'block-action-active': blockView === BlockView.PREVIEW }"
|
||||||
<a :tabindex="'0'" :class="{ 'block-action-active': blockView === BlockView.CODE }" @click="activateView($event, BlockView.CODE)">
|
@click="activateView($event, BlockView.PREVIEW)"><span>Preview</span></a>
|
||||||
|
<a :tabindex="'0'" :class="{ 'block-action-active': blockView === BlockView.CODE }"
|
||||||
|
@click="activateView($event, BlockView.CODE)">
|
||||||
<span>Code</span>
|
<span>Code</span>
|
||||||
</a>
|
</a>
|
||||||
<a :tabindex="0" class="block-action-copy" @click="copyCode($event)" v-tooltip.focus.bottom="{ value: 'Copied to clipboard' }"><i class="pi pi-copy"></i></a>
|
<a :tabindex="0" class="block-action-copy" @click="copyCode($event)"
|
||||||
|
v-tooltip.focus.bottom="{ value: 'Copied to clipboard' }"><i class="pi pi-copy"></i></a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="block-content">
|
<div class="block-content">
|
||||||
@@ -57,7 +60,7 @@ async function copyCode(event) {
|
|||||||
<slot></slot>
|
<slot></slot>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="blockView === BlockView.CODE">
|
<div v-if="blockView === BlockView.CODE">
|
||||||
<pre class="app-code"><code>{{code}}</code></pre>
|
<pre class="app-code"><code>{{ code }}</code></pre>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -172,6 +175,7 @@ pre[class*='language-'] {
|
|||||||
padding: 0 2rem !important;
|
padding: 0 2rem !important;
|
||||||
|
|
||||||
.token {
|
.token {
|
||||||
|
|
||||||
&.tag,
|
&.tag,
|
||||||
&.keyword {
|
&.keyword {
|
||||||
color: #2196f3 !important;
|
color: #2196f3 !important;
|
||||||
|
|||||||
86
src/components/CodeSnippet.vue
Normal file
86
src/components/CodeSnippet.vue
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<div class="code-snippet-container">
|
||||||
|
<div class="button-container h-8 w-8 p-0 inline-flex items-center justify-center">
|
||||||
|
<!-- Button to copy code to clipboard -->
|
||||||
|
<Button icon="pi pi-copy" @click="copyToClipboard" class="p-mt-2" />
|
||||||
|
</div>
|
||||||
|
<!-- Code display area with syntax highlighting -->
|
||||||
|
<pre v-html="highlightedCode"></pre>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import Button from 'primevue/button';
|
||||||
|
import { useToast } from 'primevue/usetoast';
|
||||||
|
import { computed } from 'vue';
|
||||||
|
|
||||||
|
import Prism from 'prismjs';
|
||||||
|
import 'prismjs/components/prism-javascript'; // Import necessary languages
|
||||||
|
import 'prismjs/components/prism-systemd'; // Import necessary languages
|
||||||
|
import 'prismjs/themes/prism-tomorrow.css'; // Import a theme for syntax highlighting
|
||||||
|
|
||||||
|
const toast = useToast();
|
||||||
|
|
||||||
|
// Define the code snippet as a prop
|
||||||
|
const props = defineProps({
|
||||||
|
code: {
|
||||||
|
type: String,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
language: {
|
||||||
|
type: String,
|
||||||
|
default: 'systemd'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const highlightedCode = computed(() => {
|
||||||
|
return Prism.highlight(props.code, Prism.languages[props.language], props.language);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Function to copy the code to the clipboard
|
||||||
|
function copyToClipboard() {
|
||||||
|
navigator.clipboard.writeText(props.code).then(() => {
|
||||||
|
toast.add({ severity: 'success', summary: 'Success', detail: 'Code copied to clipboard!', life: 10000 });
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error('Failed to copy code:', error);
|
||||||
|
toast.add({ severity: 'error', summary: 'Error', detail: 'Failed to copy code.', life: 10000 });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.code-snippet-container {
|
||||||
|
position: relative;
|
||||||
|
/* Enable positioning of child elements */
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-container {
|
||||||
|
position: sticky;
|
||||||
|
top: 10px;
|
||||||
|
/* Adjust as needed */
|
||||||
|
right: 10px;
|
||||||
|
/* Adjust as needed */
|
||||||
|
z-index: 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
background-color: #2d2d2d;
|
||||||
|
color: #ccc;
|
||||||
|
padding: 1em;
|
||||||
|
border-radius: 5px;
|
||||||
|
overflow-x: auto;
|
||||||
|
white-space: pre-wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-container {
|
||||||
|
position: absolute;
|
||||||
|
top: 10px;
|
||||||
|
/* Adjust as needed */
|
||||||
|
right: 10px;
|
||||||
|
/* Adjust as needed */
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-mt-2 {
|
||||||
|
margin-top: 1em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
72
src/components/SocketManager.vue
Normal file
72
src/components/SocketManager.vue
Normal file
@@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { Stomp } from "@stomp/stompjs";
|
||||||
|
import SockJS from 'sockjs-client/dist/sockjs';
|
||||||
|
import { onBeforeUnmount, onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
// 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(`${import.meta.env.VITE_BACKEND_URL}/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>
|
||||||
@@ -7,12 +7,16 @@ const model = ref([
|
|||||||
{
|
{
|
||||||
label: 'Knowledge Source',
|
label: 'Knowledge Source',
|
||||||
items: [{ label: 'Documents', icon: 'pi pi-fw pi-id-card', to: '/ksdocuments' },
|
items: [{ label: 'Documents', icon: 'pi pi-fw pi-id-card', to: '/ksdocuments' },
|
||||||
{ label: 'Code Repository', icon: 'pi pi-fw pi-id-card', to: '/ks_code_repo' }
|
{ label: 'Code Repository', icon: 'pi pi-fw pi-id-card', to: '/ks_git_repos' },
|
||||||
|
{ label: 'Texts', icon: 'pi pi-fw pi-id-card', to: '/kstexts' }
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
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: 'Vector Database Search', icon: 'pi pi-fw pi-search', to: '/ks_vector_data' }
|
||||||
|
]
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
</script>
|
</script>
|
||||||
|
|||||||
17
src/layout/AppProfileMenu.vue
Normal file
17
src/layout/AppProfileMenu.vue
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<script setup>
|
||||||
|
|
||||||
|
import { useAuth } from '@websanova/vue-auth/src/v3.js';
|
||||||
|
const auth = useAuth();
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="config-panel hidden">
|
||||||
|
<div class="config-panel-content">
|
||||||
|
<span class="config-panel-label">Welcome </span>
|
||||||
|
|
||||||
|
{{ auth.user().name + " " + auth.user().surname }}
|
||||||
|
<button @click="auth.logout()" class="p-button p-button-danger p-button-outlined">Logout</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,79 +1,79 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
|
import logo from '@/assets/Apollo_simple_logo.webp';
|
||||||
import { useLayout } from '@/layout/composables/layout';
|
import { useLayout } from '@/layout/composables/layout';
|
||||||
import AppConfigurator from './AppConfigurator.vue';
|
import { useAuth } from '@websanova/vue-auth/src/v3.js';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
//import AppConfigurator from './AppConfigurator.vue';
|
||||||
|
import AppProfileMenu from './AppProfileMenu.vue';
|
||||||
|
|
||||||
const { onMenuToggle, toggleDarkMode, isDarkTheme } = useLayout();
|
const { onMenuToggle, toggleDarkMode, isDarkTheme } = useLayout();
|
||||||
|
const auth = useAuth();
|
||||||
|
const logoSrc = ref(logo);
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="layout-topbar">
|
<div class="layout-topbar">
|
||||||
<div class="layout-topbar-logo-container">
|
<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">
|
<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">
|
<img :src="logoSrc" alt="Logo" class="logo-image" />
|
||||||
<path
|
|
||||||
fill-rule="evenodd"
|
|
||||||
clip-rule="evenodd"
|
|
||||||
d="M27.017 30.3135C27.0057 30.5602 27 30.8085 27 31.0581C27 39.9267 34.1894 47.1161 43.0581 47.1161C51.9267 47.1161 59.1161 39.9267 59.1161 31.0581C59.1161 30.8026 59.1102 30.5485 59.0984 30.2959C60.699 30.0511 62.2954 29.7696 63.8864 29.4515L64.0532 29.4181C64.0949 29.9593 64.1161 30.5062 64.1161 31.0581C64.1161 42.6881 54.6881 52.1161 43.0581 52.1161C31.428 52.1161 22 42.6881 22 31.0581C22 30.514 22.0206 29.9747 22.0612 29.441L22.1136 29.4515C23.7428 29.7773 25.3777 30.0646 27.017 30.3135ZM52.4613 18.0397C49.8183 16.1273 46.5698 15 43.0581 15C39.54 15 36.2862 16.1313 33.6406 18.05C31.4938 17.834 29.3526 17.5435 27.221 17.1786C31.0806 12.7781 36.7449 10 43.0581 10C49.3629 10 55.0207 12.7708 58.8799 17.1612C56.7487 17.5285 54.6078 17.8214 52.4613 18.0397ZM68.9854 28.4316C69.0719 29.2954 69.1161 30.1716 69.1161 31.0581C69.1161 45.4495 57.4495 57.1161 43.0581 57.1161C28.6666 57.1161 17 45.4495 17 31.0581C17 30.1793 17.0435 29.3108 17.1284 28.4544L12.2051 27.4697C12.0696 28.6471 12 29.8444 12 31.0581C12 48.211 25.9052 62.1161 43.0581 62.1161C60.211 62.1161 74.1161 48.211 74.1161 31.0581C74.1161 29.8366 74.0456 28.6317 73.9085 27.447L68.9854 28.4316ZM69.6705 15.0372L64.3929 16.0927C59.6785 9.38418 51.8803 5 43.0581 5C34.2269 5 26.4218 9.39306 21.7089 16.1131L16.4331 15.0579C21.867 6.03506 31.7578 0 43.0581 0C54.3497 0 64.234 6.02581 69.6705 15.0372Z"
|
|
||||||
fill="var(--primary-color)"
|
|
||||||
/>
|
|
||||||
<mask id="path-2-inside-1" fill="var(--primary-color)">
|
|
||||||
<path d="M42.5 28.9252C16.5458 30.2312 0 14 0 14C0 14 26 22.9738 42.5 22.9738C59 22.9738 85 14 85 14C85 14 68.4542 27.6193 42.5 28.9252Z" />
|
|
||||||
</mask>
|
|
||||||
<path
|
|
||||||
d="M0 14L5.87269 -3.01504L-12.6052 26.8495L0 14ZM42.5 28.9252L41.5954 10.948L42.5 28.9252ZM85 14L96.4394 27.8975L79.1273 -3.01504L85 14ZM0 14C-12.6052 26.8495 -12.5999 26.8546 -12.5946 26.8598C-12.5928 26.8617 -12.5874 26.8669 -12.5837 26.8706C-12.5762 26.8779 -12.5685 26.8854 -12.5605 26.8932C-12.5445 26.9088 -12.5274 26.9254 -12.5092 26.943C-12.4729 26.9782 -12.4321 27.0174 -12.387 27.0605C-12.2969 27.1467 -12.1892 27.2484 -12.0642 27.3646C-11.8144 27.5968 -11.4949 27.8874 -11.1073 28.2273C-10.3332 28.9063 -9.28165 29.7873 -7.96614 30.7967C-5.34553 32.8073 -1.61454 35.3754 3.11693 37.872C12.5592 42.8544 26.4009 47.7581 43.4046 46.9025L41.5954 10.948C32.6449 11.3983 25.2366 8.83942 19.9174 6.03267C17.2682 4.63475 15.2406 3.22667 13.9478 2.23478C13.3066 1.74283 12.8627 1.366 12.6306 1.16243C12.5151 1.06107 12.4538 1.00422 12.4485 0.999363C12.446 0.996981 12.4576 1.00773 12.4836 1.03256C12.4966 1.04498 12.5132 1.06094 12.5334 1.08055C12.5436 1.09035 12.5546 1.10108 12.5665 1.11273C12.5725 1.11855 12.5787 1.12461 12.5852 1.13091C12.5884 1.13405 12.5934 1.13895 12.595 1.14052C12.6 1.14548 12.6052 1.15049 0 14ZM43.4046 46.9025C59.3275 46.1013 72.3155 41.5302 81.3171 37.1785C85.8337 34.9951 89.4176 32.8333 91.9552 31.151C93.2269 30.3079 94.2446 29.5794 94.9945 29.0205C95.3698 28.7409 95.6788 28.503 95.92 28.3138C96.0406 28.2192 96.1443 28.1366 96.2309 28.067C96.2742 28.0321 96.3133 28.0005 96.348 27.9723C96.3654 27.9581 96.3817 27.9448 96.3969 27.9323C96.4045 27.9261 96.4119 27.9201 96.419 27.9143C96.4225 27.9114 96.4276 27.9072 96.4294 27.9057C96.4344 27.9016 96.4394 27.8975 85 14C73.5606 0.102497 73.5655 0.0985097 73.5703 0.0945756C73.5718 0.0933319 73.5765 0.0894438 73.5795 0.0869551C73.5856 0.0819751 73.5914 0.077195 73.597 0.0726136C73.6082 0.0634509 73.6185 0.055082 73.6278 0.0474955C73.6465 0.0323231 73.6614 0.0202757 73.6726 0.0112606C73.695 -0.00676378 73.7026 -0.0126931 73.6957 -0.00726687C73.6818 0.00363418 73.6101 0.0596753 73.4822 0.154983C73.2258 0.346025 72.7482 0.691717 72.0631 1.14588C70.6873 2.05798 68.5127 3.38259 65.6485 4.7672C59.8887 7.55166 51.6267 10.4432 41.5954 10.948L43.4046 46.9025ZM85 14C79.1273 -3.01504 79.1288 -3.01557 79.1303 -3.01606C79.1306 -3.01618 79.1319 -3.01664 79.1326 -3.01688C79.134 -3.01736 79.135 -3.0177 79.1356 -3.01791C79.1369 -3.01834 79.1366 -3.01823 79.1347 -3.01759C79.131 -3.01633 79.1212 -3.01297 79.1055 -3.00758C79.0739 -2.99681 79.0185 -2.97794 78.9404 -2.95151C78.7839 -2.89864 78.5366 -2.81564 78.207 -2.7068C77.5472 -2.48895 76.561 -2.16874 75.3165 -1.78027C72.8181 -1.00046 69.3266 0.039393 65.3753 1.07466C57.0052 3.26771 48.2826 4.97383 42.5 4.97383V40.9738C53.2174 40.9738 65.7448 38.193 74.4997 35.8992C79.1109 34.691 83.1506 33.4874 86.0429 32.5846C87.4937 32.1318 88.6676 31.7509 89.4942 31.478C89.9077 31.3414 90.2351 31.2317 90.4676 31.1531C90.5839 31.1138 90.6765 31.0823 90.7443 31.0591C90.7783 31.0475 90.806 31.038 90.8275 31.0306C90.8382 31.0269 90.8473 31.0238 90.8549 31.0212C90.8586 31.0199 90.862 31.0187 90.865 31.0177C90.8665 31.0172 90.8684 31.0165 90.8691 31.0163C90.871 31.0156 90.8727 31.015 85 14ZM42.5 4.97383C36.7174 4.97383 27.9948 3.26771 19.6247 1.07466C15.6734 0.039393 12.1819 -1.00046 9.68352 -1.78027C8.43897 -2.16874 7.4528 -2.48895 6.79299 -2.7068C6.46337 -2.81564 6.21607 -2.89864 6.05965 -2.95151C5.98146 -2.97794 5.92606 -2.99681 5.89453 -3.00758C5.87876 -3.01297 5.86897 -3.01633 5.86528 -3.01759C5.86344 -3.01823 5.86312 -3.01834 5.86435 -3.01791C5.86497 -3.0177 5.86597 -3.01736 5.86736 -3.01688C5.86805 -3.01664 5.86939 -3.01618 5.86973 -3.01606C5.87116 -3.01557 5.87269 -3.01504 0 14C-5.87269 31.015 -5.87096 31.0156 -5.86914 31.0163C-5.8684 31.0165 -5.86647 31.0172 -5.86498 31.0177C-5.86201 31.0187 -5.85864 31.0199 -5.85486 31.0212C-5.84732 31.0238 -5.83818 31.0269 -5.82747 31.0306C-5.80603 31.038 -5.77828 31.0475 -5.74435 31.0591C-5.67649 31.0823 -5.58388 31.1138 -5.46761 31.1531C-5.23512 31.2317 -4.9077 31.3414 -4.49416 31.478C-3.66764 31.7509 -2.49366 32.1318 -1.04289 32.5846C1.84938 33.4874 5.88908 34.691 10.5003 35.8992C19.2552 38.193 31.7826 40.9738 42.5 40.9738V4.97383Z"
|
|
||||||
fill="var(--primary-color)"
|
|
||||||
mask="url(#path-2-inside-1)"
|
|
||||||
/>
|
|
||||||
</svg>
|
|
||||||
|
|
||||||
<span>APOLLO</span>
|
<span>APOLLO</span>
|
||||||
</router-link>
|
</router-link>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button class="layout-menu-button layout-topbar-action" @click="onMenuToggle">
|
|
||||||
<i class="pi pi-bars"></i>
|
|
||||||
</button>
|
|
||||||
|
|
||||||
<div class="layout-topbar-actions">
|
<div class="layout-topbar-actions">
|
||||||
<div class="layout-config-menu">
|
<div class="layout-config-menu">
|
||||||
<button type="button" class="layout-topbar-action" @click="toggleDarkMode">
|
<button type="button" class="layout-topbar-action" @click="toggleDarkMode">
|
||||||
<i :class="['pi', { 'pi-moon': isDarkTheme, 'pi-sun': !isDarkTheme }]"></i>
|
<i :class="['pi', { 'pi-moon': isDarkTheme, 'pi-sun': !isDarkTheme }]"></i>
|
||||||
</button>
|
</button>
|
||||||
<div class="relative">
|
<!--div class="relative">
|
||||||
<button
|
<button
|
||||||
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
|
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
|
||||||
type="button"
|
type="button" class="layout-topbar-action layout-topbar-action-highlight">
|
||||||
class="layout-topbar-action layout-topbar-action-highlight"
|
|
||||||
>
|
|
||||||
<i class="pi pi-palette"></i>
|
<i class="pi pi-palette"></i>
|
||||||
</button>
|
</button>
|
||||||
<AppConfigurator />
|
<AppConfigurator />
|
||||||
</div>
|
</div-->
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<button
|
<button class="layout-topbar-menu-button layout-topbar-action"
|
||||||
class="layout-topbar-menu-button layout-topbar-action"
|
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }">
|
||||||
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
|
|
||||||
>
|
|
||||||
<i class="pi pi-ellipsis-v"></i>
|
<i class="pi pi-ellipsis-v"></i>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<div class="layout-topbar-menu hidden lg:block">
|
<div class="layout-topbar-menu hidden lg:block">
|
||||||
<div class="layout-topbar-menu-content">
|
<div class="layout-topbar-menu-content">
|
||||||
<button type="button" class="layout-topbar-action">
|
|
||||||
<i class="pi pi-calendar"></i>
|
<button
|
||||||
<span>Calendar</span>
|
v-styleclass="{ selector: '@next', enterFromClass: 'hidden', enterActiveClass: 'animate-scalein', leaveToClass: 'hidden', leaveActiveClass: 'animate-fadeout', hideOnOutsideClick: true }"
|
||||||
</button>
|
type="button" class="layout-topbar-action ">
|
||||||
<button type="button" class="layout-topbar-action">
|
|
||||||
<i class="pi pi-inbox"></i>
|
|
||||||
<span>Messages</span>
|
|
||||||
</button>
|
|
||||||
<button type="button" class="layout-topbar-action">
|
|
||||||
<i class="pi pi-user"></i>
|
<i class="pi pi-user"></i>
|
||||||
<span>Profile</span>
|
|
||||||
</button>
|
</button>
|
||||||
|
<AppProfileMenu />
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.logo-image {
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 40px;
|
||||||
|
/* Adjust the size as needed */
|
||||||
|
height: 40px;
|
||||||
|
/* Adjust the size as needed */
|
||||||
|
object-fit: cover;
|
||||||
|
/* Ensures the logo scales nicely within the circle */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|||||||
52
src/main.js
52
src/main.js
@@ -1,24 +1,64 @@
|
|||||||
|
import PrimeVue from 'primevue/config';
|
||||||
|
import ConfirmationService from 'primevue/confirmationservice';
|
||||||
|
import ToastService from 'primevue/toastservice';
|
||||||
import { createApp } from 'vue';
|
import { createApp } from 'vue';
|
||||||
import App from './App.vue';
|
import App from './App.vue';
|
||||||
import router from './router';
|
import router from './router';
|
||||||
|
|
||||||
import PrimeVue from 'primevue/config';
|
|
||||||
import Aura from '@primevue/themes/aura';
|
|
||||||
import ToastService from 'primevue/toastservice';
|
|
||||||
import ConfirmationService from 'primevue/confirmationservice';
|
|
||||||
|
|
||||||
import BlockViewer from '@/components/BlockViewer.vue';
|
import BlockViewer from '@/components/BlockViewer.vue';
|
||||||
|
import { definePreset } from '@primevue/themes';
|
||||||
|
|
||||||
import '@/assets/styles.scss';
|
import '@/assets/styles.scss';
|
||||||
import '@/assets/tailwind.css';
|
import '@/assets/tailwind.css';
|
||||||
|
import Aura from '@primevue/themes/aura';
|
||||||
|
import axios from 'axios';
|
||||||
|
|
||||||
|
axios.defaults.baseURL = import.meta.env.VITE_BACKEND_URL; //'http://localhost:8082'
|
||||||
|
console.log(import.meta.env.VITE_BACKEND_URL);
|
||||||
|
|
||||||
|
|
||||||
|
import { createAuth } from '@websanova/vue-auth';
|
||||||
|
import driverAuthBearer from '@websanova/vue-auth/dist/drivers/auth/bearer.esm.js';
|
||||||
|
import driverHttpAxios from '@websanova/vue-auth/dist/drivers/http/axios.1.x.esm.js';
|
||||||
|
import driverRouterVueRouter from '@websanova/vue-auth/dist/drivers/router/vue-router.2.x.esm.js';
|
||||||
|
|
||||||
|
|
||||||
|
var auth = createAuth({
|
||||||
|
plugins: {
|
||||||
|
http: axios,
|
||||||
|
router: router
|
||||||
|
},
|
||||||
|
drivers: {
|
||||||
|
http: driverHttpAxios,
|
||||||
|
auth: driverAuthBearer,
|
||||||
|
router: driverRouterVueRouter
|
||||||
|
},
|
||||||
|
options:{
|
||||||
|
notFoundRedirect: '/auth/login',
|
||||||
|
authRedirect: '/auth/login',
|
||||||
|
loginData: {url: '../api/auth/login', method: 'POST', redirect: '/'},
|
||||||
|
logoutData: {url:'../api/auth/logout', redirect: '/auth/login'},
|
||||||
|
fetchData: {url: '../api/auth/fetch-user', method: 'GET', enabled: true},
|
||||||
|
refreshData: {url: '../api/auth/refresh-token', method: 'GET', enabled: true}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
const app = createApp(App);
|
const app = createApp(App);
|
||||||
|
|
||||||
app.use(router);
|
app.use(router);
|
||||||
|
app.use(auth);
|
||||||
|
|
||||||
|
const MyPreset = definePreset(Aura, {
|
||||||
|
semantic: {
|
||||||
|
primary: {50: '#ecfeff', 100: '#cffafe', 200: '#a5f3fc', 300: '#67e8f9', 400: '#22d3ee', 500: '#06b6d4', 600: '#0891b2', 700: '#0e7490', 800: '#155e75', 900: '#164e63', 950: '#083344' }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
app.use(PrimeVue, {
|
app.use(PrimeVue, {
|
||||||
theme: {
|
theme: {
|
||||||
preset: Aura,
|
preset: MyPreset,
|
||||||
options: {
|
options: {
|
||||||
|
prefix: 'p',
|
||||||
darkModeSelector: '.app-dark'
|
darkModeSelector: '.app-dark'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,30 +2,52 @@ import AppLayout from '@/layout/AppLayout.vue';
|
|||||||
import { createRouter, createWebHistory } from 'vue-router';
|
import { createRouter, createWebHistory } from 'vue-router';
|
||||||
|
|
||||||
const router = createRouter({
|
const router = createRouter({
|
||||||
history: createWebHistory(),
|
history: createWebHistory(),
|
||||||
routes: [
|
routes: [
|
||||||
|
{
|
||||||
|
path: '/',
|
||||||
|
component: AppLayout,
|
||||||
|
meta: {
|
||||||
|
auth: true
|
||||||
|
},
|
||||||
|
children: [
|
||||||
{
|
{
|
||||||
path: '/',
|
path: '/',
|
||||||
component: AppLayout,
|
name: 'dashboard',
|
||||||
children: [
|
component: () => import('@/views/pages/ksDocuments/KsDocuments.vue')
|
||||||
{
|
},
|
||||||
path: '/',
|
{
|
||||||
name: 'dashboard',
|
path: '/ksdocuments',
|
||||||
component: () => import('@/views/Dashboard.vue')
|
children: [
|
||||||
},
|
{path: '', name: 'ks-document', component: () => import('@/views/pages/ksDocuments/KsDocuments.vue')},
|
||||||
{
|
{path: 'new', name: 'ks-document-new', component: () => import('@/views/pages/ksDocuments/KsNewDocumentForm.vue')},
|
||||||
path: '/ksdocuments',
|
//{path: ':id', name: 'ks-document-edit', component: () => import('@/views/pages/KsEditDocumentForm.vue')},
|
||||||
children: [
|
{path: '/ks_similarity_search', name: 'ks_similarity_search', component: () => import('@/views/pages/similaritySearch/KsSimilaritySearch.vue')},
|
||||||
{path: '', name: 'ks-document', component: () => import('@/views/pages/KsDocuments.vue')},
|
{path: '/ks_vector_data', name: 'ks_vector_data', component: () => import('@/views/pages/vectorDBSearch/KsVectorData.vue')}
|
||||||
{path: 'new', name: 'ks-document-new', component: () => import('@/views/pages/KsDocumentForm.vue')},
|
]
|
||||||
{path: ':id', name: 'ks-document-edit', component: () => import('@/views/pages/KsDocumentForm.vue')}
|
},
|
||||||
|
{
|
||||||
]
|
path: '/ks_git_repos',
|
||||||
|
children: [
|
||||||
},
|
{path: '', name: 'ks-git-repos', component: () => import('@/views/pages/ksGitRepo/KsGitRepos.vue')},
|
||||||
]
|
{path: 'new', name: 'ks-git-repo-new', component: () => import('@/views/pages/ksGitRepo/KsNewGitRepoForm.vue')},
|
||||||
}
|
{path: '/clone', name: 'ks-git-clone-repo', component: () => import('@/views/pages/ksGitRepo/KsGitCloneRepoForm.vue')},
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/kstexts',
|
||||||
|
children: [
|
||||||
|
{path: '', name: 'ks-texts', component: () => import('@/views/pages/KsTexts.vue')},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/auth/login',
|
||||||
|
name: 'login',
|
||||||
|
component: () => import('@/views/pages/auth/Login.vue')
|
||||||
|
},
|
||||||
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
export default router;
|
export default router;
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div className="card">
|
|
||||||
<h5>Ks document</h5>
|
|
||||||
<form @submit.prevent="submitForm">
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="description">Description</label>
|
|
||||||
<InputText id="description" v-model="ksdocument.description" />
|
|
||||||
</div>
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="fileName">File Name</label>
|
|
||||||
<InputText id="fileName" v-model="ksdocument.fileName" />
|
|
||||||
</div>
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="filePath">File Path</label>
|
|
||||||
<InputText id="filePath" v-model="ksdocument.filePath" />
|
|
||||||
</div>
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="ingestionDate">Ingestion Date</label>
|
|
||||||
<InputText id="ingestionDate" v-model="ksdocument.ingestionDate" />
|
|
||||||
</div>
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="defaultChunkSize">Default Chunk Size</label>
|
|
||||||
<InputNumber id="defaultChunkSize" v-model="ksdocument.ingestionInfo.defaultChunkSize" />
|
|
||||||
</div>
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="maxNumberOfChunks">Max Number of Chunks</label>
|
|
||||||
<InputNumber id="maxNumberOfChunks" v-model="ksdocument.ingestionInfo.maxNumberOfChunks" />
|
|
||||||
</div>
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="minChunkSize">Min Chunk Size</label>
|
|
||||||
<InputNumber id="minChunkSize" v-model="ksdocument.ingestionInfo.minChunkSize" />
|
|
||||||
</div>
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="minChunkSizeToEmbed">Min Chunk Size To Embed</label>
|
|
||||||
<InputNumber id="minChunkSizeToEmbed" v-model="ksdocument.ingestionInfo.minChunkSizeToEmbed" />
|
|
||||||
</div>
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="type">Type</label>
|
|
||||||
<InputText id="type" v-model="ksdocument.ingestionInfo.type" />
|
|
||||||
</div>
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="ingestionStatus">Ingestion Status</label>
|
|
||||||
<InputText id="ingestionStatus" v-model="ksdocument.ingestionStatus" />
|
|
||||||
</div>
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="name">Name</label>
|
|
||||||
<InputText id="name" v-model="ksdocument.name" />
|
|
||||||
</div>
|
|
||||||
<div class="p-field">
|
|
||||||
<label for="metadata">Metadata</label>
|
|
||||||
<InputTextarea id="metadata" v-model="ksdocument.ingestionInfo.metadata" />
|
|
||||||
</div>
|
|
||||||
<Button label="Submit" type="submit" />
|
|
||||||
</form>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { onMounted } from 'vue'
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
|
||||||
import { data } from 'autoprefixer';
|
|
||||||
|
|
||||||
const route = useRoute()
|
|
||||||
|
|
||||||
const ksdocument = ref({ingestionInfo:{}});
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
axios.get('http://localhost:8082/ksdocuments/'+route.params.id)
|
|
||||||
.then(response => {
|
|
||||||
console.log(response.data);
|
|
||||||
ksdocument.value = response.data;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const getStatus = (data) => {
|
|
||||||
if (data.ingestionStatus === 'INGESTED') {
|
|
||||||
return 'success';
|
|
||||||
} else if (data.ingestionStatus === 'NEW') {
|
|
||||||
return 'danger';
|
|
||||||
} else {
|
|
||||||
return 'warning';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div className="card">
|
|
||||||
|
|
||||||
<DataTable
|
|
||||||
:value="ksdocuments"
|
|
||||||
:paginator="true"
|
|
||||||
:rows="10"
|
|
||||||
dataKey="id"
|
|
||||||
:rowHover="true"
|
|
||||||
showGridlines
|
|
||||||
>
|
|
||||||
<template #header>
|
|
||||||
<div class="flex flex-wrap items-center justify-between gap-2">
|
|
||||||
<span class="text-xl font-bold">KS Documents</span>
|
|
||||||
<Button icon="pi pi-plus" rounded raised @click="newKsDocument()" />
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
<Column field="name" header="Name"></Column>
|
|
||||||
<Column field="fileName" header="File Name"></Column>
|
|
||||||
<Column field="ingestionStatus" header="Status">
|
|
||||||
<template #body="slotProps">
|
|
||||||
<Tag :value="slotProps.data.ingestionStatus" :severity="getStatus(slotProps.data)" />
|
|
||||||
</template>
|
|
||||||
</Column>
|
|
||||||
<Column field="ingestionDate" header="Ingestion Date"></Column>
|
|
||||||
<Column headerStyle="width: 5rem; text-align: center" bodyStyle="text-align: center; overflow: visible">
|
|
||||||
<template #body="slotProps">
|
|
||||||
<Button type="button" icon="pi pi-pencil" rounded @click="editKsDocument(slotProps.data)"/>
|
|
||||||
</template>
|
|
||||||
</Column>
|
|
||||||
</DataTable>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup>
|
|
||||||
import { ref } from 'vue';
|
|
||||||
import { onMounted } from 'vue'
|
|
||||||
import axios from 'axios';
|
|
||||||
|
|
||||||
import { useRoute, useRouter } from 'vue-router'
|
|
||||||
import { data } from 'autoprefixer';
|
|
||||||
|
|
||||||
const router = useRouter()
|
|
||||||
const ksdocuments = ref(null);
|
|
||||||
|
|
||||||
onMounted(() => {
|
|
||||||
axios.get('http://localhost:8082/fe-api/ksdocuments')
|
|
||||||
.then(response => {
|
|
||||||
console.log(response.data);
|
|
||||||
ksdocuments.value = response.data;
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
const getStatus = (data) => {
|
|
||||||
if (data.ingestionStatus === 'INGESTED') {
|
|
||||||
return 'success';
|
|
||||||
} else if (data.ingestionStatus === 'NEW') {
|
|
||||||
return 'danger';
|
|
||||||
} else {
|
|
||||||
return 'warning';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const editKsDocument = (data) => {
|
|
||||||
console.log(data);
|
|
||||||
router.push({ name: 'ks-document-edit', params: { id: data.id } });
|
|
||||||
}
|
|
||||||
|
|
||||||
const newKsDocument = () => {
|
|
||||||
console.log('new');
|
|
||||||
router.push({ name: 'ks-document-new'});
|
|
||||||
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
124
src/views/pages/KsTexts.vue
Normal file
124
src/views/pages/KsTexts.vue
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<script setup>
|
||||||
|
import { FilterMatchMode, FilterOperator } from '@primevue/core/api';
|
||||||
|
import axios from 'axios';
|
||||||
|
import moment from 'moment';
|
||||||
|
import Button from 'primevue/button';
|
||||||
|
import { useConfirm } from "primevue/useconfirm";
|
||||||
|
import { useToast } from 'primevue/usetoast';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
const textInfo = ref(null);
|
||||||
|
const toast = useToast();
|
||||||
|
const confirm = useConfirm();
|
||||||
|
|
||||||
|
const filters = ref({
|
||||||
|
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||||
|
name: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.CONTAINS }] },
|
||||||
|
ingestionDateFormat: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] },
|
||||||
|
ingestionStatus: { operator: FilterOperator.OR, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] }
|
||||||
|
});
|
||||||
|
onMounted(() => {
|
||||||
|
fectchDetails();
|
||||||
|
});
|
||||||
|
|
||||||
|
const fectchDetails = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get('/texts');
|
||||||
|
console.log(response.data);
|
||||||
|
textInfo.value = getCustomDatewithAllResponse(response.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch texts info: ', error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const deleteRecords = (textDetails) => {
|
||||||
|
confirm.require({
|
||||||
|
target: event.currentTarget,
|
||||||
|
message: "Do you want to Proceed?",
|
||||||
|
icon: 'pip pi-exclamation-circle',
|
||||||
|
rejectProps: {
|
||||||
|
label: 'Cancel',
|
||||||
|
severity: 'secondary',
|
||||||
|
outlined: true
|
||||||
|
},
|
||||||
|
acceptProps: {
|
||||||
|
label: 'Delete Records',
|
||||||
|
severity: 'danger',
|
||||||
|
},
|
||||||
|
accept: () => {
|
||||||
|
axios.delete(`/deleteTextRecords/${textDetails.id}`)
|
||||||
|
.then((response) => {
|
||||||
|
toast.add({ severity: 'success', summary: 'Ingestion Summary', detail: 'Deletion IN Progress', life: 6000 });
|
||||||
|
console.log("Deletion info: ", response.data)
|
||||||
|
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error while ingestion', error)
|
||||||
|
toast.add({ severity: 'error', summary: 'Error Summary', detail: 'Deletion Failed', life: 6000 });
|
||||||
|
})
|
||||||
|
},
|
||||||
|
reject: () => {
|
||||||
|
toast.add({ severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000 })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
//format date
|
||||||
|
const getCustomDatewithAllResponse = (data) => {
|
||||||
|
return [...(data || [])].map((d) => {
|
||||||
|
d.ingestionDateFormat = new Date(d.ingestionDateFormat);
|
||||||
|
return d;
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDate(dateString) {
|
||||||
|
// Parse the date string using moment
|
||||||
|
return moment(dateString).format('MM/DD/YYYY');
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div content-section introduction big-title>
|
||||||
|
<div class="feature-intro">
|
||||||
|
<h1>Texts <span>DataTable</span></h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card">
|
||||||
|
<Toast />
|
||||||
|
<ConfirmPopup></ConfirmPopup>
|
||||||
|
<Toolbar class="mb-6">
|
||||||
|
|
||||||
|
</Toolbar>
|
||||||
|
<DataTable :value="textInfo" :filters="filters">
|
||||||
|
<Column field="id" header="Id">
|
||||||
|
{{ id }}
|
||||||
|
</Column>
|
||||||
|
<Column field="name" header="Name">
|
||||||
|
<template #body="{ data }">
|
||||||
|
{{ data.name }}
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search By Name"></InputText>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="KsApplicationName" header="ApplicationName">
|
||||||
|
<template #body="{ data }">
|
||||||
|
{{ data.ingestionInfo.metadata.KsApplicationName }}
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="ingestionDate" header="Date">
|
||||||
|
<template #body="{ data }">
|
||||||
|
{{ formatDate(data.ingestionDate) }}
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column :exportable="false" style="min-width: 12rem">
|
||||||
|
<template #body="slotProps">
|
||||||
|
<Button text raised rounded severity="info" type="button" class="mr-2" icon="pi pi-trash"
|
||||||
|
@click="deleteRecords(slotProps.data)" v-tooltip.top="'Delete the records'">
|
||||||
|
</Button>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -1,59 +1,101 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { useLayout } from '@/layout/composables/layout';
|
import { useLayout } from '@/layout/composables/layout';
|
||||||
|
import { useAuth } from '@websanova/vue-auth/src/v3.js';
|
||||||
import { computed, ref } from 'vue';
|
import { computed, ref } from 'vue';
|
||||||
|
//import logo from '@/assets/Logo_Apollo_Transparent.png';
|
||||||
|
import logo from '@/assets/apollo.jpg';
|
||||||
|
const auth = useAuth();
|
||||||
|
|
||||||
const { isDarkTheme } = useLayout();
|
const { isDarkTheme } = useLayout();
|
||||||
const email = ref('');
|
const username = ref('');
|
||||||
const password = ref('');
|
const password = ref('');
|
||||||
const checked = ref(false);
|
const logoSrc = ref(logo);
|
||||||
|
|
||||||
const logoUrl = computed(() => {
|
const logoUrl = computed(() => {
|
||||||
return `/layout/images/${isDarkTheme ? 'logo-white' : 'logo-dark'}.svg`;
|
return `/layout/images/${isDarkTheme ? 'logo-white' : 'logo-dark'}.svg`;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const login = () => {
|
||||||
|
console.log('Username: ', username.value);
|
||||||
|
|
||||||
|
auth.login({
|
||||||
|
data: {
|
||||||
|
"username": username.value,
|
||||||
|
"password": password.value
|
||||||
|
},
|
||||||
|
redirect: '/ksdocuments',
|
||||||
|
fetchUser: true,
|
||||||
|
//url: '/api/auth/login'
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
|
<div
|
||||||
<div class="flex flex-col items-center justify-center">
|
class="bg-surface-50 dark:bg-surface-950 flex items-center justify-center min-h-screen min-w-[100vw] overflow-hidden">
|
||||||
<img :src="logoUrl" alt="Sakai logo" class="mb-8 w-24 shrink-0" />
|
<div class="flex flex-col items-center justify-center">
|
||||||
<div style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, var(--primary-color) 10%, rgba(33, 150, 243, 0) 30%)">
|
|
||||||
<div class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20" style="border-radius: 53px">
|
|
||||||
<div class="text-center mb-8">
|
|
||||||
<img src="/demo/images/login/avatar.png" alt="Image" height="50" class="mb-4" />
|
|
||||||
<div class="text-surface-900 dark:text-surface-0 text-3xl font-medium mb-4">Welcome, Isabel!</div>
|
|
||||||
<span class="text-surface-600 dark:text-surface-200 font-medium">Sign in to continue</span>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div>
|
<div
|
||||||
<label for="email1" class="block text-surface-900 dark:text-surface-0 text-xl font-medium mb-2">Email</label>
|
style="border-radius: 56px; padding: 0.3rem; background: linear-gradient(180deg, var(--primary-color) 10%, rgba(33, 150, 243, 0) 30%)">
|
||||||
<InputText id="email1" type="text" placeholder="Email address" class="w-full md:w-[30rem] mb-8" style="padding: 1rem" v-model="email" />
|
<div class="w-full bg-surface-0 dark:bg-surface-900 py-20 px-8 sm:px-20" style="border-radius: 53px">
|
||||||
|
<div class="text-center mb-8">
|
||||||
|
|
||||||
<label for="password1" class="block text-surface-900 dark:text-surface-0 font-medium text-xl mb-2">Password</label>
|
<img :src="logoSrc" alt="Logo" class="logo-image mx-auto" />
|
||||||
<Password id="password1" v-model="password" placeholder="Password" :toggleMask="true" class="w-full mb-4" inputClass="w-full" :inputStyle="{ padding: '1rem' }"></Password>
|
|
||||||
|
|
||||||
<div class="flex items-center justify-between mb-8 gap-8">
|
<!--span style="font-size: 24px;" class="text-surface-600 dark:text-surface-200 font-medium">Welcome to Apollo- The Knowledge Source</span-->
|
||||||
<div class="flex items-center">
|
<div style="text-align: center; padding: 20px;">
|
||||||
<Checkbox v-model="checked" id="rememberme1" binary class="mr-2"></Checkbox>
|
<span style="font-size: 36px; font-weight: bold; color: #3b7a57;">Welcome to Apollo</span><br>
|
||||||
<label for="rememberme1">Remember me</label>
|
<span style="font-size: 24px; color: #555;">The Knowledge Source</span>
|
||||||
</div>
|
|
||||||
<a class="font-medium no-underline ml-2 text-right cursor-pointer" style="color: var(--primary-color)">Forgot password?</a>
|
|
||||||
</div>
|
|
||||||
<Button label="Sign In" class="w-full p-4 text-xl"></Button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="email1"
|
||||||
|
class="block text-surface-900 dark:text-surface-0 text-xl font-medium mb-2">Username</label>
|
||||||
|
<InputText id="email1" type="text" placeholder="Username" class="w-full md:w-[30rem] mb-8"
|
||||||
|
style="padding: 1rem; width: 100%;" v-model="username" />
|
||||||
|
|
||||||
|
<label for="password1"
|
||||||
|
class="block text-surface-900 dark:text-surface-0 font-medium text-xl mb-2">Password</label>
|
||||||
|
<Password id="password1" v-model="password" placeholder="Password" :toggleMask="true" class="w-full mb-4"
|
||||||
|
inputClass="w-full" :inputStyle="{ padding: '1rem', width: '100%' }"></Password>
|
||||||
|
|
||||||
|
<!--div class="flex items-center justify-between mb-8 gap-8">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<Checkbox v-model="checked" id="rememberme1" binary class="mr-2"></Checkbox>
|
||||||
|
<label for="rememberme1">Remember me</label>
|
||||||
|
</div>
|
||||||
|
<a class="font-medium no-underline ml-2 text-right cursor-pointer"
|
||||||
|
style="color: var(--primary-color)">Forgot password?</a>
|
||||||
|
</div> -->
|
||||||
|
<Button label="Sign In" @click="login" class="w-full p-4 text-xl"></Button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
.pi-eye {
|
.pi-eye {
|
||||||
transform: scale(1.6);
|
transform: scale(1.6);
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pi-eye-slash {
|
.pi-eye-slash {
|
||||||
transform: scale(1.6);
|
transform: scale(1.6);
|
||||||
margin-right: 1rem;
|
margin-right: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.logo-image {
|
||||||
|
border-radius: 50%;
|
||||||
|
width: 220px;
|
||||||
|
/* Adjust the size as needed */
|
||||||
|
height: 220px;
|
||||||
|
/* Adjust the size as needed */
|
||||||
|
object-fit: cover;
|
||||||
|
/* Ensures the logo scales nicely within the circle */
|
||||||
|
display: block;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
402
src/views/pages/ksDocuments/KsDocuments.vue
Normal file
402
src/views/pages/ksDocuments/KsDocuments.vue
Normal file
@@ -0,0 +1,402 @@
|
|||||||
|
<template>
|
||||||
|
<div class="card">
|
||||||
|
<Toast />
|
||||||
|
<ConfirmPopup></ConfirmPopup>
|
||||||
|
<div v-if="loading" class="loading-container">
|
||||||
|
<div class="spinner-container">
|
||||||
|
<ProgressSpinner class="spinner" />
|
||||||
|
<p class="loading-text">Loading data...</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<DataTable v-model:filters="filters" :value="ksdocuments" paginator showGridlines :rows="10" dataKey="id"
|
||||||
|
filterDisplay="menu" :loading="loading"
|
||||||
|
:globalFilterFields="['ingestionInfo.metadata.KsApplicationName', 'ingestionInfo.metadata.KsFileSources', 'ingestionInfo.metadata.KsDocSource', 'ingestionStatus', 'ingestionDateFormat']">
|
||||||
|
<template #header>
|
||||||
|
<div class="flex items-center justify-between gap-4 p-4 ">
|
||||||
|
<span class="text-xl font-bold">Knowledge Source Documents</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="newKsDocument()" v-tooltip="'Create New Document'"
|
||||||
|
class="mr-2" />
|
||||||
|
<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 }" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<template #empty>No Records found</template>
|
||||||
|
|
||||||
|
<Column field="ingestionInfo.metadata.KsApplicationName" header="ApplicationName" sortable
|
||||||
|
style="min-width: 12rem">
|
||||||
|
<template #body="{ data }">
|
||||||
|
{{ data.ingestionInfo.metadata.KsApplicationName }}
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search by File" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="ingestionInfo.metadata.KsFileSource" header="FileSource" sortable>
|
||||||
|
<template #body="{ data }">
|
||||||
|
{{ data.ingestionInfo.metadata.KsFileSource }}
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search by File Name" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="ingestionInfo.metadata.KsDocSource" header="DocSource" sortable style="min-width: 12rem">
|
||||||
|
<template #body="{ data }">
|
||||||
|
{{ data.ingestionInfo.metadata.KsDocSource }}
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search by File" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column field="ingestionStatus" header="Status" sortable>
|
||||||
|
<template #body="slotProps">
|
||||||
|
<Tag :value="slotProps.data.ingestionStatus" :severity="getStatus(slotProps.data)" />
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<Select v-model="filterModel.value" @change="filterCallback()" :options="statuses"
|
||||||
|
placeholder="Select One" style="min-width: 12rem" :showClear="true">
|
||||||
|
<template #option="{ option }">
|
||||||
|
<Tag :value="option" :severity="getStatus({ ingestionStatus: option })" />
|
||||||
|
</template>
|
||||||
|
</Select>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column header="Date" filterField="ingestionDateFormat" dataType="date" style="min-width: 10rem">
|
||||||
|
<template #body="{ data }">
|
||||||
|
{{ formatDate(data.ingestionDate) }}
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel }">
|
||||||
|
<DatePicker v-model="filterModel.value" dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy"
|
||||||
|
@change="updateFilterModel" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
<Column headerStyle="width: 5rem; text-align: center" bodyStyle="text-align: center; overflow: visible">
|
||||||
|
<template #body="slotProps">
|
||||||
|
<div class="flex justify-center items-center space-x-3">
|
||||||
|
<!--Button type="button" icon="pi pi-pencil" rounded @click="editKsDocument(slotProps.data)"
|
||||||
|
v-tooltip="'Edit the information of document'" /-->
|
||||||
|
<Button type="button" icon="pi pi-play" rounded
|
||||||
|
@click="startIndividualngestion(slotProps.data.id)"
|
||||||
|
v-tooltip="'Start Ingestion of document'"
|
||||||
|
:disabled="slotProps.data.ingestionStatus === 'INGESTED'"
|
||||||
|
:class="{ 'p-button-danger': slotProps.data.ingestionStatus === 'INGESTED' }" />
|
||||||
|
<Button type="button" icon="pi pi-trash" rounded @click="confirmDelete(slotProps.data.id)"
|
||||||
|
v-tooltip="'Delete the ingested Record'"
|
||||||
|
:disabled="slotProps.data.ingestionStatus === 'NEW'"
|
||||||
|
:class="{ 'p-button-danger': slotProps.data.ingestionStatus === 'NEW' }" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
</DataTable>
|
||||||
|
<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>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { FilterMatchMode, FilterOperator } from '@primevue/core/api';
|
||||||
|
import axios from 'axios';
|
||||||
|
import moment from 'moment';
|
||||||
|
import { useConfirm } from "primevue/useconfirm";
|
||||||
|
import { useToast } from 'primevue/usetoast';
|
||||||
|
import { computed, onMounted, ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import Button from 'primevue/button';
|
||||||
|
import Column from 'primevue/column';
|
||||||
|
import DataTable from 'primevue/datatable';
|
||||||
|
import DatePicker from 'primevue/datepicker';
|
||||||
|
import Dialog from 'primevue/dialog';
|
||||||
|
import InputText from 'primevue/inputtext';
|
||||||
|
import ProgressSpinner from 'primevue/progressspinner';
|
||||||
|
import Select from 'primevue/select';
|
||||||
|
import Tag from 'primevue/tag';
|
||||||
|
|
||||||
|
|
||||||
|
const router = useRouter()
|
||||||
|
const ksdocuments = ref(null);
|
||||||
|
const loading = ref(true);
|
||||||
|
const toast = useToast();
|
||||||
|
const confirm = useConfirm();
|
||||||
|
|
||||||
|
const ingestionDialogVisible = ref(false);
|
||||||
|
const ingestionResult = ref('');
|
||||||
|
const filters = ref();
|
||||||
|
|
||||||
|
const initFilters = () => {
|
||||||
|
filters.value = {
|
||||||
|
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||||
|
id: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
|
||||||
|
'ingestionInfo.metadata.KsApplicationName': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
|
||||||
|
'ingestionInfo.metadata.KsFileSource': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
|
||||||
|
'ingestionInfo.metadata.KsDocSource': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
|
||||||
|
ingestionDateFormat: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] },
|
||||||
|
ingestionStatus: { operator: FilterOperator.OR, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
initFilters();
|
||||||
|
|
||||||
|
const statuses = ref(['NEW', 'INGESTED', 'FAILED']); // Add your statuses here
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
axios.get('/fe-api/ksdocuments')
|
||||||
|
.then(response => {
|
||||||
|
ksdocuments.value = getCustomDatewithAllResponse(response.data);
|
||||||
|
console.log(ksdocuments.value);
|
||||||
|
loading.value = false;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Computed property to check if all documents are ingested
|
||||||
|
const allDocumentsIngested = computed(() => {
|
||||||
|
return ksdocuments.value && ksdocuments.value.every(doc => doc.ingestionStatus === 'INGESTED');
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
const getStatus = (data) => {
|
||||||
|
if (data.ingestionStatus === 'INGESTED') {
|
||||||
|
return 'success';
|
||||||
|
} else if (data.ingestionStatus === 'NEW') {
|
||||||
|
return 'danger';
|
||||||
|
} else {
|
||||||
|
return 'warn';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const getCustomDatewithAllResponse = (data) => {
|
||||||
|
return [...(data || [])].map((d) => {
|
||||||
|
d.ingestionDateFormat = new Date(d.ingestionDateFormat);
|
||||||
|
return d;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateFilterModel = () => {
|
||||||
|
console.log("updateFilterModel")
|
||||||
|
}
|
||||||
|
|
||||||
|
const editKsDocument = (data) => {
|
||||||
|
console.log(data);
|
||||||
|
router.push({ name: 'ks-document-edit', params: { id: data.id } });
|
||||||
|
}
|
||||||
|
|
||||||
|
const confirmDelete = (id) => {
|
||||||
|
console.log("id", id);
|
||||||
|
|
||||||
|
confirm.require({
|
||||||
|
target: event.currentTarget,
|
||||||
|
message: 'Are you sure you want to proceed?',
|
||||||
|
icon: 'pi pi-exclamation-triangle',
|
||||||
|
rejectProps: {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestPayload = {
|
||||||
|
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)
|
||||||
|
.then(response => {
|
||||||
|
console.log('Delete resource:', response.data)
|
||||||
|
ksdocuments.value = ksdocuments.value.filter(doc => doc.id !== id);
|
||||||
|
console.log('ksdocuments.value', ksdocuments.value)
|
||||||
|
toast.add({ severity: 'info', summary: 'Confirmed', detail: 'deletion is in PROGRESS', life: 3000 });
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error deleting records: ', error)
|
||||||
|
toast.add({ severity: 'error', summary: 'Error', detail: 'Error in Deletion', life: 3000 });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
reject: () => {
|
||||||
|
toast.add({ severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000 })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
//ingestion
|
||||||
|
const startIndividualngestion = (id) => {
|
||||||
|
axios.get(`/test/ingest_document/${id}`)
|
||||||
|
.then(response => {
|
||||||
|
ingestionResult.value = response.data;
|
||||||
|
if (response.data.status == "OK") {
|
||||||
|
ksdocuments.value.forEach(element => {
|
||||||
|
if (response.data.ingestedDocumentId.includes(element.id)) {
|
||||||
|
element.status = "INGESTED"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ingestionResult.value = `Error: ${response.data.message}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
ingestionDialogVisible.value = true;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
ingestionDialogVisible.value = true;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const startlngestion = () => {
|
||||||
|
axios.get('/test/ingestion_loop')
|
||||||
|
.then(response => {
|
||||||
|
ingestionResult.value = response.data;
|
||||||
|
if (response.data.status == "OK") {
|
||||||
|
ksdocuments.value.forEach(element => {
|
||||||
|
if (response.data.ingestedDocumentId.includes(element.id)) {
|
||||||
|
element.status = "INGESTED"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
ingestionResult.value = `Error: ${response.data.message}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
ingestionDialogVisible.value = true;
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
ingestionDialogVisible.value = true;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
//new record creation
|
||||||
|
const newKsDocument = () => {
|
||||||
|
console.log('new');
|
||||||
|
router.push({ name: 'ks-document-new' });
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to format date string
|
||||||
|
function formatDate(dateString) {
|
||||||
|
// Parse the date string using moment
|
||||||
|
return moment(dateString).format('MM/DD/YYYY');
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
/* Custom styling for disabled red button */
|
||||||
|
.p-button-danger {
|
||||||
|
background-color: white;
|
||||||
|
border-color: blue;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-button-danger:disabled {
|
||||||
|
/*background-color: red;*/
|
||||||
|
border-color: red;
|
||||||
|
color: red;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.space-x-3>*+* {
|
||||||
|
margin-left: 1rem;
|
||||||
|
/* Adjust as needed for desired spacing */
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
position: fixed;
|
||||||
|
/* Change to fixed */
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
z-index: 9999;
|
||||||
|
/* Ensure it’s on top of everything */
|
||||||
|
background-color: rgba(255, 255, 255, 0.8);
|
||||||
|
/* Optional: Add a background to obscure content */
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
animation: fade-in 1s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
color: var(--primary-color, #007bff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-text {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
animation: pulse 1.5s infinite;
|
||||||
|
margin-top: 10px;
|
||||||
|
color: var(--primary-color, #007bff);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
color: var(--primary-color, #007bff);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
opacity: 0.11;
|
||||||
|
color: var(--primary-color, #007bff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
margin: 2rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
207
src/views/pages/ksDocuments/KsNewDocumentForm.vue
Normal file
207
src/views/pages/ksDocuments/KsNewDocumentForm.vue
Normal file
@@ -0,0 +1,207 @@
|
|||||||
|
<template>
|
||||||
|
<Fluid>
|
||||||
|
<div class="flex mt-6">
|
||||||
|
<div class="card flex flex-col gap-4 w-full">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-3xl font-bold mb-4">Ks document</h2>
|
||||||
|
</div>
|
||||||
|
<form @submit.prevent="submitForm" class="p-fluid">
|
||||||
|
<div class="col-12 md:col-6 mb-4">
|
||||||
|
<span class="p-float-label">
|
||||||
|
<label for="description" v-tooltip="'A brief overview of the system purpose and functionality.'">System
|
||||||
|
Description</label>
|
||||||
|
<InputText id="description" type="text" v-model="formData.description" required class="w-full" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 md:col-6 mb-4">
|
||||||
|
<span class="p-float-label">
|
||||||
|
<label for="type"
|
||||||
|
v-tooltip="'Specify the type of file here. e.g, PDF Document, DOCX, TXT, MD Document etc..'">File
|
||||||
|
Type</label>
|
||||||
|
<InputText id="type" v-model="formData.type" required class="w-full" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 md:col-6 mb-4">
|
||||||
|
<span class="p-float-label">
|
||||||
|
<label for="ksApplicationName" v-tooltip="'Enter the application name here.'">KS Application Name</label>
|
||||||
|
<InputText id="ksApplicationName" v-model="formData.ksApplicationName" required class="w-full" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 md:col-6 mb-4">
|
||||||
|
<span class="p-float-label">
|
||||||
|
<label for="ksDocType" v-tooltip="'Specify the type of document e.g, md, pdf,'">KS Document Type</label>
|
||||||
|
<Select id="ksDocType" v-model="formData.ksDocType" :options="dropdownItems" required optionLabel="name"
|
||||||
|
optionValue="value" placeholder="Select One" class="w-full"></Select>
|
||||||
|
<!--InputText id="ksDocType" v-model="formData.ksDocType" required class="w-full" /-->
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 md:col-6 mb-4">
|
||||||
|
<span class="p-float-label">
|
||||||
|
<label for="ksDocSource"
|
||||||
|
v-tooltip="'The KS Document Source field is intended to capture the origin or source from where the document was obtained or associated. ex.. Retrieved from DevopsJ2Cloud Git Repository - CSV System Configuration '">KS
|
||||||
|
Document Source</label>
|
||||||
|
<InputText id="ksDocSource" v-model="formData.ksDocSource" required class="w-full" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 md:col-6 mb-4">
|
||||||
|
<span class="p-float-label">
|
||||||
|
<label for="defaultChunkSize" v-tooltip="'Define the default size for chunks of data.'">Default Chunk
|
||||||
|
Size</label>
|
||||||
|
<InputNumber id="defaultChunkSize" v-model="formData.defaultChunkSize" required class="w-full" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 md:col-6 mb-4">
|
||||||
|
<span class="p-float-label">
|
||||||
|
<label for="minChunkSize" v-tooltip="'Specify the minimum allowable size for chunks'">Min Chunk
|
||||||
|
Size</label>
|
||||||
|
<InputNumber id="minChunkSize" v-model="formData.minChunkSize" required class="w-full" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 md:col-6 mb-4">
|
||||||
|
<span class="p-float-label">
|
||||||
|
<label for="maxNumberOfChunks" v-tooltip="'Set the maximum number of chunks allowed.'">Max Number of
|
||||||
|
Chunks</label>
|
||||||
|
<InputNumber id="maxNumberOfChunks" v-model="formData.maxNumberOfChunks" required class="w-full" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 md:col-6 mb-4">
|
||||||
|
<span class="p-float-label">
|
||||||
|
<label for="minChunkSizeToEmbed" v-tooltip="'Define the minimum chunk size that can be embedded.'">Min
|
||||||
|
Chunk Size to
|
||||||
|
Embed</label>
|
||||||
|
<InputNumber id="minChunkSizeToEmbed" v-model="formData.minChunkSizeToEmbed" required class="w-full" />
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="col-12 mb-4">
|
||||||
|
<label for="file" class="block text-lg mb-2" v-tooltip="'Upload the file here.'">File</label>
|
||||||
|
<div class="flex align-items-center">
|
||||||
|
<FileUpload ref="fileUpload" mode="basic" :maxFileSize="10000000000" chooseLabel="Select File"
|
||||||
|
class="p-button-rounded" @select="onFileSelect" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button type="submit" label="Submit" :fluid="false" class="p-button-rounded p-button-lg" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Fluid>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import axios from 'axios';
|
||||||
|
import { useToast } from 'primevue/usetoast';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
const toast = useToast();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const dropdownItems = ref([
|
||||||
|
{ name: 'PDF', value: 'pdf' },
|
||||||
|
{ name: 'MD', value: 'md' },
|
||||||
|
{ name: 'DOCX', value: 'docx' },
|
||||||
|
{ name: 'EXCEL', value: 'excel' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
const formData = ref({
|
||||||
|
description: '', //Jenkins DevopsJ2Cloud System CSV configuration md file
|
||||||
|
ingestionStatus: 'NEW',
|
||||||
|
type: '', //.md file
|
||||||
|
ksApplicationName: '', //Jenkins-DevopsJ2Cloud
|
||||||
|
ksDocType: '',
|
||||||
|
ksDocSource: '', //Git Repository - DevopsJ2Cloud CSV System Configuration
|
||||||
|
defaultChunkSize: 1000,
|
||||||
|
minChunkSize: 200,
|
||||||
|
maxNumberOfChunks: 1000,
|
||||||
|
minChunkSizeToEmbed: 20
|
||||||
|
});
|
||||||
|
|
||||||
|
const fileUpload = ref(null);
|
||||||
|
const selectedFile = ref(null);
|
||||||
|
|
||||||
|
const onFileSelect = (event) => {
|
||||||
|
selectedFile.value = event.files[0];
|
||||||
|
};
|
||||||
|
|
||||||
|
const submitForm = async () => {
|
||||||
|
const formDataToSend = new FormData();
|
||||||
|
|
||||||
|
if (selectedFile.value) {
|
||||||
|
formDataToSend.append('file', selectedFile.value);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append each field separately to ensure they are correctly processed by the server
|
||||||
|
formDataToSend.append('description', formData.value.description);
|
||||||
|
formDataToSend.append('type', formData.value.type);
|
||||||
|
formDataToSend.append('ksApplicationName', formData.value.ksApplicationName);
|
||||||
|
formDataToSend.append('ksDocType', formData.value.ksDocType);
|
||||||
|
formDataToSend.append('ksDocSource', formData.value.ksDocSource);
|
||||||
|
formDataToSend.append('defaultChunkSize', formData.value.defaultChunkSize);
|
||||||
|
formDataToSend.append('minChunkSize', formData.value.minChunkSize);
|
||||||
|
formDataToSend.append('maxNumberOfChunks', formData.value.maxNumberOfChunks);
|
||||||
|
formDataToSend.append('minChunkSizeToEmbed', formData.value.minChunkSizeToEmbed);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.post('/upload', formDataToSend, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('Upload successful:', response.data);
|
||||||
|
toast.add({ severity: 'success', summary: 'Success', detail: 'File uploaded successfully', life: 3000 });
|
||||||
|
|
||||||
|
// Redirect to desktop.vue
|
||||||
|
router.push({ name: 'ks-document' });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Upload failed:', error);
|
||||||
|
toast.add({ severity: 'error', summary: 'Error', detail: 'File upload failed', life: 3000 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.card-container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 2rem auto;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-card) {
|
||||||
|
background: linear-gradient(145deg, #f3f4f6, #ffffff);
|
||||||
|
border-radius: 15px;
|
||||||
|
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-button) {
|
||||||
|
background: linear-gradient(45deg, #4CAF50, #45a049);
|
||||||
|
border: none;
|
||||||
|
transition: all 0.3s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-button:hover) {
|
||||||
|
background: linear-gradient(45deg, #45a049, #4CAF50);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-inputtext:focus) {
|
||||||
|
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-dropdown:focus) {
|
||||||
|
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-inputnumber-input:focus) {
|
||||||
|
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
184
src/views/pages/ksGitRepo/KsGitCloneRepoForm.vue
Normal file
184
src/views/pages/ksGitRepo/KsGitCloneRepoForm.vue
Normal file
@@ -0,0 +1,184 @@
|
|||||||
|
<template>
|
||||||
|
<Fluid>
|
||||||
|
<div class="flex mt-6">
|
||||||
|
<div class="card flex flex-col gap-4 w-full">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-3xl font-bold mb-4">Clone Repository</h2>
|
||||||
|
</div>
|
||||||
|
<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" :disabled="isSubmitting" :fluid="false"
|
||||||
|
class="p-button-rounded p-button-lg mt-4" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Fluid>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import axios from 'axios';
|
||||||
|
import Button from 'primevue/button';
|
||||||
|
import InputNumber from 'primevue/inputnumber';
|
||||||
|
import InputText from 'primevue/inputtext';
|
||||||
|
import { useToast } from 'primevue/usetoast';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
const toast = useToast();
|
||||||
|
const router = useRouter();
|
||||||
|
const isSubmitting = ref(false);
|
||||||
|
|
||||||
|
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 submitForm = async () => {
|
||||||
|
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)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.post('/fe-api/ks_git_repos/clone', json, {
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
console.log('Submit successful:', response.data);
|
||||||
|
toast.add({ severity: 'success', summary: 'Success', detail: 'Repository submitted successfully', life: 3000 });
|
||||||
|
|
||||||
|
// Redirect to desktop.vue
|
||||||
|
router.push({ name: 'ks-git-repos' });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Submit failed:', error);
|
||||||
|
toast.add({ severity: 'error', summary: 'Error', detail: 'Submission failed', life: 3000 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
function formDatatoJson(formData) {
|
||||||
|
const jsonObject = {};
|
||||||
|
formData.forEach((value, key) => {
|
||||||
|
jsonObject[key] = value;
|
||||||
|
})
|
||||||
|
return jsonObject;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.card-container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 2rem auto;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-card) {
|
||||||
|
background: linear-gradient(45deg, #45a049, #4caf50);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-button:hover) {
|
||||||
|
background: linear-gradient(45deg, #45a049, #4caf50);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-inputtext:focus) {
|
||||||
|
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-dropdown:focus) {
|
||||||
|
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-inputnumber-input:focus) {
|
||||||
|
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-4 {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
154
src/views/pages/ksGitRepo/KsGitCloneRepoFormDialog.vue
Normal file
154
src/views/pages/ksGitRepo/KsGitCloneRepoFormDialog.vue
Normal file
@@ -0,0 +1,154 @@
|
|||||||
|
<template>
|
||||||
|
<form @submit.prevent="submitForm" class="p-fluid">
|
||||||
|
<div class="flex flex-col gap-6">
|
||||||
|
<div class="grid grid-cols-12 gap-4">
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label for="repoName" class="block font-bold mb-3">Repo Name</label>
|
||||||
|
<InputText id="repoName" v-model.trim="formData.repoName" placeholder="Enter Repo Name"
|
||||||
|
required="true" fluid />
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label for="group" class="block font-bold mb-3">Group Name</label>
|
||||||
|
<InputText id="group" v-model.trim="formData.group" placeholder="Enter Group Name" required="true"
|
||||||
|
fluid />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<label for="source" class="block font-bold mb-3">Git Source URL</label>
|
||||||
|
<!--InputText id="source" v-model.trim="formData.source" placeholder="Enter Source base URL"
|
||||||
|
required="true" /-->
|
||||||
|
<Select id="source" v-model="formData.source" :options="gitSourceURLs" optionLabel="label"
|
||||||
|
optionValue="value" placeholder="Select Git URL" fluid></Select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-12 gap-4">
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label for="branch" class="block font-bold mb-3">Branch</label>
|
||||||
|
<InputText id="branch" v-model.trim="formData.branch" placeholder="Enter Branch" required="true" />
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label for="tokenType" class="block font-bold mb-3">Git Token Type</label>
|
||||||
|
<Select id="tokenType" v-model="formData.tokenType" :options="tokenTypes" optionLabel="label"
|
||||||
|
optionValue="value" placeholder="Select Git Token Type" fluid></Select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
<!--div>
|
||||||
|
<label for="commitId" class="block font-bold mb-3">CommitID</label>
|
||||||
|
<InputText id="commitId" type="text" v-model.trim="formData.commitId" required="true" />
|
||||||
|
</div-->
|
||||||
|
|
||||||
|
|
||||||
|
<div class="grid grid-cols-12 gap-4">
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label for="defaultChunkSize" class="block font-bold mb-3">Default Chunk Size</label>
|
||||||
|
<InputNumber id="defaultChunkSize" v-model="formData.defaultChunkSize" required="true" integeronly
|
||||||
|
fluid />
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label for="minChunkSize" class="block font-bold mb-3">Min Chunk Size</label>
|
||||||
|
<InputNumber id="minChunkSize" v-model="formData.minChunkSize" required="true" integeronly fluid />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="grid grid-cols-12 gap-4">
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label for="maxNumberOfChunks" class="block font-bold mb-3">Max Number of Chunks</label>
|
||||||
|
<InputNumber id="maxNumberOfChunks" v-model="formData.maxNumberOfChunks" required="true" integeronly
|
||||||
|
fluid />
|
||||||
|
</div>
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label for="minChunkSizeToEmbed" class="block font-bold mb-3">Min Chunk Size to Embed</label>
|
||||||
|
<InputNumber id="minChunkSizeToEmbed" v-model="formData.minChunkSizeToEmbed" required="true"
|
||||||
|
integeronly fluid />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="button-container">
|
||||||
|
<Button type="button" label="Cancel" text rounded raised :fluid="false" severity="danger"
|
||||||
|
class="p-button-rounded p-button-lg mt-4 mr-4" @click="handleCancel" />
|
||||||
|
<Button type="submit" label="Submit" text rounded raised :disabled="isSubmitting" :fluid="false"
|
||||||
|
class="p-button-rounded p-button-lg mt-4" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</form>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { defineEmits, ref } 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 gitSourceURLs = ref([
|
||||||
|
{ label: 'https://github.com', value: 'https://github.com' },
|
||||||
|
{ label: 'https://gitlab.gcp.windtre.it', value: 'https://gitlab.gcp.windtre.it' },
|
||||||
|
{ label: 'http://devops-tool-a-vip01.wind.root.it:8888', value: 'http://devops-tool-a-vip01.wind.root.it:8888' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
const tokenTypes = ref([
|
||||||
|
{ label: 'git-cloud', value: 'cloud' },
|
||||||
|
{ label: 'git-onpremises', value: 'onpremises' },
|
||||||
|
{ label: 'git-github', value: 'github' }
|
||||||
|
]);
|
||||||
|
|
||||||
|
const isSubmitting = ref(false);
|
||||||
|
|
||||||
|
const emit = defineEmits(['submitForm', 'cancel'])
|
||||||
|
|
||||||
|
const handleCancel = () => {
|
||||||
|
emit('cancel')
|
||||||
|
}
|
||||||
|
|
||||||
|
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>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.button-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
583
src/views/pages/ksGitRepo/KsGitRepos.vue
Normal file
583
src/views/pages/ksGitRepo/KsGitRepos.vue
Normal file
@@ -0,0 +1,583 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div class="content-section introduction big-title">
|
||||||
|
<div class="feature-intro">
|
||||||
|
<h1>Repository <span>DataTable</span></h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card">
|
||||||
|
<Toast />
|
||||||
|
<ConfirmPopup></ConfirmPopup>
|
||||||
|
<Toolbar class="mb-6">
|
||||||
|
<template #start>
|
||||||
|
<Button label="Refresh" icon="pi pi-refresh" severity="secondary" class="mr-2" rounded
|
||||||
|
@click="refreshPage" v-tooltip.top="'Refresh all records'" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<template #end>
|
||||||
|
<Button label="Expand All" icon="pi pi-plus" severity="secondary" class="mr-3" rounded
|
||||||
|
@click="expandAll" v-tooltip.top="'Expand all records'" />
|
||||||
|
<Button label="Collapse All" icon="pi pi-minus" severity="secondary" class="mr-3" rounded
|
||||||
|
@click="collapseAll" v-tooltip.top="'Collapse all records'" />
|
||||||
|
<!--Button label="Add New Git Repo" icon="pi pi-plus" severity="secondary" rounded class="mr-3" @click="newCodeRepoForm()" v-tooltip.top="'Add New Git Repo'" class="mr-2" /-->
|
||||||
|
<!--Button label="Add Git Repo" icon="pi pi-bolt" severity="secondary" rounded @click="cloneRepoForm()" v-tooltip.top="'Add New Git Repo'" /-->
|
||||||
|
<Button label="New Git Repository" icon="pi pi-bolt" severity="secondary" rounded
|
||||||
|
@click="showDialog = true" v-tooltip.top="'Add New Git Repository'" />
|
||||||
|
|
||||||
|
<Dialog v-model:visible="showDialog" :style="{ width: '50rem' }" header="Repository Details"
|
||||||
|
:modal="true">
|
||||||
|
<div>
|
||||||
|
<cloneForm @submitForm="cloneRepo" @cancel="showDialog = false" />
|
||||||
|
</div>
|
||||||
|
</Dialog>
|
||||||
|
</template>
|
||||||
|
</Toolbar>
|
||||||
|
|
||||||
|
<DataTable v-model:filters="filters" v-model:expandedRows="expandedRows" @rowExpand="onRowExpand"
|
||||||
|
@rowCollapse="onRowCollapse" :value="codeRepoInfo" :paginator="true" :rows="10"
|
||||||
|
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" rowGroupMode="subheader"
|
||||||
|
groupRowsBy="repoName" sortMode="single" sortField="ksGitIngestionInfo.metadata.KsApplicationName"
|
||||||
|
:sortOrder="1" filterDisplay="menu" :loading="loading"
|
||||||
|
:globalFilterFields="['branch', 'ingestionStatus', 'ingestionDateFormat']" tableStyle="min-width: 70rem"
|
||||||
|
removableSort>
|
||||||
|
<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>
|
||||||
|
<div class=" flex justify-content-center">
|
||||||
|
<ProgressSpinner />
|
||||||
|
</div>
|
||||||
|
</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">
|
||||||
|
<template #body="{ data }">
|
||||||
|
{{ data.repoName }}
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search by Git Repo Name" />
|
||||||
|
</template>
|
||||||
|
</Column-->
|
||||||
|
|
||||||
|
<Column field="branch" header="Branch">
|
||||||
|
<template #body="{ data }">
|
||||||
|
{{ data.branch }}
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search by Git Repo Branch" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<Column field="ingestionStatus" header="Status" sortable>
|
||||||
|
<template #body="slotProps">
|
||||||
|
<Tag :value="slotProps.data.ingestionStatus" :severity="getStatus(slotProps.data)" />
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<Select v-model="filterModel.value" @change="filterCallback()" :options="statuses"
|
||||||
|
placeholder="Select One" style="min-width: 12rem" :showClear="true">
|
||||||
|
<template #option="{ option }">
|
||||||
|
<Tag :value="option" :severity="getStatus({ ingestionStatus: option })" />
|
||||||
|
</template>
|
||||||
|
</Select>
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<Column field="ingestionDate" header="Ingestion Date" sortable filterField="ingestionDateFormat"
|
||||||
|
dataType="date" style="min-width: 10rem">
|
||||||
|
<template #body="{ data }">
|
||||||
|
{{ formatDate(data.ingestionDate) }}
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel }">
|
||||||
|
<DatePicker v-model="filterModel.value" dateFormat="mm/dd/yy" placeholder="mm/dd/yyyy"
|
||||||
|
@change="updateFilterModel" />
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
<!--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">
|
||||||
|
|
||||||
|
<Button text raised rounded severity="info" type="button" class="mr-2" icon="pi pi-play"
|
||||||
|
@click="ingestGitRepo(slotProps.data)" v-tooltip.top="'Start Ingestion of Git'"
|
||||||
|
:disabled="isButtonDisabled(slotProps.data)" />
|
||||||
|
|
||||||
|
<Button text raised rounded severity="warn" type="button" class="mr-2" icon="pi pi-forward"
|
||||||
|
@click="reIngestWithPullChanges(slotProps.data)"
|
||||||
|
v-tooltip.top="'Ingest Latest changes From Git'" />
|
||||||
|
|
||||||
|
<Button text raised rounded severity="danger" type="button" icon="pi pi-trash"
|
||||||
|
@click="deleteRecordsFromVectorStore(slotProps.data)" v-tooltip.top="'Delete Records'" />
|
||||||
|
|
||||||
|
</template>
|
||||||
|
</Column>
|
||||||
|
|
||||||
|
|
||||||
|
<template #expansion="slotProps">
|
||||||
|
<div class="p-4">
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import logo from '@/assets/gitlab-logo.svg';
|
||||||
|
import VueJsonView from '@matpool/vue-json-view';
|
||||||
|
import { FilterMatchMode, FilterOperator } from '@primevue/core/api';
|
||||||
|
import axios from 'axios';
|
||||||
|
import moment from 'moment';
|
||||||
|
import { useToast } from 'primevue/usetoast';
|
||||||
|
import { computed, onMounted, ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
import Button from 'primevue/button';
|
||||||
|
import Column from 'primevue/column';
|
||||||
|
import DataTable from 'primevue/datatable';
|
||||||
|
import DatePicker from 'primevue/datepicker';
|
||||||
|
import Dialog from 'primevue/dialog';
|
||||||
|
import InputText from 'primevue/inputtext';
|
||||||
|
import Select from 'primevue/select';
|
||||||
|
import Tag from 'primevue/tag';
|
||||||
|
import { useConfirm } from "primevue/useconfirm";
|
||||||
|
|
||||||
|
import socketManager from '/src/components/SocketManager.vue';
|
||||||
|
|
||||||
|
import ProgressSpinner from 'primevue/progressspinner';
|
||||||
|
|
||||||
|
|
||||||
|
//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);
|
||||||
|
const toast = useToast();
|
||||||
|
const confirm = useConfirm();
|
||||||
|
const expandedRows = ref({});
|
||||||
|
|
||||||
|
const ingestionResult = ref('');
|
||||||
|
const popupTitle = ref('');
|
||||||
|
const popupMessage = ref('');
|
||||||
|
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();
|
||||||
|
});
|
||||||
|
|
||||||
|
const refreshPage = () => {
|
||||||
|
location.reload(); // Reloads the current page
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//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 filters = ref({
|
||||||
|
global: { value: null, matchMode: FilterMatchMode.CONTAINS },
|
||||||
|
id: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] },
|
||||||
|
branch: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] },
|
||||||
|
ingestionDateFormat: { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.DATE_IS }] },
|
||||||
|
ingestionStatus: { operator: FilterOperator.OR, constraints: [{ value: null, matchMode: FilterMatchMode.EQUALS }] }
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function calculateCustomerTotal(name) {
|
||||||
|
let total = 0;
|
||||||
|
if (codeRepoInfo.value) {
|
||||||
|
for (let RepoInfo of codeRepoInfo.value) {
|
||||||
|
if (RepoInfo.repoName === name) {
|
||||||
|
total++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return total;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fetchCodeRepoInfo = async () => {
|
||||||
|
try {
|
||||||
|
const response = await axios.get('/fe-api/ks_git_repos');
|
||||||
|
//codeRepoInfo.value = response.data;
|
||||||
|
codeRepoInfo.value = getCustomDatewithAllResponse(response.data);
|
||||||
|
console.log(codeRepoInfo.value);
|
||||||
|
loading.value = false;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch code repo info:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getCustomDatewithAllResponse = (data) => {
|
||||||
|
return [...(data || [])].map((d) => {
|
||||||
|
d.ingestionDateFormat = new Date(d.ingestionDateFormat);
|
||||||
|
return d;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
//ingest git repo functions
|
||||||
|
const ingestGitRepo = (repo) => {
|
||||||
|
confirm.require({
|
||||||
|
target: event.currentTarget,
|
||||||
|
message: 'Are you sure you want to proceed?',
|
||||||
|
icon: 'pi pi-exclamation-circle',
|
||||||
|
rejectProps: {
|
||||||
|
label: 'Cancel',
|
||||||
|
severity: 'secondary',
|
||||||
|
outlined: true
|
||||||
|
},
|
||||||
|
acceptProps: {
|
||||||
|
label: 'Ingest Record',
|
||||||
|
severity: 'danger',
|
||||||
|
},
|
||||||
|
accept: () => {
|
||||||
|
axios.get(`/test/ingest_repo?repoName=${repo.repoName}&branchName=${repo.branch}`)
|
||||||
|
.then((response) => {
|
||||||
|
toast.add({ severity: 'success', summary: 'Ingestion Summary', detail: 'Repository Ingestion Started', life: 6000 });
|
||||||
|
console.log('Delete resource:', response.data)
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
console.error('Error deleting records: ', error)
|
||||||
|
toast.add({ severity: 'error', summary: 'Error', detail: 'Error Ingesting records:', life: 6000 });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
reject: () => {
|
||||||
|
toast.add({ severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000 })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
// ---------------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
const allDocumentsIngested = computed(() => {
|
||||||
|
return codeRepoInfo.value && codeRepoInfo.value.every((doc) => doc.ingestionStatus === 'INGESTED');
|
||||||
|
});
|
||||||
|
|
||||||
|
const updateFilterModel = () => {
|
||||||
|
console.log('updateFilterModel');
|
||||||
|
};
|
||||||
|
|
||||||
|
const newCodeRepoForm = () => {
|
||||||
|
console.log('new');
|
||||||
|
router.push({ name: 'ks-git-repo-new' });
|
||||||
|
};
|
||||||
|
|
||||||
|
const cloneRepoForm = () => {
|
||||||
|
console.log("clone repo form");
|
||||||
|
router.push({ name: 'ks-git-clone-repo' });
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatDate(dateString) {
|
||||||
|
// Parse the date string using moment
|
||||||
|
return moment(dateString).format('MM/DD/YYYY');
|
||||||
|
}
|
||||||
|
|
||||||
|
const getStatus = (data) => {
|
||||||
|
if (data.ingestionStatus == 'INGESTED') {
|
||||||
|
return 'success';
|
||||||
|
} else if (data.ingestionStatus === 'INGESTION-IN-PROGRESS' || data.ingestionStatus === 'REPO-CLONE-IN-PROGRESS') {
|
||||||
|
return 'info';
|
||||||
|
} else if (data.ingestionStatus === 'INGESTION-ERROR' || data.ingestionStatus === 'REPO-CLONE-FAILED') {
|
||||||
|
return 'danger';
|
||||||
|
} else if (data.ingestionStatus === 'REPO-NEW') {
|
||||||
|
return 'warning';
|
||||||
|
} else if (data.ingestionStatus === 'REPO-CLONE-COMPLETED') {
|
||||||
|
return 'contrast';
|
||||||
|
} else {
|
||||||
|
return 'secondary';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//delete functionality
|
||||||
|
const deleteRecordsFromVectorStore = (data) => {
|
||||||
|
console.log("data", data);
|
||||||
|
console.log("reponame", data.repoName);
|
||||||
|
|
||||||
|
const requestPayload = {
|
||||||
|
ksGitInfoId: data.id,
|
||||||
|
ksGitIngestionInfoId: data.ksGitIngestionInfo.id,
|
||||||
|
ksDoctype: data.ksGitIngestionInfo.metadata.KsDoctype,
|
||||||
|
ksDocSource: data.ksGitIngestionInfo.metadata.KsDocSource,
|
||||||
|
ksFileSource: data.ksGitIngestionInfo.metadata.KsFileSource,
|
||||||
|
ksApplicationName: data.ksGitIngestionInfo.metadata.KsApplicationName,
|
||||||
|
ksBranch: data.ksGitIngestionInfo.metadata.KsBranch
|
||||||
|
};
|
||||||
|
console.log("requestPayload", requestPayload)
|
||||||
|
|
||||||
|
confirm.require({
|
||||||
|
target: event.currentTarget,
|
||||||
|
message: 'Are you sure you want to proceed?',
|
||||||
|
icon: 'pi pi-exclamation-circle',
|
||||||
|
rejectProps: {
|
||||||
|
label: 'Cancel',
|
||||||
|
severity: 'secondary',
|
||||||
|
outlined: true
|
||||||
|
},
|
||||||
|
acceptProps: {
|
||||||
|
label: 'Delete Records',
|
||||||
|
severity: 'danger',
|
||||||
|
},
|
||||||
|
accept: () => {
|
||||||
|
axios.post('/fe-api/vector-store/deleteGitRecords', requestPayload)
|
||||||
|
.then(response => {
|
||||||
|
toast.add({ severity: 'info', summary: 'Deletion', detail: 'Records Deletion INPROGRESS', life: 6000 });
|
||||||
|
console.log('Delete resource:', response.data)
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error deleting records: ', error)
|
||||||
|
toast.add({ severity: 'error', summary: 'Error', detail: 'Error deleting records:', life: 6000 });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
reject: () => {
|
||||||
|
toast.add({ severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000 })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
//reingest latest changes
|
||||||
|
const reIngestWithPullChanges = (data) => {
|
||||||
|
console.log("data", data);
|
||||||
|
console.log("reponame", data.repoName);
|
||||||
|
|
||||||
|
confirm.require({
|
||||||
|
target: event.currentTarget,
|
||||||
|
message: 'Are you sure you want to proceed?',
|
||||||
|
icon: 'pi pi-exclamation-circle',
|
||||||
|
rejectProps: {
|
||||||
|
label: 'Cancel',
|
||||||
|
severity: 'secondary',
|
||||||
|
outlined: true
|
||||||
|
},
|
||||||
|
acceptProps: {
|
||||||
|
label: 'Reingest Latest Changes',
|
||||||
|
severity: 'danger',
|
||||||
|
},
|
||||||
|
accept: () => {
|
||||||
|
axios.get(`/test/reingest_repo?repoName=${data.repoName}&branchName=${data.branch}`)
|
||||||
|
.then(response => {
|
||||||
|
console.log(response.data);
|
||||||
|
toast.add({ severity: 'info', summary: 'Confirmed', detail: 'ReIngestion with latest pull from master started', life: 3000 });
|
||||||
|
}).catch(error => {
|
||||||
|
console.log(error);
|
||||||
|
toast.add({ severity: 'error', summary: 'Error', detail: 'Error in Reingestion', life: 3000 });
|
||||||
|
})
|
||||||
|
},
|
||||||
|
reject: () => {
|
||||||
|
toast.add({ severity: 'error', summary: 'Rejected', detail: 'You have rejected', life: 3000 })
|
||||||
|
}
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
//expand
|
||||||
|
const onRowExpand = (event) => {
|
||||||
|
console.log('Row Expanded:', event.data);
|
||||||
|
toast.add({ severity: 'info', summary: event.data.repoName + ' Expanded', life: 3000 });
|
||||||
|
};
|
||||||
|
const onRowCollapse = (event) => {
|
||||||
|
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>
|
||||||
|
/* Custom styling for disabled red button */
|
||||||
|
.p-button-danger {
|
||||||
|
background-color: white;
|
||||||
|
border-color: blue;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-button-danger:disabled {
|
||||||
|
/*background-color: red;*/
|
||||||
|
border-color: red;
|
||||||
|
color: red;
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
|
||||||
|
.space-x-3>*+* {
|
||||||
|
margin-left: 1rem;
|
||||||
|
/* Adjust as needed for desired spacing */
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-container {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
height: 100%;
|
||||||
|
/* Ensure the container takes full height of the parent */
|
||||||
|
min-height: 400px;
|
||||||
|
/* Adjust this height to your DataTable height */
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner-container {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
animation: fade-in 1s ease-in-out;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner {
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
width: 50px;
|
||||||
|
height: 50px;
|
||||||
|
color: var(--primary-color, #007bff);
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-text {
|
||||||
|
font-size: 1.2rem;
|
||||||
|
animation: pulse 1.5s infinite;
|
||||||
|
margin-top: 10px;
|
||||||
|
color: var(--primary-color, #007bff);
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes spin {
|
||||||
|
0% {
|
||||||
|
transform: rotate(0deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
100% {
|
||||||
|
transform: rotate(360deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes pulse {
|
||||||
|
|
||||||
|
0%,
|
||||||
|
100% {
|
||||||
|
opacity: 1;
|
||||||
|
color: var(--primary-color, #007bff);
|
||||||
|
}
|
||||||
|
|
||||||
|
50% {
|
||||||
|
opacity: 0.11;
|
||||||
|
color: var(--primary-color, #007bff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@keyframes fade-in {
|
||||||
|
from {
|
||||||
|
opacity: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
to {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
margin: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vue-json-view {
|
||||||
|
font-size: 15px;
|
||||||
|
/* Change this value to your desired font size */
|
||||||
|
}
|
||||||
|
|
||||||
|
.big-title {
|
||||||
|
font-size: 3rem;
|
||||||
|
color: #c1c3c4;
|
||||||
|
/* Adjust the size as needed */
|
||||||
|
font-weight: bold;
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
margin-left: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.big-title span {
|
||||||
|
color: #c1c3c4;
|
||||||
|
|
||||||
|
font-size: 2rem;
|
||||||
|
/* Optional: style the span element differently */
|
||||||
|
}
|
||||||
|
</style>
|
||||||
146
src/views/pages/ksGitRepo/KsNewGitRepoForm.vue
Normal file
146
src/views/pages/ksGitRepo/KsNewGitRepoForm.vue
Normal file
@@ -0,0 +1,146 @@
|
|||||||
|
<template>
|
||||||
|
<Fluid>
|
||||||
|
<div class="flex mt-6">
|
||||||
|
<div class="card flex flex-col gap-4 w-full">
|
||||||
|
<div>
|
||||||
|
<h2 class="text-3xl font-bold mb-4">Upload New Code Repository</h2>
|
||||||
|
</div>
|
||||||
|
<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="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="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" :disabled="isSubmitting" :fluid="false"
|
||||||
|
class="p-button-rounded p-button-lg mt-4" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Fluid>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import axios from 'axios';
|
||||||
|
import Button from 'primevue/button';
|
||||||
|
import InputNumber from 'primevue/inputnumber';
|
||||||
|
import InputText from 'primevue/inputtext';
|
||||||
|
import { useToast } from 'primevue/usetoast';
|
||||||
|
import { ref } from 'vue';
|
||||||
|
import { useRouter } from 'vue-router';
|
||||||
|
|
||||||
|
const toast = useToast();
|
||||||
|
const router = useRouter();
|
||||||
|
const isSubmitting = ref(false);
|
||||||
|
|
||||||
|
const formData = ref({
|
||||||
|
repoName: '',
|
||||||
|
branch: '',
|
||||||
|
commitId: '',
|
||||||
|
repoPath: '',
|
||||||
|
defaultChunkSize: 1988,
|
||||||
|
minChunkSize: 200,
|
||||||
|
maxNumberOfChunks: 1988,
|
||||||
|
minChunkSizeToEmbed: 20
|
||||||
|
});
|
||||||
|
|
||||||
|
const submitForm = async () => {
|
||||||
|
if (isSubmitting.value) return; // Prevent duplicate submissions
|
||||||
|
|
||||||
|
isSubmitting.value = true;
|
||||||
|
|
||||||
|
const formDataToSend = new FormData();
|
||||||
|
|
||||||
|
formDataToSend.append('repoName', formData.value.repoName);
|
||||||
|
formDataToSend.append('branch', formData.value.branch);
|
||||||
|
formDataToSend.append('commitId', formData.value.commitId);
|
||||||
|
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);
|
||||||
|
|
||||||
|
try {
|
||||||
|
const response = await axios.post('/fe-api/ks_git_repos/uploadRepo', formDataToSend);
|
||||||
|
console.log('Submit successful:', response.data);
|
||||||
|
toast.add({ severity: 'success', summary: 'Success', detail: 'Repository submitted successfully', life: 3000 });
|
||||||
|
|
||||||
|
// Redirect to desktop.vue
|
||||||
|
router.push({ name: 'ks-git-repos' });
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Submit failed:', error);
|
||||||
|
toast.add({ severity: 'error', summary: 'Error', detail: 'Submission failed', life: 3000 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.card-container {
|
||||||
|
max-width: 800px;
|
||||||
|
margin: 2rem auto;
|
||||||
|
padding: 0 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-card) {
|
||||||
|
background: linear-gradient(45deg, #45a049, #4caf50);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-button:hover) {
|
||||||
|
background: linear-gradient(45deg, #45a049, #4caf50);
|
||||||
|
transform: translateY(-2px);
|
||||||
|
box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-inputtext:focus) {
|
||||||
|
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-dropdown:focus) {
|
||||||
|
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
:deep(.p-inputnumber-input:focus) {
|
||||||
|
box-shadow: 0 0 0 2px rgba(76, 175, 80, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mt-4 {
|
||||||
|
margin-top: 1rem;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
149
src/views/pages/similaritySearch/KsSimilaritySearch.vue
Normal file
149
src/views/pages/similaritySearch/KsSimilaritySearch.vue
Normal file
@@ -0,0 +1,149 @@
|
|||||||
|
<template>
|
||||||
|
<Fluid>
|
||||||
|
<h2 class="text-4xl font-semibold text-center mb-4">Similarity Search</h2>
|
||||||
|
<div class="similarity-search">
|
||||||
|
<div class="card-container flex flex-col gap-6">
|
||||||
|
<div class="flex flex-col gap-4">
|
||||||
|
<Textarea id="query" v-model="query" rows="6" placeholder="Enter your query..." class="input-textarea" />
|
||||||
|
<div class="select-container">
|
||||||
|
<!--SelectButton id="type" v-model="dropdownItem" :options="dropdownItems" optionLabel="name"
|
||||||
|
class="select-button" /-->
|
||||||
|
<InputText v-model="filterQuery" type="text" placeholder="Add filterQuery" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<Button label="Query" icon="pi pi-send" @click="sendQuery" class="send-button" />
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="messages.length > 0" class="results-container mt-6">
|
||||||
|
<Card v-for="(result, index) in messages" :key="index" class="result-card">
|
||||||
|
<template #content>
|
||||||
|
<ScrollPanel style="width: 100%; max-height: 400px">
|
||||||
|
<CodeSnippet :code="dynamicCode" language="systemd" />
|
||||||
|
</ScrollPanel>
|
||||||
|
</template>
|
||||||
|
</Card>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</Fluid>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import CodeSnippet from '@/components/CodeSnippet.vue';
|
||||||
|
import axios from 'axios';
|
||||||
|
import Button from 'primevue/button';
|
||||||
|
import Card from 'primevue/card';
|
||||||
|
import ScrollPanel from 'primevue/scrollpanel';
|
||||||
|
import { useToast } from 'primevue/usetoast';
|
||||||
|
import { ref, watch } from 'vue';
|
||||||
|
|
||||||
|
const query = ref('');
|
||||||
|
const dropdownItem = ref(null);
|
||||||
|
const messages = ref([]);
|
||||||
|
const toast = useToast();
|
||||||
|
const dynamicCode = ref('');
|
||||||
|
const filterQuery = ref("'KsApplicationName' == 'ATF'")
|
||||||
|
|
||||||
|
const dropdownItems = [
|
||||||
|
{ name: 'Documentation', code: 'setup-documentation' },
|
||||||
|
{ name: 'Deploy Documentation', code: 'deploy-documentation' },
|
||||||
|
{ name: 'Source code', code: 'sourcecode' }
|
||||||
|
];
|
||||||
|
|
||||||
|
const sendQuery = () => {
|
||||||
|
if (query.value.trim() !== '' && filterQuery) {
|
||||||
|
axios.get('/test/query_vector', {
|
||||||
|
params: {
|
||||||
|
query: query.value,
|
||||||
|
filterQuery: filterQuery.value,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(response => {
|
||||||
|
const data = response.data;
|
||||||
|
console.log('API response:', data);
|
||||||
|
|
||||||
|
if (data && Array.isArray(data) && data.length > 0) {
|
||||||
|
messages.value = data;
|
||||||
|
toast.add({ severity: 'success', summary: 'Success', detail: 'Query sent successfully', life: 3000 });
|
||||||
|
} else {
|
||||||
|
toast.add({ severity: 'info', summary: 'Info', detail: 'No results found', life: 3000 });
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(error => {
|
||||||
|
console.error('Error sending query:', error);
|
||||||
|
toast.add({ severity: 'error', summary: 'Error', detail: 'Failed to send query', life: 3000 });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
toast.add({ severity: 'warn', summary: 'Warning', detail: 'Please enter a query and select a type', life: 3000 });
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Function to generate dynamic code snippet
|
||||||
|
function generateDynamicCode() {
|
||||||
|
const randomValue = messages.value.join(', ');
|
||||||
|
return `[${randomValue}]`;
|
||||||
|
}
|
||||||
|
|
||||||
|
watch(messages, (newMessages) => {
|
||||||
|
dynamicCode.value = generateDynamicCode();
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.similarity-search {
|
||||||
|
max-width: 1000px;
|
||||||
|
margin: 0 auto;
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-container {
|
||||||
|
padding: 2rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.input-textarea {
|
||||||
|
width: 100%;
|
||||||
|
resize: vertical;
|
||||||
|
min-height: 150px;
|
||||||
|
/* Increased height for better readability */
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 1rem;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-container {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-button {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.send-button {
|
||||||
|
width: 100%;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.results-container {
|
||||||
|
padding: 2rem;
|
||||||
|
background-color: #f9f9f9;
|
||||||
|
border-radius: 8px;
|
||||||
|
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
|
||||||
|
.result-card {
|
||||||
|
margin-bottom: 1rem;
|
||||||
|
border-radius: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.p-scrollpanel {
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
99
src/views/pages/vectorDBSearch/KsVectorData.vue
Normal file
99
src/views/pages/vectorDBSearch/KsVectorData.vue
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
<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.ksFileSource']">
|
||||||
|
<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.ksFileSource" header="KsFileSource" sortable>
|
||||||
|
<template #body="{ data }">
|
||||||
|
{{ data.metadata.ksFileSource }}
|
||||||
|
</template>
|
||||||
|
<template #filter="{ filterModel, filterCallback }">
|
||||||
|
<InputText v-model="filterModel.value" type="text" @input="filterCallback()"
|
||||||
|
placeholder="Search By Source/Path" />
|
||||||
|
</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>
|
||||||
|
</DataTable>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script setup>
|
||||||
|
import { FilterMatchMode, FilterOperator } from '@primevue/core/api';
|
||||||
|
import axios from 'axios';
|
||||||
|
import { onMounted, ref } from 'vue';
|
||||||
|
|
||||||
|
const vectorDetails = ref(null);
|
||||||
|
const loading = ref(true);
|
||||||
|
const filters = ref();
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
axios.get('/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.ksFileSource': { operator: FilterOperator.AND, constraints: [{ value: null, matchMode: FilterMatchMode.STARTS_WITH }] }
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
initFilters();
|
||||||
|
</script>
|
||||||
Reference in New Issue
Block a user