From d4a5e4cc4dc7df03fb914294eb30156e88bb8fb1 Mon Sep 17 00:00:00 2001 From: Immanuel Onyeka <immanuel@onyeka.ca> Date: Thu, 7 Sep 2023 13:40:15 -0400 Subject: [PATCH] Remove vue component for PDF generation Also structure CLI functions to allow for `skouter dev seed` command. --- README.md | 3 + components/app.vue | 8 -- components/estimate-test.vue | 137 ----------------------------------- go.mod | 1 + go.sum | 2 + skouter.go | 64 ++++++++++++---- 6 files changed, 56 insertions(+), 159 deletions(-) delete mode 100644 components/estimate-test.vue diff --git a/README.md b/README.md index 5b86e99..16dc3f8 100644 --- a/README.md +++ b/README.md @@ -8,3 +8,6 @@ DBPass Uses ESbuild and the Vue node package. `sudo apt install esbuild; npm install vue;` `` + +### Starting Server +It reads database info from environment variables, unless called as `skouter dev`. Dev mode uses default datbase credentials for user 'tester'. diff --git a/components/app.vue b/components/app.vue index ab3a89d..0213069 100644 --- a/components/app.vue +++ b/components/app.vue @@ -45,13 +45,6 @@ v-else-if="active == 4" /> <login @login="start" /> </template> -<estimate-test -v-else-if="active == 7" -:token="token" -:estimate="preview" -:user="user" -/> - </div> </template> @@ -61,7 +54,6 @@ import Spinner from "./spinner.vue" import Home from "./home.vue" import NewEstimate from "./new/new.vue" import Estimates from "./estimates.vue" -import EstimateTest from "./estimate-test.vue" import Settings from "./settings.vue" import SignOut from "./sign-out.vue" import Login from "./login.vue" diff --git a/components/estimate-test.vue b/components/estimate-test.vue deleted file mode 100644 index 0cfe639..0000000 --- a/components/estimate-test.vue +++ /dev/null @@ -1,137 +0,0 @@ -<template> -<div id="pdf-doc" ref="doc" v-if="estimate"> -<div class="disclaimer"><p>Actual costs may vary from estimates after approval. Get an official quote before choosing a loan.</p></div> - -<header class="heading"> - -<img :src="letterhead" /> - -<div> - -<div class="user-info"> -<h4>{{user.firstName + " " + user.lastName}}</h4> -<span>{{user.email}}</span> -<span>{{user.phone}}</span> -<small>{{user.address.street}}</small> -<small> -{{`${user.address.city}, ${user.address.region} ${user.address.zip}`}} -</small> -</div> -<img :src="avatar"/> -</div> - -</header> - -<button @click="getPdf">Generate</button> -<a :href="pdfLink" v-if="pdfLink" download="estimate.pdf">download </a> -</div> -</template> - -<script setup> -import { ref, computed, onMounted } from "vue" -import html2pdf from "html2pdf.js"; - -const doc = ref(null) -const props = defineProps(['token', 'estimate', 'user']) -const estimate = ref(null) -const estimates = ref(null) -const pdfLink = ref('') - -const letterhead = computed(() => { - if (!props.user.letterhead) return null - return URL.createObjectURL(props.user.letterhead) -}) - -const avatar = computed(() => { - if (!props.user.letterhead) return null - console.log(props.user) - return URL.createObjectURL(props.user.avatar) -}) - -function makePDF() { - var opt = { - image: { type: 'png', quality: 1 }, - } - - html2pdf(doc.value, opt) -} - - -function getEstimates() { - return fetch(`/api/estimates`, - {method: 'GET', - headers: { - "Accept": "application/json", - "Authorization": `Bearer ${props.token}`, - }, - }).then(response => { - if (response.ok) { return response.json() } else { - response.text().then(t => console.log(t)) - } - }).then (result => { - if (!result || !result.length) return // Exit if token is invalid or no fees are saved - estimates.value = result - // console.log(result) - }) -} - -function getPdf() { - fetch(`/api/pdf`, - {method: 'POST', - body: JSON.stringify(estimate.value), - headers: { - "Accept": "application/json", - "Authorization": `Bearer ${props.token}`, - }, - }).then(response => { - if (response.ok) { return response.blob() } - else { - return null - } - }).then (result => { - if (!result) return - pdfLink.value = URL.createObjectURL(result) - }) -} - -onMounted(() => { - getEstimates().then(() => estimate.value = estimates.value[0]) -}) -</script> - -<style scoped> -#pdf-doc { - margin: 4px 30px; -} - -.disclaimer { - font-weight: bold; - border-bottom: 1px solid lightgrey; - margin-bottom: 20px; - color: var(--text); -} - -.disclaimer p { - margin: 5px 0; -} - -h4 { - margin: 4px 0; -} - -header.heading { - display: flex; - justify-content: space-between; -} - -.user-info { - display: flex; - flex-flow: column; -} - -#pdf-doc header.heading > div { - display: flex; - gap: 8px; - text-align: right; -} -</style> diff --git a/go.mod b/go.mod index 352bca1..b110535 100644 --- a/go.mod +++ b/go.mod @@ -4,6 +4,7 @@ go 1.19 require ( github.com/SebastiaanKlippert/go-wkhtmltopdf v1.9.0 + github.com/brianvoe/gofakeit/v6 v6.23.2 github.com/disintegration/gift v1.2.1 github.com/go-sql-driver/mysql v1.6.0 github.com/golang-jwt/jwt/v4 v4.5.0 diff --git a/go.sum b/go.sum index 0cb2a39..bf3e3fe 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,7 @@ github.com/SebastiaanKlippert/go-wkhtmltopdf v1.9.0 h1:DNrExYwvyyI404SxdUCCANAj9TwnGjRfa3cYFMNY1AU= github.com/SebastiaanKlippert/go-wkhtmltopdf v1.9.0/go.mod h1:SQq4xfIdvf6WYKSDxAJc+xOJdolt+/bc1jnQKMtPMvQ= +github.com/brianvoe/gofakeit/v6 v6.23.2 h1:lVde18uhad5wII/f5RMVFLtdQNE0HaGFuBUXmYKk8i8= +github.com/brianvoe/gofakeit/v6 v6.23.2/go.mod h1:Ow6qC71xtwm79anlwKRlWZW6zVq9D2XHE4QSSMP/rU8= github.com/disintegration/gift v1.2.1 h1:Y005a1X4Z7Uc+0gLpSAsKhWi4qLtsdEcMIbbdvdZ6pc= github.com/disintegration/gift v1.2.1/go.mod h1:Jh2i7f7Q2BM7Ezno3PhfezbR1xpUg9dUg3/RlKGr4HI= github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= diff --git a/skouter.go b/skouter.go index 1bf9247..3bcc780 100644 --- a/skouter.go +++ b/skouter.go @@ -24,6 +24,7 @@ import ( // pdf "github.com/SebastiaanKlippert/go-wkhtmltopdf" "github.com/golang-jwt/jwt/v4" "github.com/disintegration/gift" + "github.com/brianvoe/gofakeit/v6" "image" "image/png" _ "image/jpeg" @@ -195,7 +196,7 @@ var paths = map[string]string { var pages = map[string]Page { "home": cache("home", "Home"), "terms": cache("terms", "Terms and Conditions"), - "test": cachePdf("comparison"), + "report": cachePdf("comparison"), "app": cache("app", "App"), } @@ -1846,10 +1847,7 @@ func validateEstimate(w http.ResponseWriter, db *sql.DB, r *http.Request) { if err != nil { http.Error(w, err.Error(), 406); return } } -func showPDF(w http.ResponseWriter, r *http.Request) { - // var args []string - - // p := r.URL.Path +func checkPdf(w http.ResponseWriter, r *http.Request) { db, err := sql.Open("mysql", fmt.Sprintf("%s:%s@tcp(127.0.0.1:3306)/skouter_dev", os.Getenv("DBUser"), @@ -1863,8 +1861,6 @@ func showPDF(w http.ResponseWriter, r *http.Request) { // maybe os.Exit(1) instead } - page := cachePdf("comparison") - estimates, err := getEstimates(db, 1, 0) if err != nil { w.WriteHeader(500); return } @@ -1894,7 +1890,7 @@ func showPDF(w http.ResponseWriter, r *http.Request) { } } - err = page.tpl.ExecuteTemplate(w, "master.tpl", info) + err = pages["report"].tpl.ExecuteTemplate(w, "master.tpl", info) if err != nil {fmt.Println(err)} } @@ -1944,7 +1940,7 @@ func getPdf(w http.ResponseWriter, db *sql.DB, r *http.Request) { base64.StdEncoding.EncodeToString(letterhead) - err = pages["test"].tpl.ExecuteTemplate(stdin, "master.tpl", info) + err = pages["report"].tpl.ExecuteTemplate(stdin, "master.tpl", info) if err != nil { w.WriteHeader(500); log.Println(err) @@ -1961,7 +1957,6 @@ func getPdf(w http.ResponseWriter, db *sql.DB, r *http.Request) { } if err := cmd.Wait(); err != nil { - // w.WriteHeader(500) log.Println(err) return } @@ -2117,7 +2112,7 @@ func route(w http.ResponseWriter, r *http.Request) { case match(p, "/app", &args): page = pages[ "app" ] case match(p, "/test", &args): - showPDF(w, r) + checkPdf(w, r) return default: http.NotFound(w, r) @@ -2136,21 +2131,62 @@ func serve() { log.Fatal(http.ListenAndServe(address, nil)) } +func dbSeed() { + db, err := sql.Open("mysql", + fmt.Sprintf("%s:%s@tcp(127.0.0.1:3306)/%s", + os.Getenv("DBUser"), + os.Getenv("DBPass"), + os.Getenv("DBName"), + )) + + err = db.Ping() + if err != nil { + fmt.Println("Bad database configuration: %v\n", err) + panic(err) + // maybe os.Exit(1) instead + } +} + func dev(args []string) { if len(args) == 0 { os.Setenv("DBName", "skouter_dev") os.Setenv("DBUser", "tester") os.Setenv("DBPass", "test123") serve() + return } + + switch args[0] { + case "seed": + dbSeed() + default: + return + } +} + +func check(args []string) { + os.Setenv("DBName", "skouter_dev") + os.Setenv("DBUser", "tester") + os.Setenv("DBPass", "test123") + files := http.FileServer(http.Dir("")) + + http.Handle("/assets/", files) + http.HandleFunc("/", checkPdf) + log.Fatal(http.ListenAndServe(address, nil)) } func main() { if len(os.Args) <= 1 { serve() + return } - - if os.Args[1] == "dev" { + + switch os.Args[1] { + case "dev": dev(os.Args[2:]) - } + case "check": + check(os.Args[2:]) + default: + return + } }