This commit is contained in:
Emanuel Mutschlechner
2018-08-30 01:21:38 +02:00
commit c7c7694ac4
32 changed files with 23196 additions and 0 deletions

16
.editorconfig Normal file
View File

@@ -0,0 +1,16 @@
root = true
[*]
charset = utf-8
end_of_line = lf
insert_final_newline = true
indent_style = space
indent_size = 4
trim_trailing_whitespace = true
[*.md]
trim_trailing_whitespace = false
[*.yml]
indent_style = space
indent_size = 2

15
.gitattributes vendored Normal file
View File

@@ -0,0 +1,15 @@
* text=auto
/tests export-ignore
.editorconfig export-ignore
.gitattributes export-ignore
.gitignore export-ignore
*.css linguist-vendored
*.scss linguist-vendored
*.js linguist-vendored
*.jpg binary
*.png binary
*.gif binary
*.ico binary

51
.gitignore vendored Normal file
View File

@@ -0,0 +1,51 @@
/.idea
/.vscode
.phpunit.result.cache
### Composer
/vendor
composer.phar
### Node
/node_modules
/package-lock.json
npm-debug.log*
.npm/
.eslintcache
.node_repl_history
### Windows
Thumbs.db
ehthumbs.db
Desktop.ini
$RECYCLE.BIN/
*.cab
*.msi
*.msm
*.msp
*.lnk
### macOS
*.DS_Store
.AppleDouble
.LSOverride
._*
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk
### Linux
*~
.fuse_hidden*
.directory
.Trash-*
.nfs*

77
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,77 @@
# Contributing
Contributions are **welcome** and will be fully **credited**.
Please read and understand the contribution guide before creating an issue or
pull request.
## Etiquette
This project is open source, and as such, the maintainers give their free time
to build and maintain the source code held within. They make the code freely
available in the hope that it will be of use to other developers. It would be
extremely unfair for them to suffer abuse or anger for their hard work.
Please be considerate towards maintainers when raising issues or presenting
pull requests. Let's show the world that developers are civilized and selfless
people.
It's the duty of the maintainer to ensure that all submissions to the project
are of sufficient quality to benefit the project. Many developers have
different skillsets, strengths, and weaknesses. Respect the maintainer's
decision, and do not be upset or abusive if your submission is not used.
## Viability
When requesting or submitting new features, first consider whether it might be
useful to others. Open source projects are used by many developers, who may
have entirely different needs to your own. Think about whether or not your
feature is likely to be used by other users of the project.
## Procedure
Before filing an issue:
- Attempt to replicate the problem, to ensure that it wasn't a coincidental
incident.
- Check to make sure your feature suggestion isn't already present within the
project.
- Check the pull requests tab to ensure that the bug doesn't have a fix in
progress.
- Check the pull requests tab to ensure that the feature isn't already in
progress.
Before submitting a pull request:
- Check the codebase to ensure that your feature doesn't already exist.
- Check the pull requests to ensure that another person hasn't already
submitted the feature or fix.
## Requirements
If the project maintainer has any additional requirements, you will find them
listed here.
- **[PSR-2 Coding Standard](https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-2-coding-style-guide.md)** - The easiest way to apply the conventions is to install [PHP Code Sniffer](https://pear.php.net/package/PHP_CodeSniffer).
- **Add tests!** - Your patch won't be accepted if it doesn't have tests.
- **Document any change in behaviour** - Make sure the `README.md` and any
other relevant documentation are kept up-to-date.
- **Consider our release cycle** - We try to follow [SemVer v2.0.0](https://semver.org/).
Randomly breaking public APIs is not an option.
- **One pull request per feature** - If you want to do more than one thing,
send multiple pull requests.
- **Send coherent history** - Make sure each individual commit in your pull
request is meaningful. If you had to make multiple intermediate commits while
developing, please [squash them](https://www.git-scm.com/book/en/v2/Git-Tools-Rewriting-History#Changing-Multiple-Commit-Messages)
before submitting.
**Happy coding**!

21
LICENSE.md Normal file
View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018-present Go NoWare
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

65
README.md Normal file
View File

@@ -0,0 +1,65 @@
Publish assets to `public/vendor/maps/{css,js}`
```bash
php artisan vendor:publish --provider="GoNoWare\Maps\MapsServiceProvider" --tag=maps
```
Publish config to `config/vendor/maps.php`
```bash
php artisan vendor:publish --provider="GoNoWare\Maps\MapsServiceProvider" --tag=config
```
Add styles to `</head>`
```php
@mapstyles
```
Add scripts before `</body>`
```php
@mapscripts
```
Show map
```php
@map([
'lat' => '51',
'lng' => '0',
'zoom' => '5',
])
```
Show map with one marker
```php
@map([
'lat' => '51',
'lng' => '0',
'zoom' => '5',
'markers' => [[
'lat' => '51',
'lng' => '0',
]],
])
```
Show map with two markers
```php
@map([
'lat' => '48.134664',
'lng' => '11.555220',
'zoom' => '13',
'markers' => [[
'lat' => '48.134664',
'lng' => '11.555220',
], [
'lat' => 11,
'lng' => 11,
]],
])
```
Adjust map height
```css
.map-container {
height: 500px;
}
```

73
composer.json Normal file
View File

@@ -0,0 +1,73 @@
{
"name": "gonoware/laravel-maps",
"description": "A Laravel 5 package to add Google Maps to your application",
"keywords": [
"gonoware",
"google",
"maps",
"laravel",
"tracking"
],
"homepage": "https://gitlab.com/gonoware/laravel-maps",
"support": {
"issues": "https://gitlab.com/gonoware/laravel-maps/issues",
"source": "https://gitlab.com/gonoware/laravel-maps"
},
"license": "MIT",
"authors": [
{
"name": "Emanuel Mutschlechner",
"email": "em@gonoware.com"
},
{
"name": "Benedikt Tuschter",
"email": "bt@gonoware.com"
}
],
"type": "library",
"require": {
"php": ">=7.0.0|>=7.1.3",
"illuminate/support": "^5.5|^5.6"
},
"require-dev": {
"mockery/mockery": "^1.0",
"phpunit/phpunit": "~6.0|~7.0"
},
"autoload": {
"psr-4": {
"GoNoWare\\Maps\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"Tests\\": "tests/"
}
},
"extra": {
"branch-alias": {
"dev-master": "1.0.x-dev"
},
"laravel": {
"providers": [
"GoNoWare\\Maps\\MapsServiceProvider"
]
}
},
"scripts": {
"build-script": [
"yarn install",
"yarn run build"
],
"post-install-cmd": [
"@build-script"
],
"post-update-cmd": [
"@build-script"
]
},
"config": {
"sort-packages": true
},
"minimum-stability": "dev",
"prefer-stable": true
}

1989
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

68
config/maps.php Normal file
View File

@@ -0,0 +1,68 @@
<?php
/*
TODO:
https://www.bing.com/maps/embed-a-map
https://developers.google.com/maps/documentation/maps-static/intro
https://wiki.openstreetmap.org/wiki/OpenLinkMap#Embed_map_in_another_website
embed via iframe:
- bing
- osm?
javascript api:
- all
*/
return [
/*
|----------------------------------------------------------------------
| Map Default
|----------------------------------------------------------------------
|
| TODO
| Available maps: 'google', 'osm', 'bing', 'mapkit'
|
*/
'default' => 'osm',
/*
|--------------------------------------------------------------------------
| Maps Enabled
|--------------------------------------------------------------------------
|
| By default, Maps is enabled. You can set the value to false to disable
| rendering of the map.
|
*/
'enabled' => env('MAPS_ENABLED', true),
'maps' => [
'google' => [
// https://developers.google.com/maps/documentation/javascript/get-api-key
// https://developers.google.com/maps/documentation/embed/get-api-key
'key' => env('MAPS_GOOGLE_KEY'),
],
'bing' => [
// https://msdn.microsoft.com/en-us/library/ff428642.aspx
// https://www.bingmapsportal.com
'key' => env('MAPS_BING_KEY'),
],
'osm' => [
'tiles' => 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
],
'mapkit' => [
// https://developer.apple.com/videos/play/wwdc2018/508
'key' => env('MAPS_MAPKIT_KEY'),
],
],
];

25
package.json Normal file
View File

@@ -0,0 +1,25 @@
{
"private": true,
"scripts": {
"build": "rimraf public && cross-env NODE_ENV=production node_modules/webpack/bin/webpack.js --no-progress --hide-modules --config=node_modules/laravel-mix/setup/webpack.config.js"
},
"devDependencies": {
"cross-env": "^5.2.0",
"laravel-mix": "^2.1.11"
},
"browserslist": [
"last 1 version",
"> 1%",
"Chrome >= 45",
"Firefox >= 38",
"Edge >= 12",
"Explorer >= 10",
"iOS >= 9",
"Safari >= 9",
"Android >= 4.4",
"Opera >= 30"
],
"dependencies": {
"leaflet-bing-layer": "^3.3.0"
}
}

1
public/css/index.css vendored Normal file
View File

@@ -0,0 +1 @@
.map-container{position:relative;height:300px}@media (min-width:992px){.map-container{height:450px}}.map-container.fade{opacity:0;transition:opacity 195ms ease-out}.map-container.fade.in{opacity:1;transition:opacity 225ms ease-in}.map-container>.map{height:inherit}.mk-map-view>.syrup-canvas{margin-left:-50%}

BIN
public/img/marker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

1
public/js/index.js vendored Normal file

File diff suppressed because one or more lines are too long

5
public/mix-manifest.json Normal file
View File

@@ -0,0 +1,5 @@
{
"/js/index.js": "/js/index.js?id=0c46454e9798f21c0806",
"/css/index.css": "/css/index.css?id=c9b47a0c3100d6dc46ed",
"/img/marker.png": "/img/marker.png?id=654ced713d12ed4ae55d"
}

BIN
resources/img/marker.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 882 B

41
resources/js/index.js vendored Normal file
View File

@@ -0,0 +1,41 @@
import google from './types/google';
import osm from './types/osm';
import bing from './types/bing';
import mapkit from './types/mapkit';
import parser from './utils/parser';
import {isDefined} from './utils/helper';
const createMap = (element, createMap, createMarker) => {
if (!isDefined(element)) {
return;
}
const mapData = parser.map(element);
const map = createMap(element, mapData);
mapData.markers.forEach(markerData => {
if (!isDefined(map)) {
return;
}
createMarker(map, markerData);
})
};
const createMapType = map => {
const createMapType = element => createMap(
element,
map.createMap,
map.createMarker,
);
const selector = `[data-map-type="${map.type}"]`;
const elements = document.querySelectorAll(selector) || [];
elements.forEach(createMapType);
};
window.onGoogleMapsReady = () => createMapType(google);
(() => createMapType(osm))();
(() => createMapType(bing))();
(() => createMapType(mapkit))();

14109
resources/js/types/asd.js vendored Normal file

File diff suppressed because one or more lines are too long

45
resources/js/types/bing.js vendored Normal file
View File

@@ -0,0 +1,45 @@
import {fadeElementIn, isDefined, openLink} from '../utils/helper';
import 'leaflet-bing-layer';
// TODO: locales/culture
export default {
type: 'bing',
createMap(element, mapData) {
if (!isDefined(window.L)) {
return;
}
const {lat, lng, zoom, key} = mapData;
const map = window.L
.map(element, {})
.on('load', () => {
fadeElementIn(element);
})
.setView([lat, lng], zoom);
console.log(key);
window.L.tileLayer
.bing({
bingMapsKey: key,
imagerySet: 'CanvasLight',
})
.addTo(map);
return map;
},
createMarker(map, markerData) {
const {lat, lng, url} = markerData;
const marker = window.L
.marker([lat, lng])
.addTo(map);
if (url) {
marker.addEventListener('click', () => {
openLink(url);
});
}
},
}

46
resources/js/types/google.js vendored Normal file
View File

@@ -0,0 +1,46 @@
import {fadeElementIn, isDefined, openLink} from '../utils/helper';
export default {
type: 'google',
createMap(element, mapData) {
if (!isDefined(window.google)) {
return;
}
if (!isDefined(window.google.maps)) {
return;
}
const {lat, lng, zoom} = mapData;
const map = new window.google.maps.Map(element, {
center: new window.google.maps.LatLng(lat, lng),
zoom: zoom,
mapTypeId: window.google.maps.MapTypeId.ROADMAP,
});
window.google.maps.event.addListenerOnce(map, 'idle', () => {
fadeElementIn(element);
});
return map;
},
createMarker(map, markerData) {
const {lat, lng, url} = markerData;
const marker = new window.google.maps.Marker({
position: new window.google.maps.LatLng(lat, lng),
map: map,
title: 'Test Title', // TODO
draggable: false,
// icon: {
// url: markerConfig.mapMarkerImg,
// },
});
if (url) {
marker.addListener('click', () => {
openLink(url);
});
}
},
};

50
resources/js/types/mapkit.js vendored Normal file
View File

@@ -0,0 +1,50 @@
import {fadeElementIn, isDefined} from '../utils/helper';
export default {
type: 'mapkit',
createMap(element, mapData) {
if (!isDefined(window.mapkit)) {
return;
}
const {lat, lng, zoom, key} = mapData;
window.mapkit.init({
authorizationCallback(done) {
/*
const xhr = new XMLHttpRequest();
xhr.open('GET', '/services/jwt');
xhr.addEventListener('load', function() {
done(this.responseText);
});
xhr.send();
*/
done(key);
},
});
window.mapkit.addEventListener('configuration-change', event => {
if (event.status === 'Initialized') {
fadeElementIn(element);
}
});
const map = new window.mapkit.Map(element);
const delta = Math.exp(Math.log(360) - (zoom * Math.LN2)); // TODO: zoom to delta not working
map.region = new window.mapkit.CoordinateRegion(
new window.mapkit.Coordinate(lat, lng),
new window.mapkit.CoordinateSpan(delta, delta),
);
return map;
},
createMarker(map, markerData) {
const {lat, lng, url} = markerData;
const coordinate = new window.mapkit.Coordinate(lat, lng);
const marker = new window.mapkit.MarkerAnnotation(coordinate, {
title: 'Test title',
});
map.showItems([marker]); // TODO: map auto resize bugging if multiple markers
},
};

46
resources/js/types/osm.js vendored Normal file
View File

@@ -0,0 +1,46 @@
import {fadeElementIn, isDefined, openLink} from '../utils/helper';
// TODO maybe add this https://github.com/elmarquis/Leaflet.GestureHandling/
// TODO add config for different styles like database connections: https://wiki.openstreetmap.org/wiki/Tile_servers
// http://leaflet-extras.github.io/leaflet-providers/preview/
// TODO custom icons: https://leafletjs.com/examples/custom-icons/
export default {
type: 'osm',
createMap(element, mapData) {
if (!isDefined(window.L)) {
return;
}
const {lat, lng, zoom} = mapData;
const map = window.L
.map(element, {})
.on('load', () => {
fadeElementIn(element);
})
.setView([lat, lng], zoom);
window.L
.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
})
.addTo(map);
return map;
},
createMarker(map, markerData) {
const {lat, lng, url} = markerData;
const marker = window.L
.marker([lat, lng])
.addTo(map);
if (url) {
marker.addEventListener('click', () => {
openLink(url);
});
}
},
}

5
resources/js/utils/helper.js vendored Normal file
View File

@@ -0,0 +1,5 @@
export const isDefined = object => typeof object !== 'undefined';
export const fadeElementIn = element => element.closest('.fade').classList.add('in');
export const openLink = url => window.open(url, '_blank');

29
resources/js/utils/parser.js vendored Normal file
View File

@@ -0,0 +1,29 @@
const parseMarker = marker => {
const lat = parseFloat(marker.lat);
const lng = parseFloat(marker.lng);
const url = marker.url;
return {
lat,
lng,
url,
};
};
export default {
map(element) {
const lat = parseFloat(element.dataset.mapLat);
const lng = parseFloat(element.dataset.mapLng);
const zoom = parseInt(element.dataset.mapZoom);
const key = element.dataset.mapKey;
const markers = (JSON.parse(element.dataset.mapMarkers) || []).map(parseMarker);
return {
lat,
lng,
zoom,
key,
markers,
};
},
}

27
resources/sass/index.scss vendored Normal file
View File

@@ -0,0 +1,27 @@
.map-container {
position: relative;
height: 300px;
@media (min-width: 992px) {
height: 450px;
}
&.fade {
opacity: 0;
transition: opacity 195ms ease-out;
&.in {
opacity: 1;
transition: opacity 225ms ease-in;
}
}
> .map {
height: inherit;
}
}
// Fix Mapkit canvas
.mk-map-view {
> .syrup-canvas {
margin-left: -50%;
}
}

View File

@@ -0,0 +1,23 @@
@if ($enabled)
<div class="map-container fade">
<div class="map" data-map-key="{{ $key }}" data-map-type="{{ $type }}" data-map-lat="{{ $lat }}" data-map-lng="{{ $lng }}" data-map-zoom="{{ $zoom }}" data-map-markers="{{ json_encode($markers) }}"></div>
</div>
{{--
<div class="col-lg-12"></div>
<div class="clear-fix"></div>
<div class="col-lg-12"></div>
<div class="clear-fix"></div>
<iframe class="map" width="800" height="450" frameborder="0" style="border:0" src="https://www.google.com/maps/embed/v1/place?key={{ $key ?? '' }}&q={{ $lat }},{{ $lng }}&center={{ $lat }},{{ $lng }}&zoom={{ $zoom }}" scrolling="no">
</iframe>
<div class="col-lg-12"></div>
<div class="clear-fix"></div>
<div class="map-container fade in">
<iframe class="map" width="800" height="800" frameborder="0" style="border:0" src="https://www.bing.com/maps/embed?h=800&w=800&cp={{ $lat }}~{{ $lng }}&lvl={{ $zoom }}&typ=d&sty=r&src=SHELL&FORM=MBEDV8" scrolling="no">
</iframe>
</div>
--}}
@endif

View File

@@ -0,0 +1,16 @@
@if ($enabled)
{{--TODO: If overriding type via @map() then type is not working--}}
@if ($type == 'osm' || $type == 'bing')
<script src="https://unpkg.com/leaflet@1.3.4/dist/leaflet.js"
integrity="sha512-nMMmRyTVoLYqjP9hrbed9S+FzjZHW5gY1TWCHA5ckwXZBadntCNs8kEqAWdrb9O7rxbCaA4lKTIWjDXZxflOcA=="
crossorigin="" async defer></script>
{{-- TODO check if bing needs polyfill: https://github.com/digidem/leaflet-bing-layer--}}
@endif
@if ($type == 'mapkit')
<script src="https://cdn.apple-mapkit.com/mk/5.x.x/mapkit.js" async defer></script>
@endif
<script src="{{ asset(mix('js/index.js', 'vendor/maps')) }}" type="text/javascript"></script>
@if($type == 'google')
<script src="https://maps-api-ssl.google.com/maps/api/js?v=3&ie=UTF8&oe=UTF8&key={{ $key }}&language={{ app()->getLocale() }}&callback=onGoogleMapsReady" async defer></script>
@endif
@endif

View File

@@ -0,0 +1,8 @@
@if ($enabled)
@if($type == 'osm' || $type == 'bing')
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.3.4/dist/leaflet.css"
integrity="sha512-puBpdR0798OZvTTbP4A8Ix/l+A4dHDD0DGqYW6RQ+9jxkRFclaxxQb/SJAWZfWAkuyeQUytO7+7N4QKrDh+drA=="
crossorigin=""/>
@endif
<link rel="stylesheet" href="{{ asset(mix('css/index.css', 'vendor/maps')) }}" type="text/css">
@endif

View File

@@ -0,0 +1,82 @@
<?php
namespace GoNoWare\Maps;
use Illuminate\Support\Facades\Blade;
use Illuminate\Support\ServiceProvider as BaseServiceProvider;
class MapsServiceProvider extends BaseServiceProvider
{
/**
* Bootstrap services.
*
* @return void
*/
public function boot()
{
$this->publishFiles();
$this->loadViewsFrom(__DIR__ . '/../resources/views', 'maps');
view()->composer('maps::*', function ($view) {
$type = $view->type ?? config('vendor.maps.default');
$enabled = $view->enabled ?? config('vendor.maps.enabled');
$key = config('vendor.maps.maps.' . $type . '.key');
// TODO: Warn missing key?
return $view->with(compact(
'type',
'enabled',
'key'
));
});
view()->composer('maps::index', function ($view) {
$lat = $view->lat ?? config('vendor.maps.lat');
$lng = $view->lng ?? config('vendor.maps.lng');
$zoom = $view->zoom ?? config('vendor.maps.zoom');
$markers = $view->markers ?? config('vendor.maps.markers');
return $view->with(compact(
'lat',
'lng',
'zoom',
'markers'
));
});
}
/**
* Register services.
*
* @return void
*/
public function register()
{
$this->mergeConfigFrom(__DIR__ . '/../config/maps.php', 'vendor.maps');
Blade::include('maps::styles', 'mapstyles');
Blade::include('maps::scripts', 'mapscripts');
Blade::include('maps::index', 'map');
}
/**
* Publish files.
*
* @return void
*/
private function publishFiles()
{
if ($this->app->runningInConsole()) {
$this->publishes([
__DIR__ . '/../config/maps.php' => config_path('vendor/maps.php'),
], 'config');
$this->publishes([
__DIR__ . '/../public' => public_path('vendor/maps'),
], 'public');
$this->publishes([
__DIR__ . '/../public' => public_path('vendor/maps'),
], 'maps');
}
}
}

16
styleci.yml Normal file
View File

@@ -0,0 +1,16 @@
preset: laravel
linting: true
enabled:
- alpha_ordered_imports
disabled:
- length_ordered_imports
finder:
exclude:
- "node_modules"
- "public"
- "tests"
- "vendor"

0
tests/.gitkeep Normal file
View File

9
webpack.mix.js vendored Normal file
View File

@@ -0,0 +1,9 @@
const mix = require('laravel-mix');
mix.setPublicPath('public')
.setResourceRoot('resources')
.js('resources/js/index.js', 'js')
.sass('resources/sass/index.scss', 'css', {precision: 8})
.copy('resources/img/marker.png', 'public/img')
.version('img');

6237
yarn.lock Normal file

File diff suppressed because it is too large Load Diff