ソースを参照

Working on funcmap

Andrea Fazzi 5 年 前
コミット
3275f70a54

+ 33 - 0
generator/funcmap/funcmap.go

@@ -2,6 +2,7 @@ package funcmap
 
 
 import (
 import (
 	"fmt"
 	"fmt"
+	"sort"
 	"strings"
 	"strings"
 	"text/template"
 	"text/template"
 
 
@@ -9,6 +10,10 @@ import (
 	"gogs.carducci-dante.gov.it/karmen/core/orm"
 	"gogs.carducci-dante.gov.it/karmen/core/orm"
 )
 )
 
 
+type Stringer interface {
+	String() string
+}
+
 var FuncMap template.FuncMap = template.FuncMap{
 var FuncMap template.FuncMap = template.FuncMap{
 	"comma":        comma,
 	"comma":        comma,
 	"groupClasses": groupClasses,
 	"groupClasses": groupClasses,
@@ -16,6 +21,34 @@ var FuncMap template.FuncMap = template.FuncMap{
 	"nbsp":         nbsp,
 	"nbsp":         nbsp,
 	"globFilter":   globFilter,
 	"globFilter":   globFilter,
 	"toUpper":      toUpper,
 	"toUpper":      toUpper,
+	"order":        order,
+	"stringSlice":  stringSlice,
+}
+
+func order(items []string) []string {
+	sort.Strings(items)
+
+	return items
+}
+
+func stringSlice(items interface{}) []string {
+	// var (
+	// 	interfaces []interface{}
+	// 	result     []string
+	// )
+
+	// val := reflect.ValueOf(items)
+	// interfaces = make([]interface{}, val.Len())
+
+	// for i := 0; i < val.Len(); i++ {
+	// 	interfaces = append(interfaces, items[i])
+	// }
+	// for _, i := range interfaces {
+	// 	result = append(result, i.(Stringer).String())
+	// }
+
+	//	return result
+	return []string{}
 }
 }
 
 
 func toUpper(content string) string {
 func toUpper(content string) string {

+ 41 - 0
generator/generator.go

@@ -0,0 +1,41 @@
+package generator
+
+import (
+	"io/ioutil"
+
+	"gogs.carducci-dante.gov.it/karmen/core/config"
+	"gopkg.in/yaml.v2"
+)
+
+type Generator interface {
+	Run()
+	SetJobId(id uint)
+}
+
+type Config struct {
+	config.ConfigT
+
+	KeepArtifacts bool   `yaml:"keep_artifacts"`
+	OutputPath    string `yaml:"output_path"`
+	CloudPath     string `yaml:"cloud_path"`
+}
+
+var (
+	Generators map[string]Generator
+)
+
+// ReadFile reads the config file placed at the given path.
+func ReadFile(path string, conf *Config) error {
+	err := config.ReadFile(path, &conf.ConfigT)
+	if err != nil {
+		return err
+	}
+	cf, err := ioutil.ReadFile(path)
+	if err != nil {
+		return err
+	}
+	if err := yaml.Unmarshal(cf, conf); err != nil {
+		return err
+	}
+	return nil
+}

+ 0 - 10
generator/generators.go

@@ -1,10 +0,0 @@
-package generator
-
-type Generator interface {
-	Run()
-	SetJobId(id uint)
-}
-
-var (
-	Generators map[string]Generator
-)

+ 212 - 0
generator/generators/department/department.go

@@ -0,0 +1,212 @@
+package department
+
+import (
+	"fmt"
+	"io/ioutil"
+	"log"
+	"os"
+	"path/filepath"
+	"sync"
+	"text/template"
+	"time"
+
+	"github.com/remogatto/cloud"
+
+	karmen_client "gogs.carducci-dante.gov.it/karmen/client"
+	"gogs.carducci-dante.gov.it/karmen/core/generator"
+	"gogs.carducci-dante.gov.it/karmen/core/generator/funcmap"
+	"gogs.carducci-dante.gov.it/karmen/core/generator/logger"
+	"gogs.carducci-dante.gov.it/karmen/core/orm"
+	"gogs.carducci-dante.gov.it/karmen/util/fileutil"
+	"gogs.carducci-dante.gov.it/karmen/util/libreoffice"
+	"gogs.carducci-dante.gov.it/karmen/util/pandoc"
+	tpl_util "gogs.carducci-dante.gov.it/karmen/util/template"
+)
+
+type Data struct {
+	Departments []*orm.Department
+}
+
+type DepartmentGenerator struct {
+	sync.Mutex
+	Config *generator.Config
+
+	JobID uint
+
+	Data *Data
+
+	ncClient *cloud.Client
+	kaClient *karmen_client.Client
+	logger   *logger.JobLogger
+}
+
+func (generator *DepartmentGenerator) generate(outputPath string, cloudPath string, funcMap template.FuncMap) {
+	tplFilename := filepath.Join(cloudPath, "template.md")
+	log.Printf("Downloading %s from the cloud...", tplFilename)
+
+	tplContent, err := generator.ncClient.Download(tplFilename)
+	if err != nil {
+		log.Println(err)
+	}
+	log.Println("Download completed.")
+
+	refFilename := filepath.Join(cloudPath, "reference.odt")
+	log.Printf("Downloading %s from the cloud...", tplFilename)
+	refContent, err := generator.ncClient.Download(refFilename)
+	if err != nil {
+		log.Println(err)
+	}
+	log.Println("Download completed.")
+
+	err = ioutil.WriteFile(filepath.Join(outputPath, "reference.odt"), refContent, 0777)
+	if err != nil {
+		log.Println(err)
+	}
+
+	tpl, err := tpl_util.LoadTextTemplateFromString(string(tplContent), funcMap)
+	if err != nil {
+		log.Println(err)
+	}
+
+	for _, department := range generator.Data.Departments {
+		filename := filepath.Join(outputPath, fmt.Sprintf("Dipartimento di %s", department.Name))
+		f, err := os.Create(filename + ".md")
+		if err != nil {
+			log.Println(err)
+		}
+		defer f.Close()
+
+		err = tpl.Execute(f, department)
+		if err != nil {
+			log.Println(err)
+		}
+
+		odtFilename := fileutil.ReplaceExt(filename, "odt")
+
+		log.Println("Generate", odtFilename)
+
+		if err := pandoc.Convert(filename+".md", odtFilename, "--data-dir", outputPath); err != nil {
+			log.Println(outputPath, err)
+		}
+
+		if err := libreoffice.Convert(filename+".odt", "pdf", "--outdir", outputPath); err != nil {
+			log.Println(err)
+		}
+	}
+
+}
+
+func NewDepartmentGenerator(config *generator.Config) *DepartmentGenerator {
+	return &DepartmentGenerator{
+		Config: config,
+		Data:   new(Data),
+	}
+}
+
+func (generator *DepartmentGenerator) SetJobId(id uint) {
+	generator.Lock()
+	generator.JobID = id
+	generator.Unlock()
+}
+
+func (generator *DepartmentGenerator) Run() {
+	var err error
+
+	log.Printf("Connecting to the cloud...")
+	generator.ncClient, err = cloud.Dial(
+		generator.Config.Cloud.Url,
+		generator.Config.Cloud.Username,
+		generator.Config.Cloud.Password,
+	)
+	if err != nil {
+		log.Println(err)
+	}
+
+	log.Printf("Connecting to karmen...")
+	generator.kaClient, err = karmen_client.Dial(
+		generator.Config.Url,
+		generator.Config.Admin.Username,
+		generator.Config.Admin.Password,
+	)
+	if err != nil {
+		log.Println(err)
+	}
+
+	var job *orm.Job
+
+	if generator.JobID > 0 {
+		job, err = generator.kaClient.GetJob(generator.JobID)
+		if err != nil {
+			log.Println(err)
+		}
+
+		generator.logger = logger.NewJobLogger(job)
+		log.SetOutput(generator.logger)
+
+		job.Start = time.Now()
+		err = generator.kaClient.UpdateJob(job)
+		if err != nil {
+			log.Println(err)
+		}
+	}
+
+	generator.Data.Departments, err = generator.kaClient.GetDepartments()
+	if err != nil {
+		log.Println(err)
+	}
+
+	var (
+		outputPath string
+		cloudPath  string
+	)
+
+	if job != nil {
+		outputPath = filepath.Join(generator.Config.Documents.OutputPath, fmt.Sprintf("%d/%d", job.DocumentID, job.ID))
+		cloudPath = job.Document.CloudPath
+	} else {
+		outputPath = generator.Config.OutputPath
+		cloudPath = generator.Config.CloudPath
+	}
+
+	log.Println("Output dir", outputPath)
+
+	if err := os.MkdirAll(outputPath, 0777); err != nil {
+		log.Println(err)
+	}
+
+	generator.generate(outputPath, cloudPath, funcmap.FuncMap)
+
+	if generator.JobID > 0 {
+		job.End = time.Now()
+
+		job.Files = append(job.Files, &orm.File{Path: "elenco_docenti.pdf"})
+
+		err = generator.kaClient.UpdateJob(job)
+		if err != nil {
+			log.Println(err)
+		}
+	}
+
+	var keepArtifacts bool
+
+	if job != nil {
+		keepArtifacts = job.Document.KeepArtifacts
+	} else {
+		keepArtifacts = generator.Config.KeepArtifacts
+	}
+
+	if !keepArtifacts {
+		log.Println("Uploading resulting files to the cloud...")
+		_, err = generator.ncClient.UploadDir(filepath.Join(outputPath, "*.pdf"), cloudPath)
+		if err != nil {
+			log.Println(err)
+		}
+	} else {
+		log.Println("Uploading resulting files and artifacts to the cloud...")
+		_, err = generator.ncClient.UploadDir(filepath.Join(outputPath, "*"), cloudPath)
+		if err != nil {
+			log.Println(err)
+		}
+	}
+	log.Println("Files were uploaded to the cloud...")
+}

+ 19 - 0
generator/generators/department/example_1/config.yaml

@@ -0,0 +1,19 @@
+document_name: "Elenco docenti"
+cloud_path: "Documents/Example 1"
+output_path: "output"
+keep_artifacts: true
+url: "http://localhost:3000"
+domain: "foo.org"
+log_level: 2
+
+admin:
+  username: admin
+  password: admin
+  
+cloud:
+  username: admin
+  password: password
+  url: "http://localhost:8080/remote.php/webdav/"
+  
+documents:
+  output_path: "output"

BIN
generator/generators/department/example_1/example_1


+ 47 - 0
generator/generators/department/example_1/main.go

@@ -0,0 +1,47 @@
+package main
+
+import (
+	"log"
+
+	"github.com/remogatto/cloud"
+	"gogs.carducci-dante.gov.it/karmen/core/generator"
+	"gogs.carducci-dante.gov.it/karmen/core/generator/generators/department"
+)
+
+func main() {
+	conf := new(generator.Config)
+
+	err := generator.ReadFile("config.yaml", conf)
+	if err != nil {
+		panic(err)
+	}
+
+	log.Printf("Connecting to the cloud...")
+	client, err := cloud.Dial(
+		conf.Cloud.Url,
+		conf.Cloud.Username,
+		conf.Cloud.Password,
+	)
+	if err != nil {
+		log.Println(err)
+	}
+
+	err = client.Mkdir("Documents/Example 1")
+	if err != nil {
+		panic(err)
+
+	}
+
+	// Upload resources on the cloud
+
+	if files, err := client.UploadDir("resources/*", "Documents/Example 1"); err != nil {
+		panic(err)
+	} else {
+		for _, file := range files {
+			log.Println(file, " was uploaded.")
+		}
+	}
+
+	gen := department.NewDepartmentGenerator(conf)
+	gen.Run()
+}

+ 11 - 0
generator/generators/department/example_1/output/Dipartimento di LINGUE STRANIERE.md

@@ -0,0 +1,11 @@
+# I.S.I.S. “GIOSUE’ CARDUCCI – DANTE ALIGHIERI”
+# Liceo Classico; Liceo Linguistico; Liceo Musicale
+# Liceo delle Scienze Umane; delle Scienze Umane opzione Economico Sociale;
+# 34133 TRIESTE - Via Giustiniano, 3
+# A.S.  2019/2020
+
+## Dipartimento di LINGUE STRANIERE
+
+### Materie afferenti al dipartimento
+
+* FRANCESE

BIN
generator/generators/department/example_1/output/Dipartimento di LINGUE STRANIERE.odt


BIN
generator/generators/department/example_1/output/Dipartimento di LINGUE STRANIERE.pdf


+ 11 - 0
generator/generators/department/example_1/output/Dipartimento di SOSTEGNO.md

@@ -0,0 +1,11 @@
+# I.S.I.S. “GIOSUE’ CARDUCCI – DANTE ALIGHIERI”
+# Liceo Classico; Liceo Linguistico; Liceo Musicale
+# Liceo delle Scienze Umane; delle Scienze Umane opzione Economico Sociale;
+# 34133 TRIESTE - Via Giustiniano, 3
+# A.S.  2019/2020
+
+## Dipartimento di SOSTEGNO
+
+### Materie afferenti al dipartimento
+
+* SOSTEGNO

BIN
generator/generators/department/example_1/output/Dipartimento di SOSTEGNO.odt


BIN
generator/generators/department/example_1/output/Dipartimento di SOSTEGNO.pdf


BIN
generator/generators/department/example_1/output/reference.odt


+ 0 - 0
generator/generators/department/example_1/reference.odt


BIN
generator/generators/department/example_1/resources/reference.odt


+ 19 - 0
generator/generators/department/example_1/resources/template.md

@@ -0,0 +1,19 @@
+# I.S.I.S. “GIOSUE’ CARDUCCI – DANTE ALIGHIERI”
+# Liceo Classico; Liceo Linguistico; Liceo Musicale
+# Liceo delle Scienze Umane; delle Scienze Umane opzione Economico Sociale;
+# 34133 TRIESTE - Via Giustiniano, 3
+# A.S.  2019/2020
+
+## Dipartimento di {{.Name}}
+
+### Materie afferenti al dipartimento
+
+{{range $subject := .Subjects -}}
+* {{$subject.Name}}
+{{range $teacher := ($.Teachers | stringSlice | order)}}
+  * prof./prof.ssa {{$teacher}}
+{{end}}
+{{- end}}
+
+Il coordinatore del Dipartimento è il/la prof./prof.ssa **{{.Coordinator.CompleteName}}**.
+

+ 26 - 0
generator/logger/logger.go

@@ -0,0 +1,26 @@
+package logger
+
+import (
+	"os"
+
+	"gogs.carducci-dante.gov.it/karmen/core/orm"
+)
+
+type JobLogger struct {
+	job *orm.Job
+}
+
+func NewJobLogger(job *orm.Job) *JobLogger {
+	return &JobLogger{job}
+}
+
+func (l *JobLogger) Write(p []byte) (n int, err error) {
+	os.Stdout.Write(p)
+	origLen := len(p)
+	if len(p) > 0 && p[len(p)-1] == '\n' {
+		p = p[:len(p)-1] // Cut terminating newline
+	}
+	l.job.Logs = append(l.job.Logs, &orm.Log{Content: string(p)})
+
+	return origLen, nil
+}

+ 6 - 0
main.go

@@ -15,6 +15,7 @@ import (
 	"gogs.carducci-dante.gov.it/karmen/core/config"
 	"gogs.carducci-dante.gov.it/karmen/core/config"
 	"gogs.carducci-dante.gov.it/karmen/core/cron/sync"
 	"gogs.carducci-dante.gov.it/karmen/core/cron/sync"
 	"gogs.carducci-dante.gov.it/karmen/core/generator"
 	"gogs.carducci-dante.gov.it/karmen/core/generator"
+	"gogs.carducci-dante.gov.it/karmen/core/generator/generators/department"
 	"gogs.carducci-dante.gov.it/karmen/core/generator/generators/list"
 	"gogs.carducci-dante.gov.it/karmen/core/generator/generators/list"
 	karmen_handlers "gogs.carducci-dante.gov.it/karmen/core/handlers"
 	karmen_handlers "gogs.carducci-dante.gov.it/karmen/core/handlers"
 	"gogs.carducci-dante.gov.it/karmen/core/orm"
 	"gogs.carducci-dante.gov.it/karmen/core/orm"
@@ -67,6 +68,11 @@ func main() {
 	generator.Generators = make(map[string]generator.Generator)
 	generator.Generators = make(map[string]generator.Generator)
 	generator.Generators["list"] = list.NewListGenerator(config.Config)
 	generator.Generators["list"] = list.NewListGenerator(config.Config)
 
 
+	log.Println("Initialize DepartmentGenerator")
+
+	generator.Generators = make(map[string]generator.Generator)
+	generator.Generators["department"] = department.NewDepartmentGenerator(&generator.Config{ConfigT: *config.Config})
+
 	files, err := filepath.Glob("generator/generators/*")
 	files, err := filepath.Glob("generator/generators/*")
 	log.Println("Found the following generators...")
 	log.Println("Found the following generators...")
 	gTypes := make([]*orm.GeneratorType, 0)
 	gTypes := make([]*orm.GeneratorType, 0)

+ 1 - 4
orm/department.go

@@ -89,15 +89,12 @@ func GetDepartments(args map[string]string) (interface{}, error) {
 
 
 func GetDepartmentsAll(args map[string]string) (interface{}, error) {
 func GetDepartmentsAll(args map[string]string) (interface{}, error) {
 	var departments []*Department
 	var departments []*Department
-	if err := DB().Preload("Coordinator").Order("name").Find(&departments).Error; err != nil {
+	if err := DB().Preload("Coordinator").Preload("Subjects").Order("name").Find(&departments).Error; err != nil {
 		return nil, err
 		return nil, err
 	}
 	}
 	for _, department := range departments {
 	for _, department := range departments {
 		department.GetTeachers()
 		department.GetTeachers()
 	}
 	}
-	for _, department := range departments {
-		department.GetSubjects()
-	}
 	return departments, nil
 	return departments, nil
 }
 }
 
 

+ 4 - 0
orm/teacher.go

@@ -65,6 +65,10 @@ WHERE supply_teacher_id <> 0 ORDER BY surname,name
 
 
 func (t *Teacher) GetID() uint { return t.ID }
 func (t *Teacher) GetID() uint { return t.ID }
 
 
+func (t *Teacher) String() string {
+	return fmt.Sprintf("%s %s", t.Surname, t.Name)
+}
+
 func GetTeacher(args map[string]string) (interface{}, error) {
 func GetTeacher(args map[string]string) (interface{}, error) {
 	var teacher Teacher
 	var teacher Teacher
 	if err := DB().First(&teacher, args["id"]).Error; err != nil {
 	if err := DB().First(&teacher, args["id"]).Error; err != nil {