diff --git a/Makefile b/Makefile index fa3a949..df383f9 100644 --- a/Makefile +++ b/Makefile @@ -23,7 +23,11 @@ front: NODE_ENV=prod ./node_modules/.bin/webpack .PHONY: -build: front rice +tpl: + TEMPL_EXPERIMENT=rawgo templ generate + +.PHONY: +build: tpl front rice CGO_ENABLED=$(CGO_ENABLED) \ GOARCH=$(GO_ARCH_AMD) \ GOOS=$(GO_OS_LINUX) \ diff --git a/bin/watch.sh b/bin/watch.sh index 7a5d99b..b9a58f2 100755 --- a/bin/watch.sh +++ b/bin/watch.sh @@ -1,9 +1,11 @@ #!/bin/sh +export TEMPL_EXPERIMENT=rawgo + while true; do rm -f cmd/server/rice-box.go ./node_modules/.bin/webpack - templ generate + make tpl screen -S budget -d -m go run ./cmd/server notify-send "Budget" "Ready!" inotifywait -r . -e close_write diff --git a/config.ini b/config.ini index b9a2396..a18ab45 100644 --- a/config.ini +++ b/config.ini @@ -5,6 +5,9 @@ address = "0.0.0.0" [security] secret = "e93865c991358ff7a14f9781fa33ba4f28c33bb8d1cf3490ce6fd68521513536" +[calc] +url = "https://deblan.cloud/index.php/apps/files/files/1402577?dir=%2FAdministratif%2FProjet+de+construction&openfile=true" + [log] ; level = "debug" level = "warn" diff --git a/config/config.go b/config/config.go index f9b1664..53f1787 100644 --- a/config/config.go +++ b/config/config.go @@ -23,11 +23,16 @@ type server struct { Port int } +type calc struct { + Url string +} + type Config struct { Database database Log logging Security security Server server + Calc calc } var config *Config @@ -52,4 +57,5 @@ func (c *Config) Load(file string) { config.Security.Secret = cfg.Section("security").Key("secret").String() config.Server.Address = cfg.Section("server").Key("address").String() config.Server.Port, _ = cfg.Section("server").Key("port").Int() + config.Calc.Url = cfg.Section("calc").Key("url").String() } diff --git a/frontend/img/favicon.png b/frontend/img/favicon.png new file mode 100644 index 0000000..47fce4c Binary files /dev/null and b/frontend/img/favicon.png differ diff --git a/frontend/js/chart/distribution.js b/frontend/js/chart/distribution.js index 0fc7c5e..5873123 100644 --- a/frontend/js/chart/distribution.js +++ b/frontend/js/chart/distribution.js @@ -29,7 +29,7 @@ const computeBar = (transactions, stacked) => { let category = transaction.category ?? emptyCategory let date = getDate(transaction.date) - + if (!indexes.hasOwnProperty(date)) { indexes[date] = labels.length labels.push(date) @@ -40,7 +40,7 @@ const computeBar = (transactions, stacked) => { label: category.label, data: [], borderColor: category.color, - backgroundColor : category.color, + backgroundColor: category.color, fill: true, cubicInterpolationMode: 'monotone', } @@ -49,7 +49,7 @@ const computeBar = (transactions, stacked) => { for (let key in bars) { labels.forEach(() => { - bars[key].data.push(0) + bars[key].data.push(0) }) } @@ -61,8 +61,6 @@ const computeBar = (transactions, stacked) => { let category = transaction.category ?? emptyCategory let date = getDate(transaction.date) - console.log(category) - bars[category.label].data[indexes[date]] += transaction.debit }) @@ -117,15 +115,13 @@ const computeDoughnut = (transactions) => { data[indexes[category.id]] += transaction.debit }) - const d = { + return { labels: labels, datasets: [{ data: Object.values(data), backgroundColor: backgroundColor, }], } - - return d } export { diff --git a/frontend/js/router/index.js b/frontend/js/router/index.js index 21becf8..a20b330 100644 --- a/frontend/js/router/index.js +++ b/frontend/js/router/index.js @@ -33,6 +33,12 @@ const router = createRouter({ meta: { icon: ['fa-solid', 'fa-piggy-bank'] }, component: () => import('../views/BankAccountsView.vue') }, + // { + // path: '/calc', + // name: 'Tableur', + // meta: { icon: ['fa-solid', 'fa-table'] }, + // component: () => import('../views/CalcView.vue') + // }, ] }) diff --git a/frontend/js/views/CalcView.vue b/frontend/js/views/CalcView.vue new file mode 100644 index 0000000..e13714f --- /dev/null +++ b/frontend/js/views/CalcView.vue @@ -0,0 +1,15 @@ + + + + + diff --git a/package-lock.json b/package-lock.json index d42328b..43d29a6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -21,6 +21,7 @@ "@vitejs/plugin-vue": "^5.0.5", "babel-loader": "^9.1.3", "css-loader": "^7.1.2", + "file-loader": "^6.2.0", "mini-css-extract-plugin": "^2.9.1", "postcss-loader": "^8.1.1", "sass": "^1.78.0", @@ -4659,6 +4660,27 @@ "node": ">= 4.9.1" } }, + "node_modules/file-loader": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz", + "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "loader-utils": "^2.0.0", + "schema-utils": "^3.0.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", diff --git a/package.json b/package.json index 8c8d140..ff8a500 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@vitejs/plugin-vue": "^5.0.5", "babel-loader": "^9.1.3", "css-loader": "^7.1.2", + "file-loader": "^6.2.0", "mini-css-extract-plugin": "^2.9.1", "postcss-loader": "^8.1.1", "sass": "^1.78.0", diff --git a/web/view/template/base.templ b/web/view/template/base.templ index fccdef5..b7e4def 100644 --- a/web/view/template/base.templ +++ b/web/view/template/base.templ @@ -2,10 +2,15 @@ package template import "gitnet.fr/deblan/budget/web/view" +templ Fav(url string) { + +} + templ Head(title string) { + @Fav(view.Asset("static/img/favicon.png")) { title } @templ.Raw(view.EntrypointCss("main")) diff --git a/web/view/template/base_templ.go b/web/view/template/base_templ.go index 0222c21..8125c00 100644 --- a/web/view/template/base_templ.go +++ b/web/view/template/base_templ.go @@ -10,7 +10,7 @@ import templruntime "github.com/a-h/templ/runtime" import "gitnet.fr/deblan/budget/web/view" -func Head(title string) templ.Component { +func Fav(url string) templ.Component { return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { @@ -31,19 +31,69 @@ func Head(title string) templ.Component { templ_7745c5c3_Var1 = templ.NopComponent } ctx = templ.ClearChildren(ctx) - _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<link rel=\"icon\" type=\"image/x-icon\" href=\"") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } var templ_7745c5c3_Var2 string - templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title) + templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(url) if templ_7745c5c3_Err != nil { - return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/view/template/base.templ`, Line: 9, Col: 16} + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/view/template/base.templ`, Line: 6, Col: 48} } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2)) if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("\">") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + return templ_7745c5c3_Err + }) +} + +func Head(title string) templ.Component { + return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) { + templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context + if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil { + return templ_7745c5c3_CtxErr + } + templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W) + if !templ_7745c5c3_IsBuffer { + defer func() { + templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer) + if templ_7745c5c3_Err == nil { + templ_7745c5c3_Err = templ_7745c5c3_BufErr + } + }() + } + ctx = templ.InitializeContext(ctx) + templ_7745c5c3_Var3 := templ.GetChildren(ctx) + if templ_7745c5c3_Var3 == nil { + templ_7745c5c3_Var3 = templ.NopComponent + } + ctx = templ.ClearChildren(ctx) + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<head><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + templ_7745c5c3_Err = Fav(view.Asset("static/img/favicon.png")).Render(ctx, templ_7745c5c3_Buffer) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<title>") + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } + var templ_7745c5c3_Var4 string + templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(title) + if templ_7745c5c3_Err != nil { + return templ.Error{Err: templ_7745c5c3_Err, FileName: `web/view/template/base.templ`, Line: 14, Col: 16} + } + _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4)) + if templ_7745c5c3_Err != nil { + return templ_7745c5c3_Err + } _, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("") if templ_7745c5c3_Err != nil { return templ_7745c5c3_Err @@ -76,9 +126,9 @@ func JS() templ.Component { }() } ctx = templ.InitializeContext(ctx) - templ_7745c5c3_Var3 := templ.GetChildren(ctx) - if templ_7745c5c3_Var3 == nil { - templ_7745c5c3_Var3 = templ.NopComponent + templ_7745c5c3_Var5 := templ.GetChildren(ctx) + if templ_7745c5c3_Var5 == nil { + templ_7745c5c3_Var5 = templ.NopComponent } ctx = templ.ClearChildren(ctx) templ_7745c5c3_Err = templ.Raw(view.EntrypointJs("main")).Render(ctx, templ_7745c5c3_Buffer) diff --git a/webpack.config.js b/webpack.config.js index d887d6f..58c040f 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -48,10 +48,10 @@ Encore config.plugins.push('@babel/plugin-syntax-dynamic-import'); }) - // .copyFiles({ - // from: './frontend/images', - // to: 'images/[path][name].[hash:8].[ext]' - // }) + .copyFiles({ + from: './frontend/img', + to: 'img/[path][name].[hash:8].[ext]' + }) // enables Sass/SCSS support .enableSassLoader()