finish create issue with labels
This commit is contained in:
		
							parent
							
								
									17de3ab0a3
								
							
						
					
					
						commit
						922f3f3062
					
				
					 9 changed files with 160 additions and 41 deletions
				
			
		|  | @ -144,8 +144,8 @@ func (i *Issue) AfterDelete() { | |||
| 	} | ||||
| } | ||||
| 
 | ||||
| // CreateIssue creates new issue for repository.
 | ||||
| func NewIssue(issue *Issue) (err error) { | ||||
| // CreateIssue creates new issue with labels for repository.
 | ||||
| func NewIssue(issue *Issue, labelIDs []int64) (err error) { | ||||
| 	sess := x.NewSession() | ||||
| 	defer sessionRelease(sess) | ||||
| 	if err = sess.Begin(); err != nil { | ||||
|  | @ -158,6 +158,12 @@ func NewIssue(issue *Issue) (err error) { | |||
| 		return err | ||||
| 	} | ||||
| 
 | ||||
| 	for _, id := range labelIDs { | ||||
| 		if err = issue.addLabel(sess, id); err != nil { | ||||
| 			return fmt.Errorf("addLabel: %v", err) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if err = sess.Commit(); err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | @ -688,6 +694,10 @@ func HasIssueLabel(issueID, labelID int64) bool { | |||
| } | ||||
| 
 | ||||
| func newIssueLabel(e Engine, issueID, labelID int64) error { | ||||
| 	if issueID == 0 || labelID == 0 { | ||||
| 		return nil | ||||
| 	} | ||||
| 
 | ||||
| 	_, err := e.Insert(&IssueLabel{ | ||||
| 		IssueID: issueID, | ||||
| 		LabelID: labelID, | ||||
|  |  | |||
|  | @ -98,8 +98,8 @@ func (f *NewSlackHookForm) Validate(ctx *macaron.Context, errs binding.Errors) b | |||
| //          \/     \/            \/
 | ||||
| 
 | ||||
| type CreateIssueForm struct { | ||||
| 	Title       string  `binding:"Required;MaxSize(255)"` | ||||
| 	LabelIDs    []int64 `form:"label_id"` | ||||
| 	Title       string `binding:"Required;MaxSize(255)"` | ||||
| 	LabelIDs    string `form:"label_ids"` | ||||
| 	MilestoneID int64 | ||||
| 	AssigneeID  int64 | ||||
| 	Content     string | ||||
|  |  | |||
|  | @ -420,3 +420,21 @@ func Subtract(left interface{}, right interface{}) interface{} { | |||
| 		return fleft + float64(rleft) - (fright + float64(rright)) | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| // StringsToInt64s converts a slice of string to a slice of int64.
 | ||||
| func StringsToInt64s(strs []string) []int64 { | ||||
| 	ints := make([]int64, len(strs)) | ||||
| 	for i := range strs { | ||||
| 		ints[i] = com.StrTo(strs[i]).MustInt64() | ||||
| 	} | ||||
| 	return ints | ||||
| } | ||||
| 
 | ||||
| // Int64sToMap converts a slice of int64 to a int64 map.
 | ||||
| func Int64sToMap(ints []int64) map[int64]bool { | ||||
| 	m := make(map[int64]bool) | ||||
| 	for _, i := range ints { | ||||
| 		m[i] = true | ||||
| 	} | ||||
| 	return m | ||||
| } | ||||
|  |  | |||
							
								
								
									
										2
									
								
								public/css/gogs.min.css
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								public/css/gogs.min.css
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -134,24 +134,65 @@ $(document).ready(function () { | |||
|     $('.poping.up').popup(); | ||||
| 
 | ||||
|     // Comment form
 | ||||
|     $('.comment.form .tabular.menu .item').tab(); | ||||
|     $('.comment.form .tabular.menu .item[data-tab="preview"]').click(function () { | ||||
|         var $this = $(this); | ||||
|         console.log($('.comment.form .tab.segment[data-tab="write"] textarea').val()) | ||||
|         console.log($('.comment.form .tab.segment[data-tab="preview"]').html()) | ||||
|         $.post($this.data('url'), { | ||||
|                 "_csrf": csrf, | ||||
|                 "mode": "gfm", | ||||
|                 "context": $this.data('context'), | ||||
|                 "text": $('.comment.form .tab.segment[data-tab="write"] textarea').val() | ||||
|             }, | ||||
|             function (data) { | ||||
|                 console.log(data) | ||||
|                 $('.comment.form .tab.segment[data-tab="preview"]').html(data); | ||||
|     if ($('.comment.form').length > 0) { | ||||
|         var $form = $(this); | ||||
|         $form.find('.tabular.menu .item').tab(); | ||||
|         $form.find('.tabular.menu .item[data-tab="preview"]').click(function () { | ||||
|             var $this = $(this); | ||||
|             $.post($this.data('url'), { | ||||
|                     "_csrf": csrf, | ||||
|                     "mode": "gfm", | ||||
|                     "context": $this.data('context'), | ||||
|                     "text": $form.find('.tab.segment[data-tab="write"] textarea').val() | ||||
|                 }, | ||||
|                 function (data) { | ||||
|                     $form.find('.tab.segment[data-tab="preview"]').html(data); | ||||
|                 } | ||||
|             ); | ||||
|         }); | ||||
| 
 | ||||
|         // Labels
 | ||||
|         var $list = $('.ui.labels.list'); | ||||
|         var $no_select = $list.find('.no-select'); | ||||
|         $('.select-label .item:not(.no-select)').click(function () { | ||||
|             if ($(this).hasClass('checked')) { | ||||
|                 $(this).removeClass('checked') | ||||
|                 $(this).find('.octicon').removeClass('octicon-check') | ||||
|             } else { | ||||
|                 $(this).addClass('checked') | ||||
|                 $(this).find('.octicon').addClass('octicon-check') | ||||
|             } | ||||
|         ) | ||||
|         ; | ||||
|     }) | ||||
| 
 | ||||
|             var label_ids = ""; | ||||
|             $(this).parent().find('.item').each(function () { | ||||
|                 if ($(this).hasClass('checked')) { | ||||
|                     label_ids += $(this).data('id') + ","; | ||||
|                     $($(this).data('id-selector')).removeClass('hide'); | ||||
|                 } else { | ||||
|                     $($(this).data('id-selector')).addClass('hide'); | ||||
|                 } | ||||
|             }); | ||||
|             if (label_ids.length == 0) { | ||||
|                 $no_select.removeClass('hide'); | ||||
|             } else { | ||||
|                 $no_select.addClass('hide'); | ||||
|             } | ||||
|             $($(this).parent().data('id')).val(label_ids); | ||||
|             return false; | ||||
|         }); | ||||
|         $('.select-label .no-select.item').click(function () { | ||||
|             $(this).parent().find('.item').each(function () { | ||||
|                 $(this).removeClass('checked'); | ||||
|                 $(this).find('.octicon').removeClass('octicon-check'); | ||||
|             }); | ||||
| 
 | ||||
|             $list.find('.item').each(function () { | ||||
|                 $(this).addClass('hide'); | ||||
|             }); | ||||
|             $no_select.removeClass('hide'); | ||||
|             $($(this).parent().data('id')).val(''); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     // Helpers.
 | ||||
|     $('.delete-button').click(function () { | ||||
|  |  | |||
|  | @ -102,7 +102,7 @@ footer { | |||
| } | ||||
| 
 | ||||
| .hide { | ||||
| 	display: none; | ||||
| 	display: none!important; | ||||
| } | ||||
| .center { | ||||
| 	text-align: center; | ||||
|  |  | |||
|  | @ -29,6 +29,22 @@ | |||
| 			font-weight: bold; | ||||
| 		} | ||||
| 	} | ||||
| 	.metas .ui.list { | ||||
| 		.label.color { | ||||
| 			padding: 0 8px; | ||||
| 			margin-right: 5px; | ||||
| 		} | ||||
| 		a { | ||||
| 			padding-top: 5px; | ||||
| 			padding-right: 10px; | ||||
| 			.text { | ||||
| 				color: #444; | ||||
| 				&:hover { | ||||
| 					color: #000; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	.filter.menu { | ||||
| 		.label.color { | ||||
| 			margin-left: 15px; | ||||
|  | @ -91,6 +107,10 @@ | |||
| 		.comment.form { | ||||
| 			.metas { | ||||
| 				min-width: 220px; | ||||
| 				.filter.menu { | ||||
| 					max-height: 300px; | ||||
| 					overflow-x: auto; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  |  | |||
|  | @ -180,14 +180,16 @@ func NewIssue(ctx *middleware.Context) { | |||
| 	ctx.Data["IsAttachmentEnabled"] = setting.AttachmentEnabled | ||||
| 	ctx.Data["AttachmentAllowedTypes"] = setting.AttachmentAllowedTypes | ||||
| 
 | ||||
| 	var ( | ||||
| 		repo = ctx.Repo.Repository | ||||
| 		err  error | ||||
| 	) | ||||
| 	ctx.Data["Labels"], err = models.GetLabelsByRepoID(repo.ID) | ||||
| 	if err != nil { | ||||
| 		ctx.Handle(500, "GetLabelsByRepoID: %v", err) | ||||
| 		return | ||||
| 	if ctx.User.IsAdmin { | ||||
| 		var ( | ||||
| 			repo = ctx.Repo.Repository | ||||
| 			err  error | ||||
| 		) | ||||
| 		ctx.Data["Labels"], err = models.GetLabelsByRepoID(repo.ID) | ||||
| 		if err != nil { | ||||
| 			ctx.Handle(500, "GetLabelsByRepoID: %v", err) | ||||
| 			return | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	// // Get all milestones.
 | ||||
|  | @ -219,6 +221,31 @@ func NewIssuePost(ctx *middleware.Context, form auth.CreateIssueForm) { | |||
| 	ctx.Data["IsAttachmentEnabled"] = setting.AttachmentEnabled | ||||
| 	ctx.Data["AttachmentAllowedTypes"] = setting.AttachmentAllowedTypes | ||||
| 
 | ||||
| 	var ( | ||||
| 		repo     = ctx.Repo.Repository | ||||
| 		labelIDs []int64 | ||||
| 	) | ||||
| 	if ctx.User.IsAdmin { | ||||
| 		// Check labels.
 | ||||
| 		labelIDs = base.StringsToInt64s(strings.Split(form.LabelIDs, ",")) | ||||
| 		labelIDMark := base.Int64sToMap(labelIDs) | ||||
| 		labels, err := models.GetLabelsByRepoID(repo.ID) | ||||
| 		if err != nil { | ||||
| 			ctx.Handle(500, "GetLabelsByRepoID: %v", err) | ||||
| 			return | ||||
| 		} | ||||
| 		hasSelected := false | ||||
| 		for i := range labels { | ||||
| 			if labelIDMark[labels[i].ID] { | ||||
| 				labels[i].IsChecked = true | ||||
| 				hasSelected = true | ||||
| 			} | ||||
| 		} | ||||
| 		ctx.Data["HasSelectedLabel"] = hasSelected | ||||
| 		ctx.Data["label_ids"] = form.LabelIDs | ||||
| 		ctx.Data["Labels"] = labels | ||||
| 	} | ||||
| 
 | ||||
| 	if ctx.HasError() { | ||||
| 		ctx.HTML(200, ISSUE_NEW) | ||||
| 		return | ||||
|  | @ -226,18 +253,17 @@ func NewIssuePost(ctx *middleware.Context, form auth.CreateIssueForm) { | |||
| 
 | ||||
| 	issue := &models.Issue{ | ||||
| 		RepoID:   ctx.Repo.Repository.ID, | ||||
| 		Index:    int64(ctx.Repo.Repository.NumIssues) + 1, | ||||
| 		Index:    int64(repo.NumIssues) + 1, | ||||
| 		Name:     form.Title, | ||||
| 		PosterID: ctx.User.Id, | ||||
| 		// MilestoneID: form.MilestoneID,
 | ||||
| 		// AssigneeID:  form.AssigneeID,
 | ||||
| 		// LabelIDs:    "$" + strings.Join(form.LabelIDs, "|$") + "|",
 | ||||
| 		Content: form.Content, | ||||
| 	} | ||||
| 	if err := models.NewIssue(issue); err != nil { | ||||
| 	if err := models.NewIssue(issue, labelIDs); err != nil { | ||||
| 		ctx.Handle(500, "NewIssue", err) | ||||
| 		return | ||||
| 	} else if err := models.NewIssueUserPairs(ctx.Repo.Repository, issue); err != nil { | ||||
| 	} else if err := models.NewIssueUserPairs(repo, issue); err != nil { | ||||
| 		ctx.Handle(500, "NewIssue", err) | ||||
| 		return | ||||
| 	} | ||||
|  |  | |||
|  | @ -38,22 +38,26 @@ | |||
| 	</div> | ||||
| 
 | ||||
| 	{{if .IsRepositoryAdmin}} | ||||
| 	<input id="label_ids" name="label_ids" type="hidden" value="{{.label_ids}}"> | ||||
| 	<div class="four wide column"> | ||||
| 		<div class="ui segment metas"> | ||||
| 			<div class="ui {{if not .Labels}}disabled{{end}} dropdown jump item"> | ||||
| 			<div class="ui {{if not .Labels}}disabled{{end}} jump select-label dropdown"> | ||||
| 				<span class="text"> | ||||
| 					<strong>{{.i18n.Tr "repo.issues.new.labels"}}</strong> | ||||
| 					<span class="octicon octicon-gear"></span> | ||||
| 				</span> | ||||
|         <div class="filter menu"> | ||||
|         	<a class="item" href="#">{{.i18n.Tr "repo.issues.new.clear_labels"}}</a> | ||||
|         <div class="filter menu" data-id="#label_ids"> | ||||
|         	<a class="no-select item" href="#">{{.i18n.Tr "repo.issues.new.clear_labels"}}</a> | ||||
|         	{{range .Labels}} | ||||
|         	<a class="item" href="#"><span class="octicon {{if .IsChecked}}octicon-check{{end}}"></span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name}}</a> | ||||
|         	<a class="{{if .IsChecked}}checked{{end}} item" href="#" data-id="{{.ID}}" data-id-selector="#label_{{.ID}}"><span class="octicon {{if .IsChecked}}octicon-check{{end}}"></span><span class="label color" style="background-color: {{.Color}}"></span> {{.Name}}</a> | ||||
|           {{end}} | ||||
| 				</div> | ||||
| 			</div> | ||||
| 			<div class="ui list"> | ||||
| 				<span class="item {{if .SelectedLabels}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_label"}}</span> | ||||
| 			<div class="ui labels list"> | ||||
| 				<span class="no-select item {{if .HasSelectedLabel}}hide{{end}}">{{.i18n.Tr "repo.issues.new.no_label"}}</span> | ||||
|       	{{range .Labels}} | ||||
|       	<a class="{{if not .IsChecked}}hide{{end}} item" id="label_{{.ID}}" href="{{$.RepoLink}}/issues?labels={{.ID}}"><span class="label color" style="background-color: {{.Color}}"></span> <span class="text">{{.Name}}</span></a> | ||||
|         {{end}} | ||||
| 			</div> | ||||
| 			<!-- <div class="ui divider"></div> | ||||
| 			<div class="ui {{if .Labels}}disabled{{end}} dropdown jump item"> | ||||
|  |  | |||
		Loading…
	
		Reference in a new issue