[web] new notification style for dashboard (#15878)

* Create `new-notification-style` split test

GitOrigin-RevId: 3b6d8894da049939c424459ddb7d0afe967dab4c
This commit is contained in:
Miguel Serrano 2023-11-22 15:43:25 +01:00 committed by Copybot
parent d7198156c1
commit b1978d9362
5 changed files with 90 additions and 20 deletions

View file

@ -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,
})
}

View file

@ -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

View file

@ -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)

View file

@ -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"

View file

@ -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"