Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
69 changes: 39 additions & 30 deletions src/ROUTES.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,45 @@ const DYNAMIC_ROUTES = {
path: 'visibility',
entryScreens: [SCREENS.REPORT_SETTINGS.ROOT],
},
SETTINGS_TAG_CREATE: {
path: 'tag-create',
entryScreens: [SCREENS.SETTINGS_TAGS.SETTINGS_TAGS_ROOT],
},
SETTINGS_TAGS_EDIT: {
path: 'tags-edit',
entryScreens: [SCREENS.SETTINGS_TAGS.SETTINGS_TAGS_SETTINGS, SCREENS.SETTINGS_TAGS.SETTINGS_TAG_LIST_VIEW],
getRoute: (orderWeight: number) => `tags-edit?orderWeight=${orderWeight}`,
queryParams: ['orderWeight'],
},
SETTINGS_TAG_SETTINGS: {
path: 'tag-settings',
entryScreens: [SCREENS.SETTINGS_TAGS.SETTINGS_TAGS_ROOT, SCREENS.SETTINGS_TAGS.SETTINGS_TAG_LIST_VIEW, SCREENS.SETTINGS_TAGS.SETTINGS_TAG_APPROVER],
getRoute: (orderWeight: number, tagName: string, parentTagsFilter?: string) =>
getUrlWithParams('tag-settings', {
orderWeight,
tagName,
parentTagsFilter,
}),
queryParams: ['orderWeight', 'tagName', 'parentTagsFilter'],
},
SETTINGS_TAG_EDIT: {
path: 'tag-edit',
entryScreens: [SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_SETTINGS],
getRoute: (orderWeight?: number, tagName?: string) =>
getUrlWithParams('tag-edit', {
orderWeight,
tagName,
}),
},
SETTINGS_TAG_GL_CODE: {
path: 'tag-gl-code',
entryScreens: [SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_SETTINGS],
getRoute: (orderWeight?: number, tagName?: string) =>
getUrlWithParams('tag-gl-code', {
orderWeight,
tagName,
}),
},
POLICY_ACCOUNTING_NETSUITE_EXPORT_EXPENSES_VENDOR_SELECT: {
path: 'vendor/select',
entryScreens: [SCREENS.WORKSPACE.ACCOUNTING.NETSUITE_EXPORT_EXPENSES],
Expand Down Expand Up @@ -1366,30 +1405,6 @@ const ROUTES = {
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
getRoute: (policyID: string, backTo = '') => getUrlWithBackToParam(`settings/${policyID}/tags/settings` as const, backTo),
},
SETTINGS_TAGS_EDIT: {
route: 'settings/:policyID/tags/:orderWeight/edit',

// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
getRoute: (policyID: string, orderWeight: number, backTo = '') => getUrlWithBackToParam(`settings/${policyID}/tags/${orderWeight}/edit` as const, backTo),
},
SETTINGS_TAG_CREATE: {
route: 'settings/:policyID/tags/new',

// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
getRoute: (policyID: string, backTo = '') => getUrlWithBackToParam(`settings/${policyID}/tags/new` as const, backTo),
},
SETTINGS_TAG_EDIT: {
route: 'settings/:policyID/tag/:orderWeight/:tagName/edit',
getRoute: (policyID: string, orderWeight: number, tagName: string, backTo = '') =>
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
getUrlWithBackToParam(`settings/${policyID}/tag/${orderWeight}/${encodeURIComponent(tagName)}/edit` as const, backTo),
},
SETTINGS_TAG_SETTINGS: {
route: 'settings/:policyID/tag/:orderWeight/:tagName',
getRoute: (policyID: string, orderWeight: number, tagName: string, backTo = '') =>
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
getUrlWithBackToParam(`settings/${policyID}/tag/${orderWeight}/${encodeURIComponent(tagName)}` as const, backTo),
},
SETTINGS_TAG_APPROVER: {
route: 'settings/:policyID/tag/:orderWeight/:tagName/approver',
getRoute: (policyID: string, orderWeight: number, tagName: string, backTo = '') =>
Expand All @@ -1402,12 +1417,6 @@ const ROUTES = {
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
getRoute: (policyID: string, orderWeight: number, backTo = '') => getUrlWithBackToParam(`settings/${policyID}/tag-list/${orderWeight}` as const, backTo),
},
SETTINGS_TAG_GL_CODE: {
route: 'settings/:policyID/tag/:orderWeight/:tagName/gl-code',
getRoute: (policyID: string, orderWeight: number, tagName: string, backTo = '') =>
// eslint-disable-next-line no-restricted-syntax -- Legacy route generation
getUrlWithBackToParam(`settings/${policyID}/tag/${orderWeight}/${encodeURIComponent(tagName)}/gl-code` as const, backTo),
},
SETTINGS_TAGS_IMPORT: {
route: 'settings/:policyID/tags/import',

Expand Down
10 changes: 5 additions & 5 deletions src/SCREENS.ts
Original file line number Diff line number Diff line change
Expand Up @@ -451,13 +451,13 @@ const SCREENS = {
SETTINGS_TAGS: {
SETTINGS_TAGS_ROOT: 'Settings_Tags',
SETTINGS_TAGS_SETTINGS: 'Settings_Tags_Settings',
SETTINGS_TAGS_EDIT: 'Settings_Tags_Edit',
SETTINGS_TAG_CREATE: 'Settings_Tag_Create',
SETTINGS_TAG_EDIT: 'Settings_Tag_Edit',
SETTINGS_TAG_SETTINGS: 'Settings_Tag_Settings',
DYNAMIC_TAGS_EDIT: 'Dynamic_Settings_Tags_Edit',
DYNAMIC_TAG_CREATE: 'Dynamic_Settings_Tag_Create',
DYNAMIC_TAG_EDIT: 'Dynamic_Settings_Tag_Edit',
DYNAMIC_TAG_SETTINGS: 'Dynamic_Settings_Tag_Settings',
SETTINGS_TAG_APPROVER: 'Settings_Tag_Approver',
SETTINGS_TAG_LIST_VIEW: 'Settings_Tag_List_View',
SETTINGS_TAG_GL_CODE: 'Settings_Tag_GL_Code',
DYNAMIC_TAG_GL_CODE: 'Dynamic_Settings_Tag_GL_Code',
SETTINGS_TAGS_IMPORT: 'Settings_Tags_Import',
SETTINGS_TAGS_IMPORTED: 'Settings_Tags_Imported',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,16 +321,16 @@ const CategoriesModalStackNavigator = createModalStackNavigator({

const TagsModalStackNavigator = createModalStackNavigator({
[SCREENS.SETTINGS_TAGS.SETTINGS_TAGS_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/WorkspaceTagsSettingsPage').default,
[SCREENS.SETTINGS_TAGS.SETTINGS_TAGS_EDIT]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/WorkspaceEditTagsPage').default,
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAGS_EDIT]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/WorkspaceEditTagsPage').default,
[SCREENS.SETTINGS_TAGS.SETTINGS_TAGS_IMPORT]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/ImportTagsPage').default,
[SCREENS.WORKSPACE.TAGS_IMPORT_OPTIONS]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/ImportTagsOptionsPage').default,
[SCREENS.SETTINGS_TAGS.SETTINGS_TAGS_IMPORTED]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/ImportedTagsPage').default,
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/TagSettingsPage').default,
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_SETTINGS]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/TagSettingsPage').default,
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_LIST_VIEW]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/WorkspaceViewTagsPage').default,
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_CREATE]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/WorkspaceCreateTagPage').default,
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_EDIT]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/EditTagPage').default,
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_CREATE]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/WorkspaceCreateTagPage').default,
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_EDIT]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/EditTagPage').default,
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_APPROVER]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/TagApproverPage').default,
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_GL_CODE]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/TagGLCodePage').default,
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_GL_CODE]: () => require<ReactComponentModule>('../../../../pages/workspace/tags/TagGLCodePage').default,
});

const ExpensifyCardModalStackNavigator = createModalStackNavigator({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import {DYNAMIC_ROUTES} from '@src/ROUTES';
import type {DynamicRouteSuffix} from '@src/ROUTES';
import splitPathAndQuery from './splitPathAndQuery';

type ParseConfig = Record<string, (value: string) => unknown>;

type LeafRoute = {
name: string;
path: string;
Expand All @@ -26,7 +28,7 @@ const configEntries = Object.entries(normalizedConfigs);
*
* @private - Internal helper. Do not export or use outside this file.
*/
function getParamsFromQuery(query: string | undefined): Record<string, string> | undefined {
function getParamsFromQuery(query: string | undefined, parseConfig?: ParseConfig): Record<string, unknown> | undefined {
if (!query) {
return undefined;
}
Expand All @@ -36,28 +38,45 @@ function getParamsFromQuery(query: string | undefined): Record<string, string> |
return undefined;
}

return Object.fromEntries(entries);
return Object.fromEntries(
entries.map(([key, value]) => {
const parser = parseConfig?.[key];

if (!parser) {
return [key, value];
}

try {
return [key, parser(value)];
} catch {
return [key, value];
}
}),
);
}

/**
* Looks up the navigation screen hierarchy (routeNames) for a given dynamic route suffix.
*
* @private - Internal helper. Do not export or use outside this file.
*/
function getRouteNamesForDynamicRoute(dynamicRouteName: DynamicRouteSuffix): string[] | null {
function getRouteConfigForDynamicRoute(dynamicRouteName: DynamicRouteSuffix): {routeNames: string[]; parse?: ParseConfig} | null {
for (const [, config] of configEntries) {
if (config.path === dynamicRouteName) {
return config.routeNames;
return {
routeNames: config.routeNames,
parse: config.parse,
};
}
}

return null;
}

function getStateForDynamicRoute(path: string, dynamicRouteName: keyof typeof DYNAMIC_ROUTES, parentRouteParams?: Record<string, unknown>) {
const routeConfig = getRouteNamesForDynamicRoute(DYNAMIC_ROUTES[dynamicRouteName].path);
const routeConfig = getRouteConfigForDynamicRoute(DYNAMIC_ROUTES[dynamicRouteName].path);
const [, query] = splitPathAndQuery(path);
const params = getParamsFromQuery(query);
const params = getParamsFromQuery(query, routeConfig?.parse);

if (!routeConfig) {
throw new Error(`No route configuration found for dynamic route '${dynamicRouteName}'`);
Expand Down Expand Up @@ -89,7 +108,7 @@ function getStateForDynamicRoute(path: string, dynamicRouteName: keyof typeof DY
};

// Start building from the first route
const rootRoute = {routes: [buildNestedState(routeConfig, 0)]};
const rootRoute = {routes: [buildNestedState(routeConfig.routeNames, 0)]};

return rootRoute;
}
Expand Down
20 changes: 9 additions & 11 deletions src/libs/Navigation/linkingConfig/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1502,23 +1502,21 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
[SCREENS.SETTINGS_TAGS.SETTINGS_TAGS_SETTINGS]: {
path: ROUTES.SETTINGS_TAGS_SETTINGS.route,
},
[SCREENS.SETTINGS_TAGS.SETTINGS_TAGS_EDIT]: {
path: ROUTES.SETTINGS_TAGS_EDIT.route,
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAGS_EDIT]: {
path: DYNAMIC_ROUTES.SETTINGS_TAGS_EDIT.path,
parse: {
orderWeight: Number,
},
},
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_CREATE]: {
path: ROUTES.SETTINGS_TAG_CREATE.route,
},
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_EDIT]: {
path: ROUTES.SETTINGS_TAG_EDIT.route,
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_CREATE]: DYNAMIC_ROUTES.SETTINGS_TAG_CREATE.path,
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_EDIT]: {
path: DYNAMIC_ROUTES.SETTINGS_TAG_EDIT.path,
parse: {
orderWeight: Number,
},
},
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_SETTINGS]: {
path: ROUTES.SETTINGS_TAG_SETTINGS.route,
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_SETTINGS]: {
path: DYNAMIC_ROUTES.SETTINGS_TAG_SETTINGS.path,
parse: {
orderWeight: Number,
},
Expand All @@ -1535,8 +1533,8 @@ const config: LinkingOptions<RootNavigatorParamList>['config'] = {
orderWeight: Number,
},
},
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_GL_CODE]: {
path: ROUTES.SETTINGS_TAG_GL_CODE.route,
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_GL_CODE]: {
path: DYNAMIC_ROUTES.SETTINGS_TAG_GL_CODE.path,
parse: {
orderWeight: Number,
},
Expand Down
20 changes: 5 additions & 15 deletions src/libs/Navigation/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -459,10 +459,8 @@ type SettingsNavigatorParamList = {
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
backTo?: Routes;
};
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_CREATE]: {
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_CREATE]: {
policyID: string;
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
backTo?: Routes;
};
[SCREENS.WORKSPACE.DISTANCE_RATE_DETAILS]: {
policyID: string;
Expand Down Expand Up @@ -537,12 +535,10 @@ type SettingsNavigatorParamList = {
backTo?: Routes;
parentTagsFilter?: string;
};
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_SETTINGS]: {
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_SETTINGS]: {
policyID: string;
orderWeight: number;
tagName: string;
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
backTo?: Routes;
parentTagsFilter?: string;
};
[SCREENS.WORKSPACE.TAG_LIST_VIEW]: {
Expand All @@ -563,11 +559,9 @@ type SettingsNavigatorParamList = {
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
backTo?: Routes;
};
[SCREENS.SETTINGS_TAGS.SETTINGS_TAGS_EDIT]: {
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAGS_EDIT]: {
policyID: string;
orderWeight: number;
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
backTo?: Routes;
};
[SCREENS.WORKSPACE.TAG_EDIT]: {
policyID: string;
Expand All @@ -576,12 +570,10 @@ type SettingsNavigatorParamList = {
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
backTo?: Routes;
};
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_EDIT]: {
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_EDIT]: {
policyID: string;
orderWeight: number;
tagName: string;
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
backTo?: Routes;
};
[SCREENS.WORKSPACE.TAG_APPROVER]: {
policyID: string;
Expand All @@ -604,12 +596,10 @@ type SettingsNavigatorParamList = {
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
backTo?: Routes;
};
[SCREENS.SETTINGS_TAGS.SETTINGS_TAG_GL_CODE]: {
[SCREENS.SETTINGS_TAGS.DYNAMIC_TAG_GL_CODE]: {
policyID: string;
orderWeight: number;
tagName: string;
// eslint-disable-next-line no-restricted-syntax -- `backTo` usages in this file are legacy. Do not add new `backTo` params to screens. See contributingGuides/NAVIGATION.md
backTo?: Routes;
};
[SCREENS.SETTINGS.SUBSCRIPTION.SIZE]: {
canChangeSize: 0 | 1;
Expand Down
2 changes: 1 addition & 1 deletion src/libs/Url.ts
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ function getUrlWithParams<TBase extends string, TParams extends UrlParams>(baseU
const searchParams = new URLSearchParams(existingQuery || '');

for (const [key, value] of Object.entries(params)) {
if (value) {
if (value !== undefined && value !== '') {
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I updated this to handle the case where the value is 0.

searchParams.set(key, String(value));
}
}
Expand Down
Loading
Loading