Browse Source

Merge pull request #3 from justoverclockl/revert-2-revert-1-main

Revert "Revert "improved UI and changed how locations are stored in database""
main
Marco Colia 3 years ago committed by GitHub
parent
commit
ceae4d76f9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      js/dist/admin.js
  2. 2
      js/dist/admin.js.map
  3. 4
      js/dist/forum.js
  4. 2
      js/dist/forum.js.map
  5. 225
      js/src/forum/components/AddLocationComponent.js
  6. 109
      js/src/forum/index.js
  7. 2
      js/tsconfig.json
  8. 10
      less/forum.less
  9. 7
      locale/en.yml
  10. 14
      locale/fr.yml
  11. 30
      migrations/2022_02_15_000000_location_details.php
  12. 7
      src/Listeners/AddLocationAttribute.php
  13. 18
      src/Listeners/SaveLocationToDatabase.php

2
js/dist/admin.js vendored

@ -1,2 +1,2 @@
module.exports=function(t){var e={};function o(n){if(e[n])return e[n].exports;var r=e[n]={i:n,l:!1,exports:{}};return t[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}return o.m=t,o.c=e,o.d=function(t,e,n){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)o.d(n,r,function(e){return t[e]}.bind(null,r));return n},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=11)}([,function(t,e){t.exports=flarum.core.compat["common/extend"]},function(t,e){t.exports=flarum.core.compat["admin/app"]},,,,,,function(t,e){t.exports=flarum.core.compat["admin/components/UserListPage"]},,,function(t,e,o){"use strict";o.r(e);var n=o(2),r=o.n(n),a=o(1),i=o(8),u=o.n(i);r.a.initializers.add("justoverclock/users-map-location",(function(){r.a.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:r.a.translator.trans("justoverclock-users-map-location.admin.mapBox-api-key"),help:r.a.translator.trans("justoverclock-users-map-location.admin.mapBox-api-key-help")}),Object(a.extend)(u.a.prototype,"columns",(function(t){t.add("location",{name:r.a.translator.trans("justoverclock-users-map-location.admin.adminLocationField"),content:function(t){return m("div",null,t.data.attributes.location)}},-50)}))}))}]);
module.exports=function(t){var e={};function o(n){if(e[n])return e[n].exports;var r=e[n]={i:n,l:!1,exports:{}};return t[n].call(r.exports,r,r.exports,o),r.l=!0,r.exports}return o.m=t,o.c=e,o.d=function(t,e,n){o.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:n})},o.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},o.t=function(t,e){if(1&e&&(t=o(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var n=Object.create(null);if(o.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)o.d(n,r,function(e){return t[e]}.bind(null,r));return n},o.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return o.d(e,"a",e),e},o.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},o.p="",o(o.s=12)}({1:function(t,e){t.exports=flarum.core.compat["common/extend"]},12:function(t,e,o){"use strict";o.r(e);var n=o(4),r=o.n(n),a=o(1),i=o(9),u=o.n(i);r.a.initializers.add("justoverclock/users-map-location",(function(){r.a.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:r.a.translator.trans("justoverclock-users-map-location.admin.mapBox-api-key"),help:r.a.translator.trans("justoverclock-users-map-location.admin.mapBox-api-key-help")}),Object(a.extend)(u.a.prototype,"columns",(function(t){t.add("location",{name:r.a.translator.trans("justoverclock-users-map-location.admin.adminLocationField"),content:function(t){return m("div",null,t.data.attributes.location)}},-50)}))}))},4:function(t,e){t.exports=flarum.core.compat["admin/app"]},9:function(t,e){t.exports=flarum.core.compat["admin/components/UserListPage"]}});
//# sourceMappingURL=admin.js.map

2
js/dist/admin.js.map vendored

File diff suppressed because one or more lines are too long

4
js/dist/forum.js vendored

File diff suppressed because one or more lines are too long

2
js/dist/forum.js.map vendored

File diff suppressed because one or more lines are too long

225
js/src/forum/components/AddLocationComponent.js

@ -1,29 +1,234 @@
import app from 'flarum/forum/app';
import Component from 'flarum/Component';
import Switch from 'flarum/common/components/Switch';
export default class AddLocationComponent extends Component {
oninit(vnode) {
super.oninit(vnode);
this.location = app.session.user.location();
this.search_country = app.session.user.location_country() || 'France';
this.search_city = ((app.session.user.location_postcode() || '') + ' ' + (app.session.user.location_city() || '')).trim();
this.location = app.session.user.location_latitude()
? {
lat: app.session.user.location_latitude(),
lon: app.session.user.location_longitude()
}
: null;
//console.log(this.location);
this.enableLocation = this.location != null;
this.map = null;
this.locationMarker = null;
}
view(vnode) {
return (
<fieldset className="Settings-theme">
<legend>{app.translator.trans('justoverclock-users-map-location.forum.location')}</legend>
<p className="location-description">{app.translator.trans('justoverclock-users-map-location.forum.locationDescription')}</p>
<input type="text" className="FormControl location" id="location" name="location" value={this.location} onblur={this.saveValue.bind(this)} />
<Switch state={this.enableLocation} onchange={val => this.setEnableLocation(val)}>{app.translator.trans('justoverclock-users-map-location.forum.enableLocation')}</Switch>
<div className="fieldset-separator"></div>
{ this.enableLocation ? <div>
<label for="search-country">{app.translator.trans('justoverclock-users-map-location.forum.locationCountry')}</label>
<input type="text" className="FormControl search-country" id="search-country" name="search-country" value={this.search_country} onblur={this.countryChanged.bind(this)} />
<div className="fieldset-separator"></div>
<label for="search-city">{app.translator.trans('justoverclock-users-map-location.forum.locationCity')}</label>
<p className="helpText">{app.translator.trans('justoverclock-users-map-location.forum.locationCityDescription')}</p>
<input type="text" className="FormControl search-city" id="search-city" name="search-city" value={this.search_city} onblur={this.cityChanged.bind(this)} />
<div className="fieldset-separator"></div>
{this.location ? <div className="location-map" /> : []}
</div> : [] }
</fieldset>
);
}
saveValue(e) {
const user = app.session.user;
user
.save({
location: e.target.value,
})
.then(app.alerts.show({ type: 'success' }, app.translator.trans('justoverclock-users-map-location.forum.locationSaved')));
setEnableLocation(enable) {
this.enableLocation = enable;
if(this.location && !this.enableLocation) {
this.search_country = '';
this.search_city = '';
this.save();
}
}
oncreate(vnode) {
this.onupdate(vnode);
}
onupdate(vnode) {
let dom = vnode.dom;
let mapElements = dom.getElementsByClassName('location-map');
if(mapElements.length > 0) {
if(!this.map) {
let mapElement = mapElements[0];
const publicToken = app.forum.attribute('justoverclock-users-map-location.mapBox-api-key');
const markerIconPath = app.forum.attribute('baseUrl') + '/assets/extensions/justoverclock-users-map-location/marker-icon.png';
let markerIcon = L.icon({
iconUrl: markerIconPath,
iconSize: [25, 41], // size of the icon
iconAnchor: [13, 40]
});
this.map = L.map(mapElement);
this.locationMarker = L.marker([this.location.lat, this.location.lon], { icon: markerIcon }).addTo(this.map);
let layer = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution:
'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> ' +
'contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>, ' +
'Developed by <a href="https://flarum.it/">Marco Colia</a>',
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: publicToken,
}).addTo(this.map);
this.updateMap();
}
} else {
this.map = null;
this.locationMarker = null;
}
}
updateMap() {
if(this.map && this.location) {
this.map.setView([this.location.lat, this.location.lon], 7)
this.locationMarker.setLatLng([this.location.lat, this.location.lon]);
}
}
countryChanged(e) {
this.search_country = e.target.value.trim();
this.save();
}
cityChanged(e) {
this.search_city = e.target.value.trim();
this.save();
}
save() {
if(this.search_country == '' || this.search_city == '') {
if(this.location) {
const user = app.session.user;
let attributes = {
location_country: null,
location_countrycode: null,
location_postcode: null,
location_city: null,
location_latitude: null,
location_longitude: null
};
user.save(attributes)
.then(() => {
this.search_country = 'France';
this.search_city = '';
this.location = null;
app.alerts.show({ type: 'success' }, app.translator.trans('justoverclock-users-map-location.forum.locationCleared'))
this.updateMap();
});
}
return;
}
let postcodeRegexps = [
'([0-9]{5})', // used in many countries (ex: 75000)
'([0-9]{2} [0-9]{3})', // same, but with a space (ex: 75 000)
'([A-Z0-9]{3} [A-Z0-9]{3})', // Canada (ex: H3B 1M7)
'([0-9]{4})', // used in a lot of small countries
];
let postcode = '';
let city = '';
for(let postcodeReIdx = 0; postcodeReIdx < postcodeRegexps.length; ++postcodeReIdx) {
let postcodeRe = postcodeRegexps[postcodeReIdx];
for(let mode = 0; mode <= 2; ++mode) {
let re;
if(mode == 0) {
re = new RegExp('^' + postcodeRe + '$');
} else {
re = new RegExp('^' + (mode == 1 ? postcodeRe + '[, ]+(.*)' : '(.*)[, ]+' + postcodeRe) + '$');
}
let match = this.search_city.match(re);
if(match) {
if(mode == 0) {
postcode = match[1];
city = '';
} else {
postcode = match[mode == 1 ? 1 : 2];
city = match[mode == 1 ? 2 : 1];
}
break;
}
}
}
if(postcode == '' && city == '')
city = this.search_city;
if(postcode != '') postcode = 'postalcode='+encodeURI(postcode.split(' ').join(''));
if(city != '') city = 'city='+encodeURI(city);
let query = postcode == '' ? city : postcode + (city == '' ? '' : '&' + city);
query += '&country=' + encodeURIComponent(this.search_country);
fetch('https://nominatim.openstreetmap.org/search?' + query + '&format=json&addressdetails=1')
.then((responseText) => responseText.json())
.then((response) => {
//console.log('search reuslts:');
//console.log(response);
let foundResult = false;
for(let idx = 0; idx < response.length; ++idx) {
let result = response[idx];
if((result.class=='place' && result.type=='postcode') || (result.class=='boundary' && result.type=='administrative')) {
//console.log('found valid result:');
//console.log(result);
foundResult = true;
const user = app.session.user;
let attributes = {
location_country: result.address.country,
location_countrycode: result.address.country_code,
location_postcode: result.address.postcode,
location_city: result.address.village || result.address.town || result.address.city || result.address.administrative,
location_latitude: result.lat,
location_longitude: result.lon
};
user.save(attributes)
.then(() => {
this.search_country = attributes.location_country || 'France';
this.search_city = ((attributes.location_postcode || '') + ' ' + (attributes.location_city || '')).trim();
this.location = {
lat: attributes.location_latitude,
lon: attributes.location_longitude
};
app.alerts.show({ type: 'success' }, app.translator.trans('justoverclock-users-map-location.forum.locationSaved'))
this.updateMap();
});
break;
}
}
if(!foundResult) {
app.alerts.show({ type: 'error' }, app.translator.trans('justoverclock-users-map-location.forum.locationNotFound'))
}
});
}
}

109
js/src/forum/index.js

@ -8,84 +8,61 @@ import UserCard from 'flarum/forum/components/UserCard';
import Leaflet from 'leaflet';
app.initializers.add('justoverclock/users-map-location', () => {
User.prototype.location = Model.attribute('location');
User.prototype.location_country = Model.attribute('location_country');
User.prototype.location_countrycode = Model.attribute('location_countrycode');
User.prototype.location_postcode = Model.attribute('location_postcode');
User.prototype.location_city = Model.attribute('location_city');
User.prototype.location_latitude = Model.attribute('location_latitude');
User.prototype.location_longitude = Model.attribute('location_longitude');
extend(UserCard.prototype, 'oncreate', function () {
extend(UserCard.prototype, 'infoItems', function (items) {
const user = this.attrs.user;
let UserLocation = user.location();
const publicToken = app.forum.attribute('justoverclock-users-map-location.mapBox-api-key');
const geocode = 'https://nominatim.openstreetmap.org/search?city=' + UserLocation + '&format=json';
if (UserLocation === '') return;
let GetCoordinates = fetch(geocode)
.then((response) => response.json())
.then((coordinates) => {
this.latitude = coordinates[0].lat;
this.longitude = coordinates[0].lon;
const markerIconPath = app.forum.attribute('baseUrl') + '/assets/extensions/justoverclock-users-map-location/marker-icon.png';
if(user.location_latitude()) {
items.add('mapLocation', <div className="location-map location-map-user-profile"/>, -100);
}
});
let markerIcon = L.icon({
iconUrl: markerIconPath,
iconSize: [28, 45], // size of the icon
});
extend(UserCard.prototype, 'oncreate', function (originalResult, vnode) {
const user = this.attrs.user;
let map2 = L.map('map2').setView([this.latitude, this.longitude], 13);
let layerUserCard = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution:
'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>, Developed by <a href="https://flarum.it/">Marco Colia</a>',
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: publicToken,
}).addTo(map2);
});
});
extend(SettingsPage.prototype, 'oncreate', function () {
const location = app.session.user.location();
const publicToken = app.forum.attribute('justoverclock-users-map-location.mapBox-api-key');
const geocode = 'https://nominatim.openstreetmap.org/search?city=' + location + '&format=json';
let location = user.location_latitude()
? {
lat: user.location_latitude(),
lon: user.location_longitude()
}
: null;
if (location === '') return;
if (!location) return;
let GetCoordinates = fetch(geocode)
.then((response) => response.json())
.then((coordinates) => {
this.latitude = coordinates[0].lat;
this.longitude = coordinates[0].lon;
let mapElement = vnode.dom.getElementsByClassName('location-map')[0];
const markerIconPath = app.forum.attribute('baseUrl') + '/assets/extensions/justoverclock-users-map-location/marker-icon.png';
const publicToken = app.forum.attribute('justoverclock-users-map-location.mapBox-api-key');
const markerIconPath = app.forum.attribute('baseUrl') + '/assets/extensions/justoverclock-users-map-location/marker-icon.png';
let markerIcon = L.icon({
iconUrl: markerIconPath,
iconSize: [28, 45], // size of the icon
});
let markerIcon = L.icon({
iconUrl: markerIconPath,
iconSize: [25, 41], // size of the icon
iconAnchor: [13, 40]
});
let map = L.map('map').setView([this.latitude, this.longitude], 13);
let marker = L.marker([this.latitude, this.longitude], { icon: markerIcon }).addTo(map);
let layer = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution:
'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> ' +
'contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>, ' +
'Developed by <a href="https://flarum.it/">Marco Colia</a>',
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: publicToken,
}).addTo(map);
});
let map = L.map(mapElement).setView([location.lat, location.lon], 13);
let layerUserCard = L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token={accessToken}', {
attribution:
'Map data &copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>, Developed by <a href="https://flarum.it/">Marco Colia</a>',
maxZoom: 18,
id: 'mapbox/streets-v11',
tileSize: 512,
zoomOffset: -1,
accessToken: publicToken,
}).addTo(map);
});
extend(SettingsPage.prototype, 'settingsItems', function (items) {
items.add('location', <AddLocationComponent />);
items.add('mapDiv', <div className="map-div" id="map" />);
});
extend(UserCard.prototype, 'infoItems', function (items) {
const user = this.attrs.user;
let UserLocation = user.location();
if (UserLocation === '') return;
items.add('mapLocation', <div className="map-div" id="map2" />, -100);
});
});
export {
AddLocationComponent
}

2
js/tsconfig.json

@ -1,6 +1,6 @@
{
"extends": "flarum-tsconfig",
"include": ["src/**/*"],
"include": ["src/**/*", "../vendor/flarum/core/js/dist-typings/@types/**/*"],
"compilerOptions": {
"declarationDir": "./dist-typings",
"baseUrl": ".",

10
less/forum.less

File diff suppressed because one or more lines are too long

7
locale/en.yml

@ -4,6 +4,11 @@ justoverclock-users-map-location:
mapBox-api-key: MapBox Public Token
mapBox-api-key-help: "retrieve your free public token on <a>https://account.mapbox.com/</a>"
forum:
locationDescription: Here you can setup your location. Be sure to specify your City name only.
location: Location
enableLocation: Display my location on the members map
locationCity: City
locationCityDescription: Indicate your city name, postal code, or both
locationCountry: Country
locationSaved: Location saved successfully!
locationNotFound: Location not found
locationCleared: Your location has been deleted

14
locale/fr.yml

@ -0,0 +1,14 @@
justoverclock-users-map-location:
admin:
adminLocationField: Localisation
mapBox-api-key: Jeton public MapBox
mapBox-api-key-help: "Créez votre accès MapBox gratuit sur <a>https://account.mapbox.com/</a>"
forum:
location: Localisation
enableLocation: Afficher ma localisation sur la carte des membres
locationCity: Ville
locationCityDescription: Indiquez votre commune, code postal, ou les deux
locationCountry: Pays
locationSaved: Localisation sauvegardée !
locationNotFound: Ville ou commune non trouvée dans ce pays
locationCleared: Votre localisation a été supprimée

30
migrations/2022_02_15_000000_location_details.php

@ -0,0 +1,30 @@
<?php
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Schema\Builder;
return [
'up' => function (Builder $schema) {
$schema->table('users', function (Blueprint $table) use ($schema) {
$table->decimal('location_latitude', $precision = 9, $scale = 6)->nullable();
$table->decimal('location_longitude', $precision = 9, $scale = 6)->nullable();
$table->text('location_countrycode')->nullable();
$table->text('location_country')->nullable();
$table->text('location_postcode')->nullable();
$table->text('location_city')->nullable();
$table->dropColumn('location');
});
},
'down' => function (Builder $schema) {
$schema->table('users', function (Blueprint $table) {
$table->text('location');
$table->dropColumn('location_city');
$table->dropColumn('location_postcode');
$table->dropColumn('location_country');
$table->dropColumn('location_countrycode');
$table->dropColumn('location_longitude');
$table->dropColumn('location_latitude');
});
},
];

7
src/Listeners/AddLocationAttribute.php

@ -11,7 +11,12 @@ class AddLocationAttribute
{
$actor = $serializer->getActor();
$attributes['location'] = $user->location;
$attributes['location_city'] = $user->location_city;
$attributes['location_postcode'] = $user->location_postcode;
$attributes['location_countrycode'] = $user->location_countrycode;
$attributes['location_country'] = $user->location_country;
$attributes['location_longitude'] = $user->location_longitude;
$attributes['location_latitude'] = $user->location_latitude;
return $attributes;
}

18
src/Listeners/SaveLocationToDatabase.php

@ -17,11 +17,25 @@ class SaveLocationToDatabase
$canEdit = $actor->can('edit', $user);
$attributes = Arr::get($data, 'attributes', []);
if (isset($attributes['location'])) {
if(array_key_exists('location_latitude', $attributes)) {
if (!$isSelf) {
$actor->assertPermission($canEdit);
}
$user->location = $attributes['location'];
if(!isset($attributes['location_latitude']) || !isset($attributes['location_longitude'])) {
$user->location_city = null;
$user->location_postcode = null;
$user->location_countrycode = null;
$user->location_country = null;
$user->location_latitude = null;
$user->location_longitude = null;
} else {
$user->location_city = $attributes['location_city'];
$user->location_postcode = $attributes['location_postcode'];
$user->location_countrycode = $attributes['location_countrycode'];
$user->location_country = $attributes['location_country'];
$user->location_latitude = $attributes['location_latitude'];
$user->location_longitude = $attributes['location_longitude'];
}
}
}
}

Loading…
Cancel
Save