ui_locations_entries_query_button.mjs

/**
The query_button [location] entries module exports the query_button method as default.

@requires /utils/queryParams

@module /ui/locations/entries/query_button
*/

/**
@function query_button

@description
## mapp.ui.locations.entries.query_button(entry)
Returns a button element. The `query(entry)` method will be called by the button onclick event.

```js
{
  "label": "Snap to Postal Sector",
  "type": "query_button",
  "query": "catchment_statistics_snap_to_postal_sector",
  "queryparams": {
    "id": true
  },
  "alert": "Query has executed!",
  "reload": true,
  "dependents": [
    "geom_3857",
    "perimeter",
    "area"
  ]
}
```

@param {infoj-entry} entry type:query_button infoj entry.

@returns {HTMLElement} Location view entry node.
*/

export default function _query_button(entry) {

  if (!entry.query) {
    console.warn('You must provide a query to use "type": "query_button".');
    return;
  };

  // If a label is provided, use it, otherwise use the default
  entry.label ??= `Run query:${entry.query}`;

  // Return button to update the entry.
  return mapp.utils.html.node`
    <button 
      class="flat wide bold primary-colour"
      onclick=${() => query(entry)}>${entry.label}`;
};

/**
@function query
@async

@description
Will be called by the onclick event of the query_button element.

The `entry.location.view` will be disabled.

Runs the `entry.query` template with the provided `entry.queryparams`.

The `entry.host` defaults to the entry.mapview.host concatenated with the `/api/query` path.

The location.layer will reload after the query response with the `entry.reload` flag.

The entry values of fields in the `entry.dependents` array will be synched after the query has been resolved.

The `entry.alert` message will be displayed after the query has been resolved.

The `entry.location.view` will be enabled by calling the `updateInfo` element event.

@param {infoj-entry} entry type:query_button infoj entry.
@property {string} entry.query Query template.
@property {Object} [entry.queryparams] Parameter for query in template.
@property {string} [entry.host] The host for the query.
@property {string} [entry.alert] Alert message after the query has responded.
@property {boolean} [entry.reload] Reload location.layer if true.
@property {Array} [entry.dependents] Reload dependent entry.field values.
*/

async function query(entry) {

  // Warning for legacy config.
  if (entry.updated_fields) {

    console.warn('entry.updated_fields is deprecated, please use entry.dependents instead.');

    // If entry.updated_fields, set to entry.dependents and warn
    entry.dependents ??= entry.updated_fields;
  }

  // Disable location view.
  entry.location.view.classList.add('disabled');

  entry.queryparams ??= {}

  entry.queryparams.template = entry.query

  // Stringify paramString from object.
  const paramString = mapp.utils.paramString(mapp.utils.queryParams(entry))

  entry.host ??= entry.location.layer.mapview.host + '/api/query'

  // Run query to get data to update the entry on the db.
  const response = await mapp.utils.xhr(`${entry.host}?${paramString}`);

  if (response instanceof Error) {

    alert('Query failed.')

    // Enable location view.
    entry.location.view.classList.remove('disabled');

    return;
  }

  entry.value = response

  entry.alert && alert(entry.alert)

  entry.reload && entry.location.layer.reload()

  if (entry.dependents) {

    // Reload the dependent fields
    await entry.location.syncFields(entry.dependents)

  }

  // Updating the view will enable the view itself.
  // No need to enable the button and view themselves.
  entry.location.view.dispatchEvent(new Event('updateInfo'))

  // Enable location view.
  entry.location.view.classList.remove('disabled');
}