fix: allow tag rename without type payload

This commit is contained in:
yyh
2026-05-14 20:35:18 +08:00
parent 5798610f27
commit dc48a0855d
8 changed files with 32 additions and 23 deletions

View File

@ -25,6 +25,10 @@ class TagBasePayload(BaseModel):
type: TagType = Field(description="Tag type")
class TagUpdateRequestPayload(BaseModel):
name: str = Field(description="Tag name", min_length=1, max_length=50)
class TagBindingPayload(BaseModel):
tag_ids: list[str] = Field(description="Tag IDs to bind")
target_id: str = Field(description="Target ID to bind tags to")
@ -68,6 +72,7 @@ class TagResponse(ResponseModel):
register_schema_models(
console_ns,
TagBasePayload,
TagUpdateRequestPayload,
TagBindingPayload,
TagBindingRemovePayload,
TagListQueryParam,
@ -118,7 +123,7 @@ class TagListApi(Resource):
@console_ns.route("/tags/<uuid:tag_id>")
class TagUpdateDeleteApi(Resource):
@console_ns.expect(console_ns.models[TagBasePayload.__name__])
@console_ns.expect(console_ns.models[TagUpdateRequestPayload.__name__])
@setup_required
@login_required
@account_initialization_required
@ -129,8 +134,8 @@ class TagUpdateDeleteApi(Resource):
if not (current_user.has_edit_permission or current_user.is_dataset_editor):
raise Forbidden()
payload = TagBasePayload.model_validate(console_ns.payload or {})
tag = TagService.update_tags(UpdateTagPayload(name=payload.name, type=payload.type), tag_id)
payload = TagUpdateRequestPayload.model_validate(console_ns.payload or {})
tag = TagService.update_tags(UpdateTagPayload(name=payload.name), tag_id)
binding_count = TagService.get_tag_binding_count(tag_id)

View File

@ -31,7 +31,9 @@ from services.tag_service import (
TagBindingCreatePayload,
TagBindingDeletePayload,
TagService,
UpdateTagPayload,
)
from services.tag_service import (
UpdateTagPayload as UpdateTagServicePayload,
)
register_enum_models(service_api_ns, DatasetPermissionEnum)
@ -556,7 +558,7 @@ class DatasetTagsApi(DatasetApiResource):
payload = TagUpdatePayload.model_validate(service_api_ns.payload or {})
tag_id = payload.tag_id
tag = TagService.update_tags(UpdateTagPayload(name=payload.name, type=TagType.KNOWLEDGE), tag_id)
tag = TagService.update_tags(UpdateTagServicePayload(name=payload.name), tag_id)
binding_count = TagService.get_tag_binding_count(tag_id)

View File

@ -21,7 +21,6 @@ class SaveTagPayload(BaseModel):
class UpdateTagPayload(BaseModel):
name: str = Field(min_length=1, max_length=50)
type: TagType
class TagBindingCreatePayload(BaseModel):

View File

@ -759,7 +759,7 @@ class TestTagService:
tag = TagService.save_tags(tag_args)
# Update args
update_args = UpdateTagPayload(name="updated_name", type="knowledge")
update_args = UpdateTagPayload(name="updated_name")
# Act: Execute the method under test
result = TagService.update_tags(update_args, tag.id)
@ -799,7 +799,7 @@ class TestTagService:
non_existent_tag_id = str(uuid.uuid4())
update_args = UpdateTagPayload(name="updated_name", type="knowledge")
update_args = UpdateTagPayload(name="updated_name")
# Act & Assert: Verify proper error handling
with pytest.raises(NotFound) as exc_info:
@ -830,7 +830,7 @@ class TestTagService:
tag2 = TagService.save_tags(tag2_args)
# Try to update second tag with first tag's name
update_args = UpdateTagPayload(name="first_tag", type="app")
update_args = UpdateTagPayload(name="first_tag")
# Act & Assert: Verify proper error handling
with pytest.raises(ValueError) as exc_info:

View File

@ -14,6 +14,7 @@ from controllers.console.tag.tags import (
TagUpdateDeleteApi,
)
from models.enums import TagType
from services.tag_service import UpdateTagPayload
def unwrap(func):
@ -147,7 +148,7 @@ class TestTagUpdateDeleteApi:
api = TagUpdateDeleteApi()
method = unwrap(api.patch)
payload = {"name": "updated", "type": "knowledge"}
payload = {"name": "updated"}
with app.test_request_context("/", json=payload):
with (
@ -159,7 +160,7 @@ class TestTagUpdateDeleteApi:
patch(
"controllers.console.tag.tags.TagService.update_tags",
return_value=tag,
),
) as update_tags_mock,
patch(
"controllers.console.tag.tags.TagService.get_tag_binding_count",
return_value=3,
@ -168,6 +169,9 @@ class TestTagUpdateDeleteApi:
result, status = method(api, "tag-1")
assert status == 200
update_payload, tag_id = update_tags_mock.call_args.args
assert update_payload == UpdateTagPayload(name="updated")
assert tag_id == "tag-1"
assert result["binding_count"] == "3"
def test_patch_forbidden(self, app: Flask, readonly_user, payload_patch):

View File

@ -48,7 +48,7 @@ export const tagUpdateContract = base
name: string
}
}>())
.output(type<unknown>())
.output(type<Tag>())
export const tagDeleteContract = base
.route({

View File

@ -187,15 +187,20 @@ describe('consoleQuery tag mutation defaults', () => {
queryClient.setQueryData(appListKey, [targetTag, otherTag])
queryClient.setQueryData(knowledgeListKey, [knowledgeTag])
const updatedTag = createTag({
...targetTag,
name: 'After',
binding_count: 5,
})
const mutationOptions = consoleQuery.tags.update.mutationOptions()
await mutationOptions.onSuccess?.(
undefined,
updatedTag,
{
params: {
tagId: targetTag.id,
},
body: {
name: 'After',
name: 'Ignored Client Name',
},
},
undefined,
@ -203,10 +208,7 @@ describe('consoleQuery tag mutation defaults', () => {
)
expect(queryClient.getQueryData(appListKey)).toEqual([
{
...targetTag,
name: 'After',
},
updatedTag,
otherTag,
])
expect(queryClient.getQueryData(knowledgeListKey)).toEqual([knowledgeTag])

View File

@ -108,16 +108,13 @@ export const consoleQuery = createTanstackQueryUtils(consoleClient, {
},
update: {
mutationOptions: {
onSuccess: (_data, variables, _onMutateResult, context) => {
onSuccess: (updatedTag, variables, _onMutateResult, context) => {
context.client.setQueriesData(
{
queryKey: consoleQuery.tags.list.key({ type: 'query' }),
},
(oldTags: Tag[] | undefined) => oldTags?.map(tag => tag.id === variables.params.tagId
? {
...tag,
name: variables.body.name,
}
? updatedTag
: tag),
)
},