Logo

Hockley County Democrats

Officer & Chair Content Management Portal

How to log in:

Paste your Personal Access Token. Once entered, your browser remembers your login automatically.

Logo Hockley Dems Admin Logged In
🌐 View Live Site
County Executive Committee (CEC) Officers
Precinct Chairs Roster
Precinct / Area Chair Name Status Action
Top Site Alert & Meeting Banner

Controls the colored announcement bar displayed at the very top of the website.

Published Articles & Press Releases

Articles appear dynamically on the News & Press page (news.html).

Upcoming Events & Meetings
Create a New Custom Page

Instantly generate and publish a new HTML page on the website with standard navigation and styling.

General Contact Info & Official Links
Social Media Channels
✅ Changes Saved & Published Live!
`; try { let existingSha = undefined; try { const check = await fetch('https://api.github.com/repos/' + OWNER + '/' + REPO + '/contents/' + targetPath, { headers: { 'Authorization': 'Bearer ' + currentToken, 'Accept': 'application/vnd.github.v3+json' } }); if (check.ok) { const d = await check.json(); existingSha = d.sha; } } catch (e) {} const b64 = btoa(unescape(encodeURIComponent(fullPageHtml))); const res = await fetch('https://api.github.com/repos/' + OWNER + '/' + REPO + '/contents/' + targetPath, { method: 'PUT', headers: { 'Authorization': 'Bearer ' + currentToken, 'Accept': 'application/vnd.github.v3+json', 'Content-Type': 'application/json' }, body: JSON.stringify({ message: 'Create page ' + targetPath + ' via Officer Dashboard', content: b64, sha: existingSha, branch: BRANCH }) }); if (!res.ok) throw new Error(await res.text()); status.innerHTML = '🎉 Page published live! Link: ' + targetPath + ''; btn.innerHTML = '🚀 Publish New Page Live'; btn.disabled = false; } catch (err) { status.innerHTML = 'Failed to create page: ' + err.message + ''; btn.innerHTML = '🚀 Publish New Page Live'; btn.disabled = false; } } async function saveAllChanges() { const btn = document.getElementById('save-all-btn'); btn.innerHTML = '⏳ Publishing to Website...'; btn.disabled = true; try { // 1. Leadership leadershipData.chair = document.getElementById('lead-chair').value; leadershipData.chair_title = document.getElementById('lead-chair-title').value; leadershipData.vice_chair = document.getElementById('lead-vice').value; leadershipData.vice_chair_title = document.getElementById('lead-vice-title').value; leadershipData.secretary = document.getElementById('lead-sec').value; leadershipData.secretary_title = document.getElementById('lead-sec-title').value; leadershipData.social_media = document.getElementById('lead-social').value; leadershipData.social_media_title = document.getElementById('lead-social-title').value; // 2. Banner bannerData = { active: document.getElementById('banner-active').checked, text: document.getElementById('banner-text').value, button_text: document.getElementById('banner-btn-text').value, link: document.getElementById('banner-link').value, bg_color: document.getElementById('banner-color').value }; // 3. Settings settingsData.phone = document.getElementById('set-phone').value; settingsData.email = document.getElementById('set-email').value; settingsData.donate_link = document.getElementById('set-donate').value; settingsData.linktree_link = document.getElementById('set-linktree').value; settingsData.appointment_form_link = document.getElementById('set-app-form').value; settingsData.address_ropesville = document.getElementById('set-addr-ropes').value; settingsData.address_levelland = document.getElementById('set-addr-level').value; settingsData.socials = { facebook: document.getElementById('soc-fb').value, instagram: document.getElementById('soc-ig').value, threads: document.getElementById('soc-threads').value, bluesky: document.getElementById('soc-bsky').value, x: document.getElementById('soc-x').value }; // Push updates to GitHub const [resS, resL, resE, resB, resA, resG] = await Promise.all([ ghPut('data/settings.json', settingsData, settingsSha, 'Update site settings via Officer Dashboard'), ghPut('data/leadership.json', leadershipData, leadershipSha, 'Update leadership roster via Officer Dashboard'), ghPut('data/events.json', eventsData, eventsSha, 'Update events via Officer Dashboard'), ghPut('data/announcements.json', bannerData, bannerSha, 'Update banner via Officer Dashboard'), ghPut('data/articles.json', articlesData, articlesSha, 'Update articles via Officer Dashboard'), ghPut('data/gallery.json', galleryData, gallerySha, 'Update gallery via Officer Dashboard') ]); settingsSha = resS.content.sha; leadershipSha = resL.content.sha; eventsSha = resE.content.sha; bannerSha = resB.content.sha; articlesSha = resA.content.sha; gallerySha = resG.content.sha; const toast = document.getElementById('toast'); toast.style.display = 'block'; setTimeout(() => { toast.style.display = 'none'; }, 4000); btn.innerHTML = '✅ Published Live!'; setTimeout(() => { btn.innerHTML = '💾 Save & Publish Live'; btn.disabled = false; }, 2000); } catch (err) { alert('Failed to publish: ' + err.message); btn.innerHTML = '💾 Save & Publish Live'; btn.disabled = false; } } document.addEventListener('DOMContentLoaded', checkAuth);