taggart

Simple golang tagging filesystem webapp
Log | Files | Refs

admin.html (15054B)


      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('orphans')" id="admin-tab-orphans" class="admin-tab-btn" style="padding: 10px 20px; border: none; background: none; cursor: pointer; border-bottom: 3px solid transparent;">
     28         Orphans
     29     </button>
     30     <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;">
     31         Thumbnails
     32     </button>
     33 </div>
     34 
     35 <!-- Settings Tab -->
     36 <div id="admin-content-settings">
     37     <h2>Settings</h2>
     38     <form method="post" style="max-width: 600px;">
     39         <div style="margin-bottom: 20px;">
     40             <label for="database_path" style="display: block; font-weight: bold; margin-bottom: 5px;">Database Path:</label>
     41             <input type="text" id="database_path" name="database_path" value="{{.Data.Config.DatabasePath}}" required
     42                    style="width: 100%; padding: 8px; font-size: 14px;"
     43                    placeholder="./database.db">
     44             <small style="color: #666;">Path to SQLite database file (requires restart if changed)</small>
     45         </div>
     46 
     47         <div style="margin-bottom: 20px;">
     48             <label for="upload_dir" style="display: block; font-weight: bold; margin-bottom: 5px;">Upload Directory:</label>
     49             <input type="text" id="upload_dir" name="upload_dir" value="{{.Data.Config.UploadDir}}" required
     50                    style="width: 100%; padding: 8px; font-size: 14px;"
     51                    placeholder="uploads">
     52             <small style="color: #666;">Directory where uploaded files are stored</small>
     53         </div>
     54 
     55         <div style="margin-bottom: 20px;">
     56             <label for="server_port" style="display: block; font-weight: bold; margin-bottom: 5px;">Server Port:</label>
     57             <input type="text" id="server_port" name="server_port" value="{{.Data.Config.ServerPort}}" required
     58                    style="width: 100%; padding: 8px; font-size: 14px;"
     59                    placeholder=":8080">
     60             <small style="color: #666;">Port for web server (format: :8080, requires restart if changed)</small>
     61         </div>
     62 
     63         <div style="margin-bottom: 20px;">
     64             <label for="instance_name" style="display: block; font-weight: bold; margin-bottom: 5px;">Instance Name:</label>
     65             <input type="text" id="instance_name" name="instance_name" value="{{.Data.Config.InstanceName}}" required
     66                    style="width: 100%; padding: 8px; font-size: 14px;"
     67                    placeholder="Taggart">
     68             <small style="color: #666;">Instance Name, used in header and title bar</small>
     69         </div>
     70 
     71         <div style="margin-bottom: 20px;">
     72             <label for="gallery_size" style="display: block; font-weight: bold; margin-bottom: 5px;">Gallery Size:</label>
     73             <input type="text" id="gallery_size" name="gallery_size" value="{{.Data.Config.GallerySize}}" required
     74                    style="width: 100%; padding: 8px; font-size: 14px;"
     75                    placeholder="400px">
     76             <small style="color: #666;">Size of previews used in galleries</small>
     77         </div>
     78 
     79         <div style="margin-bottom: 20px;">
     80             <label for="items_per_page" style="display: block; font-weight: bold; margin-bottom: 5px;">Items per Page:</label>
     81             <input type="text" id="items_per_page" name="items_per_page" value="{{.Data.Config.ItemsPerPage}}" required
     82                    style="width: 100%; padding: 8px; font-size: 14px;"
     83                    placeholder="100">
     84             <small style="color: #666;">Items per page in galleries</small>
     85         </div>
     86 
     87         <button type="submit" style="background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer;">
     88             Save Settings
     89         </button>
     90     </form>
     91 
     92     <div style="margin-top: 40px; padding: 20px; background-color: #f8f9fa; border-radius: 5px;">
     93         <h3>Current Configuration:</h3>
     94         <ul>
     95             <li><strong>Database:</strong> {{.Data.Config.DatabasePath}}</li>
     96             <li><strong>Upload Directory:</strong> {{.Data.Config.UploadDir}}</li>
     97             <li><strong>Server Port:</strong> {{.Data.Config.ServerPort}}</li>
     98             <li><strong>Instance Name:</strong> {{.Data.Config.InstanceName}}</li>
     99             <li><strong>Gallery Size:</strong> {{.Data.Config.GallerySize}}</li>
    100             <li><strong>Items per Page:</strong> {{.Data.Config.ItemsPerPage}}</li>
    101         </ul>
    102 
    103         <h4>Configuration File:</h4>
    104         <p>Settings are stored in <code>config.json</code> in the application directory.</p>
    105     </div>
    106 </div>
    107 
    108 <!-- Database Tab -->
    109 <div id="admin-content-database" style="display: none;">
    110     <h2>Database Maintenance</h2>
    111 
    112     <form method="post" style="margin-bottom: 20px;">
    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="action" value="vacuum">
    122         <button type="submit" style="background-color: #6f42c1; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer;">
    123             Vacuum Database
    124         </button>
    125         <small style="color: #666; margin-left: 10px;">Reclaims unused space and optimizes database performance</small>
    126     </form>
    127 </div>
    128 
    129 <!-- Aliases Tab -->
    130 <div id="admin-content-aliases" style="display: none;">
    131     <h2>Tag Aliases</h2>
    132     <p style="color: #666; margin-bottom: 20px;">
    133         Define tag aliases so that multiple tag values are treated as equivalent when searching or filtering.
    134         For example, if you alias "colour/blue" with "colour/navy", searching for either will show files tagged with both.
    135     </p>
    136 
    137     <div id="aliases-section" style="max-width: 800px;">
    138         <div id="alias-groups"></div>
    139 
    140         <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;">
    141             + Add Alias Group
    142         </button>
    143 
    144         <form method="post" id="aliases-form" style="margin-top: 20px;">
    145             <input type="hidden" name="action" value="save_aliases">
    146             <input type="hidden" name="aliases_json" id="aliases_json">
    147             <button type="submit" style="background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer;">
    148                 Save Aliases
    149             </button>
    150         </form>
    151     </div>
    152 </div>
    153 
    154 <!-- Orphans Tab -->
    155 <div id="admin-content-orphans" style="display: none;">
    156     <h2>Orphaned Files</h2>
    157     <p style="color: #666; margin-bottom: 20px;">
    158         These files exist in the upload directory but are not tracked in the database.
    159     </p>
    160 
    161     {{if .Data.Orphans}}
    162     <ul style="list-style-type: disc; padding-left: 20px;">
    163       {{range .Data.Orphans}}
    164         <li style="margin-bottom: 5px; font-family: monospace;">{{.}}</li>
    165       {{end}}
    166     </ul>
    167     {{else}}
    168     <div style="padding: 20px; background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; border-radius: 4px;">
    169         <strong>✓ No orphaned files found!</strong>
    170     </div>
    171     {{end}}
    172 </div>
    173 
    174 <!-- Thumbnails Tab -->
    175 <div id="admin-content-thumbnails" style="display: none;">
    176     <h2>Thumbnail Management</h2>
    177 
    178     <!-- Sub-tab Navigation -->
    179     <div style="margin-bottom: 20px; border-bottom: 1px solid #ddd;">
    180         <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;">
    181             Missing ({{len .Data.MissingThumbnails}})
    182         </button>
    183         <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;">
    184             Regenerate
    185         </button>
    186     </div>
    187 
    188     <!-- Missing Thumbnails Sub-tab -->
    189     <div id="thumb-content-missing">
    190         <h3>Missing Thumbnails ({{len .Data.MissingThumbnails}})</h3>
    191 
    192         {{if .Data.MissingThumbnails}}
    193             <form method="post" action="/thumbnails/generate" style="margin-bottom: 20px;">
    194                 <input type="hidden" name="action" value="generate_all">
    195                 <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;">
    196                     Generate All Missing Thumbnails
    197                 </button>
    198                 <small style="color: #666; margin-left: 10px;">Uses timestamp 00:00:05 for all videos</small>
    199             </form>
    200 
    201             <div style="display: grid; grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); gap: 20px;">
    202                 {{range .Data.MissingThumbnails}}
    203                 <div style="border: 1px solid #ddd; padding: 15px; border-radius: 5px; background-color: #f8f9fa;">
    204                     <h4 style="margin-top: 0; font-size: 14px; word-break: break-word;">
    205                         <a href="/file/{{.ID}}" target="_blank">{{.Filename}}</a>
    206                     </h4>
    207                     <p style="color: #666; font-size: 12px; margin: 5px 0;">ID: {{.ID}}</p>
    208 
    209                     <video width="100%" style="max-height: 200px; background: #000; margin: 10px 0; cursor: pointer;" title="Click to capture frame">
    210                         <source src="/uploads/{{.EscapedFilename}}">
    211                     </video>
    212 
    213                     <form method="post" action="/thumbnails/generate" style="margin-top: 10px;">
    214                         <input type="hidden" name="action" value="generate_single">
    215                         <input type="hidden" name="file_id" value="{{.ID}}">
    216                         <input type="hidden" name="redirect" value="admin">
    217 
    218                         <div style="display: flex; gap: 5px; align-items: center; margin-bottom: 10px;">
    219                             <label style="font-size: 13px; white-space: nowrap;">Timestamp:</label>
    220                             <input type="text" name="timestamp" value="00:00:05" placeholder="00:00:05"
    221                                    style="flex: 1; padding: 5px; font-size: 13px; font-family: monospace;">
    222                         </div>
    223 
    224                         <button type="submit" style="background-color: #007bff; color: white; padding: 6px 12px; border: none; border-radius: 3px; font-size: 13px; cursor: pointer; width: 100%;">
    225                             Generate Thumbnail
    226                         </button>
    227                     </form>
    228                 </div>
    229                 {{end}}
    230             </div>
    231         {{else}}
    232             <div style="padding: 20px; background-color: #d4edda; color: #155724; border: 1px solid #c3e6cb; border-radius: 4px;">
    233                 <strong>✓ All videos have thumbnails!</strong>
    234             </div>
    235         {{end}}
    236     </div>
    237 
    238     <!-- Regenerate Sub-tab -->
    239     <div id="thumb-content-regenerate" style="display: none;">
    240         <h3>Regenerate Thumbnail</h3>
    241 
    242         <div style="margin-bottom: 20px; padding: 10px; background-color: #e7f3ff; border: 1px solid #b3d9ff; border-radius: 4px;">
    243             <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).
    244         </div>
    245 
    246         <form method="post" action="/thumbnails/generate" style="max-width: 500px; padding: 20px; background-color: #f8f9fa; border: 1px solid #ddd; border-radius: 5px;">
    247             <input type="hidden" name="action" value="generate_single">
    248             <input type="hidden" name="redirect" value="admin">
    249 
    250             <div style="margin-bottom: 20px;">
    251                 <label for="file_id" style="display: block; font-weight: bold; margin-bottom: 5px;">File ID:</label>
    252                 <input type="text" id="file_id" name="file_id" required
    253                        style="width: 100%; padding: 8px; font-size: 14px; font-family: monospace;"
    254                        placeholder="e.g., 312">
    255                 <small style="color: #666;">Enter the ID of the video file</small>
    256             </div>
    257 
    258             <div style="margin-bottom: 20px;">
    259                 <label for="timestamp" style="display: block; font-weight: bold; margin-bottom: 5px;">Timestamp:</label>
    260                 <input type="text" id="timestamp" name="timestamp" value="00:00:05" required
    261                        style="width: 100%; padding: 8px; font-size: 14px; font-family: monospace;"
    262                        placeholder="00:00:05">
    263                 <small style="color: #666;">Format: HH:MM:SS (e.g., 00:00:05 for 5 seconds)</small>
    264             </div>
    265 
    266             <button type="submit" style="background-color: #007bff; color: white; padding: 10px 20px; border: none; border-radius: 4px; font-size: 16px; cursor: pointer; width: 100%;">
    267                 Generate/Regenerate Thumbnail
    268             </button>
    269         </form>
    270     </div>
    271 </div>
    272 
    273 <script>window.initialAliasGroups = {{.Data.Config.TagAliases}};</script>
    274 <script src="/static/tag-alias.js" defer></script>
    275 <script src="/static/admin-tabs.js" defer></script>
    276 
    277 {{template "_footer"}}