-
Notifications
You must be signed in to change notification settings - Fork 56
Paragraphs Simple Edit - CRUD on separate pages #938
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
tanmayk
wants to merge
10
commits into
Gizra:main
Choose a base branch
from
tanmayk:783-paragraphs-crud
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from 2 commits
Commits
Show all changes
10 commits
Select commit
Hold shift + click to select a range
dfe4077
Paragraphs simple edit module.
tanmayk 91c120e
Removed debug.
tanmayk 344713b
Paragraph add form.
tanmayk 3f1293c
Use route from paragraphs_modal_add.
tanmayk 9e10dcc
Settings & other changes.
tanmayk f004250
Added test.
tanmayk 98ae914
783 : Working tests with other required changes.
tanmayk a92063b
Added info text for new entities.
tanmayk dc6d611
Added more tests.
tanmayk 866d65f
Merge branch 'main' into 783-paragraphs-crud
tanmayk File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
14 changes: 14 additions & 0 deletions
14
web/modules/custom/paragraphs_simple_edit/css/paragraphs_simple_edit.claro.css
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | ||
| } |
8 changes: 8 additions & 0 deletions
8
web/modules/custom/paragraphs_simple_edit/paragraphs_simple_edit.info.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
5 changes: 5 additions & 0 deletions
5
web/modules/custom/paragraphs_simple_edit/paragraphs_simple_edit.libraries.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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: {} |
8 changes: 8 additions & 0 deletions
8
web/modules/custom/paragraphs_simple_edit/paragraphs_simple_edit.routing.yml
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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 |
89 changes: 89 additions & 0 deletions
89
web/modules/custom/paragraphs_simple_edit/src/Controller/ParagraphsSimpleEditController.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | ||
| } | ||
|
|
||
| } |
215 changes: 215 additions & 0 deletions
215
...paragraphs_simple_edit/src/Plugin/Field/FieldWidget/ParagraphsSimpleEditDefaultWidget.php
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| 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; | ||
| } | ||
|
|
||
| } | ||
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.