Implement add repository form (#14)

* Add repo request form

* fix add repo card placement and click logic

* Add modal for repo submission

* Refine modal styling and add private repo CTA

* Improve modal layout and fix CORS

* style: ensure modal close button has no background

* Refine repo request logic

* Revise repo submission modal

* Restore repo grid and add private CTA

* Tweak modal styling

* Fix drawer event handler

* Revert .gitignore changes

* Update assets/js/main.js

* Update assets/js/main.js
This commit is contained in:
guyeisenkot
2025-07-06 15:00:24 +03:00
committed by GitHub
parent 0c326fdafe
commit 75418b781a
6 changed files with 245 additions and 4 deletions

2
.gitignore vendored
View File

@@ -1,4 +1,4 @@
.idea
vendor
_site
.jekyll-cache
.jekyll-cache

24
_includes/modal.html Normal file
View File

@@ -0,0 +1,24 @@
<div id="add-repo-modal" class="modal">
<div class="modal__backdrop"></div>
<div class="modal__dialog">
<button class="modal__close" aria-label="Close">×</button>
<h2 class="modal__title">Add Repository</h2>
<p>Enter the URL of a public GitHub repository</p>
<form id="add-repo-form" class="modal__form">
<input
type="url"
id="repo-url-input"
placeholder="https://github.com/owner/repo"
required
>
<button type="submit">Add</button>
</form>
<div id="repo-add-feedback" class="modal__feedback"></div>
<div class="modal__private">
<h3>Private Repository</h3>
<a href="https://baz.co/agents" class="drawer-deploy-btn" target="_blank" rel="noopener noreferrer">Get private Reviewers with Baz</a>
</div>
</div>
</div>

View File

@@ -439,7 +439,6 @@
}, 300);
}
async function deployToBaz() {
console.log('🚀 Deploy to baz clicked');
// Get the current reviewer slug from the URL hash
@@ -604,5 +603,7 @@
filterReviewers();
}
</script>
{% include modal.html %}
<script src="{{ '/assets/js/main.js' | relative_url }}"></script>
</body>
</html>
</html>

View File

@@ -16,6 +16,116 @@
--shadow-lg: 0 10px 15px -3px rgb(0 0 0 / 0.1), 0 4px 6px -4px rgb(0 0 0 / 0.1);
}
/* Base modal */
.modal {
display: none;
position: fixed;
inset: 0;
z-index: 1000;
}
.modal__backdrop {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.5);
}
.modal__dialog {
position: relative;
max-width: 420px;
margin: 6rem auto;
padding: 2rem;
background: var(--bg-card);
border-radius: 8px;
color: var(--text-primary);
box-shadow: var(--shadow-lg);
display: flex;
flex-direction: column;
gap: 1rem;
}
.modal__close {
position: absolute;
top: 12px;
right: 12px;
background: none;
background-color: transparent;
border: none;
font-size: 1.2em;
color: var(--text-primary);
cursor: pointer;
padding: 0;
line-height: 1;
}
.modal__close:hover,
.modal__close:focus {
background: none;
background-color: transparent;
color: var(--text-primary);
outline: none;
}
.modal__form {
display: flex;
gap: 0.5rem;
}
.modal__form input[type="url"] {
flex: 1;
margin: 0;
}
.modal__form button {
margin: 0;
}
.modal__dialog input[type="url"] {
width: 100%;
padding: 0.5rem;
margin: 0;
background: var(--bg-secondary);
border: 1px solid var(--border);
color: var(--text-primary);
border-radius: 4px;
}
.modal__dialog input::placeholder {
color: var(--text-muted);
}
.modal__dialog button {
padding: 0.375rem 0.75rem;
background: var(--accent);
border: none;
color: #fff;
border-radius: 6px;
cursor: pointer;
font-size: 0.875rem;
font-weight: 500;
transition: background-color 0.2s ease;
}
.modal__dialog button:hover {
background: var(--accent-hover);
}
.modal__feedback {
margin-top: 0.5rem;
font-size: 0.875rem;
}
.modal__feedback.valid {
color: #6FCF97;
}
.modal__feedback.invalid {
color: #EB5757;
}
.modal__private {
margin-top: 1rem;
padding-top: 1rem;
border-top: 1px solid var(--border);
display: flex;
flex-direction: column;
align-items: center;
text-align: center;
gap: 0.5rem;
}
/* Utility to show modal */
.modal--open {
display: block;
}
[data-theme="dark"] {
--bg-primary: #1c2026;
--bg-secondary: #1e293b;
@@ -489,6 +599,7 @@ h1, h2, h3, h4, h5, h6 {
transform: translateY(-2px);
}
.reviewer-header {
display: flex;
align-items: flex-start;
@@ -1014,4 +1125,27 @@ h2 .stat-value {
width: 100%;
min-width: unset;
}
}
}
.library-header .container {
display: flex;
align-items: center;
gap: 1rem;
flex-wrap: wrap;
}
.add-repo-btn {
background: var(--accent);
color: #fff;
border: none;
padding: 0.375rem 0.75rem;
border-radius: 6px;
cursor: pointer;
font-size: 0.875rem;
font-weight: 500;
transition: background-color 0.2s ease;
}
.add-repo-btn:hover {
background: var(--accent-hover);
}

81
assets/js/main.js Normal file
View File

@@ -0,0 +1,81 @@
// Add Repository modal handling
// Attempt POST with required header; if it fails, fall back to a GET request
const modal = document.getElementById('add-repo-modal');
const openBtn = document.getElementById('add-repo-button');
const closeBtn = modal.querySelector('.modal__close');
const backdrop = modal.querySelector('.modal__backdrop');
const form = document.getElementById('add-repo-form');
const feedbackEl = document.getElementById('repo-add-feedback');
// Open modal
openBtn && openBtn.addEventListener('click', () => {
modal.classList.add('modal--open');
feedbackEl.textContent = '';
form.reset();
});
// Close modal
[closeBtn, backdrop].forEach(el =>
el.addEventListener('click', () => modal.classList.remove('modal--open'))
);
// Submit handler
form && form.addEventListener('submit', async e => {
e.preventDefault();
feedbackEl.textContent = '';
const url = document.getElementById('repo-url-input').value.trim();
const m = url.match(/github\.com\/([^/]+\/[^/]+)(?:\/|$)/);
if (!m) {
feedbackEl.textContent = 'Repo not valid';
feedbackEl.className = 'modal__feedback invalid';
return;
}
const repo = encodeURIComponent(m[1]);
try {
let res;
try {
res = await fetch(
`https://awesome.baz.co/request?repo_name=${repo}`,
{
method: 'POST',
headers: {
'x-amz-content-sha256':
'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855'
}
}
);
if (!res.ok && res.status !== 409) throw new Error(res.statusText);
} catch (postErr) {
res = await fetch(
`https://awesome.baz.co/request?repo_name=${repo}`
);
if (!res.ok && res.status !== 409) throw new Error(res.statusText);
}
const status = res.status;
let message = '';
try {
const data = await res.json();
message = data.message || '';
} catch (e) {
// no JSON body
}
let valid = true;
if (status === 202) {
feedbackEl.textContent = '✅ Request accepted processing soon.';
} else if (status === 409 && message) {
feedbackEl.textContent = `⚠️ ${message}`;
} else if (status === 400 && message) {
feedbackEl.textContent = `${message}`;
valid = false;
} else {
feedbackEl.textContent = '⚠️ Request submitted.';
}
feedbackEl.className = valid ? 'modal__feedback valid' : 'modal__feedback invalid';
} catch (err) {
feedbackEl.textContent = 'Repo not valid';
feedbackEl.className = 'modal__feedback invalid';
}
});

View File

@@ -12,6 +12,7 @@ layout: default
<section class="library-header">
<div class="container">
<h2>Reviewers Library (<span id="reviewer-count" class="stat-value" data-count="{{ site.reviewers.size }}">{{ site.reviewers.size }}</span>)</h2>
<button id="add-repo-button" class="add-repo-btn">Add Repository</button>
</div>
</section>