Parcourir la source

Improvement to OLButton loading labels (#28659)

* Create eslint rule for requiring loadingLabel prop when isLoading is specified on OLButton

* Add `loadingLabel` props for OLButton components with `isLoading`

* Clarify loading label and button loading state

GitOrigin-RevId: 89279d5b4c346f9c3b67a59d0db822a2ff04314a
Rebeka Dekany il y a 1 an
Parent
commit
aebff54a6b
28 fichiers modifiés avec 59 ajouts et 6 suppressions
  1. 1 0
      services/web/.eslintrc.js
  2. 12 0
      services/web/frontend/extracted-translations.json
  3. 1 0
      services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-footer.tsx
  4. 6 1
      services/web/frontend/js/features/file-tree/components/modals/file-tree-modal-create-folder.tsx
  5. 6 1
      services/web/frontend/js/features/file-tree/components/modals/file-tree-modal-delete.tsx
  6. 1 0
      services/web/frontend/js/features/group-management/components/managers-table.tsx
  7. 1 0
      services/web/frontend/js/features/group-management/components/members-table/remove-managed-user-modal.tsx
  8. 1 0
      services/web/frontend/js/features/history/components/change-list/add-label-modal.tsx
  9. 1 0
      services/web/frontend/js/features/history/components/change-list/tag-tooltip.tsx
  10. 1 0
      services/web/frontend/js/features/history/components/diff-view/modals/restore-project-modal.tsx
  11. 1 0
      services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-restore-file-button.tsx
  12. 1 0
      services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-restore-file-to-version-button.tsx
  13. 1 0
      services/web/frontend/js/features/pdf-preview/components/detach-compile-button.tsx
  14. 1 0
      services/web/frontend/js/features/project-list/components/modals/create-tag-modal.tsx
  15. 1 0
      services/web/frontend/js/features/project-list/components/modals/delete-tag-modal.tsx
  16. 1 0
      services/web/frontend/js/features/project-list/components/modals/edit-tag-modal.tsx
  17. 2 0
      services/web/frontend/js/features/project-list/components/modals/manage-tag-modal.tsx
  18. 1 0
      services/web/frontend/js/features/project-list/components/new-project-button/modal-content-new-project-form.tsx
  19. 1 0
      services/web/frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirm-affiliation.tsx
  20. 3 0
      services/web/frontend/js/features/settings/components/emails/actions/make-primary/primary-button.tsx
  21. 1 0
      services/web/frontend/js/features/settings/components/emails/add-email/add-new-email-btn.tsx
  22. 1 0
      services/web/frontend/js/features/settings/components/emails/resend-confirmation-code-modal.tsx
  23. 1 0
      services/web/frontend/js/features/subscription/components/dashboard/reactivate-subscription.tsx
  24. 1 0
      services/web/frontend/js/features/subscription/components/dashboard/states/active/confirm-unpause-modal.tsx
  25. 4 1
      services/web/locales/en.json
  26. 5 1
      services/web/modules/user-activate/frontend/js/components/register-form.jsx
  27. 1 1
      services/web/test/frontend/features/project-list/components/notifications.test.tsx
  28. 1 1
      services/web/test/frontend/features/settings/components/emails/emails-section-add-new-email.test.tsx

+ 1 - 0
services/web/.eslintrc.js

@@ -531,6 +531,7 @@ module.exports = {
       rules: {
         '@overleaf/no-unnecessary-trans': 'error',
         '@overleaf/should-unescape-trans': 'error',
+        '@overleaf/require-loading-label': 'error',
 
         // https://astexplorer.net/
         'no-restricted-syntax': [

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

@@ -45,6 +45,7 @@
   "accept_selected_changes": "",
   "accept_terms_and_conditions": "",
   "accepted_invite": "",
+  "accepting": "",
   "access_all_premium_features": "",
   "access_all_premium_features_including_more_collaborators_real_time_track_changes_and_a_longer_compile_time": "",
   "access_denied": "",
@@ -268,6 +269,7 @@
   "cite_faster": "",
   "clear_cached_files": "",
   "clear_search": "",
+  "clearing": "",
   "click_here_to_view_sl_in_lng": "",
   "click_to_unpause": "",
   "clicking_delete_will_remove_sso_config_and_clear_saml_data": "",
@@ -359,6 +361,7 @@
   "create_project_in_github": "",
   "created": "",
   "created_at": "",
+  "creating": "",
   "cross_reference": "",
   "current_file": "",
   "current_password": "",
@@ -646,6 +649,7 @@
   "generate_from_text_or_image": "",
   "generate_tables_and_equations": "",
   "generate_token": "",
+  "generating": "",
   "generic_if_problem_continues_contact_us": "",
   "generic_linked_file_compile_error": "",
   "generic_something_went_wrong": "",
@@ -1393,9 +1397,11 @@
   "recompile_from_scratch": "",
   "recompile_pdf": "",
   "reconfirm_secondary_email": "",
+  "reconfirming": "",
   "reconnect": "",
   "reconnecting": "",
   "reconnecting_in_x_secs": "",
+  "recovering": "",
   "recurly_email_update_needed": "",
   "recurly_email_updated": "",
   "redirect_to_editor": "",
@@ -1417,6 +1423,7 @@
   "refresh_page_after_starting_free_trial": "",
   "refreshing": "",
   "regards": "",
+  "registering": "",
   "reject_change": "",
   "reject_selected_changes": "",
   "relink_your_account": "",
@@ -1471,9 +1478,11 @@
   "restore_file_version": "",
   "restore_project_to_this_version": "",
   "restore_this_version": "",
+  "restoring": "",
   "resync_completed": "",
   "resync_message": "",
   "resync_project_history": "",
+  "resyncing": "",
   "retry_test": "",
   "reverse_x_sort_order": "",
   "revert_pending_plan_change": "",
@@ -1576,6 +1585,7 @@
   "send_first_message": "",
   "send_message": "",
   "send_request": "",
+  "sending": "",
   "server_error": "",
   "server_pro_license_entitlement_line_1": "",
   "server_pro_license_entitlement_line_2": "",
@@ -1721,6 +1731,7 @@
   "subject_area": "",
   "subject_to_additional_vat": "",
   "submit_title": "",
+  "submitting": "",
   "subscribe": "",
   "subscribe_to_find_the_symbols_you_need_faster": "",
   "subscribe_to_plan": "",
@@ -2005,6 +2016,7 @@
   "unlinking": "",
   "unmerge_cells": "",
   "unpause_subscription": "",
+  "unpausing": "",
   "unpublish": "",
   "unpublishing": "",
   "unsubscribe": "",

+ 1 - 0
services/web/frontend/js/features/file-tree/components/file-tree-create/file-tree-modal-create-file-footer.tsx

@@ -77,6 +77,7 @@ export function FileTreeModalCreateFileFooterContent({
           form="create-file"
           disabled={inFlight || !valid}
           isLoading={inFlight}
+          loadingLabel={t('creating')}
         >
           {t('create')}
         </OLButton>

+ 6 - 1
services/web/frontend/js/features/file-tree/components/modals/file-tree-modal-create-folder.tsx

@@ -85,7 +85,12 @@ function FileTreeModalCreateFolder() {
 
       <OLModalFooter>
         {inFlight ? (
-          <OLButton variant="primary" disabled isLoading={inFlight} />
+          <OLButton
+            variant="primary"
+            disabled
+            isLoading={inFlight}
+            loadingLabel={t('creating')}
+          />
         ) : (
           <>
             <OLButton variant="secondary" onClick={handleHide}>

+ 6 - 1
services/web/frontend/js/features/file-tree/components/modals/file-tree-modal-delete.tsx

@@ -59,7 +59,12 @@ function FileTreeModalDelete() {
 
       <OLModalFooter>
         {inFlight ? (
-          <OLButton variant="danger" disabled isLoading />
+          <OLButton
+            variant="danger"
+            disabled
+            isLoading
+            loadingLabel={t('deleting')}
+          />
         ) : (
           <>
             <OLButton variant="secondary" onClick={handleHide}>

+ 1 - 0
services/web/frontend/js/features/group-management/components/managers-table.tsx

@@ -265,6 +265,7 @@ export function ManagersTable({
                           variant="primary"
                           onClick={addManagers}
                           isLoading={inviteUserInflightCount > 0}
+                          loadingLabel={t('adding')}
                         >
                           {t('add')}
                         </OLButton>

+ 1 - 0
services/web/frontend/js/features/group-management/components/members-table/remove-managed-user-modal.tsx

@@ -128,6 +128,7 @@ export default function RemoveManagedUserModal({
             variant="danger"
             disabled={isLoading || isSuccess || !shouldEnableRemoveUserButton}
             isLoading={isLoading}
+            loadingLabel={t('removing')}
           >
             {t('remove_user')}
           </OLButton>

+ 1 - 0
services/web/frontend/js/features/history/components/change-list/add-label-modal.tsx

@@ -118,6 +118,7 @@ function AddLabelModal({ show, setShow, version }: AddLabelModalProps) {
             variant="primary"
             disabled={isLoading || !comment.length}
             isLoading={isLoading}
+            loadingLabel={t('adding')}
           >
             {t('history_add_label')}
           </OLButton>

+ 1 - 0
services/web/frontend/js/features/history/components/change-list/tag-tooltip.tsx

@@ -122,6 +122,7 @@ const ChangeTag = forwardRef<HTMLElement, TagProps>(
                 variant="danger"
                 disabled={isLoading}
                 isLoading={isLoading}
+                loadingLabel={t('deleting')}
                 onClick={localDeleteHandler}
               >
                 {t('history_delete_label')}

+ 1 - 0
services/web/frontend/js/features/history/components/diff-view/modals/restore-project-modal.tsx

@@ -51,6 +51,7 @@ export const RestoreProjectModal = ({
           onClick={onRestore}
           disabled={isRestoring}
           isLoading={isRestoring}
+          loadingLabel={t('restoring')}
         >
           {t('restore')}
         </OLButton>

+ 1 - 0
services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-restore-file-button.tsx

@@ -20,6 +20,7 @@ export default function ToolbarRestoreFileButton({
       size="sm"
       className="history-react-toolbar-restore-file-button"
       isLoading={isLoading}
+      loadingLabel={t('restoring')}
       onClick={() => restoreDeletedFile(selection)}
     >
       {t('restore_file')}

+ 1 - 0
services/web/frontend/js/features/history/components/diff-view/toolbar/toolbar-restore-file-to-version-button.tsx

@@ -37,6 +37,7 @@ function ToolbarRestoreFileToVersionButton({
         variant="secondary"
         size="sm"
         isLoading={isLoading}
+        loadingLabel={t('restoring')}
         onClick={() => setShowConfirmModal(true)}
       >
         {t('restore_file_version')}

+ 1 - 0
services/web/frontend/js/features/pdf-preview/components/detach-compile-button.tsx

@@ -36,6 +36,7 @@ function DetachCompileButton() {
           })}
           size="sm"
           isLoading={compiling}
+          loadingLabel={t('compiling')}
         >
           {t('recompile')}
         </OLButton>

+ 1 - 0
services/web/frontend/js/features/project-list/components/modals/create-tag-modal.tsx

@@ -129,6 +129,7 @@ export default function CreateTagModal({
             status === 'pending' || !tagName?.length || !!validationError
           }
           isLoading={isLoading}
+          loadingLabel={t('creating')}
         >
           {t('create')}
         </OLButton>

+ 1 - 0
services/web/frontend/js/features/project-list/components/modals/delete-tag-modal.tsx

@@ -72,6 +72,7 @@ export default function DeleteTagModal({
           variant="danger"
           disabled={isLoading}
           isLoading={isLoading}
+          loadingLabel={t('deleting')}
         >
           {t('delete')}
         </OLButton>

+ 1 - 0
services/web/frontend/js/features/project-list/components/modals/edit-tag-modal.tsx

@@ -139,6 +139,7 @@ export function EditTagModal({ id, tag, onEdit, onClose }: EditTagModalProps) {
             !!validationError
           }
           isLoading={isLoading}
+          loadingLabel={t('saving')}
         >
           {t('save')}
         </OLButton>

+ 2 - 0
services/web/frontend/js/features/project-list/components/modals/manage-tag-modal.tsx

@@ -127,6 +127,7 @@ export function ManageTagModal({
           className="me-auto"
           disabled={isDeleteLoading || isUpdateLoading}
           isLoading={isDeleteLoading}
+          loadingLabel={t('deleting')}
         >
           {t('delete_tag')}
         </OLButton>
@@ -147,6 +148,7 @@ export function ManageTagModal({
               (newTagName === tag?.name && selectedColor === getTagColor(tag))
           )}
           isLoading={isUpdateLoading}
+          loadingLabel={t('saving')}
         >
           {t('save_or_cancel-save')}
         </OLButton>

+ 1 - 0
services/web/frontend/js/features/project-list/components/new-project-button/modal-content-new-project-form.tsx

@@ -109,6 +109,7 @@ function ModalContentNewProjectForm({ onCancel, template = 'none' }: Props) {
           onClick={createNewProject}
           disabled={projectName === '' || isLoading || redirecting}
           isLoading={isLoading}
+          loadingLabel={t('creating')}
         >
           {t('create')}
         </OLButton>

+ 1 - 0
services/web/frontend/js/features/project-list/components/notifications/groups/affiliation/reconfirm-affiliation.tsx

@@ -58,6 +58,7 @@ function ReconfirmAffiliation({
           <OLButton
             variant="secondary"
             isLoading={isPending}
+            loadingLabel={t('reconfirming')}
             disabled={isPending}
             onClick={() => {
               setIsPending(true)

+ 3 - 0
services/web/frontend/js/features/settings/components/emails/actions/make-primary/primary-button.tsx

@@ -1,4 +1,5 @@
 import OLButton, { OLButtonProps } from '@/shared/components/ol/ol-button'
+import { useTranslation } from 'react-i18next'
 
 function PrimaryButton({
   children,
@@ -6,11 +7,13 @@ function PrimaryButton({
   isLoading,
   onClick,
 }: OLButtonProps) {
+  const { t } = useTranslation()
   return (
     <OLButton
       size="sm"
       disabled={disabled && !isLoading}
       isLoading={isLoading}
+      loadingLabel={t('processing')}
       onClick={onClick}
       variant="secondary"
     >

+ 1 - 0
services/web/frontend/js/features/settings/components/emails/add-email/add-new-email-btn.tsx

@@ -22,6 +22,7 @@ function AddNewEmailBtn({
       variant="primary"
       disabled={(disabled && !isLoading) || !isValidEmail(email)}
       isLoading={isLoading}
+      loadingLabel={t('adding')}
       {...props}
     >
       {t('add_new_email')}

+ 1 - 0
services/web/frontend/js/features/settings/components/emails/resend-confirmation-code-modal.tsx

@@ -96,6 +96,7 @@ function ResendConfirmationCodeModal({
         variant={triggerVariant}
         disabled={groupLoading}
         isLoading={isLoading}
+        loadingLabel={t('sending')}
         onClick={handleResendConfirmationEmail}
         className={triggerVariant === 'link' ? 'btn-inline-link' : undefined}
       >

+ 1 - 0
services/web/frontend/js/features/subscription/components/dashboard/reactivate-subscription.tsx

@@ -31,6 +31,7 @@ function ReactivateSubscription() {
       disabled={isLoading || isSuccess}
       onClick={handleReactivate}
       isLoading={isLoading}
+      loadingLabel={t('reactivating')}
     >
       {t('reactivate_subscription')}
     </OLButton>

+ 1 - 0
services/web/frontend/js/features/subscription/components/dashboard/states/active/confirm-unpause-modal.tsx

@@ -93,6 +93,7 @@ export function ConfirmUnpauseSubscriptionModal() {
           variant="primary"
           disabled={inflight}
           isLoading={inflight}
+          loadingLabel={t('unpausing')}
           onClick={handleConfirmUnpause}
         >
           {t('unpause_subscription')}

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

@@ -845,6 +845,7 @@
   "generate_from_text_or_image": "From text or image",
   "generate_tables_and_equations": "Generate tables and equations from text and images. Try it for free in the Overleaf toolbar!",
   "generate_token": "Generate token",
+  "generating": "Generating",
   "generic_if_problem_continues_contact_us": "If the problem continues please contact us",
   "generic_linked_file_compile_error": "This project’s output files are not available because it failed to compile. Please open the project to see the compilation error details.",
   "generic_something_went_wrong": "Sorry, something went wrong",
@@ -1813,6 +1814,7 @@
   "reconfirm_account": "Reconfirm account",
   "reconfirm_explained": "We need to reconfirm your account. Please request a password reset link via the form below to reconfirm your account. If you have any problems reconfirming your account, please contact us at",
   "reconfirm_secondary_email": "To enhance the security of your __appName__ account, please reconfirm your secondary email address __emailAddress__.",
+  "reconfirming": "Reconfirming",
   "reconnect": "Try again",
   "reconnecting": "Reconnecting",
   "reconnecting_in_x_secs": "Reconnecting in __seconds__ secs",
@@ -1925,6 +1927,7 @@
   "resync_completed": "Resync completed!",
   "resync_message": "Resyncing project history can take several minutes depending on the size of the project.",
   "resync_project_history": "Resync Project History",
+  "resyncing": "Resyncing",
   "retry_test": "Retry test",
   "return_to_login_page": "Return to Login page",
   "reverse_x_sort_order": "Reverse __x__ sort order",
@@ -2507,7 +2510,6 @@
   "uncategorized_projects": "Uncategorized Projects",
   "unconfirmed": "Unconfirmed",
   "undelete": "Undelete",
-  "undeleting": "Undeleting",
   "understanding_labels": "Understanding labels",
   "undo": "Undo",
   "unfold_line": "Unfold line",
@@ -2541,6 +2543,7 @@
   "unlinking": "Unlinking",
   "unmerge_cells": "Unmerge cells",
   "unpause_subscription": "Unpause subscription",
+  "unpausing": "Unpausing",
   "unpublish": "Unpublish",
   "unpublishing": "Unpublishing",
   "unsubscribe": "Unsubscribe",

+ 5 - 1
services/web/modules/user-activate/frontend/js/components/register-form.jsx

@@ -78,7 +78,11 @@ function RegisterForm({
           lg={4}
           className="mt-3 mt-lg-0 d-flex align-items-center flex-column flex-lg-row"
         >
-          <OLButton type="submit" isLoading={isLoading}>
+          <OLButton
+            type="submit"
+            isLoading={isLoading}
+            loadingLabel={t('registering')}
+          >
             Register
           </OLButton>
         </OLCol>

+ 1 - 1
services/web/test/frontend/features/project-list/components/notifications.test.tsx

@@ -884,7 +884,7 @@ describe('<UserNotifications />', function () {
         screen.getByRole('button', { name: 'Send confirmation code' })
       )
 
-      await waitForElementToBeRemoved(() => screen.getByText(/loading/i))
+      await waitForElementToBeRemoved(() => screen.getByText(/sending/i))
       screen.getByText(/Enter the 6-digit code sent to foo@overleaf.com/i)
       expect(sendReconfirmationMock.callHistory.called()).to.be.true
       fireEvent.click(

+ 1 - 1
services/web/test/frontend/features/settings/components/emails/emails-section-add-new-email.test.tsx

@@ -220,7 +220,7 @@ describe('<EmailsSection />', function () {
 
     await waitForElementToBeRemoved(() =>
       screen.getByRole('button', {
-        name: 'Loading',
+        name: /adding/i,
       })
     )