Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ dependencies:
module:
- content_moderation
- metatag
- paragraphs
- paragraphs_simple_edit
- path
id: node.landing_page.default
targetEntityType: node
Expand Down Expand Up @@ -40,7 +40,7 @@ content:
use_details: true
third_party_settings: { }
field_paragraphs:
type: paragraphs
type: paragraphs_simple_edit_default
weight: 10
region: content
settings:
Expand All @@ -49,14 +49,15 @@ content:
edit_mode: closed
closed_mode: summary
autocollapse: none
closed_mode_threshold: 0
closed_mode_threshold: '0'
add_mode: dropdown
form_display_mode: default
default_paragraph_type: _none
features:
add_above: '0'
collapse_edit_all: collapse_edit_all
duplicate: duplicate
collapse_edit_all: collapse_edit_all
add_above: 0
convert: 0
third_party_settings: { }
langcode:
type: language_select
Expand Down
1 change: 1 addition & 0 deletions config/sync/core.extension.yml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ module:
page_cache: 0
pantheon_advanced_page_cache: 0
paragraphs_edit: 0
paragraphs_simple_edit: 0
password_policy_blacklist: 0
password_policy_character_types: 0
password_policy_length: 0
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* Claro theme automatically adds the .button--small class, which introduces
extra margin and padding. These overrides remove the unwanted spacing
applied to the link wrapper. */
.paragraph-simple-edit--add-button.dropbutton.button--small {
margin: 0;
padding: 0;
}

/* Claro theme applies certain admin styles (e.g., accordion, tabs) based on
class names. These overrides ensure paragraph widgets display correctly
regardless of their type. */
.paragraph-simple-edit--add-button li {
box-shadow: none;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
name: 'Paragraphs Simple Edit'
type: module
description: 'Provides a paragraphs field widget that allows editing, adding, and deleting paragraphs on dedicated pages.'
package: Paragraphs
core_version_requirement: ^10 || ^11
dependencies:
- drupal:field
- paragraphs:paragraphs
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
widget.claro:
version: 1.x
css:
theme:
css/paragraphs_simple_edit.claro.css: {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
paragraphs_simple_edit.add_form:
path: '/paragraphs-simple-edit/{root_parent_type}/{root_parent}/paragraph/{bundle}/add'
defaults:
_controller: '\Drupal\paragraphs_simple_edit\Controller\ParagraphsSimpleEditController::add'
requirements:
root_parent: \d+
options:
_admin_route: TRUE
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<?php

namespace Drupal\paragraphs_simple_edit\Controller;

use Drupal\Core\Controller\ControllerBase;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Access\AccessResult;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\Request;

/**
* Controller for showing a Paragraph add form targeted to a host entity.
*/
class ParagraphsSimpleEditController extends ControllerBase {

/**
* Show paragraph add form.
*/
public function add($root_parent_type, $root_parent, $bundle, Request $request) {

// Load host entity storage and the host entity itself.
// $entity_storage = $this->entityTypeManager->getStorage($host_entity_type);
// if (!$entity_storage) {
// throw new NotFoundHttpException("Unknown host entity type: $host_entity_type");
// }

// $host = $entity_storage->load($host_entity);
// if (!$host) {
// throw new NotFoundHttpException("Host entity not found: $host_entity_type $host_entity");
// }

// // Ensure the current user can view the host (basic protection).
// if (!$host->access('view')) {
// throw new NotFoundHttpException("Host entity not accessible.");
// }

// Create a paragraph entity of the requested bundle (unsaved).
//$paragraph_storage = $this->entityTypeManager->getStorage('paragraph');
// if (!$paragraph_storage) {
// // Paragraph module not enabled or entity type missing.
// throw new NotFoundHttpException("Paragraph entity type is not available on this site.");
// }

//$paragraph = $paragraph_storage->create(['type' => $paragraph_type]);

// Access check: can current user create this paragraph bundle?
// if (!$paragraph->access('create')) {
// // Use access denied rather than 404 if you prefer.
// return $this->accessDenied();
// }

// OPTIONAL / HELPFUL: If you want the paragraph form to know which host it
// will be attached to (so you can attach in the save path), you can add
// these as form state values or as query parameters. Here we inject them
// as #attached form build info (a small, non-invasive approach):
//
// The form can read these values in a hook_form_alter or in a custom form
// submit handler.
// $paragraph->parent_type = $host_entity_type;
// $paragraph->parent_id = $host_entity;

// Render and return the paragraph entity add form.
// Use the standard entity form builder. We present the default form mode.
//$form = $this->entityFormBuilder->getForm($paragraph, 'add');

// Attach the host info as a hidden form element so submit handlers can
// pick it up easily. We must alter the built form structure here.
// Only add if form is an array and not cached markup.
// if (is_array($form)) {
// $form['#cache']['contexts'][] = 'user'; // conservative cache context
// // Add hidden values for downstream submit handlers.
// $form['mymodule_host_info'] = [
// '#type' => 'value',
// '#value' => [
// 'host_entity_type' => $host_entity_type,
// 'host_entity_id' => $host_entity,
// ],
// ];
// }

$form['test'] = [
'#markup' => 'test',
];

return $form;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
<?php

namespace Drupal\paragraphs_simple_edit\Plugin\Field\FieldWidget;

use Drupal\Core\Entity\EntityFieldManagerInterface;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\Core\Field\Attribute\FieldWidget;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RedirectDestinationInterface;
use Drupal\Core\Theme\ThemeManagerInterface;
use Drupal\Core\Url;
use Drupal\paragraphs\Plugin\Field\FieldWidget\ParagraphsWidget;
use Drupal\Core\StringTranslation\TranslatableMarkup;
use Symfony\Component\DependencyInjection\ContainerInterface;

/**
* Plugin implementation of the 'paragraphs_simple_edit_default' widget.
*/
#[FieldWidget(
id: 'paragraphs_simple_edit_default',
label: new TranslatableMarkup('Simple Edit (Default)'),
description: new TranslatableMarkup('The paragraphs form that allows editing, adding, and deleting paragraphs on dedicated pages.'),
field_types: ['entity_reference_revisions']
)]
class ParagraphsSimpleEditDefaultWidget extends ParagraphsWidget {

/**
* The entity type manager.
*/
protected EntityTypeManagerInterface $entityTypeManager;

/**
* The theme manager.
*/
protected ThemeManagerInterface $themeManager;

/**
* The redirect destination
*/
protected RedirectDestinationInterface $redirectDestination;

/**
* Constructs a ParagraphsSimpleEditDefaultWidget object.
*
* @param string $plugin_id
* The plugin_id for the widget.
* @param mixed $plugin_definition
* The plugin implementation definition.
* @param \Drupal\Core\Field\FieldDefinitionInterface $field_definition
* The definition of the field to which the widget is associated.
* @param array $settings
* The widget settings.
* @param array $third_party_settings
* Any third party settings.
* @param \Drupal\Core\Entity\EntityFieldManagerInterface $entity_field_manager
* The entity field manager.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
* @param \Drupal\Core\Theme\ThemeManagerInterface $theme_manager
* The theme manager.
* @param \Drupal\Core\Routing\RedirectDestinationInterface $redirect_destination
* The redirect destination.
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, EntityFieldManagerInterface $entity_field_manager, EntityTypeManagerInterface $entity_type_manager, ThemeManagerInterface $theme_manager, RedirectDestinationInterface $redirect_destination) {
$this->entityTypeManager = $entity_type_manager;
$this->themeManager = $theme_manager;
$this->redirectDestination = $redirect_destination;
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings, $entity_field_manager);
}

/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$plugin_id,
$plugin_definition,
$configuration['field_definition'],
$configuration['settings'],
$configuration['third_party_settings'],
$container->get('entity_field.manager'),
$container->get('entity_type.manager'),
$container->get('theme.manager'),
$container->get('redirect.destination')
);
}

/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
$element = parent::formElement($items, $delta, $element, $form, $form_state);

$paragraph = $items[$delta]->entity;
if (!$paragraph || $paragraph->isNew()) {
return $element;
}

$host = $items->getEntity();

if (!$host->id()) {
// Edit and Delete links require saved paragraph entities with IDs.
// For new host entities, paragraphs are created on form submission.
return $element;
}

$destination = $this->redirectDestination->getAsArray();

$edit_url = Url::fromRoute('paragraphs_edit.edit_form', [
'root_parent_type' => $host->getEntityTypeId(),
'root_parent' => $host->id(),
'paragraph' => $paragraph->id(),
],
[
'query' => $destination,
]);

$delete_url = Url::fromRoute('paragraphs_edit.delete_form', [
'root_parent_type' => $host->getEntityTypeId(),
'root_parent' => $host->id(),
'paragraph' => $paragraph->id(),
],
[
'query' => $destination,
]);

$element['top']['actions']['actions'] = [
'#type' => 'dropbutton',
'#dropbutton_type' => 'extrasmall',
'#links' => [
'edit' => [
'title' => $this->t('Edit'),
'url' => $edit_url,
],
'delete' => [
'title' => $this->t('Delete'),
'url' => $delete_url,
],
],
'#weight' => 10,
];

return $element;
}

/**
* {@inheritdoc}
*/
public function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
$elements = parent::formMultipleElements($items, $form, $form_state);

$field_name = $this->fieldDefinition->getName();

if (!isset($elements['add_more'])) {
return $elements;
}

$bundle_fields = $this->entityFieldManager
->getFieldDefinitions($items->getEntity()->getEntityTypeId(), $items->getEntity()->bundle());

if (!isset($bundle_fields[$field_name])) {
return $elements;
}

$field_config = $bundle_fields[$field_name];
$handler_settings = $field_config->getSetting('handler_settings');
$target_bundles = $handler_settings['target_bundles'] ?? [];

if (empty($target_bundles)) {
$paragraph_types = $this->entityTypeManager
->getStorage('paragraphs_type')
->loadMultiple();
$target_bundles = array_keys($paragraph_types);
}

$add_links = [];
foreach ($target_bundles as $bundle) {
$paragraph_type = $this->entityTypeManager
->getStorage('paragraphs_type')
->load($bundle);

if (!$paragraph_type) {
continue;
}

$add_links[$bundle] = [
'title' => $this->t('Add @type', ['@type' => $paragraph_type->label()]),
'url' => Url::fromRoute('<front>'),
];
}

if (empty($add_links)) {
return $elements;
}

$elements['add_more'] = [
'#type' => 'dropbutton',
'#dropbutton_type' => 'extrasmall',
'#links' => $add_links,
'#attributes' => [
'class' => ['paragraph-simple-edit--add-button']
],
];

// Add css for claro theme to fix styling for add button.
if ($this->themeManager->getActiveTheme()->getName() == 'claro') {
$elements['add_more']['#attached']['library'][] = 'paragraphs_simple_edit/widget.claro';
}

return $elements;
}

}