# Entity Builder UI

The `eb_ui` module provides the base UI functionality for Entity Builder, including a YAML editor interface and shared API endpoints used by all grid providers.

## Overview

eb_ui serves two primary purposes:

1. **YAML Editor Fallback**: Provides a CodeMirror-based YAML editor when no grid provider is active
2. **Shared API Endpoints**: Provides validation, preview, and entity configuration endpoints used by all UI components

## Architecture

```
eb_ui (Submodule of eb)
├── GridProviderManager (discovers providers via hook)
├── EbUiYamlForm (YAML textarea + CodeMirror)
├── EbUiApiController (shared API endpoints)
├── EbUiSettingsForm (editor configuration)
└── Routes: /eb/api/validate, /eb/api/preview, etc.
```

## Installation

```bash
drush en eb_ui -y
```

For AG-Grid spreadsheet interface, also enable:
```bash
drush en eb_aggrid -y
```

## Grid Provider System

eb_ui discovers available grid providers via the `hook_eb_ui_grid_provider_info` hook:

```php
#[Hook('eb_ui_grid_provider_info')]
public function gridProviderInfo(): array {
  return [
    'my_provider' => [
      'id' => 'my_provider',
      'label' => $this->t('My Custom Grid'),
      'form_class' => '\Drupal\my_module\Form\MyGridForm',
      'library' => 'my_module/grid',
      'theme_class' => 'my-theme-class',
    ],
  ];
}
```

### Provider Selection

The active provider is determined by `eb_ui.settings.editor_mode`:

| Value | Behavior |
|-------|----------|
| `yaml` | Always use YAML editor |
| `auto` | Use first available provider, fall back to YAML |
| `{provider_id}` | Use specific provider |

## API Endpoints

### POST /eb/api/validate

Validates YAML/JSON content against EB operations.

**Headers Required:**
- `X-Requested-With: XMLHttpRequest`
- `X-CSRF-Token: {token}`
- `Content-Type: application/json` or `text/plain`

**Response:**
```json
{
  "valid": true,
  "operation_count": 5
}
```

### POST /eb/api/preview

Generates a preview of operations that will be performed.

**Headers Required:**
- `X-Requested-With: XMLHttpRequest`
- `X-CSRF-Token: {token}`

**Response:**
```json
{
  "success": true,
  "operation_count": 5,
  "previews": [
    {
      "index": 0,
      "type": "create_bundle",
      "summary": "Create node bundle 'article'",
      "details": {...},
      "warnings": []
    }
  ]
}
```

### GET /eb/api/bundles/{entity_type}

Fetches available bundles for an entity type.

**Response:**
```json
{
  "success": true,
  "bundles": {
    "article": {"id": "article", "label": "Article"},
    "page": {"id": "page", "label": "Basic page"}
  }
}
```

### GET /eb/api/entity-config/{entity_type}/{bundle}

Fetches existing field configuration for an entity/bundle.

**Response:**
```json
{
  "success": true,
  "entity_type": "node",
  "bundle": "article",
  "fields": {
    "field_body": {
      "name": "field_body",
      "label": "Body",
      "type": "text_long",
      "required": false
    }
  }
}
```

## YAML Editor

When no grid provider is active or when accessing the `/source` route, eb_ui displays a CodeMirror-based YAML editor:

### Features

- Syntax highlighting for YAML
- Line numbers
- Auto-indentation
- Error markers from validation

### CodeMirror CDN

The editor loads CodeMirror from CDN:

```yaml
# eb_ui.libraries.yml
codemirror:
  js:
    https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.18/codemirror.min.js: { type: external }
    https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.18/mode/yaml/yaml.min.js: { type: external }
  css:
    https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.65.18/codemirror.min.css: { type: external }
```

## Configuration

Navigate to **Configuration > Development > Entity Builder > UI Settings**:

| Setting | Default | Description |
|---------|---------|-------------|
| `editor_mode` | auto | Editor selection: yaml, auto, or provider ID |
| `yaml_editor` | codemirror_cdn | YAML editor type |

## Security

All API endpoints include:

- **CSRF Protection**: X-CSRF-Token header required for POST requests
- **AJAX Validation**: X-Requested-With header required
- **Authentication**: User must be authenticated
- **Content Size Limits**: Configurable maximum payload size
- **Nesting Depth Limits**: Configurable maximum JSON nesting

## Creating Custom Grid Providers

To create a custom grid provider:

1. **Implement the hook**:
```php
#[Hook('eb_ui_grid_provider_info')]
public function gridProviderInfo(): array {
  return [
    'my_grid' => [
      'id' => 'my_grid',
      'label' => $this->t('My Custom Grid'),
      'form_class' => '\Drupal\my_module\Form\MyGridForm',
      'library' => 'my_module/grid',
    ],
  ];
}
```

2. **Create the form class** extending `FormBase`:
```php
class MyGridForm extends FormBase {
  public function getFormId() {
    return 'my_grid_form';
  }

  public function buildForm(array $form, FormStateInterface $form_state) {
    // Build your grid interface
    // Use the shared API endpoints for validation/preview
  }
}
```

3. **Add access checker** (optional, for route priority):
```php
class MyGridAccess {
  public function access(AccountInterface $account): AccessResultInterface {
    $provider = $this->providerManager->getActiveProvider();
    return AccessResult::allowedIf($provider && $provider['id'] === 'my_grid');
  }
}
```

## Permissions

| Permission | Description |
|------------|-------------|
| `administer entity builder` | Access the UI |

## Related Modules

- **eb_aggrid**: AG-Grid spreadsheet provider for eb_ui
- **eb**: Core Entity Builder functionality
