From 9e1a3464eb6ada2df22e85c96ffacc7c139f28d6 Mon Sep 17 00:00:00 2001 From: stz184 Date: Fri, 30 Oct 2020 15:24:35 +0200 Subject: [PATCH 01/10] AlbumsPages is migrated to a functional component --- ui/src/Pages/AllAlbumsPage/AlbumsPage.js | 37 +++++++++++------------- 1 file changed, 17 insertions(+), 20 deletions(-) diff --git a/ui/src/Pages/AllAlbumsPage/AlbumsPage.js b/ui/src/Pages/AllAlbumsPage/AlbumsPage.js index 249f5ab5..bdb8ade1 100644 --- a/ui/src/Pages/AllAlbumsPage/AlbumsPage.js +++ b/ui/src/Pages/AllAlbumsPage/AlbumsPage.js @@ -1,8 +1,7 @@ -import React, { Component } from 'react' +import React from 'react' import AlbumBoxes from '../../components/albumGallery/AlbumBoxes' import Layout from '../../Layout' -import { gql } from '@apollo/client' -import { Query } from '@apollo/client/react/components' +import { useQuery, gql } from '@apollo/client' const getAlbumsQuery = gql` query getMyAlbums { @@ -18,23 +17,21 @@ const getAlbumsQuery = gql` } ` -class AlbumsPage extends Component { - render() { - return ( - -

Albums

- - {({ loading, error, data }) => ( - - )} - -
- ) - } +const AlbumsPage = () => { + const { loading, error, data } = useQuery(getAlbumsQuery) + + return ( + +

Albums

+ {!loading && ( + + )} +
+ ) } export default AlbumsPage From f76c3e4e0dd1ddf979deac3edb42fee7d8a14df4 Mon Sep 17 00:00:00 2001 From: stz184 Date: Fri, 30 Oct 2020 15:54:09 +0200 Subject: [PATCH 02/10] AlbumPages is now using useQuery hook instead of component --- ui/src/Pages/AlbumPage/AlbumPage.js | 68 ++++++++++++----------------- 1 file changed, 27 insertions(+), 41 deletions(-) diff --git a/ui/src/Pages/AlbumPage/AlbumPage.js b/ui/src/Pages/AlbumPage/AlbumPage.js index bcf8641d..ea4c08c9 100644 --- a/ui/src/Pages/AlbumPage/AlbumPage.js +++ b/ui/src/Pages/AlbumPage/AlbumPage.js @@ -1,8 +1,7 @@ import React, { useCallback, useState, useEffect } from 'react' import ReactRouterPropTypes from 'react-router-prop-types' import { useLocation } from 'react-router-dom' -import { gql } from '@apollo/client' -import { Query } from '@apollo/client/react/components' +import { useQuery, gql } from '@apollo/client' import AlbumGallery from '../../components/albumGallery/AlbumGallery' import PropTypes from 'prop-types' import Layout from '../../Layout' @@ -80,7 +79,7 @@ function AlbumPage({ match }) { ) const toggleFavorites = useCallback( - (onlyFavorites, refetch) => { + onlyFavorites => { if ( (refetchNeededAll && !onlyFavorites) || (refetchNeededFavorites && onlyFavorites) @@ -97,7 +96,7 @@ function AlbumPage({ match }) { setOnlyFavorites(onlyFavorites) } }, - [setOnlyFavorites] + [setOnlyFavorites, refetch] ) useEffect(() => { @@ -107,44 +106,31 @@ function AlbumPage({ match }) { history.replaceState({}, '', pathName + '?' + queryString) }, [onlyFavorites, ordering]) - return ( - - {({ loading, error, data, refetch }) => { - const setOnlyFavorites = useCallback( - checked => { - toggleFavorites(checked, refetch) - }, - [toggleFavorites, refetch] - ) + const { loading, error, data, refetch } = useQuery(albumQuery, { + variables: { + id: albumId, + onlyFavorites, + mediaOrderBy: ordering.orderBy, + mediaOrderDirection: ordering.orderDirection, + }, + }) - if (error) return
Error
- return ( - - - (refetchNeededAll = refetchNeededFavorites = true) - } - showFilter - setOrdering={setOrderingCallback} - ordering={ordering} - /> - - ) - }} -
+ if (error) return
Error
+ + return ( + + (refetchNeededAll = refetchNeededFavorites = true)} + showFilter + setOrdering={setOrderingCallback} + ordering={ordering} + /> + ) } From 4ccc50ec49aa1c76f7e9c6f68258b22793bbe39a Mon Sep 17 00:00:00 2001 From: stz184 Date: Sat, 31 Oct 2020 23:44:00 +0200 Subject: [PATCH 03/10] Fixed issue that caused error when no image state is available on history popstate --- ui/src/components/albumGallery/AlbumGallery.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ui/src/components/albumGallery/AlbumGallery.js b/ui/src/components/albumGallery/AlbumGallery.js index 4bed3351..dc61a92e 100644 --- a/ui/src/components/albumGallery/AlbumGallery.js +++ b/ui/src/components/albumGallery/AlbumGallery.js @@ -56,7 +56,9 @@ const AlbumGallery = ({ useEffect(() => { const updateImageState = event => { - setImageState(event.state.imageState) + if (event.state.imageState) { + setImageState(event.state.imageState) + } } window.addEventListener('popstate', updateImageState) From d03525d3157392408c3b26595c172b0f277a94a2 Mon Sep 17 00:00:00 2001 From: stz184 Date: Sat, 31 Oct 2020 23:50:08 +0200 Subject: [PATCH 04/10] AlbumSidebar, AuthorizedRoute, LoginPage are now using hooks instead of the deprecated Query component --- ui/src/Pages/LoginPage/LoginPage.js | 179 ++++++++++---------- ui/src/components/routes/AuthorizedRoute.js | 21 +-- ui/src/components/sidebar/AlbumSidebar.js | 27 ++- 3 files changed, 105 insertions(+), 122 deletions(-) diff --git a/ui/src/Pages/LoginPage/LoginPage.js b/ui/src/Pages/LoginPage/LoginPage.js index b6c3dffa..b7ba752e 100644 --- a/ui/src/Pages/LoginPage/LoginPage.js +++ b/ui/src/Pages/LoginPage/LoginPage.js @@ -1,6 +1,5 @@ -import React, { Component } from 'react' -import { gql } from '@apollo/client' -import { Mutation, Query } from '@apollo/client/react/components' +import React, { useState, useCallback } from 'react' +import { useQuery, gql, useMutation } from '@apollo/client' import { Redirect } from 'react-router-dom' import styled from 'styled-components' import { Button, Form, Message, Header } from 'semantic-ui-react' @@ -34,98 +33,92 @@ const LogoHeaderStyled = styled(LogoHeader)` margin-bottom: 72px !important; ` -class LoginPage extends Component { - constructor(props) { - super(props) - - this.state = { - username: '', - password: '', - } - } - - handleChange(event, key) { - this.setState({ [key]: event.target.value }) - } - - signIn(event, authorize) { - event.preventDefault() - - authorize({ - variables: { - username: this.state.username, - password: this.state.password, - }, - }) +const LoginPage = () => { + const [credentials, setCredentials] = useState({ + username: '', + password: '', + }) + + const handleChange = useCallback( + (event, key) => { + const value = event.target.value + setCredentials(credentials => { + return { + ...credentials, + [key]: value, + } + }) + }, + [setCredentials] + ) + + const signIn = useCallback( + (event, authorize) => { + event.preventDefault() + + authorize({ + variables: { + username: credentials.username, + password: credentials.password, + }, + }) + }, + [credentials] + ) + + const { initialSetupData } = useQuery(checkInitialSetupQuery) + + const [authorize, { loading, data }] = useMutation(authorizeMutation, { + onCompleted: data => { + const { success, token } = data.authorizeUser + + if (success) { + login(token) + } + }, + }) + + const errorMessage = + data && !data.authorizeUser.success ? data.authorizeUser.status : null + + if (authToken()) { + return } - render() { - if (authToken()) { - return - } - - return ( -
- - - - {({ data }) => { - if (data && data.siteInfo && data.siteInfo.initialSetup) { - return - } - - return null - }} - - { - const { success, token } = data.authorizeUser - - if (success) { - login(token) - } - }} - > - {(authorize, { loading, data }) => { - let errorMessage = null - if (data) { - if (!data.authorizeUser.success) - errorMessage = data.authorizeUser.status - } - - return ( -
this.signIn(e, authorize)} - loading={loading || (data && data.authorizeUser.success)} - > - - - this.handleChange(e, 'username')} - /> - - - - this.handleChange(e, 'password')} - /> - - - - - ) - }} -
-
-
- ) - } + return ( +
+ + + {initialSetupData?.siteInfo?.initialSetup && ( + + )} +
signIn(e, authorize)} + loading={loading || (data && data.authorizeUser.success)} + > + + + handleChange(e, 'username')} + /> + + + + handleChange(e, 'password')} + /> + + + + +
+
+ ) } export default LoginPage diff --git a/ui/src/components/routes/AuthorizedRoute.js b/ui/src/components/routes/AuthorizedRoute.js index 1eb55be2..15581f66 100644 --- a/ui/src/components/routes/AuthorizedRoute.js +++ b/ui/src/components/routes/AuthorizedRoute.js @@ -1,8 +1,7 @@ import React from 'react' import PropTypes from 'prop-types' import { Route, Redirect } from 'react-router-dom' -import { gql } from '@apollo/client' -import { Query } from '@apollo/client/react/components' +import { useQuery, gql } from '@apollo/client' import { authToken } from '../../authentication' export const ADMIN_QUERY = gql` @@ -29,19 +28,13 @@ const AuthorizedRoute = ({ component: Component, admin = false, ...props }) => { let adminRedirect = null if (token && admin) { - adminRedirect = ( - - {({ error, data }) => { - if (error) alert(error) + const { error, data } = useQuery(ADMIN_QUERY) - if (data && data.myUser && !data.myUser.admin) { - return - } + if (error) alert(error) - return null - }} - - ) + if (data && data.myUser && !data.myUser.admin) { + adminRedirect = + } } return ( @@ -54,7 +47,7 @@ const AuthorizedRoute = ({ component: Component, admin = false, ...props }) => { )} - > + /> ) } diff --git a/ui/src/components/sidebar/AlbumSidebar.js b/ui/src/components/sidebar/AlbumSidebar.js index 8ead9089..361445ae 100644 --- a/ui/src/components/sidebar/AlbumSidebar.js +++ b/ui/src/components/sidebar/AlbumSidebar.js @@ -1,7 +1,6 @@ import React from 'react' import PropTypes from 'prop-types' -import { Query } from '@apollo/client/react/components' -import { gql } from '@apollo/client' +import { useQuery, gql } from '@apollo/client' import SidebarShare from './Sharing' const albumQuery = gql` @@ -14,22 +13,20 @@ const albumQuery = gql` ` const AlbumSidebar = ({ albumId }) => { + const { loading, error, data } = useQuery(albumQuery, { + variables: { id: albumId }, + }) + + if (loading) return
Loading...
+ if (error) return
{error.message}
+ return (

Album options

- - {({ loading, error, data }) => { - if (loading) return
Loading...
- if (error) return
{error.message}
- - return ( -
-

{data.album.title}

- -
- ) - }} -
+
+

{data.album.title}

+ +
) } From dd6fc65b620cab8ca3420d689af39e9459931494 Mon Sep 17 00:00:00 2001 From: stz184 Date: Sat, 31 Oct 2020 23:52:05 +0200 Subject: [PATCH 05/10] Fixed issue that caused warnings on logout page --- ui/src/Layout.js | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/ui/src/Layout.js b/ui/src/Layout.js index 6a49b111..c5c6fd87 100644 --- a/ui/src/Layout.js +++ b/ui/src/Layout.js @@ -8,6 +8,7 @@ import { useQuery, gql } from '@apollo/client' import { Authorized } from './components/routes/AuthorizedRoute' import { Helmet } from 'react-helmet' import Header from './components/header/Header' +import { authToken } from './authentication' export const ADMIN_QUERY = gql` query adminQuery { @@ -94,13 +95,11 @@ const SideButtonLabel = styled.div` ` export const SideMenu = () => { - const adminQuery = useQuery(ADMIN_QUERY) - const mapboxQuery = useQuery(MAPBOX_QUERY) + const adminQuery = authToken() ? useQuery(ADMIN_QUERY) : null + const mapboxQuery = authToken() ? useQuery(MAPBOX_QUERY) : null - const isAdmin = - adminQuery.data && adminQuery.data.myUser && adminQuery.data.myUser.admin - - const mapboxEnabled = mapboxQuery.data && mapboxQuery.data.mapboxToken != null + const isAdmin = adminQuery?.data?.myUser?.admin + const mapboxEnabled = !!mapboxQuery?.data?.mapboxToken return ( From 432f8adff783ccad53ea13fe8b4d450b64598949 Mon Sep 17 00:00:00 2001 From: stz184 Date: Fri, 6 Nov 2020 09:53:04 +0200 Subject: [PATCH 06/10] Fixed Layout.test.js --- ui/src/Layout.test.js | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ui/src/Layout.test.js b/ui/src/Layout.test.js index dbf39032..4262974e 100644 --- a/ui/src/Layout.test.js +++ b/ui/src/Layout.test.js @@ -7,6 +7,10 @@ import { render, screen } from '@testing-library/react' import Layout, { ADMIN_QUERY, MAPBOX_QUERY, SideMenu } from './Layout' import { MemoryRouter } from 'react-router-dom' +import * as authentication from './authentication' + +jest.mock('./authentication.js') + test('Layout component', async () => { render( @@ -18,7 +22,13 @@ test('Layout component', async () => { expect(screen.getByText('layout_content')).toBeInTheDocument() }) +afterEach(() => { + authentication.authToken.mockClear() +}) + test('Layout sidebar component', async () => { + authentication.authToken.mockImplementation(() => true) + const mockedGraphql = [ { request: { From d5e21f6a5e6d2927278b8ab599472e2f9412a4d0 Mon Sep 17 00:00:00 2001 From: stz184 Date: Fri, 6 Nov 2020 09:56:27 +0200 Subject: [PATCH 07/10] Moved refetch declaration before its use --- ui/src/Pages/AlbumPage/AlbumPage.js | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/ui/src/Pages/AlbumPage/AlbumPage.js b/ui/src/Pages/AlbumPage/AlbumPage.js index ea4c08c9..9d69bf94 100644 --- a/ui/src/Pages/AlbumPage/AlbumPage.js +++ b/ui/src/Pages/AlbumPage/AlbumPage.js @@ -66,6 +66,15 @@ function AlbumPage({ match }) { orderDirection: urlParams.get('orderDirection') || 'ASC', }) + const { loading, error, data, refetch } = useQuery(albumQuery, { + variables: { + id: albumId, + onlyFavorites, + mediaOrderBy: ordering.orderBy, + mediaOrderDirection: ordering.orderDirection, + }, + }) + const setOrderingCallback = useCallback( ordering => { setOrdering(prevState => { @@ -106,15 +115,6 @@ function AlbumPage({ match }) { history.replaceState({}, '', pathName + '?' + queryString) }, [onlyFavorites, ordering]) - const { loading, error, data, refetch } = useQuery(albumQuery, { - variables: { - id: albumId, - onlyFavorites, - mediaOrderBy: ordering.orderBy, - mediaOrderDirection: ordering.orderDirection, - }, - }) - if (error) return
Error
return ( From a0f7b4b1353e34725a695e9ee90910329ce5228d Mon Sep 17 00:00:00 2001 From: stz184 Date: Sun, 15 Nov 2020 01:25:21 +0200 Subject: [PATCH 08/10] The following components are migrated to apollo hooks instead of deprecated and components: - AddUserRow.js - AlbumGallery.js - UserRow.js LazyPhoto is migrated to functional component --- ui/src/Pages/SettingsPage/AddUserRow.js | 124 +++--- ui/src/Pages/SettingsPage/UserRow.js | 391 +++++++++--------- .../components/albumGallery/AlbumGallery.js | 4 +- .../components/photoGallery/MediaThumbnail.js | 15 +- 4 files changed, 259 insertions(+), 275 deletions(-) diff --git a/ui/src/Pages/SettingsPage/AddUserRow.js b/ui/src/Pages/SettingsPage/AddUserRow.js index 9a33be64..63cb8771 100644 --- a/ui/src/Pages/SettingsPage/AddUserRow.js +++ b/ui/src/Pages/SettingsPage/AddUserRow.js @@ -1,7 +1,6 @@ -import { gql } from '@apollo/client' +import { gql, useMutation } from '@apollo/client' import PropTypes from 'prop-types' import React, { useState } from 'react' -import { Mutation } from '@apollo/client' import { Button, Checkbox, Input, Table } from 'semantic-ui-react' const createUserMutation = gql` @@ -28,6 +27,12 @@ const initialState = { const AddUserRow = ({ setShow, show, onUserAdded }) => { const [state, setState] = useState(initialState) + const [createUser, { loading }] = useMutation(createUserMutation, { + onCompleted: () => { + onUserAdded() + }, + }) + function updateInput(event, key) { setState({ ...state, @@ -40,68 +45,59 @@ const AddUserRow = ({ setShow, show, onUserAdded }) => { } return ( - { - onUserAdded() - }} - > - {(createUser, { loading }) => ( - - - updateInput(e, 'username')} - /> - - - updateInput(e, 'rootPath')} - /> - - - { - setState({ - ...state, - admin: data.checked, - }) - }} - /> - - - - - - - - - )} - + + + updateInput(e, 'username')} + /> + + + updateInput(e, 'rootPath')} + /> + + + { + setState({ + ...state, + admin: data.checked, + }) + }} + /> + + + + + + + + ) } diff --git a/ui/src/Pages/SettingsPage/UserRow.js b/ui/src/Pages/SettingsPage/UserRow.js index c1b0a185..23762efa 100644 --- a/ui/src/Pages/SettingsPage/UserRow.js +++ b/ui/src/Pages/SettingsPage/UserRow.js @@ -1,7 +1,6 @@ import PropTypes from 'prop-types' import React, { useState } from 'react' -import { Mutation } from '@apollo/client/react/components' -import { gql } from '@apollo/client' +import { gql, useMutation } from '@apollo/client' import { Button, Checkbox, @@ -61,50 +60,47 @@ const scanUserMutation = gql` const ChangePasswordModal = ({ onClose, user, ...props }) => { const [passwordInput, setPasswordInput] = useState('') + const [changePassword] = useMutation(changeUserPasswordMutation, { + onCompleted: () => { + onClose && onClose() + }, + }) + return ( - { - onClose && onClose() - }} - > - {changePassword => ( - - Change password - -

- Change password for {user.username} -

-
- - - setPasswordInput(e.target.value)} - type="password" - /> - -
-
- - - - -
- )} -
+ + Change password + +

+ Change password for {user.username} +

+
+ + + setPasswordInput(e.target.value)} + type="password" + /> + +
+
+ + + + +
) } @@ -119,7 +115,7 @@ const UserRow = ({ user, refetchUsers }) => { editing: false, }) - const [showComfirmDelete, setConfirmDelete] = useState(false) + const [showConfirmDelete, setConfirmDelete] = useState(false) const [showChangePassword, setChangePassword] = useState(false) function updateInput(event, key) { @@ -129,171 +125,168 @@ const UserRow = ({ user, refetchUsers }) => { }) } + const [updateUser, { loading: updateUserLoading }] = useMutation( + updateUserMutation, + { + onCompleted: data => { + setState({ + ...data.updateUser, + editing: false, + }) + refetchUsers() + }, + } + ) + + const [deleteUser] = useMutation(deleteUserMutation, { + onCompleted: () => { + refetchUsers() + }, + }) + + const [scanUser, { called: scanUserCalled }] = useMutation(scanUserMutation, { + onCompleted: () => { + refetchUsers() + }, + }) + if (state.editing) { return ( - { - setState({ - ...data.updateUser, - editing: false, - }) - refetchUsers() - }} - > - {(updateUser, { loading }) => ( - - - updateInput(e, 'username')} - /> - - - updateInput(e, 'rootPath')} - /> - - - { - setState({ - ...state, - admin: data.checked, - }) - }} - /> - - - - - - - - - )} - + + + updateInput(e, 'username')} + /> + + + updateInput(e, 'rootPath')} + /> + + + { + setState({ + ...state, + admin: data.checked, + }) + }} + /> + + + + + + + + ) } return ( - { - refetchUsers() - }} - > - {deleteUser => ( - - {user.username} - {user.rootPath} - - {user.admin ? : null} - - - - - - {(scanUser, { called }) => ( - - )} - - - setChangePassword(false)} - /> + + {user.username} + {user.rootPath} + + {user.admin ? : null} + + + + + + + setChangePassword(false)} + /> + + + Delete user + +

+ {`Are you sure, you want to delete `} + {user.username}? +

+

{`This action cannot be undone`}

+
+ + - - Delete user - -

- {`Are you sure, you want to delete `} - {user.username}? -

-

{`This action cannot be undone`}

-
- - - - -
-
-
-
- )} -
+ + + + + ) } diff --git a/ui/src/components/albumGallery/AlbumGallery.js b/ui/src/components/albumGallery/AlbumGallery.js index dc61a92e..4bed3351 100644 --- a/ui/src/components/albumGallery/AlbumGallery.js +++ b/ui/src/components/albumGallery/AlbumGallery.js @@ -56,9 +56,7 @@ const AlbumGallery = ({ useEffect(() => { const updateImageState = event => { - if (event.state.imageState) { - setImageState(event.state.imageState) - } + setImageState(event.state.imageState) } window.addEventListener('popstate', updateImageState) diff --git a/ui/src/components/photoGallery/MediaThumbnail.js b/ui/src/components/photoGallery/MediaThumbnail.js index dad95f1a..11c05faf 100644 --- a/ui/src/components/photoGallery/MediaThumbnail.js +++ b/ui/src/components/photoGallery/MediaThumbnail.js @@ -49,19 +49,16 @@ const PhotoImg = photoProps => { ) } -class LazyPhoto extends React.Component { - shouldComponentUpdate(nextProps) { - return nextProps.src != this.props.src - } - - render() { +const LazyPhoto = React.memo( + props => { return ( - + ) - } -} + }, + (prevProps, nextProps) => prevProps.src === nextProps.src +) LazyPhoto.propTypes = { src: PropTypes.string, From 9d25d3d89d42cd235bd734811ac2d915cdc21800 Mon Sep 17 00:00:00 2001 From: stz184 Date: Mon, 16 Nov 2020 22:46:42 +0200 Subject: [PATCH 09/10] Migrated InitialSetupPage.js to functional component with hooks Fixed issue checking the initial setup status on LoginPage --- ui/src/Pages/LoginPage/InitialSetupPage.js | 168 ++++++++++----------- ui/src/Pages/LoginPage/LoginPage.js | 2 +- 2 files changed, 82 insertions(+), 88 deletions(-) diff --git a/ui/src/Pages/LoginPage/InitialSetupPage.js b/ui/src/Pages/LoginPage/InitialSetupPage.js index 5b33bd82..84894476 100644 --- a/ui/src/Pages/LoginPage/InitialSetupPage.js +++ b/ui/src/Pages/LoginPage/InitialSetupPage.js @@ -1,6 +1,5 @@ -import React, { Component } from 'react' -import { gql } from '@apollo/client' -import { Mutation, Query } from '@apollo/client/react/components' +import React, { useState } from 'react' +import { gql, useQuery, useMutation } from '@apollo/client' import { Redirect } from 'react-router-dom' import { Button, Form, Message, Header } from 'semantic-ui-react' import { Container } from './loginUtilities' @@ -26,106 +25,101 @@ const initialSetupMutation = gql` } ` -class InitialSetupPage extends Component { - constructor(props) { - super(props) +const InitialSetupPage = () => { + const [state, setState] = useState({ + username: '', + password: '', + rootPath: '', + }) - this.state = { - username: '', - password: '', - rootPath: '', - } - } - - handleChange(event, key) { - this.setState({ [key]: event.target.value }) + const handleChange = (event, key) => { + const value = event.target.value + setState(prevState => ({ + ...prevState, + [key]: value, + })) } - signIn(event, authorize) { + const signIn = (event, authorize) => { event.preventDefault() authorize({ variables: { - username: this.state.username, - password: this.state.password, - rootPath: this.state.rootPath, + username: state.username, + password: state.password, + rootPath: state.rootPath, }, }) } - render() { - if (authToken()) { - return - } + if (authToken()) { + return + } - return ( -
- -
- Initial Setup -
- - {({ data }) => { - if (data && data.siteInfo && data.siteInfo.initialSetup) { - return null - } + const { data: initialSetupData } = useQuery(checkInitialSetupQuery) + const initialSetupRedirect = initialSetupData?.siteInfo + ?.initialSetup ? null : ( + + ) - return - }} - - { - const { success, token } = data.initialSetupWizard + const [ + authorize, + { loading: authorizeLoading, data: authorizationData }, + ] = useMutation(initialSetupMutation, { + onCompleted: data => { + const { success, token } = data.initialSetupWizard - if (success) { - login(token) - } - }} - > - {(authorize, { loading, data }) => { - let errorMessage = null - if (data) { - if (!data.initialSetupWizard.success) - errorMessage = data.initialSetupWizard.status - } + if (success) { + login(token) + } + }, + }) - return ( -
this.signIn(e, authorize)} - loading={loading || (data && data.initialSetupWizard.success)} - > - - - this.handleChange(e, 'username')} /> - - - - this.handleChange(e, 'password')} - /> - - - - this.handleChange(e, 'rootPath')} - /> - - - - - ) - }} -
-
-
- ) + let errorMessage = null + if (authorizationData && !authorizationData.initialSetupWizard.success) { + errorMessage = authorizationData.initialSetupWizard.status } + + return ( +
+ {initialSetupRedirect} + +
+ Initial Setup +
+
signIn(e, authorize)} + loading={ + authorizeLoading || authorizationData?.initialSetupWizard?.success + } + > + + + handleChange(e, 'username')} /> + + + + handleChange(e, 'password')} + /> + + + + handleChange(e, 'rootPath')} + /> + + + + +
+
+ ) } export default InitialSetupPage diff --git a/ui/src/Pages/LoginPage/LoginPage.js b/ui/src/Pages/LoginPage/LoginPage.js index b7ba752e..5c4f6ff2 100644 --- a/ui/src/Pages/LoginPage/LoginPage.js +++ b/ui/src/Pages/LoginPage/LoginPage.js @@ -66,7 +66,7 @@ const LoginPage = () => { [credentials] ) - const { initialSetupData } = useQuery(checkInitialSetupQuery) + const { data: initialSetupData } = useQuery(checkInitialSetupQuery) const [authorize, { loading, data }] = useMutation(authorizeMutation, { onCompleted: data => { From 18997a0d3e85e33fe5af86c63b5793bb03e3aa15 Mon Sep 17 00:00:00 2001 From: stz184 Date: Mon, 16 Nov 2020 23:26:38 +0200 Subject: [PATCH 10/10] App, Routes and Sidebar components are migrated to functional ones --- ui/src/App.js | 32 +++++++------- ui/src/components/routes/Routes.js | 60 +++++++++++++-------------- ui/src/components/sidebar/Sidebar.js | 62 +++++++++++++--------------- 3 files changed, 72 insertions(+), 82 deletions(-) diff --git a/ui/src/App.js b/ui/src/App.js index 59fb942b..ffd77adf 100644 --- a/ui/src/App.js +++ b/ui/src/App.js @@ -1,4 +1,4 @@ -import React, { Component } from 'react' +import React from 'react' import { createGlobalStyle } from 'styled-components' import { Helmet } from 'react-helmet' import Routes from './components/routes/Routes' @@ -23,22 +23,20 @@ const GlobalStyle = createGlobalStyle` import 'semantic-ui-css/semantic.min.css' -class App extends Component { - render() { - return ( - <> - - - - - - - - ) - } +const App = () => { + return ( + <> + + + + + + + + ) } export default App diff --git a/ui/src/components/routes/Routes.js b/ui/src/components/routes/Routes.js index 954951e2..e6a7cf01 100644 --- a/ui/src/components/routes/Routes.js +++ b/ui/src/components/routes/Routes.js @@ -24,37 +24,35 @@ const SettingsPage = React.lazy(() => import('../../Pages/SettingsPage/SettingsPage') ) -class Routes extends React.Component { - render() { - return ( - - Loading page -
- } - > - - - - {() => { - clearTokenCookie() - location.href = '/' - }} - - - - - - - - - } /> -
Page not found
} /> -
- - ) - } +const Routes = () => { + return ( + + Loading page + + } + > + + + + {() => { + clearTokenCookie() + location.href = '/' + }} + + + + + + + + + } /> +
Page not found
} /> +
+
+ ) } export default Routes diff --git a/ui/src/components/sidebar/Sidebar.js b/ui/src/components/sidebar/Sidebar.js index cf304497..508d2635 100644 --- a/ui/src/components/sidebar/Sidebar.js +++ b/ui/src/components/sidebar/Sidebar.js @@ -1,4 +1,4 @@ -import React, { createContext } from 'react' +import React, { createContext, useState } from 'react' import PropTypes from 'prop-types' import styled from 'styled-components' import { Icon } from 'semantic-ui-react' @@ -41,42 +41,36 @@ const SidebarDismissButton = styled(Icon)` export const SidebarContext = createContext() SidebarContext.displayName = 'SidebarContext' -class Sidebar extends React.Component { - constructor(props) { - super(props) +const Sidebar = ({ children }) => { + const [state, setState] = useState({ + content: null, + }) - this.state = { - content: null, - } - - this.update = content => { - this.setState({ content }) - } + const update = content => { + setState({ content }) } - render() { - return ( - - {this.props.children} - - {value => ( - - {value.content} - this.setState({ content: null })} - /> -
-
- )} -
-
- ) - } + return ( + + {children} + + {value => ( + + {value.content} + setState({ content: null })} + /> +
+
+ )} +
+
+ ) } Sidebar.propTypes = {