diff --git a/app/client/cypress/integration/Smoke_TestSuite/CommonWidgets/Button_spec.js b/app/client/cypress/integration/Smoke_TestSuite/CommonWidgets/Button_spec.js index 0035266866..12e1f1b428 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/CommonWidgets/Button_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/CommonWidgets/Button_spec.js @@ -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 diff --git a/app/client/cypress/integration/Smoke_TestSuite/CommonWidgets/Text_spec.js b/app/client/cypress/integration/Smoke_TestSuite/CommonWidgets/Text_spec.js index 298dd1761f..90173f379b 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/CommonWidgets/Text_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/CommonWidgets/Text_spec.js @@ -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( diff --git a/app/client/cypress/integration/Smoke_TestSuite/FormWidgets/DatePicker_spec.js b/app/client/cypress/integration/Smoke_TestSuite/FormWidgets/DatePicker_spec.js index 85692ff96f..5d2d311c60 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/FormWidgets/DatePicker_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/FormWidgets/DatePicker_spec.js @@ -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 diff --git a/app/client/cypress/integration/Smoke_TestSuite/FormWidgets/RichTextEditor_spec.js b/app/client/cypress/integration/Smoke_TestSuite/FormWidgets/RichTextEditor_spec.js index 6d3de67223..06e3863d20 100644 --- a/app/client/cypress/integration/Smoke_TestSuite/FormWidgets/RichTextEditor_spec.js +++ b/app/client/cypress/integration/Smoke_TestSuite/FormWidgets/RichTextEditor_spec.js @@ -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 diff --git a/app/client/cypress/locators/FormWidgets.json b/app/client/cypress/locators/FormWidgets.json index 02df4287fc..009e00c55a 100644 --- a/app/client/cypress/locators/FormWidgets.json +++ b/app/client/cypress/locators/FormWidgets.json @@ -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", diff --git a/app/client/cypress/locators/Layout.json b/app/client/cypress/locators/Layout.json index da4dfd643c..b406e8dc3a 100644 --- a/app/client/cypress/locators/Layout.json +++ b/app/client/cypress/locators/Layout.json @@ -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", diff --git a/app/client/cypress/locators/ModalWidget.json b/app/client/cypress/locators/ModalWidget.json index 1cf2110a40..0419936c51 100644 --- a/app/client/cypress/locators/ModalWidget.json +++ b/app/client/cypress/locators/ModalWidget.json @@ -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" } \ No newline at end of file diff --git a/app/client/cypress/locators/ViewWidgets.json b/app/client/cypress/locators/ViewWidgets.json index a84df6bc25..2c83bf7464 100644 --- a/app/client/cypress/locators/ViewWidgets.json +++ b/app/client/cypress/locators/ViewWidgets.json @@ -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", diff --git a/app/client/cypress/locators/Widgets.json b/app/client/cypress/locators/Widgets.json index 8ae5c9b159..58f2a13175 100644 --- a/app/client/cypress/locators/Widgets.json +++ b/app/client/cypress/locators/Widgets.json @@ -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" } \ No newline at end of file diff --git a/app/client/cypress/locators/commonlocators.json b/app/client/cypress/locators/commonlocators.json index 03ecf5cf25..30d03afa20 100644 --- a/app/client/cypress/locators/commonlocators.json +++ b/app/client/cypress/locators/commonlocators.json @@ -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", diff --git a/app/client/src/assets/icons/control/delete.svg b/app/client/src/assets/icons/control/delete.svg index 09b3855266..273eb462b8 100644 --- a/app/client/src/assets/icons/control/delete.svg +++ b/app/client/src/assets/icons/control/delete.svg @@ -1,4 +1,3 @@ - - - + + diff --git a/app/client/src/assets/icons/control/settings.svg b/app/client/src/assets/icons/control/settings.svg new file mode 100644 index 0000000000..5bc7daef54 --- /dev/null +++ b/app/client/src/assets/icons/control/settings.svg @@ -0,0 +1,3 @@ + + + diff --git a/app/client/src/components/designSystems/appsmith/PositionedContainer.tsx b/app/client/src/components/designSystems/appsmith/PositionedContainer.tsx index 8943201283..e755ae4ee4 100644 --- a/app/client/src/components/designSystems/appsmith/PositionedContainer.tsx +++ b/app/client/src/components/designSystems/appsmith/PositionedContainer.tsx @@ -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 ( -
{ } > {props.children} -
+ ); }; diff --git a/app/client/src/components/designSystems/blueprint/ModalComponent.tsx b/app/client/src/components/designSystems/blueprint/ModalComponent.tsx index 16a849e25c..ad69c4f190 100644 --- a/app/client/src/components/designSystems/blueprint/ModalComponent.tsx +++ b/app/client/src/components/designSystems/blueprint/ModalComponent.tsx @@ -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} > props.theme.colors.grid} 2px, + ${props => props.theme.colors.grid} 1px, transparent 0 ); background-size: ${props => props.columnWidth}px ${props => props.rowHeight}px; diff --git a/app/client/src/components/editorComponents/ResizeStyledComponents.tsx b/app/client/src/components/editorComponents/ResizeStyledComponents.tsx index be73e16c29..e9798759fd 100644 --- a/app/client/src/components/editorComponents/ResizeStyledComponents.tsx +++ b/app/client/src/components/editorComponents/ResizeStyledComponents.tsx @@ -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` diff --git a/app/client/src/components/editorComponents/WidgetNameComponent.tsx b/app/client/src/components/editorComponents/WidgetNameComponent.tsx deleted file mode 100644 index fdbba2372f..0000000000 --- a/app/client/src/components/editorComponents/WidgetNameComponent.tsx +++ /dev/null @@ -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 = ( - -); -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 = ( - -); - -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 = ; - - 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 ? ( - -
{props.widgetName}
- {FeatureFlag.check(FeatureFlagsEnum.documentationV2) && ( - { - dispatch(setHelpDefaultRefinement(HelpMap[props.type].searchKey)); - dispatch(setHelpModalVisibility(true)); - // window.open(`${HelpBaseURL}${HelpMap[props.type]}`, "_blank"); - }} - > - - {helpControlIcon} - - - )} - - - {deleteControlIcon} - - - - - {editControlIcon} - - -
- ) : null; -}; - -export default WidgetNameComponent; diff --git a/app/client/src/components/editorComponents/WidgetNameComponent/DeleteControl.tsx b/app/client/src/components/editorComponents/WidgetNameComponent/DeleteControl.tsx new file mode 100644 index 0000000000..b5f6ef8679 --- /dev/null +++ b/app/client/src/components/editorComponents/WidgetNameComponent/DeleteControl.tsx @@ -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 = ; + +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 ? ( + + + {deleteControlIcon} + + + ) : null; +}; +export default DeleteControl; diff --git a/app/client/src/components/editorComponents/WidgetNameComponent/HelpControl.tsx b/app/client/src/components/editorComponents/WidgetNameComponent/HelpControl.tsx new file mode 100644 index 0000000000..88e170065b --- /dev/null +++ b/app/client/src/components/editorComponents/WidgetNameComponent/HelpControl.tsx @@ -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 = ( + +); + +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 ? ( + { + dispatch(setHelpDefaultRefinement(HelpMap[props.type].searchKey)); + dispatch(setHelpModalVisibility(true)); + // window.open(`${HelpBaseURL}${HelpMap[props.type]}`, "_blank"); + }} + > + + {helpControlIcon} + + + ) : null; +}; + +export default HelpControl; diff --git a/app/client/src/components/editorComponents/WidgetNameComponent/SettingsControl.tsx b/app/client/src/components/editorComponents/WidgetNameComponent/SettingsControl.tsx new file mode 100644 index 0000000000..fb20ebb40f --- /dev/null +++ b/app/client/src/components/editorComponents/WidgetNameComponent/SettingsControl.tsx @@ -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 = ( + + ); + + return ( + + + {props.name} + {settingsIcon} + + + ); +}; + +export default SettingsControl; diff --git a/app/client/src/components/editorComponents/WidgetNameComponent/index.tsx b/app/client/src/components/editorComponents/WidgetNameComponent/index.tsx new file mode 100644 index 0000000000..828384b074 --- /dev/null +++ b/app/client/src/components/editorComponents/WidgetNameComponent/index.tsx @@ -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 ? ( + + + + + + + + ) : null; +}; + +export default WidgetNameComponent; diff --git a/app/client/src/constants/Colors.tsx b/app/client/src/constants/Colors.tsx index a66ea82fce..5b7d806e2f 100644 --- a/app/client/src/constants/Colors.tsx +++ b/app/client/src/constants/Colors.tsx @@ -45,6 +45,7 @@ export const Colors: Record = { BLUE_CHARCOAL: "#23292E", TROUT: "#4C565E", JAFFA_DARK: "#EF7541", + WATUSI: "#FFE0D2", GRAY: "#828282", ATHENS_GRAY_DARKER: "#F8F9FA", }; diff --git a/app/client/src/constants/DefaultTheme.tsx b/app/client/src/constants/DefaultTheme.tsx index a20651719b..1f8be7477f 100644 --- a/app/client/src/constants/DefaultTheme.tsx +++ b/app/client/src/constants/DefaultTheme.tsx @@ -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, diff --git a/app/client/src/constants/WidgetConstants.tsx b/app/client/src/constants/WidgetConstants.tsx index a2e1505b94..e05ba7bf43 100644 --- a/app/client/src/constants/WidgetConstants.tsx +++ b/app/client/src/constants/WidgetConstants.tsx @@ -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, }; diff --git a/app/client/src/icons/ControlIcons.tsx b/app/client/src/icons/ControlIcons.tsx index de7d527747..5d913fdc19 100644 --- a/app/client/src/icons/ControlIcons.tsx +++ b/app/client/src/icons/ControlIcons.tsx @@ -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: { ), + SETTINGS_CONTROL: (props: IconProps) => ( + + + + ), HELP_CONTROL: (props: IconProps) => (