Browse Source

Merge pull request 'search_trusted_props' (#118) from search_trusted_props into dev_mirocod

Reviewed-on: http://git.mirocod.ru/MIROCOD/Platform_Mirocod/pulls/118
dev_mirocod
parent
commit
d2c4d13988
  1. 33
      models/user/search.go
  2. 3
      models/user/user.go
  3. 3
      options/locale/locale_ru-RU.ini
  4. 33
      routers/web/explore/competence.go
  5. 33
      routers/web/explore/interest.go
  6. 33
      routers/web/explore/resource.go
  7. 21
      routers/web/explore/user.go
  8. 39
      routers/web/user/profile.go
  9. 3
      routers/web/web.go
  10. 39
      templates/explore/competences.tmpl
  11. 39
      templates/explore/interests.tmpl
  12. 9
      templates/explore/navbar.tmpl
  13. 39
      templates/explore/resources.tmpl

33
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})
}

3
models/user/user.go

@ -46,6 +46,9 @@ const (
// UserTypeOrganization defines an organization
UserTypeOrganization
// UserTypeIdentity defines individual + organization
UserTypeIdentity
)
const (

3
options/locale/locale_ru-RU.ini

@ -259,6 +259,9 @@ users=Пользователи
organizations=Сообщества
search=Поиск
code=Файлы
competences=Компетенции
resources=Ресурсы
interests=Интересы
search.fuzzy=Неточный
search.match=Соответствие
repo_no_results=Подходящие проекты не найдены.

33
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)
}

33
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)
}

33
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)
}

21
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

39
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
}

3
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)

39
templates/explore/competences.tmpl

@ -0,0 +1,39 @@
{{template "base/head" .}}
<div class="page-content explore">
{{template "explore/navbar" .}}
<div class="ui container">
{{template "explore/search" .}}
<div class="ui user list">
{{range .Users}}
<div class="item">
{{avatar .}}
<div class="content">
<span class="header"><a href="{{.HomeLink}}">{{.Name}}</a> {{.FullName}}</span>
<div class="description">
{{if .Location}}
{{svg "octicon-location"}} {{.Location}} ({{.LocationCoordinate}})
{{end}}
{{if and $.ShowUserEmail .Email $.IsSigned (not .KeepEmailPrivate)}}
{{svg "octicon-mail"}}
<a href="mailto:{{.Email}}" rel="nofollow">{{.Email}}</a>
{{end}}
{{svg "octicon-clock"}} {{$.i18n.Tr "user.join_on"}} {{.CreatedUnix.FormatShort}}
{{if .Competences}}
<h4>{{$.i18n.Tr "explore.competences"}}:</h4>
<div>{{(index $.RenderedContent .ID)|Str2html}}</div>
{{end}}
</div>
</div>
</div>
{{else}}
<div>{{$.i18n.Tr "explore.user_no_results"}}</div>
{{end}}
</div>
{{template "base/paginate" .}}
</div>
</div>
{{template "base/footer" .}}

39
templates/explore/interests.tmpl

@ -0,0 +1,39 @@
{{template "base/head" .}}
<div class="page-content explore">
{{template "explore/navbar" .}}
<div class="ui container">
{{template "explore/search" .}}
<div class="ui user list">
{{range .Users}}
<div class="item">
{{avatar .}}
<div class="content">
<span class="header"><a href="{{.HomeLink}}">{{.Name}}</a> {{.FullName}}</span>
<div class="description">
{{if .Location}}
{{svg "octicon-location"}} {{.Location}} ({{.LocationCoordinate}})
{{end}}
{{if and $.ShowUserEmail .Email $.IsSigned (not .KeepEmailPrivate)}}
{{svg "octicon-mail"}}
<a href="mailto:{{.Email}}" rel="nofollow">{{.Email}}</a>
{{end}}
{{svg "octicon-clock"}} {{$.i18n.Tr "user.join_on"}} {{.CreatedUnix.FormatShort}}
{{if .Interests}}
<h4>{{$.i18n.Tr "explore.interests"}}:</h4>
<div>{{(index $.RenderedContent .ID)|Str2html}}</div>
{{end}}
</div>
</div>
</div>
{{else}}
<div>{{$.i18n.Tr "explore.user_no_results"}}</div>
{{end}}
</div>
{{template "base/paginate" .}}
</div>
</div>
{{template "base/footer" .}}

9
templates/explore/navbar.tmpl

@ -15,4 +15,13 @@
{{svg "octicon-code"}} {{.i18n.Tr "explore.code"}}
</a>
{{end}}
<a class="{{if .PageIsExploreCompetences}}active{{end}} item" href="{{AppSubUrl}}/explore/competences">
{{svg "octicon-book"}} {{.i18n.Tr "explore.competences"}}
</a>
<a class="{{if .PageIsExploreResources}}active{{end}} item" href="{{AppSubUrl}}/explore/resources">
{{svg "octicon-briefcase"}} {{.i18n.Tr "explore.resources"}}
</a>
<a class="{{if .PageIsExploreInterests}}active{{end}} item" href="{{AppSubUrl}}/explore/interests">
{{svg "octicon-code-of-conduct"}} {{.i18n.Tr "explore.interests"}}
</a>
</div>

39
templates/explore/resources.tmpl

@ -0,0 +1,39 @@
{{template "base/head" .}}
<div class="page-content explore">
{{template "explore/navbar" .}}
<div class="ui container">
{{template "explore/search" .}}
<div class="ui user list">
{{range .Users}}
<div class="item">
{{avatar .}}
<div class="content">
<span class="header"><a href="{{.HomeLink}}">{{.Name}}</a> {{.FullName}}</span>
<div class="description">
{{if .Location}}
{{svg "octicon-location"}} {{.Location}} ({{.LocationCoordinate}})
{{end}}
{{if and $.ShowUserEmail .Email $.IsSigned (not .KeepEmailPrivate)}}
{{svg "octicon-mail"}}
<a href="mailto:{{.Email}}" rel="nofollow">{{.Email}}</a>
{{end}}
{{svg "octicon-clock"}} {{$.i18n.Tr "user.join_on"}} {{.CreatedUnix.FormatShort}}
{{if .Resources}}
<h4>{{$.i18n.Tr "explore.resources"}}:</h4>
<div>{{(index $.RenderedContent .ID)|Str2html}}</div>
{{end}}
</div>
</div>
</div>
{{else}}
<div>{{$.i18n.Tr "explore.user_no_results"}}</div>
{{end}}
</div>
{{template "base/paginate" .}}
</div>
</div>
{{template "base/footer" .}}
Loading…
Cancel
Save