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

Filter toast alerts #745

Merged
merged 30 commits into from
Apr 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
f97e3b9
add react-select package
austensen Apr 5, 2023
5665f10
add react-relect (wip)
austensen Apr 6, 2023
623bb31
add back placeholder styles
austensen Apr 6, 2023
819cef2
separated selected values working
austensen Apr 6, 2023
62a5ae5
add more/less selections
austensen Apr 7, 2023
d6f2549
custom close icon for selected values
austensen Apr 7, 2023
01c44c4
replace old multiselect, new functional, styled for desktop
austensen Apr 7, 2023
e5ad5f2
fix multiselect error placement and input border
austensen Apr 7, 2023
d864725
fix info-alert styles
austensen Apr 7, 2023
f6ce0fa
multiselect mobile styles, start refactoring filter styles
austensen Apr 8, 2023
3608053
separate out MinMaxSelect component
austensen Apr 8, 2023
e160550
separate out MinMaxSelect styles
austensen Apr 8, 2023
909a533
fix up alert styles for no-close, align apply buttons
austensen Apr 8, 2023
c59cf10
finish styles refactor, fix multiselect apply move
austensen Apr 8, 2023
05cee1a
fix primary button letter spacing (from #738)
austensen Apr 8, 2023
ff20821
Merge 'filters' into multiselect-screen-reader
austensen Apr 8, 2023
b4a563f
reduce font weight for table body (except firefox)
austensen Apr 9, 2023
04c10c2
remove old styles mistakenly adding in 'filters' merge
austensen Apr 9, 2023
0176fdb
fix min-max label font styles & "to" -> "and"
austensen Apr 9, 2023
752f464
delete old multiselect styles file
austensen Apr 9, 2023
5afdd2c
"Zip Code" (fix capitalization)
austensen Apr 9, 2023
57bf5ca
adjust down firefox font-weight in minmax- & multi-select components
austensen Apr 9, 2023
623503d
fix multiselect filename
austensen Apr 9, 2023
cfc797f
adjust desktop filter dropdowns for scrollbars on windows
austensen Apr 10, 2023
6715daa
add aria labels for multiselect buttons & description on input
austensen Apr 10, 2023
ee37552
change placement of filter result alerts (formerly "toasts")
austensen Apr 10, 2023
bd05d3a
only render filter alert row if there are alerts to show
austensen Apr 10, 2023
8a9ca00
align alert text left, drop unused import
austensen Apr 10, 2023
8b9db7d
Merge branch 'filters' into filter-toast-alerts
austensen Apr 11, 2023
99c1eaa
Merge branch 'filters' into filter-toast-alerts
austensen Apr 12, 2023
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
120 changes: 50 additions & 70 deletions client/src/components/PortfolioFilters.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -282,100 +282,80 @@ const FiltersWrapper = (props: {
const numActiveFilters = Object.values(activeFilters).filter(Boolean).length;
const [isOpen, setIsOpen] = React.useState(false);

return (
<>
{!isMobile ? (
<div className="filters">{children}</div>
) : (
<FocusTrap
active={isOpen}
focusTrapOptions={{
clickOutsideDeactivates: true,
returnFocusOnDeactivate: false,
onDeactivate: () => setIsOpen(false),
}}
return !isMobile ? (
<div className="filters">{children}</div>
) : (
<FocusTrap
active={isOpen}
focusTrapOptions={{
clickOutsideDeactivates: true,
returnFocusOnDeactivate: false,
onDeactivate: () => setIsOpen(false),
}}
>
<div className="filters">
<details
className={classnames("filter filter-accordion filters-mobile-wrapper", {
active: numActiveFilters > 0,
})}
open={isOpen}
>
<div className="filters">
<details
className={classnames("filter filter-accordion filters-mobile-wrapper", {
active: numActiveFilters > 0,
})}
open={isOpen}
>
<summary
onClick={(e) => {
e.preventDefault();
setIsOpen(!isOpen);
}}
>
<Trans>Filters</Trans>
{!isOpen && !!numActiveFilters && (
<span className="active-filter-count">{numActiveFilters}</span>
)}
{isOpen ? (
<CloseIcon className="closeIcon" />
) : (
<ChevronIcon className="chevronIcon" />
)}
</summary>
<div className="dropdown-container scroll-gradient mobile-wrapper-dropdown">
{children}
{numActiveFilters > 0 && (
<button onClick={() => setIsOpen(!isOpen)} className="button is-primary">
<Trans>View Results</Trans>
{resultsCount != null && (
<span className="view-results-count">{resultsCount}</span>
)}
</button>
)}
{resultsCount === 0 ? ZeroResultsAlert : <></>}
</div>
</details>
<summary
onClick={(e) => {
e.preventDefault();
setIsOpen(!isOpen);
}}
>
<Trans>Filters</Trans>
{!isOpen && !!numActiveFilters && (
<span className="active-filter-count">{numActiveFilters}</span>
)}
{isOpen ? <CloseIcon className="closeIcon" /> : <ChevronIcon className="chevronIcon" />}
</summary>
<div className="dropdown-container scroll-gradient mobile-wrapper-dropdown">
{children}
{numActiveFilters > 0 && (
<button onClick={() => setIsOpen(!isOpen)} className="button is-primary">
<Trans>View Results</Trans>
{resultsCount != null && <span className="view-results-count">{resultsCount}</span>}
</button>
)}
{resultsCount === 0 ? ZeroResultsAlert : <></>}
</div>
</FocusTrap>
)}
<div className="filter-toast-container">
{activeFilters.rsunitslatestActive && (!isOpen || !isMobile) && resultsCount ? (
RsUnitsToastAlert
) : (
<></>
)}
{activeFilters.ownernamesActive && (!isOpen || !isMobile) && resultsCount ? (
OwnernamesToastAlert
) : (
<></>
)}
</details>
</div>
</>
</FocusTrap>
);
};

const OwnernamesToastAlert = (
export const OwnernamesResultAlert = (
<Alert
className="filter-toast-alert"
className="filter-result-alert"
type="info"
variant="secondary"
closeType="none"
closeType="session"
storageId="filter-ownernames-results-alert"
role="status"
>
<Trans>
Expand the the Owner/Manager column in Table view to see all contacts associated with that
Expand the Person/ Entity column in the Table to see all contacts associated with that
building.
</Trans>
</Alert>
);

const RsUnitsToastAlert = (
export const RsUnitsResultAlert = (
<Alert
className="filter-toast-alert"
className="filter-result-alert"
type="info"
variant="secondary"
closeType="none"
closeType="session"
storageId="filter-rsunits-results-alert"
role="status"
>
<Trans>
Rent stabilized units are self-reported in yearly tax statements by building owners. As a
result, many buildings with rent stabilized units may not be documented.
result, many buildings with rent stabilized units may appear to be deregulated.
</Trans>
</Alert>
);
Expand Down
21 changes: 21 additions & 0 deletions client/src/components/PortfolioTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { sortContactsByImportance } from "./DetailView";
import { ArrowIcon } from "./Icons";
import classnames from "classnames";
import { isLegacyPath } from "./WowzaToggle";
import { OwnernamesResultAlert, RsUnitsResultAlert } from "./PortfolioFilters";

const FIRST_COLUMN_WIDTH = 130;
export const MAX_TABLE_ROWS_PER_PAGE = 100;
Expand Down Expand Up @@ -75,6 +76,14 @@ export const PortfolioTable = React.memo((props: PortfolioTableProps) => {

const { filterContext, setFilterContext } = React.useContext(FilterContext);

const { filterSelections } = filterContext;
const activeFilters = {
rsunitslatestActive: filterSelections.rsunitslatest,
ownernamesActive: !!filterSelections.ownernames.length,
unitsresActive: filterSelections.unitsres !== MINMAX_DEFAULT,
zipActive: !!filterSelections.zip.length,
};

const lastColumnRef = React.useRef<HTMLDivElement>(null);
const isLastColumnVisible = Helpers.useOnScreen(lastColumnRef);
/**
Expand Down Expand Up @@ -559,6 +568,18 @@ export const PortfolioTable = React.memo((props: PortfolioTableProps) => {
))}
</thead>
<tbody>
{table.getRowModel().rows.length &&
(activeFilters.rsunitslatestActive || activeFilters.ownernamesActive) && (
<tr>
<td
className="filter-table-alert-container"
colSpan={table.getVisibleFlatColumns().length}
>
{activeFilters.rsunitslatestActive && RsUnitsResultAlert}
{activeFilters.ownernamesActive && OwnernamesResultAlert}
</td>
</tr>
)}
{table.getRowModel().rows.map((row, i) => {
return (
<Fragment key={row.id}>
Expand Down
Loading