Browse Source

Rewrite as a multi features app

- Add a nomenclature editor to allow modifications of field surveys
object types
master
William Petit 6 months ago
parent
commit
562a677bd2

+ 8
- 8
Makefile View File

@@ -1,25 +1,25 @@
1
-build: bin/tiff-optimizer
1
+build: bin/server
2 2
 	docker build \
3 3
 		--build-arg "HTTP_PROXY=$(HTTP_PROXY)" \
4 4
 		--build-arg "HTTPS_PROXY=$(HTTPS_PROXY)" \
5 5
 		--build-arg "http_proxy=$(http_proxy)" \
6 6
 		--build-arg "https_proxy=$(https_proxy)" \
7
-		-t tiff-optimizer \
7
+		-t fieldnotes-server \
8 8
 		.
9 9
 
10 10
 run:
11 11
 	docker run \
12 12
 		--rm -it \
13 13
 		-p "3000:3000" \
14
-		tiff-optimizer:latest
14
+		fieldnotes-server:latest
15 15
 
16
-bin/tiff-optimizer:
17
-	CGO_ENABLED=0 go build -o ./bin/tiff-optimizer ./
16
+bin/server:
17
+	CGO_ENABLED=0 go build -o ./bin/server ./cmd/server
18 18
 
19
-server: bin/tiff-optimizer
20
-	./bin/tiff-optimizer
19
+server: bin/server
20
+	./bin/server
21 21
 
22 22
 watch:
23 23
 	modd
24 24
 
25
-.PHONY: bin/tiff-optimizer
25
+.PHONY: bin/server

+ 9
- 0
cmd/server/geotiff_explorer.go View File

@@ -0,0 +1,9 @@
1
+package main
2
+
3
+import "net/http"
4
+
5
+func showGeoTiffExplorerPage(w http.ResponseWriter, r *http.Request) {
6
+	if err := xt.ExecuteTemplate(w, "geotiff_explorer.html.tmpl", nil); err != nil {
7
+		panic(err)
8
+	}
9
+}

+ 9
- 0
cmd/server/home.go View File

@@ -0,0 +1,9 @@
1
+package main
2
+
3
+import "net/http"
4
+
5
+func showHomePage(w http.ResponseWriter, r *http.Request) {
6
+	if err := xt.ExecuteTemplate(w, "home.html.tmpl", nil); err != nil {
7
+		panic(err)
8
+	}
9
+}

+ 81
- 0
cmd/server/main.go View File

@@ -0,0 +1,81 @@
1
+package main
2
+
3
+import (
4
+	"flag"
5
+	"log"
6
+	"net/http"
7
+	"os"
8
+
9
+	"github.com/dannyvankooten/extemplate"
10
+
11
+	"github.com/go-chi/chi/middleware"
12
+
13
+	"github.com/go-chi/chi"
14
+)
15
+
16
+//nolint: gochecknoglobals
17
+var (
18
+	address           = ":3000"
19
+	staticDir         = "./static"
20
+	tiffDir           = "./tiff"
21
+	templateDir       = "template/"
22
+	nomenclaturesPath = "data/nomenclatures.json"
23
+	xt                = extemplate.New()
24
+)
25
+
26
+func init() { //nolint: gochecknoinits
27
+	flag.StringVar(&address, "address", address, "Server HTTP address")
28
+	flag.StringVar(&staticDir, "static", staticDir, "Static files directory")
29
+	flag.StringVar(&tiffDir, "tiff", tiffDir, "Tiff files directory")
30
+	flag.StringVar(&templateDir, "template", templateDir, "Template files directory")
31
+	flag.StringVar(&nomenclaturesPath, "nomenclature", nomenclaturesPath, "Nomenclatures file path")
32
+}
33
+
34
+func main() {
35
+
36
+	flag.Parse()
37
+
38
+	if err := os.MkdirAll(tiffDir, os.FileMode(0740)); err != nil {
39
+		panic(err)
40
+	}
41
+
42
+	if err := xt.ParseDir(templateDir, []string{".tmpl"}); err != nil {
43
+		panic(err)
44
+	}
45
+
46
+	r := chi.NewRouter()
47
+
48
+	r.Use(middleware.Logger)
49
+	r.Use(middleware.Recoverer)
50
+
51
+	r.Group(func(r chi.Router) {
52
+
53
+		r.Get("/", showHomePage)
54
+
55
+		r.Get("/geotiff-explorer", showGeoTiffExplorerPage)
56
+
57
+		r.Route("/field-surveys", func(r chi.Router) {
58
+			r.Get("/editor", showNomenclatureEditorPage)
59
+			r.Post("/nomenclatures.json", saveNomenclatures)
60
+		})
61
+
62
+		r.Route("/tiff-optimizer", func(r chi.Router) {
63
+			r.Get("/", showTiffOptimizerPage)
64
+			r.With(middleware.Throttle(1)).Post("/", uploadImage)
65
+			r.Get("/results/{ID}", downloadResult)
66
+		})
67
+
68
+		r.Get("/*", http.FileServer(http.Dir(staticDir)).ServeHTTP)
69
+
70
+	})
71
+
72
+	r.Group(func(r chi.Router) {
73
+		r.Get("/field-surveys/nomenclatures.json", downloadNomenclatures)
74
+	})
75
+
76
+	log.Printf("listening on '%s'", address)
77
+	if err := http.ListenAndServe(address, r); err != nil {
78
+		panic(err)
79
+	}
80
+
81
+}

+ 72
- 0
cmd/server/nomenclature_editor.go View File

@@ -0,0 +1,72 @@
1
+package main
2
+
3
+import (
4
+	"encoding/json"
5
+	"io/ioutil"
6
+	"net/http"
7
+
8
+	"github.com/dchest/safefile"
9
+	"github.com/qri-io/jsonschema"
10
+)
11
+
12
+const nomenclatureSchemaPath = "schema/nomenclatures.json"
13
+
14
+func showNomenclatureEditorPage(w http.ResponseWriter, r *http.Request) {
15
+	nomenclatures, err := ioutil.ReadFile(nomenclaturesPath)
16
+	if err != nil {
17
+		panic(err)
18
+	}
19
+	schema := getNomenclatureSchemaData()
20
+	data := map[string]interface{}{
21
+		"Nomenclatures": string(nomenclatures),
22
+		"Schema":        string(schema),
23
+	}
24
+	if err := xt.ExecuteTemplate(w, "nomenclature_editor.html.tmpl", data); err != nil {
25
+		panic(err)
26
+	}
27
+}
28
+
29
+func saveNomenclatures(w http.ResponseWriter, r *http.Request) {
30
+	body, err := ioutil.ReadAll(r.Body)
31
+	if err != nil {
32
+		panic(err)
33
+	}
34
+	schema := getNomenclatureSchema()
35
+	if errors, _ := schema.ValidateBytes(body); len(errors) > 0 {
36
+		panic(errors)
37
+	}
38
+
39
+	f, err := safefile.Create(nomenclaturesPath, 0644)
40
+	if err != nil {
41
+		panic(err)
42
+	}
43
+	defer f.Close()
44
+	if _, err := f.Write(body); err != nil {
45
+		panic(err)
46
+	}
47
+	if err := f.Commit(); err != nil {
48
+		panic(err)
49
+	}
50
+	w.WriteHeader(http.StatusNoContent)
51
+}
52
+
53
+func downloadNomenclatures(w http.ResponseWriter, r *http.Request) {
54
+	http.ServeFile(w, r, nomenclaturesPath)
55
+}
56
+
57
+func getNomenclatureSchemaData() []byte {
58
+	schema, err := ioutil.ReadFile(nomenclatureSchemaPath)
59
+	if err != nil {
60
+		panic(err)
61
+	}
62
+	return schema
63
+}
64
+
65
+func getNomenclatureSchema() *jsonschema.RootSchema {
66
+	data := getNomenclatureSchemaData()
67
+	rs := &jsonschema.RootSchema{}
68
+	if err := json.Unmarshal(data, rs); err != nil {
69
+		panic(err)
70
+	}
71
+	return rs
72
+}

main.go → cmd/server/tiff_optimizer.go View File

@@ -1,7 +1,6 @@
1 1
 package main
2 2
 
3 3
 import (
4
-	"flag"
5 4
 	"fmt"
6 5
 	"io"
7 6
 	"io/ioutil"
@@ -11,47 +10,14 @@ import (
11 10
 	"os/exec"
12 11
 	"path"
13 12
 
14
-	"github.com/go-chi/chi/middleware"
15
-	"github.com/pborman/uuid"
16
-
17 13
 	"github.com/go-chi/chi"
14
+	"github.com/pborman/uuid"
18 15
 )
19 16
 
20
-var (
21
-	address   string = ":3000"
22
-	staticDir string = "./static"
23
-	tiffDir   string = "./tiff"
24
-)
25
-
26
-func init() {
27
-	flag.StringVar(&address, "address", address, "Server HTTP address")
28
-	flag.StringVar(&staticDir, "static", staticDir, "Static files directory")
29
-	flag.StringVar(&tiffDir, "tiff", tiffDir, "Tiff files directory")
30
-}
31
-
32
-func main() {
33
-
34
-	flag.Parse()
35
-
36
-	if err := os.MkdirAll(tiffDir, os.FileMode(0740)); err != nil {
37
-		panic(err)
38
-	}
39
-
40
-	r := chi.NewRouter()
41
-
42
-	r.Use(middleware.Logger)
43
-	r.Use(middleware.Recoverer)
44
-	r.Use(middleware.Throttle(1))
45
-
46
-	r.Post("/", uploadImage)
47
-	r.Get("/results/{ID}", downloadResult)
48
-	r.Get("/", http.FileServer(http.Dir(staticDir)).ServeHTTP)
49
-
50
-	log.Printf("listening on '%s'", address)
51
-	if err := http.ListenAndServe(address, r); err != nil {
17
+func showTiffOptimizerPage(w http.ResponseWriter, r *http.Request) {
18
+	if err := xt.ExecuteTemplate(w, "tiff_optimizer.html.tmpl", nil); err != nil {
52 19
 		panic(err)
53 20
 	}
54
-
55 21
 }
56 22
 
57 23
 func uploadImage(w http.ResponseWriter, r *http.Request) {
@@ -95,7 +61,7 @@ func uploadImage(w http.ResponseWriter, r *http.Request) {
95 61
 		panic(err)
96 62
 	}
97 63
 
98
-	url := fmt.Sprintf("/results/%s", resultID)
64
+	url := fmt.Sprintf("/tiff-optimizer/results/%s", resultID)
99 65
 
100 66
 	http.Redirect(w, r, url, http.StatusSeeOther)
101 67
 
@@ -105,7 +71,7 @@ func downloadResult(w http.ResponseWriter, r *http.Request) {
105 71
 
106 72
 	resultID := chi.URLParam(r, "ID")
107 73
 	if resultID == "" {
108
-		http.Redirect(w, r, "/", http.StatusSeeOther)
74
+		http.Redirect(w, r, "/tiff-optimizer", http.StatusSeeOther)
109 75
 		return
110 76
 	}
111 77
 

+ 1
- 0
data/nomenclatures.json View File

@@ -0,0 +1 @@
1
+{"entities":[{"category":"energie","label":"Énergie","types":[{"label":"Réseau électrique","code":"SSL_ERDF_reseau","types":["line","curve"]},{"label":"Réseau électrique BT","code":"SSL_ERDF_reseauBTA","types":["line","curve"]},{"label":"Réseau électrique HT","code":"SSL_ERDF_reseauHTA","types":["line","curve"]},{"label":"Plaque électrique","code":"SOL_ERDF_plaque","types":["rect"]},{"label":"Réseau gaz","code":"SSL_GRDF_reseau","types":["line","curve"]},{"label":"Plaque gaz","code":"SOL_GRDF_plaque","types":["rect"]}]},{"category":"reseau_sec","label":"Réseau sec","types":[{"label":"Réseau éclairage public","code":"SSL_ECL_reseau","types":["line","curve"]},{"label":"Plaque éclairage public","code":"SSL_ECL_chambre","types":["rect"]},{"label":"Lampadaire","code":"SOL_ECL_lampad","types":["circle"]}]}]}

+ 4
- 1
go.mod View File

@@ -1,7 +1,10 @@
1
-module forge.cadoles.com/Pyxis/tiff-optimizer
1
+module forge.cadoles.com/Pyxis/fieldnotes-server
2 2
 
3 3
 require (
4
+	github.com/dannyvankooten/extemplate v0.0.0-20180818082729-efbdf6eacd7e
4 5
 	github.com/davecgh/go-spew v1.1.1
6
+	github.com/dchest/safefile v0.0.0-20151022103144-855e8d98f185
5 7
 	github.com/go-chi/chi v4.0.1+incompatible
6 8
 	github.com/pborman/uuid v1.2.0
9
+	github.com/qri-io/jsonschema v0.0.0-20190304170034-8d0aab861541
7 10
 )

+ 8
- 0
go.sum View File

@@ -1,8 +1,16 @@
1
+github.com/dannyvankooten/extemplate v0.0.0-20180818082729-efbdf6eacd7e h1:B9dlwlvX/aw7ILWxPoCQxU86UDXUxQmKlsSYGO8QNcg=
2
+github.com/dannyvankooten/extemplate v0.0.0-20180818082729-efbdf6eacd7e/go.mod h1:1OaUZ894pZUQPj/84mS9XOztabi4FFJW46+rS7KjHTo=
1 3
 github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
2 4
 github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5
+github.com/dchest/safefile v0.0.0-20151022103144-855e8d98f185 h1:3T8ZyTDp5QxTx3NU48JVb2u+75xc040fofcBaN+6jPA=
6
+github.com/dchest/safefile v0.0.0-20151022103144-855e8d98f185/go.mod h1:cFRxtTwTOJkz2x3rQUNCYKWC93yP1VKjR8NUhqFxZNU=
3 7
 github.com/go-chi/chi v4.0.1+incompatible h1:RSRC5qmFPtO90t7pTL0DBMNpZFsb/sHF3RXVlDgFisA=
4 8
 github.com/go-chi/chi v4.0.1+incompatible/go.mod h1:eB3wogJHnLi3x/kFX2A+IbTBlXxmMeXJVKy9tTv1XzQ=
5 9
 github.com/google/uuid v1.0.0 h1:b4Gk+7WdP/d3HZH8EJsZpvV7EtDOgaZLtnaNGIu1adA=
6 10
 github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
7 11
 github.com/pborman/uuid v1.2.0 h1:J7Q5mO4ysT1dv8hyrUGHb9+ooztCXu1D8MY8DZYsu3g=
8 12
 github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k=
13
+github.com/qri-io/jsonpointer v0.0.0-20190212172158-7f104febd1fd h1:A/otcrPitGkmouHBoyuvt7xFMVeGbNq2HLQGMgshdJE=
14
+github.com/qri-io/jsonpointer v0.0.0-20190212172158-7f104febd1fd/go.mod h1:DnJPaYgiKu56EuDp8TU5wFLdZIcAnb/uH9v37ZaMV64=
15
+github.com/qri-io/jsonschema v0.0.0-20190304170034-8d0aab861541 h1:03fNJCjKOTPGT0T40hX2UQ3nwq0Zqsl3wFgGwKjtUp4=
16
+github.com/qri-io/jsonschema v0.0.0-20190304170034-8d0aab861541/go.mod h1:rlnuSZCX0LfkXwEhqARuBp800hH8tKV/EtgeD3yVT8s=

+ 3
- 2
modd.conf View File

@@ -1,4 +1,5 @@
1
-**/*.go {
2
-    prep: make bin/tiff-optimizer
1
+**/*.go
2
+template/**/*.tmpl {
3
+    prep: make bin/server
3 4
     daemon: make server
4 5
 }

+ 60
- 0
schema/nomenclatures.json View File

@@ -0,0 +1,60 @@
1
+{
2
+    "title": "Nomenclatures des relevés",
3
+    "type": "object",
4
+    "required": [
5
+        "entities"
6
+    ],
7
+    "properties": {
8
+        "entities": {
9
+            "type": "array",
10
+            "format": "table",
11
+            "title": "Catégories de relevés",
12
+            "uniqueItems": true,
13
+            "items": {
14
+                "type": "object",
15
+                "title": "Catégorie",
16
+                "properties": {
17
+                    "category": {
18
+                        "type": "string",
19
+                        "title": "Identifiant de la catégorie"
20
+                    },
21
+                    "label": {
22
+                        "type": "string",
23
+                        "title": "Label de la catégorie"
24
+                    },
25
+                    "types": {
26
+                        "type": "array",
27
+                        "format": "table",
28
+                        "title": "Objets",
29
+                        "uniqueItems": true,
30
+                        "items": {
31
+                            "type": "object",
32
+                            "title": "Objet",
33
+                            "properties": {
34
+                                "label": {
35
+                                    "type": "string",
36
+                                    "title": "Label"
37
+                                },
38
+                                "code": {
39
+                                    "type": "string",
40
+                                    "title": "Code"
41
+                                },
42
+                                "types": {
43
+                                    "type": "array",
44
+                                    "uniqueItems": true,
45
+                                    "title": "Format associés",
46
+                                    "items": {
47
+                                        "type": "string",
48
+                                        "enum": [
49
+                                            "line", "curve", "rect", "circle"
50
+                                        ]
51
+                                    } 
52
+                                }
53
+                            }
54
+                        }
55
+                    }
56
+                }
57
+            }
58
+        }
59
+    }
60
+}

+ 1
- 0
static/geotiff.bundle.min.js
File diff suppressed because it is too large
View File


+ 0
- 42
static/index.html View File

@@ -1,42 +0,0 @@
1
-<html>
2
-<head>
3
-  <meta charset="utf8">
4
-  <meta name="viewport" content="width=device-width, initial-scale=1">
5
-  <title>Tiff Optimizer</title>
6
-  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
7
-  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css">
8
-</head>
9
-<body>
10
-  <div class="container">
11
-    <div class="columns">
12
-      <div class="column">
13
-        <div class="level is-mobile is-marginless">
14
-          <div class="level-left">
15
-            <h1 class="is-size-1 level-item">Tiff Optimizer</h1>
16
-          </div>
17
-        </div>
18
-        <form action="." method="POST" enctype="multipart/form-data">
19
-          <div class="file is-primary is-large" style="justify-content:center">
20
-            <label class="file-label">
21
-              <input class="file-input"
22
-              id="tiffImage"
23
-              name="tiffImage"
24
-              accept=".tif"
25
-              onchange="javascript:this.form.submit()"
26
-              type="file" name="resume">
27
-              <span class="file-cta">
28
-                <span class="file-icon">
29
-                  <i class="fas fa-upload"></i>
30
-                </span>
31
-                <span class="file-label">
32
-                  Optimiser un fichier Tiff
33
-                </span>
34
-              </span>
35
-            </label>
36
-          </div>
37
-        </form>
38
-      </div>
39
-    </div>
40
-  </div>
41
-</body>
42
-</html>

+ 205
- 0
template/geotiff_explorer.html.tmpl View File

@@ -0,0 +1,205 @@
1
+{{ extends "layout.html.tmpl" }}
2
+{{define "title" -}}Explorateur de fichier GeoTiff - Fieldnotes{{- end}}
3
+{{define "body_content"}}
4
+<div class="container is-fluid">
5
+    <div class="columns">
6
+        <div class="column is-narrow">
7
+            {{template "partials/menu.html.tmpl" .}}
8
+        </div>
9
+        <div class="column">
10
+        <div class="level is-mobile is-marginless">
11
+            <div class="level-left"></div>
12
+            <div class="level-right">
13
+            <div class="level-item">
14
+                <div class="file is-primary">
15
+                <label class="file-label">
16
+                    <input class="file-input"
17
+                    id="geotiffInput"
18
+                    accept=".tif"
19
+                    type="file" name="resume">
20
+                    <span class="file-cta">
21
+                    <span class="file-icon">
22
+                        <i class="fas fa-upload"></i>
23
+                    </span>
24
+                    <span class="file-label">
25
+                        Charger un fichier
26
+                    </span>
27
+                    </span>
28
+                </label>
29
+                </div>
30
+            </div>
31
+            </div>
32
+        </div>
33
+        <div class="is-clearfix">
34
+            <a class="is-pulled-right" href="https://www.mapbox.com/help/data/landsat.tif">Exemple de fichier GeoTIFF valide</a>
35
+        </div>
36
+        <div id="output" class="content"></div>
37
+        </div>
38
+    </div>
39
+</div>
40
+<script type="text/javascript" src="/geotiff.bundle.min.js"></script>
41
+<script type="text/javascript">
42
+
43
+const output =  document.getElementById("output");
44
+const geotiffInput =  document.getElementById("geotiffInput");
45
+
46
+geotiffInput.addEventListener("change", handleGeoTiffOpen, false);
47
+
48
+function handleGeoTiffOpen(evt) {
49
+    if (evt.target.files.length === 0) return;
50
+    const reader = new FileReader();
51
+    const file = evt.target.files[0];
52
+    reader.onload = () => {
53
+    GeoTIFF.fromArrayBuffer(reader.result)
54
+        .then(geotiff => geotiff.getImage())
55
+        .then(image => updateOutput(image))
56
+        .catch(err => {
57
+        console.error(err);
58
+        alert(err.message);
59
+        })
60
+    ;
61
+    }
62
+    reader.readAsArrayBuffer(file);
63
+}
64
+
65
+function updateOutput(image) {
66
+
67
+    let html = '';
68
+    
69
+    const geoKeys = image.getGeoKeys();
70
+
71
+    html += '<h4 class="is-size-4">Attributs de géopositionnement</h4>'
72
+
73
+    html += `
74
+    <table class="table">
75
+        <thead>
76
+        <tr>
77
+            <th>Clé</th>
78
+            <th>Valeur</th>
79
+        </tr>
80
+        </thead>
81
+        <tbody>
82
+    `
83
+
84
+    if (geoKeys) {
85
+    Object.keys(geoKeys).forEach(key => {
86
+        if (key === 'ProjectedCSTypeGeoKey') {
87
+        html += `
88
+            <tr>
89
+            <td><b>${key}</b></td>
90
+            <td><a href="https://epsg.io/${geoKeys[key]}">EPSG:${geoKeys[key]}</a></td>
91
+            </tr>
92
+        `;
93
+        } else {
94
+        html += `
95
+            <tr>
96
+            <td><b>${key}</b></td>
97
+            <td>${geoKeys[key]}</td>
98
+            </tr>
99
+        `;
100
+        }
101
+    });
102
+    } else {
103
+    html += `
104
+        <tr>
105
+        <td class="has-text-centered" colspan="2"><i>Aucune donnée.</i></td>
106
+        </tr>
107
+    `
108
+    }
109
+
110
+    html += `
111
+        </tbody>
112
+    </table>
113
+    `
114
+    
115
+    let boundingBox;
116
+    try {
117
+    boundingBox = image.getBoundingBox();
118
+    } catch(err) {
119
+    // Do nothing
120
+    }
121
+
122
+    html += '<h4 class="is-size-4">Encadrement de l\'image</h4>';
123
+
124
+    html += `
125
+    <table class="table">
126
+        <thead>
127
+        <tr>
128
+            <th>Min X</th>
129
+            <th>Min Y</th>
130
+            <th>Max X</th>
131
+            <th>Max Y</th>
132
+        </tr>
133
+        </thead>
134
+        <tbody>
135
+    `
136
+
137
+    if (boundingBox) {
138
+    html += `
139
+        <tr>
140
+        <td>${boundingBox[0]}</td>
141
+        <td>${boundingBox[1]}</td>
142
+        <td>${boundingBox[2]}</td>
143
+        <td>${boundingBox[3]}</td>
144
+        </tr>
145
+        `;
146
+    } else {
147
+    html += `
148
+        <tr>
149
+        <td class="has-text-centered" colspan="4"><i>Aucune donnée.</i></td>
150
+        </tr>
151
+    `
152
+    }
153
+
154
+    html += `
155
+        </tbody>
156
+    </table>
157
+    `
158
+
159
+    html += '<h4 class="is-size-4">Points d\'attache</h4>';
160
+
161
+    let tiePoints;
162
+    try {
163
+    tiePoints = image.getTiePoints();
164
+    } catch(err) {
165
+    // Do nothing
166
+    }
167
+
168
+    html += `
169
+    <table class="table">
170
+        <thead>
171
+        <tr>
172
+            <th>Coordonnées de l'image (x, y, z)</th>
173
+            <th>Coordonnées géographiques (x, y, z)</th>
174
+        </tr>
175
+        </thead>
176
+        <tbody>
177
+    `
178
+
179
+    if(tiePoints && tiePoints.length > 0) {
180
+    tiePoints.forEach(p => {
181
+        html += `
182
+        <tr>
183
+            <td>${p.i},${p.j},${p.k}</td>
184
+            <td>${p.x},${p.y},${p.z}</td>
185
+        </tr>
186
+        `;
187
+    });
188
+    } else {
189
+    html += `
190
+        <tr>
191
+        <td class="has-text-centered" colspan="2"><i>Aucune donnée.</i></td>
192
+        </tr>
193
+    `
194
+    }
195
+
196
+    html += `
197
+        </tbody>
198
+    </table>
199
+    `
200
+    
201
+    output.innerHTML = html;
202
+
203
+}
204
+</script>
205
+{{end}}

+ 18
- 0
template/home.html.tmpl View File

@@ -0,0 +1,18 @@
1
+{{ extends "layout.html.tmpl" }}
2
+{{define "title" -}}Accueil - Fieldnotes{{- end}}
3
+{{ define "body_content" }}
4
+<div class="container is-fluid">
5
+    <div class="columns">
6
+        <div class="column is-narrow">
7
+            {{template "partials/menu.html.tmpl" .}}
8
+        </div>
9
+        <div class="column">
10
+            <article class="message is-info">
11
+                <div class="message-body">
12
+                    <strong>Bienvenue !</strong>
13
+                </div>
14
+            </article>
15
+        </div>
16
+    </div>
17
+</div>
18
+{{ end }}

+ 21
- 0
template/layout.html.tmpl View File

@@ -0,0 +1,21 @@
1
+<html>
2
+<head>
3
+    <meta charset="utf8">
4
+    <meta name="viewport" content="width=device-width, initial-scale=1">
5
+    <title>{{block "title" .}}Fieldnotes Server{{ end }}</title>
6
+    <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.6.3/css/all.css" integrity="sha384-UHRtZLI+pbxtHCWp1t77Bi1L4ZtiqrqD80Kn4Z8NTSRyMA2Fd33n5dQ8lWUE00s/" crossorigin="anonymous">
7
+    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.7.2/css/bulma.min.css">
8
+</head>
9
+<body>
10
+    <nav class="navbar" role="navigation" aria-label="main navigation">
11
+        <div class="container is-fluid">
12
+            <div class="navbar-brand">
13
+                <a class="navbar-item" href="/">
14
+                    <span class="is-uppercase">Fieldnotes Server</span>
15
+                </a>
16
+            </div>
17
+        </div>
18
+    </nav>
19
+    {{block "body_content" .}}{{end}}
20
+</body>
21
+</html>

+ 56
- 0
template/nomenclature_editor.html.tmpl View File

@@ -0,0 +1,56 @@
1
+{{ extends "layout.html.tmpl" }}
2
+{{ define "title" }}Éditeur de nomenclatures{{end}}
3
+{{ define "body_content" }}
4
+<div class="container is-fluid">
5
+    <div class="columns">
6
+        <div class="column is-narrow">
7
+            {{template "partials/menu.html.tmpl" .}}
8
+        </div>
9
+        <div class="column">
10
+            <div class="level is-mobile is-marginless">
11
+                <div class="level-left"></div>
12
+                <div class="level-right">
13
+                    <div class="level-item">
14
+                        <div class="button is-primary" id="save-button"><i class="fas fa-save"></i>&nbsp;Enregistrer</div>
15
+                    </div>
16
+                </div>
17
+            </div>
18
+            <div id="editor"></div>
19
+        </div>
20
+    </div>
21
+</div>
22
+<script src="https://cdn.jsdelivr.net/npm/@json-editor/json-editor@latest/dist/jsoneditor.min.js"></script>
23
+<script type="text/javascript">
24
+(function() {
25
+    var element = document.getElementById('editor');
26
+    var editor = new JSONEditor(element, {
27
+        no_additional_properties: true,
28
+        disable_edit_json: true,
29
+        iconlib: 'fontawesome5',
30
+        startval: JSON.parse('{{ .Nomenclatures }}'),
31
+        schema: JSON.parse('{{ .Schema }}'),
32
+    });
33
+
34
+    var saveButton = document.getElementById('save-button');
35
+    saveButton.onclick = function() {
36
+        var errors = editor.validate();
37
+        if (errors.length > 0) return;
38
+        fetch("/field-surveys/nomenclatures.json", {
39
+            method: 'POST',
40
+            headers: {
41
+                "Content-Type": "application/json",
42
+            },
43
+            body: JSON.stringify(editor.getValue())
44
+        })
45
+        .then(function() {
46
+            window.location.reload();
47
+        })
48
+        .catch(function(err) {
49
+            console.error(err);
50
+            alert("Une erreur est survenue ! Veuillez contacter le développeur.");
51
+        })
52
+    };
53
+
54
+}());
55
+</script>
56
+{{ end }}

+ 15
- 0
template/partials/menu.html.tmpl View File

@@ -0,0 +1,15 @@
1
+<aside class="menu">
2
+  <p class="menu-label">
3
+    Relevés
4
+  </p>
5
+  <ul class="menu-list">
6
+    <li><a href="/field-surveys/editor">Éditeur de nomenclatures</a></li>
7
+  </ul>
8
+  <p class="menu-label">
9
+    Plans
10
+  </p>
11
+  <ul class="menu-list">
12
+    <li><a href="/geotiff-explorer">Explorateur de fichier GeoTiff</a></li>
13
+    <li><a href="/tiff-optimizer">Optimiseur de fichier Tiff</a></li>
14
+  </ul>
15
+</aside>

+ 40
- 0
template/tiff_optimizer.html.tmpl View File

@@ -0,0 +1,40 @@
1
+{{ extends "layout.html.tmpl" }}
2
+{{define "title" -}}Optimiseur de fichier Tiff - Fieldnotes{{- end}}
3
+{{ define "body_content" }}
4
+<div class="container is-fluid">
5
+    <div class="columns">
6
+        <div class="column is-narrow">
7
+            {{template "partials/menu.html.tmpl" .}}
8
+        </div>
9
+        <div class="column">
10
+            <div class="level is-mobile is-marginless">
11
+                <div class="level-left"></div>
12
+                <div class="level-right">
13
+                    <div class="level-item">
14
+                        <form action="/tiff-optimizer" method="POST" enctype="multipart/form-data">
15
+                            <div class="file is-primary" style="justify-content:center">
16
+                                <label class="file-label">
17
+                                    <input class="file-input"
18
+                                        id="tiffImage"
19
+                                        name="tiffImage"
20
+                                        accept=".tif"
21
+                                        onchange="javascript:this.form.submit()"
22
+                                        type="file" name="resume">
23
+                                    <span class="file-cta">
24
+                                        <span class="file-icon">
25
+                                            <i class="fas fa-upload"></i>
26
+                                        </span>
27
+                                        <span class="file-label">
28
+                                            Optimiser un fichier Tiff
29
+                                        </span>
30
+                                    </span>
31
+                                </label>
32
+                            </div>
33
+                        </form>
34
+                    </div>
35
+                </div>
36
+            </div>
37
+        </div>
38
+    </div>
39
+</div>
40
+{{ end }}

Loading…
Cancel
Save