{% extends 'base.html' %} {% block content %} <form id="upload-form" class="py-2 border border-gray-700 px-2 rounded-lg flex items-start gap-4" enctype="multipart/form-data"> <div class="flex flex-col gap-2"> <img src="{{ s3_endpoint }}/{{ s3_bucket }}/{{ img }}" alt="" class="w-[296px] object-cover rounded-lg" /> <div id="datepicker-inline" inline-datepicker datepicker-buttons datepicker-format="dd/mm/yyyy" datepicker-title="Shoot Date" data-date="{{ date }}"></div> </div> <div class="flex flex-col gap-4 w-full"> <div class="w-full"> <label for="tags-input" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Tags</label> <input type="text" id="tags-input" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Winter" /> <div class="w-full flex gap-2 mt-2 flex-wrap" id="tags-container"> </div> </div> <div class="w-full"> <label for="url-input" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Urls</label> <input type="text" id="url-input" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="https://www.example.com" /> <div class="w-full flex flex-wrap gap-2 mt-2" id="url-container"> {% for url in urls %} <input data-name="{{url.name}}" type="text" class="w-full bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" value="{{ url.value }}" /> {% endfor %} </div> </div> <div class="w-full"> <label for="url-input" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Description</label> <textarea id="alt-text" rows="4" name="alt" class="block p-2.5 text-sm text-gray-900 w-full h-full resize-none bg-gray-50 rounded-lg border border-gray-300 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Alt-Text" draggable="false">{{ alt }}</textarea> </div> <div class="w-full flex flex-wrap gap-2"> <button type="submit" id="btn-submit" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">Save</button> <button type="button" id="btn-delete" class="focus:outline-none text-white bg-red-700 hover:bg-red-800 focus:ring-4 focus:ring-red-300 font-medium rounded-lg text-sm px-5 py-2.5 me-2 mb-2 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900">Delete</button> </div> </div> </form> <script> let tags = "{{ tags }}".split(':') || []; if (tags[0] == '') { tags = []; } let urls = []; let datepicker = null; const tagInp = document.getElementById('tags-input') const tagCon = document.getElementById('tags-container') const urlInp = document.getElementById('url-input') const urlCon = document.getElementById('url-container') window.onload = () => { tags.forEach((tag) => { const tagEl = document.createElement('div'); tagEl.classList.add('bg-gray-600', 'rounded-lg', 'p-2', 'flex', 'items-center', 'gap-2'); tagEl.innerHTML = `${tag} <button class="rounded-full bg-gray-800 w-6 h-6 text-sm cursor-pointer" type="button" onclick="removeTag('${tag}')">X</button>`; tagCon.appendChild(tagEl); }) const urlsEls = document.querySelectorAll('#url-container input'); urlsEls.forEach((input) => { urls.push({ "name": input.dataset.name, "value": input.value }); input.onchange = (e) => { const target = urls.find(url => url.name === e.target.dataset.name); const index = urls.indexOf(url => url.name === e.target.dataset.name); if (e.target.value.trim() === '') { urls.splice(index, 1); urlCon.removeChild(e.target); return; } if (target) { target.value = e.target.value.trim(); return; } } }) datepicker = FlowbiteInstances.getInstance('Datepicker', 'datepicker-inline') } function removeTag(tag) { tags.splice(tags.indexOf(tag), 1); tagCon.innerHTML = ''; tags.forEach(tag => { const tagEl = document.createElement('div'); tagEl.classList.add('bg-gray-600', 'rounded-lg', 'p-2', 'flex', 'items-center', 'gap-2'); tagEl.innerHTML = `${tag} <button class="rounded-full bg-gray-800 w-6 h-6 text-sm cursor-pointer" type="button" onclick="removeTag('${tag}')">X</button>`; tagCon.appendChild(tagEl); }); }; // const tagSearch = ["Winter", "Summer", "Spring", "Autumn"]; tagInp.addEventListener('input', (e) => { if (e.target.value.includes(',')) { const tag = e.target.value.split(',')[0].trim().replaceAll(" ", "_").toLowerCase(); if (tags.includes(tag) || !tag) { tagInp.value = ''; return; }; tags.push(tag); tagInp.value = ''; tagCon.innerHTML = ''; tags.forEach(tag => { const tagEl = document.createElement('div'); tagEl.classList.add('bg-gray-600', 'rounded-lg', 'p-2', 'flex', 'items-center', 'gap-2'); tagEl.innerHTML = `${tag} <button class="rounded-full bg-gray-800 w-6 h-6 text-sm cursor-pointer" type="button" onclick="removeTag('${tag}')">X</button>`; tagCon.appendChild(tagEl); }); } }); urlInp.addEventListener('keyup', (e) => { if (e.code == 'Enter') { if (!e.target.value.startsWith('http')) { alert('Invalid URL'); return; } if (!e.target.value.split('/')[2].includes(".")) { alert('Invalid URL'); return; } if (urls.find(url => url.value === e.target.value.trim())) { e.target.value = ''; return; } const urlEl = document.createElement('input'); urlEl.type = 'text'; urlEl.classList.add('bg-gray-50', 'border', 'border-gray-300', 'text-gray-900', 'text-sm', 'rounded-lg', 'focus:ring-blue-500', 'focus:border-blue-500', 'block', 'w-full', 'p-2.5', 'dark:bg-gray-700', 'dark:border-gray-600', 'dark:placeholder-gray-400', 'dark:text-white', 'dark:focus:ring-blue-500', 'dark:focus:border-blue-500'); urlEl.value = e.target.value.trim(); urlEl.dataset.name = `${e.target.value.split('/')[2].split('.')[0]}`; urlEl.onchange = (e) => { const target = urls.find(url => url.name === e.target.dataset.name); const index = urls.indexOf(url => url.name === e.target.dataset.name); if (e.target.value.trim() === '') { urls.splice(index, 1); urlCon.removeChild(e.target); return; } if (target) { target.value = e.target.value.trim(); return; } } urls.push({ name: e.target.value.split('/')[2].split('.')[0], value: e.target.value.trim() }) urlCon.appendChild(urlEl) e.target.value = ''; } }); const btnDelete = document.getElementById('btn-delete'); const btnSubmit = document.getElementById('btn-submit'); btnDelete.addEventListener('click', () => { if (confirm('Are you sure you want to delete this post?')) { fetch(`{{ url_for('ApiDelete', file=name) }}`, { method: 'DELETE', headers: { 'Content-Type': 'application/json' }, }) .then(res => res.json()) .then(data => { alert(data.message); window.location.href = "{{url_for('Home')}}"; }) .catch(err => { console.log(err); alert(err.message); }); } }); const form = document.getElementById('upload-form'); form.addEventListener('keydown', (e) => { if (e.key === "Enter") { e.preventDefault(); // Prevent form submission } }); form.addEventListener('submit', (e) => { e.preventDefault(); const formFields = form.elements; const formData = new FormData(form); if (!datepicker.getDate()) { alert('Please select a date'); return; } let convertedUrls = ""; urls.forEach(url => { convertedUrls += `{"name":"${url.name}","value":"${url.value}"};`; }); formData.set('alt', formFields['alt'].value.trim()); formData.append('tags', tags.toString()); formData.append('urls', convertedUrls.toString()); formData.append('date', datepicker.getDatepickerInstance().picker.viewDate); for (let pair of formData.entries()) { if (pair[0] == "urls") { console.log(`${pair[0]}:`, urls); } else { console.log(`${pair[0]}: ${pair[1]}`); } } btnSubmit.setAttribute('disabled', true); fetch('{{ url_for("ApiUpdate", file=name) }}', { method: 'PUT', body: formData }) .then(res => { return res.json(); }) .then(data => { console.log(data); btnSubmit.removeAttribute('disabled'); alert(data.message); if (data.status != "error") { window.location.href = "{{ url_for('Home') }}"; } }) .catch(err => { console.log(err); btnSubmit.removeAttribute('disabled'); alert(err.message); }) }); </script> {% endblock %}