Guía de integración del Editor de esquemas mediante iframe

Esta guía explica cómo integrar el editor de esquemas en tu aplicación mediante iframes, incluidas las opciones de configuración y los patrones de comunicación.

Integración básica mediante iframe

Integrar un iframe te permite incorporar aplicaciones externas en tu aplicación web. A continuación se ofrece información sobre cómo integrar un iframe y configurar la comunicación de mensajes mediante el método postMessage.

Integración simple de iframe

<!DOCTYPE html>
<html>
  <head>
    <style>
      .container {
        height: 100vh;
        display: flex;
        flex-direction: column;
      }
      iframe {
        flex-grow: 1;
        border: none;
      }
    </style>
  </head>
  <body>
    <div class="container">
      <!-- create iframe using js -->
      <div class="controls">
        <button id="openModalBtn">Open in modal window</button>
        <span id="messageDisplay"></span>
      </div>

      <!-- or html -->
      <iframe src="/app/venues/2/schemas/150" width="100%" height="100%"></iframe>
    </div>
  </body>
</html>

Integración en ventana modal

Crear una ventana modal con un iframe

document.getElementById('openModalBtn').addEventListener('click', function () {
  const modal = document.createElement('div');
  modal.style.position = 'fixed';
  modal.style.top = '0';
  modal.style.left = '0';
  modal.style.width = '100%';
  modal.style.height = '100%';
  modal.style.backgroundColor = 'rgba(0,0,0,0.5)';

  const iframe = document.createElement('iframe');
  iframe.src = '/app/venues/2/schemas/150?hideNavbar=true';
  iframe.style.width = '95%';
  iframe.style.height = '95%';

  modal.appendChild(iframe);
  document.body.appendChild(modal);
});

Configuración de la pantalla de edición de esquemas

Se puede acceder a la interfaz de edición de esquemas mediante dos patrones de URL principales:

/app/venues/{venueId}/schemas/{schemaId}  // Edit existing schema
/app/venues/{venueId}/schemas/new         // Create new schema

Donde venueId es el ID del recinto y schemaId es el ID del esquema a editar, o “new” para crear un nuevo esquema.

Personalizar la interfaz con parámetros de URL

La interfaz del editor de esquemas se puede personalizar mediante diversos parámetros de URL:

1. Ocultar elementos de la interfaz

Usa el parámetro hidden para ocultar elementos específicos de la barra de herramientas:

/app/venues/2/schemas/150?hidden=pricing,save,shape

El ejemplo anterior ocultaría de la interfaz el botón de modo de precios, el botón de guardar y las herramientas de formas.

2. Ocultar la barra de navegación

Para crear una experiencia más integrada, puedes ocultar la barra de navegación superior:

/app/venues/2/schemas/150?hideNavbar=true

Esto resulta especialmente útil para la integración mediante iframe, ya que ofrece una interfaz más limpia con solo los componentes del editor.

3. Forzar la visualización de las herramientas de precios

Aunque las herramientas de precios estén ocultas por defecto o mediante el parámetro hidden, puedes forzar que aparezcan:

/app/venues/2/schemas/150?showPricing=true

4. Combinar parámetros

Estos parámetros se pueden combinar para crear una experiencia de edición altamente personalizada:

/app/venues/2/schemas/150?hideNavbar=true&hidden=save,shape&showPricing=true

Ejemplo de implementación completo

Aquí tienes un ejemplo completo que demuestra cómo integrar el editor de esquemas en una ventana modal con una interfaz personalizada y gestión de mensajes:

function openSchemaEditor(venueId, schemaId, options = {}) {
  // Create modal container
  const modal = document.createElement('div');
  modal.style.position = 'fixed';
  modal.style.top = '0';
  modal.style.left = '0';
  modal.style.width = '100%';
  modal.style.height = '100%';
  modal.style.backgroundColor = 'rgba(0,0,0,0.5)';
  modal.style.zIndex = '9999';
  modal.style.display = 'flex';
  modal.style.justifyContent = 'center';
  modal.style.alignItems = 'center';

  // Create close button
  const closeBtn = document.createElement('button');
  closeBtn.textContent = 'Close';
  closeBtn.style.position = 'absolute';
  closeBtn.style.top = '10px';
  closeBtn.style.right = '10px';
  closeBtn.style.zIndex = '10000';
  modal.appendChild(closeBtn);

  // Create iframe
  const iframe = document.createElement('iframe');

  // Build the base URL
  let url = `/app/venues/${venueId}/schemas/${schemaId}`;

  // Build query parameters
  const params = new URLSearchParams();

  // Hide specific UI elements if specified
  if (options.hiddenElements && options.hiddenElements.length > 0) {
    params.set('hidden', options.hiddenElements.join(','));
  }

  // Hide navbar if specified (default to true for modal)
  if (options.hideNavbar !== false) {
    params.set('hideNavbar', 'true');
  }

  // Force show pricing if specified
  if (options.showPricing) {
    params.set('showPricing', 'true');
  }

  // Append parameters if any exist
  if (params.toString()) {
    url += `?${params.toString()}`;
  }

  iframe.src = url;
  iframe.style.width = '95%';
  iframe.style.height = '95%';
  iframe.style.border = 'none';

  modal.appendChild(iframe);
  document.body.appendChild(modal);

  let hasUnsavedChanges = false;

  // Set up message listener for schema changes
  window.addEventListener('message', function (event) {
    // Handle schema changes
    if (event.data.type === 'SCHEMA_CHANGED') {
      console.log('Schema modified:', event.data);
      hasUnsavedChanges = event.data.hasChanges;

      // Update UI to indicate unsaved changes
      if (hasUnsavedChanges) {
        closeBtn.textContent = 'Close*';
      } else {
        closeBtn.textContent = 'Close';
      }
    }

    // Handle close confirmation response
    if (event.data.type === 'MODAL_CLOSE_RESPONSE' && event.data.canClose) {
      document.body.removeChild(modal);
    }
  });

  // Set up close button handler with confirmation
  closeBtn.addEventListener('click', function () {
    if (hasUnsavedChanges) {
      iframe.contentWindow.postMessage({ type: 'MODAL_CLOSING' }, '*');
    } else {
      document.body.removeChild(modal);
    }
  });

  // Return control functions
  return {
    close: function () {
      if (hasUnsavedChanges) {
        iframe.contentWindow.postMessage({ type: 'MODAL_CLOSING' }, '*');
      } else {
        document.body.removeChild(modal);
      }
    },
    getIframe: function () {
      return iframe;
    },
  };
}

// Example usage:
document.getElementById('openEditorBtn').addEventListener('click', function () {
  const editor = openSchemaEditor(2, 150, {
    hiddenElements: ['save', 'tool.shape.circle', 'tool.shape.polygon'],
    showPricing: true,
  });
});

Elementos de la interfaz disponibles

La barra de herramientas del editor de esquemas consta de varios modos y herramientas que se pueden ocultar de forma selectiva:

Modos del editor

// Mode options that can be hidden
const modes = {
  'mode.schema': 'Schema editing mode',
  'mode.underlay': 'Underlay/background editing',
  'mode.venueShape': 'Venue shape editing',
  'mode.pricingZones': 'Pricing zones configuration',
  'mode.pricing': 'Pricing management',
  'mode.section': 'Section editing mode',
};

Herramientas de esquema

// Tools available in Schema mode
const schemaTools = {
  'tool.select': 'Selection tool',
  'tool.seatRows': 'Add seat rows tool',
  'tool.table': 'Add table tool',
  'tool.shape': 'Add shapes (all types)',
  'tool.shape.rect': 'Add rectangle shape',
  'tool.shape.circle': 'Add circle shape',
  'tool.shape.line': 'Add line shape',
  'tool.shape.polygon': 'Add polygon shape',
  'tool.label': 'Add label tool',
};

Herramientas de sección

// Tools available in Section mode
const sectionTools = {
  'tool.selectSeats': 'Select individual seats',
  'tool.selectRows': 'Select entire rows',
  'tool.addSeat': 'Add individual seats',
  'tool.numberSeats': 'Number seats automatically',
};

Herramientas de precios

// Tools available in Pricing modes
const pricingTools = {
  'tool.selectSeats': 'Select individual seats',
  'tool.selectRows': 'Select entire rows',
  'tool.selectSections': 'Select entire sections',
};

Herramientas de base

// Tools available in Underlay mode
const underlayTools = {
  'tool.importSvgBackground': 'Import SVG as background',
  'tool.exportSvgBackground': 'Export SVG background',
  'tool.removeSvgBackground': 'Remove SVG background',
  'tool.viewbox': 'Adjust viewbox',
};

Herramientas globales

// Global tools
const globalTools = {
  'tool.save': 'Save changes',
  'tool.publish': 'Publish schema (only appears when in draft mode)',
  'tool.preview': 'Preview schema (only appears when event ID is available)',
};

Ocultar elementos en la URL

En el parámetro de la URL puedes usar tanto el identificador completo (por ejemplo, mode.schema) como el identificador corto (por ejemplo, schema):

?hidden=schema,pricing,save

O usando identificadores completos:

?hidden=mode.schema,mode.pricing,tool.save

Ajustes de diseño del editor

Al ocultar la barra de navegación con hideNavbar=true, el editor ajusta automáticamente su diseño:

  1. La barra de navegación superior se elimina por completo
  2. La altura del área de contenido y de la barra lateral aumenta para llenar el espacio disponible
  3. El botón de publicación se oculta en la barra lateral (controlado por la propiedad hidePublishing)

Esto crea una experiencia de edición más limpia y enfocada, ideal para la integración mediante iframe.

Casos de uso y ejemplos

1. Vista de solo lectura para clientes

// Open a read-only view of the schema with minimal UI
openSchemaEditor(2, 150, {
  hideNavbar: true,
  hiddenElements: [
    'save',
    'tool.shape',
    'tool.table',
    'tool.label',
    'tool.seatRows',
    'mode.underlay',
    'mode.venueShape',
    'mode.pricingZones',
    'mode.pricing',
    'tool.addSeat',
    'tool.numberSeats',
  ],
});

2. Editor centrado en precios

// Open editor focused on pricing configuration
openSchemaEditor(2, 150, {
  hideNavbar: true,
  showPricing: true,
  hiddenElements: [
    'mode.schema',
    'mode.underlay',
    'mode.venueShape',
    'tool.shape',
    'tool.label',
    'tool.seatRows',
    'tool.table',
  ],
});

3. Asistente de creación de esquemas

// Open editor for creating a new schema with step-by-step guidance
openSchemaEditor(2, 'new', {
  hideNavbar: true,
  hiddenElements: ['mode.pricing', 'mode.pricingZones', 'tool.shape.polygon', 'tool.shape.line'],
});

Implementar tipos de mensajes personalizados

Puedes ampliar la comunicación de mensajes entre la aplicación principal y el editor de esquemas implementando tipos de mensajes personalizados:

// In the parent application
function sendCustomCommand(iframe, command, data) {
  iframe.contentWindow.postMessage(
    {
      type: 'CUSTOM_COMMAND',
      command: command,
      data: data,
    },
    '*',
  );
}

// Example: Set zoom level
sendCustomCommand(editorIframe, 'SET_ZOOM', { level: 0.75 });

// Example: Focus on a specific section
sendCustomCommand(editorIframe, 'FOCUS_SECTION', { sectionId: 'A3' });

Estos comandos personalizados necesitarían los controladores correspondientes en la aplicación del iframe.