You've already forked AstralRinth
forked from didirus/AstralRinth
@@ -45,6 +45,7 @@ export default {
|
||||
{ text: 'Copy Code', link: '/components/copy-code' },
|
||||
{ text: 'Notifications', link: '/components/notifications' },
|
||||
{ text: 'Share Modal', link: '/components/share-modal' },
|
||||
{ text: 'Analytics', link: '/components/analytics' },
|
||||
],
|
||||
},
|
||||
],
|
||||
|
||||
108
docs/components/analytics.md
Normal file
108
docs/components/analytics.md
Normal file
@@ -0,0 +1,108 @@
|
||||
# Analytics
|
||||
|
||||
<DemoContainer>
|
||||
<LineChart
|
||||
:data="{
|
||||
labels: [
|
||||
'2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05',
|
||||
'2021-01-06', '2021-01-07', '2021-01-08', '2021-01-09', '2021-01-10',
|
||||
'2021-01-11', '2021-01-12', '2021-01-13', '2021-01-14', '2021-01-15',
|
||||
'2021-01-16', '2021-01-17'
|
||||
],
|
||||
data: [
|
||||
{
|
||||
title: 'Spirit',
|
||||
color: 16711680,
|
||||
data: [120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280],
|
||||
},
|
||||
{
|
||||
title: 'Ad Astra',
|
||||
color: 65280,
|
||||
data: [150, 155, 160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230],
|
||||
},
|
||||
{
|
||||
title: 'Tempad',
|
||||
color: 255,
|
||||
data: [180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212],
|
||||
},
|
||||
]
|
||||
}"
|
||||
/>
|
||||
<PieChart
|
||||
:data="{
|
||||
title: 'Downloads',
|
||||
data: [
|
||||
{
|
||||
title: 'Spirit',
|
||||
color: 16711680, // Red in decimal (equivalent to #FF0000 in hexadecimal)
|
||||
data: 120, // Example download numbers for the three dates
|
||||
},
|
||||
{
|
||||
title: 'Ad Astra',
|
||||
color: 65280, // Green in decimal (equivalent to #00FF00 in hexadecimal)
|
||||
data: 150, // Example download numbers for the three dates
|
||||
},
|
||||
{
|
||||
title: 'Tempad',
|
||||
color: 255, // Blue in decimal (equivalent to #0000FF in hexadecimal)
|
||||
data: 180, // Example download numbers for the three dates
|
||||
},
|
||||
],
|
||||
}"
|
||||
/>
|
||||
</DemoContainer>
|
||||
|
||||
```vue
|
||||
<LineChart
|
||||
:formatLabel="(label) => doFormattingThings(label)"
|
||||
:data="{
|
||||
labels: [
|
||||
'2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05',
|
||||
'2021-01-06', '2021-01-07', '2021-01-08', '2021-01-09', '2021-01-10',
|
||||
'2021-01-11', '2021-01-12', '2021-01-13', '2021-01-14', '2021-01-15',
|
||||
'2021-01-16', '2021-01-17'
|
||||
],
|
||||
data: [
|
||||
{
|
||||
title: 'Spirit',
|
||||
color: 16711680,
|
||||
data: [120, 130, 140, 150, 160, 170, 180, 190, 200, 210, 220, 230, 240, 250, 260, 270, 280],
|
||||
},
|
||||
{
|
||||
title: 'Ad Astra',
|
||||
color: 65280,
|
||||
data: [150, 155, 160, 165, 170, 175, 180, 185, 190, 195, 200, 205, 210, 215, 220, 225, 230],
|
||||
},
|
||||
{
|
||||
title: 'Tempad',
|
||||
color: 255,
|
||||
data: [180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212],
|
||||
},
|
||||
]
|
||||
}"
|
||||
/>
|
||||
```
|
||||
```vue
|
||||
<PieChart
|
||||
:data="{
|
||||
title: 'Downloads',
|
||||
data: [
|
||||
{
|
||||
title: 'Spirit',
|
||||
color: 16711680, // Red in decimal (equivalent to #FF0000 in hexadecimal)
|
||||
data: 120, // Example download numbers for the three dates
|
||||
},
|
||||
{
|
||||
title: 'Ad Astra',
|
||||
color: 65280, // Green in decimal (equivalent to #00FF00 in hexadecimal)
|
||||
data: 150, // Example download numbers for the three dates
|
||||
},
|
||||
{
|
||||
title: 'Tempad',
|
||||
color: 255, // Blue in decimal (equivalent to #0000FF in hexadecimal)
|
||||
data: 180, // Example download numbers for the three dates
|
||||
},
|
||||
],
|
||||
}"
|
||||
/>
|
||||
```
|
||||
125
lib/components/base/LineChart.vue
Normal file
125
lib/components/base/LineChart.vue
Normal file
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<Line :options="chartOptions" :data="chartData" />
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { Line } from 'vue-chartjs'
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
Title,
|
||||
Tooltip,
|
||||
PointElement,
|
||||
LineElement,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
Filler,
|
||||
} from 'chart.js'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
ChartJS.register(Title, Tooltip, PointElement, LineElement, CategoryScale, LinearScale, Filler)
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
formatLabels: {
|
||||
type: Function,
|
||||
default: (label) => dayjs(label).format('MMM D'),
|
||||
},
|
||||
})
|
||||
|
||||
const decimalToRgba = (decimalColor, alpha = 0.75) => {
|
||||
const red = (decimalColor >> 16) & 255
|
||||
const green = (decimalColor >> 8) & 255
|
||||
const blue = decimalColor & 255
|
||||
|
||||
return `rgba(${red}, ${green}, ${blue}, ${alpha})`
|
||||
}
|
||||
|
||||
const chartData = ref({
|
||||
labels: props.data.labels.map((date) => props.formatLabels(date)),
|
||||
datasets: props.data.data.map((project) => ({
|
||||
label: project.title,
|
||||
backgroundColor: decimalToRgba(project.color, 0.75),
|
||||
borderColor: decimalToRgba(project.color),
|
||||
data: project.data,
|
||||
})),
|
||||
})
|
||||
|
||||
const chartOptions = ref({
|
||||
responsive: true,
|
||||
scales: {
|
||||
x: {
|
||||
grid: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--color-button-bg'),
|
||||
},
|
||||
ticks: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--color-base'),
|
||||
},
|
||||
},
|
||||
y: {
|
||||
grid: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--color-button-bg'),
|
||||
},
|
||||
ticks: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--color-base'),
|
||||
},
|
||||
},
|
||||
},
|
||||
interaction: {
|
||||
mode: 'x',
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'right',
|
||||
align: 'start',
|
||||
labels: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--color-base'),
|
||||
font: {
|
||||
size: 12,
|
||||
family: 'Inter',
|
||||
},
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
position: 'nearest',
|
||||
backgroundColor: getComputedStyle(document.documentElement).getPropertyValue(
|
||||
'--color-raised-bg'
|
||||
),
|
||||
borderColor: getComputedStyle(document.documentElement).getPropertyValue('--color-button-bg'),
|
||||
borderWidth: 1,
|
||||
titleColor: getComputedStyle(document.documentElement).getPropertyValue('--color-contrast'),
|
||||
titleFont: {
|
||||
size: 14,
|
||||
family: 'Inter',
|
||||
},
|
||||
bodyColor: getComputedStyle(document.documentElement).getPropertyValue('--color-base'),
|
||||
bodyFont: {
|
||||
size: 12,
|
||||
family: 'Inter',
|
||||
},
|
||||
boxPadding: 8,
|
||||
intersect: false,
|
||||
padding: 12,
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
/*
|
||||
The data for the graph should look like this
|
||||
|
||||
downloads, views, likes = {
|
||||
dates: [ '2021-01-01', '2021-01-02', '2021-01-03' ], // Last 2 weeks
|
||||
data: [
|
||||
{
|
||||
title: projectName,
|
||||
color: projectColor,
|
||||
data: [ ... ],
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
*/
|
||||
</script>
|
||||
93
lib/components/base/PieChart.vue
Normal file
93
lib/components/base/PieChart.vue
Normal file
@@ -0,0 +1,93 @@
|
||||
<script setup>
|
||||
import { ref } from 'vue'
|
||||
import { Pie } from 'vue-chartjs'
|
||||
import {
|
||||
Chart as ChartJS,
|
||||
Title,
|
||||
Tooltip,
|
||||
PieController,
|
||||
ArcElement,
|
||||
Legend,
|
||||
CategoryScale,
|
||||
LinearScale,
|
||||
} from 'chart.js'
|
||||
|
||||
ChartJS.register(Title, Tooltip, PieController, ArcElement, Legend, CategoryScale, LinearScale)
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
required: true,
|
||||
},
|
||||
})
|
||||
|
||||
const decimalToRgba = (decimalColor, alpha = 0.75) => {
|
||||
const red = (decimalColor >> 16) & 255
|
||||
const green = (decimalColor >> 8) & 255
|
||||
const blue = decimalColor & 255
|
||||
|
||||
return `rgba(${red}, ${green}, ${blue}, ${alpha})`
|
||||
}
|
||||
|
||||
const chartData = ref({
|
||||
labels: props.data.data.map((project) => project.title),
|
||||
datasets: [
|
||||
{
|
||||
label: props.data.title,
|
||||
backgroundColor: props.data.data.map((project) => decimalToRgba(project.color)),
|
||||
borderColor: getComputedStyle(document.documentElement).getPropertyValue('--color-button-bg'),
|
||||
data: props.data.data.map((project) => project.data),
|
||||
fill: true,
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const chartOptions = ref({
|
||||
responsive: true,
|
||||
elements: {
|
||||
point: {
|
||||
radius: 0,
|
||||
},
|
||||
},
|
||||
plugins: {
|
||||
legend: {
|
||||
position: 'right',
|
||||
labels: {
|
||||
color: getComputedStyle(document.documentElement).getPropertyValue('--color-base'),
|
||||
font: {
|
||||
size: 12,
|
||||
family: 'Inter',
|
||||
},
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
position: 'nearest',
|
||||
backgroundColor: getComputedStyle(document.documentElement).getPropertyValue(
|
||||
'--color-raised-bg'
|
||||
),
|
||||
borderColor: getComputedStyle(document.documentElement).getPropertyValue('--color-button-bg'),
|
||||
borderWidth: 1,
|
||||
titleColor: getComputedStyle(document.documentElement).getPropertyValue('--color-contrast'),
|
||||
titleFont: {
|
||||
size: 16,
|
||||
family: 'Inter',
|
||||
},
|
||||
bodyColor: getComputedStyle(document.documentElement).getPropertyValue('--color-base'),
|
||||
bodyFont: {
|
||||
size: 12,
|
||||
family: 'Inter',
|
||||
},
|
||||
boxPadding: 8,
|
||||
intersect: false,
|
||||
padding: 12,
|
||||
displayColors: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<Pie :options="chartOptions" :data="chartData" />
|
||||
</template>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
@@ -24,6 +24,8 @@ export { default as ModalConfirm } from './base/ModalConfirm.vue'
|
||||
export { default as Breadcrumbs } from './base/Breadcrumbs.vue'
|
||||
export { default as DropdownButton } from './base/DropdownButton.vue'
|
||||
export { default as ShareModal } from './base/ShareModal.vue'
|
||||
export { default as LineChart } from './base/LineChart.vue'
|
||||
export { default as PieChart } from './base/PieChart.vue'
|
||||
|
||||
export { default as Categories } from './search/Categories.vue'
|
||||
export { default as SearchFilter } from './search/SearchFilter.vue'
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "omorphia",
|
||||
"type": "module",
|
||||
"version": "0.4.38",
|
||||
"version": "0.4.39",
|
||||
"files": [
|
||||
"dist",
|
||||
"lib"
|
||||
@@ -25,12 +25,14 @@
|
||||
"docs:preview": "vitepress preview docs"
|
||||
},
|
||||
"dependencies": {
|
||||
"chart.js": "^4.3.3",
|
||||
"dayjs": "^1.11.7",
|
||||
"floating-vue": "^2.0.0-beta.20",
|
||||
"highlight.js": "^11.8.0",
|
||||
"markdown-it": "^13.0.1",
|
||||
"qrcode.vue": "^3.4.0",
|
||||
"vue": "^3.3.4",
|
||||
"vue-chartjs": "^5.2.0",
|
||||
"vue-router": "^4.2.1",
|
||||
"vue-select": "^4.0.0-beta.6",
|
||||
"xss": "^1.0.14"
|
||||
|
||||
27
pnpm-lock.yaml
generated
27
pnpm-lock.yaml
generated
@@ -1,6 +1,9 @@
|
||||
lockfileVersion: '6.0'
|
||||
|
||||
dependencies:
|
||||
chart.js:
|
||||
specifier: ^4.3.3
|
||||
version: 4.3.3
|
||||
dayjs:
|
||||
specifier: ^1.11.7
|
||||
version: 1.11.7
|
||||
@@ -19,6 +22,9 @@ dependencies:
|
||||
vue:
|
||||
specifier: ^3.3.4
|
||||
version: 3.3.4
|
||||
vue-chartjs:
|
||||
specifier: ^5.2.0
|
||||
version: 5.2.0(chart.js@4.3.3)(vue@3.3.4)
|
||||
vue-router:
|
||||
specifier: ^4.2.1
|
||||
version: 4.2.1(vue@3.3.4)
|
||||
@@ -552,6 +558,10 @@ packages:
|
||||
'@jridgewell/sourcemap-codec': 1.4.14
|
||||
dev: true
|
||||
|
||||
/@kurkle/color@0.3.2:
|
||||
resolution: {integrity: sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==}
|
||||
dev: false
|
||||
|
||||
/@nodelib/fs.scandir@2.1.5:
|
||||
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
|
||||
engines: {node: '>= 8'}
|
||||
@@ -1040,6 +1050,13 @@ packages:
|
||||
supports-color: 7.2.0
|
||||
dev: true
|
||||
|
||||
/chart.js@4.3.3:
|
||||
resolution: {integrity: sha512-aTk7pBw+x6sQYhon/NR3ikfUJuym/LdgpTlgZRe2PaEhjUMKBKyNaFCMVRAyTEWYFNO7qRu7iQVqOw/OqzxZxQ==}
|
||||
engines: {pnpm: '>=7'}
|
||||
dependencies:
|
||||
'@kurkle/color': 0.3.2
|
||||
dev: false
|
||||
|
||||
/chokidar@3.5.3:
|
||||
resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
@@ -2309,6 +2326,16 @@ packages:
|
||||
resolution: {integrity: sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==}
|
||||
dev: true
|
||||
|
||||
/vue-chartjs@5.2.0(chart.js@4.3.3)(vue@3.3.4):
|
||||
resolution: {integrity: sha512-d3zpKmGZr2OWHQ1xmxBcAn5ShTG917+/UCLaSpaCDDqT0U7DBsvFzTs69ZnHCgKoXT55GZDW8YEj9Av+dlONLA==}
|
||||
peerDependencies:
|
||||
chart.js: ^4.1.1
|
||||
vue: ^3.0.0-0 || ^2.7.0
|
||||
dependencies:
|
||||
chart.js: 4.3.3
|
||||
vue: 3.3.4
|
||||
dev: false
|
||||
|
||||
/vue-demi@0.14.5(vue@3.3.4):
|
||||
resolution: {integrity: sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
Reference in New Issue
Block a user