Browse Source

Merge pull request 'project_requirements' (#120) from project_requirements into dev_mirocod

Указывать для проекта доверительные свойства и находить подходящие лица #65
Reviewed-on: http://git.mirocod.ru/MIROCOD/Platform_Mirocod/pulls/120
Reviewed-by: Алексей Безбородов <alexeibv+mirocod@narod.ru>
dev_mirocod
parent
commit
9fc208802b
  1. 4
      models/migrations/migrations.go
  2. 28
      models/migrations/v212.go
  3. 28
      models/migrations/v213.go
  4. 3
      models/repo/repo.go
  5. 3
      options/locale/locale_ru-RU.ini
  6. 2
      routers/web/explore/user.go
  7. 26
      routers/web/repo/competence.go
  8. 70
      routers/web/repo/resource.go
  9. 3
      routers/web/repo/setting.go
  10. 24
      routers/web/user/profile.go
  11. 2
      routers/web/web.go
  12. 37
      services/forms/repo_form.go
  13. 11
      templates/repo/competences/list.tmpl
  14. 16
      templates/repo/header.tmpl
  15. 11
      templates/repo/resources/list.tmpl
  16. 12
      templates/repo/settings/options.tmpl

4
models/migrations/migrations.go

@ -375,6 +375,10 @@ var migrations = []Migration{
NewMigration("v208 was completely broken - remigrate", remigrateU2FCredentials),
// v211 -> v212
NewMigration("add competences, resources, interests to user tbl", addTrustedPropsToUser),
// v212 -> v213
NewMigration("add competences and resources to repo tbl", addTrustedPropsToRepo),
// v213 -> v214
NewMigration("add location_coordinate to repo tbl", addLocationCoordinateToRepo),
}
// GetCurrentDBVersion returns the current db version

28
models/migrations/v212.go

@ -0,0 +1,28 @@
package migrations
import (
"fmt"
"xorm.io/xorm"
"xorm.io/xorm/schemas"
)
func addTrustedPropsToRepo(engine *xorm.Engine) error {
var err error
tableName := "repository"
switch engine.Dialect().URI().DBType {
case schemas.POSTGRES:
addColsQuery := fmt.Sprintf("ALTER TABLE \"%s\" ADD COLUMN competences TEXT, ADD COLUMN resources 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;", tableName, tableName)
_, err = engine.Exec(addColsQuery)
case schemas.MYSQL:
addColsQuery := fmt.Sprintf("ALTER TABLE `%s` ADD COLUMN competences TEXT, ADD COLUMN resources TEXT;", tableName)
_, err = engine.Exec(addColsQuery)
}
if err != nil {
return fmt.Errorf("Ошибка добавления колонок компетенции и ресурсы в проект: %v", err)
} else {
return nil
}
}

28
models/migrations/v213.go

@ -0,0 +1,28 @@
package migrations
import (
"fmt"
"xorm.io/xorm"
"xorm.io/xorm/schemas"
)
func addLocationCoordinateToRepo(engine *xorm.Engine) error {
var err error
tableName := "repository"
switch engine.Dialect().URI().DBType {
case schemas.POSTGRES:
addColsQuery := fmt.Sprintf("ALTER TABLE \"%s\" ADD COLUMN location_coordinates VARCHAR(1024);", tableName)
_, err = engine.Exec(addColsQuery)
case schemas.SQLITE:
addColsQuery := fmt.Sprintf("ALTER TABLE \"%s\" ADD COLUMN location_coordinates TEXT;", tableName)
_, err = engine.Exec(addColsQuery)
case schemas.MYSQL:
addColsQuery := fmt.Sprintf("ALTER TABLE `%s` ADD COLUMN location_coordinates VARCHAR(1024);", tableName)
_, err = engine.Exec(addColsQuery)
}
if err != nil {
return fmt.Errorf("Ошибка добавления колонок компетенции и ресурсы в проект: %v", err)
} else {
return nil
}
}

3
models/repo/repo.go

@ -100,7 +100,10 @@ type Repository struct {
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
Name string `xorm:"INDEX NOT NULL"`
Description string `xorm:"TEXT"`
Resources string `xorm:"TEXT"`
Competences string `xorm:"TEXT"`
Website string `xorm:"VARCHAR(2048)"`
LocationCoordinates string `xorm:"VARCHAR(1024)"`
OriginalServiceType api.GitServiceType `xorm:"index"`
OriginalURL string `xorm:"VARCHAR(2048)"`
DefaultBranch string

3
options/locale/locale_ru-RU.ini

@ -804,6 +804,8 @@ download_bundle=Скачать BUNDLE
generate_repo=Создать проект
generate_from=Создать из
repo_desc=Описание
resources=Ресурсы
competences=Компетенции
repo_desc_helper=Добавьте краткое описание (необязательно)
repo_lang=Язык
repo_gitignore_helper=Выберите шаблон .gitignore.
@ -1717,6 +1719,7 @@ settings.email_notifications.onmention=Посылать письмо на эл.
settings.email_notifications.disable=Отключить почтовые уведомления
settings.email_notifications.submit=Установить настройки электронной почты
settings.site=Сайт
settings.location_coordinates=Координаты
settings.update_settings=Обновить настройки
settings.branches.update_default_branch=Обновить ветку по умолчанию
settings.advanced_settings=Расширенные настройки

2
routers/web/explore/user.go

@ -92,7 +92,7 @@ func RenderUserSearch(ctx *context.Context, opts *user_model.SearchUserOptions,
contentFieldName = "Description"
}
for _, curUser := range users {
renderedContent[curUser.ID], err = user.GetRenderedTextField(ctx, curUser, contentFieldName)
renderedContent[curUser.ID], err = user.GetRenderedTextFieldByName(ctx, curUser, contentFieldName)
if err != nil {
ctx.ServerError("RenderContent", err)
return

26
routers/web/repo/competence.go

@ -0,0 +1,26 @@
package repo
import (
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"net/http"
)
const (
tplCompetences base.TplName = "repo/competences/list"
)
func Competences(ctx *context.Context) {
ctx.Data["PageIsCompetences"] = true
repo := ctx.Data["Repository"]
var err error
ctx.Data["RenderedCompetences"], err = GetRenderedTrustPropsWithSearchLinks(ctx, repo, "Competences")
if err != nil {
ctx.ServerError("Render", err)
return
}
ctx.HTML(http.StatusOK, tplCompetences)
}

70
routers/web/repo/resource.go

@ -0,0 +1,70 @@
package repo
import (
"code.gitea.io/gitea/modules/base"
"code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/routers/web/user"
"fmt"
"net/http"
"regexp"
"strings"
)
const (
tplResources base.TplName = "repo/resources/list"
)
func Resources(ctx *context.Context) {
ctx.Data["PageIsResources"] = true
repo := ctx.Data["Repository"]
var err error
ctx.Data["RenderedResources"], err = GetRenderedTrustPropsWithSearchLinks(ctx, repo, "Resources")
if err != nil {
ctx.ServerError("Render", err)
return
}
ctx.HTML(http.StatusOK, tplResources)
}
func GetRenderedTrustPropsWithSearchLinks(ctx *context.Context, repo interface{}, fieldName string) (string, error) {
trustProps := user.GetTextField(repo, fieldName)
var regExp *regexp.Regexp
var err error
regExp, err = regexp.Compile(`- \[ \] (.+)`)
if err != nil {
return "", err
}
trustPropNamesMatches := regExp.FindAllStringSubmatch(trustProps, -1)
var transformedTrustProps string
if trustPropNamesMatches == nil {
transformedTrustProps = trustProps
} else {
transformedTrustProps = strings.Clone(trustProps)
var trustPropName string
var searchQS string
for _, curTrustPropNameMatches := range trustPropNamesMatches {
trustPropName = curTrustPropNameMatches[1]
searchQS = strings.ReplaceAll(trustPropName, " ", "+")
trustPropSubstitutionPattern := fmt.Sprintf(
`- [ ] %s [найти](/explore/%s?tab=&q=%s)`,
trustPropName,
strings.ToLower(fieldName),
searchQS)
transformedTrustProps = strings.Replace(transformedTrustProps, curTrustPropNameMatches[0], trustPropSubstitutionPattern, -1)
}
}
var renderedTrustPropsWithSafeURLs string
renderedTrustPropsWithSafeURLs, err = user.GetRenderedTextFieldByValue(ctx, repo, transformedTrustProps)
renderedTrustPropsWithTargetBlank := strings.ReplaceAll(renderedTrustPropsWithSafeURLs, "<a", "<a target='blank'")
return renderedTrustPropsWithTargetBlank, err
}

3
routers/web/repo/setting.go

@ -151,7 +151,10 @@ func SettingsPost(ctx *context.Context) {
repo.Name = newRepoName
repo.LowerName = strings.ToLower(newRepoName)
repo.Description = form.Description
repo.Resources = form.Resources
repo.Competences = form.Competences
repo.Website = form.Website
repo.LocationCoordinates = form.LocationCoordinates
repo.IsTemplate = form.Template
// Visibility of forked repository is forced sync with base repository.

24
routers/web/user/profile.go

@ -164,7 +164,7 @@ func Profile(ctx *context.Context) {
content string
)
content, renderErr = GetRenderedTextField(ctx, ctxUser, "Description")
content, renderErr = GetRenderedTextFieldByName(ctx, ctxUser, "Description")
if renderErr == nil {
ctx.Data["RenderedDescription"] = content
} else {
@ -172,7 +172,7 @@ func Profile(ctx *context.Context) {
return
}
content, renderErr = GetRenderedTextField(ctx, ctxUser, "Competences")
content, renderErr = GetRenderedTextFieldByName(ctx, ctxUser, "Competences")
if renderErr == nil {
ctx.Data["RenderedCompetences"] = content
} else {
@ -180,7 +180,7 @@ func Profile(ctx *context.Context) {
return
}
content, renderErr = GetRenderedTextField(ctx, ctxUser, "Resources")
content, renderErr = GetRenderedTextFieldByName(ctx, ctxUser, "Resources")
if renderErr == nil {
ctx.Data["RenderedResources"] = content
} else {
@ -188,7 +188,7 @@ func Profile(ctx *context.Context) {
return
}
content, renderErr = GetRenderedTextField(ctx, ctxUser, "Interests")
content, renderErr = GetRenderedTextFieldByName(ctx, ctxUser, "Interests")
if renderErr == nil {
ctx.Data["RenderedInterests"] = content
} else {
@ -402,16 +402,24 @@ func Action(ctx *context.Context) {
ctx.RedirectToFirst(ctx.FormString("redirect_to"), u.HomeLink())
}
func getTextField(user interface{}, fieldName string) string {
reflectedObj := reflect.ValueOf(user)
func GetTextField(obj interface{}, fieldName string) string {
reflectedObj := reflect.ValueOf(obj)
dynamicField := reflect.Indirect(reflectedObj).FieldByName(fieldName)
return dynamicField.String()
}
func GetRenderedTextField(ctx *context.Context, ctxUser interface{}, fieldName string) (string, error) {
func GetRenderedTextFieldByName(ctx *context.Context, obj interface{}, fieldName string) (string, error) {
var err error = nil
var content string
fieldVal := getTextField(ctxUser, fieldName)
fieldVal := GetTextField(obj, fieldName)
content, err = GetRenderedTextFieldByValue(ctx, obj, fieldVal)
return content, err
}
func GetRenderedTextFieldByValue(ctx *context.Context, obj interface{}, fieldVal string) (string, error) {
var content string
var err error
if len(fieldVal) != 0 {
content, err = markdown.RenderString(&markup.RenderContext{
URLPrefix: ctx.Repo.RepoLink,

2
routers/web/web.go

@ -890,6 +890,8 @@ func RegisterRoutes(m *web.Route) {
m.Group("", func() {
m.Get("/{type:issues|pulls}", repo.Issues)
m.Get("/issues_tree", repo.IssuesTree)
m.Get("/resources", repo.Resources)
m.Get("/competences", repo.Competences)
m.Get("/{type:issues|pulls}/{index}", repo.ViewIssue)
m.Group("/{type:issues|pulls}/{index}/content-history", func() {
m.Get("/overview", repo.GetContentHistoryOverview)

37
services/forms/repo_form.go

@ -113,23 +113,26 @@ func ParseRemoteAddr(remoteAddr, authUsername, authPassword string) (string, err
// RepoSettingForm form for changing repository settings
type RepoSettingForm struct {
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
Description string `binding:"MaxSize(255)"`
Website string `binding:"ValidUrl;MaxSize(255)"`
Interval string
MirrorAddress string
MirrorUsername string
MirrorPassword string
LFS bool `form:"mirror_lfs"`
LFSEndpoint string `form:"mirror_lfs_endpoint"`
PushMirrorID string
PushMirrorAddress string
PushMirrorUsername string
PushMirrorPassword string
PushMirrorInterval string
Private bool
Template bool
EnablePrune bool
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
Description string `binding:"MaxSize(255)"`
Resources string
Competences string
Website string `binding:"ValidUrl;MaxSize(255)"`
LocationCoordinates string `binding:"MaxSize(1024)"`
Interval string
MirrorAddress string
MirrorUsername string
MirrorPassword string
LFS bool `form:"mirror_lfs"`
LFSEndpoint string `form:"mirror_lfs_endpoint"`
PushMirrorID string
PushMirrorAddress string
PushMirrorUsername string
PushMirrorPassword string
PushMirrorInterval string
Private bool
Template bool
EnablePrune bool
// Advanced settings
EnableWiki bool

11
templates/repo/competences/list.tmpl

@ -0,0 +1,11 @@
{{template "base/head" .}}
<div class="page-content repository">
{{template "repo/header" .}}
<div class="ui container">
<h1>{{.i18n.Tr "repo.competences"}}</h1>
<div>
{{$.RenderedCompetences | Str2html}}
</div>
</div>
</div>
{{template "base/footer" .}}

16
templates/repo/header.tmpl

@ -152,7 +152,7 @@
{{svg "octicon-book"}} {{.i18n.Tr "repo.wiki"}}
</a>
{{end}}
{{if .Permission.CanRead $.UnitTypeIssues}}
<a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoLink}}/issues">
{{svg "octicon-issue-opened"}} {{.i18n.Tr "repo.issues"}}
@ -162,6 +162,18 @@
</a>
{{end}}
{{if .Repository.Resources}}
<a class="{{if .PageIsResources}}active{{end}} item" href="{{.RepoLink}}/resources">
{{svg "octicon-briefcase"}} {{.i18n.Tr "repo.resources"}}
</a>
{{end}}
{{if .Repository.Competences}}
<a class="{{if .PageIsCompetences}}active{{end}} item" href="{{.RepoLink}}/competences">
{{svg "octicon-multi-select"}} {{.i18n.Tr "repo.competences"}}
</a>
{{end}}
{{if .Permission.CanRead $.UnitTypeExternalTracker}}
<a class="{{if .PageIsIssueList}}active{{end}} item" href="{{.RepoExternalIssuesLink}}" target="_blank" rel="noopener noreferrer">
{{svg "octicon-link-external"}} {{.i18n.Tr "repo.issues"}} </span>
@ -176,7 +188,7 @@
{{end}}
</a>
{{ end }}
{{if .Permission.CanRead $.UnitTypeCode}}
<a class="{{if .PageIsViewCode}}active{{end}} item" href="{{.RepoLink}}{{if (ne .BranchName .Repository.DefaultBranch)}}/src/{{.BranchNameSubURL}}{{else}}/code{{end}}">
{{svg "octicon-code"}} {{.i18n.Tr "repo.code"}}

11
templates/repo/resources/list.tmpl

@ -0,0 +1,11 @@
{{template "base/head" .}}
<div class="page-content repository">
{{template "repo/header" .}}
<div class="ui container">
<h1>{{.i18n.Tr "repo.resources"}}</h1>
<div>
{{$.RenderedResources | Str2html}}
</div>
</div>
</div>
{{template "base/footer" .}}

12
templates/repo/settings/options.tmpl

@ -44,10 +44,22 @@
<label for="description">{{$.i18n.Tr "repo.repo_desc"}}</label>
<textarea id="description" name="description" rows="2">{{.Repository.Description}}</textarea>
</div>
<div class="field {{if .Err_Resources}}error{{end}}">
<label for="resources">{{$.i18n.Tr "repo.resources"}}</label>
<textarea id="resources" name="resources" rows="6">{{.Repository.Resources}}</textarea>
</div>
<div class="field {{if .Err_Competences}}error{{end}}">
<label for="competences">{{$.i18n.Tr "repo.competences"}}</label>
<textarea id="competences" name="competences" rows="6">{{.Repository.Competences}}</textarea>
</div>
<div class="field {{if .Err_Website}}error{{end}}">
<label for="website">{{.i18n.Tr "repo.settings.site"}}</label>
<input id="website" name="website" type="url" value="{{.Repository.Website}}">
</div>
<div class="field {{if .Err_LocationCoordinates}}error{{end}}">
<label for="location_coordinates">{{.i18n.Tr "repo.settings.location_coordinates"}}</label>
<input id="location_coordinates" name="location_coordinates" value="{{.Repository.LocationCoordinates}}" placeholder="55.4, 37.3">
</div>
<div class="field">
<button class="ui green button">{{$.i18n.Tr "repo.settings.update_settings"}}</button>

Loading…
Cancel
Save