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: Create weather widget #1079

Merged
merged 73 commits into from
Sep 1, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
73 commits
Select commit Hold shift + click to select a range
091a0db
Add baseline component
jcbcapps Jul 28, 2023
c5e6aab
Add resolvers and mutations for managing weather widget
abbyoung Jul 31, 2023
10e7aa6
Add component boilerplate
jcbcapps Jul 31, 2023
ad55be0
fix copy pasta
abbyoung Jul 31, 2023
1df88d5
actually use the editWeatherWidget from mySpaceContext
abbyoung Jul 31, 2023
62f5c37
Merge
jcbcapps Jul 31, 2023
9a2aa61
Remove unnecessary lines
jcbcapps Jul 31, 2023
de073b1
Remove unused imports and add type
jcbcapps Jul 31, 2023
db054b5
Update types
jcbcapps Jul 31, 2023
85a8ddc
Add weather widget option to AddWidget
jcbcapps Aug 1, 2023
d564d01
Change to DraggableWidget
jcbcapps Aug 1, 2023
28dede1
Remove prop for AddWidget in favor of using myspaceContext
jcbcapps Aug 2, 2023
2dae958
update edit to change zipcode and coords
abbyoung Aug 2, 2023
b281fe6
remove unused
abbyoung Aug 2, 2023
0a7dacd
refresh weather widget if coords updated
abbyoung Aug 2, 2023
762df4a
removing a comment
abbyoung Aug 2, 2023
c15b839
Add TemporaryWidget
jcbcapps Aug 3, 2023
faf90ba
Add WeatherWidget as an option in TemporaryWidget
jcbcapps Aug 4, 2023
ff0b1f7
Merge latest api updates
jcbcapps Aug 4, 2023
e126bb5
Pass user-provided zip to mutation and create weather widget in db
jcbcapps Aug 4, 2023
88559b9
Clean up and display appropriate weather info
jcbcapps Aug 7, 2023
802413e
Move temporaryWidget state
jcbcapps Aug 7, 2023
d255c5f
Focus input on add/edit and disable drag-and-drop
jcbcapps Aug 8, 2023
3702512
Add initial icons
jcbcapps Aug 9, 2023
0483b1d
Add WeatherWidgetIcon component
jcbcapps Aug 10, 2023
f09f3b3
Pin version
jcbcapps Aug 10, 2023
8f1ce10
Add WeatherWidget to drag-and-drop
jcbcapps Aug 11, 2023
0d341c6
Remove comment
jcbcapps Aug 11, 2023
128e0e3
Fix display bug and increase number of allowed weather widgets
jcbcapps Aug 11, 2023
e683cfc
Fix dnd bug and edit display bug
jcbcapps Aug 11, 2023
cb57fc7
Add validation to zip
jcbcapps Aug 11, 2023
46527a3
Close settings dropdown automatically when user clicks edit option
jcbcapps Aug 14, 2023
624fb93
Merge branch 'main' into sc-1444/create-weather-widget
jcbcapps Aug 14, 2023
d74a546
Do not display Add Widget component when isAddingWidget is true
jcbcapps Aug 14, 2023
057d1a5
Test adding weather widget
jcbcapps Aug 14, 2023
7f372ac
Update tests
jcbcapps Aug 14, 2023
d47412d
Merge branch 'sc-1444/create-weather-widget' of github.com:USSF-ORBIT…
jcbcapps Aug 14, 2023
1bb4d00
Add tests
jcbcapps Aug 14, 2023
beabf55
Add tests
jcbcapps Aug 15, 2023
1320b0f
Add test
jcbcapps Aug 15, 2023
d28649f
Update test
jcbcapps Aug 15, 2023
a615ba5
Remove duplicate test
jcbcapps Aug 15, 2023
baccce3
Add LD flag
jcbcapps Aug 15, 2023
70f8363
Style updates
jcbcapps Aug 16, 2023
880b92f
Fix padding
jcbcapps Aug 16, 2023
4ac2690
Add Weather widget with data
jcbcapps Aug 16, 2023
0d631a9
Update tests w/ mockFlags
jcbcapps Aug 16, 2023
ebee211
Merge branch 'main' into sc-1444/create-weather-widget
jcbcapps Aug 16, 2023
673474c
Remove duplicates
jcbcapps Aug 16, 2023
efcf31b
adds fill properties and css variable for weather icon colors
shkeating Aug 16, 2023
e9c6fa9
Add font-family
jcbcapps Aug 16, 2023
c3dc4db
adds font family for short forecast paragraph bc the suggestion i lef…
shkeating Aug 16, 2023
30e8448
removed font assignment i had suggested in the wrong spot
shkeating Aug 16, 2023
40d3447
adjusts scaling and spacing of forecast elements to make things a lit…
shkeating Aug 16, 2023
2aa3b86
Remove key press func and add pattern
jcbcapps Aug 17, 2023
6d6f671
Validate onBlur
jcbcapps Aug 17, 2023
e17080c
Clear error and zip on cancel
jcbcapps Aug 17, 2023
4c2b244
Update heading elements
jcbcapps Aug 17, 2023
a627cd4
Remove onBlur and display city/state
jcbcapps Aug 17, 2023
e09e27e
Update tests
jcbcapps Aug 17, 2023
0a4d4be
Merge branch 'main' into sc-1444/create-weather-widget
jcbcapps Aug 24, 2023
98a6095
Add error state
jcbcapps Aug 25, 2023
076ccb2
Update number of allowed weather widgets
jcbcapps Aug 25, 2023
72974ba
Merge branch 'main' into sc-1444/create-weather-widget
jcbcapps Aug 25, 2023
31b668a
Add ld flag
jcbcapps Aug 25, 2023
a6b17f7
Add error state to storybook
jcbcapps Aug 25, 2023
54684ea
Remove error message on retry
jcbcapps Aug 28, 2023
dc532b6
Add setIsAddingWidget call back after accidentally removing
jcbcapps Aug 28, 2023
59eefab
Merge branch 'main' into sc-1444/create-weather-widget
gidjin Aug 29, 2023
2cb5900
Merge branch 'main' into sc-1444/create-weather-widget
jcbcapps Aug 30, 2023
e0e7e7d
Merge branch 'main' into sc-1444/create-weather-widget
shkeating Aug 31, 2023
b43ff0e
add mock function to generate hourly forcast
gidjin Sep 1, 2023
150a5e0
add all the weather states
gidjin Sep 1, 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
76 changes: 76 additions & 0 deletions src/__fixtures__/data/hourlyForecast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4251,3 +4251,79 @@ export const mockHourlyForecast = {
],
},
}

export const mockHourlyForecastFunc = (
shortForcast: string,
temperature: number,
isDaytime: boolean,
windSpeed: number
) => {
const ids = [0, 1, 2, 3, 4]
const periods = ids.map((id) => {
return {
number: id,
name: '',
startTime: `2023-08-16T1${id}:00:00-05:00`,
endTime: `2023-08-16T1${id + 1}:00:00-05:00`,
isDaytime: isDaytime,
temperature: temperature + id,
temperatureUnit: 'F',
temperatureTrend: null,
probabilityOfPrecipitation: {
unitCode: 'wmoUnit:percent',
value: 0,
},
dewpoint: {
unitCode: 'wmoUnit:degC',
value: 15.555555555555555,
},
relativeHumidity: {
unitCode: 'wmoUnit:percent',
value: 61,
},
windSpeed: windSpeed,
windDirection: 'S',
icon: 'https://api.weather.gov/icons/land/day/skc,0?size=small',
shortForecast: shortForcast,
detailedForecast: '',
}
})
return {
'@context': [
'https://geojson.org/geojson-ld/geojson-context.jsonld',
{
'@version': '1.1',
wx: 'https://api.weather.gov/ontology#',
geo: 'http://www.opengis.net/ont/geosparql#',
unit: 'http://codes.wmo.int/common/unit/',
'@vocab': 'https://api.weather.gov/ontology#',
},
],
type: 'Feature',
geometry: {
type: 'Polygon',
coordinates: [
[
[-97.1089731, 39.766826299999998],
[-97.108526900000001, 39.744778799999999],
[-97.079846700000004, 39.745119500000001],
[-97.08028680000001, 39.767167000000001],
[-97.1089731, 39.766826299999998],
],
],
},
properties: {
updated: '2023-08-16T15:25:50+00:00',
units: 'us',
forecastGenerator: 'HourlyForecastGenerator',
generatedAt: '2023-08-16T15:44:41+00:00',
updateTime: '2023-08-16T15:25:50+00:00',
validTimes: '2023-08-16T09:00:00+00:00/P7DT16H',
elevation: {
unitCode: 'wmoUnit:m',
value: 441.95999999999998,
},
periods: periods,
},
}
}
30 changes: 15 additions & 15 deletions src/components/AddWidget/AddWidget.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ const mockMySpaceContext: MySpaceContextType = {
setDisableDragAndDrop: () => {
return
},
isAddingWidget: false,
setIsAddingWidget: () => {
return
},
initializeMySpace: () => {
return
},
Expand All @@ -34,6 +38,7 @@ const mockMySpaceContext: MySpaceContextType = {
},
canAddCollections: true,
canAddNews: true,
canAddWeather: true,
canAddGuardianIdeal: true,
canAddFeaturedShortcuts: true,
addNewsWidget: () => {
Expand All @@ -48,15 +53,19 @@ const mockMySpaceContext: MySpaceContextType = {
addNewCollection: () => {
return
},
handleOnDragEnd: () => {
return
},
addNewWeatherWidget: () => {
return
},
editWeatherWidget: () => {
return
},
handleOnDragEnd: () => {
return
},
temporaryWidget: '',
setTemporaryWidget: () => {
return
},
}

const MockContextProvider = ({
Expand All @@ -83,10 +92,7 @@ export default {
} as Meta

export const DefaultAddWidget = (argTypes: StorybookArgTypes) => (
<AddWidget
handleSelectCollection={argTypes.handleSelectCollection}
handleCreateCollection={argTypes.handleCreateCollection}
/>
<AddWidget handleSelectCollection={argTypes.handleSelectCollection} />
)

export const AddCollectionDisabled = (argTypes: StorybookArgTypes) => (
Expand All @@ -95,10 +101,7 @@ export const AddCollectionDisabled = (argTypes: StorybookArgTypes) => (
...mockMySpaceContext,
canAddCollections: false,
}}>
<AddWidget
handleSelectCollection={argTypes.handleSelectCollection}
handleCreateCollection={argTypes.handleCreateCollection}
/>
<AddWidget handleSelectCollection={argTypes.handleSelectCollection} />
</MockContextProvider>
)

Expand All @@ -108,9 +111,6 @@ export const NewsWidgetDisabled = (argTypes: StorybookArgTypes) => (
...mockMySpaceContext,
canAddNews: false,
}}>
<AddWidget
handleSelectCollection={argTypes.handleSelectCollection}
handleCreateCollection={argTypes.handleCreateCollection}
/>
<AddWidget handleSelectCollection={argTypes.handleSelectCollection} />
</MockContextProvider>
)
101 changes: 79 additions & 22 deletions src/components/AddWidget/AddWidget.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,6 @@ import AddWidget from './AddWidget'
describe('AddWidget component', () => {
const testProps = {
handleSelectCollection: jest.fn(),
handleCreateCollection: jest.fn(),
handleAddNews: jest.fn(),
handleAddGuardianIdeal: jest.fn(),
handleAddFeaturedShortcuts: jest.fn(),
}

test('renders an add widget menu', () => {
Expand Down Expand Up @@ -53,7 +49,7 @@ describe('AddWidget component', () => {
).not.toBeInTheDocument()
})

test('handles the select collection button', async () => {
test('Select collection button', async () => {
const user = userEvent.setup()
const mockHandleSelect = jest.fn()

Expand Down Expand Up @@ -81,13 +77,13 @@ describe('AddWidget component', () => {
).not.toBeInTheDocument()
})

test('handles the create collection button', async () => {
test('Create collection button', async () => {
const user = userEvent.setup()
const mockHandleCreate = jest.fn()

render(
<AddWidget {...testProps} handleCreateCollection={mockHandleCreate} />
)
renderWithMySpaceAndModalContext(<AddWidget {...testProps} />, {
addNewCollection: mockHandleCreate,
})

const menuButton = screen.getByRole('button', { name: 'Add widget' })
expect(menuButton).toBeInTheDocument()
Expand All @@ -107,18 +103,14 @@ describe('AddWidget component', () => {
).not.toBeInTheDocument()
})

test('the add collection buttons are disabled if the user cannot add collections', async () => {
test('Add collection buttons are disabled if the user cannot add collections', async () => {
const user = userEvent.setup()
const mockHandleCreate = jest.fn()
const mockHandleSelect = jest.fn()

renderWithMySpaceAndModalContext(
<AddWidget
{...testProps}
handleCreateCollection={mockHandleCreate}
handleSelectCollection={mockHandleSelect}
/>,
{ canAddCollections: false }
<AddWidget {...testProps} handleSelectCollection={mockHandleSelect} />,
{ canAddCollections: false, addNewCollection: mockHandleCreate }
)

const menuButton = screen.getByRole('button', { name: 'Add widget' })
Expand Down Expand Up @@ -146,7 +138,7 @@ describe('AddWidget component', () => {
expect(mockHandleCreate).not.toHaveBeenCalled()
})

test('handles the Add news widget button', async () => {
test('Add news widget button', async () => {
const user = userEvent.setup()
const mockAddNews = jest.fn()

Expand All @@ -170,7 +162,7 @@ describe('AddWidget component', () => {
).not.toBeInTheDocument()
})

test('the Add news widget button is disabled if the user cannot add News', async () => {
test('Add news widget button is disabled if the user cannot add News', async () => {
const user = userEvent.setup()
const mockAddNews = jest.fn()

Expand All @@ -195,7 +187,72 @@ describe('AddWidget component', () => {
expect(mockAddNews).not.toHaveBeenCalled()
})

test('handles Add Guardian Ideal widget button', async () => {
test('Add weather widget', async () => {
mockFlags({
weatherWidget: true,
})

const user = userEvent.setup()
const mockSetTemporaryWidget = jest.fn()
const mockIsAddingWidget = jest.fn()

renderWithMySpaceAndModalContext(<AddWidget {...testProps} />, {
setTemporaryWidget: mockSetTemporaryWidget,
setIsAddingWidget: mockIsAddingWidget,
})

const menuButton = screen.getByRole('button', { name: 'Add widget' })
expect(menuButton).toBeInTheDocument()

await user.click(menuButton)

expect(
screen.getByRole('button', { name: 'Add weather widget' })
).toBeInTheDocument()
await user.click(screen.getByRole('button', { name: 'Add weather widget' }))

expect(mockSetTemporaryWidget).toHaveBeenCalledWith('Weather')
expect(mockIsAddingWidget).toHaveBeenCalledWith(true)

expect(
screen.queryByRole('button', { name: 'Add weather widget' })
).not.toBeInTheDocument()
})

test('Add weather widget button is disabled if the user cannot add Weather', async () => {
mockFlags({
weatherWidget: true,
})

const user = userEvent.setup()
const mockSetTemporaryWidget = jest.fn()
const mockIsAddingWidget = jest.fn()

renderWithMySpaceAndModalContext(<AddWidget {...testProps} />, {
canAddWeather: false,
setTemporaryWidget: mockSetTemporaryWidget,
setIsAddingWidget: mockIsAddingWidget,
})

const menuButton = screen.getByRole('button', { name: 'Add widget' })
expect(menuButton).toBeInTheDocument()

await user.click(menuButton)

expect(
screen.getByRole('button', { name: 'Add weather widget' })
).toBeInTheDocument()
expect(
screen.getByRole('button', { name: 'Add weather widget' })
).toBeDisabled()

await user.click(screen.getByRole('button', { name: 'Add weather widget' }))

expect(mockSetTemporaryWidget).not.toHaveBeenCalled()
expect(mockIsAddingWidget).not.toHaveBeenCalled()
})

test('Add Guardian Ideal widget button', async () => {
const user = userEvent.setup()
const mockAddGuardianIdeal = jest.fn()

Expand Down Expand Up @@ -225,7 +282,7 @@ describe('AddWidget component', () => {
).not.toBeInTheDocument()
})

test('the Add Guardian Ideal widget button is disabled if the user cannot add it', async () => {
test('Add Guardian Ideal widget button is disabled if the user cannot add it', async () => {
const user = userEvent.setup()
const mockAddGuardianIdeal = jest.fn()

Expand All @@ -252,7 +309,7 @@ describe('AddWidget component', () => {
expect(mockAddGuardianIdeal).not.toHaveBeenCalled()
})

test('handles Add Featured Shortcuts widget button', async () => {
test('Add Featured Shortcuts widget button', async () => {
const user = userEvent.setup()
const mockAddFeaturedShortcuts = jest.fn()

Expand Down Expand Up @@ -282,7 +339,7 @@ describe('AddWidget component', () => {
).not.toBeInTheDocument()
})

test('the Add Featured Shortcuts widget button is disabled if the user cannot add it', async () => {
test('Add Featured Shortcuts widget button is disabled if the user cannot add it', async () => {
const user = userEvent.setup()
const mockAddFeaturedShortcuts = jest.fn()
mockFlags({
Expand Down
20 changes: 17 additions & 3 deletions src/components/AddWidget/AddWidget.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,8 @@ import { useCloseWhenClickedOutside } from 'hooks/useCloseWhenClickedOutside'

const AddWidget = ({
handleSelectCollection,
handleCreateCollection,
}: {
handleSelectCollection: () => void
handleCreateCollection: () => void
}) => {
const dropdownEl = useRef<HTMLDivElement>(null)
const [isDropdownOpen, setIsDropdownOpen] = useCloseWhenClickedOutside(
Expand All @@ -23,12 +21,16 @@ const AddWidget = ({

const {
canAddNews,
canAddWeather,
canAddCollections,
canAddGuardianIdeal,
canAddFeaturedShortcuts,
addNewCollection,
addNewsWidget,
addGuardianIdeal,
addFeaturedShortcuts,
setIsAddingWidget,
setTemporaryWidget,
} = useMySpaceContext()

const menuOnClick = () => {
Expand Down Expand Up @@ -64,7 +66,7 @@ const AddWidget = ({
type="button"
disabled={!canAddCollections}
onClick={() => {
handleCreateCollection()
addNewCollection()
setIsDropdownOpen(false)
}}>
Create new collection
Expand All @@ -87,6 +89,18 @@ const AddWidget = ({
}}>
Add news widget
</Button>
{flags?.weatherWidget && (
<Button
disabled={!canAddWeather}
type="button"
onClick={() => {
setTemporaryWidget('Weather')
setIsAddingWidget(true)
setIsDropdownOpen(false)
}}>
Add weather widget
</Button>
)}
{flags?.guardianIdealCarousel && (
<Button
disabled={!canAddGuardianIdeal}
Expand Down
Loading