Browse Source

Update for Edit

pull/3287/head
Richard Mahn 9 years ago
parent
commit
d10d128c51
  1. 4
      conf/app.ini
  2. 61
      conf/locale/locale_en-US.ini
  3. 16
      models/issue.go
  4. 31
      models/repo.go
  5. 40
      models/wiki.go
  6. 48
      models/working_pool.go
  7. 8
      modules/auth/repo_form.go
  8. 1625
      modules/bindata/bindata.go
  9. 9
      modules/markdown/markdown.go
  10. 14
      modules/setting/setting.go
  11. 37
      public/css/gogs.css
  12. 124
      public/js/gogs.js
  13. 55
      routers/repo/branch.go
  14. 8
      routers/repo/edit.go
  15. 11
      routers/repo/issue.go
  16. 2
      routers/repo/pull.go
  17. 2
      routers/repo/view.go
  18. 2
      templates/admin/dashboard.tmpl
  19. 6
      templates/base/alert.tmpl
  20. 2
      templates/base/head.tmpl
  21. 51
      templates/repo/branch_dropdown.tmpl
  22. 8
      templates/repo/diff_box.tmpl
  23. 8
      templates/repo/edit.tmpl
  24. 20
      templates/repo/home.tmpl
  25. 5
      templates/repo/issue/comment_tab.tmpl
  26. 34
      templates/repo/view_file.tmpl
  27. 2
      templates/repo/wiki/new.tmpl

4
conf/app.ini

@ -19,9 +19,11 @@ FORCE_PRIVATE = false
MAX_CREATION_LIMIT = -1
; Patch test queue length, make it as large as possible
PULL_REQUEST_QUEUE_LENGTH = 10000
[editor]
; List of file extensions that should have line wraps in the CodeMirror editor
; Separate extensions with a comma. To line wrap files w/o extension, just put a comma
LINE_WRAP_EXTENSIONS = .txt,,.md,.markdown,.mdown,.mkd
LINE_WRAP_EXTENSIONS = .txt,.md,.markdown,.mdown,.mkd,,
; Valid file modes that have a preview API associated with them, such as api/v1/markdown
; Separate values by commas. Preview tab in edit mode won't show if the file extension doesn't match
PREVIEW_TAB_APIS = markdown

61
conf/locale/locale_en-US.ini

@ -186,6 +186,13 @@ TeamName = Team name
AuthName = Authorization name
AdminEmail = Admin email
NewBranchName = New branch name
CommitSummary = Commit summary
CommitMessage = Commit message
CommitChoice = Commit choice
TreeName = File path
Content = Content
require_error = ` cannot be empty.`
alpha_dash_error = ` must be valid alpha or numeric or dash(-_) characters.`
alpha_dash_dot_error = ` must be valid alpha or numeric or dash(-_) or dot characters.`
@ -413,6 +420,51 @@ file_view_raw = View Raw
file_permalink = Permalink
file_too_large = This file is too large to be shown
cancel = Cancel
cancel_lower = cancel
or = or
new_file = New file
upload_files = Upload files
find_file = Find file
commit_changes = Commit Changes
default_commit_message = Add an optional extended description…
last_commit_info = %s edited this file %s
delete_this_file = Delete this file
edit_this_file = Edit this file
edit_file = Edit file
delete_confirm_message = Are you sure you want to delete this file?
delete_commit_message = Write a note about this delete (optional)
file_editing_no_longer_exists = The file you are editing no longer exists in the repository
file_already_exists = A file by that name already exists
unable_to_update_file = Unable to update this file, error occurred
add = Add
update = Update
filename_cannot_be_empty = Filename cannot be empty
directory_is_a_file = One of the directories in the path is already a file in this repository
filename_is_a_directory = The filename given is an existing directory in the repository
must_be_on_branch = You must be on a branch to make or propose changes to this file
must_be_writer = You must have write access to make or propose changes to this file
cannot_edit_binary_files = Cannot edit binary files
filename_help = To add directory, just type it and press /. To remove a directory, go to the beginning of the field and press backspace.
fork_before_edit = You must fork this before editing
branch_already_exists = Branch already exists
create_new_branch = Create a %s for this commit and start a pull request.
new_branch = new branch
commit_directly_to_this_branch = Commit directly to the %s branch.
create_branch = Create branch
from = from
upload_file = Upload file
add_files_to_dir = Add files to %s
unable_to_upload_files = Unable to upload files, an error occurred.
add_subdir = Add subdirectory…
name_your_file = Name your file…
user_has_committed_since_you_started_editing = %s has committed since you started editing.
see_what_changed = See what changed.
pressing_commit_again_will_overwrite_those_changes = Pressing '%s' again will overwrite those changes.
copy_file_path_to_clipboard = Copy file path to clipboard
preview_changes = Preview Changes
no_changes_to_show = There are no changes to show.
commits.commits = Commits
commits.search = Search commits
commits.find = Find
@ -436,7 +488,7 @@ issues.new.clear_assignee = Clear assignee
issues.new.no_assignee = No assignee
issues.create = Create Issue
issues.new_label = New Label
issues.new_label_placeholder = Label name...
issues.new_label_placeholder = Label name
issues.create_label = Create Label
issues.open_tab = %d Open
issues.close_tab = %d Closed
@ -622,7 +674,7 @@ settings.delete_collaborator = Delete
settings.collaborator_deletion = Collaborator Deletion
settings.collaborator_deletion_desc = This user will no longer have collaboration access to this repository after deletion. Do you want to continue?
settings.remove_collaborator_success = Collaborator has been removed.
settings.search_user_placeholder = Search user...
settings.search_user_placeholder = Search user
settings.org_not_allowed_to_be_collaborator = Organization is not allowed to be added as a collaborator.
settings.user_is_org_member = User is organization member who cannot be added as a collaborator.
settings.add_webhook = Add Webhook
@ -696,6 +748,7 @@ diff.view_file = View File
diff.file_suppressed = File diff suppressed because it is too large
diff.too_many_files = Some files were not shown because too many files changed in this diff
release.releases = Releases
release.new_release = New Release
release.draft = Draft
@ -713,7 +766,7 @@ release.title = Title
release.content = Content
release.write = Write
release.preview = Preview
release.loading = Loading...
release.loading = Loading
release.prerelease_desc = This is a pre-release
release.prerelease_helper = We'll point out that this release is not production-ready.
release.cancel = Cancel
@ -801,7 +854,7 @@ teams.read_permission_desc = This team grants <strong>Read</strong> access: memb
teams.write_permission_desc = This team grants <strong>Write</strong> access: members can read from and push to the team's repositories.
teams.admin_permission_desc = This team grants <strong>Admin</strong> access: members can read from, push to, and add collaborators to the team's repositories.
teams.repositories = Team Repositories
teams.search_repo_placeholder = Search repository...
teams.search_repo_placeholder = Search repository
teams.add_team_repository = Add Team Repository
teams.remove_repo = Remove
teams.add_nonexistent_repo = The repository you're trying to add does not exist, please create it first.

16
models/issue.go

@ -383,23 +383,18 @@ func newIssue(e *xorm.Session, repo *Repository, issue *Issue, labelIDs []int64,
}
// Check attachments.
attachments := make([]*Attachment, 0, len(uuids))
for _, uuid := range uuids {
attach, err := getAttachmentByUUID(e, uuid)
attachment, err := getAttachmentByUUID(e, uuid)
if err != nil {
if IsErrAttachmentNotExist(err) {
continue
}
return fmt.Errorf("getAttachmentByUUID[%s]: %v", uuid, err)
}
attachments = append(attachments, attach)
}
for i := range attachments {
attachments[i].IssueID = issue.ID
attachment.IssueID = issue.ID
// No assign value could be 0, so ignore AllCols().
if _, err = e.Id(attachments[i].ID).Update(attachments[i]); err != nil {
return fmt.Errorf("update attachment[%d]: %v", attachments[i].ID, err)
if _, err = e.Id(attachment.ID).Update(attachment); err != nil {
return fmt.Errorf("update attachment[%d]: %v", attachment.ID, err)
}
}
@ -426,6 +421,7 @@ func NewIssue(repo *Repository, issue *Issue, labelIDs []int64, uuids []string)
act := &Action{
ActUserID: issue.Poster.Id,
ActUserName: issue.Poster.Name,
ActEmail: issue.Poster.Email,
OpType: ACTION_CREATE_ISSUE,
Content: fmt.Sprintf("%d|%s", issue.Index, issue.Name),
@ -1456,7 +1452,7 @@ func DeleteAttachments(attachments []*Attachment, remove bool) (int, error) {
}
}
if _, err := x.Delete(a.ID); err != nil {
if _, err := x.Delete(a); err != nil {
return i, err
}
}

31
models/repo.go

@ -2510,3 +2510,34 @@ func DeleteUploads(uploads []*Upload, remove bool) (int, error) {
return len(uploads), nil
}
// __________ .__
// \______ \____________ ____ ____ | |__
// | | _/\_ __ \__ \ / \_/ ___\| | \
// | | \ | | \// __ \| | \ \___| Y \
// |______ / |__| (____ /___| /\___ >___| /
// \/ \/ \/ \/ \/
//
func (repo *Repository) CreateNewBranch(doer *User, oldBranchName, branchName string) (err error) {
repoWorkingPool.CheckIn(com.ToStr(repo.ID))
defer repoWorkingPool.CheckOut(com.ToStr(repo.ID))
localPath := repo.LocalRepoPath()
if err = discardLocalRepoChanges(localPath, oldBranchName); err != nil {
return fmt.Errorf("discardLocalRepoChanges: %v", err)
} else if err = repo.UpdateLocalRepo(oldBranchName); err != nil {
return fmt.Errorf("UpdateLocalRepo: %v", err)
}
if err = repo.CheckoutNewBranch(oldBranchName, branchName); err != nil {
return fmt.Errorf("CreateNewBranch: %v", err)
}
if err = git.Push(localPath, "origin", branchName); err != nil {
return fmt.Errorf("Push: %v", err)
}
return nil
}

40
models/wiki.go

@ -21,44 +21,6 @@ import (
"github.com/gogits/gogs/modules/setting"
)
// workingPool represents a pool of working status which makes sure
// that only one instance of same task is performing at a time.
// However, different type of tasks can performing at the same time.
type workingPool struct {
lock sync.Mutex
pool map[string]*sync.Mutex
count map[string]int
}
// CheckIn checks in a task and waits if others are running.
func (p *workingPool) CheckIn(name string) {
p.lock.Lock()
lock, has := p.pool[name]
if !has {
lock = &sync.Mutex{}
p.pool[name] = lock
}
p.count[name]++
p.lock.Unlock()
lock.Lock()
}
// CheckOut checks out a task to let other tasks run.
func (p *workingPool) CheckOut(name string) {
p.lock.Lock()
defer p.lock.Unlock()
p.pool[name].Unlock()
if p.count[name] == 1 {
delete(p.pool, name)
delete(p.count, name)
} else {
p.count[name]--
}
}
var wikiWorkingPool = &workingPool{
pool: make(map[string]*sync.Mutex),
count: make(map[string]int),
@ -115,7 +77,7 @@ func (repo *Repository) LocalWikiPath() string {
// UpdateLocalWiki makes sure the local copy of repository wiki is up-to-date.
func (repo *Repository) UpdateLocalWiki() error {
return updateLocalCopy(repo.WikiPath(), repo.LocalWikiPath(), repo.DefaultBranch)
return updateLocalCopy(repo.WikiPath(), repo.LocalWikiPath(), "")
}
// discardLocalWikiChanges discards local commits make sure

48
models/working_pool.go

@ -0,0 +1,48 @@
// Copyright 2015 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 models
import (
"sync"
)
// workingPool represents a pool of working status which makes sure
// that only one instance of same task is performing at a time.
// However, different type of tasks can performing at the same time.
type workingPool struct {
lock sync.Mutex
pool map[string]*sync.Mutex
count map[string]int
}
// CheckIn checks in a task and waits if others are running.
func (p *workingPool) CheckIn(name string) {
p.lock.Lock()
lock, has := p.pool[name]
if !has {
lock = &sync.Mutex{}
p.pool[name] = lock
}
p.count[name]++
p.lock.Unlock()
lock.Lock()
}
// CheckOut checks out a task to let other tasks run.
func (p *workingPool) CheckOut(name string) {
p.lock.Lock()
defer p.lock.Unlock()
p.pool[name].Unlock()
if p.count[name] == 1 {
delete(p.pool, name)
delete(p.count, name)
} else {
p.count[name]--
}
}

8
modules/auth/repo_form.go

@ -168,7 +168,7 @@ type CreateIssueForm struct {
MilestoneID int64
AssigneeID int64
Content string
Attachments []string
Files []string
}
func (f *CreateIssueForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {
@ -176,9 +176,9 @@ func (f *CreateIssueForm) Validate(ctx *macaron.Context, errs binding.Errors) bi
}
type CreateCommentForm struct {
Content string
Status string `binding:"OmitEmpty;In(reopen,close)"`
Attachments []string
Content string
Status string `binding:"OmitEmpty;In(reopen,close)"`
Files []string
}
func (f *CreateCommentForm) Validate(ctx *macaron.Context, errs binding.Errors) binding.Errors {

1625
modules/bindata/bindata.go

File diff suppressed because one or more lines are too long

9
modules/markdown/markdown.go

@ -53,10 +53,11 @@ func isLink(link []byte) bool {
// IsMarkdownFile reports whether name looks like a Markdown file
// based on its extension.
func IsMarkdownFile(name string) bool {
name = strings.ToLower(name)
switch filepath.Ext(name) {
case ".md", ".markdown", ".mdown", ".mkd":
return true
extension := strings.ToLower(filepath.Ext(name))
for _, ext := range setting.Markdown.MdFileExtensions {
if strings.ToLower(ext) == extension {
return true
}
}
return false
}

14
modules/setting/setting.go

@ -110,12 +110,16 @@ var (
ForcePrivate bool
MaxCreationLimit int
PullRequestQueueLength int
LineWrapExtensions []string
PreviewTabApis []string
}
RepoRootPath string
ScriptType string
// Repo editor settings
Editor struct {
LineWrapExtensions []string
PreviewTabApis []string
}
// UI settings
ExplorePagingNum int
IssuePagingNum int
@ -498,6 +502,8 @@ func NewContext() {
log.Fatal(4, "Fail to map Git settings: %v", err)
} else if err = Cfg.Section("api").MapTo(&API); err != nil {
log.Fatal(4, "Fail to map API settings: %v", err)
} else if err = Cfg.Section("editor").MapTo(&Editor); err != nil {
log.Fatal(4, "Fail to map Editor settings: %v", err)
}
Langs = Cfg.Section("i18n").Key("LANGS").Strings(",")
@ -508,6 +514,10 @@ func NewContext() {
ShowFooterVersion = Cfg.Section("other").Key("SHOW_FOOTER_VERSION").MustBool()
HasRobotsTxt = com.IsFile(path.Join(CustomPath, "robots.txt"))
Markdown.MdFileExtensions = Cfg.Section("markdown").Key("MD_FILE_EXTENSIONS").Strings(",")
Editor.LineWrapExtensions = Cfg.Section("editor").Key("LINE_WRAP_EXTENSIONS").Strings(",")
Editor.PreviewTabApis = Cfg.Section("editor").Key("PREVIEW_TAB_APIS").Strings(",")
}
var Service struct {

37
public/css/gogs.css

@ -263,6 +263,9 @@ code.wrap {
.ui.status.buttons .octicon {
margin-right: 4px;
}
.ui.menu .item .octicon {
margin-right: 4px;
}
.ui.inline.delete-button {
padding: 8px 15px;
font-weight: normal;
@ -2864,3 +2867,37 @@ footer .ui.language .menu {
.repo-edit-file-cancel {
padding-left: 10px;
}
#new-branch-item {
display:none;
margin: 0;
text-align: left;
padding: .71428571em 1.14285714em!important;
background: 0 0!important;
color: rgba(0,0,0,.87)!important;
text-transform: none!important;
box-shadow: none!important;
-webkit-transition: none!important;
transition: none!important;
border-top: none;
padding-right: calc(1.14285714rem + 17px)!important;
font-size: 14px;
font-weight: bold;
line-height: 1.1;
}
#new-branch-item:hover {
background: rgba(0,0,0,.05)!important;
color: rgba(0,0,0,.95)!important;
}
#new-branch-item .icon {
float: left;
margin-left: -15px;
}
#new-branch-item .description {
margin-top: 3px;
font-size: 12px;
}
.repository .ui.container .ui.breadcrumb {
font-size: 1.5em;
color: #767676;
max-width: 600px;
}

124
public/js/gogs.js

@ -574,8 +574,6 @@ function initWikiForm() {
function initIssueForm() {
var $edit_area = $('.repository.issue textarea.edit_area');
console.log($edit_area);
console.log($edit_area.length);
if ($edit_area.length > 0) {
$edit_area.each(function(i, edit_area) {
new SimpleMDE({
@ -627,30 +625,75 @@ String.prototype.endsWith = function(pattern) {
return d >= 0 && this.lastIndexOf(pattern) === d;
};
// Adding function to get the cursor position in a text field to jquery objects
(function ($, undefined) {
$.fn.getCursorPosition = function () {
var el = $(this).get(0);
var pos = 0;
if ('selectionStart' in el) {
pos = el.selectionStart;
} else if ('selection' in document) {
el.focus();
var Sel = document.selection.createRange();
var SelLength = document.selection.createRange().text.length;
Sel.moveStart('character', -el.value.length);
pos = Sel.text.length - SelLength;
}
return pos;
}
})(jQuery);
function initEditor() {
editFilename = $("#file-name");
editFilename.keyup(function (e) {
var sections = $('.breadcrumb span.section');
var dividers = $('.breadcrumb div.divider');
if (e.keyCode == 8) {
if ($(this).getCursorPosition() == 0) {
if (sections.length > 0) {
var value = sections.last().find('a').text();
$(this).val(value + $(this).val());
$(this)[0].setSelectionRange(value.length, value.length);
sections.last().remove();
dividers.last().remove();
}
}
}
if (e.keyCode == 191) {
var parts = $(this).val().split('/');
for (var i = 0; i < parts.length; ++i) {
var value = parts[i];
if (i < parts.length - 1) {
if (value.length) {
$('<span class="section"><a href="#">' + value + '</a></span>').insertBefore($(this));
$('<div class="divider"> / </div>').insertBefore($(this));
}
}
else {
$(this).val(value);
}
$(this)[0].setSelectionRange(0, 0);
}
}
var parts = [];
$('.breadcrumb span.section').each(function (i, element) {
element = $(element);
if (element.find('a').length) {
parts.push(element.find('a').text());
} else {
parts.push(element.text());
}
});
if ($(this).val())
parts.push($(this).val());
$('#tree-name').val(parts.join('/'));
}).trigger('keyup');
editArea = $('.repository.edit textarea#edit_area');
if (!editArea.length)
return;
(function ($, undefined) {
$.fn.getCursorPosition = function () {
var el = $(this).get(0);
var pos = 0;
if ('selectionStart' in el) {
pos = el.selectionStart;
} else if ('selection' in document) {
el.focus();
var Sel = document.selection.createRange();
var SelLength = document.selection.createRange().text.length;
Sel.moveStart('character', -el.value.length);
pos = Sel.text.length - SelLength;
}
return pos;
}
})(jQuery);
CodeMirror.modeURL = editArea.data("mode-url");
mdFileExtensions = editArea.data("md-file-extensions").split(",");
lineWrapExtensions = editArea.data("line-wrap-extensions").split(",");
@ -707,49 +750,6 @@ function initEditor() {
else {
cmEditor.setOption("lineWrapping", false);
}
})
.keyup(function (e) {
var sections = $('.breadcrumb span.section');
var dividers = $('.breadcrumb div.divider');
if (e.keyCode == 8) {
if ($(this).getCursorPosition() == 0) {
if (sections.length > 0) {
var value = sections.last().find('a').text();
$(this).val(value + $(this).val());
$(this)[0].setSelectionRange(value.length, value.length);
sections.last().remove();
dividers.last().remove();
}
}
}
if (e.keyCode == 191) {
var parts = $(this).val().split('/');
for (var i = 0; i < parts.length; ++i) {
var value = parts[i];
if (i < parts.length - 1) {
if (value.length) {
$('<span class="section"><a href="#">' + value + '</a></span>').insertBefore($(this));
$('<div class="divider"> / </div>').insertBefore($(this));
}
}
else {
$(this).val(value);
}
$(this)[0].setSelectionRange(0, 0);
}
}
var parts = [];
$('.breadcrumb span.section').each(function (i, element) {
element = $(element);
if (element.find('a').length) {
parts.push(element.find('a').text());
} else {
parts.push(element.text());
}
});
if ($(this).val())
parts.push($(this).val());
$('#tree-name').val(parts.join('/'));
}).trigger('keyup');
}

55
routers/repo/branch.go

@ -7,6 +7,11 @@ package repo
import (
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/context"
"github.com/gogits/gogs/modules/auth"
"github.com/gogits/gogs/modules/log"
"strings"
"net/url"
"github.com/gogits/gogs/models"
)
const (
@ -29,3 +34,53 @@ func Branches(ctx *context.Context) {
ctx.Data["Branches"] = brs
ctx.HTML(200, BRANCH)
}
func NewBranchPost(ctx *context.Context, form auth.NewBranchForm) {
oldBranchName := form.OldBranchName
branchName := form.BranchName
if ctx.HasError() || ! ctx.Repo.IsWriter() || branchName == oldBranchName {
ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + oldBranchName))
return
}
branchName = url.QueryEscape(strings.Replace(strings.Trim(branchName, " "), " ", "-", -1))
if _, err := ctx.Repo.Repository.GetBranch(branchName); err == nil {
ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + branchName))
return
}
if err := ctx.Repo.Repository.CreateNewBranch(ctx.User, oldBranchName, branchName); err != nil {
ctx.Handle(404, "repo.Branches(CreateNewBranch)", err)
log.Error(4, "%s: %v", "EditFile", err)
return
}
// Was successful, so now need to call models.CommitRepoAction() with the new commitID for webhooks and watchers
if branch, err := ctx.Repo.Repository.GetBranch(branchName); err != nil {
log.Error(4, "repo.Repository.GetBranch(%s): %v", branchName, err)
} else if commit, err := branch.GetCommit(); err != nil {
log.Error(4, "branch.GetCommit(): %v", err)
} else {
pc := &models.PushCommits{
Len: 1,
Commits: []*models.PushCommit{&models.PushCommit{
commit.ID.String(),
commit.Message(),
commit.Author.Email,
commit.Author.Name,
}},
}
oldCommitID := "0000000000000000000000000000000000000000" // New Branch so we use all 0s
newCommitID := commit.ID.String()
if err := models.CommitRepoAction(ctx.User.Id, ctx.Repo.Owner.Id, ctx.User.LowerName, ctx.Repo.Owner.Email,
ctx.Repo.Repository.ID, ctx.Repo.Owner.LowerName, ctx.Repo.Repository.Name, "refs/heads/"+branchName, pc,
oldCommitID, newCommitID); err != nil {
log.Error(4, "models.CommitRepoAction(branch = %s): %v", branchName, err)
}
models.HookQueue.Add(ctx.Repo.Repository.ID)
}
ctx.Redirect(EscapeUrl(ctx.Repo.RepoLink + "/src/" + branchName))
}

8
routers/repo/edit.go

@ -117,8 +117,8 @@ func editFile(ctx *context.Context, isNewFile bool) {
ctx.Data["CreateNewBranch"] = ctx.Tr("repo.create_new_branch", "<strong>"+ctx.Tr("repo.new_branch")+"</strong>")
ctx.Data["LastCommit"] = ctx.Repo.Commit.ID
ctx.Data["MdFileExtensions"] = strings.Join(setting.Markdown.MdFileExtensions, ",")
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.LineWrapExtensions, ",")
ctx.Data["PreviewTabApis"] = strings.Join(setting.Repository.PreviewTabApis, ",")
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Editor.LineWrapExtensions, ",")
ctx.Data["PreviewTabApis"] = strings.Join(setting.Editor.PreviewTabApis, ",")
ctx.Data["PreviewDiffUrl"] = ctx.Repo.RepoLink + "/preview/" + branchName + "/" + treeName
ctx.HTML(200, EDIT)
@ -177,8 +177,8 @@ func editFilePost(ctx *context.Context, form auth.EditRepoFileForm, isNewFile bo
ctx.Data["CreateNewBranch"] = ctx.Tr("repo.create_new_branch", "<strong>"+ctx.Tr("repo.new_branch")+"</strong>")
ctx.Data["LastCommit"] = ctx.Repo.Commit.ID
ctx.Data["MdFileExtensions"] = strings.Join(setting.Markdown.MdFileExtensions, ",")
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Repository.LineWrapExtensions, ",")
ctx.Data["PreviewTabApis"] = strings.Join(setting.Repository.PreviewTabApis, ",")
ctx.Data["LineWrapExtensions"] = strings.Join(setting.Editor.LineWrapExtensions, ",")
ctx.Data["PreviewTabApis"] = strings.Join(setting.Editor.PreviewTabApis, ",")
ctx.Data["PreviewDiffUrl"] = ctx.Repo.RepoLink + "/preview/" + branchName + "/" + treeName
if ctx.HasError() {

11
routers/repo/issue.go

@ -340,6 +340,8 @@ func NewIssue(ctx *context.Context) {
}
ctx.Data["RequireHighlightJS"] = true
ctx.Data["RequireSimpleMDE"] = true
ctx.Data["RepoName"] = ctx.Repo.Repository.Name
ctx.HTML(200, ISSUE_NEW)
}
@ -401,6 +403,9 @@ func ValidateRepoMetas(ctx *context.Context, form auth.CreateIssueForm) ([]int64
func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) {
ctx.Data["Title"] = ctx.Tr("repo.issues.new")
ctx.Data["PageIsIssueList"] = true
ctx.Data["RepoName"] = ctx.Repo.Repository.Name
ctx.Data["RequireHighlightJS"] = true
ctx.Data["RequireSimpleMDE"] = true
renderAttachmentSettings(ctx)
var (
@ -414,7 +419,7 @@ func NewIssuePost(ctx *context.Context, form auth.CreateIssueForm) {
}
if setting.AttachmentEnabled {
attachments = form.Attachments
attachments = form.Files
}
if ctx.HasError() {
@ -640,6 +645,8 @@ func ViewIssue(ctx *context.Context) {
ctx.Data["SignInLink"] = setting.AppSubUrl + "/user/login"
ctx.Data["RequireHighlightJS"] = true
ctx.Data["RequireSimpleMDE"] = true
ctx.Data["RepoName"] = ctx.Repo.Repository.Name
ctx.HTML(200, ISSUE_VIEW)
}
@ -819,7 +826,7 @@ func NewComment(ctx *context.Context, form auth.CreateCommentForm) {
var attachments []string
if setting.AttachmentEnabled {
attachments = form.Attachments
attachments = form.Files
}
if ctx.HasError() {

2
routers/repo/pull.go

@ -645,7 +645,7 @@ func CompareAndPullRequestPost(ctx *context.Context, form auth.CreateIssueForm)
}
if setting.AttachmentEnabled {
attachments = form.Attachments
attachments = form.Files
}
if ctx.HasError() {

2
routers/repo/view.go

@ -39,6 +39,7 @@ func Home(ctx *context.Context) {
ctx.Data["Title"] = title
ctx.Data["PageIsViewCode"] = true
ctx.Data["RequireHighlightJS"] = true
ctx.Data["IsWriter"] = ctx.Repo.IsWriter()
branchName := ctx.Repo.BranchName
userName := ctx.Repo.Owner.Name
@ -206,6 +207,7 @@ func Home(ctx *context.Context) {
buf = append(buf, d...)
switch {
case markdown.IsMarkdownFile(readmeFile.Name()):
ctx.Data["IsMarkdown"] = true
buf = markdown.Render(buf, treeLink, ctx.Repo.Repository.ComposeMetas())
default:
buf = bytes.Replace(buf, []byte("\n"), []byte(`<br>`), -1)

2
templates/admin/dashboard.tmpl

@ -10,7 +10,7 @@
</h4>
<div class="ui attached segment">
<p>
{{.i18n.Tr "admin.dashboard.statistic_info" .Stats.Counter.User .Stats.Counter.Org .Stats.Counter.PublicKey .Stats.Counter.Repo .Stats.Counter.Watch .Stats.Counter.Star .Stats.Counter.Action .Stats.Counter.Access .Stats.Counter.Issue .Stats.Counter.Comment .Stats.Counter.Oauth .Stats.Counter.Follow .Stats.Counter.Mirror .Stats.Counter.Release .Stats.Counter.LoginSource .Stats.Counter.Webhook .Stats.Counter.Milestone .Stats.Counter.Label .Stats.Counter.HookTask .Stats.Counter.Team .Stats.Counter.UpdateTask .Stats.Counter.Attachment | Str2html}}
{{.i18n.Tr "admin.dashboard.statistic_info" .Stats.Counter.User .Stats.Counter.Org .Stats.Counter.PublicKey .Stats.Counter.Repo .Stats.Counter.Watch .Stats.Counter.Star .Stats.Counter.Action .Stats.Counter.Access .Stats.Counter.Issue .Stats.Counter.Comment .Stats.Counter.Oauth .Stats.Counter.Follow .Stats.Counter.Mirror .Stats.Counter.Release .Stats.Counter.LoginSource .Stats.Counter.Webhook .Stats.Counter.Milestone .Stats.Counter.Label .Stats.Counter.HookTask .Stats.Counter.Team .Stats.Counter.UpdateTask .Stats.Counter.Attachment .Stats.Counter.Upload | Str2html}}
</p>
</div>
<h4 class="ui top attached header">

6
templates/base/alert.tmpl

@ -1,15 +1,15 @@
{{if .Flash.ErrorMsg}}
<div class="ui negative message">
<p>{{.Flash.ErrorMsg}}</p>
<p>{{.Flash.ErrorMsg | Safe}}</p>
</div>
{{end}}
{{if .Flash.SuccessMsg}}
<div class="ui positive message">
<p>{{.Flash.SuccessMsg}}</p>
<p>{{.Flash.SuccessMsg | Safe}}</p>
</div>
{{end}}
{{if .Flash.InfoMsg}}
<div class="ui info message">
<p>{{.Flash.InfoMsg}}</p>
<p>{{.Flash.InfoMsg| Safe}}</p>
</div>
{{end}}

2
templates/base/head.tmpl

@ -24,6 +24,8 @@
{{if .RequireSimpleMDE}}
<link rel="stylesheet" href="{{AppSubUrl}}/plugins/simplemde-1.10.1/simplemde.min.css">
<script src="{{AppSubUrl}}/plugins/simplemde-1.10.1/simplemde.min.js"></script>
<script src="{{AppSubUrl}}/plugins/simplemde-1.10.1/loadmode.js"></script>
<script src="{{AppSubUrl}}/plugins/simplemde-1.10.1/mode/meta.js"></script>
{{end}}
<!-- Stylesheet -->

51
templates/repo/branch_dropdown.tmpl

@ -1,6 +1,6 @@
<div class="fitted item choose reference">
<div class="ui floating filter dropdown" data-no-results="{{.i18n.Tr "repo.pulls.no_results"}}">
<div class="ui basic small button">
<div id="branch-dropdown" class="ui floating filter dropdown" data-no-results="{{.i18n.Tr "repo.pulls.no_results"}}">
<div class="ui basic small button">
<span class="text">
<i class="octicon octicon-git-branch"></i>
{{if .IsViewBranch}}{{.i18n.Tr "repo.branch"}}{{else}}{{.i18n.Tr "repo.tree"}}{{end}}:
@ -31,14 +31,57 @@
</div>
<div id="branch-list" class="scrolling menu" {{if .IsViewTag}}style="display: none"{{end}}>
{{range .Branches}}
<div class="item {{if eq $.BranchName .}}selected{{end}}" data-url="{{$.RepoLink}}/{{if $.PageIsCommits}}commits{{else}}src{{end}}/{{EscapePound .}}">{{.}}</div>
<div class="item {{if eq $.BranchName .}}selected{{end}}" data-url="{{$.RepoLink}}/{{if $.PageIsCommits}}commits{{else}}src{{end}}/{{EscapePound .}}{{if $.TreeName}}/{{EscapePound $.TreeName}}{{end}}">{{.}}</div>
{{end}}
{{if .IsWriter}}
<a href="javascript:void(0)" id="new-branch-item">
<i class="octicon octicon-git-branch"></i>
{{.i18n.Tr "repo.create_branch"}}: <span id="branch-name-text"></span>
<br/>
<span class="description">{{.i18n.Tr "repo.from"}} ‘{{.BranchName}}’</span>
<form accept-charset="UTF-8" action="{{.RepoLink}}/branches" method="post">
{{.CsrfTokenHtml}}
<input type="hidden" name="old_branch_name" value="{{.BranchName}}">
<input type="hidden" name="branch_name" id="branch-name" value="">
</form>
</a>
{{end}}
</div>
<div id="tag-list" class="scrolling menu" {{if not .IsViewTag}}style="display: none"{{end}}>
{{range .Tags}}
<div class="item {{if eq $.BranchName .}}selected{{end}}" data-url="{{$.RepoLink}}/{{if $.PageIsCommits}}commits{{else}}src{{end}}/{{EscapePound .}}">{{.}}</div>
<div class="item {{if eq $.BranchName .}}selected{{end}}" data-url="{{$.RepoLink}}/{{if $.PageIsCommits}}commits{{else}}src{{end}}/{{EscapePound .}}{{if $.TreeName}}/{{EscapePound $.TreeName}}{{end}}">{{.}}</div>
{{end}}
</div>
</div>
</div>
</div>
{{if .IsWriter}}
<script type="text/javascript">
$(document).ready(function(){
$('#branch-dropdown #new-branch-item').on('click', function(){
$(this).find('form').submit();
return true;
});
$('#branch-dropdown input[name=search]').on('keyup', function(){
var query = $(this).val().toLowerCase();
if(query.length){
var unique = true;
$('#branch-dropdown #branch-list .item').each(function(i, item){
if($(item).text().toLowerCase() == query){
unique = false;
}
});
if(unique){
$('#new-branch-item #branch-name-text').text(query);
$('#new-branch-item #branch-name').val(query);
$('#new-branch-item').css('display', 'block');
return;
}
}
$('#new-branch-item').hide();
});
});
</script>
{{end}}

8
templates/repo/diff_box.tmpl

@ -88,8 +88,8 @@
<table>
<tbody>
{{if $.IsSplitStyle}}
{{range $j, $section := .Sections}}
{{range $k, $line := .Lines}}
{{range $j, $section := $file.Sections}}
{{range $k, $line := $section.Lines}}
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
<td class="lines-num lines-num-old">
<span rel="{{if $line.LeftIdx}}diff-{{Sha1 $file.Name}}L{{$line.LeftIdx}}{{end}}">{{if $line.LeftIdx}}{{$line.LeftIdx}}{{end}}</span>
@ -107,8 +107,8 @@
{{end}}
{{end}}
{{else}}
{{range $j, $section := .Sections}}
{{range $k, $line := .Lines}}
{{range $j, $section := $file.Sections}}
{{range $k, $line := $section.Lines}}
<tr class="{{DiffLineTypeToStr .GetType}}-code nl-{{$k}} ol-{{$k}}">
{{if eq .GetType 4}}
<td colspan="2" class="lines-num">

8
templates/repo/edit.tmpl

@ -21,7 +21,7 @@
<span class="section"><a href="{{EscapePound $.BranchLink}}/{{EscapePound $v}}">{{$v}}</a></span>
{{end}}
{{end}}
<button class="clipboard-tree-name icon octicon octicon-clippy poping up" type="button" data-content="{{.i18n.Tr "repo.copy_file_path_to_clipboard"}}" data-position="bottom center" data-variation="tiny inverted"></button>
<button class="clipboard-tree-name octicon octicon-clippy poping up" type="button" data-content="{{.i18n.Tr "repo.copy_file_path_to_clipboard"}}" data-position="bottom center" data-variation="tiny inverted"></button>
<span class="repo-edit-file-cancel">{{.i18n.Tr "repo.or"}} <a href="{{EscapePound $.BranchLink}}/{{EscapePound $.TreeName}}">{{.i18n.Tr "repo.cancel_lower"}}</a></span>
<input type="hidden" id="tree-name" name="tree_name" value="{{.TreeName}}" required>
</div>
@ -29,9 +29,9 @@
</div>
<div class="field">
<div class="ui top attached tabular menu" data-write="write" data-preview="preview" data-diff="diff">
<a class="active item" data-tab="write"><i class="icon octicon octicon-code"></i> {{.i18n.Tr "repo.edit_file"}}</a>
<a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}" data-preview-apis="{{.PreviewTabApis}}"><i class="icon octicon octicon-eye"></i> {{.i18n.Tr "repo.release.preview"}}</a>
<a class="item" data-tab="diff" data-url="{{.PreviewDiffUrl}}" data-context="{{.BranchLink}}"><i class="icon octicon octicon-diff"></i> {{.i18n.Tr "repo.preview_changes"}}</a>
<a class="active item" data-tab="write"><i class="octicon octicon-code"></i> {{.i18n.Tr "repo.edit_file"}}</a>
<a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}" data-preview-apis="{{.PreviewTabApis}}"><i class="octicon octicon-eye"></i> {{.i18n.Tr "repo.release.preview"}}</a>
<a class="item" data-tab="diff" data-url="{{.PreviewDiffUrl}}" data-context="{{.BranchLink}}"><i class="octicon octicon-diff"></i> {{.i18n.Tr "repo.preview_changes"}}</a>
</div>
<div class="ui bottom attached active tab segment" data-tab="write">
<textarea id="edit_area" name="content" data-id="repo-{{.Repository.Name}}-{{.TreeName}}"

20
templates/repo/home.tmpl

@ -31,8 +31,20 @@
{{end}}
</div>
</div>
{{if eq $n 0}}
<div class="right fitted item">
<div class="right fitted item">
<div id="file-buttons" class="ui buttons nowrap">
{{if .NewFileLink}}
<a href="{{EscapePound .NewFileLink}}" class="ui button nowrap">
<i class="plus square outline icon"></i> {{.i18n.Tr "repo.new_file"}}
</a>
{{end}}
{{if .UploadFileLink}}
<a href="{{EscapePound .UploadFileLink}}" class="ui button nowrap">
<i class="upload icon"></i> {{.i18n.Tr "repo.upload_file"}}
</a>
{{end}}
</div>
{{if eq $n 0}}
<div class="ui action small input" id="clone-panel">
<button class="ui basic clone button" id="repo-clone-https" data-link="{{.CloneLink.HTTPS}}">
{{if UseHTTPS}}HTTPS{{else}}HTTP{{end}}
@ -54,8 +66,8 @@
</div>
</div>
</div>
</div>
{{end}}
{{end}}
</div>
</div>
{{if .IsFile}}
{{template "repo/view_file" .}}

5
templates/repo/issue/comment_tab.tmpl

@ -4,13 +4,14 @@
<a class="item" data-tab="preview" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}">{{.i18n.Tr "repo.release.preview"}}</a>
</div>
<div class="ui bottom attached active tab segment" data-tab="write">
<textarea id="content" name="content" tabindex="4">{{if .IssueTemplate}}{{.IssueTemplate}}{{end}}{{if .PullRequestTemplate}}{{.PullRequestTemplate}}{{end}}</textarea>
<textarea id="content" class="edit_area" name="content" tabindex="4" data-id="issue-{{.RepoName}}" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.Repo.RepoLink}}">
{{if .IssueTemplate}}{{.IssueTemplate}}{{end}}{{if .PullRequestTemplate}}{{.PullRequestTemplate}}{{end}}</textarea>
</div>
<div class="ui bottom attached tab segment markdown" data-tab="preview">
{{.i18n.Tr "repo.release.loading"}}
</div>
</div>
{{if .IsAttachmentEnabled}}
<div class="attachments"></div>
<div class="files"></div>
<div class="ui basic button dropzone" id="dropzone" data-upload-url="{{AppSubUrl}}/issues/attachments" data-accepts="{{.AttachmentAllowedTypes}}" data-max-file="{{.AttachmentMaxFiles}}" data-max-size="{{.AttachmentMaxSize}}" data-default-message="{{.i18n.Tr "dropzone.default_message"}}" data-invalid-input-type="{{.i18n.Tr "dropzone.invalid_input_type"}}" data-file-too-big="{{.i18n.Tr "dropzone.file_too_big"}}" data-remove-file="{{.i18n.Tr "dropzone.remove_file"}}"></div>
{{end}}

34
templates/repo/view_file.tmpl

@ -12,20 +12,34 @@
<strong>{{.FileName}}</strong> <span class="text grey normal">{{FileSize .FileSize}}</span>
{{end}}
{{if not .ReadmeInList}}
<div class="ui right">
<div class="ui small grey basic buttons">
<div class="ui right file-actions">
<div class="ui buttons">
{{if not .IsViewCommit}}
<a class="ui button" href="{{.RepoLink}}/src/{{.CommitID}}/{{EscapePound .TreeName}}">{{.i18n.Tr "repo.file_permalink"}}</a>
{{end}}
<a class="ui button" href="{{.RepoLink}}/commits/{{EscapePound .BranchName}}/{{EscapePound .TreeName}}">{{.i18n.Tr "repo.file_history"}}</a>
<a class="ui button" href="{{EscapePound .FileLink}}">{{.i18n.Tr "repo.file_raw"}}</a>
</div>
{{if .FileEditLink}}
<a href="{{EscapePound $.FileEditLink}}"><i class="poping up octicon octicon-pencil btn-octicon" data-content="{{.FileEditLinkTooltip}}" data-position="bottom center" data-variation="tiny inverted"></i></a>
{{else}}
<i class="icon octicon octicon-pencil poping up disabled" data-content="{{.FileEditLinkTooltip}}" data-position="bottom center" data-variation="tiny inverted"></i>
{{end}}
{{if .FileDeleteLink}}
<form id="delete-file-form" class="ui form inline-form" action="{{EscapePound $.FileDeleteLink}}" method="post">
{{.CsrfTokenHtml}}
<button onclick="submitDeleteForm()" class="octicon octicon-trashcan btn-octicon btn-octicon-danger poping up" type="button" data-content="{{.FileDeleteLinkTooltip}}" data-position="bottom center" data-variation="tiny inverted"></button>
<input type="hidden" id="delete-message" name="commit_message" value="">
</form>
{{else}}
<i class="icon octicon octicon-trashcan poping up disabled" data-content="{{.FileDeleteLinkTooltip}}" data-position="bottom center" data-variation="tiny inverted"></i>
{{end}}
</div>
{{end}}
</h4>
<div class="ui attached table segment">
<div class="file-view {{if .ReadmeExist}}markdown{{else if .IsFileText}}code-view{{end}} has-emoji">
{{if .ReadmeExist}}
<div class="file-view {{if .IsMarkdown}}markdown{{else if .IsFileText}}code-view{{end}} has-emoji">
{{if .IsMarkdown}}
{{if .FileContent}}{{.FileContent | Str2html}}{{end}}
{{else if not .IsFileText}}
<div class="view-raw ui center">
@ -34,7 +48,7 @@
{{else if .IsPDFFile}}
<iframe width="100%" height="600px" src="{{AppSubUrl}}/plugins/pdfjs-1.4.20/web/viewer.html?file={{EscapePound .FileLink}}"></iframe>
{{else}}
<a href="{{EscapePound .FileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_raw"}}</a>
<a href="{{EscapePound $.FileLink}}" rel="nofollow" class="btn btn-gray btn-radius">{{.i18n.Tr "repo.file_view_raw"}}</a>
{{end}}
</div>
{{else if .FileSize}}
@ -54,3 +68,13 @@
</div>
</div>
</div>
<script>
function submitDeleteForm() {
var message = prompt("{{.i18n.Tr "repo.delete_confirm_message"}}\n\n{{.i18n.Tr "repo.delete_commit_summary"}}", "Delete '{{.TreeName}}'");
if (message != null) {
$("#delete-message").val(message);
$("#delete-file-form").submit()
}
}
</script>

2
templates/repo/wiki/new.tmpl

@ -18,7 +18,7 @@
<input name="title" value="{{.title}}" autofocus required>
</div>
<div class="field">
<textarea id="edit-area" name="content" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}">{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.i18n.Tr "repo.wiki.welcome"}}{{end}}</textarea required>
<textarea id="edit_area" name="content" data-id="wiki-{{.old_title}}" data-url="{{AppSubUrl}}/api/v1/markdown" data-context="{{.RepoLink}}">{{if .PageIsWikiEdit}}{{.content}}{{else}}{{.i18n.Tr "repo.wiki.welcome"}}{{end}}</textarea required>
</div>
<div class="field">
<input name="message" placeholder="{{.i18n.Tr "repo.wiki.default_commit_message"}}">

Loading…
Cancel
Save