Skip to content

Commit d1726ed

Browse files
Feature/infinite user loading (#854)
* added the infinite user loading feature * fixed the bugs in the loading * altered the API_BASE_URL to original one * added the infinite user loading feature * fixed the bugs in the loading * altered the API_BASE_URL to original one * updated the loader property * updated the test for the loading feature --------- Co-authored-by: Vinit khandal <[email protected]>
1 parent 7cb2884 commit d1726ed

File tree

5 files changed

+95
-89
lines changed

5 files changed

+95
-89
lines changed

__tests__/users/user-management-home-screen.test.js

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -116,32 +116,24 @@ describe('Tests the User Management User Listing Screen', () => {
116116
expect(userCard.length).toBeGreaterThan(0);
117117
});
118118

119-
it('checks the next and previous button functionality', async () => {
119+
it('checks infinite scroll functionality to load more users', async () => {
120120
await page.goto('http://localhost:8000/users');
121121
await page.waitForNetworkIdle();
122122

123-
// Get the "next" button and check if it is enabled
124-
const nextBtn = await page.$('#nextButton');
125-
const isNextButtonDisabled = await page.evaluate(
126-
(button) => button.disabled,
127-
nextBtn,
128-
);
129-
expect(isNextButtonDisabled).toBe(false);
123+
const userList = await page.$('#user-list');
124+
let initialUserCount = await userList.$$eval('li', (items) => items.length);
125+
expect(initialUserCount).toBeGreaterThan(0);
130126

131-
// Click the "next" button and wait for the page to load
132-
await nextBtn.click();
127+
// Scroll to the bottom of the page to trigger infinite scroll
128+
await page.evaluate(() => {
129+
window.scrollTo(0, document.body.scrollHeight);
130+
});
133131
await page.waitForNetworkIdle();
134-
135-
// Check that the "next" button is still present and the "previous" button is not disabled
136-
const updatedNextButton = await page.$('#nextButton');
137-
expect(updatedNextButton).toBeTruthy();
138-
139-
const prevBtn = await page.$('#prevButton');
140-
const isPrevButtonDisabled = await page.evaluate(
141-
(button) => button.disabled,
142-
prevBtn,
132+
const updatedUserCount = await userList.$$eval(
133+
'li',
134+
(items) => items.length,
143135
);
144-
expect(isPrevButtonDisabled).toBe(false);
136+
expect(updatedUserCount).toBeGreaterThanOrEqual(initialUserCount);
145137
});
146138

147139
it('Clicking on filter button should display filter modal', async () => {

users/constants.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ const RDS_API_USERS = `${API_BASE_URL}/users`;
22
const RDS_API_SKILLS = `${API_BASE_URL}/tags`;
33
const USER_LIST_ELEMENT = 'user-list';
44
const LOADER_ELEMENT = 'loader';
5+
const USER_LOADER_ELEMENT = 'loader_tag';
56
const TILE_VIEW_BTN = 'tile-view-btn';
67
const TABLE_VIEW_BTN = 'table-view-btn';
78
const USER_SEARCH_ELEMENT = 'user-search';

users/index.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,9 @@ <h2>Skills</h2>
6969
</div>
7070
<div id="user-list">
7171
<div id="loader"></div>
72+
<ul id="head_list"></ul>
7273
</div>
74+
<div id="loader_tag" style="display: none"></div>
7375
<div id="pagination" class="remove-element">
7476
<button class="pagination-btn" id="prevButton">&laquo; Previous</button>
7577
<button class="pagination-btn" id="nextButton">Next &raquo;</button>

users/script.js

Lines changed: 64 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const params = new URLSearchParams(window.location.search);
22
const userListElement = document.getElementById(USER_LIST_ELEMENT);
33
const loaderElement = document.getElementById(LOADER_ELEMENT);
4+
const userloaderElement = document.getElementById(USER_LOADER_ELEMENT);
45
const tileViewBtn = document.getElementById(TILE_VIEW_BTN);
56
const tableViewBtn = document.getElementById(TABLE_VIEW_BTN);
67
const userSearchElement = document.getElementById(USER_SEARCH_ELEMENT);
@@ -15,7 +16,9 @@ const clearButton = document.getElementById(CLEAR_BUTTON);
1516

1617
let tileViewActive = false;
1718
let tableViewActive = true;
19+
let isLoading = false;
1820
let page = 0;
21+
let run = true;
1922

2023
const init = (
2124
prevBtn,
@@ -27,26 +30,23 @@ const init = (
2730
paginationElement,
2831
loaderElement,
2932
) => {
30-
prevBtn.addEventListener('click', () => {
31-
showUserDataList(
32-
--page,
33-
userListElement,
34-
paginationElement,
35-
loaderElement,
36-
prevBtn,
37-
nextBtn,
38-
);
39-
});
40-
41-
nextBtn.addEventListener('click', () => {
42-
showUserDataList(
43-
++page,
44-
userListElement,
45-
paginationElement,
46-
loaderElement,
47-
prevBtn,
48-
nextBtn,
49-
);
33+
window.addEventListener('scroll', async () => {
34+
console.log('Page No is: ' + page);
35+
if (
36+
window.innerHeight + window.scrollY >= document.body.offsetHeight - 100 &&
37+
run
38+
) {
39+
if (!run) {
40+
return;
41+
}
42+
run = false;
43+
showUserDataList(
44+
page++,
45+
userListElement,
46+
paginationElement,
47+
loaderElement,
48+
);
49+
}
5050
});
5151

5252
tileViewBtn.addEventListener('click', () => {
@@ -86,6 +86,8 @@ function showTileView(userListElement, tableViewBtn, tileViewBtn) {
8686
tableViewBtn.classList.remove('btn-active');
8787
tileViewBtn.classList.add('btn-active');
8888
const listContainerElement = userListElement.lastChild;
89+
const headList = document.getElementById('head_list');
90+
headList.classList.add('tile-webview');
8991
listContainerElement.childNodes.forEach((listElement) => {
9092
const imgElement = listElement.firstChild;
9193
imgElement.classList.add('remove-element');
@@ -149,14 +151,7 @@ function generateUserList(
149151
userListElement,
150152
paginationElement,
151153
loaderElement,
152-
prevBtn,
153154
) {
154-
userListElement.innerHTML = '';
155-
if (page <= 0) {
156-
prevBtn.classList.add('btn-disabled');
157-
} else {
158-
prevBtn.classList.remove('btn-disabled');
159-
}
160155
if (!users || !users.length) {
161156
showErrorMessage(
162157
'No data found',
@@ -166,40 +161,39 @@ function generateUserList(
166161
);
167162
return;
168163
}
169-
const ulElement = document.createElement('ul');
170-
users.forEach((userData) => {
171-
const listElement = document.createElement('li');
172-
const imgElement = document.createElement('img');
173-
imgElement.src = userData.picture ? userData.picture : DEFAULT_AVATAR;
174-
imgElement.classList.add('user-img-dimension');
175-
const pElement = document.createElement('p');
176-
const node = document.createTextNode(
177-
`${userData.first_name} ${userData.last_name}`,
178-
);
179-
pElement.appendChild(node);
180-
listElement.appendChild(imgElement);
181-
listElement.appendChild(pElement);
182164

183-
if (tileViewActive) {
184-
let imgElement = listElement.firstChild;
185-
listElement.classList.remove('tile-width');
186-
imgElement.classList.add('remove-element');
187-
}
188-
listElement.onclick = () => {
189-
document.getElementById('user-search').value = '';
190-
window.location.href = `/users/details/index.html?username=${userData.username}`;
191-
};
192-
ulElement.appendChild(listElement);
193-
});
194-
loaderElement.classList.add('remove-element');
195-
if (showPagination) {
196-
paginationElement.classList.remove('remove-element');
197-
paginationElement.classList.add('pagination');
198-
} else {
199-
paginationElement.classList.add('remove-element');
200-
paginationElement.classList.remove('pagination');
165+
const ulElement = document.getElementById('head_list');
166+
167+
if (users != null) {
168+
users.forEach((userData) => {
169+
const listElement = document.createElement('li');
170+
const imgElement = document.createElement('img');
171+
imgElement.src = userData.picture ? userData.picture : DEFAULT_AVATAR;
172+
imgElement.classList.add('user-img-dimension');
173+
listElement.classList.add('tile-webview');
174+
const pElement = document.createElement('p');
175+
const node = document.createTextNode(
176+
`${userData.first_name} ${userData.last_name}`,
177+
);
178+
pElement.appendChild(node);
179+
listElement.appendChild(imgElement);
180+
listElement.appendChild(pElement);
181+
182+
if (tileViewActive) {
183+
let imgElement = listElement.firstChild;
184+
listElement.classList.add('tile-width');
185+
imgElement.classList.add('remove-element');
186+
}
187+
listElement.onclick = () => {
188+
document.getElementById('user-search').value = '';
189+
window.location.href = `/users/details/index.html?username=${userData.username}`;
190+
};
191+
ulElement.appendChild(listElement);
192+
});
193+
loaderElement.classList.add('remove-element');
194+
userListElement.appendChild(ulElement);
195+
run = true;
201196
}
202-
userListElement.appendChild(ulElement);
203197
}
204198

205199
async function fetchUsersData(searchInput) {
@@ -333,17 +327,17 @@ const showUserDataList = async (
333327
userListElement,
334328
paginationElement,
335329
loaderElement,
336-
prevBtn,
337-
nextBtn,
338330
) => {
339331
try {
332+
if (isLoading) return;
333+
if (page != 0) {
334+
isLoading = true;
335+
userloaderElement.style.display = 'block';
336+
}
337+
340338
const userData = await getUsersData(page);
341-
if (userData.length) {
342-
if (userData.length < USER_FETCH_COUNT) {
343-
nextBtn.classList.add('btn-disabled');
344-
} else {
345-
nextBtn.classList.remove('btn-disabled');
346-
}
339+
340+
if (userData && userData.length) {
347341
let usersDataList = userData.filter(
348342
(user) => user.first_name && !user.roles?.archived,
349343
);
@@ -359,7 +353,6 @@ const showUserDataList = async (
359353
userListElement,
360354
paginationElement,
361355
loaderElement,
362-
prevBtn,
363356
);
364357
}
365358
} catch (err) {
@@ -370,6 +363,9 @@ const showUserDataList = async (
370363
paginationElement,
371364
loaderElement,
372365
);
366+
} finally {
367+
userloaderElement.style.display = 'none';
368+
isLoading = false;
373369
}
374370
};
375371

users/style.css

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -120,8 +120,12 @@ li p {
120120
white-space: nowrap;
121121
}
122122

123+
.tile-webview {
124+
display: block;
125+
}
126+
123127
.tile-width {
124-
width: 200px;
128+
width: 400px;
125129
}
126130

127131
.error-text {
@@ -145,10 +149,21 @@ li p {
145149
margin: 150px auto;
146150
}
147151

152+
#loader_tag {
153+
border: 5px solid var(--gray-color);
154+
border-top: 5px solid var(--loader-blue-color);
155+
border-radius: 50%;
156+
width: 50px;
157+
height: 50px;
158+
animation: spin 2s linear infinite;
159+
margin: 150px auto;
160+
}
161+
148162
.pagination {
149163
display: flex;
150164
justify-content: space-between;
151165
margin-top: auto;
166+
visibility: hidden;
152167
}
153168

154169
.pagination-btn {

0 commit comments

Comments
 (0)