New Widget borders

This commit is contained in:
Abhinav Jha 2020-06-10 17:31:20 +00:00
parent 4322555d16
commit 80f03d970b
25 changed files with 399 additions and 252 deletions

View File

@ -21,7 +21,7 @@ describe("Button Widget Functionality", function() {
cy.widgetText(
this.data.ButtonName,
widgetsPage.buttonWidget,
widgetsPage.buttonWidget + " pre",
widgetsPage.buttonWidget + " " + commonlocators.widgetNameTag,
);
//Changing the text on the Button

View File

@ -20,7 +20,7 @@ describe("Text Widget Functionality", function() {
cy.widgetText(
this.data.TextName,
widgetsPage.textWidget,
widgetsPage.textWidget + " pre",
widgetsPage.textWidget + " " + commonlocators.widgetNameTag,
);
cy.ChangeTextStyle(

View File

@ -21,7 +21,7 @@ describe("DatePicker Widget Functionality", function() {
cy.widgetText(
this.data.Datepickername,
formWidgetsPage.datepickerWidget,
formWidgetsPage.datepickerWidget + " pre",
formWidgetsPage.datepickerWidget + " " + commonlocators.widgetNameTag,
);
// change the date to next day

View File

@ -17,7 +17,7 @@ describe("RichTextEditor Widget Functionality", function() {
cy.widgetText(
this.data.RichTextEditorName,
formWidgetsPage.richTextEditorWidget,
formWidgetsPage.richTextEditorWidget + " pre",
formWidgetsPage.richTextEditorWidget + " " + commonlocators.widgetNameTag,
);
//Edit the text area with Html

View File

@ -21,8 +21,8 @@
"deleteradiovalue": ".t--property-control-options mask",
"inputRadio": ".t--draggable-radiogroupwidget input",
"defaultSelect": ".t--property-control-defaultselectedvalue .CodeMirror-code",
"formInner": ".t--draggable-formwidget pre",
"radioInput": ".t--draggable-radiogroupwidget pre",
"formInner": ".t--draggable-formwidget span.t--widget-name",
"radioInput": ".t--draggable-radiogroupwidget span.t--widget-name",
"radioAddButton": ".t--property-control-options button",
"formD": "div[type='FORM_WIDGET']",
"datepickerFooter": ".bp3-datepicker-footer span",

View File

@ -1,6 +1,6 @@
{
"tabWidget": ".t--draggable-tabswidget",
"tabInput": ".t--draggable-tabswidget pre",
"tabInput": ".t--draggable-tabswidget span.t--widget-name",
"tabName": ".t--property-control-tabs input",
"tabDefault": ".t--property-control-defaulttab .CodeMirror-code",
"tabButton": ".t--property-control-tabs button",

View File

@ -3,7 +3,7 @@
"createModalButton": ".t--create-modal-btn",
"controlModalType": ".t--property-control-modaltype",
"modalWidget": ".t--modal-widget",
"modalName": ".t--modal-widget >div>pre",
"modalName": ".t--modal-widget span.t--widget-name",
"modelTextField": ".t--modal-widget .t--widget-textwidget"
}

View File

@ -12,7 +12,7 @@
"enablecreatemarker": ".t--property-control-createnewmarker input",
"zoom": ".t--property-control-zoomable input",
"searchloc": "input[placeholder='Enter location to search']",
"imagecontainer": ".t--draggable-imagewidget pre",
"imagecontainer": ".t--draggable-imagewidget span.t--widget-name",
"imageinner": ".t--draggable-imagewidget img",
"chartInnerText": ".t--draggable-chartwidget text",
"inputChartValue": ".t--property-control-chartdata .CodeMirror textarea",
@ -20,7 +20,7 @@
"rectangleChart": ".t--draggable-chartwidget g rect",
"xlabel": ".t--property-control-x-axislabel .CodeMirror-code",
"ylabel": ".t--property-control-y-axislabel .CodeMirror-code",
"mapInner": ".t--draggable-mapwidget pre",
"mapInner": ".t--draggable-mapwidget span.t--widget-name",
"mapInput": ".t--property-control-defaultmarkers .CodeMirror-code",
"mapinitialloc": ".t--property-control-initiallocation input",
"mapSearch": ".t--draggable-mapwidget input",

View File

@ -12,7 +12,7 @@
"buttonOnClick": ".t--property-control-onclick",
"Scrollbutton": ".t--property-control-scrollcontents input",
"label": ".t--draggable-inputwidget label",
"inputval": ".t--draggable-inputwidget pre",
"inputval": ".t--draggable-inputwidget span.t--widget-name",
"dataclass": "'.bp3-input",
"datatype": ".t--property-control-datatype",
"innertext": ".t--draggable-inputwidget input",
@ -26,7 +26,7 @@
"indicator": ".bp3-checkbox",
"Regex": ".t--property-control-regex .CodeMirror-lines",
"RadioInput": ".t--property-control-options input",
"checkboxInput": ".t--draggable-checkboxwidget pre",
"checkboxInput": ".t--draggable-checkboxwidget span.t--widget-name",
"checkboxLabel": ".t--draggable-checkboxwidget label",
"containerD": "div[type='CONTAINER_WIDGET']",
"defaultInput": ".t--property-control-defaultinput .CodeMirror-code",
@ -34,7 +34,7 @@
"inputButtonPos": ".t--draggable-inputwidget button",
"deleteWidget": ".t--modal-widget>div .t--widget-delete-control",
"textbuttonWidget": ".t--draggable-buttonwidget button.bp3-button[type='button']",
"textInputval": ".t--draggable-textwidget pre",
"textInputval": ".t--draggable-textwidget span.t--widget-name",
"textAlign": ".t--property-control-textalign",
"ColumnAction": ".t--property-control-rowbutton button"
}

View File

@ -9,7 +9,7 @@
"datatypedropdown": ".t--property-control-datatype button",
"Alerttypedropdown": ".t--open-dropdown-Select-type",
"dropdownmenu": "ul.bp3-menu",
"containerInnerText": ".t--draggable-containerwidget pre",
"containerInnerText": ".t--draggable-containerwidget span.t--widget-name",
"optionchangetextDropdown": " .t--property-control-onoptionchange .CodeMirror-code",
"optionchangetextCheckbox": ".t--property-control-oncheckchange .CodeMirror-code",
"optionchangetextInput": ".t--property-control-ontextchanged .CodeMirror-code",
@ -37,7 +37,7 @@
"Disablejs": ".t--property-control-disabled",
"requiredjs": ".t--property-control-required",
"horizontalScroll": ".t--property-control-allowhorizontalscroll input",
"tableInner": ".t--draggable-tablewidget pre",
"tableInner": ".t--draggable-tablewidget span.t--widget-name",
"pdfSupport": ".t--property-control-pdfexport input",
"ExcelSupport": ".t--property-control-excelexport input",
"dropDownBtn": ".bp3-icon-chevron-down",
@ -49,6 +49,7 @@
"enableSearchLocCheckbox": ".t--property-control-enablesearchlocation input",
"enablePickLocCheckbox": ".t--property-control-enablepicklocation input",
"enableCreateMarkerCheckbox": ".t--property-control-createnewmarker input",
"widgetNameTag": "span.t--widget-name",
"serverSidePaginationCheckbox": ".t--property-control-serversidepagination input",
"rightArrowBtn": "span[icon='chevron-right']",
"toastMsg": ".Toastify__toast.Toastify__toast--default span",

View File

@ -1,4 +1,3 @@
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<circle cx="10" cy="10" r="10" fill="#21282C"/>
<path d="M11.75 5.5H14C14.45 5.5 14.75 5.8 14.75 6.25V7H5V6.25C5 5.8 5.375 5.5 5.75 5.5H8C8.15 4.675 8.975 4 9.875 4C10.775 4 11.6 4.675 11.75 5.5ZM8.75 5.5H11C10.85 5.05 10.325 4.75 9.875 4.75C9.425 4.75 8.9 5.05 8.75 5.5ZM5.75 7.75H14L13.325 15.325C13.325 15.7 12.95 16 12.575 16H7.175C6.8 16 6.5 15.7 6.425 15.325L5.75 7.75Z" fill="#F2FAFF"/>
<svg width="10" height="12" viewBox="0 0 10 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M6.74996 1.5H8.99996C9.44996 1.5 9.74996 1.8 9.74996 2.25V3H-3.8147e-05V2.25C-3.8147e-05 1.8 0.374962 1.5 0.749962 1.5H2.99996C3.14996 0.675004 3.97496 3.8147e-06 4.87496 3.8147e-06C5.77496 3.8147e-06 6.59996 0.675004 6.74996 1.5ZM3.74996 1.5H5.99996C5.84996 1.05 5.32496 0.750004 4.87496 0.750004C4.42496 0.750004 3.89996 1.05 3.74996 1.5ZM0.749962 3.75H8.99996L8.32496 11.325C8.32496 11.7 7.94996 12 7.57496 12H2.17496C1.79996 12 1.49996 11.7 1.42496 11.325L0.749962 3.75Z" fill="#F2FAFF"/>
</svg>

Before

Width:  |  Height:  |  Size: 497 B

After

Width:  |  Height:  |  Size: 605 B

View File

@ -0,0 +1,3 @@
<svg width="12" height="12" viewBox="0 0 12 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5844 6.588C10.6091 6.396 10.6276 6.204 10.6276 6C10.6276 5.796 10.6091 5.604 10.5844 5.412L11.8859 4.422C12.0031 4.332 12.034 4.17 11.96 4.038L10.7263 1.962C10.6523 1.83 10.4857 1.782 10.35 1.83L8.81412 2.43C8.49336 2.19 8.14794 1.992 7.77167 1.842L7.53727 0.252C7.51877 0.108 7.38923 0 7.23503 0H4.7677C4.61349 0 4.48396 0.108 4.46545 0.252L4.23105 1.842C3.85479 1.992 3.50936 2.196 3.18861 2.43L1.6527 1.83C1.51083 1.776 1.35045 1.83 1.27643 1.962L0.0427659 4.038C-0.0374222 4.17 -0.00041223 4.332 0.116786 4.422L1.4183 5.412C1.39363 5.604 1.37512 5.802 1.37512 6C1.37512 6.198 1.39363 6.396 1.4183 6.588L0.116786 7.578C-0.00041223 7.668 -0.0312539 7.83 0.0427659 7.962L1.27643 10.038C1.35045 10.17 1.51699 10.218 1.6527 10.17L3.18861 9.57C3.50936 9.81 3.85479 10.008 4.23105 10.158L4.46545 11.748C4.48396 11.892 4.61349 12 4.7677 12H7.23503C7.38923 12 7.51877 11.892 7.53727 11.748L7.77167 10.158C8.14794 10.008 8.49336 9.804 8.81412 9.57L10.35 10.17C10.4919 10.224 10.6523 10.17 10.7263 10.038L11.96 7.962C12.034 7.83 12.0031 7.668 11.8859 7.578L10.5844 6.588ZM6.00136 8.1C4.81088 8.1 3.84245 7.158 3.84245 6C3.84245 4.842 4.81088 3.9 6.00136 3.9C7.19185 3.9 8.16027 4.842 8.16027 6C8.16027 7.158 7.19185 8.1 6.00136 8.1Z" fill="white"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -2,6 +2,13 @@ import React, { ReactNode } from "react";
import { BaseStyle } from "widgets/BaseWidget";
import { WIDGET_PADDING } from "constants/WidgetConstants";
import { generateClassName } from "utils/generators";
import styled from "styled-components";
const PositionedWidget = styled.div`
&:hover {
z-index: 1;
}
`;
type PositionedContainerProps = {
style: BaseStyle;
children: ReactNode;
@ -14,7 +21,7 @@ export const PositionedContainer = (props: PositionedContainerProps) => {
const y = props.style.yPosition + (props.style.yPositionUnit || "px");
const padding = WIDGET_PADDING;
return (
<div
<PositionedWidget
style={{
position: "absolute",
left: x,
@ -34,7 +41,7 @@ export const PositionedContainer = (props: PositionedContainerProps) => {
}
>
{props.children}
</div>
</PositionedWidget>
);
};

View File

@ -80,7 +80,7 @@ export const ModalComponent = (props: ModalComponentProps) => {
height={props.height}
top={props.top}
left={props.left}
zIndex={props.zIndex !== undefined ? props.zIndex : 1}
zIndex={props.zIndex !== undefined ? props.zIndex : 3}
>
<Overlay
isOpen={props.isOpen}

View File

@ -31,7 +31,7 @@ const WrappedDragLayer = styled.div<{
background-image: radial-gradient(
circle,
${props => props.theme.colors.grid} 2px,
${props => props.theme.colors.grid} 1px,
transparent 0
);
background-size: ${props => props.columnWidth}px ${props => props.rowHeight}px;

View File

@ -2,7 +2,7 @@ import { invisible, theme } from "constants/DefaultTheme";
import { WIDGET_PADDING } from "constants/WidgetConstants";
import styled, { css } from "styled-components";
const EDGE_RESIZE_HANDLE_WIDTH = 10;
const EDGE_RESIZE_HANDLE_WIDTH = 12;
const CORNER_RESIZE_HANDLE_WIDTH = 10;
export const VisibilityContainer = styled.div<{
@ -38,14 +38,14 @@ export const EdgeHandleStyles = css`
export const VerticalHandleStyles = css`
${EdgeHandleStyles}
top:-${WIDGET_PADDING}px;
height: calc(100% + ${2 * WIDGET_PADDING}px);
top:-${WIDGET_PADDING - 1}px;
height: calc(100% + ${2 * WIDGET_PADDING - 1}px);
cursor: col-resize;
&:before {
left: 50%;
bottom: 0px;
top: 0;
width: 2px;
width: 1px;
}
`;
@ -58,7 +58,7 @@ export const HorizontalHandleStyles = css`
top: 50%;
right: 0px;
left: 0px;
height: 2px;
height: 1px;
}
`;
@ -70,7 +70,7 @@ export const LeftHandleStyles = styled.div`
export const RightHandleStyles = styled.div`
${VerticalHandleStyles};
right: ${-EDGE_RESIZE_HANDLE_WIDTH / 2 - WIDGET_PADDING + 1}px;
height: calc(100% + ${2 * WIDGET_PADDING + 1}px);
height: calc(100% + ${2 * WIDGET_PADDING}px);
`;
export const TopHandleStyles = styled.div`
@ -80,7 +80,7 @@ export const TopHandleStyles = styled.div`
export const BottomHandleStyles = styled.div`
${HorizontalHandleStyles};
bottom: ${-EDGE_RESIZE_HANDLE_WIDTH / 2 - WIDGET_PADDING + 1}px;
bottom: ${-EDGE_RESIZE_HANDLE_WIDTH / 2 - WIDGET_PADDING}px;
`;
export const CornerHandleStyles = css`

View File

@ -1,220 +0,0 @@
import React, { useContext } from "react";
import styled from "styled-components";
import { useSelector, useDispatch } from "react-redux";
import { AppState } from "reducers";
import { ControlIcons } from "icons/ControlIcons";
import { EditorContext } from "components/editorComponents/EditorContextProvider";
import { theme } from "constants/DefaultTheme";
import { Colors } from "constants/Colors";
import { PropertyPaneReduxState } from "reducers/uiReducers/propertyPaneReducer";
import { Tooltip, Icon } from "@blueprintjs/core";
import {
useShowPropertyPane,
useWidgetSelection,
} from "utils/hooks/dragResizeHooks";
import AnalyticsUtil from "utils/AnalyticsUtil";
import { WidgetOperations } from "widgets/BaseWidget";
import { WidgetType } from "constants/WidgetConstants";
import { HelpMap } from "constants/HelpConstants";
import {
setHelpDefaultRefinement,
setHelpModalVisibility,
} from "actions/helpActions";
import FeatureFlag from "utils/featureFlags";
import { FeatureFlagsEnum } from "configs/types";
const CONTROL_ICON_SIZE = 20;
const PositionStyle = styled.div<{ selected?: boolean }>`
position: absolute;
top: -${props => props.theme.spaces[7]}px;
left: ${props => props.theme.spaces[5]}px;
font-size: ${props => props.theme.fontSizes[2]}px;
font-weight: ${props => props.theme.fontWeights[2]};
text-align: left;
width: 100%;
z-index: 2;
display: inline-block;
& pre {
display: inline;
padding: 3px;
background: ${props =>
props.selected
? props.theme.colors.widgetBorder
: props.theme.colors.widgetSecondaryBorder};
}
`;
const HelpControl = styled.div`
position: absolute;
right: ${props => props.theme.spaces[13] * 2 - 10}px;
top: -${props => props.theme.spaces[2]}px;
cursor: pointer;
`;
const DeleteControl = styled.div`
position: absolute;
right: ${props => props.theme.spaces[13]}px;
top: -${props => props.theme.spaces[2]}px;
cursor: pointer;
`;
const EditControl = styled.div`
position: absolute;
right: ${props => props.theme.spaces[4]}px;
top: -${props => props.theme.spaces[2]}px;
cursor: pointer;
`;
const DeleteIcon = ControlIcons.DELETE_CONTROL;
const deleteControlIcon = (
<DeleteIcon width={CONTROL_ICON_SIZE} height={CONTROL_ICON_SIZE} />
);
const EditIcon = ControlIcons.EDIT_CONTROL;
const HelpIcon = styled(Icon)<{ width: number; height: number }>`
width: ${props => props.width}px;
height: ${props => props.width}px;
color: ${Colors.SHARK};
svg {
width: ${props => props.width}px;
height: ${props => props.width}px;
}
`;
// const HelpIcon = ControlIcons.HELP_CONTROL;
const helpControlIcon = (
<HelpIcon
width={CONTROL_ICON_SIZE}
height={CONTROL_ICON_SIZE}
icon="help"
></HelpIcon>
);
type WidgetNameComponentProps = {
widgetName?: string;
widgetId: string;
parentId?: string;
type: WidgetType;
showControls?: boolean;
};
export const WidgetNameComponent = (props: WidgetNameComponentProps) => {
const { updateWidget } = useContext(EditorContext);
const dispatch = useDispatch();
const showPropertyPane = useShowPropertyPane();
// Dispatch hook handy to set a widget as focused/selected
const { selectWidget } = useWidgetSelection();
const propertyPaneState: PropertyPaneReduxState = useSelector(
(state: AppState) => state.ui.propertyPane,
);
const selectedWidget = useSelector(
(state: AppState) => state.ui.editor.selectedWidget,
);
const focusedWidget = useSelector(
(state: AppState) => state.ui.editor.focusedWidget,
);
const isResizing = useSelector(
(state: AppState) => state.ui.widgetDragResize.isResizing,
);
const isDragging = useSelector(
(state: AppState) => state.ui.widgetDragResize.isDragging,
);
const editIconProps = {
width: CONTROL_ICON_SIZE,
height: CONTROL_ICON_SIZE,
color:
propertyPaneState.widgetId === props.widgetId &&
propertyPaneState.isVisible
? theme.colors.textDefault
: theme.colors.textOnDarkBG,
background:
propertyPaneState.widgetId === props.widgetId &&
propertyPaneState.isVisible
? Colors.HIT_GRAY
: Colors.SHARK,
};
const editControlIcon = <EditIcon {...editIconProps} />;
const deleteWidget = () => {
AnalyticsUtil.logEvent("WIDGET_DELETE", {
widgetName: props.widgetName,
widgetType: props.type,
});
showPropertyPane && showPropertyPane();
updateWidget &&
updateWidget(WidgetOperations.DELETE, props.widgetId, {
parentId: props.parentId,
});
};
const togglePropertyEditor = (e: any) => {
if (
(!propertyPaneState.isVisible &&
props.widgetId === propertyPaneState.widgetId) ||
props.widgetId !== propertyPaneState.widgetId
) {
AnalyticsUtil.logEvent("PROPERTY_PANE_OPEN_CLICK", {
widgetType: props.type,
widgetId: props.widgetId,
});
showPropertyPane && showPropertyPane(props.widgetId, undefined, true);
selectWidget && selectWidget(props.widgetId);
} else {
AnalyticsUtil.logEvent("PROPERTY_PANE_CLOSE_CLICK", {
widgetType: props.type,
widgetId: props.widgetId,
});
showPropertyPane && showPropertyPane();
}
e.preventDefault();
e.stopPropagation();
};
const showWidgetName =
props.showControls ||
((focusedWidget === props.widgetId || selectedWidget === props.widgetId) &&
!isDragging &&
!isResizing);
return showWidgetName ? (
<PositionStyle selected={selectedWidget === props.widgetId}>
<pre>{props.widgetName}</pre>
{FeatureFlag.check(FeatureFlagsEnum.documentationV2) && (
<HelpControl
className="control t--widget-help-control"
onClick={() => {
dispatch(setHelpDefaultRefinement(HelpMap[props.type].searchKey));
dispatch(setHelpModalVisibility(true));
// window.open(`${HelpBaseURL}${HelpMap[props.type]}`, "_blank");
}}
>
<Tooltip content="Open Help" hoverOpenDelay={500}>
{helpControlIcon}
</Tooltip>
</HelpControl>
)}
<DeleteControl
className="control t--widget-delete-control"
onClick={deleteWidget}
>
<Tooltip content="Delete" hoverOpenDelay={500}>
{deleteControlIcon}
</Tooltip>
</DeleteControl>
<EditControl
className="control t--widget-propertypane-toggle"
onClick={togglePropertyEditor}
>
<Tooltip content="Edit widget properties" hoverOpenDelay={500}>
{editControlIcon}
</Tooltip>
</EditControl>
</PositionStyle>
) : null;
};
export default WidgetNameComponent;

View File

@ -0,0 +1,48 @@
import React from "react";
import { Tooltip } from "@blueprintjs/core";
import styled from "styled-components";
import { ControlIcons } from "icons/ControlIcons";
import { Colors } from "constants/Colors";
const DeleteIcon = ControlIcons.DELETE_CONTROL;
const deleteControlIcon = <DeleteIcon height={14} width={10} />;
const StyledDeleteIcon = styled.div`
justify-self: flex-start;
cursor: pointer;
align-self: center;
width: 22px;
height: 22px;
min-width: 22px;
min-height: 22px;
margin-right: 2px;
background: ${props => props.theme.colors.widgetBorder};
display: flex;
justify-content: center;
align-items: center;
border-radius: 2px;
& > span {
height: 12px;
}
&:hover {
background: ${Colors.OUTER_SPACE};
}
`;
type DeleteControlProps = {
deleteWidget: () => void;
show: boolean;
};
const DeleteControl = (props: DeleteControlProps) => {
return props.show ? (
<StyledDeleteIcon
className="control t--widget-delete-control"
onClick={props.deleteWidget}
>
<Tooltip content="Delete" hoverOpenDelay={500} position="top">
{deleteControlIcon}
</Tooltip>
</StyledDeleteIcon>
) : null;
};
export default DeleteControl;

View File

@ -0,0 +1,61 @@
import React from "react";
import { useDispatch } from "react-redux";
import { Tooltip } from "@blueprintjs/core";
import styled from "styled-components";
import { ControlIcons } from "icons/ControlIcons";
import { Colors } from "constants/Colors";
import { HelpMap } from "constants/HelpConstants";
import {
setHelpDefaultRefinement,
setHelpModalVisibility,
} from "actions/helpActions";
import FeatureFlag from "utils/featureFlags";
import { FeatureFlagsEnum } from "configs/types";
import { WidgetType } from "constants/WidgetConstants";
const HelpIcon = ControlIcons.HELP_CONTROL;
const helpControlIcon = (
<HelpIcon width={14} height={14} background="transparent" />
);
const StyledHelpIcon = styled.div`
justify-self: flex-start;
cursor: pointer;
align-self: center;
width: 22px;
height: 22px;
min-width: 22px;
min-height: 22px;
margin-right: 2px;
background: ${props => props.theme.colors.widgetBorder};
display: flex;
justify-content: center;
align-items: center;
border-radius: 2px;
& > span {
height: 12px;
}
&:hover {
background: ${Colors.OUTER_SPACE};
}
`;
export const HelpControl = (props: { type: WidgetType; show: boolean }) => {
const dispatch = useDispatch();
return FeatureFlag.check(FeatureFlagsEnum.documentationV2) && props.show ? (
<StyledHelpIcon
className="control t--widget-help-control"
onClick={() => {
dispatch(setHelpDefaultRefinement(HelpMap[props.type].searchKey));
dispatch(setHelpModalVisibility(true));
// window.open(`${HelpBaseURL}${HelpMap[props.type]}`, "_blank");
}}
>
<Tooltip content="Open Help" hoverOpenDelay={500} position="top">
{helpControlIcon}
</Tooltip>
</StyledHelpIcon>
) : null;
};
export default HelpControl;

View File

@ -0,0 +1,99 @@
import React, { CSSProperties } from "react";
import { ControlIcons } from "icons/ControlIcons";
import { Colors } from "constants/Colors";
import styled from "styled-components";
import { Tooltip, Classes } from "@blueprintjs/core";
// I honestly can't think of a better name for this enum
export enum Activities {
HOVERING,
SELECTED,
ACTIVE,
NONE,
}
const StyledTooltip = styled(Tooltip)`
.${Classes.POPOVER_TARGET} {
height: 100%;
}
`;
const SettingsWrapper = styled.div`
justify-self: flex-end;
height: 100%;
padding: 0 10px;
display: flex;
justify-content: space-between;
align-items: center;
& {
pre {
margin: 0 5px 0 0;
font-size: ${props => props.theme.fontSizes[3]}px;
height: ${props => props.theme.fontSizes[3]}px;
line-height: ${props => props.theme.fontSizes[3] - 1}px;
}
}
border-radius: 2px;
`;
const WidgetName = styled.span`
margin-right: 5px;
`;
type SettingsControlProps = {
toggleSettings: (e: any) => void;
activity: Activities;
name: string;
};
const SettingsIcon = ControlIcons.SETTINGS_CONTROL;
const getStyles = (activity: Activities): CSSProperties | undefined => {
switch (activity) {
case Activities.ACTIVE:
return {
background: Colors.JAFFA_DARK,
color: Colors.WHITE,
};
case Activities.HOVERING:
return {
background: Colors.WATUSI,
color: Colors.BLACK_PEARL,
};
case Activities.SELECTED:
return {
background: Colors.OUTER_SPACE,
color: Colors.WHITE,
};
}
};
export const SettingsControl = (props: SettingsControlProps) => {
const settingsIcon = (
<SettingsIcon
width={12}
height={14}
color={
props.activity === Activities.HOVERING
? Colors.BLACK_PEARL
: Colors.WHITE
}
/>
);
return (
<StyledTooltip
content="Edit widget properties"
position="top-right"
hoverOpenDelay={500}
>
<SettingsWrapper
style={getStyles(props.activity)}
onClick={props.toggleSettings}
className="t--widget-propertypane-toggle"
>
<WidgetName className="t--widget-name">{props.name}</WidgetName>
{settingsIcon}
</SettingsWrapper>
</StyledTooltip>
);
};
export default SettingsControl;

View File

@ -0,0 +1,141 @@
import React, { useContext } from "react";
import styled from "styled-components";
import { useSelector } from "react-redux";
import { AppState } from "reducers";
import { EditorContext } from "components/editorComponents/EditorContextProvider";
import { PropertyPaneReduxState } from "reducers/uiReducers/propertyPaneReducer";
import DeleteControl from "./DeleteControl";
import SettingsControl, { Activities } from "./SettingsControl";
import {
useShowPropertyPane,
useWidgetSelection,
} from "utils/hooks/dragResizeHooks";
import AnalyticsUtil from "utils/AnalyticsUtil";
import { WidgetOperations } from "widgets/BaseWidget";
import { WidgetType, WidgetTypes } from "constants/WidgetConstants";
import HelpControl from "./HelpControl";
const PositionStyle = styled.div`
position: absolute;
top: -${props => props.theme.spaces[10]}px;
height: ${props => props.theme.spaces[10]}px;
width: 100%;
left: 0;
display: flex;
padding: 0 4px;
`;
const ControlGroup = styled.div`
display: flex;
margin-left: auto;
justify-content: flex-start;
align-items: center;
height: 100%;
& > span {
height: 100%;
}
`;
type WidgetNameComponentProps = {
widgetName: string;
widgetId: string;
parentId?: string;
type: WidgetType;
showControls?: boolean;
};
export const WidgetNameComponent = (props: WidgetNameComponentProps) => {
const { updateWidget } = useContext(EditorContext);
const showPropertyPane = useShowPropertyPane();
// Dispatch hook handy to set a widget as focused/selected
const { selectWidget } = useWidgetSelection();
const propertyPaneState: PropertyPaneReduxState = useSelector(
(state: AppState) => state.ui.propertyPane,
);
const selectedWidget = useSelector(
(state: AppState) => state.ui.editor.selectedWidget,
);
const focusedWidget = useSelector(
(state: AppState) => state.ui.editor.focusedWidget,
);
const isResizing = useSelector(
(state: AppState) => state.ui.widgetDragResize.isResizing,
);
const isDragging = useSelector(
(state: AppState) => state.ui.widgetDragResize.isDragging,
);
const deleteWidget = () => {
AnalyticsUtil.logEvent("WIDGET_DELETE", {
widgetName: props.widgetName,
widgetType: props.type,
});
showPropertyPane && showPropertyPane();
updateWidget &&
updateWidget(WidgetOperations.DELETE, props.widgetId, {
parentId: props.parentId,
});
};
const togglePropertyEditor = (e: any) => {
if (
(!propertyPaneState.isVisible &&
props.widgetId === propertyPaneState.widgetId) ||
props.widgetId !== propertyPaneState.widgetId
) {
AnalyticsUtil.logEvent("PROPERTY_PANE_OPEN_CLICK", {
widgetType: props.type,
widgetId: props.widgetId,
});
showPropertyPane && showPropertyPane(props.widgetId, undefined, true);
selectWidget && selectWidget(props.widgetId);
} else {
AnalyticsUtil.logEvent("PROPERTY_PANE_CLOSE_CLICK", {
widgetType: props.type,
widgetId: props.widgetId,
});
showPropertyPane && showPropertyPane();
}
e.preventDefault();
e.stopPropagation();
};
const showWidgetName =
props.showControls ||
((focusedWidget === props.widgetId || selectedWidget === props.widgetId) &&
!isDragging &&
!isResizing);
let currentActivity = Activities.NONE;
if (focusedWidget === props.widgetId) currentActivity = Activities.HOVERING;
if (selectedWidget === props.widgetId) currentActivity = Activities.SELECTED;
if (
propertyPaneState.isVisible &&
propertyPaneState.widgetId === props.widgetId
)
currentActivity = Activities.ACTIVE;
return showWidgetName ? (
<PositionStyle>
<DeleteControl
deleteWidget={deleteWidget}
show={selectedWidget === props.widgetId}
/>
<ControlGroup>
<HelpControl
type={props.type}
show={selectedWidget === props.widgetId}
/>
<SettingsControl
toggleSettings={togglePropertyEditor}
activity={currentActivity}
name={props.widgetName}
/>
</ControlGroup>
</PositionStyle>
) : null;
};
export default WidgetNameComponent;

View File

@ -45,6 +45,7 @@ export const Colors: Record<string, string> = {
BLUE_CHARCOAL: "#23292E",
TROUT: "#4C565E",
JAFFA_DARK: "#EF7541",
WATUSI: "#FFE0D2",
GRAY: "#828282",
ATHENS_GRAY_DARKER: "#F8F9FA",
};

View File

@ -345,13 +345,13 @@ export const theme: Theme = {
paneTextUnderline: Colors.LIGHT_GREYISH_BLUE,
paneSectionLabel: Colors.CADET_BLUE,
navBG: Colors.SHARK,
grid: Colors.GEYSER_LIGHT,
grid: Colors.TROUT,
containerBorder: Colors.FRENCH_PASS,
menuButtonBGInactive: Colors.JUNGLE_MIST,
menuIconColorInactive: Colors.OXFORD_BLUE,
bodyBG: Colors.ATHENS_GRAY,
builderBodyBG: Colors.WHITE,
widgetBorder: Colors.MINT_TULIP,
widgetBorder: Colors.SLATE_GRAY,
widgetSecondaryBorder: Colors.MERCURY,
messageBG: Colors.CONCRETE,
paneIcon: Colors.TROUT,

View File

@ -72,7 +72,7 @@ export const GridDefaults = {
DEFAULT_WIDGET_WIDTH: 200,
DEFAULT_WIDGET_HEIGHT: 100,
DEFAULT_GRID_COLUMNS: 16,
DEFAULT_GRID_ROW_HEIGHT: 38,
DEFAULT_GRID_ROW_HEIGHT: 40,
CANVAS_EXTENSION_OFFSET: 2,
};

View File

@ -15,6 +15,8 @@ import { ReactComponent as CloseIcon } from "assets/icons/control/close.svg";
import { ReactComponent as HelpIcon } from "assets/icons/control/help.svg";
import { ReactComponent as PickMyLocationSelectedIcon } from "assets/icons/control/pick-location-selected.svg";
import { ReactComponent as SettingsIcon } from "assets/icons/control/settings.svg";
/* eslint-disable react/display-name */
export const ControlIcons: {
@ -80,6 +82,11 @@ export const ControlIcons: {
<PickMyLocationSelectedIcon />
</IconWrapper>
),
SETTINGS_CONTROL: (props: IconProps) => (
<IconWrapper {...props}>
<SettingsIcon />
</IconWrapper>
),
HELP_CONTROL: (props: IconProps) => (
<IconWrapper {...props}>
<HelpIcon />