From 48337b2e2ca84da0cdf675ada0e8e945fbe64a10 Mon Sep 17 00:00:00 2001 From: Mathias Jakobsen Date: Mon, 2 Jun 2025 15:27:18 +0100 Subject: [PATCH] Merge pull request #25808 from overleaf/mj-ide-full-project-search [web] Editor redesign: Add full project search GitOrigin-RevId: b4327c4ba0ddd7387ec8d6640e31200ca0fe4a6e --- services/web/config/settings.defaults.js | 1 + .../web/frontend/extracted-translations.json | 1 + ...alSymbolsRoundedUnfilledPartialSlice.woff2 | Bin 4384 -> 4444 bytes .../material-symbols/unfilled-symbols.mjs | 3 ++- .../features/event-tracking/search-events.ts | 2 +- .../components/full-project-search-panel.tsx | 19 +++++++++++++++ .../features/ide-redesign/components/rail.tsx | 23 ++++++++++++++++-- .../ide-redesign/contexts/rail-context.tsx | 1 + .../components/codemirror-search-form.tsx | 5 +--- .../components/full-project-search-button.tsx | 12 +++++++-- services/web/locales/en.json | 1 + 11 files changed, 58 insertions(+), 10 deletions(-) create mode 100644 services/web/frontend/js/features/ide-redesign/components/full-project-search-panel.tsx diff --git a/services/web/config/settings.defaults.js b/services/web/config/settings.defaults.js index a7ff970ef0..d8892e70ff 100644 --- a/services/web/config/settings.defaults.js +++ b/services/web/config/settings.defaults.js @@ -996,6 +996,7 @@ module.exports = { toastGenerators: [], editorSidebarComponents: [], fileTreeToolbarComponents: [], + fullProjectSearchPanel: [], integrationPanelComponents: [], referenceSearchSetting: [], }, diff --git a/services/web/frontend/extracted-translations.json b/services/web/frontend/extracted-translations.json index 09c2ba90dc..20459e0ed6 100644 --- a/services/web/frontend/extracted-translations.json +++ b/services/web/frontend/extracted-translations.json @@ -1292,6 +1292,7 @@ "project_ownership_transfer_confirmation_2": "", "project_renamed_or_deleted": "", "project_renamed_or_deleted_detail": "", + "project_search": "", "project_search_file_count": "", "project_search_file_count_plural": "", "project_search_result_count": "", diff --git a/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 b/services/web/frontend/fonts/material-symbols/MaterialSymbolsRoundedUnfilledPartialSlice.woff2 index df942df17688781db3c188df5a20253919ec02fc..8e72799b077bd442cf7211bd1488813826bc9018 100644 GIT binary patch literal 4444 zcmV-i5u@&RPew8T0RR9101;dO4gdfE03%=k01*TL0RR9100000000000000000000 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 literal 4384 zcmV+*5#R22Pew8T0RR9101+Sn4gdfE03zG~01(Ik0RR9100000000000000000000 z0000ShYAK@KT}jeRAK;vL=gxIuvn=Z3t|8PHUcCAVgw)sg$@TG3W^Q4{`v0*&wp#L_szlwpjp8DY*JuwfNVr`*{CYCs;931mouF&$uuKMA_xKB z%aUe+T_Di3ta;5zus{K(TgzVi6kz961poiI>0fA(CXisQ=T+R&rFCiw^-R?0IX@E% zGtZ2<=^y^R-=7Fxu`O}kh$XGPB%BBO3-(tKfL%F@06tVt;KbdRsz|H=c1e|VU&XwB z?$Z_k9Ui(9t|V(rjr-a6lHZrj`;f!X5vBOy0FxAmUF&+)M4(#N@dUyF>FO#`DXT<( z#$4Y+Mr&KY{1+MF6UigMabsN%0u=FCjoQ2a=vk`wuRMQ96_cUVD?~iKf9DqYBUv2G zBnK$@LosvlkVoVLdC8>DU%qgY!(?=GE~Y|(F#|IC#KeqAWNFKk2yqG62($@0!SS@U zGWrZ=6&XWj{NND@ias`7@(9OE(D+P=F{lwHI8?=v5o5*xmqh{%ODgi@u(=TuAYsh_ zCj3Jq#w?&2Gbcw|p(107C#YpUz(@wFII{C#d8%lJB%~5r$LNfZ5fkA9mghW??|;My zlg((_6h(!J&qNpvEE84ONdSRIBiBiN+JM>`pBqbIpXXo9wrBw z)1`=oxsFhMOz*}L=!QL0+84#J|o9V9&Ia-3ocYs#JF-Q^?Y|L#t|`|l6Vj}QK~*?!OmIVTe^NwJBUk}`yA|Fj`L!)pd;nbUJ&|H z8!8o~k+w5glW6=oLfK0Q;f;#Hth$v#QfjAA4yCiuccSEH=>!}+10F%acXTD4xFC1S zZa@-6Q5=m`73(;Yk#t?xRoRebS=|cscE-x;$ZXb-bZMxrTl#! z1BEg0_;wK4HXLk0g1?pU?I5ykIM{*&e`^g0i~+F01w5w)ry#{n6OErll7HewO~O=A zU7TM)9uvrDCq#?|LT^*?vr?7Y!LG0xOkDg!lFJA-_;4c)SFxh=T(1`)V13^_-9C%uUf|8N$fPG+xE+9X*fiNp2;XSBQ5!;jtKozjutz9( z*g<(%W89R}>MR002SmB{pLy(<>nsLjVpA^~-1qPJzfy6NR5df`0qDw>HjJQn`W_fX7gueN3 z(u8z;P576CNT9UW+NsJ@6%?rDM|GFmfeCryJdwFGysBufyl(I)*iZ-1B6T_h4z{%b z@_m4vRQ=W|1vP^J;7NX=1^)%aVU?4jh$pU5z4-A|!wHMk$ZfkheS+;Z;>QuiVL7;yD<4zN2+GVL3QJCrxtb zBv=lva(9{IY&q6VxGO?D9|ZGI_JQB>k4*OD;1qzuPfuDpi3G-8ToIpZR|VUGcRSe$ zLt4PRp=0ujwRu5&6;XwEgeyAR3kuuv!FP~i=NIG;e~AQt$JnMYEYpd?XtRJ;)1JOE zr%D_fhDb;fyQYmq*1C~zgu#l` zw7HXG$S%;wSDXIHwoyI3?P7sR0m zFO^CoNTE9Mo$^$9B85mPzCc_|TH)516(Pn&N{K?G z28Fc}WVQO@y?|`1Y)xcq)Cjyj9FH`p-Iga7R)y6>VD4gEg7?QgB)By;0CN{Nny!gF zN*Jx2Zn^>`W=qI-qf$&EwyHIe3Eaht`qxxe<0!bLv7*t}u3hul_AmrFh&>JC>eXmO z$!_XI(+U@B!Qt|*T)EQN1#d0KE8B6lyaBIw$2|?hTdBhuJTSL9yd7`HTd)?g4Qs<& z@z!#Y8c@KzdiJWwxPH0BmdYw>Ng&GJULVwn1K|hm54SW~n*Td?+|qb_YO|%OW__ap zVmZX42MUrVNt&FOvOz3EG4H?QD;^*o`RN}3fF1xIGb2TQd22aIPs~iZG8-Pi^8B82 zDoUVKXf>sxRwET91ie;uBk+Y{uwk>YuFzOiTlb-}N!_XgbqC-&r`j3u31&nxPsFrM z5SM2KXrt!`03hbRD@l{9s?usz1`)d;>kA^j7j-1EY+^@|KGDRo9f?JHQ+9|+UzFI< z%Cs#rX6x25lch$-er_hX(s~&LSIXinBBk$jyLDvsX}N;-FJ9wR(Oi5P3u0u{lL16I`%;It^_Zb=kfw^^Dv%S;E7wunQP_+ z;s$feY`!(ud~=v3>sEHeY|=ruTQ?mVhTX-c2=oPw4h|07K;3SgQ5HMW=wKXZ?~p4{ zdT?r}Bj3lQbEDp8BFhOe+;zkw>ng+d4)LGWcRS=u^8Ph?EC&kRp@wWf;&G^ zoh#x|FT^7!f){4ad{rY5k5)#Gi|y9ET3Pl5C&rPqY#NLsZ3nn&$4{U`uDQE5J6VwI zbTxPVjo)p2pL6K*KYc}cg%&8GzMkG9mv5m#6>wLr-WgH@aVz&D9$AWjMD593GT2`1 zm0pxU)m}~QB6uM;H%?f3%6uKVqxcGg0RVOxaqP(#T9Rwd9_v+u1@TIs31~;A$dA%T zkG3`1*z~G6Q(m?0H!9Y5jQJ5)c;^9WI* zUhIq`xgj30B_;F`mu27XX4 zmx8OoZ-B4A$0j>0)-KoczSFmHjtRX_%dy+o9016#=>hW*k76&a^aOyremQ{$^XBf= z-n{&L`r>rm9l{?QfwcJO{iRD=SB<@U>3o?ip9Y#;9=BB5#&Q_A&ISAGH=X$W!7obO z{!+a@ocMgmS0A!^AU$+;{=?&{>oU1f9#+zC;hQPA&~M4ZovvZ&X7l6=l_?pX z;Hed~T0v_!=YH=`pI5iGrlj2UyQ{wIdsi|OmN&TFpza$=6tF8pa~+?&8t$7lykXZ; zXM3g6-g)V+hU~lT)stMu(3LDv5ZYI*zwuie&v1&8Cj4MJJV(CT%uRA_v3&wAQX~71nnd&|_eaSW94DKu{iZU-PwgVRpCpRQkMV zM5m(6ZVRg#)?}|OF3pVd;1|IN+m6hH1^at=2YZIifWOL-v-UNy0WDa3KyyvZtbHV< zL8HVyGDeAuT^IPpnG{*VJoyF_mJ(19eW7U4&cxLJ@YUh$^UUB0N~IWz4e|5Ae@1ia`b`?8HKhc#qpZU zV#ggKyc*QXUE;z|C2a^jMMg>T=1mv6I>+ym9ax*{)SMmCq7dYM(+c1avv#!>K@r83 z0w_q8P8EV6RXSA&z#+B}FyD3S*FpSPp1^Ty926c&F1U<>G+6#k6_Z51sg}c-{|w2( zH~+%l{!5Z{`44cI=*E(yOGLvYXS$@x7I>z-{&V@D+QFa8>uWz(_p9yyxw;zEe2nZ< z>pQlsx%DX7uhxI87T{3IJwr3h#WRFL@dycb$?-?;a7+=*ETshiVD^DOtHa z$;pRwk`K`%8EkeGm3Am8`ME`s>L*X|N_qdks8VT6nz2sVT;A^GVU^|HYD%i7-L2Nh zw?k1z=-$NpKh_GOrQ@Yp!`_=qeNMjmLAH6uC7Qg;CKqF~M2|7BKe+`>MVperGi70i zbzU&5GK|28roDJ+@&3XFB9;haR^|n_TZ6rldv|40{?qa$8TlS!e;Ur7=B0e+bi+z< zqr7pwXxbufk(VqL>+hVd-#p@y{Akk%MxX5-nHREXpE|NBW=nI-(7o!i+>oK?x(TSw zGw1PQZ2Ib{9Rax+L2{)$?_&K7b!0?%>)2-fpTM%GnLQ~Bv?)G@0B!lPV#DN*sXjaW z3NlyDXo<|KOh_xM8HiXv1poj9KzyG0>eQ|CP2=Lf4i}~C0E21ocK{5gi=qEN|34@_ zlAZxW5dje3r|Ejq_5Yv$f0Z8nDD5J(1?f8Xxy~Bawi(w5ybi(Um-VlsFrQ|+^fV92 z3HPL}<1_^m$BdUJiY5pHFrCo^l5IgRf`x$29`B_-hJ8PShUF2&Y8F&oRu*LlZ_Z8Yo1e z6%Pj7RAIq^4Lj`=q0){6leD*nvg7w+A&XWFn6Z$FW02BK0S4NQRvc=z%jm&_5hbbL zMkxv%c$IB4p#)=U0hEGfql4Q9TB+1!ZQ@fac+n6_Akl;og*-2fn3qNbHDYuc2j2TW zjx35OB8xc7JuAi_XxHG6PIWhZ-;} awAp~2GYtG2#iPx+myzd%{|nE^D**u2R#deB diff --git a/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs b/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs index baefac05aa..1c41421910 100644 --- a/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs +++ b/services/web/frontend/fonts/material-symbols/unfilled-symbols.mjs @@ -10,6 +10,7 @@ export default /** @type {const} */ ([ 'create_new_folder', 'delete', 'description', + 'error', 'experiment', 'forum', 'help', @@ -20,10 +21,10 @@ export default /** @type {const} */ ([ 'picture_as_pdf', 'rate_review', 'report', + 'search', 'settings', 'space_dashboard', 'table_chart', 'upload_file', 'web_asset', - 'error', ]) diff --git a/services/web/frontend/js/features/event-tracking/search-events.ts b/services/web/frontend/js/features/event-tracking/search-events.ts index cd9ff4b8ba..630d07aeaa 100644 --- a/services/web/frontend/js/features/event-tracking/search-events.ts +++ b/services/web/frontend/js/features/event-tracking/search-events.ts @@ -6,7 +6,7 @@ type SearchEventSegmentation = { searchType: 'full-project' } & ( | { method: 'keyboard' } - | { method: 'button'; location: 'toolbar' | 'search-form' } + | { method: 'button'; location: 'toolbar' | 'search-form' | 'rail' } )) | ({ searchType: 'document' diff --git a/services/web/frontend/js/features/ide-redesign/components/full-project-search-panel.tsx b/services/web/frontend/js/features/ide-redesign/components/full-project-search-panel.tsx new file mode 100644 index 0000000000..926341ce89 --- /dev/null +++ b/services/web/frontend/js/features/ide-redesign/components/full-project-search-panel.tsx @@ -0,0 +1,19 @@ +import { ElementType } from 'react' +import importOverleafModules from '../../../../macros/import-overleaf-module.macro' + +const componentModule = importOverleafModules('fullProjectSearchPanel')[0] as + | { + import: { default: ElementType } + path: string + } + | undefined + +export const FullProjectSearchPanel = () => { + if (!componentModule) { + return null + } + const FullProjectSearch = componentModule.import.default + return +} + +export const hasFullProjectSearch = Boolean(componentModule) diff --git a/services/web/frontend/js/features/ide-redesign/components/rail.tsx b/services/web/frontend/js/features/ide-redesign/components/rail.tsx index d6e1112536..9bd70ac4bb 100644 --- a/services/web/frontend/js/features/ide-redesign/components/rail.tsx +++ b/services/web/frontend/js/features/ide-redesign/components/rail.tsx @@ -34,6 +34,11 @@ import OLTooltip from '@/features/ui/components/ol/ol-tooltip' import OLIconButton from '@/features/ui/components/ol/ol-icon-button' import { useChatContext } from '@/features/chat/context/chat-context' import { useEditorAnalytics } from '@/shared/hooks/use-editor-analytics' +import { + FullProjectSearchPanel, + hasFullProjectSearch, +} from './full-project-search-panel' +import { sendSearchEvent } from '@/features/event-tracking/search-events' type RailElement = { icon: AvailableUnfilledIcon @@ -106,6 +111,13 @@ export const RailLayout = () => { title: t('file_tree'), component: , }, + { + key: 'full-project-search', + icon: 'search', + title: t('project_search'), + component: , + hide: !hasFullProjectSearch, + }, { key: 'integrations', icon: 'integration_instructions', @@ -170,10 +182,17 @@ export const RailLayout = () => { // Attempting to open a non-existent tab return } - const keyOrDefault = key ?? 'file-tree' + const keyOrDefault = (key ?? 'file-tree') as RailTabKey // Change the selected tab and make sure it's open - openTab(keyOrDefault as RailTabKey) + openTab(keyOrDefault) sendEvent('rail-click', { tab: keyOrDefault }) + if (keyOrDefault === 'full-project-search') { + sendSearchEvent('search-open', { + searchType: 'full-project', + method: 'button', + location: 'rail', + }) + } if (key === 'chat') { markMessagesAsRead() diff --git a/services/web/frontend/js/features/ide-redesign/contexts/rail-context.tsx b/services/web/frontend/js/features/ide-redesign/contexts/rail-context.tsx index c02d17fb9b..85ec482fc0 100644 --- a/services/web/frontend/js/features/ide-redesign/contexts/rail-context.tsx +++ b/services/web/frontend/js/features/ide-redesign/contexts/rail-context.tsx @@ -19,6 +19,7 @@ export type RailTabKey = | 'review-panel' | 'chat' | 'errors' + | 'full-project-search' export type RailModalKey = 'keyboard-shortcuts' | 'contact-us' | 'dictionary' diff --git a/services/web/frontend/js/features/source-editor/components/codemirror-search-form.tsx b/services/web/frontend/js/features/source-editor/components/codemirror-search-form.tsx index 90a968add6..a65232f94d 100644 --- a/services/web/frontend/js/features/source-editor/components/codemirror-search-form.tsx +++ b/services/web/frontend/js/features/source-editor/components/codemirror-search-form.tsx @@ -36,7 +36,6 @@ import { getStoredSelection, setStoredSelection } from '../extensions/search' import { debounce } from 'lodash' import { EditorSelection, EditorState } from '@codemirror/state' import { sendSearchEvent } from '@/features/event-tracking/search-events' -import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils' import { FullProjectSearchButton } from './full-project-search-button' const MATCH_COUNT_DEBOUNCE_WAIT = 100 // the amount of ms to wait before counting matches @@ -82,8 +81,6 @@ const CodeMirrorSearchForm: FC = () => { const inputRef = useRef(null) const replaceRef = useRef(null) - const newEditor = useIsNewEditorEnabled() - const handleInputRef = useCallback((node: HTMLInputElement) => { inputRef.current = node @@ -443,7 +440,7 @@ const CodeMirrorSearchForm: FC = () => { - {!newEditor && } + {position !== null && (
diff --git a/services/web/frontend/js/features/source-editor/components/full-project-search-button.tsx b/services/web/frontend/js/features/source-editor/components/full-project-search-button.tsx index 698204d89c..be02fdbe3c 100644 --- a/services/web/frontend/js/features/source-editor/components/full-project-search-button.tsx +++ b/services/web/frontend/js/features/source-editor/components/full-project-search-button.tsx @@ -12,6 +12,8 @@ import Close from '@/shared/components/close' import useTutorial from '@/shared/hooks/promotions/use-tutorial' import { useEditorContext } from '@/shared/context/editor-context' import getMeta from '@/utils/meta' +import { useIsNewEditorEnabled } from '@/features/ide-redesign/utils/new-editor-utils' +import { useRailContext } from '@/features/ide-redesign/contexts/rail-context' const PROMOTION_SIGNUP_CUT_OFF_DATE = new Date('2025-04-22T00:00:00Z') @@ -19,6 +21,8 @@ export const FullProjectSearchButton = ({ query }: { query: SearchQuery }) => { const view = useCodeMirrorViewContext() const { t } = useTranslation() const { setProjectSearchIsOpen } = useLayoutContext() + const newEditor = useIsNewEditorEnabled() + const { openTab } = useRailContext() const ref = useRef(null) const { inactiveTutorials } = useEditorContext() @@ -44,14 +48,18 @@ export const FullProjectSearchButton = ({ query }: { query: SearchQuery }) => { } const openFullProjectSearch = useCallback(() => { - setProjectSearchIsOpen(true) + if (newEditor) { + openTab('full-project-search') + } else { + setProjectSearchIsOpen(true) + } closeSearchPanel(view) window.setTimeout(() => { window.dispatchEvent( new CustomEvent('editor:full-project-search', { detail: query }) ) }, 200) - }, [setProjectSearchIsOpen, query, view]) + }, [setProjectSearchIsOpen, query, view, newEditor, openTab]) const onClick = useCallback(() => { sendSearchEvent('search-open', { diff --git a/services/web/locales/en.json b/services/web/locales/en.json index 445fb62c8b..2efd23fd9f 100644 --- a/services/web/locales/en.json +++ b/services/web/locales/en.json @@ -1708,6 +1708,7 @@ "project_ownership_transfer_confirmation_2": "This action cannot be undone. The new owner will be notified and will be able to change project access settings (including removing your own access).", "project_renamed_or_deleted": "Project Renamed or Deleted", "project_renamed_or_deleted_detail": "This project has either been renamed or deleted by an external data source such as Dropbox. We don’t want to delete your data on Overleaf, so this project still contains your history and collaborators. If the project has been renamed please look in your project list for a new project under the new name.", + "project_search": "Project search", "project_search_file_count": "in __count__ file", "project_search_file_count_plural": "in __count__ files", "project_search_result_count": "__count__ result",