Correct use selector (#515)

This commit is contained in:
mrdrogdrog 2020-08-30 21:24:34 +02:00 committed by GitHub
parent 971421925a
commit a41d3d1515
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
20 changed files with 74 additions and 205 deletions

View file

@ -1,3 +1,5 @@
import equal from 'fast-deep-equal'
import React from 'react'
import { useSelector } from 'react-redux'
import { ApplicationState } from '../../../redux'
@ -9,7 +11,7 @@ export interface BrandingProps {
}
export const Branding: React.FC<BrandingProps> = ({ inline = false }) => {
const branding = useSelector((state: ApplicationState) => state.config.branding)
const branding = useSelector((state: ApplicationState) => state.config.branding, equal)
const showBranding = !!branding.name || !!branding.logo
return (

View file

@ -7,11 +7,11 @@ export interface DocumentTitleProps {
}
export const DocumentTitle: React.FC<DocumentTitleProps> = ({ title }) => {
const branding = useSelector((state: ApplicationState) => state.config.branding)
const brandingName = useSelector((state: ApplicationState) => state.config.branding.name)
useEffect(() => {
document.title = `${title ? title + ' - ' : ''}CodiMD ${branding.name ? ` @ ${branding.name}` : ''}`
}, [branding, title])
document.title = `${title ? title + ' - ' : ''}CodiMD ${brandingName ? ` @ ${brandingName}` : ''}`
}, [brandingName, title])
return null
}

View file

@ -1,3 +1,4 @@
import equal from 'fast-deep-equal'
import React from 'react'
import { useSelector } from 'react-redux'
import { Link } from 'react-router-dom'
@ -8,7 +9,7 @@ import { ForkAwesomeIcon } from '../fork-awesome/fork-awesome-icon'
import { ShowIf } from '../show-if/show-if'
export const MotdBanner: React.FC = () => {
const bannerState = useSelector((state: ApplicationState) => state.banner)
const bannerState = useSelector((state: ApplicationState) => state.banner, equal)
const dismissBanner = () => {
setBanner({ ...bannerState, show: false })

View file

@ -19,7 +19,7 @@ import { NavbarBranding } from './navbar-branding'
export const AppBar: React.FC = () => {
const { t } = useTranslation()
const { id } = useParams<EditorPathParams>()
const user = useSelector((state: ApplicationState) => state.user)
const userExists = useSelector((state: ApplicationState) => !!state.user)
return (
<Navbar bg={'light'}>
@ -39,10 +39,10 @@ export const AppBar: React.FC = () => {
<Button className="mx-2" size="sm" variant="primary">
<ForkAwesomeIcon icon="plus"/> <Trans i18nKey="editor.documentBar.new"/>
</Button>
<ShowIf condition={!user}>
<ShowIf condition={!userExists}>
<SignInButton size={'sm'} />
</ShowIf>
<ShowIf condition={!!user}>
<ShowIf condition={userExists}>
<UserDropdown />
</ShowIf>
</Nav>

View file

@ -14,12 +14,12 @@ export enum EditorMode {
export const EditorViewMode: React.FC = () => {
const { t } = useTranslation()
const editorConfig = useSelector((state: ApplicationState) => state.editorConfig)
const editorMode = useSelector((state: ApplicationState) => state.editorConfig.editorMode)
return (
<ToggleButtonGroup
type="radio"
name="options"
value={editorConfig.editorMode}
value={editorMode}
onChange={(value: EditorMode) => {
setEditorMode(value)
}}>

View file

@ -5,6 +5,7 @@ import { useSelector } from 'react-redux'
import { deleteHistory, deleteHistoryEntry, getHistory, setHistory, updateHistoryEntry } from '../../api/history'
import { deleteNote } from '../../api/notes'
import { ApplicationState } from '../../redux'
import {
collectEntries,
downloadHistory,
@ -46,7 +47,7 @@ export const HistoryPage: React.FC = () => {
const [localHistoryEntries, setLocalHistoryEntries] = useState<HistoryEntry[]>(loadHistoryFromLocalStore)
const [remoteHistoryEntries, setRemoteHistoryEntries] = useState<HistoryEntry[]>([])
const [toolbarState, setToolbarState] = useState<HistoryToolbarState>(toolbarInitState)
const user = useSelector((state: ApplicationState) => state.user)
const userExists = useSelector((state: ApplicationState) => !!state.user)
const [error, setError] = useState('')
const historyWrite = useCallback((entries: HistoryEntry[]) => {
@ -61,24 +62,24 @@ export const HistoryPage: React.FC = () => {
}, [historyWrite, localHistoryEntries])
const importHistory = useCallback((entries: HistoryEntry[]): void => {
if (user) {
if (userExists) {
setHistory(entries)
.then(() => setRemoteHistoryEntries(entries))
.catch(() => setError('setHistory'))
} else {
setLocalHistoryEntries(entries)
}
}, [user])
}, [userExists])
const refreshHistory = useCallback(() => {
const localHistory = loadHistoryFromLocalStore()
setLocalHistoryEntries(localHistory)
if (user) {
if (userExists) {
getHistory()
.then((remoteHistory) => setRemoteHistoryEntries(remoteHistory))
.catch(() => setError('getHistory'))
}
}, [user])
}, [userExists])
useEffect(() => {
refreshHistory()
@ -94,17 +95,17 @@ export const HistoryPage: React.FC = () => {
const clearHistory = useCallback(() => {
setLocalHistoryEntries([])
if (user) {
if (userExists) {
deleteHistory()
.then(() => setRemoteHistoryEntries([]))
.catch(() => setError('deleteHistory'))
}
historyWrite([])
}, [historyWrite, user])
}, [historyWrite, userExists])
const uploadAll = useCallback((): void => {
const newHistory = mergeEntryArrays(localHistoryEntries, remoteHistoryEntries)
if (user) {
if (userExists) {
setHistory(newHistory)
.then(() => {
setRemoteHistoryEntries(newHistory)
@ -113,7 +114,7 @@ export const HistoryPage: React.FC = () => {
})
.catch(() => setError('setHistory'))
}
}, [historyWrite, localHistoryEntries, remoteHistoryEntries, user])
}, [historyWrite, localHistoryEntries, remoteHistoryEntries, userExists])
const removeFromHistoryClick = useCallback((entryId: string, location: HistoryEntryOrigin): void => {
if (location === HistoryEntryOrigin.LOCAL) {
@ -126,14 +127,14 @@ export const HistoryPage: React.FC = () => {
}, [])
const deleteNoteClick = useCallback((entryId: string, location: HistoryEntryOrigin): void => {
if (user) {
if (userExists) {
deleteNote(entryId)
.then(() => {
removeFromHistoryClick(entryId, location)
})
.catch(() => setError('deleteNote'))
}
}, [user, removeFromHistoryClick])
}, [userExists, removeFromHistoryClick])
const pinClick = useCallback((entryId: string, location: HistoryEntryOrigin): void => {
if (location === HistoryEntryOrigin.LOCAL) {

View file

@ -49,7 +49,7 @@ export const initState: HistoryToolbarState = {
export const HistoryToolbar: React.FC<HistoryToolbarProps> = ({ onSettingsChange, tags, onClearHistory, onRefreshHistory, onExportHistory, onImportHistory, onUploadAll }) => {
const [t] = useTranslation()
const [state, setState] = useState<HistoryToolbarState>(initState)
const user = useSelector((state: ApplicationState) => state.user)
const userExists = useSelector((state: ApplicationState) => !!state.user)
const titleSortChanged = (direction: SortModeEnum) => {
setState(prevState => ({
@ -118,7 +118,7 @@ export const HistoryToolbar: React.FC<HistoryToolbarProps> = ({ onSettingsChange
<ForkAwesomeIcon icon='refresh'/>
</Button>
</InputGroup>
<ShowIf condition={!!user}>
<ShowIf condition={userExists}>
<InputGroup className={'mr-1 mb-1'}>
<Button variant={'light'} title={t('landing.history.toolbar.uploadAll')} onClick={onUploadAll}>
<ForkAwesomeIcon icon='cloud-upload'/>

View file

@ -10,10 +10,10 @@ import { SignInButton } from '../../landing-layout/navigation/sign-in-button'
export const CoverButtons: React.FC = () => {
useTranslation()
const user = useSelector((state: ApplicationState) => state.user)
const authProviders = useSelector((state: ApplicationState) => state.config.authProviders)
const userExists = useSelector((state: ApplicationState) => !!state.user)
const anyAuthProviderActivated = useSelector((state: ApplicationState) => Object.values(state.config.authProviders).includes(true))
if (user) {
if (userExists) {
return null
}
@ -24,7 +24,7 @@ export const CoverButtons: React.FC = () => {
variant="success"
size="lg"
/>
<ShowIf condition={Object.values(authProviders).includes(true)}>
<ShowIf condition={anyAuthProviderActivated}>
<span className="m-2">
<Trans i18nKey="common.or"/>
</span>

View file

@ -10,7 +10,7 @@ import { VersionInfo } from './version-info'
export const PoweredByLinks: React.FC = () => {
useTranslation()
const config = useSelector((state: ApplicationState) => state.config)
const specialLinks = useSelector((state: ApplicationState) => Object.entries(state.config.specialLinks) as [string, string][])
return (
<p>
@ -20,7 +20,7 @@ export const PoweredByLinks: React.FC = () => {
&nbsp;|&nbsp;
<TranslatedInternalLink href='/n/release-notes' i18nKey='landing.footer.releases'/>
{
Object.entries({ ...config.specialLinks }).map(([i18nKey, href]) =>
specialLinks.map(([i18nKey, href]) =>
<Fragment key={i18nKey}>
&nbsp;|&nbsp;
<TranslatedExternalLink href={href} i18nKey={'landing.footer.' + i18nKey}/>

View file

@ -8,6 +8,7 @@ import frontendVersion from '../../../version.json'
import { TranslatedExternalLink } from '../../common/links/translated-external-link'
import { ShowIf } from '../../common/show-if/show-if'
import { CopyableField } from '../../common/copyable-field/copyable-field'
import equal from 'fast-deep-equal'
export const VersionInfo: React.FC = () => {
const [show, setShow] = useState(false)
@ -17,7 +18,7 @@ export const VersionInfo: React.FC = () => {
const { t } = useTranslation()
const serverVersion = useSelector((state: ApplicationState) => state.config.version)
const serverVersion = useSelector((state: ApplicationState) => state.config.version, equal)
const column = (title: string, version: string, sourceCodeLink: string, issueTrackerLink: string) => (
<Col md={6} className={'flex-column'}>

View file

@ -12,7 +12,7 @@ import './header-bar.scss'
const HeaderBar: React.FC = () => {
useTranslation()
const user = useSelector((state: ApplicationState) => state.user)
const userExists = useSelector((state: ApplicationState) => !!state.user)
return (
<Navbar className="justify-content-between">
@ -25,7 +25,7 @@ const HeaderBar: React.FC = () => {
</HeaderNavLink>
</div>
<div className="d-inline-flex">
{!user
{!userExists
? <Fragment>
<span className={'mx-1 d-flex'}>
<NewGuestNoteButton/>

View file

@ -13,9 +13,9 @@ type SignInButtonProps = {
export const SignInButton: React.FC<SignInButtonProps> = ({ variant, ...props }) => {
const { t } = useTranslation()
const authProviders = useSelector((state: ApplicationState) => state.config.authProviders)
const anyAuthProviderActive = useSelector((state: ApplicationState) => Object.values(state.config.authProviders).includes(true))
return (
<ShowIf condition={Object.values(authProviders).includes(true)}>
<ShowIf condition={anyAuthProviderActive}>
<LinkContainer to="/login" title={t('login.signIn')}>
<Button
variant={variant || 'success'}

View file

@ -7,10 +7,11 @@ import { ApplicationState } from '../../../redux'
import { clearUser } from '../../../redux/user/methods'
import { ForkAwesomeIcon } from '../../common/fork-awesome/fork-awesome-icon'
import { UserAvatar } from '../../common/user-avatar/user-avatar'
import equal from 'fast-deep-equal'
export const UserDropdown: React.FC = () => {
useTranslation()
const user = useSelector((state: ApplicationState) => state.user)
const user = useSelector((state: ApplicationState) => state.user, equal)
if (!user) {
return null

View file

@ -9,12 +9,13 @@ import { ViaInternal } from './auth/via-internal'
import { ViaLdap } from './auth/via-ldap'
import { OneClickType, ViaOneClick } from './auth/via-one-click'
import { ViaOpenId } from './auth/via-openid'
import equal from 'fast-deep-equal'
export const LoginPage: React.FC = () => {
useTranslation()
const authProviders = useSelector((state: ApplicationState) => state.config.authProviders)
const customAuthNames = useSelector((state: ApplicationState) => state.config.customAuthNames)
const userLoginState = useSelector((state: ApplicationState) => state.user)
const authProviders = useSelector((state: ApplicationState) => state.config.authProviders, equal)
const customSamlAuthName = useSelector((state: ApplicationState) => state.config.customAuthNames.saml)
const customOauthAuthName = useSelector((state: ApplicationState) => state.config.customAuthNames.oauth2)
const userLoggedIn = useSelector((state: ApplicationState) => !!state.user)
const oneClickProviders = [authProviders.dropbox, authProviders.facebook, authProviders.github, authProviders.gitlab,
authProviders.google, authProviders.oauth2, authProviders.saml, authProviders.twitter]
@ -22,15 +23,15 @@ export const LoginPage: React.FC = () => {
const oneClickCustomName: (type: OneClickType) => string | undefined = (type) => {
switch (type) {
case OneClickType.SAML:
return customAuthNames.saml
return customSamlAuthName
case OneClickType.OAUTH2:
return customAuthNames.oauth2
return customOauthAuthName
default:
return undefined
}
}
if (userLoginState) {
if (userLoggedIn) {
// TODO Redirect to previous page?
return (
<Redirect to='/history'/>

View file

@ -1,4 +1,4 @@
import equal from 'deep-equal'
import equal from 'fast-deep-equal'
import { DomElement } from 'domhandler'
import emojiData from 'emoji-mart/data/twitter.json'
import { Data } from 'emoji-mart/dist-es/utils/data'

View file

@ -10,9 +10,9 @@ import { ProfileChangePassword } from './settings/profile-change-password'
import { ProfileDisplayName } from './settings/profile-display-name'
export const ProfilePage: React.FC = () => {
const user = useSelector((state: ApplicationState) => state.user)
const userProvider = useSelector((state: ApplicationState) => state.user?.provider)
if (!user) {
if (!userProvider) {
return (
<Redirect to={'/login'}/>
)
@ -23,7 +23,7 @@ export const ProfilePage: React.FC = () => {
<Row className="h-100 flex justify-content-center">
<Col lg={6}>
<ProfileDisplayName/>
<ShowIf condition={user.provider === LoginProvider.INTERNAL}>
<ShowIf condition={userProvider === LoginProvider.INTERNAL}>
<ProfileChangePassword/>
</ShowIf>
<ProfileAccountManagement/>

View file

@ -9,18 +9,18 @@ import { getAndSetUser } from '../../login-page/auth/utils'
export const ProfileDisplayName: React.FC = () => {
const regexInvalidDisplayName = /^\s*$/
const { t } = useTranslation()
const user = useSelector((state: ApplicationState) => state.user)
const userName = useSelector((state: ApplicationState) => state.user?.name)
const [submittable, setSubmittable] = useState(false)
const [error, setError] = useState(false)
const [displayName, setDisplayName] = useState('')
useEffect(() => {
if (user) {
setDisplayName(user.name)
if (userName !== undefined) {
setDisplayName(userName)
}
}, [user])
}, [userName])
if (!user) {
if (!userName) {
return <Alert variant={'danger'}>User not logged in</Alert>
}

View file

@ -17,8 +17,9 @@ export enum RegisterError {
export const RegisterPage: React.FC = () => {
const { t } = useTranslation()
const config = useSelector((state: ApplicationState) => state.config)
const user = useSelector((state: ApplicationState) => state.user)
const allowRegister = useSelector((state: ApplicationState) => state.config.allowRegister)
const specialLinks = useSelector((state: ApplicationState) => state.config.specialLinks)
const userExists = useSelector((state: ApplicationState) => !!state.user)
const [username, setUsername] = useState('')
const [password, setPassword] = useState('')
@ -40,13 +41,13 @@ export const RegisterPage: React.FC = () => {
setReady(username !== '' && password !== '' && password.length >= 8 && password === passwordAgain)
}, [username, password, passwordAgain])
if (!config.allowRegister) {
if (!allowRegister) {
return (
<Redirect to={'/login'}/>
)
}
if (user) {
if (userExists) {
return (
<Redirect to={'/intro'}/>
)
@ -105,17 +106,17 @@ export const RegisterPage: React.FC = () => {
required
/>
</Form.Group>
<ShowIf condition={!!config.specialLinks?.termsOfUse || !!config.specialLinks?.privacy}>
<ShowIf condition={!!specialLinks?.termsOfUse || !!specialLinks?.privacy}>
<Trans i18nKey='login.register.infoTermsPrivacy'/>
<ul>
<ShowIf condition={!!config.specialLinks?.termsOfUse}>
<ShowIf condition={!!specialLinks?.termsOfUse}>
<li>
<TranslatedExternalLink i18nKey='landing.footer.termsOfUse' href={config.specialLinks.termsOfUse}/>
<TranslatedExternalLink i18nKey='landing.footer.termsOfUse' href={specialLinks.termsOfUse}/>
</li>
</ShowIf>
<ShowIf condition={!!config.specialLinks?.privacy}>
<ShowIf condition={!!specialLinks?.privacy}>
<li>
<TranslatedExternalLink i18nKey='landing.footer.privacy' href={config.specialLinks.privacy}/>
<TranslatedExternalLink i18nKey='landing.footer.privacy' href={specialLinks.privacy}/>
</li>
</ShowIf>
</ul>