New article fix, and button cosmetics
This commit is contained in:
parent
11877b63b1
commit
67af29210e
1 changed files with 14 additions and 13 deletions
27
admin.php
27
admin.php
|
|
@ -264,7 +264,7 @@ function write_article_id($dir, $id){
|
|||
$idFile = rtrim((string)$dir, '/').'/'.ARTICLE_ID_FILE;
|
||||
$tmp = $idFile . '.tmp.' . bin2hex(random_bytes(4));
|
||||
if (file_put_contents($tmp, $id . "\n", LOCK_EX) === false) throw new RuntimeException('Cannot write article id.');
|
||||
chmod($tmp, 0664);
|
||||
@chmod($tmp, 0664);
|
||||
if (!rename($tmp, $idFile)) { @unlink($tmp); throw new RuntimeException('Cannot save article id.'); }
|
||||
}
|
||||
function ensure_article_id($dir, &$seenIds = null){
|
||||
|
|
@ -734,7 +734,7 @@ function input_dir_running($dir){
|
|||
function input_dir_enabled($dir){ return is_file($dir . '/.movmaker-enabled'); }
|
||||
function set_input_dir_enabled($dir, $enabled){
|
||||
$path = $dir . '/.movmaker-enabled';
|
||||
if ($enabled) { file_put_contents($path, "enabled\n"); chmod($path, 0664); }
|
||||
if ($enabled) { file_put_contents($path, "enabled\n"); @chmod($path, 0664); }
|
||||
elseif (is_file($path)) unlink($path);
|
||||
}
|
||||
function input_dir_preview($dir){
|
||||
|
|
@ -746,7 +746,7 @@ function input_dir_preview($dir){
|
|||
}
|
||||
function set_input_dir_preview($dir, $preview){
|
||||
$path = $dir . '/.movmaker-preview';
|
||||
if ($preview) { file_put_contents($path, "preview\n"); chmod($path, 0664); }
|
||||
if ($preview) { file_put_contents($path, "preview\n"); @chmod($path, 0664); }
|
||||
elseif (is_file($path)) unlink($path);
|
||||
$stateFile = $dir . '/.movmaker-state.json';
|
||||
$state = is_file($stateFile) ? json_decode((string)file_get_contents($stateFile), true) : [];
|
||||
|
|
@ -755,18 +755,18 @@ function set_input_dir_preview($dir, $preview){
|
|||
$state['preview'] = (bool)$preview;
|
||||
$state['preview_updated_at'] = gmdate('c');
|
||||
file_put_contents($stateFile, json_encode($state, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n");
|
||||
chmod($stateFile, 0664);
|
||||
@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\n"); chmod($path, 0664); }
|
||||
else { file_put_contents($path, "hidden\n"); @chmod($path, 0664); }
|
||||
}
|
||||
function input_dir_map_hidden($dir){ return is_file($dir . '/' . MAP_HIDDEN_FILE); }
|
||||
function set_input_dir_map_hidden($dir, $hidden){
|
||||
$path = $dir . '/' . MAP_HIDDEN_FILE;
|
||||
if ($hidden) { file_put_contents($path, "hide-map\n"); chmod($path, 0664); }
|
||||
if ($hidden) { file_put_contents($path, "hide-map\n"); @chmod($path, 0664); }
|
||||
elseif (is_file($path)) unlink($path);
|
||||
}
|
||||
function is_image_media_file($name){
|
||||
|
|
@ -814,7 +814,7 @@ function ensure_state_article_id($dir){
|
|||
if (($state['article_id'] ?? '') !== $articleId) {
|
||||
$state['article_id'] = $articleId;
|
||||
file_put_contents($stateFile, json_encode($state, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT) . "\n");
|
||||
chmod($stateFile, 0664);
|
||||
@chmod($stateFile, 0664);
|
||||
}
|
||||
return $articleId;
|
||||
}
|
||||
|
|
@ -958,7 +958,7 @@ try {
|
|||
$tmpSlug = '.upload-' . date('YmdHis') . '-' . bin2hex(random_bytes(4));
|
||||
$tmpDir = $config['uploads_dir'] . '/' . $tmpSlug;
|
||||
if (!mkdir($tmpDir, 0775, true)) throw new RuntimeException('Cannot create temporary input directory.');
|
||||
chmod($tmpDir, 02775);
|
||||
@chmod($tmpDir, 02775);
|
||||
$media = save_uploads('media', $tmpDir, $allowedMedia);
|
||||
if (!$media) { rrmdir($tmpDir); throw new RuntimeException('Upload at least one image or video.'); }
|
||||
save_uploads('audio', $tmpDir, $allowedAudio);
|
||||
|
|
@ -967,7 +967,7 @@ try {
|
|||
$dir = unique_input_dir($config['uploads_dir'], $slug);
|
||||
$slug = basename($dir);
|
||||
if (!rename($tmpDir, $dir)) { rrmdir($tmpDir); throw new RuntimeException('Cannot create input directory.'); }
|
||||
chmod($dir, 02775);
|
||||
@chmod($dir, 02775);
|
||||
$articleId = ensure_article_id($dir);
|
||||
write_data($dir, $_POST);
|
||||
set_input_dir_enabled($dir, false);
|
||||
|
|
@ -1356,8 +1356,8 @@ $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="?id=<?=rawurlencode(read_article_id($d))?>&edit=<?=rawurlencode(basename($d))?>" data-edit-action="1" data-edit-href="?id=<?=rawurlencode(read_article_id($d))?>&edit=<?=rawurlencode(basename($d))?>">Edit</a><?php endif; ?></div></div><?php $articleIdForLink = read_article_id($d); $titleText = h($meta['title'] ?: ($info['title'] ?? basename($d))); ?><h2><?php if(article_id_is_valid($articleIdForLink)): ?><a href="index.php?id=<?=rawurlencode($articleIdForLink)?>"><?= $titleText ?></a><?php else: ?><?= $titleText ?><?php endif; ?></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(!empty($meta['teaser'])): ?><p class="description-teaser"><?=h((string)$meta['teaser'])?></p><?php endif; ?><?php if($meta['description']): ?><p class="description"><?=nl2br(h($meta['description']), false)?></p><?php endif; ?><?php if(!empty($meta['quote_da'])): ?><p class="description-quote">“<?=h(trim((string)$meta['quote_da'], "\"“”"))?>”</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))?>"><input type="hidden" name="id" value="<?=h(ensure_article_id($editDir))?>"><label>Title<input name="title" value="<?=h($editData['title'])?>"></label><label>Teaser<input name="teaser" value="<?=h($editData['teaser'])?>" maxlength="240"></label><label>Danish quote<input name="quote_da" value="<?=h($editData['quote_da'])?>" maxlength="280"></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><div class="file-actions" style="display:flex;gap:.45rem;flex-wrap:wrap;align-self:start"><?php if(in_array($ext,['jpg','jpeg','png','webp','gif'])): ?><button type="button" class="set-thumb-btn" onclick="setThumb(<?=h(json_encode($f))?>)">Set as thumb</button><?php endif; ?><button type="button" onclick="deleteFile(<?=h(json_encode($f))?>)">Remove</button></div></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="id" value="<?=h(ensure_article_id($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))?>"><input type="hidden" name="id" value="<?=h(ensure_article_id($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>Teaser<input name="teaser" maxlength="240"></label><label>Danish quote<input name="quote_da" maxlength="280"></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; ?>
|
||||
<?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))?>"><input type="hidden" name="id" value="<?=h(ensure_article_id($editDir))?>"><label>Title<input name="title" value="<?=h($editData['title'])?>"></label><label>Teaser<input name="teaser" value="<?=h($editData['teaser'])?>" maxlength="240"></label><label>Danish quote<input name="quote_da" value="<?=h($editData['quote_da'])?>" maxlength="280"></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><div class="file-actions" style="display:flex;gap:.45rem;flex-wrap:wrap;align-self:start"><?php if(in_array($ext,['jpg','jpeg','png','webp','gif'])): ?><button type="button" class="set-thumb-btn" onclick="setThumb(<?=h(json_encode($f))?>)">Set as thumb</button><?php endif; ?><button type="button" onclick="deleteFile(<?=h(json_encode($f))?>)">Remove</button></div></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="id" value="<?=h(ensure_article_id($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))?>"><input type="hidden" name="id" value="<?=h(ensure_article_id($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 Article</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>Teaser<input name="teaser" maxlength="240"></label><label>Danish quote<input name="quote_da" maxlength="280"></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</button></form></section><?php endif; ?>
|
||||
<script>
|
||||
function deleteFile(name){
|
||||
if(!confirm('Remove this file?')) return;
|
||||
|
|
@ -1686,7 +1686,8 @@ function handleAjaxFormSubmit(form, redirectTab) {
|
|||
|
||||
let timer = 0;
|
||||
let success = false;
|
||||
const useBusyOverlay = action === 'update';
|
||||
const useBusyOverlay = action === 'update' || action === 'create';
|
||||
const busyLabel = action === 'create' ? 'Creating input directory…' : 'Saving changes…';
|
||||
if (submit) {
|
||||
submit.dataset.label = submit.dataset.label || submit.textContent.trim() || 'Submit';
|
||||
submit.disabled = true;
|
||||
|
|
@ -1701,7 +1702,7 @@ function handleAjaxFormSubmit(form, redirectTab) {
|
|||
}, 320);
|
||||
}
|
||||
}
|
||||
if (useBusyOverlay) showThumbBusy('Saving changes…');
|
||||
if (useBusyOverlay) showThumbBusy(busyLabel);
|
||||
|
||||
try{
|
||||
const res = await fetch('admin.php', { method: 'POST', body: data, credentials: 'same-origin', headers: { 'Accept': 'application/json' }});
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue