Skip to content

Commit 28c0fbf

Browse files
committed
fixup! Apply Git branch dropdown select
1 parent 0b56f66 commit 28c0fbf

File tree

5 files changed

+116
-2
lines changed

5 files changed

+116
-2
lines changed

packages/dashboard-backend/src/routes/api/gitBranches.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { FastifyInstance, FastifyRequest } from 'fastify';
1515
import { baseApiPath } from '@/constants/config';
1616
import { gitBranchSchema } from '@/constants/schemas';
1717
import { restParams } from '@/models';
18-
import { getBranches } from '@/routes/api/helpers/getGitBranches';
18+
import { getBranches } from '@/services/gitClient';
1919
import { getSchema } from '@/services/helpers';
2020

2121
const tags = ['GitBranches'];
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
/*
2+
* Copyright (c) 2018-2025 Red Hat, Inc.
3+
* This program and the accompanying materials are made
4+
* available under the terms of the Eclipse Public License 2.0
5+
* which is available at https://www.eclipse.org/legal/epl-2.0/
6+
*
7+
* SPDX-License-Identifier: EPL-2.0
8+
*
9+
* Contributors:
10+
* Red Hat, Inc. - initial API and implementation
11+
*/
12+
13+
import mockAxios from 'axios';
14+
15+
import { fetchGitBranches } from '@/services/backend-client/gitBranchesApi';
16+
import SessionStorageService, { SessionStorageKey } from '@/services/session-storage';
17+
18+
describe('fetch git branches', () => {
19+
const mockSessionStorageServiceGet = jest.fn();
20+
const mockSessionStorageServiceUpdate = jest.fn();
21+
const mockDateNow = jest.fn();
22+
23+
beforeEach(() => {
24+
jest.clearAllMocks();
25+
SessionStorageService.update = mockSessionStorageServiceUpdate;
26+
SessionStorageService.get = mockSessionStorageServiceGet;
27+
Date.now = mockDateNow;
28+
});
29+
30+
it('should get branches from storage', async () => {
31+
const time = 1555555555555;
32+
const elapsedTime = 59 * 60 * 1000;
33+
mockDateNow.mockReturnValue(time + elapsedTime);
34+
const storageData = { url: { branches: ['branch1', 'branch2'], lastFetched: time } };
35+
mockSessionStorageServiceGet.mockReturnValue(JSON.stringify(storageData));
36+
37+
const response = await fetchGitBranches('url');
38+
39+
expect(response.branches).toEqual(storageData.url.branches);
40+
});
41+
42+
it('should set branches to storage', async () => {
43+
const mockGet = mockAxios.get as jest.Mock;
44+
const branches = ['branch1', 'branch2'];
45+
mockGet.mockResolvedValue({ data: { branches } });
46+
mockDateNow.mockReturnValue(0);
47+
48+
await fetchGitBranches('url');
49+
expect(mockSessionStorageServiceUpdate).toHaveBeenCalledWith(
50+
SessionStorageKey.GIT_BRANCHES,
51+
JSON.stringify({
52+
url: { branches, lastFetched: 0 },
53+
}),
54+
);
55+
});
56+
});

packages/dashboard-frontend/src/services/backend-client/gitBranchesApi.ts

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,17 +14,74 @@ import common, { api } from '@eclipse-che/common';
1414

1515
import { AxiosWrapper } from '@/services/axios-wrapper/axiosWrapper';
1616
import { dashboardBackendPrefix } from '@/services/backend-client/const';
17+
import SessionStorageService, { SessionStorageKey } from '@/services/session-storage';
18+
19+
const EXPIRATION_TIME_FOR_STORED_BRANCHES = 60 * 60 * 1000; // expiration time in milliseconds
1720

1821
/**
1922
* Returns object with git branches list.
2023
*/
2124
export async function fetchGitBranches(url: string): Promise<api.IGitBranches> {
2225
const requestUrl = `${dashboardBackendPrefix}/gitbranches/${encodeURIComponent(url)}`;
2326
try {
27+
const branchesFromStorage = getBranchesFromStorage(url);
28+
if (branchesFromStorage) {
29+
return { branches: branchesFromStorage } as api.IGitBranches;
30+
}
2431
const response =
2532
await AxiosWrapper.createToRetryMissedBearerTokenError().get<api.IGitBranches>(requestUrl);
26-
return response.data;
33+
const data = response.data;
34+
setGitBranchesToStorage(url, data.branches);
35+
return data;
2736
} catch (e) {
2837
throw new Error(`Failed to fetch git branches. ${common.helpers.errors.getMessage(e)}`);
2938
}
3039
}
40+
41+
function getBranchesFromStorage(url: string): string[] | undefined {
42+
const branches = SessionStorageService.get(SessionStorageKey.GIT_BRANCHES);
43+
if (typeof branches !== 'string') {
44+
return undefined;
45+
}
46+
try {
47+
const branchesObj = JSON.parse(branches);
48+
if (!branchesObj[url]?.lastFetched || !branchesObj[url]?.branches) {
49+
return undefined;
50+
}
51+
const timeElapsed = Date.now() - branchesObj[url]?.lastFetched;
52+
if (timeElapsed > EXPIRATION_TIME_FOR_STORED_BRANCHES) {
53+
return undefined;
54+
}
55+
return branchesObj[url]?.branches;
56+
} catch (e) {
57+
return undefined;
58+
}
59+
}
60+
61+
function setGitBranchesToStorage(url: string, branches: string[]): void {
62+
const gitBranches = SessionStorageService.get(SessionStorageKey.GIT_BRANCHES);
63+
let gitBranchesObj: {
64+
[url: string]: {
65+
branches: string[];
66+
lastFetched: number;
67+
};
68+
};
69+
if (typeof gitBranches === 'string') {
70+
try {
71+
gitBranchesObj = JSON.parse(gitBranches);
72+
} catch (e) {
73+
gitBranchesObj = {};
74+
}
75+
} else {
76+
gitBranchesObj = {};
77+
}
78+
gitBranchesObj[url] = {
79+
branches,
80+
lastFetched: Date.now(),
81+
};
82+
try {
83+
SessionStorageService.update(SessionStorageKey.GIT_BRANCHES, JSON.stringify(gitBranchesObj));
84+
} catch (e) {
85+
// noop
86+
}
87+
}

packages/dashboard-frontend/src/services/session-storage/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ export enum SessionStorageKey {
1414
PRIVATE_FACTORY_RELOADS = 'private-factory-reloads-number',
1515
ORIGINAL_LOCATION_PATH = 'original-location-path',
1616
EXTERNAL_REGISTRIES = 'external-registries',
17+
GIT_BRANCHES = 'git-branches',
1718
}
1819

1920
export default class SessionStorageService {

0 commit comments

Comments
 (0)