mirror of
https://github.com/overleaf/overleaf.git
synced 2025-04-11 21:35:32 +00:00
[web] new notification style for dashboard (#15878)
* Create `new-notification-style` split test GitOrigin-RevId: 3b6d8894da049939c424459ddb7d0afe967dab4c
This commit is contained in:
parent
d7198156c1
commit
b1978d9362
5 changed files with 90 additions and 20 deletions
|
@ -447,6 +447,22 @@ async function projectListPage(req, res, next) {
|
|||
logger.error({ err: error }, 'Failed to get individual subscription')
|
||||
}
|
||||
|
||||
let newNotificationStyle
|
||||
try {
|
||||
const newNotificationStyleAssignment =
|
||||
await SplitTestHandler.promises.getAssignment(
|
||||
req,
|
||||
res,
|
||||
'new-notification-style'
|
||||
)
|
||||
newNotificationStyle = newNotificationStyleAssignment.variant === 'enabled'
|
||||
} catch (error) {
|
||||
logger.error(
|
||||
{ err: error },
|
||||
'failed to get "new-notification-style" split test assignment'
|
||||
)
|
||||
}
|
||||
|
||||
res.render('project/list-react', {
|
||||
title: 'your_projects',
|
||||
usersBestSubscription,
|
||||
|
@ -477,6 +493,7 @@ async function projectListPage(req, res, next) {
|
|||
groupName: subscription.teamName,
|
||||
})),
|
||||
hasIndividualRecurlySubscription,
|
||||
newNotificationStyle,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@ block append meta
|
|||
meta(name="ol-welcomePageRedesignVariant" data-type="string" content=welcomePageRedesignVariant)
|
||||
meta(name="ol-groupSubscriptionsPendingEnrollment" data-type="json" content=groupSubscriptionsPendingEnrollment)
|
||||
meta(name="ol-hasIndividualRecurlySubscription" data-type="boolean" content=hasIndividualRecurlySubscription)
|
||||
meta(name="ol-newNotificationStyle" data-type="boolean" content=newNotificationStyle)
|
||||
|
||||
block content
|
||||
main.content.content-alt.project-list-react#project-list-root
|
||||
|
|
|
@ -7,6 +7,8 @@ import { getUserFacingMessage } from '../../../../infrastructure/fetch-json'
|
|||
import useIsMounted from '../../../../shared/hooks/use-is-mounted'
|
||||
import * as eventTracking from '../../../../infrastructure/event-tracking'
|
||||
import { isMobileDevice } from '../../../../infrastructure/event-tracking'
|
||||
import getMeta from '@/utils/meta'
|
||||
import Notification from '@/shared/components/notification'
|
||||
|
||||
type ProjectsActionModalProps = {
|
||||
title?: string
|
||||
|
@ -80,18 +82,7 @@ function ProjectsActionModal({
|
|||
<Modal.Footer>
|
||||
{!isProcessing &&
|
||||
errors.length > 0 &&
|
||||
errors.map((e, i) => (
|
||||
<Alert
|
||||
bsStyle="danger"
|
||||
key={`action-error-${i}`}
|
||||
className="text-center"
|
||||
aria-live="polite"
|
||||
>
|
||||
<b>{e.projectName}</b>
|
||||
<br />
|
||||
{getUserFacingMessage(e.error)}
|
||||
</Alert>
|
||||
))}
|
||||
errors.map((e, i) => <ErrorNotification error={e} key={i} />)}
|
||||
<button className="btn btn-secondary" onClick={handleCloseModal}>
|
||||
{t('cancel')}
|
||||
</button>
|
||||
|
@ -107,4 +98,37 @@ function ProjectsActionModal({
|
|||
)
|
||||
}
|
||||
|
||||
type ErrorNotificationProps = {
|
||||
error: any
|
||||
}
|
||||
|
||||
function ErrorNotification({ error }: ErrorNotificationProps) {
|
||||
const newNotificationStyle = getMeta(
|
||||
'ol-newNotificationStyle',
|
||||
false
|
||||
) as boolean
|
||||
|
||||
if (newNotificationStyle) {
|
||||
return (
|
||||
// `notification-list` sets the margin-bottom correctly also when used individually in each notification.
|
||||
// Once the legacy alerts are cleaned up we should move the styled div up to the notification list container.
|
||||
<div className="notification-list">
|
||||
<Notification
|
||||
type="error"
|
||||
title={error.projectName}
|
||||
content={getUserFacingMessage(error.error) as string}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
} else {
|
||||
return (
|
||||
<Alert bsStyle="danger" className="text-center" aria-live="polite">
|
||||
<b>{error.projectName}</b>
|
||||
<br />
|
||||
{getUserFacingMessage(error.error)}
|
||||
</Alert>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
export default memo(ProjectsActionModal)
|
||||
|
|
|
@ -17,6 +17,8 @@ import { useProjectListContext } from '../../context/project-list-context'
|
|||
import { getUserFacingMessage } from '../../../../infrastructure/fetch-json'
|
||||
import { debugConsole } from '@/utils/debugging'
|
||||
import { isMobileDevice } from '../../../../infrastructure/event-tracking'
|
||||
import Notification from '@/shared/components/notification'
|
||||
import getMeta from '@/utils/meta'
|
||||
|
||||
type RenameProjectModalProps = {
|
||||
handleCloseModal: () => void
|
||||
|
@ -33,6 +35,10 @@ function RenameProjectModal({
|
|||
const [newProjectName, setNewProjectName] = useState(project.name)
|
||||
const { error, isError, isLoading, runAsync } = useAsync()
|
||||
const { updateProjectViewData } = useProjectListContext()
|
||||
const newNotificationStyle = getMeta(
|
||||
'ol-newNotificationStyle',
|
||||
false
|
||||
) as boolean
|
||||
|
||||
useEffect(() => {
|
||||
if (showModal) {
|
||||
|
@ -94,6 +100,19 @@ function RenameProjectModal({
|
|||
<Modal.Title>{t('rename_project')}</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
{isError &&
|
||||
(newNotificationStyle ? (
|
||||
<div className="notification-list">
|
||||
<Notification
|
||||
type="error"
|
||||
content={getUserFacingMessage(error) as string}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<Alert bsStyle="danger" className="text-center" aria-live="polite">
|
||||
{getUserFacingMessage(error)}
|
||||
</Alert>
|
||||
))}
|
||||
<form id="rename-project-form" onSubmit={handleSubmit}>
|
||||
<FormGroup>
|
||||
<ControlLabel htmlFor="rename-project-form-name">
|
||||
|
@ -112,11 +131,6 @@ function RenameProjectModal({
|
|||
</form>
|
||||
</Modal.Body>
|
||||
<Modal.Footer>
|
||||
{isError && (
|
||||
<Alert bsStyle="danger" className="text-center" aria-live="polite">
|
||||
{getUserFacingMessage(error)}
|
||||
</Alert>
|
||||
)}
|
||||
<Button
|
||||
bsStyle={null}
|
||||
className="btn-secondary"
|
||||
|
|
|
@ -8,6 +8,8 @@ import {
|
|||
} from '../../../../infrastructure/fetch-json'
|
||||
import { useRefWithAutoFocus } from '../../../../shared/hooks/use-ref-with-auto-focus'
|
||||
import { useLocation } from '../../../../shared/hooks/use-location'
|
||||
import getMeta from '@/utils/meta'
|
||||
import Notification from '@/shared/components/notification'
|
||||
|
||||
type NewProjectData = {
|
||||
project_id: string
|
||||
|
@ -31,6 +33,10 @@ function ModalContentNewProjectForm({ onCancel, template = 'none' }: Props) {
|
|||
const [projectName, setProjectName] = useState('')
|
||||
const { isLoading, isError, error, runAsync } = useAsync<NewProjectData>()
|
||||
const location = useLocation()
|
||||
const newNotificationStyle = getMeta(
|
||||
'ol-newNotificationStyle',
|
||||
false
|
||||
) as boolean
|
||||
|
||||
const createNewProject = () => {
|
||||
runAsync(
|
||||
|
@ -68,9 +74,17 @@ function ModalContentNewProjectForm({ onCancel, template = 'none' }: Props) {
|
|||
</Modal.Header>
|
||||
|
||||
<Modal.Body>
|
||||
{isError && (
|
||||
<Alert bsStyle="danger">{getUserFacingMessage(error)}</Alert>
|
||||
)}
|
||||
{isError &&
|
||||
(newNotificationStyle ? (
|
||||
<div className="notification-list">
|
||||
<Notification
|
||||
type="error"
|
||||
content={getUserFacingMessage(error) as string}
|
||||
/>
|
||||
</div>
|
||||
) : (
|
||||
<Alert bsStyle="danger">{getUserFacingMessage(error)}</Alert>
|
||||
))}
|
||||
<Form onSubmit={handleSubmit}>
|
||||
<input
|
||||
type="text"
|
||||
|
|
Loading…
Add table
Reference in a new issue