Laravel-Backpack / CRUD

Build custom admin panels. Fast!
https://backpackforlaravel.com
MIT License
3.16k stars 893 forks source link

[Bug] Google Map [pro] field issue (solution proposed) #5710

Open manfield opened 6 days ago

manfield commented 6 days ago

Bug report

What I did

I'm using lat, lng, location on datbaase, as explained in the documentation.

If I click to set the pin on the map, instead of drag'n'dropping it, an empty set of lat, lng is passed to the location() custom function, raising an error.

Probably the value would not been saved either if I didn't use lat, lng, location columns on the database, with the standard way. It seems to be a js bug.

What I expected to happen

In any case moving the pin, clicking on the map, should save values correctly.

Backpack, Laravel, PHP, DB version

When I run php artisan backpack:version the output is:

### PHP VERSION:
8.3.9

### PHP EXTENSIONS:
Core, date, libxml, openssl, pcre, zlib, filter, hash, json, pcntl, random, Reflection, SPL, session, standard, sodium, mysqlnd, PDO, xml, ast, bcmath, calendar, ctype, curl, dom, mbstring, FFI, fileinfo, ftp, gd, gettext, iconv, igbinary, intl, exif, msgpack, mysqli, pdo_mysql, pdo_pgsql, pdo_sqlite, pgsql, Phar, posix, readline, redis, shmop, SimpleXML, sockets, sqlite3, sysvmsg, sysvsem, sysvshm, tokenizer, xmlreader, xmlwriter, xsl, zip, memcached, Zend OPcache, xdebug

### LARAVEL VERSION:
11.23.5.0

### BACKPACK PACKAGE VERSIONS:
backpack/basset: 1.3.6
backpack/crud: 6.7.41
backpack/devtools: 3.1.6
backpack/generators: v4.0.6
backpack/language-switcher: 2.0.0
backpack/medialibrary-uploaders: 1.2.1
backpack/permissionmanager: 7.2.1
backpack/pro: 2.2.21
backpack/settings: 3.1.1
backpack/theme-tabler: 1.2.13
backpack/translation-manager: 1.0.4
backpack-ai-bot[bot] commented 6 days ago

Thank you for reporting this issue with the Google Map [pro] field in Backpack. Based on the information provided, it appears you're experiencing a bug with the map pin functionality. Let me address your concerns:

  1. The issue you're describing where clicking to set the pin on the map results in empty lat/lng values being passed to the location() custom function does indeed sound like a JavaScript bug in the Google Map field implementation.

  2. This behavior is not expected, and you're correct in assuming that the values should be saved correctly regardless of whether you're using lat, lng, location columns in the database or the standard way.

  3. Unfortunately, I don't have specific information about this particular bug in the knowledge sources provided. However, this seems like a legitimate issue that should be reported to the Backpack developers.

Given the nature of this bug, here are some suggestions:

  1. Make sure you're using the latest version of backpack/pro (currently you're on 2.2.21, which is the latest according to the information provided).

  2. Clear your application cache and compiled views to ensure you're not experiencing any caching issues:

    php artisan optimize:clear
    php artisan view:clear
  3. If the issue persists, I recommend reporting this bug on the official Backpack GitHub repository or community forum. Include the details you've provided here, along with any relevant code snippets and steps to reproduce the issue.

  4. In the meantime, as a workaround, you might consider handling the lat/lng values manually in your JavaScript code and submitting them to your backend separately if the built-in functionality is not working as expected.

If you need further assistance or if the problem continues after trying these steps, I encourage you to reach out to the Backpack community or developers directly, as they would be best equipped to address this specific bug and provide a fix or workaround.

Relevant sources:

Github Issue (closed): google_map PRO field Github Issue (closed): google_map PRO field Github Issue (closed): google_map PRO field Github Issue (closed): google_map PRO field Github Issue (closed): google_map PRO field Github Issue (closed): google_map field not working in Production env Github Issue (closed): google_map field not working in Production env Github Issue (closed): google_map field not working in Production env Github Issue (closed): google_map field not working in Production env Github Issue (closed): google_map field not working in Production env

manfield commented 5 days ago

Actually the issue is the javascript code in google_map.blade row 76 getAddressAndSavePosition expects to receive a literal LatLng object, instead it receives a google.map.LatLng . A solution would be transforming in literal the latLng event attribute.

From:

  map.addListener('click', function({domEvent, latLng}) {
      if(element.attr('disabled') === undefined) {
          getAddressAndSavePosition(latLng, mapField, searchInput);
          marker.position = latLng;
      }
  });

To:

  map.addListener('click', function({domEvent, latLng}) {
      if(element.attr('disabled') === undefined) {
          let literalLatLng = {'lat': latLng.lat(), 'lng': latLng.lng()};
          getAddressAndSavePosition(literalLatLng, mapField, searchInput);
          marker.position = literalLatLng;
      }
  });
jcastroa87 commented 3 days ago

Hello @manfield

I will test this issue, can you share how did you configure the field?

Thanks.

Cheers.

manfield commented 3 days ago

Hi, here the field configuration:

    [
        'name' => 'place',
        'label' => trans('custom.geo_location'),
        'type' => 'google_map',
        'map_options' => [
            'default_lat' => 41.902782,
            'default_lng' => 12.496366,
            'locate' => false, 
            'height' => 400 
        ],
        'tab' => trans('custom.main'),
    ],
manfield commented 3 days ago

Please note that "place" is retrieved by this method on the model: Though is irrelevant for this issue. The problem is on the map js script, as you click to set the pin position.

    protected function place(): \Illuminate\Database\Eloquent\Casts\Attribute
    {

        $fallbackLocation = [
            'lat' => config('services.google_places.default_lat'),
            'lng' => config('services.google_places.default_lng'),
            'full_address' => $location?->formatted_address ?? ''
        ];

        return \Illuminate\Database\Eloquent\Casts\Attribute::make(
            get: function($value, $attributes) {
                return json_encode([
                    'lat' => $attributes['lat'],
                    'lng' => $attributes['lng'],
                    'formatted_address' => $attributes['full_address'] ?? ''
                ], JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT | JSON_THROW_ON_ERROR);
            },
            set: function($value)  use ($fallbackLocation) {
                $location = json_decode($value);
                if (!empty($location)) {
                    if (!property_exists($location, 'lat')){
                        return $fallbackLocation;
                    }
                } else {
                    return $fallbackLocation;
                }

                return [
                    'lat' => $location?->lat,
                    'lng' => $location?->lng,
                    'full_address' => $location?->formatted_address ?? ''
                ];
            }
        );
    }
jcastroa87 commented 3 days ago

Thanks a lot @manfield i confirm this bug.

I will be working in a PR and let you know about the fix.

Thanks again.

Cheers.

manfield commented 3 days ago

No rush for me. I could override the blade template. Thanks for your support