mirror of
https://github.com/olegvodyanov/instalinks.git
synced 2025-12-20 05:47:03 +03:00
167 lines
4.7 KiB
JavaScript
167 lines
4.7 KiB
JavaScript
const newLinkInput = document.getElementById('newLinkInput');
|
||
const addLinkBtn = document.getElementById('addLinkBtn');
|
||
const newLinksContainer = document.getElementById('newLinksContainer');
|
||
const watchedLinksContainer = document.getElementById('watchedLinksContainer');
|
||
|
||
const PER_PAGE = 8;
|
||
let currentPage = 1;
|
||
|
||
function loadLinks() {
|
||
fetch('/api/links/?page=${currentPage}&per_page=${PER_PAGE}')
|
||
.then(res => res.json())
|
||
.then(data => {
|
||
linksData = data.results;
|
||
renderPaginatedList(linksData, newLinksContainer, false, data.page, data.pages);
|
||
renderPaginatedList(linksData.filter(l => l.watched), watchedLinksContainer, true, data.page, data.pages);
|
||
})
|
||
.catch(err => console.error(err));
|
||
}
|
||
|
||
function renderPaginatedList(linkList, container, isWatched, page, totalPages) {
|
||
container.innerHTML = '';
|
||
|
||
const row = document.createElement('div');
|
||
row.className = 'row gy-4';
|
||
|
||
linkList
|
||
.filter(link => link.watched === isWatched)
|
||
.forEach(link => {
|
||
const col = document.createElement('div');
|
||
col.className = 'col-12 col-sm-6 col-md-4 col-lg-3';
|
||
col.appendChild(createLinkElement(link, isWatched));
|
||
row.appendChild(col);
|
||
});
|
||
|
||
container.appendChild(row);
|
||
|
||
// Pagination controls
|
||
if (totalPages > 1) {
|
||
const nav = document.createElement('div');
|
||
nav.className = 'd-flex justify-content-center mt-4 gap-2';
|
||
|
||
const prevBtn = document.createElement('button');
|
||
prevBtn.innerText = '← Previous';
|
||
prevBtn.className = 'btn btn-outline-primary';
|
||
prevBtn.disabled = page <= 1;
|
||
prevBtn.onclick = () => {
|
||
currentPage--;
|
||
loadLinks();
|
||
};
|
||
|
||
const nextBtn = document.createElement('button');
|
||
nextBtn.innerText = 'Next →';
|
||
nextBtn.className = 'btn btn-outline-primary';
|
||
nextBtn.disabled = page >= totalPages;
|
||
nextBtn.onclick = () => {
|
||
currentPage++;
|
||
loadLinks();
|
||
};
|
||
|
||
nav.appendChild(prevBtn);
|
||
nav.appendChild(nextBtn);
|
||
container.appendChild(nav);
|
||
}
|
||
|
||
reinitializeInstagramEmbeds();
|
||
}
|
||
|
||
// Create a DOM element for a single link
|
||
function createLinkElement(link, isWatched) {
|
||
const wrapper = document.createElement('div');
|
||
wrapper.className = 'mb-3';
|
||
|
||
// Instagram embed blockquote
|
||
const blockquote = document.createElement('blockquote');
|
||
blockquote.className = 'instagram-media';
|
||
blockquote.setAttribute('data-instgrm-permalink', link.url);
|
||
blockquote.style.background = '#FFF';
|
||
|
||
const p = document.createElement('p');
|
||
p.innerText = 'Loading Instagram...';
|
||
blockquote.appendChild(p);
|
||
wrapper.appendChild(blockquote);
|
||
|
||
// Button to mark watched if it's not watched
|
||
if (!isWatched) {
|
||
const watchButton = document.createElement('button');
|
||
watchButton.className = 'btn btn-sm btn-secondary';
|
||
watchButton.innerText = 'Mark Watched';
|
||
watchButton.onclick = () => markLinkWatched(link.id);
|
||
wrapper.appendChild(watchButton);
|
||
}
|
||
|
||
// Delete button
|
||
const deleteButton = document.createElement('button');
|
||
deleteButton.innerText = 'Delete';
|
||
deleteButton.className = 'btn btn-sm btn-danger';
|
||
deleteButton.onclick = () => deleteLink(link.id);
|
||
wrapper.appendChild(deleteButton);
|
||
|
||
return wrapper;
|
||
}
|
||
|
||
function deleteLink(linkId) {
|
||
fetch(`/api/links/${linkId}/delete/`, {
|
||
method: 'DELETE'
|
||
})
|
||
.then(res => {
|
||
if (res.ok) {
|
||
linksData = linksData.filter(link => link.id !== linkId);
|
||
currentPage = 1;
|
||
renderPaginatedList();
|
||
reinitializeInstagramEmbeds();
|
||
}
|
||
})
|
||
.catch(err => console.error(err));
|
||
}
|
||
|
||
// Re-run the Instagram embed script after we’ve injected new blockquotes
|
||
function reinitializeInstagramEmbeds() {
|
||
if (window.instgrm) {
|
||
window.instgrm.Embeds.process();
|
||
}
|
||
}
|
||
|
||
// Mark a link as watched
|
||
function markLinkWatched(linkId) {
|
||
fetch(`/api/links/${linkId}/watched/`, {
|
||
method: 'PATCH'
|
||
})
|
||
.then(res => res.json())
|
||
.then(updatedLink => {
|
||
// Update the local array
|
||
const idx = linksData.findIndex(l => l.id === updatedLink.id);
|
||
if (idx !== -1) {
|
||
linksData[idx] = updatedLink;
|
||
}
|
||
renderPaginatedList();
|
||
reinitializeInstagramEmbeds();
|
||
})
|
||
.catch(err => console.error(err));
|
||
}
|
||
|
||
// Add new link
|
||
addLinkBtn.addEventListener('click', () => {
|
||
const newUrl = newLinkInput.value.trim();
|
||
if (!newUrl) return;
|
||
|
||
fetch('/api/links/add/', {
|
||
method: 'POST',
|
||
headers: { 'Content-Type': 'application/json' },
|
||
body: JSON.stringify({ url: newUrl })
|
||
})
|
||
.then(res => res.json())
|
||
.then(addedLink => {
|
||
// update local data
|
||
linksData.push(addedLink);
|
||
newLinkInput.value = '';
|
||
currentPage = 1;
|
||
renderPaginatedList();
|
||
reinitializeInstagramEmbeds();
|
||
})
|
||
.catch(err => console.error(err));
|
||
});
|
||
|
||
// On page load
|
||
loadLinks();
|