final app for testing and deployment
This commit is contained in:
@@ -141,12 +141,27 @@
|
||||
border-radius: 8px;
|
||||
padding: 20px;
|
||||
margin-bottom: 15px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
.link-item.editing {
|
||||
border-color: #667eea;
|
||||
}
|
||||
|
||||
.link-content {
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
.link-logo {
|
||||
width: 32px;
|
||||
height: 32px;
|
||||
border-radius: 6px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.link-display {
|
||||
display: block;
|
||||
}
|
||||
@@ -253,6 +268,13 @@
|
||||
<div class="header">
|
||||
<h1>✏️ Edit Links</h1>
|
||||
<p>Manage your link collection: {{ page.title }}</p>
|
||||
{% if page.short_url %}
|
||||
<div style="margin-top: 15px; padding: 12px; background: rgba(255,255,255,0.2); border-radius: 8px; font-size: 0.9em;">
|
||||
<strong>🔗 Page Short URL:</strong>
|
||||
<a href="{{ page.short_url }}" target="_blank" style="color: #fff; text-decoration: underline;">{{ page.short_url }}</a>
|
||||
<button onclick="copyToClipboard('{{ page.short_url }}')" style="margin-left: 10px; padding: 4px 8px; background: rgba(255,255,255,0.3); color: white; border: 1px solid rgba(255,255,255,0.5); border-radius: 3px; cursor: pointer; font-size: 0.8em;">Copy</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<div class="alert alert-success" id="success-alert">
|
||||
@@ -292,12 +314,21 @@
|
||||
{% if page.links %}
|
||||
{% for link in page.links %}
|
||||
<div class="link-item" data-link-id="{{ link.id }}">
|
||||
<div class="link-display">
|
||||
<div class="link-title">{{ link.title }}</div>
|
||||
{% if link.description %}
|
||||
<div class="link-description">{{ link.description }}</div>
|
||||
<div class="link-content">
|
||||
<div class="link-display">
|
||||
<div class="link-title">{{ link.title }}</div>
|
||||
{% if link.description %}
|
||||
<div class="link-description">{{ link.description }}</div>
|
||||
{% endif %}
|
||||
<div class="link-url" data-url="{{ link.url }}">{{ link.url }}</div>
|
||||
{% if link.short_url %}
|
||||
<div class="short-url-display" style="margin-top: 8px; padding: 8px; background: #e3f2fd; border-radius: 5px; border-left: 3px solid #2196f3;">
|
||||
<small style="color: #1976d2; font-weight: 600;">🔗 Short URL:</small>
|
||||
<br>
|
||||
<a href="{{ link.short_url }}" target="_blank" style="color: #1976d2; text-decoration: none; font-family: monospace;">{{ link.short_url }}</a>
|
||||
<button class="btn-copy" onclick="copyToClipboard('{{ link.short_url }}')" style="margin-left: 10px; padding: 2px 8px; background: #2196f3; color: white; border: none; border-radius: 3px; cursor: pointer; font-size: 0.8em;">Copy</button>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="link-url">{{ link.url }}</div>
|
||||
<div class="link-actions">
|
||||
<button class="btn btn-small btn-secondary" onclick="editLink('{{ link.id }}')">Edit</button>
|
||||
<button class="btn btn-small btn-danger" onclick="deleteLink('{{ link.id }}')">Delete</button>
|
||||
@@ -322,6 +353,7 @@
|
||||
<button class="btn btn-small btn-secondary" onclick="cancelEdit('{{ link.id }}')">Cancel</button>
|
||||
</div>
|
||||
</div>
|
||||
<img class="link-logo" src="" alt="" style="display: none;" onerror="this.style.display='none'">
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% else %}
|
||||
@@ -344,6 +376,87 @@
|
||||
<script>
|
||||
const pageId = '{{ page.id }}';
|
||||
|
||||
// Social media and website logo detection
|
||||
function getWebsiteLogo(url) {
|
||||
try {
|
||||
const urlObj = new URL(url.startsWith('http') ? url : 'https://' + url);
|
||||
const domain = urlObj.hostname.toLowerCase().replace('www.', '');
|
||||
|
||||
// Logo mapping for popular sites
|
||||
const logoMap = {
|
||||
'facebook.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/facebook.svg',
|
||||
'instagram.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/instagram.svg',
|
||||
'twitter.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/twitter.svg',
|
||||
'x.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/x.svg',
|
||||
'tiktok.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/tiktok.svg',
|
||||
'youtube.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/youtube.svg',
|
||||
'linkedin.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/linkedin.svg',
|
||||
'pinterest.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/pinterest.svg',
|
||||
'snapchat.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/snapchat.svg',
|
||||
'whatsapp.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/whatsapp.svg',
|
||||
'telegram.org': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/telegram.svg',
|
||||
'discord.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/discord.svg',
|
||||
'reddit.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/reddit.svg',
|
||||
'github.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/github.svg',
|
||||
'gmail.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/gmail.svg',
|
||||
'google.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/google.svg',
|
||||
'amazon.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/amazon.svg',
|
||||
'apple.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/apple.svg',
|
||||
'microsoft.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/microsoft.svg',
|
||||
'spotify.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/spotify.svg',
|
||||
'netflix.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/netflix.svg',
|
||||
'twitch.tv': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/twitch.svg',
|
||||
'dropbox.com': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/dropbox.svg',
|
||||
'zoom.us': 'https://cdn.jsdelivr.net/npm/simple-icons@v9/icons/zoom.svg'
|
||||
};
|
||||
|
||||
if (logoMap[domain]) {
|
||||
return logoMap[domain];
|
||||
}
|
||||
|
||||
// Fallback to favicon
|
||||
return `https://www.google.com/s2/favicons?domain=${domain}&sz=64`;
|
||||
} catch (e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Set logos for existing links
|
||||
function setLogosForLinks() {
|
||||
document.querySelectorAll('.link-url[data-url]').forEach(linkElement => {
|
||||
const url = linkElement.getAttribute('data-url');
|
||||
const logoImg = linkElement.closest('.link-item').querySelector('.link-logo');
|
||||
const logoSrc = getWebsiteLogo(url);
|
||||
|
||||
if (logoSrc && logoImg) {
|
||||
logoImg.src = logoSrc;
|
||||
logoImg.style.display = 'block';
|
||||
logoImg.alt = new URL(url.startsWith('http') ? url : 'https://' + url).hostname;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Initialize logos when page loads
|
||||
document.addEventListener('DOMContentLoaded', setLogosForLinks);
|
||||
|
||||
// Copy to clipboard function
|
||||
function copyToClipboard(text) {
|
||||
navigator.clipboard.writeText(text).then(function() {
|
||||
// Show temporary success message
|
||||
const btn = event.target;
|
||||
const originalText = btn.textContent;
|
||||
btn.textContent = 'Copied!';
|
||||
btn.style.background = '#4caf50';
|
||||
setTimeout(() => {
|
||||
btn.textContent = originalText;
|
||||
btn.style.background = '#2196f3';
|
||||
}, 1500);
|
||||
}).catch(function(err) {
|
||||
console.error('Could not copy text: ', err);
|
||||
alert('Failed to copy to clipboard');
|
||||
});
|
||||
}
|
||||
|
||||
// Add new link
|
||||
document.getElementById('add-link-form').addEventListener('submit', async function(e) {
|
||||
e.preventDefault();
|
||||
@@ -358,7 +471,11 @@
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ title, url, description })
|
||||
body: JSON.stringify({
|
||||
title,
|
||||
url,
|
||||
description
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
@@ -399,7 +516,11 @@
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify({ title, url, description })
|
||||
body: JSON.stringify({
|
||||
title,
|
||||
url,
|
||||
description
|
||||
})
|
||||
});
|
||||
|
||||
const result = await response.json();
|
||||
|
||||
Reference in New Issue
Block a user