Update delete workspace error message when frozen expensify cards are present#92917
Conversation
|
Hey, I noticed you changed If you want to automatically generate translations for other locales, an Expensify employee will have to:
Alternatively, if you are an external contributor, you can run the translation script locally with your own OpenAI API key. To learn more, try running: npx ts-node ./scripts/generateTranslations.ts --helpTypically, you'd want to translate only what you changed by running |
|
@linhvovan29546 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 700097bd40
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
Codecov Report❌ Looks like you've decreased code coverage for some files. Please write tests to increase, or at least maintain, the existing level of code coverage. See our documentation here for how to interpret this table.
|
|
Codex Review: Didn't find any major issues. 👍 ℹ️ About Codex in GitHubCodex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
If Codex has suggestions, it will comment; otherwise it will react with 👍. When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback". |
|
|
||
| const HTML_TAG_PATTERN = /<\/?[a-z][^>]*>/i; | ||
|
|
||
| type DotIndicatorMessageProps = { |
There was a problem hiding this comment.
Is the change in this file necessary? I checked with AI, and it said:
Neither
WorkspaceOverviewPagenorWorkspacesListPageuseDotIndicatorMessagefor this error — they both use the confirmation modal. TheDotIndicatorMessagechange appears to be dead code for the purpose of this PR.
Could you clarify whether this change is actually needed?
| deleteConfirmation: 'Are you sure you want to delete this workspace?', | ||
| deleteWithCardsConfirmation: 'Are you sure you want to delete this workspace? This will remove all card feeds and assigned cards.', | ||
| deleteOpenExpensifyCardsError: 'Your company still has open Expensify Cards.', | ||
| deleteOpenExpensifyCardsError: 'Your company still has Expensify Cards. Please <concierge-link>reach out to Concierge</concierge-link> to remove them.', |
There was a problem hiding this comment.
Missing translations in other languages. I think we can trigger translations workflow for this
There was a problem hiding this comment.
Right! I'll ask someone on slack to trigger the translation script
Co-authored-by: Linh Vo <vovanlinh29546@gmail.com>
🦜 Polyglot Parrot! 🦜Squawk! Looks like you added some shiny new English strings. Allow me to parrot them back to you in other tongues: View the translation diffdiff --git a/src/languages/de.ts b/src/languages/de.ts
index 32c68c42a5b..8e74fc3d85c 100644
--- a/src/languages/de.ts
+++ b/src/languages/de.ts
@@ -4323,7 +4323,7 @@ ${amount} für ${merchant} – ${date}`,
defaultNote: `Belege, die an ${CONST.EMAIL.RECEIPTS} gesendet werden, erscheinen in diesem Workspace.`,
deleteConfirmation: 'Möchten Sie diesen Workspace wirklich löschen?',
deleteWithCardsConfirmation: 'Möchtest du diesen Workspace wirklich löschen? Dadurch werden alle Kartenfeeds und zugewiesenen Karten entfernt.',
- deleteOpenExpensifyCardsError: 'Ihr Unternehmen hat noch aktive Expensify Cards.',
+ deleteOpenExpensifyCardsError: 'Ihre Firma hat noch Expensify Karten. Bitte <concierge-link>wenden Sie sich an Concierge</concierge-link>, um sie zu entfernen.',
outstandingBalanceWarning:
'Sie haben einen offenen Saldo, der beglichen werden muss, bevor Sie Ihren letzten Workspace löschen können. Bitte gehen Sie zu Ihren Abonnementeinstellungen, um die Zahlung abzuschließen.',
settleBalance: 'Zu Abo wechseln',
diff --git a/src/languages/es.ts b/src/languages/es.ts
index a776b747936..7ef3cab434e 100644
--- a/src/languages/es.ts
+++ b/src/languages/es.ts
@@ -4204,7 +4204,7 @@ ${amount} para ${merchant} - ${date}`,
defaultNote: `Los recibos enviados a ${CONST.EMAIL.RECEIPTS} aparecerán en este espacio de trabajo.`,
deleteConfirmation: '¿Estás seguro de que quieres eliminar este espacio de trabajo?',
deleteWithCardsConfirmation: '¿Estás seguro de que quieres eliminar este espacio de trabajo? Se eliminarán todos los datos de las tarjetas y las tarjetas asignadas.',
- deleteOpenExpensifyCardsError: 'Su empresa todavía tiene tarjetas Expensify activas.',
+ deleteOpenExpensifyCardsError: 'Tu empresa todavía tiene Tarjetas Expensify. Por favor, <concierge-link>contacta con Concierge</concierge-link> para eliminarlas.',
outstandingBalanceWarning:
'Tienes un saldo pendiente que debe liquidarse antes de eliminar tu último espacio de trabajo. Por favor, ve a la configuración de tu suscripción para resolver el pago.',
settleBalance: 'Ir a Suscripción',
diff --git a/src/languages/fr.ts b/src/languages/fr.ts
index 7ba2b143d6e..d8ea247d964 100644
--- a/src/languages/fr.ts
+++ b/src/languages/fr.ts
@@ -4335,7 +4335,7 @@ ${amount} pour ${merchant} - ${date}`,
defaultNote: `Les reçus envoyés à ${CONST.EMAIL.RECEIPTS} apparaîtront dans cet espace de travail.`,
deleteConfirmation: 'Voulez-vous vraiment supprimer cet espace de travail ?',
deleteWithCardsConfirmation: 'Voulez-vous vraiment supprimer cet espace de travail ? Cela supprimera tous les flux de cartes et les cartes assignées.',
- deleteOpenExpensifyCardsError: 'Votre entreprise a encore des cartes Expensify actives.',
+ deleteOpenExpensifyCardsError: 'Votre entreprise a encore des Cartes Expensify. Veuillez <concierge-link>contacter Concierge</concierge-link> pour les supprimer.',
outstandingBalanceWarning:
'Vous avez un solde impayé qui doit être réglé avant de supprimer votre dernier espace de travail. Veuillez accéder à vos paramètres d’abonnement pour résoudre le paiement.',
settleBalance: 'Aller à l’abonnement',
diff --git a/src/languages/it.ts b/src/languages/it.ts
index 16c336b978b..55120b41b1e 100644
--- a/src/languages/it.ts
+++ b/src/languages/it.ts
@@ -4309,7 +4309,7 @@ ${amount} per ${merchant} - ${date}`,
defaultNote: `Le ricevute inviate a ${CONST.EMAIL.RECEIPTS} verranno visualizzate in questo workspace.`,
deleteConfirmation: 'Sei sicuro di voler eliminare questo spazio di lavoro?',
deleteWithCardsConfirmation: 'Sei sicuro di voler eliminare questo spazio di lavoro? Questa azione rimuoverà tutti i feed delle carte e le carte assegnate.',
- deleteOpenExpensifyCardsError: 'La tua azienda ha ancora carte Expensify attive.',
+ deleteOpenExpensifyCardsError: 'La tua azienda ha ancora delle Carte Expensify. Per favore, <concierge-link>contatta Concierge</concierge-link> per rimuoverle.',
outstandingBalanceWarning:
'Hai un saldo in sospeso che deve essere saldato prima di eliminare il tuo ultimo workspace. Vai alle impostazioni dell’abbonamento per risolvere il pagamento.',
settleBalance: 'Vai all’abbonamento',
diff --git a/src/languages/ja.ts b/src/languages/ja.ts
index 2b1a926f254..2e0bb0ae6c2 100644
--- a/src/languages/ja.ts
+++ b/src/languages/ja.ts
@@ -4278,7 +4278,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
defaultNote: `${CONST.EMAIL.RECEIPTS} に送信されたレシートは、このワークスペースに表示されます。`,
deleteConfirmation: 'このワークスペースを削除してもよろしいですか?',
deleteWithCardsConfirmation: 'このワークスペースを削除してもよろしいですか? すべてのカードフィードと割り当て済みカードが削除されます。',
- deleteOpenExpensifyCardsError: 'あなたの会社にはまだ有効なExpensifyカードがあります。',
+ deleteOpenExpensifyCardsError: '御社にはまだ Expensify カードが残っています。削除するには、<concierge-link>Concierge までお問い合わせください</concierge-link>。',
outstandingBalanceWarning: '最後のワークスペースを削除する前に精算する必要がある未払残高があります。支払いを解決するには、サブスクリプション設定に移動してください。',
settleBalance: 'サブスクリプションに移動',
unavailable: '利用できないワークスペース',
diff --git a/src/languages/nl.ts b/src/languages/nl.ts
index 58c0c33708d..44f302d79e1 100644
--- a/src/languages/nl.ts
+++ b/src/languages/nl.ts
@@ -4305,7 +4305,7 @@ ${amount} voor ${merchant} - ${date}`,
defaultNote: `Bonnetjes die naar ${CONST.EMAIL.RECEIPTS} worden gestuurd, verschijnen in deze workspace.`,
deleteConfirmation: 'Weet je zeker dat je deze werkruimte wilt verwijderen?',
deleteWithCardsConfirmation: 'Weet je zeker dat je deze werkruimte wilt verwijderen? Hiermee worden alle kaartfeeds en toegewezen kaarten verwijderd.',
- deleteOpenExpensifyCardsError: 'Uw bedrijf heeft nog actieve Expensify Cards.',
+ deleteOpenExpensifyCardsError: 'Je bedrijf heeft nog Expensify Kaarten. <concierge-link>Neem contact op met Concierge</concierge-link> om ze te verwijderen.',
outstandingBalanceWarning:
'Je hebt een openstaand saldo dat moet worden vereffend voordat je je laatste werkruimte kunt verwijderen. Ga naar je abonnementsinstellingen om de betaling af te ronden.',
settleBalance: 'Ga naar abonnement',
diff --git a/src/languages/pl.ts b/src/languages/pl.ts
index ae2c2b5fa0a..d0fb7aaa0b2 100644
--- a/src/languages/pl.ts
+++ b/src/languages/pl.ts
@@ -4297,7 +4297,7 @@ ${amount} dla ${merchant} - ${date}`,
defaultNote: `Paragony wysłane na ${CONST.EMAIL.RECEIPTS} pojawią się w tym obszarze roboczym.`,
deleteConfirmation: 'Czy na pewno chcesz usunąć tę przestrzeń roboczą?',
deleteWithCardsConfirmation: 'Na pewno chcesz usunąć tę przestrzeń roboczą? Spowoduje to usunięcie wszystkich źródeł kart i przypisanych kart.',
- deleteOpenExpensifyCardsError: 'Twoja firma nadal ma aktywne karty Expensify.',
+ deleteOpenExpensifyCardsError: 'Twoja firma wciąż ma Karty Expensify. Prosimy, <concierge-link>skontaktuj się z Concierge</concierge-link>, aby je usunąć.',
outstandingBalanceWarning:
'Masz zaległe saldo, które musi zostać uregulowane przed usunięciem ostatniego miejsca pracy. Przejdź do ustawień subskrypcji, aby uregulować płatność.',
settleBalance: 'Przejdź do subskrypcji',
diff --git a/src/languages/pt-BR.ts b/src/languages/pt-BR.ts
index de0e271772d..08d3edf9b4c 100644
--- a/src/languages/pt-BR.ts
+++ b/src/languages/pt-BR.ts
@@ -4298,7 +4298,7 @@ ${amount} para ${merchant} - ${date}`,
defaultNote: `Recibos enviados para ${CONST.EMAIL.RECEIPTS} aparecerão neste workspace.`,
deleteConfirmation: 'Tem certeza de que deseja excluir este workspace?',
deleteWithCardsConfirmation: 'Tem certeza de que deseja excluir este workspace? Isso removerá todos os feeds de cartão e cartões atribuídos.',
- deleteOpenExpensifyCardsError: 'Sua empresa ainda possui cartões Expensify ativos.',
+ deleteOpenExpensifyCardsError: 'Sua empresa ainda tem Cartões Expensify. Por favor, <concierge-link>fale com o Concierge</concierge-link> para removê-los.',
outstandingBalanceWarning:
'Você tem um saldo pendente que precisa ser quitado antes de excluir seu último espaço de trabalho. Acesse as configurações de assinatura para resolver o pagamento.',
settleBalance: 'Ir para a assinatura',
diff --git a/src/languages/zh-hans.ts b/src/languages/zh-hans.ts
index 1df8087de86..84fa44e59e0 100644
--- a/src/languages/zh-hans.ts
+++ b/src/languages/zh-hans.ts
@@ -4202,7 +4202,7 @@ ${amount},商户:${merchant} - 日期:${date}`,
defaultNote: `发送到 ${CONST.EMAIL.RECEIPTS} 的收据将显示在此工作区中。`,
deleteConfirmation: '确定要删除此工作区吗?',
deleteWithCardsConfirmation: '确定要删除此工作区吗?这将移除所有卡片数据源和已分配的卡片。',
- deleteOpenExpensifyCardsError: '您的公司仍有未关闭的 Expensify 卡。',
+ deleteOpenExpensifyCardsError: '您的公司仍在使用 Expensify 卡。请<concierge-link>联系 Concierge</concierge-link>以停用它们。',
outstandingBalanceWarning: '您有一笔未结清的余额,必须在删除最后一个工作区之前结清。请前往订阅设置以解决付款问题。',
settleBalance: '前往订阅',
unavailable: '工作区不可用',
Note You can apply these changes to your branch by copying the patch to your clipboard, then running |
Reviewer Checklist
Screenshots/VideosAndroid: HybridApptelegram-cloud-document-5-6186218164397809820.mp4Android: mWeb Chrometelegram-cloud-document-5-6186218164397809819.mp4iOS: HybridAppScreen.Recording.2026-06-23.at.15.16.00.moviOS: mWeb SafariScreen.Recording.2026-06-23.at.14.39.03.mov |
| import RenderHTML from './RenderHTML'; | ||
| import Text from './Text'; | ||
|
|
||
| const HTML_TAG_PATTERN = /<\/?[a-z][^>]*>/i; |
|
Reviewing again.... |
| success: false, | ||
| shouldHandleNavigationBack: false, | ||
| }).then(() => { | ||
| onDismiss(); |
There was a problem hiding this comment.
In the previous, we also called dismissWorkspaceError, but that call is not included in this change. It also looks like we're missing policyLatestErrorMessage(old code showed a generic error modal for any policyLastErrorMessage). Could you please compare this with the main branch?
| const [activePolicyID] = useOnyx(ONYXKEYS.NVP_ACTIVE_POLICY_ID); | ||
|
|
||
| const hasDeleteWorkspaceExpensifyCardsError = !!hasExpensifyCard && !!isOffline; | ||
| const hasExpensifyCardsEnabledOnWorkspace = !!policy?.areExpensifyCardsEnabled && !!policy?.policyAccountID; |
There was a problem hiding this comment.
Looks like the delete flow on the Overview page is the same as on the WorkspacesList page, so I think we could use DeleteWorkspaceFlow to avoid duplication.
|
Hey! I think it should be ready to be re-reviewed! |
|
|
||
| if (hasDeleteWorkspaceExpensifyCardsError) { | ||
| showDeleteWorkspaceErrorModal(); | ||
| } else if (isOffline) { |
There was a problem hiding this comment.
Missing closeModal.
|
I've adjusted the code to the comments |
This comment was marked as resolved.
This comment was marked as resolved.
|
Failing checks on last commit 👀 |
|
passing now, merging |
|
🚧 @robertjchen has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/robertjchen in version: 9.4.18-0 🚀
Bundle Size Analysis (Sentry): |
|
🤖 I reviewed the changes in this PR against Expensify's help site files under Docs change required: Yes. This PR updates the in-app error shown when a billing owner tries to delete a workspace that still has Expensify Cards (now "Your company still has Expensify Cards. Please reach out to Concierge to remove them." with a clickable Concierge link). The help article that covers deleting a workspace — Draft PR: #94378 — adds an FAQ entry to the existing subscription article documenting that workspaces with Expensify Cards can't be deleted until the cards are removed via Concierge. Labeled
@jnowakow, please review the linked help site PR and confirm it reflects the current behavior. Then mark the linked help site PR |
|
Deploy Blocker #94408 was identified to be related to this PR. |
|
🚀 Deployed to production by https://github.com/blimpich in version: 9.4.18-2 🚀
|


Explanation of Change
Add links to Concierge to error messages when there are frozen Expensify cards.
Fixed Issues
$ #92511
PROPOSAL: N/A
Tests
Prerequisites:
Have workspace with at least one frozen expensify card.
Go to Workspace list page.
Go offline
Three dots > Delete > confirm Delete
Verify that error modal says: "Your company still has Expensify Cards. Please reach out to Concierge to remove them." and "reach out to Concierge" is clickable.
Offline tests
Prerequisites:
Have workspace with at least one frozen expensify card.
Go to Workspace list page.
Go offline
Three dots > Delete > confirm Delete
Verify that error modal says: "Your company still has Expensify Cards. Please reach out to Concierge to remove them." and "reach out to Concierge" is clickable.
QA Steps
// TODO: These must be filled out, or the issue title must include "[No QA]."
Prerequisites:
Have workspace with at least one frozen expensify card.
Go to Workspace list page.
Go offline
Three dots > Delete > confirm Delete
Verify that error modal says: "Your company still has Expensify Cards. Please reach out to Concierge to remove them." and "reach out to Concierge" is clickable.
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Android: Native
Android: mWeb Chrome
iOS: Native
iOS: mWeb Safari
MacOS: Chrome / Safari
delete-offline.mov