mirror of
https://github.com/cupcakearmy/ora.git
synced 2026-04-02 12:05:23 +00:00
lots of stuff
This commit is contained in:
@@ -1,115 +0,0 @@
|
||||
<script>
|
||||
import * as am4core from '@amcharts/amcharts4/core'
|
||||
import * as am4charts from '@amcharts/amcharts4/charts'
|
||||
import am4themes_frozen from '@amcharts/amcharts4/themes/frozen'
|
||||
import am4themes_animated from '@amcharts/amcharts4/themes/animated'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
/* Chart code */
|
||||
// Themes begin
|
||||
am4core.useTheme(am4themes_frozen)
|
||||
am4core.useTheme(am4themes_animated)
|
||||
|
||||
let el
|
||||
let chart
|
||||
|
||||
export let data = [
|
||||
{
|
||||
network: 'Facebook',
|
||||
MAU: 2255250000,
|
||||
},
|
||||
{
|
||||
network: 'Google+',
|
||||
MAU: 430000000,
|
||||
},
|
||||
{
|
||||
network: 'Instagram',
|
||||
MAU: 1000000000,
|
||||
},
|
||||
{
|
||||
network: 'Pinterest',
|
||||
MAU: 246500000,
|
||||
},
|
||||
{
|
||||
network: 'Reddit',
|
||||
MAU: 355000000,
|
||||
},
|
||||
{
|
||||
network: 'TikTok',
|
||||
MAU: 500000000,
|
||||
},
|
||||
{
|
||||
network: 'Tumblr',
|
||||
MAU: 624000000,
|
||||
},
|
||||
{
|
||||
network: 'Twitter',
|
||||
MAU: 329500000,
|
||||
},
|
||||
{
|
||||
network: 'WeChat',
|
||||
MAU: 1000000000,
|
||||
},
|
||||
{
|
||||
network: 'Weibo',
|
||||
MAU: 431000000,
|
||||
},
|
||||
{
|
||||
network: 'Whatsapp',
|
||||
MAU: 1433333333,
|
||||
},
|
||||
{
|
||||
network: 'YouTube',
|
||||
MAU: 1900000000,
|
||||
},
|
||||
]
|
||||
|
||||
$: if (chart) {
|
||||
chart.data = data
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
chart = am4core.create(el, am4charts.XYChart)
|
||||
|
||||
let categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis())
|
||||
categoryAxis.renderer.grid.template.location = 0
|
||||
categoryAxis.dataFields.category = 'host'
|
||||
categoryAxis.renderer.minGridDistance = 1
|
||||
categoryAxis.renderer.inversed = true
|
||||
categoryAxis.renderer.grid.template.disabled = true
|
||||
|
||||
let valueAxis = chart.xAxes.push(new am4charts.ValueAxis())
|
||||
valueAxis.min = 0
|
||||
|
||||
let series = chart.series.push(new am4charts.ColumnSeries())
|
||||
series.dataFields.categoryY = 'host'
|
||||
series.dataFields.valueX = 'total'
|
||||
series.columns.template.strokeOpacity = 0
|
||||
series.columns.template.column.cornerRadiusBottomRight = 5
|
||||
series.columns.template.column.cornerRadiusTopRight = 5
|
||||
|
||||
let labelBullet = series.bullets.push(new am4charts.LabelBullet())
|
||||
labelBullet.label.horizontalCenter = 'left'
|
||||
labelBullet.label.dx = 10
|
||||
labelBullet.label.text = '{values.valueX.workingValue}'
|
||||
// labelBullet.label.text = "{values.valueX.workingValue.formatNumber('#.0as')}"
|
||||
labelBullet.locationX = 1
|
||||
|
||||
// as by default columns of the same series are of the same color, we add adapter which takes colors from chart.colors color set
|
||||
series.columns.template.adapter.add('fill', function (fill, target) {
|
||||
return chart.colors.getIndex(target.dataItem.index)
|
||||
})
|
||||
|
||||
categoryAxis.sortBySeries = series
|
||||
chart.data = data
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
div {
|
||||
width: 100%;
|
||||
height: 32em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div bind:this={el}>chart</div>
|
||||
@@ -1,68 +1,115 @@
|
||||
<script>
|
||||
import * as am4core from '@amcharts/amcharts4/core'
|
||||
import * as am4charts from '@amcharts/amcharts4/charts'
|
||||
import am4themes_frozen from '@amcharts/amcharts4/themes/frozen'
|
||||
import am4themes_animated from '@amcharts/amcharts4/themes/animated'
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
import Chart from 'chart.js'
|
||||
import palette from 'google-palette'
|
||||
/* Chart code */
|
||||
// Themes begin
|
||||
am4core.useTheme(am4themes_frozen)
|
||||
am4core.useTheme(am4themes_animated)
|
||||
|
||||
Chart.defaults.global.legend.display = false
|
||||
let el
|
||||
let chart
|
||||
|
||||
export let type = 'horizontalBar'
|
||||
export let data = {
|
||||
labels: [],
|
||||
data: [],
|
||||
}
|
||||
export let options = {
|
||||
scales: {
|
||||
xAxes: [
|
||||
{
|
||||
// type: 'logarithmic',
|
||||
ticks: {
|
||||
beginAtZero: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
export let data = [
|
||||
{
|
||||
network: 'Facebook',
|
||||
MAU: 2255250000,
|
||||
},
|
||||
}
|
||||
{
|
||||
network: 'Google+',
|
||||
MAU: 430000000,
|
||||
},
|
||||
{
|
||||
network: 'Instagram',
|
||||
MAU: 1000000000,
|
||||
},
|
||||
{
|
||||
network: 'Pinterest',
|
||||
MAU: 246500000,
|
||||
},
|
||||
{
|
||||
network: 'Reddit',
|
||||
MAU: 355000000,
|
||||
},
|
||||
{
|
||||
network: 'TikTok',
|
||||
MAU: 500000000,
|
||||
},
|
||||
{
|
||||
network: 'Tumblr',
|
||||
MAU: 624000000,
|
||||
},
|
||||
{
|
||||
network: 'Twitter',
|
||||
MAU: 329500000,
|
||||
},
|
||||
{
|
||||
network: 'WeChat',
|
||||
MAU: 1000000000,
|
||||
},
|
||||
{
|
||||
network: 'Weibo',
|
||||
MAU: 431000000,
|
||||
},
|
||||
{
|
||||
network: 'Whatsapp',
|
||||
MAU: 1433333333,
|
||||
},
|
||||
{
|
||||
network: 'YouTube',
|
||||
MAU: 1900000000,
|
||||
},
|
||||
]
|
||||
|
||||
let ctx
|
||||
let mounted
|
||||
|
||||
function draw() {
|
||||
const backgroundColor = palette('rainbow', data.data.length).map((color) => '#' + color + '88')
|
||||
|
||||
new Chart(ctx, {
|
||||
type,
|
||||
options,
|
||||
data: {
|
||||
labels: data.labels,
|
||||
datasets: [
|
||||
{
|
||||
data: data.data,
|
||||
// backgroundColor: backgroundColor,
|
||||
backgroundColor: '#dddddd',
|
||||
borderColor: '#000000',
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
$: if (mounted) {
|
||||
data
|
||||
draw()
|
||||
$: if (chart) {
|
||||
chart.data = data
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
mounted = true
|
||||
chart = am4core.create(el, am4charts.XYChart)
|
||||
|
||||
let categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis())
|
||||
categoryAxis.renderer.grid.template.location = 0
|
||||
categoryAxis.dataFields.category = 'host'
|
||||
categoryAxis.renderer.minGridDistance = 1
|
||||
categoryAxis.renderer.inversed = true
|
||||
categoryAxis.renderer.grid.template.disabled = true
|
||||
|
||||
let valueAxis = chart.xAxes.push(new am4charts.ValueAxis())
|
||||
valueAxis.min = 0
|
||||
|
||||
let series = chart.series.push(new am4charts.ColumnSeries())
|
||||
series.dataFields.categoryY = 'host'
|
||||
series.dataFields.valueX = 'total'
|
||||
series.columns.template.strokeOpacity = 0
|
||||
series.columns.template.column.cornerRadiusBottomRight = 5
|
||||
series.columns.template.column.cornerRadiusTopRight = 5
|
||||
|
||||
let labelBullet = series.bullets.push(new am4charts.LabelBullet())
|
||||
labelBullet.label.horizontalCenter = 'left'
|
||||
labelBullet.label.dx = 10
|
||||
labelBullet.label.text = '{values.valueX.workingValue}'
|
||||
// labelBullet.label.text = "{values.valueX.workingValue.formatNumber('#.0as')}"
|
||||
labelBullet.locationX = 1
|
||||
|
||||
// as by default columns of the same series are of the same color, we add adapter which takes colors from chart.colors color set
|
||||
series.columns.template.adapter.add('fill', function (fill, target) {
|
||||
return chart.colors.getIndex(target.dataItem.index)
|
||||
})
|
||||
|
||||
categoryAxis.sortBySeries = series
|
||||
chart.data = data
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
canvas {
|
||||
div {
|
||||
width: 100%;
|
||||
height: 20em;
|
||||
height: 32em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<canvas bind:this={ctx} />
|
||||
<div bind:this={el}>chart</div>
|
||||
|
||||
68
src/dashboard/components/ChartOlder.svelte
Normal file
68
src/dashboard/components/ChartOlder.svelte
Normal file
@@ -0,0 +1,68 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
|
||||
import Chart from 'chart.js'
|
||||
import palette from 'google-palette'
|
||||
|
||||
Chart.defaults.global.legend.display = false
|
||||
|
||||
export let type = 'horizontalBar'
|
||||
export let data = {
|
||||
labels: [],
|
||||
data: [],
|
||||
}
|
||||
export let options = {
|
||||
scales: {
|
||||
xAxes: [
|
||||
{
|
||||
// type: 'logarithmic',
|
||||
ticks: {
|
||||
beginAtZero: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
|
||||
let ctx
|
||||
let mounted
|
||||
|
||||
function draw() {
|
||||
const backgroundColor = palette('rainbow', data.data.length).map((color) => '#' + color + '88')
|
||||
|
||||
new Chart(ctx, {
|
||||
type,
|
||||
options,
|
||||
data: {
|
||||
labels: data.labels,
|
||||
datasets: [
|
||||
{
|
||||
data: data.data,
|
||||
// backgroundColor: backgroundColor,
|
||||
backgroundColor: '#dddddd',
|
||||
borderColor: '#000000',
|
||||
borderWidth: 1,
|
||||
},
|
||||
],
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
$: if (mounted) {
|
||||
data
|
||||
draw()
|
||||
}
|
||||
|
||||
onMount(() => {
|
||||
mounted = true
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
canvas {
|
||||
width: 100%;
|
||||
height: 20em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<canvas bind:this={ctx} />
|
||||
@@ -1,12 +0,0 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
export let name = ''
|
||||
export let date = new Date()
|
||||
let internal = dayjs(date).format('YYYY-MM-DD')
|
||||
|
||||
$: date = dayjs(internal, 'YYYY-MM-DD')
|
||||
</script>
|
||||
|
||||
<label class="form-label">{name}<input class="form-input" type="date" bind:value={internal} /> </label>
|
||||
19
src/dashboard/components/DateInput.svelte
Normal file
19
src/dashboard/components/DateInput.svelte
Normal file
@@ -0,0 +1,19 @@
|
||||
<script>
|
||||
import { onMount } from 'svelte'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
const format = 'YYYY-MM-DD'
|
||||
|
||||
export let name = ''
|
||||
|
||||
export let date = new Date()
|
||||
let internal
|
||||
|
||||
const input = (x) => (internal = dayjs(x).format(format))
|
||||
const output = (x) => (date = dayjs(x, format).toDate())
|
||||
|
||||
$: input(date)
|
||||
$: output(internal)
|
||||
</script>
|
||||
|
||||
<input class="form-input input-sm" type="date" bind:value={internal} {name} />
|
||||
@@ -3,29 +3,25 @@
|
||||
import day from 'dayjs'
|
||||
import { range, random } from 'lodash'
|
||||
|
||||
import { Logs } from '../../shared/db'
|
||||
import { insertLog, normalizeTimestamp } from '../../shared/db'
|
||||
|
||||
let loading = false
|
||||
|
||||
async function fill() {
|
||||
try {
|
||||
loading = true
|
||||
|
||||
const start = day().subtract('7', 'days').valueOf()
|
||||
const end = Date.now()
|
||||
|
||||
const all = []
|
||||
for (const n of range(50)) {
|
||||
for (const n of range(20)) {
|
||||
const host = faker.internet.domainName()
|
||||
for (const m of range(random(500))) {
|
||||
const frequency = random(1, 10) * 1000
|
||||
const timestamp = new Date(random(start, end))
|
||||
all.push({ host, timestamp, frequency })
|
||||
for (const m of range(random(20))) {
|
||||
const date = new Date(random(start, end))
|
||||
const timestamp = normalizeTimestamp(date)
|
||||
const seconds = random(15 * 60)
|
||||
// console.log(host, date, seconds)
|
||||
await insertLog({ host, timestamp, seconds })
|
||||
}
|
||||
}
|
||||
console.log(`Generated ${all.length} data points`)
|
||||
console.debug(all)
|
||||
await Logs.insert(all)
|
||||
} finally {
|
||||
loading = false
|
||||
}
|
||||
|
||||
41
src/dashboard/components/RangeChooser.svelte
Normal file
41
src/dashboard/components/RangeChooser.svelte
Normal file
@@ -0,0 +1,41 @@
|
||||
<script>
|
||||
import dj from 'dayjs'
|
||||
|
||||
import DateInput from './DateInput.svelte'
|
||||
|
||||
export let start
|
||||
export let end
|
||||
|
||||
function set(interval, amount = 1) {
|
||||
return () => {
|
||||
start = dj().subtract(amount, interval).toDate()
|
||||
end = new Date()
|
||||
}
|
||||
}
|
||||
|
||||
function all() {
|
||||
start = new Date(0)
|
||||
end = new Date()
|
||||
}
|
||||
</script>
|
||||
|
||||
<style>
|
||||
.spacer {
|
||||
width: 0.5em;
|
||||
}
|
||||
</style>
|
||||
|
||||
<!-- <div class="flex flex-col"> -->
|
||||
<div class="flex items-center">
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-sm" on:click={all}>All</button>
|
||||
<button class="btn btn-sm" on:click={set('month')}>Month</button>
|
||||
<button class="btn btn-sm" on:click={set('week')}>Week</button>
|
||||
<button class="btn btn-sm" on:click={set('day')}>Day</button>
|
||||
</div>
|
||||
<div class="spacer" />
|
||||
<div class="input-group">
|
||||
<DateInput bind:date={start} />
|
||||
<DateInput bind:date={end} />
|
||||
</div>
|
||||
</div>
|
||||
Reference in New Issue
Block a user