Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
7a4ba4b
add members page to domains
sumo-slonik Dec 16, 2025
7d2aaef
Merge branch 'main' into feature/kuba-nowakowski/add__domain_members_…
sumo-slonik Dec 17, 2025
276fd9e
fix general members component after marge from main
sumo-slonik Dec 17, 2025
4fc8339
fix SecurityGroup type
sumo-slonik Dec 17, 2025
5d2698e
review changes
sumo-slonik Dec 18, 2025
d376360
changes after review without components from main
sumo-slonik Dec 18, 2025
984e680
Merge branch 'main' into feature/kuba-nowakowski/add__domain_members_…
sumo-slonik Dec 18, 2025
f8d5411
changes after review with components from main
sumo-slonik Dec 18, 2025
010d826
add test to selector
sumo-slonik Dec 18, 2025
896d64a
simplify selector
sumo-slonik Dec 18, 2025
2cdf216
remove unnecessary useMemo, useCallback
sumo-slonik Dec 18, 2025
ac42828
Merge branch 'main' into feature/kuba-nowakowski/add__domain_members_…
sumo-slonik Dec 22, 2025
00d70f1
add new admin features to page using baseMemberPage
sumo-slonik Dec 22, 2025
5313572
remove callback
sumo-slonik Dec 22, 2025
96e0d89
npm run prettier
sumo-slonik Dec 22, 2025
7183f29
add spain translations
sumo-slonik Dec 23, 2025
fcd8581
remove polish comment
sumo-slonik Dec 23, 2025
56ba188
Merge branch 'main' into feature/kuba-nowakowski/add__domain_members_…
sumo-slonik Dec 23, 2025
6cbbbd8
Merge branch 'main' into feature/kuba-nowakowski/add__domain_members_…
sumo-slonik Dec 23, 2025
900a841
remove polish comment
sumo-slonik Dec 23, 2025
827b5fc
fix selector typing
sumo-slonik Dec 23, 2025
4d9aa05
fix import
sumo-slonik Dec 23, 2025
b01543f
remove unnecessary if(loading)
sumo-slonik Dec 23, 2025
2e74fa4
resolve Jan's comments
sumo-slonik Dec 23, 2025
8baba9b
Merge branch 'main' into feature/kuba-nowakowski/add__domain_members_…
war-in Jan 7, 2026
10467eb
chore: add translations
war-in Jan 7, 2026
a0a234a
fix: improve types in addAdminToDomain
war-in Jan 7, 2026
7c2c1c4
feat: update icons
war-in Jan 7, 2026
ef1ced1
Merge branch 'main' into feature/kuba-nowakowski/add__domain_members_…
war-in Jan 7, 2026
9bb3367
refactor: move expensify_adminPermissions_ and domain_securityGroup_ …
war-in Jan 7, 2026
9bd0c0e
chore: compress svg
war-in Jan 7, 2026
501fb34
chore: fix eslint
war-in Jan 8, 2026
f933295
Merge branch 'refs/heads/main' into feature/kuba-nowakowski/add__doma…
war-in Jan 8, 2026
718e428
refactor: address review
war-in Jan 8, 2026
0aeee27
fix: dont show Hidden as selected on add primary contact page
war-in Jan 9, 2026
b32bdc1
Merge branch 'main' into feature/kuba-nowakowski/add__domain_members_…
war-in Jan 9, 2026
d666c78
fix: prettier
war-in Jan 9, 2026
50fe039
Merge branch 'refs/heads/main' into feature/kuba-nowakowski/add__doma…
war-in Jan 12, 2026
c5f471f
fix: post-merge fixes
war-in Jan 12, 2026
8c48a19
Merge branch 'main' into feature/kuba-nowakowski/add__domain_members_…
war-in Jan 12, 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
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
7 changes: 7 additions & 0 deletions src/CONST/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7907,6 +7907,13 @@ const CONST = {
HEADER_ACTION_BUTTON: 'Task-HeaderActionButton',
},
},

DOMAIN: {
/** Onyx prefix for domain admin account IDs */
EXPENSIFY_ADMIN_ACCESS_PREFIX: 'expensify_adminPermissions_',
/** Onyx prefix for domain security groups */
DOMAIN_SECURITY_GROUP_PREFIX: 'domain_securityGroup_',
},
} as const;

const CONTINUATION_DETECTION_SEARCH_FILTER_KEYS = [
Expand Down
4 changes: 0 additions & 4 deletions src/ONYXKEYS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -761,9 +761,6 @@ const ONYXKEYS = {
/** SAML login metadata for a domain */
SAML_METADATA: 'saml_metadata_',

/** Stores domain admin account ID */
EXPENSIFY_ADMIN_ACCESS_PREFIX: 'expensify_adminPermissions_',

/** Pending actions for a domain */
DOMAIN_PENDING_ACTIONS: 'domainPendingActions_',

Expand Down Expand Up @@ -1160,7 +1157,6 @@ type OnyxCollectionValuesMapping = {
[ONYXKEYS.COLLECTION.ISSUE_NEW_EXPENSIFY_CARD]: OnyxTypes.IssueNewCard;
[ONYXKEYS.COLLECTION.SHARED_NVP_PRIVATE_ADMIN_ACCESS]: boolean;
[ONYXKEYS.COLLECTION.SAML_METADATA]: OnyxTypes.SamlMetadata;
[ONYXKEYS.COLLECTION.EXPENSIFY_ADMIN_ACCESS_PREFIX]: number;
[ONYXKEYS.COLLECTION.DOMAIN_PENDING_ACTIONS]: OnyxTypes.DomainPendingActions;
[ONYXKEYS.COLLECTION.DOMAIN_ERRORS]: OnyxTypes.DomainErrors;
};
Expand Down
4 changes: 4 additions & 0 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3600,6 +3600,10 @@ const ROUTES = {
route: 'domain/:domainAccountID/admins/invite',
getRoute: (domainAccountID: number) => `domain/${domainAccountID}/admins/invite` as const,
},
DOMAIN_MEMBERS: {
route: 'domain/:domainAccountID/members',
getRoute: (domainAccountID: number) => `domain/${domainAccountID}/members` as const,
},
} as const;

/**
Expand Down
1 change: 1 addition & 0 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -874,6 +874,7 @@ const SCREENS = {
ADMINS_SETTINGS: 'Admins_Settings',
ADD_PRIMARY_CONTACT: 'Add_Primary_Contact',
ADD_ADMIN: 'Domain_Add_Admin',
MEMBERS: 'Domain_Members',
},
} as const;

Expand Down
2 changes: 2 additions & 0 deletions src/components/Icon/chunks/illustrations.chunk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ import TrashCan from '@assets/images/simple-illustrations/simple-illustration__t
import TravelAlerts from '@assets/images/simple-illustrations/simple-illustration__travelalerts.svg';
import TreasureChest from '@assets/images/simple-illustrations/simple-illustration__treasurechest.svg';
import CompanyCard from '@assets/images/simple-illustrations/simple-illustration__twocards-horizontal.svg';
import UserShield from '@assets/images/simple-illustrations/simple-illustration__user-shield.svg';
import VirtualCard from '@assets/images/simple-illustrations/simple-illustration__virtualcard.svg';
import Workflows from '@assets/images/simple-illustrations/simple-illustration__workflows.svg';
import ExpensifyApprovedLogo from '@assets/images/subscription-details__approvedlogo.svg';
Expand Down Expand Up @@ -329,6 +330,7 @@ const Illustrations = {
ShieldYellow,
Clock,
Members,
UserShield,
};

/**
Expand Down
1 change: 1 addition & 0 deletions src/languages/de.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7933,6 +7933,7 @@ Hier ist ein *Testbeleg*, um dir zu zeigen, wie es funktioniert:`,
cantRevokeAdminAccess: 'Adminzugriff kann dem technischen Ansprechpartner nicht entzogen werden',
error: {removeAdmin: 'Dieser Benutzer kann nicht als Admin entfernt werden. Bitte versuchen Sie es erneut.'},
},
members: {title: 'Mitglieder', findMember: 'Mitglied suchen'},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure why the formatting is bit different for each of these

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's how the parrot did that. I didn't change anything so not sure too 🤷

@ZhenjaHorbach ZhenjaHorbach Jan 8, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you try npm run prettier?
But as I remember, we have a similar format in other places

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, I tried that

},
gps: {
tooltip: 'GPS-Verfolgung läuft! Wenn du fertig bist, stoppe die Verfolgung unten.',
Expand Down
4 changes: 4 additions & 0 deletions src/languages/en.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7841,6 +7841,10 @@ const translations = {
removeAdmin: 'Unable to remove this user as an Admin. Please try again.',
},
},
members: {
title: 'Members',
findMember: 'Find member',
},
},
};

Expand Down
4 changes: 4 additions & 0 deletions src/languages/es.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8009,6 +8009,10 @@ ${amount} para ${merchant} - ${date}`,
cantRevokeAdminAccess: 'No se puede revocar el acceso de administrador del contacto técnico',
error: {removeAdmin: 'No se pudo eliminar a este usuario como administrador. Por favor, inténtalo de nuevo.'},
},
members: {
title: 'Miembros',
findMember: 'Buscar miembro',
},
},
gps: {
tooltip: '¡Seguimiento por GPS en curso! Cuando termines, detén el seguimiento a continuación.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/fr.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7937,6 +7937,7 @@ Voici un *reçu test* pour vous montrer comment cela fonctionne :`,
cantRevokeAdminAccess: 'Impossible de révoquer l’accès administrateur au contact technique',
error: {removeAdmin: 'Impossible de supprimer cet utilisateur en tant qu’administrateur. Veuillez réessayer.'},
},
members: {title: 'Membres', findMember: 'Rechercher un membre'},
},
gps: {
tooltip: 'Suivi GPS en cours ! Quand vous avez terminé, arrêtez le suivi ci-dessous.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/it.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7915,6 +7915,7 @@ Ecco una *ricevuta di prova* per mostrarti come funziona:`,
cantRevokeAdminAccess: 'Impossibile revocare i privilegi di amministratore dal referente tecnico',
error: {removeAdmin: 'Impossibile rimuovere questo utente come amministratore. Riprova.'},
},
members: {title: 'Membri', findMember: 'Trova membro'},
},
gps: {
tooltip: 'Monitoraggio GPS in corso! Quando hai finito, interrompi il monitoraggio qui sotto.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/ja.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7853,6 +7853,7 @@ Expensify の使い方をお見せするための*テストレシート*がこ
cantRevokeAdminAccess: '技術連絡先から管理者アクセス権を取り消すことはできません',
error: {removeAdmin: 'このユーザーを管理者として削除できません。もう一度お試しください。'},
},
members: {title: 'メンバー', findMember: 'メンバーを検索'},
},
gps: {
tooltip: 'GPS 追跡を進行中です!完了したら、下で追跡を停止してください。',
Expand Down
1 change: 1 addition & 0 deletions src/languages/nl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7904,6 +7904,7 @@ Hier is een *testbon* om je te laten zien hoe het werkt:`,
cantRevokeAdminAccess: 'Kan de beheerdersrechten niet intrekken van de technische contactpersoon',
error: {removeAdmin: 'Kan deze gebruiker niet als beheerder verwijderen. Probeer het opnieuw.'},
},
members: {title: 'Leden', findMember: 'Lid zoeken'},
},
gps: {
tooltip: 'GPS-tracking bezig! Als je klaar bent, stop dan hieronder met tracken.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/pl.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7884,6 +7884,7 @@ Oto *paragon testowy*, który pokazuje, jak to działa:`,
cantRevokeAdminAccess: 'Nie można odebrać uprawnień administratora kontaktowi technicznemu',
error: {removeAdmin: 'Nie można usunąć tego użytkownika jako administratora. Spróbuj ponownie.'},
},
members: {title: 'Członkowie', findMember: 'Znajdź członka'},
},
gps: {
tooltip: 'Śledzenie GPS w toku! Gdy skończysz, zatrzymaj śledzenie poniżej.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/pt-BR.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7891,6 +7891,7 @@ Aqui está um *recibo de teste* para mostrar como funciona:`,
cantRevokeAdminAccess: 'Não é possível revogar o acesso de administrador do contato técnico',
error: {removeAdmin: 'Não foi possível remover este usuário como Administrador. Tente novamente.'},
},
members: {title: 'Membros', findMember: 'Encontrar membro'},
},
gps: {
tooltip: 'Rastreamento por GPS em andamento! Quando terminar, pare o rastreamento abaixo.',
Expand Down
1 change: 1 addition & 0 deletions src/languages/zh-hans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7708,6 +7708,7 @@ ${reportName}
cantRevokeAdminAccess: '无法撤销技术联系人的管理员访问权限',
error: {removeAdmin: '无法将此用户移除管理员角色。请重试。'},
},
members: {title: '成员', findMember: '查找成员'},
},
gps: {
tooltip: 'GPS 跟踪进行中!完成后,请在下方停止跟踪。',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import type ReactComponentModule from '@src/types/utils/ReactComponentModule';
const loadDomainInitialPage = () => require<ReactComponentModule>('../../../../pages/domain/DomainInitialPage').default;
const loadDomainSamlPage = () => require<ReactComponentModule>('../../../../pages/domain/DomainSamlPage').default;
const loadDomainAdminsPage = () => require<ReactComponentModule>('../../../../pages/domain/Admins/DomainAdminsPage').default;
const loadDomainMembersPage = () => require<ReactComponentModule>('../../../../pages/domain/Members/DomainMembersPage').default;

const Split = createSplitNavigator<DomainSplitNavigatorParamList>();

Expand Down Expand Up @@ -50,6 +51,12 @@ function DomainSplitNavigator({route, navigation}: PlatformStackScreenProps<Auth
name={SCREENS.DOMAIN.ADMINS}
getComponent={loadDomainAdminsPage}
/>

<Split.Screen
key={SCREENS.DOMAIN.MEMBERS}
name={SCREENS.DOMAIN.MEMBERS}
getComponent={loadDomainMembersPage}
/>
</Split.Navigator>
</View>
</FocusTrapForScreens>
Expand Down
3 changes: 3 additions & 0 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2014,6 +2014,9 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
[SCREENS.DOMAIN.ADMINS]: {
path: ROUTES.DOMAIN_ADMINS.route,
},
[SCREENS.DOMAIN.MEMBERS]: {
path: ROUTES.DOMAIN_MEMBERS.route,
},
},
},

Expand Down
3 changes: 3 additions & 0 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2511,6 +2511,9 @@ type DomainSplitNavigatorParamList = {
[SCREENS.DOMAIN.ADMINS]: {
domainAccountID: number;
};
[SCREENS.DOMAIN.MEMBERS]: {
domainAccountID: number;
};
};

type OnboardingModalNavigatorParamList = {
Expand Down
5 changes: 3 additions & 2 deletions src/libs/actions/Domain.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {getMicroSecondOnyxErrorWithTranslationKey} from '@libs/ErrorUtils';
import {getAuthToken} from '@libs/Network/NetworkStore';
import CONST from '@src/CONST';
import ONYXKEYS from '@src/ONYXKEYS';
import type PrefixedRecord from '@src/types/utils/PrefixedRecord';
import type {ScimTokenWithState} from './ScimToken/ScimTokenUtils';
import {ScimTokenState} from './ScimToken/ScimTokenUtils';

Expand Down Expand Up @@ -527,15 +528,15 @@ function clearToggleConsolidatedDomainBillingErrors(domainAccountID: number) {
}

function addAdminToDomain(domainAccountID: number, accountID: number, targetEmail: string, domainName: string) {
const PERMISSION_KEY = `${ONYXKEYS.COLLECTION.EXPENSIFY_ADMIN_ACCESS_PREFIX}${accountID}`;
const PERMISSION_KEY = `${CONST.DOMAIN.EXPENSIFY_ADMIN_ACCESS_PREFIX}${accountID}`;

const optimisticData: OnyxUpdate[] = [
{
onyxMethod: Onyx.METHOD.MERGE,
key: `${ONYXKEYS.COLLECTION.DOMAIN}${domainAccountID}`,
value: {
[PERMISSION_KEY]: accountID,
},
} as PrefixedRecord<typeof CONST.DOMAIN.EXPENSIFY_ADMIN_ACCESS_PREFIX, number>,
},
{
onyxMethod: Onyx.METHOD.MERGE,
Expand Down
6 changes: 4 additions & 2 deletions src/pages/domain/Admins/DomainAddPrimaryContactPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,13 @@ function DomainAddPrimaryContactPage({route}: DomainAddPrimaryContactPageProps)
}

const details = personalDetails?.[accountID];
if (details?.login === technicalContactSettings?.technicalContactEmail) {
let isSelected = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NAB: Since all we need from the technicalContactSettings in this component is the email imho we should use the selector to directly pull the email

if (!!details?.login && !!technicalContactSettings?.technicalContactEmail && details.login === technicalContactSettings.technicalContactEmail) {
technicalContactEmailKey = String(accountID);
isSelected = true;
}
data.push({
isSelected: details?.login === technicalContactSettings?.technicalContactEmail,
isSelected,
keyForList: String(accountID),
accountID,
login: details?.login ?? '',
Expand Down
Loading
Loading