Skip to content

Commit

Permalink
YALB-1696: Hotfix: Can't configure Page title as Site admin (#547)
Browse files Browse the repository at this point in the history
* fix(YALB-1696): guard against empty block_form

Code was added in YALB-959 that attached javascript to specific block
types:

* tabs
* quick_links
* image_grids
* media_gallery

It referenced a block_form array that tells us which block type we are
currently attempting to use.  In some cases, though, like the heading
block, this block_form array does not exist, resulting in a background
error.  This makes it look as if the user cannot modify the block.

While block_form doesn't always exist, it seems that getting the
blockInfo and looking at the args can tell you which block type we are
dealing with.  I'm hoping there's a more elegant way of doing this, but
it does seem to be working for existing and new block elements.

In some cases, the arguments dictate the type of block, and in others,
it has a block_form object.  We abstract this to just get it.

* fix(YALB-1696): fallback js error to submit button

In fixing the block_form issue, I noticed that when testing the
functionality of YALB-959, there was an issue where paragraph items that
weren't expanded couldn't display the error message to the user, and
would error.  It would not hinder the submissions of the form, so it
would result in users being able to submit with one tab, for instance.

This fix checks if the input that was found is visible, and if not, it
appends the message to the submit button that we know is there, thus
letting the form continue to submit or stop.
  • Loading branch information
dblanken-yale authored Jan 24, 2024
1 parent eebfad2 commit d435f5b
Show file tree
Hide file tree
Showing 2 changed files with 98 additions and 42 deletions.
Original file line number Diff line number Diff line change
@@ -1,59 +1,78 @@
((Drupal) => {
Drupal.behaviors.ysCoreBlockForm = {
attach: () => { // eslint-disable-line
attach: () => {
// eslint-disable-line

/*
* Function to validate that all media items contain media.
*
* @param object blockType
* blockType object.
*
* @return string
* The error message or empty string.
* */
* Function to validate that all media items contain media.
*
* @param object blockType
* blockType object.
*
* @return string
* The error message or empty string.
* */
function getErrors(blockType) {
// Get all items of the specified type.
const items = document.querySelectorAll(blockType.itemSelector);

// Count the number of items present.
const numberOfItems = items.length;
if (numberOfItems < blockType.min || (blockType.max > 0 && numberOfItems > blockType.max)) {
let messageText = '';
if (
numberOfItems < blockType.min ||
(blockType.max > 0 && numberOfItems > blockType.max)
) {
let messageText = "";
if (blockType.max > 0) {
messageText = `Number of ${blockType.type} must be between ${blockType.min} and ${blockType.max}. `;
} else {
messageText = `Number of ${blockType.type} must be ${blockType.min} or more. `;
}
return messageText + `Number of ${blockType.type} added: ${numberOfItems}.`;
return (
messageText + `Number of ${blockType.type} added: ${numberOfItems}.`
);
}

// An empty string signifies no errors and resets validation for the input.
return '';
return "";
}

/*
* Function to validate a block type.
*
* @param object blocktype
* Object containing block type information for validation.
*
* @return void
* */
* Function to validate a block type.
*
* @param object blocktype
* Object containing block type information for validation.
*
* @return void
* */
function validateBlockType(blockType) {
// Get the layout builder add and update forms.
const blockContentForm = document.querySelector('form[id^="block-content"]');
const blockContentForm = document.querySelector(
'form[id^="block-content"]'
);
// Inputs and submit selectors are different on block content and layout builder forms.
const inputSelector = blockContentForm ? blockType.inputSelector : blockType.lbInputSelector;
const submitSelector = blockContentForm ? 'edit-submit' : 'edit-actions-submit';
const submitButton = document.querySelector(`input[data-drupal-selector=${submitSelector}]`);
const inputSelector = blockContentForm
? blockType.inputSelector
: blockType.lbInputSelector;
const submitSelector = blockContentForm
? "edit-submit"
: "edit-actions-submit";
const submitButton = document.querySelector(
`input[data-drupal-selector=${submitSelector}]`
);

if (submitButton) {
// On click, check for custom errors.
submitButton.addEventListener("click", () => {
const input = document.querySelector(inputSelector);
const errorMsg = getErrors(blockType);
// If there are any errors, set custom validity on the chosen input field.
input.setCustomValidity(errorMsg);
// If there are any errors, set custom validity on the chosen input field if it's visible.
if (input.type === "hidden") {
submitButton.setCustomValidity(errorMsg);
// Otherwise set it on the submit button.
} else {
input.setCustomValidity(errorMsg);
}
});
}
}
Expand All @@ -62,40 +81,44 @@
const blockTypes = [
{
// Tabs
itemSelector: 'tr.paragraph-type--tab',
itemSelector: "tr.paragraph-type--tab",
inputSelector: 'input[data-drupal-selector^="edit-field-tabs"]',
lbInputSelector: 'input[data-drupal-selector^="edit-settings-block-form-field-tabs"]',
lbInputSelector:
'input[data-drupal-selector^="edit-settings-block-form-field-tabs"]',
min: 2,
max: 5,
type: 'tabs',
type: "tabs",
},
{
// Quick links
itemSelector: 'input.ui-autocomplete-input',
itemSelector: "input.ui-autocomplete-input",
inputSelector: 'input[data-drupal-selector^="edit-field-heading"]',
lbInputSelector: 'input[data-drupal-selector^="edit-settings-block-form-field-links"]',
lbInputSelector:
'input[data-drupal-selector^="edit-settings-block-form-field-links"]',
min: 3,
max: 9,
type: 'links',
type: "links",
},
{
// Media Grid
itemSelector: '.paragraph-type--media-grid-item',
itemSelector: ".paragraph-type--media-grid-item",
inputSelector: 'input[data-drupal-selector^="edit-field-heading"]',
lbInputSelector: 'input[data-drupal-selector^="edit-settings-block-form-field-heading"]',
lbInputSelector:
'input[data-drupal-selector^="edit-settings-block-form-field-heading"]',
min: 2,
max: 0,
type: 'media grid items',
type: "media grid items",
},
{
// Gallery
itemSelector: '.paragraph-type--gallery-item',
itemSelector: ".paragraph-type--gallery-item",
inputSelector: 'input[data-drupal-selector^="edit-field-heading"]',
lbInputSelector: 'input[data-drupal-selector^="edit-settings-block-form-field-heading"]',
lbInputSelector:
'input[data-drupal-selector^="edit-settings-block-form-field-heading"]',
min: 2,
max: 0,
type: 'gallery items',
}
type: "gallery items",
},
];

// Apply the function to each block type.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -138,19 +138,20 @@ function ys_core_form_alter(&$form, $form_state, $form_id) {
];

if (in_array($form_id, $layout_builder_block_forms)) {
// Get the block type from the form.
$block = $form['settings']['block_form']['#block'];
$block_type_name = ys_core_get_block_type($form, $form_state);

$limited_block_types = [
'tabs',
'quick_links',
'media_grid',
'gallery',
];
if (in_array($block->bundle(), $limited_block_types)) {
if (in_array($block_type_name, $limited_block_types)) {
$form['#attached']['library'][] = 'ys_core/block_form';
}

}

}

/**
Expand Down Expand Up @@ -416,3 +417,35 @@ function ys_core_preprocess_page(&$variables) {
$config = \Drupal::config('ys_core.header_settings');
\Drupal::service('renderer')->addCacheableDependency($variables, $config);
}

/**
* Retrieves the block type from a form.
*
* @param array $form
* The form array.
* @param \Drupal\Core\Form\FormStateInterface $form_state
* The form state.
*
* @return string
* The block type name.
*/
function ys_core_get_block_type(&$form, &$form_state) {
$block_type_name = "";
$inline_block_type_name = $form_state->getBuildInfo()['args'][3];

// If adding a new element, arg 3 should be of the form:
// inline_block:BLOCK_TYPE_NAME.
if (strpos($inline_block_type_name, ':') !== FALSE) {
$block_type_name = explode(':', $inline_block_type_name)[1];
}
// Otherwise, attempt to get it the original way if it exists.
elseif (isset($form['settings']['block_form'])) {
$block_type_name = $form['settings']['block_form']['#block']->bundle();
}
// If we can't find it, make it something that will fail any future checks.
else {
$block_type_name = "unknown";
}

return $block_type_name;
}

0 comments on commit d435f5b

Please sign in to comment.