diff --git a/dashboard/components/dashboard/EventsChart.vue b/dashboard/components/dashboard/EventsChart.vue index bbf2e87..c34f3e3 100644 --- a/dashboard/components/dashboard/EventsChart.vue +++ b/dashboard/components/dashboard/EventsChart.vue @@ -2,7 +2,7 @@ import { Chart, registerables, type ChartData, type ChartOptions } from 'chart.js'; import { DoughnutChart, useDoughnutChart } from 'vue-chart-3'; -import type { EventsPie } from '~/server/api/metrics/[project_id]/events_pie'; +import type { CustomEventsAggregated } from '~/server/api/metrics/[project_id]/data/events'; definePageMeta({ layout: 'dashboard' }); @@ -20,15 +20,6 @@ const chartOptions = ref>({ ticks: { display: false }, grid: { display: false, drawBorder: false }, }, - // r: { - // ticks: { display: false }, - // grid: { - // display: true, - // drawBorder: false, - // color: '#CCCCCC22', - // borderDash: [20, 8] - // }, - // } }, plugins: { legend: { @@ -65,45 +56,53 @@ const chartData = ref>({ const { doughnutChartProps, doughnutChartRef } = useDoughnutChart({ chartData: chartData, options: chartOptions }); +const activeProject = useActiveProject(); -const res = useEventsData(); +const { safeSnapshotDates } = useSnapshot(); -onMounted(async () => { - res.onResponse(resData => { - if (!resData.value) return; - chartData.value.labels = resData.value.map(e => { - return `${e._id}`; - }); - - chartData.value.datasets[0].data = resData.value.map(e => e.count); - doughnutChartRef.value?.update(); - - if (window.innerWidth < 800) { - if (chartOptions.value?.plugins?.legend?.display) { - chartOptions.value.plugins.legend.display = false; - } - } +function transformResponse(input: CustomEventsAggregated[]) { + chartData.value.labels = input.map(e => { + return `${e._id}`; }); -}) + chartData.value.datasets[0].data = input.map(e => e.count); + doughnutChartRef.value?.update(); + if (window.innerWidth < 800) { + if (chartOptions.value?.plugins?.legend?.display) { + chartOptions.value.plugins.legend.display = false; + } + } +} + +const headers = computed(() => { + return { + 'x-from': safeSnapshotDates.value.from, + 'x-to': safeSnapshotDates.value.to, + Authorization: authorizationHeaderComputed.value, + limit: "10" + } +}); + +const eventsData = useFetch(`/api/metrics/${activeProject.value?._id}/data/events`, { + method: 'POST', headers, lazy: true, immediate: false,transform:transformResponse +}); + +onMounted(() => { + eventsData.execute(); +}); -const chartVisible = computed(() => { - if (res.pending.value) return false; - if (!res.data.value) return false; - return true; -}) diff --git a/dashboard/components/events/EventsStackedBarChart.vue b/dashboard/components/events/EventsStackedBarChart.vue index 369e60a..6d399f3 100644 --- a/dashboard/components/events/EventsStackedBarChart.vue +++ b/dashboard/components/events/EventsStackedBarChart.vue @@ -2,73 +2,75 @@ import type { Slice } from '@services/DateService'; import { onMounted } from 'vue'; -const datasets = ref([]); -const labels = ref([]); -const ready = ref(false); -const props = defineProps<{ slice: Slice }>(); +const props = defineProps<{ slice: Slice }>(); const slice = computed(() => props.slice); -const res = useEventsStackedTimeline(slice); - +const activeProject = useActiveProject(); const { safeSnapshotDates } = useSnapshot() -onMounted(async () => { +const body = computed(() => { + return { + from: safeSnapshotDates.value.from, + to: safeSnapshotDates.value.to, + slice: slice.value, + Authorization: authorizationHeaderComputed.value, + } +}); - res.execute(); - res.onResponse(resData => { +function transformResponse(input: { _id: string, name: string, count: number }[]) { - if (!resData.value) return; - - const fixed = fixMetrics({ - data:resData.value, - from: safeSnapshotDates.value.from, - to: safeSnapshotDates.value.to - }, slice.value, { - advanced: true, - advancedGroupKey: 'name' - }); - - const parsedDatasets: any[] = []; - const colors = ['#5655d0', '#6bbbe3', '#a6d5cb', '#fae0b9']; - - for (let i = 0; i < fixed.allKeys.length; i++) { - const line: any = { - data: [], - color: colors[i] || '#FF0000', - label: fixed.allKeys[i] - }; - parsedDatasets.push(line) - fixed.data.forEach((e: { key: string, value: number }[]) => { - const target = e.find(e => e.key == fixed.allKeys[i]); - if (!target) return; - line.data.push(target.value); - }); - } - - datasets.value = parsedDatasets; - labels.value = fixed.labels; - ready.value = true; + const fixed = fixMetrics({ + data: input, + from: safeSnapshotDates.value.from, + to: safeSnapshotDates.value.to + }, slice.value, { + advanced: true, + advancedGroupKey: 'name' }); -}) + const parsedDatasets: any[] = []; + const colors = ['#5655d0', '#6bbbe3', '#a6d5cb', '#fae0b9']; + + for (let i = 0; i < fixed.allKeys.length; i++) { + const line: any = { + data: [], + color: colors[i] || '#FF0000', + label: fixed.allKeys[i] + }; + parsedDatasets.push(line) + fixed.data.forEach((e: { key: string, value: number }[]) => { + const target = e.find(e => e.key == fixed.allKeys[i]); + if (!target) return; + line.data.push(target.value); + }); + } + + return { + datasets: parsedDatasets, + labels: fixed.labels + } +} + +const eventsStackedData = useFetch(`/api/metrics/${activeProject.value?._id}/timeline/events_stacked`, { + method: 'POST', body, lazy: true, immediate: false, transform: transformResponse +}); -const chartVisible = computed(() => { - if (res.pending.value) return false; - if (!res.data.value) return false; - return true; -}) +onMounted(async () => { + eventsStackedData.execute(); +}); \ No newline at end of file diff --git a/dashboard/components/settings/General.vue b/dashboard/components/settings/General.vue index f8c877a..5f28c5f 100644 --- a/dashboard/components/settings/General.vue +++ b/dashboard/components/settings/General.vue @@ -32,6 +32,36 @@ async function changeProjectName() { location.reload(); } +async function deleteProject() { + if (!activeProject.value) return; + const sure = confirm(`Are you sure to delete the project ${activeProject.value.name} ?`); + if (!sure) return; + + try { + + await $fetch('/api/project/delete', { + method: 'DELETE', + ...signHeaders({ 'Content-Type': 'application/json' }), + body: JSON.stringify({ project_id: activeProject.value._id.toString() }) + }); + + const projectsList = useProjectsList() + await projectsList.refresh(); + + const firstProjectId = projectsList.data.value?.[0]?._id.toString(); + if (firstProjectId) { + await setActiveProject(firstProjectId); + } + + + } catch (ex: any) { + alert(ex.message); + } + + +} + + @@ -62,7 +92,7 @@ async function changeProjectName() {