Implement order.json sorting, auto-gen, and fix map display
This commit is contained in:
parent
9c09f2d381
commit
c3f0d0dcc1
2 changed files with 64 additions and 26 deletions
88
new.php
88
new.php
|
|
@ -6,17 +6,6 @@ foreach (["videos_dir", "thumbs_dir", "uploads_dir"] as $d) if (!is_dir($config[
|
|||
if (!is_dir(__DIR__ . "/cache")) mkdir(__DIR__ . "/cache", 0775, true);
|
||||
function h($s){ return htmlspecialchars((string)$s, ENT_QUOTES, "UTF-8"); }
|
||||
function ajax_json($data){ header('Content-Type: application/json; charset=UTF-8'); echo json_encode($data, JSON_UNESCAPED_UNICODE); exit; }
|
||||
function run_gpsmap($dir) {
|
||||
file_put_contents("/var/www/html/mvlog/gps_err.log", "DEBUG: run_gpsmap called for " . $dir . "
|
||||
", FILE_APPEND);
|
||||
$stateFile = $dir . '/.movmaker-state.json';
|
||||
$state = is_file($stateFile) ? json_decode((string)file_get_contents($stateFile), true) : [];
|
||||
$output = basename((string)($state['output'] ?? ''));
|
||||
$map_filename = ($output !== '' ? pathinfo($output, PATHINFO_FILENAME) : basename($dir)) . '.png';
|
||||
$out_path = '/var/www/html/mvlog/out-dir/' . $map_filename;
|
||||
$cmd = "/usr/bin/python3 /var/www/html/mvlog/bin/gpsmap.py " . escapeshellarg($dir) . " " . escapeshellarg($out_path) . " >> /var/www/html/mvlog/gps_err.log 2>&1 &";
|
||||
$cmd = "PATH=/usr/bin:/usr/local/bin " . $cmd; shell_exec($cmd);
|
||||
}
|
||||
function slugify($s){ $s = strtolower(trim($s)); $s = preg_replace('/[^a-z0-9]+/', '-', $s); return trim($s, '-') ?: 'movie'; }
|
||||
function rrmdir($dir){ if(!is_dir($dir)) return; foreach(scandir($dir) as $f){ if($f==='.'||$f==='..') continue; $p="$dir/$f"; is_dir($p)?rrmdir($p):unlink($p);} rmdir($dir); }
|
||||
function input_dirs($base){ return glob($base.'/*', GLOB_ONLYDIR) ?: []; }
|
||||
|
|
@ -77,30 +66,77 @@ function write_data($dir, $post){
|
|||
if ($fileName !== '' && $caption !== '') $lines[] = $fileName . ': ' . $caption;
|
||||
}
|
||||
}
|
||||
file_put_contents($dir . '/data.txt', implode("\n", $lines) . "\n");
|
||||
}
|
||||
function editable_file($f){ $ext = strtolower(pathinfo((string)$f, PATHINFO_EXTENSION)); return $f !== '' && $f[0] !== '.' && $f !== 'data.txt' && in_array($ext, ['jpg','jpeg','png','webp','gif','mp4','mov','m4v','avi','mkv','webm','mp3','wav','m4a','aac','ogg','flac'], true); }
|
||||
function natural_file_compare($a, $b){ return strnatcasecmp((string)$a, (string)$b); }
|
||||
function list_files($dir){ $files = array_values(array_filter(scandir($dir), fn($f)=>editable_file($f) && is_file($dir.'/'.$f))); usort($files, 'natural_file_compare'); return $files; }
|
||||
function list_files($dir){
|
||||
$files = array_values(array_filter(scandir($dir), fn($f)=>editable_file($f) && is_file($dir.'/'.$f)));
|
||||
$orderFile = $dir . '/order.json';
|
||||
if (file_exists($orderFile)) {
|
||||
$order = json_decode(file_get_contents($orderFile), true);
|
||||
if (is_array($order)) {
|
||||
$files_map = array_flip($files);
|
||||
$sorted_files = [];
|
||||
foreach ($order as $filename) {
|
||||
if (isset($files_map[$filename])) {
|
||||
$sorted_files[] = $filename;
|
||||
unset($files_map[$filename]);
|
||||
}
|
||||
}
|
||||
return array_merge($sorted_files, array_keys($files_map));
|
||||
}
|
||||
}
|
||||
usort($files, 'natural_file_compare');
|
||||
return $files;
|
||||
}
|
||||
function media_sort_files($dir, $files){
|
||||
usort($files, function($a, $b) use ($dir) {
|
||||
$da = media_file_date($dir . '/' . $a) ?? date('Ymd', filemtime($dir . '/' . $a));
|
||||
$db = media_file_date($dir . '/' . $b) ?? date('Ymd', filemtime($dir . '/' . $b));
|
||||
return $da === $db ? natural_file_compare($a, $b) : strcmp($da, $db);
|
||||
});
|
||||
$orderFile = $dir . '/order.json';
|
||||
if (!file_exists($orderFile)) {
|
||||
$allowed = ['jpg','jpeg','png','webp','gif','mp4','mov','m4v','avi','mkv','webm'];
|
||||
$mediaFiles = array_filter($files, function($f) use ($allowed) {
|
||||
$ext = strtolower(pathinfo((string)$f, PATHINFO_EXTENSION));
|
||||
return in_array($ext, $allowed, true);
|
||||
});
|
||||
file_put_contents($orderFile, json_encode(array_values($mediaFiles), JSON_PRETTY_PRINT));
|
||||
chmod($orderFile, 0664);
|
||||
}
|
||||
return $files;
|
||||
}
|
||||
function parse_date_from_filename($path) {
|
||||
$filename = basename($path);
|
||||
if (preg_match('/(\d{8})/', $filename, $m)) {
|
||||
return $m[1];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
function media_file_date($path){
|
||||
$ext = strtolower(pathinfo((string)$path, PATHINFO_EXTENSION));
|
||||
if (in_array($ext, ["jpg","jpeg","tif","tiff"], true) && function_exists("exif_read_data")) {
|
||||
if (in_array($ext, ['jpg','jpeg','tif','tiff'], true) && function_exists('exif_read_data')) {
|
||||
$exif = @exif_read_data($path);
|
||||
foreach (["DateTimeOriginal","DateTimeDigitized","DateTime"] as $k) {
|
||||
if (!empty($exif[$k]) && preg_match("/^(\d{4}):(\d{2}):(\d{2})\s*(\d{2}):(\d{2}):(\d{2})/", (string)$exif[$k], $m)) return $m[1].$m[2].$m[3].$m[4].$m[5].$m[6];
|
||||
foreach (['DateTimeOriginal','DateTimeDigitized','DateTime'] as $k) {
|
||||
if (!empty($exif[$k]) && preg_match('/^(\d{4}):(\d{2}):(\d{2})/', (string)$exif[$k], $m)) return "$m[1]$m[2]$m[3]";
|
||||
}
|
||||
}
|
||||
if (preg_match("/(\d{8})[_-]?(\d{6})?/", basename($path), $m)) {
|
||||
return $m[1] . ($m[2] ?? "000000");
|
||||
if (in_array($ext, ['mp4','mov','m4v','avi','mkv','webm'], true)) {
|
||||
$ffprobe = trim((string)shell_exec('command -v ffprobe 2>/dev/null'));
|
||||
if ($ffprobe !== '') {
|
||||
$json = shell_exec(escapeshellarg($ffprobe).' -v quiet -print_format json -show_entries format_tags=creation_time:stream_tags=creation_time '.escapeshellarg($path).' 2>/dev/null');
|
||||
$data = json_decode((string)$json, true);
|
||||
$candidates = [];
|
||||
if (is_array($data['format']['tags'] ?? null)) $candidates[] = $data['format']['tags']['creation_time'] ?? '';
|
||||
foreach (($data['streams'] ?? []) as $stream) if (is_array($stream['tags'] ?? null)) $candidates[] = $stream['tags']['creation_time'] ?? '';
|
||||
foreach ($candidates as $value) {
|
||||
if (preg_match('/^(\d{4})-(\d{2})-(\d{2})/', (string)$value, $m)) return "$m[1]$m[2]$m[3]";
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
return parse_date_from_filename($path);
|
||||
}
|
||||
function input_dir_date_from_media($dir){
|
||||
$dates = [];
|
||||
|
|
@ -153,7 +189,7 @@ for dirpath, dirnames, filenames in os.walk(root):
|
|||
entries.sort()
|
||||
print(hashlib.sha256(json.dumps(entries, ensure_ascii=False, separators=(',', ':')).encode('utf-8')).hexdigest())
|
||||
PY;
|
||||
$cmd = '/usr/bin/python3 -c ' . escapeshellarg($script) . ' ' . escapeshellarg($dir);
|
||||
$cmd = 'python3 -c ' . escapeshellarg($script) . ' ' . escapeshellarg($dir);
|
||||
$output = trim(shell_exec($cmd) ?? '');
|
||||
return $output !== '' ? $output : '';
|
||||
}
|
||||
|
|
@ -186,6 +222,7 @@ function load_input_dir_cache($dirs){
|
|||
}
|
||||
}
|
||||
if (array_diff(array_keys($oldItems), array_keys($items))) $changed = true;
|
||||
if ($changed) file_put_contents($cacheFile, json_encode(['version'=>1,'generated_at'=>date('c'),'items'=>$items], JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT), LOCK_EX);
|
||||
return $items;
|
||||
}
|
||||
function sort_input_dirs_by_metadata_date(&$dirs, $dirInfo){
|
||||
|
|
@ -243,15 +280,15 @@ function set_input_dir_preview($dir, $preview){
|
|||
if (!is_array($state)) $state = [];
|
||||
$state['preview'] = (bool)$preview;
|
||||
$state['preview_updated_at'] = gmdate('c');
|
||||
file_put_contents($stateFile, json_encode($state, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n");
|
||||
file_put_contents($stateFile, json_encode($state, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "
|
||||
");
|
||||
chmod($stateFile, 0664);
|
||||
}
|
||||
function input_dir_visible($dir){ return !is_file($dir . '/.mvlog-hidden'); }
|
||||
function set_input_dir_visible($dir, $visible){
|
||||
$path = $dir . '/.mvlog-hidden';
|
||||
if ($visible) { if (is_file($path)) unlink($path); }
|
||||
else { file_put_contents($path, "hidden
|
||||
"); chmod($path, 0664); }
|
||||
else { file_put_contents($path, "hidden\n"); chmod($path, 0664); }
|
||||
}
|
||||
function input_dir_state($dir){
|
||||
$stateFile = $dir . '/.movmaker-state.json';
|
||||
|
|
@ -353,7 +390,6 @@ try {
|
|||
if (!rename($tmpDir, $dir)) { rrmdir($tmpDir); throw new RuntimeException('Cannot create input directory.'); }
|
||||
chmod($dir, 02775);
|
||||
write_data($dir, $_POST);
|
||||
run_gpsmap($dir);
|
||||
set_input_dir_enabled($dir, false);
|
||||
set_input_dir_preview($dir, false);
|
||||
set_input_dir_visible($dir, false);
|
||||
|
|
@ -423,6 +459,7 @@ try {
|
|||
include_once __DIR__ . '/lib/send_push.php';
|
||||
try_send_show_notification(basename($dir), $dir, __DIR__, '/var/log/mvlog_notify.log');
|
||||
} else {
|
||||
error_log("[mvlog] send_push helper missing, cannot send notification for " . basename($dir) . "\n", 3, '/var/log/mvlog_notify.log');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -445,7 +482,6 @@ try {
|
|||
write_data($dir, $_POST);
|
||||
save_uploads('media', $dir, $allowedMedia);
|
||||
save_uploads('audio', $dir, $allowedAudio);
|
||||
run_gpsmap($dir);
|
||||
if (!empty($_POST['ajax'])) ajax_json(['ok'=>true, 'message'=>'Updated input directory: in-dir/' . basename($dir), 'dir'=>basename($dir)]);
|
||||
header('Location: new.php?tab=edit');
|
||||
exit;
|
||||
|
|
@ -519,7 +555,7 @@ $runningJobs = active_worker_jobs($config);
|
|||
<?php if($err): ?><div class="err"><?=h($err)?></div><?php endif; ?>
|
||||
|
||||
<?php if($tab==='videos'): ?><section><h2>Videos without input dir</h2><?php if(!$orphanVideos): ?><p>No orphan videos.</p><?php endif; ?><div class="admin-list"><?php foreach($orphanVideosPage as $v): $vn=basename($v); ?><form method="post" class="admin-item" onsubmit="return confirm('Delete this generated video?') js-ajax-form"><div><strong><?=h($vn)?></strong><br><span><?=h(round(filesize($v)/1048576,1))?> MB</span></div><input type="hidden" name="action" value="delete_video"><input type="hidden" name="video" value="<?=h($vn)?>"><button type="submit">Delete video</button></form><?php endforeach; ?></div><?=page_links('videos',$videoPage,$videoPages)?></section><?php endif; ?>
|
||||
<?php if($tab==='edit' && !$editDir): ?><section><h2>Existing input dirs</h2><?php if(!$dirs): ?><p>No input directories yet.</p><?php endif; ?><div class="admin-list video-list"><?php foreach($dirsPage as $d): $runStatus=input_dir_status($d); $running=input_dir_running($d); $enabled=input_dir_enabled($d); $preview=input_dir_preview($d); $state=input_dir_state($d); $fullOutput=basename((string)($state['output'] ?? '')); $previewOutput=basename((string)($state['preview_output'] ?? '')); $hasFullVideo=$fullOutput !== '' && is_file($config['videos_dir'].'/'.$fullOutput); $hasPreviewVideo=$previewOutput !== '' && is_file($config['videos_dir'].'/'.$previewOutput); $displayOutput=($preview && $hasPreviewVideo) ? $previewOutput : ($hasFullVideo ? $fullOutput : ($hasPreviewVideo ? $previewOutput : '')); $hasVideo=$displayOutput !== ''; $displayVideoPath=$hasVideo ? $config['videos_dir'].'/'.$displayOutput : ''; $previewVideo=$hasVideo && $displayOutput === $previewOutput; $canShow=$hasFullVideo && !$preview; $visible=$canShow && input_dir_visible($d); $info=$dirInfo[basename($d)] ?? input_dir_info($d); $data=read_data($d); $meta=cached_video_metadata($displayOutput, $data); $currentSignature=$info['signature'] ?? ''; $fullFingerprint=is_array($state)?(string)($state['fingerprint'] ?? ''):''; $previewFingerprint=is_array($state)?(string)($state['preview_fingerprint'] ?? ''):''; $editedSinceRender=$hasFullVideo && $currentSignature !== '' && $fullFingerprint !== '' && $currentSignature !== $fullFingerprint; $editedSincePreview=!$hasFullVideo && $previewVideo && $currentSignature !== '' && $previewFingerprint !== '' && $currentSignature !== $previewFingerprint; $staleLabel=$editedSinceRender ? 'Edited since render' : ($editedSincePreview ? 'Edited since preview' : ''); ?><article class="video-row admin-video-row<?= $visible ? ' shown' : '' ?>" data-job="<?=h(basename($d))?>"><div><?php if($hasVideo): ?><div class="video-wrapper"><video controls preload="metadata" src="<?=h($config['public_videos'].'/'.rawurlencode($displayOutput))?>"></video> <?php $map_n = ($displayOutput != "" ? pathinfo($displayOutput, PATHINFO_FILENAME) : basename($d)) . ".png"; if(is_file($config["videos_dir"]."/".$map_n)): ?><img class="map-image" src="<?=h($config["public_videos"]."/".rawurlencode($map_n))?>" alt="Map"><?php endif; ?></div><?php else: ?><div class="video-placeholder"><img src="assets/img/moto_travel.png" alt=""><span>No video yet</span></div><?php endif; ?></div><div class="video-info"><div class="admin-row-top"><div class="admin-switches">
|
||||
<?php if($tab==='edit' && !$editDir): ?><section><h2>Existing input dirs</h2><?php if(!$dirs): ?><p>No input directories yet.</p><?php endif; ?><div class="admin-list video-list"><?php foreach($dirsPage as $d): $runStatus=input_dir_status($d); $running=input_dir_running($d); $enabled=input_dir_enabled($d); $preview=input_dir_preview($d); $state=input_dir_state($d); $fullOutput=basename((string)($state['output'] ?? '')); $previewOutput=basename((string)($state['preview_output'] ?? '')); $hasFullVideo=$fullOutput !== '' && is_file($config['videos_dir'].'/'.$fullOutput); $hasPreviewVideo=$previewOutput !== '' && is_file($config['videos_dir'].'/'.$previewOutput); $displayOutput=($preview && $hasPreviewVideo) ? $previewOutput : ($hasFullVideo ? $fullOutput : ($hasPreviewVideo ? $previewOutput : '')); $hasVideo=$displayOutput !== ''; $displayVideoPath=$hasVideo ? $config['videos_dir'].'/'.$displayOutput : ''; $previewVideo=$hasVideo && $displayOutput === $previewOutput; $canShow=$hasFullVideo && !$preview; $visible=$canShow && input_dir_visible($d); $info=$dirInfo[basename($d)] ?? input_dir_info($d); $data=read_data($d); $meta=cached_video_metadata($displayOutput, $data); $currentSignature=$info['signature'] ?? ''; $fullFingerprint=is_array($state)?(string)($state['fingerprint'] ?? ''):''; $previewFingerprint=is_array($state)?(string)($state['preview_fingerprint'] ?? ''):''; $editedSinceRender=$hasFullVideo && $currentSignature !== '' && $fullFingerprint !== '' && $currentSignature !== $fullFingerprint; $editedSincePreview=!$hasFullVideo && $previewVideo && $currentSignature !== '' && $previewFingerprint !== '' && $currentSignature !== $previewFingerprint; $staleLabel=$editedSinceRender ? 'Edited since render' : ($editedSincePreview ? 'Edited since preview' : ''); ?><article class="video-row admin-video-row<?= $visible ? ' shown' : '' ?>" data-job="<?=h(basename($d))?>"><div><?php if($hasVideo): ?><video controls preload="metadata" src="<?=h($config['public_videos'].'/'.rawurlencode($displayOutput))?>"></video> <?php $map_n = ($displayOutput != "" ? pathinfo($displayOutput, PATHINFO_FILENAME) : basename($d)) . ".png"; if(is_file($config["videos_dir"]."/".$map_n)): ?><img class="map-image" src="<?=h($config["public_videos"]."/".rawurlencode($map_n))?>" alt="Map"><?php endif; ?><?php else: ?><div class="video-placeholder"><img src="assets/img/moto_travel.png" alt=""><span>No video yet</span></div><?php endif; ?></div><div class="video-info"><div class="admin-row-top"><div class="admin-switches">
|
||||
<form method="post" class="inline-form switch-form" data-switch="preview">
|
||||
<input type="hidden" name="action" value="set_preview">
|
||||
<input type="hidden" name="dir" value="<?=h(basename($d))?>">
|
||||
|
|
@ -550,7 +586,7 @@ $runningJobs = active_worker_jobs($config);
|
|||
<?php if($hasVideo): ?><time class="admin-time<?= $staleLabel ? ' admin-time-stale' : '' ?>" title="<?=h($staleLabel ?: 'Video created at')?>"><?=h(date('d.m.Y H:i', filemtime($displayVideoPath)))?></time><?php endif; ?>
|
||||
</div><div class="admin-actions"><?php if($running): ?><span class="button disabled" title="Rendering now" data-edit-action="1">Rendering</span><?php else: ?><a class="button" href="?edit=<?=rawurlencode(basename($d))?>" data-edit-action="1" data-edit-href="?edit=<?=rawurlencode(basename($d))?>">Edit</a><?php endif; ?></div></div><h2><?=h($meta['title'] ?: ($info['title'] ?? basename($d)))?></h2><p class="meta"><?php if($meta['date']): ?><span><?=h($meta['date'])?></span><?php endif; ?><?php if($meta['location']): ?><span><?=h($meta['location'])?></span><?php endif; ?><?php if(!$hasVideo): ?><span>No video</span><?php endif; ?><?php if($previewVideo): ?><span>Preview video</span><?php endif; ?></p><?php if($meta['description']): ?><p class="description"><?=nl2br(h($meta['description']), false)?></p><?php endif; ?><p class="details"><?=h(basename($d))?> · <?=h($info['file_count'] ?? count(list_files($d)))?> files</p></div></article><?php endforeach; ?></div><?=page_links('edit',$editPage,$editPages)?></section><?php endif; ?>
|
||||
<?php if($tab==='edit' && $editDir && $editRunning): ?><section><h2>Edit input dir</h2><p><code>in-dir/<?=h(basename($editDir))?></code></p><div class="err">This input directory is <?=h($editStatus)?>. Editing is disabled until the job completes.</div></section><?php endif; ?>
|
||||
<?php if($tab==='edit' && $editDir && !$editRunning): ?><section><h2>Edit input dir</h2><p><code>in-dir/<?=h(basename($editDir))?></code></p><form method="post" enctype="multipart/form-data" id="edit-form"><input type="hidden" name="action" value="update"><input type="hidden" name="dir" value="<?=h(basename($editDir))?>"><label>Title<input name="title" value="<?=h($editData['title'])?>"></label><label>Date<input name="date" value="<?=h($editData['date'])?>"></label><label>Place<input name="place" value="<?=h($editData['place'])?>"></label><label>Description<textarea name="description" maxlength="5000" data-counter="description-counter-edit"><?=h($editData['description'])?></textarea><small id="description-counter-edit" class="counter"></small></label><label>Add images / videos<input type="file" name="media[]" multiple accept="image/*,video/*"></label><label>Add audio<input type="file" name="audio[]" multiple accept="audio/*"></label><h3>Files and captions</h3><div class="file-list"><?php foreach($editFiles as $f): $ext=strtolower(pathinfo($f, PATHINFO_EXTENSION)); $fileUrl='in-dir/'.rawurlencode(basename($editDir)).'/'.rawurlencode($f); ?><div class="caption-row"><div class="preview"><?php if(in_array($ext,['jpg','jpeg','png','webp','gif'])): ?><img src="<?=h($fileUrl)?>" alt=""><?php elseif(in_array($ext,['mp4','mov','m4v','webm'])): ?><video src="<?=h($fileUrl)?>" controls preload="metadata"></video><a class="download-link" href="<?=h($fileUrl)?>" download>Download</a><?php else: ?><span><?=h(strtoupper($ext ?: 'FILE'))?></span><?php endif; ?></div><div class="caption-fields"><strong><?=h($f)?></strong><?php if(in_array($ext,['jpg','jpeg','png','webp','gif','mp4','mov','m4v','webm'])): ?><input type="hidden" name="caption_files[]" value="<?=h($f)?>"><textarea name="captions[]" placeholder="Optional caption for this file"><?=h($editData['captions'][$f] ?? '')?></textarea><?php if(in_array($ext,['mp4','mov','m4v','webm'])): ?><label class="checkbox-label"><input type="checkbox" name="use_audio_files[]" value="<?=h($f)?>" <?=!empty($editData['video_audio'][$f])?'checked':''?>> <span>Use video file audio</span></label><?php endif; ?><?php else: ?><small>No caption for audio files</small><?php endif; ?></div><button type="button" onclick="deleteFile(<?=h(json_encode($f))?>)">Remove</button></div><?php endforeach; ?></div><button type="submit">Save changes</button></form><form method="post" id="delete-file-form" style="display:none"><input type="hidden" name="action" value="delete_file"><input type="hidden" name="dir" value="<?=h(basename($editDir))?>"><input type="hidden" name="file" id="delete-file-name" value=""></form><form method="post" onsubmit="return confirm(\'Delete this input directory\?\')" id="delete-dir-form""><input type="hidden" name="action" value="delete_dir"><input type="hidden" name="dir" value="<?=h(basename($editDir))?>"><label class="checkbox-label"><input type="checkbox" name="delete_output" value="1"> <span>Also delete generated video, if any</span></label><button class="danger" type="submit">Delete input dir</button></form></section><?php endif; ?>
|
||||
<?php if($tab==='edit' && $editDir && !$editRunning): ?><section><h2>Edit input dir</h2><p><code>in-dir/<?=h(basename($editDir))?></code></p><form method="post" enctype="multipart/form-data" id="edit-form"><input type="hidden" name="action" value="update"><input type="hidden" name="dir" value="<?=h(basename($editDir))?>"><label>Title<input name="title" value="<?=h($editData['title'])?>"></label><label>Date<input name="date" value="<?=h($editData['date'])?>"></label><label>Place<input name="place" value="<?=h($editData['place'])?>"></label><label>Description<textarea name="description" maxlength="5000" data-counter="description-counter-edit"><?=h($editData['description'])?></textarea><small id="description-counter-edit" class="counter"></small></label><label>Add images / videos<input type="file" name="media[]" multiple accept="image/*,video/*"></label><label>Add audio<input type="file" name="audio[]" multiple accept="audio/*"></label><h3>Files and captions</h3><div class="file-list"><?php foreach($editFiles as $f): $ext=strtolower(pathinfo($f, PATHINFO_EXTENSION)); $fileUrl='in-dir/'.rawurlencode(basename($editDir)).'/'.rawurlencode($f); ?><div class="caption-row"><div class="preview"><?php if(in_array($ext,['jpg','jpeg','png','webp','gif'])): ?><img src="<?=h($fileUrl)?>" alt=""><?php elseif(in_array($ext,['mp4','mov','m4v','webm'])): ?><video src="<?=h($fileUrl)?>" controls preload="metadata"></video> <?php $map_n = ($displayOutput != "" ? pathinfo($displayOutput, PATHINFO_FILENAME) : basename($d)) . ".png"; if(is_file($config["videos_dir"]."/".$map_n)): ?><img class="map-image" src="<?=h($config["public_videos"]."/".rawurlencode($map_n))?>" alt="Map"><?php endif; ?><a class="download-link" href="<?=h($fileUrl)?>" download>Download</a><?php else: ?><span><?=h(strtoupper($ext ?: 'FILE'))?></span><?php endif; ?></div><div class="caption-fields"><strong><?=h($f)?></strong><?php if(in_array($ext,['jpg','jpeg','png','webp','gif','mp4','mov','m4v','webm'])): ?><input type="hidden" name="caption_files[]" value="<?=h($f)?>"><textarea name="captions[]" placeholder="Optional caption for this file"><?=h($editData['captions'][$f] ?? '')?></textarea><?php if(in_array($ext,['mp4','mov','m4v','webm'])): ?><label class="checkbox-label"><input type="checkbox" name="use_audio_files[]" value="<?=h($f)?>" <?=!empty($editData['video_audio'][$f])?'checked':''?>> <span>Use video file audio</span></label><?php endif; ?><?php else: ?><small>No caption for audio files</small><?php endif; ?></div><button type="button" onclick="deleteFile(<?=h(json_encode($f))?>)">Remove</button></div><?php endforeach; ?></div><button type="submit">Save changes</button></form><form method="post" id="delete-file-form" style="display:none"><input type="hidden" name="action" value="delete_file"><input type="hidden" name="dir" value="<?=h(basename($editDir))?>"><input type="hidden" name="file" id="delete-file-name" value=""></form><form method="post" onsubmit="return confirm(\'Delete this input directory\?\')" id="delete-dir-form""><input type="hidden" name="action" value="delete_dir"><input type="hidden" name="dir" value="<?=h(basename($editDir))?>"><label class="checkbox-label"><input type="checkbox" name="delete_output" value="1"> <span>Also delete generated video, if any</span></label><button class="danger" type="submit">Delete input dir</button></form></section><?php endif; ?>
|
||||
<?php if($tab==='new'): ?><section><h2>Add new movie input</h2><form method="post" enctype="multipart/form-data" id="new-form"><input type="hidden" name="action" value="create"><label>Title*<input name="title" required></label><label>Date<input name="date" placeholder="2026-05-25"></label><label>Place<input name="place"></label><label>Description<textarea name="description" maxlength="5000" data-counter="description-counter-new"></textarea><small id="description-counter-new" class="counter"></small></label><label>Images / videos*<input type="file" name="media[]" multiple required accept="image/*,video/*"></label><label>Audio (optional)<input type="file" name="audio[]" multiple accept="audio/*"></label><button type="submit">Create input-dir</button></form></section><?php endif; ?>
|
||||
<script>
|
||||
function deleteFile(name){
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue