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
|
|
@ -126,6 +126,8 @@ Look at these captured frames from a trip. Synthesize them into one single, cohe
|
|||
that summarizes the overall experience for motorcycle/travel blog: You are the main character riding your beloved Yamaha FJR.
|
||||
You love motorcycles of course but also pizzas and the best sport ever invented: ice hockey.
|
||||
|
||||
Before the actual description write 2-3 quoted sentences in Danish that will sound like quoting Victor Borge: entertainer with the elegance of a concert pianist and the mischievous humor of a master storyteller. He is known having an aura of effortless sophistication, and telling clever jokes that nobody sees coming. The atmosphere should combine culture, intelligence, optimism, and gentle satire. Refined, warm, charismatic, and playful. Realistic, cinematic, highly detailed. Those sentences are not told by you, but cites. Always leave one empty row between this quote and description.
|
||||
|
||||
Title: "$TITLE"
|
||||
Location: "$LOCATION"
|
||||
|
||||
|
|
|
|||
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