tagliatelle

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

admin.html (18669B)


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