Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft: Feature/edit extension request #907

102 changes: 95 additions & 7 deletions extension-requests/script.js
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,18 @@ const getExtensionColor = (deadline, createdTime) => {
return 'orange-text';
};

const currentUserDetailsPromise = getSelfUser()
.then((response) => {
currentUserDetails = response;
})
.catch((error) => {
currentUserDetails = null;
});

async function populateExtensionRequests(query = {}, newLink) {
if(!currentUserDetails){
await currentUserDetailsPromise;
}
extensionPageVersion++;
const currentVersion = extensionPageVersion;
try {
Expand Down Expand Up @@ -540,6 +551,17 @@ async function createExtensionCard(data, dev) {
value: data.title,
},
});
const titleInputWrapper = createElement({
type: 'div',
attributes: { class: 'title-input-wrapper hidden' },
});
const titleInputError = createElement({
type: 'div',
attributes: { class: 'title-input-error hidden' },
innerText: 'Title is required',
});
titleInputWrapper.appendChild(titleInput);
titleInputWrapper.appendChild(titleInputError);
const commitedHoursHoverCard = createElement({
type: 'div',
attributes: { class: 'comitted-hours hidden' },
Expand All @@ -562,7 +584,7 @@ async function createExtensionCard(data, dev) {
});
commitedHoursHoverCard.appendChild(CommitedHourslabel);
commitedHoursHoverCard.appendChild(CommitedHoursContent);
extensionCardHeaderWrapper.appendChild(titleInput);
extensionCardHeaderWrapper.appendChild(titleInputWrapper);
extensionCardHeaderWrapper.appendChild(titleText);
extensionCardHeaderWrapper.appendChild(commitedHoursHoverTrigger);
extensionCardHeaderWrapper.appendChild(commitedHoursHoverCard);
Expand Down Expand Up @@ -806,7 +828,13 @@ async function createExtensionCard(data, dev) {
value: dateString(secondsToMilliSeconds(data.newEndsOn)),
},
});
const extensionInputError = createElement({
type: 'div',
attributes: { class: 'extension-input-error hidden' },
innerText: "Past date can't be the new deadline",
});
newDeadlineContainer.appendChild(extensionInput);
newDeadlineContainer.appendChild(extensionInputError)
extensionForContainer.appendChild(extensionForValue);

const extensionRequestNumberContainer = createElement({ type: 'div' });
Expand Down Expand Up @@ -909,7 +937,9 @@ async function createExtensionCard(data, dev) {
type: 'button',
attributes: { class: 'edit-button' },
});
extensionCardButtons.appendChild(editButton);
if (shouldDisplayEditButton(data.assigneeId)) {
extensionCardButtons.appendChild(editButton);
}
const editIcon = createElement({
type: 'img',
attributes: { src: EDIT_ICON, alt: 'edit-icon' },
Expand Down Expand Up @@ -963,6 +993,7 @@ async function createExtensionCard(data, dev) {
handleFormPropagation(event);
toggleInputs();
toggleActionButtonVisibility();
extensionInputError.classList.add('hidden')
editButton.classList.toggle('hidden');
updateWrapper.classList.toggle('hidden');
if (!panel.style.maxHeight) {
Expand All @@ -971,10 +1002,23 @@ async function createExtensionCard(data, dev) {
updateAccordionHeight(panel);
});
updateButton.addEventListener('click', (event) => {
toggleInputs();
toggleActionButtonVisibility();
editButton.classList.toggle('hidden');
updateWrapper.classList.toggle('hidden');
const isTitleMissing = !titleInput.value;
const isReasonMissing = !reasonInput.value;
const todayDate = Math.floor(new Date().getTime() / 1000)
const newDeadline = new Date(extensionInput.value).getTime() / 1000
const isDeadlineInPast = newDeadline<todayDate

titleInputError.classList.toggle('hidden', !isTitleMissing);
reasonInputError.classList.toggle('hidden', !isReasonMissing);
extensionInputError.classList.toggle('hidden', !isDeadlineInPast);

if (!isTitleMissing && !isReasonMissing && !isDeadlineInPast) {
toggleInputs();
toggleActionButtonVisibility();
editButton.classList.toggle('hidden');
updateWrapper.classList.toggle('hidden');
titleInputWrapper.classList.add('hidden')
}
});
cancelButton.addEventListener('click', (event) => {
titleInput.value = data.title;
Expand All @@ -985,6 +1029,9 @@ async function createExtensionCard(data, dev) {
toggleActionButtonVisibility();
editButton.classList.toggle('hidden');
updateWrapper.classList.toggle('hidden');
titleInputError.classList.add('hidden');
reasonInputError.classList.add('hidden');
extensionInputError.classList.add('hidden')
});
const payloadForLog = {
body: {},
Expand Down Expand Up @@ -1115,7 +1162,13 @@ async function createExtensionCard(data, dev) {
},
innerText: data.reason,
});
const reasonInputError = createElement({
type: 'span',
attributes: { class: 'reason-input-error red-text hidden' },
innerText: 'Reason is required',
});
reasonContainer.appendChild(reasonInput);
reasonContainer.appendChild(reasonInputError);
reasonContainer.appendChild(reasonParagraph);

const renderExtensionCreatedLog = () => {
Expand Down Expand Up @@ -1171,6 +1224,10 @@ async function createExtensionCard(data, dev) {
e.preventDefault();
let formData = formDataToObject(new FormData(e.target));
formData['newEndsOn'] = new Date(formData['newEndsOn']).getTime() / 1000;
const todayDate = Math.floor(new Date().getTime() / 1000)
if (!formData.title || !formData.reason || formData['newEndsOn'] < todayDate) {
return;
}
const removeSpinner = addSpinner(rootElement);
rootElement.classList.add('disabled');
const revertDataChange = updateCardData(formData);
Expand Down Expand Up @@ -1207,11 +1264,15 @@ async function createExtensionCard(data, dev) {
data.tile = formData.title;
data.newEndsOn = data.newEndsOn;
handleSuccess(rootElement);
const successMessage = 'Extension request successfully updated.';
showToast(successMessage, 'success');
appendLogs(payloadForLog, data.id);
})
.catch(() => {
.catch((error) => {
revertDataChange();
handleFailure(rootElement);
const errorMessage = error?.response?.data?.message || error?.message || 'An error occurred. Please try again.';
showToast(errorMessage, 'error');
})
.finally(() => {
rootElement.classList.remove('disabled');
Expand Down Expand Up @@ -1257,6 +1318,7 @@ async function createExtensionCard(data, dev) {
return revertDataChange;
}
function toggleInputs() {
titleInputWrapper.classList.toggle('hidden')
titleInput.classList.toggle('hidden');
titleText.classList.toggle('hidden');
reasonInput.classList.toggle('hidden');
Expand Down Expand Up @@ -1398,6 +1460,32 @@ async function createExtensionCard(data, dev) {
}
}

function shouldDisplayEditButton(assigneeId) {
return (
currentUserDetails &&
(assigneeId === currentUserDetails.id || currentUserDetails.roles.super_user)
);
}

function showToast(message, type) {
const existingToast = document.querySelector('.extension-request-update-toast');
if (existingToast) {
existingToast.remove();
}
const toast = document.createElement('div');
toast.className = `extension-request-update-toast toast-${type}`;
toast.textContent = message;

document.body.appendChild(toast);

setTimeout(() => {
toast.classList.add('fade-out');
toast.addEventListener('transitionend', () => {
toast.remove();
});
}, 3000);
}

function generateSentence(response, parentClassName, id) {
let arraySentence = [];
let sentence = '';
Expand Down
35 changes: 34 additions & 1 deletion extension-requests/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -773,8 +773,41 @@ body {
align-items: center;
justify-content: space-between;
position: relative;
height: 1.6rem;
height: 2rem;
}
.title-input-wrapper {
display: flex;
flex-direction: column;
gap: 0.5rem;
}
.title-input-error,
.reason-input-error, .extension-input-error {
font-size: 12px;
color: var(--red-color);
}

.extension-request-update-toast {
position: fixed;
bottom: 20px;
right: 20px;
padding: 15px 20px;
background-color: var(--red-color);
color: #fff;
font-size: 14px;
border-radius: 5px;
opacity: 1;
transition: opacity 0.3s ease;
z-index: 1000;
}

.extension-request-update-toast.fade-out {
opacity: 0;
}

.extension-request-update-toast.toast-success {
background-color: var(--green-color);
}

.disabled {
opacity: 0.5;
pointer-events: none;
Expand Down