diff --git a/.vscode/launch.json b/.vscode/launch.json index 824eaa6a..8258179a 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,32 +9,57 @@ "type": "node", "request": "attach", "port": 9229, + "presentation": { + "hidden": false, + "group": "", + "order": 0 + } }, { - "name": "Next: Attach Chrome", - "type": "pwa-chrome", - "request": "attach", + "name": "Next: Launch Edge", + "type": "pwa-msedge", + "request": "launch", "port": 9222, - "url": "${config:develop.attachurl}", - "webRoot": "${workspaceFolder}" - } + "url": "${config:develop.attachurl}", // Custom vscode config property. does not actually exist, but configurable via user config. + "webRoot": "${workspaceFolder}", + "presentation": { + "hidden": false, + "group": "", + "order": 0 + } + }, { - "name": "Next: Attach Edge", - "type": "pwa-msedge", - "request": "attach", + "name": "Next: Launch Chrome", + "type": "pwa-chrome", + "request": "launch", "port": 9222, - "url": "${config:develop.attachurl}", - "webRoot": "${workspaceFolder}" + "url": "${config:develop.attachurl}", // Custom vscode config property. does not actually exist, but configurable via user config. + "webRoot": "${workspaceFolder}", + "presentation": { + "hidden": false, + "group": "", + "order": 0 + } } ], "compounds": [ { - "name": "Next: Attach All", - "configurations": ["Next: Attach Server", "Next: Attach Chrome"] + "name": "Next: Attach & Launch Edge", + "configurations": ["Next: Attach Server", "Next: Launch Edge"], + "presentation": { + "hidden": false, + "group": "next", + "order": 0 + } }, { - "name": "Next: Attach All (Edge)", - "configurations": ["Next: Attach Server", "Next: Attach Edge"] + "name": "Next: Attach & Launch Chrome", + "configurations": ["Next: Attach Server", "Next: Launch Edge"], + "presentation": { + "hidden": false, + "group": "next", + "order": 1 + } } ] } diff --git a/.vscode/settings.json b/.vscode/settings.json index 9f11f470..35456f1c 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -61,5 +61,4 @@ "stylelint.packageManager": "yarn", "stylelint.reportNeedlessDisables": true, "cSpell.language": "en,en-US", - "develop.attachurl": "http://localhost:3000/" } diff --git a/CHANGELOG.md b/CHANGELOG.md index cb6c5e25..fe2e841f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,12 +18,16 @@ For detailed rules of this file, see [Changelog Rules](#changelog-rules) * Optimized image loading and accessibility for images site-wide. - [#328][] * Further optimized font loading. - [#328][] * Moved raw version information to an API route (`/api/version`), and reworked version page to draw information from that route. - [#328][] -* Other smaller changes to sreamline development. - [#328][] +* Moved all custom server functions into suitable replacements provided by our site framework. - [#329][] + * This move has let us drop our entire custom backend. +* Updated `` with an improved loading state animation. - [#330][] +* Other smaller changes to sreamline development. - [#328][], [#329][] ### 🐛 Fixed * Resolved form submitting issues that occured when password evaluation fails to load. - [#328][] * Fixed authorization page displaying an `Invalid Authorize Request` error when redirecting users after login. - [#328][] +* Fixed `Using Odyssey` switch not properly entering loading state while waiting on a response from the API. - [#330][] ### ⚙ Tasks * Update lint configs @@ -31,6 +35,8 @@ For detailed rules of this file, see [Changelog Rules](#changelog-rules) [#328]: https://github.com/fuelRats/fuelrats.com/pull/328 +[#329]: https://github.com/fuelRats/fuelrats.com/pull/329 +[#330]: https://github.com/fuelRats/fuelrats.com/pull/330 [Unreleased]: https://github.com/FuelRats/fuelrats.com/compare/v2.13.0...HEAD diff --git a/src/components/RatCard/RatCard.js b/src/components/RatCard/RatCard.js index 80b621eb..dd96d6bf 100644 --- a/src/components/RatCard/RatCard.js +++ b/src/components/RatCard/RatCard.js @@ -147,8 +147,8 @@ class RatCard extends React.Component { } } - _handleOdysseySwitch = async () => { - await this.props.updateRat({ + _handleOdysseySwitch = () => { + return this.props.updateRat({ id: this.props.rat.id, attributes: { odyssey: !this.props.rat.attributes.odyssey, @@ -224,10 +224,10 @@ class RatCard extends React.Component { rat.attributes.platform === 'pc' && (
+ onChange={this._handleOdysseySwitch} />
) } diff --git a/src/components/Switch/Switch.js b/src/components/Switch/Switch.js index d97827ed..7356a21c 100644 --- a/src/components/Switch/Switch.js +++ b/src/components/Switch/Switch.js @@ -2,6 +2,8 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome' import PropTypes from 'prop-types' import { useCallback, useState } from 'react' +import isPromise from '~/util/isPromise' + import styles from './Switch.module.scss' @@ -10,7 +12,6 @@ import styles from './Switch.module.scss' function Switch (props) { const { - async: isAsync, containerProps, className, disabled, @@ -23,19 +24,17 @@ function Switch (props) { const [loading, setLoading] = useState(false) const handleChange = useCallback(async (event) => { - if (!isAsync) { - onChange?.(event) - return + const result = onChange?.(event) + if (isPromise(result)) { + setLoading(true) + await result + setLoading(false) } - - setLoading(true) - await onChange?.(event) - setLoading(false) - }, [isAsync, onChange]) + }, [onChange]) let icon = 'times' if (loading) { - icon = 'circle' + icon = 'sync' } else if (props.checked) { icon = 'check' } @@ -71,7 +70,6 @@ function Switch (props) { } Switch.propTypes = { - async: PropTypes.bool, checked: PropTypes.bool, className: PropTypes.string, containerProps: PropTypes.object, diff --git a/src/components/Switch/Switch.module.scss b/src/components/Switch/Switch.module.scss index 20b3221a..a315ec4a 100644 --- a/src/components/Switch/Switch.module.scss +++ b/src/components/Switch/Switch.module.scss @@ -1,5 +1,15 @@ @import '../../scss/colors'; +@keyframes loader-spin { + 0% { + transform: rotate(0deg); + } + + 100% { + transform: rotate(360deg); + } +} + .switch { display: inline-block; position: relative; @@ -23,6 +33,11 @@ background: $grey; transform: translateX(50%); + + > path { + animation: loader-spin 2s infinite linear; + transform-origin: center; + } } } diff --git a/src/util/isPromise.js b/src/util/isPromise.js new file mode 100644 index 00000000..2e84334a --- /dev/null +++ b/src/util/isPromise.js @@ -0,0 +1,9 @@ +/** + * Accepts an object and tests some basic patterns of promises + * @param {any} obj + * @returns {boolean} + */ +export default function isPromise (obj) { + return (typeof obj === 'object' || typeof obj === 'function') + && typeof obj.then === 'function' +}