tagliatelle

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

admin.html (17201B)


      1 {{template "_header" .}}
      2 <h1>Admin</h1>
      3 
      4 {{if .Data.Error}}
      5 <div style="background-color: #f8d7da; color: #721c24; padding: 10px; border: 1px solid #f5c6cb; border-radius: 4px; margin-bottom: 20px;">
      6     <strong>Error:</strong> {{.Data.Error}}
      7 </div>
      8 {{end}}
      9 
     10 {{if .Data.Success}}
     11 <div style="background-color: #d4edda; color: #155724; padding: 10px; border: 1px solid #c3e6cb; border-radius: 4px; margin-bottom: 20px;">
     12     <strong>Success:</strong> {{.Data.Success}}
     13 </div>
     14 {{end}}
     15 
     16 <!-- Tab Navigation -->
     17 <div style="margin-bottom: 20px; border-bottom: 2px solid #ddd;">
     18     <button onclick="showAdminTab('settings')" id="admin-tab-settings" class="admin-tab-btn" style="padding: 10px 20px; border: none; background: none; cursor: pointer; border-bottom: 3px solid #007bff; font-weight: bold;">
     19         Settings
     20     </button>
     21     <button onclick="showAdminTab('database')" id="admin-tab-database" class="admin-tab-btn" style="padding: 10px 20px; border: none; background: none; cursor: pointer; border-bottom: 3px solid transparent;">
     22         Database
     23     </button>
     24     <button onclick="showAdminTab('aliases')" id="admin-tab-aliases" class="admin-tab-btn" style="padding: 10px 20px; border: none; background: none; cursor: pointer; border-bottom: 3px solid transparent;">
     25         Aliases
     26     </button>
     27     <button onclick="showAdminTab('sedrules')" id="admin-tab-sedrules" class="admin-tab-btn" style="padding: 10px 20px; border: none; background: none; cursor: pointer; border-bottom: 3px solid transparent;">
     28         Sed Rules
     29     </button>
     30     <button onclick="showAdminTab('orphans')" id="admin-tab-orphans" class="admin-tab-btn" style="padding: 10px 20px; border: none; background: none; cursor: pointer; border-bottom: 3px solid transparent;">
     31         Orphans
     32     </button>
     33     <button onclick="showAdminTab('thumbnails')" id="admin-tab-thumbnails" class="admin-tab-btn" style="padding: 10px 20px; border: none; background: none; cursor: pointer; border-bottom: 3px solid transparent;">
     34         Thumbnails
     35     </button>
     36 </div>
     37 
     38 <!-- Settings Tab -->
     39 <div id="admin-content-settings">
     40 	<div class="config-container">
     41     <div class="config-split">
     42     <h2>Settings</h2>
     43     <form method="post" style="max-width: 600px;">
     44         <input type="hidden" name="active_tab" value="settings">
     45 
     46         <div style="margin-bottom: 20px;">
     47             <label for="gallery_size" style="display: block; font-weight: bold; margin-bottom: 5px;">Gallery Size:</label>
     48             <input type="text" id="gallery_size" name="gallery_size" value="{{.Data.Config.GallerySize}}" required
     49                    style="width: 100%; padding: 8px; font-size: 14px;"
     50                    placeholder="400px">
     51             <small style="color: #666;">Size of previews used in galleries</small>
     52         </div>
     53 
     54         <div style="margin-bottom: 20px;">
     55             <label for="items_per_page" style="display: block; font-weight: bold; margin-bottom: 5px;">Items per Page:</label>
     56             <input type="text" id="items_per_page" name="items_per_page" value="{{.Data.Config.ItemsPerPage}}" required
     57                    style="width: 100%; padding: 8px; font-size: 14px;"
     58                    placeholder="100">
     59             <small style="color: #666;">Items per page in galleries</small>
     60         </div>
     61 
     62         <button type="submit" style="background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer;">
     63             Save Settings
     64         </button>
     65     </form>
     66 	</div>
     67 
     68     <div class="config-split">
     69         <h3>Current Configuration:</h3>
     70         <ul>
     71             <li><strong>Database:</strong> {{.Data.Config.DatabasePath}}</li>
     72             <li><strong>Upload Directory:</strong> {{.Data.Config.UploadDir}}</li>
     73             <li><strong>Server Port:</strong> {{.Data.Config.ServerPort}}</li>
     74             <li><strong>Gallery Size:</strong> {{.Data.Config.GallerySize}}</li>
     75             <li><strong>Items per Page:</strong> {{.Data.Config.ItemsPerPage}}</li>
     76         </ul>
     77 
     78         <h4>Configuration:</h4>
     79         <p>Working directory is specified via the <code>-d</code> flag on launch.</p>
     80         <p>Webserver port is specified via the <code>-p</code> flag on launch.</p>
     81     </div>
     82     </div>
     83 </div>
     84 
     85 <!-- Database Tab -->
     86 <div id="admin-content-database" style="display: none;">
     87     <h2>Database Maintenance</h2>
     88 
     89     <form method="post" style="margin-bottom: 20px;">
     90         <input type="hidden" name="active_tab" value="database">
     91         <input type="hidden" name="action" value="backup">
     92         <button type="submit" style="background-color: #28a745; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer;">
     93             Backup Database
     94         </button>
     95         <small style="color: #666; margin-left: 10px;">Creates a timestamped backup of the database file</small>
     96     </form>
     97 
     98     <form method="post">
     99         <input type="hidden" name="active_tab" value="database">
    100         <input type="hidden" name="action" value="vacuum">
    101         <button type="submit" style="background-color: #6f42c1; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer;">
    102             Vacuum Database
    103         </button>
    104         <small style="color: #666; margin-left: 10px;">Reclaims unused space and optimizes database performance</small>
    105     </form>
    106 
    107     <hr style="margin: 30px 0; border: none; border-top: 1px solid #ddd;">
    108     <h3>File Properties</h3>
    109     <p style="color: #666; margin-bottom: 10px;">
    110         Compute auto-detected properties (filetype, duration, orientation, resolution) for any files that do not yet have them.
    111     </p>
    112     <form method="post">
    113         <input type="hidden" name="active_tab" value="database">
    114         <input type="hidden" name="action" value="compute_properties">
    115         <button type="submit" style="background-color: #17a2b8; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer;">
    116             Compute Missing Properties
    117         </button>
    118         <small style="color: #666; margin-left: 10px;">Processes only files with no existing properties</small>
    119     </form>
    120 </div>
    121 
    122 <!-- Aliases Tab -->
    123 <div id="admin-content-aliases" style="display: none;">
    124     <h2>Tag Aliases</h2>
    125     <p>
    126         Define tag aliases so that multiple tag values are treated as equivalent when searching or filtering.
    127         For example, if you alias "colour/blue" with "colour/navy", searching for either will show files tagged with both.
    128     </p>
    129 
    130     <div id="aliases-section" style="max-width: 800px;">
    131         <div id="alias-groups"></div>
    132 
    133         <button onclick="addAliasGroup()" style="background-color: #28a745; color: white; padding: 8px 16px; border: none; border-radius: 4px; font-size: 14px; cursor: pointer; margin-top: 10px;">
    134             + Add Alias Group
    135         </button>
    136 
    137         <form method="post" id="aliases-form" style="margin-top: 20px;">
    138             <input type="hidden" name="active_tab" value="aliases">
    139             <input type="hidden" name="action" value="save_aliases">
    140             <input type="hidden" name="aliases_json" id="aliases_json">
    141             <button type="submit" style="background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer;">
    142                 Save Aliases
    143             </button>
    144         </form>
    145     </div>
    146 </div>
    147 
    148 <!-- Sed Rules Tab -->
    149 <div id="admin-content-sedrules" style="display: none;">
    150 	<div class="config-container">
    151     <div class="config-split">
    152     <h2>Sed Rules for Notes</h2>
    153     <p>
    154         Define sed rules that can be applied to notes in the Notes editor.
    155         These rules will appear as buttons in the notes interface for quick text transformations.
    156     </p>
    157 
    158     <div id="sedrules-section" style="max-width: 800px;">
    159         <div id="sed-rules"></div>
    160 
    161         <button onclick="addSedRule()" style="background-color: #28a745; color: white; padding: 8px 16px; border: none; border-radius: 4px; font-size: 14px; cursor: pointer; margin-top: 10px;">
    162             + Add Sed Rule
    163         </button>
    164 
    165         <form method="post" action="/admin" id="sedrules-form" style="margin-top: 20px;">
    166             <input type="hidden" name="active_tab" value="sedrules">
    167             <input type="hidden" name="action" value="save_sed_rules">
    168             <input type="hidden" name="sed_rules_json" id="sed_rules_json">
    169             <button type="submit" style="background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer;">
    170                 Save Sed Rules
    171             </button>
    172         </form>
    173     </div>
    174     </div>
    175 
    176     <div class="config-split">
    177         <h4 style="margin-top: 0;">Example Sed Commands:</h4>
    178         <ul style="font-family: monospace; font-size: 13px;">
    179             <li><code>s?[?&]brandIds=[0-9]\+&productId=[0-9]\+??g</code> - Remove URL parameters</li>
    180             <li><code>s/[[:space:]]*$//</code> - Remove trailing whitespace</li>
    181             <li><code>s/  \+/ /g</code> - Replace multiple spaces with single space</li>
    182             <li><code>s/https\?:\/\/[^ ]*//g</code> - Remove URLs</li>
    183             <li><code>/^$/d</code> - Delete empty lines</li>
    184         </ul>
    185     </div>
    186     </div>
    187 </div>
    188 
    189 <!-- Orphans Tab -->
    190 <div id="admin-content-orphans" style="display: none;">
    191     <h2>Orphaned Files</h2>
    192 
    193     <!-- Files on disk, not in DB -->
    194     <h3 style="margin-top: 24px;">Disk Orphans</h3>
    195     <p style="color: #666; margin-bottom: 12px;">
    196         These files exist in the upload directory but are not tracked in the database.
    197     </p>
    198     {{if .Data.OrphanData.Orphans}}
    199     <ul style="list-style-type: disc; padding-left: 20px;">
    200       {{range .Data.OrphanData.Orphans}}
    201         <li style="margin-bottom: 5px; font-family: monospace;">{{.}}</li>
    202       {{end}}
    203     </ul>
    204     {{else}}
    205     <div style="padding: 20px; background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; border-radius: 4px;">
    206         <strong>✓ No disk orphans found!</strong>
    207     </div>
    208     {{end}}
    209 
    210     <!-- Files in DB, not on disk -->
    211     <h3 style="margin-top: 32px;">Database Orphans</h3>
    212     <p style="color: #666; margin-bottom: 12px;">
    213         These files are tracked in the database but are missing from the upload directory.
    214     </p>
    215     {{if .Data.OrphanData.ReverseOrphans}}
    216     <ul style="list-style-type: disc; padding-left: 20px;">
    217       {{range .Data.OrphanData.ReverseOrphans}}
    218         <li style="margin-bottom: 5px; font-family: monospace;">{{.}}</li>
    219       {{end}}
    220     </ul>
    221     {{else}}
    222     <div style="padding: 20px; background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; border-radius: 4px;">
    223         <strong>✓ No database orphans found!</strong>
    224     </div>
    225     {{end}}
    226 </div>
    227 
    228 <!-- Thumbnails Tab -->
    229 <div id="admin-content-thumbnails" style="display: none;">
    230     <h2>Thumbnail Management</h2>
    231 
    232     <!-- Sub-tab Navigation -->
    233     <div style="margin-bottom: 20px; border-bottom: 1px solid #ddd;">
    234         <button onclick="showThumbnailSubTab('missing')" id="thumb-subtab-missing" class="thumb-subtab-btn" style="padding: 8px 16px; border: none; background: none; cursor: pointer; border-bottom: 2px solid #007bff; font-weight: bold;">
    235             Missing ({{len .Data.MissingThumbnails}})
    236         </button>
    237         <button onclick="showThumbnailSubTab('regenerate')" id="thumb-subtab-regenerate" class="thumb-subtab-btn" style="padding: 8px 16px; border: none; background: none; cursor: pointer; border-bottom: 2px solid transparent;">
    238             Regenerate
    239         </button>
    240     </div>
    241 
    242     <!-- Missing Thumbnails Sub-tab -->
    243     <div id="thumb-content-missing">
    244         <h3>Missing Thumbnails ({{len .Data.MissingThumbnails}})</h3>
    245 
    246         {{if .Data.MissingThumbnails}}
    247             <form method="post" action="/thumbnails/generate" style="margin-bottom: 20px;">
    248                 <input type="hidden" name="action" value="generate_all">
    249                 <button type="submit" onclick="return confirm('Generate thumbnails for all {{len .Data.MissingThumbnails}} videos? This may take a while.');" style="background-color: #28a745; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer;">
    250                     Generate All Missing Thumbnails
    251                 </button>
    252                 <small style="color: #666; margin-left: 10px;">Uses timestamp 00:00:05 for all videos</small>
    253             </form>
    254 
    255             <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;">
    256                 {{range .Data.MissingThumbnails}}
    257                 <div style="border: 1px solid #ddd; padding: 15px; border-radius: 5px; background-color: #f8f9fa;">
    258                     <h4 style="margin-top: 0; font-size: 14px; word-break: break-word;">
    259                         <a href="/file/{{.ID}}" target="_blank">{{.Filename}}</a>
    260                     </h4>
    261                     <p style="color: #666; font-size: 12px; margin: 5px 0;">ID: {{.ID}}</p>
    262 
    263                     <video width="100%" style="max-height: 200px; background: #000; margin: 10px 0; cursor: pointer;" title="Click to capture frame">
    264                         <source src="/uploads/{{.EscapedFilename}}">
    265                     </video>
    266 
    267                     <form method="post" action="/thumbnails/generate" style="margin-top: 10px;">
    268                         <input type="hidden" name="action" value="generate_single">
    269                         <input type="hidden" name="file_id" value="{{.ID}}">
    270                         <input type="hidden" name="redirect" value="admin">
    271 
    272                         <div style="display: flex; gap: 5px; align-items: center; margin-bottom: 10px;">
    273                             <label style="font-size: 13px; white-space: nowrap;">Timestamp:</label>
    274                             <input type="text" name="timestamp" value="00:00:05" placeholder="00:00:05"
    275                                    style="flex: 1; padding: 5px; font-size: 13px; font-family: monospace;">
    276                         </div>
    277 
    278                         <button type="submit" style="background-color: #007bff; color: white; padding: 6px 12px; border: none; border-radius: 3px; font-size: 13px; cursor: pointer; width: 100%;">
    279                             Generate Thumbnail
    280                         </button>
    281                     </form>
    282                 </div>
    283                 {{end}}
    284             </div>
    285         {{else}}
    286             <div style="padding: 20px; background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; border-radius: 4px;">
    287                 <strong>✓ All videos have thumbnails!</strong>
    288             </div>
    289         {{end}}
    290     </div>
    291 
    292     <!-- Regenerate Sub-tab -->
    293     <div id="thumb-content-regenerate" style="display: none;">
    294         <h3>Regenerate Thumbnail</h3>
    295 
    296         <div style="margin-bottom: 20px; padding: 10px; background-color: #e7f3ff; border: 1px solid #b3d9ff; border-radius: 4px;">
    297             <strong>Tip:</strong> Enter a file ID to regenerate its thumbnail with a custom timestamp. You can find file IDs in the URL when viewing a file (e.g., /file/312).
    298         </div>
    299 
    300         <form method="post" action="/thumbnails/generate" style="max-width: 500px; padding: 20px; background-color: #f8f9fa; border: 1px solid #ddd; border-radius: 5px;">
    301             <input type="hidden" name="action" value="generate_single">
    302             <input type="hidden" name="redirect" value="admin">
    303 
    304             <div style="margin-bottom: 20px;">
    305                 <label for="file_id" style="display: block; font-weight: bold; margin-bottom: 5px;">File ID:</label>
    306                 <input type="text" id="file_id" name="file_id" required
    307                        style="width: 100%; padding: 8px; font-size: 14px; font-family: monospace;"
    308                        placeholder="e.g., 312">
    309                 <small style="color: #666;">Enter the ID of the video file</small>
    310             </div>
    311 
    312             <div style="margin-bottom: 20px;">
    313                 <label for="timestamp" style="display: block; font-weight: bold; margin-bottom: 5px;">Timestamp:</label>
    314                 <input type="text" id="timestamp" name="timestamp" value="00:00:05" required
    315                        style="width: 100%; padding: 8px; font-size: 14px; font-family: monospace;"
    316                        placeholder="00:00:05">
    317                 <small style="color: #666;">Format: HH:MM:SS (e.g., 00:00:05 for 5 seconds)</small>
    318             </div>
    319 
    320             <button type="submit" style="background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; width: 100%;">
    321                 Generate/Regenerate Thumbnail
    322             </button>
    323         </form>
    324     </div>
    325 </div>
    326 
    327 <script>window.initialAliasGroups = {{.Data.Config.TagAliases}};</script>
    328 <script>window.initialSedRules = {{.Data.Config.SedRules}};</script>
    329 <script>window.activeAdminTab = "{{.Data.ActiveTab}}";</script>
    330 <script src="/static/tag-alias.js" defer></script>
    331 <script src="/static/sed-rules.js" defer></script>
    332 <script src="/static/admin-tabs.js" defer></script>
    333 <script src="/static/common.js" defer></script>
    334 
    335 {{template "_footer"}}