فهرست منبع

Merge pull request #15887 from overleaf/msm-new-notification-inr-latam

[web] New notification style: inr/latam/writefull/groups

GitOrigin-RevId: 85ffa6d5c7ee775bf16fbb6e1fb7ce1860077b93
Miguel Serrano 2 سال پیش
والد
کامیت
b61f34c740

+ 17 - 12
services/web/frontend/js/features/project-list/components/notifications/ads/inr-banner.tsx

@@ -96,14 +96,16 @@ export default function INRBanner({ variant, splitTestName }: INRBannerProps) {
 
 
   if (variant === 'default') {
   if (variant === 'default') {
     return (
     return (
-      <Notification bsStyle="info" onDismiss={bannerDismissed}>
-        <Notification.Body>
+      <Notification
+        bsStyle="info"
+        onDismiss={bannerDismissed}
+        body={
           <Trans
           <Trans
             i18nKey="inr_discount_offer"
             i18nKey="inr_discount_offer"
             components={[<b />]} // eslint-disable-line react/jsx-key
             components={[<b />]} // eslint-disable-line react/jsx-key
           />
           />
-        </Notification.Body>
-        <Notification.Action>
+        }
+        action={
           <Button
           <Button
             bsStyle="info"
             bsStyle="info"
             bsSize="sm"
             bsSize="sm"
@@ -112,13 +114,15 @@ export default function INRBanner({ variant, splitTestName }: INRBannerProps) {
           >
           >
             {t('get_discounted_plan')}
             {t('get_discounted_plan')}
           </Button>
           </Button>
-        </Notification.Action>
-      </Notification>
+        }
+      />
     )
     )
   } else if (variant === 'green-banner') {
   } else if (variant === 'green-banner') {
     return (
     return (
-      <Notification bsStyle="success" onDismiss={bannerDismissed}>
-        <Notification.Body>
+      <Notification
+        bsStyle="success"
+        onDismiss={bannerDismissed}
+        body={
           <Trans
           <Trans
             i18nKey="inr_discount_offer_green_banner"
             i18nKey="inr_discount_offer_green_banner"
             components={[<b />, <br />]} // eslint-disable-line react/jsx-key
             components={[<b />, <br />]} // eslint-disable-line react/jsx-key
@@ -126,17 +130,18 @@ export default function INRBanner({ variant, splitTestName }: INRBannerProps) {
             shouldUnescape
             shouldUnescape
             tOptions={{ interpolation: { escapeValue: true } }}
             tOptions={{ interpolation: { escapeValue: true } }}
           />
           />
-        </Notification.Body>
-        <Notification.Action>
+        }
+        action={
           <Button
           <Button
             bsStyle="success"
             bsStyle="success"
+            bsSize="sm"
             className="pull-right"
             className="pull-right"
             onClick={handleClick}
             onClick={handleClick}
           >
           >
             {t('get_discounted_plan')} ₹
             {t('get_discounted_plan')} ₹
           </Button>
           </Button>
-        </Notification.Action>
-      </Notification>
+        }
+      />
     )
     )
   } else if (variant === 'modal') {
   } else if (variant === 'modal') {
     return (
     return (

+ 8 - 6
services/web/frontend/js/features/project-list/components/notifications/ads/latam-banner.tsx

@@ -83,8 +83,10 @@ export default function LATAMBanner() {
   } = LATAM_CURRENCIES[currency as keyof typeof LATAM_CURRENCIES]
   } = LATAM_CURRENCIES[currency as keyof typeof LATAM_CURRENCIES]
 
 
   return (
   return (
-    <Notification bsStyle="info" onDismiss={() => handleDismiss()}>
-      <Notification.Body>
+    <Notification
+      bsStyle="info"
+      onDismiss={() => handleDismiss()}
+      body={
         <Trans
         <Trans
           i18nKey="latam_discount_offer"
           i18nKey="latam_discount_offer"
           components={[<b />]} // eslint-disable-line react/jsx-key
           components={[<b />]} // eslint-disable-line react/jsx-key
@@ -92,8 +94,8 @@ export default function LATAMBanner() {
           shouldUnescape
           shouldUnescape
           tOptions={{ interpolation: { escapeValue: true } }}
           tOptions={{ interpolation: { escapeValue: true } }}
         />
         />
-      </Notification.Body>
-      <Notification.Action>
+      }
+      action={
         <Button
         <Button
           bsStyle="info"
           bsStyle="info"
           bsSize="sm"
           bsSize="sm"
@@ -102,7 +104,7 @@ export default function LATAMBanner() {
         >
         >
           {t('get_discounted_plan')}
           {t('get_discounted_plan')}
         </Button>
         </Button>
-      </Notification.Action>
-    </Notification>
+      }
+    />
   )
   )
 }
 }

+ 7 - 7
services/web/frontend/js/features/project-list/components/notifications/groups-and-enterprise-banner.tsx

@@ -62,11 +62,11 @@ export default function GroupsAndEnterpriseBanner() {
   }
   }
 
 
   return (
   return (
-    <Notification bsStyle="info" onDismiss={handleClose}>
-      <Notification.Body>
-        <BannerContent variant={groupsAndEnterpriseBannerVariant} />
-      </Notification.Body>
-      <Notification.Action>
+    <Notification
+      bsStyle="info"
+      onDismiss={handleClose}
+      body={<BannerContent variant={groupsAndEnterpriseBannerVariant} />}
+      action={
         <a
         <a
           className="pull-right btn btn-info btn-sm"
           className="pull-right btn btn-info btn-sm"
           href={contactSalesUrl}
           href={contactSalesUrl}
@@ -76,8 +76,8 @@ export default function GroupsAndEnterpriseBanner() {
         >
         >
           {t('contact_sales')}
           {t('contact_sales')}
         </a>
         </a>
-      </Notification.Action>
-    </Notification>
+      }
+    />
   )
   )
 }
 }
 
 

+ 67 - 13
services/web/frontend/js/features/project-list/components/notifications/notification.tsx

@@ -4,21 +4,44 @@ import Body from './body'
 import Action from './action'
 import Action from './action'
 import Close from '../../../../shared/components/close'
 import Close from '../../../../shared/components/close'
 import classnames from 'classnames'
 import classnames from 'classnames'
+import NewNotification, {
+  NotificationType,
+} from '@/shared/components/notification'
+import getMeta from '@/utils/meta'
 
 
 type NotificationProps = {
 type NotificationProps = {
   bsStyle: AlertProps['bsStyle']
   bsStyle: AlertProps['bsStyle']
-  children: React.ReactNode
+  children?: React.ReactNode
+  body?: React.ReactNode
+  action?: React.ReactElement
   onDismiss?: AlertProps['onDismiss']
   onDismiss?: AlertProps['onDismiss']
   className?: string
   className?: string
 }
 }
 
 
+/**
+ * Renders either a legacy-styled notification using Boostrap `Alert`, or a new-styled notification using
+ * the shared `Notification` component.
+ *
+ * The content of the notification is provided either with `children` (keeping backwards compatibility),
+ * or a `body` prop (along with an optional `action`).
+ *
+ * When the content is provided via `body` prop the notification is rendered with the new Notification component
+ * if `ol-newNotificationStyle` meta is set to true.
+ */
 function Notification({
 function Notification({
   bsStyle,
   bsStyle,
   children,
   children,
   onDismiss,
   onDismiss,
   className,
   className,
+  body,
+  action,
   ...props
   ...props
 }: NotificationProps) {
 }: NotificationProps) {
+  const newNotificationStyle = getMeta(
+    'ol-newNotificationStyle',
+    false
+  ) as boolean
+
   const [show, setShow] = useState(true)
   const [show, setShow] = useState(true)
 
 
   const handleDismiss = () => {
   const handleDismiss = () => {
@@ -33,18 +56,49 @@ function Notification({
     return null
     return null
   }
   }
 
 
-  return (
-    <li className={classnames('notification-entry', className)} {...props}>
-      <Alert bsStyle={bsStyle}>
-        {children}
-        {onDismiss ? (
-          <div className="notification-close">
-            <Close onDismiss={handleDismiss} />
-          </div>
-        ) : null}
-      </Alert>
-    </li>
-  )
+  if (newNotificationStyle && body) {
+    const newNotificationType = (
+      bsStyle === 'danger' ? 'error' : bsStyle
+    ) as NotificationType
+    return (
+      <NewNotification
+        type={newNotificationType}
+        isDismissible={onDismiss != null}
+        onDismiss={handleDismiss}
+        content={body as React.ReactElement}
+        action={action}
+      />
+    )
+  }
+
+  if (body) {
+    return (
+      <li className={classnames('notification-entry', className)} {...props}>
+        <Alert bsStyle={bsStyle}>
+          <Body>{body}</Body>
+          {action && <Action>{action}</Action>}
+          {onDismiss ? (
+            <div className="notification-close">
+              <Close onDismiss={handleDismiss} />
+            </div>
+          ) : null}
+        </Alert>
+      </li>
+    )
+  } else {
+    return (
+      <li className={classnames('notification-entry', className)} {...props}>
+        <Alert bsStyle={bsStyle}>
+          {children}
+          {onDismiss ? (
+            <div className="notification-close">
+              <Close onDismiss={handleDismiss} />
+            </div>
+          ) : null}
+        </Alert>
+      </li>
+    )
+  }
 }
 }
 
 
 Notification.Body = Body
 Notification.Body = Body

+ 5 - 6
services/web/frontend/js/features/project-list/components/notifications/writefull-promo-banner.tsx

@@ -41,15 +41,14 @@ function WritefullPromoBanner({
       bsStyle="info"
       bsStyle="info"
       onDismiss={handleClose}
       onDismiss={handleClose}
       className="centered-alert"
       className="centered-alert"
-    >
-      <Notification.Body>
+      body={
         <span>
         <span>
           Get <b>10% off</b> Writefull premium—AI-based language feedback and
           Get <b>10% off</b> Writefull premium—AI-based language feedback and
           TeXGPT to help you write great papers faster. Use code:{' '}
           TeXGPT to help you write great papers faster. Use code:{' '}
           <b>OVERLEAF10</b>
           <b>OVERLEAF10</b>
         </span>
         </span>
-      </Notification.Body>
-      <Notification.Action>
+      }
+      action={
         <a
         <a
           className="pull-right btn btn-info btn-sm"
           className="pull-right btn btn-info btn-sm"
           href="https://my.writefull.com/overleaf-invite?code=OVERLEAF10"
           href="https://my.writefull.com/overleaf-invite?code=OVERLEAF10"
@@ -66,8 +65,8 @@ function WritefullPromoBanner({
           />
           />
           <span>Get Writefull for Overleaf</span>
           <span>Get Writefull for Overleaf</span>
         </a>
         </a>
-      </Notification.Action>
-    </Notification>
+      }
+    />
   )
   )
 }
 }
 
 

+ 1 - 1
services/web/frontend/js/shared/components/notification.tsx

@@ -3,7 +3,7 @@ import React, { ReactElement, useState } from 'react'
 import { useTranslation } from 'react-i18next'
 import { useTranslation } from 'react-i18next'
 import MaterialIcon from './material-icon'
 import MaterialIcon from './material-icon'
 
 
-type NotificationType = 'info' | 'success' | 'warning' | 'error'
+export type NotificationType = 'info' | 'success' | 'warning' | 'error'
 
 
 type NotificationProps = {
 type NotificationProps = {
   action?: React.ReactElement
   action?: React.ReactElement