diff --git a/models/user/search.go b/models/user/search.go index 24a21777e8..4edb4c9f03 100644 --- a/models/user/search.go +++ b/models/user/search.go @@ -17,6 +17,15 @@ import ( "xorm.io/xorm" ) +type SearchKind int64 + +const ( + ByDescription SearchKind = iota + ByCompetence + ByResource + ByInterest +) + // SearchUserOptions contains the options for searching type SearchUserOptions struct { db.ListOptions @@ -28,6 +37,7 @@ type SearchUserOptions struct { Visible []structs.VisibleType Actor *User // The user doing the search SearchByEmail bool // Search by email as well as username/full name + Kind SearchKind IsActive util.OptionalBool IsAdmin util.OptionalBool @@ -39,14 +49,33 @@ type SearchUserOptions struct { } func (opts *SearchUserOptions) toSearchQueryBase() *xorm.Session { - var cond builder.Cond = builder.Eq{"type": opts.Type} + var cond builder.Cond + if opts.Type == UserTypeIdentity { + cond = builder.Or( + builder.Eq{"type": UserTypeIndividual}, + builder.Eq{"type": UserTypeOrganization}, + ) + } else { + cond = builder.Eq{"type": opts.Type} + } if len(opts.Keyword) > 0 { lowerKeyword := strings.ToLower(opts.Keyword) keywordCond := builder.Or( builder.Like{"lower_name", lowerKeyword}, builder.Like{"LOWER(full_name)", lowerKeyword}, - builder.Like{"LOWER(description)", lowerKeyword}, ) + switch opts.Kind { + case ByDescription: + keywordCond = builder.Or(builder.Like{"LOWER(description)", lowerKeyword}) + case ByCompetence: + keywordCond = builder.Or(builder.Like{"LOWER(competences)", lowerKeyword}) + case ByResource: + keywordCond = builder.Or(builder.Like{"LOWER(resources)", lowerKeyword}) + case ByInterest: + keywordCond = builder.Or(builder.Like{"LOWER(interests)", lowerKeyword}) + default: + keywordCond = builder.Or(builder.Like{"LOWER(description)", lowerKeyword}) + } if opts.SearchByEmail { keywordCond = keywordCond.Or(builder.Like{"LOWER(email)", lowerKeyword}) } diff --git a/models/user/user.go b/models/user/user.go index 5ce5d3cbd5..9270951449 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -46,6 +46,9 @@ const ( // UserTypeOrganization defines an organization UserTypeOrganization + + // UserTypeIdentity defines individual + organization + UserTypeIdentity ) const ( diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index c7a318409c..4bc3f3faf8 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -259,6 +259,9 @@ users=Пользователи organizations=Сообщества search=Поиск code=Файлы +competences=Компетенции +resources=Ресурсы +interests=Интересы search.fuzzy=Неточный search.match=Соответствие repo_no_results=Подходящие проекты не найдены. diff --git a/routers/web/explore/competence.go b/routers/web/explore/competence.go new file mode 100644 index 0000000000..20eaaa38c5 --- /dev/null +++ b/routers/web/explore/competence.go @@ -0,0 +1,33 @@ +package explore + +import ( + "code.gitea.io/gitea/models/db" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" +) + +const ( + tplExploreCompetences base.TplName = "explore/competences" +) + +func Competences(ctx *context.Context) { + ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage + ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled + ctx.Data["Title"] = ctx.Tr("explore") + ctx.Data["PageIsExplore"] = true + ctx.Data["PageIsExploreCompetences"] = true + + RenderUserSearch(ctx, &user_model.SearchUserOptions{ + Actor: ctx.User, + Type: user_model.UserTypeIdentity, + ListOptions: db.ListOptions{PageSize: setting.UI.ExplorePagingNum}, + IsActive: util.OptionalBoolTrue, + Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, + Kind: user_model.ByCompetence, + }, tplExploreCompetences) + +} diff --git a/routers/web/explore/interest.go b/routers/web/explore/interest.go new file mode 100644 index 0000000000..071b989f36 --- /dev/null +++ b/routers/web/explore/interest.go @@ -0,0 +1,33 @@ +package explore + +import ( + "code.gitea.io/gitea/models/db" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" +) + +const ( + tplExploreInterests base.TplName = "explore/interests" +) + +func Interests(ctx *context.Context) { + ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage + ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled + ctx.Data["Title"] = ctx.Tr("explore") + ctx.Data["PageIsExplore"] = true + ctx.Data["PageIsExploreInterests"] = true + + RenderUserSearch(ctx, &user_model.SearchUserOptions{ + Actor: ctx.User, + Type: user_model.UserTypeIdentity, + ListOptions: db.ListOptions{PageSize: setting.UI.ExplorePagingNum}, + IsActive: util.OptionalBoolTrue, + Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, + Kind: user_model.ByInterest, + }, tplExploreInterests) + +} diff --git a/routers/web/explore/resource.go b/routers/web/explore/resource.go new file mode 100644 index 0000000000..f13300bbf0 --- /dev/null +++ b/routers/web/explore/resource.go @@ -0,0 +1,33 @@ +package explore + +import ( + "code.gitea.io/gitea/models/db" + user_model "code.gitea.io/gitea/models/user" + "code.gitea.io/gitea/modules/base" + "code.gitea.io/gitea/modules/context" + "code.gitea.io/gitea/modules/setting" + "code.gitea.io/gitea/modules/structs" + "code.gitea.io/gitea/modules/util" +) + +const ( + tplExploreResources base.TplName = "explore/resources" +) + +func Resources(ctx *context.Context) { + ctx.Data["UsersIsDisabled"] = setting.Service.Explore.DisableUsersPage + ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled + ctx.Data["Title"] = ctx.Tr("explore") + ctx.Data["PageIsExplore"] = true + ctx.Data["PageIsExploreResources"] = true + + RenderUserSearch(ctx, &user_model.SearchUserOptions{ + Actor: ctx.User, + Type: user_model.UserTypeIdentity, + ListOptions: db.ListOptions{PageSize: setting.UI.ExplorePagingNum}, + IsActive: util.OptionalBoolTrue, + Visible: []structs.VisibleType{structs.VisibleTypePublic, structs.VisibleTypeLimited, structs.VisibleTypePrivate}, + Kind: user_model.ByResource, + }, tplExploreResources) + +} diff --git a/routers/web/explore/user.go b/routers/web/explore/user.go index 5973a4e066..cecb4578eb 100644 --- a/routers/web/explore/user.go +++ b/routers/web/explore/user.go @@ -6,6 +6,7 @@ package explore import ( "bytes" + "code.gitea.io/gitea/routers/web/user" "net/http" "code.gitea.io/gitea/models/db" @@ -78,6 +79,26 @@ func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions, ctx.Data["Keyword"] = opts.Keyword ctx.Data["Total"] = count ctx.Data["Users"] = users + var renderedContent = make(map[int64]string) + var contentFieldName string + switch opts.Kind { + case user_model.ByCompetence: + contentFieldName = "Competences" + case user_model.ByResource: + contentFieldName = "Resources" + case user_model.ByInterest: + contentFieldName = "Interests" + default: + contentFieldName = "Description" + } + for _, curUser := range users { + renderedContent[curUser.ID], err = user.GetRenderedTextField(ctx, curUser, contentFieldName) + if err != nil { + ctx.ServerError("RenderContent", err) + return + } + } + ctx.Data["RenderedContent"] = renderedContent ctx.Data["UsersTwoFaStatus"] = user_model.UserList(users).GetTwoFaStatus() ctx.Data["ShowUserEmail"] = setting.UI.ShowUserEmail ctx.Data["IsRepoIndexerEnabled"] = setting.Indexer.RepoIndexerEnabled diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index 2ad333a6af..90fafb871e 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -159,28 +159,39 @@ func Profile(ctx *context.Context) { ctx.Data["HeatmapData"] = data } - var renderErr error + var ( + renderErr error + content string + ) - renderErr = getRenderedTextField(ctx, ctxUser, "Description") - if renderErr != nil { + content, renderErr = GetRenderedTextField(ctx, ctxUser, "Description") + if renderErr == nil { + ctx.Data["RenderedDescription"] = content + } else { ctx.ServerError("RenderString", renderErr) return } - renderErr = getRenderedTextField(ctx, ctxUser, "Competences") - if renderErr != nil { + content, renderErr = GetRenderedTextField(ctx, ctxUser, "Competences") + if renderErr == nil { + ctx.Data["RenderedCompetences"] = content + } else { ctx.ServerError("RenderString", renderErr) return } - renderErr = getRenderedTextField(ctx, ctxUser, "Resources") - if renderErr != nil { + content, renderErr = GetRenderedTextField(ctx, ctxUser, "Resources") + if renderErr == nil { + ctx.Data["RenderedResources"] = content + } else { ctx.ServerError("RenderString", renderErr) return } - renderErr = getRenderedTextField(ctx, ctxUser, "Interests") - if renderErr != nil { + content, renderErr = GetRenderedTextField(ctx, ctxUser, "Interests") + if renderErr == nil { + ctx.Data["RenderedInterests"] = content + } else { ctx.ServerError("RenderString", renderErr) return } @@ -391,13 +402,13 @@ func Action(ctx *context.Context) { ctx.RedirectToFirst(ctx.FormString("redirect_to"), u.HomeLink()) } -func getTextField(user *user_model.User, fieldName string) string { +func getTextField(user interface{}, fieldName string) string { reflectedObj := reflect.ValueOf(user) dynamicField := reflect.Indirect(reflectedObj).FieldByName(fieldName) return dynamicField.String() } -func getRenderedTextField(ctx *context.Context, ctxUser *user_model.User, fieldName string) error { +func GetRenderedTextField(ctx *context.Context, ctxUser interface{}, fieldName string) (string, error) { var err error = nil var content string fieldVal := getTextField(ctxUser, fieldName) @@ -408,10 +419,6 @@ func getRenderedTextField(ctx *context.Context, ctxUser *user_model.User, fieldN GitRepo: ctx.Repo.GitRepo, Ctx: ctx, }, fieldVal) - if err == nil { - renderedFieldName := fmt.Sprintf("Rendered%s", fieldName) - ctx.Data[renderedFieldName] = content - } } - return err + return content, err } diff --git a/routers/web/web.go b/routers/web/web.go index 1810185425..171d5c0e81 100644 --- a/routers/web/web.go +++ b/routers/web/web.go @@ -254,6 +254,9 @@ func RegisterRoutes(m *web.Route) { m.Get("/users", explore.Users) m.Get("/organizations", explore.Organizations) m.Get("/code", explore.Code) + m.Get("/competences", explore.Competences) + m.Get("/resources", explore.Resources) + m.Get("/interests", explore.Interests) }, ignExploreSignIn) m.Group("/map", func() { m.Get("/umap", umap.UsersMap) diff --git a/templates/explore/competences.tmpl b/templates/explore/competences.tmpl new file mode 100644 index 0000000000..e49159f579 --- /dev/null +++ b/templates/explore/competences.tmpl @@ -0,0 +1,39 @@ +{{template "base/head" .}} + +