Skip to content

Ability to select multiple blocks on Drag and Drop App Builder #1151

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 25 commits into from
Jun 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
af3e0bd
build(MultiBlockSelection): multi block selection commit
NaveenRamasamy028 May 14, 2025
0170d1f
Merge branch 'dev' of https://github.com/SEMOSS/semoss-ui into feat/M…
NaveenRamasamy028 May 15, 2025
b0d4b53
build(MultiBlockSelection): multi block selection design commit
NaveenRamasamy028 May 15, 2025
9458919
build(MultiBlockSelection): multi block selection design commit
NaveenRamasamy028 May 15, 2025
ba4f454
feat(client): permission issue resolved when the user is not in first…
pallabi2303 May 22, 2025
e442e2e
Removed unnecessary commented lines MembersTable.tsx
pallabi2303 May 22, 2025
e824d3c
Merge branch 'dev' into MembersTable-setUserDetailsChange-paginationBug
anurag91jain May 23, 2025
88c5bc3
Removed unnecessary dependenices
pallabi2303 May 24, 2025
2071d2f
Changed the double ternary to simple if-else statements
pallabi2303 May 26, 2025
b1f7e79
Merge branch 'dev' into MembersTable-setUserDetailsChange-paginationBug
AAfghahi May 28, 2025
e31cce6
Fixing build issue
anurag91jain May 29, 2025
d90be3d
Merge branch 'dev' into MembersTable-setUserDetailsChange-paginationBug
anurag91jain May 29, 2025
ca45538
Merge branch 'dev' into MembersTable-setUserDetailsChange-paginationBug
pallabi2303 Jun 3, 2025
b4973b0
Editor will not be able to demote Authors
pallabi2303 Jun 3, 2025
e34ced6
Merge branch 'dev' into MembersTable-setUserDetailsChange-paginationBug
pallabi2303 Jun 3, 2025
cd02f78
Merge branch 'MembersTable-setUserDetailsChange-paginationBug' of git…
johbaxter Jun 5, 2025
838a318
Merge branch 'dev' of github.com:SEMOSS/semoss-ui into dev
johbaxter Jun 5, 2025
56b03e0
Merge branch 'dev' of github.com:SEMOSS/semoss-ui into dev
johbaxter Jun 5, 2025
2ac1909
Merge branch 'dev' of github.com:SEMOSS/semoss-ui into dev
johbaxter Jun 13, 2025
4880e4e
Merge branch 'dev' of github.com:SEMOSS/semoss-ui into dev
johbaxter Jun 13, 2025
7b66b5d
Merge branch 'dev' of github.com:SEMOSS/semoss-ui into dev
johbaxter Jun 13, 2025
3b618cc
Merge branch 'dev' of github.com:SEMOSS/semoss-ui into dev
johbaxter Jun 13, 2025
f7d6982
Merge branch 'dev' of github.com:SEMOSS/semoss-ui into dev
johbaxter Jun 13, 2025
2fca6f1
feat(client): select and drag multiple blocks via drag and drop canvas
johbaxter Jun 13, 2025
87bdcb6
feat(client): select and drag multiple blocks via drag and drop canvas
johbaxter Jun 13, 2025
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
5 changes: 5 additions & 0 deletions packages/client/src/assets/img/Group.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
5 changes: 5 additions & 0 deletions packages/client/src/assets/img/Multiple_Block.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions packages/client/src/assets/img/VariationLogo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -13,21 +13,20 @@ import {
Stack,
Typography,
IconButton,
Divider,
TextField,
Collapse,
useNotification,
Modal,
Tabs,
Tab,
ToggleTabsGroup,
AlertTitle,
} from '@semoss/ui';

import { useDesigner } from '@/hooks';
import { BlockAvatar, SelectedMenuSection } from '@/components/designer';
import { SelectedMenuSection } from '@/components/designer';
import { AddVariableModal } from '@/components/notebook';
import { Panel } from '@/components/workspace';
import VariationIcon from '../../../../../../libs/renderer/src/assets/img/VariationLogo.svg';
import MultiBlockIcon from '../../../assets/img/Multiple_Block.svg';
import GroupIcon from '../../../assets/img/Group.svg';
import VariationIcon from '../../../assets/img/VariationLogo.svg';

const StyledTitle = styled(Typography)(() => ({
textTransform: 'capitalize',
Expand Down Expand Up @@ -72,6 +71,35 @@ const StyledMessage = styled('div')(({ theme }) => ({
width: '100%',
alignItems: 'center',
justifyContent: 'center',
padding: '6px 0px',
}));
const StyledMultiBlockMessage = styled('div')(({ theme }) => ({
display: 'flex',
flexDirection: 'column',
alignItems: 'flex-start',
justifyContent: 'center',
padding: '8px 0px',
flex: '1 0 0',
}));
const StyledAlertTitle = styled(AlertTitle)(({ theme }) => ({
alignSelf: 'stretch',
color: '#666',
fontFamily: 'Inter',
fontSize: '16px',
fontStyle: 'normal',
fontWeight: 500,
lineHeight: '150%',
letterSpacing: '0.15px',
}));
const StyledTypography = styled(Typography)(({ theme }) => ({
alignSelf: 'stretch',
color: '#666',
fontFamily: 'Inter',
fontSize: '14px',
fontStyle: 'normal',
fontWeight: 400,
lineHeight: '150%',
letterSpacing: '0.17px',
}));
//Tab group with custom style with width and margin
const StyledToggleTabsGroup = styled(ToggleTabsGroup)(({ theme }) => ({
Expand Down Expand Up @@ -112,6 +140,27 @@ const StyledToggleTabsGroupItem = styled(ToggleTabsGroup.Item)(({ theme }) => ({
}));
const StyledCustomTabPanel = styled('div')(({ theme }) => ({}));

const StyledParentDiv = styled('div')(({ theme }) => ({
padding: '16px 8px',
}));

const StyledDiv = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'center',
padding: '6px 16px',
gap: '12px',
alignSelf: 'stretch',
borderRadius: '4px',
background: '#F5F5F5',
}));

const StyledImgDiv = styled('div')(({ theme }) => ({
display: 'flex',
alignItems: 'flex-start',
width: '22px',
height: '22px',
}));

const StyledVariationIcon = styled('img')(({ theme }) => ({
width: theme.spacing(4),
height: theme.spacing(4),
Expand Down Expand Up @@ -283,16 +332,50 @@ export const SelectedBlockPanel = observer(() => {
return '';
}
};
if (designer.selectedBlocks.length > 1) {
return (
<Panel>
<StyledParentDiv>
<StyledDiv>
<StyledImgDiv>
<img
src={MultiBlockIcon}
alt="Multiple Blocks Selected"
></img>
</StyledImgDiv>
<StyledMultiBlockMessage>
<StyledAlertTitle>
Multiple Blocks Selected
</StyledAlertTitle>
<StyledTypography variant="body2">
Select a single block to view its setting
</StyledTypography>
</StyledMultiBlockMessage>
</StyledDiv>
</StyledParentDiv>
</Panel>
);
}

// ignore if there is no menu
if (!block) {
return (
<Panel>
<StyledMessage>
<Typography variant="caption">
Select a block to update
</Typography>
</StyledMessage>
<StyledParentDiv>
<StyledDiv>
<StyledImgDiv>
<img src={GroupIcon} alt="No Blocks Selected"></img>
</StyledImgDiv>
<StyledMessage>
<StyledAlertTitle>
No Block Selected
</StyledAlertTitle>
<StyledTypography variant="body2">
Select a block to view its setting
</StyledTypography>
</StyledMessage>
</StyledDiv>
</StyledParentDiv>
</Panel>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,9 @@ export const AddBlocksMenuCard = observer((props: AddBlocksMenuItemProps) => {
// clear the selected
designer.setSelected(id ? id : '');

// clear the selectedBlocks
designer.addBlockToSelected('clear');

// set as active
setLocal(false);
}, [
Expand Down
34 changes: 32 additions & 2 deletions packages/client/src/components/designer/Screen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,26 @@ export const Screen = observer((props: ScreenProps) => {
designer.setSelected(designer.hovered);
};

const handleMultipleSelection = (event) => {
if (!designer.hovered || designer.hovered === designer.selected) {
return;
}
const id = getNearestBlock(event.target as Element);

// prevent events for elements until selected
event.stopPropagation();
event.preventDefault();
if (designer.selectedBlocks.includes(id)) {
return; // Do nothing if the id is already selected
}

designer.setSelected(id);
designer.addBlockToSelected(id);
if (designer.selectedBlocks.length > 1) {
designer.setSelected('');
}
};

/**
* Handle the mouseover on the page. This will hover the nearest block.
*
Expand Down Expand Up @@ -256,7 +276,8 @@ export const Screen = observer((props: ScreenProps) => {
<StyledContainer ref={eleRef}>
{eleRef.current ? (
<>
{designer.selected && (
{(designer.selected ||
designer.selectedBlocks.length > 1) && (
<SelectedMask screenEle={eleRef.current} />
)}
{designer.hovered && (
Expand All @@ -279,7 +300,16 @@ export const Screen = observer((props: ScreenProps) => {
<StyledContentInner
onMouseOver={handleMouseOver}
isHoveredOverSelectedBlock={isHoveredOverSelectedBlock}
onClickCapture={handleClickCapture}
onClickCapture={(e) => {
if (e.ctrlKey || e.metaKey || e.shiftKey) {
e.stopPropagation();
e.preventDefault();
handleMultipleSelection(e);
} else {
designer.addBlockToSelected('clear');
handleClickCapture(e);
}
}}
>
{children}
</StyledContentInner>
Expand Down
Loading