Fix up CanvasDateInput and use it in MutationAuditLog
Refs FOO-625 flag=none The new InstUI DateInput is way less opinionated than the old one, so it takes a lot more handholding to make it function. Fortunately someone had written much of a Canvas driver for that component and it is only going to need a little tweaking. As a first test of this, I did the MutationAuditLog requester using this new component. Test plan: * Go to Admin Tools -> Logging -> GraphQL Mutation Activity * That form doesn't look exactly the same, but should have all the same functionality as it used to Change-Id: Ic61e91623562e7990f861ef44019ba92f5e87fd8 Reviewed-on: https://gerrit.instructure.com/c/canvas-lms/+/247425 Tested-by: Service Cloud Jenkins <svc.cloudjenkins@instructure.com> Reviewed-by: Ahmad Amireh <ahmad@instructure.com> QA-Review: Ahmad Amireh <ahmad@instructure.com> Product-Review: Charley Kline <ckline@instructure.com>
This commit is contained in:
parent
ebbd319d8a
commit
07a43d4024
|
@ -18,19 +18,26 @@
|
|||
import {ApolloProvider, Query, gql, createClient} from 'jsx/canvas-apollo'
|
||||
import React, {useState} from 'react'
|
||||
import I18n from 'i18n!mutationActivity'
|
||||
import tz from 'timezone'
|
||||
import {Button} from '@instructure/ui-buttons'
|
||||
import {DateInput, TextInput} from '@instructure/ui-forms'
|
||||
import {TextInput} from '@instructure/ui-text-input'
|
||||
import CanvasDateInput from 'jsx/shared/components/CanvasDateInput'
|
||||
import {Heading} from '@instructure/ui-elements'
|
||||
import {Table} from '@instructure/ui-table'
|
||||
import {Spinner} from '@instructure/ui-spinner'
|
||||
import {View} from '@instructure/ui-layout'
|
||||
import {Grid} from '@instructure/ui-grid'
|
||||
|
||||
function formatDate(date) {
|
||||
return tz.format(date, 'date.formats.medium_with_weekday')
|
||||
}
|
||||
|
||||
const AuditLogForm = ({onSubmit}) => {
|
||||
const [assetString, setAssetString] = useState('')
|
||||
const [startDate, setStartDate] = useState(null)
|
||||
const [endDate, setEndDate] = useState(null)
|
||||
const makeDateHandler = setter => (_e, isoDate, _raw, conversionFailed) => {
|
||||
if (!conversionFailed) setter(isoDate)
|
||||
const makeDateHandler = setter => value => {
|
||||
if (value) setter(value)
|
||||
}
|
||||
const formDisabled = assetString.length === 0
|
||||
|
||||
|
@ -52,29 +59,38 @@ const AuditLogForm = ({onSubmit}) => {
|
|||
}}
|
||||
required
|
||||
/>
|
||||
<br />
|
||||
|
||||
<DateInput
|
||||
label={I18n.t('Start Date')}
|
||||
previousLabel={I18n.t('Previous Month')}
|
||||
nextLabel={I18n.t('Next Month')}
|
||||
onDateChange={makeDateHandler(setStartDate)}
|
||||
dateValue={startDate}
|
||||
/>
|
||||
<br />
|
||||
<div style={{marginTop: '1.5em'}} />
|
||||
|
||||
<DateInput
|
||||
label={I18n.t('End Date')}
|
||||
previousLabel={I18n.t('Previous Month')}
|
||||
nextLabel={I18n.t('Next Month')}
|
||||
onDateChange={makeDateHandler(setEndDate)}
|
||||
dateValue={endDate}
|
||||
/>
|
||||
<br />
|
||||
|
||||
<Button variant="primary" type="submit" margin="small 0 0" disabled={formDisabled}>
|
||||
{I18n.t('Find')}
|
||||
</Button>
|
||||
<Grid>
|
||||
<Grid.Row>
|
||||
<Grid.Col>
|
||||
<CanvasDateInput
|
||||
renderLabel={I18n.t('Start Date')}
|
||||
onSelectedDateChange={makeDateHandler(setStartDate)}
|
||||
formatDate={formatDate}
|
||||
selectedDate={startDate}
|
||||
placement="top center"
|
||||
withRunningValue
|
||||
/>
|
||||
</Grid.Col>
|
||||
<Grid.Col>
|
||||
<CanvasDateInput
|
||||
renderLabel={I18n.t('End Date')}
|
||||
onSelectedDateChange={makeDateHandler(setEndDate)}
|
||||
formatDate={formatDate}
|
||||
selectedDate={endDate}
|
||||
placement="top center"
|
||||
withRunningValue
|
||||
/>
|
||||
</Grid.Col>
|
||||
<Grid.Col vAlign="middle">
|
||||
<Button variant="primary" type="submit" margin="small 0 0" disabled={formDisabled}>
|
||||
{I18n.t('Find')}
|
||||
</Button>
|
||||
</Grid.Col>
|
||||
</Grid.Row>
|
||||
</Grid>
|
||||
</form>
|
||||
</View>
|
||||
)
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
import I18n from 'i18n!app_shared_components_canvas_date_time'
|
||||
import React, {useRef, useState} from 'react'
|
||||
import {arrayOf, element, func, instanceOf, oneOfType, shape, string} from 'prop-types'
|
||||
import {arrayOf, bool, element, func, instanceOf, oneOfType, shape, string} from 'prop-types'
|
||||
import moment from 'moment-timezone'
|
||||
import tz from 'timezone'
|
||||
import {DateTime} from '@instructure/ui-i18n'
|
||||
|
@ -37,14 +37,18 @@ CanvasDateInput.propTypes = {
|
|||
timezone: string,
|
||||
formatDate: func.isRequired,
|
||||
onSelectedDateChange: func.isRequired,
|
||||
interaction: string
|
||||
interaction: string,
|
||||
placement: string,
|
||||
withRunningValue: bool
|
||||
}
|
||||
|
||||
CanvasDateInput.defaultProps = {
|
||||
timezone: ENV?.TIMEZONE || DateTime.browserTimeZone(),
|
||||
renderLabel: I18n.t('Choose a date'),
|
||||
messages: [],
|
||||
interaction: 'enabled'
|
||||
interaction: 'enabled',
|
||||
placement: 'bottom center',
|
||||
withRunningValue: false
|
||||
}
|
||||
|
||||
export default function CanvasDateInput({
|
||||
|
@ -54,7 +58,9 @@ export default function CanvasDateInput({
|
|||
timezone,
|
||||
formatDate,
|
||||
onSelectedDateChange,
|
||||
interaction
|
||||
interaction,
|
||||
placement,
|
||||
withRunningValue
|
||||
}) {
|
||||
const todayMoment = moment().tz(timezone)
|
||||
const selectedMoment = selectedDate && moment.tz(selectedDate, timezone)
|
||||
|
@ -62,7 +68,7 @@ export default function CanvasDateInput({
|
|||
const [inputValue, setInputValue] = useState('')
|
||||
const [isShowingCalendar, setIsShowingCalendar] = useState(false)
|
||||
const [renderedMoment, setRenderedMoment] = useState(selectedMoment || todayMoment)
|
||||
const [errorMessages, setErrorMessages] = useState([])
|
||||
const [internalMessages, setInternalMessages] = useState([])
|
||||
|
||||
const priorSelectedMoment = useRef(null)
|
||||
function isDifferentMoment(firstMoment, secondMoment) {
|
||||
|
@ -82,7 +88,7 @@ export default function CanvasDateInput({
|
|||
function syncInput(newMoment) {
|
||||
const newInputValue = newMoment ? formatDate(newMoment.toDate()) : ''
|
||||
setInputValue(newInputValue)
|
||||
setErrorMessages([])
|
||||
setInternalMessages([])
|
||||
setRenderedMoment(newMoment || todayMoment)
|
||||
}
|
||||
|
||||
|
@ -119,12 +125,13 @@ export default function CanvasDateInput({
|
|||
setInputValue(value)
|
||||
const newDate = tz.parse(value)
|
||||
if (newDate) {
|
||||
const msgs = withRunningValue ? [{type: 'success', text: formatDate(newDate)}] : []
|
||||
setRenderedMoment(moment.tz(newDate, timezone))
|
||||
setErrorMessages([])
|
||||
setInternalMessages(msgs)
|
||||
} else if (value === '') {
|
||||
setErrorMessages([])
|
||||
setInternalMessages([])
|
||||
} else {
|
||||
setErrorMessages([{type: 'error', text: I18n.t("That's not a date!")}])
|
||||
setInternalMessages([{type: 'error', text: I18n.t('Invalid Date')}])
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -207,7 +214,8 @@ export default function CanvasDateInput({
|
|||
value={inputValue}
|
||||
onChange={handleChange}
|
||||
isInline
|
||||
messages={messages.concat(errorMessages)}
|
||||
placement={placement}
|
||||
messages={messages.concat(internalMessages)}
|
||||
isShowingCalendar={isShowingCalendar}
|
||||
onBlur={handleBlur}
|
||||
onRequestShowCalendar={() => setIsShowingCalendar(true)}
|
||||
|
|
|
@ -226,34 +226,34 @@ describe('rendered month', () => {
|
|||
describe('error messages', () => {
|
||||
it('shows an error message if the input date is unparseable', () => {
|
||||
const {getByText} = renderAndDirtyInput('asdf')
|
||||
expect(getByText("That's not a date!")).toBeInTheDocument()
|
||||
expect(getByText('Invalid Date')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('clears error messages when the selectedDate changes', () => {
|
||||
const {props, rerender, queryByText} = renderAndDirtyInput('asdf')
|
||||
props.selectedDate = new Date()
|
||||
rerender(<CanvasDateInput {...props} />)
|
||||
expect(queryByText("That's not a date!")).toBeNull()
|
||||
expect(queryByText('Invalid Date')).toBeNull()
|
||||
})
|
||||
|
||||
it('clears error messages when a day is clicked', () => {
|
||||
const date = new Date()
|
||||
const {getByText, queryByText} = renderAndDirtyInput('asdf', {selectedDate: date})
|
||||
fireEvent.click(getByText('15'))
|
||||
expect(queryByText("That's not a date!")).toBeNull()
|
||||
expect(queryByText('Invalid Date')).toBeNull()
|
||||
})
|
||||
|
||||
it('clears error messages even when selectedDay is clicked', () => {
|
||||
const date = new Date()
|
||||
const {getByText, queryByText} = renderAndDirtyInput('asdf', {selectedDate: date})
|
||||
fireEvent.click(getByText('20'))
|
||||
expect(queryByText("That's not a date!")).toBeNull()
|
||||
expect(queryByText('Invalid Date')).toBeNull()
|
||||
})
|
||||
|
||||
it('clears error messages when the input changes to an empty string', () => {
|
||||
const {getInput, queryByText} = renderAndDirtyInput('asdf')
|
||||
fireEvent.change(getInput(), {target: {value: ''}})
|
||||
expect(queryByText("That's not a date!")).toBeNull()
|
||||
expect(queryByText('Invalid Date')).toBeNull()
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -264,6 +264,12 @@ describe('messages', () => {
|
|||
})
|
||||
expect(getByText('my what an interesting date')).toBeInTheDocument()
|
||||
})
|
||||
|
||||
it('shows a running result when requested', () => {
|
||||
const {getByText} = renderAndDirtyInput('sat', {withRunningValue: true})
|
||||
// The Saturday after our "current date" is 5/23/2020
|
||||
expect(getByText('2020-05-23T00:00:00.000Z')).toBeInTheDocument()
|
||||
})
|
||||
})
|
||||
|
||||
describe('locales', () => {
|
||||
|
|
Loading…
Reference in New Issue