Parcourir la source

Merge pull request #28050 from overleaf/dp-3-way-feature-flag

Add 3 way editor-redesign-new-users feature flag in preparation for new user split test

GitOrigin-RevId: adc1ce43277647208a2f0098bf9dcf2101a86f65
David il y a 1 an
Parent
commit
1fe9277b5b

+ 1 - 1
services/web/app/src/Features/Project/ProjectController.js

@@ -379,8 +379,8 @@ const _ProjectController = {
       'overleaf-assist-bundle',
       'word-count-client',
       'editor-popup-ux-survey',
-      'new-editor-error-logs-redesign',
       'client-side-references',
+      'editor-redesign-new-users',
     ].filter(Boolean)
 
     const getUserValues = async userId =>

+ 1 - 0
services/web/frontend/extracted-translations.json

@@ -980,6 +980,7 @@
   "log_entry_maximum_entries": "",
   "log_entry_maximum_entries_enable_stop_on_first_error": "",
   "log_entry_maximum_entries_see_full_logs": "",
+  "log_entry_maximum_entries_see_full_logs_new": "",
   "log_entry_maximum_entries_title": "",
   "log_hint_extra_info": "",
   "log_in": "",

+ 5 - 0
services/web/frontend/js/features/ide-redesign/components/pdf-preview/pdf-preview-hybrid-toolbar.tsx

@@ -5,9 +5,13 @@ import PdfCompileButton from '@/features/pdf-preview/components/pdf-compile-butt
 import PdfHybridDownloadButton from '@/features/pdf-preview/components/pdf-hybrid-download-button'
 import { DetachedSynctexControl } from '@/features/pdf-preview/components/detach-synctex-control'
 import SwitchToEditorButton from '@/features/pdf-preview/components/switch-to-editor-button'
+import PdfHybridLogsButton from '@/features/pdf-preview/components/pdf-hybrid-logs-button'
+import { useAreNewErrorLogsEnabled } from '../../utils/new-editor-utils'
 
 function PdfPreviewHybridToolbar() {
   const { t } = useTranslation()
+  const newErrorLogs = useAreNewErrorLogsEnabled()
+
   // TODO: add detached pdf logic
   return (
     <OLButtonToolbar
@@ -16,6 +20,7 @@ function PdfPreviewHybridToolbar() {
     >
       <div className="toolbar-pdf-left">
         <PdfCompileButton />
+        {!newErrorLogs && <PdfHybridLogsButton />}
         <PdfHybridDownloadButton />
       </div>
       <div className="toolbar-pdf-right">

+ 1 - 8
services/web/frontend/js/features/ide-redesign/components/rail/rail-panel.tsx

@@ -1,4 +1,3 @@
-import { useFeatureFlag } from '@/shared/context/split-test-context'
 import { Panel } from 'react-resizable-panels'
 import { useRailContext } from '../../contexts/rail-context'
 import classNames from 'classnames'
@@ -20,8 +19,6 @@ export default function RailPanel({
   const { selectedTab, panelRef, handlePaneExpand, handlePaneCollapse } =
     useRailContext()
 
-  const newErrorlogs = useFeatureFlag('new-editor-error-logs-redesign')
-
   const prevTab = usePreviousValue(selectedTab)
 
   const tabHasChanged = useMemo(() => {
@@ -36,11 +33,7 @@ export default function RailPanel({
 
   return (
     <Panel
-      id={
-        newErrorlogs
-          ? `ide-redesign-sidebar-panel-${isHistoryView ? 'file-tree' : selectedTab}`
-          : 'ide-redesign-sidebar-panel'
-      }
+      id={`ide-redesign-sidebar-panel-${isHistoryView ? 'file-tree' : selectedTab}`}
       className={classNames({ hidden: isReviewPanelOpen })}
       order={1}
       defaultSize={15}

+ 4 - 4
services/web/frontend/js/features/ide-redesign/components/rail/rail.tsx

@@ -18,8 +18,6 @@ import {
 import { sendSearchEvent } from '@/features/event-tracking/search-events'
 import ErrorLogsPanel from '../error-logs/error-logs-panel'
 import { useDetachCompileContext as useCompileContext } from '@/shared/context/detach-compile-context'
-import OldErrorPane from '../error-logs/old-error-pane'
-import { useFeatureFlag } from '@/shared/context/split-test-context'
 import { useProjectContext } from '@/shared/context/project-context'
 import { useCommandProvider } from '@/features/ide-react/hooks/use-command-provider'
 import RailHelpDropdown from './rail-help-dropdown'
@@ -31,6 +29,7 @@ import RailResizeHandle from './rail-resize-handle'
 import RailModals from './rail-modals'
 import RailOverflowDropdown from './rail-overflow-dropdown'
 import useRailOverflow from '../../hooks/use-rail-overflow'
+import { useAreNewErrorLogsEnabled } from '../../utils/new-editor-utils'
 
 export const RailLayout = () => {
   const { sendEvent } = useEditorAnalytics()
@@ -46,7 +45,7 @@ export const RailLayout = () => {
 
   const isHistoryView = view === 'history'
 
-  const newErrorlogs = useFeatureFlag('new-editor-error-logs-redesign')
+  const newErrorlogs = useAreNewErrorLogsEnabled()
 
   const railTabs: RailElement[] = useMemo(
     () => [
@@ -92,9 +91,10 @@ export const RailLayout = () => {
         key: 'errors',
         icon: 'report',
         title: t('error_log'),
-        component: newErrorlogs ? <ErrorLogsPanel /> : <OldErrorPane />,
+        component: <ErrorLogsPanel />,
         indicator: <ErrorIndicator />,
         disabled: errorLogsDisabled,
+        hide: !newErrorlogs,
       },
     ],
     [t, features.trackChangesVisible, newErrorlogs, errorLogsDisabled, view]

+ 42 - 2
services/web/frontend/js/features/ide-redesign/utils/new-editor-utils.ts

@@ -1,8 +1,43 @@
 import { useUserSettingsContext } from '@/shared/context/user-settings-context'
-import { isSplitTestEnabled } from '@/utils/splitTestUtils'
+import getMeta from '@/utils/meta'
+import { isSplitTestEnabled, getSplitTestVariant } from '@/utils/splitTestUtils'
+
+// TODO: change this when we have a launch date
+const NEW_USER_CUTOFF_DATE = new Date('2100-01-01')
+
+const isNewUser = () => {
+  const user = getMeta('ol-user')
+
+  if (!user.signUpDate) return false
+
+  const createdAt = new Date(user.signUpDate)
+  return createdAt > NEW_USER_CUTOFF_DATE
+}
 
 export const canUseNewEditor = () => {
-  return isSplitTestEnabled('editor-redesign')
+  const newUserTestVariant = getSplitTestVariant('editor-redesign-new-users')
+
+  const canUseNewEditorViaPrimaryFeatureFlag =
+    isSplitTestEnabled('editor-redesign')
+  const canUseNewEditorViaNewUserFeatureFlag =
+    isNewUser() &&
+    (newUserTestVariant === 'new-editor' ||
+      newUserTestVariant === 'new-editor-old-logs')
+  return (
+    canUseNewEditorViaPrimaryFeatureFlag || canUseNewEditorViaNewUserFeatureFlag
+  )
+}
+
+const canUseNewLogs = () => {
+  const newUserTestVariant = getSplitTestVariant('editor-redesign-new-users')
+  const canUseNewLogsViaPrimaryFeatureFlag =
+    isSplitTestEnabled('editor-redesign')
+  const canUseNewLogsViaNewUserFeatureFlag =
+    isNewUser() && newUserTestVariant === 'new-editor'
+
+  return (
+    canUseNewLogsViaPrimaryFeatureFlag || canUseNewLogsViaNewUserFeatureFlag
+  )
 }
 
 export const useIsNewEditorEnabled = () => {
@@ -11,3 +46,8 @@ export const useIsNewEditorEnabled = () => {
   const enabled = userSettings.enableNewEditor
   return hasAccess && enabled
 }
+
+export const useAreNewErrorLogsEnabled = () => {
+  const newEditorEnabled = useIsNewEditorEnabled()
+  return newEditorEnabled && canUseNewLogs()
+}

+ 3 - 5
services/web/frontend/js/features/pdf-preview/components/pdf-log-entry.tsx

@@ -5,9 +5,8 @@ import HumanReadableLogsHints from '../../../ide/human-readable-logs/HumanReadab
 import { sendMB } from '@/infrastructure/event-tracking'
 import getMeta from '@/utils/meta'
 import { ErrorLevel, LogEntry, SourceLocation } from '../util/types'
-import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
+import { useAreNewErrorLogsEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
 import NewLogEntry from '@/features/ide-redesign/components/error-logs/log-entry'
-import { useFeatureFlag } from '@/shared/context/split-test-context'
 
 function PdfLogEntry({
   autoExpand,
@@ -71,10 +70,9 @@ function PdfLogEntry({
       [level, onSourceLocationClick, ruleId, sourceLocation]
     )
 
-  const newEditor = useIsNewEditorEnabled()
-  const newErrorlogs = useFeatureFlag('new-editor-error-logs-redesign')
+  const newErrorlogs = useAreNewErrorLogsEnabled()
 
-  if (newEditor && newErrorlogs) {
+  if (newErrorlogs) {
     return (
       <NewLogEntry
         autoExpand={autoExpand}

+ 7 - 3
services/web/frontend/js/features/pdf-preview/components/pdf-preview-pane.tsx

@@ -10,7 +10,10 @@ import CompileTimeWarningUpgradePrompt from './compile-time-warning-upgrade-prom
 import { PdfPreviewProvider } from './pdf-preview-provider'
 import PdfPreviewHybridToolbarNew from '@/features/ide-redesign/components/pdf-preview/pdf-preview-hybrid-toolbar'
 import PdfErrorState from '@/features/ide-redesign/components/pdf-preview/pdf-error-state/pdf-error-state'
-import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
+import {
+  useAreNewErrorLogsEnabled,
+  useIsNewEditorEnabled,
+} from '@/features/ide-redesign/utils/new-editor-utils'
 import importOverleafModules from '../../../../macros/import-overleaf-module.macro'
 import PdfCodeCheckFailedBanner from '@/features/ide-redesign/components/pdf-preview/pdf-code-check-failed-banner'
 import getMeta from '@/utils/meta'
@@ -22,6 +25,7 @@ function PdfPreviewPane() {
     'pdf-empty': !pdfUrl,
   })
   const newEditor = useIsNewEditorEnabled()
+  const newErrorLogs = useAreNewErrorLogsEnabled()
   const pdfPromotions = importOverleafModules('pdfPreviewPromotions') as {
     import: { default: ElementType }
     path: string
@@ -35,7 +39,7 @@ function PdfPreviewPane() {
         ) : (
           <PdfHybridPreviewToolbar />
         )}
-        {newEditor && <PdfCodeCheckFailedBanner />}
+        {newErrorLogs && <PdfCodeCheckFailedBanner />}
         <PdfPreviewMessages>
           {compileTimeout < 60 && <CompileTimeWarningUpgradePrompt />}
         </PdfPreviewMessages>
@@ -44,7 +48,7 @@ function PdfPreviewPane() {
             <PdfViewer />
           </div>
         </Suspense>
-        {newEditor ? <PdfErrorState /> : <PdfLogsViewer />}
+        {newErrorLogs ? <PdfErrorState /> : <PdfLogsViewer />}
         {pdfPromotions.map(({ import: { default: Component }, path }) => (
           <Component key={path} />
         ))}

+ 10 - 2
services/web/frontend/js/features/preview/components/preview-logs-pane-max-entries.tsx

@@ -5,6 +5,7 @@ import { useDetachCompileContext as useCompileContext } from '../../../shared/co
 import { useStopOnFirstError } from '../../../shared/hooks/use-stop-on-first-error'
 import MaterialIcon from '@/shared/components/material-icon'
 import PdfLogEntry from '@/features/pdf-preview/components/pdf-log-entry'
+import { useAreNewErrorLogsEnabled } from '@/features/ide-redesign/utils/new-editor-utils'
 
 function PreviewLogsPaneMaxEntries({
   totalEntries,
@@ -39,6 +40,7 @@ function PreviewLogsPaneMaxEntriesContent({
 }: {
   hasErrors?: boolean
 }) {
+  const newLogs = useAreNewErrorLogsEnabled()
   const { t } = useTranslation()
   const { startCompile, stoppedOnFirstError, setAnimateCompileDropdownArrow } =
     useCompileContext()
@@ -76,7 +78,11 @@ function PreviewLogsPaneMaxEntriesContent({
             ]}
           />{' '}
         </p>
-        <p>{t('log_entry_maximum_entries_see_full_logs')}</p>
+        <p>
+          {newLogs
+            ? t('log_entry_maximum_entries_see_full_logs_new')
+            : t('log_entry_maximum_entries_see_full_logs')}
+        </p>
       </>
     )
   }
@@ -86,7 +92,9 @@ function PreviewLogsPaneMaxEntriesContent({
       <MaterialIcon type="lightbulb" className="align-middle" />
       &nbsp;
       <strong>{t('tip')}: </strong>
-      {t('log_entry_maximum_entries_see_full_logs')}
+      {newLogs
+        ? t('log_entry_maximum_entries_see_full_logs_new')
+        : t('log_entry_maximum_entries_see_full_logs')}
     </p>
   )
 }

+ 1 - 0
services/web/locales/en.json

@@ -1266,6 +1266,7 @@
   "log_entry_maximum_entries": "Maximum log entries limit hit",
   "log_entry_maximum_entries_enable_stop_on_first_error": "Try to fix the first error and recompile. Often one error causes many later error messages. You can <0>Enable “Stop on first error”</0> to focus on fixing errors. We recommend fixing errors as soon as possible; letting them accumulate may lead to hard-to-debug and fatal errors. <1>Learn more</1>",
   "log_entry_maximum_entries_see_full_logs": "If you need to see the full logs, you can still download them or view the raw logs below.",
+  "log_entry_maximum_entries_see_full_logs_new": "If you need to see the full logs, you can still view the raw logs at the bottom of this pane or download them using the button at the top.",
   "log_entry_maximum_entries_title": "__total__ log messages total. Showing the first __displayed__",
   "log_hint_extra_info": "Learn more",
   "log_in": "Log in",