From 5911749864da896f39ac8f9cd54701fcb51b7c19 Mon Sep 17 00:00:00 2001 From: Chloe Rice Date: Mon, 30 Sep 2024 16:00:36 -0400 Subject: [PATCH] IFS Proto Side by Side: Includes filter separate --- polaris-react/playground/OrdersPage.tsx | 152 ++++++++++++++---- .../components/FiltersBar/FiltersBar.tsx | 28 +--- .../components/SearchField/SearchField.tsx | 2 +- .../IndexFilters/IndexFilters.module.css | 22 +++ .../components/IndexFilters/IndexFilters.tsx | 20 +-- .../components/SearchField/SearchField.tsx | 2 +- .../components/TextField/TextField.module.css | 6 +- 7 files changed, 164 insertions(+), 68 deletions(-) diff --git a/polaris-react/playground/OrdersPage.tsx b/polaris-react/playground/OrdersPage.tsx index 9b119d252ed..646f62a748c 100644 --- a/polaris-react/playground/OrdersPage.tsx +++ b/polaris-react/playground/OrdersPage.tsx @@ -45,6 +45,7 @@ import { IndexFiltersMode, Badge, Text, + TextField, } from '../src'; import {orders} from './orders'; @@ -408,11 +409,20 @@ function OrdersIndexTableWithFilters( const [selectedView, setSelectedView] = useState(0); const [sortSelected, setSortSelected] = useState(['order desc']); const [queryValue, setQueryValue] = useState(''); + const [contains, setContains] = useState(''); const [status, setStatus] = useState([]); const [paymentStatus, setPaymentStatus] = useState([]); const [fulfillmentStatus, setFulfillmentStatus] = useState([]); const [loading, setLoading] = useState(false); const [filteredOrders, setFilteredOrders] = useState(orders); + const [tempPersistedSearch, setTempPersistedSearch] = useState([ + '', + '', + '', + '', + '', + ]); + const [savedViewFilters, setSavedViewFilters] = useState( [ [], @@ -512,6 +522,7 @@ function OrdersIndexTableWithFilters( }; const handleFilterOrders = (nextFilters: { + contains?: string; queryValue?: string; paymentStatus?: string[]; fulfillmentStatus?: string[]; @@ -523,6 +534,8 @@ function OrdersIndexTableWithFilters( ? nextFilters.queryValue : queryValue; + const nextContains = + nextFilters.contains !== undefined ? nextFilters.contains : contains; const nextStatus = nextFilters.status !== undefined ? nextFilters.status : status; const nextPaymentStatus = @@ -534,11 +547,16 @@ function OrdersIndexTableWithFilters( ? nextFilters.fulfillmentStatus : fulfillmentStatus; + const containsSet = new Set(nextContains); const statusSet = new Set(nextStatus); const paymentStatusSet = new Set(nextPaymentStatus); const fulfillmentStatusSet = new Set(nextFulfillmentStatus); const result = orders.filter((order) => { const matchesQueryValue = hasTextValueMatches(nextQueryValue, order); + const matchesContains = hasTextValueMatches( + preProcessText(nextContains), + order, + ); const matchesStatus = hasArrayValueMatches( new Set([order.status]), @@ -558,6 +576,7 @@ function OrdersIndexTableWithFilters( setLoading(false); return ( matchesQueryValue && + matchesContains && matchesPaymentStatus && matchesFulfillmentStatus && matchesStatus @@ -580,6 +599,16 @@ function OrdersIndexTableWithFilters( handleFilterOrders({queryValue: ''}); }; + const handleContainsChange = (value: string) => { + setContains(value); + handleFilterOrders({contains: value}); + }; + + const handleContainsRemove = (value: string[]) => { + setContains(''); + handleFilterOrders({contains: ''}); + }; + const handlePaymentStatusChange = (value: string[]) => { setPaymentStatus(value); handleFilterOrders({paymentStatus: value}); @@ -618,6 +647,13 @@ function OrdersIndexTableWithFilters( emptyValue: '', label: 'Include', }, + contains: { + set: setContains, + change: handleContainsChange, + remove: handleContainsRemove, + emptyValue: '', + label: 'Include', + }, status: { set: setStatus, change: handleStatusChange, @@ -668,6 +704,7 @@ function OrdersIndexTableWithFilters( }; const handleChangeFilters = (nextFilterValues: { + contains?: string; queryValue?: string; paymentStatus?: string[]; fulfillmentStatus?: string[]; @@ -684,11 +721,13 @@ function OrdersIndexTableWithFilters( const handleResetToSavedFilters = (view: number) => { const nextFilters: { + contains: string; queryValue: string; paymentStatus: string[]; fulfillmentStatus: string[]; status: string[]; } = { + contains: '', queryValue: '', paymentStatus: [], fulfillmentStatus: [], @@ -713,6 +752,7 @@ function OrdersIndexTableWithFilters( const handleClearFilters = () => { handleChangeFilters({ + contains: '', queryValue: '', paymentStatus: [], fulfillmentStatus: [], @@ -746,6 +786,21 @@ function OrdersIndexTableWithFilters( // ---- Filters const filters: FilterInterface[] = [ + { + key: 'contains', + label: handlers.contains.label, + filter: ( + + ), + }, { key: 'paymentStatus', value: paymentStatus, @@ -809,6 +864,8 @@ function OrdersIndexTableWithFilters( const appliedFilters: AppliedFilterInterface[] = []; Object.entries({ + contains, + queryValue, status, paymentStatus, fulfillmentStatus, @@ -824,14 +881,32 @@ function OrdersIndexTableWithFilters( value, label: getHumanReadableValue(handlers[key].label, value), unsavedChanges: selectedView === 0 ? true : isUnsaved(value, savedValue), - onRemove: key === 'queryValue' ? undefined : handlers[key].remove, + onRemove: handlers[key].remove, }); }); + // const appliedFiltersWithQuery = [ + // ...appliedFilters, + // { + // key: 'queryValue', + // value: queryValue, + // label: handlers.queryValue.label, + // onRemove: handlers.queryValue.remove, + // }, + // ]; + + const appliedFiltersWithoutQuery = appliedFilters.filter( + ({key}) => key !== 'queryValue', + ); + + const savedViewFiltersWithoutQuery = savedViewFilters.filter( + ({key}) => key !== 'queryValue', + ); + const appliedFilterMatchesSavedFilter = ( appliedFilter: AppliedFilterInterface, ) => { - const savedFilter = savedViewFilters[selectedView].find( + const savedFilter = savedViewFiltersWithoutQuery[selectedView]?.find( (savedFilter) => savedFilter.key === appliedFilter.key, ); @@ -839,41 +914,45 @@ function OrdersIndexTableWithFilters( return false; } else if (typeof appliedFilter.value === 'string') { return appliedFilter.value === savedFilter.value; - } else { + } else if (Array.isArray(appliedFilter.value)) { const hasSameArrayValue = new Set(savedFilter.value).difference(new Set(appliedFilter.value)) .size === 0; - return hasSameArrayValue; + } else { + return true; } }; - const appliedFiltersWithQuery = [ - ...appliedFilters, - { - key: 'queryValue', - value: queryValue, - unsavedChanges: - queryValue && selectedView === 0 - ? true - : queryValue && - queryValue !== - savedViewFilters[selectedView]?.find( - ({key}) => key === 'queryValue', - )?.value, - }, - ]; - const hasUnsavedSortChange = (selectedView === 0 && sortSelected[0] !== 'order desc') || sortSelected[0] !== savedSortSelected[selectedView]; + const isAllViewAndFiltersAreApplied = + selectedView === 0 && appliedFiltersWithoutQuery.length > 0; + + const appliedFilterCountDoesNotEqualSavedFilterCount = + appliedFiltersWithoutQuery.length !== + savedViewFiltersWithoutQuery[selectedView]?.length; + + const appliedFiltersDoNotMatchSavedFilters = + !appliedFiltersWithoutQuery.every(appliedFilterMatchesSavedFilter); + const hasUnsavedFilterChange = - (selectedView === 0 && appliedFiltersWithQuery.length > 0) || - (!savedViewFilters[selectedView] && appliedFilters.length > 0) || - (appliedFiltersWithQuery.length === 0 && - savedViewFilters[selectedView]?.length > 0) || - !appliedFiltersWithQuery.every(appliedFilterMatchesSavedFilter); + isAllViewAndFiltersAreApplied || + (selectedView > 0 && + (appliedFilterCountDoesNotEqualSavedFilterCount || + appliedFiltersDoNotMatchSavedFilters)); + + console.table({ + hasUnsavedFilterChange, + isAllViewAndFiltersAreApplied, + countDoesNotEqual: + selectedView > 0 && appliedFilterCountDoesNotEqualSavedFilterCount, + filtersDoNotMatch: selectedView > 0 && appliedFiltersDoNotMatchSavedFilters, + }); + + console.table(savedViewFilters[selectedView]); const hasUnsavedChanges = hasUnsavedSortChange || hasUnsavedFilterChange; @@ -884,10 +963,11 @@ function OrdersIndexTableWithFilters( const getFiltersToSave = () => { return Object.entries({ + contains, queryValue, - fulfillmentStatus, - paymentStatus, status, + paymentStatus, + fulfillmentStatus, }) .filter(([, value]) => value !== undefined) .map(([key, value]) => { @@ -900,7 +980,7 @@ function OrdersIndexTableWithFilters( const previousSortSelected = sortSelected[0]; let nextFilters; - if (previousView === 0 && hasUnsavedChanges) { + if ((previousView === 0 && hasUnsavedChanges) || queryValue) { nextFilters = getFiltersToSave(); } @@ -920,8 +1000,10 @@ function OrdersIndexTableWithFilters( const handleDeleteView = (index: number) => async () => { const nextViewNames = [...viewNames]; + const nextTempPersistedSearch = [...tempPersistedSearch]; const nextSavedViewFilters = [...savedViewFilters]; nextViewNames.splice(index, 1); + nextTempPersistedSearch.splice(index, 1); nextSavedViewFilters.splice(index, 1); setSavedViewFilters(nextSavedViewFilters); setViewNames(nextViewNames); @@ -945,6 +1027,7 @@ function OrdersIndexTableWithFilters( setSavedViewFilters((filters) => [...filters, duplicateViewFilters]); const nextAppliedFilters = { queryValue: '', + contains: '', status: [], paymentStatus: [], fulfillmentStatus: [], @@ -953,7 +1036,12 @@ function OrdersIndexTableWithFilters( duplicateViewFilters.forEach(({key, value}) => { nextAppliedFilters[key] = value; }); + setViewNames((names) => [...names, name]); + setSavedSortSelected((currentSavedSortSelected) => [ + ...currentSavedSortSelected, + 'order desc', + ]); await sleep(250); setSelectedView(duplicateViewIndex); setLoading(false); @@ -996,8 +1084,9 @@ function OrdersIndexTableWithFilters( sortSelected[0] !== savedSortSelected[0]); const nextFilters = shouldSaveAppliedFiltersAsNew - ? {queryValue, status, paymentStatus, fulfillmentStatus} + ? getFiltersToSave() : { + contains: '', queryValue: '', status: [], paymentStatus: [], @@ -1005,7 +1094,7 @@ function OrdersIndexTableWithFilters( }; if (shouldSaveAppliedFiltersAsNew) { - handleSaveViewFilters(newViewIndex); + handleSaveViewFilters(newViewIndex, nextFilters); } else { handleClearFilters(); setSavedViewFilters((filters) => [...filters, []]); @@ -1059,6 +1148,8 @@ function OrdersIndexTableWithFilters( handleResetToSavedFilters(selectedView); console.log('cancelled -- resetting to saved'); } + + setQueryValue(''); }; const tabs: TabProps[] = viewNames.map((name, index) => { @@ -1097,6 +1188,7 @@ function OrdersIndexTableWithFilters( const cancelAction: IndexFiltersProps['cancelAction'] = { onAction: handleCancel, + disabled: !hasUnsavedChanges, }; const queryPlaceholder = `Search ${viewNames[selectedView]?.toLowerCase()}`; diff --git a/polaris-react/src/components/Filters/components/FiltersBar/FiltersBar.tsx b/polaris-react/src/components/Filters/components/FiltersBar/FiltersBar.tsx index 3cffb963207..69200622ce4 100644 --- a/polaris-react/src/components/Filters/components/FiltersBar/FiltersBar.tsx +++ b/polaris-react/src/components/Filters/components/FiltersBar/FiltersBar.tsx @@ -1,6 +1,7 @@ import type {PropsWithChildren, ReactNode} from 'react'; import React, {useState, useRef, useEffect} from 'react'; import {PlusIcon} from '@shopify/polaris-icons'; +import {Transition} from 'react-transition-group'; import type {TransitionStatus} from 'react-transition-group'; import {useI18n} from '../../../../utilities/i18n'; @@ -179,13 +180,7 @@ export function FiltersBar({ ); - const handleClearAllFilters = () => { - setLocalPinnedFilters(pinnedFromPropsKeys); - onClearAll?.(); - }; - const shouldShowAddButton = - filters.some((filter) => !filter.pinned) || - filters.length !== localPinnedFilters.length; + const shouldShowAddButton = filters.length !== localPinnedFilters?.length; const pinnedFiltersMarkup = ( ) : null; - const clearAllMarkup = appliedFilters?.length ? ( -
- -
- ) : null; - const filterMarkup = (
{pinnedFiltersMarkup} -
- {addButton} - {clearAllMarkup} -
+
{addButton}
); return ( diff --git a/polaris-react/src/components/Filters/components/SearchField/SearchField.tsx b/polaris-react/src/components/Filters/components/SearchField/SearchField.tsx index 5469662544f..3a5ad2479a2 100644 --- a/polaris-react/src/components/Filters/components/SearchField/SearchField.tsx +++ b/polaris-react/src/components/Filters/components/SearchField/SearchField.tsx @@ -60,7 +60,7 @@ export function SearchField({ } return ( - + { - return primaryAction + return primaryAction && !primaryAction.disabled ? { ...primaryAction, onAction: onExecutedPrimaryAction, @@ -167,7 +167,7 @@ export function IndexFilters({ }, [onExecutedPrimaryAction, primaryAction]); const enhancedCancelAction = useMemo(() => { - return cancelAction + return cancelAction && !cancelAction.disabled ? { ...cancelAction, onAction: onExecutedCancelAction, @@ -186,12 +186,14 @@ export function IndexFilters({ const updateButtonsMarkup = useMemo( () => enhancedCancelAction || enhancedPrimaryAction ? ( - +
+ +
) : null, [enhancedPrimaryAction, enhancedCancelAction, disabled, viewNames], ); @@ -336,7 +338,7 @@ export function IndexFilters({ loading={loading || isActionLoading} closeOnChildOverlayClick={closeOnChildOverlayClick} > -
{updateButtonsMarkup}
+ {updateButtonsMarkup} diff --git a/polaris-react/src/components/IndexFilters/components/SearchField/SearchField.tsx b/polaris-react/src/components/IndexFilters/components/SearchField/SearchField.tsx index 0c79a97635e..63e23ea65a3 100644 --- a/polaris-react/src/components/IndexFilters/components/SearchField/SearchField.tsx +++ b/polaris-react/src/components/IndexFilters/components/SearchField/SearchField.tsx @@ -60,7 +60,7 @@ export function SearchField({ } return ( - +