commit 97065c0377e268af866c81149a942cdebdea6adc Author: Lasse S. Haslev Date: Sun Oct 25 18:34:21 2020 +0100 First commit. diff --git a/.gitignore b/.gitignore new file mode 100755 index 0000000..b817577 --- /dev/null +++ b/.gitignore @@ -0,0 +1,10 @@ +/.idea +/vendor +/node_modules +package-lock.json +composer.phar +composer.lock +phpunit.xml +.phpunit.result.cache +.DS_Store +Thumbs.db diff --git a/composer.json b/composer.json new file mode 100755 index 0000000..dfc0768 --- /dev/null +++ b/composer.json @@ -0,0 +1,29 @@ +{ + "name": "lassehaslev/nova-map-fields", + "description": "A Laravel Nova field.", + "keywords": [ + "laravel", + "nova" + ], + "license": "MIT", + "require": { + "php": ">=7.1.0" + }, + "autoload": { + "psr-4": { + "Lassehaslev\\NovaMapFields\\": "src/" + } + }, + "extra": { + "laravel": { + "providers": [ + "Lassehaslev\\NovaMapFields\\FieldServiceProvider" + ] + } + }, + "config": { + "sort-packages": true + }, + "minimum-stability": "dev", + "prefer-stable": true +} diff --git a/dist/css/field.css b/dist/css/field.css new file mode 100755 index 0000000..e69de29 diff --git a/dist/images/vendor/leaflet/dist/layers-2x.png b/dist/images/vendor/leaflet/dist/layers-2x.png new file mode 100755 index 0000000..200c333 Binary files /dev/null and b/dist/images/vendor/leaflet/dist/layers-2x.png differ diff --git a/dist/images/vendor/leaflet/dist/layers.png b/dist/images/vendor/leaflet/dist/layers.png new file mode 100755 index 0000000..1a72e57 Binary files /dev/null and b/dist/images/vendor/leaflet/dist/layers.png differ diff --git a/dist/images/vendor/leaflet/dist/marker-icon.png b/dist/images/vendor/leaflet/dist/marker-icon.png new file mode 100755 index 0000000..950edf2 Binary files /dev/null and b/dist/images/vendor/leaflet/dist/marker-icon.png differ diff --git a/dist/js/field.js b/dist/js/field.js new file mode 100755 index 0000000..8310493 --- /dev/null +++ b/dist/js/field.js @@ -0,0 +1,25553 @@ +/******/ (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, { +/******/ configurable: false, +/******/ enumerable: true, +/******/ get: getter +/******/ }); +/******/ } +/******/ }; +/******/ +/******/ // 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 = 3); +/******/ }) +/************************************************************************/ +/******/ ([ +/* 0 */ +/***/ (function(module, exports) { + +/* globals __VUE_SSR_CONTEXT__ */ + +// IMPORTANT: Do NOT use ES2015 features in this file. +// This module is a runtime utility for cleaner component module output and will +// be included in the final webpack user bundle. + +module.exports = function normalizeComponent ( + rawScriptExports, + compiledTemplate, + functionalTemplate, + injectStyles, + scopeId, + moduleIdentifier /* server only */ +) { + var esModule + var scriptExports = rawScriptExports = rawScriptExports || {} + + // ES6 modules interop + var type = typeof rawScriptExports.default + if (type === 'object' || type === 'function') { + esModule = rawScriptExports + scriptExports = rawScriptExports.default + } + + // Vue.extend constructor export interop + var options = typeof scriptExports === 'function' + ? scriptExports.options + : scriptExports + + // render functions + if (compiledTemplate) { + options.render = compiledTemplate.render + options.staticRenderFns = compiledTemplate.staticRenderFns + options._compiled = true + } + + // functional template + if (functionalTemplate) { + options.functional = true + } + + // scopedId + if (scopeId) { + options._scopeId = scopeId + } + + var hook + if (moduleIdentifier) { // server build + hook = function (context) { + // 2.3 injection + context = + context || // cached call + (this.$vnode && this.$vnode.ssrContext) || // stateful + (this.parent && this.parent.$vnode && this.parent.$vnode.ssrContext) // functional + // 2.2 with runInNewContext: true + if (!context && typeof __VUE_SSR_CONTEXT__ !== 'undefined') { + context = __VUE_SSR_CONTEXT__ + } + // inject component styles + if (injectStyles) { + injectStyles.call(this, context) + } + // register component module identifier for async chunk inferrence + if (context && context._registeredComponents) { + context._registeredComponents.add(moduleIdentifier) + } + } + // used by ssr in case component is cached and beforeCreate + // never gets called + options._ssrRegister = hook + } else if (injectStyles) { + hook = injectStyles + } + + if (hook) { + var functional = options.functional + var existing = functional + ? options.render + : options.beforeCreate + + if (!functional) { + // inject component registration as beforeCreate hook + options.beforeCreate = existing + ? [].concat(existing, hook) + : [hook] + } else { + // for template-only hot-reload because in that case the render fn doesn't + // go through the normalizer + options._injectStyles = hook + // register for functioal component in vue file + options.render = function renderWithStyleInjection (h, context) { + hook.call(context) + return existing(h, context) + } + } + } + + return { + esModule: esModule, + exports: scriptExports, + options: options + } +} + + +/***/ }), +/* 1 */ +/***/ (function(module, exports, __webpack_require__) { + +!function(t,e){ true?module.exports=e(__webpack_require__(26)):"function"==typeof define&&define.amd?define(["leaflet"],e):"object"==typeof exports?exports.Vue2Leaflet=e(require("leaflet")):t.Vue2Leaflet=e(t.L)}(window,function(t){return function(t){var e={};function n(i){if(e[i])return e[i].exports;var r=e[i]={i:i,l:!1,exports:{}};return t[i].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var r in t)n.d(i,r,function(e){return t[e]}.bind(null,r));return i},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=53)}([function(t,e,n){"use strict";n.r(e);var i=n(51),r=n.n(i);e.default=function(t,e,n,i){for(var o=r()(n),s=function(){var i=o[a],r="set"+function(t){return t.charAt(0).toUpperCase()+t.slice(1)}(i),s=n[i].type===Object||n[i].type===Array||Array.isArray(n[i].type);n[i].custom?t.$watch(i,function(e,n){t[r](e,n)},{deep:s}):"setOptions"===r?t.$watch(i,function(t,n){L.setOptions(e,t)},{deep:s}):t.$watch(i,function(t,n){e[r](t)},{deep:s})},a=0;au;)i(a,n=e[u++])&&(~o(c,n)||c.push(n));return c}},function(t,e,n){var i=n(43);t.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==i(t)?t.split(""):Object(t)}},function(t,e){var n={}.toString;t.exports=function(t){return n.call(t).slice(8,-1)}},function(t,e){var n=Math.ceil,i=Math.floor;t.exports=function(t){return isNaN(t=+t)?0:(t>0?i:n)(t)}},function(t,e,n){var i=n(30)("keys"),r=n(19);t.exports=function(t){return i[t]||(i[t]=r(t))}},function(t,e,n){t.exports=!n(12)&&!n(13)(function(){return 7!=Object.defineProperty(n(47)("div"),"a",{get:function(){return 7}}).a})},function(t,e,n){var i=n(18),r=n(9).document,o=i(r)&&i(r.createElement);t.exports=function(t){return o?r.createElement(t):{}}},function(t,e,n){e.f=n(36)},function(t,e){t.exports=!0},function(t,e,n){var i=n(41),r=n(31).concat("length","prototype");e.f=Object.getOwnPropertyNames||function(t){return i(t,r)}},function(t,e,n){t.exports={default:n(54),__esModule:!0}},function(t,e,n){t.exports={default:n(62),__esModule:!0}},function(t,e,n){e.L=n(6),e.findRealParent=n(3).default,e.propsBinder=n(0).default,e.LCircle=n(96).default,e.LCircleMarker=n(94).default,e.LControl=n(93).default,e.LControlAttribution=n(101).default,e.LControlLayers=n(103).default,e.LControlScale=n(105).default,e.LControlZoom=n(104).default,e.LFeatureGroup=n(87).default,e.LGeoJson=n(100).default,e.LIcon=n(90).default,e.LIconDefault=n(102).default,e.LImageOverlay=n(85).default,e.LLayerGroup=n(84).default,e.LMap=n(95).default,e.LMarker=n(98).default,e.LPolygon=n(92).default,e.LPolyline=n(91).default,e.LPopup=n(99).default,e.LRectangle=n(89).default,e.LTileLayer=n(88).default,e.LTooltip=n(97).default,e.LWMSTileLayer=n(86).default},function(t,e,n){n(55),t.exports=n(10).Object.keys},function(t,e,n){var i=n(39),r=n(15);n(59)("keys",function(){return function(t){return r(i(t))}})},function(t,e,n){var i=n(17),r=n(57),o=n(58);t.exports=function(t){return function(e,n,s){var a,u=i(e),c=r(u.length),l=o(s,c);if(t&&n!=n){for(;c>l;)if((a=u[l++])!=a)return!0}else for(;c>l;l++)if((t||l in u)&&u[l]===n)return t||l||0;return!t&&-1}}},function(t,e,n){var i=n(44),r=Math.min;t.exports=function(t){return t>0?r(i(t),9007199254740991):0}},function(t,e,n){var i=n(44),r=Math.max,o=Math.min;t.exports=function(t,e){return(t=i(t))<0?r(t+e,0):o(t,e)}},function(t,e,n){var i=n(32),r=n(10),o=n(13);t.exports=function(t,e){var n=(r.Object||{})[t]||Object[t],s={};s[t]=e(n),i(i.S+i.F*o(function(){n(1)}),"Object",s)}},function(t,e,n){var i=n(61);t.exports=function(t,e,n){if(i(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,i){return t.call(e,n,i)};case 3:return function(n,i,r){return t.call(e,n,i,r)}}return function(){return t.apply(e,arguments)}}},function(t,e){t.exports=function(t){if("function"!=typeof t)throw TypeError(t+" is not a function!");return t}},function(t,e,n){n(63),n(74),n(75),n(76),t.exports=n(10).Symbol},function(t,e,n){"use strict";var i=n(9),r=n(16),o=n(12),s=n(32),a=n(64),u=n(65).KEY,c=n(13),l=n(30),p=n(66),f=n(19),h=n(36),d=n(48),m=n(37),y=n(67),b=n(68),O=n(20),v=n(18),j=n(17),g=n(34),L=n(35),S=n(69),C=n(72),x=n(73),_=n(11),$=n(15),w=x.f,A=_.f,E=C.f,T=i.Symbol,I=i.JSON,B=I&&I.stringify,N=h("_hidden"),P=h("toPrimitive"),M={}.propertyIsEnumerable,D=l("symbol-registry"),R=l("symbols"),U=l("op-symbols"),z=Object.prototype,F="function"==typeof T,k=i.QObject,W=!k||!k.prototype||!k.prototype.findChild,G=o&&c(function(){return 7!=S(A({},"a",{get:function(){return A(this,"a",{value:7}).a}})).a})?function(t,e,n){var i=w(z,e);i&&delete z[e],A(t,e,n),i&&t!==z&&A(z,e,i)}:A,J=function(t){var e=R[t]=S(T.prototype);return e._k=t,e},Z=F&&"symbol"==typeof T.iterator?function(t){return"symbol"==typeof t}:function(t){return t instanceof T},H=function(t,e,n){return t===z&&H(U,e,n),O(t),e=g(e,!0),O(n),r(R,e)?(n.enumerable?(r(t,N)&&t[N][e]&&(t[N][e]=!1),n=S(n,{enumerable:L(0,!1)})):(r(t,N)||A(t,N,L(1,{})),t[N][e]=!0),G(t,e,n)):A(t,e,n)},V=function(t,e){O(t);for(var n,i=y(e=j(e)),r=0,o=i.length;o>r;)H(t,n=i[r++],e[n]);return t},q=function(t){var e=M.call(this,t=g(t,!0));return!(this===z&&r(R,t)&&!r(U,t))&&(!(e||!r(this,t)||!r(R,t)||r(this,N)&&this[N][t])||e)},K=function(t,e){if(t=j(t),e=g(e,!0),t!==z||!r(R,e)||r(U,e)){var n=w(t,e);return!n||!r(R,e)||r(t,N)&&t[N][e]||(n.enumerable=!0),n}},X=function(t){for(var e,n=E(j(t)),i=[],o=0;n.length>o;)r(R,e=n[o++])||e==N||e==u||i.push(e);return i},Y=function(t){for(var e,n=t===z,i=E(n?U:j(t)),o=[],s=0;i.length>s;)!r(R,e=i[s++])||n&&!r(z,e)||o.push(R[e]);return o};F||(a((T=function(){if(this instanceof T)throw TypeError("Symbol is not a constructor!");var t=f(arguments.length>0?arguments[0]:void 0),e=function(n){this===z&&e.call(U,n),r(this,N)&&r(this[N],t)&&(this[N][t]=!1),G(this,t,L(1,n))};return o&&W&&G(z,t,{configurable:!0,set:e}),J(t)}).prototype,"toString",function(){return this._k}),x.f=K,_.f=H,n(50).f=C.f=X,n(21).f=q,n(38).f=Y,o&&!n(49)&&a(z,"propertyIsEnumerable",q,!0),d.f=function(t){return J(h(t))}),s(s.G+s.W+s.F*!F,{Symbol:T});for(var Q="hasInstance,isConcatSpreadable,iterator,match,replace,search,species,split,toPrimitive,toStringTag,unscopables".split(","),tt=0;Q.length>tt;)h(Q[tt++]);for(var et=$(h.store),nt=0;et.length>nt;)m(et[nt++]);s(s.S+s.F*!F,"Symbol",{for:function(t){return r(D,t+="")?D[t]:D[t]=T(t)},keyFor:function(t){if(!Z(t))throw TypeError(t+" is not a symbol!");for(var e in D)if(D[e]===t)return e},useSetter:function(){W=!0},useSimple:function(){W=!1}}),s(s.S+s.F*!F,"Object",{create:function(t,e){return void 0===e?S(t):V(S(t),e)},defineProperty:H,defineProperties:V,getOwnPropertyDescriptor:K,getOwnPropertyNames:X,getOwnPropertySymbols:Y}),I&&s(s.S+s.F*(!F||c(function(){var t=T();return"[null]"!=B([t])||"{}"!=B({a:t})||"{}"!=B(Object(t))})),"JSON",{stringify:function(t){for(var e,n,i=[t],r=1;arguments.length>r;)i.push(arguments[r++]);if(n=e=i[1],(v(e)||void 0!==t)&&!Z(t))return b(e)||(e=function(t,e){if("function"==typeof n&&(e=n.call(this,t,e)),!Z(e))return e}),i[1]=e,B.apply(I,i)}}),T.prototype[P]||n(33)(T.prototype,P,T.prototype.valueOf),p(T,"Symbol"),p(Math,"Math",!0),p(i.JSON,"JSON",!0)},function(t,e,n){t.exports=n(33)},function(t,e,n){var i=n(19)("meta"),r=n(18),o=n(16),s=n(11).f,a=0,u=Object.isExtensible||function(){return!0},c=!n(13)(function(){return u(Object.preventExtensions({}))}),l=function(t){s(t,i,{value:{i:"O"+ ++a,w:{}}})},p=t.exports={KEY:i,NEED:!1,fastKey:function(t,e){if(!r(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!o(t,i)){if(!u(t))return"F";if(!e)return"E";l(t)}return t[i].i},getWeak:function(t,e){if(!o(t,i)){if(!u(t))return!0;if(!e)return!1;l(t)}return t[i].w},onFreeze:function(t){return c&&p.NEED&&u(t)&&!o(t,i)&&l(t),t}}},function(t,e,n){var i=n(11).f,r=n(16),o=n(36)("toStringTag");t.exports=function(t,e,n){t&&!r(t=n?t:t.prototype,o)&&i(t,o,{configurable:!0,value:e})}},function(t,e,n){var i=n(15),r=n(38),o=n(21);t.exports=function(t){var e=i(t),n=r.f;if(n)for(var s,a=n(t),u=o.f,c=0;a.length>c;)u.call(t,s=a[c++])&&e.push(s);return e}},function(t,e,n){var i=n(43);t.exports=Array.isArray||function(t){return"Array"==i(t)}},function(t,e,n){var i=n(20),r=n(70),o=n(31),s=n(45)("IE_PROTO"),a=function(){},u=function(){var t,e=n(47)("iframe"),i=o.length;for(e.style.display="none",n(71).appendChild(e),e.src="javascript:",(t=e.contentWindow.document).open(),t.write(" diff --git a/resources/js/components/FieldMap.vue b/resources/js/components/FieldMap.vue new file mode 100755 index 0000000..a15894a --- /dev/null +++ b/resources/js/components/FieldMap.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/resources/js/components/FormField.vue b/resources/js/components/FormField.vue new file mode 100755 index 0000000..0d5b1fc --- /dev/null +++ b/resources/js/components/FormField.vue @@ -0,0 +1,40 @@ + + + diff --git a/resources/js/components/IndexField.vue b/resources/js/components/IndexField.vue new file mode 100755 index 0000000..5a07928 --- /dev/null +++ b/resources/js/components/IndexField.vue @@ -0,0 +1,9 @@ + + + diff --git a/resources/js/components/fields/Marker.vue b/resources/js/components/fields/Marker.vue new file mode 100755 index 0000000..4d4fd09 --- /dev/null +++ b/resources/js/components/fields/Marker.vue @@ -0,0 +1,80 @@ + + + diff --git a/resources/js/components/fields/Polyline.vue b/resources/js/components/fields/Polyline.vue new file mode 100755 index 0000000..a61406b --- /dev/null +++ b/resources/js/components/fields/Polyline.vue @@ -0,0 +1,87 @@ + + + diff --git a/resources/js/field.js b/resources/js/field.js new file mode 100755 index 0000000..b79122e --- /dev/null +++ b/resources/js/field.js @@ -0,0 +1,12 @@ +Nova.booting((Vue, router) => { + Vue.component('index-nova-map-fields', require('./components/IndexField')); + Vue.component('detail-nova-map-fields', require('./components/DetailField')); + Vue.component('form-nova-map-fields', require('./components/FormField')); + + Vue.component('field-map', require('./components/FieldMap')); + Vue.component('field-marker', require('./components/fields/Marker')); + Vue.component('field-polyline', require('./components/fields/Polyline')); + + // Config leaflet images to load images from CDN + L.Icon.Default.imagePath = 'https://cdnjs.cloudflare.com/ajax/libs/leaflet/1.3.4/images/'; +}) diff --git a/resources/sass/field.scss b/resources/sass/field.scss new file mode 100755 index 0000000..f85ad40 --- /dev/null +++ b/resources/sass/field.scss @@ -0,0 +1 @@ +// Nova Tool CSS diff --git a/src/FieldServiceProvider.php b/src/FieldServiceProvider.php new file mode 100755 index 0000000..2e0137d --- /dev/null +++ b/src/FieldServiceProvider.php @@ -0,0 +1,28 @@ +setHeight('250px'); + $this->setCenter(0, 0); + $this->setZoom(13); + + $this->withMapMeta('type', $this->getMapFieldType()); + + parent::__construct($name, $attribute = null, $resolveCallback); + } + + /** + * Set the height for the map. + * + * @param mixed $height + * + * @return $this + */ + public function setHeight($height) + { + return $this->withMapMeta('height', $height); + } + + /** + * Set the zoom for the map. + * + * @param mixed $level + * + * @return $this + */ + public function setZoom($level) + { + return $this->withMapMeta('zoom', $level); + } + + /** + * Set the position for the map. + * + * @param mixed $latitude + * @param mixed $longitude + * + * @return $this + */ + public function setCenter($latitude, $longitude) + { + return $this->withMapMeta('center', [ + 'latitude' => $latitude, + 'longitude' => $longitude, + ]); + } + + /** + * Add meta data for the map. + * + * @param mixed $key + * @param mixed $value + */ + protected function withMapMeta($key, $value) + { + $existingMapMeta = $this->meta['map'] ?? []; + + return $this->withMeta([ + 'map' => array_merge($existingMapMeta, [ + $key => $value, + ]), + ]); + } + + /** + * Get component name. + * + * @return string + */ + public function getMapFieldType() + { + return Str::kebab(class_basename($this)); + } +} diff --git a/src/Marker.php b/src/Marker.php new file mode 100755 index 0000000..4d1ffb5 --- /dev/null +++ b/src/Marker.php @@ -0,0 +1,85 @@ +help('Drag the marker to change the point.'); + + parent::__construct($name, $attribute = null, $resolveCallback); + } + + /** + * Set the latutude field. + * + * @param mixed $fieldName + * + * @return $this + */ + public function setLatitude($fieldName) + { + return $this->withMeta([ + 'latitudeField' => $fieldName, + ]); + } + + /** + * Set the longitude field. + * + * @param mixed $fieldName + * + * @return $this + */ + public function setLongitude($fieldName) + { + return $this->withMeta([ + 'longitudeField' => $fieldName, + ]); + } + + /** + * Resolve the attribute before sending to frontend. + * + * @param mixed $resource + * @param mixed|null $attribute + * + * @return array + */ + public function resolveAttribute($resource, $attribute = null) + { + return [ + 'lat' => $resource->{$this->meta['latitudeField']}, + 'lng' => $resource->{$this->meta['longitudeField']}, + ]; + } + + /** + * Hydrate the given attribute on the model based on the incoming request. + * + * @param \Laravel\Nova\Http\Requests\NovaRequest $request + * @param string $requestAttribute + * @param object $model + * @param string $attribute + */ + protected function fillAttributeFromRequest(NovaRequest $request, $requestAttribute, $model, $attribute) + { + if ($request->exists($requestAttribute)) { + $latLng = json_decode($request[$requestAttribute]); + + $model->{$this->meta['latitudeField']} = $latLng->lat; + $model->{$this->meta['longitudeField']} = $latLng->lng; + } + } +} diff --git a/src/Polyline.php b/src/Polyline.php new file mode 100755 index 0000000..388d3c1 --- /dev/null +++ b/src/Polyline.php @@ -0,0 +1,39 @@ +help('Click on the map to create a new point. Drag a marker to change the point. When the map is selected, you can press [backspace] to remove markers.'); + + parent::__construct($name, $attribute = null, $resolveCallback); + } + + /** + * Resolve the attribute before sending to frontend. + * + * @param mixed $resource + * @param mixed|null $attribute + * + * @return array + */ + public function resolveAttribute($resource, $attribute = null) + { + return json_decode($resource->{$attribute}); + + return [ + 'lat' => $resource->{$this->meta['latitudeField']}, + 'lng' => $resource->{$this->meta['longitudeField']}, + ]; + } +} diff --git a/webpack.mix.js b/webpack.mix.js new file mode 100755 index 0000000..b96c97e --- /dev/null +++ b/webpack.mix.js @@ -0,0 +1,5 @@ +let mix = require('laravel-mix') + +mix.setPublicPath('dist') + .js('resources/js/field.js', 'js') + .sass('resources/sass/field.scss', 'css')