Skip to content
Snippets Groups Projects
Commit 8078292d authored by Alexis POYEN's avatar Alexis POYEN
Browse files

Merge branch '74-display-a-map' into 'master'

Resolve "Display a map"

Closes #74

See merge request !71
parents 425de039 351b22ec
No related branches found
No related tags found
1 merge request!71Resolve "Display a map"
Pipeline #6569 passed
...@@ -7,7 +7,7 @@ import ( ...@@ -7,7 +7,7 @@ import (
"os" "os"
"strconv" "strconv"
"forge.grandlyon.com/systemes-dinformation/project-template/sdk-go/pkg/middlewares" "forge.grandlyon.com/gestion-des-assemblees/elections/pkg/middlewares"
) )
const literralContentType = "Content-Type" const literralContentType = "Content-Type"
......
...@@ -6,7 +6,7 @@ import ( ...@@ -6,7 +6,7 @@ import (
"forge.grandlyon.com/gestion-des-assemblees/elections/internal/auth" "forge.grandlyon.com/gestion-des-assemblees/elections/internal/auth"
"forge.grandlyon.com/gestion-des-assemblees/elections/internal/models" "forge.grandlyon.com/gestion-des-assemblees/elections/internal/models"
"forge.grandlyon.com/systemes-dinformation/project-template/sdk-go/pkg/middlewares" "forge.grandlyon.com/gestion-des-assemblees/elections/pkg/middlewares"
"forge.grandlyon.com/systemes-dinformation/project-template/sdk-go/pkg/common" "forge.grandlyon.com/systemes-dinformation/project-template/sdk-go/pkg/common"
) )
...@@ -47,6 +47,6 @@ func CreateRootMux(port int, staticDir string) RootMux { ...@@ -47,6 +47,6 @@ func CreateRootMux(port int, staticDir string) RootMux {
mainMux.Handle("/", middlewares.NoCache(http.FileServer(&common.FallBackWrapper{Assets: http.Dir(staticDir)}))) mainMux.Handle("/", middlewares.NoCache(http.FileServer(&common.FallBackWrapper{Assets: http.Dir(staticDir)})))
// Put it together into the main handler // Put it together into the main handler
mux := http.NewServeMux() mux := http.NewServeMux()
mux.Handle(hostname+"/", middlewares.WebSecurity(mainMux, "*."+hostname+":*", false)) mux.Handle(hostname+"/", middlewares.WebSecurity(mainMux, "*."+hostname+":* *.mapbox.com *.grandlyon.com ", false))
return RootMux{mux, &m} return RootMux{mux, &m}
} }
...@@ -11,7 +11,7 @@ import ( ...@@ -11,7 +11,7 @@ import (
"syscall" "syscall"
"time" "time"
"forge.grandlyon.com/systemes-dinformation/project-template/sdk-go/pkg/middlewares" "forge.grandlyon.com/gestion-des-assemblees/elections/pkg/middlewares"
"forge.grandlyon.com/systemes-dinformation/project-template/sdk-go/pkg/tokens" "forge.grandlyon.com/systemes-dinformation/project-template/sdk-go/pkg/tokens"
"forge.grandlyon.com/gestion-des-assemblees/elections/internal/mocks" "forge.grandlyon.com/gestion-des-assemblees/elections/internal/mocks"
......
package middlewares
import (
"fmt"
"net/http"
"strconv"
)
// Cors enables CORS Request on server (for development purposes)
func Cors(next http.Handler, allowedOrigin string) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Access-Control-Allow-Origin", allowedOrigin)
w.Header().Set("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE, PROPFIND, MKCOL, MOVE, COPY")
w.Header().Set("Access-Control-Allow-Headers", "Accept, Content-Type, Content-Length, Accept-Encoding, XSRF-TOKEN, Authorization, Depth, Destination")
w.Header().Set("Access-Control-Allow-Credentials", "true")
next.ServeHTTP(w, req)
})
}
// WebSecurity adds good practices security headers on http responses
func WebSecurity(next http.Handler, source string, allowEvalInlineScript bool) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Strict-Transport-Security", "max-age=63072000")
var inline string
if allowEvalInlineScript {
inline = "'unsafe-inline' 'unsafe-eval'"
}
w.Header().Set("Content-Security-Policy", fmt.Sprintf("default-src %[1]v 'self'; img-src %[1]v 'self' data: blob:; script-src %[1]v 'self' %[2]v; style-src %[1]v 'self' 'unsafe-inline'; frame-src %[1]v; frame-ancestors %[1]v; worker-src blob: ;child-src blob: ;", source, inline))
//w.Header().Set("X-Frame-Options", "SAMEORIGIN") // Works fine with chrome but is not obsoleted by frame-src in firefox 72.0.2
w.Header().Set("X-XSS-Protection", "1; mode=block")
w.Header().Set("Referrer-Policy", "strict-origin")
w.Header().Set("X-Content-Type-Options", "nosniff")
next.ServeHTTP(w, req)
})
}
// NoCache disable caching
func NoCache(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
w.Header().Set("Cache-Control", "no-store, must-revalidate")
next.ServeHTTP(w, req)
})
}
// GetFullHostname returns the full hostname of the server
func GetFullHostname(hostname string, port int) string {
if port == 80 || port == 443 {
return "https://" + hostname
}
return "https://" + hostname + ":" + strconv.Itoa(port)
}
This diff is collapsed.
// Imports
import * as PartyModel from "/services/model/party-model.js";
import * as AreaModel from "/services/model/area-model.js";
export async function mount(parent) {
const mapComponent = new MapComponent(parent);
return mapComponent;
}
class MapComponent {
constructor(parent) {
this.parent = parent;
this.PartyModel = PartyModel.getPartyModel();
this.AreaModel = AreaModel.getAreaModel();
}
async displayMapAreas() {
console.log("mount area map")
await this.initMap("/assets/maps/area.json", this.colorAreas);
}
async displayMapSections() {
console.log("mount section map")
await this.initMap("/assets/maps/section.json", this.colorSections);
}
async initMap(mapFile, colorationFunction) {
// Create datasource
const request = new XMLHttpRequest();
request.open("GET", mapFile, false);
request.send(null);
let dataSource = JSON.parse(request.responseText);
// Add parties and colors to datasource
dataSource = await colorationFunction(dataSource);
document.getElementById("map-component").innerHTML = "";
// Create a popup, but don't add it to the map yet.
let popup = new mapboxgl.Popup({
closeButton: false,
});
const map = new mapboxgl.Map({
container: "map-component", // container id
style: "/assets/mapbox/vector.json", // stylesheet location
center: [4.9, 45.75], // starting position [lng, lat]
zoom: 9.7, // starting zoom
});
// map.on("load", function () {
// map.addSource("data-source", {
// type: "geojson",
// data: dataSource,
// });
// map.addLayer(
// {
// id: "winners-fills",
// type: "fill",
// source: "data-source",
// layout: {},
// paint: {
// "fill-color": { type: "identity", property: "color" },
// "fill-opacity": 0.5,
// "fill-outline-color": "black",
// },
// },
// "place_label_city"
// );
// map.addLayer({
// id: "winners-names",
// type: "symbol",
// source: "data-source",
// filter: ["all"],
// layout: {
// "text-field": "{partyName}",
// "text-font": ["titiliumweb-regular"],
// },
// });
// });
}
async colorAreas(dataSource) {}
async colorSections(dataSource) {}
}
...@@ -6,6 +6,7 @@ import * as AreaModel from "/services/model/area-model.js"; ...@@ -6,6 +6,7 @@ import * as AreaModel from "/services/model/area-model.js";
import * as Scroller from "/services/common/scroller.js"; import * as Scroller from "/services/common/scroller.js";
import * as ResultsFlow from "/components/visualization/results-flow.js"; import * as ResultsFlow from "/components/visualization/results-flow.js";
import * as ResultsDetaileds from "/components/visualization/results-detaileds.js"; import * as ResultsDetaileds from "/components/visualization/results-detaileds.js";
import * as ResultsMap from "/components/visualization/results-map.js";
export async function mount(where, parent) { export async function mount(where, parent) {
const resultZoneComponent = new ResultZoneComponent(parent); const resultZoneComponent = new ResultZoneComponent(parent);
...@@ -91,6 +92,7 @@ class ResultZoneComponent { ...@@ -91,6 +92,7 @@ class ResultZoneComponent {
`; `;
this.ResultsFlow = await ResultsFlow.mount(this); this.ResultsFlow = await ResultsFlow.mount(this);
this.ResultsDetaileds = await ResultsDetaileds.mount(this); this.ResultsDetaileds = await ResultsDetaileds.mount(this);
this.ResultsMap = await ResultsMap.mount(this);
this.scroller = Scroller.scrollInit( this.scroller = Scroller.scrollInit(
"news-flow", "news-flow",
document.getElementById("auto-scroll") document.getElementById("auto-scroll")
...@@ -136,6 +138,9 @@ class ResultZoneComponent { ...@@ -136,6 +138,9 @@ class ResultZoneComponent {
let resultHandler = this; let resultHandler = this;
document.getElementById("map-section").parentElement.className = document.getElementById("map-section").parentElement.className =
"column is-full"; "column is-full";
console.log(this.ResultsMap);
if (this.parent.zone === "areas") this.ResultsMap.displayMapAreas();
else this.ResultsMap.displayMapSections();
document.getElementById("zoom-map").addEventListener("click", function () { document.getElementById("zoom-map").addEventListener("click", function () {
resultHandler.unZoom(); resultHandler.unZoom();
}); });
...@@ -215,6 +220,9 @@ class ResultZoneComponent { ...@@ -215,6 +220,9 @@ class ResultZoneComponent {
<i class="fa fa-expand-arrows-alt"></i> <i class="fa fa-expand-arrows-alt"></i>
</span>`; </span>`;
if (this.parent.zone === "areas") this.ResultsMap.displayMapAreas();
else this.ResultsMap.displayMapSections();
this.handleDom(); this.handleDom();
} }
......
...@@ -104,12 +104,14 @@ class ResultComponent { ...@@ -104,12 +104,14 @@ class ResultComponent {
await this.hideGeneralSection(); await this.hideGeneralSection();
document.getElementById("sections").setAttribute("class", ""); document.getElementById("sections").setAttribute("class", "");
document.getElementById("areas").setAttribute("class", "is-active"); document.getElementById("areas").setAttribute("class", "is-active");
this.resultsZone.ResultsMap.displayMapAreas();
}); });
document.getElementById("sections").addEventListener("click", async () => { document.getElementById("sections").addEventListener("click", async () => {
resultHandler.zone = "sections"; resultHandler.zone = "sections";
await this.hideGeneralSection(); await this.hideGeneralSection();
document.getElementById("areas").setAttribute("class", ""); document.getElementById("areas").setAttribute("class", "");
document.getElementById("sections").setAttribute("class", "is-active"); document.getElementById("sections").setAttribute("class", "is-active");
this.resultsZone.ResultsMap.displayMapSections();
}); });
let radioButtons = document.getElementsByName("filter"); let radioButtons = document.getElementsByName("filter");
......
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en" class="has-navbar-fixed-top"> <html lang="en" class="has-navbar-fixed-top">
<head> <head>
<title>Elections</title> <title>Elections</title>
...@@ -9,6 +10,11 @@ ...@@ -9,6 +10,11 @@
<link rel="stylesheet" href="assets/bulma.min.css" /> <link rel="stylesheet" href="assets/bulma.min.css" />
<link rel="stylesheet" href="assets/animate.css" /> <link rel="stylesheet" href="assets/animate.css" />
<link rel="stylesheet" href="style.css" /> <link rel="stylesheet" href="style.css" />
<script src="https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.js"></script>
<link
rel="stylesheet"
href="https://api.mapbox.com/mapbox-gl-js/v1.11.1/mapbox-gl.css"
/>
<script defer src="assets/fontawesome/brands.min.js"></script> <script defer src="assets/fontawesome/brands.min.js"></script>
<script defer src="assets/fontawesome/solid.min.js"></script> <script defer src="assets/fontawesome/solid.min.js"></script>
<script defer src="assets/fontawesome/fontawesome.min.js"></script> <script defer src="assets/fontawesome/fontawesome.min.js"></script>
...@@ -16,7 +22,12 @@ ...@@ -16,7 +22,12 @@
</head> </head>
<body> <body>
<!-- Navbar --> <!-- Navbar -->
<nav id="navbar" class="navbar is-dark is-fixed-top" role="navigation" aria-label="main navigation"></nav> <nav
id="navbar"
class="navbar is-dark is-fixed-top"
role="navigation"
aria-label="main navigation"
></nav>
<!-- Main content--> <!-- Main content-->
<section class="section" id="main" style="margin-bottom: 230px;"></section> <section class="section" id="main" style="margin-bottom: 230px;"></section>
...@@ -29,7 +40,12 @@ ...@@ -29,7 +40,12 @@
<div class="navbar-brand"> <div class="navbar-brand">
<div class="navbar-item"> <div class="navbar-item">
<div class="buttons"> <div class="buttons">
<a class="button is-danger" href="https://forge.grandlyon.com/gestion-des-assemblees/elections" target="_blank" rel="noopener noreferrer"> <a
class="button is-danger"
href="https://forge.grandlyon.com/gestion-des-assemblees/elections"
target="_blank"
rel="noopener noreferrer"
>
<span class="icon"> <span class="icon">
<svg <svg
class="svg-inline--fa fa-gitlab fa-w-16" class="svg-inline--fa fa-gitlab fa-w-16"
...@@ -45,8 +61,8 @@ ...@@ -45,8 +61,8 @@
<path <path
fill="currentColor" fill="currentColor"
d="M105.2 24.9c-3.1-8.9-15.7-8.9-18.9 0L29.8 199.7h132c-.1 0-56.6-174.8-56.6-174.8zM.9 287.7c-2.6 8 .3 16.9 7.1 22l247.9 184-226.2-294zm160.8-88l94.3 294 94.3-294zm349.4 88l-28.8-88-226.3 294 247.9-184c6.9-5.1 9.7-14 7.2-22zM425.7 24.9c-3.1-8.9-15.7-8.9-18.9 0l-56.6 174.8h132z" d="M105.2 24.9c-3.1-8.9-15.7-8.9-18.9 0L29.8 199.7h132c-.1 0-56.6-174.8-56.6-174.8zM.9 287.7c-2.6 8 .3 16.9 7.1 22l247.9 184-226.2-294zm160.8-88l94.3 294 94.3-294zm349.4 88l-28.8-88-226.3 294 247.9-184c6.9-5.1 9.7-14 7.2-22zM425.7 24.9c-3.1-8.9-15.7-8.9-18.9 0l-56.6 174.8h132z"
></path></svg ></path>
> </svg>
</span> </span>
</a> </a>
</div> </div>
......
...@@ -211,4 +211,12 @@ select { ...@@ -211,4 +211,12 @@ select {
.clickable { .clickable {
cursor: pointer; cursor: pointer;
} }
\ No newline at end of file
#map-section {
height: 70vh;
}
#map-component {
height: 100%;
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment