@@ -11,8 +11,12 @@ import type {
1111 ReportStatus ,
1212 ReportSummaryDTO ,
1313} from " @reprojs/shared"
14+ import LabelsPicker from " ./pickers/labels-picker.vue"
15+ import AssigneesPicker from " ./pickers/assignees-picker.vue"
16+ import MilestonePicker from " ./pickers/milestone-picker.vue"
1417import UnlinkDialog from " ~/components/integrations/github/unlink-dialog.vue"
1518import { safeHref } from " ~/composables/use-safe-href"
19+ import { useGithubIntegration } from " ~/composables/use-github-integration"
1620
1721interface Props {
1822 projectId: string
@@ -42,6 +46,11 @@ const githubReady = computed(
4246 () => Boolean (githubConfig .value ?.installed ) && githubConfig .value ?.status === " connected" ,
4347)
4448
49+ // Per-project integration state — drives the live picker section
50+ const projectIdRef = toRef (() => props .projectId )
51+ const { state : integrationState } = useGithubIntegration (projectIdRef )
52+ const isLinked = computed (() => integrationState .value .isLinked )
53+
4554const tagDraft = ref (" " )
4655const posting = ref (false )
4756const unlinkOpen = ref (false )
@@ -209,14 +218,35 @@ const open = reactive({
209218 </div >
210219 <div class =" flex items-center gap-3" >
211220 <label class =" w-20 shrink-0 text-xs font-medium text-muted" >Assignee</label >
212- <USelectMenu
213- v-model =" primaryAssignee"
214- :items =" assigneeItems"
215- value-key =" value"
216- size =" sm"
217- class =" flex-1 min-w-0"
218- :disabled =" !canEdit || posting"
219- />
221+ <template v-if =" isLinked " >
222+ <AssigneesPicker
223+ :project-id =" projectId"
224+ :model-value =" {
225+ dashboardUserIds: report.assignees.filter((a) => a.id).map((a) => a.id as string),
226+ githubLogins: report.assignees
227+ .filter((a) => !a.id && a.githubLogin)
228+ .map((a) => a.githubLogin as string),
229+ }"
230+ :disabled =" !canEdit || posting"
231+ class =" flex-1 min-w-0"
232+ @update:model-value ="
233+ patch({
234+ assigneeIds: $event.dashboardUserIds,
235+ githubAssigneeLogins: $event.githubLogins,
236+ })
237+ "
238+ />
239+ </template >
240+ <template v-else >
241+ <USelectMenu
242+ v-model =" primaryAssignee"
243+ :items =" assigneeItems"
244+ value-key =" value"
245+ size =" sm"
246+ class =" flex-1 min-w-0"
247+ :disabled =" !canEdit || posting"
248+ />
249+ </template >
220250 </div >
221251 <div class =" flex items-center gap-3" >
222252 <label class =" w-20 shrink-0 text-xs font-medium text-muted" >Priority</label >
@@ -229,55 +259,86 @@ const open = reactive({
229259 :disabled =" !canEdit || posting"
230260 />
231261 </div >
262+ <template v-if =" isLinked " >
263+ <div class =" flex items-center gap-3" >
264+ <label class =" w-20 shrink-0 text-xs font-medium text-muted" >Milestone</label >
265+ <MilestonePicker
266+ :project-id =" projectId"
267+ :model-value ="
268+ report.milestoneNumber !== null && report.milestoneTitle !== null
269+ ? {
270+ number: report.milestoneNumber as number,
271+ title: report.milestoneTitle as string,
272+ }
273+ : null
274+ "
275+ :disabled =" !canEdit || posting"
276+ class =" flex-1 min-w-0"
277+ @update:model-value =" patch({ milestone: $event })"
278+ />
279+ </div >
280+ </template >
232281 </div >
233282 </section >
234283
235284 <div class =" border-t border-default/60" />
236285
237- <!-- Tags — proper chips with hashtag + dismiss, input lives in the
238- same row so the editor feels contiguous with the tag pile . -->
286+ <!-- Tags / Labels — when repo-linked, shows the live label picker;
287+ otherwise the manual tag-chip editor . -->
239288 <section >
240289 <button
241290 type =" button"
242291 class =" flex w-full items-center justify-between gap-2 mb-3 text-xs font-semibold uppercase tracking-[0.14em] text-muted hover:text-default transition-colors"
243292 :aria-expanded =" open.tags"
244293 @click =" open.tags = !open.tags"
245294 >
246- <span >Tags</span >
295+ <span >{{ isLinked ? "Labels" : " Tags" }} </span >
247296 <UIcon
248297 name =" i-heroicons-chevron-down"
249298 class =" size-4 transition-transform"
250299 :class =" open.tags ? '' : '-rotate-90'"
251300 />
252301 </button >
253- <div v-show =" open.tags" class =" flex flex-wrap gap-1.5 items-center" >
254- <span
255- v-for =" t in report.tags"
256- :key =" t"
257- :class =" [
258- 'inline-flex items-center gap-1 rounded-md px-2 py-0.5 text-xs font-medium',
259- 'bg-primary/10 text-primary ring-1 ring-primary/20',
260- canEdit ? 'cursor-pointer hover:bg-primary/15 transition-colors' : '',
261- ]"
262- @click =" canEdit ? removeTag(t) : null"
263- >
264- <UIcon name =" i-heroicons-hashtag" class =" size-3" />
265- <span >{{ t }}</span >
266- <UIcon v-if =" canEdit" name =" i-heroicons-x-mark" class =" size-3 opacity-60" />
267- </span >
268- <UInput
269- v-if =" canEdit"
270- v-model =" tagDraft"
271- placeholder =" Add tag…"
272- size =" sm"
273- variant =" soft"
274- icon =" i-heroicons-plus"
275- class =" w-28"
276- @keydown.enter.prevent =" addTag"
277- />
278- <span v-if =" !canEdit && report.tags.length === 0" class =" text-xs text-muted italic" >
279- None
280- </span >
302+ <div v-show =" open.tags" >
303+ <template v-if =" isLinked " >
304+ <LabelsPicker
305+ :project-id =" projectId"
306+ :model-value =" report.tags"
307+ :disabled =" !canEdit || posting"
308+ @update:model-value =" patch({ tags: $event })"
309+ />
310+ </template >
311+ <template v-else >
312+ <div class =" flex flex-wrap gap-1.5 items-center" >
313+ <span
314+ v-for =" t in report.tags"
315+ :key =" t"
316+ :class =" [
317+ 'inline-flex items-center gap-1 rounded-md px-2 py-0.5 text-xs font-medium',
318+ 'bg-primary/10 text-primary ring-1 ring-primary/20',
319+ canEdit ? 'cursor-pointer hover:bg-primary/15 transition-colors' : '',
320+ ]"
321+ @click =" canEdit ? removeTag(t) : null"
322+ >
323+ <UIcon name =" i-heroicons-hashtag" class =" size-3" />
324+ <span >{{ t }}</span >
325+ <UIcon v-if =" canEdit" name =" i-heroicons-x-mark" class =" size-3 opacity-60" />
326+ </span >
327+ <UInput
328+ v-if =" canEdit"
329+ v-model =" tagDraft"
330+ placeholder =" Add tag…"
331+ size =" sm"
332+ variant =" soft"
333+ icon =" i-heroicons-plus"
334+ class =" w-28"
335+ @keydown.enter.prevent =" addTag"
336+ />
337+ <span v-if =" !canEdit && report.tags.length === 0" class =" text-xs text-muted italic" >
338+ None
339+ </span >
340+ </div >
341+ </template >
281342 </div >
282343 </section >
283344
0 commit comments