Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .env.example
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
# No special permissions needed for public repositories
GITHUB_TOKEN=your_github_token_here

# GitHub token used by Docusaurus for dynamic features (discussions, stats, leaderboard)
# This must be set for the discussions section to fetch live data from GitHub
# Create a Classic PAT with read:discussion scope at https://github.com/settings/tokens
DOCUSAURUS_GIT_TOKEN=your_github_token_here

# Shopify Configuration (for Merch Store)
# Get these from: Shopify Admin > Settings > Apps and sales channels > Develop apps
# Required scopes: unauthenticated_read_product_listings, unauthenticated_write_checkouts
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ yarn-error.log*

# Temporary files
/tmp/
tsconfig.tsbuildinfo
42 changes: 2 additions & 40 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions src/components/discussions/discussions.css
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,44 @@
box-shadow: 0 6px 20px rgba(16, 185, 129, 0.4);
}

.refresh-discussions-btn {
background: var(--ifm-card-background-color);
color: var(--ifm-color-emphasis-700);
border: 1px solid var(--ifm-color-emphasis-300);
padding: 0.75rem;
border-radius: 12px;
cursor: pointer;
transition: all 0.2s ease;
display: flex;
align-items: center;
justify-content: center;
flex-shrink: 0;
}

.refresh-discussions-btn:hover:not(:disabled) {
border-color: var(--ifm-color-primary);
color: var(--ifm-color-primary);
transform: translateY(-1px);
}

.refresh-discussions-btn:disabled {
opacity: 0.6;
cursor: not-allowed;
}

@keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}

.spinning {
animation: spin 1s linear infinite;
}

.tab-btn {
background: var(--ifm-card-background-color);
border: 2px solid var(--ifm-color-emphasis-200);
Expand Down
37 changes: 37 additions & 0 deletions src/pages/dashboard/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
} from "@site/src/lib/statsProvider";
import SlotCounter from "react-slot-counter";
import { useLocation, useHistory } from "@docusaurus/router";
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import {
githubService,
GitHubDiscussion,
Expand All @@ -30,6 +31,7 @@ import {
BarChart3,
ArrowLeft,
GitFork,
RefreshCw,
} from "lucide-react";
import NavbarIcon from "@site/src/components/navbar/NavbarIcon";
import "@site/src/components/discussions/discussions.css";
Expand Down Expand Up @@ -65,6 +67,9 @@ const categories: Category[] = [
const DashboardContent: React.FC = () => {
const location = useLocation();
const history = useHistory();
const {
siteConfig: { customFields },
} = useDocusaurusContext();
const [activeTab, setActiveTab] = useState<
"home" | "discuss" | "giveaway" | "contributors"
>("home");
Expand All @@ -80,6 +85,14 @@ const DashboardContent: React.FC = () => {
const [discussionsError, setDiscussionsError] = useState<string | null>(null);
const [showDashboardMenu, setShowDashboardMenu] = useState(false);

// Initialize GitHub service with token from Docusaurus config
useEffect(() => {
const token = customFields?.gitToken as string;
if (token) {
githubService.setToken(token);
}
}, [customFields?.gitToken]);

// Close dashboard menu when clicking outside
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
Expand Down Expand Up @@ -138,6 +151,10 @@ const DashboardContent: React.FC = () => {
}
};

const handleRefreshDiscussions = () => {
fetchDiscussions();
};

// Discussion handlers
const handleDiscussionTabChange = (tab: DiscussionTab) => {
setActiveDiscussionTab(tab);
Expand Down Expand Up @@ -597,6 +614,17 @@ const DashboardContent: React.FC = () => {
<option value="latest">Latest</option>
<option value="oldest">Oldest</option>
</select>
<button
className="refresh-discussions-btn"
onClick={handleRefreshDiscussions}
disabled={discussionsLoading}
title="Refresh discussions"
>
<RefreshCw
size={16}
className={discussionsLoading ? "spinning" : ""}
/>
</button>
<button
className="new-discussion-btn"
onClick={handleNewDiscussion}
Expand Down Expand Up @@ -629,6 +657,15 @@ const DashboardContent: React.FC = () => {
{discussionsError && (
<div className="discussions-error-message">
<p>{discussionsError}</p>
<p>
<a
href="https://github.com/recodehive/recode-website/discussions"
target="_blank"
rel="noopener noreferrer"
>
View discussions on GitHub →
</a>
</p>
</div>
)}
{!discussionsLoading &&
Expand Down
20 changes: 16 additions & 4 deletions src/services/githubService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,17 +68,29 @@ class GitHubService {
// === ADDED: include anonymous contributors configurable (default false)
private includeAnonymousContributors = false;

// === ADDED: stored token for authenticated API calls
private token: string = "";

// === ADDED: set the GitHub token (e.g. from Docusaurus customFields.gitToken)
setToken(token: string): void {
if (token && token.trim()) {
this.token = token.trim();
}
}

// Get headers for GitHub API requests
private getHeaders(): Record<string, string> {
const headers: Record<string, string> = {
Accept: "application/vnd.github.v3+json",
"Content-Type": "application/json",
};

// Add GitHub token if available in environment
// Note: In production, you might want to use a server-side proxy to avoid exposing tokens
if (typeof window !== "undefined" && (window as any).GITHUB_TOKEN) {
headers["Authorization"] = `token ${(window as any).GITHUB_TOKEN}`;
// Use stored token first, then fall back to window.GITHUB_TOKEN
const token =
this.token ||
(typeof window !== "undefined" ? (window as any).GITHUB_TOKEN : "");
if (token) {
headers["Authorization"] = `token ${token}`;
}

return headers;
Expand Down
Loading