Implement 'Add Affiliation' UI on the mobile version of the new react dashboard (#11606)
* Refactor & change `add-affiliation.tsx` file:
* Change class from `user-profile` to `add-affiliation`
* Add new optional `className` props for custom styling
* Show affiliation widget on mobile screen:
* Fix bug on use add affiliation hooks: return type should be `boolean`, not `boolean | 0`
GitOrigin-RevId: 800b951e2a012797266b1780993b4ed9a918d565
This commit is contained in:
@@ -127,7 +127,7 @@ if (isOverleaf)
|
||||
.row-spaced#userProfileInformation(ng-if="hasProjects")
|
||||
div(ng-hide="withAffiliations", ng-cloak)
|
||||
hr
|
||||
.text-centered.user-profile
|
||||
.text-centered.add-affiliation
|
||||
p Are you affiliated with an institution?
|
||||
|
||||
a.btn.btn-secondary-info.btn-secondary(
|
||||
|
||||
+16
-7
@@ -1,19 +1,26 @@
|
||||
import { useTranslation } from 'react-i18next'
|
||||
import { Button } from 'react-bootstrap'
|
||||
import { useProjectListContext } from '../../context/project-list-context'
|
||||
import getMeta from '../../../../utils/meta'
|
||||
import { Affiliation } from '../../../../../../types/affiliation'
|
||||
import { ExposedSettings } from '../../../../../../types/exposed-settings'
|
||||
import { useProjectListContext } from '../context/project-list-context'
|
||||
import getMeta from '../../../utils/meta'
|
||||
import { Affiliation } from '../../../../../types/affiliation'
|
||||
import { ExposedSettings } from '../../../../../types/exposed-settings'
|
||||
import classNames from 'classnames'
|
||||
|
||||
export function useAddAffiliation() {
|
||||
const { totalProjectsCount } = useProjectListContext()
|
||||
const { isOverleaf } = getMeta('ol-ExposedSettings') as ExposedSettings
|
||||
const userAffiliations = getMeta('ol-userAffiliations', []) as Affiliation[]
|
||||
|
||||
return { show: isOverleaf && totalProjectsCount && !userAffiliations.length }
|
||||
return {
|
||||
show: isOverleaf && totalProjectsCount > 0 && !userAffiliations.length,
|
||||
}
|
||||
}
|
||||
|
||||
function AddAffiliation() {
|
||||
type AddAffiliationProps = {
|
||||
className?: string
|
||||
}
|
||||
|
||||
function AddAffiliation({ className }: AddAffiliationProps) {
|
||||
const { t } = useTranslation()
|
||||
const { show } = useAddAffiliation()
|
||||
|
||||
@@ -21,8 +28,10 @@ function AddAffiliation() {
|
||||
return null
|
||||
}
|
||||
|
||||
const classes = classNames('text-centered', 'add-affiliation', className)
|
||||
|
||||
return (
|
||||
<div className="text-centered user-profile">
|
||||
<div className={classes}>
|
||||
<p>{t('are_you_affiliated_with_an_institution')}</p>
|
||||
<Button
|
||||
bsStyle={null}
|
||||
@@ -8,6 +8,7 @@ import getMeta from '../../../utils/meta'
|
||||
import NewProjectButtonModal, {
|
||||
NewProjectButtonModalVariant,
|
||||
} from './new-project-button/new-project-button-modal'
|
||||
import AddAffiliation, { useAddAffiliation } from './add-affiliation'
|
||||
import { Nullable } from '../../../../../types/utils'
|
||||
import { sendMB } from '../../../infrastructure/event-tracking'
|
||||
|
||||
@@ -32,6 +33,7 @@ type NewProjectButtonProps = {
|
||||
className?: string
|
||||
menuClassName?: string
|
||||
trackingKey?: string
|
||||
showAddAffiliationWidget?: boolean
|
||||
}
|
||||
|
||||
function NewProjectButton({
|
||||
@@ -40,12 +42,14 @@ function NewProjectButton({
|
||||
className,
|
||||
menuClassName,
|
||||
trackingKey,
|
||||
showAddAffiliationWidget,
|
||||
}: NewProjectButtonProps) {
|
||||
const { t } = useTranslation()
|
||||
const { templateLinks } = getMeta('ol-ExposedSettings') as ExposedSettings
|
||||
const [modal, setModal] =
|
||||
useState<Nullable<NewProjectButtonModalVariant>>(null)
|
||||
const portalTemplates = getMeta('ol-portalTemplates') as PortalTemplate[]
|
||||
const { show: enableAddAffiliationWidget } = useAddAffiliation()
|
||||
|
||||
const sendTrackingEvent = useCallback(
|
||||
({
|
||||
@@ -223,6 +227,14 @@ function NewProjectButton({
|
||||
: templateLink.name}
|
||||
</MenuItem>
|
||||
))}
|
||||
{showAddAffiliationWidget && enableAddAffiliationWidget ? (
|
||||
<>
|
||||
<MenuItem divider />
|
||||
<li className="add-affiliation-mobile-wrapper">
|
||||
<AddAffiliation className="is-mobile" />
|
||||
</li>
|
||||
</>
|
||||
) : null}
|
||||
</Dropdown.Menu>
|
||||
</ControlledDropdown>
|
||||
<NewProjectButtonModal modal={modal} onHide={() => setModal(null)} />
|
||||
|
||||
@@ -104,6 +104,7 @@ function ProjectListPageContent() {
|
||||
<NewProjectButton
|
||||
id="new-project-button-projects-table"
|
||||
className="pull-left me-2"
|
||||
showAddAffiliationWidget
|
||||
/>
|
||||
<SearchForm
|
||||
inputValue={searchText}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import NewProjectButton from '../new-project-button'
|
||||
import SidebarFilters from './sidebar-filters'
|
||||
import AddAffiliation, { useAddAffiliation } from './add-affiliation'
|
||||
import AddAffiliation, { useAddAffiliation } from '../add-affiliation'
|
||||
import { usePersistedResize } from '../../../../shared/hooks/use-resize'
|
||||
|
||||
function Sidebar() {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import AddAffiliation from '../../js/features/project-list/components/sidebar/add-affiliation'
|
||||
import AddAffiliation from '../../js/features/project-list/components/add-affiliation'
|
||||
import { ProjectListProvider } from '../../js/features/project-list/context/project-list-context'
|
||||
import useFetchMock from '../hooks/use-fetch-mock'
|
||||
import { projectsData } from '../../../test/frontend/features/project-list/fixtures/projects-data'
|
||||
|
||||
@@ -217,7 +217,11 @@ input.project-list-table-select-item[type='checkbox'] {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.user-profile {
|
||||
.add-affiliation-mobile-wrapper {
|
||||
padding: @padding-md 0;
|
||||
}
|
||||
|
||||
.add-affiliation {
|
||||
.progress {
|
||||
height: @line-height-computed / 2;
|
||||
margin-bottom: @line-height-computed / 4;
|
||||
@@ -225,6 +229,10 @@ input.project-list-table-select-item[type='checkbox'] {
|
||||
p {
|
||||
margin-bottom: @line-height-computed / 4;
|
||||
}
|
||||
&.is-mobile p {
|
||||
font-size: 12px;
|
||||
white-space: normal;
|
||||
}
|
||||
}
|
||||
|
||||
.user-notifications {
|
||||
|
||||
+9
-3
@@ -1,8 +1,14 @@
|
||||
import { render, fireEvent, screen } from '@testing-library/react'
|
||||
import { fireEvent, screen } from '@testing-library/react'
|
||||
import { expect } from 'chai'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import NewProjectButton from '../../../../../frontend/js/features/project-list/components/new-project-button'
|
||||
import { renderWithProjectListContext } from '../helpers/render-with-context'
|
||||
|
||||
describe('<NewProjectButton />', function () {
|
||||
beforeEach(function () {
|
||||
fetchMock.reset()
|
||||
})
|
||||
|
||||
describe('for every user (affiliated and non-affiliated)', function () {
|
||||
beforeEach(function () {
|
||||
window.metaAttributesCache.set('ol-ExposedSettings', {
|
||||
@@ -18,7 +24,7 @@ describe('<NewProjectButton />', function () {
|
||||
],
|
||||
})
|
||||
|
||||
render(<NewProjectButton id="test" />)
|
||||
renderWithProjectListContext(<NewProjectButton id="test" />)
|
||||
|
||||
const newProjectButton = screen.getByRole('button', {
|
||||
name: 'New Project',
|
||||
@@ -100,7 +106,7 @@ describe('<NewProjectButton />', function () {
|
||||
})
|
||||
|
||||
it('shows the correct dropdown menu', function () {
|
||||
render(<NewProjectButton id="test" />)
|
||||
renderWithProjectListContext(<NewProjectButton id="test" />)
|
||||
|
||||
const newProjectButton = screen.getByRole('button', {
|
||||
name: 'New Project',
|
||||
|
||||
+4
-2
@@ -2,7 +2,7 @@ import { screen, waitFor } from '@testing-library/react'
|
||||
import { expect } from 'chai'
|
||||
import fetchMock from 'fetch-mock'
|
||||
import { renderWithProjectListContext } from '../../helpers/render-with-context'
|
||||
import AddAffiliation from '../../../../../../frontend/js/features/project-list/components/sidebar/add-affiliation'
|
||||
import AddAffiliation from '../../../../../../frontend/js/features/project-list/components/add-affiliation'
|
||||
import { Affiliation } from '../../../../../../types/affiliation'
|
||||
|
||||
describe('Add affiliation widget', function () {
|
||||
@@ -54,7 +54,9 @@ describe('Add affiliation widget', function () {
|
||||
window.metaAttributesCache.set('ol-ExposedSettings', { isOverleaf: true })
|
||||
window.metaAttributesCache.set('ol-userAffiliations', [])
|
||||
|
||||
renderWithProjectListContext(<AddAffiliation />, { projects: [] })
|
||||
renderWithProjectListContext(<AddAffiliation />, {
|
||||
projects: [],
|
||||
})
|
||||
|
||||
await fetchMock.flush(true)
|
||||
await waitFor(() => expect(fetchMock.called('/api/project')))
|
||||
|
||||
Reference in New Issue
Block a user