FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Issue 5915: clipboard by elzadj · Pull Request #5917 · maxi-blocks/maxi-blocks · GitHub

Issue 5915: clipboard - #5917

Draft
elzadj wants to merge 24 commits into
masterfrom
issue-5915-clipboard
Draft

elzadj wants to merge 24 commits into
masterfrom
issue-5915-clipboard

Conversation

elzadj commented Mar 28, 2025
edited by coderabbitai Bot
Loading

Copy link
Copy Markdown
Collaborator

Description

Adds copy and paste block styles to and from clipboard. Works between pages, sites, and browsers.

Note: please test on localhost, since browsers allow access to clipboard only from https or localhost (use docker if your local server has a different address)

Note 2: the first time you try to copy or paste styles, browsers is going to ask you for a permission, you need to allow it.

A first part for #5915

How Has This Been Tested?

Test the component in the toolbar. Try to copy and paste to and from a text editor. Try it between different pages, posts, FSE.

Test checklist

_ Front/Back Testing _

  • Test the component in normal state in sidebar
  • Test the component in hover state in sidebar (if hover exists)
  • Check that the settings work on frontend
  • Check that backend works and saves the settings after the editor reload
  • Same 1-4 points for the toolbar
  • Same 1-4 points on responsive
  • Test the block inside the grid (Container + Row + Column)
  • Test the block as a standalone block
  • Duplicate the block, test that the settings of the first do not affect the second
  • Test with 2 blocks of the same type

_ Pre-Code Testing _

  • Test the component in normal state in sidebar
  • Test the component in hover state in sidebar (if hover exists)
  • Check that the settings work on frontend
  • Check that backend works and saves the settings after the editor reload
  • Same 1-4 points for the toolbar
  • Same 1-4 points on responsive
  • Test the block inside the grid (Container + Row + Column)
  • Test the block as a standalone block
  • Duplicate the block, test that the settings of the first do not affect the second
  • Test with 2 blocks of the same type
  • Check no commented code and no unnecessary imports
  • Standards of the project have been followed
  • No errors/warnings on console

Checklist

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • My changes generate no new warnings/errors
  • I have added/updated tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes

Summary by CodeRabbit

  • New Features

    • Added clipboard integration for copying and pasting block styles with validation and error feedback.
    • Introduced persistent saved styles management with save, rename, delete, and apply capabilities.
    • Added a "Copy and paste styles" tab in the inspector across multiple block types.
    • Enabled saved styles access and management via new UI controls in the inspector and toolbar.
  • Enhancements

    • Improved UI styling and interactivity for saved styles controls and toolbar buttons.
    • Added toggle to switch between block-specific and all saved styles in the saved styles panel.
  • Bug Fixes

    • Improved reliability of copy-paste toolbar tests with better error handling and UI synchronization.
  • Documentation

    • Added internal documentation comments for improved code clarity.

elzadj added 🌟 enhancement New feature or request 2.0.9 labels Mar 28, 2025
elzadj requested review from Olekrut and kyrapieterse March 28, 2025 16:28
elzadj self-assigned this Mar 28, 2025
dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Mar 28, 2025

coderabbitai Bot commented Mar 28, 2025
edited
Loading

Copy link
Copy Markdown
Contributor

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 33d34657-57cd-4e3a-b6d1-c9fd27bb7c11

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This update introduces a comprehensive saved styles feature across multiple block types and the toolbar. It adds new backend REST API endpoints for persisting and retrieving saved styles, and implements a robust React component for managing saved styles, including filtering, renaming, deleting, and applying styles. The toolbar's copy-paste functionality is enhanced with clipboard integration, improved block type validation, saved styles management, user feedback, and UI updates. Inspector tabs for saved styles are integrated into various block inspectors. Accompanying these features are new and updated stylesheets and end-to-end tests, ensuring a cohesive user experience and reliable operation.

Changes

File(s) Change Summary
core/class-maxi-api.php Added REST API endpoints for getting and setting saved styles, with validation and permission checks.
src/components/saved-styles/index.js
src/components/saved-styles/editor.scss
New React component and styles for managing saved styles: loading, filtering, renaming, deleting, applying, and copying styles.
src/components/inspector-tabs/inspector-saved-styles.js
src/components/inspector-tabs/index.js
Added new inspector tab component and export for saved styles.
src/blocks/*/inspector.js (accordion, button, column, container, divider, group, image, list-item, map, number-counter, pane, row, search, slide, slider, svg-icon, text, video) Integrated the saved styles tab into the inspector controls for multiple block types.
src/components/toolbar/components/copy-paste/index.js Enhanced copy-paste component: clipboard integration, block type validation, saved styles management, user feedback, and UI updates.
src/components/toolbar/components/copy-paste/editor.scss Added error state styling for copy-paste toolbar buttons.
src/blocks/text-maxi/editor.scss Added styles for the save style button.
e2e-tests/components/toolbar/components/copy-paste/index.spec.js Updated tests: added error suppression, improved UI synchronization, and adjusted button indices.
src/extensions/store/actions.js
src/extensions/store/resolvers.js
Minor formatting and documentation comment added; no logic changes.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant BlockInspector
    participant SavedStylesComponent
    participant API
    participant Clipboard

    User->>BlockInspector: Opens inspector for a block
    BlockInspector->>SavedStylesComponent: Renders saved styles tab
    SavedStylesComponent->>API: GET /saved-styles
    API-->>SavedStylesComponent: Returns saved styles
    User->>SavedStylesComponent: Selects style, renames, deletes, or applies
    SavedStylesComponent->>API: POST /saved-styles (on save/rename/delete)
    API-->>SavedStylesComponent: Confirms update
    User->>SavedStylesComponent: Clicks "Copy" or "Paste"
    SavedStylesComponent->>Clipboard: Writes or reads style data
    Clipboard-->>SavedStylesComponent: Returns clipboard data
    SavedStylesComponent->>BlockInspector: Applies styles to block
Loading
sequenceDiagram
    participant User
    participant ToolbarCopyPaste
    participant Clipboard
    participant API

    User->>ToolbarCopyPaste: Opens copy-paste popover
    User->>ToolbarCopyPaste: Clicks "Copy to Clipboard"
    ToolbarCopyPaste->>Clipboard: Writes style JSON
    User->>ToolbarCopyPaste: Clicks "Paste from Clipboard"
    ToolbarCopyPaste->>Clipboard: Reads style JSON
    Clipboard-->>ToolbarCopyPaste: Returns style JSON
    ToolbarCopyPaste->>ToolbarCopyPaste: Validates block type
    ToolbarCopyPaste->>API: (Optionally) POST /saved-styles on save
    API-->>ToolbarCopyPaste: Confirms save
    ToolbarCopyPaste->>User: Updates UI with feedback
Loading

Suggested labels

ui, Final code review, size:L, 2.1.0

Suggested reviewers

  • Olekrut

Poem

🐇✨
A rabbit hopped through fields of style,
Saving colors, borders, all the while.
With clipboard magic, blocks now gleam,
Copy, paste, and manage—what a dream!
Tabs for every block, new buttons to press,
This garden of styles is now truly the best.
🌿🎨

✨ Finishing Touches 🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issue-5915-clipboard

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Actionable comments posted: 1

🧹 Nitpick comments (1)
src/components/toolbar/components/copy-paste/index.js (1)

159-169: Consider adding user feedback for clipboard operations.

While the implementation of copying to the clipboard is technically sound, users won't receive any feedback if the operation fails or succeeds. They'll only see console errors if something goes wrong.

Consider adding a simple notification or toast message to inform users about the success or failure of the clipboard operation:

const onCopyStylesToClipboard = async () => {
  try {
    // Copy to system clipboard using native API
    await navigator.clipboard.writeText(
      JSON.stringify(blockAttributes)
    );
    closeMoreSettings();
+   // If you have a notification system
+   dispatch('core/notices').createNotice(
+     'success',
+     __('Styles copied to clipboard!', 'maxi-blocks'),
+     { type: 'snackbar' }
+   );
  } catch (err) {
    console.error('Failed to copy styles:', err);
+   // Show error to user
+   dispatch('core/notices').createNotice(
+     'error',
+     __('Failed to copy styles to clipboard. Please grant permission when prompted.', 'maxi-blocks'),
+     { type: 'snackbar' }
+   );
  }
};
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9272f01 and 5b587f9.

📒 Files selected for processing (3)
  • src/components/toolbar/components/copy-paste/index.js (3 hunks)
  • src/components/toolbar/components/more-settings/editor.scss (1 hunks)
  • src/extensions/store/actions.js (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: e2e-js
🔇 Additional comments (4)
src/components/toolbar/components/more-settings/editor.scss (1)

20-20: Width increase accommodates new clipboard buttons.

The popover width has been increased from 190px to 210px to provide adequate space for the newly added clipboard copy/paste buttons in the CopyPaste component.

src/extensions/store/actions.js (1)

125-145: Good implementation of cross-browser clipboard functionality.

The code now supports both modern and legacy clipboard APIs:

  1. First attempts to use the modern navigator.clipboard.writeText API
  2. Falls back to the older document.execCommand('copy') method if needed
  3. Includes appropriate error handling for both approaches

This ensures broad browser compatibility while leveraging modern APIs when available.

src/components/toolbar/components/copy-paste/index.js (2)

331-341: Well-implemented clipboard reading utility.

The readFromClipboard function is well-structured:

  • Properly handles async/await pattern
  • Includes specific error messages for different failure scenarios
  • Throws appropriate errors that can be caught by the caller

514-525: New clipboard buttons enhance cross-site style sharing.

These new buttons provide a valuable feature for users to copy styles across different pages, sites, and browsers using the system clipboard. This implementation achieves the core objective of the PR.

elzadj marked this pull request as draft March 31, 2025 15:51
elzadj removed the request for review from Olekrut April 4, 2025 14:36
elzadj marked this pull request as ready for review April 4, 2025 14:40
dosubot Bot added size:XL This PR changes 500-999 lines, ignoring generated files. and removed size:L This PR changes 100-499 lines, ignoring generated files. labels Apr 4, 2025

coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Actionable comments posted: 5

♻️ Duplicate comments (1)
src/components/toolbar/components/copy-paste/index.js (1)

195-205: ⚠️ Potential issue

Add permission handling for clipboard operations.

The implementation handles JSON stringify errors but doesn't specifically address the case where a user denies clipboard permission, which is common on first use.

Enhance the error handling to provide clearer messaging for permission issues:

const onCopyStylesToClipboard = async () => {
    try {
        // Copy to system clipboard using native API
        await navigator?.clipboard?.writeText(
            JSON.stringify(blockAttributes)
        );
        closeMoreSettings();
    } catch (err) {
+       // Check for permission errors
+       if (err.name === 'NotAllowedError' || err.message.includes('permission')) {
+           console.error('Clipboard permission denied:', err);
+           // Show user-friendly message
+           setErrorMessage(__('Clipboard permission required', 'maxi-blocks'));
+           return;
+       }
        console.error('Failed to copy styles:', err);
    }
};
🧹 Nitpick comments (6)
src/blocks/text-maxi/editor.scss (1)

65-87: New styling added for save style button.

The new CSS classes provide a consistent and visually appealing styling for the save style button, including hover and focus states. The styles follow the application's design system by using CSS variables for colors.

Some suggestions for improvement:

  • Consider adding a transition for the box-shadow property on focus
  • For better accessibility, you might want to increase the contrast ratio between text and background colors
.maxi-save-style-control {
	.maxi-save-style-button {
		width: 100%;
		padding: 8px 12px;
		background-color: var(--maxi-primary-color);
		color: #fff;
		border: none;
		border-radius: 4px;
		cursor: pointer;
		font-size: 13px;
		line-height: 1.4;
-		transition: background-color 0.2s ease;
+		transition: background-color 0.2s ease, box-shadow 0.2s ease;

		&:hover {
			background-color: var(--maxi-secondary-color);
		}

		&:focus {
			outline: none;
			box-shadow: 0 0 0 2px rgba(0, 124, 186, 0.3);
		}
	}
}
src/components/saved-styles/index.js (2)

28-60: Loading styles implementation handles errors appropriately.

The code properly handles loading of saved styles with error handling and sets loading states correctly. It also has logic to auto-select a style if there's one stored in a global variable.

Some suggestions for improvement:

  • Add a timeout to the API call to prevent hanging if the server doesn't respond
  • Consider implementing a retry mechanism for failed API calls
const loadStyles = async () => {
	setIsLoading(true);
	try {
+		const controller = new AbortController();
+		const timeoutId = setTimeout(() => controller.abort(), 10000); // 10 second timeout
+
		const response = await apiFetch({
			path: '/maxi-blocks/v1.0/saved-styles',
+			signal: controller.signal,
		});
+		clearTimeout(timeoutId);

		// Parse the response if needed
		const parsedResponse =
			typeof response === 'string'
				? JSON.parse(response)
				: response;

		setLocalSavedStyles(parsedResponse || {});

		// Check if there's a style to auto-select from the global variable
		if (
			window.maxiLastSavedStyleName &&
			parsedResponse[window.maxiLastSavedStyleName]
		) {
			setSelectedStyle(window.maxiLastSavedStyleName);
			// Clear the global variable after using it
			window.maxiLastSavedStyleName = null;
		}
	} catch (err) {
+		if (err.name === 'AbortError') {
+			console.error('Request timed out when loading styles');
+		} else {
			console.error('Error loading saved styles:', err);
+		}
		setLocalSavedStyles({});
	}
	setIsLoading(false);
};

182-262: Component UI rendering is well-structured and handles different states.

The component renders different UIs based on the component state (renaming, loading, etc.). It provides good user feedback and disables controls appropriately when operations are in progress.

Two suggestions for improvement:

  1. Add confirmation before deleting a style to prevent accidental deletions
  2. Consider adding tooltips for buttons to improve usability

Implementing a confirmation for style deletion would improve user experience:

-							<Button onClick={handleDelete} disabled={isLoading}>
+							<Button 
+								onClick={() => {
+									if (window.confirm(__('Are you sure you want to delete this style?', 'maxi-blocks'))) {
+										handleDelete();
+									}
+								}} 
+								disabled={isLoading}
+							>
								{isLoading
									? __('Deleting…', 'maxi-blocks')
									: __('Delete', 'maxi-blocks')}
							</Button>
src/components/toolbar/components/copy-paste/index.js (3)

367-377: Improve error handling specificity in readFromClipboard.

The function correctly reads from clipboard and handles errors, but could be more specific about permission errors.

const readFromClipboard = async () => {
    try {
        const text = await navigator.clipboard.readText();
        if (!text) {
            throw new Error('Clipboard is empty');
        }
        return text;
    } catch (err) {
+       // Distinguish between permission errors and other errors
+       if (err.name === 'NotAllowedError') {
+           throw new Error('Clipboard permission denied');
+       }
        throw new Error('Failed to read from clipboard');
    }
};

379-426: Improve JSON validation and error handling.

The implementation provides basic JSON validation and error handling, but could be more robust.

const onPasteStylesFromClipboard = async () => {
    try {
        const clipboardText = await readFromClipboard();
        const trimmedContent = clipboardText.trim();

        if (!trimmedContent || trimmedContent === '') {
            setErrorMessage(__('Empty clipboard', 'maxi-blocks'));
            return;
        }

-       if (
-           !trimmedContent.startsWith('{') ||
-           !trimmedContent.endsWith('}')
-       ) {
-           setErrorMessage(__('Invalid clipboard format', 'maxi-blocks'));
-           return;
-       }

        let clipboardData;
        try {
            clipboardData = JSON.parse(trimmedContent);
        } catch (err) {
            setErrorMessage(__('Invalid clipboard data', 'maxi-blocks'));
            return;
        }

        if (!clipboardData || typeof clipboardData !== 'object') {
            setErrorMessage(__('Invalid data format', 'maxi-blocks'));
            return;
        }

        const styles = excludeAttributes(
            clipboardData,
            attributes,
            copyPasteMapping
        );

        closeMoreSettings();
        handleAttributesOnPaste(styles);
        updateBlockAttributes(clientId, styles);
        onPasteStylesIntoRepeaterBlock();
        setPasteButtonText(
            __('Paste styles from clipboard - all', 'maxi-blocks')
        );
    } catch (err) {
+       // Check for specific error types
+       if (err.message === 'Clipboard permission denied') {
+           setErrorMessage(__('Clipboard permission required', 'maxi-blocks'));
+       } else {
            setErrorMessage(__('Failed to read clipboard', 'maxi-blocks'));
+       }
    }
};

The basic JSON validation with startsWith and endsWith was removed because the proper JSON.parse will handle validation more accurately.


597-597: Consider importing MAX_SAVED_STYLES from a constants file.

The MAX_SAVED_STYLES constant is defined as 100 here, but it's also defined in src/components/saved-styles/index.js with the same value. It would be better to define it in a single location and import it to avoid potential inconsistencies.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 22223c8 and 981fa1f.

📒 Files selected for processing (29)
  • core/class-maxi-api.php (2 hunks)
  • e2e-tests/components/toolbar/components/copy-paste/index.spec.js (5 hunks)
  • src/blocks/accordion-maxi/inspector.js (1 hunks)
  • src/blocks/button-maxi/inspector.js (2 hunks)
  • src/blocks/column-maxi/inspector.js (1 hunks)
  • src/blocks/container-maxi/inspector.js (1 hunks)
  • src/blocks/divider-maxi/inspector.js (1 hunks)
  • src/blocks/group-maxi/inspector.js (1 hunks)
  • src/blocks/image-maxi/inspector.js (1 hunks)
  • src/blocks/list-item-maxi/inspector.js (1 hunks)
  • src/blocks/map-maxi/inspector.js (1 hunks)
  • src/blocks/number-counter-maxi/inspector.js (1 hunks)
  • src/blocks/pane-maxi/inspector.js (1 hunks)
  • src/blocks/row-maxi/inspector.js (1 hunks)
  • src/blocks/search-maxi/inspector.js (1 hunks)
  • src/blocks/slide-maxi/inspector.js (1 hunks)
  • src/blocks/slider-maxi/inspector.js (1 hunks)
  • src/blocks/svg-icon-maxi/inspector.js (2 hunks)
  • src/blocks/text-maxi/editor.scss (1 hunks)
  • src/blocks/text-maxi/inspector.js (1 hunks)
  • src/blocks/video-maxi/inspector.js (1 hunks)
  • src/components/inspector-tabs/index.js (1 hunks)
  • src/components/inspector-tabs/inspector-saved-styles.js (1 hunks)
  • src/components/saved-styles/editor.scss (1 hunks)
  • src/components/saved-styles/index.js (1 hunks)
  • src/components/toolbar/components/copy-paste/editor.scss (1 hunks)
  • src/components/toolbar/components/copy-paste/index.js (6 hunks)
  • src/extensions/store/actions.js (1 hunks)
  • src/extensions/store/resolvers.js (1 hunks)
✅ Files skipped from review due to trivial changes (2)
  • src/extensions/store/resolvers.js
  • src/components/saved-styles/editor.scss
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/extensions/store/actions.js
  • e2e-tests/components/toolbar/components/copy-paste/index.spec.js
🧰 Additional context used 🧬 Code Definitions (3) src/components/inspector-tabs/inspector-saved-styles.js (1)
src/components/saved-styles/index.js (2)
  • props (19-19)
  • SavedStyles (18-263)
src/components/saved-styles/index.js (11)
src/blocks/text-maxi/inspector.js (1)
  • props (23-29)
src/blocks/accordion-maxi/inspector.js (1)
  • props (25-33)
src/blocks/column-maxi/inspector.js (1)
  • props (22-23)
src/blocks/container-maxi/inspector.js (1)
  • props (28-34)
src/blocks/button-maxi/inspector.js (1)
  • props (35-36)
src/blocks/divider-maxi/inspector.js (1)
  • props (26-34)
src/blocks/image-maxi/inspector.js (1)
  • props (42-42)
src/blocks/number-counter-maxi/inspector.js (1)
  • props (23-29)
src/blocks/map-maxi/inspector.js (1)
  • props (32-40)
src/blocks/row-maxi/inspector.js (2)
  • props (22-30)
  • props (61-62)
src/extensions/store/actions.js (1)
  • select (60-61)
src/components/toolbar/components/copy-paste/index.js (2)
src/components/inspector-tabs/inspector-saved-styles.js (1)
  • savedStyles (11-16)
src/components/saved-styles/index.js (1)
  • MAX_SAVED_STYLES (16-16)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: e2e-js
🔇 Additional comments (38)
src/components/inspector-tabs/index.js (1)

35-35: Properly exposes new functionality for inspector tabs.

The addition of the savedStyles export aligns well with the PR objective of implementing clipboard functionality for block styles. The export follows the consistent pattern established in this file.

src/blocks/slide-maxi/inspector.js (1)

64-66: Good implementation of savedStyles in slide block.

The integration of the saved styles functionality into the slide block's inspector follows the established pattern of other inspector tabs. The placement after the context loop section is consistent with implementations in other block types.

src/blocks/row-maxi/inspector.js (1)

129-131: Consistent implementation of savedStyles in row block.

The saved styles feature is properly integrated into the row block's inspector settings tab, following the same implementation pattern seen in other blocks. This ensures consistent UI/UX across different block types.

src/blocks/column-maxi/inspector.js (1)

93-95: Well-integrated savedStyles implementation for column block.

The saved styles functionality is correctly added to the column block's inspector, maintaining consistency with other block implementations. This completes the clipboard functionality across the column structure hierarchy (row → column).

src/blocks/slider-maxi/inspector.js (1)

192-194: Successfully integrated saved styles tab into slider block inspector

This addition integrates the new saved styles functionality into the slider block's inspector panel, allowing users to copy and paste block styles as described in the PR objectives.

src/blocks/divider-maxi/inspector.js (1)

275-277: Successfully integrated saved styles tab into divider block inspector

The saved styles functionality has been properly added to the divider block's inspector panel, consistent with the implementation in other block types.

src/blocks/map-maxi/inspector.js (1)

199-201: Successfully integrated saved styles tab into map block inspector

The saved styles functionality has been properly implemented in the map block's inspector panel, allowing users to copy and paste styles via the system clipboard as intended.

src/blocks/video-maxi/inspector.js (1)

225-227:

Details

✅ Verification successful

Successfully integrated saved styles tab into video block inspector

The saved styles functionality has been correctly added to the video block's inspector panel, consistent with the implementation in other blocks.

Let's verify that the savedStyles component is properly exported from the inspector-tabs module:


🏁 Script executed:

#!/bin/bash
# Check if the savedStyles function is properly exported in the inspector-tabs module
cat src/components/inspector-tabs/index.js | grep -A 3 "export.*savedStyles"

# Also check if there's an implementation file for this functionality
find src/components -name "*saved-styles*" -type f

Length of output: 254


Integration Confirmed:
The savedStyles functionality is correctly integrated into the video block inspector. The verification confirms that the savedStyles function is properly exported from src/components/inspector-tabs/index.js (with the corresponding implementation available in src/components/inspector-tabs/inspector-saved-styles.js), and its usage in src/blocks/video-maxi/inspector.js aligns with how it's implemented in other blocks.

src/components/toolbar/components/copy-paste/editor.scss (1)

152-155: Good error styling implementation.

The new CSS class for error state styling provides clear visual feedback when clipboard operations fail. The red color is a conventional choice for error indication, and using float: left !important ensures the error message is properly aligned regardless of other styles.

src/components/inspector-tabs/inspector-saved-styles.js (1)

1-18: Well-structured component implementation.

The savedStyles component is cleanly implemented, following best practices:

  • Proper import organization with WordPress and internal dependencies clearly separated
  • Good use of internationalization via the __ function for translations
  • Component correctly passes all props to the underlying SavedStyles component
  • Clear structure with a labeled return object

This implementation aligns well with the PR objective of enabling clipboard styling functionality.

src/blocks/pane-maxi/inspector.js (1)

140-145: Successfully integrated saved styles functionality.

The changes correctly integrate the saved styles functionality into the inspector panel, allowing users to copy and paste styles as outlined in the PR objectives. The removal of the contentType: 'pane' property and addition of the savedStyles tab maintain a consistent pattern being applied across multiple block types.

src/blocks/image-maxi/inspector.js (1)

454-459: Successfully integrated saved styles functionality.

The modifications correctly integrate the saved styles functionality into the Image block inspector. Removing the prefix from the marginPadding call and adding the savedStyles tab maintains consistency with how this feature is being implemented across other blocks.

src/blocks/list-item-maxi/inspector.js (1)

73-75: Added savedStyles tab to the Inspector

This change adds the savedStyles functionality to the List Item Maxi block inspector, allowing users to save and load block styles. This aligns with the PR objective of implementing clipboard functionality for styles across pages and sites.

src/blocks/search-maxi/inspector.js (1)

403-405: Added savedStyles tab to the Inspector

This change adds the savedStyles functionality to the Search Maxi block inspector, enabling users to save and load block styles. This is consistent with the implementation in other block inspectors and supports the PR's clipboard functionality objective.

src/blocks/number-counter-maxi/inspector.js (1)

115-117: Added savedStyles tab to the Inspector

This change adds the savedStyles functionality to the Number Counter Maxi block inspector, enabling users to save and load block styles. This matches the implementation pattern found in other block inspectors and supports the clipboard functionality initiative.

src/blocks/button-maxi/inspector.js (2)

294-296: Added savedStyles tab to the Settings section

This change adds the savedStyles functionality to the Button Maxi block inspector's Settings section, allowing users to save and load block styles. This supports the clipboard copy/paste functionality objective of the PR.


384-386: Duplicate savedStyles tab in Advanced section

The savedStyles functionality has been added to both the Settings and Advanced sections. While this provides multiple access points, it creates duplicate functionality which may be confusing to users.

Verify that having the savedStyles tab in both sections is intentional and necessary. If not, consider removing one of them for consistency with other block inspectors, which typically only include this functionality once.

src/blocks/accordion-maxi/inspector.js (1)

212-216: Added savedStyles inspector tab

The addition of inspectorTabs.savedStyles and removal of the contentType parameter from contextLoop implements the clipboard functionality for copying and pasting block styles as mentioned in the PR objectives. This change enhances the accordion block with the ability to save and load styles, improving workflow efficiency across pages and sites.

src/blocks/text-maxi/inspector.js (1)

137-139: Added savedStyles inspector tab to text block

The addition of the savedStyles inspector tab properly integrates the clipboard functionality into the text block, allowing users to copy and paste styles as outlined in the PR objectives. This implementation maintains consistency with other block types and enhances user experience.

src/blocks/group-maxi/inspector.js (1)

62-66: Added savedStyles tab and simplified contextLoop

The modification removes the hardcoded contentType parameter from contextLoop and adds the new savedStyles functionality. This change is consistent with the pattern applied to other blocks, ensuring a unified approach to the clipboard feature implementation across all block types.

src/blocks/container-maxi/inspector.js (1)

114-118: Added savedStyles tab to container block

The addition of the savedStyles inspector tab and the simplification of the contextLoop call align with the changes made in other block types. This implementation ensures that container blocks can also participate in the clipboard-based style copying and pasting functionality as described in the PR objectives.

src/blocks/svg-icon-maxi/inspector.js (2)

20-20: Import statement simplified for better readability.

The imports for getColorRGBAString and getGroupAttributes have been consolidated into a single line, which improves code readability while maintaining the same functionality.


301-303: Added "Saved Styles" feature to the inspector settings.

This addition integrates the saved styles functionality into the SVG icon inspector settings tab, which allows users to save, load, and manage styles for SVG icons. This change is part of the PR objective to introduce copy and paste block styles functionality.

core/class-maxi-api.php (2)

357-377: Added new API routes for saved styles.

These new routes provide the backend API support for the clipboard functionality, allowing the client to save and retrieve styles from the server. The permission check ensures only users with appropriate permissions can access these endpoints.

The validation for the POST route properly ensures that the styles parameter is a string, which is in line with the expected JSON string format.


1216-1232: Implementation of get_maxi_blocks_saved_styles method.

This method retrieves saved styles from the database in a secure manner using prepared SQL statements. It properly handles the case when no saved styles exist by returning an empty JSON object.

src/components/saved-styles/index.js (8)

16-17: Defined maximum number of saved styles.

Setting a maximum limit of 100 saved styles is a good practice to prevent potential performance issues with an unlimited number of styles.


18-26: Component state management is well-structured.

The component uses React hooks to manage state in a clean and organized manner. All necessary states for handling the saved styles functionality are properly defined.


62-71: Auto-selection of first available style.

This is a good UX improvement to automatically select the first available style when styles are loaded and none is currently selected.


73-91: Copy to clipboard implementation is secure.

The copy to clipboard functionality uses the modern Clipboard API and properly handles errors. It also provides feedback to the user when the copy is successful.


93-121: Rename functionality is well-implemented.

The rename functionality properly updates both the local state and the server data. It handles loading states correctly and resets the UI after completion.


123-147: Delete functionality is properly implemented.

The delete operation correctly removes the style from both local state and the server. It handles loading states and properly resets the selected style after deletion.


175-181: Styles list transformation and count are correctly implemented.

The code correctly transforms the object of saved styles into a format suitable for the SelectControl component, and it keeps track of the number of saved styles for display.


1-15: Dependencies and imports are correct.

The component imports all necessary dependencies from WordPress and internal components. The inclusion of editor.scss ensures that the component styling is properly loaded.

src/components/toolbar/components/copy-paste/index.js (5)

5-7: Imports now correctly include all necessary dependencies.

The imports have been properly updated to include the required functions and hooks for the new clipboard functionality.


69-73: State variables correctly initialized for clipboard operations.

Good implementation of state variables for managing the paste button text and storing saved styles.


74-93: Properly implemented API fetch for saved styles.

The useEffect hook correctly loads saved styles when the component mounts, with proper error handling and response parsing.


95-102: Well-implemented error message handling with auto-reset.

The setErrorMessage function provides a good user experience by temporarily showing error messages and automatically resetting them after 3 seconds.


548-566: Good implementation of clipboard buttons with error state handling.

The buttons for copying and pasting styles to/from the clipboard are well-implemented. The paste button correctly displays error messages with appropriate styling.

Comment thread core/class-maxi-api.php
elzadj added 2.1.0 and removed 2.0.9 labels Apr 9, 2025
elzadj removed the 2.1.0 label Apr 14, 2025
elzadj added the 2.1.1 label Apr 14, 2025
elzadj marked this pull request as draft April 14, 2025 09:47
elzadj marked this pull request as ready for review May 2, 2025 15:40
dosubot Bot added size:XXL This PR changes 1000+ lines, ignoring generated files. and removed size:XL This PR changes 500-999 lines, ignoring generated files. labels May 2, 2025

coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Actionable comments posted: 2

♻️ Duplicate comments (1)
src/components/saved-styles/index.js (1)

95-111: Using globals for cross-component communication is brittle

The component relies on window.maxiLastSavedStyleName / window.maxiLastSavedStyleBlockType (set by the toolbar) to auto-select a just-saved style. Storing transient state on window easily breaks in iframes, tests, or when multiple editors run on the page.

Previous reviews already flagged this pattern. Please consider a scoped state solution (e.g. a custom data store, React Context, or @wordpress/data selector) to avoid hidden coupling.

🧹 Nitpick comments (5)
src/components/saved-styles/editor.scss (1)

11-24: Add focus-visible styles for keyboard accessibility.

Buttons inside __filter-toggle have hover feedback but no :focus / :focus-visible style. Users navigating with a keyboard will not receive any visual cue when the button is focused. Consider adding something like:

&__filter-toggle {
  .maxi-saved-styles-control__filter-button.components-button {
     …
+    &:focus-visible {
+       outline: 2px solid var(--wp-admin-theme-color);
+       outline-offset: 1px;
+    }
  }
}

This small addition meets WCAG 2.1 AA §2.4.7 (“Focus Visible”).

src/components/saved-styles/index.js (1)

197-204: Clear the timeout on unmount to avoid state-update warnings.

setTimeout stores an id but isn’t cleared in useEffect cleanup, so if the component unmounts (<3 s) React will warn: “Cannot perform a React state update on an unmounted component”.

// after setCopySuccess(true);
const timer = setTimeout(() => setCopySuccess(false), 3000);

return () => clearTimeout(timer); // inside useEffect or copy handler
src/components/toolbar/components/copy-paste/index.js (3)

5-5: Shadowed identifier can confuse readers.

select is imported here:

import { select, useSelect, useDispatch, dispatch } from '@wordpress/data';

Inside the large useSelect call the parameter is also named select, shadowing the outer variable. This is legal but increases cognitive load.
Rename one of them (e.g. import { select as wpSelect … }).


104-111: Reset-message timeout should be cleared on unmount.

setTimeout is created in setErrorMessage, but not cleaned up, leading to possible memory leaks when the popover closes quickly. Store the id in useRef and clear it in a useEffect cleanup.


415-425: Differentiate clipboard permission errors for better UX.

readFromClipboard converts any failure into "Failed to read from clipboard", losing information. Detect NotAllowedError to tell the user that permission was denied, matching earlier review feedback.

catch (err) {
-   throw new Error('Failed to read from clipboard');
+   if (err.name === 'NotAllowedError') {
+     throw new Error('permission');
+   }
+   throw new Error('general');
}

…and adjust the caller to show specific notices.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ed248e0 and 294fe48.

📒 Files selected for processing (6)
  • core/class-maxi-api.php (2 hunks)
  • src/components/inspector-tabs/inspector-saved-styles.js (1 hunks)
  • src/components/saved-styles/editor.scss (1 hunks)
  • src/components/saved-styles/index.js (1 hunks)
  • src/components/toolbar/components/copy-paste/index.js (8 hunks)
  • src/extensions/store/actions.js (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/extensions/store/actions.js
  • core/class-maxi-api.php
🧰 Additional context used 🧬 Code Graph Analysis (1) src/components/inspector-tabs/inspector-saved-styles.js (1)
src/components/saved-styles/index.js (2)
  • props (37-37)
  • SavedStyles (36-450)
🔇 Additional comments (1)
src/components/inspector-tabs/inspector-saved-styles.js (1)

12-49: Is it intentional that SavedStylesTab returns a plain object instead of a React element?

SavedStylesTab returns

{ label: 'Copy and paste styles', content: <SavedStyles  /> }

rather than JSX. This works only if every consumer of this module expects such an object (e.g. a tab-registration helper). If any code treats SavedStylesTab as a normal React component ( <SavedStylesTab …/> ), React will warn (Objects are not valid as a React child …) and the UI will break.

Please double-check the import sites (e.g. inspector-tabs/index.js) to be sure the returned shape is indeed what the framework expects; otherwise wrap the object in a component or convert the consumer.

elzadj requested a review from Olekrut May 5, 2025 10:05

kyrapieterse left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Cool

dosubot Bot added the lgtm This PR has been approved by maintainer label May 6, 2025
elzadj removed the 2.1.1 label Jun 2, 2025
elzadj marked this pull request as draft August 26, 2025 13:07
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

🌟 enhancement New feature or request lgtm This PR has been approved by maintainer size:XXL This PR changes 1000+ lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants


Back | FazBrowse Home | New Git URL