@@ -113,7 +116,14 @@ function App() { )} /> - + {enableWidgets && ( + ( + + )} + /> + )} {admin && ( { }, ], }; - const regions = allRegionsUserHasPermissionTo(user); + const includeAdmin = true; + const regions = allRegionsUserHasPermissionTo(user, includeAdmin); expect(regions).toEqual(expect.arrayContaining([14, 3, 4])); }); diff --git a/frontend/src/components/RegionDropdown.css b/frontend/src/components/RegionDropdown.css new file mode 100644 index 0000000000..a920bd7b61 --- /dev/null +++ b/frontend/src/components/RegionDropdown.css @@ -0,0 +1,24 @@ +.smart-hub--region-dropdown { + background-color: #0166AB; + border: none; + border-radius: 5px; + color: #FFFFFF; + padding-left: 18px; + font-weight: 700; + font-size: 17px; + display:inline-block; + background-image: url(../images/triange_down.png); +} + +.smart-hub--region-dropdown option{ + background-color: white; + border: none; + border-radius: 5px; + padding: 0px; +} + +/* .arrow-down { + border-left:5px solid rgba(0,0,0,0); + border-right:5px solid rgba(0,0,0,0); + color: #FFFFFF; +} */ diff --git a/frontend/src/fetchers/Widgets.js b/frontend/src/fetchers/Widgets.js new file mode 100644 index 0000000000..9639982873 --- /dev/null +++ b/frontend/src/fetchers/Widgets.js @@ -0,0 +1,10 @@ +import join from 'url-join'; +import { get } from './index'; + +const fetchWidget = async (widgetId, region, query = '') => { + const queryStr = query ? `?${query}&` : '?&'; + const res = await get(join('/', 'api', 'widgets', `${widgetId}${queryStr}region.in[]=${region}`)); + return res.json(); +}; + +export default fetchWidget; diff --git a/frontend/src/images/check.svg b/frontend/src/images/check.svg new file mode 100644 index 0000000000..522695ef3d --- /dev/null +++ b/frontend/src/images/check.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/frontend/src/images/triange_down.png b/frontend/src/images/triange_down.png new file mode 100644 index 0000000000000000000000000000000000000000..241c6258eead275875f1c5557a492d8a94c26ed7 GIT binary patch literal 298 zcmeAS@N?(olHy`uVBq!ia0vp^qChOj!2~4tJ}I~kq;yJLBTAf$QWHxu^Yau!GILWI zLP}E=3@sFV6Dt*r42%pF3@ojTEv$@;6?6?u4Gfx{{%iv3V=wXab!C6bD#WWU$#;7v zGf;@Lz$3Dlfq`2Hgc&d0t@{HMWJ!1Qb!1@J*w6hZkrl{iD+%%o2GT%~w~T!vkjnRT zaSW-rm7E}PvqA7&(3(5X@)cAMob(Df-+El$EG2qzx7?1Ouk0@#Soxg6MO--M|DnhH zoh6@-s>|!!{A_SlDm<9kWX3G3AF_dQ`OP1_3JWCn3%X<;OJ(7lW!S3_X}n1=C993$ g@Uy#3DcN$su<#H&UGZyOUKYp+p00i_>zopr0G`-hDF6Tf literal 0 HcmV?d00001 diff --git a/frontend/src/pages/Landing/Filter.js b/frontend/src/pages/Landing/Filter.js index acadf1b65b..b943c27da2 100644 --- a/frontend/src/pages/Landing/Filter.js +++ b/frontend/src/pages/Landing/Filter.js @@ -14,6 +14,7 @@ import { DATE_FMT, QUERY_CONDITIONS, } from './constants'; +import { DECIMAL_BASE } from '../../Constants'; import './Filter.css'; const defaultFilter = () => ( @@ -186,7 +187,7 @@ Filter.defaultProps = { forMyAlerts: false, }; -export function filtersToQueryString(filters) { +export function filtersToQueryString(filters, region) { const filtersWithValues = filters.filter((f) => { if (f.condition === WITHIN) { const [startDate, endDate] = f.query.split('-'); @@ -198,6 +199,9 @@ export function filtersToQueryString(filters) { const con = QUERY_CONDITIONS[filter.condition]; return `${filter.topic}.${con}=${filter.query}`; }); + if (region && (parseInt(region, DECIMAL_BASE) !== -1)) { + queryFragments.push(`region.in[]=${parseInt(region, DECIMAL_BASE)}`); + } return queryFragments.join('&'); } diff --git a/frontend/src/pages/Landing/RegionalSelect.js b/frontend/src/pages/Landing/RegionalSelect.js new file mode 100644 index 0000000000..ce253d1d1e --- /dev/null +++ b/frontend/src/pages/Landing/RegionalSelect.js @@ -0,0 +1,152 @@ +/* eslint-disable react/forbid-prop-types */ +/* eslint-disable react/jsx-props-no-spreading */ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import Select, { components } from 'react-select'; +import { Button } from '@trussworks/react-uswds'; + +import 'uswds/dist/css/uswds.css'; +import '@trussworks/react-uswds/lib/index.css'; +import './index.css'; + +import triangleDown from '../../images/triange_down.png'; +import check from '../../images/check.svg'; + +const DropdownIndicator = (props) => ( + + + +); + +const Placeholder = (props) => ; + +export const getUserOptions = (regions) => regions.map((region) => ({ value: region, label: `Region ${region}` })); + +const styles = { + container: (provided, state) => { + // To match the focus indicator provided by uswds + const outline = state.isFocused ? '0.25rem solid #2491ff;' : ''; + return { + ...provided, + outline, + }; + }, + input: () => ({ display: 'none' }), + control: (provided) => ({ + ...provided, + borderColor: '#0166AB', + backgroundColor: '#0166AB', + borderRadius: '5px', + paddingLeft: '5px', + paddingTop: '4px', + paddingBottom: '4px', + whiteSpace: 'nowrap', + color: 'white', + width: '120px', + }), + indicatorSeparator: () => ({ display: 'none' }), + menu: (provided) => ({ + ...provided, + width: '200px', + }), + option: (provided, state) => ({ + ...provided, + color: state.isSelected ? '#0166AB' : 'black', + fontWeight: state.isSelected ? '700' : 'normal', + backgroundColor: state.isSelected ? '#F8F8F8' : '#FFFFFF', + padding: 11, + }), + singleValue: (provided) => { + const single = { color: '#FFFFFF', fontWeight: 600 }; + + return { + ...provided, ...single, + }; + }, + valueContainer: () => ({ padding: '10px 8px' }), +}; + +function RegionalSelect(props) { + const { + regions, onApply, + } = props; + + const [selectedItem, setSelectedItem] = useState(); + const [appliedItem, setAppliedItem] = useState(); + const [menuIsOpen, setMenuIsOpen] = useState(false); + + // const delayedCloseMenu = () => setTimeout(setMenuIsOpen(false), 1000); + + const CustomOption = (customOptionProps) => { + const { + data, innerRef, innerProps, isSelected, + } = customOptionProps; + return data.custom ? ( +
+ +
+ ) : ( + + {data.label} + {isSelected && ( + {data.label} + )} + + ); + }; + + CustomOption.propTypes = { + data: PropTypes.object.isRequired, + innerRef: PropTypes.string.isRequired, + innerProps: PropTypes.object.isRequired, + }; + + const options = [...getUserOptions(regions), { custom: true }]; + return ( +