package ods
import (
"archive/zip"
"bytes"
"dev.tandem.ws/tandem/camper/pkg/auth"
"dev.tandem.ws/tandem/camper/pkg/template"
"encoding/xml"
"fmt"
"net/http"
"strings"
"time"
"dev.tandem.ws/tandem/camper/pkg/database"
"dev.tandem.ws/tandem/camper/pkg/locale"
)
const (
mimetype = "application/vnd.oasis.opendocument.spreadsheet"
metaDashInfManifestXml = `
`
metaXml = `
Camper
`
stylesXml = `
`
)
func WriteTable[K interface{}](rows []*K, columns []string, locale *locale.Locale, writeRow func(*strings.Builder, *K) error) ([]byte, error) {
var sb strings.Builder
sb.WriteString(`
/
/
`)
sb.WriteString(fmt.Sprintf(" \n", len(columns)))
sb.WriteString(`
`)
for _, t := range columns {
if err := WriteCellString(&sb, locale.GetC(t, "header")); err != nil {
return nil, err
}
}
sb.WriteString(" \n")
for _, row := range rows {
sb.WriteString(" \n")
if err := writeRow(&sb, row); err != nil {
return nil, err
}
sb.WriteString(" \n")
}
sb.WriteString(`
`)
return writeOds(sb.String())
}
func writeOds(content string) ([]byte, error) {
buf := new(bytes.Buffer)
ods := zip.NewWriter(buf)
if err := writeOdsFile(ods, "mimetype", mimetype, zip.Store); err != nil {
return nil, err
}
if err := writeOdsFile(ods, "META-INF/manifest.xml", metaDashInfManifestXml, zip.Deflate); err != nil {
return nil, err
}
if err := writeOdsFile(ods, "meta.xml", metaXml, zip.Deflate); err != nil {
return nil, err
}
if err := writeOdsFile(ods, "styles.xml", stylesXml, zip.Deflate); err != nil {
return nil, err
}
if err := writeOdsFile(ods, "content.xml", content, zip.Deflate); err != nil {
return nil, err
}
if err := ods.Close(); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
func writeOdsFile(ods *zip.Writer, name string, content string, method uint16) error {
f, err := ods.CreateHeader(&zip.FileHeader{
Name: name,
Method: method,
Modified: time.Now(),
})
if err != nil {
return err
}
_, err = f.Write([]byte(content))
return err
}
func WriteCellString(sb *strings.Builder, s string) error {
sb.WriteString(` `)
if err := xml.EscapeText(sb, []byte(s)); err != nil {
return err
}
sb.WriteString("\n")
return nil
}
func WriteCellDate(sb *strings.Builder, t time.Time) {
sb.WriteString(fmt.Sprintf(" %s\n", t.Format(database.ISODateFormat), t.Format("02/01/06")))
}
func WriteCellFloat(sb *strings.Builder, s string, company *auth.Company, locale *locale.Locale) {
sb.WriteString(fmt.Sprintf(" %s\n", s, template.FormatPrice(s, locale.Language, locale.CurrencyPattern, company.DecimalDigits, company.CurrencySymbol)))
}
func MustWriteResponse(w http.ResponseWriter, ods []byte, filename string) {
w.Header().Set("Content-Type", "application/vnd.oasis.opendocument.spreadsheet")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%s", filename))
w.WriteHeader(http.StatusOK)
if _, err := w.Write(ods); err != nil {
panic(err)
}
}