chore: Fix .env.test quotes and format frontend code
- Fix TEST_ORACLE_USER quotes in .env.test for shell source compatibility - Format 14 frontend files with Prettier (stores, views, utils) - All 122 tests passing (77 telegram + 35 backend + 10 E2E) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -38,8 +38,11 @@
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<label>Your Setting:</label>
|
||||
<InputSwitch v-model="userCacheEnabled" @change="toggleUserCache" />
|
||||
<span>{{ userCacheEnabled ? 'ON' : 'OFF' }}</span>
|
||||
<InputSwitch
|
||||
v-model="userCacheEnabled"
|
||||
@change="toggleUserCache"
|
||||
/>
|
||||
<span>{{ userCacheEnabled ? "ON" : "OFF" }}</span>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<label>Auto-Invalidation:</label>
|
||||
@@ -58,7 +61,10 @@
|
||||
<template #content>
|
||||
<div class="hit-rate">
|
||||
<h3>Hit Rate: {{ stats.hit_rate?.toFixed(1) }}%</h3>
|
||||
<p>{{ stats.total_hits }} hits / {{ stats.total_hits + stats.total_misses }} total requests</p>
|
||||
<p>
|
||||
{{ stats.total_hits }} hits /
|
||||
{{ stats.total_hits + stats.total_misses }} total requests
|
||||
</p>
|
||||
<ProgressBar :value="stats.hit_rate" />
|
||||
</div>
|
||||
</template>
|
||||
@@ -70,13 +76,23 @@
|
||||
<template #content>
|
||||
<ul class="queries-list">
|
||||
<li>
|
||||
Today: <strong>{{ stats.queries_saved?.today?.toLocaleString() }}</strong> queries avoided
|
||||
Today:
|
||||
<strong>{{
|
||||
stats.queries_saved?.today?.toLocaleString()
|
||||
}}</strong>
|
||||
queries avoided
|
||||
</li>
|
||||
<li>
|
||||
This week: <strong>{{ stats.queries_saved?.week?.toLocaleString() }}</strong> queries avoided
|
||||
This week:
|
||||
<strong>{{ stats.queries_saved?.week?.toLocaleString() }}</strong>
|
||||
queries avoided
|
||||
</li>
|
||||
<li>
|
||||
All time: <strong>{{ stats.queries_saved?.total?.toLocaleString() }}</strong> queries avoided
|
||||
All time:
|
||||
<strong>{{
|
||||
stats.queries_saved?.total?.toLocaleString()
|
||||
}}</strong>
|
||||
queries avoided
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
@@ -102,8 +118,9 @@
|
||||
</DataTable>
|
||||
<div v-if="overallAvg" class="average-row">
|
||||
<strong>Overall Average:</strong>
|
||||
{{ overallAvg.cached }} ms vs {{ overallAvg.oracle }} ms
|
||||
({{ overallAvg.improvement }}% faster)
|
||||
{{ overallAvg.cached }} ms vs {{ overallAvg.oracle }} ms ({{
|
||||
overallAvg.improvement
|
||||
}}% faster)
|
||||
</div>
|
||||
</template>
|
||||
</Card>
|
||||
@@ -113,9 +130,17 @@
|
||||
<template #title>Cache Details</template>
|
||||
<template #content>
|
||||
<ul class="details-list">
|
||||
<li>Memory entries: <strong>{{ stats.cache_size?.memory?.toLocaleString() }}</strong></li>
|
||||
<li>SQLite entries: <strong>{{ stats.cache_size?.sqlite?.toLocaleString() }}</strong></li>
|
||||
<li>Cache type: <strong>{{ stats.cache_type }}</strong></li>
|
||||
<li>
|
||||
Memory entries:
|
||||
<strong>{{ stats.cache_size?.memory?.toLocaleString() }}</strong>
|
||||
</li>
|
||||
<li>
|
||||
SQLite entries:
|
||||
<strong>{{ stats.cache_size?.sqlite?.toLocaleString() }}</strong>
|
||||
</li>
|
||||
<li>
|
||||
Cache type: <strong>{{ stats.cache_type }}</strong>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
</Card>
|
||||
@@ -135,150 +160,162 @@
|
||||
<label for="clear_all">All companies</label>
|
||||
</div>
|
||||
<div class="p-field-radiobutton">
|
||||
<RadioButton id="clear_current" v-model="clearScope" value="current" />
|
||||
<RadioButton
|
||||
id="clear_current"
|
||||
v-model="clearScope"
|
||||
value="current"
|
||||
/>
|
||||
<label for="clear_current">Current company only</label>
|
||||
</div>
|
||||
</div>
|
||||
<template #footer>
|
||||
<Button label="Cancel" text @click="showClearDialog = false" />
|
||||
<Button label="Clear" severity="danger" @click="clearCache" :loading="loading" />
|
||||
<Button
|
||||
label="Clear"
|
||||
severity="danger"
|
||||
@click="clearCache"
|
||||
:loading="loading"
|
||||
/>
|
||||
</template>
|
||||
</Dialog>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, computed, onMounted } from 'vue'
|
||||
import { useCacheStore } from '@/stores/cacheStore'
|
||||
import { useCompanyStore } from '@/stores/companies'
|
||||
import { useToast } from 'primevue/usetoast'
|
||||
import Button from 'primevue/button'
|
||||
import Card from 'primevue/card'
|
||||
import DataTable from 'primevue/datatable'
|
||||
import Column from 'primevue/column'
|
||||
import Tag from 'primevue/tag'
|
||||
import ProgressBar from 'primevue/progressbar'
|
||||
import InputSwitch from 'primevue/inputswitch'
|
||||
import Dialog from 'primevue/dialog'
|
||||
import RadioButton from 'primevue/radiobutton'
|
||||
import Message from 'primevue/message'
|
||||
import { ref, computed, onMounted } from "vue";
|
||||
import { useCacheStore } from "@/stores/cacheStore";
|
||||
import { useCompanyStore } from "@/stores/companies";
|
||||
import { useToast } from "primevue/usetoast";
|
||||
import Button from "primevue/button";
|
||||
import Card from "primevue/card";
|
||||
import DataTable from "primevue/datatable";
|
||||
import Column from "primevue/column";
|
||||
import Tag from "primevue/tag";
|
||||
import ProgressBar from "primevue/progressbar";
|
||||
import InputSwitch from "primevue/inputswitch";
|
||||
import Dialog from "primevue/dialog";
|
||||
import RadioButton from "primevue/radiobutton";
|
||||
import Message from "primevue/message";
|
||||
|
||||
const cacheStore = useCacheStore()
|
||||
const companyStore = useCompanyStore()
|
||||
const toast = useToast()
|
||||
const cacheStore = useCacheStore();
|
||||
const companyStore = useCompanyStore();
|
||||
const toast = useToast();
|
||||
|
||||
const loading = computed(() => cacheStore.isLoading)
|
||||
const error = computed(() => cacheStore.error)
|
||||
const stats = computed(() => cacheStore.stats)
|
||||
const loading = computed(() => cacheStore.isLoading);
|
||||
const error = computed(() => cacheStore.error);
|
||||
const stats = computed(() => cacheStore.stats);
|
||||
|
||||
const userCacheEnabled = ref(true)
|
||||
const showClearDialog = ref(false)
|
||||
const clearScope = ref('current')
|
||||
const userCacheEnabled = ref(true);
|
||||
const showClearDialog = ref(false);
|
||||
const clearScope = ref("current");
|
||||
|
||||
const responseTimesTable = computed(() => {
|
||||
if (!stats.value?.response_times) return []
|
||||
if (!stats.value?.response_times) return [];
|
||||
|
||||
return Object.entries(stats.value.response_times).map(([key, data]) => ({
|
||||
endpoint: formatEndpointName(key),
|
||||
cached: data.cached,
|
||||
oracle: data.oracle,
|
||||
improvement: data.improvement
|
||||
}))
|
||||
})
|
||||
improvement: data.improvement,
|
||||
}));
|
||||
});
|
||||
|
||||
const overallAvg = computed(() => {
|
||||
const times = Object.values(stats.value?.response_times || {})
|
||||
if (times.length === 0) return null
|
||||
const times = Object.values(stats.value?.response_times || {});
|
||||
if (times.length === 0) return null;
|
||||
|
||||
const avgCached = times.reduce((sum, t) => sum + t.cached, 0) / times.length
|
||||
const avgOracle = times.reduce((sum, t) => sum + t.oracle, 0) / times.length
|
||||
const improvement = ((avgOracle - avgCached) / avgOracle * 100).toFixed(0)
|
||||
const avgCached = times.reduce((sum, t) => sum + t.cached, 0) / times.length;
|
||||
const avgOracle = times.reduce((sum, t) => sum + t.oracle, 0) / times.length;
|
||||
const improvement = (((avgOracle - avgCached) / avgOracle) * 100).toFixed(0);
|
||||
|
||||
return {
|
||||
cached: avgCached.toFixed(0),
|
||||
oracle: avgOracle.toFixed(0),
|
||||
improvement
|
||||
}
|
||||
})
|
||||
improvement,
|
||||
};
|
||||
});
|
||||
|
||||
async function loadStats() {
|
||||
try {
|
||||
await cacheStore.getStats()
|
||||
userCacheEnabled.value = stats.value?.user_enabled ?? true
|
||||
await cacheStore.getStats();
|
||||
userCacheEnabled.value = stats.value?.user_enabled ?? true;
|
||||
} catch (error) {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: 'Error',
|
||||
detail: 'Failed to load cache statistics',
|
||||
life: 3000
|
||||
})
|
||||
severity: "error",
|
||||
summary: "Error",
|
||||
detail: "Failed to load cache statistics",
|
||||
life: 3000,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleUserCache() {
|
||||
try {
|
||||
await cacheStore.toggleUserCache(userCacheEnabled.value)
|
||||
await cacheStore.toggleUserCache(userCacheEnabled.value);
|
||||
toast.add({
|
||||
severity: 'success',
|
||||
summary: 'Success',
|
||||
detail: `Cache ${userCacheEnabled.value ? 'enabled' : 'disabled'} for you`,
|
||||
life: 3000
|
||||
})
|
||||
severity: "success",
|
||||
summary: "Success",
|
||||
detail: `Cache ${userCacheEnabled.value ? "enabled" : "disabled"} for you`,
|
||||
life: 3000,
|
||||
});
|
||||
} catch (error) {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: 'Error',
|
||||
detail: 'Failed to toggle cache',
|
||||
life: 3000
|
||||
})
|
||||
severity: "error",
|
||||
summary: "Error",
|
||||
detail: "Failed to toggle cache",
|
||||
life: 3000,
|
||||
});
|
||||
// Revert toggle
|
||||
userCacheEnabled.value = !userCacheEnabled.value
|
||||
userCacheEnabled.value = !userCacheEnabled.value;
|
||||
}
|
||||
}
|
||||
|
||||
async function clearCache() {
|
||||
try {
|
||||
const companyId = clearScope.value === 'current' ? companyStore.currentCompany?.id_firma : null
|
||||
await cacheStore.invalidateCache(companyId, null)
|
||||
const companyId =
|
||||
clearScope.value === "current"
|
||||
? companyStore.currentCompany?.id_firma
|
||||
: null;
|
||||
await cacheStore.invalidateCache(companyId, null);
|
||||
|
||||
toast.add({
|
||||
severity: 'success',
|
||||
summary: 'Success',
|
||||
detail: 'Cache cleared successfully',
|
||||
life: 3000
|
||||
})
|
||||
severity: "success",
|
||||
summary: "Success",
|
||||
detail: "Cache cleared successfully",
|
||||
life: 3000,
|
||||
});
|
||||
|
||||
showClearDialog.value = false
|
||||
await loadStats()
|
||||
showClearDialog.value = false;
|
||||
await loadStats();
|
||||
} catch (error) {
|
||||
toast.add({
|
||||
severity: 'error',
|
||||
summary: 'Error',
|
||||
detail: 'Failed to clear cache',
|
||||
life: 3000
|
||||
})
|
||||
severity: "error",
|
||||
summary: "Error",
|
||||
detail: "Failed to clear cache",
|
||||
life: 3000,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function formatEndpointName(key) {
|
||||
const names = {
|
||||
'schema': 'Schema Lookup',
|
||||
'dashboard_summary': 'Dashboard',
|
||||
'dashboard_trends': 'Dashboard Trends',
|
||||
'companies': 'Companies List',
|
||||
'invoices': 'Invoices',
|
||||
'treasury': 'Treasury'
|
||||
}
|
||||
return names[key] || key
|
||||
schema: "Schema Lookup",
|
||||
dashboard_summary: "Dashboard",
|
||||
dashboard_trends: "Dashboard Trends",
|
||||
companies: "Companies List",
|
||||
invoices: "Invoices",
|
||||
treasury: "Treasury",
|
||||
};
|
||||
return names[key] || key;
|
||||
}
|
||||
|
||||
function clearError() {
|
||||
cacheStore.clearError()
|
||||
cacheStore.clearError();
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
loadStats()
|
||||
})
|
||||
loadStats();
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
Reference in New Issue
Block a user