Commit 4cc4036c authored by catch's avatar catch
Browse files

feat: #2409559 User should be able to identify required fields from field listing

By: @pameeela
By: @lauriii
By: @phenaproxima
By: @arpitr
By: @benjifisher
By: @catch
By: @dead_arm
By: @ckrina
(cherry picked from commit 2e4b5a62)
parent c9ad9ca8
Loading
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -66,3 +66,30 @@
.field-ui-overview .field-plugin-settings-edit-form .plugin-name {
  font-weight: bold;
}

.field-label-container {
  display: flex;
  flex-direction: column;
  min-width: 0;
}

.field-machine-name {
  white-space: nowrap;
}

.field-details-container {
  display: flex;
  flex-direction: row;
  align-items: flex-start;
  gap: 0.5rem;
}

.field-settings-summary-container {
  display: flex;
  flex-direction: column;
}

.field-settings-summary-items {
  display: flex;
  flex-direction: column;
}
+87 −11
Original line number Diff line number Diff line
@@ -119,11 +119,7 @@ public function load() {
   */
  public function buildHeader() {
    $header = [
      'label' => $this->t('Label'),
      'field_name' => [
        'data' => $this->t('Machine name'),
        'class' => [RESPONSIVE_PRIORITY_MEDIUM],
      ],
      'label' => $this->t('Field'),
      'settings_summary' => $this->t('Field type'),
    ];
    return $header + parent::buildHeader();
@@ -140,22 +136,102 @@ public function buildRow(EntityInterface $field_config) {
    $instance_summary = $this->fieldTypeManager->getFieldSettingsSummary($field_config);
    $summary_list = [...$storage_summary, ...$instance_summary];

    $secondary_summary_items = [];
    foreach ($summary_list as $item) {
      $secondary_summary_items[] = [
        '#type' => 'html_tag',
        '#tag' => 'div',
        '#value' => $item,
        '#attributes' => [
          'class' => ['field-ui-secondary-text'],
        ],
      ];
    }

    $settings_summary = [
      'data' => [
        '#theme' => 'item_list',
        '#items' => [
          $this->fieldTypeManager->getDefinitions()[$field_storage->getType()]['label'],
          ...$summary_list,
        '#type' => 'container',
        '#attributes' => ['class' => ['field-settings-summary-container']],
        'field_type' => [
          '#type' => 'html_tag',
          '#tag' => 'div',
          '#value' => $this->fieldTypeManager->getDefinitions()[$field_storage->getType()]['label'],
          '#attributes' => [
            'class' => ['field-type-label'],
          ],
        ],
        'summary_items' => [
          '#type' => 'container',
          '#attributes' => ['class' => ['field-settings-summary-items']],
          ...$secondary_summary_items,
        ],
      ],
      'class' => ['field-settings-summary-cell'],
    ];

    $cardinality = $field_storage->getCardinality();
    if ($cardinality === -1) {
      $cardinality_text = $this->t('Unlimited');
    }
    else {
      $cardinality_text = $this->formatPlural($cardinality, 'Single', 'Limited to @count');
    }

    $label_data = [
      'data' => [
        '#type' => 'container',
        '#attributes' => ['class' => ['field-label-container']],
        'label_wrapper' => [
          '#type' => 'container',
          '#attributes' => ['class' => ['field-label-wrapper']],
          'label' => [
            '#type' => 'html_tag',
            '#tag' => 'span',
            '#value' => $field_config->getLabel(),
            '#attributes' => [
              'class' => ['field-label-text'],
            ],
          ],
          'machine_name' => [
            '#type' => 'html_tag',
            '#tag' => 'span',
            '#value' => ' ' . $field_config->getName(),
            '#attributes' => [
              'class' => ['field-ui-secondary-text', 'field-machine-name'],
            ],
          ],
        ],
        'details' => [
          '#type' => 'container',
          '#attributes' => ['class' => ['field-details-container']],
          'cardinality_pill' => [
            '#type' => 'html_tag',
            '#tag' => 'span',
            '#value' => $cardinality_text,
            '#attributes' => [
              'class' => ['field-ui-pill'],
            ],
          ],
        ],
      ],
    ];

    // Add required pill if field is required.
    if ($field_config->isRequired()) {
      $label_data['data']['details']['required_pill'] = [
        '#type' => 'html_tag',
        '#tag' => 'span',
        '#value' => $this->t('Required'),
        '#attributes' => [
          'class' => ['field-ui-pill'],
        ],
      ];
    }

    $row = [
      'id' => Html::getClass($field_config->getName()),
      'data' => [
        'label' => $field_config->getLabel(),
        'field_name' => $field_config->getName(),
        'label' => $label_data,
        'settings_summary' => $settings_summary,
      ],
    ];
+6 −2
Original line number Diff line number Diff line
@@ -138,7 +138,7 @@ public function testLockedField(): void {

    // Check that the links for edit and delete are not present.
    $this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields');
    $locked = $this->xpath('//tr[@id=:field_name]/td[4]', [':field_name' => $field_name]);
    $locked = $this->xpath('//tr[@id=:field_name]/td[3]', [':field_name' => $field_name]);
    $this->assertSame('Locked', $locked[0]->getHtml(), 'Field is marked as Locked in the UI');
    $this->drupalGet('admin/structure/types/manage/' . $this->contentType . '/fields/node.' . $this->contentType . '.' . $field_name . '/delete');
    $this->assertSession()->statusCodeEquals(403);
@@ -271,7 +271,11 @@ public function testInvalidUrlsAndDestinations(): void {
    $this->drupalGet('admin/structure/types/manage/article/fields/node.article.body', $options);
    $this->submitForm([], 'Save settings');
    // The external redirect should not fire.
    $this->assertSession()->addressEquals('admin/structure/types/manage/article/fields/node.article.body?destinations%5B0%5D=http%3A//example.com');
    $url = parse_url($this->getSession()->getCurrentUrl());
    $this->assertStringEndsWith('/admin/structure/types/manage/article/fields/node.article.body', $url['path']);
    $query = [];
    parse_str($url['query'], $query);
    $this->assertSame(['http://example.com'], $query['destinations']);
    $this->assertSession()->statusCodeEquals(200);
    $this->assertSession()->responseContains('Attempt to update field <em class="placeholder">Body</em> failed: <em class="placeholder">The internal path component &#039;http://example.com&#039; is external. You are not allowed to specify an external URL together with internal:/.</em>.');
  }
+2 −2
Original line number Diff line number Diff line
@@ -44,7 +44,7 @@ protected function manageFieldsPage($type = ''): void {
    $type = empty($type) ? $this->contentType : $type;
    $this->drupalGet('admin/structure/types/manage/' . $type . '/fields');
    // Check all table columns.
    $table_headers = ['Label', 'Machine name', 'Field type', 'Operations'];
    $table_headers = ['Field', 'Field type', 'Operations'];
    foreach ($table_headers as $table_header) {
      // We check that the label appear in the table headings.
      $this->assertSession()->responseContains($table_header . '</th>');
@@ -299,7 +299,7 @@ protected function addPersistentFieldStorage(): void {
    $this->assertSession()->pageTextContains('Re-use an existing field');

    // Ensure that we test with a label that contains HTML.
    $label = $this->randomMachineName(4) . '<br/>' . $this->randomMachineName(4);
    $label = $this->randomMachineName(4) . '<br>' . $this->randomMachineName(4);
    // Add a new field for the orphaned storage.
    $this->fieldUIAddExistingField("admin/structure/types/manage/page", $this->fieldName, $label);
  }
+2 −3
Original line number Diff line number Diff line
@@ -89,9 +89,8 @@ public function testFieldDropButtonOperations(): void {
    // Check that the summary element for the string field type exists and has
    // the correct text (which comes from the FieldItemBase class).
    $element = $assert_session->elementExists('css', '#highlander');
    $summary = $assert_session->elementExists('css', '.field-settings-summary-cell > ul > li', $element);
    $field_label = $this->container->get('plugin.manager.field.field_type')->getDefinitions()['string']['label'];
    $this->assertEquals($field_label, $summary->getText());
    $field_label = (string) $this->container->get('plugin.manager.field.field_type')->getDefinitions()['string']['label'];
    $assert_session->elementExists('css', '.field-settings-summary-cell .field-type-label:contains("' . $field_label . '")', $element);

    // Add an entity reference field, and check that its summary is custom.
    /** @var \Drupal\field\FieldStorageConfigInterface $storage */
Loading