1
0
forked from MTSR/mapserver

module wip

This commit is contained in:
NatureFreshMilk 2019-06-11 14:16:41 +02:00
parent 922fbee059
commit 67ea4d9e71
30 changed files with 95 additions and 461 deletions

View File

@ -1,38 +0,0 @@
package bundle
import (
"net/http"
)
type CSSHandler struct {
Webdev bool
Cache []byte
}
func NewCSSHandler(Webdev bool) *CSSHandler {
h := &CSSHandler{Webdev: Webdev}
if !Webdev {
//populate cache
manifest := getManifest(Webdev)
h.Cache = createBundle(Webdev, manifest.Styles)
}
return h
}
func (h *CSSHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
resp.Header().Add("content-type", "text/css")
if h.Cache == nil {
//dev
manifest := getManifest(h.Webdev)
resp.Write(createBundle(h.Webdev, manifest.Styles))
} else {
//prod
resp.Header().Add("Cache-Control", "public, max-age=3600")
resp.Write(h.Cache)
}
}

View File

@ -1,38 +0,0 @@
package bundle
import (
"net/http"
)
type JsHandler struct {
Webdev bool
Cache []byte
}
func NewJsHandler(Webdev bool) *JsHandler {
h := &JsHandler{Webdev: Webdev}
if !Webdev {
//populate cache
manifest := getManifest(Webdev)
h.Cache = createBundle(Webdev, manifest.Scripts)
}
return h
}
func (h *JsHandler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
resp.Header().Add("content-type", "text/javascript")
if h.Cache == nil {
//dev
manifest := getManifest(h.Webdev)
resp.Write(createBundle(h.Webdev, manifest.Scripts))
} else {
//prod
resp.Header().Add("Cache-Control", "public, max-age=3600")
resp.Write(h.Cache)
}
}

View File

@ -1,6 +0,0 @@
package bundle
type Manifest struct {
Scripts []string `json:"scripts"`
Styles []string `json:"styles"`
}

View File

@ -1,33 +0,0 @@
package bundle
import (
"encoding/json"
"mapserver/vfs"
)
func getManifest(useLocal bool) *Manifest {
manifestBytes := vfs.FSMustByte(useLocal, "/manifest.js")
manifest := &Manifest{}
err := json.Unmarshal(manifestBytes, manifest)
if err != nil {
panic(err)
}
return manifest
}
func createBundle(useLocal bool, files []string) []byte {
script := make([]byte, 0)
for _, name := range files {
script = append(script, []byte("\n/*File: "+name+"*/\n")...)
content, err := vfs.FSByte(useLocal, name)
if err != nil {
panic("vfs-file not found: " + name)
}
script = append(script, content...)
}
return script
}

View File

@ -4,12 +4,30 @@
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="viewport" content="width=device-width, initial-scale=1"/>
<meta name="theme-color" content="#000"> <meta name="theme-color" content="#000">
<link rel="stylesheet" href="css/bundle.css"/>
<!-- styles -->
<link rel="stylesheet" href="css/bootstrap.min.css"/>
<link rel="stylesheet" href="css/fontawesome.min.css"/>
<link rel="stylesheet" href="css/leaflet.css"/>
<link rel="stylesheet" href="css/leaflet.aewsome-markers.css"/>
<link rel="stylesheet" href="css/custom.css"/>
<title>Minetest Mapserver</title> <title>Minetest Mapserver</title>
</head> </head>
<body> <body>
<div id="image-map"></div> <div id="image-map"></div>
<div id="search-content"></div> <div id="search-content"></div>
<script src="js/bundle.js"></script>
<!-- libraries -->
<script src="js/mithril.min.js"></script>
<script src="js/leaflet.js"></script>
<script src="js/leaflet.aewsome-markers.js"></script>
<script src="js/moment.min.js"></script>
<!-- main module -->
<script src="js/main.js" type="module"></script>
<!-- unsupported -->
<script src="js/nomodule.js" nomodule></script>
</body> </body>
</html> </html>

View File

@ -1,7 +1,5 @@
/* exported CoordinatesDisplay */
// coord display export default L.Control.extend({
var CoordinatesDisplay = L.Control.extend({
onAdd: function(map) { onAdd: function(map) {
var div = L.DomUtil.create('div', 'leaflet-bar leaflet-custom-display'); var div = L.DomUtil.create('div', 'leaflet-bar leaflet-custom-display');
@ -34,5 +32,4 @@ var CoordinatesDisplay = L.Control.extend({
return div; return div;
} }
}); });

View File

@ -1,6 +1,6 @@
/* exported Hashroute */ /* exported Hashroute */
var Hashroute = { export default {
setup: function(map, layerMgr){ setup: function(map, layerMgr){
function updateHash(){ function updateHash(){

View File

@ -1,6 +1,5 @@
/* exported RealtimeTileLayer */
var RealtimeTileLayer = L.TileLayer.extend({ export default L.TileLayer.extend({
initialize: function(wsChannel, layerId, map) { initialize: function(wsChannel, layerId, map) {
var self = this; var self = this;

View File

@ -1,8 +1,5 @@
/* exported SearchControl */
/* globals SearchInput: true */
/* globals SearchMenu: true */
var SearchControl = L.Control.extend({ export default L.Control.extend({
initialize: function(wsChannel, opts) { initialize: function(wsChannel, opts) {
L.Control.prototype.initialize.call(this, opts); L.Control.prototype.initialize.call(this, opts);
}, },

View File

@ -1,6 +1,5 @@
/* exported SimpleCRS */
var SimpleCRS = L.Util.extend({}, L.CRS.Simple, { export default L.Util.extend({}, L.CRS.Simple, {
scale: function (zoom) { scale: function (zoom) {
return Math.pow(2, zoom-9); return Math.pow(2, zoom-9);
} }

View File

@ -50,7 +50,7 @@ var worldInfoRender = function(info){
}; };
// coord display // coord display
var WorldInfoDisplay = L.Control.extend({ export default L.Control.extend({
initialize: function(wsChannel, opts) { initialize: function(wsChannel, opts) {
L.Control.prototype.initialize.call(this, opts); L.Control.prototype.initialize.call(this, opts);
this.wsChannel = wsChannel; this.wsChannel = wsChannel;

View File

@ -1,18 +1,12 @@
/* exported api */
var api = { export getMapObjects(query){
return m.request({
method: "POST",
url: "api/mapobjects/",
data: query
});
}
getMapObjects: function(query){ export getConfig(){
return m.request({ return m.request("api/config");
method: "POST", }
url: "api/mapobjects/",
data: query
});
},
getConfig: function(){
return m.request("api/config");
}
};

View File

@ -1,173 +0,0 @@
(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.ColorHash = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
/**
* BKDR Hash (modified version)
*
* @param {String} str string to hash
* @returns {Number}
*/
var BKDRHash = function(str) {
var seed = 131;
var seed2 = 137;
var hash = 0;
// make hash more sensitive for short string like 'a', 'b', 'c'
str += 'x';
// Note: Number.MAX_SAFE_INTEGER equals 9007199254740991
var MAX_SAFE_INTEGER = parseInt(9007199254740991 / seed2);
for(var i = 0; i < str.length; i++) {
if(hash > MAX_SAFE_INTEGER) {
hash = parseInt(hash / seed2);
}
hash = hash * seed + str.charCodeAt(i);
}
return hash;
};
module.exports = BKDRHash;
},{}],2:[function(require,module,exports){
var BKDRHash = require('./bkdr-hash');
/**
* Convert RGB Array to HEX
*
* @param {Array} RGBArray - [R, G, B]
* @returns {String} 6 digits hex starting with #
*/
var RGB2HEX = function(RGBArray) {
var hex = '#';
RGBArray.forEach(function(value) {
if (value < 16) {
hex += 0;
}
hex += value.toString(16);
});
return hex;
};
/**
* Convert HSL to RGB
*
* @see {@link http://zh.wikipedia.org/wiki/HSL和HSV色彩空间} for further information.
* @param {Number} H Hue [0, 360)
* @param {Number} S Saturation [0, 1]
* @param {Number} L Lightness [0, 1]
* @returns {Array} R, G, B [0, 255]
*/
var HSL2RGB = function(H, S, L) {
H /= 360;
var q = L < 0.5 ? L * (1 + S) : L + S - L * S;
var p = 2 * L - q;
return [H + 1/3, H, H - 1/3].map(function(color) {
if(color < 0) {
color++;
}
if(color > 1) {
color--;
}
if(color < 1/6) {
color = p + (q - p) * 6 * color;
} else if(color < 0.5) {
color = q;
} else if(color < 2/3) {
color = p + (q - p) * 6 * (2/3 - color);
} else {
color = p;
}
return Math.round(color * 255);
});
};
function isArray(o) {
return Object.prototype.toString.call(o) === '[object Array]';
}
/**
* Color Hash Class
*
* @class
*/
var ColorHash = function(options) {
options = options || {};
var LS = [options.lightness, options.saturation].map(function(param) {
param = param || [0.35, 0.5, 0.65]; // note that 3 is a prime
return isArray(param) ? param.concat() : [param];
});
this.L = LS[0];
this.S = LS[1];
if (typeof options.hue === 'number') {
options.hue = {min: options.hue, max: options.hue};
}
if (typeof options.hue === 'object' && !isArray(options.hue)) {
options.hue = [options.hue];
}
if (typeof options.hue === 'undefined') {
options.hue = [];
}
this.hueRanges = options.hue.map(function (range) {
return {
min: typeof range.min === 'undefined' ? 0 : range.min,
max: typeof range.max === 'undefined' ? 360: range.max
};
});
this.hash = options.hash || BKDRHash;
};
/**
* Returns the hash in [h, s, l].
* Note that H [0, 360); S [0, 1]; L [0, 1];
*
* @param {String} str string to hash
* @returns {Array} [h, s, l]
*/
ColorHash.prototype.hsl = function(str) {
var H, S, L;
var hash = this.hash(str);
if (this.hueRanges.length) {
var range = this.hueRanges[hash % this.hueRanges.length];
var hueResolution = 727; // note that 727 is a prime
H = ((hash / this.hueRanges.length) % hueResolution) * (range.max - range.min) / hueResolution + range.min;
} else {
H = hash % 359; // note that 359 is a prime
}
hash = parseInt(hash / 360);
S = this.S[hash % this.S.length];
hash = parseInt(hash / this.S.length);
L = this.L[hash % this.L.length];
return [H, S, L];
};
/**
* Returns the hash in [r, g, b].
* Note that R, G, B [0, 255]
*
* @param {String} str string to hash
* @returns {Array} [r, g, b]
*/
ColorHash.prototype.rgb = function(str) {
var hsl = this.hsl(str);
return HSL2RGB.apply(this, hsl);
};
/**
* Returns the hash in hex
*
* @param {String} str string to hash
* @returns {String} hex with #
*/
ColorHash.prototype.hex = function(str) {
var rgb = this.rgb(str);
return RGB2HEX(rgb);
};
module.exports = ColorHash;
},{"./bkdr-hash":1}]},{},[2])(2)
});

View File

@ -1,40 +0,0 @@
/* jshint undef: false */
api.getConfig().then(function(cfg){
var wsChannel = new WebSocketChannel();
wsChannel.connect();
var map = L.map('image-map', {
minZoom: 2,
maxZoom: 12,
center: Hashroute.getCenter(),
zoom: Hashroute.getZoom(),
crs: SimpleCRS
});
map.attributionControl.addAttribution('<a href="https://github.com/thomasrudin-mt/mapserver">Minetest Mapserver</a>');
var overlays = {};
window.layerMgr = new LayerManager(wsChannel, cfg.layers, map, Hashroute.getLayerId());
//All overlays
Overlaysetup(cfg, map, overlays, wsChannel, layerMgr);
new CoordinatesDisplay({ position: 'bottomleft' }).addTo(map);
new WorldInfoDisplay(wsChannel, { position: 'bottomright' }).addTo(map);
if (cfg.enablesearch){
new SearchControl(wsChannel, { position: 'topright' }).addTo(map);
}
//layer control
L.control.layers(layerMgr.layerObjects, overlays, { position: "topright" }).addTo(map);
Hashroute.setup(map, layerMgr);
}).catch(function(e){
console.error(e);
});

35
server/static/js/map.js Normal file
View File

@ -0,0 +1,35 @@
export function setup(cfg){
var wsChannel = new WebSocketChannel();
wsChannel.connect();
var map = L.map('image-map', {
minZoom: 2,
maxZoom: 12,
center: Hashroute.getCenter(),
zoom: Hashroute.getZoom(),
crs: SimpleCRS
});
map.attributionControl.addAttribution('<a href="https://github.com/thomasrudin-mt/mapserver">Minetest Mapserver</a>');
var overlays = {};
window.layerMgr = new LayerManager(wsChannel, cfg.layers, map, Hashroute.getLayerId());
//All overlays
Overlaysetup(cfg, map, overlays, wsChannel, layerMgr);
new CoordinatesDisplay({ position: 'bottomleft' }).addTo(map);
new WorldInfoDisplay(wsChannel, { position: 'bottomright' }).addTo(map);
if (cfg.enablesearch){
new SearchControl(wsChannel, { position: 'topright' }).addTo(map);
}
//layer control
L.control.layers(layerMgr.layerObjects, overlays, { position: "topright" }).addTo(map);
Hashroute.setup(map, layerMgr);
}

View File

View File

@ -1,8 +1,6 @@
/* exported ATMOverlay */ import AbstractIconOverlay from './AbstractIconOverlay.js';
/* globals AbstractIconOverlay: true */
export default AbstractIconOverlay.extend({
var ATMOverlay = AbstractIconOverlay.extend({
initialize: function(wsChannel, layerMgr) { initialize: function(wsChannel, layerMgr) {
AbstractIconOverlay.prototype.initialize.call(this, wsChannel, layerMgr, "atm"); AbstractIconOverlay.prototype.initialize.call(this, wsChannel, layerMgr, "atm");
}, },

View File

@ -1,7 +1,5 @@
/* exported AbstractGeoJsonOverlay */
/* jshint unused: false */
var AbstractGeoJsonOverlay = L.LayerGroup.extend({ export default L.LayerGroup.extend({
initialize: function(wsChannel, layerMgr, type) { initialize: function(wsChannel, layerMgr, type) {
L.LayerGroup.prototype.initialize.call(this); L.LayerGroup.prototype.initialize.call(this);

View File

@ -1,7 +1,5 @@
/* exported AbstractIconOverlay */
/* jshint unused: false */
var AbstractIconOverlay = L.LayerGroup.extend({ export default L.LayerGroup.extend({
initialize: function(wsChannel, layerMgr, type, icon) { initialize: function(wsChannel, layerMgr, type, icon) {
L.LayerGroup.prototype.initialize.call(this); L.LayerGroup.prototype.initialize.call(this);

View File

@ -1,7 +1,6 @@
/* exported BonesOverlay */ import AbstractIconOverlay from './AbstractIconOverlay.js';
/* globals AbstractIconOverlay: true */
var BonesIcon = L.icon({ export default L.icon({
iconUrl: 'pics/bones_top.png', iconUrl: 'pics/bones_top.png',
iconSize: [16, 16], iconSize: [16, 16],

View File

@ -1,7 +1,6 @@
/* exported BorderOverlay */ import AbstractGeoJsonOverlay from './AbstractGeoJsonOverlay.js';
/* globals AbstractGeoJsonOverlay: true */
var BorderOverlay = AbstractGeoJsonOverlay.extend({ export default AbstractGeoJsonOverlay.extend({
initialize: function(wsChannel, layerMgr) { initialize: function(wsChannel, layerMgr) {
AbstractGeoJsonOverlay.prototype.initialize.call(this, wsChannel, layerMgr, "border"); AbstractGeoJsonOverlay.prototype.initialize.call(this, wsChannel, layerMgr, "border");
}, },

View File

@ -1,5 +1,4 @@
/* exported DigitermOverlay */ import AbstractIconOverlay from './AbstractIconOverlay.js';
/* globals AbstractIconOverlay: true */
var DigitermIcon = L.icon({ var DigitermIcon = L.icon({
iconUrl: 'pics/digiterms_beige_front.png', iconUrl: 'pics/digiterms_beige_front.png',
@ -9,7 +8,7 @@ var DigitermIcon = L.icon({
popupAnchor: [0, -16] popupAnchor: [0, -16]
}); });
var DigitermOverlay = AbstractIconOverlay.extend({ export default AbstractIconOverlay.extend({
initialize: function(wsChannel, layerMgr) { initialize: function(wsChannel, layerMgr) {
AbstractIconOverlay.prototype.initialize.call(this, wsChannel, layerMgr, "digiterm", DigitermIcon); AbstractIconOverlay.prototype.initialize.call(this, wsChannel, layerMgr, "digiterm", DigitermIcon);
}, },

View File

@ -1,8 +1,4 @@
/* exported SearchInput */ export default {
/* globals SearchService: true */
/* globals SearchStore: true */
var SearchInput = {
view: function(){ view: function(){
function handleInput(e){ function handleInput(e){
SearchStore.query = e.target.value; SearchStore.query = e.target.value;

View File

@ -1,9 +1,9 @@
/* exported SearchMenu */
/* globals SearchResult: true */
/* globals SearchService: true */
/* globals SearchStore: true */
var SearchMenu = { import SearchService from './SearchService.js';
import SearchStore from './SearchStore.js';
import SearchResult from './SearchResult.js';
export default {
view: function(vnode){ view: function(vnode){
var style = {}; var style = {};

View File

@ -1,8 +1,6 @@
/* exported SearchResult */ import SearchStore from './SearchStore.js';
/* globals SearchStore: true */
/* globals layerMgr: true */
var SearchResult = { export default {
view: function(vnode){ view: function(vnode){
var map = vnode.attrs.map; var map = vnode.attrs.map;

View File

@ -1,7 +1,7 @@
/* exported SearchService */ import SearchStore from './SearchStore.js';
/* globals SearchStore: true */ import { getMapObjects } from '../api.js';
var SearchService = { export default {
search: function(){ search: function(){
SearchStore.show = true; SearchStore.show = true;
@ -18,7 +18,7 @@ var SearchService = {
SearchStore.busy = true; SearchStore.busy = true;
function searchFor(type, key, valuelike){ function searchFor(type, key, valuelike){
return api.getMapObjects({ return getMapObjects({
pos1: { x:-2048, y:-2048, z:-2048 }, pos1: { x:-2048, y:-2048, z:-2048 },
pos2: { x:2048, y:2048, z:2048 }, pos2: { x:2048, y:2048, z:2048 },
type: type, type: type,

View File

@ -1,6 +1,5 @@
/* exported SearchStore */
var SearchStore = { export default {
query: "", query: "",
show: false, show: false,
busy: false, busy: false,

View File

@ -1,6 +1,5 @@
/* exported debounce */
function debounce(func, wait, immediate) { export default function debounce(func, wait, immediate) {
var timeout; var timeout;
return function() { return function() {
var context = this, args = arguments; var context = this, args = arguments;

View File

@ -1,56 +0,0 @@
{
"scripts": [
"/js/lib/leaflet.js",
"/js/lib/leaflet.awesome-markers.js",
"/js/lib/mithril.min.js",
"/js/lib/color-hash.js",
"/js/util/debounce.js",
"/js/api.js",
"/js/LayerManager.js",
"/js/SimpleCRS.js",
"/js/WebSocketChannel.js",
"/js/RealtimeTileLayer.js",
"/js/SearchControl.js",
"/js/CoordinatesDisplay.js",
"/js/WorldInfoDisplay.js",
"/js/search/SearchStore.js",
"/js/search/SearchService.js",
"/js/search/SearchResult.js",
"/js/search/SearchMenu.js",
"/js/search/SearchInput.js",
"/js/overlays/AbstractIconOverlay.js",
"/js/overlays/AbstractGeoJsonOverlay.js",
"/js/overlays/ATMOverlay.js",
"/js/overlays/TravelnetOverlay.js",
"/js/overlays/ShopOverlay.js",
"/js/overlays/PoiOverlay.js",
"/js/overlays/LabelOverlay.js",
"/js/overlays/PlayerOverlay.js",
"/js/overlays/TrainOverlay.js",
"/js/overlays/MinecartOverlay.js",
"/js/overlays/TrainlineOverlay.js",
"/js/overlays/BorderOverlay.js",
"/js/overlays/ProtectorOverlay.js",
"/js/overlays/XPProtectorOverlay.js",
"/js/overlays/PrivProtectorOverlay.js",
"/js/overlays/BonesOverlay.js",
"/js/overlays/LcdOverlay.js",
"/js/overlays/LocatorOverlay.js",
"/js/overlays/DigitermOverlay.js",
"/js/overlays/LuacontrollerOverlay.js",
"/js/overlays/TechnicAnchorOverlay.js",
"/js/overlays/TechnicQuarryOverlay.js",
"/js/overlays/TechnicSwitchOverlay.js",
"/js/overlays/MissionOverlay.js",
"/js/Overlaysetup.js",
"/js/Hashroute.js",
"/js/main.js"
],
"styles": [
"/css/fontawesome.min.css",
"/css/bootstrap.min.css",
"/css/leaflet.css",
"/css/leaflet.awesome-markers.css",
"/css/custom.css"
]
}

View File

@ -2,7 +2,6 @@ package web
import ( import (
"mapserver/app" "mapserver/app"
"mapserver/bundle"
"mapserver/vfs" "mapserver/vfs"
"net" "net"
"net/http" "net/http"
@ -23,9 +22,6 @@ func Serve(ctx *app.App) {
mux.Handle("/", http.FileServer(vfs.FS(ctx.Config.Webdev))) mux.Handle("/", http.FileServer(vfs.FS(ctx.Config.Webdev)))
mux.Handle("/js/bundle.js", bundle.NewJsHandler(ctx.Config.Webdev))
mux.Handle("/css/bundle.css", bundle.NewCSSHandler(ctx.Config.Webdev))
tiles := &Tiles{ctx: ctx} tiles := &Tiles{ctx: ctx}
tiles.Init() tiles.Init()
mux.Handle("/api/tile/", tiles) mux.Handle("/api/tile/", tiles)