Add discourse API for better data retrieval

This commit is contained in:
2025-10-22 11:37:13 +13:00
parent 63cc7cf460
commit d097013853

196
static/js/discourse-api.js Normal file
View File

@ -0,0 +1,196 @@
/**
* Discourse API Integration for enviPath Community
* Handles fetching topics from the Discourse forum API
*/
class DiscourseAPI {
constructor() {
this.baseUrl = 'https://community.envipath.org';
this.categoryId = 10; // Announcements category
this.limit = 3; // Number of topics to fetch
}
/**
* Fetch topics from Discourse API
* @param {number} limit - Number of topics to fetch
* @returns {Promise<Array>} Array of topic objects
*/
async fetchTopics(limit = this.limit) {
try {
const url = `${this.baseUrl}/c/announcements/${this.categoryId}.json`;
const response = await fetch(url);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const data = await response.json();
return this.processTopics(data.topic_list.topics, limit);
} catch (error) {
console.error('Error fetching Discourse topics:', error);
return this.getFallbackTopics();
}
}
/**
* Process raw Discourse topics into standardized format
* @param {Array} topics - Raw topics from Discourse API
* @param {number} limit - Number of topics to return
* @returns {Array} Processed topics
*/
processTopics(topics, limit) {
return topics
.slice(0, limit)
.map(topic => ({
id: topic.id,
title: topic.title,
excerpt: this.extractExcerpt(topic.excerpt),
url: `${this.baseUrl}/t/${topic.slug}/${topic.id}`,
replies: topic.reply_count,
views: topic.views,
created_at: topic.created_at,
category: 'Announcements',
category_id: this.categoryId,
author: topic.last_poster_username,
author_avatar: this.getAvatarUrl(topic.last_poster_username)
}))
.sort((a, b) => new Date(b.created_at) - new Date(a.created_at)); // Latest first
}
/**
* Extract excerpt from topic content
* @param {string} excerpt - Raw excerpt from Discourse
* @returns {string} Cleaned excerpt
*/
extractExcerpt(excerpt) {
if (!excerpt) return 'Click to read more...';
// Remove HTML tags and clean up
return excerpt
.replace(/<[^>]*>/g, '') // Remove HTML tags
.replace(/&nbsp;/g, ' ') // Replace &nbsp; with spaces
.replace(/&amp;/g, '&') // Replace &amp; with &
.replace(/&lt;/g, '<') // Replace &lt; with <
.replace(/&gt;/g, '>') // Replace &gt; with >
.trim()
.substring(0, 200) + '...'; // Limit length
}
/**
* Get avatar URL for user
* @param {string} username - Username
* @returns {string} Avatar URL
*/
getAvatarUrl(username) {
if (!username) return `${this.baseUrl}/letter_avatar_proxy/v4/letter/u/1.png`;
return `${this.baseUrl}/user_avatar/${this.baseUrl.replace('https://', '')}/${username}/40/1_1.png`;
}
/**
* Get fallback topics when API fails
* @returns {Array} Fallback topics
*/
getFallbackTopics() {
return [
{
id: 110,
title: "enviPath Beta Update: Major Improvements to Prediction, Analysis & Collaboration!",
excerpt: "We're excited to announce major updates to the enviPath beta platform! This release includes significant improvements to our prediction algorithms, enhanced analysis tools, and new collaboration features that will make environmental biotransformation research more accessible and efficient.",
url: "https://community.envipath.org/t/envipath-beta-update-major-improvements-to-prediction-analysis-collaboration/110",
replies: 0,
views: 16,
created_at: "2025-09-23T00:00:00Z",
category: "Announcements",
category_id: 10,
author: "wicker",
author_avatar: "https://community.envipath.org/user_avatar/community.envipath.org/wicker/40/1_1.png"
},
{
id: 109,
title: "enviPath License",
excerpt: "Information about the enviPath license and terms of use for the platform. Learn about our licensing model and how it affects your research and commercial use of enviPath data and predictions.",
url: "https://community.envipath.org/t/envipath-license/109",
replies: 0,
views: 13,
created_at: "2025-09-22T00:00:00Z",
category: "Announcements",
category_id: 10,
author: "wicker",
author_avatar: "https://community.envipath.org/user_avatar/community.envipath.org/wicker/40/1_1.png"
},
{
id: 95,
title: "Apply to join our Closed Beta",
excerpt: "We're opening applications for our closed beta program! Join early adopters in testing new features and helping shape the future of environmental biotransformation prediction. Apply now to get early access to cutting-edge tools and provide valuable feedback.",
url: "https://community.envipath.org/t/apply-to-join-our-closed-beta/95",
replies: 0,
views: 69,
created_at: "2025-07-23T00:00:00Z",
category: "Announcements",
category_id: 10,
author: "wicker",
author_avatar: "https://community.envipath.org/user_avatar/community.envipath.org/wicker/40/1_1.png"
}
];
}
/**
* Format date for display
* @param {string} dateString - ISO date string
* @returns {string} Formatted date
*/
formatDate(dateString) {
const date = new Date(dateString);
return date.toLocaleDateString();
}
/**
* Load topics and call render function
* @param {string} containerId - ID of container element
* @param {Function} renderCallback - Function to render topics
*/
async loadTopics(containerId = 'community-news-container', renderCallback = null) {
const container = document.getElementById(containerId);
if (!container) {
console.error(`Container with ID '${containerId}' not found`);
return;
}
// Hide loading spinner
const loading = document.getElementById('loading');
if (loading) {
loading.style.display = 'none';
}
try {
const topics = await this.fetchTopics();
if (renderCallback && typeof renderCallback === 'function') {
renderCallback(topics);
} else {
// Default rendering - just log topics
console.log('Topics loaded:', topics);
}
} catch (error) {
console.error('Error loading topics:', error);
container.innerHTML = '<p class="text-neutral">No updates found. Head over to the <a href="https://community.envipath.org" target="_blank" class="link link-primary">community</a> to see the latest discussions.</p>';
}
}
}
// Export for use in other scripts
window.DiscourseAPI = DiscourseAPI;
// Auto-initialize if container exists
document.addEventListener('DOMContentLoaded', function() {
if (document.getElementById('community-news-container')) {
const discourseAPI = new DiscourseAPI();
discourseAPI.loadTopics('community-news-container', function(topics) {
// This will be handled by the template's render function
if (window.renderDiscourseTopics) {
window.renderDiscourseTopics(topics);
}
});
}
});