Skip to content

Commit dcf9a1a

Browse files
committed
added set button
1 parent e318225 commit dcf9a1a

File tree

3 files changed

+159
-78
lines changed

3 files changed

+159
-78
lines changed

src/index.css

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -417,4 +417,51 @@ hr,
417417

418418
.dark-mode .token-preview-char {
419419
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.18);
420+
}
421+
422+
/* Organization validation styles */
423+
#validateOrgBtn {
424+
transition: all 0.2s ease;
425+
min-width: 80px;
426+
}
427+
428+
#validateOrgBtn:disabled {
429+
opacity: 0.7;
430+
cursor: not-allowed;
431+
}
432+
433+
#validateOrgBtn i {
434+
transition: all 0.2s ease;
435+
}
436+
437+
#orgValidationStatus {
438+
transition: all 0.3s ease;
439+
padding: 4px 8px;
440+
border-radius: 4px;
441+
font-weight: 500;
442+
}
443+
444+
#orgValidationStatus i {
445+
margin-right: 4px;
446+
}
447+
448+
/* Dark mode organization validation */
449+
.dark-mode #validateOrgBtn {
450+
border-color: #404040;
451+
}
452+
453+
.dark-mode #orgValidationStatus {
454+
background-color: rgba(255, 255, 255, 0.05);
455+
}
456+
457+
/* Organization input focus styles */
458+
#orgInput:focus {
459+
outline: none;
460+
border-color: #3b82f6;
461+
box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.1);
462+
}
463+
464+
.dark-mode #orgInput:focus {
465+
border-color: #60a5fa;
466+
box-shadow: 0 0 0 3px rgba(96, 165, 250, 0.1);
420467
}

src/popup.html

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,20 @@ <h4>Organization Name</h4>
140140
</span>
141141
</span>
142142
</div>
143-
<input id="orgInput" type="text"
144-
class="w-full border-2 border-gray-200 bg-gray-200 rounded-xl text-gray-800 p-2 my-2"
145-
placeholder="Enter organization name (default: fossasia)">
143+
<div class="flex gap-2 items-center">
144+
<input id="orgInput" type="text"
145+
class="flex-1 border-2 border-gray-200 bg-gray-200 rounded-xl text-gray-800 p-2 my-2"
146+
placeholder="Enter organization name (default: fossasia)">
147+
<button id="validateOrgBtn"
148+
class="bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded flex items-center gap-2 transition-colors duration-200"
149+
title="Validate organization name">
150+
<i class="fa fa-check"></i>
151+
<span>Set</span>
152+
</button>
153+
</div>
154+
<div id="orgValidationStatus" class="text-sm mt-1 hidden">
155+
<!-- Status messages will be shown here -->
156+
</div>
146157
</div>
147158
<div class="">
148159
<div class="flex items-center justify-between">

src/scripts/popup.js

Lines changed: 98 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,8 @@ document.addEventListener('DOMContentLoaded', function () {
6060
let tokenVisible = false;
6161

6262
const orgInput = document.getElementById('orgInput');
63-
const setOrgBtn = document.getElementById('setOrgBtn');
63+
const validateOrgBtn = document.getElementById('validateOrgBtn');
64+
const orgValidationStatus = document.getElementById('orgValidationStatus');
6465

6566
chrome.storage.local.get(['darkMode'], function (result) {
6667
if (result.darkMode) {
@@ -295,7 +296,7 @@ document.addEventListener('DOMContentLoaded', function () {
295296
endDateInput.value = getToday();
296297
}
297298
startDateInput.readOnly = endDateInput.readOnly = true;
298-
299+
299300
chrome.storage.local.set({
300301
startingDate: startDateInput.value,
301302
endingDate: endDateInput.value,
@@ -347,89 +348,111 @@ document.addEventListener('DOMContentLoaded', function () {
347348
orgInput.value = result.orgName || '';
348349
});
349350

350-
// Debounce function
351-
function debounce(func, wait) {
352-
let timeout;
353-
return function (...args) {
354-
clearTimeout(timeout);
355-
timeout = setTimeout(() => func.apply(this, args), wait);
356-
};
357-
}
358-
359-
let lastInvalidOrg = '';
360-
// Validate and set org as user types
361-
const handleOrgInput = debounce(function () {
351+
// Organization validation function
352+
async function validateOrganization() {
362353
let org = orgInput.value.trim().toLowerCase();
363354
if (!org) {
364355
org = 'fossasia';
365356
}
366-
console.log('[Org Check] Checking organization:', org);
367-
fetch(`https://api.github.com/orgs/${org}`)
368-
.then(res => {
369-
console.log('[Org Check] Response status for', org, ':', res.status);
370-
if (res.status === 404) {
371-
console.log('[Org Check] Organization not found on GitHub:', org);
372-
const oldToast = document.getElementById('invalid-org-toast');
373-
if (oldToast) oldToast.parentNode.removeChild(oldToast);
374-
const toastDiv = document.createElement('div');
375-
toastDiv.id = 'invalid-org-toast';
376-
toastDiv.className = 'toast';
377-
toastDiv.style.background = '#dc2626';
378-
toastDiv.style.color = '#fff';
379-
toastDiv.style.fontWeight = 'bold';
380-
toastDiv.style.padding = '12px 24px';
381-
toastDiv.style.borderRadius = '8px';
382-
toastDiv.style.position = 'fixed';
383-
toastDiv.style.top = '24px';
384-
toastDiv.style.left = '50%';
385-
toastDiv.style.transform = 'translateX(-50%)';
386-
toastDiv.style.zIndex = '9999';
387-
toastDiv.innerText = 'Organization not found on GitHub.';
388-
document.body.appendChild(toastDiv);
389-
setTimeout(() => {
390-
if (toastDiv.parentNode) toastDiv.parentNode.removeChild(toastDiv);
391-
}, 3000);
392-
return;
393-
}
394-
const oldToast = document.getElementById('invalid-org-toast');
395-
if (oldToast) oldToast.parentNode.removeChild(oldToast);
396-
console.log('[Org Check] Organisation exists on GitHub:', org);
397357

398-
// Valid org: update storage and fetch data
399-
chrome.storage.local.set({ orgName: org, githubCache: null }, function () {
400-
const scrumReport = document.getElementById('scrumReport');
401-
if (scrumReport) {
402-
scrumReport.innerHTML = '<p style="text-align: center; color: #666; padding: 20px;">Organisation changed. Click "Generate Report" to fetch new data.</p>';
403-
}
358+
// Show loading state
359+
validateOrgBtn.disabled = true;
360+
validateOrgBtn.innerHTML = '<i class="fa fa-spinner fa-spin"></i><span>Checking...</span>';
404361

405-
});
406-
})
407-
.catch((err) => {
408-
console.log('[Org Check] Error validating organisation:', org, err);
409-
const oldToast = document.getElementById('invalid-org-toast');
410-
if (oldToast) oldToast.parentNode.removeChild(oldToast);
411-
const toastDiv = document.createElement('div');
412-
toastDiv.id = 'invalid-org-toast';
413-
toastDiv.className = 'toast';
414-
toastDiv.style.background = '#dc2626';
415-
toastDiv.style.color = '#fff';
416-
toastDiv.style.fontWeight = 'bold';
417-
toastDiv.style.padding = '12px 24px';
418-
toastDiv.style.borderRadius = '8px';
419-
toastDiv.style.position = 'fixed';
420-
toastDiv.style.top = '24px';
421-
toastDiv.style.left = '50%';
422-
toastDiv.style.transform = 'translateX(-50%)';
423-
toastDiv.style.zIndex = '9999';
424-
toastDiv.innerText = 'Error validating organization.';
425-
document.body.appendChild(toastDiv);
362+
// Show status message
363+
orgValidationStatus.className = 'text-sm mt-1 text-blue-600';
364+
orgValidationStatus.innerHTML = '<i class="fa fa-spinner fa-spin"></i> Validating organization...';
365+
orgValidationStatus.classList.remove('hidden');
366+
367+
try {
368+
console.log('[Org Check] Checking organization:', org);
369+
const response = await fetch(`https://api.github.com/orgs/${org}`);
370+
371+
console.log('[Org Check] Response status for', org, ':', response.status);
372+
373+
if (response.status === 404) {
374+
console.log('[Org Check] Organization not found on GitHub:', org);
375+
376+
// Show error state
377+
validateOrgBtn.innerHTML = '<i class="fa fa-times"></i><span>Invalid</span>';
378+
validateOrgBtn.className = 'bg-red-600 hover:bg-red-700 text-white font-medium py-2 px-4 rounded flex items-center gap-2 transition-colors duration-200';
379+
380+
orgValidationStatus.className = 'text-sm mt-1 text-red-600';
381+
orgValidationStatus.innerHTML = '<i class="fa fa-times"></i> Organization not found on GitHub';
382+
383+
// Reset button after 3 seconds
426384
setTimeout(() => {
427-
if (toastDiv.parentNode) toastDiv.parentNode.removeChild(toastDiv);
385+
validateOrgBtn.disabled = false;
386+
validateOrgBtn.innerHTML = '<i class="fa fa-check"></i><span>Set</span>';
387+
validateOrgBtn.className = 'bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded flex items-center gap-2 transition-colors duration-200';
388+
orgValidationStatus.classList.add('hidden');
428389
}, 3000);
390+
391+
return;
392+
}
393+
394+
if (!response.ok) {
395+
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
396+
}
397+
398+
console.log('[Org Check] Organisation exists on GitHub:', org);
399+
400+
// Valid org: update storage and fetch data
401+
await new Promise((resolve) => {
402+
chrome.storage.local.set({ orgName: org, githubCache: null }, resolve);
429403
});
430-
}, 2500);
431404

432-
orgInput.addEventListener('input', handleOrgInput);
405+
// Show success state
406+
validateOrgBtn.innerHTML = '<i class="fa fa-check"></i><span>Set</span>';
407+
validateOrgBtn.className = 'bg-green-600 hover:bg-green-700 text-white font-medium py-2 px-4 rounded flex items-center gap-2 transition-colors duration-200';
408+
409+
orgValidationStatus.className = 'text-sm mt-1 text-green-600';
410+
orgValidationStatus.innerHTML = '<i class="fa fa-check"></i> Organization validated successfully!';
411+
412+
// Update scrum report
413+
const scrumReport = document.getElementById('scrumReport');
414+
if (scrumReport) {
415+
scrumReport.innerHTML = '<p style="text-align: center; color: #666; padding: 20px;">Organisation changed. Click "Generate Report" to fetch new data.</p>';
416+
}
417+
418+
// Reset button after 3 seconds
419+
setTimeout(() => {
420+
validateOrgBtn.disabled = false;
421+
validateOrgBtn.innerHTML = '<i class="fa fa-check"></i><span>Set</span>';
422+
validateOrgBtn.className = 'bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded flex items-center gap-2 transition-colors duration-200';
423+
orgValidationStatus.classList.add('hidden');
424+
}, 3000);
425+
426+
} catch (error) {
427+
console.log('[Org Check] Error validating organisation:', org, error);
428+
429+
// Show error state
430+
validateOrgBtn.innerHTML = '<i class="fa fa-exclamation-triangle"></i><span>Error</span>';
431+
validateOrgBtn.className = 'bg-red-600 hover:bg-red-700 text-white font-medium py-2 px-4 rounded flex items-center gap-2 transition-colors duration-200';
432+
433+
orgValidationStatus.className = 'text-sm mt-1 text-red-600';
434+
orgValidationStatus.innerHTML = '<i class="fa fa-exclamation-triangle"></i> Error validating organization. Please try again.';
435+
436+
// Reset button after 3 seconds
437+
setTimeout(() => {
438+
validateOrgBtn.disabled = false;
439+
validateOrgBtn.innerHTML = '<i class="fa fa-check"></i><span>Set</span>';
440+
validateOrgBtn.className = 'bg-blue-600 hover:bg-blue-700 text-white font-medium py-2 px-4 rounded flex items-center gap-2 transition-colors duration-200';
441+
orgValidationStatus.classList.add('hidden');
442+
}, 3000);
443+
}
444+
}
445+
446+
// Add click event listener to validation button
447+
validateOrgBtn.addEventListener('click', validateOrganization);
448+
449+
// Add Enter key support for the input field
450+
orgInput.addEventListener('keypress', function (event) {
451+
if (event.key === 'Enter') {
452+
event.preventDefault();
453+
validateOrganization();
454+
}
455+
});
433456

434457
});
435458

0 commit comments

Comments
 (0)