mirror of
https://github.com/lukaszraczylo/ghtracker.git
synced 2026-10-12 00:45:38 +00:00
* feat(refresh): refresh a single repository with POST /refresh?repo= The endpoint refreshes one configured repository and returns the full state plus the repo name. Each repository has a 60-second cooldown that is separate from the full-refresh limit. A running full refresh or a refresh of the same repository returns 409. An unknown repository returns 404. Cross-site and disabled-config behaviour stay the same. The collector reuses its fetch path and replaces only that repository. * feat(ui): add a refresh button beside each repository The button appears in the project list and in each attention group header. It stays hidden when the server disables manual refresh. The button shows a spinner while its repository refreshes and reports refusals in the notice line. The store swaps in the returned state, so no extra fetch follows.
58 lines
2.0 KiB
Vue
58 lines
2.0 KiB
Vue
<script setup lang="ts">
|
|
import { faTag } from '@fortawesome/free-solid-svg-icons'
|
|
import { FontAwesomeIcon } from '@fortawesome/vue-fontawesome'
|
|
import AttentionRow from '@/components/AttentionRow.vue'
|
|
import RepoRefreshButton from '@/components/RepoRefreshButton.vue'
|
|
import { Badge } from '@/components/ui/badge'
|
|
import type { Block } from '@/lib/types'
|
|
|
|
defineProps<{
|
|
block: Block
|
|
nowMs: number
|
|
critSeconds: number
|
|
manualRefresh?: boolean
|
|
refreshing?: string[]
|
|
scanning?: boolean
|
|
}>()
|
|
defineEmits<{ refresh: [fullName: string] }>()
|
|
</script>
|
|
|
|
<template>
|
|
<section class="border-border bg-surface rounded-lg border" data-test="repo-block">
|
|
<header class="border-border flex flex-wrap items-center gap-x-3 gap-y-1 border-b px-4 py-3">
|
|
<h3 class="font-semibold">
|
|
<a :href="block.repo.url" class="hover:text-link underline-offset-4 hover:underline">
|
|
<span class="text-muted-foreground font-normal"
|
|
>{{ block.repo.fullName.split('/')[0] }}/</span
|
|
>{{ block.repo.fullName.split('/')[1] }}
|
|
</a>
|
|
</h3>
|
|
<Badge v-if="block.repo.release" variant="secondary" as-child class="font-mono">
|
|
<a :href="block.repo.release.url">
|
|
<FontAwesomeIcon :icon="faTag" aria-hidden="true" class="text-[0.7em]" />
|
|
{{ block.repo.release.tag }}
|
|
</a>
|
|
</Badge>
|
|
<span class="text-muted-foreground ml-auto flex items-center gap-1 text-xs">
|
|
{{ block.rows.length }} {{ block.rows.length === 1 ? 'item' : 'items' }}
|
|
<RepoRefreshButton
|
|
v-if="manualRefresh"
|
|
:repo="block.repo.fullName"
|
|
:busy="refreshing?.includes(block.repo.fullName) ?? false"
|
|
:blocked="scanning ?? false"
|
|
@refresh="$emit('refresh', block.repo.fullName)"
|
|
/>
|
|
</span>
|
|
</header>
|
|
<ul class="divide-border divide-y px-4">
|
|
<AttentionRow
|
|
v-for="row in block.rows"
|
|
:key="row.url"
|
|
:row="row"
|
|
:now-ms="nowMs"
|
|
:crit-seconds="critSeconds"
|
|
/>
|
|
</ul>
|
|
</section>
|
|
</template>
|