Browse Source

Added leaflet cluster plugin

Less and CSS files are now loaded from forum.js so that webpack can load
resources from node modules (leaflet etc.)
main
Youen 8 months ago
parent
commit
969d68cba8
  1. 5
      extend.php
  2. 216
      js/dist/admin.js
  3. 2
      js/dist/admin.js.map
  4. 3267
      js/dist/forum.js
  5. 2
      js/dist/forum.js.map
  6. 776
      js/dist/forum.less
  7. 9559
      js/package-lock.json
  8. 14
      js/package.json
  9. 17
      js/src/forum/components/GlobalMapPage.tsx
  10. 6
      js/src/forum/index.js
  11. 23
      js/webpack.config.js
  12. 5545
      js/yarn.lock
  13. 2
      less/forum.less

5
extend.php

@ -36,11 +36,14 @@ class UserLocationFilterMutator
return [
(new Extend\Frontend('forum'))
->js(__DIR__.'/js/dist/forum.js')
->css(__DIR__.'/less/forum.less'),
->css(__DIR__.'/js/dist/forum.less'),
(new Extend\Frontend('admin'))
->js(__DIR__.'/js/dist/admin.js')
->css(__DIR__.'/less/admin.less'),
new Extend\Locales(__DIR__.'/locale'),
(new Extend\Event())
->listen(Saving::class, SaveLocationToDatabase::class),

216
js/dist/admin.js vendored

@ -1,112 +1,12 @@
module.exports =
/******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, { enumerable: true, get: getter });
/******/ }
/******/ };
/******/
/******/ // define __esModule on exports
/******/ __webpack_require__.r = function(exports) {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/
/******/ // create a fake namespace object
/******/ // mode & 1: value is a module id, require it
/******/ // mode & 2: merge all properties of value into the ns
/******/ // mode & 4: return value when already ns object
/******/ // mode & 8|1: behave like require
/******/ __webpack_require__.t = function(value, mode) {
/******/ if(mode & 1) value = __webpack_require__(value);
/******/ if(mode & 8) return value;
/******/ if((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;
/******/ var ns = Object.create(null);
/******/ __webpack_require__.r(ns);
/******/ Object.defineProperty(ns, 'default', { enumerable: true, value: value });
/******/ if(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));
/******/ return ns;
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "";
/******/
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = "./admin.js");
/******/ })
/************************************************************************/
/******/ ({
/***/ "./admin.js":
/*!******************!*\
!*** ./admin.js ***!
\******************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _src_admin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/admin */ "./src/admin/index.js");
/* empty/unused harmony star reexport */
/***/ }),
/******/ (() => { // webpackBootstrap
/******/ // runtime can't be in strict mode because a global variable is assign and maybe created.
/******/ var __webpack_modules__ = ({
/***/ "./src/admin/index.js":
/*!****************************!*\
!*** ./src/admin/index.js ***!
\****************************/
/*! no exports provided */
/***/ (function(module, __webpack_exports__, __webpack_require__) {
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
"use strict";
__webpack_require__.r(__webpack_exports__);
@ -119,17 +19,17 @@ __webpack_require__.r(__webpack_exports__);
flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default.a.initializers.add('justoverclock/users-map-location', function () {
flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default.a.extensionData["for"]('justoverclock-users-map-location').registerSetting({
flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default().initializers.add('justoverclock/users-map-location', function () {
flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default().extensionData["for"]('justoverclock-users-map-location').registerSetting({
setting: 'justoverclock-users-map-location.mapBox-api-key',
name: 'justoverclock-users-map-location.mapBox-api-key',
type: 'text',
label: flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default.a.translator.trans('justoverclock-users-map-location.admin.mapBox-api-key'),
help: flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default.a.translator.trans('justoverclock-users-map-location.admin.mapBox-api-key-help')
label: flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default().translator.trans('justoverclock-users-map-location.admin.mapBox-api-key'),
help: flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default().translator.trans('justoverclock-users-map-location.admin.mapBox-api-key-help')
});
Object(flarum_common_extend__WEBPACK_IMPORTED_MODULE_1__["extend"])(flarum_admin_components_UserListPage__WEBPACK_IMPORTED_MODULE_2___default.a.prototype, 'columns', function (items) {
(0,flarum_common_extend__WEBPACK_IMPORTED_MODULE_1__.extend)((flarum_admin_components_UserListPage__WEBPACK_IMPORTED_MODULE_2___default().prototype), 'columns', function (items) {
items.add('location', {
name: flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default.a.translator.trans('justoverclock-users-map-location.admin.adminLocationField'),
name: flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default().translator.trans('justoverclock-users-map-location.admin.adminLocationField'),
content: function content(user) {
return m("div", null, user.data.attributes.location);
}
@ -143,9 +43,9 @@ flarum_admin_app__WEBPACK_IMPORTED_MODULE_0___default.a.initializers.add('justov
/*!**************************************************!*\
!*** external "flarum.core.compat['admin/app']" ***!
\**************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
/***/ ((module) => {
"use strict";
module.exports = flarum.core.compat['admin/app'];
/***/ }),
@ -154,9 +54,9 @@ module.exports = flarum.core.compat['admin/app'];
/*!**********************************************************************!*\
!*** external "flarum.core.compat['admin/components/UserListPage']" ***!
\**********************************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
/***/ ((module) => {
"use strict";
module.exports = flarum.core.compat['admin/components/UserListPage'];
/***/ }),
@ -165,12 +65,94 @@ module.exports = flarum.core.compat['admin/components/UserListPage'];
/*!******************************************************!*\
!*** external "flarum.core.compat['common/extend']" ***!
\******************************************************/
/*! no static exports found */
/***/ (function(module, exports) {
/***/ ((module) => {
"use strict";
module.exports = flarum.core.compat['common/extend'];
/***/ })
/******/ });
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ (() => {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = (module) => {
/******/ var getter = module && module.__esModule ?
/******/ () => (module['default']) :
/******/ () => (module);
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ (() => {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = (exports, definition) => {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ (() => {
/******/ __webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))
/******/ })();
/******/
/******/ /* webpack/runtime/make namespace object */
/******/ (() => {
/******/ // define __esModule on exports
/******/ __webpack_require__.r = (exports) => {
/******/ if(typeof Symbol !== 'undefined' && Symbol.toStringTag) {
/******/ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
/******/ }
/******/ Object.defineProperty(exports, '__esModule', { value: true });
/******/ };
/******/ })();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be in strict mode.
(() => {
"use strict";
/*!******************!*\
!*** ./admin.js ***!
\******************/
__webpack_require__.r(__webpack_exports__);
/* harmony import */ var _src_admin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./src/admin */ "./src/admin/index.js");
})();
module.exports = __webpack_exports__;
/******/ })()
;
//# sourceMappingURL=admin.js.map

2
js/dist/admin.js.map vendored

File diff suppressed because one or more lines are too long

3267
js/dist/forum.js vendored

File diff suppressed because it is too large Load Diff

2
js/dist/forum.js.map vendored

File diff suppressed because one or more lines are too long

776
js/dist/forum.less vendored

@ -0,0 +1,776 @@
/*!********************************************************************!*\
!*** css ./node_modules/css-loader/dist/cjs.js!../less/forum.less ***!
\********************************************************************/
input#location {
width: 400px;
}
.location-map { height: 180px; width: 550px; border-radius: 10px;}
.location-map-user-profile {
height: 50px;
width: 180px;
border-radius: 10px;
transition: width 600ms, height 600ms;
.leaflet-control-attribution.leaflet-control {
display: none;
}
.leaflet-control-zoom.leaflet-bar.leaflet-control {
display: none;
}
}
.location-map-user-profile:hover{
height: 160px;
width: 100%;
.leaflet-control-attribution.leaflet-control {
display: block;
}
.leaflet-control-zoom.leaflet-bar.leaflet-control {
display: block;
}
}
.global-map {
height: ~"calc(100vh - 170px)";
width: 100%;
border-radius: 10px;
}
/* required styles */
li.item-mapLocation {
display: block;
padding: 8px;
}
.location-map-user-profile img {
width: 100%;
max-height: none;
}
fieldset .fieldset-separator {
margin-top: 10px;
}
/*!*****************************************************************************************!*\
!*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/leaflet/dist/leaflet.css ***!
\*****************************************************************************************/
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
/* Prevents IE11 from highlighting tiles in blue */
.leaflet-tile::selection {
background: transparent;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg,
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer,
.leaflet-container .leaflet-tile {
max-width: none !important;
max-height: none !important;
}
.leaflet-container.leaflet-touch-zoom {
-ms-touch-action: pan-x pan-y;
touch-action: pan-x pan-y;
}
.leaflet-container.leaflet-touch-drag {
-ms-touch-action: pinch-zoom;
/* Fallback for FF which doesn't support pinch-zoom */
touch-action: none;
touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
-ms-touch-action: none;
touch-action: none;
}
.leaflet-container {
-webkit-tap-highlight-color: transparent;
}
.leaflet-container a {
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 800;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-tooltip-pane { z-index: 650; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 800;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-tile {
will-change: opacity;
}
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-interactive {
cursor: pointer;
}
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
cursor: grabbing;
}
/* marker & overlays interactivity */
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-image-layer,
.leaflet-pane > svg path,
.leaflet-tile-container {
pointer-events: none;
}
.leaflet-marker-icon.leaflet-interactive,
.leaflet-image-layer.leaflet-interactive,
.leaflet-pane > svg path.leaflet-interactive,
svg.leaflet-image-layer.leaflet-interactive path {
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
/* visual tweaks */
.leaflet-container {
background: #ddd;
outline: 0;
}
.leaflet-container a {
color: #0078A8;
}
.leaflet-container a.leaflet-active {
outline: 2px solid orange;
}
.leaflet-zoom-box {
border: 2px dotted #38f;
background: rgba(255,255,255,0.5);
}
/* general typography */
.leaflet-container {
font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif;
}
/* general toolbar styles */
.leaflet-bar {
box-shadow: 0 1px 5px rgba(0,0,0,0.65);
border-radius: 4px;
}
.leaflet-bar a,
.leaflet-bar a:hover {
background-color: #fff;
border-bottom: 1px solid #ccc;
width: 26px;
height: 26px;
line-height: 26px;
display: block;
text-align: center;
text-decoration: none;
color: black;
}
.leaflet-bar a,
.leaflet-control-layers-toggle {
background-position: 50% 50%;
background-repeat: no-repeat;
display: block;
}
.leaflet-bar a:hover {
background-color: #f4f4f4;
}
.leaflet-bar a:first-child {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
}
.leaflet-bar a:last-child {
border-bottom-left-radius: 4px;
border-bottom-right-radius: 4px;
border-bottom: none;
}
.leaflet-bar a.leaflet-disabled {
cursor: default;
background-color: #f4f4f4;
color: #bbb;
}
.leaflet-touch .leaflet-bar a {
width: 30px;
height: 30px;
line-height: 30px;
}
.leaflet-touch .leaflet-bar a:first-child {
border-top-left-radius: 2px;
border-top-right-radius: 2px;
}
.leaflet-touch .leaflet-bar a:last-child {
border-bottom-left-radius: 2px;
border-bottom-right-radius: 2px;
}
/* zoom control */
.leaflet-control-zoom-in,
.leaflet-control-zoom-out {
font: bold 18px 'Lucida Console', Monaco, monospace;
text-indent: 1px;
}
.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out {
font-size: 22px;
}
/* layers control */
.leaflet-control-layers {
box-shadow: 0 1px 5px rgba(0,0,0,0.4);
background: #fff;
border-radius: 5px;
}
.leaflet-control-layers-toggle {
background-image: url(416d91365b44e4b4f477.png);
width: 36px;
height: 36px;
}
.leaflet-retina .leaflet-control-layers-toggle {
background-image: url(8f2c4d11474275fbc161.png);
background-size: 26px 26px;
}
.leaflet-touch .leaflet-control-layers-toggle {
width: 44px;
height: 44px;
}
.leaflet-control-layers .leaflet-control-layers-list,
.leaflet-control-layers-expanded .leaflet-control-layers-toggle {
display: none;
}
.leaflet-control-layers-expanded .leaflet-control-layers-list {
display: block;
position: relative;
}
.leaflet-control-layers-expanded {
padding: 6px 10px 6px 6px;
color: #333;
background: #fff;
}
.leaflet-control-layers-scrollbar {
overflow-y: scroll;
overflow-x: hidden;
padding-right: 5px;
}
.leaflet-control-layers-selector {
margin-top: 2px;
position: relative;
top: 1px;
}
.leaflet-control-layers label {
display: block;
}
.leaflet-control-layers-separator {
height: 0;
border-top: 1px solid #ddd;
margin: 5px -10px 5px -6px;
}
/* Default icon URLs */
.leaflet-default-icon-path {
background-image: url(2b3e1faf89f94a483539.png);
}
/* attribution and scale controls */
.leaflet-container .leaflet-control-attribution {
background: #fff;
background: rgba(255, 255, 255, 0.7);
margin: 0;
}
.leaflet-control-attribution,
.leaflet-control-scale-line {
padding: 0 5px;
color: #333;
}
.leaflet-control-attribution a {
text-decoration: none;
}
.leaflet-control-attribution a:hover {
text-decoration: underline;
}
.leaflet-container .leaflet-control-attribution,
.leaflet-container .leaflet-control-scale {
font-size: 11px;
}
.leaflet-left .leaflet-control-scale {
margin-left: 5px;
}
.leaflet-bottom .leaflet-control-scale {
margin-bottom: 5px;
}
.leaflet-control-scale-line {
border: 2px solid #777;
border-top: none;
line-height: 1.1;
padding: 2px 5px 1px;
font-size: 11px;
white-space: nowrap;
overflow: hidden;
-moz-box-sizing: border-box;
box-sizing: border-box;
background: #fff;
background: rgba(255, 255, 255, 0.5);
}
.leaflet-control-scale-line:not(:first-child) {
border-top: 2px solid #777;
border-bottom: none;
margin-top: -2px;
}
.leaflet-control-scale-line:not(:first-child):not(:last-child) {
border-bottom: 2px solid #777;
}
.leaflet-touch .leaflet-control-attribution,
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
box-shadow: none;
}
.leaflet-touch .leaflet-control-layers,
.leaflet-touch .leaflet-bar {
border: 2px solid rgba(0,0,0,0.2);
background-clip: padding-box;
}
/* popup */
.leaflet-popup {
position: absolute;
text-align: center;
margin-bottom: 20px;
}
.leaflet-popup-content-wrapper {
padding: 1px;
text-align: left;
border-radius: 12px;
}
.leaflet-popup-content {
margin: 13px 19px;
line-height: 1.4;
}
.leaflet-popup-content p {
margin: 18px 0;
}
.leaflet-popup-tip-container {
width: 40px;
height: 20px;
position: absolute;
left: 50%;
margin-left: -20px;
overflow: hidden;
pointer-events: none;
}
.leaflet-popup-tip {
width: 17px;
height: 17px;
padding: 1px;
margin: -10px auto 0;
-webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg);
-ms-transform: rotate(45deg);
transform: rotate(45deg);
}
.leaflet-popup-content-wrapper,
.leaflet-popup-tip {
background: white;
color: #333;
box-shadow: 0 3px 14px rgba(0,0,0,0.4);
}
.leaflet-container a.leaflet-popup-close-button {
position: absolute;
top: 0;
right: 0;
padding: 4px 4px 0 0;
border: none;
text-align: center;
width: 18px;
height: 14px;
font: 16px/14px Tahoma, Verdana, sans-serif;
color: #c3c3c3;
text-decoration: none;
font-weight: bold;
background: transparent;
}
.leaflet-container a.leaflet-popup-close-button:hover {
color: #999;
}
.leaflet-popup-scrolled {
overflow: auto;
border-bottom: 1px solid #ddd;
border-top: 1px solid #ddd;
}
.leaflet-oldie .leaflet-popup-content-wrapper {
-ms-zoom: 1;
}
.leaflet-oldie .leaflet-popup-tip {
width: 24px;
margin: 0 auto;
-ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)";
filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678);
}
.leaflet-oldie .leaflet-popup-tip-container {
margin-top: -1px;
}
.leaflet-oldie .leaflet-control-zoom,
.leaflet-oldie .leaflet-control-layers,
.leaflet-oldie .leaflet-popup-content-wrapper,
.leaflet-oldie .leaflet-popup-tip {
border: 1px solid #999;
}
/* div icon */
.leaflet-div-icon {
background: #fff;
border: 1px solid #666;
}
/* Tooltip */
/* Base styles for the element that has a tooltip */
.leaflet-tooltip {
position: absolute;
padding: 6px;
background-color: #fff;
border: 1px solid #fff;
border-radius: 3px;
color: #222;
white-space: nowrap;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
pointer-events: none;
box-shadow: 0 1px 3px rgba(0,0,0,0.4);
}
.leaflet-tooltip.leaflet-clickable {
cursor: pointer;
pointer-events: auto;
}
.leaflet-tooltip-top:before,
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
position: absolute;
pointer-events: none;
border: 6px solid transparent;
background: transparent;
content: "";
}
/* Directions */
.leaflet-tooltip-bottom {
margin-top: 6px;
}
.leaflet-tooltip-top {
margin-top: -6px;
}
.leaflet-tooltip-bottom:before,
.leaflet-tooltip-top:before {
left: 50%;
margin-left: -6px;
}
.leaflet-tooltip-top:before {
bottom: 0;
margin-bottom: -12px;
border-top-color: #fff;
}
.leaflet-tooltip-bottom:before {
top: 0;
margin-top: -12px;
margin-left: -6px;
border-bottom-color: #fff;
}
.leaflet-tooltip-left {
margin-left: -6px;
}
.leaflet-tooltip-right {
margin-left: 6px;
}
.leaflet-tooltip-left:before,
.leaflet-tooltip-right:before {
top: 50%;
margin-top: -6px;
}
.leaflet-tooltip-left:before {
right: 0;
margin-right: -12px;
border-left-color: #fff;
}
.leaflet-tooltip-right:before {
left: 0;
margin-left: -12px;
border-right-color: #fff;
}
/*!*************************************************************************************************************!*\
!*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/leaflet.markercluster/dist/MarkerCluster.css ***!
\*************************************************************************************************************/
.leaflet-cluster-anim .leaflet-marker-icon, .leaflet-cluster-anim .leaflet-marker-shadow {
-webkit-transition: -webkit-transform 0.3s ease-out, opacity 0.3s ease-in;
-moz-transition: -moz-transform 0.3s ease-out, opacity 0.3s ease-in;
-o-transition: -o-transform 0.3s ease-out, opacity 0.3s ease-in;
transition: transform 0.3s ease-out, opacity 0.3s ease-in;
}
.leaflet-cluster-spider-leg {
/* stroke-dashoffset (duration and function) should match with leaflet-marker-icon transform in order to track it exactly */
-webkit-transition: -webkit-stroke-dashoffset 0.3s ease-out, -webkit-stroke-opacity 0.3s ease-in;
-moz-transition: -moz-stroke-dashoffset 0.3s ease-out, -moz-stroke-opacity 0.3s ease-in;
-o-transition: -o-stroke-dashoffset 0.3s ease-out, -o-stroke-opacity 0.3s ease-in;
transition: stroke-dashoffset 0.3s ease-out, stroke-opacity 0.3s ease-in;
}
/*!*********************************************************************************************************************!*\
!*** css ./node_modules/css-loader/dist/cjs.js!./node_modules/leaflet.markercluster/dist/MarkerCluster.Default.css ***!
\*********************************************************************************************************************/
.marker-cluster-small {
background-color: rgba(181, 226, 140, 0.6);
}
.marker-cluster-small div {
background-color: rgba(110, 204, 57, 0.6);
}
.marker-cluster-medium {
background-color: rgba(241, 211, 87, 0.6);
}
.marker-cluster-medium div {
background-color: rgba(240, 194, 12, 0.6);
}
.marker-cluster-large {
background-color: rgba(253, 156, 115, 0.6);
}
.marker-cluster-large div {
background-color: rgba(241, 128, 23, 0.6);
}
/* IE 6-8 fallback colors */
.leaflet-oldie .marker-cluster-small {
background-color: rgb(181, 226, 140);
}
.leaflet-oldie .marker-cluster-small div {
background-color: rgb(110, 204, 57);
}
.leaflet-oldie .marker-cluster-medium {
background-color: rgb(241, 211, 87);
}
.leaflet-oldie .marker-cluster-medium div {
background-color: rgb(240, 194, 12);
}
.leaflet-oldie .marker-cluster-large {
background-color: rgb(253, 156, 115);
}
.leaflet-oldie .marker-cluster-large div {
background-color: rgb(241, 128, 23);
}
.marker-cluster {
background-clip: padding-box;
border-radius: 20px;
}
.marker-cluster div {
width: 30px;
height: 30px;
margin-left: 5px;
margin-top: 5px;
text-align: center;
border-radius: 15px;
font: 12px "Helvetica Neue", Arial, Helvetica, sans-serif;
}
.marker-cluster span {
line-height: 30px;
}

9559
js/package-lock.json generated

File diff suppressed because it is too large Load Diff

14
js/package.json

@ -7,13 +7,19 @@
"@flarum/prettier-config": "^1.0.0",
"flarum": "^0.1.0-beta.16",
"flarum-tsconfig": "^1.0.0",
"flarum-webpack-config": "^1.0.0",
"leaflet": "^1.7.1",
"webpack": "^4.26.0",
"webpack-cli": "^3.0.7"
"leaflet.markercluster": "^1.5.3"
},
"devDependencies": {
"prettier": "^2.3.0"
"css-loader": "^6.8.1",
"flarum-webpack-config": "^2.0.0",
"less": "^4.2.0",
"less-loader": "^11.1.3",
"mini-css-extract-plugin": "^2.7.6",
"prettier": "^2.3.0",
"style-loader": "^3.3.3",
"webpack": "^5.0.0",
"webpack-cli": "^5.1.4"
},
"scripts": {
"dev": "webpack --mode development --watch",

17
js/src/forum/components/GlobalMapPage.tsx

@ -6,6 +6,10 @@ function translate(id: string): string {
return app.translator.trans(id) as string;
}
const escapeHtml = (unsafe) => {
return unsafe.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;').replaceAll('"', '&quot;').replaceAll("'", '&#039;');
}
export default class GlobalMapPage extends Page {
oninit(vnode: Mithril.Vnode) {
super.oninit(vnode);
@ -57,7 +61,18 @@ export default class GlobalMapPage extends Page {
accessToken: publicToken,
}).addTo(this.map);
this.map.setView([46, 2], 6);
this.map.setView([47, 2], 6);
app.store.find('user-locations').then((response) => {
let markers = L.markerClusterGroup();
for(let item of response) {
let user = item.data.attributes;
let marker = L.marker([parseFloat(user.location_latitude), parseFloat(user.location_longitude)], { icon: markerIcon });
marker.bindPopup('<a href="/u/'+escapeHtml(user.username)+'">'+escapeHtml(user.displayName)+'</a>');
markers.addLayer(marker);
}
this.map.addLayer(markers);
});
}
} else {
this.map = null;

6
js/src/forum/index.js

@ -8,8 +8,14 @@ import UserCard from 'flarum/forum/components/UserCard';
import HeaderPrimary from 'flarum/forum/components/HeaderPrimary';
import Link from 'flarum/common/components/Link';
import Leaflet from 'leaflet';
import 'leaflet.markercluster';
import GlobalMapPage from './components/GlobalMapPage';
import "./../../../less/forum.less";
import "./../../node_modules/leaflet/dist/leaflet.css";
import "./../../node_modules/leaflet.markercluster/dist/MarkerCluster.css";
import "./../../node_modules/leaflet.markercluster/dist/MarkerCluster.Default.css";
app.initializers.add('justoverclock/users-map-location', (app) => {
User.prototype.location_country = Model.attribute('location_country');
User.prototype.location_countrycode = Model.attribute('location_countrycode');

23
js/webpack.config.js

@ -1 +1,24 @@
const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = require('flarum-webpack-config')();
module.exports.plugins.push(new MiniCssExtractPlugin({filename: '[name].less'}));
module.exports.resolve.extensions.push('.less');
module.exports.module.rules.push({
test: /\.less$/i,
use: [
MiniCssExtractPlugin.loader,
"css-loader",
//"less-loader", // We don't compile less at this stage, flarum already compiles less at runtime. Compiling twice can cause issues.
],
});
module.exports.module.rules.push({
test: /\.css$/i,
use: [
MiniCssExtractPlugin.loader,
"css-loader"
],
});

5545
js/yarn.lock

File diff suppressed because it is too large Load Diff

2
less/forum.less

File diff suppressed because one or more lines are too long
Loading…
Cancel
Save