mirror of https://github.com/gogs/gogs.git
repo: update repository description field to contain more than 256 symbols (#5219)
* Update repository description field to contain more than 256 symbols - update repository model - description field now is `TEXT` and limited by 4000 symbols - new migration - add description to html forms - repo creation and repo settings - add translation for description * Update for description field, new features - add autosize (height) for description textarea, new plugin - set max description length to 512 symbols - update locales * Fix migration - typo in var * Update repo description behaviour - add textarea autosize for /repo/create - add symbols counter under description testarea (create/edit) * Fix function definition - it a var * Revert ru-RU locale * Update by review - Use type `varchar(512)` in migration - Remove unused files from autosize plugin * Fix migration - new project paths * Fixes after review 2 - copyright year - format includes - use switch instead of multi-if * Remove unused `default:` option.pull/5293/head
parent
459c8be94f
commit
57897cc8c2
|
@ -421,6 +421,8 @@ mirror_last_synced = Last Synced
|
||||||
watchers = Watchers
|
watchers = Watchers
|
||||||
stargazers = Stargazers
|
stargazers = Stargazers
|
||||||
forks = Forks
|
forks = Forks
|
||||||
|
repo_description_helper = Description of repository. Maximum 512 characters length.
|
||||||
|
repo_description_length = Available characters
|
||||||
|
|
||||||
form.reach_limit_of_creation = The owner has reached maximum creation limit of %d repositories.
|
form.reach_limit_of_creation = The owner has reached maximum creation limit of %d repositories.
|
||||||
form.name_reserved = Repository name '%s' is reserved.
|
form.name_reserved = Repository name '%s' is reserved.
|
||||||
|
@ -856,6 +858,8 @@ settings.add_key_success = New deploy key '%s' has been added successfully!
|
||||||
settings.deploy_key_deletion = Delete Deploy Key
|
settings.deploy_key_deletion = Delete Deploy Key
|
||||||
settings.deploy_key_deletion_desc = Deleting this deploy key will remove all related accesses for this repository. Do you want to continue?
|
settings.deploy_key_deletion_desc = Deleting this deploy key will remove all related accesses for this repository. Do you want to continue?
|
||||||
settings.deploy_key_deletion_success = Deploy key has been deleted successfully!
|
settings.deploy_key_deletion_success = Deploy key has been deleted successfully!
|
||||||
|
settings.description_desc = Description of repository. Maximum 512 characters length.
|
||||||
|
settings.description_length = Available characters
|
||||||
|
|
||||||
diff.browse_source = Browse Source
|
diff.browse_source = Browse Source
|
||||||
diff.parent = parent
|
diff.parent = parent
|
||||||
|
|
|
@ -64,6 +64,8 @@ var migrations = []Migration{
|
||||||
NewMigration("update repository sizes", updateRepositorySizes),
|
NewMigration("update repository sizes", updateRepositorySizes),
|
||||||
// v16 -> v17:v0.10.31
|
// v16 -> v17:v0.10.31
|
||||||
NewMigration("remove invalid protect branch whitelist", removeInvalidProtectBranchWhitelist),
|
NewMigration("remove invalid protect branch whitelist", removeInvalidProtectBranchWhitelist),
|
||||||
|
// v17 -> v18:v0.11.48
|
||||||
|
NewMigration("store long text in repository description field", updateRepositoryDescriptionField),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Migrate database to current version
|
// Migrate database to current version
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
// Copyright 2018 The Gogs Authors. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT-style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package migrations
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/go-xorm/xorm"
|
||||||
|
|
||||||
|
"github.com/gogs/gogs/pkg/setting"
|
||||||
|
)
|
||||||
|
|
||||||
|
func updateRepositoryDescriptionField(x *xorm.Engine) error {
|
||||||
|
exist, err := x.IsTableExist("repository")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("IsTableExist: %v", err)
|
||||||
|
} else if !exist {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
switch {
|
||||||
|
case setting.UseMySQL:
|
||||||
|
_, err = x.Exec("ALTER TABLE `repository` MODIFY `description` VARCHAR(512);")
|
||||||
|
case setting.UseMSSQL:
|
||||||
|
_, err = x.Exec("ALTER TABLE `repository` ALTER COLUMN `description` VARCHAR(512);")
|
||||||
|
case setting.UsePostgreSQL:
|
||||||
|
_, err = x.Exec("ALTER TABLE `repository` ALTER COLUMN `description` TYPE VARCHAR(512);")
|
||||||
|
case setting.UseSQLite3:
|
||||||
|
// Sqlite3 uses TEXT type by default for any string type field.
|
||||||
|
// Keep this comment to mention that we don't missed any option.
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
|
@ -146,7 +146,7 @@ type Repository struct {
|
||||||
Owner *User `xorm:"-" json:"-"`
|
Owner *User `xorm:"-" json:"-"`
|
||||||
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
LowerName string `xorm:"UNIQUE(s) INDEX NOT NULL"`
|
||||||
Name string `xorm:"INDEX NOT NULL"`
|
Name string `xorm:"INDEX NOT NULL"`
|
||||||
Description string
|
Description string `xorm:"VARCHAR(512)"`
|
||||||
Website string
|
Website string
|
||||||
DefaultBranch string
|
DefaultBranch string
|
||||||
Size int64 `xorm:"NOT NULL DEFAULT 0"`
|
Size int64 `xorm:"NOT NULL DEFAULT 0"`
|
||||||
|
@ -1331,8 +1331,8 @@ func GetRepositoriesByForkID(forkID int64) ([]*Repository, error) {
|
||||||
func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err error) {
|
func updateRepository(e Engine, repo *Repository, visibilityChanged bool) (err error) {
|
||||||
repo.LowerName = strings.ToLower(repo.Name)
|
repo.LowerName = strings.ToLower(repo.Name)
|
||||||
|
|
||||||
if len(repo.Description) > 255 {
|
if len(repo.Description) > 512 {
|
||||||
repo.Description = repo.Description[:255]
|
repo.Description = repo.Description[:512]
|
||||||
}
|
}
|
||||||
if len(repo.Website) > 255 {
|
if len(repo.Website) > 255 {
|
||||||
repo.Website = repo.Website[:255]
|
repo.Website = repo.Website[:255]
|
||||||
|
|
|
@ -26,7 +26,7 @@ type CreateRepo struct {
|
||||||
UserID int64 `binding:"Required"`
|
UserID int64 `binding:"Required"`
|
||||||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
||||||
Private bool
|
Private bool
|
||||||
Description string `binding:"MaxSize(255)"`
|
Description string `binding:"MaxSize(512)"`
|
||||||
AutoInit bool
|
AutoInit bool
|
||||||
Gitignores string
|
Gitignores string
|
||||||
License string
|
License string
|
||||||
|
@ -45,7 +45,7 @@ type MigrateRepo struct {
|
||||||
RepoName string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"`
|
RepoName string `json:"repo_name" binding:"Required;AlphaDashDot;MaxSize(100)"`
|
||||||
Mirror bool `json:"mirror"`
|
Mirror bool `json:"mirror"`
|
||||||
Private bool `json:"private"`
|
Private bool `json:"private"`
|
||||||
Description string `json:"description" binding:"MaxSize(255)"`
|
Description string `json:"description" binding:"MaxSize(512)"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *MigrateRepo) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
func (f *MigrateRepo) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
|
||||||
|
@ -82,7 +82,7 @@ func (f MigrateRepo) ParseRemoteAddr(user *models.User) (string, error) {
|
||||||
|
|
||||||
type RepoSetting struct {
|
type RepoSetting struct {
|
||||||
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
RepoName string `binding:"Required;AlphaDashDot;MaxSize(100)"`
|
||||||
Description string `binding:"MaxSize(255)"`
|
Description string `binding:"MaxSize(512)"`
|
||||||
Website string `binding:"Url;MaxSize(100)"`
|
Website string `binding:"Url;MaxSize(100)"`
|
||||||
Branch string
|
Branch string
|
||||||
Interval int
|
Interval int
|
||||||
|
|
|
@ -1443,3 +1443,24 @@ $(function () {
|
||||||
if ($('.user.signin').length > 0) return;
|
if ($('.user.signin').length > 0) return;
|
||||||
$('form').areYouSure();
|
$('form').areYouSure();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function showMessageMaxLength(maxLen, textElemId, counterId) {
|
||||||
|
var $msg = $('#'+textElemId); //text message
|
||||||
|
$('#'+counterId).html(maxLen - $msg.val().length); //symbols count
|
||||||
|
|
||||||
|
var onMessageKey = function (e) {
|
||||||
|
var $msg = $(this);
|
||||||
|
var text = $msg.val();
|
||||||
|
var len = text.length;
|
||||||
|
var remainder = maxLen - len;
|
||||||
|
|
||||||
|
if (len >= maxLen) {
|
||||||
|
$msg.val($msg.val().substr(0, maxLen));
|
||||||
|
remainder = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
$('#'+counterId).html(remainder);
|
||||||
|
};
|
||||||
|
|
||||||
|
$msg.keyup(onMessageKey).keydown(onMessageKey);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
/*!
|
||||||
|
autosize 4.0.2
|
||||||
|
license: MIT
|
||||||
|
http://www.jacklmoore.com/autosize
|
||||||
|
*/
|
||||||
|
!function(e,t){if("function"==typeof define&&define.amd)define(["module","exports"],t);else if("undefined"!=typeof exports)t(module,exports);else{var n={exports:{}};t(n,n.exports),e.autosize=n.exports}}(this,function(e,t){"use strict";var n,o,p="function"==typeof Map?new Map:(n=[],o=[],{has:function(e){return-1<n.indexOf(e)},get:function(e){return o[n.indexOf(e)]},set:function(e,t){-1===n.indexOf(e)&&(n.push(e),o.push(t))},delete:function(e){var t=n.indexOf(e);-1<t&&(n.splice(t,1),o.splice(t,1))}}),c=function(e){return new Event(e,{bubbles:!0})};try{new Event("test")}catch(e){c=function(e){var t=document.createEvent("Event");return t.initEvent(e,!0,!1),t}}function r(r){if(r&&r.nodeName&&"TEXTAREA"===r.nodeName&&!p.has(r)){var e,n=null,o=null,i=null,d=function(){r.clientWidth!==o&&a()},l=function(t){window.removeEventListener("resize",d,!1),r.removeEventListener("input",a,!1),r.removeEventListener("keyup",a,!1),r.removeEventListener("autosize:destroy",l,!1),r.removeEventListener("autosize:update",a,!1),Object.keys(t).forEach(function(e){r.style[e]=t[e]}),p.delete(r)}.bind(r,{height:r.style.height,resize:r.style.resize,overflowY:r.style.overflowY,overflowX:r.style.overflowX,wordWrap:r.style.wordWrap});r.addEventListener("autosize:destroy",l,!1),"onpropertychange"in r&&"oninput"in r&&r.addEventListener("keyup",a,!1),window.addEventListener("resize",d,!1),r.addEventListener("input",a,!1),r.addEventListener("autosize:update",a,!1),r.style.overflowX="hidden",r.style.wordWrap="break-word",p.set(r,{destroy:l,update:a}),"vertical"===(e=window.getComputedStyle(r,null)).resize?r.style.resize="none":"both"===e.resize&&(r.style.resize="horizontal"),n="content-box"===e.boxSizing?-(parseFloat(e.paddingTop)+parseFloat(e.paddingBottom)):parseFloat(e.borderTopWidth)+parseFloat(e.borderBottomWidth),isNaN(n)&&(n=0),a()}function s(e){var t=r.style.width;r.style.width="0px",r.offsetWidth,r.style.width=t,r.style.overflowY=e}function u(){if(0!==r.scrollHeight){var e=function(e){for(var t=[];e&&e.parentNode&&e.parentNode instanceof Element;)e.parentNode.scrollTop&&t.push({node:e.parentNode,scrollTop:e.parentNode.scrollTop}),e=e.parentNode;return t}(r),t=document.documentElement&&document.documentElement.scrollTop;r.style.height="",r.style.height=r.scrollHeight+n+"px",o=r.clientWidth,e.forEach(function(e){e.node.scrollTop=e.scrollTop}),t&&(document.documentElement.scrollTop=t)}}function a(){u();var e=Math.round(parseFloat(r.style.height)),t=window.getComputedStyle(r,null),n="content-box"===t.boxSizing?Math.round(parseFloat(t.height)):r.offsetHeight;if(n<e?"hidden"===t.overflowY&&(s("scroll"),u(),n="content-box"===t.boxSizing?Math.round(parseFloat(window.getComputedStyle(r,null).height)):r.offsetHeight):"hidden"!==t.overflowY&&(s("hidden"),u(),n="content-box"===t.boxSizing?Math.round(parseFloat(window.getComputedStyle(r,null).height)):r.offsetHeight),i!==n){i=n;var o=c("autosize:resized");try{r.dispatchEvent(o)}catch(e){}}}}function i(e){var t=p.get(e);t&&t.destroy()}function d(e){var t=p.get(e);t&&t.update()}var l=null;"undefined"==typeof window||"function"!=typeof window.getComputedStyle?((l=function(e){return e}).destroy=function(e){return e},l.update=function(e){return e}):((l=function(e,t){return e&&Array.prototype.forEach.call(e.length?e:[e],function(e){return r(e)}),e}).destroy=function(e){return e&&Array.prototype.forEach.call(e.length?e:[e],i),e},l.update=function(e){return e&&Array.prototype.forEach.call(e.length?e:[e],d),e}),t.default=l,e.exports=t.default});
|
|
@ -75,6 +75,7 @@ func Create(c *context.Context) {
|
||||||
c.Data["readme"] = "Default"
|
c.Data["readme"] = "Default"
|
||||||
c.Data["private"] = c.User.LastRepoVisibility
|
c.Data["private"] = c.User.LastRepoVisibility
|
||||||
c.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
|
c.Data["IsForcedPrivate"] = setting.Repository.ForcePrivate
|
||||||
|
c.Data["RequireAutosize"] = true
|
||||||
|
|
||||||
ctxUser := checkContextUser(c, c.QueryInt64("org"))
|
ctxUser := checkContextUser(c, c.QueryInt64("org"))
|
||||||
if c.Written() {
|
if c.Written() {
|
||||||
|
|
|
@ -34,6 +34,7 @@ const (
|
||||||
func Settings(c *context.Context) {
|
func Settings(c *context.Context) {
|
||||||
c.Title("repo.settings")
|
c.Title("repo.settings")
|
||||||
c.PageIs("SettingsOptions")
|
c.PageIs("SettingsOptions")
|
||||||
|
c.Data["RequireAutosize"] = true
|
||||||
c.Success(SETTINGS_OPTIONS)
|
c.Success(SETTINGS_OPTIONS)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,9 @@
|
||||||
<script src="{{AppSubURL}}/js/libs/jquery.are-you-sure.js"></script>
|
<script src="{{AppSubURL}}/js/libs/jquery.are-you-sure.js"></script>
|
||||||
<link rel="stylesheet" href="{{AppSubURL}}/assets/font-awesome-4.6.3/css/font-awesome.min.css">
|
<link rel="stylesheet" href="{{AppSubURL}}/assets/font-awesome-4.6.3/css/font-awesome.min.css">
|
||||||
<link rel="stylesheet" href="{{AppSubURL}}/assets/octicons-4.3.0/octicons.min.css">
|
<link rel="stylesheet" href="{{AppSubURL}}/assets/octicons-4.3.0/octicons.min.css">
|
||||||
|
{{if .RequireAutosize}}
|
||||||
|
<script src="{{AppSubURL}}/plugins/autosize-4.0.2/dist/autosize.min.js"></script>
|
||||||
|
{{end}}
|
||||||
<!-- notebook.js for rendering ipython notebooks and marked.js for rendering markdown in notebooks -->
|
<!-- notebook.js for rendering ipython notebooks and marked.js for rendering markdown in notebooks -->
|
||||||
{{if .IsIPythonNotebook}}
|
{{if .IsIPythonNotebook}}
|
||||||
<script src="{{AppSubURL}}/plugins/notebookjs-0.3.0/notebook.min.js"></script>
|
<script src="{{AppSubURL}}/plugins/notebookjs-0.3.0/notebook.min.js"></script>
|
||||||
|
|
|
@ -52,7 +52,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="inline field {{if .Err_Description}}error{{end}}">
|
<div class="inline field {{if .Err_Description}}error{{end}}">
|
||||||
<label for="description">{{.i18n.Tr "repo.repo_desc"}}</label>
|
<label for="description">{{.i18n.Tr "repo.repo_desc"}}</label>
|
||||||
<textarea id="description" name="description">{{.description}}</textarea>
|
<textarea id="description" name="description" rows="3">{{.description}}</textarea>
|
||||||
|
<span class="help">{{.i18n.Tr "repo.repo_description_helper" | Safe}}</span>
|
||||||
|
<span class="help">{{.i18n.Tr "repo.repo_description_length"}}: <span id="descLength"></span></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="ui divider"></div>
|
<div class="ui divider"></div>
|
||||||
|
@ -113,4 +115,14 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function(){
|
||||||
|
if (typeof window.autosize !== "undefined") {
|
||||||
|
autosize($('#description'));
|
||||||
|
}
|
||||||
|
showMessageMaxLength(512, 'description', 'descLength');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
||||||
|
|
|
@ -19,7 +19,9 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="field {{if .Err_Description}}error{{end}}">
|
<div class="field {{if .Err_Description}}error{{end}}">
|
||||||
<label for="description">{{$.i18n.Tr "repo.repo_desc"}}</label>
|
<label for="description">{{$.i18n.Tr "repo.repo_desc"}}</label>
|
||||||
<textarea id="description" name="description" rows="2">{{.Repository.Description}}</textarea>
|
<textarea id="description" name="description" rows="3">{{.Repository.Description}}</textarea>
|
||||||
|
<p class="help">{{.i18n.Tr "repo.settings.description_desc"}}</p>
|
||||||
|
<p class="help">{{.i18n.Tr "repo.settings.description_length"}}: <span id="descLength"></span></p>
|
||||||
</div>
|
</div>
|
||||||
<div class="field {{if .Err_Website}}error{{end}}">
|
<div class="field {{if .Err_Website}}error{{end}}">
|
||||||
<label for="website">{{.i18n.Tr "repo.settings.site"}}</label>
|
<label for="website">{{.i18n.Tr "repo.settings.site"}}</label>
|
||||||
|
@ -415,4 +417,13 @@
|
||||||
{{end}}
|
{{end}}
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
$(document).ready(function(){
|
||||||
|
if (typeof window.autosize !== "undefined") {
|
||||||
|
autosize($('#description'));
|
||||||
|
}
|
||||||
|
showMessageMaxLength(512, 'description', 'descLength');
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
{{template "base/footer" .}}
|
{{template "base/footer" .}}
|
||||||
|
|
Loading…
Reference in New Issue