Skip to content

1020 integrate add blocks get client blocks reactors #1149

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

Merged
merged 13 commits into from
Jun 2, 2025

Conversation

Paulson-Robert
Copy link
Contributor

Description

Changes Made

How to Test

  1. Steps to reproduce/test the behavior
  2. Expected outcomes

Notes

…ntegerate-AddBlocks-GetClientBlocks-reactors
@Paulson-Robert Paulson-Robert requested a review from a team as a code owner May 15, 2025 07:48
@Paulson-Robert Paulson-Robert linked an issue May 15, 2025 that may be closed by this pull request
Copy link

@CodiumAI-Agent /describe

@Paulson-Robert Paulson-Robert requested a review from johbaxter May 15, 2025 07:49
@Paulson-Robert Paulson-Robert self-assigned this May 15, 2025
@CodiumAI-Agent
Copy link

Title

1020 integrate add blocks get client blocks reactors


User description

Description

Changes Made

How to Test

  1. Steps to reproduce/test the behavior
  2. Expected outcomes

Notes


PR Type

Enhancement


Description

  • Support slots as array or object children

  • Integrate getClientBlocks with notifications

  • Add modal to register blocks as client blocks

  • Add UI button to open block-add modal


Changes walkthrough 📝

Relevant files
Enhancement
state.store.ts
Support dual slot children formats                                             

libs/renderer/src/store/state/state.store.ts

  • Allow json.slots to be array or object
  • Normalize children mapping logic
  • +1/-1     
    BlocksMenuPanel.tsx
    Integrate client blocks fetch and notify                                 

    packages/client/src/components/blocks-workspace/panels/BlocksMenuPanel.tsx

  • Import and use useNotification for errors
  • Replace dummy data with runPixelTwo call
  • Dynamically include new sections in ordering
  • +31/-16 
    AddClientBlockModal.tsx
    Add modal for client block creation                                           

    packages/client/src/components/designer/AddClientBlockModal.tsx

  • Introduce AddClientBlockModal component
  • Build recursive child-block collector
  • Validate inputs and call AddBlock query
  • Show success/error notifications
  • +214/-0 
    DeleteDuplicateMask.tsx
    Add block-add button to mask                                                         

    packages/client/src/components/designer/DeleteDuplicateMask.tsx

  • Import Add icon and AddClientBlockModal
  • Add UI button to open the modal
  • Manage modal open/close state
  • +19/-3   

    Need help?
  • Type /help how to ... in the comments thread for any questions about PR-Agent usage.
  • Check out the documentation for more information.
  • Copy link

    @CodiumAI-Agent /review

    Copy link

    @CodiumAI-Agent /improve

    @CodiumAI-Agent
    Copy link

    PR Reviewer Guide 🔍

    Here are some key observations to aid the review process:

    ⏱️ Estimated effort to review: 3 🔵🔵🔵⚪⚪
    🧪 No relevant tests
    🔒 No security concerns identified
    ⚡ Recommended focus areas for review

    Possible Runtime Error

    The code assumes json.slots[slot] always has a children property when not an array, which may be undefined or non-array, leading to runtime errors. Ensure the children field exists and is an array before mapping.

    children: (Array.isArray(json.slots[slot]) ? json.slots[slot] : json.slots[slot]['children']).map((child) => {
    Incorrect Variable Use

    The mapped result is stored in a local res, but setClientBlock uses the original output instead of the processed array. Update the call to use the mapped variable or remove the unused mapping.

    const res = (output as DesignerMenuItem[]).map((item) => {
        return {
            ...item,
            json: JSON.parse(JSON.stringify(item.json)),
        };
    });
    setClientBlock(output as DesignerMenuItem[]);
    Missing Import

    useNotification is invoked but not imported, causing a reference error. Add the import for useNotification from @semoss/ui or remove the unused hook.

    const notification = useNotification();

    @CodiumAI-Agent
    Copy link

    CodiumAI-Agent commented May 15, 2025

    PR Code Suggestions ✨

    Latest suggestions up to a730405

    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Fix client-block loading

    Use the mapped result rather than the raw output, and ensure getClientBlocks is
    called whenever mode switches to CLIENT. Re-introduce a useEffect hook to trigger
    loading when mode changes.

    packages/client/src/components/blocks-workspace/panels/BlocksMenuPanel.tsx [128-145]

     runPixelTwo('GetClientBlocks()').then((res) => {
       const { pixelReturn, errors } = res;
       if (errors.length) {
         notification.add({ color: 'error', message: errors.join('') });
       } else {
    -    const { output } = pixelReturn[0];
    -    const res = (output as DesignerMenuItem[]).map((item) => ({
    +    const mapped = (pixelReturn[0].output as DesignerMenuItem[]).map((item) => ({
           ...item,
           json: JSON.parse(JSON.stringify(item.json)),
         }));
    -    setClientBlock(output as DesignerMenuItem[]);
    +    setClientBlock(mapped);
       }
     });
    +useEffect(() => {
    +  if (mode === 'CLIENT') {
    +    getClientBlocks();
    +  }
    +}, [mode]);
    Suggestion importance[1-10]: 7

    __

    Why: Replacing the raw output with the mapped result ensures correct state, and re-adding the useEffect hook is necessary to fetch blocks when mode switches to CLIENT.

    Medium
    Preserve nested child slots

    Capture nested slots when collecting children by using the return value of
    collectChildBlocks and including it in the new block's slots.

    packages/client/src/components/designer/AddClientBlockModal.tsx [70-76]

     accumulatedSlots[slotName] = slotValue.map((childId) => {
       const childBlock = state.blocks[childId];
    -  if (childBlock && childBlock.slots) {
    -    collectChildBlocks(childBlock.slots, {});
    -  }
    -  const { parent, ...newClientBlock } = childBlock;
    -  return newClientBlock ?? {};
    +  const nested = childBlock?.slots
    +    ? collectChildBlocks(childBlock.slots, {})
    +    : {};
    +  const { parent, slots, ...rest } = childBlock || {};
    +  return { ...rest, slots: nested };
     });
    Suggestion importance[1-10]: 7

    __

    Why: Capturing and assigning the return value of collectChildBlocks ensures nested slot data isn’t lost, which is important for correctly serializing client blocks.

    Medium
    Guard missing slot children

    Guard against missing or non‐array children to avoid runtime errors. Default to an
    empty array if neither the slot nor its children property is a valid array.

    libs/renderer/src/store/state/state.store.ts [828]

    -children: (Array.isArray(json.slots[slot]) ? json.slots[slot] : json.slots[slot]['children']).map((child) => {
    +const childrenArray = Array.isArray(json.slots[slot])
    +  ? json.slots[slot]
    +  : Array.isArray(json.slots[slot]?.children)
    +    ? json.slots[slot].children
    +    : [];
    +children: childrenArray.map((child) => {
    Suggestion importance[1-10]: 6

    __

    Why: The change enhances robustness by defaulting to an empty array when json.slots[slot] or its children aren’t valid arrays, preventing potential runtime errors.

    Low
    General
    Fallback until snapshot ready

    Prevent blank renders before the snapshot is ready by falling back to the original
    images. Only use imageSrc when it is non‐null.

    packages/client/src/components/designer/AddBlocksMenuCard.tsx [333-341]

     <BlockCardContent
       image={
    -    isClient
    +    isClient && imageSrc
           ? imageSrc
           : hovered
             ? item.hoverImage
             : item.activeImage
       }
       name={item.name}
     />
    Suggestion importance[1-10]: 5

    __

    Why: Adding a check for imageSrc avoids rendering a blank image when the snapshot isn’t ready, improving the UI experience without major code changes.

    Low

    Previous suggestions

    Suggestions up to commit d67d99a
    CategorySuggestion                                                                                                                                    Impact
    Possible issue
    Use deep-cloned blocks correctly

    Rename the mapped result to avoid shadowing and actually use the deep‐cloned array
    in setClientBlock. This ensures your UI reflects the sanitized JSON.

    packages/client/src/components/blocks-workspace/panels/BlocksMenuPanel.tsx [128-145]

    -runPixelTwo('GetClientBlocks()').then((res) => {
    +runPixelTwo('GetClientBlocks()')
    +  .then((res) => {
         const { pixelReturn, errors } = res;
         if (errors.length) {
    -        notification.add({
    -            color: 'error',
    -            message: errors.join(''),
    -        });
    +      notification.add({ color: 'error', message: errors.join('') });
         } else {
    -        const { output } = pixelReturn[0];
    -        const res = (output as DesignerMenuItem[]).map((item) => {
    -            return {
    -                ...item,
    -                json: JSON.parse(JSON.stringify(item.json)),
    -            };
    -        });
    -        setClientBlock(output as DesignerMenuItem[]);
    +      const { output } = pixelReturn[0];
    +      const mappedBlocks = (output as DesignerMenuItem[]).map(item => ({
    +        ...item,
    +        json: JSON.parse(JSON.stringify(item.json)),
    +      }));
    +      setClientBlock(mappedBlocks);
         }
    -});
    +  });
    Suggestion importance[1-10]: 8

    __

    Why: Fixes a bug where the deep‐cloned array is ignored by renaming the mapped result and passing it to setClientBlock, ensuring the UI uses sanitized JSON.

    Medium
    Add safe fallback for children array

    Guard against undefined or non-array slot data by falling back to an empty array
    before mapping to prevent runtime errors. This ensures children is always an array.

    libs/renderer/src/store/state/state.store.ts [828]

    -children: (Array.isArray(json.slots[slot]) ? json.slots[slot] : json.slots[slot]['children']).map((child) => {
    +const slotData = json.slots[slot];
    +const childArray = Array.isArray(slotData)
    +  ? slotData
    +  : Array.isArray(slotData?.children)
    +  ? slotData.children
    +  : [];
    +children: childArray.map((child) => {
    Suggestion importance[1-10]: 6

    __

    Why: The fallback to an empty array prevents runtime errors when json.slots[slot] or its children is undefined, improving stability.

    Low
    General
    Fetch client blocks on mode change

    Re-introduce an effect to invoke getClientBlocks when switching to CLIENT mode so
    blocks are fetched dynamically.

    packages/client/src/components/blocks-workspace/panels/BlocksMenuPanel.tsx [127-146]

    -const getClientBlocks = async () => {
    -  runPixelTwo('GetClientBlocks()').then((res) => { /* ... */ });
    -};
    +useEffect(() => {
    +  if (mode === 'CLIENT') {
    +    getClientBlocks();
    +  }
    +}, [mode]);
    Suggestion importance[1-10]: 8

    __

    Why: Without a useEffect, getClientBlocks never runs when switching to CLIENT mode, so re‐introducing the effect is essential for dynamic data fetching.

    Medium
    Preserve nested child slots

    Capture and assign the nested slots returned by the recursive call so child
    components include their sub-slots. This prevents loss of nested structure.

    packages/client/src/components/designer/AddClientBlockModal.tsx [69-77]

     if (slotName === 'children' && Array.isArray(slotValue)) {
    -    accumulatedSlots[slotName] = slotValue.map((childId) => {
    -        const childBlock = state.blocks[childId];
    -        if (childBlock && childBlock.slots) {
    -            collectChildBlocks(childBlock.slots, {});
    -        }
    -        const { parent, ...newClientBlock } = childBlock;
    -        return newClientBlock ?? {};
    -    });
    +  accumulatedSlots[slotName] = slotValue.map(childId => {
    +    const childBlock = state.blocks[childId];
    +    if (!childBlock) return {};
    +    const nestedSlots = collectChildBlocks(childBlock.slots, {});
    +    const { parent, slots, ...rest } = childBlock;
    +    return { ...rest, slots: nestedSlots };
    +  });
    Suggestion importance[1-10]: 7

    __

    Why: Capturing the return value of collectChildBlocks ensures nested slots are included in the client block, preserving the complete hierarchy.

    Medium

    @johbaxter
    Copy link
    Contributor

    image

    Copy link
    Contributor

    @johbaxter johbaxter left a comment

    Choose a reason for hiding this comment

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

    image

    Paulson-Robert and others added 7 commits May 16, 2025 03:07

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    …ctors
    …ntegerate-AddBlocks-GetClientBlocks-reactors
    …ttps://github.com/SEMOSS/semoss-ui into 1020-Integerate-AddBlocks-GetClientBlocks-reactors

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    …ctors

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature.
    …ctors
    @johbaxter
    Copy link
    Contributor

    We have a new client database set up

    You will be able to see all blocks that you have decided to save in this menu here

    image

    We plan on fixing the default images in next iteration.

    Make anything a client component, by hitting the action on the DeleteDuplicateMask.

    image

    Will fix order of icons and styles in a future iteration

    You can also delete client blocks

    image

    @johbaxter johbaxter merged commit 04487af into dev Jun 2, 2025
    3 checks passed
    @johbaxter johbaxter deleted the 1020-Integerate-AddBlocks-GetClientBlocks-reactors branch June 2, 2025 18:24
    Copy link

    github-actions bot commented Jun 2, 2025

    @CodiumAI-Agent /update_changelog

    @CodiumAI-Agent
    Copy link

    Changelog updates: 🔄

    2025-06-02 *

    Added

    • Integrated addBlocks and getClientBlocks reactors with loading states and error notifications
    • Client block database controls: snapshot support, add‐as‐client modal and delete actions
    • Skeleton loaders and preProcess listeners for menu items to improve UX

    to commit the new content to the CHANGELOG.md file, please type:
    '/update_changelog --pr_update_changelog.push_changelog_changes=true'

    @johbaxter johbaxter restored the 1020-Integerate-AddBlocks-GetClientBlocks-reactors branch June 3, 2025 15:11
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
    Labels
    None yet
    Projects
    None yet
    Development

    Successfully merging this pull request may close these issues.

    Incorporate AddBlocks and GetClientBlocks Reactor
    3 participants