From 592923b6d137f08bff472b667a60d1781121e097 Mon Sep 17 00:00:00 2001 From: Sudheer Salavadi Date: Tue, 17 Dec 2024 08:32:22 -0500 Subject: [PATCH] Various improvements Cards, OmniSearch and Cards Listing (#2881) --- .../components/AddToDashboardButton.tsx | 111 +++++++++--------- .../components/FilterSeries/FilterSeries.tsx | 6 +- .../FilterSeries/SeriesName/SeriesName.tsx | 67 ++++++----- .../MetricViewHeader/MetricViewHeader.tsx | 8 +- .../components/WidgetChart/WidgetChart.tsx | 3 +- .../WidgetDatatable/WidgetDatatable.tsx | 1 + .../WidgetDateRange/RangeGranularity.tsx | 2 +- .../components/WidgetForm/WidgetFormNew.tsx | 2 +- .../components/WidgetName/WidgetName.tsx | 86 ++++++-------- .../Dashboard/components/WidgetOptions.tsx | 4 +- .../components/WidgetView/CardViewMenu.tsx | 52 +++----- .../WidgetView/WidgetViewHeader.tsx | 28 +++-- .../Funnels/FunnelWidget/FunnelBar.tsx | 4 +- .../Funnels/FunnelWidget/FunnelTable.tsx | 23 ++-- .../FilterAutoComplete/AutocompleteModal.tsx | 4 +- .../shared/Filters/FilterItem/FilterItem.tsx | 5 +- .../shared/Filters/FilterList/EventsOrder.tsx | 5 +- .../shared/Filters/FilterList/FilterList.tsx | 45 ++++--- .../Filters/FilterOperator/FilterOperator.tsx | 8 +- .../FilterSelection/FilterSelection.tsx | 6 +- .../Filters/SubFilterItem/SubFilterItem.tsx | 2 +- .../SelectDateRange/SelectDateRange.tsx | 4 +- frontend/app/styles/general.css | 4 +- 23 files changed, 247 insertions(+), 233 deletions(-) diff --git a/frontend/app/components/Dashboard/components/AddToDashboardButton.tsx b/frontend/app/components/Dashboard/components/AddToDashboardButton.tsx index 054576024..509c66426 100644 --- a/frontend/app/components/Dashboard/components/AddToDashboardButton.tsx +++ b/frontend/app/components/Dashboard/components/AddToDashboardButton.tsx @@ -1,64 +1,67 @@ +// Components/Dashboard/components/AddToDashboardButton.tsx + import React from 'react'; -import {Grid2x2Check} from "lucide-react" -import {Button, Modal} from "antd"; -import Select from "Shared/Select/Select"; -import {Form} from "UI"; -import {useStore} from "App/mstore"; +import { Grid2x2Check } from 'lucide-react'; +import { Button, Modal } from 'antd'; +import Select from 'Shared/Select/Select'; +import { Form } from 'UI'; +import { useStore } from 'App/mstore'; interface Props { - metricId: string; + metricId: string; } -function AddToDashboardButton({metricId}: Props) { - const {dashboardStore} = useStore(); - const dashboardOptions = dashboardStore.dashboards.map((i: any) => ({ - key: i.id, - label: i.name, - value: i.dashboardId, - })); - const [selectedId, setSelectedId] = React.useState(dashboardOptions[0]?.value); +export const showAddToDashboardModal = (metricId: string, dashboardStore: any) => { + const dashboardOptions = dashboardStore.dashboards.map((i: any) => ({ + key: i.id, + label: i.name, + value: i.dashboardId, + })); + let selectedId = dashboardOptions[0]?.value; - const onSave = (close: any) => { - const dashboard = dashboardStore.getDashboard(selectedId) - if (dashboard) { - dashboardStore.addWidgetToDashboard(dashboard, [metricId]).then(close) - } + const onSave = (close: any) => { + const dashboard = dashboardStore.getDashboard(selectedId); + if (dashboard) { + dashboardStore.addWidgetToDashboard(dashboard, [metricId]).then(close); } + }; - const onClick = () => { - Modal.confirm({ - title: 'Add to selected dashboard', - icon: null, - content: ( - - (selectedId = value.value)} + /> + + ), + cancelText: 'Cancel', + onOk: onSave, + okText: 'Add', + footer: (_, { OkBtn, CancelBtn }) => ( + <> + + + + ), + }); +}; - return ( - - ); -} +const AddToDashboardButton = ({ metricId }: Props) => { + const { dashboardStore } = useStore(); -export default AddToDashboardButton; + return ( + + ); +}; + +export default AddToDashboardButton; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx index d9ce2d7f2..a1e0f706f 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/FilterSeries.tsx @@ -56,7 +56,7 @@ const FilterSeriesHeader = observer( }; return (
} + type='text' + className='btn-delete-series' />
diff --git a/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx b/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx index 54f94aff9..3496c91f1 100644 --- a/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx +++ b/frontend/app/components/Dashboard/components/FilterSeries/SeriesName/SeriesName.tsx @@ -1,61 +1,68 @@ import React, { useState, useRef, useEffect } from 'react'; import { Icon } from 'UI'; -import {Input, Tooltip} from 'antd'; +import { Input, Tooltip } from 'antd'; interface Props { name: string; - onUpdate: (name) => void; + onUpdate: (name: string) => void; seriesIndex?: number; } + function SeriesName(props: Props) { const { seriesIndex = 1 } = props; - const [editing, setEditing] = useState(false) - const [name, setName] = useState(props.name) - const ref = useRef(null) + const [editing, setEditing] = useState(false); + const [name, setName] = useState(props.name); + const ref = useRef(null); - const write = ({ target: { value, name } }) => { - setName(value) - } + const write = ({ target: { value } }) => { + setName(value); + }; const onBlur = () => { - setEditing(false) - props.onUpdate(name) - } + setEditing(false); + props.onUpdate(name); + }; + + const onKeyDown = (e: React.KeyboardEvent) => { + if (e.key === 'Enter') { + setEditing(false); + props.onUpdate(name); + } + }; useEffect(() => { if (editing) { - ref.current.focus() + ref.current.focus(); } - }, [editing]) + }, [editing]); useEffect(() => { - setName(props.name) - }, [props.name]) - - // const { name } = props; + setName(props.name); + }, [props.name]); + return (
- { editing ? ( + {editing ? ( setEditing(true)} - className='bg-white' + onKeyDown={onKeyDown} + className="bg-white text-lg border-transparent rounded-lg font-medium ps-2" /> ) : ( -
{name && name.trim() === '' ? 'Series ' + (seriesIndex + 1) : name }
- )} - - -
setEditing(true)}> - - + +
setEditing(true)} + data-event='input-rename-series' + > + {name && name.trim() === '' ? 'Series ' + (seriesIndex + 1) : name} +
-
+ )}
); } diff --git a/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx b/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx index 109729b76..b1972c4cb 100644 --- a/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx +++ b/frontend/app/components/Dashboard/components/MetricViewHeader/MetricViewHeader.tsx @@ -5,6 +5,7 @@ import { PlusOutlined } from '@ant-design/icons'; import AddCardSection from '../AddCardSection/AddCardSection'; import MetricsSearch from '../MetricsSearch'; import Select from 'Shared/Select'; +import {Select as AntSelect} from 'antd'; import { useStore } from 'App/mstore'; import { observer, useObserver } from 'mobx-react-lite'; import { DROPDOWN_OPTIONS } from 'App/constants/card'; @@ -44,9 +45,9 @@ function MetricViewHeader() {
- onBlur()} + onKeyDown={onKeyDown} onFocus={() => setEditing(true)} maxLength={80} + className="bg-white text-2xl ps-2 rounded-lg h-8" /> ) : ( // @ts-ignore
setEditing(true)} - className={ - cn( - "text-2xl h-8 flex items-center border-transparent", - canEdit && 'cursor-pointer select-none border-b border-b-borderColor-transparent hover:border-dotted hover:border-gray-medium' - ) - } + className={cn( + "text-2xl h-8 flex items-center p-2 rounded-lg", + canEdit && 'cursor-pointer select-none ps-2 hover:bg-teal/10' + )} > - { name } + {name}
- )} - { canEdit &&
setEditing(true)}> - - - -
}
); } -export default WidgetName; +export default WidgetName; \ No newline at end of file diff --git a/frontend/app/components/Dashboard/components/WidgetOptions.tsx b/frontend/app/components/Dashboard/components/WidgetOptions.tsx index 9e71edf31..8f92eb904 100644 --- a/frontend/app/components/Dashboard/components/WidgetOptions.tsx +++ b/frontend/app/components/Dashboard/components/WidgetOptions.tsx @@ -112,7 +112,7 @@ const SeriesTypeOptions = observer(({ metric }: { metric: any }) => { }, }} > -
); }; -export default observer(CardViewMenu); +export default observer(CardViewMenu); \ No newline at end of file diff --git a/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx index f1a385c71..ab0d51a78 100644 --- a/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx +++ b/frontend/app/components/Dashboard/components/WidgetView/WidgetViewHeader.tsx @@ -3,7 +3,7 @@ import cn from 'classnames'; import WidgetName from 'Components/Dashboard/components/WidgetName'; import { useStore } from 'App/mstore'; import { observer } from 'mobx-react-lite'; -import AddToDashboardButton from 'Components/Dashboard/components/AddToDashboardButton'; + import { Button, Space, Tooltip } from 'antd'; import CardViewMenu from 'Components/Dashboard/components/WidgetView/CardViewMenu'; import { Link2 } from 'lucide-react' @@ -31,11 +31,11 @@ function WidgetViewHeader({ onClick, onSave }: Props) { return (
-

+

metricStore.merge({ name })} @@ -43,20 +43,28 @@ function WidgetViewHeader({ onClick, onSave }: Props) { />

- - - - - - + + + + + + + + +
); diff --git a/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx b/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx index 1b04d76f9..9af12271a 100644 --- a/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx +++ b/frontend/app/components/Funnels/FunnelWidget/FunnelBar.tsx @@ -90,7 +90,7 @@ function FunnelBarData({ bottom: 0, background: isFocused ? 'rgba(204, 0, 0, 0.3)' - : 'repeating-linear-gradient(325deg, lightgray, lightgray 2px, #FFF1F0 2px, #FFF1F0 6px)', + : 'repeating-linear-gradient(325deg, lightgray, lightgray 1px, #FFF1F0 1px, #FFF1F0 6px)', cursor: 'pointer', } const horizontalEmptyBarStyle = { @@ -102,7 +102,7 @@ function FunnelBarData({ left: 0, background: isFocused ? 'rgba(204, 0, 0, 0.3)' - : 'repeating-linear-gradient(325deg, lightgray, lightgray 2px, #FFF1F0 2px, #FFF1F0 6px)', + : 'repeating-linear-gradient(325deg, lightgray, lightgray 1px, #FFF1F0 1px, #FFF1F0 6px)', cursor: 'pointer', } diff --git a/frontend/app/components/Funnels/FunnelWidget/FunnelTable.tsx b/frontend/app/components/Funnels/FunnelWidget/FunnelTable.tsx index c5c5bb9a2..97f850b91 100644 --- a/frontend/app/components/Funnels/FunnelWidget/FunnelTable.tsx +++ b/frontend/app/components/Funnels/FunnelWidget/FunnelTable.tsx @@ -1,10 +1,10 @@ import React from 'react'; -import { Table } from 'antd'; +import { Table, Tooltip } from 'antd'; import type { TableProps } from 'antd'; import Widget from 'App/mstore/types/widget'; import Funnel from 'App/mstore/types/funnel'; import { ItemMenu } from 'UI'; -import { EllipsisVertical } from 'lucide-react'; +import { EllipsisVertical, FileDown } from 'lucide-react'; import { exportAntCsv } from '../../../utils'; interface Props { @@ -101,30 +101,27 @@ export function TableExporter({ }) { const onClick = () => exportAntCsv(tableColumns, tableData, filename); return ( +
+
} />
+
); } diff --git a/frontend/app/components/shared/Filters/FilterAutoComplete/AutocompleteModal.tsx b/frontend/app/components/shared/Filters/FilterAutoComplete/AutocompleteModal.tsx index 4602486c2..727235893 100644 --- a/frontend/app/components/shared/Filters/FilterAutoComplete/AutocompleteModal.tsx +++ b/frontend/app/components/shared/Filters/FilterAutoComplete/AutocompleteModal.tsx @@ -134,10 +134,10 @@ export function AutocompleteModal({
- - +
); diff --git a/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx b/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx index 0648a4090..f1ad74bb1 100644 --- a/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx +++ b/frontend/app/components/shared/Filters/FilterItem/FilterItem.tsx @@ -91,7 +91,7 @@ function FilterItem(props: Props) { @@ -105,7 +105,7 @@ function FilterItem(props: Props) { @@ -157,6 +157,7 @@ function FilterItem(props: Props) { type="text" onClick={props.onRemoveFilter} size="small" + className='btn-remove-step' > diff --git a/frontend/app/components/shared/Filters/FilterList/EventsOrder.tsx b/frontend/app/components/shared/Filters/FilterList/EventsOrder.tsx index aa920e50d..bf6ec8ef9 100644 --- a/frontend/app/components/shared/Filters/FilterList/EventsOrder.tsx +++ b/frontend/app/components/shared/Filters/FilterList/EventsOrder.tsx @@ -38,14 +38,15 @@ const EventsOrder = observer( title="Select the operator to be applied between events." placement="bottom" > -
Events Order
+
Events Order
diff --git a/frontend/app/components/shared/Filters/FilterList/FilterList.tsx b/frontend/app/components/shared/Filters/FilterList/FilterList.tsx index 119f6e641..3c329fee8 100644 --- a/frontend/app/components/shared/Filters/FilterList/FilterList.tsx +++ b/frontend/app/components/shared/Filters/FilterList/FilterList.tsx @@ -70,6 +70,7 @@ export const FilterList = observer((props: Props) => { icon={} type="default" size={'small'} + className='btn-add-filter' > Add @@ -214,6 +215,7 @@ export const EventsList = observer((props: Props) => { icon={} type="default" size={'small'} + className='btn-add-event' > Add @@ -228,27 +230,39 @@ export const EventsList = observer((props: Props) => { actions.map((action, index) =>
{action}
)} -
+
{filters.map((filter: any, filterIndex: number) => filter.isEvent ? (
handleDragOverEv(e, filterIndex)} onDrop={(e) => handleDrop(e)} @@ -257,16 +271,19 @@ export const EventsList = observer((props: Props) => { {!!props.onFilterMove && eventsNum > 1 ? (
- handleDragStart( - e, - filterIndex, - `${filter.key}-${filterIndex}` - ) + handleDragStart(e, filterIndex, `${filter.key}-${filterIndex}`) } + onDragEnd={() => { + setHoveredItem({ i: null, position: null }); + setDraggedItem(null); + }} + style={{ + cursor: draggedInd !== null ? 'grabbing' : 'grab', + }} >
diff --git a/frontend/app/components/shared/Filters/FilterOperator/FilterOperator.tsx b/frontend/app/components/shared/Filters/FilterOperator/FilterOperator.tsx index d8b4741dd..84e8bda4f 100644 --- a/frontend/app/components/shared/Filters/FilterOperator/FilterOperator.tsx +++ b/frontend/app/components/shared/Filters/FilterOperator/FilterOperator.tsx @@ -1,3 +1,4 @@ +import { backgroundClip } from 'html2canvas/dist/types/css/property-descriptors/background-clip'; import React from 'react'; import Select from 'Shared/Select'; @@ -5,14 +6,18 @@ const dropdownStyles = { control: (provided: any) => { const obj = { ...provided, - border: 'solid thin #ddd !important', + border: 'solid thin #ddd', boxShadow: 'none !important', cursor: 'pointer', height: '26px', minHeight: '26px', backgroundColor: 'white', borderRadius: '.5rem', + '&:hover': { + borderColor: 'rgb(115 115 115 / 0.9)', } + } + return obj; }, valueContainer: (provided: any) => ({ @@ -79,6 +84,7 @@ function FilterOperator(props: Props) { isDisabled={isDisabled} value={value ? options?.find((i: any) => i.value === value) : null} onChange={({ value }: any) => onChange(null, { name: 'operator', value: value.value })} + className='btn-event-operator' />
); diff --git a/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx b/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx index d4aa16f3f..b01ced93e 100644 --- a/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx +++ b/frontend/app/components/shared/Filters/FilterSelection/FilterSelection.tsx @@ -62,7 +62,7 @@ function FilterSelection(props: Props) { ) : (
setShowModal(true)} > -
{getNewIcon(filter)}
-
{`${filter.category} •`}
+
{getNewIcon(filter)}
+
{`${filter.category} •`}
diff --git a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx index 8c5a0e3b4..58ba088b3 100644 --- a/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx +++ b/frontend/app/components/shared/SelectDateRange/SelectDateRange.tsx @@ -197,7 +197,7 @@ function AndDateRange({ {comparison ? (
-