tagliatelle

Simple self-hosted tagging filesystem webapp
Log | Files | Refs

admin-magic-links.js (5471B)


      1 let magicLinkRules = [];
      2 
      3 // Init on page load
      4 document.addEventListener('DOMContentLoaded', function() {
      5     magicLinkRules = window.initialMagicLinks || [];
      6     renderMagicLinkRules();
      7     setupMagicLinksForm();
      8 });
      9 
     10 function renderMagicLinkRules() {
     11     const container = document.getElementById('magic-link-rules');
     12     if (!container) return;
     13 
     14     container.innerHTML = '';
     15 
     16     magicLinkRules.forEach((rule, index) => {
     17         const ruleDiv = document.createElement('div');
     18         ruleDiv.style.cssText = 'border: 1px solid #ddd; padding: 15px; margin-bottom: 15px; border-radius: 5px;';
     19 
     20         ruleDiv.innerHTML = `
     21             <div style="display: flex; justify-content: space-between; align-items: start; margin-bottom: 10px;">
     22                 <h4 style="margin: 0;">Rule ${index + 1}</h4>
     23                 <button onclick="removeMagicLinkRule(${index})" style="background-color: #dc3545; color: white; padding: 5px 10px; border: none; border-radius: 3px; font-size: 12px; cursor: pointer;">
     24                     Remove
     25                 </button>
     26             </div>
     27 
     28             <div style="margin-bottom: 10px;">
     29                 <label style="display: block; font-weight: bold; margin-bottom: 5px; font-size: 13px;">Name:</label>
     30                 <input type="text" value="${escapeHtml(rule.name)}"
     31                        onchange="updateMagicLinkRule(${index}, 'name', this.value)"
     32                        placeholder="e.g., Open on website.tld"
     33                        style="width: 100%; padding: 6px; font-size: 13px; border: 1px solid #ccc; border-radius: 3px;">
     34                 <small>Shown as the label next to the link in the file viewer</small>
     35             </div>
     36 
     37             <div style="display: flex; gap: 10px; margin-bottom: 10px;">
     38                 <div style="flex: 1;">
     39                     <label style="display: block; font-weight: bold; margin-bottom: 5px; font-size: 13px;">If tag category is:</label>
     40                     <input type="text" value="${escapeHtml(rule.category)}"
     41                            onchange="updateMagicLinkRule(${index}, 'category', this.value)"
     42                            placeholder="e.g., source"
     43                            style="width: 100%; padding: 6px; font-size: 13px; border: 1px solid #ccc; border-radius: 3px;">
     44                 </div>
     45                 <div style="flex: 1;">
     46                     <label style="display: block; font-weight: bold; margin-bottom: 5px; font-size: 13px;">equal to:</label>
     47                     <input type="text" value="${escapeHtml(rule.value)}"
     48                            onchange="updateMagicLinkRule(${index}, 'value', this.value)"
     49                            placeholder="e.g., example"
     50                            style="width: 100%; padding: 6px; font-size: 13px; border: 1px solid #ccc; border-radius: 3px;">
     51                 </div>
     52             </div>
     53 
     54             <div style="margin-bottom: 0;">
     55                 <label style="display: block; font-weight: bold; margin-bottom: 5px; font-size: 13px;">URL Template:</label>
     56                 <input type="text" value="${escapeHtml(rule.template)}"
     57                        onchange="updateMagicLinkRule(${index}, 'template', this.value)"
     58                        placeholder="e.g., https://website.tld/$name"
     59                        style="width: 100%; padding: 6px; font-size: 13px; font-family: monospace; border: 1px solid #ccc; border-radius: 3px;">
     60                 <small>Must start with http:// or https://. Use $category or \${category} to insert the file's tag value.</small>
     61             </div>
     62         `;
     63 
     64         container.appendChild(ruleDiv);
     65     });
     66 }
     67 
     68 function addMagicLinkRule() {
     69     magicLinkRules.push({
     70         name: '',
     71         category: '',
     72         value: '',
     73         template: ''
     74     });
     75     renderMagicLinkRules();
     76 }
     77 
     78 function removeMagicLinkRule(index) {
     79     if (confirm('Remove this magic link rule?')) {
     80         magicLinkRules.splice(index, 1);
     81         renderMagicLinkRules();
     82     }
     83 }
     84 
     85 function updateMagicLinkRule(index, field, value) {
     86     if (magicLinkRules[index]) {
     87         magicLinkRules[index][field] = value;
     88     }
     89 }
     90 
     91 function setupMagicLinksForm() {
     92     const form = document.getElementById('magiclinks-form');
     93     if (!form) return;
     94 
     95     form.addEventListener('submit', function(e) {
     96         // Validate rules
     97         for (let i = 0; i < magicLinkRules.length; i++) {
     98             const rule = magicLinkRules[i];
     99             if (!rule.name || !rule.category || !rule.value || !rule.template) {
    100                 e.preventDefault();
    101                 alert(`Rule ${i + 1} is incomplete. Please fill in Name, tag category, tag value and URL Template.`);
    102                 return;
    103             }
    104             if (!/^https?:\/\//i.test(rule.template.trim())) {
    105                 e.preventDefault();
    106                 alert(`Rule ${i + 1}: URL Template must start with http:// or https://`);
    107                 return;
    108             }
    109         }
    110 
    111         // Remove any previously-injected hidden fields from a prior submit
    112         this.querySelectorAll('input[data-generated]').forEach(el => el.remove());
    113 
    114         // Append one hidden field per value
    115         magicLinkRules.forEach((rule, i) => {
    116             appendHidden(this, `magic_links[${i}][name]`,     rule.name);
    117             appendHidden(this, `magic_links[${i}][category]`, rule.category);
    118             appendHidden(this, `magic_links[${i}][value]`,    rule.value);
    119             appendHidden(this, `magic_links[${i}][template]`, rule.template);
    120         });
    121     });
    122 }