added node modules for chartjs :(
This commit is contained in:
parent
c20830a334
commit
656e665ad7
12 changed files with 154 additions and 30 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -6,6 +6,7 @@ web/*_templ.go
|
|||
web/static/*.css
|
||||
web/static/*.css.map
|
||||
.sass-cache/*
|
||||
*/node_modules/*
|
||||
|
||||
# --> nix
|
||||
.direnv/
|
||||
|
|
|
@ -75,6 +75,7 @@
|
|||
default = pkgs.mkShell {
|
||||
buildInputs = with pkgs; [
|
||||
air # live go app reloading
|
||||
corepack # npm install for the web folder
|
||||
dart-sass
|
||||
go
|
||||
gopls
|
||||
|
|
|
@ -25,3 +25,8 @@ type HumanLegibleTransaction struct {
|
|||
BucketName sql.NullString `db:"bucket_name" json:"BucketName"`
|
||||
Date time.Time `db:"trns_date" json:"TransactionDate"`
|
||||
}
|
||||
|
||||
type ChartjsData struct {
|
||||
Labels []string `json:"labels"`
|
||||
Data []int `json:"data"`
|
||||
}
|
||||
|
|
|
@ -9,6 +9,18 @@ templ dashboard() {
|
|||
<i class="my-auto c-text py-3 ps-3 ms-1" data-feather="arrow-left"></i>
|
||||
<i class="my-auto c-text py-3 pe-3 me-1 ms-auto" data-feather="arrow-right"></i>
|
||||
</div>
|
||||
<div class="d-flex">
|
||||
<div class="my-auto mx-2 w-75">
|
||||
<canvas
|
||||
class="chartjs-chart"
|
||||
data-chart-endpoint="/web/dashboard/expenditure_chart"
|
||||
data-chart-type="bar"
|
||||
id="IncomeVsExpenditureChart"
|
||||
></canvas>
|
||||
</div>
|
||||
<div class="c-mantle">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<div class="c-crust col card mx-auto cr-all">
|
||||
|
|
53
web/data_endpoints.go
Normal file
53
web/data_endpoints.go
Normal file
|
@ -0,0 +1,53 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/rs/zerolog/log"
|
||||
"nickiel.net/recount_server/types"
|
||||
)
|
||||
|
||||
|
||||
const DEFAULT_RESULT_COUNT = 20;
|
||||
|
||||
func getTransactions(w http.ResponseWriter, req *http.Request) {
|
||||
transactions := make([]types.HumanLegibleTransaction, 10)
|
||||
|
||||
// Populate the slice with dummy data (you can replace this with your actual data)
|
||||
for i := 10; i > 0; i-- {
|
||||
transaction := types.HumanLegibleTransaction{
|
||||
Id: i,
|
||||
Amount: fmt.Sprintf("%d.00", (i+1)*100),
|
||||
Description: sql.NullString{String: fmt.Sprintf("Transaction %d", i+1), Valid: true},
|
||||
AccountName: sql.NullString{String: "Savings", Valid: true},
|
||||
Account: 123,
|
||||
Bucket: sql.NullInt64{Int64: int64(i + 100), Valid: true},
|
||||
BucketName: sql.NullString{String: fmt.Sprintf("Bucket %d", i+1), Valid: true},
|
||||
Date: time.Now(),
|
||||
}
|
||||
|
||||
transactions[10 - i] = transaction
|
||||
}
|
||||
|
||||
component := transaction_rows(&transactions);
|
||||
component.Render(context.Background(), w);
|
||||
}
|
||||
|
||||
func getExpenditureChart(w http.ResponseWriter, req *http.Request) {
|
||||
data_package := types.ChartjsData {
|
||||
Labels: []string{"Income", "Expenses"},
|
||||
Data: []int{500, 200},
|
||||
};
|
||||
|
||||
json_data, err := json.Marshal(data_package);
|
||||
if err != nil {
|
||||
log.Fatal().Err(err).Msg("Could not jsonify data_package");
|
||||
}
|
||||
|
||||
w.Write(json_data);
|
||||
}
|
28
web/package-lock.json
generated
Normal file
28
web/package-lock.json
generated
Normal file
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"name": "web",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"dependencies": {
|
||||
"chart.js": "^4.4.1"
|
||||
}
|
||||
},
|
||||
"node_modules/@kurkle/color": {
|
||||
"version": "0.3.2",
|
||||
"resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
|
||||
"integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
|
||||
},
|
||||
"node_modules/chart.js": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.1.tgz",
|
||||
"integrity": "sha512-C74QN1bxwV1v2PEujhmKjOZ7iUM4w6BWs23Md/6aOZZSlwMzeCIDGuZay++rBgChYru7/+QFeoQW0fQoP534Dg==",
|
||||
"dependencies": {
|
||||
"@kurkle/color": "^0.3.0"
|
||||
},
|
||||
"engines": {
|
||||
"pnpm": ">=7"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
5
web/package.json
Normal file
5
web/package.json
Normal file
|
@ -0,0 +1,5 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"chart.js": "^4.4.1"
|
||||
}
|
||||
}
|
|
@ -1,20 +1,16 @@
|
|||
package web
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"html/template"
|
||||
"net/http"
|
||||
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/rs/zerolog/log"
|
||||
"nickiel.net/recount_server/types"
|
||||
)
|
||||
|
||||
type TemplateState struct {
|
||||
|
@ -32,6 +28,7 @@ func WebRouter() http.Handler {
|
|||
r := chi.NewRouter()
|
||||
r.Get("/", getIndex)
|
||||
r.Get("/web/transaction_table_rows", getTransactions)
|
||||
r.Get("/web/dashboard/expenditure_chart", getExpenditureChart)
|
||||
r.Get("/hello", getHello)
|
||||
r.Handle("/static/*", http.StripPrefix("/static/", http.FileServer(http.Dir("web/static/"))))
|
||||
return r
|
||||
|
@ -99,27 +96,3 @@ func getHello(w http.ResponseWriter, req *http.Request) {
|
|||
}
|
||||
}
|
||||
|
||||
const DEFAULT_RESULT_COUNT = 20;
|
||||
|
||||
func getTransactions(w http.ResponseWriter, req *http.Request) {
|
||||
transactions := make([]types.HumanLegibleTransaction, 10)
|
||||
|
||||
// Populate the slice with dummy data (you can replace this with your actual data)
|
||||
for i := 10; i > 0; i-- {
|
||||
transaction := types.HumanLegibleTransaction{
|
||||
Id: i,
|
||||
Amount: fmt.Sprintf("%d.00", (i+1)*100),
|
||||
Description: sql.NullString{String: fmt.Sprintf("Transaction %d", i+1), Valid: true},
|
||||
AccountName: sql.NullString{String: "Savings", Valid: true},
|
||||
Account: 123,
|
||||
Bucket: sql.NullInt64{Int64: int64(i + 100), Valid: true},
|
||||
BucketName: sql.NullString{String: fmt.Sprintf("Bucket %d", i+1), Valid: true},
|
||||
Date: time.Now(),
|
||||
}
|
||||
|
||||
transactions[10 - i] = transaction
|
||||
}
|
||||
|
||||
component := transaction_rows(&transactions);
|
||||
component.Render(context.Background(), w);
|
||||
}
|
||||
|
|
|
@ -56,6 +56,9 @@ $directions: (
|
|||
.w-full {
|
||||
width: 100%;
|
||||
}
|
||||
.w-75 {
|
||||
width: 75%;
|
||||
}
|
||||
.w-50 {
|
||||
width: 50%;
|
||||
}
|
||||
|
|
39
web/static/chart_functions.js
Normal file
39
web/static/chart_functions.js
Normal file
|
@ -0,0 +1,39 @@
|
|||
|
||||
function fill_charts() {
|
||||
document.querySelectorAll(".chartjs-chart").forEach(function (el) {
|
||||
var url = el.dataset.chartEndpoint;
|
||||
var type = el.dataset.chartType;
|
||||
|
||||
fetch(url)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
console.log(response);
|
||||
throw new Error("Fetch response was not ok!")
|
||||
}
|
||||
return response.json();
|
||||
}).then(jsonData => {
|
||||
const config = {
|
||||
type: type,
|
||||
data: {
|
||||
labels: jsonData.labels,
|
||||
datasets: [{
|
||||
data: jsonData.data
|
||||
}]
|
||||
},
|
||||
options: {
|
||||
scales: {
|
||||
y: {
|
||||
beginAtZero: true
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
new Chart(el, config)();
|
||||
}).catch(error => {
|
||||
console.error("Unable to set up chart: ", error)
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
export {fill_charts}
|
|
@ -1,3 +1,5 @@
|
|||
import {fill_charts} from "./chart_functions.js";
|
||||
|
||||
|
||||
function debounce(func, delay) {
|
||||
let timeoutId;
|
||||
|
@ -48,4 +50,4 @@ function load_in_table() {
|
|||
|
||||
const trigger_table_animation = debounce(load_in_table, 100);
|
||||
|
||||
export {register_handlers, trigger_table_animation};
|
||||
export {register_handlers, trigger_table_animation, fill_charts};
|
||||
|
|
|
@ -60,13 +60,15 @@
|
|||
</div>
|
||||
<script type="module" src="/static/index.js"></script>
|
||||
<script type="module">
|
||||
import {register_handlers, trigger_table_animation} from "/static/index.js";
|
||||
import {register_handlers, fill_charts, trigger_table_animation} from "/static/index.js";
|
||||
register_handlers();
|
||||
feather.replace();
|
||||
htmx.onLoad(function (element) {
|
||||
if (element.localName === "tr") {
|
||||
console.log(element);
|
||||
trigger_table_animation();
|
||||
} else {
|
||||
fill_charts();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
|
Loading…
Reference in a new issue