Merge pull request #12417 from overleaf/ii-history-react-toggle-switch

[web] Toggle switch history migration

GitOrigin-RevId: c0812d03d576bc66dd8878fa80d4ac18dd8576d0
This commit is contained in:
ilkin-overleaf 2023-03-29 10:54:53 +03:00 committed by Copybot
parent 568092e16b
commit 867b37b76f
8 changed files with 147 additions and 20 deletions

View file

@ -347,6 +347,9 @@
"hide_document_preamble": "", "hide_document_preamble": "",
"hide_outline": "", "hide_outline": "",
"history": "", "history": "",
"history_view_a11y_description": "",
"history_view_all": "",
"history_view_labels": "",
"hotkey_add_a_comment": "", "hotkey_add_a_comment": "",
"hotkey_autocomplete_menu": "", "hotkey_autocomplete_menu": "",
"hotkey_beginning_of_document": "", "hotkey_beginning_of_document": "",

View file

@ -1,15 +1,21 @@
import usePersistedState from '../../../../shared/hooks/use-persisted-state'
import ToggleSwitch from './toggle-switch' import ToggleSwitch from './toggle-switch'
import Main from './main' import Main from './main'
import { useState } from 'react' import { useHistoryContext } from '../../context/history-context'
function ChangeList() { function ChangeList() {
// eslint-disable-next-line no-unused-vars const { projectId, isError } = useHistoryContext()
const [labelsOnly, setLabelsOnly] = useState(false) const [labelsOnly, setLabelsOnly] = usePersistedState(
`history.userPrefs.showOnlyLabels.${projectId}`,
false
)
return ( return (
<aside className="change-list"> <aside className="change-list">
<div className="history-header toggle-switch-container"> <div className="history-header toggle-switch-container">
<ToggleSwitch /> {!isError && (
<ToggleSwitch labelsOnly={labelsOnly} setLabelsOnly={setLabelsOnly} />
)}
</div> </div>
<div className="version-list-container"> <div className="version-list-container">
<Main /> <Main />

View file

@ -1,5 +1,45 @@
function ToggleSwitch() { import { useTranslation } from 'react-i18next'
return <div>Toggle Switch</div>
type ToggleSwitchProps = {
labelsOnly: boolean
setLabelsOnly: React.Dispatch<
React.SetStateAction<ToggleSwitchProps['labelsOnly']>
>
}
function ToggleSwitch({ labelsOnly, setLabelsOnly }: ToggleSwitchProps) {
const { t } = useTranslation()
return (
<fieldset className="toggle-switch">
<legend className="sr-only">{t('history_view_a11y_description')}</legend>
<input
type="radio"
name="labels-only-toggle-switch"
checked={!labelsOnly}
onChange={() => setLabelsOnly(false)}
className="toggle-switch-input"
id="toggle-switch-all-history"
/>
<label
htmlFor="toggle-switch-all-history"
className="toggle-switch-label"
>
<span>{t('history_view_all')}</span>
</label>
<input
type="radio"
name="labels-only-toggle-switch"
checked={labelsOnly}
onChange={() => setLabelsOnly(true)}
className="toggle-switch-input"
id="toggle-switch-labels"
/>
<label htmlFor="toggle-switch-labels" className="toggle-switch-label">
<span>{t('history_view_labels')}</span>
</label>
</fieldset>
)
} }
export default ToggleSwitch export default ToggleSwitch

View file

@ -20,8 +20,6 @@ function useHistory() {
const [nextBeforeTimestamp, setNextBeforeTimestamp] = const [nextBeforeTimestamp, setNextBeforeTimestamp] =
useState<HistoryContextValue['nextBeforeTimestamp']>(null) useState<HistoryContextValue['nextBeforeTimestamp']>(null)
const [atEnd, setAtEnd] = useState<HistoryContextValue['atEnd']>(false) const [atEnd, setAtEnd] = useState<HistoryContextValue['atEnd']>(false)
const [showOnlyLabels, setShowOnlyLabels] =
useState<HistoryContextValue['showOnlyLabels']>(false)
const [userHasFullFeature, setUserHasFullFeature] = const [userHasFullFeature, setUserHasFullFeature] =
useState<HistoryContextValue['userHasFullFeature']>(undefined) useState<HistoryContextValue['userHasFullFeature']>(undefined)
const [freeHistoryLimitHit, setFreeHistoryLimitHit] = const [freeHistoryLimitHit, setFreeHistoryLimitHit] =
@ -44,12 +42,8 @@ function useHistory() {
}) })
/* eslint-enable no-unused-vars */ /* eslint-enable no-unused-vars */
const { const { isLoading, isError, error, data, runAsync } =
isLoading: loading, useAsync<{ updates: Update[] }>()
error,
data,
runAsync,
} = useAsync<{ updates: Update[] }>()
const updates = useMemo(() => data?.updates ?? [], [data?.updates]) const updates = useMemo(() => data?.updates ?? [], [data?.updates])
const loadingFileTree = true const loadingFileTree = true
@ -92,13 +86,13 @@ function useHistory() {
() => ({ () => ({
atEnd, atEnd,
error, error,
isError,
isLoading,
freeHistoryLimitHit, freeHistoryLimitHit,
loading,
labels, labels,
loadingFileTree, loadingFileTree,
nextBeforeTimestamp, nextBeforeTimestamp,
selection, selection,
showOnlyLabels,
updates, updates,
userHasFullFeature, userHasFullFeature,
viewMode, viewMode,
@ -111,13 +105,13 @@ function useHistory() {
[ [
atEnd, atEnd,
error, error,
isError,
isLoading,
freeHistoryLimitHit, freeHistoryLimitHit,
loading,
labels, labels,
loadingFileTree, loadingFileTree,
nextBeforeTimestamp, nextBeforeTimestamp,
selection, selection,
showOnlyLabels,
updates, updates,
userHasFullFeature, userHasFullFeature,
viewMode, viewMode,

View file

@ -7,13 +7,13 @@ export type HistoryContextValue = {
updates: Update[] updates: Update[]
viewMode: string viewMode: string
nextBeforeTimestamp: Nullable<number> nextBeforeTimestamp: Nullable<number>
loading: boolean
atEnd: boolean atEnd: boolean
userHasFullFeature: boolean | undefined userHasFullFeature: boolean | undefined
freeHistoryLimitHit: boolean freeHistoryLimitHit: boolean
selection: Selection selection: Selection
isError: boolean
isLoading: boolean
error: Nullable<unknown> error: Nullable<unknown>
showOnlyLabels: boolean
labels: Nullable<unknown> labels: Nullable<unknown>
loadingFileTree: boolean loadingFileTree: boolean
projectId: string projectId: string

View file

@ -0,0 +1,41 @@
import { useState } from 'react'
import ToggleSwitchComponent from '../../js/features/history/components/change-list/toggle-switch'
export const LabelsOnlyToggleSwitch = () => {
const [labelsOnly, setLabelsOnly] = useState(false)
return (
<ToggleSwitchComponent
labelsOnly={labelsOnly}
setLabelsOnly={setLabelsOnly}
/>
)
}
export default {
title: 'History / Change list',
component: ToggleSwitchComponent,
argTypes: {
labelsOnly: {
table: {
disable: true,
},
},
setLabelsOnly: {
table: {
disable: true,
},
},
},
decorators: [
(Story: React.ComponentType) => (
<div className="history-react">
<div className="change-list">
<div className="history-header toggle-switch-container">
<Story />
</div>
</div>
</div>
),
],
}

View file

@ -46,4 +46,12 @@ history-root {
padding: 0 16px; padding: 0 16px;
} }
} }
.toggle-switch-label {
flex: 1;
span {
display: block;
}
}
} }

View file

@ -0,0 +1,35 @@
import { useState } from 'react'
import ToggleSwitch from '../../../../../frontend/js/features/history/components/change-list/toggle-switch'
describe('change list', function () {
describe('toggle switch', function () {
it('renders switch buttons', function () {
cy.mount(<ToggleSwitch labelsOnly={false} setLabelsOnly={() => {}} />)
cy.findByLabelText(/all history/i)
cy.findByLabelText(/labels/i)
})
it('toggles "all history" and "labels" buttons', function () {
function ToggleSwitchWrapped({ labelsOnly }: { labelsOnly: boolean }) {
const [labelsOnlyLocal, setLabelsOnlyLocal] = useState(labelsOnly)
return (
<ToggleSwitch
labelsOnly={labelsOnlyLocal}
setLabelsOnly={setLabelsOnlyLocal}
/>
)
}
cy.mount(<ToggleSwitchWrapped labelsOnly={false} />)
cy.findByLabelText(/all history/i).as('all-history')
cy.findByLabelText(/labels/i).as('labels')
cy.get('@all-history').should('be.checked')
cy.get('@labels').should('not.be.checked')
cy.get('@labels').click({ force: true })
cy.get('@all-history').should('not.be.checked')
cy.get('@labels').should('be.checked')
})
})
})