diff --git a/models/migrations/migrations.go b/models/migrations/migrations.go index 6dff3e055b..4e27af4d73 100644 --- a/models/migrations/migrations.go +++ b/models/migrations/migrations.go @@ -373,6 +373,8 @@ var migrations = []Migration{ NewMigration("Increase WebAuthentication CredentialID size to 410 - NO-OPED", increaseCredentialIDTo410), // v210 -> v211 NewMigration("v208 was completely broken - remigrate", remigrateU2FCredentials), + // v211 -> v212 + NewMigration("add competences, resources, interests to user tbl", addTrustedPropsToUser), } // GetCurrentDBVersion returns the current db version diff --git a/models/migrations/v211.go b/models/migrations/v211.go new file mode 100644 index 0000000000..7a72b4b20a --- /dev/null +++ b/models/migrations/v211.go @@ -0,0 +1,28 @@ +package migrations + +import ( + "fmt" + "xorm.io/xorm" + "xorm.io/xorm/schemas" +) + +func addTrustedPropsToUser(engine *xorm.Engine) error { + var err error + tableName := "user" + switch engine.Dialect().URI().DBType { + case schemas.POSTGRES: + addColsQuery := fmt.Sprintf("ALTER TABLE \"%s\" ADD COLUMN competences TEXT, ADD COLUMN resources TEXT, ADD COLUMN interests TEXT;", tableName) + _, err = engine.Exec(addColsQuery) + case schemas.SQLITE: + addColsQuery := fmt.Sprintf("ALTER TABLE \"%s\" ADD COLUMN competences TEXT;\nALTER TABLE \"%s\" ADD COLUMN resources TEXT;\nALTER TABLE \"%s\" ADD COLUMN interests TEXT;", tableName, tableName, tableName) + _, err = engine.Exec(addColsQuery) + case schemas.MYSQL: + addColsQuery := fmt.Sprintf("ALTER TABLE `%s` ADD COLUMN competences TEXT, ADD COLUMN resources TEXT, ADD COLUMN interests TEXT;", tableName) + _, err = engine.Exec(addColsQuery) + } + if err != nil { + return fmt.Errorf("Ошибка добавление колонок компетенций и тд: %v", err) + } else { + return nil + } +} diff --git a/models/user/user.go b/models/user/user.go index ac70c242b5..5ce5d3cbd5 100644 --- a/models/user/user.go +++ b/models/user/user.go @@ -100,6 +100,9 @@ type User struct { Salt string `xorm:"VARCHAR(32)"` Language string `xorm:"VARCHAR(5)"` Description string `xorm:"TEXT"` + Competences string `xorm:"TEXT"` + Resources string `xorm:"TEXT"` + Interests string `xorm:"TEXT"` CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"` diff --git a/options/locale/locale_ru-RU.ini b/options/locale/locale_ru-RU.ini index 7a3a9bb10d..c7a318409c 100644 --- a/options/locale/locale_ru-RU.ini +++ b/options/locale/locale_ru-RU.ini @@ -494,6 +494,9 @@ follow=Подписаться unfollow=Отписаться heatmap.loading=Загрузка тепловой карты… user_bio=О себе +user_competences=Компетенции +user_resources=Ресурсы +user_interests=Интересы disabled_public_activity=Этот пользователь отключил публичную видимость активности. form.name_reserved=Имя пользователя '%s' зарезервировано. @@ -2201,6 +2204,8 @@ lower_repositories=Проекты create_new_team=Создание команды create_team=Создать команду org_desc=Описание +org_competences=Компетенции +org_resources=Ресурсы team_name=Название команды team_desc=Описание team_name_helper=Названия команд должны быть короткими и запоминающимися. diff --git a/routers/web/admin/users.go b/routers/web/admin/users.go index 4b94fe9e10..7cb7e9c8d9 100644 --- a/routers/web/admin/users.go +++ b/routers/web/admin/users.go @@ -372,6 +372,9 @@ func EditUserPost(ctx *context.Context) { u.Email = form.Email u.Website = form.Website u.Description = form.Description + u.Competences = form.Competences + u.Resources = form.Resources + u.Interests = form.Interests u.Location = form.Location u.LocationCoordinate = form.LocationCoordinate u.MaxRepoCreation = form.MaxRepoCreation diff --git a/routers/web/org/home.go b/routers/web/org/home.go index 4967ce0e99..13c4b1c73d 100644 --- a/routers/web/org/home.go +++ b/routers/web/org/home.go @@ -5,7 +5,9 @@ package org import ( + "fmt" "net/http" + "reflect" "strings" "code.gitea.io/gitea/models" @@ -46,17 +48,24 @@ func Home(ctx *context.Context) { ctx.Data["PageIsUserProfile"] = true ctx.Data["Title"] = org.DisplayName() - if len(org.Description) != 0 { - desc, err := markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.Repo.RepoLink, - Metas: map[string]string{"mode": "document"}, - GitRepo: ctx.Repo.GitRepo, - }, org.Description) - if err != nil { - ctx.ServerError("RenderString", err) - return - } - ctx.Data["RenderedDescription"] = desc + + var renderErr error + renderErr = getRenderedTextField(ctx, org, "Description") + if renderErr != nil { + ctx.ServerError("RenderString", renderErr) + return + } + + renderErr = getRenderedTextField(ctx, org, "Competences") + if renderErr != nil { + ctx.ServerError("RenderString", renderErr) + return + } + + renderErr = getRenderedTextField(ctx, org, "Resources") + if renderErr != nil { + ctx.ServerError("RenderString", renderErr) + return } var orderBy db.SearchOrderBy @@ -159,3 +168,32 @@ func Home(ctx *context.Context) { ctx.HTML(http.StatusOK, tplOrgHome) } + +func getTextField(user *models.Organization, fieldName string) string { + reflectedObj := reflect.ValueOf(user) + dynamicField := reflect.Indirect(reflectedObj).FieldByName(fieldName) + return dynamicField.String() +} + +/** +Приходится дублировать код, т.к. не получилось вынести эту функцию и функцию getTextField в services, +т.к. modules/context/context.go зависит от models/user. +*/ +func getRenderedTextField(ctx *context.Context, ctxUser *models.Organization, fieldName string) error { + var err error = nil + var content string + fieldVal := getTextField(ctxUser, fieldName) + if len(fieldVal) != 0 { + content, err = markdown.RenderString(&markup.RenderContext{ + URLPrefix: ctx.Repo.RepoLink, + Metas: map[string]string{"mode": "document"}, + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, + }, fieldVal) + if err == nil { + renderedFieldName := fmt.Sprintf("Rendered%s", fieldName) + ctx.Data[renderedFieldName] = content + } + } + return err +} diff --git a/routers/web/org/setting.go b/routers/web/org/setting.go index 16f83f8b80..0f50eac54b 100644 --- a/routers/web/org/setting.go +++ b/routers/web/org/setting.go @@ -98,6 +98,8 @@ func SettingsPost(ctx *context.Context) { org.FullName = form.FullName org.Description = form.Description + org.Competences = form.Competences + org.Resources = form.Resources org.Website = form.Website org.Location = form.Location org.LocationCoordinate = form.LocationCoordinate diff --git a/routers/web/user/profile.go b/routers/web/user/profile.go index 40fc44ed14..2ad333a6af 100644 --- a/routers/web/user/profile.go +++ b/routers/web/user/profile.go @@ -9,6 +9,7 @@ import ( "fmt" "net/http" "path" + "reflect" "strings" "code.gitea.io/gitea/models" @@ -158,18 +159,30 @@ func Profile(ctx *context.Context) { ctx.Data["HeatmapData"] = data } - if len(ctxUser.Description) != 0 { - content, err := markdown.RenderString(&markup.RenderContext{ - URLPrefix: ctx.Repo.RepoLink, - Metas: map[string]string{"mode": "document"}, - GitRepo: ctx.Repo.GitRepo, - Ctx: ctx, - }, ctxUser.Description) - if err != nil { - ctx.ServerError("RenderString", err) - return - } - ctx.Data["RenderedDescription"] = content + var renderErr error + + renderErr = getRenderedTextField(ctx, ctxUser, "Description") + if renderErr != nil { + ctx.ServerError("RenderString", renderErr) + return + } + + renderErr = getRenderedTextField(ctx, ctxUser, "Competences") + if renderErr != nil { + ctx.ServerError("RenderString", renderErr) + return + } + + renderErr = getRenderedTextField(ctx, ctxUser, "Resources") + if renderErr != nil { + ctx.ServerError("RenderString", renderErr) + return + } + + renderErr = getRenderedTextField(ctx, ctxUser, "Interests") + if renderErr != nil { + ctx.ServerError("RenderString", renderErr) + return } showPrivate := ctx.IsSigned && (ctx.User.IsAdmin || ctx.User.ID == ctxUser.ID) @@ -377,3 +390,28 @@ func Action(ctx *context.Context) { // FIXME: We should check this URL and make sure that it's a valid Gitea URL ctx.RedirectToFirst(ctx.FormString("redirect_to"), u.HomeLink()) } + +func getTextField(user *user_model.User, 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 { + var err error = nil + var content string + fieldVal := getTextField(ctxUser, fieldName) + if len(fieldVal) != 0 { + content, err = markdown.RenderString(&markup.RenderContext{ + URLPrefix: ctx.Repo.RepoLink, + Metas: map[string]string{"mode": "document"}, + GitRepo: ctx.Repo.GitRepo, + Ctx: ctx, + }, fieldVal) + if err == nil { + renderedFieldName := fmt.Sprintf("Rendered%s", fieldName) + ctx.Data[renderedFieldName] = content + } + } + return err +} diff --git a/routers/web/user/setting/profile.go b/routers/web/user/setting/profile.go index ddc5a7c47d..255318a8c9 100644 --- a/routers/web/user/setting/profile.go +++ b/routers/web/user/setting/profile.go @@ -121,6 +121,9 @@ func ProfilePost(ctx *context.Context) { ctx.User.Location = form.Location ctx.User.LocationCoordinate = form.LocationCoordinate ctx.User.Description = form.Description + ctx.User.Competences = form.Competences + ctx.User.Resources = form.Resources + ctx.User.Interests = form.Interests ctx.User.KeepActivityPrivate = form.KeepActivityPrivate ctx.User.Visibility = form.Visibility if err := user_model.UpdateUserSetting(ctx.User); err != nil { diff --git a/services/forms/admin.go b/services/forms/admin.go index 8a4aaaed50..94e487ee0d 100644 --- a/services/forms/admin.go +++ b/services/forms/admin.go @@ -42,6 +42,9 @@ type AdminEditUserForm struct { Password string `binding:"MaxSize(255)"` Website string `binding:"ValidUrl;MaxSize(255)"` Description string `binding:"MaxSize(1024)"` + Competences string `binding:"MaxSize(1024)"` + Resources string `binding:"MaxSize(1024)"` + Interests string `binding:"MaxSize(1024)"` Location string `binding:"MaxSize(50)"` LocationCoordinate string `binding:"MaxSize(255)"` MaxRepoCreation int diff --git a/services/forms/org.go b/services/forms/org.go index a5a0b06d7b..9d73f029a1 100644 --- a/services/forms/org.go +++ b/services/forms/org.go @@ -40,6 +40,8 @@ type UpdateOrgSettingForm struct { Name string `binding:"Required;AlphaDashDot;MaxSize(40)" locale:"org.org_name_holder"` FullName string `binding:"MaxSize(100)"` Description string `binding:"MaxSize(1024)"` + Competences string `binding:"MaxSize(1024)"` + Resources string `binding:"MaxSize(1024)"` Website string `binding:"ValidUrl;MaxSize(255)"` Location string `binding:"MaxSize(50)"` LocationCoordinate string `binding:"MaxSize(255)"` diff --git a/services/forms/user_form.go b/services/forms/user_form.go index 1ea967ca1b..00d9cba093 100644 --- a/services/forms/user_form.go +++ b/services/forms/user_form.go @@ -247,6 +247,9 @@ type UpdateProfileForm struct { Location string `binding:"MaxSize(50)"` LocationCoordinate string `binding:"MaxSize(255)"` Description string `binding:"MaxSize(1024)"` + Competences string `binding:"MaxSize(1024)"` + Resources string `binding:"MaxSize(1024)"` + Interests string `binding:"MaxSize(1024)"` Visibility structs.VisibleType KeepActivityPrivate bool } diff --git a/templates/admin/user/edit.tmpl b/templates/admin/user/edit.tmpl index 7487baf947..518fc1bda2 100644 --- a/templates/admin/user/edit.tmpl +++ b/templates/admin/user/edit.tmpl @@ -77,6 +77,18 @@ +
{{$.RenderedDescription|Str2html}}
{{end}} + {{if $.RenderedDescription}} +{{$.RenderedDescription|Str2html}}
+ {{end}} + {{if $.RenderedCompetences}} +{{$.RenderedCompetences|Str2html}}
+ {{end}} + {{if $.RenderedResources}} +{{$.RenderedResources|Str2html}}
+ {{end}} +