ui_locations_entries_dataview.mjs

/**
## ui/locations/entries/dataview

The dataview entry module exports the dataview method as mapp.ui.locations.entries.dataview()

@requires /ui/Dataview

@module /ui/locations/entries/dataview
*/

/**
@function dataview

@description
### mapp.ui.locations.entries.dataview()

The `dataview.data{}` will be assigned from the entry.value if available.

The `dataview.layer` will be assigned from the `entry.location.layer`

A document lookup for the target ID will be attempted if the target is provided as string. The dataview will be decorated, created, and updated in this case.

A dataview has already been decorated if a `dataview.update` method exists. The entry method will check the display condition to show the dataview and return the entry HTMLElements.

The `dataview.tabview` will be assigned if the document queryselector finds a matching data-id, eg. "tabview".

The dataview will be added as a new tab to the tabview.

A locationViewTarget element will be created and returned to the location.view without a tabview or implicit target element for the dataview.

The dataview entry is decorated to be a `typedef:dataview` object by passing the entry as argument to the `mapp.ui.Dataview(entry)` method.

A decorated dataview entry will have show(), hide(), and an update() method.

A checkbox element will be created if the dataview entry has a label.

The display flag controls whether the dataview should be immediately displayed.

The dataview checkbox and locationViewTarget elements will be returned if available.

@param {infoj-entry} entry type:dataview entry.
@property {location} entry.location The entry location.
@property {layer} entry.layer The entry layer will be assigned from the entry.location.
@property {Object} entry.data The dataview data.
@property {string} [entry.label] Label for checkbox element.
@property {string} [entry.dataview] The dataview type, eg. "chartjs", "tabulator".
@property {string} [entry.target] The dataview target. Will resolve to HTMLElement.
@property {Function} [entry.update] The dataview update method.
@property {boolean} [entry.display] The dataview display flag.
@property {Function} [entry.show] The dataview show method.
@property {Function} [entry.hide] The dataview hide method.
@property {HTMLElement} [entry.locationViewTarget] Dataview target for display in location.view.

@return {HTMLElement} Location view dataview and checkbox.
*/

export default function dataview(entry) {
  if (entry.value !== undefined) {
    entry.data = entry.value;

    if (entry.data?.length === 0) {
      entry.data = null;
    }
  }

  if (entry.data === null) {
    // The entry must be disabled if the query has run with querycheck:true and the data is null.
    // This is to prevent the query running over and over again getting the same result.
    entry._display ??= entry.display;
    delete entry.display;
  } else {
    entry.display ??= entry._display;
  }

  if (entry.label) {
    // Create checkbox if a label is provided.
    entry.chkbox = mapp.ui.elements.chkbox({
      data_id: entry.key,
      label: entry.label,
      checked: !!entry.display,
      disabled: entry.data === null,
      onchange: (checked) => {
        entry.display = checked;
        entry.display ? entry.show() : entry.hide();
      },
    });
  }

  // Dataview queries may require the layer and host to be defined on the entry.
  entry.layer ??= entry.location.layer;
  entry.host ??= entry.layer.mapview.host;

  // Dataview will be rendered into target identified by ID.
  if (
    typeof entry.target === 'string' &&
    document.getElementById(entry.target)
  ) {
    // Assign element by ID as target.
    entry.target = document.getElementById(entry.target);

    // Create and update the dataview.
    if (mapp.ui.Dataview(entry) instanceof Error) return;

    entry.update();
    return;
  }

  // Dataview has already been created. e.g. after the location (view) is updated, and it is not dynamic.
  if (entry.update && !entry.dynamic) {
    if (entry.display) entry.show?.();

    // Return elements to location view.
    return mapp.utils.html.node`
      ${entry.chkbox || ''}
      ${entry.locationViewTarget || ''}`;
  }

  if (
    typeof entry.target === 'string' &&
    document.querySelector(`[data-id=${entry.target}]`)
  ) {
    // Tabview entries return empty on mobile.
    if (mapp.utils.mobile()) return;

    // Assign tabview element from queryselector
    entry.tabview ??= document.querySelector(`[data-id=${entry.target}]`);

    // Assign border style based on the location view record (from list)
    entry.tab_style ??= `border-bottom: 3px solid ${
      entry.location.style?.strokeColor || 'var(--color-primary)'
    }`;

    // Assign target html element for dataview.
    entry.target = mapp.utils.html.node`
      <div class="dataview-target">`;

    // Create tab after dataview creation is complete.
    entry.tabview.dispatchEvent(
      new CustomEvent('addTab', {
        detail: entry,
      }),
    );
  } else if (!entry.tabview) {
    // Dataview will be rendered into location view.
    const location_class = `location ${entry.key || entry.query}`;

    entry.locationViewTarget = mapp.utils.html.node`
      <div class="${location_class}">`;

    entry.target = entry.locationViewTarget;
  }

  // Decorate the dataview entry.
  if (mapp.ui.Dataview(entry) instanceof Error) return;

  // Dataview should be displayed.
  entry.display && entry.show?.();

  // Return elements to location view.
  return mapp.utils.html.node`
    ${entry.chkbox || ''}
    ${entry.locationViewTarget || ''}`;
}