mirror of
https://github.com/abrendan/smolNews.git
synced 2025-06-15 20:15:24 +02:00
Initial commit
This commit is contained in:
commit
2d9757a346
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
node_modules/
|
10
.replit
Normal file
10
.replit
Normal file
@ -0,0 +1,10 @@
|
||||
entrypoint="index.html"
|
||||
hidden=[".config"]
|
||||
modules = ["web:v2-20230623-0b7a606"]
|
||||
|
||||
[nix]
|
||||
channel = "stable-23_11"
|
||||
|
||||
[deployment]
|
||||
publicDir = "/"
|
||||
deploymentTarget = "static"
|
77
index.html
Normal file
77
index.html
Normal file
@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>smolNews</title>
|
||||
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link href="style.css" rel="stylesheet">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container mt-5">
|
||||
<h1 class="text-center">smolNews</h1>
|
||||
<div class="form-group">
|
||||
<select id="topicSelect" class="form-control">
|
||||
<option value="">All Topics</option>
|
||||
<option value="business">Business</option>
|
||||
<option value="entertainment">Entertainment</option>
|
||||
<option value="health">Health</option>
|
||||
<option value="science">Science</option>
|
||||
<option value="sports">Sports</option>
|
||||
<option value="technology">Technology</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select id="apiSelect" class="form-control">
|
||||
<option value="currents">Currents API</option>
|
||||
<option value="nyt">NYT API</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" id="sourceSelectContainer">
|
||||
<select id="sourceSelect" class="form-control">
|
||||
<option value="">All Sources</option>
|
||||
<option value="cnn.com">CNN</option>
|
||||
<option value="bbc.com">BBC News</option>
|
||||
<option value="theverge.com">The Verge</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select id="languageSelect" class="form-control">
|
||||
<option value="">All Languages</option>
|
||||
<option value="en">English</option>
|
||||
<option value="es">Spanish</option>
|
||||
<option value="fr">French</option>
|
||||
<option value="de">German</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" id="searchInput" class="form-control" placeholder="Search for articles...">
|
||||
</div>
|
||||
<button id="searchButton" class="btn btn-primary btn-block">Search</button>
|
||||
<div id="articles" class="mt-4"></div>
|
||||
</div>
|
||||
<div class="modal fade" id="articleModal" tabindex="-1" aria-labelledby="articleModalLabel" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" id="articleModalLabel">Article Details</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body" id="articleDetails">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
|
||||
<a id="fullArticleLink" href="#" target="_blank" class="btn btn-primary">Read Full Article</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.2/dist/umd/popper.min.js"></script>
|
||||
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
|
||||
<script src="script.js"></script>
|
||||
</body>
|
||||
</html>
|
161
script.js
Normal file
161
script.js
Normal file
@ -0,0 +1,161 @@
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
configureDropdowns();
|
||||
fetchNewsArticles();
|
||||
});
|
||||
|
||||
document.getElementById('apiSelect').addEventListener('change', function() {
|
||||
configureDropdowns();
|
||||
fetchNewsArticles();
|
||||
});
|
||||
|
||||
document.getElementById('searchButton').addEventListener('click', function() {
|
||||
fetchNewsArticles();
|
||||
});
|
||||
|
||||
function configureDropdowns() {
|
||||
const apiSelection = document.getElementById('apiSelect').value;
|
||||
const sourceSelectContainer = document.getElementById('sourceSelectContainer');
|
||||
const languageSelectContainer = document.getElementById('languageSelect').parentElement;
|
||||
|
||||
if (apiSelection === 'currents') {
|
||||
sourceSelectContainer.style.display = 'block';
|
||||
languageSelectContainer.style.display = 'block';
|
||||
} else if (apiSelection === 'nyt') {
|
||||
sourceSelectContainer.style.display = 'none';
|
||||
languageSelectContainer.style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
function fetchNewsArticles() {
|
||||
const query = document.getElementById('searchInput').value;
|
||||
const topic = document.getElementById('topicSelect').value;
|
||||
const apiSelection = document.getElementById('apiSelect').value;
|
||||
const language = document.getElementById('languageSelect').value;
|
||||
|
||||
if (apiSelection === 'currents') {
|
||||
const source = document.getElementById('sourceSelect').value;
|
||||
fetchFromCurrentsAPI(query, source, topic, language);
|
||||
} else if (apiSelection === 'nyt') {
|
||||
fetchFromNYTAPI(query, topic);
|
||||
}
|
||||
}
|
||||
|
||||
function fetchFromCurrentsAPI(query, source, topic, language) {
|
||||
const apiKey = 'b2uZWPY42BaUWN4Luaj_fbjJR6y7idTudew9UcpSbzr2D2VO';
|
||||
let url = `https://api.currentsapi.services/v1/search?apiKey=${apiKey}`;
|
||||
|
||||
if (query) {
|
||||
url += `&keywords=${encodeURIComponent(query)}`;
|
||||
}
|
||||
if (source) {
|
||||
url += `&domain=${source}`;
|
||||
}
|
||||
if (topic) {
|
||||
url += `&category=${topic}`;
|
||||
}
|
||||
if (language) {
|
||||
url += `&language=${language}`;
|
||||
}
|
||||
|
||||
fetch(url)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Network response was not ok: ${response.statusText} (${response.status})`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.news) {
|
||||
displayArticles(data.news, 'currents');
|
||||
} else {
|
||||
throw new Error('No articles found');
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error fetching news:', error));
|
||||
}
|
||||
|
||||
function fetchFromNYTAPI(query, topic) {
|
||||
const apiKey = 'NQdorI46QZM3Kythn8ymAWID8ojT7ntY';
|
||||
let url = `https://api.nytimes.com/svc/search/v2/articlesearch.json?api-key=${apiKey}`;
|
||||
|
||||
if (query) {
|
||||
url += `&q=${encodeURIComponent(query)}`;
|
||||
}
|
||||
if (topic) {
|
||||
url += `&fq=news_desk:("${topic}")`;
|
||||
}
|
||||
|
||||
fetch(url)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(`Network response was not ok: ${response.statusText} (${response.status})`);
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
if (data.response && data.response.docs) {
|
||||
displayArticles(data.response.docs.map(doc => ({
|
||||
title: doc.headline.main,
|
||||
description: doc.abstract,
|
||||
image: (doc.multimedia.length > 0) ? `https://nytimes.com/${doc.multimedia[0].url}` : 'default-thumbnail.jpg',
|
||||
content: doc.lead_paragraph,
|
||||
url: doc.web_url,
|
||||
published: doc.pub_date
|
||||
})), 'nyt');
|
||||
} else {
|
||||
throw new Error('No articles found');
|
||||
}
|
||||
})
|
||||
.catch(error => console.error('Error fetching news:', error));
|
||||
}
|
||||
|
||||
function displayArticles(articles, apiType) {
|
||||
const articlesDiv = document.getElementById('articles');
|
||||
articlesDiv.innerHTML = '';
|
||||
articles.forEach(article => {
|
||||
const thumbnailUrl = article.image || 'default-thumbnail.jpg';
|
||||
|
||||
const articleElement = document.createElement('div');
|
||||
articleElement.classList.add('card', 'mb-3', 'card-horizontal');
|
||||
let buttonHtml = '';
|
||||
|
||||
if (apiType === 'currents') {
|
||||
buttonHtml = `<a href="${article.url}" target="_blank" class="btn btn-info">Read Full Article</a>`;
|
||||
} else if (apiType === 'nyt') {
|
||||
buttonHtml = `<button class="btn btn-info" onclick='viewArticleDetails(${JSON.stringify(article)})'>Read More</button>`;
|
||||
}
|
||||
|
||||
articleElement.innerHTML = `
|
||||
<img src="${thumbnailUrl}" class="card-img-left" alt="Article thumbnail">
|
||||
<div class="card-body">
|
||||
<h5 class="card-title">${article.title}</h5>
|
||||
<p class="card-text">${article.description || 'No description available.'}</p>
|
||||
${buttonHtml}
|
||||
</div>
|
||||
`;
|
||||
articlesDiv.appendChild(articleElement);
|
||||
});
|
||||
}
|
||||
|
||||
function viewArticleDetails(article) {
|
||||
const articleDetailsModal = document.getElementById('articleDetails');
|
||||
const fullArticleLink = document.getElementById('fullArticleLink');
|
||||
|
||||
const publishedDate = article.published
|
||||
? new Date(article.published).toLocaleDateString()
|
||||
: 'Date not available';
|
||||
|
||||
articleDetailsModal.innerHTML = `
|
||||
<h5>${article.title}</h5>
|
||||
<div class="article-metadata">
|
||||
Published: ${publishedDate}
|
||||
</div>
|
||||
<img src="${article.image}" alt="Article Image" class="img-fluid">
|
||||
<p>${article.content || 'No content available.'}</p>
|
||||
`;
|
||||
|
||||
fullArticleLink.href = article.url || '#';
|
||||
fullArticleLink.style.display = article.url ? 'block' : 'none';
|
||||
|
||||
$('#articleModal').modal('show');
|
||||
}
|
28
style.css
Normal file
28
style.css
Normal file
@ -0,0 +1,28 @@
|
||||
.card-horizontal {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.card-horizontal img {
|
||||
width: 337px;
|
||||
height: 200px;
|
||||
margin-right: 15px;
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.modal-body img {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
.modal-dialog {
|
||||
max-width: 800px;
|
||||
}
|
||||
|
||||
.article-metadata {
|
||||
color: #666;
|
||||
font-size: 0.9em;
|
||||
margin-bottom: 15px;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user