| @@ -181,6 +181,8 @@ SERVICE = server | |||||
| DISABLE_GRAVATAR = false | DISABLE_GRAVATAR = false | ||||
| [attachment] | [attachment] | ||||
| ; Whether attachments are enabled. Defaults to `true` | |||||
| ENABLE = | |||||
| ; Path for attachments. Defaults to files/attachments | ; Path for attachments. Defaults to files/attachments | ||||
| PATH = | PATH = | ||||
| ; One or more allowed types, e.g. image/jpeg|image/png | ; One or more allowed types, e.g. image/jpeg|image/png | ||||
| @@ -76,6 +76,7 @@ var ( | |||||
| AttachmentAllowedTypes string | AttachmentAllowedTypes string | ||||
| AttachmentMaxSize int64 | AttachmentMaxSize int64 | ||||
| AttachmentMaxFiles int | AttachmentMaxFiles int | ||||
| AttachmentEnabled bool | |||||
| // Cache settings. | // Cache settings. | ||||
| Cache cache.Cache | Cache cache.Cache | ||||
| @@ -176,6 +177,7 @@ func NewConfigContext() { | |||||
| AttachmentAllowedTypes = Cfg.MustValue("attachment", "ALLOWED_TYPES", "*/*") | AttachmentAllowedTypes = Cfg.MustValue("attachment", "ALLOWED_TYPES", "*/*") | ||||
| AttachmentMaxSize = Cfg.MustInt64("attachment", "MAX_SIZE", 32) | AttachmentMaxSize = Cfg.MustInt64("attachment", "MAX_SIZE", 32) | ||||
| AttachmentMaxFiles = Cfg.MustInt("attachment", "MAX_FILES", 10) | AttachmentMaxFiles = Cfg.MustInt("attachment", "MAX_FILES", 10) | ||||
| AttachmentEnabled = Cfg.MustBool("attachment", "ENABLE", true) | |||||
| if err = os.MkdirAll(AttachmentPath, os.ModePerm); err != nil { | if err = os.MkdirAll(AttachmentPath, os.ModePerm); err != nil { | ||||
| log.Fatal("Could not create directory %s: %s", AttachmentPath, err) | log.Fatal("Could not create directory %s: %s", AttachmentPath, err) | ||||
| @@ -160,6 +160,7 @@ func CreateIssue(ctx *middleware.Context, params martini.Params) { | |||||
| ctx.Data["Title"] = "Create issue" | ctx.Data["Title"] = "Create issue" | ||||
| ctx.Data["IsRepoToolbarIssues"] = true | ctx.Data["IsRepoToolbarIssues"] = true | ||||
| ctx.Data["IsRepoToolbarIssuesList"] = false | ctx.Data["IsRepoToolbarIssuesList"] = false | ||||
| ctx.Data["AttachmentsEnabled"] = setting.AttachmentEnabled | |||||
| var err error | var err error | ||||
| // Get all milestones. | // Get all milestones. | ||||
| @@ -190,6 +191,7 @@ func CreateIssuePost(ctx *middleware.Context, params martini.Params, form auth.C | |||||
| ctx.Data["Title"] = "Create issue" | ctx.Data["Title"] = "Create issue" | ||||
| ctx.Data["IsRepoToolbarIssues"] = true | ctx.Data["IsRepoToolbarIssues"] = true | ||||
| ctx.Data["IsRepoToolbarIssuesList"] = false | ctx.Data["IsRepoToolbarIssuesList"] = false | ||||
| ctx.Data["AttachmentsEnabled"] = setting.AttachmentEnabled | |||||
| var err error | var err error | ||||
| // Get all milestones. | // Get all milestones. | ||||
| @@ -239,7 +241,9 @@ func CreateIssuePost(ctx *middleware.Context, params martini.Params, form auth.C | |||||
| return | return | ||||
| } | } | ||||
| uploadFiles(ctx, issue.Id, 0) | |||||
| if setting.AttachmentEnabled { | |||||
| uploadFiles(ctx, issue.Id, 0) | |||||
| } | |||||
| // Update mentions. | // Update mentions. | ||||
| ms := base.MentionPattern.FindAllString(issue.Content, -1) | ms := base.MentionPattern.FindAllString(issue.Content, -1) | ||||
| @@ -313,6 +317,8 @@ func checkLabels(labels, allLabels []*models.Label) { | |||||
| } | } | ||||
| func ViewIssue(ctx *middleware.Context, params martini.Params) { | func ViewIssue(ctx *middleware.Context, params martini.Params) { | ||||
| ctx.Data["AttachmentsEnabled"] = setting.AttachmentEnabled | |||||
| idx, _ := base.StrTo(params["index"]).Int64() | idx, _ := base.StrTo(params["index"]).Int64() | ||||
| if idx == 0 { | if idx == 0 { | ||||
| ctx.Handle(404, "issue.ViewIssue", nil) | ctx.Handle(404, "issue.ViewIssue", nil) | ||||
| @@ -628,6 +634,10 @@ func UpdateAssignee(ctx *middleware.Context) { | |||||
| } | } | ||||
| func uploadFiles(ctx *middleware.Context, issueId, commentId int64) { | func uploadFiles(ctx *middleware.Context, issueId, commentId int64) { | ||||
| if !setting.AttachmentEnabled { | |||||
| return | |||||
| } | |||||
| allowedTypes := strings.Split(setting.AttachmentAllowedTypes, "|") | allowedTypes := strings.Split(setting.AttachmentAllowedTypes, "|") | ||||
| attachments := ctx.Req.MultipartForm.File["attachments"] | attachments := ctx.Req.MultipartForm.File["attachments"] | ||||
| @@ -101,13 +101,17 @@ | |||||
| <div class="tab-pane issue-preview-content" id="issue-preview">loading...</div> | <div class="tab-pane issue-preview-content" id="issue-preview">loading...</div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{if .AttachmentsEnabled}} | |||||
| <div id="attached"> | <div id="attached"> | ||||
| <div id="attached-list"></div> | <div id="attached-list"></div> | ||||
| </div> | </div> | ||||
| {{end}} | |||||
| <div class="text-right panel-body"> | <div class="text-right panel-body"> | ||||
| <div class="form-group"> | <div class="form-group"> | ||||
| {{if .AttachmentsEnabled}} | |||||
| <input type="file" accept="{{.AllowedTypes}}" style="display: none;" id="attachments-input" name="attachments" multiple /> | <input type="file" accept="{{.AllowedTypes}}" style="display: none;" id="attachments-input" name="attachments" multiple /> | ||||
| <button class="btn-default btn attachment-add" id="attachments-button">Select Attachments...</button> | <button class="btn-default btn attachment-add" id="attachments-button">Select Attachments...</button> | ||||
| {{end}} | |||||
| <input type="hidden" value="id" name="repo-id"/> | <input type="hidden" value="id" name="repo-id"/> | ||||
| <button class="btn-success btn">Create new issue</button> | <button class="btn-success btn">Create new issue</button> | ||||
| </div> | </div> | ||||
| @@ -137,13 +137,17 @@ | |||||
| <div class="tab-pane issue-preview-content" id="issue-preview">Loading...</div> | <div class="tab-pane issue-preview-content" id="issue-preview">Loading...</div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| {{if .AttachmentsEnabled}} | |||||
| <div id="attached"> | <div id="attached"> | ||||
| <div id="attached-list"></div> | <div id="attached-list"></div> | ||||
| </div> | </div> | ||||
| {{end}} | |||||
| <div class="text-right"> | <div class="text-right"> | ||||
| <div class="form-group"> | <div class="form-group"> | ||||
| {{if .AttachmentsEnabled}} | |||||
| <input type="file" accept="{{.AllowedTypes}}" style="display: none;" id="attachments-input" name="attachments" multiple /> | <input type="file" accept="{{.AllowedTypes}}" style="display: none;" id="attachments-input" name="attachments" multiple /> | ||||
| <button class="btn-default btn attachment-add" id="attachments-button">Select Attachments...</button> | <button class="btn-default btn attachment-add" id="attachments-button">Select Attachments...</button> | ||||
| {{end}} | |||||
| {{if .IsIssueOwner}}{{if .Issue.IsClosed}} | {{if .IsIssueOwner}}{{if .Issue.IsClosed}} | ||||
| <input type="submit" class="btn-default btn issue-open" id="issue-open-btn" data-origin="Reopen" data-text="Reopen & Comment" name="change_status" value="Reopen"/>{{else}} | <input type="submit" class="btn-default btn issue-open" id="issue-open-btn" data-origin="Reopen" data-text="Reopen & Comment" name="change_status" value="Reopen"/>{{else}} | ||||
| <input type="submit" class="btn-default btn issue-close" id="issue-close-btn" data-origin="Close" data-text="Close & Comment" name="change_status" value="Close"/>{{end}}{{end}} | <input type="submit" class="btn-default btn issue-close" id="issue-close-btn" data-origin="Close" data-text="Close & Comment" name="change_status" value="Close"/>{{end}}{{end}} | ||||