Merge pull request #8074 from overleaf/ii-ts-strict-fixes-1

GitOrigin-RevId: b99c5c998de9cc36cffffaab5b318331b45e931d
This commit is contained in:
Alf Eaton 2022-05-26 10:39:07 +01:00 committed by Copybot
parent 16f3dc3abc
commit 5e08d5f505
11 changed files with 80 additions and 56 deletions

View file

@ -39,16 +39,18 @@ function AccountInfoSection() {
const { isLoading, isSuccess, isError, error, runAsync } = useAsync()
const [isFormValid, setIsFormValid] = useState(true)
const handleEmailChange = event => {
const handleEmailChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setEmail(event.target.value)
setIsFormValid(event.target.validity.valid)
}
const handleFirstNameChange = event => {
const handleFirstNameChange = (
event: React.ChangeEvent<HTMLInputElement>
) => {
setFirstName(event.target.value)
}
const handleLastNameChange = event => {
const handleLastNameChange = (event: React.ChangeEvent<HTMLInputElement>) => {
setLastName(event.target.value)
}
@ -56,7 +58,7 @@ function AccountInfoSection() {
!hasAffiliationsFeature && !isExternalAuthenticationSystemUsed
const canUpdateNames = shouldAllowEditingDetails
const handleSubmit = event => {
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
if (!isFormValid) {
return
@ -151,11 +153,15 @@ function ReadOrWriteFormGroup({
}: ReadOrWriteFormGroupProps) {
const [validationMessage, setValidationMessage] = useState('')
const handleInvalid = event => {
const handleInvalid = (
event: React.InvalidEvent<HTMLInputElement & FormControl>
) => {
event.preventDefault()
}
const handleChangeAndValidity = event => {
const handleChangeAndValidity = (
event: React.ChangeEvent<HTMLInputElement & FormControl>
) => {
handleChange(event)
setValidationMessage(event.target.validationMessage)
}

View file

@ -70,20 +70,20 @@ function Input({ onChange, handleAddNewEmail }: InputProps) {
(event: ChangeEvent<HTMLInputElement>) => {
const hint = event.target.value
setInputValue(hint)
const match = matchLocalAndDomain(hint)
if (!matchedDomain?.hostname.startsWith(match.domain)) {
const { local, domain } = matchLocalAndDomain(hint)
if (domain && !matchedDomain?.hostname.startsWith(domain)) {
setSuggestion(null)
}
if (!match.domain) {
if (!domain) {
return
}
if (domainCache.has(match.domain)) {
const cachedDomain = domainCache.get(match.domain)
setSuggestion(`${match.local}@${cachedDomain.hostname}`)
if (domainCache.has(domain)) {
const cachedDomain = domainCache.get(domain) as DomainInfo
setSuggestion(`${local}@${cachedDomain.hostname}`)
setMatchedDomain(cachedDomain)
return
}
const query = `?hostname=${match.domain}&limit=1`
const query = `?hostname=${domain}&limit=1`
getJSON<Nullable<DomainInfo[]>>(`/institutions/domains${query}`, {
signal,
})
@ -96,8 +96,8 @@ function Input({ onChange, handleAddNewEmail }: InputProps) {
}
const hostname = data[0]?.hostname
if (hostname) {
domainCache.set(match.domain, data[0])
setSuggestion(`${match.local}@${hostname}`)
domainCache.set(domain, data[0])
setSuggestion(`${local}@${hostname}`)
setMatchedDomain(data[0])
} else {
setSuggestion(null)
@ -142,7 +142,7 @@ function Input({ onChange, handleAddNewEmail }: InputProps) {
)
useEffect(() => {
if (suggestion && !suggestion.startsWith(inputValue)) {
if (suggestion && inputValue && !suggestion.startsWith(inputValue)) {
setSuggestion(null)
}
}, [suggestion, inputValue])

View file

@ -35,24 +35,20 @@ export function SSOAlert() {
const handleErrorClosed = () => setErrorClosed(true)
if (samlError) {
return (
!errorClosed && (
<Alert bsStyle="danger" className="mb-0" onDismiss={handleErrorClosed}>
<p className="text-center">
<Icon
type="exclamation-triangle"
accessibilityLabel={t('generic_something_went_wrong')}
/>{' '}
{samlError.translatedMessage
? samlError.translatedMessage
: samlError.message}
</p>
{samlError.tryAgain && (
<p className="text-center">{t('try_again')}</p>
)}
</Alert>
)
)
return !errorClosed ? (
<Alert bsStyle="danger" className="mb-0" onDismiss={handleErrorClosed}>
<p className="text-center">
<Icon
type="exclamation-triangle"
accessibilityLabel={t('generic_something_went_wrong')}
/>{' '}
{samlError.translatedMessage
? samlError.translatedMessage
: samlError.message}
</p>
{samlError.tryAgain && <p className="text-center">{t('try_again')}</p>}
</Alert>
) : null
}
if (!institutionLinked) {

View file

@ -24,11 +24,15 @@ function LeaveModalForm({
const [confirmation, setConfirmation] = useState(false)
const [error, setError] = useState<FetchError | null>(null)
const handleEmailChange = event => {
const handleEmailChange = (
event: React.ChangeEvent<HTMLFormElement & FormControl>
) => {
setEmail(event.target.value)
}
const handlePasswordChange = event => {
const handlePasswordChange = (
event: React.ChangeEvent<HTMLFormElement & FormControl>
) => {
setPassword(event.target.value)
}
@ -36,7 +40,7 @@ function LeaveModalForm({
setConfirmation(prev => !prev)
}
const handleSubmit = event => {
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
if (!isFormValid) {
return

View file

@ -13,12 +13,12 @@ function LinkingSection() {
const projectSyncSuccessMessage = getMeta(
'ol-projectSyncSuccessMessage'
) as string
const [integrationLinkingWidgets] = useState(
const [integrationLinkingWidgets] = useState<any[]>(
() =>
getMeta('integrationLinkingWidgets') ||
importOverleafModules('integrationLinkingWidgets')
)
const [referenceLinkingWidgets] = useState(
const [referenceLinkingWidgets] = useState<any[]>(
() =>
getMeta('referenceLinkingWidgets') ||
importOverleafModules('referenceLinkingWidgets')
@ -139,7 +139,7 @@ function SSOLinkingWidgetContainer({
const { t } = useTranslation()
const { unlink } = useSSOContext()
let description = null
let description = ''
switch (subscription.providerId) {
case 'collabratec':
description = t('linked_collabratec_description')

View file

@ -141,7 +141,9 @@ function UnlinkConfirmationModal({
}: UnlinkConfirmModalProps) {
const { t } = useTranslation()
const handleCancel = event => {
const handleCancel = (
event: React.MouseEvent<HTMLButtonElement & Button>
) => {
event.preventDefault()
handleHide()
}

View file

@ -8,7 +8,7 @@ import GoogleLogo from '../../../../shared/svgs/google-logo'
import OrcidLogo from '../../../../shared/svgs/orcid-logo'
import LinkingStatus from './status'
const providerLogos = {
const providerLogos: { readonly [p: string]: JSX.Element } = {
collabratec: <IEEELogo />,
google: <GoogleLogo />,
orcid: <OrcidLogo />,
@ -95,6 +95,7 @@ export function SSOLinkingWidget({
</div>
)
}
type ActionButtonProps = {
unlinkRequestInflight: boolean
accountIsLinked?: boolean

View file

@ -4,7 +4,7 @@ import Icon from '../../../../shared/components/icon'
type Status = 'pending' | 'success' | 'error'
type LinkingStatusProps = {
status?: Status
status: Status
description: string | ReactNode
}

View file

@ -72,16 +72,22 @@ function PasswordForm() {
const [isNewPasswordValid, setIsNewPasswordValid] = useState(false)
const [isFormValid, setIsFormValid] = useState(false)
const handleCurrentPasswordChange = event => {
const handleCurrentPasswordChange = (
event: React.ChangeEvent<HTMLInputElement>
) => {
setCurrentPassword(event.target.value)
}
const handleNewPassword1Change = event => {
const handleNewPassword1Change = (
event: React.ChangeEvent<HTMLInputElement>
) => {
setNewPassword1(event.target.value)
setIsNewPasswordValid(event.target.validity.valid)
}
const handleNewPassword2Change = event => {
const handleNewPassword2Change = (
event: React.ChangeEvent<HTMLInputElement>
) => {
setNewPassword2(event.target.value)
}
@ -91,7 +97,7 @@ function PasswordForm() {
)
}, [currentPassword, newPassword1, newPassword2, isNewPasswordValid])
const handleSubmit = event => {
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
if (!isFormValid) {
return
@ -157,7 +163,7 @@ type PasswordFormGroupProps = {
id: string
label: string
value: string
handleChange: (event: any) => void
handleChange: (event: React.ChangeEvent<HTMLInputElement>) => void
minLength?: number
validationMessage?: string
}
@ -173,11 +179,15 @@ function PasswordFormGroup({
const [validationMessage, setValidationMessage] = useState('')
const [hadInteraction, setHadInteraction] = useState(false)
const handleInvalid = event => {
const handleInvalid = (
event: React.InvalidEvent<HTMLInputElement & FormControl>
) => {
event.preventDefault()
}
const handleChangeAndValidity = event => {
const handleChangeAndValidity = (
event: React.ChangeEvent<HTMLInputElement & FormControl>
) => {
handleChange(event)
setHadInteraction(true)
setValidationMessage(event.target.validationMessage)

View file

@ -79,7 +79,9 @@ export class FetchError extends OError {
getUserFacingMessage() {
const statusCode = this.response?.status
const defaultMessage = getErrorMessageForStatusCode(statusCode)
const message = this.data?.message?.text || this.data?.message
const message = (this.data?.message?.text || this.data?.message) as
| string
| undefined
if (message && message !== defaultMessage) return message
const statusCodes: { readonly [K: number]: string } = {
@ -208,11 +210,14 @@ async function parseResponseBody(response: Response) {
return {}
}
export function getUserFacingMessage(error: Error): string {
export function getUserFacingMessage(error: Error | null) {
if (!error) {
return undefined
}
if (error instanceof FetchError) {
return error.getUserFacingMessage()
} else {
// checking existence of `error` to prevent errors when called from Javascript
return error?.message
}
return error.message
}

View file

@ -38,7 +38,7 @@ function usePersistedState<T>(
useEffect(() => {
if (listen) {
const listener = event => {
const listener = (event: StorageEvent) => {
if (event.key === key) {
// note: this value is read via getItem rather than from event.newValue
// because getItem handles deserializing the JSON that's stored in localStorage.