Skip to content
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

feat: add column layout options in settings #5186

Closed
wants to merge 7 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
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
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,16 @@ const POSITION_LABELS = {
bottom: 'Bottom',
}

const COLUMN_LAYOUT_LABELS = {
DEFAULT: 'Default view',
VIEW_2: 'Limit price / Fills at / Distance',
VIEW_3: 'Limit price / Fills at + Distance / Market',
}

export function Settings({ state, onStateChanged }: SettingsProps) {
const { showRecipient, partialFillsEnabled, limitPricePosition, limitPriceLocked } = state
const { showRecipient, partialFillsEnabled, limitPricePosition, limitPriceLocked, columnLayout } = state
const [isOpen, setIsOpen] = useState(false)
const [isColumnLayoutOpen, setIsColumnLayoutOpen] = useState(false)

const handleSelect = useCallback(
(value: LimitOrdersSettingsState['limitPricePosition']) => (e: React.MouseEvent) => {
Expand All @@ -122,11 +129,25 @@ export function Settings({ state, onStateChanged }: SettingsProps) {
[onStateChanged],
)

const handleColumnLayoutSelect = useCallback(
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to use useCallback since React 19

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed

(value: LimitOrdersSettingsState['columnLayout']) => (e: React.MouseEvent) => {
e.stopPropagation()
onStateChanged({ columnLayout: value })
setIsColumnLayoutOpen(false)
},
[onStateChanged],
)

const toggleDropdown = (e: React.MouseEvent) => {
e.stopPropagation()
setIsOpen(!isOpen)
}

const toggleColumnLayoutDropdown = (e: React.MouseEvent) => {
e.stopPropagation()
setIsColumnLayoutOpen(!isColumnLayoutOpen)
}

return (
<SettingsContainer>
<SettingsTitle>Limit Order Settings</SettingsTitle>
Expand Down Expand Up @@ -178,6 +199,26 @@ export function Settings({ state, onStateChanged }: SettingsProps) {
</DropdownList>
</DropdownContainer>
</SettingsRow>

<SettingsRow>
<SettingsLabel>
Column Layout
<HelpTooltip text="Choose how to display the columns in the orders table." />
</SettingsLabel>
<DropdownContainer>
<DropdownButton onClick={toggleColumnLayoutDropdown}>{COLUMN_LAYOUT_LABELS[columnLayout]}</DropdownButton>
<DropdownList isOpen={isColumnLayoutOpen}>
{Object.entries(COLUMN_LAYOUT_LABELS).map(([value, label]) => (
<DropdownItem
key={value}
onClick={handleColumnLayoutSelect(value as LimitOrdersSettingsState['columnLayout'])}
>
{label}
</DropdownItem>
))}
</DropdownList>
</DropdownContainer>
</SettingsRow>
</SettingsContainer>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,16 @@ import {
alternativeOrderReadWriteAtomFactory,
} from 'modules/trade/state/alternativeOrder'

export type ColumnLayoutType = 'DEFAULT' | 'VIEW_2' | 'VIEW_3'

export interface LimitOrdersSettingsState {
readonly showRecipient: boolean
readonly partialFillsEnabled: boolean
readonly deadlineMilliseconds: Milliseconds
readonly customDeadlineTimestamp: Timestamp | null
readonly limitPricePosition: 'top' | 'between' | 'bottom'
readonly limitPriceLocked: boolean
readonly columnLayout: ColumnLayoutType
}

export const defaultLimitOrdersSettings: LimitOrdersSettingsState = {
Expand All @@ -28,6 +31,7 @@ export const defaultLimitOrdersSettings: LimitOrdersSettingsState = {
customDeadlineTimestamp: null,
limitPricePosition: 'top',
limitPriceLocked: true,
columnLayout: 'DEFAULT',
}

// regular
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import styled from 'styled-components/macro'
import { Order } from 'legacy/state/orders/actions'

import { useInjectedWidgetParams } from 'modules/injectedWidget'
import { limitOrdersSettingsAtom } from 'modules/limitOrders/state/limitOrdersSettingsAtom'
import { pendingOrdersPricesAtom } from 'modules/orders/state/pendingOrdersPricesAtom'
import { useGetSpotPrice } from 'modules/orders/state/spotPricesAtom'
import { PendingPermitUpdater, useGetOrdersPermitStatus } from 'modules/permit'
Expand All @@ -30,6 +31,7 @@ import { useValidatePageUrlParams } from './hooks/useValidatePageUrlParams'
import { BalancesAndAllowances } from '../../../tokens'
import { OPEN_TAB, ORDERS_TABLE_TABS } from '../../const/tabs'
import { OrdersTableContainer } from '../../pure/OrdersTableContainer'
import { ColumnLayout } from '../../pure/OrdersTableContainer/tableHeaders'
import { OrderActions } from '../../pure/OrdersTableContainer/types'
import { TabOrderTypes } from '../../types'
import { buildOrdersTableUrl } from '../../utils/buildOrdersTableUrl'
Expand Down Expand Up @@ -124,6 +126,19 @@ export function OrdersTableWidget({
const ordersPermitStatus = useGetOrdersPermitStatus()
const injectedWidgetParams = useInjectedWidgetParams()
const [searchTerm, setSearchTerm] = useState('')
const limitOrdersSettings = useAtomValue(limitOrdersSettingsAtom)
const columnLayout = useMemo(() => {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const layoutMap: Record<string, ColumnLayout> = {
    DEFAULT: ColumnLayout.DEFAULT,
    VIEW_2: ColumnLayout.VIEW_2,
    VIEW_3: ColumnLayout.VIEW_3,
  };
  
const columnLayout = layoutMap[limitOrdersSettings.columnLayout] || ColumnLayout.DEFAULT;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@shoom3301 Addressed this now

switch (limitOrdersSettings.columnLayout) {
case 'DEFAULT':
return ColumnLayout.DEFAULT
case 'VIEW_2':
return ColumnLayout.VIEW_2
case 'VIEW_3':
return ColumnLayout.VIEW_3
default:
return ColumnLayout.DEFAULT
}
}, [limitOrdersSettings.columnLayout])

const balancesState = useTokensBalances()
const allowancesState = useTokensAllowances()
Expand Down Expand Up @@ -290,6 +305,7 @@ export function OrdersTableWidget({
ordersPermitStatus={ordersPermitStatus}
injectedWidgetParams={injectedWidgetParams}
searchTerm={searchTerm}
columnLayout={columnLayout}
>
{(currentTabId === OPEN_TAB.id || currentTabId === 'all' || currentTabId === 'unfillable') &&
orders.length > 0 && <MultipleCancellationMenu pendingOrders={tableItemsToOrders(orders)} />}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import * as styledEl from './styled'
import { OrderParams } from '../../../utils/getOrderParams'
import { OrderStatusBox } from '../../OrderStatusBox'
import { CheckboxCheckmark, TableRow, TableRowCheckbox, TableRowCheckboxWrapper } from '../styled'
import { ColumnLayout } from '../tableHeaders'
import { OrderActions } from '../types'

// Constants
Expand Down Expand Up @@ -83,6 +84,7 @@ export interface OrderRowProps {
orderActions: OrderActions
hasValidPendingPermit?: boolean | undefined
children?: React.ReactNode
columnLayout?: ColumnLayout
}

export function OrderRow({
Expand All @@ -100,6 +102,7 @@ export function OrderRow({
spotPrice,
hasValidPendingPermit,
children,
columnLayout = ColumnLayout.DEFAULT,
}: OrderRowProps) {
const { buyAmount, rateInfoParams, hasEnoughAllowance, hasEnoughBalance, chainId } = orderParams
const { creationTime, expirationTime, status } = order
Expand Down Expand Up @@ -177,8 +180,111 @@ export function OrderRow({
/>
)

const renderLimitPrice = () => (
<styledEl.RateValue onClick={toggleIsInverted}>
<RateInfo
prependSymbol={false}
isInvertedState={[isInverted, setIsInverted]}
noLabel={true}
doNotUseSmartQuote
isInverted={isInverted}
rateInfoParams={rateInfoParams}
opacitySymbol={true}
/>
</styledEl.RateValue>
)

const renderFillsAt = () => (
<>
{getIsFinalizedOrder(order) ? (
'-'
) : prices && estimatedExecutionPrice ? (
<styledEl.ExecuteCellWrapper>
{!isUnfillable &&
priceDiffs?.percentage &&
Math.abs(Number(priceDiffs.percentage.toFixed(4))) <= MIN_PERCENTAGE_TO_DISPLAY ? (
<span>⚡️ Pending execution</span>
) : (
<EstimatedExecutionPrice
amount={executionPriceInverted}
tokenSymbol={executionPriceInverted?.quoteCurrency}
opacitySymbol
isInverted={isInverted}
percentageDifference={priceDiffs?.percentage}
amountDifference={priceDiffs?.amount}
percentageFee={feeDifference}
amountFee={feeAmount}
canShowWarning={getUiOrderType(order) !== UiOrderType.SWAP && !isUnfillable}
isUnfillable={withWarning}
warningText={getWarningText()}
onApprove={() => orderActions.approveOrderToken(order.inputToken)}
WarningTooltip={renderWarningTooltip()}
/>
)}
</styledEl.ExecuteCellWrapper>
) : prices === null || !estimatedExecutionPrice || isOrderCreating ? (
'-'
) : (
<Loader size="14px" style={{ margin: '0 0 -2px 7px' }} />
)}
</>
)

const renderFillsAtWithDistance = () => {
const fillsAtContent = renderFillsAt()
const distance =
!isUnfillable && priceDiffs?.percentage && Number(priceDiffs?.percentage.toFixed(4)) >= MIN_PERCENTAGE_TO_DISPLAY
? `${priceDiffs?.percentage.toFixed(2)}%`
: '-'

return (
<styledEl.CellElement doubleRow>
<b>{fillsAtContent}</b>
<i
style={{
color: !isUnfillable ? getDistanceColor(Number(priceDiffs?.percentage?.toFixed(4) || '0')) : 'inherit',
}}
>
{distance}
</i>
</styledEl.CellElement>
)
}

const renderDistanceToMarket = () => (
<>
{isUnfillable ? (
'-'
) : priceDiffs?.percentage && Number(priceDiffs.percentage.toFixed(4)) >= MIN_PERCENTAGE_TO_DISPLAY ? (
<styledEl.DistanceToMarket $color={getDistanceColor(Number(priceDiffs.percentage.toFixed(4)))}>
{priceDiffs.percentage.toFixed(2)}%
</styledEl.DistanceToMarket>
) : (
'-'
)}
</>
)

const renderMarketPrice = () => (
<>
{spotPrice ? (
<TokenAmount amount={spotPriceInverted} tokenSymbol={spotPriceInverted?.quoteCurrency} opacitySymbol />
) : spotPrice === null ? (
'-'
) : (
<Loader size="14px" style={{ margin: '0 0 -2px 7px' }} />
)}
</>
)

return (
<TableRow data-id={order.id} isChildOrder={isChild} isHistoryTab={isHistoryTab} isRowSelectable={isRowSelectable}>
<TableRow
data-id={order.id}
isChildOrder={isChild}
isHistoryTab={isHistoryTab}
isRowSelectable={isRowSelectable}
columnLayout={columnLayout}
>
{/*Checkbox for multiple cancellation*/}
{isRowSelectable && !isHistoryTab && (
<TableRowCheckboxWrapper>
Expand Down Expand Up @@ -207,79 +313,32 @@ export function OrderRow({
{/* Non-history tab columns */}
{!isHistoryTab ? (
<>
{/* Fills at / Limit price */}
<styledEl.PriceElement onClick={toggleIsInverted}>
{showLimitPrice ? (
<styledEl.RateValue onClick={toggleIsInverted}>
<RateInfo
prependSymbol={false}
isInvertedState={[isInverted, setIsInverted]}
noLabel={true}
doNotUseSmartQuote
isInverted={isInverted}
rateInfoParams={rateInfoParams}
opacitySymbol={true}
/>
</styledEl.RateValue>
) : (
<>
{getIsFinalizedOrder(order) ? (
'-'
) : prices && estimatedExecutionPrice ? (
<styledEl.ExecuteCellWrapper>
{priceDiffs?.percentage &&
Math.abs(Number(priceDiffs.percentage.toFixed(4))) <= MIN_PERCENTAGE_TO_DISPLAY ? (
<span>⚡️ Pending execution</span>
) : (
<EstimatedExecutionPrice
amount={executionPriceInverted}
tokenSymbol={executionPriceInverted?.quoteCurrency}
opacitySymbol
isInverted={isInverted}
percentageDifference={priceDiffs?.percentage}
amountDifference={priceDiffs?.amount}
percentageFee={feeDifference}
amountFee={feeAmount}
canShowWarning={getUiOrderType(order) !== UiOrderType.SWAP && !isUnfillable}
isUnfillable={withWarning}
warningText={getWarningText()}
onApprove={() => orderActions.approveOrderToken(order.inputToken)}
WarningTooltip={renderWarningTooltip()}
/>
)}
</styledEl.ExecuteCellWrapper>
) : prices === null || !estimatedExecutionPrice || isOrderCreating ? (
'-'
) : (
<Loader size="14px" style={{ margin: '0 0 -2px 7px' }} />
)}
</>
)}
</styledEl.PriceElement>

{/* Distance to market */}
<styledEl.PriceElement>
{isUnfillable ? (
'-'
) : priceDiffs?.percentage && Number(priceDiffs.percentage.toFixed(4)) >= MIN_PERCENTAGE_TO_DISPLAY ? (
<styledEl.DistanceToMarket $color={getDistanceColor(Number(priceDiffs.percentage.toFixed(4)))}>
{priceDiffs.percentage.toFixed(2)}%
</styledEl.DistanceToMarket>
) : (
'-'
)}
</styledEl.PriceElement>

{/* Market price */}
<styledEl.PriceElement onClick={toggleIsInverted}>
{spotPrice ? (
<TokenAmount amount={spotPriceInverted} tokenSymbol={spotPriceInverted?.quoteCurrency} opacitySymbol />
) : spotPrice === null ? (
'-'
) : (
<Loader size="14px" style={{ margin: '0 0 -2px 7px' }} />
)}
</styledEl.PriceElement>
{/* Price columns based on layout */}
{columnLayout === ColumnLayout.DEFAULT && (
<>
<styledEl.PriceElement onClick={toggleIsInverted}>
{showLimitPrice ? renderLimitPrice() : renderFillsAt()}
</styledEl.PriceElement>
<styledEl.PriceElement>{renderDistanceToMarket()}</styledEl.PriceElement>
<styledEl.PriceElement onClick={toggleIsInverted}>{renderMarketPrice()}</styledEl.PriceElement>
</>
)}

{columnLayout === ColumnLayout.VIEW_2 && (
<>
<styledEl.PriceElement onClick={toggleIsInverted}>{renderLimitPrice()}</styledEl.PriceElement>
<styledEl.PriceElement onClick={toggleIsInverted}>{renderFillsAt()}</styledEl.PriceElement>
<styledEl.PriceElement>{renderDistanceToMarket()}</styledEl.PriceElement>
</>
)}

{columnLayout === ColumnLayout.VIEW_3 && (
<>
<styledEl.PriceElement onClick={toggleIsInverted}>{renderLimitPrice()}</styledEl.PriceElement>
<styledEl.PriceElement onClick={toggleIsInverted}>{renderFillsAtWithDistance()}</styledEl.PriceElement>
<styledEl.PriceElement onClick={toggleIsInverted}>{renderMarketPrice()}</styledEl.PriceElement>
</>
)}

{/* Expires and Created for open orders */}
<styledEl.CellElement doubleRow>
Expand Down
Loading
Loading