mirror of
https://codeberg.org/forgejo/forgejo.git
synced 2025-03-14 15:52:43 +00:00
Add new 'Report abuse' form and links for user profile, repository page, issues, pulls and comments.
This commit is contained in:
parent
bca6ac6f6c
commit
248e2d3861
18 changed files with 233 additions and 63 deletions
|
@ -14,8 +14,8 @@ import (
|
|||
// CommentData represents a trimmed down comment that is used for preserving
|
||||
// only the fields needed for abusive content reports (mainly string fields).
|
||||
type CommentData struct {
|
||||
OriginalAuthor string // TODO: decide if this is needed
|
||||
TreePath string // TODO: decide if this is needed
|
||||
OriginalAuthor string // TODO: decide if this is useful
|
||||
TreePath string // TODO: decide if this is useful
|
||||
Content string
|
||||
ContentVersion int
|
||||
CreatedUnix timeutil.TimeStamp
|
||||
|
|
|
@ -25,8 +25,17 @@ const (
|
|||
ReportStatusTypeIgnored // 3
|
||||
)
|
||||
|
||||
// AbuseCategoryType defines the categories in which a user can include the reported content.
|
||||
type AbuseCategoryType int //revive:disable-line:exported
|
||||
type (
|
||||
// AbuseCategoryType defines the categories in which a user can include the reported content.
|
||||
AbuseCategoryType int //revive:disable-line:exported
|
||||
|
||||
// AbuseCategoryItem defines a pair of value and it's corresponding translation key
|
||||
// (used when new reports are submitted).
|
||||
AbuseCategoryItem struct {
|
||||
Value AbuseCategoryType
|
||||
TranslationKey string
|
||||
}
|
||||
)
|
||||
|
||||
const (
|
||||
AbuseCategoryTypeSpam AbuseCategoryType = iota + 1 // 1
|
||||
|
@ -35,6 +44,17 @@ const (
|
|||
AbuseCategoryTypeOtherViolations // 4 (Other violations of platform rules)
|
||||
)
|
||||
|
||||
// GetAbuseCategoriesList returns a list of pairs with the available abuse category types
|
||||
// and their corresponding translation keys
|
||||
func GetAbuseCategoriesList() []AbuseCategoryItem {
|
||||
return []AbuseCategoryItem{
|
||||
{AbuseCategoryTypeSpam, "moderation.abuse_category.spam"},
|
||||
{AbuseCategoryTypeMalware, "moderation.abuse_category.malware"},
|
||||
{AbuseCategoryTypeIllegalContent, "moderation.abuse_category.illegal_content"},
|
||||
{AbuseCategoryTypeOtherViolations, "moderation.abuse_category.other_violations"},
|
||||
}
|
||||
}
|
||||
|
||||
// ReportedContentType defines the types of content that can be reported
|
||||
// (i.e. user/organization profile, repository, issue/pull, comment).
|
||||
type ReportedContentType int //revive:disable-line:exported
|
||||
|
@ -97,6 +117,15 @@ func alreadyReportedBy(ctx context.Context, doerID int64, contentType ReportedCo
|
|||
return reported
|
||||
}
|
||||
|
||||
func ReportAbuse(ctx context.Context, report *AbuseReport) error {
|
||||
if report.ContentType == ReportedContentTypeUser && report.ReporterID == report.ContentID {
|
||||
return nil
|
||||
}
|
||||
|
||||
return reportAbuse(ctx, report)
|
||||
}
|
||||
|
||||
/*
|
||||
// ReportUser creates a new abuse report regarding the user with the provided reportedUserID.
|
||||
func ReportUser(ctx context.Context, reporterID int64, reportedUserID int64, remarks string) error {
|
||||
if reporterID == reportedUserID {
|
||||
|
@ -148,6 +177,7 @@ func ReportComment(ctx context.Context, reporterID int64, commentID int64, remar
|
|||
|
||||
return reportAbuse(ctx, report)
|
||||
}
|
||||
*/
|
||||
|
||||
func reportAbuse(ctx context.Context, report *AbuseReport) error {
|
||||
if alreadyReportedBy(ctx, report.ReporterID, report.ContentType, report.ContentID) {
|
||||
|
@ -156,8 +186,6 @@ func reportAbuse(ctx context.Context, report *AbuseReport) error {
|
|||
}
|
||||
|
||||
report.Status = ReportStatusTypeOpen
|
||||
report.Category = AbuseCategoryTypeOtherViolations // TODO: replace with user's selection
|
||||
|
||||
_, err := db.GetEngine(ctx).Insert(report)
|
||||
|
||||
return err
|
||||
|
|
|
@ -938,6 +938,8 @@ func UpdateUserCols(ctx context.Context, u *User, cols ...string) error {
|
|||
return err
|
||||
}
|
||||
|
||||
// If the user was reported as abusive and any of the columns being updated is relevant
|
||||
// for moderation purposes a shadow copy should be created before first update.
|
||||
if err := IfNeededCreateShadowCopyForUser(ctx, u, cols...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -3964,10 +3964,23 @@ filepreview.truncated = Preview has been truncated
|
|||
report = Report
|
||||
;already_reported = Already reported
|
||||
report_abuse = Report abuse
|
||||
report_comment = Report comment
|
||||
report_content = Report content
|
||||
report_abuse_form.header = Report abuse to administrator
|
||||
report_abuse_form.details = This form should be used to report users who create spam profiles, repositories, issues, comments or behave inappropriately.
|
||||
report_abuse_form.invalid = Invalid arguments
|
||||
|
||||
abuse_category = Category
|
||||
abuse_category.placeholder = Please select a category
|
||||
abuse_category.spam = Spam
|
||||
abuse_category.malware = Malware
|
||||
abuse_category.illegal_content = Illegal content
|
||||
abuse_category.other_violations = Other violations of platform rules
|
||||
|
||||
report_remarks = Remarks
|
||||
report_user = Report user
|
||||
report_user.detail = Are you sure you that this user committed an abuse and you want to report them?<br>TODO: Reason dropdown<br>TODO: Remarks textarea
|
||||
report_remarks.placeholder = Please provide some details regarding the abuse you are reporting.
|
||||
|
||||
submit_report = Submit report
|
||||
reported_thank_you = Thank you for your report. An administrator will look into it shortly.
|
||||
|
||||
[translation_meta]
|
||||
test = This is a test string. It is not displayed in Forgejo UI but is used for testing purposes. Feel free to enter "ok" to save time (or a fun fact of your choice) to hit that sweet 100% completion mark :)
|
||||
|
|
89
routers/web/moderation/report.go
Normal file
89
routers/web/moderation/report.go
Normal file
|
@ -0,0 +1,89 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package moderation
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/models/moderation"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
"code.gitea.io/gitea/modules/log"
|
||||
"code.gitea.io/gitea/modules/web"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
"code.gitea.io/gitea/services/forms"
|
||||
)
|
||||
|
||||
const (
|
||||
tplSubmitAbuseReport base.TplName = "moderation/new_abuse_report"
|
||||
)
|
||||
|
||||
// NewReport renders the page for new abuse reports.
|
||||
func NewReport(ctx *context.Context) {
|
||||
contentID := ctx.FormInt64("id")
|
||||
if contentID <= 0 {
|
||||
ctx.RenderWithErr(ctx.Tr("moderation.report_abuse_form.invalid"), tplSubmitAbuseReport, nil)
|
||||
log.Warn("The content ID is expected to be an integer greater that 0; the provided value is %d.", contentID)
|
||||
return
|
||||
}
|
||||
|
||||
contentTypeString := ctx.FormString("type")
|
||||
var contentType moderation.ReportedContentType
|
||||
switch contentTypeString {
|
||||
case "user", "org":
|
||||
contentType = moderation.ReportedContentTypeUser
|
||||
case "repo":
|
||||
contentType = moderation.ReportedContentTypeRepository
|
||||
case "issue", "pull":
|
||||
contentType = moderation.ReportedContentTypeIssue
|
||||
case "comment":
|
||||
contentType = moderation.ReportedContentTypeComment
|
||||
default:
|
||||
ctx.RenderWithErr(ctx.Tr("moderation.report_abuse_form.invalid"), tplSubmitAbuseReport, nil)
|
||||
log.Warn("The provided content type `%s` is not among the expected values.", contentTypeString)
|
||||
return
|
||||
}
|
||||
|
||||
setContextDataAndRender(ctx, contentType, contentID)
|
||||
}
|
||||
|
||||
// setContextDataAndRender adds some values into context data and renders the new abuse report page.
|
||||
func setContextDataAndRender(ctx *context.Context, contentType moderation.ReportedContentType, contentID int64) {
|
||||
ctx.Data["Title"] = ctx.Tr("moderation.report_abuse")
|
||||
ctx.Data["ContentID"] = contentID
|
||||
ctx.Data["ContentType"] = contentType
|
||||
ctx.Data["AbuseCategories"] = moderation.GetAbuseCategoriesList()
|
||||
ctx.Data["CancelLink"] = ctx.Doer.DashboardLink()
|
||||
ctx.HTML(http.StatusOK, tplSubmitAbuseReport)
|
||||
}
|
||||
|
||||
// CreatePost handles the POST for creating a new abuse report.
|
||||
func CreatePost(ctx *context.Context) {
|
||||
form := *web.GetForm(ctx).(*forms.ReportAbuseForm)
|
||||
|
||||
if form.ContentID <= 0 || form.ContentType == 0 {
|
||||
ctx.RenderWithErr(ctx.Tr("moderation.report_abuse_form.invalid"), tplSubmitAbuseReport, nil)
|
||||
return
|
||||
}
|
||||
|
||||
if ctx.HasError() {
|
||||
setContextDataAndRender(ctx, form.ContentType, form.ContentID)
|
||||
return
|
||||
}
|
||||
|
||||
report := moderation.AbuseReport{
|
||||
ReporterID: ctx.Doer.ID,
|
||||
ContentType: form.ContentType,
|
||||
ContentID: form.ContentID,
|
||||
Category: form.AbuseCategory,
|
||||
Remarks: form.Remarks,
|
||||
}
|
||||
|
||||
if err := moderation.ReportAbuse(ctx, &report); err != nil {
|
||||
ctx.ServerError("Something went wrong while trying to submit the new abuse report.", err)
|
||||
return
|
||||
}
|
||||
|
||||
ctx.Flash.Success(ctx.Tr("moderation.reported_thank_you"))
|
||||
ctx.Redirect(ctx.Doer.DashboardLink())
|
||||
}
|
|
@ -13,7 +13,7 @@ import (
|
|||
|
||||
activities_model "code.gitea.io/gitea/models/activities"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
"code.gitea.io/gitea/models/moderation"
|
||||
|
||||
repo_model "code.gitea.io/gitea/models/repo"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/base"
|
||||
|
@ -360,8 +360,6 @@ func Action(ctx *context.Context) {
|
|||
err = user_service.BlockUser(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
|
||||
case "unblock":
|
||||
err = user_model.UnblockUser(ctx, ctx.Doer.ID, ctx.ContextUser.ID)
|
||||
case "report":
|
||||
err = moderation.ReportUser(ctx, ctx.Doer.ID, ctx.ContextUser.ID, "{remarks not implemented}")
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2017 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package web
|
||||
|
@ -33,6 +34,7 @@ import (
|
|||
"code.gitea.io/gitea/routers/web/feed"
|
||||
"code.gitea.io/gitea/routers/web/healthcheck"
|
||||
"code.gitea.io/gitea/routers/web/misc"
|
||||
"code.gitea.io/gitea/routers/web/moderation"
|
||||
"code.gitea.io/gitea/routers/web/org"
|
||||
org_setting "code.gitea.io/gitea/routers/web/org/setting"
|
||||
"code.gitea.io/gitea/routers/web/repo"
|
||||
|
@ -479,6 +481,9 @@ func registerRoutes(m *web.Route) {
|
|||
m.Get("/search", repo.SearchIssues)
|
||||
}, reqSignIn)
|
||||
|
||||
m.Get("/-/abuse_reports/new", moderation.NewReport, reqSignIn)
|
||||
m.Post("/-/abuse_reports/new", web.Bind(forms.ReportAbuseForm{}), moderation.CreatePost, reqSignIn)
|
||||
|
||||
m.Get("/pulls", reqSignIn, user.Pulls)
|
||||
m.Get("/milestones", reqSignIn, reqMilestonesDashboardPageEnabled, user.Milestones)
|
||||
|
||||
|
|
28
services/forms/report_abuse.go
Normal file
28
services/forms/report_abuse.go
Normal file
|
@ -0,0 +1,28 @@
|
|||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
package forms
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"code.gitea.io/gitea/models/moderation"
|
||||
"code.gitea.io/gitea/modules/web/middleware"
|
||||
"code.gitea.io/gitea/services/context"
|
||||
|
||||
"code.forgejo.org/go-chi/binding"
|
||||
)
|
||||
|
||||
// ReportAbuseForm is used to interact with the UI of the form that submits new abuse reports.
|
||||
type ReportAbuseForm struct {
|
||||
ContentID int64
|
||||
ContentType moderation.ReportedContentType
|
||||
AbuseCategory moderation.AbuseCategoryType `binding:"Required" locale:"moderation.abuse_category"`
|
||||
Remarks string `binding:"Required;MinSize(20);MaxSize(500)" preprocess:"TrimSpace" locale:"moderation.report_remarks"`
|
||||
}
|
||||
|
||||
// Validate validates the fields of ReportAbuseForm.
|
||||
func (f *ReportAbuseForm) Validate(req *http.Request, errs binding.Errors) binding.Errors {
|
||||
ctx := context.GetValidateContext(req)
|
||||
return middleware.Validate(errs, ctx.Data, f, ctx.Locale)
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||
// Copyright 2025 The Forgejo Authors. All rights reserved.
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
package user
|
||||
|
@ -216,6 +217,7 @@ func deleteUser(ctx context.Context, u *user_model.User, purge bool) (err error)
|
|||
}
|
||||
// ***** END: ExternalLoginUser *****
|
||||
|
||||
// If the user was reported as abusive, a shadow copy should be created before deletion.
|
||||
if err = user_model.IfNeededCreateShadowCopyForUser(ctx, u); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
43
templates/moderation/new_abuse_report.tmpl
Normal file
43
templates/moderation/new_abuse_report.tmpl
Normal file
|
@ -0,0 +1,43 @@
|
|||
{{template "base/head" .}}
|
||||
<div role="main" aria-label="{{.Title}}" class="page-content organization new org">
|
||||
<div class="ui middle very relaxed page grid">
|
||||
<div class="column">
|
||||
<form class="ui form" action="{{.Link}}" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<h3 class="ui top attached header">
|
||||
{{ctx.Locale.Tr "moderation.report_abuse_form.header"}}
|
||||
</h3>
|
||||
<div class="ui attached segment">
|
||||
{{template "base/alert" .}}
|
||||
<p class="ui center">{{ctx.Locale.Tr "moderation.report_abuse_form.details"}}</p>
|
||||
|
||||
<input type="hidden" name="content_id" value="{{.ContentID}}" />
|
||||
<input type="hidden" name="content_type" value="{{.ContentType}}" />
|
||||
|
||||
<fieldset>
|
||||
<label{{if .Err_AbuseCategory}} class="error"{{end}}>
|
||||
{{ctx.Locale.Tr "moderation.abuse_category"}}
|
||||
<select class="ui selection dropdown" id="abuse_category" name="abuse_category" required autofocus>
|
||||
<option value="">{{ctx.Locale.Tr "moderation.abuse_category.placeholder"}}</option>
|
||||
{{range $cat := .AbuseCategories}}
|
||||
<option value="{{$cat.Value}}"{{if eq $.abuse_category $cat.Value}} selected{{end}}>{{ctx.Locale.Tr $cat.TranslationKey}}</option>
|
||||
{{end}}
|
||||
</select>
|
||||
</label>
|
||||
<label{{if .Err_Remarks}} class="error"{{end}}>
|
||||
{{ctx.Locale.Tr "moderation.report_remarks"}}
|
||||
<textarea id="remarks" name="remarks" required minlength="20" maxlength="500" placeholder="{{ctx.Locale.Tr "moderation.report_remarks.placeholder"}}">{{.remarks}}</textarea>
|
||||
</label>
|
||||
</fieldset>
|
||||
|
||||
<div class="divider"></div>
|
||||
<div class="text right actions">
|
||||
<a class="ui cancel button" href="{{$.CancelLink}}">{{ctx.Locale.Tr "cancel"}}</a>
|
||||
<button class="ui primary button"{{if not .ContentID}} disabled{{end}}>{{ctx.Locale.Tr "moderation.submit_report"}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{template "base/footer" .}}
|
|
@ -67,6 +67,12 @@
|
|||
{{if not $.DisableForks}}
|
||||
{{template "repo/header_fork" $}}
|
||||
{{end}}
|
||||
<button class="ui small compact jump dropdown icon button"{{if not $.IsSigned}} disabled{{end}} data-tooltip-content="{{ctx.Locale.Tr "repo.more_operations"}}" aria-label="{{ctx.Locale.Tr "toggle_menu"}}">
|
||||
{{svg "octicon-kebab-horizontal"}}
|
||||
<div class="menu top left">
|
||||
<a class="item context" href="/-/abuse_reports/new?type=repo&id={{$.Repository.ID}}">{{ctx.Locale.Tr "moderation.report_content"}}</a>
|
||||
</div>
|
||||
</button>
|
||||
</div>
|
||||
{{end}}
|
||||
</div>
|
||||
|
|
|
@ -172,8 +172,6 @@
|
|||
|
||||
{{template "repo/issue/view_content/reference_issue_dialog" .}}
|
||||
|
||||
{{template "repo/issue/view_content/report_comment_dialog" .}}
|
||||
|
||||
<div class="tw-hidden" id="no-content">
|
||||
<span class="no-content">{{ctx.Locale.Tr "repo.issues.no_content"}}</span>
|
||||
</div>
|
||||
|
|
|
@ -24,8 +24,12 @@
|
|||
{{end}}
|
||||
{{end}}
|
||||
{{if and .ctxData.IsSigned (not .IsCommentPoster)}}
|
||||
{{$contentType := "comment"}}
|
||||
{{if eq .item .ctxData.Issue}}
|
||||
{{if .ctxData.Issue.IsPull}} {{$contentType = "pull"}} {{else}} {{$contentType = "issue"}} {{end}}
|
||||
{{end}}
|
||||
<div class="divider"></div>
|
||||
<div class="item context js-aria-clickable report-comment" data-target="{{.item.HashTag}}-raw" data-modal="#report-comment-modal" data-repo-url="{{.ctxData.RepoLink}}" data-comment-id="{{.item.ID}}">{{ctx.Locale.Tr "moderation.report_abuse"}}</div>
|
||||
<a class="item context" href="/-/abuse_reports/new?type={{$contentType}}&id={{.item.ID}}">{{ctx.Locale.Tr "moderation.report_content"}}</a>
|
||||
{{end}}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
<div class="ui small modal" id="report-comment-modal">
|
||||
<div class="header">
|
||||
{{ctx.Locale.Tr "moderation.report_comment"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<form class="ui form" id="report-comment-form" action="" method="post">
|
||||
{{.CsrfTokenHtml}}
|
||||
<input type="hidden" name="comment-id" />
|
||||
<div class="inline required field">
|
||||
<label><strong>{{ctx.Locale.Tr "moderation.report_remarks"}}</strong></label>
|
||||
<textarea name="remarks"></textarea>
|
||||
</div>
|
||||
<div class="text right">
|
||||
<button class="ui primary button">{{ctx.Locale.Tr "moderation.report_comment"}}</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
|
@ -124,9 +124,7 @@
|
|||
{{end}}
|
||||
</li>
|
||||
<li class="block" hx-target="#profile-avatar-card" hx-indicator="#profile-avatar-card">
|
||||
<button type="submit" {{if $.IsReported}} disabled {{end}} class="ui basic orange button" data-modal-id="report-user" hx-post="{{.ContextUser.HomeLink}}?action=report" hx-confirm="-">
|
||||
{{svg "octicon-blocked"}} {{ctx.Locale.Tr "moderation.report"}}
|
||||
</button>
|
||||
<a {{if $.IsReported}}disabled {{end}}class="ui basic orange button" href="/-/abuse_reports/new?type=user&id={{.ContextUser.ID}}">{{ctx.Locale.Tr "moderation.report_abuse"}}</a>
|
||||
</li>
|
||||
{{end}}
|
||||
</ul>
|
||||
|
|
|
@ -77,14 +77,4 @@
|
|||
{{template "base/modal_actions_confirm" .}}
|
||||
</div>
|
||||
|
||||
<div class="ui g-modal-confirm delete modal" id="report-user">
|
||||
<div class="header">
|
||||
{{ctx.Locale.Tr "moderation.report_user"}}
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>{{ctx.Locale.Tr "moderation.report_user.detail"}}</p>
|
||||
</div>
|
||||
{{template "base/modal_actions_confirm" .}}
|
||||
</div>
|
||||
|
||||
{{template "base/footer" .}}
|
||||
|
|
|
@ -599,21 +599,6 @@ export function initRepoIssueReferenceIssue() {
|
|||
});
|
||||
}
|
||||
|
||||
export function initRepoIssueReportComment() {
|
||||
// Report abusive comment
|
||||
$(document).on('click', '.report-comment', function (event) {
|
||||
const $this = $(this);
|
||||
const repo_url = $this.data('repo-url');
|
||||
const comment_id = $this.data('comment-id');
|
||||
const $modal = $($this.data('modal'));
|
||||
$modal.find('#report-comment-form').attr('action',`${repo_url}/comments/${comment_id}/report`);
|
||||
$modal.find('input[name="comment-id"]').val(`${comment_id}`);
|
||||
$modal.modal('show');
|
||||
|
||||
event.preventDefault();
|
||||
});
|
||||
}
|
||||
|
||||
export function initRepoIssueWipToggle() {
|
||||
// Toggle WIP
|
||||
$('.toggle-wip a, .toggle-wip button').on('click', async (e) => {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import $ from 'jquery';
|
||||
import {
|
||||
initRepoIssueBranchSelect, initRepoIssueCodeCommentCancel, initRepoIssueCommentDelete,
|
||||
initRepoIssueComments, initRepoIssueDependencyDelete, initRepoIssueReferenceIssue, initRepoIssueReportComment,
|
||||
initRepoIssueComments, initRepoIssueDependencyDelete, initRepoIssueReferenceIssue,
|
||||
initRepoIssueTitleEdit, initRepoIssueWipToggle,
|
||||
initRepoPullRequestUpdate, updateIssuesMeta, handleReply, initIssueTemplateCommentEditors, initSingleCommentEditor,
|
||||
initRepoIssueAssignMe, reloadConfirmDraftComment,
|
||||
|
@ -561,7 +561,6 @@ export function initRepository() {
|
|||
|
||||
initRepoDiffConversationNav();
|
||||
initRepoIssueReferenceIssue();
|
||||
initRepoIssueReportComment();
|
||||
|
||||
initRepoIssueCommentDelete();
|
||||
initRepoIssueDependencyDelete();
|
||||
|
|
Loading…
Reference in a new issue