Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
aae910e
Implement new AddDomain, DomainAdded, AccessRestricted and VerifyAcco…
mhawryluk Nov 27, 2025
baf7f05
Small fixes
mhawryluk Nov 27, 2025
1deecfd
Add domains empty state banner
mhawryluk Nov 27, 2025
0511786
Implement navigating to Verify Account RHP for non-validated accounts…
mhawryluk Nov 28, 2025
2bb8c2d
Improve styling
mhawryluk Nov 28, 2025
0f33daf
Validate domain name before sending create domain request
mhawryluk Nov 28, 2025
30fff5d
Add translations
mhawryluk Nov 28, 2025
a8195d3
Remove unused property from Domain type
mhawryluk Nov 28, 2025
ff4ed06
More fixes and improvements
mhawryluk Dec 1, 2025
9f78686
Add translations (again)
mhawryluk Dec 1, 2025
399bffa
Further fixes
mhawryluk Dec 1, 2025
c0bd99b
Fix autofocus
mhawryluk Dec 1, 2025
dd9a8fe
Clear AddDomainPage form on enter
mhawryluk Dec 1, 2025
b5d1858
Merge branch 'main' into feat/add-domain
mhawryluk Dec 1, 2025
7c45978
Add some tests + move workspaces header button to a separate componen…
mhawryluk Dec 2, 2025
ee6a6fc
Fix eslint
mhawryluk Dec 2, 2025
4c9f70f
Don't show "New workspace" option in WorkspacesListPageHeaderButton w…
mhawryluk Dec 2, 2025
12c6981
Add one more test
mhawryluk Dec 2, 2025
63694a5
Fix DomainAccessRestricted feature row styling
mhawryluk Dec 3, 2025
d0af026
Implement review suggestions
mhawryluk Dec 3, 2025
d5289bc
Show loading spinner in AddDomainPage action button
mhawryluk Dec 3, 2025
8ebdc8e
Fix createDomain test
mhawryluk Dec 3, 2025
b146546
Apply suggestions
mhawryluk Dec 3, 2025
385e942
Merge branch 'main' into feat/add-domain
mhawryluk Dec 3, 2025
40642cc
Merge branch 'main' into feat/add-domain
mhawryluk Dec 3, 2025
fb21734
Show domain empty state component when there are no workspaces
mhawryluk Dec 4, 2025
5388bcb
Ignore case when looking for the just created domain
mhawryluk Dec 4, 2025
9748779
Show "New domain" button when there are domains, but no workspaces
mhawryluk Dec 4, 2025
2f9c463
Show dropdown button when there are no workspaces but are domains + l…
mhawryluk Dec 5, 2025
1ffaba0
Change the buttons once again
mhawryluk Dec 5, 2025
57dc189
Fix "new" dropdown button bottom margin
mhawryluk Dec 8, 2025
0bcb2ed
Remove console.error on not found added domain's accountID
mhawryluk Dec 8, 2025
c8036ae
Fix showing navigation tab bar when navigating back to a screen witho…
mhawryluk Dec 8, 2025
df2b2ee
Fix test after navigationtabbar change
mhawryluk Dec 8, 2025
48c558f
Revert changes for TopLevelNavigationTabBar for now
mhawryluk Dec 8, 2025
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
2 changes: 1 addition & 1 deletion src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,7 @@ const CONST = {
COLLECT_UPGRADE_HELP_URL: 'https://help.expensify.com/Hidden/collect-upgrade',
MERGE_ACCOUNT_HELP_URL: 'https://help.expensify.com/articles/new-expensify/settings/Merge-Accounts',
CONNECT_A_BUSINESS_BANK_ACCOUNT_HELP_URL: 'https://help.expensify.com/articles/new-expensify/expenses-&-payments/Connect-a-Business-Bank-Account',
DOMAIN_VERIFICATION_HELP_URL: 'https://help.expensify.com/articles/expensify-classic/domains/Claim-And-Verify-A-Domain',
DOMAIN_VERIFICATION_HELP_URL: 'https://help.expensify.com/articles/new-expensify/workspaces/Verify-a-Domain',
SAML_HELP_URL: 'https://help.expensify.com/articles/expensify-classic/domains/Managing-Single-Sign-On-(SSO)-in-Expensify',
REGISTER_FOR_WEBINAR_URL: 'https://events.zoom.us/eo/Aif1I8qCi1GZ7KnLnd1vwGPmeukSRoPjFpyFAZ2udQWn0-B86e1Z~AggLXsr32QYFjq8BlYLZ5I06Dg',
TEST_RECEIPT_URL: `${CLOUDFRONT_URL}/images/fake-receipt__tacotodds.png`,
Expand Down
3 changes: 3 additions & 0 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -920,6 +920,8 @@ const ONYXKEYS = {
WORKSPACE_PER_DIEM_FORM_DRAFT: 'workspacePerDiemFormDraft',
ENABLE_GLOBAL_REIMBURSEMENTS: 'enableGlobalReimbursementsForm',
ENABLE_GLOBAL_REIMBURSEMENTS_DRAFT: 'enableGlobalReimbursementsFormDraft',
CREATE_DOMAIN_FORM: 'createDomainForm',
CREATE_DOMAIN_FORM_DRAFT: 'createDomainFormDraft',
},
DERIVED: {
REPORT_ATTRIBUTES: 'reportAttributes',
Expand Down Expand Up @@ -1034,6 +1036,7 @@ type OnyxFormValuesMapping = {
[ONYXKEYS.FORMS.INTERNATIONAL_BANK_ACCOUNT_FORM]: FormTypes.InternationalBankAccountForm;
[ONYXKEYS.FORMS.WORKSPACE_PER_DIEM_FORM]: FormTypes.WorkspacePerDiemForm;
[ONYXKEYS.FORMS.ENABLE_GLOBAL_REIMBURSEMENTS]: FormTypes.EnableGlobalReimbursementsForm;
[ONYXKEYS.FORMS.CREATE_DOMAIN_FORM]: FormTypes.CreateDomainForm;
};

type OnyxFormDraftValuesMapping = {
Expand Down
10 changes: 10 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3394,6 +3394,16 @@ const ROUTES = {
route: 'workspaces/domain-verified/:accountID',
getRoute: (accountID: number) => `workspaces/domain-verified/${accountID}` as const,
},
WORKSPACES_ADD_DOMAIN: 'workspaces/add-domain',
WORKSPACES_ADD_DOMAIN_VERIFY_ACCOUNT: `workspaces/add-domain/${VERIFY_ACCOUNT}`,
WORKSPACES_DOMAIN_ADDED: {
route: 'workspaces/domain-added/:accountID',
getRoute: (accountID: number) => `workspaces/domain-added/${accountID}` as const,
},
WORKSPACES_DOMAIN_ACCESS_RESTRICTED: {
route: 'workspaces/domain-access-restricted/:accountID',
getRoute: (accountID: number) => `workspaces/domain-access-restricted/${accountID}` as const,
},
DOMAIN_INITIAL: {
route: 'domain/:accountID',
getRoute: (accountID: number) => `domain/${accountID}` as const,
Expand Down
4 changes: 4 additions & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,10 @@ const SCREENS = {
},
WORKSPACES_VERIFY_DOMAIN: 'Workspaces_Verify_Domain',
WORKSPACES_DOMAIN_VERIFIED: 'Workspaces_Domain_Verified',
WORKSPACES_ADD_DOMAIN: 'Workspaces_Add_Domain',
WORKSPACES_ADD_DOMAIN_VERIFY_ACCOUNT: 'Workspaces_Add_Domain_VerifyAccount',
WORKSPACES_DOMAIN_ADDED: 'Workspaces_Domain_Added',
WORKSPACES_DOMAIN_ACCESS_RESTRICTED: 'Workspaces_Domain_Access_Restricted',
DOMAIN: {
VERIFY: 'Domain_Verify',
VERIFIED: 'Domain_Verified',
Expand Down
1 change: 0 additions & 1 deletion src/components/Domain/DomainMenuItem.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,6 @@ function DomainMenuItem({item, index}: DomainMenuItemProps) {
accessibilityLabel="row"
style={styles.mh5}
onPress={action}
disabled={!isAdmin}
>
{({hovered}) => (
<DomainsListRow
Expand Down
38 changes: 38 additions & 0 deletions src/components/DomainsEmptyStateComponent.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import React from 'react';
import {View} from 'react-native';
import {useMemoizedLazyAsset} from '@hooks/useLazyAsset';
import useLocalize from '@hooks/useLocalize';
import useThemeStyles from '@hooks/useThemeStyles';
import Navigation from '@libs/Navigation/Navigation';
import BillingBanner from '@pages/settings/Subscription/CardSection/BillingBanner/BillingBanner';
import ROUTES from '@src/ROUTES';
import Button from './Button';
import {loadIllustration} from './Icon/IllustrationLoader';

function DomainsEmptyStateComponent() {
const {asset: BlueShield} = useMemoizedLazyAsset(() => loadIllustration('BlueShield'));
const styles = useThemeStyles();
const {translate} = useLocalize();

return (
<View style={styles.ph5}>
<BillingBanner
icon={BlueShield}
title={translate('domain.enhancedSecurity.title')}
subtitle={translate('domain.enhancedSecurity.subtitle')}
subtitleStyle={[styles.textLabelSupporting, styles.pt1]}
style={[styles.borderRadiusComponentLarge, styles.hoveredComponentBG]}
rightComponent={
<Button
text={translate('domain.enhancedSecurity.enable')}
success
onPress={() => Navigation.navigate(ROUTES.WORKSPACES_ADD_DOMAIN)}
/>
}
/>
</View>
);
}

DomainsEmptyStateComponent.displayName = 'DomainsEmptyStateComponent';
export default DomainsEmptyStateComponent;
25 changes: 25 additions & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7787,6 +7787,31 @@ ${
fetchError: 'SAML-Konfigurationsdetails konnten nicht abgerufen werden',
setMetadataGenericError: 'SAML-Metadaten konnten nicht gesetzt werden',
},
accessRestricted: {
title: 'Zugriff eingeschränkt',
subtitle: (domainName: string) =>
`Bitte verifizieren Sie sich als autorisierte/r Unternehmensadministrator/in für <strong>${domainName}</strong>, wenn Sie Kontrolle über Folgendes benötigen:`,
companyCardManagement: 'Firmenkartenverwaltung',
accountCreationAndDeletion: 'Kontoerstellung und -löschung',
workspaceCreation: 'Erstellung des Arbeitsbereichs',
samlSSO: 'SAML-SSO',
},
addDomain: {
title: 'Domain hinzufügen',
subtitle: 'Geben Sie den Namen der privaten Domain ein, auf die Sie zugreifen möchten (z. B. expensify.com).',
domainName: 'Domainname',
newDomain: 'Neue Domain',
},
domainAdded: {
title: 'Domain hinzugefügt',
description: 'Als Nächstes müssen Sie die Inhaberschaft der Domain bestätigen und Ihre Sicherheitseinstellungen anpassen.',
configure: 'Konfigurieren',
},
enhancedSecurity: {
title: 'Verbesserte Sicherheit',
subtitle: 'Erzwingen Sie für Mitglieder Ihrer Domain die Anmeldung per Single Sign-On, schränken Sie die Erstellung von Workspaces ein und vieles mehr.',
enable: 'Aktivieren',
},
},
};
// IMPORTANT: This line is manually replaced in generate translation files by scripts/generateTranslations.ts,
Expand Down
24 changes: 24 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7723,6 +7723,30 @@ const translations = {
fetchError: "Couldn't fetch SAML configuration details",
setMetadataGenericError: "Couldn't set SAML MetaData",
},
accessRestricted: {
title: 'Access restricted',
subtitle: (domainName: string) => `Please verify yourself as an authorized company administrator for <strong>${domainName}</strong> if you need control over:`,
companyCardManagement: 'Company card management',
accountCreationAndDeletion: 'Account creation and deletion',
workspaceCreation: 'Workspace creation',
samlSSO: 'SAML SSO',
},
addDomain: {
title: 'Add domain',
subtitle: 'Enter the name of the private domain you want to access (e.g. expensify.com).',
domainName: 'Domain name',
newDomain: 'New domain',
},
domainAdded: {
title: 'Domain added',
description: "Next, you'll need to verify ownership of the domain and adjust your security settings.",
configure: 'Configure',
},
enhancedSecurity: {
title: 'Enhanced security',
subtitle: 'Require members on your domain to log in via single sign-on, restrict workspace creation, and more.',
enable: 'Enable',
},
},
};

Expand Down
24 changes: 24 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7842,6 +7842,30 @@ ${amount} para ${merchant} - ${date}`,
fetchError: 'No se pudieron obtener los detalles de configuración de SAML',
setMetadataGenericError: 'No se pudieron establecer los metadatos de SAML',
},
accessRestricted: {
title: 'Acceso restringido',
subtitle: (domainName: string) => `Por favor, verifícate como un administrador autorizado de la empresa para <strong>${domainName}</strong> si necesitas control sobre:`,
companyCardManagement: 'Gestión de tarjetas de la empresa',
accountCreationAndDeletion: 'Creación y eliminación de cuentas',
workspaceCreation: 'Creación de espacios de trabajo',
samlSSO: 'SAML SSO',
},
addDomain: {
title: 'Añadir dominio',
subtitle: 'Introduce el nombre del dominio privado al que deseas acceder (por ejemplo, expensify.com).',
domainName: 'Nombre de dominio',
newDomain: 'Nuevo dominio',
},
domainAdded: {
title: 'Dominio añadido',
description: 'A continuación, deberás verificar la propiedad del dominio y ajustar tu configuración de seguridad.',
configure: 'Configurar',
},
enhancedSecurity: {
title: 'Seguridad mejorada',
subtitle: 'Solicita que los miembros de tu dominio inicien sesión mediante inicio de sesión único, restringe la creación de espacios de trabajo y más.',
enable: 'Habilitar',
},
},
};

Expand Down
21 changes: 21 additions & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7791,6 +7791,27 @@ ${
fetchError: 'Impossible de récupérer les détails de la configuration SAML',
setMetadataGenericError: 'Impossible de définir les métadonnées SAML',
},
accessRestricted: {
title: 'Accès restreint',
subtitle: (domainName: string) =>
`Veuillez vous authentifier en tant qu’administrateur d’entreprise autorisé pour <strong>${domainName}</strong> si vous avez besoin d’avoir le contrôle sur :`,
companyCardManagement: 'Gestion des cartes d’entreprise',
accountCreationAndDeletion: 'Création et suppression de compte',
workspaceCreation: "Création d'espace de travail",
samlSSO: 'SSO SAML',
},
addDomain: {
title: 'Ajouter un domaine',
subtitle: 'Saisissez le nom du domaine privé auquel vous souhaitez accéder (par exemple expensify.com).',
domainName: 'Nom de domaine',
newDomain: 'Nouveau domaine',
},
domainAdded: {title: 'Domaine ajouté', description: 'Ensuite, vous devrez vérifier la propriété du domaine et ajuster vos paramètres de sécurité.', configure: 'Configurer'},
enhancedSecurity: {
title: 'Sécurité renforcée',
subtitle: "Exiger que les membres de votre domaine se connectent via l'authentification unique, restreindre la création d'espaces de travail, et plus encore.",
enable: 'Activer',
},
},
};
// IMPORTANT: This line is manually replaced in generate translation files by scripts/generateTranslations.ts,
Expand Down
24 changes: 24 additions & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7771,6 +7771,30 @@ ${
fetchError: 'Impossibile recuperare i dettagli della configurazione SAML',
setMetadataGenericError: 'Impossibile impostare i metadati SAML',
},
accessRestricted: {
title: 'Accesso limitato',
subtitle: (domainName: string) => `Verificati come amministratore aziendale autorizzato per <strong>${domainName}</strong> se hai bisogno di gestire:`,
companyCardManagement: 'Gestione delle carte aziendali',
accountCreationAndDeletion: "Creazione e cancellazione dell'account",
workspaceCreation: 'Creazione dello spazio di lavoro',
samlSSO: 'SAML SSO',
},
addDomain: {
title: 'Aggiungi dominio',
subtitle: 'Inserisci il nome del dominio privato a cui desideri accedere (ad esempio expensify.com).',
domainName: 'Nome di dominio',
newDomain: 'Nuovo dominio',
},
domainAdded: {
title: 'Dominio aggiunto',
description: 'Successivamente, dovrai verificare la proprietà del dominio e regolare le tue impostazioni di sicurezza.',
configure: 'Configura',
},
enhancedSecurity: {
title: 'Sicurezza avanzata',
subtitle: 'Richiedi ai membri del tuo dominio di accedere tramite Single Sign-On, limita la creazione di spazi di lavoro e altro ancora.',
enable: 'Abilita',
},
},
};
// IMPORTANT: This line is manually replaced in generate translation files by scripts/generateTranslations.ts,
Expand Down
20 changes: 20 additions & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7696,6 +7696,26 @@ ${
fetchError: 'SAML 構成の詳細を取得できませんでした',
setMetadataGenericError: 'SAML メタデータを設定できませんでした',
},
accessRestricted: {
title: 'アクセスが制限されています',
subtitle: (domainName: string) => `以下を管理する必要がある場合は、<strong>${domainName}</strong> の認可された会社管理者であることを確認してください:`,
companyCardManagement: '法人カードの管理',
accountCreationAndDeletion: 'アカウントの作成と削除',
workspaceCreation: 'ワークスペースの作成',
samlSSO: 'SAML シングルサインオン',
},
addDomain: {
title: 'ドメインを追加',
subtitle: 'アクセスしたいプライベートドメイン名を入力してください(例:expensify.com)。',
domainName: 'ドメイン名',
newDomain: '新しいドメイン',
},
domainAdded: {title: 'ドメインが追加されました', description: '次に、ドメインの所有権を確認し、セキュリティ設定を調整する必要があります。', configure: '設定'},
enhancedSecurity: {
title: '強化されたセキュリティ',
subtitle: 'ドメインのメンバーにシングルサインオンでのログインを必須化し、ワークスペースの作成を制限するなど、さらに多くのことができます。',
enable: '有効にする',
},
},
};
// IMPORTANT: This line is manually replaced in generate translation files by scripts/generateTranslations.ts,
Expand Down
24 changes: 24 additions & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7740,6 +7740,30 @@ ${
fetchError: 'Kon SAML-configuratiedetails niet ophalen',
setMetadataGenericError: 'Kon SAML-metadata niet instellen',
},
accessRestricted: {
title: 'Toegang beperkt',
subtitle: (domainName: string) => `Bevestig dat u een geautoriseerde bedrijfsbeheerder bent voor <strong>${domainName}</strong> als u controle nodig hebt over:`,
companyCardManagement: 'Beheer van bedrijfskaarten',
accountCreationAndDeletion: 'Accountaanmaak en -verwijdering',
workspaceCreation: 'Werkruimte aanmaken',
samlSSO: 'SAML SSO',
},
addDomain: {
title: 'Domein toevoegen',
subtitle: 'Voer de naam in van het privédomein waartoe je toegang wilt krijgen (bijv. expensify.com).',
domainName: 'Domeinnaam',
newDomain: 'Nieuw domein',
},
domainAdded: {
title: 'Domein toegevoegd',
description: 'Vervolgens moet je het eigendom van het domein verifiëren en je beveiligingsinstellingen aanpassen.',
configure: 'Configureren',
},
enhancedSecurity: {
title: 'Verbeterde beveiliging',
subtitle: 'Verplicht leden van je domein om in te loggen via single sign-on, beperk het aanmaken van werkruimten en meer.',
enable: 'Inschakelen',
},
},
};
// IMPORTANT: This line is manually replaced in generate translation files by scripts/generateTranslations.ts,
Expand Down
20 changes: 20 additions & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7731,6 +7731,26 @@ ${
fetchError: 'Nie udało się pobrać szczegółów konfiguracji SAML',
setMetadataGenericError: 'Nie można ustawić metadanych SAML',
},
accessRestricted: {
title: 'Dostęp ograniczony',
subtitle: (domainName: string) => `Proszę zweryfikować się jako autoryzowany administrator firmy dla <strong>${domainName}</strong>, jeśli potrzebujesz kontroli nad:`,
companyCardManagement: 'Zarządzanie kartami firmowymi',
accountCreationAndDeletion: 'Tworzenie i usuwanie konta',
workspaceCreation: 'Tworzenie obszaru roboczego',
samlSSO: 'SAML SSO',
},
addDomain: {
title: 'Dodaj domenę',
subtitle: 'Wprowadź nazwę prywatnej domeny, do której chcesz uzyskać dostęp (np. expensify.com).',
domainName: 'Nazwa domeny',
newDomain: 'Nowa domena',
},
domainAdded: {title: 'Dodano domenę', description: 'Następnie musisz zweryfikować własność domeny i dostosować ustawienia zabezpieczeń.', configure: 'Skonfiguruj'},
enhancedSecurity: {
title: 'Zwiększone bezpieczeństwo',
subtitle: 'Wymagaj, aby członkowie Twojej domeny logowali się przez Single Sign-On (SSO), ograniczaj tworzenie obszarów roboczych i nie tylko.',
enable: 'Włącz',
},
},
};
// IMPORTANT: This line is manually replaced in generate translation files by scripts/generateTranslations.ts,
Expand Down
24 changes: 24 additions & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7747,6 +7747,30 @@ ${
fetchError: 'Não foi possível obter os detalhes da configuração SAML',
setMetadataGenericError: 'Não foi possível definir os metadados SAML',
},
accessRestricted: {
title: 'Acesso restrito',
subtitle: (domainName: string) => `Confirme que você é um administrador autorizado da empresa para <strong>${domainName}</strong> se precisar de controle sobre:`,
companyCardManagement: 'Gerenciamento de cartões corporativos',
accountCreationAndDeletion: 'Criação e exclusão de conta',
workspaceCreation: 'Criação do espaço de trabalho',
samlSSO: 'SSO SAML',
},
addDomain: {
title: 'Adicionar domínio',
subtitle: 'Digite o nome do domínio privado que você deseja acessar (ex.: expensify.com).',
domainName: 'Nome de domínio',
newDomain: 'Novo domínio',
},
domainAdded: {
title: 'Domínio adicionado',
description: 'Em seguida, você precisará verificar a propriedade do domínio e ajustar suas configurações de segurança.',
configure: 'Configurar',
},
enhancedSecurity: {
title: 'Segurança aprimorada',
subtitle: 'Exija que os membros do seu domínio façam login por meio de logon único (SSO), restrinja a criação de espaços de trabalho e muito mais.',
enable: 'Ativar',
},
},
};
// IMPORTANT: This line is manually replaced in generate translation files by scripts/generateTranslations.ts,
Expand Down
Loading
Loading