Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
7316a47
feat: Replace vacation delegate policy diff warning with RHP invite step
jakubstec Aug 25, 2026
d6a29c2
fix: Guard vacation delegate RHP flow against races and stale UI
jakubstec Sep 1, 2026
e57d900
fix: guard invite/skip/confirm against double press, rollback optimis…
jakubstec Sep 1, 2026
58c4eba
fix: race condition causing not found page appearing on the rhp when …
jakubstec Sep 1, 2026
d677b48
Merge remote-tracking branch 'upstream/main' into jakubstec/policy-di…
jakubstec Sep 1, 2026
b7c0064
fix: follow-up on useOnyx subscription optimalization, use already ex…
jakubstec Sep 1, 2026
a4a3524
Merge remote-tracking branch 'origin/main' into jakubstec/policy-diff…
jakubstec Sep 3, 2026
457fd18
chore: align sending emails to non-admin workspace owners behavior to…
jakubstec Sep 3, 2026
32a13a3
fix: pre-existing bug causing vacation delegate row to disappear afte…
jakubstec Sep 3, 2026
49bfd30
fix: request race condition causing not found page bug
jakubstec Sep 4, 2026
1e11823
Merge remote-tracking branch 'upstream/main' into jakubstec/policy-di…
jakubstec Sep 7, 2026
bea0666
fix: handle request failure properly, refactor to the new MenuItems A…
jakubstec Sep 7, 2026
d9e1a07
fix: update tests
jakubstec Sep 7, 2026
7735a50
fix: consistency comments
jakubstec Sep 7, 2026
111ba04
fix: apply review changes
jakubstec Sep 7, 2026
bc23313
fix: address review comments - refactor VacationDelegateMissingWorksp…
jakubstec Sep 9, 2026
671cd1c
fix: don't disable policy diff rhp when offline, allow to optimistica…
jakubstec Sep 9, 2026
8b54c27
fix: hide RBR after first setVacationDelegate() request
jakubstec Sep 9, 2026
ec775d1
Merge remote-tracking branch 'upstream/main' into jakubstec/policy-di…
jakubstec Sep 11, 2026
35cac1f
fix: don't show unsaved delegate as saved after abandoning missing wo…
jakubstec Sep 14, 2026
1d81018
fix: remove hardcoded welcome message
jakubstec Sep 16, 2026
0dcdb41
fix: regression causing showing email names instead of full names
jakubstec Sep 16, 2026
4f2ef8c
fix: address codex comment
jakubstec Sep 16, 2026
dc4256a
fix: remove unneccesary displayName props naming
jakubstec Sep 17, 2026
4201657
fix: update test comments, ensure proper format of test: given, when,…
jakubstec Sep 17, 2026
a12c1bc
fix: ensure all test files related to vacation delegate have given wh…
jakubstec Sep 17, 2026
e75bec3
fix: add missing comments to DomainTest.ts
jakubstec Sep 17, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2612,6 +2612,7 @@ const ROUTES = {
SETTINGS_STATUS_CLEAR_AFTER_DATE: 'settings/profile/status/clear-after/date',
SETTINGS_STATUS_CLEAR_AFTER_TIME: 'settings/profile/status/clear-after/time',
SETTINGS_VACATION_DELEGATE: 'settings/profile/status/vacation-delegate',
SETTINGS_VACATION_DELEGATE_MISSING_WORKSPACES: 'settings/profile/status/vacation-delegate/missing-workspaces',
SETTINGS_TROUBLESHOOT: 'settings/troubleshoot',
SETTINGS_TROUBLESHOOT_BETA_OVERRIDES: 'settings/troubleshoot/beta-overrides',
SETTINGS_HELP: 'settings/help',
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,7 @@ const SCREENS = {
STATUS_CLEAR_AFTER_DATE: 'Settings_Status_Clear_After_Date',
STATUS_CLEAR_AFTER_TIME: 'Settings_Status_Clear_After_Time',
VACATION_DELEGATE: 'Settings_Status_Vacation_Delegate',
VACATION_DELEGATE_MISSING_WORKSPACES: 'Settings_Status_Vacation_Delegate_Missing_Workspaces',
STATUS: 'Settings_Status',
PRONOUNS: 'Settings_Pronouns',
TIMEZONE: 'Settings_Timezone',
Expand Down
1 change: 1 addition & 0 deletions src/components/VacationDelegateMenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ function VacationDelegateMenuItem({vacationDelegate, errors, pendingAction, onCl
errorRowStyles={styles.mh5}
onClose={onCloseError}
style={hasVacationDelegate && styles.mt4}
shouldHideOnDelete={false}
>
{hasVacationDelegate ? (
<MenuItemWithLabel
Expand Down
12 changes: 10 additions & 2 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3761,8 +3761,15 @@ ${amount} für ${merchant} – ${date}`,
vacationDelegateError: 'Beim Aktualisieren Ihrer Vertretung im Urlaub ist ein Fehler aufgetreten.',
asVacationDelegate: (nameOrEmail: string) => `als Urlaubsvertretung von ${nameOrEmail}`,
toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `an ${submittedToName} als Urlaubsvertretung für ${vacationDelegateName}`,
vacationDelegateWarning: (nameOrEmail: string) =>
`Sie weisen ${nameOrEmail} als Ihre Urlaubsvertretung zu. Diese Person ist noch nicht in all Ihren Arbeitsbereichen. Wenn Sie fortfahren, wird eine E-Mail an alle Admins Ihrer Arbeitsbereiche gesendet, damit sie hinzugefügt wird.`,
vacationDelegate: {
notAMemberAdminsWillBeAsked: (delegate: string) =>
`<strong>${delegate}</strong> ist kein Mitglied der unten aufgeführten Arbeitsbereiche. Admins der Arbeitsbereiche, die Sie nicht verwalten, werden gebeten, die Person hinzuzufügen.`,
notAMemberInviteThemNow: (delegate: string) => `<strong>${delegate}</strong> ist kein Mitglied der unten aufgeführten Arbeitsbereiche. Möchten Sie die Person jetzt einladen?`,
notAMemberMixed: (delegate: string) =>
`<strong>${delegate}</strong> ist kein Mitglied der unten aufgeführten Arbeitsbereiche. Admins der Arbeitsbereiche, die Sie nicht verwalten, werden gebeten, die Person hinzuzufügen. Möchten Sie die Person jetzt zu den Arbeitsbereichen einladen, in denen Sie Admin sind?`,
youAreAMemberOf: 'Sie sind Mitglied dieser Arbeitsbereiche:',
youAreAnAdminOf: 'Sie sind Admin dieser Arbeitsbereiche:',
},
},
stepCounter: (step: number, total?: number, text?: string) => {
let result = `Schritt ${step}`;
Expand Down Expand Up @@ -4692,6 +4699,7 @@ ${amount} für ${merchant} – ${date}`,
defaultDescription: 'Ein Ort für all Ihre Belege und Ausgaben.',
descriptionHint: 'Teile Informationen über diesen Arbeitsbereich mit allen Mitgliedern.',
welcomeNote: 'Bitte nutze Expensify, um deine Belege zur Erstattung einzureichen, danke!',
invitedYouToWorkspace: (inviterName: string, workspaceName: string) => `# ${inviterName} hat dich zu ${workspaceName} eingeladen`,
subscription: 'Abonnement',
markAsEntered: 'Als manuell erfasst markieren',
markAsExported: 'Als exportiert markieren',
Expand Down
12 changes: 10 additions & 2 deletions src/languages/el.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3816,8 +3816,15 @@ ${amount} για ${merchant} - ${date}`,
vacationDelegateError: 'Παρουσιάστηκε σφάλμα κατά την ενημέρωση του αναπληρωτή σας για την άδεια.',
asVacationDelegate: (nameOrEmail: string) => `ως εκπρόσωπος αδειών του/της ${nameOrEmail}`,
toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `στον/στη ${submittedToName} ως αναπληρωτής/τρια αδειούχου για τον/τη ${vacationDelegateName}`,
vacationDelegateWarning: (nameOrEmail: string) =>
`Ορίζετε τον/την ${nameOrEmail} ως αναπληρωτή/τριά σας κατά τις διακοπές. Δεν συμμετέχει ακόμη σε όλους τους χώρους εργασίας σας. Αν επιλέξετε να συνεχίσετε, θα σταλεί email σε όλους τους διαχειριστές των χώρων εργασίας σας για να τον/την προσθέσουν.`,
vacationDelegate: {
notAMemberAdminsWillBeAsked: (delegate: string) =>
`Ο/Η <strong>${delegate}</strong> δεν είναι μέλος των παρακάτω χώρων εργασίας. Θα ζητηθεί από τους διαχειριστές των χώρων εργασίας που δεν διαχειρίζεστε να τον/την προσθέσουν.`,
notAMemberInviteThemNow: (delegate: string) => `Ο/Η <strong>${delegate}</strong> δεν είναι μέλος των παρακάτω χώρων εργασίας. Θέλετε να τον/την προσκαλέσετε τώρα;`,
notAMemberMixed: (delegate: string) =>
`Ο/Η <strong>${delegate}</strong> δεν είναι μέλος των παρακάτω χώρων εργασίας. Θα ζητηθεί από τους διαχειριστές των χώρων εργασίας που δεν διαχειρίζεστε να τον/την προσθέσουν. Θέλετε να τον/την προσκαλέσετε τώρα σε αυτούς που διαχειρίζεστε ως διαχειριστής;`,
youAreAMemberOf: 'Είστε μέλος αυτών των χώρων εργασίας:',
youAreAnAdminOf: 'Είστε διαχειριστής αυτών των χώρων εργασίας:',
},
},
stepCounter: (step, total, text) => {
let result = `Βήμα ${step}`;
Expand Down Expand Up @@ -4767,6 +4774,7 @@ ${amount} για ${merchant} - ${date}`,
defaultDescription: 'Ένα μέρος για όλες τις αποδείξεις και τα έξοδά σας.',
descriptionHint: 'Κοινοποιήστε πληροφορίες σχετικά με αυτόν τον χώρο εργασίας σε όλα τα μέλη.',
welcomeNote: 'Παρακαλούμε χρησιμοποιήστε το Expensify για να υποβάλετε τις αποδείξεις σας για αποζημίωση, ευχαριστούμε!',
invitedYouToWorkspace: (inviterName: string, workspaceName: string) => `# Ο/Η ${inviterName} σας προσκάλεσε στο ${workspaceName}`,
subscription: 'Συνδρομή',
markAsEntered: 'Σήμανση ως καταχωρισμένο χειροκίνητα',
markAsExported: 'Επισήμανση ως εξαχθέν',
Expand Down
12 changes: 10 additions & 2 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3869,8 +3869,15 @@ const translations = {
vacationDelegateError: 'There was an error updating your vacation delegate.',
asVacationDelegate: (nameOrEmail: string) => `as ${nameOrEmail}'s vacation delegate`,
toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `to ${submittedToName} as vacation delegate for ${vacationDelegateName}`,
vacationDelegateWarning: (nameOrEmail: string) =>
`You're assigning ${nameOrEmail} as your vacation delegate. They're not on all your workspaces yet. If you choose to continue, an email will be sent to all your workspace admins to add them.`,
vacationDelegate: {
notAMemberAdminsWillBeAsked: (delegate: string) =>
`<strong>${delegate}</strong> is not a member of the workspaces below. Admins of the workspaces you don't manage will be asked to add them.`,
notAMemberInviteThemNow: (delegate: string) => `<strong>${delegate}</strong> is not a member of the workspaces below. Do you want to invite them now?`,
notAMemberMixed: (delegate: string) =>
`<strong>${delegate}</strong> isn't a member of the workspaces below. Admins of the workspaces you don't manage will be asked to add them. Do you want to invite them to the ones you are an admin of now?`,
youAreAMemberOf: 'You are a member of these workspaces:',
youAreAnAdminOf: 'You are an admin of these workspaces:',
},
},
stepCounter: (step: number, total?: number, text?: string) => {
let result = `Step ${step}`;
Expand Down Expand Up @@ -4815,6 +4822,7 @@ const translations = {
defaultDescription: 'One place for all your receipts and expenses.',
descriptionHint: 'Share information about this workspace with all members.',
welcomeNote: 'Please use Expensify to submit your receipts for reimbursement, thanks!',
invitedYouToWorkspace: (inviterName: string, workspaceName: string) => `# ${inviterName} invited you to ${workspaceName}`,
subscription: 'Subscription',
markAsEntered: 'Mark as manually entered',
markAsExported: 'Mark as exported',
Expand Down
12 changes: 10 additions & 2 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3686,8 +3686,15 @@ ${amount} para ${merchant} - ${date}`,
vacationDelegateError: 'Hubo un error al actualizar tu delegado de vacaciones.',
asVacationDelegate: (managerName) => `como delegado de vacaciones de ${managerName}`,
toAsVacationDelegate: (submittedToName, vacationDelegateName) => `a ${submittedToName} como delegado de vacaciones de ${vacationDelegateName}`,
vacationDelegateWarning: (nameOrEmail) =>
`Está asignando a ${nameOrEmail} como su delegado de vacaciones. Aún no está en todos sus espacios de trabajo. Si decide continuar, se enviará un correo electrónico a todos los administradores de sus espacios de trabajo para agregarlo.`,
vacationDelegate: {
notAMemberAdminsWillBeAsked: (delegate) =>
`<strong>${delegate}</strong> no es miembro de los siguientes espacios de trabajo. Se pedirá a los administradores de los espacios de trabajo que no gestiona que lo agreguen.`,
notAMemberInviteThemNow: (delegate) => `<strong>${delegate}</strong> no es miembro de los siguientes espacios de trabajo. ¿Desea invitarlo ahora?`,
notAMemberMixed: (delegate) =>
`<strong>${delegate}</strong> no es miembro de los siguientes espacios de trabajo. Se pedirá a los administradores de los espacios de trabajo que no gestiona que lo agreguen. ¿Desea invitarlo ahora a los espacios de trabajo en los que es administrador?`,
youAreAMemberOf: 'Usted es miembro de estos espacios de trabajo:',
youAreAnAdminOf: 'Usted es administrador de estos espacios de trabajo:',
},
},
stepCounter: (step, total, text) => {
let result = `Paso ${step}`;
Expand Down Expand Up @@ -4625,6 +4632,7 @@ ${amount} para ${merchant} - ${date}`,
defaultDescription: 'Un solo lugar para todos tus recibos y gastos.',
descriptionHint: 'Comparte información sobre este espacio de trabajo con todos los miembros.',
welcomeNote: `Por favor, utiliza Expensify para enviar tus recibos para reembolso, ¡gracias!`,
invitedYouToWorkspace: (inviterName, workspaceName) => `# ${inviterName} te invitó a ${workspaceName}`,
subscription: 'Suscripción',
markAsEntered: 'Marcar como introducido manualmente',
markAsExported: 'Marcar como exportado',
Expand Down
12 changes: 10 additions & 2 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3769,8 +3769,15 @@ ${amount} pour ${merchant} - ${date}`,
vacationDelegateError: 'Une erreur s’est produite lors de la mise à jour de votre remplaçant de congés.',
asVacationDelegate: (nameOrEmail: string) => `en tant que délégué de vacances de ${nameOrEmail}`,
toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `à ${submittedToName} en tant que délégué de congés pour ${vacationDelegateName}`,
vacationDelegateWarning: (nameOrEmail: string) =>
`Vous assignez ${nameOrEmail} comme remplaçant pendant vos congés. Cette personne n’est pas encore présente dans tous vos espaces de travail. Si vous choisissez de continuer, un e-mail sera envoyé aux administrateurs de tous vos espaces de travail pour l’ajouter.`,
vacationDelegate: {
notAMemberAdminsWillBeAsked: (delegate: string) =>
`<strong>${delegate}</strong> n'est pas membre des espaces de travail ci-dessous. Les administrateurs des espaces de travail que vous ne gérez pas seront invités à l'ajouter.`,
notAMemberInviteThemNow: (delegate: string) => `<strong>${delegate}</strong> n'est pas membre des espaces de travail ci-dessous. Voulez-vous l'inviter maintenant ?`,
notAMemberMixed: (delegate: string) =>
`<strong>${delegate}</strong> n'est pas membre des espaces de travail ci-dessous. Les administrateurs des espaces de travail que vous ne gérez pas seront invités à l'ajouter. Voulez-vous l'inviter dès maintenant à ceux dont vous êtes administrateur ?`,
youAreAMemberOf: 'Vous êtes membre de ces espaces de travail :',
youAreAnAdminOf: 'Vous êtes administrateur de ces espaces de travail :',
},
},
stepCounter: (step: number, total?: number, text?: string) => {
let result = `Étape ${step}`;
Expand Down Expand Up @@ -4700,6 +4707,7 @@ ${amount} pour ${merchant} - ${date}`,
defaultDescription: 'Un seul endroit pour tous vos reçus et dépenses.',
descriptionHint: 'Partager des informations sur cet espace de travail avec tous les membres.',
welcomeNote: 'Veuillez utiliser Expensify pour soumettre vos reçus en vue de leur remboursement, merci !',
invitedYouToWorkspace: (inviterName: string, workspaceName: string) => `# ${inviterName} vous a invité à ${workspaceName}`,
subscription: 'Abonnement',
markAsEntered: 'Marquer comme saisi manuellement',
markAsExported: 'Marquer comme exporté',
Expand Down
12 changes: 10 additions & 2 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3745,8 +3745,15 @@ ${amount} per ${merchant} - ${date}`,
vacationDelegateError: 'Si è verificato un errore durante l’aggiornamento del tuo delegato per le ferie.',
asVacationDelegate: (nameOrEmail: string) => `come delegato per le ferie di ${nameOrEmail}`,
toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `a ${submittedToName} come delegato ferie per ${vacationDelegateName}`,
vacationDelegateWarning: (nameOrEmail: string) =>
`Stai assegnando ${nameOrEmail} come tuo delegato per le ferie. Non fa ancora parte di tutti i tuoi spazi di lavoro. Se scegli di continuare, verrà inviata un’email a tutti gli amministratori dei tuoi spazi di lavoro per aggiungerlo.`,
vacationDelegate: {
notAMemberAdminsWillBeAsked: (delegate: string) =>
`<strong>${delegate}</strong> non è membro degli spazi di lavoro elencati di seguito. Agli amministratori degli spazi di lavoro che non gestisci verrà chiesto di aggiungerlo.`,
notAMemberInviteThemNow: (delegate: string) => `<strong>${delegate}</strong> non è membro degli spazi di lavoro elencati di seguito. Vuoi invitarlo ora?`,
notAMemberMixed: (delegate: string) =>
`<strong>${delegate}</strong> non è membro degli spazi di lavoro elencati di seguito. Agli amministratori degli spazi di lavoro che non gestisci verrà chiesto di aggiungerlo. Vuoi invitarlo ora in quelli di cui sei amministratore?`,
youAreAMemberOf: 'Sei membro di questi spazi di lavoro:',
youAreAnAdminOf: 'Sei amministratore di questi spazi di lavoro:',
},
},
stepCounter: (step: number, total?: number, text?: string) => {
let result = `Passaggio ${step}`;
Expand Down Expand Up @@ -4665,6 +4672,7 @@ ${amount} per ${merchant} - ${date}`,
defaultDescription: 'Un unico posto per tutte le tue ricevute e spese.',
descriptionHint: 'Condividi informazioni su questo workspace con tutti i membri.',
welcomeNote: 'Usa Expensify per inviare le tue ricevute per il rimborso, grazie!',
invitedYouToWorkspace: (inviterName: string, workspaceName: string) => `# ${inviterName} ti ha invitato a ${workspaceName}`,
subscription: 'Abbonamento',
markAsEntered: 'Segna come inserito manualmente',
markAsExported: 'Segna come esportato',
Expand Down
12 changes: 10 additions & 2 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3717,8 +3717,15 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
vacationDelegateError: '休暇の代理人を更新中にエラーが発生しました。',
asVacationDelegate: (nameOrEmail: string) => `${nameOrEmail} さんの休暇代理として`,
toAsVacationDelegate: (submittedToName: string, vacationDelegateName: string) => `${vacationDelegateName} の休暇代理人として ${submittedToName} に`,
vacationDelegateWarning: (nameOrEmail: string) =>
`${nameOrEmail} さんをあなたの休暇代理人に指定しようとしています。この人は、まだすべてのワークスペースに参加していません。続行すると、すべてのワークスペース管理者に、この人を追加するようメールが送信されます。`,
vacationDelegate: {
notAMemberAdminsWillBeAsked: (delegate: string) =>
`<strong>${delegate}</strong>は以下のワークスペースのメンバーではありません。あなたが管理していないワークスペースの管理者に追加を依頼します。`,
notAMemberInviteThemNow: (delegate: string) => `<strong>${delegate}</strong>は以下のワークスペースのメンバーではありません。今すぐ招待しますか?`,
notAMemberMixed: (delegate: string) =>
`<strong>${delegate}</strong>は以下のワークスペースのメンバーではありません。あなたが管理していないワークスペースの管理者に追加を依頼します。あなたが管理者になっているワークスペースには今すぐ招待しますか?`,
youAreAMemberOf: 'あなたはこれらのワークスペースのメンバーです:',
youAreAnAdminOf: 'あなたはこれらのワークスペースの管理者です:',
},
},
stepCounter: (step: number, total?: number, text?: string) => {
let result = `ステップ ${step}`;
Expand Down Expand Up @@ -4630,6 +4637,7 @@ ${integrationName === CONST.ONBOARDING_ACCOUNTING_MAPPING.other ? 'あなたの'
defaultDescription: 'すべての領収書と経費を一か所で管理。',
descriptionHint: 'このワークスペースに関する情報をすべてのメンバーと共有します。',
welcomeNote: '精算のための領収書提出には Expensify をご利用ください。ありがとうございます!',
invitedYouToWorkspace: (inviterName: string, workspaceName: string) => `# ${inviterName}さんがあなたを${workspaceName}に招待しました`,
subscription: 'サブスクリプション',
markAsEntered: '手入力としてマーク',
markAsExported: 'エクスポート済みにする',
Expand Down
Loading
Loading