Skip to content

Commit 7444c5c

Browse files
committed
fix: align item creation with API v2 contract
1 parent 06716e9 commit 7444c5c

8 files changed

Lines changed: 22 additions & 10 deletions

File tree

frontend/src/lib/dialogs/CreateModal.svelte

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -229,10 +229,6 @@
229229
}
230230
231231
let result = await api.items.create(formData);
232-
if (formData.label_ids?.length > 0) {
233-
const labels = await api.labels.setForItem(result.id, formData.label_ids);
234-
result = { ...result, labels: labels || [] };
235-
}
236232
const originalDescription = formData.description || '';
237233
const updatedDescription = await uploadPendingDescriptionImages(result.id, originalDescription);
238234
if (updatedDescription !== originalDescription) {

frontend/src/lib/features/collections/CollectionMap.svelte

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,13 +417,11 @@
417417
}
418418
419419
try {
420-
// Create the item
421420
const newItem = await api.items.create({
422421
workspace_id: state.workspaceId,
423422
item_type_id: state.itemTypeId,
424423
title: state.title.trim(),
425424
description: '',
426-
priority: 'medium',
427425
parent_id: parentId
428426
});
429427
@@ -768,6 +766,7 @@
768766
<!-- Add Card button when there are existing items -->
769767
{#if !quickAddState[backboneItem.id]?.show && childItemsByParent[backboneItem.id]?.length > 0 && canAddChildren(backboneItem.id)}
770768
<button
769+
data-testid="map-add-card-{backboneItem.id}"
771770
onclick={() => initQuickAdd(backboneItem.id)}
772771
class="w-full flex items-center gap-2 px-3 py-2 text-sm font-medium rounded border-2 border-dashed transition-colors "
773772
style="border-color: var(--ctx-border, var(--ds-border)); background-color: transparent; color: var(--ds-text-subtle);"
@@ -789,6 +788,7 @@
789788
{#if !quickAddState[backboneItem.id]?.show && (!childItemsByParent[backboneItem.id] || childItemsByParent[backboneItem.id].length === 0)}
790789
{#if canAddChildren(backboneItem.id)}
791790
<button
791+
data-testid="map-add-card-{backboneItem.id}"
792792
onclick={() => initQuickAdd(backboneItem.id)}
793793
class="w-full flex items-center gap-2 px-3 py-2 text-sm font-medium rounded border-2 border-dashed transition-colors"
794794
style="border-color: var(--ctx-border, var(--ds-border)); background-color: transparent; color: var(--ds-text-subtle);"

frontend/src/lib/features/collections/QuickAddForm.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@
131131
<div class={compact ? 'p-3 pb-2' : ''}>
132132
<Textarea
133133
value={formState.title}
134+
data-testid={`quick-add-title-${parentId}`}
134135
data-quick-add-parent={parentId}
135136
oninput={(e) => onUpdateField(parentId, 'title', e.currentTarget.value)}
136137
onkeydown={handleKeydown}

frontend/src/lib/mobile/MobileCreateDialog.svelte

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,7 @@
596596
priority_id: priorityId || null,
597597
assignee_id: assigneeId || null,
598598
milestone_ids: Array.isArray(milestoneIds) ? milestoneIds : [],
599+
label_ids: selectedLabelIds(),
599600
iteration_id: iterationId || null,
600601
project_id: projectId || null,
601602
due_date: dateInputToISOString(dueDate),
@@ -618,9 +619,6 @@
618619
if (!isPersonal && !validateConfiguredFields()) return;
619620
620621
const result = await api.items.create(createPayload());
621-
if (!isPersonal && selectedLabelIds().length > 0) {
622-
await api.labels.setForItem(result.id, selectedLabelIds());
623-
}
624622
if (isPersonal) {
625623
// The newly created personal task lives in this tab's list - let the
626624
// active Personal view refresh itself. BroadcastChannel excludes the

internal/restapi/v2/items.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type itemCreateRequest struct {
4545
EstimateMinutes *int `json:"estimate_minutes"`
4646
CustomFieldValues map[string]any `json:"custom_field_values"`
4747
MilestoneIDs []int `json:"milestone_ids"`
48+
LabelIDs []int `json:"label_ids"`
4849
}
4950

5051
type itemPatchRequest struct {
@@ -131,7 +132,7 @@ func registerItemRoutes(builder *routeBuilder, app *services.ItemApplicationServ
131132
AssigneeID: input.AssigneeID, ParentID: input.ParentID,
132133
RelatedWorkItemID: input.RelatedWorkItemID, StoryPoints: input.StoryPoints,
133134
EstimateMinutes: input.EstimateMinutes, CustomFieldValues: input.CustomFieldValues,
134-
MilestoneIDs: input.MilestoneIDs,
135+
MilestoneIDs: input.MilestoneIDs, LabelIDs: input.LabelIDs,
135136
})
136137
return result, itemError(err)
137138
})

internal/services/item_creation.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,14 @@ func (c *itemCreation) validateAssignments() error {
5757
if err := validation.ValidatePlanningAssignments(c.db, params.WorkspaceID, params.MilestoneIDs, params.IterationID); err != nil {
5858
return err
5959
}
60+
labels := repository.NewLabelRepository(c.db)
61+
for _, labelID := range params.LabelIDs {
62+
if _, err := labels.GetByID(labelID); errors.Is(err, repository.ErrNotFound) {
63+
return &validation.ValidationError{Field: "label_ids", Message: fmt.Sprintf("Label %d not found", labelID)}
64+
} else if err != nil {
65+
return fmt.Errorf("validate label %d: %w", labelID, err)
66+
}
67+
}
6068
if params.ValidatingUserID > 0 && params.AssigneeID != nil {
6169
actionable, err := c.assigneeCanAct()
6270
if err != nil {
@@ -275,6 +283,11 @@ func (c *itemCreation) extendTransaction(tx database.Tx, itemID int) error {
275283
return fmt.Errorf("failed to attach milestone %d to new item: %w", milestoneID, err)
276284
}
277285
}
286+
if len(c.params.LabelIDs) > 0 {
287+
if err := repository.NewLabelRepository(c.db).ReplaceItemLabelsTx(c.ctx, tx, itemID, c.params.LabelIDs); err != nil {
288+
return err
289+
}
290+
}
278291
if c.params.AfterCreate != nil {
279292
return c.params.AfterCreate(c.ctx, tx, itemID)
280293
}

internal/services/item_creation_service.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ type ItemCreateInput struct {
4545
EstimateMinutes *int
4646
CustomFieldValues map[string]any
4747
MilestoneIDs []int
48+
LabelIDs []int
4849
}
4950

5051
// ItemCreateResult contains the committed item and mandatory-template detail
@@ -156,6 +157,7 @@ func (s *ItemCreationService) create(
156157
IsTask: input.IsTask,
157158
ParentID: input.ParentID,
158159
MilestoneIDs: input.MilestoneIDs,
160+
LabelIDs: input.LabelIDs,
159161
IterationID: input.IterationID,
160162
ProjectID: input.ProjectID,
161163
InheritProject: input.InheritProject,

internal/services/items.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ type ItemCreationParams struct {
9393
IsTask bool
9494
ParentID *int
9595
MilestoneIDs []int
96+
LabelIDs []int
9697
IterationID *int
9798
ProjectID *int
9899
InheritProject bool

0 commit comments

Comments
 (0)