Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EDIT: Heavy duty endpoints #65

Merged
merged 5 commits into from
Dec 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .eslintrc-auto-import.json
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,7 @@
"ExtractPublicPropTypes": true,
"WritableComputedRef": true,
"injectLocal": true,
"storeRouteMapping": true,
"provideLocal": true
}
}
1 change: 1 addition & 0 deletions auto-imports.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ declare global {
const shallowReactive: typeof import('vue')['shallowReactive']
const shallowReadonly: typeof import('vue')['shallowReadonly']
const shallowRef: typeof import('vue')['shallowRef']
const storeRouteMapping: typeof import('./src/utils/storeRouteMapping')['default']
const storeToRefs: typeof import('pinia')['storeToRefs']
const suite: typeof import('vitest')['suite']
const syncRef: typeof import('@vueuse/core')['syncRef']
Expand Down
17 changes: 16 additions & 1 deletion src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@
import { useSettings } from '@stores/useSettings'
import ModalBox from '@components/ModalBox.vue'
import { updateAuthKey } from '@/api'
import useStoreMapping from '@/utils/storeRouteMapping'

const routesToExclude = ['home', 'settings']
const route = useRoute()
const { storeMapping } = useStoreMapping()
const settings = useSettings()
const { getStatus } = settings
const { isReadyAndAuth } = storeToRefs(settings)
Expand All @@ -23,6 +27,17 @@ const authenticate = async () => {
//resetAllStores()
}
}

const currentComponentLoading = computed(() => {
const routeName = route.name?.toString()
let store
if (routeName !== undefined && !routesToExclude.includes(routeName)) {
store = storeMapping[routeName]
const { currentState } = storeToRefs(store)
return store && currentState.value.loading
}
return false
})
</script>

<template>
Expand Down Expand Up @@ -50,7 +65,7 @@ const authenticate = async () => {
enterActiveClass="animate__animated animate__fadeIn animate__fastest"
leaveActiveClass="animate__animated animate__fadeOut animate__fastest">
<KeepAlive>
<component :is="Component" />
<component :is="Component" v-lock="currentComponentLoading" :currentComponentLoading="currentComponentLoading" />
</KeepAlive>
</Transition>
</template>
Expand Down
1 change: 1 addition & 0 deletions src/components/ModalBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ const closeModal = () => {
defineExpose({
toggleModal,
isOpen,
closeModal,
})
</script>

Expand Down
15 changes: 10 additions & 5 deletions src/components/SidePanel.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script setup lang="ts">
defineProps<{
const props = defineProps<{
title: string
currentComponentLoading?: boolean
}>()

const [isOpen, togglePanel] = useToggle(false)
Expand All @@ -16,13 +17,18 @@ const closePanel = () => {

defineExpose({
togglePanel,
closePanel,
isOpen,
})

const closeIfCurrentComponentNotLoading = () => {
if (!props.currentComponentLoading) isOpen.value = false
}
</script>

<template>
<TransitionRoot as="template" :show="isOpen">
<Dialog as="div" class="relative z-40" @close="isOpen = false">
<Dialog as="div" class="relative z-40" @close="closeIfCurrentComponentNotLoading()">
<TransitionChild
as="template"
enter="ease-in-out duration-300"
Expand All @@ -43,15 +49,14 @@ defineExpose({
enter-to="translate-x-0"
leave="transform transition ease-in-out duration-500"
leave-from="translate-x-0"
leave-to="translate-x-full"
@afterLeave="closePanel">
leave-to="translate-x-full">
<DialogPanel class="pointer-events-auto relative w-screen md:max-w-xl">
<div class="flex h-full flex-col overflow-y-auto bg-base-200 text-neutral">
<div class="flex items-center justify-between gap-2 p-2 md:p-4">
<DialogTitle class="text-lg font-semibold">
{{ title }}
</DialogTitle>
<button class="btn btn-circle btn-sm" @click="isOpen = false">
<button class="btn btn-circle btn-sm" @click="closeIfCurrentComponentNotLoading()">
<span class="sr-only">Close panel</span>
<heroicons-x-mark-20-solid class="h-6 w-6" />
</button>
Expand Down
19 changes: 19 additions & 0 deletions src/directives/vLock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import type { Directive } from 'vue'

export const vLock: Directive<HTMLElement, boolean> = {
mounted(el, binding) {
if (binding.value) {
el.style.pointerEvents = 'none'
} else {
el.style.pointerEvents = 'initial'
}
},
updated(el, binding) {
if (binding.value) {
el.style.pointerEvents = 'none'
} else {
el.style.pointerEvents = 'initial'
}
},
}
export default vLock
3 changes: 2 additions & 1 deletion src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { createApp } from 'vue'
import { createPinia } from 'pinia'
import { defineRule } from 'vee-validate'
import AllRules from '@vee-validate/rules'
import vLock from '@/directives/vLock'

Object.keys(AllRules).forEach(rule => {
defineRule(rule, AllRules[rule])
Expand All @@ -23,8 +24,8 @@ pinia.use(({ store }) => {
const state = cloneDeep(store.$state)
store.$reset = () => store.$patch(state)
})

app.use(pinia)
app.use(router)
app.directive('lock', vLock)

app.mount('#app')
4 changes: 4 additions & 0 deletions src/stores/useMemory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,9 @@ export const useMemory = defineStore('memory', () => {
const { sendNotificationFromJSON } = useNotifications()

const wipeAllCollections = async () => {
currentState.loading = true
const result = await MemoryService.wipeAllCollections()
currentState.loading = false
if (result.status == 'success' && currentState.data) {
remove(currentState.data, v => v.name != 'procedural')
fetchCollections()
Expand All @@ -43,7 +45,9 @@ export const useMemory = defineStore('memory', () => {
}

const wipeCollection = async (collection: string) => {
currentState.loading = true
const result = await MemoryService.wipeCollection(collection)
currentState.loading = false
if (result.status == 'success' && currentState.data) {
remove(currentState.data, v => v.name == collection)
fetchCollections()
Expand Down
8 changes: 7 additions & 1 deletion src/stores/usePlugins.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,17 @@ export const usePlugins = defineStore('plugins', () => {
const getSettings = async (id: Plugin['id']) => (await PluginService.getSinglePluginSettings(id))?.value

const togglePlugin = async (id: Plugin['id'], name: Plugin['name'], active: boolean) => {
currentState.loading = true
const res = await PluginService.togglePlugin(id)
if (res.status == 'success') {
showNotification({
text: `Plugin "${name}" is being switched ${active ? 'OFF' : 'ON'}!`,
type: 'info',
})
} else sendNotificationFromJSON(res)
fetchSettings()
fetchPlugins()
currentState.loading = false
return res.status != 'error'
}

Expand All @@ -69,9 +72,10 @@ export const usePlugins = defineStore('plugins', () => {
const installPlugin = async (file: File) => {
currentState.loading = true
const res = await PluginService.sendFile(file)
await fetchSettings()
await fetchPlugins()
currentState.loading = false
sendNotificationFromJSON(res)
fetchPlugins()
}

const searchPlugin = async (query: string) => {
Expand All @@ -86,6 +90,8 @@ export const usePlugins = defineStore('plugins', () => {
currentState.loading = true
const res = await PluginService.installFromRegistry(url)
if (res.status == 'error') sendNotificationFromJSON(res)
fetchSettings()
fetchPlugins()
currentState.loading = false
return res.data
}
Expand Down
20 changes: 20 additions & 0 deletions src/utils/storeRouteMapping.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { useEmbedderConfig } from '@/stores/useEmbedderConfig'
import { useLLMConfig } from '@/stores/useLLMConfig'
import { useMemory } from '@/stores/useMemory'
import { usePlugins } from '@/stores/usePlugins'

export default function useStoreMapping() {
const storeEmbedder = useEmbedderConfig()
const storeLLM = useLLMConfig()
const storePlugins = usePlugins()
const storeMemory = useMemory()

const storeMapping: Record<string, typeof storeEmbedder | typeof storeLLM | typeof storeMemory | typeof storePlugins> = {
embedders: storeEmbedder,
providers: storeLLM,
memory: storeMemory,
plugins: storePlugins,
}

return { storeMapping }
}
84 changes: 43 additions & 41 deletions src/views/MemoryView.vue
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ const wipeMemory = async () => {
if (selectCollection.value) {
const selected = selectCollection.value.selected?.value
if (!selected) return
if (boxWipe.value?.isOpen) boxWipe.value?.closeModal()
if (selected === 'all') await wipeAllCollections()
else await wipeCollection(selected)
if (boxWipe.value?.isOpen) boxWipe.value?.toggleModal()
Expand Down Expand Up @@ -210,10 +211,51 @@ const dateFilter = ref(''),
<input v-model="sourceFilter" type="text" placeholder="Source" class="input input-primary input-xs w-32" />
</div>
</div>
<div class="divider !my-0" />
<div class="join w-fit self-center shadow-xl">
<button
:disabled="Boolean(memoryState.error) || memoryState.loading"
class="btn btn-primary join-item hover:border-error hover:bg-error"
@click="boxWipe?.toggleModal()">
<heroicons-trash-solid class="h-4 w-4" />
Wipe
</button>
<SelectBox
ref="selectCollection"
color="bg-base-100 bottom-16"
class="join-item min-w-fit bg-base-100 p-1"
:list="selectBoxCollections" />
</div>
<Teleport to="#modal">
<ModalBox ref="boxWipe">
<div class="flex flex-col items-center justify-center gap-4 text-neutral">
<h3 class="text-lg font-bold text-primary">Wipe collection</h3>
<p v-if="selectCollection?.selected.label.startsWith('All')">
Are you sure you want to wipe
<span class="font-bold">
{{ selectCollection?.selected.label.toLowerCase() }}
</span>
the collections?
</p>
<p v-else>
Are you sure you want to wipe the
<span class="font-bold">
{{ selectCollection?.selected.label.toLowerCase() }}
</span>
collection?
</p>
<div class="flex items-center justify-center gap-2">
<button class="btn btn-outline btn-sm" @click="boxWipe?.toggleModal()">No</button>
<button class="btn btn-error btn-sm" @click="wipeMemory()">Yes</button>
</div>
</div>
</ModalBox>
</Teleport>
<ErrorBox
v-if="showSpinner || memoryState.loading || memoryState.error"
:load="showSpinner || memoryState.loading"
:error="memoryState.error" />
:error="memoryState.error"
:text="`Doing some magic...`" />
<ApexChart
v-else-if="plotOutput && callOutput"
v-memo="[callOutput, plotOutput]"
Expand Down Expand Up @@ -328,46 +370,6 @@ const dateFilter = ref(''),
}"
:series="plotOutput"
@markerClick="onMarkerClick" />
<div class="divider !my-0" />
<div class="join w-fit self-center shadow-xl">
<button
:disabled="Boolean(memoryState.error) || memoryState.loading"
class="btn btn-primary join-item hover:border-error hover:bg-error"
@click="boxWipe?.toggleModal()">
<heroicons-trash-solid class="h-4 w-4" />
Wipe
</button>
<SelectBox
ref="selectCollection"
color="bg-base-100 bottom-16"
class="join-item min-w-fit bg-base-100 p-1"
:list="selectBoxCollections" />
</div>
<Teleport to="#modal">
<ModalBox ref="boxWipe">
<div class="flex flex-col items-center justify-center gap-4 text-neutral">
<h3 class="text-lg font-bold text-primary">Wipe collection</h3>
<p v-if="selectCollection?.selected.label.startsWith('All')">
Are you sure you want to wipe
<span class="font-bold">
{{ selectCollection?.selected.label.toLowerCase() }}
</span>
the collections?
</p>
<p v-else>
Are you sure you want to wipe the
<span class="font-bold">
{{ selectCollection?.selected.label.toLowerCase() }}
</span>
collection?
</p>
<div class="flex items-center justify-center gap-2">
<button class="btn btn-outline btn-sm" @click="boxWipe?.toggleModal()">No</button>
<button class="btn btn-error btn-sm" @click="wipeMemory()">Yes</button>
</div>
</div>
</ModalBox>
</Teleport>
<SidePanel ref="memoryDetailsPanel" title="Memory details">
<div v-if="callOutput" class="flex w-full flex-col">
<p class="z-10 self-start rounded-t-md bg-base-100 px-2 py-1 font-medium text-neutral">
Expand Down
5 changes: 4 additions & 1 deletion src/views/SettingsView.vue
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<script setup lang="ts">
import SidePanel from '@components/SidePanel.vue'
import { useSettings } from '@stores/useSettings'
defineProps<{
currentComponentLoading: boolean
}>()

const { cat } = storeToRefs(useSettings())

Expand Down Expand Up @@ -38,7 +41,7 @@ const openSidePanel = (title: keyof typeof panelTitles) => {
<p class="text-center">Choose a language embedder to help the Cat remember conversations and documents</p>
<RouterLink :to="{ name: 'embedders' }" class="btn btn-primary btn-sm" @click="openSidePanel('embedder')"> Configure </RouterLink>
</div>
<SidePanel ref="sidePanel" :title="panelTitle">
<SidePanel ref="sidePanel" :title="panelTitle" :currentComponentLoading="currentComponentLoading">
<RouterView @close="sidePanel?.togglePanel()" />
</SidePanel>
</div>
Expand Down