ChangelogView.vue 2.23 KB
<template>
  <div class="changelog-view">
    <div class="bar">
      <span>Total: {{ entries.length }} changes</span>
      <span class="grow" />
      <button class="btn" @click="reload">Refresh</button>
    </div>

    <table v-if="entries.length">
      <thead>
        <tr>
          <th>When</th>
          <th>Kind</th>
          <th>Rev</th>
          <th>By</th>
          <th>Trigger</th>
          <th>Summary</th>
        </tr>
      </thead>
      <tbody>
        <tr v-for="(e, i) in entries" :key="i">
          <td class="ts">{{ formatTs(e.ts) }}</td>
          <td><span :class="['k', e.kind]">{{ e.kind }}</span></td>
          <td>{{ e.rev }}</td>
          <td>{{ e.by || '-' }}</td>
          <td class="trigger">[{{ e.trigger || '-' }}]</td>
          <td class="summary">{{ e.summary }}</td>
        </tr>
      </tbody>
    </table>
    <p v-else class="empty">no changelog entries</p>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue';
const props = defineProps({ pid: { type: String, required: true } });
const entries = ref([]);

async function reload() {
  const r = await fetch(`/api/devloop/projects/${props.pid}/changelog`);
  if (!r.ok) return;
  const j = await r.json();
  entries.value = j.entries || [];
}

function formatTs(s) {
  if (!s) return '-';
  try { return new Date(s).toLocaleString(); } catch { return s; }
}

onMounted(reload);
</script>

<style scoped>
.changelog-view {}
.bar { display:flex; align-items:center; gap:14px; margin-bottom:12px; font-size:13px; }
.bar .grow { flex:1; }
.btn { background:#222; color:#fff; border:none; border-radius:4px; padding:4px 12px; cursor:pointer; font-size:12px; }
table { width:100%; border-collapse:collapse; font-size:13px; }
th, td { padding:8px 10px; text-align:left; border-bottom:1px solid #eee; }
th { background:#fafafb; color:#666; font-weight:500; font-size:12px; }
.ts { color:#888; font-size:11px; }
.k {
  display:inline-block; padding:1px 8px; border-radius:10px;
  font-family: ui-monospace, monospace; font-size:11px;
}
.k.prd_rev { background:#deecff; color:#1d4d99; }
.k.sdd_rev { background:#ffeede; color:#a64a00; }
.trigger { color:#888; font-size:11px; }
.summary { color:#444; }
.empty { padding:30px; text-align:center; color:#888; }
</style>