Skip to content

Conversation

HenriquerPimentel
Copy link
Contributor

Implemented #29798

This feature implements:

  • List all badges (screenshot)
  • Create new badges (screenshot)
  • View badge (screenshot)
  • Edit badge (screenshot)
  • Add user to badge (screenshot)

Implemented Badge Management in administration panel

  1. Updated badge model (models/user/badge.go)
  2. Added new type of errors ErrBadgeAlreadyExist and ErrBadgeNotExist (models/user/error.go)
  3. Implemented badge service methods (services/user/badge.go)
  4. Implemented new type of form AdminCreateBadgeForm (services/forms/admin.go)
  5. Implemented new binding rules to check if ImageURL is valid and if is Slug Pattern (modules/validation/binding.go) (modules/web/middleware.go) (modules/validation/helpers.go)
  6. Implemented badge search (routers/web/explore/badge.go) (routers/web/admin/badges.go)
  7. Implemented badges routing (routers/web/web.go)
  8. Implemented templates for create/list/edit/view badges (templates/admin/badge/*) (templates/admin/navbar.tmpl)
    9 Added new translation phrases (en-US): search.badge_kind, form.ImageURL, form.invalid_image_url_error, form.slug_been_taken, admin.badges, admin.badges.badges_manage_panel, admin.badges.details, admin.badges.new_badge, admin.badges.slug, admin.badges.description, admin.badges.image_url, admin.badges.slug.must_fill, admin.badges.new_success, admin.badges.update_success, admin.badges.deletion_success, admin.badges.edit_badge, admin.badges.update_badge, admin.badges.delete_badge, admin.badges.delete_badge_desc

Implemented User Badge Management Interface

  1. Implemented rule to verify if a user badge already exists before insert (models/user/badge.go).
  2. Implemented interface to manage user badge, within administration panel. (routers/web/web.go) (routers/web/explore/badge.go) (routers/web/admin/badges.go) (templates/admin/badge/users.tmpl).
  3. Small bug fixes (view.tmpl, list.tmpl)
  4. Added new translation phrases: admin.badges.users_with_badge, admin.badges.add_user, admin.badges.remove_user, admin.badges.delete_user_desc, admin.badges.not_found, admin.badges.user_add_success, admin.badges.user_remove_success, admin.badges.manage_users.

@GiteaBot GiteaBot added the lgtm/need 2 This PR needs two approvals by maintainers to be considered for merging. label Jun 5, 2024
@github-actions github-actions bot added modifies/translation modifies/go Pull requests that update Go code modifies/templates This PR modifies the template files labels Jun 5, 2024
@HenriquerPimentel HenriquerPimentel marked this pull request as draft June 5, 2024 14:10
@HenriquerPimentel HenriquerPimentel marked this pull request as ready for review June 14, 2024 12:00
@lunny lunny added this to the 1.23.0 milestone Jun 14, 2024
Copy link
Member

@techknowlogick techknowlogick left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR! The CI has a few linting reports that came up that I've reported in line :)

@HenriquerPimentel
Copy link
Contributor Author

Thanks for the PR! The CI has a few linting reports that came up that I've reported in line :)

Thank you so much!

HenriquerPimentel and others added 3 commits June 19, 2024 13:53
Co-authored-by: Diogo Vicente <diogo.m.s.vicente@tecnico.ulisboa.pt>
Co-authored-by: Diogo Vicente <diogo.m.s.vicente@tecnico.ulisboa.pt>
@techknowlogick
Copy link
Member

@HenriquerPimentel looks like some different CI steps are failing, also related to linting (some public go functions require comments to document their purpose, eg AdminCreateBadge), although with AdminCreateBadge as it is a wrapper for another function without any transformative properties or checks that one could probably be kept as just CreateBadge without the secondary function.

As a sidenote: force pushing erases some review history as GitHub sees some files as new (even if they remain the same). If you could reduce your force pushes, it'd be helpful to me as a reviewer so I can keep track of what I've seen already
disclaimer: most of the time we try to discourage force pushing to PRs for this reason, although depending on the reviewer of a certain PR they can "call an audible" depending on the situation and might be ok with it.

@github-actions github-actions bot added topic/code-linting modifies/api This PR adds API routes or modifies them modifies/cli PR changes something on the CLI, i.e. gitea doctor or gitea admin modifies/docs modifies/internal modifies/dependencies modifies/frontend labels Sep 14, 2025
@github-actions github-actions bot removed topic/code-linting modifies/api This PR adds API routes or modifies them modifies/cli PR changes something on the CLI, i.e. gitea doctor or gitea admin modifies/docs modifies/internal modifies/dependencies modifies/frontend labels Sep 15, 2025
if err != nil {
if user_model.IsErrUserNotExist(err) {
ctx.Flash.Error(ctx.Tr("form.user_not_exist"))
ctx.JSONRedirect(fmt.Sprintf("%s/-/admin/badges/%s/users", setting.AppSubURL, ctx.PathParam("badge_slug")))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two bugs:

  1. string variables used in a URL should be escaped (and other places)
  2. this if block will continue executing, then you have 2 JSONRedirect calls in one response.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@go-gitea/maintainers

I have suggested many times to have a better framework to handle various errors and returns.

You can see that how many bugs caused by our stupid framework in this PR.

// UpdateBadgeDescription changes the description and/or image of a badge
func UpdateBadge(ctx context.Context, b *user_model.Badge) error {
return db.WithTx(ctx, func(ctx context.Context) error {
return user_model.UpdateBadge(ctx, b)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why single SQL needs transaction?

Comment on lines +23 to +28
return db.WithTx(ctx, func(ctx context.Context) error {
if err := user_model.DeleteBadge(ctx, b); err != nil {
return fmt.Errorf("DeleteBadge: %w", err)
}
return nil
})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is already a transaction in DeleteBadge.

So why we need this wrap function in service package?

Comment on lines +10 to +13
<div class="non-local field {{if .Err_Slug}}error{{end}}" disabled=disabled>
<label for="slug">{{ctx.Locale.Tr "admin.badges.slug"}}</label>
<input disabled=disabled id="slug" name="slug" value="{{.Badge.Slug}}">
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some questions:

  • Why parent "div" has "disabled=disabled" and inner "input" also has "disabled=disabled"?
  • If there is no input (no change), why {{if .Err_Slug}} would occurs?
  • If the input is disabled, why the "label" has "for"?
  • What does "non-local" mean here?

Comment on lines +15 to +16
<label for="description">{{ctx.Locale.Tr "admin.badges.description"}}</label>
<textarea id="description" type="text" name="description" rows="2">{{.Badge.Description}}</textarea>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our frontend framework can handle most a11y cases, so no need to repeat id and for (and other places)

</div>
</div>

<div class="ui g-modal-confirm delete modal" id="delete-badge-modal">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

delete class is a no-op IIRC

{{end}}
{{template "base/paginate" .}}
<div class="ui bottom attached segment">
<form class="ui form" id="search-badge-user-form" action="{{.Link}}" method="post">
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why the search form is at the bottom?

IIRC for all (at least almost) cases Gitea layout is like this: search form at top, table at bottom.

ps: why it needs an id? I don't see it is used anywhere.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm ... it is not a real "search" form, but it is used to add a new user, so maybe it's fine.

But still have the question why there are unused id attributes.

Comment on lines +13 to +29
<div class="flex-list">
<div class="flex-item">
{{if .Image}}
<div class="flex-item-leading">
<img width="64" height="64" src="{{.Badge.ImageURL}}" alt="{{.Badge.Description}}" data-tooltip-content="{{.Badge.Description}}">
</div>
{{end}}
<div class="flex-item-main">
<div class="flex-item-title">
{{.Badge.Slug}}
</div>
<div class="flex-item-body">
{{.Badge.Description}}
</div>
</div>
</div>
</div>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Many "div" open/close tags misaligned, I think it's better to make the tags align correctly to make code readable.

@lunny lunny modified the milestones: 1.25.0, 1.26.0 Sep 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lgtm/need 1 This PR needs approval from one additional maintainer to be merged. modifies/go Pull requests that update Go code modifies/migrations modifies/templates This PR modifies the template files modifies/translation
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants