Initial commit.
commit
fa2662369b
|
@ -0,0 +1,18 @@
|
||||||
|
root = true
|
||||||
|
|
||||||
|
[*]
|
||||||
|
indent_style = tab
|
||||||
|
end_of_line = lf
|
||||||
|
charset = utf-8
|
||||||
|
trim_trailing_whitespace = false
|
||||||
|
insert_final_newline = true
|
||||||
|
|
||||||
|
[*.json]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 2
|
||||||
|
insert_final_newline = false
|
||||||
|
|
||||||
|
[*.{yaml,yml}]
|
||||||
|
indent_style = space
|
||||||
|
indent_size = 4
|
||||||
|
insert_final_newline = true
|
|
@ -0,0 +1,24 @@
|
||||||
|
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||||
|
*.o
|
||||||
|
*.a
|
||||||
|
*.so
|
||||||
|
|
||||||
|
# Folders
|
||||||
|
_obj
|
||||||
|
_test
|
||||||
|
|
||||||
|
# Architecture specific extensions/prefixes
|
||||||
|
*.[568vq]
|
||||||
|
[568vq].out
|
||||||
|
|
||||||
|
*.cgo1.go
|
||||||
|
*.cgo2.c
|
||||||
|
_cgo_defun.c
|
||||||
|
_cgo_gotypes.go
|
||||||
|
_cgo_export.*
|
||||||
|
|
||||||
|
_testmain.go
|
||||||
|
|
||||||
|
workreportmgr
|
||||||
|
*.exe
|
||||||
|
*.test
|
|
@ -0,0 +1,49 @@
|
||||||
|
package latex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"github.com/nicksnyder/go-i18n/i18n"
|
||||||
|
|
||||||
|
"git.dekart811.net/icedream/workreportmgr/project"
|
||||||
|
)
|
||||||
|
|
||||||
|
// TexMarker represents information about a TeX document to be read in by the
|
||||||
|
// respective compiler. It contains information for example about which TeX
|
||||||
|
// variant to use.
|
||||||
|
type TexMarker struct {
|
||||||
|
Program string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Exporter provides functionality to export a workreports project to a LaTeX
|
||||||
|
// file.
|
||||||
|
type Exporter struct {
|
||||||
|
Locale string
|
||||||
|
Inputs []string
|
||||||
|
Marker TexMarker
|
||||||
|
}
|
||||||
|
|
||||||
|
// Export generates LaTeX code from the given project and writes it to the given
|
||||||
|
// writer.
|
||||||
|
func (e *Exporter) Export(prj *project.Project, w io.Writer) (err error) {
|
||||||
|
T, err := i18n.Tfunc(e.Locale)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
exportTemplate.Funcs(template.FuncMap{
|
||||||
|
"T": T,
|
||||||
|
})
|
||||||
|
|
||||||
|
data := struct {
|
||||||
|
Project *project.Project
|
||||||
|
TexMarker TexMarker
|
||||||
|
TexInputs []string
|
||||||
|
}{
|
||||||
|
Project: prj,
|
||||||
|
TexInputs: e.Inputs,
|
||||||
|
TexMarker: e.Marker,
|
||||||
|
}
|
||||||
|
return exportTemplate.Execute(w, data)
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
package latex
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
initLocalization()
|
||||||
|
initTemplate()
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package latex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
|
||||||
|
"github.com/nicksnyder/go-i18n/i18n"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate go-bindata -pkg latex -o localization_assets.go localization/
|
||||||
|
|
||||||
|
func initLocalization() {
|
||||||
|
log.Println("Initializing localization for LaTeX export...")
|
||||||
|
|
||||||
|
files, err := AssetDir("localization")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed to browse embedded asset directory.", err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, file := range files {
|
||||||
|
if localizationBytes, err := Asset("localization/" + file); err != nil {
|
||||||
|
log.Fatal("Failed to read localization file.", err)
|
||||||
|
panic(err)
|
||||||
|
} else if err := i18n.ParseTranslationFileBytes(file, localizationBytes); err != nil {
|
||||||
|
log.Fatal("Failed to parse localization file.", err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "calendar_week",
|
||||||
|
"translation": "Kalenderwoche"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "calendar_week_short",
|
||||||
|
"translation": "KW"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "department",
|
||||||
|
"translation": "Abteilung"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "instructor",
|
||||||
|
"translation": "Ausbilder/in"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "legal_representative",
|
||||||
|
"translation": "Gesetzlicher Vertreter"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "name",
|
||||||
|
"translation": "Name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "no_school_periods_this_week",
|
||||||
|
"translation": "Hat in dieser Woche noch nicht stattgefunden."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "operational_activities",
|
||||||
|
"translation": "Betriebliche Tätigkeiten"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "operational_instruction",
|
||||||
|
"translation": "Betrieblicher Unterricht"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "professional_school",
|
||||||
|
"translation": "Berufsschule"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "proof_of_education",
|
||||||
|
"translation": "Ausbildungsnachweis Nr. {{.Count}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "trainee",
|
||||||
|
"translation": "Auszubildende/r"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "time_period",
|
||||||
|
"translation": "Zeitraum"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1 @@
|
||||||
|
[]
|
|
@ -0,0 +1,54 @@
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "calendar_week",
|
||||||
|
"translation": "Calendar week"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "calendar_week_short",
|
||||||
|
"translation": "CW"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "department",
|
||||||
|
"translation": "Department"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "instructor",
|
||||||
|
"translation": "Instructor"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "legal_representative",
|
||||||
|
"translation": "Legal representative"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "name",
|
||||||
|
"translation": "Name"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "no_school_periods_this_week",
|
||||||
|
"translation": "No school periods this week."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "operational_activities",
|
||||||
|
"translation": "Operational activities"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "operational_instruction",
|
||||||
|
"translation": "Operational instruction"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "professional_school",
|
||||||
|
"translation": "Professional school"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "proof_of_education",
|
||||||
|
"translation": "Proof of Education No. {{.Count}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "trainee",
|
||||||
|
"translation": "Trainee"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "time_period",
|
||||||
|
"translation": "Time period"
|
||||||
|
}
|
||||||
|
]
|
|
@ -0,0 +1 @@
|
||||||
|
[]
|
|
@ -0,0 +1,306 @@
|
||||||
|
// Code generated by go-bindata.
|
||||||
|
// sources:
|
||||||
|
// localization/de-de.all.json
|
||||||
|
// localization/de-de.untranslated.json
|
||||||
|
// localization/en-us.all.json
|
||||||
|
// localization/en-us.untranslated.json
|
||||||
|
// DO NOT EDIT!
|
||||||
|
|
||||||
|
package latex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"compress/gzip"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||||
|
gz, err := gzip.NewReader(bytes.NewBuffer(data))
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var buf bytes.Buffer
|
||||||
|
_, err = io.Copy(&buf, gz)
|
||||||
|
clErr := gz.Close()
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Read %q: %v", name, err)
|
||||||
|
}
|
||||||
|
if clErr != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return buf.Bytes(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type asset struct {
|
||||||
|
bytes []byte
|
||||||
|
info os.FileInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
type bindataFileInfo struct {
|
||||||
|
name string
|
||||||
|
size int64
|
||||||
|
mode os.FileMode
|
||||||
|
modTime time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
func (fi bindataFileInfo) Name() string {
|
||||||
|
return fi.name
|
||||||
|
}
|
||||||
|
func (fi bindataFileInfo) Size() int64 {
|
||||||
|
return fi.size
|
||||||
|
}
|
||||||
|
func (fi bindataFileInfo) Mode() os.FileMode {
|
||||||
|
return fi.mode
|
||||||
|
}
|
||||||
|
func (fi bindataFileInfo) ModTime() time.Time {
|
||||||
|
return fi.modTime
|
||||||
|
}
|
||||||
|
func (fi bindataFileInfo) IsDir() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
func (fi bindataFileInfo) Sys() interface{} {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _localizationDeDeAllJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x84\xd2\xc1\x6a\xdb\x40\x10\x06\xe0\x73\xfc\x14\x83\xce\xc1\xb9\xf7\x96\xf6\xd0\x42\x21\xa7\xb6\x81\x96\x22\xd6\xab\x5f\xd2\x90\xf5\xac\x98\x99\x8d\x21\xc6\x6f\xd3\x37\xe9\x8b\x15\xc9\x31\xb4\x45\xeb\x9c\x77\xff\x6f\xa5\x99\xff\xc7\x86\xe8\xb8\x21\x22\x6a\xb8\x6b\xde\x51\x13\x43\x82\x74\x41\xdb\x03\xf0\xd4\xdc\x9e\x8f\x5c\x83\x58\x0a\xce\x59\xe6\x3b\x9f\x97\x3b\xd0\x43\x8e\x23\x9a\x0d\xd1\xe9\xf6\x2a\xd3\xda\x98\xd5\x6b\xd8\xe3\xba\xd0\x61\x0a\xea\x7b\x48\x2d\x78\xbf\x73\x70\x2a\x32\xac\xe7\x59\xcc\xb5\x44\xcf\x5a\xcb\x17\xdb\x71\xea\xa0\x77\x2c\xeb\x44\xc2\x10\x52\xab\x98\x14\x06\xf1\xe0\xfc\x8c\x0a\xf6\x11\x06\x7f\x49\x1c\x47\x28\x7d\x83\xba\xc2\xa1\xeb\xac\x84\x7d\x8d\x79\x98\x8f\xd6\x43\xb9\xb5\x38\xe6\x9c\xda\x09\xca\xb9\xb3\xd6\x47\xb6\x6b\x5b\xfa\x14\x9c\x58\xa8\x63\x18\x94\x1e\xe7\x5d\x91\xe4\x38\x92\x70\x1c\x9d\xcc\x83\xfb\x80\xbe\x48\x07\xd9\xae\x3f\x9a\x27\xe8\xe2\x85\xd4\x86\xe8\xfc\xcc\xce\xb0\xca\x7b\xef\xe1\xca\xd8\x2d\x33\xa0\x2f\xbf\x7f\x39\x0f\x4f\x60\x47\x65\xb8\x7f\xdb\x97\x5d\xcd\xd2\xdb\xb8\xd2\x57\x71\xa8\xce\xbf\xb1\x6e\x4f\x9a\x7b\x98\x9d\xf1\xf3\xd8\xaa\xae\x96\xde\x2c\x8e\x25\x55\x06\x3f\x69\xce\x7d\x9b\xfb\x16\x5d\x89\xe1\xca\x27\xbe\xf6\xa9\xc8\x60\x12\xe2\x78\x00\x1b\x3d\xe8\x96\x8e\xc7\xed\x87\x5c\xc4\x4f\xa7\xf5\x07\x5c\x03\x0b\x6a\x8d\xb8\x2f\xf6\x52\x96\x9e\x4a\x87\xbb\x7f\x1b\x75\x73\x11\x78\x8f\xd7\x5a\x2c\xca\xcd\xff\xc8\x77\xb0\x6b\x28\xfb\x25\xbd\xf9\xf9\x27\x00\x00\xff\xff\x2b\xa3\xd3\x89\xf5\x03\x00\x00")
|
||||||
|
|
||||||
|
func localizationDeDeAllJsonBytes() ([]byte, error) {
|
||||||
|
return bindataRead(
|
||||||
|
_localizationDeDeAllJson,
|
||||||
|
"localization/de-de.all.json",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func localizationDeDeAllJson() (*asset, error) {
|
||||||
|
bytes, err := localizationDeDeAllJsonBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := bindataFileInfo{name: "localization/de-de.all.json", size: 1013, mode: os.FileMode(436), modTime: time.Unix(1486647823, 0)}
|
||||||
|
a := &asset{bytes: bytes, info: info}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _localizationDeDeUntranslatedJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x8a\x8e\x05\x04\x00\x00\xff\xff\x29\xbb\x4c\x0d\x02\x00\x00\x00")
|
||||||
|
|
||||||
|
func localizationDeDeUntranslatedJsonBytes() ([]byte, error) {
|
||||||
|
return bindataRead(
|
||||||
|
_localizationDeDeUntranslatedJson,
|
||||||
|
"localization/de-de.untranslated.json",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func localizationDeDeUntranslatedJson() (*asset, error) {
|
||||||
|
bytes, err := localizationDeDeUntranslatedJsonBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := bindataFileInfo{name: "localization/de-de.untranslated.json", size: 2, mode: os.FileMode(436), modTime: time.Unix(1479981513, 0)}
|
||||||
|
a := &asset{bytes: bytes, info: info}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _localizationEnUsAllJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x84\x92\xc1\x4a\xc3\x40\x10\x86\xcf\xcd\x53\x0c\x39\x97\x3e\x80\xd7\xea\x41\x90\xda\x83\xe0\x41\x64\x19\x92\x89\x1d\x4c\x76\xc2\xec\xb4\x1e\x4a\xdf\x5d\x92\x6c\x69\xd0\xdd\xf4\x3c\xdf\xf7\xb5\xc9\x9f\x8f\x02\xe0\x5c\x00\x00\x94\x5c\x97\x0f\x50\x56\xd8\x92\xaf\x51\xdd\x0f\xd1\x77\xb9\x9e\x4e\xa6\xe8\x43\x8b\xc6\xe2\x07\x66\x1b\x19\x18\x99\x02\xe0\xb2\x5e\xcc\xb8\x70\x10\xb5\x5c\xec\x3d\x5d\xa8\xa9\x47\xb5\x8e\x7c\x4e\x7c\xbc\x01\xc9\x00\xfb\x60\x7a\xac\x4c\x34\x13\x78\xbe\x01\xc9\x40\x4b\x5f\xd8\x3a\xa5\x5e\x29\x90\x37\x34\x3e\x51\x26\xf5\x32\xa0\xf0\x07\x4d\x46\x3d\x76\xb9\xc8\x6e\x38\xa5\x25\x71\xa1\x3a\x88\xb4\xae\x27\x65\xa9\x83\xb3\x03\x87\xa5\x89\x76\x02\x93\x01\xd1\x80\xc1\x18\x07\xdb\xa4\x7f\x43\x7a\xd2\x51\xc7\xd6\x61\x65\x7c\x62\x63\x0a\x99\xfc\xeb\x0d\x86\x19\x7c\x37\x7c\xdd\x64\xc8\xdc\x2f\xcf\xe9\x64\xba\x57\x69\x28\x84\xa9\x3d\x3d\x6f\x26\xbb\x9f\x91\xf1\xcd\x64\x93\xd2\x38\x69\x1c\xd5\xc7\x0a\x17\xfe\xe8\x7e\x00\x41\x1a\x78\xba\x82\xb0\x93\x0d\x9c\xcf\x9b\xad\x1c\xbd\x5d\x2e\xe9\xbe\x29\xb2\xa7\xdc\x27\xf0\x16\xaf\x73\x75\x75\x35\xb9\xa3\xb8\xff\x68\xaf\xfe\xc9\xdc\x51\x9c\x7b\x0c\x14\x9f\xbf\x01\x00\x00\xff\xff\x24\x12\x73\xee\xde\x03\x00\x00")
|
||||||
|
|
||||||
|
func localizationEnUsAllJsonBytes() ([]byte, error) {
|
||||||
|
return bindataRead(
|
||||||
|
_localizationEnUsAllJson,
|
||||||
|
"localization/en-us.all.json",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func localizationEnUsAllJson() (*asset, error) {
|
||||||
|
bytes, err := localizationEnUsAllJsonBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := bindataFileInfo{name: "localization/en-us.all.json", size: 990, mode: os.FileMode(436), modTime: time.Unix(1486647790, 0)}
|
||||||
|
a := &asset{bytes: bytes, info: info}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _localizationEnUsUntranslatedJson = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x8a\x8e\x05\x04\x00\x00\xff\xff\x29\xbb\x4c\x0d\x02\x00\x00\x00")
|
||||||
|
|
||||||
|
func localizationEnUsUntranslatedJsonBytes() ([]byte, error) {
|
||||||
|
return bindataRead(
|
||||||
|
_localizationEnUsUntranslatedJson,
|
||||||
|
"localization/en-us.untranslated.json",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
func localizationEnUsUntranslatedJson() (*asset, error) {
|
||||||
|
bytes, err := localizationEnUsUntranslatedJsonBytes()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
info := bindataFileInfo{name: "localization/en-us.untranslated.json", size: 2, mode: os.FileMode(436), modTime: time.Unix(1479981513, 0)}
|
||||||
|
a := &asset{bytes: bytes, info: info}
|
||||||
|
return a, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Asset loads and returns the asset for the given name.
|
||||||
|
// It returns an error if the asset could not be found or
|
||||||
|
// could not be loaded.
|
||||||
|
func Asset(name string) ([]byte, error) {
|
||||||
|
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
|
if f, ok := _bindata[cannonicalName]; ok {
|
||||||
|
a, err := f()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("Asset %s can't read by error: %v", name, err)
|
||||||
|
}
|
||||||
|
return a.bytes, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("Asset %s not found", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// MustAsset is like Asset but panics when Asset would return an error.
|
||||||
|
// It simplifies safe initialization of global variables.
|
||||||
|
func MustAsset(name string) []byte {
|
||||||
|
a, err := Asset(name)
|
||||||
|
if err != nil {
|
||||||
|
panic("asset: Asset(" + name + "): " + err.Error())
|
||||||
|
}
|
||||||
|
|
||||||
|
return a
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssetInfo loads and returns the asset info for the given name.
|
||||||
|
// It returns an error if the asset could not be found or
|
||||||
|
// could not be loaded.
|
||||||
|
func AssetInfo(name string) (os.FileInfo, error) {
|
||||||
|
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
|
if f, ok := _bindata[cannonicalName]; ok {
|
||||||
|
a, err := f()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("AssetInfo %s can't read by error: %v", name, err)
|
||||||
|
}
|
||||||
|
return a.info, nil
|
||||||
|
}
|
||||||
|
return nil, fmt.Errorf("AssetInfo %s not found", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssetNames returns the names of the assets.
|
||||||
|
func AssetNames() []string {
|
||||||
|
names := make([]string, 0, len(_bindata))
|
||||||
|
for name := range _bindata {
|
||||||
|
names = append(names, name)
|
||||||
|
}
|
||||||
|
return names
|
||||||
|
}
|
||||||
|
|
||||||
|
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||||
|
var _bindata = map[string]func() (*asset, error){
|
||||||
|
"localization/de-de.all.json": localizationDeDeAllJson,
|
||||||
|
"localization/de-de.untranslated.json": localizationDeDeUntranslatedJson,
|
||||||
|
"localization/en-us.all.json": localizationEnUsAllJson,
|
||||||
|
"localization/en-us.untranslated.json": localizationEnUsUntranslatedJson,
|
||||||
|
}
|
||||||
|
|
||||||
|
// AssetDir returns the file names below a certain
|
||||||
|
// directory embedded in the file by go-bindata.
|
||||||
|
// For example if you run go-bindata on data/... and data contains the
|
||||||
|
// following hierarchy:
|
||||||
|
// data/
|
||||||
|
// foo.txt
|
||||||
|
// img/
|
||||||
|
// a.png
|
||||||
|
// b.png
|
||||||
|
// then AssetDir("data") would return []string{"foo.txt", "img"}
|
||||||
|
// AssetDir("data/img") would return []string{"a.png", "b.png"}
|
||||||
|
// AssetDir("foo.txt") and AssetDir("notexist") would return an error
|
||||||
|
// AssetDir("") will return []string{"data"}.
|
||||||
|
func AssetDir(name string) ([]string, error) {
|
||||||
|
node := _bintree
|
||||||
|
if len(name) != 0 {
|
||||||
|
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
|
pathList := strings.Split(cannonicalName, "/")
|
||||||
|
for _, p := range pathList {
|
||||||
|
node = node.Children[p]
|
||||||
|
if node == nil {
|
||||||
|
return nil, fmt.Errorf("Asset %s not found", name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if node.Func != nil {
|
||||||
|
return nil, fmt.Errorf("Asset %s not found", name)
|
||||||
|
}
|
||||||
|
rv := make([]string, 0, len(node.Children))
|
||||||
|
for childName := range node.Children {
|
||||||
|
rv = append(rv, childName)
|
||||||
|
}
|
||||||
|
return rv, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type bintree struct {
|
||||||
|
Func func() (*asset, error)
|
||||||
|
Children map[string]*bintree
|
||||||
|
}
|
||||||
|
var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
|
"localization": &bintree{nil, map[string]*bintree{
|
||||||
|
"de-de.all.json": &bintree{localizationDeDeAllJson, map[string]*bintree{}},
|
||||||
|
"de-de.untranslated.json": &bintree{localizationDeDeUntranslatedJson, map[string]*bintree{}},
|
||||||
|
"en-us.all.json": &bintree{localizationEnUsAllJson, map[string]*bintree{}},
|
||||||
|
"en-us.untranslated.json": &bintree{localizationEnUsUntranslatedJson, map[string]*bintree{}},
|
||||||
|
}},
|
||||||
|
}}
|
||||||
|
|
||||||
|
// RestoreAsset restores an asset under the given directory
|
||||||
|
func RestoreAsset(dir, name string) error {
|
||||||
|
data, err := Asset(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
info, err := AssetInfo(name)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RestoreAssets restores an asset under the given directory recursively
|
||||||
|
func RestoreAssets(dir, name string) error {
|
||||||
|
children, err := AssetDir(name)
|
||||||
|
// File
|
||||||
|
if err != nil {
|
||||||
|
return RestoreAsset(dir, name)
|
||||||
|
}
|
||||||
|
// Dir
|
||||||
|
for _, child := range children {
|
||||||
|
err = RestoreAssets(dir, filepath.Join(name, child))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func _filePath(dir, name string) string {
|
||||||
|
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
|
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
package stringutil
|
||||||
|
|
||||||
|
type converter interface {
|
||||||
|
Process(text string) string
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package stringutil
|
||||||
|
|
||||||
|
import "regexp"
|
||||||
|
|
||||||
|
type simpleRegexConverter struct {
|
||||||
|
regex *regexp.Regexp
|
||||||
|
replacement string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newSimpleRegexConverter(regexStr string, replacementStr string) *simpleRegexConverter {
|
||||||
|
return &simpleRegexConverter{
|
||||||
|
regex: regexp.MustCompile(regexStr),
|
||||||
|
replacement: replacementStr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conv *simpleRegexConverter) Process(text string) string {
|
||||||
|
return conv.regex.ReplaceAllString(text, conv.replacement)
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
package stringutil
|
||||||
|
|
||||||
|
import "strings"
|
||||||
|
|
||||||
|
type stringConverter struct {
|
||||||
|
old string
|
||||||
|
replacement string
|
||||||
|
}
|
||||||
|
|
||||||
|
func newStringConverter(old string, replacementStr string) *stringConverter {
|
||||||
|
return &stringConverter{
|
||||||
|
old: old,
|
||||||
|
replacement: replacementStr,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (conv *stringConverter) Process(text string) string {
|
||||||
|
return strings.Replace(text, conv.old, conv.replacement, -1)
|
||||||
|
}
|
|
@ -0,0 +1,28 @@
|
||||||
|
package stringutil
|
||||||
|
|
||||||
|
var replacements = []converter{
|
||||||
|
newStringConverter("{", "\\{"),
|
||||||
|
newStringConverter("}", "\\}"),
|
||||||
|
newStringConverter("\\", "\\textbackslash{}"),
|
||||||
|
|
||||||
|
newStringConverter("&", "\\&"),
|
||||||
|
newStringConverter("%", "\\%"),
|
||||||
|
newStringConverter("$", "\\$"),
|
||||||
|
newStringConverter("#", "\\#"),
|
||||||
|
newStringConverter("_", "\\_"),
|
||||||
|
newStringConverter("~", "\\textasciitilde{}"),
|
||||||
|
newStringConverter("^", "\\textasciicircum{}"),
|
||||||
|
newStringConverter("ß", "\\ss{}"),
|
||||||
|
|
||||||
|
newSimpleRegexConverter(`"([^"]+)"`, `\enquote{$1}`),
|
||||||
|
}
|
||||||
|
|
||||||
|
// TexEscape modifies a string so it can be safely places in a LaTeX file
|
||||||
|
// without causing any errors due to special characters.
|
||||||
|
func TexEscape(s string) string {
|
||||||
|
for _, replacer := range replacements {
|
||||||
|
s = replacer.Process(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
return s
|
||||||
|
}
|
|
@ -0,0 +1,152 @@
|
||||||
|
package latex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
"text/template"
|
||||||
|
|
||||||
|
"git.dekart811.net/icedream/workreportmgr/export/latex/stringutil"
|
||||||
|
"git.dekart811.net/icedream/workreportmgr/project"
|
||||||
|
"github.com/jinzhu/now"
|
||||||
|
"github.com/nicksnyder/go-i18n/i18n"
|
||||||
|
)
|
||||||
|
|
||||||
|
const dateFormat = "02.01.2006" // TODO - localize!
|
||||||
|
|
||||||
|
var exportTemplate = template.Must(template.
|
||||||
|
New("latex_export").
|
||||||
|
Funcs(template.FuncMap{
|
||||||
|
"T": i18n.IdentityTfunc,
|
||||||
|
"escape": stringutil.TexEscape,
|
||||||
|
"add": func(a, b int) int {
|
||||||
|
return a + b
|
||||||
|
},
|
||||||
|
"beginofweek": func(date project.Date) project.Date {
|
||||||
|
return project.Date{now.New(date.Time).BeginningOfWeek()}
|
||||||
|
},
|
||||||
|
"endofweek": func(date project.Date) project.Date {
|
||||||
|
return project.Date{now.New(date.Time).EndOfWeek()}
|
||||||
|
},
|
||||||
|
}).
|
||||||
|
Delims("<", ">").
|
||||||
|
Parse(`% !TeX
|
||||||
|
<- with .TexMarker.Program> program = <.><end>
|
||||||
|
|
||||||
|
\documentclass[11pt,a4paper,oneside]{article}
|
||||||
|
|
||||||
|
\usepackage{fancyhdr}
|
||||||
|
\usepackage{tabularx}
|
||||||
|
\usepackage[left=2cm,right=2cm,top=2cm,bottom=6cm,includeheadfoot]{geometry}
|
||||||
|
\usepackage{csquotes}
|
||||||
|
\usepackage{fontspec}
|
||||||
|
\usepackage{ifluatex}
|
||||||
|
\ifluatex
|
||||||
|
\else
|
||||||
|
\usepackage[utf8]{inputenc}
|
||||||
|
\fi
|
||||||
|
|
||||||
|
\pagestyle{fancy}
|
||||||
|
\fancyhf{}
|
||||||
|
\setlength{\headheight}{2cm}
|
||||||
|
|
||||||
|
\newcommand{\Name}{<.Project.Name>}
|
||||||
|
\newcommand{\Department}{<.Project.Department>}
|
||||||
|
|
||||||
|
\newcommand{\wrSigningField}[0]{
|
||||||
|
\begin{tabularx}{\textwidth}{| X | X | X |}
|
||||||
|
\hline
|
||||||
|
<T "trainee"> &
|
||||||
|
<T "legal_representative"> &
|
||||||
|
<T "instructor"> \\[2cm]
|
||||||
|
\hline
|
||||||
|
\end{tabularx}
|
||||||
|
}
|
||||||
|
|
||||||
|
\newenvironment{weeklyreport}{
|
||||||
|
}{
|
||||||
|
\fancyfoot[C]{\wrSigningField}
|
||||||
|
}
|
||||||
|
|
||||||
|
\newcommand{\preweeklyreporthead}[3]{}
|
||||||
|
|
||||||
|
\newcommand{\weeklyreporthead}[3]{
|
||||||
|
\preweeklyreporthead{#1}{#2}{#3}
|
||||||
|
\fancyhead[R]{
|
||||||
|
\begin{tabularx}{8cm}{rl}
|
||||||
|
\textbf{<T "name">}: & \Name \\
|
||||||
|
\textbf{<T "department">}: & \Department \\
|
||||||
|
\textbf{<T "time_period">}: & #2 - #3 \\
|
||||||
|
\end{tabularx}
|
||||||
|
}
|
||||||
|
\fancyfoot{}
|
||||||
|
\newpage
|
||||||
|
\setcounter{section}{#1}
|
||||||
|
\setcounter{subsection}{0}
|
||||||
|
\section*{<T "proof_of_education" "#1">}
|
||||||
|
\addcontentsline{toc}{section}{<T "proof_of_education" "#1">}
|
||||||
|
}
|
||||||
|
|
||||||
|
\newcommand{\weeklyreportsection}[1]{
|
||||||
|
\subsection*{#1}
|
||||||
|
}
|
||||||
|
|
||||||
|
<with .TexInputs>
|
||||||
|
<range .>
|
||||||
|
\input{<.>}
|
||||||
|
<end>
|
||||||
|
<end>
|
||||||
|
|
||||||
|
\begin{document}
|
||||||
|
\tableofcontents
|
||||||
|
|
||||||
|
<range $index, $week := .Project.Weeks>
|
||||||
|
\begin{weeklyreport}
|
||||||
|
\weeklyreporthead{<add $index 1>}{<beginofweek $week.Date>}{<endofweek $week.Date>}
|
||||||
|
|
||||||
|
\weeklyreportsection{<T "operational_activities">}
|
||||||
|
<with $week.WorkActivities>
|
||||||
|
\begin{itemize}
|
||||||
|
<range .>
|
||||||
|
\item <. | escape>
|
||||||
|
<end>
|
||||||
|
\end{itemize}
|
||||||
|
<end>
|
||||||
|
|
||||||
|
\weeklyreportsection{<T "operational_instruction">}
|
||||||
|
<$week.WorkActivityDetails | escape>
|
||||||
|
|
||||||
|
\weeklyreportsection{<T "professional_school">}
|
||||||
|
<if eq (len $week.Periods) 0>
|
||||||
|
<T "no_school_periods_this_week" | escape>
|
||||||
|
<else>
|
||||||
|
\begin{itemize}
|
||||||
|
<range $week.Periods>
|
||||||
|
\item{
|
||||||
|
<- .Subject | escape ->
|
||||||
|
<- with .Topics ->:
|
||||||
|
<range $index, $topic := . ->
|
||||||
|
<- if ne $index 0 ->, <end -><- $topic | escape ->
|
||||||
|
<- end ->
|
||||||
|
<- end ->
|
||||||
|
}
|
||||||
|
<end>
|
||||||
|
\end{itemize}
|
||||||
|
<end>
|
||||||
|
|
||||||
|
\end{weeklyreport}
|
||||||
|
<end>
|
||||||
|
|
||||||
|
\end{document}
|
||||||
|
`))
|
||||||
|
|
||||||
|
func initTemplate() {
|
||||||
|
log.Println("Initializing template for LaTeX export...")
|
||||||
|
|
||||||
|
var err error
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Failed at initializing template.", err)
|
||||||
|
os.Exit(0xFF)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
}
|
|
@ -0,0 +1,105 @@
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"git.dekart811.net/icedream/workreportmgr/export/latex"
|
||||||
|
"git.dekart811.net/icedream/workreportmgr/project"
|
||||||
|
|
||||||
|
"github.com/alecthomas/kingpin"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
cli = kingpin.New("workreport-manager", "Manage all of your workreports through an easy to read and manage format.")
|
||||||
|
|
||||||
|
flagProjectFile = cli.Flag("file", "Defines the project filename from which to parse all workreports.").Short('f').Default("workreports.yml").File()
|
||||||
|
flagVerbose = cli.Flag("verbose", "Print extra information about what's happening.").Short('v').Bool()
|
||||||
|
flagLocale = cli.Flag("locale", "The locale to use for exports.").Default("en-US").String()
|
||||||
|
|
||||||
|
cmdInit = cli.Command("init", "Creates a new workreports project file.")
|
||||||
|
|
||||||
|
cmdAdd = cli.Command("add", "Add new information to the workreport.")
|
||||||
|
|
||||||
|
cmdAddActivity = cmdAdd.Command("activity", "Adds a new work activity to the workreport for the current date.")
|
||||||
|
|
||||||
|
cmdAddPeriod = cmdAdd.Command("period", "Adds a new school period to the workreport for the current date.")
|
||||||
|
|
||||||
|
cmdAddActivityDetails = cmdAdd.Command("details", "Sets the detail information for a work activity for the current date.")
|
||||||
|
cmdAddActivityDetailsFlagInput = cmdAddActivityDetails.Flag("input", "The file from which to read the information. Defaults to stdin.").Short('i').Default(os.Stdin.Name()).ExistingFile()
|
||||||
|
|
||||||
|
cmdExportToLatex = cli.Command("latex", "Exports the current workreport project to Latex.")
|
||||||
|
cmdExportToLatexFlagOutput = cmdExportToLatex.Flag("output", "The file to write the generated code to. Defaults to stdout.").Short('o').Default(os.Stdout.Name()).String()
|
||||||
|
cmdExportToLatexFlagInput = cmdExportToLatex.Flag("input", "Use this to write additional \\input statements in the resulting LaTeX file.").Short('i').Strings()
|
||||||
|
cmdExportToLatexFlagProgram = cmdExportToLatex.Flag("program", "The LaTeX compiler program to use, for example \"lualatex\". Leave empty if you don't know what to put here.").Short('p').String()
|
||||||
|
|
||||||
|
version = "master"
|
||||||
|
|
||||||
|
currentProject *project.Project
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
cli.Version(version)
|
||||||
|
if *flagVerbose {
|
||||||
|
log.Printf("%s v%s", cli.Name, version)
|
||||||
|
}
|
||||||
|
|
||||||
|
command := kingpin.MustParse(cli.Parse(os.Args[1:]))
|
||||||
|
|
||||||
|
switch command {
|
||||||
|
case cmdInit.FullCommand():
|
||||||
|
log.Println("Not yet implemented") // TODO
|
||||||
|
case cmdAddActivity.FullCommand():
|
||||||
|
log.Println("Not yet implemented") // TODO
|
||||||
|
case cmdAddActivityDetails.FullCommand():
|
||||||
|
log.Println("Not yet implemented") // TODO
|
||||||
|
case cmdAddPeriod.FullCommand():
|
||||||
|
log.Println("Not yet implemented") // TODO
|
||||||
|
case cmdExportToLatex.FullCommand():
|
||||||
|
parseProject()
|
||||||
|
if *flagVerbose {
|
||||||
|
log.Println("Going to export to Latex file...")
|
||||||
|
}
|
||||||
|
w, err := os.Create(*cmdExportToLatexFlagOutput)
|
||||||
|
if err != nil {
|
||||||
|
log.Print("Failed to create output file.")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
log.Println("Created output file.")
|
||||||
|
defer w.Close()
|
||||||
|
exporter := new(latex.Exporter)
|
||||||
|
if flagLocale != nil {
|
||||||
|
exporter.Locale = *flagLocale
|
||||||
|
}
|
||||||
|
if cmdExportToLatexFlagInput != nil {
|
||||||
|
exporter.Inputs = *cmdExportToLatexFlagInput
|
||||||
|
}
|
||||||
|
if cmdExportToLatexFlagProgram != nil {
|
||||||
|
exporter.Marker.Program = *cmdExportToLatexFlagProgram
|
||||||
|
}
|
||||||
|
log.Println("Now exporting...")
|
||||||
|
if err := exporter.Export(currentProject, w); err != nil {
|
||||||
|
log.Print("Failed to generate LaTeX output:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
log.Println("Done.")
|
||||||
|
default:
|
||||||
|
log.Println("Unknown command.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseProject() {
|
||||||
|
var err error
|
||||||
|
defer func() {
|
||||||
|
if err != nil {
|
||||||
|
log.Print("Failed to parse project file:", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
currentProject, err = project.DecodeFromFile(*flagProjectFile)
|
||||||
|
if *flagVerbose {
|
||||||
|
log.Println("Parsed project file successfully.")
|
||||||
|
log.Printf("Resulting project: %+v", currentProject)
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package project
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
)
|
||||||
|
|
||||||
|
const dateFormat = "2006-01-02"
|
||||||
|
|
||||||
|
// Date is a wrapper around time.Time with a different UnmarshalJSON
|
||||||
|
// implementation that parses just date information.
|
||||||
|
type Date struct {
|
||||||
|
time.Time
|
||||||
|
}
|
||||||
|
|
||||||
|
// UnmarshalJSON takes the given buffer and translates it into a proper
|
||||||
|
// time.Time object.
|
||||||
|
func (t *Date) UnmarshalJSON(buf []byte) (err error) {
|
||||||
|
tt, err := time.Parse(dateFormat, strings.Trim(string(buf), `"`))
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
t.Time = tt
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (t Date) String() string {
|
||||||
|
// TODO - Localize date!
|
||||||
|
return fmt.Sprintf("%02d.%02d.%04d", t.Time.Day(), t.Time.Month(), t.Time.Year())
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package project_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.dekart811.net/icedream/workreportmgr/project"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDate_String(t *testing.T) {
|
||||||
|
date := project.Date{time.Date(2016, 8, 22, 11, 22, 33, 97, time.Local)}
|
||||||
|
require.Equal(t, "22.08.2016", date.String())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDate_UnmarshalJSON_Quotes(t *testing.T) {
|
||||||
|
date := project.Date{}
|
||||||
|
require.Nil(t, date.UnmarshalJSON([]byte(`"2016-08-22"`)))
|
||||||
|
require.Equal(t, 2016, date.Time.Year())
|
||||||
|
require.Equal(t, time.Month(8), date.Time.Month())
|
||||||
|
require.Equal(t, 22, date.Time.Day())
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDate_UnmarshalJSON_NoQuotes(t *testing.T) {
|
||||||
|
date := project.Date{}
|
||||||
|
require.Nil(t, date.UnmarshalJSON([]byte(`2016-08-22`)))
|
||||||
|
require.Equal(t, 2016, date.Time.Year())
|
||||||
|
require.Equal(t, time.Month(8), date.Time.Month())
|
||||||
|
require.Equal(t, 22, date.Time.Day())
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package project
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestDate_dateFormat(t *testing.T) {
|
||||||
|
date, err := time.Parse(dateFormat, "2013-04-05")
|
||||||
|
require.Nil(t, err)
|
||||||
|
require.Equal(t, 2013, date.Year())
|
||||||
|
require.Equal(t, time.Month(4), date.Month())
|
||||||
|
require.Equal(t, 5, date.Day())
|
||||||
|
}
|
|
@ -0,0 +1,40 @@
|
||||||
|
package project
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/ghodss/yaml"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Marshal takes the data from this Project instance and turns it into a YAML
|
||||||
|
// text that is easy to read and can easily be decoded with Unmarshal or Decode.
|
||||||
|
func (prj Project) Marshal() ([]byte, error) {
|
||||||
|
return yaml.Marshal(prj)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unmarshal decodes project information from a given YAML text blob into this
|
||||||
|
// Project instance.
|
||||||
|
func (prj *Project) Unmarshal(yamlData []byte) error {
|
||||||
|
return yaml.Unmarshal(yamlData, prj)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Decode decodes project information from a given YAML text blob into a new
|
||||||
|
// instance of Project.
|
||||||
|
func Decode(yamlData []byte) (prj *Project, err error) {
|
||||||
|
prj = new(Project)
|
||||||
|
if err = prj.Unmarshal(yamlData); err != nil {
|
||||||
|
prj = nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// DecodeFromFile decodes project information from a given file into a new
|
||||||
|
// instance of Project.
|
||||||
|
func DecodeFromFile(file *os.File) (prj *Project, err error) {
|
||||||
|
contents, err := ioutil.ReadAll(file)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
return Decode(contents)
|
||||||
|
}
|
|
@ -0,0 +1,10 @@
|
||||||
|
package project
|
||||||
|
|
||||||
|
// Project represents the root structure of a project file.
|
||||||
|
type Project struct {
|
||||||
|
Name string `json:"Name"`
|
||||||
|
Department string `json:"Department"`
|
||||||
|
Begin Date `json:"Begin"`
|
||||||
|
End Date `json:"End"`
|
||||||
|
Weeks []Week `json:"Weeks"`
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package project
|
||||||
|
|
||||||
|
// Period represents a school period in the weekly report.
|
||||||
|
type Period struct {
|
||||||
|
Subject string `json:"Subject"`
|
||||||
|
Topics []string `json:"Topics"`
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
package project
|
||||||
|
|
||||||
|
// Week represents a week in the report.
|
||||||
|
type Week struct {
|
||||||
|
Date Date
|
||||||
|
WorkActivities []string `json:"Operational activities"`
|
||||||
|
WorkActivityDetails string `json:"Operational instructions"`
|
||||||
|
Periods []Period `json:"Professional school"`
|
||||||
|
}
|
Loading…
Reference in New Issue