Skip to content

Commit eedd3d1

Browse files
authored
Merge branch 'dev' into feature/#765-Add-calculator-icon-to-set-of-icons
2 parents 479e8c2 + a32f1cc commit eedd3d1

File tree

13 files changed

+179
-17
lines changed

13 files changed

+179
-17
lines changed

public/rich-components/fab-button.svg

Lines changed: 10 additions & 0 deletions
Loading

src/common/components/mock-components/front-components/icon/icon-shape.business.ts

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,5 @@
11
import { IconSize } from '@/core/model';
22

3-
export const loadSvgWithFill = async (url: string, fillColor: string) => {
4-
const response = await fetch(url);
5-
const svgText = await response.text();
6-
7-
const modifiedSvg = svgText.replace(/fill="[^"]*"/g, `fill="${fillColor}"`);
8-
9-
const svgBlob = new Blob([modifiedSvg], { type: 'image/svg+xml' });
10-
const objectURL = URL.createObjectURL(svgBlob);
11-
12-
const img = new window.Image();
13-
img.src = objectURL;
14-
15-
return img;
16-
};
17-
183
export const returnIconSize = (iconSize: IconSize): number[] => {
194
switch (iconSize) {
205
case 'XS':

src/common/components/mock-components/front-components/icon/icon-shape.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import { useModalDialogContext } from '@/core/providers/model-dialog-providers/m
77
import { IconModal } from '@/pods/properties/components/icon-selector/modal';
88
import { useCanvasContext } from '@/core/providers';
99
import { useGroupShapeProps } from '../../mock-components.utils';
10-
import { loadSvgWithFill, returnIconSize } from './icon-shape.business';
10+
import { returnIconSize } from './icon-shape.business';
11+
import { loadSvgWithFill } from '@/common/utils/svg.utils';
1112

1213
const iconShapeRestrictions: ShapeSizeRestrictions = {
1314
minWidth: 25,
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
import { BASE_ICONS_URL, ShapeSizeRestrictions, ShapeType } from '@/core/model';
2+
import { forwardRef, useEffect, useState } from 'react';
3+
import { Circle, Group, Image } from 'react-konva';
4+
import { ShapeProps } from '../../shape.model';
5+
import { fitSizeToShapeSizeRestrictions } from '@/common/utils/shapes';
6+
import { useShapeProps } from '@/common/components/shapes/use-shape-props.hook';
7+
import { useGroupShapeProps } from '../../mock-components.utils';
8+
import { BASIC_SHAPE } from '../../front-components/shape.const';
9+
import { IconModal } from '@/pods/properties/components/icon-selector/modal';
10+
import { useModalDialogContext } from '@/core/providers/model-dialog-providers/model-dialog.provider';
11+
import { useCanvasContext } from '@/core/providers';
12+
import { loadSvgWithFill } from '@/common/utils/svg.utils';
13+
14+
const fabButtonShapeRestrictions: ShapeSizeRestrictions = {
15+
minWidth: 25,
16+
minHeight: 25,
17+
maxWidth: -1,
18+
maxHeight: -1,
19+
defaultWidth: 85,
20+
defaultHeight: 85,
21+
};
22+
23+
const shapeType: ShapeType = 'fabButton';
24+
25+
export const getFabButtonShapeSizeRestrictions = (): ShapeSizeRestrictions =>
26+
fabButtonShapeRestrictions;
27+
28+
export const FabButtonShape = forwardRef<any, ShapeProps>((props, ref) => {
29+
const { x, y, width, height, id, onSelected, otherProps, ...shapeProps } =
30+
props;
31+
32+
const [iconImage, setIconImage] = useState<HTMLImageElement | null>(null);
33+
34+
const { openModal } = useModalDialogContext();
35+
const { selectionInfo } = useCanvasContext();
36+
const { updateOtherPropsOnSelected } = selectionInfo;
37+
38+
const restrictedSize = fitSizeToShapeSizeRestrictions(
39+
fabButtonShapeRestrictions,
40+
width,
41+
height
42+
);
43+
const { width: restrictedWidth, height: restrictedHeight } = restrictedSize;
44+
45+
const radius = Math.min(restrictedWidth, restrictedHeight) / 2;
46+
const center = radius;
47+
48+
const iconInfo = otherProps?.icon;
49+
const iconSize = radius * 1.2;
50+
const iconStroke = otherProps?.stroke || '#ffffff';
51+
52+
const { fill } = useShapeProps(otherProps, BASIC_SHAPE);
53+
const commonGroupProps = useGroupShapeProps(
54+
props,
55+
restrictedSize,
56+
shapeType,
57+
ref
58+
);
59+
60+
const handleDoubleClick = () => {
61+
if (iconInfo) {
62+
openModal(
63+
<IconModal
64+
actualIcon={iconInfo}
65+
onChange={icon => updateOtherPropsOnSelected('icon', icon)}
66+
/>,
67+
'Choose Icon'
68+
);
69+
}
70+
};
71+
72+
useEffect(() => {
73+
if (iconInfo?.filename) {
74+
loadSvgWithFill(`${BASE_ICONS_URL}${iconInfo.filename}`, iconStroke).then(
75+
img => setIconImage(img)
76+
);
77+
}
78+
}, [iconInfo?.filename, iconStroke]);
79+
80+
return (
81+
<Group {...commonGroupProps} {...shapeProps} onDblClick={handleDoubleClick}>
82+
{/* Background Circle */}
83+
<Circle x={center} y={center} radius={radius} fill={fill} />
84+
{/* Icon */}
85+
{iconImage && (
86+
<Image
87+
image={iconImage}
88+
x={center - iconSize / 2}
89+
y={center - iconSize / 2}
90+
width={iconSize}
91+
height={iconSize}
92+
/>
93+
)}
94+
</Group>
95+
);
96+
});

src/common/components/mock-components/front-rich-components/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ export * from './loading-indicator';
1818
export * from './videoconference';
1919
export * from './togglelightdark-shape';
2020
export * from './gauge/gauge';
21+
export * from './fab-button/fab-button';

src/common/utils/svg.utils.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
export const loadSvgWithFill = async (url: string, fillColor: string) => {
2+
const response = await fetch(url);
3+
const svgText = await response.text();
4+
5+
const modifiedSvg = svgText.replace(/fill="[^"]*"/g, `fill="${fillColor}"`);
6+
7+
const svgBlob = new Blob([modifiedSvg], { type: 'image/svg+xml' });
8+
const objectURL = URL.createObjectURL(svgBlob);
9+
10+
const img = new window.Image();
11+
img.src = objectURL;
12+
13+
return img;
14+
};

src/core/model/index.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,8 @@ export type ShapeType =
8484
| 'rectangleLow'
8585
| 'circleLow'
8686
| 'textScribbled'
87-
| 'paragraphScribbled';
87+
| 'paragraphScribbled'
88+
| 'fabButton';
8889

8990
export const ShapeDisplayName: Record<ShapeType, string> = {
9091
multiple: 'multiple',
@@ -158,6 +159,7 @@ export const ShapeDisplayName: Record<ShapeType, string> = {
158159
circleLow: 'Circle',
159160
textScribbled: 'Text Scribbled',
160161
paragraphScribbled: 'Paragraph Scribbled',
162+
fabButton: 'Fab Button',
161163
};
162164

163165
export type EditType = 'input' | 'textarea' | 'imageupload';

src/pods/canvas/model/shape-other-props.utils.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,17 @@ export const generateDefaultOtherProps = (
7575
stroke: '#808080',
7676
textColor: BASIC_SHAPE.DEFAULT_FILL_TEXT,
7777
};
78+
case 'fabButton':
79+
return {
80+
icon: {
81+
name: 'chat',
82+
filename: 'chat.svg',
83+
searchTerms: ['chat', 'message', 'conversation', 'chatting'],
84+
categories: ['IT'],
85+
},
86+
stroke: '#ffffff',
87+
backgroundColor: '#A9A9A9',
88+
};
7889
case 'buttonBar':
7990
return {
8091
stroke: BASIC_SHAPE.DEFAULT_STROKE_COLOR,

src/pods/canvas/model/shape-size.mapper.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ import {
6464
getVideoPlayerShapeSizeRestrictions,
6565
getVideoconferenceShapeSizeRestrictions,
6666
getGaugeShapeSizeRestrictions,
67+
getFabButtonShapeSizeRestrictions,
6768
// other imports
6869
} from '@/common/components/mock-components/front-rich-components';
6970
import {
@@ -171,6 +172,7 @@ const shapeSizeMap: Record<ShapeType, () => ShapeSizeRestrictions> = {
171172
circleLow: getCircleLowShapeSizeRestrictions,
172173
textScribbled: getTextScribbledShapeRestrictions,
173174
paragraphScribbled: getParagraphScribbledShapeRestrictions,
175+
fabButton: getFabButtonShapeSizeRestrictions,
174176
};
175177

176178
export default shapeSizeMap;

src/pods/canvas/shape-renderer/index.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import {
4848
renderCalendar,
4949
renderAppBar,
5050
renderLoadingIndicator,
51+
renderFabButton,
5152
} from './simple-rich-components';
5253
import {
5354
renderDiamond,
@@ -209,6 +210,8 @@ export const renderShapeComponent = (
209210
return renderLoadingIndicator(shape, shapeRenderedProps);
210211
case 'videoconference':
211212
return renderVideoconference(shape, shapeRenderedProps);
213+
case 'fabButton':
214+
return renderFabButton(shape, shapeRenderedProps);
212215
case 'gauge':
213216
return renderGauge(shape, shapeRenderedProps);
214217
case 'imagePlaceholder':

0 commit comments

Comments
 (0)