Sfoglia il codice sorgente

Resize selected letterhead to good dimensions

Uses gift package for server side resizing of selected letterhead
file. It should fit an image file with aspect ratio of 2:1 and be a
reasonable size. A 400x200 resizeToFit is used for now.
gift just uses the native image/draw package internally.
https://pkg.go.dev/image/draw
master
Immanuel Onyeka 1 anno fa
parent
commit
7055f5d6c7
6 ha cambiato i file con 784 aggiunte e 3014 eliminazioni
  1. +30
    -7
      components/settings.vue
  2. +1
    -0
      go.mod
  3. +2
    -0
      go.sum
  4. +713
    -3003
      package-lock.json
  5. +3
    -2
      package.json
  6. +35
    -2
      skouter.go

+ 30
- 7
components/settings.vue Vedi File

@@ -16,10 +16,10 @@
<h3>Letterhead</h3>
<canvas class="displayer" height="200" ref="letterhead"></canvas>
<input type="file"
@change="e => changeLetterhead(e.target.files[0])"
@change="e => {setLetterhead(e.target.files[0])}"
/>
<button @click="uploadLetterhead">Upload</button>
<label class="error">{{avatarError}}</label>
<label class="error">{{letterheadError}}</label>
</section>

<section class="form inputs special">
@@ -68,6 +68,7 @@ let letterhead = ref(null) // the canvas element
let ready = ref(false)
let avatarChanged = ref(false)
let avatarError = ref('')
let letterHeadError = ref('')
let letterheadError = ref('')
const props = defineProps(['user', 'token'])
const emit = defineEmits(['updateAvatar', 'updateLetterhead'])
@@ -109,6 +110,28 @@ function uploadLetterhead() {
})
}

function setLetterhead(f) {
const validTypes = ['image/jpeg', 'image/png']
if (!validTypes.includes(f.type)) {
letterheadError.value = 'Image must be JPEG of PNG format'
return
}
fetch(`/api/letterhead`,
{method: 'POST',
body: f,
headers: {
"Accept": "application/json",
"Authorization": `Bearer ${props.token}`,
},
}).then(resp => {
if (resp.ok) {
resp.blob().then(b => changeLetterhead(b))
} else {
resp.text().then(e => letterheadError.value = e)
}
})
}

function changeAvatar(blob) {
const validTypes = ['image/jpeg', 'image/png']
@@ -135,13 +158,13 @@ function changeLetterhead(blob) {
return
}
letterheadError.value = ''
return createImageBitmap(blob,
{resizeWidth: 400, resizeHeight: 200, resizeQuality: 'medium'}).
createImageBitmap(blob).
then((img) => {
letterhead.value.getContext("2d").drawImage(img, 0, 0, 400, 200)
let ctx = letterhead.value.getContext("2d")
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
ctx.drawImage(img, 0, 0)
})

}

watch(props.user, (u) => {


+ 1
- 0
go.mod Vedi File

@@ -4,6 +4,7 @@ go 1.19

require (
github.com/SebastiaanKlippert/go-wkhtmltopdf v1.9.0
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
)

+ 2
- 0
go.sum Vedi File

@@ -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/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=
github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=


+ 713
- 3003
package-lock.json
File diff soppresso perché troppo grande
Vedi File


+ 3
- 2
package.json Vedi File

@@ -1,9 +1,10 @@
{
"scripts": {
"watch": "webpack --mode development --watch"
"watch": "webpack --mode development --watch"
},
"dependencies": {
"vue": "^3.2.41"
"vue": "^3.2.41",
"vue-html2pdf": "^1.8.0"
},
"devDependencies": {
"css-loader": "^6.7.1",


+ 35
- 2
skouter.go Vedi File

@@ -20,6 +20,10 @@ import (
"io"
// pdf "github.com/SebastiaanKlippert/go-wkhtmltopdf"
"github.com/golang-jwt/jwt/v4"
"github.com/disintegration/gift"
"image"
"image/png"
_ "image/jpeg"
)

type User struct {
@@ -1566,12 +1570,13 @@ func checkFHA(l Loan, b Borrower) error {
return nil
}

// Loan option for veterans with no set rules
// Loan option for veterans with no set rules. Mainly placeholder.
func checkVA(l Loan, b Borrower) error {
return nil
}

// Loan option for residents of rural areas with no set rules
// Loan option for residents of rural areas with no set rules.
// Mainly placeholder.
func checkUSDA(l Loan, b Borrower) error {
return nil
}
@@ -1677,6 +1682,31 @@ func showPDF(w http.ResponseWriter, r *http.Request) {

}

func clipLetterhead(w http.ResponseWriter, db *sql.DB, r *http.Request) {
var validTypes []string = []string{"image/png", "image/jpeg"}
var isValidType bool
var err error
// claims, err := getClaims(r)
if err != nil { http.Error(w, "Invalid token.", 422); return }
img, t, err := image.Decode(r.Body)
if err != nil { http.Error(w, "Invalid file.", 422); return }
for _, v := range validTypes {
if v == "image/"+t { isValidType = true }
}
if !isValidType { http.Error(w, "Invalid file type.", 422); return }
g := gift.New(
gift.ResizeToFit(400, 200, gift.LanczosResampling),
)
dst := image.NewRGBA(g.Bounds(img.Bounds()))
g.Draw(dst, img)
w.Header().Set("Content-Type", "image/png")
err = png.Encode(w, dst)
if err != nil { http.Error(w, "Error encoding.", 500); return }
}

func api(w http.ResponseWriter, r *http.Request) {
var args []string

@@ -1702,6 +1732,9 @@ func api(w http.ResponseWriter, r *http.Request) {
case match(p, "/api/token", &args) &&
r.Method == http.MethodGet && guard(r, 1):
getToken(w, db, r)
case match(p, "/api/letterhead", &args) &&
r.Method == http.MethodPost && guard(r, 1):
clipLetterhead(w, db, r)
case match(p, "/api/users", &args) && // Array of all users
r.Method == http.MethodGet && guard(r, 3):
getUsers(w, db, r)


Loading…
Annulla
Salva