Better usage menu

This commit is contained in:
Adrien Bouvais 2024-05-23 17:00:31 +02:00
parent 26450e7d39
commit 255f86e48b
4 changed files with 172 additions and 61 deletions

104
Chat.go
View File

@ -2,6 +2,7 @@ package main
import (
"context"
"fmt"
"sort"
"strings"
"time"
@ -379,64 +380,83 @@ func LoadUsageKPIHandler(c *fiber.Ctx) error {
if !checkIfLogin() || !checkIfHaveKey() {
return c.SendString("")
}
var TotalUsage float32
// Using the database. Get the sum of all usage.inputCost and outputCost
err := edgeClient.QuerySingle(edgeCtx, `
WITH
U := (
SELECT Usage
FILTER .user = global currentUser
)
SELECT sum(U.input_cost) + sum(U.output_cost)
`, &TotalUsage)
InputDateID := c.FormValue("month", time.Now().Format("01-2006"))
offset := c.FormValue("offset")
IsActive := false
var InputDate time.Time
InputDate, err := time.Parse("01-2006", InputDateID)
if err != nil {
panic(err)
}
now := time.Now()
if offset == "-1" {
InputDate = InputDate.AddDate(0, -1, 0)
IsActive = true
} else if offset == "1" {
InputDate = InputDate.AddDate(0, 1, 0)
IsActive = true
}
var TodayUsage float32
// Using the database. Get the sum of all usage.inputCost and outputCost
err = edgeClient.QuerySingle(edgeCtx, `
WITH
U := (
SELECT Usage
FILTER .user = global currentUser AND .date >= <datetime>$0
)
SELECT sum(U.input_cost) + sum(U.output_cost)
`, &TodayUsage, now.Add(time.Hour*-24))
type UsageKPI struct {
Key struct {
ModelID string `edgedb:"model_id"`
} `edgedb:"key"`
TotalCost float32 `edgedb:"total_cost"`
TotalCount int64 `edgedb:"total_count"`
}
var usages []UsageKPI
err = edgeClient.Query(edgeCtx, `
WITH
U := (
SELECT Usage
FILTER .user = global currentUser and .date >= <datetime>$0 AND .date < <datetime>$1
),
grouped := (
GROUP U {
model_id,
input_cost,
output_cost,
} BY .model_id
)
SELECT grouped {
key := .key { model_id },
total_count := count(.elements),
total_cost := sum(.elements.input_cost) + sum(.elements.output_cost),
} FILTER .total_count > 0 ORDER BY .total_cost DESC
`, &usages, InputDate, InputDate.AddDate(0, 1, 0))
if err != nil {
fmt.Println(err)
panic(err)
}
var WeekUsage float32
// Using the database. Get the sum of all usage.inputCost and outputCost
edgeClient.QuerySingle(edgeCtx, `
WITH
U := (
SELECT Usage
FILTER .user = global currentUser AND .date >= <datetime>$0
)
SELECT sum(U.input_cost) + sum(U.output_cost)
`, &WeekUsage, now.Add(time.Hour*-24*7))
BeautifullDate := InputDate.Format("Jan 2006")
var MonthUsage float32
// Using the database. Get the sum of all usage.inputCost and outputCost
edgeClient.QuerySingle(edgeCtx, `
WITH
U := (
SELECT Usage
FILTER .user = global currentUser AND .date >= <datetime>$0
)
SELECT sum(U.input_cost) + sum(U.output_cost)
`, &MonthUsage, now.Add(time.Hour*-24*30))
var (
TotalCount int64
TotalCost float32
)
for _, usage := range usages {
TotalCost += usage.TotalCost
TotalCount += usage.TotalCount
}
fmt.Println(TotalCost, TotalCount)
out, err := pongo2.Must(pongo2.FromFile("views/partials/popover-usage.html")).Execute(pongo2.Context{
"TotalUsage": TotalUsage, "TodayUsage": TodayUsage, "WeekUsage": WeekUsage, "MonthUsage": MonthUsage,
"usages": usages,
"TotalCost": TotalCost,
"TotalCount": TotalCount,
"Date": BeautifullDate,
"DateID": InputDate.Format("01-2006"),
"IsActive": IsActive,
})
if err != nil {
panic(err)
}
return c.SendString(out)
}

View File

@ -9,7 +9,7 @@
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.1.1/css/all.min.css">
<link href="https://fonts.googleapis.com/css?family=Russo+One" rel="stylesheet">
<link rel="stylesheet" href="/animations.css">
<!--link rel="stylesheet" href="/animations.css"-->
<link rel="stylesheet" href="/style.css">
<script src="https://unpkg.com/htmx.org@1.9.11"></script>

View File

@ -6,7 +6,7 @@
</button>
</div>
<div class="dropdown-menu" id="dropdown-menu3" role="menu">
<div class="dropdown-content is-small">
<div class="dropdown-content">
<div class="dropdown-item" id="models-list">
{% for LLM in LLMs %}
<div class="icon-text has-text unselected" onclick="toggleSelection(this)" style="cursor: pointer;"
@ -84,18 +84,11 @@
</div>
<script>
function toggleDropdown(event) {
event.stopPropagation();
document.getElementById('models-dropdown').classList.toggle('is-active');
}
function closeDropdown(event) {
document.addEventListener('click', function (event) {
if (!document.getElementById('models-dropdown').contains(event.target)) {
document.getElementById('models-dropdown').classList.remove('is-active');
}
}
document.addEventListener('click', closeDropdown);
});
document.getElementById('model-id-input').querySelector('select').addEventListener('change', function () {
const customEndpoint = this.value === 'custom';

View File

@ -1,17 +1,115 @@
<div class="dropdown is-hoverable is-up is-right">
<div class="dropdown is-up is-right {% if IsActive %} is-active{% endif %}" id="usage-dropdown">
<div class="dropdown-trigger">
<button class="button is-small" aria-haspopup="true" aria-controls="dropdown-menu4">
<button class="button is-small" aria-haspopup="true" aria-controls="dropdown-menu3"
onclick="this.parentElement.parentElement.classList.toggle('is-active')">
<span class="icon"><i class="fa-regular fa-money-bill-1"></i></span>
</button>
</div>
<div class="dropdown-menu" id="dropdown-menu4" role="menu">
<div class="dropdown-menu" id="dropdown-menu3" role="menu">
<div class="dropdown-content">
<div class="dropdown-item">
<div><strong>Total: {{ TotalUsage }}$</strong></div>
<div><strong>Month: {{ MonthUsage }}$</strong></div>
<div><strong>Week: {{ WeekUsage }}$</strong></div>
<div><strong>Today: {{ TodayUsage }}$</strong></div>
<!-- Placeholder for additional text -->
<div class="content" style="max-height: 50vh; overflow-y: auto;">
<table class="table is-narrow is-fullwidth is-striped">
<tbody>
{% for usage in usages %}
<tr>
<td>
<small>{{ usage.Key.ModelID }}</small>
</td>
<td class="has-text-right totalCostCell">
<small>{{ usage.TotalCost|floatformat:2 }}$</small>
</td>
<td class="has-text-right is-hidden totalCountCell">
<small>{{ usage.TotalCount }}</small>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<!-- Total cost -->
<div class="content totalCostCell">
<p>
<strong>Total: </strong>
<span class="totalCost">
{{ TotalCost|floatformat:2 }}$
</span>
</p>
</div>
<!-- Total count -->
<div class="content is-hidden totalCountCell">
<p>
<strong>Total: </strong>
<span class="totalCount">
{{ TotalCount }} messages
</span>
</p>
</div>
<!-- Top buttons -->
<div class="buttons has-addons is-centered">
<button class="button is-small is-primary" title="Money Spent" id="money-spent-button">
<span class="icon ml-4 mr-4"><i class="fa-regular fa-money-bill-1"></i></span>
</button>
<button class="button is-small" title="Messages Sent" id="messages-sent-button">
<span class="icon ml-4 mr-4"><i class="fa-regular fa-envelope"></i></span>
</button>
</div>
<!-- Row with text and buttons -->
<div class="level">
<div class="level-left">
<button class="button is-small" hx-get="/loadUsageKPI?month={{ DateID }}&offset=-1"
hx-swap="outerHTML" hx-target="#usage-dropdown">
<span class="icon"><i class="fa-solid fa-chevron-left"></i></span>
</button>
</div>
<div class="level-item">
<p>{{ Date }}</p>
</div>
<div class="level-right">
<button class="button is-small" hx-get="/loadUsageKPI?month={{ DateID }}&offset=1"
hx-swap="outerHTML" hx-target="#usage-dropdown">
<span class="icon"><i class="fa-solid fa-chevron-right"></i></span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<script>
document.addEventListener('click', function (event) {
if (!document.getElementById('usage-dropdown').contains(event.target)) {
document.getElementById('usage-dropdown').classList.remove('is-active');
}
});
document.getElementById('money-spent-button').addEventListener('click', function () {
document.getElementById('money-spent-button').classList.add('is-primary');
document.getElementById('messages-sent-button').classList.remove('is-primary');
// Change all totalCountCell to is-hidden and remove is-hidden from totalCostCell
const totalCountCells = document.getElementsByClassName('totalCountCell');
for (let i = 0; i < totalCountCells.length; i++) {
totalCountCells[i].classList.add('is-hidden');
}
const totalCostCells = document.getElementsByClassName('totalCostCell');
for (let i = 0; i < totalCostCells.length; i++) {
totalCostCells[i].classList.remove('is-hidden');
}
})
document.getElementById('messages-sent-button').addEventListener('click', function () {
document.getElementById('messages-sent-button').classList.add('is-primary');
document.getElementById('money-spent-button').classList.remove('is-primary');
// Change all totalCostCell to is-hidden and remove is-hidden from totalCountCell
const totalCostCells = document.getElementsByClassName('totalCostCell');
for (let i = 0; i < totalCostCells.length; i++) {
totalCostCells[i].classList.add('is-hidden');
}
const totalCountCells = document.getElementsByClassName('totalCountCell');
for (let i = 0; i < totalCountCells.length; i++) {
totalCountCells[i].classList.remove('is-hidden');
}
})
</script>