Jake Vanderwerf
2025-11-25 2a2303d1dccc120dd7aa5f6b6ade0f89e0064850
inc/managers/CRUDManager.php
@@ -58,6 +58,10 @@
      ];
      $this->init();
      if ($this->isTimeline) {
         $this->stuck[] = 'post_thumbnail';
      }
      add_filter('jvbAdditionalActions', [$this, 'createItem']);
   }
@@ -89,6 +93,7 @@
      }));
      array_unshift($this->timelineSharedFields, 'post_thumbnail');
      array_unshift($this->timelineSharedFields, 'post_title');
      array_unshift($this->timelineSharedFields, 'post_status');
      $this->timelineUniqueFields = array_keys(array_filter($this->fields, function ($field) {
         if (array_key_exists('for_all', $field) && $field['for_all'] === true) {
@@ -192,7 +197,7 @@
   {
      ob_start();
      ?>
      <div class="dashboard-page <?= esc_attr($this->content) ?>">
      <div class="dashboard-page <?= esc_attr($this->content) ?>"<?=($this->isTimeline) ? ' data-timeline' : ''?>>
         <?php
         $this->renderHeader();
         $this->renderContent();
@@ -331,7 +336,7 @@
         <?php
            $order = [
               'orderby' => [
                  'calendar' => 'Order by date created',
                  'date' => 'Order by date created',
                  'alphabetical' => 'Order alphabetically'
               ],
               'order' => [
@@ -347,10 +352,11 @@
               <?php
               $i = 0;
               foreach ($option as $opt => $label) {
                  $icon = $opt === 'date' ? 'calendar' : $opt;
                  ?>
                  <input id="<?=$opt?>" class="btn" type="radio" name="<?=$o?>" data-filter="<?=$o?>" value="<?=$opt?>"<?=$i===0 ? ' checked':''?>>
                  <label for="<?=$opt?>" title="<?=$label?>"><?=jvbIcon($opt)?></label>
                  <label for="<?=$opt?>" title="<?=$label?>"><?=jvbIcon($icon)?></label>
                  <?php
                  $i++;
               }
@@ -736,36 +742,6 @@
   }
   protected function renderTimelineFields():string
   {
      ob_start();
      ?>
      <div class="repeater-field timeline-repeater" data-timeline data-field="fields">
         <div class="repeater-rows" data-repeater-container>
            <!-- Parent row (non-draggable) -->
            <div class="repeater-row parent-row" data-row-index="0" data-id="">
               <div class="row-header">
                  <h4>Before (Starting Point)</h4>
               </div>
               <div class="row-fields">
                  <?php $this->renderRowFields(); ?>
               </div>
            </div>
            <!-- Child rows will be added dynamically -->
         </div>
         <button type="button" class="add-repeater-row btn secondary">
            <?= jvbIcon('plus-square') ?>
            <span>Add Progress Step</span>
         </button>
      </div>
      <?php
      return ob_get_clean();
   }
   protected function renderRowFields():void
   {
      $fields = $this->fields;
@@ -1010,6 +986,10 @@
   protected function renderTableView():void
   {
      if ($this->isTimeline) {
         $this->renderTimelineTableView();
         return;
      }
      ?>
      <template class="contentTable">
         <form class="table"
@@ -1038,13 +1018,17 @@
    * Render table row template
    */
   protected function renderTableRow(): void {
      if ($this->isTimeline) {
         $this->renderTimelineTableGroup();
         return;
      }
      ?>
      <template class="tableView">
         <tr class="item">
            <td class="select">
               <?= $this->renderItemSelect() ?>
            </td>
            <td class="status">
            <td class="status" data-field="post_status">
               <?= $this->renderStatusRadios() ?>
            </td>
            <?php
@@ -1070,6 +1054,102 @@
      </template>
      <?php
   }
   protected function renderTimelineTableView():void
   {
      ?>
      <template class="contentTable">
         <form class="table"
              data-save="content"
              data-content="<?= esc_attr($this->content) ?>"
              data-form-id="content-table-<?= esc_attr($this->content) ?>">
            <?= jvbFormStatus() ?>
            <?= $this->renderTableActions() ?>
            <table>
               <thead>
               <?= $this->renderTimelineTableHeader() ?>
               </thead>
               <!-- Rows are inserted as tbody groups -->
               <tfoot>
               <?= $this->renderTimelineTableHeader() ?>
               </tfoot>
            </table>
         </form>
      </template>
      <?php
   }
   protected function renderTimelineTableGroup():void
   {
      $makeDetails = [
         'group',
         'repeater',
         'checkbox',
         'radio'
      ];
      ?>
      <template class="tableView">
         <tbody class="item">
            <tr class="shared">
               <td class="select">
                  <?= $this->renderItemSelect() ?>
               </td>
               <td class="show-post_status field" data-field="post_status">
                  <?= $this->renderStatusRadios() ?>
               </td>
               <?php
               foreach ($this->fields as $name => $config) {
                  if(array_key_exists('hidden', $config) || $name === 'post_status') {
                     continue;
                  }
                  if (!in_array($name, $this->timelineSharedFields)) {
                     echo '<td></td>';
                     continue;
                  }
                     $makeThisDetailed = (in_array($config['type'], $makeDetails));
                  ?>
                  <td class="field show-<?= esc_attr($name) ?>" data-field="<?= esc_attr($name) ?>" data-field-type="<?=$config['type']?>"<?=(in_array($name, $this->stuck)) ? ' data-stuck':''?>>
                     <?= $makeThisDetailed ? '<details><summary class="row btw">See Value</summary>' : '' ?>
                     <?php $this->meta->render('form', $name, $config); ?>
                     <?= $makeThisDetailed ? '</details>' : '' ?>
                  </td>
                  <?php
               }
               ?>
            </tr>
            <tr class="timeline-point">
               <td class="select">
                  <button class="drag-handle" title="Drag to reorder" aria-label="Drag to reorder this timeline point"><?= jvbIcon('dots-six') ?></button>
               </td>
               <td class="show-post_status field" data-field="post_status">
                  <?= $this->renderStatusRadios() ?>
               </td>
               <?php
               foreach ($this->fields as $name => $config) {
                  if(array_key_exists('hidden', $config) || $name === 'post_status') {
                     continue;
                  }
                  if (!in_array($name, $this->timelineUniqueFields)) {
                     echo '<td></td>';
                     continue;
                  }
                  $makeThisDetailed = (in_array($config['type'], $makeDetails));
                  ?>
                  <td class="field show-<?= esc_attr($name) ?>" data-field="<?= esc_attr($name) ?>" data-field-type="<?=$config['type']?>"<?=(in_array($name, $this->stuck)) ? ' data-stuck':''?>>
                     <?= $makeThisDetailed ? '<details><summary class="row btw">See Value</summary>' : '' ?>
                     <?php $this->meta->render('form', $name, $config); ?>
                     <?= $makeThisDetailed ? '</details>' : '' ?>
                  </td>
                  <?php
               }
               ?>
            </tr>
         </tbody>
      </template>
      <?php
   }
   /**
    * Render status radio buttons
    */
@@ -1131,6 +1211,32 @@
      return ob_get_clean();
   }
   protected function renderTimelineTableHeader(): string {
      ob_start();
      ?>
      <tr>
         <th scope="col" class="select-header">
            <input type="checkbox" id="select-all" name="select-all">
            <label for="select-all">All</label>
         </th>
         <th scope="col" class="show-post_status">
            Status
         </th>
         <?php foreach ($this->fields as $name => $config):
            if (array_key_exists('hidden', $config) || $name === 'post_status'){
               continue;
            }
            ?>
            <th scope="col" class="show-<?= esc_attr($name) ?>"<?= (in_array($name, $this->stuck)) ? ' data-stuck':''?>>
               <?= esc_html($config['label']) ?>
            </th>
         <?php endforeach; ?>
      </tr>
      <?php
      return ob_get_clean();
   }
   /**
    * Render table action controls
    */