Skip to content

Commit b7d2aed

Browse files
Achintya-Chatterjeedevanshdixitiamitprakash
authored
Feat: UI for listing extension requests in /requests page (#774)
* tabs are switching on request page * added extension-request in request page * added extension-request in request page * feat: Added the whole extension page UI * refactor: Abstract fetch logic into reusable function - Created fetchData function to handle fetch requests with different query parameters and controllers. - Updated getOooRequests and getExtensionRequests to use fetchData. * refactor: Abstract fetch logic into reusable function - Created fetchData function to handle fetch requests with different query parameters and controllers. - Updated getOooRequests and getExtensionRequests to use fetchData. * refactor: createExtensionCard function to optimize element creation - Use DocumentFragment to accumulate and append elements efficiently - Simplify element creation with template literals - Extract repetitive tasks and event listeners into separate functions - Maintain coding standards and improve readability Resolves PR comment regarding optimizing document.createElement calls in createExtensionCard function. * refactor: code refactored to show superusers the extension request * Merge branch 'feat/extension-request-page' of github.com:Real-Dev-Squad/website-dashboard into feat/extension-request-page bbbjbLines starting with '#' will be ignored, and an empty message aborts e commit. :wq Merge branch 'feat/extension-request-page' of github.com:Real-Dev-Squad/website-dashboard into feat/extension-request-page This merge is necessary to integrate the latest changes from the remote branch into the local branch. * fix: delete the mock-date, will raise the test PR separately * feat: add UI for listing extension requests with status update controls - Implemented a separate tab for listing extension requests on the /requests page. - Added functionality for super users to approve or reject extension requests directly from the UI. - Updated script.js to handle API calls for both OOO and extension requests. - Ensured correct query parameters are reflected in the URL when switching between tabs. - Improved error handling and message display for extension requests. * fix(css): center the loading text on the requests page - Updated .container__body__loader class to center the loading text both horizontally and vertically using Flexbox. --------- Co-authored-by: devanshdixit <[email protected]> Co-authored-by: Amit Prakash <[email protected]>
1 parent 5bdead1 commit b7d2aed

File tree

5 files changed

+114
-41
lines changed

5 files changed

+114
-41
lines changed

requests/constants.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@ const Status = {
66
};
77

88
const OOO_REQUEST_TYPE = 'OOO';
9+
const EXTENSION_REQUEST_TYPE = 'EXTENSION';
910
const REQUEST_CONTAINER_ID = 'request_container';
1011
const OOO_TAB_ID = 'ooo_tab_link';
12+
const EXTENSION_TAB_ID = 'extension_tab_link';
1113

1214
const DEFAULT_DATE_FORMAT = 'DD MMM YYYY';
1315

@@ -19,8 +21,9 @@ const MessageStatus = {
1921
const ErrorMessages = {
2022
UNAUTHENTICATED:
2123
'You are unauthenticated to view this section, please login!',
22-
UNAUTHORIZED: 'You are unauthrozed to view this section',
24+
UNAUTHORIZED: 'You are unauthorized to view this section',
2325
OOO_NOT_FOUND: 'OOO Requests not found',
26+
EXTENSION_NOT_FOUND: 'Extension Requests not found',
2427
SERVER_ERROR: 'Unexpected error occurred',
2528
};
2629

requests/index.html

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,9 @@
66
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
77
<meta
88
name="description"
9-
content="This web page is for the requests managment functionality in real dev squad's dashboard website. admin can view and take action on the requests raised by the team members."
9+
content="This web page is for the requests management functionality in real dev squad's dashboard website. Admins can view and take action on the requests raised by the team members."
1010
/>
11-
<meta name="keywords" content="RDS, Request Managment" />
11+
<meta name="keywords" content="RDS, Request Management" />
1212
<meta name="author" content="Real Dev Squad" />
1313
<link rel="icon" href="/images/index.ico" type="image/x-icon" />
1414
<link rel="preconnect" href="https://fonts.googleapis.com" />
@@ -17,7 +17,6 @@
1717
href="https://fonts.googleapis.com/css2?family=Inter:wght@100;400;700;800&display=swap"
1818
rel="stylesheet"
1919
/>
20-
2120
<title>Requests | Real Dev Squad</title>
2221
<link rel="stylesheet" href="/global.css" />
2322
<link rel="stylesheet" href="/requests/style.css" />

requests/script.js

Lines changed: 85 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const loader = document.querySelector('.container__body__loader');
88
const startLoading = () => loader.classList.remove('hidden');
99
const stopLoading = () => loader.classList.add('hidden');
1010
let oooTabLink = document.getElementById(OOO_TAB_ID);
11+
let extensionTabLink = document.getElementById(EXTENSION_TAB_ID);
1112
let currentReqType = OOO_REQUEST_TYPE;
1213
let selected__tab__class = 'selected__tab';
1314
let statusValue = null;
@@ -25,7 +26,7 @@ const intersectionObserver = new IntersectionObserver(async (entries) => {
2526
return;
2627
}
2728
if (entries[0].isIntersecting && !isDataLoading) {
28-
await renderOooRequestCards({
29+
await renderRequestCards({
2930
state: statusValue,
3031
sort: sortByValue,
3132
next: nextLink,
@@ -42,18 +43,35 @@ const removeIntersectionObserver = () => {
4243

4344
oooTabLink.addEventListener('click', async function () {
4445
if (isDataLoading) return;
45-
oooTabLink.classList.add(selected__tab__class);
4646
currentReqType = OOO_REQUEST_TYPE;
47+
nextLink = '';
48+
oooTabLink.classList.add(selected__tab__class);
49+
extensionTabLink.classList.remove(selected__tab__class);
50+
changeFilter();
51+
updateUrlWithQuery(currentReqType);
52+
await renderRequestCards({ state: statusValue, sort: sortByValue });
53+
});
54+
55+
extensionTabLink.addEventListener('click', async function () {
56+
if (isDataLoading) return;
57+
currentReqType = EXTENSION_REQUEST_TYPE;
58+
nextLink = '';
59+
extensionTabLink.classList.add(selected__tab__class);
60+
oooTabLink.classList.remove(selected__tab__class);
4761
changeFilter();
48-
await renderOooRequestCards({ state: statusValue, sort: sortByValue });
62+
updateUrlWithQuery(currentReqType);
63+
await renderRequestCards({ state: statusValue, sort: sortByValue });
4964
});
5065

66+
function updateUrlWithQuery(type) {
67+
const url = new URL(window.location);
68+
url.searchParams.set('type', type.toLowerCase());
69+
window.history.pushState({ path: url.toString() }, '', url.toString());
70+
}
71+
5172
async function getOooRequests(query = {}) {
5273
let finalUrl =
5374
API_BASE_URL + (nextLink || '/requests' + getOooQueryParamsString(query));
54-
let windowUrl = `${window.location.origin}${window.location.pathname}`;
55-
56-
window.history.pushState({ path: windowUrl }, '', windowUrl);
5775

5876
try {
5977
const res = await fetch(finalUrl, {
@@ -88,6 +106,44 @@ async function getOooRequests(query = {}) {
88106
}
89107
}
90108

109+
async function getExtensionRequests(query = {}) {
110+
let finalUrl =
111+
API_BASE_URL +
112+
(nextLink || '/requests' + getExtensionQueryParamsString(query));
113+
114+
try {
115+
const res = await fetch(finalUrl, {
116+
credentials: 'include',
117+
});
118+
119+
const data = await res.json();
120+
if (res.ok) {
121+
return data;
122+
} else {
123+
switch (res.status) {
124+
case 401:
125+
showMessage('ERROR', ErrorMessages.UNAUTHENTICATED);
126+
return;
127+
case 403:
128+
showMessage('ERROR', ErrorMessages.UNAUTHORIZED);
129+
return;
130+
case 404:
131+
showMessage('ERROR', ErrorMessages.EXTENSION_NOT_FOUND);
132+
return;
133+
case 400:
134+
showMessage('ERROR', data.message);
135+
showToast(data.message, 'failure');
136+
return;
137+
default:
138+
break;
139+
}
140+
}
141+
showMessage('ERROR', ErrorMessages.SERVER_ERROR);
142+
} catch (e) {
143+
console.error(e);
144+
}
145+
}
146+
91147
function showMessage(type, message) {
92148
const p = document.createElement('p');
93149
const classes = ['request__message'];
@@ -106,11 +162,7 @@ const changeFilter = () => {
106162
requestContainer.innerHTML = '';
107163
};
108164

109-
function createOooRequestCard(
110-
oooRequest,
111-
superUserDetails,
112-
requesterUserDetails,
113-
) {
165+
function createRequestCard(request, superUserDetails, requesterUserDetails) {
114166
let {
115167
id,
116168
state,
@@ -121,7 +173,7 @@ function createOooRequestCard(
121173
lastModifiedBy,
122174
reason,
123175
updatedAt,
124-
} = oooRequest;
176+
} = request;
125177
let showSuperuserDetailsClass = 'notHidden';
126178
let showActionButtonClass = 'notHidden';
127179
if (
@@ -161,17 +213,17 @@ function createOooRequestCard(
161213
child: [
162214
generateRequesterInfo(),
163215
generateRequestContent(),
164-
addHotizontalBreakLine(),
216+
addHorizontalBreakLine(),
165217
generateSuperuserInfo(),
166218
generateActionButtonsContainer(),
167219
],
168220
});
169221
return card;
170222

171-
function addHotizontalBreakLine() {
223+
function addHorizontalBreakLine() {
172224
return createElementFromMap({
173225
tagName: 'hr',
174-
class: 'horizontal__line__saperator',
226+
class: 'horizontal__line__separator',
175227
});
176228
}
177229

@@ -378,28 +430,28 @@ function createOooRequestCard(
378430
}
379431
}
380432

381-
async function renderOooRequestCards(queries = {}) {
433+
async function renderRequestCards(queries = {}) {
382434
if (isDataLoading) return;
383-
let oooRequestResponse;
435+
let requestResponse;
384436
try {
385437
isDataLoading = true;
386438
startLoading();
387439
if (userDetails.length === 0) {
388440
userDetails = await getInDiscordUserList();
389441
}
390-
oooRequestResponse = await getOooRequests(queries);
391-
for (const oooRequest of oooRequestResponse?.data || []) {
442+
requestResponse =
443+
currentReqType === OOO_REQUEST_TYPE
444+
? await getOooRequests(queries)
445+
: await getExtensionRequests(queries);
446+
447+
for (const request of requestResponse?.data || []) {
392448
let superUserDetails;
393-
let requesterUserDetails = await getUserDetails(oooRequest.requestedBy);
394-
if (oooRequest.state !== 'PENDING') {
395-
superUserDetails = await getUserDetails(oooRequest.lastModifiedBy);
449+
let requesterUserDetails = await getUserDetails(request.requestedBy);
450+
if (request.state !== 'PENDING') {
451+
superUserDetails = await getUserDetails(request.lastModifiedBy);
396452
}
397453
requestContainer.appendChild(
398-
createOooRequestCard(
399-
oooRequest,
400-
superUserDetails,
401-
requesterUserDetails,
402-
),
454+
createRequestCard(request, superUserDetails, requesterUserDetails),
403455
);
404456
}
405457
} catch (error) {
@@ -410,15 +462,15 @@ async function renderOooRequestCards(queries = {}) {
410462
isDataLoading = false;
411463
if (
412464
requestContainer.innerHTML === '' ||
413-
oooRequestResponse === undefined ||
414-
oooRequestResponse?.data?.length === 0
465+
requestResponse === undefined ||
466+
requestResponse?.data?.length === 0
415467
) {
416-
showMessage('INFO', 'No OOO requests found!');
468+
showMessage('INFO', `No ${currentReqType.toLowerCase()} requests found!`);
417469
}
418470
}
419471

420472
addIntersectionObserver();
421-
nextLink = oooRequestResponse?.next;
473+
nextLink = requestResponse?.next;
422474
}
423475

424476
async function acceptRejectRequest(id, reqBody) {
@@ -497,7 +549,7 @@ async function performAcceptRejectAction(isAccepted, e) {
497549
updatedRequestDetails.requestedBy,
498550
);
499551

500-
const updatedCard = createOooRequestCard(
552+
const updatedCard = createRequestCard(
501553
updatedRequestDetails,
502554
superUserDetails,
503555
requesterUserDetails,
@@ -535,4 +587,4 @@ function showToast(message, type) {
535587
}, 5000);
536588
}
537589

538-
renderOooRequestCards({ state: statusValue, sort: sortByValue });
590+
renderRequestCards({ state: statusValue, sort: sortByValue });

requests/style.css

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ p {
8888
text-align: center;
8989
font-size: 1.5rem;
9090
margin: 2rem;
91+
display: flex;
92+
justify-content: center;
93+
align-items: center;
94+
margin-top: 8rem;
9195
}
9296
.container__body {
9397
margin-top: 2.5rem;
@@ -333,7 +337,6 @@ nav a:hover {
333337
}
334338

335339
.disabled__tab {
336-
pointer-events: none;
337340
color: var(--color-gray);
338341
}
339342

@@ -547,3 +550,7 @@ nav a:hover {
547550
.virtual {
548551
width: 100%;
549552
}
553+
554+
#search_filter_container {
555+
display: none;
556+
}

requests/util.js

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,18 @@ function getOooQueryParamsString(query) {
4444
return `?${queryParam}`;
4545
}
4646

47+
function getExtensionQueryParamsString(query) {
48+
let queryParam = 'dev=true&type=EXTENSION&size=12';
49+
if (
50+
query.state !== undefined &&
51+
query.state !== null &&
52+
query.state !== 'ALL'
53+
) {
54+
queryParam += `&state=${query.state}`;
55+
}
56+
return `?${queryParam}`;
57+
}
58+
4759
function convertDateToReadableStringDate(date, format) {
4860
if (format === undefined || format === null) {
4961
format = DEFAULT_DATE_FORMAT;
@@ -104,9 +116,9 @@ async function getInDiscordUserList() {
104116
}
105117

106118
const addSpinner = (container) => {
107-
const spinner = createElement({
108-
type: 'div',
109-
attributes: { class: 'spinner' },
119+
const spinner = createElementFromMap({
120+
tagName: 'div',
121+
class: 'spinner',
110122
});
111123

112124
container.append(spinner);

0 commit comments

Comments
 (0)