forked from HHS/Head-Start-TTADP
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* First pass at a pattern for widgets * Set coverage limits to 0 so we deploy to staging These limits will be increased back to what they are on main before merging. * Reset coverage limits * TTA Overview widget initial commit * Add backend tests * Deploy to sandbox * Fix lint error * Fix frontend lint errors * Merge main and fix invalid region * Refactor test * Add frontend tests * Add frontend tests * Styling improvements * Add region number in caption * Update mocks in landing tests * Adjusted sizing, flickering * Add temp border to overview widget Co-authored-by: Josh Salisbury <[email protected]>
- Loading branch information
1 parent
0e4fa94
commit 6b48a0f
Showing
38 changed files
with
1,242 additions
and
118 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; | ||
} */ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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; |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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) => ( | ||
<components.DropdownIndicator {...props}> | ||
<img alt="" style={{ width: '22px' }} src={triangleDown} /> | ||
</components.DropdownIndicator> | ||
); | ||
|
||
const Placeholder = (props) => <components.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 ? ( | ||
<div ref={innerRef} {...innerProps}> | ||
<Button | ||
type="button" | ||
className="float-left margin-2 smart-hub--filter-button" | ||
onClick={() => { | ||
onApply(selectedItem); | ||
setAppliedItem(selectedItem); | ||
setMenuIsOpen(false); | ||
}} | ||
> | ||
Apply | ||
</Button> | ||
</div> | ||
) : ( | ||
<components.Option {...customOptionProps}> | ||
{data.label} | ||
{isSelected && ( | ||
<img | ||
className="tta-smarthub--check" | ||
src={check} | ||
style={{ | ||
width: 32, | ||
float: 'right', | ||
marginTop: '-9px ', | ||
}} | ||
alt={data.label} | ||
/> | ||
)} | ||
</components.Option> | ||
); | ||
}; | ||
|
||
CustomOption.propTypes = { | ||
data: PropTypes.object.isRequired, | ||
innerRef: PropTypes.string.isRequired, | ||
innerProps: PropTypes.object.isRequired, | ||
}; | ||
|
||
const options = [...getUserOptions(regions), { custom: true }]; | ||
return ( | ||
<Select | ||
options={options} | ||
menuIsOpen={menuIsOpen} | ||
onChange={(value) => { if (value && value.value) setSelectedItem(value); }} | ||
onMenuOpen={() => setMenuIsOpen(true)} | ||
onBlur={() => setMenuIsOpen(false)} | ||
// onBlur={() => delayedCloseMenu()} | ||
name="RegionalSelect" | ||
defaultValue={options[0]} | ||
value={{ | ||
value: selectedItem ? selectedItem.value : options[0].value, | ||
label: appliedItem ? appliedItem.label : options[0].label, | ||
}} | ||
styles={styles} | ||
components={{ Placeholder, DropdownIndicator, Option: CustomOption }} | ||
placeholder="Select Region" | ||
closeMenuOnSelect={false} | ||
maxMenuHeight={600} | ||
/> | ||
); | ||
} | ||
|
||
RegionalSelect.propTypes = { | ||
regions: PropTypes.arrayOf(PropTypes.number).isRequired, | ||
onApply: PropTypes.func.isRequired, | ||
}; | ||
|
||
export default RegionalSelect; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
import '@testing-library/jest-dom'; | ||
import React from 'react'; | ||
import { | ||
render, screen, fireEvent, | ||
} from '@testing-library/react'; | ||
import { Router } from 'react-router'; | ||
import { createMemoryHistory } from 'history'; | ||
|
||
import selectEvent from 'react-select-event'; | ||
import RegionalSelect from '../RegionalSelect'; | ||
|
||
const renderRegionalSelect = () => { | ||
const history = createMemoryHistory(); | ||
const onApplyRegion = jest.fn(); | ||
|
||
render( | ||
<Router history={history}> | ||
<RegionalSelect | ||
regions={[1, 2]} | ||
onApply={onApplyRegion} | ||
/> | ||
</Router>, | ||
); | ||
return history; | ||
}; | ||
|
||
describe('Regional Select', () => { | ||
test('displays correct region in input', async () => { | ||
renderRegionalSelect(); | ||
const input = await screen.findByText(/region 1/i); | ||
expect(input).toBeVisible(); | ||
}); | ||
|
||
test('changes input value on apply', async () => { | ||
renderRegionalSelect(); | ||
let input = await screen.findByText(/region 1/i); | ||
expect(input).toBeVisible(); | ||
await selectEvent.select(screen.getByText(/region 1/i), [/region 2/i]); | ||
const applyButton = await screen.findByText(/apply/i); | ||
fireEvent.click(applyButton); | ||
input = await screen.findByText(/region 2/i); | ||
expect(input).toBeVisible(); | ||
}); | ||
}); |
Oops, something went wrong.