Руководство по интеграции Редактора схем через iframe

Это руководство объясняет, как встроить редактор схем в ваше приложение с помощью iframe, включая параметры конфигурации и схемы обмена сообщениями.

Базовая интеграция через iframe

Встраивание iframe позволяет интегрировать внешние приложения в ваше веб-приложение. Ниже приведена информация о том, как интегрировать iframe и настроить обмен сообщениями с помощью метода postMessage.

Простое встраивание 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>

Интеграция в модальном окне

Создание модального окна с 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);
});

Настройка экрана редактирования схемы

К интерфейсу редактирования схемы можно получить доступ через два основных шаблона URL:

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

Где venueId — это ID площадки, а schemaId — ID редактируемой схемы, или “new” для создания новой схемы.

Настройка интерфейса с помощью параметров URL

Интерфейс редактора схем можно настраивать с помощью различных параметров URL:

1. Скрытие элементов интерфейса

Используйте параметр hidden, чтобы скрыть определённые элементы панели инструментов:

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

В приведённом выше примере будут скрыты кнопка режима цен, кнопка сохранения и инструменты форм из интерфейса.

2. Скрытие панели навигации

Чтобы создать более встроенный вид, вы можете скрыть верхнюю панель навигации:

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

Это особенно полезно для интеграции через iframe, обеспечивая более чистый интерфейс только с компонентами редактора.

3. Принудительное отображение инструментов цен

Даже если инструменты цен скрыты по умолчанию или с помощью параметра hidden, вы можете принудительно отобразить их:

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

4. Комбинирование параметров

Эти параметры можно комбинировать, чтобы создать максимально настроенный режим редактирования:

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

Полный пример реализации

Ниже приведён полный пример, демонстрирующий встраивание редактора схем в модальное окно с настроенным интерфейсом и обработкой сообщений:

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,
  });
});

Доступные элементы интерфейса

Панель инструментов редактора схем состоит из нескольких режимов и инструментов, которые можно выборочно скрыть:

Режимы редактора

// 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',
};

Инструменты схемы

// 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',
};

Инструменты секций

// 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',
};

Инструменты цен

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

Инструменты подложки

// 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',
};

Глобальные инструменты

// 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)',
};

Скрытие элементов в URL

В параметре URL вы можете использовать как полный идентификатор (например, mode.schema), так и короткий идентификатор (например, schema):

?hidden=schema,pricing,save

Или используя полные идентификаторы:

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

Корректировки макета редактора

При скрытии панели навигации с помощью hideNavbar=true редактор автоматически корректирует свой макет:

  1. Верхняя панель навигации полностью удаляется
  2. Высота области контента и боковой панели увеличивается, чтобы заполнить доступное пространство
  3. Кнопка публикации скрывается на боковой панели (управляется свойством hidePublishing)

Это создаёт более чистый и сфокусированный режим редактирования, идеально подходящий для встраивания через iframe.

Сценарии использования и примеры

1. Режим только для просмотра для клиентов

// 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. Редактор с фокусом на ценах

// 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. Мастер создания схемы

// 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'],
});

Реализация пользовательских типов сообщений

Вы можете расширить обмен сообщениями между родительским приложением и редактором схем, реализовав пользовательские типы сообщений:

// 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' });

Для этих пользовательских команд потребуются соответствующие обработчики в приложении iframe.