diff --git a/cmd/config.go b/cmd/config.go index 00e6d92..d50fb36 100644 --- a/cmd/config.go +++ b/cmd/config.go @@ -8,9 +8,12 @@ import ( type Config struct { TemplatesPath string `env:"TEMPLATES_PATH" envDefault:"cmd/testdata/"` - RenderTimeout time.Duration `env:"RENDER_TIMEOUT envDefault:"3s"` + RenderTimeout time.Duration `env:"RENDER_TIMEOUT" envDefault:"10s"` ServerHost string `env:"SERVER_HOST" envDefault:"localhost"` ServerPort int `env:"SERVER_PORT" envDefault:"8080"` + + ViewportHeight int `env:"VIEWPORT_HEIGHT" envDefault:"2048"` + ViewportWidth int `env:"VIEWPORT_WIDTH" envDefault:"1920"` } func (config Config) BaseUrl() string { diff --git a/cmd/module.go b/cmd/module.go index 9c1989b..8d84224 100644 --- a/cmd/module.go +++ b/cmd/module.go @@ -22,7 +22,7 @@ type Module struct { func NewModule(config Config) *Module { engine := data.NewGolangTemplateEngine() repo := data.NewFilesystemTemplateRepo(config.TemplatesPath) - png := data.NewPngReportExporter(config.RenderTimeout) + png := data.NewPngReportExporter(config.RenderTimeout, config.ViewportHeight, config.ViewportWidth) pdf := data.NewPdfReportExporter(png) tmplSrv := business.NewTemplateService(engine, repo) diff --git a/examples/long_invoice.html b/examples/long_invoice.html new file mode 100644 index 0000000..ede9b3c --- /dev/null +++ b/examples/long_invoice.html @@ -0,0 +1,305 @@ + + + + + + + +
+

COMMERCIAL INVOICE

+ This invoice must be completed in English. + +
+
+ EXPORTER: + TAX ID#: + Contact Name: + Telephone No.: + E-Mail: + Company Name/Address: + Country/Territory: + Parties to transaction: +
+ Related + Non-Related +
+
+
+ Ship Date: + Air Waybill No./Tracking No.: +
+
+ Invoice No.: + Purchase Order No.: +
+
+ Payment Terms: + Bill of Lading: +
+
+ Purpose of Shipment: +
+
+ +
+
+ CONSIGNEE: + TAX ID#: + Contact Name: + Telephone No.: + E-Mail: + Company Name/Address: + Country/Territory: +
+
+ SOLD TO/IMPORTER (if different from Consignee): + Same as CONSIGNEE: + TAX ID#: + Company Name/Address: + Country/Territory: +
+
+ +
+
+ If there is a designated broker for this shipment, please provide contact information. +
+
+ Name of broker: + Tel. No.: + Contact Name: +
+
+ +
+
+ Duties and Taxes Payable by + Exporter + Consignee + Other + If other please specify: +
+
+ +
+ + + + + + + + + + + + + + + + + + {{- range $i, $j := .Sequence 20 }} + {{- if lt $i (len $.Values.lineItems) }} + {{- with index $.Values.lineItems $i }} + + + + + + + + + + + + {{- end }} + {{- else }} + + + + + + + + + + + + {{- end }} + {{- end }} + + + +
No. of PackagesNo. of UnitsNet Weight (LBS/KGS)Unit of MeasureDescription of GoodsHarmonized Tariff NumberCountry of ManufactureUnit ValueTotal Value
{{ .quantity }}{{ .quantity }}{{ .netWeight }}EA{{ .description }}{{ .origin }}{{ .unitValue }}{{ .totalValue }}
00
+
+ +
+
+ + + + + + + + + + + + + + + + + + + + + +
Total PkgsNo. of UnitsTotal Net WeightTotal Gross WeightTerms of Sale
{{ .Values.totalPackages }}{{ .Values.totalUnits }}{{ .Values.totalNetWeight }} KG{{ .Values.totalGrossWeight }} KGDDP
+ +
+ Special Instructions:
+
+ +
+ Declaration Statement(s):
+
+ +
+ I declare that all the information contained in this invoice to be true and correct. +
+ +
+ Originator or Name of Company Representative if the invoice is being completed on behalf of a company or individual: +
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Subtotal:{{ .Values.subTotal }}
Insurance:0.00
Freight:{{ .Values.freight }}
Packing:0.00
Handling:0.00
Other:0.00
Invoice Total:{{ .Values.total }}
Country Code:{{ .Values.countryCode }}
+
+
+ +
+ Signature/Title/Date: +
+ +
+ + + \ No newline at end of file diff --git a/internal/data/png_report_exporter.go b/internal/data/png_report_exporter.go index 2e935dc..ad36d4f 100644 --- a/internal/data/png_report_exporter.go +++ b/internal/data/png_report_exporter.go @@ -10,17 +10,17 @@ import ( ) type pngReportExporter struct { - timeout time.Duration + timeout time.Duration + viewportHeight int + viewportWidth int } -func NewPngReportExporter(timeout time.Duration) *pngReportExporter { - return &pngReportExporter{timeout: timeout} +func NewPngReportExporter(timeout time.Duration, vpHeight, vpWidth int) *pngReportExporter { + return &pngReportExporter{timeout: timeout, viewportHeight: vpHeight, viewportWidth: vpWidth} } func (pre *pngReportExporter) Export(url string) ([]byte, *models.PrintOptions, error) { - baseCtx, to := context.WithTimeout(context.Background(), pre.timeout) - ctx, cancel := chromedp.NewContext(baseCtx) - defer to() + ctx, cancel := createContext(pre.timeout, pre.viewportHeight, pre.viewportWidth) defer cancel() var res []byte @@ -39,6 +39,28 @@ func (pre *pngReportExporter) Export(url string) ([]byte, *models.PrintOptions, return res, &options, nil } +func createContext(timeout time.Duration, vph int, vpw int) (context.Context, context.CancelFunc) { + baseCtx, cancelTimeout := context.WithTimeout(context.Background(), timeout) + + opts := []chromedp.ExecAllocatorOption{ + chromedp.WindowSize(vpw, vph), + chromedp.NoFirstRun, + chromedp.NoDefaultBrowserCheck, + chromedp.Headless, + chromedp.DisableGPU, + } + allocCtx, cancelAlloc := chromedp.NewExecAllocator(baseCtx, opts...) + ctx, cancelCtx := chromedp.NewContext(allocCtx) + + cancelFuncs := func() { + cancelTimeout() + cancelAlloc() + cancelCtx() + } + + return ctx, cancelFuncs +} + const extractPrintOptions = `function extractStyles() { var styles = getComputedStyle(document.body); diff --git a/internal/data/report_exporter_test.go b/internal/data/report_exporter_test.go index 0939f10..e992bad 100644 --- a/internal/data/report_exporter_test.go +++ b/internal/data/report_exporter_test.go @@ -12,7 +12,7 @@ import ( ) func TestPngReportExporter_Export_PrintableNotFound(t *testing.T) { - ts := NewPngReportExporter(1 * time.Second) + ts := NewPngReportExporter(1*time.Second, 2000, 1920) png, _, err := ts.Export(fmt.Sprintf("http://localhost:%d/subfolder/report2.html", testPort)) assert.NotNil(t, err) assert.Nil(t, png) @@ -20,7 +20,7 @@ func TestPngReportExporter_Export_PrintableNotFound(t *testing.T) { } func TestPngReportExporter_Export_PrintableFound(t *testing.T) { - ts := NewPngReportExporter(2 * time.Second) + ts := NewPngReportExporter(2*time.Second, 2000, 1920) png, _, err := ts.Export(fmt.Sprintf("http://localhost:%d/report1.html", testPort)) assert.Nil(t, err) assert.NotEmpty(t, png) @@ -30,7 +30,7 @@ func TestPngReportExporter_Export_PrintableFound(t *testing.T) { } func TestPdfReportExporter_Export_PrintableNotFound(t *testing.T) { - ts := NewPdfReportExporter(NewPngReportExporter(1 * time.Second)) + ts := NewPdfReportExporter(NewPngReportExporter(1*time.Second, 2000, 1920)) png, _, err := ts.Export(fmt.Sprintf("http://localhost:%d/subfolder/report2.html", testPort)) assert.NotNil(t, err) assert.Nil(t, png) @@ -38,7 +38,7 @@ func TestPdfReportExporter_Export_PrintableNotFound(t *testing.T) { } func TestPdfReportExporter_Export_PrintableFound(t *testing.T) { - ts := NewPdfReportExporter(NewPngReportExporter(1 * time.Second)) + ts := NewPdfReportExporter(NewPngReportExporter(1*time.Second, 2000, 1920)) pdf, _, err := ts.Export(fmt.Sprintf("http://localhost:%d/report1.html", testPort)) assert.Nil(t, err) assert.NotEmpty(t, pdf) diff --git a/internal/data/testdata/report1.png b/internal/data/testdata/report1.png index 49488e0..647ccb0 100755 Binary files a/internal/data/testdata/report1.png and b/internal/data/testdata/report1.png differ