refactor: Simplify click URL resolution logic

This commit is contained in:
gsxdsm
2026-03-02 21:30:49 -08:00
committed by gsxdsm
parent cf3d312eef
commit b2915f4de1
2 changed files with 26 additions and 26 deletions

View File

@@ -588,29 +588,26 @@ export class EventHookService {
eventType: context.eventType,
};
// Build click URL with deep-link if project context is available
let clickUrl = action.clickUrl;
if (!clickUrl && endpoint.defaultClickUrl) {
clickUrl = endpoint.defaultClickUrl;
// If we have a project path and the click URL looks like the server URL,
// append deep-link path
if (context.projectPath && clickUrl) {
try {
const url = new URL(clickUrl);
// Add featureId as query param for deep linking to board with feature output modal
if (context.featureId) {
url.pathname = '/board';
url.searchParams.set('featureId', context.featureId);
} else if (context.projectPath) {
url.pathname = '/board';
}
clickUrl = url.toString();
} catch (error) {
// If URL parsing fails, log warning and use as-is
logger.warn(
`Failed to parse defaultClickUrl "${clickUrl}" for deep linking: ${error instanceof Error ? error.message : String(error)}`
);
// Resolve click URL: action-level overrides endpoint default
let clickUrl = action.clickUrl || endpoint.defaultClickUrl;
// Apply deep-link parameters to the resolved click URL
if (clickUrl && context.projectPath) {
try {
const url = new URL(clickUrl);
// Add featureId as query param for deep linking to board with feature output modal
if (context.featureId) {
url.pathname = '/board';
url.searchParams.set('featureId', context.featureId);
} else {
url.pathname = '/board';
}
clickUrl = url.toString();
} catch (error) {
// If URL parsing fails, log warning and use as-is
logger.warn(
`Failed to parse click URL "${clickUrl}" for deep linking: ${error instanceof Error ? error.message : String(error)}`
);
}
}

View File

@@ -1246,7 +1246,9 @@ describe('EventHookService', () => {
const options = mockFetch.mock.calls[0][1];
// Hook values should override endpoint defaults
expect(options.headers['Tags']).toBe('override-emoji,override-tag');
expect(options.headers['Click']).toBe('https://override.example.com');
// Click URL uses hook-specific base URL with deep link params applied
expect(options.headers['Click']).toContain('https://override.example.com/board');
expect(options.headers['Click']).toContain('featureId=feat-1');
expect(options.headers['Priority']).toBe('5');
});
@@ -1359,7 +1361,7 @@ describe('EventHookService', () => {
expect(clickUrl).not.toContain('featureId=');
});
it('should use hook-specific click URL overriding default with featureId', async () => {
it('should apply deep link params to hook-specific click URL', async () => {
mockFetch.mockResolvedValueOnce({
ok: true,
status: 200,
@@ -1409,8 +1411,9 @@ describe('EventHookService', () => {
const options = mockFetch.mock.calls[0][1];
const clickUrl = options.headers['Click'];
// Should use the hook-specific click URL (not modified with featureId since it's a custom URL)
expect(clickUrl).toBe('https://custom.example.com/custom-page');
// Should use the hook-specific click URL with deep link params applied
expect(clickUrl).toContain('https://custom.example.com/board');
expect(clickUrl).toContain('featureId=feat-789');
});
it('should preserve existing query params when adding featureId', async () => {