• File: edit.php
  • Full Path: /home/daemondevin/public_html/portableapps/lib/vendor/edit.php
  • Date Modified: 10/17/2026 7:00 PM
  • File size: 8.05 KB
  • MIME-type: text/x-php
  • Charset: utf-8
<?php
defined('TS_ROOT') or exit();
// Variables: $post (array|null), $csrf
$isNew = $post === null;
$p = $post ?? ['slug' => '', 'title' => '', 'date' => date('Y-m-d H:i'), 'status' => 'draft', 'type' => 'post', 'tags' => [], 'description' => '', 'image' => '', 'format' => 'standard', 'media' => [], 'body' => ''];
$fmt = TSMedia::format($p['format'] ?? '');
$mediaList = (array) ($p['media'] ?? []);
$cfgJson = json_encode([
    'csrf' => $csrf, 'save' => ts_url('admin/save'), 'delete' => ts_url('admin/delete'), 'upload' => ts_url('admin/upload'), 'render' => ts_url('admin/render'),
    'list' => ts_url('admin'), 'siteUrl' => ts_abs(), 'limit' => ts_upload_limit(), 'allowHtml' => (bool) ts_cfg('allow_html'), 'original' => $isNew ? '' : $p['slug'], 'status' => $p['status'],
    'body' => $p['body'], 'key' => 'tsblog-draft-' . ($isNew ? 'new' : $p['slug']),
], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG | JSON_HEX_AMP);
?>
<script type="application/json" id="ts-config"><?= $cfgJson ?></script>

<form id="post-form" class="editor" autocomplete="off" novalidate>
  <header class="ed-bar">
    <a class="icon-btn" href="<?= e(ts_url('admin')) ?>" title="All posts" aria-label="Back to all posts"><i class="fas fa-arrow-left"></i></a>
    <span id="state" class="state" role="status" aria-live="polite"><?= $isNew ? 'New post' : e($p['status'] === 'draft' ? 'Draft' : 'Published') ?></span>
    <span class="grow"></span>
    <div class="seg" role="group" aria-label="Editor mode">
      <button type="button" data-mode="rich" title="Write with a toolbar">Simple</button>
      <button type="button" data-mode="markdown" class="on" title="Write in Markdown">Markdown</button>
    </div>
    <button type="button" class="icon-btn" id="btn-focus" title="Focus mode (Esc to leave)" aria-label="Focus mode"><i class="fas fa-expand"></i></button>
    <button type="button" class="icon-btn" id="btn-details" title="Post settings" aria-label="Post settings" aria-expanded="false"><i class="fas fa-sliders"></i></button>
    <button type="button" class="icon-btn" data-theme-toggle title="Toggle dark mode" aria-label="Toggle dark mode"><i class="fas fa-circle-half-stroke"></i></button>
    <button type="button" class="btn" id="btn-save"><?= $p['status'] === 'published' ? 'Update' : 'Save draft' ?></button>
    <button type="button" class="btn primary" id="btn-publish"><?= $p['status'] === 'published' ? 'Unpublish' : 'Publish' ?></button>
  </header>

  <div class="ed-main">
    <div class="paper">
      <label class="sr" for="f-title">Title</label>
      <textarea id="f-title" class="title" rows="1" placeholder="Title" maxlength="200"><?= e($p['title']) ?></textarea>
      <textarea id="f-body" class="manual" data-plugin-markdowneditor></textarea>
      <div id="f-rich" class="manual" hidden></div>
    </div>

    <aside id="details" class="details" hidden aria-label="Post settings">
      <h2>Post settings</h2>
      <label>Address
        <span class="slug"><i><?= e(preg_replace('#^https?://#', '', ts_abs())) ?>/</i><input id="f-slug" type="text" value="<?= e($p['slug']) ?>" placeholder="auto-from-title" spellcheck="false"></span>
      </label>
      <div class="field">
        <span class="lbl" id="date-lbl">Publish date</span>
        <input id="f-date" type="hidden" value="<?= e(date('Y-m-d\TH:i', strtotime($p['date']))) ?>">
        <div class="date-row">
          <button type="button" class="btn" id="date-toggle" aria-expanded="false" aria-controls="date-pop" aria-describedby="date-hint"><i class="fas fa-calendar-days"></i> <span id="date-label"></span></button>
          <input id="f-time" type="text" aria-label="Publish time" value="<?= e(date('H:i', strtotime($p['date']))) ?>" data-plugin-timepicker class="manual">
        </div>
        <div id="date-pop" class="date-pop" hidden>
          <div id="f-cal" class="manual"></div>
          <div class="date-actions"><button type="button" class="link-btn" id="date-now">Now</button><button type="button" class="link-btn" id="date-close">Done</button></div>
        </div>
        <small class="muted" id="date-hint"></small>
      </div>
      <div class="field"><span class="lbl" id="lbl-f-type">Type</span>
        <div data-plugin-select class="manual"><select id="f-type">
          <option value="post"<?= $p['type'] === 'post' ? ' selected' : '' ?>>Post (appears in the feed)</option>
          <option value="page"<?= $p['type'] === 'page' ? ' selected' : '' ?>>Page (appears in the menu)</option>
        </select></div></div>
      <div class="field" id="format-field"<?= $p['type'] === 'page' ? ' hidden' : '' ?>><span class="lbl" id="lbl-f-format">Entry format</span>
        <div data-plugin-select class="manual"><select id="f-format">
<?php foreach (TSMedia::FORMATS as $k => $label): ?>
          <option value="<?= e($k) ?>"<?= $fmt === $k ? ' selected' : '' ?>><?= e($label) ?></option>
<?php endforeach; ?>
        </select></div></div>
      <div class="field" id="media-field"<?= $p['type'] === 'page' || $fmt === 'standard' ? ' hidden' : '' ?>>
        <span class="lbl" id="media-label">Media</span>
        <textarea id="f-media" rows="4" spellcheck="false" aria-labelledby="media-label"><?= e(implode("\n", $mediaList)) ?></textarea>
        <small class="muted" id="media-hint"></small>
        <button type="button" class="btn" id="media-upload" hidden><i class="fas fa-images"></i> Add pictures</button>
        <input type="file" id="media-input" accept="image/jpeg,image/png,image/gif,image/webp" multiple hidden>
      </div>
      <label>Tags
        <input id="f-tags" type="text" class="manual" value="<?= e(implode(', ', $p['tags'])) ?>">
      </label>
      <label>Summary for search engines
        <textarea id="f-desc" rows="3" maxlength="320" placeholder="One or two sentences. Leave empty to use the opening paragraph."><?= e($p['description']) ?></textarea>
        <small class="muted"><span id="desc-count">0</span> / 160 characters recommended</small>
      </label>
      <div class="field">
        <span class="lbl">Cover image</span>
        <div id="cover-preview" class="cover-preview" hidden><img alt=""><button type="button" class="link-btn" id="cover-clear">Remove</button></div>
        <input id="f-image" type="text" value="<?= e($p['image']) ?>" placeholder="Image address" spellcheck="false">
        <button type="button" class="btn" id="cover-upload"><i class="fas fa-image"></i> Upload image</button>
      </div>
      <input type="file" id="file-input" accept="image/jpeg,image/png,image/gif,image/webp" hidden>
      <div class="danger" id="danger"<?= $isNew ? ' hidden' : '' ?>>
        <a class="btn" id="view-link" href="<?= e(ts_url($p['slug'])) ?>" target="_blank" rel="noopener"><i class="fas fa-eye"></i> View</a>
        <button type="button" class="btn warn" id="btn-delete"><i class="fas fa-trash"></i> Delete</button>
      </div>
    </aside>
  </div>
</form>

<div id="toast" class="toast" role="status" aria-live="polite" hidden></div>

<script src="<?= e(ts_file_v('assets/admin/jquery.min.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/themestrap/namespace.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/themestrap/themestrap.plugin.toolbar.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/themestrap/themestrap.plugin.dialog.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/themestrap/themestrap.plugin.tagsinput.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/themestrap/themestrap.plugin.markdown.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/themestrap/themestrap.plugin.richeditor.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/themestrap/themestrap.plugin.calendar.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/themestrap/themestrap.plugin.select.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/themestrap/themestrap.plugin.timepicker.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/themestrap/themestrap.plugin.markdowneditor.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/prompts.js')) ?>"></script>
<script src="<?= e(ts_file_v('assets/admin/editor.js')) ?>"></script>