mirror of
				https://gitea.com/gitea/tea.git
				synced 2025-10-30 16:55:25 +01:00 
			
		
		
		
	Add --fields to notification & milestone listings (#422)
				
					
				
			Together with #415 this finally adds the field flag to all entity listings. closes #342 ### ⚠️ breaking changes ⚠️ This changes the column names of `tea milestones ls`: ```diff - TITLE | OPEN/CLOSED ISSUES | DUEDATE + TITLE | ITEMS | DUEDATE ``` Co-authored-by: Norwin <git@nroo.de> Co-authored-by: 6543 <6543@obermui.de> Reviewed-on: https://gitea.com/gitea/tea/pulls/422 Reviewed-by: delvh <dev.lh@web.de> Reviewed-by: 6543 <6543@obermui.de> Co-authored-by: Norwin <noerw@noreply.gitea.io> Co-committed-by: Norwin <noerw@noreply.gitea.io>
This commit is contained in:
		| @@ -13,6 +13,10 @@ import ( | |||||||
| 	"github.com/urfave/cli/v2" | 	"github.com/urfave/cli/v2" | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | var fieldsFlag = flags.FieldsFlag(print.MilestoneFields, []string{ | ||||||
|  | 	"title", "items", "duedate", | ||||||
|  | }) | ||||||
|  |  | ||||||
| // CmdMilestonesList represents a sub command of milestones to list milestones | // CmdMilestonesList represents a sub command of milestones to list milestones | ||||||
| var CmdMilestonesList = cli.Command{ | var CmdMilestonesList = cli.Command{ | ||||||
| 	Name:        "list", | 	Name:        "list", | ||||||
| @@ -22,6 +26,7 @@ var CmdMilestonesList = cli.Command{ | |||||||
| 	ArgsUsage:   " ", // command does not accept arguments | 	ArgsUsage:   " ", // command does not accept arguments | ||||||
| 	Action:      RunMilestonesList, | 	Action:      RunMilestonesList, | ||||||
| 	Flags: append([]cli.Flag{ | 	Flags: append([]cli.Flag{ | ||||||
|  | 		fieldsFlag, | ||||||
| 		&cli.StringFlag{ | 		&cli.StringFlag{ | ||||||
| 			Name:        "state", | 			Name:        "state", | ||||||
| 			Usage:       "Filter by milestone state (all|open|closed)", | 			Usage:       "Filter by milestone state (all|open|closed)", | ||||||
| @@ -37,10 +42,18 @@ func RunMilestonesList(cmd *cli.Context) error { | |||||||
| 	ctx := context.InitCommand(cmd) | 	ctx := context.InitCommand(cmd) | ||||||
| 	ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) | 	ctx.Ensure(context.CtxRequirement{RemoteRepo: true}) | ||||||
|  |  | ||||||
|  | 	fields, err := fieldsFlag.GetValues(cmd) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	state := gitea.StateOpen | 	state := gitea.StateOpen | ||||||
| 	switch ctx.String("state") { | 	switch ctx.String("state") { | ||||||
| 	case "all": | 	case "all": | ||||||
| 		state = gitea.StateAll | 		state = gitea.StateAll | ||||||
|  | 		if !cmd.IsSet("fields") { // add to default fields | ||||||
|  | 			fields = append(fields, "state") | ||||||
|  | 		} | ||||||
| 	case "closed": | 	case "closed": | ||||||
| 		state = gitea.StateClosed | 		state = gitea.StateClosed | ||||||
| 	} | 	} | ||||||
| @@ -55,6 +68,6 @@ func RunMilestonesList(cmd *cli.Context) error { | |||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	print.MilestonesList(milestones, ctx.Output, state) | 	print.MilestonesList(milestones, ctx.Output, fields) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -15,7 +15,11 @@ import ( | |||||||
| 	"github.com/urfave/cli/v2" | 	"github.com/urfave/cli/v2" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| var notifTypeFlag = flags.NewCsvFlag("types", "subject types to filter by", []string{"t"}, | var notifyFieldsFlag = flags.FieldsFlag(print.NotificationFields, []string{ | ||||||
|  | 	"id", "status", "index", "type", "state", "title", | ||||||
|  | }) | ||||||
|  |  | ||||||
|  | var notifyTypeFlag = flags.NewCsvFlag("types", "subject types to filter by", []string{"t"}, | ||||||
| 	[]string{"issue", "pull", "repository", "commit"}, nil) | 	[]string{"issue", "pull", "repository", "commit"}, nil) | ||||||
|  |  | ||||||
| // CmdNotificationsList represents a sub command of notifications to list notifications | // CmdNotificationsList represents a sub command of notifications to list notifications | ||||||
| @@ -26,7 +30,10 @@ var CmdNotificationsList = cli.Command{ | |||||||
| 	Description: `List notifications`, | 	Description: `List notifications`, | ||||||
| 	ArgsUsage:   " ", // command does not accept arguments | 	ArgsUsage:   " ", // command does not accept arguments | ||||||
| 	Action:      RunNotificationsList, | 	Action:      RunNotificationsList, | ||||||
| 	Flags:       append([]cli.Flag{notifTypeFlag}, flags.NotificationFlags...), | 	Flags: append([]cli.Flag{ | ||||||
|  | 		notifyFieldsFlag, | ||||||
|  | 		notifyTypeFlag, | ||||||
|  | 	}, flags.NotificationFlags...), | ||||||
| } | } | ||||||
|  |  | ||||||
| // RunNotificationsList list notifications | // RunNotificationsList list notifications | ||||||
| @@ -41,7 +48,7 @@ func RunNotificationsList(ctx *cli.Context) error { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	var types []gitea.NotifySubjectType | 	var types []gitea.NotifySubjectType | ||||||
| 	typesStr, err := notifTypeFlag.GetValues(ctx) | 	typesStr, err := notifyTypeFlag.GetValues(ctx) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		return err | 		return err | ||||||
| 	} | 	} | ||||||
| @@ -67,7 +74,17 @@ func listNotifications(cmd *cli.Context, status []gitea.NotifyStatus, subjects [ | |||||||
| 		listOpts.Page = 1 | 		listOpts.Page = 1 | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	fields, err := notifyFieldsFlag.GetValues(cmd) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return err | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	if all { | 	if all { | ||||||
|  | 		// add repository to the default fields | ||||||
|  | 		if !cmd.IsSet("fields") { | ||||||
|  | 			fields = append(fields, "repository") | ||||||
|  | 		} | ||||||
|  |  | ||||||
| 		news, _, err = client.ListNotifications(gitea.ListNotificationOptions{ | 		news, _, err = client.ListNotifications(gitea.ListNotificationOptions{ | ||||||
| 			ListOptions:  listOpts, | 			ListOptions:  listOpts, | ||||||
| 			Status:       status, | 			Status:       status, | ||||||
| @@ -85,6 +102,6 @@ func listNotifications(cmd *cli.Context, status []gitea.NotifyStatus, subjects [ | |||||||
| 		log.Fatal(err) | 		log.Fatal(err) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	print.NotificationsList(news, ctx.Output, all) | 	print.NotificationsList(news, ctx.Output, fields) | ||||||
| 	return nil | 	return nil | ||||||
| } | } | ||||||
|   | |||||||
| @@ -28,7 +28,7 @@ var CmdNotificationsMarkRead = cli.Command{ | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		if !flags.NotificationStateFlag.IsSet() { | 		if !cmd.IsSet(flags.NotificationStateFlag.Name) { | ||||||
| 			filter = []string{string(gitea.NotifyStatusUnread)} | 			filter = []string{string(gitea.NotifyStatusUnread)} | ||||||
| 		} | 		} | ||||||
| 		return markNotificationAs(cmd, filter, gitea.NotifyStatusRead) | 		return markNotificationAs(cmd, filter, gitea.NotifyStatusRead) | ||||||
| @@ -49,7 +49,7 @@ var CmdNotificationsMarkUnread = cli.Command{ | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		if !flags.NotificationStateFlag.IsSet() { | 		if !cmd.IsSet(flags.NotificationStateFlag.Name) { | ||||||
| 			filter = []string{string(gitea.NotifyStatusRead)} | 			filter = []string{string(gitea.NotifyStatusRead)} | ||||||
| 		} | 		} | ||||||
| 		return markNotificationAs(cmd, filter, gitea.NotifyStatusUnread) | 		return markNotificationAs(cmd, filter, gitea.NotifyStatusUnread) | ||||||
| @@ -70,7 +70,7 @@ var CmdNotificationsMarkPinned = cli.Command{ | |||||||
| 		if err != nil { | 		if err != nil { | ||||||
| 			return err | 			return err | ||||||
| 		} | 		} | ||||||
| 		if !flags.NotificationStateFlag.IsSet() { | 		if !cmd.IsSet(flags.NotificationStateFlag.Name) { | ||||||
| 			filter = []string{string(gitea.NotifyStatusUnread)} | 			filter = []string{string(gitea.NotifyStatusUnread)} | ||||||
| 		} | 		} | ||||||
| 		return markNotificationAs(cmd, filter, gitea.NotifyStatusPinned) | 		return markNotificationAs(cmd, filter, gitea.NotifyStatusPinned) | ||||||
|   | |||||||
| @@ -24,40 +24,65 @@ func MilestoneDetails(milestone *gitea.Milestone) { | |||||||
| } | } | ||||||
|  |  | ||||||
| // MilestonesList prints a listing of milestones | // MilestonesList prints a listing of milestones | ||||||
| func MilestonesList(miles []*gitea.Milestone, output string, state gitea.StateType) { | func MilestonesList(news []*gitea.Milestone, output string, fields []string) { | ||||||
| 	headers := []string{ | 	var printables = make([]printable, len(news)) | ||||||
| 		"Title", | 	for i, x := range news { | ||||||
|  | 		printables[i] = &printableMilestone{x} | ||||||
| 	} | 	} | ||||||
| 	if state == gitea.StateAll { | 	t := tableFromItems(fields, printables, isMachineReadable(output)) | ||||||
| 		headers = append(headers, "State") |  | ||||||
| 	} |  | ||||||
| 	headers = append(headers, |  | ||||||
| 		"Open/Closed Issues", |  | ||||||
| 		"DueDate", |  | ||||||
| 	) |  | ||||||
|  |  | ||||||
| 	t := table{headers: headers} |  | ||||||
|  |  | ||||||
| 	for _, m := range miles { |  | ||||||
| 		var deadline = "" |  | ||||||
|  |  | ||||||
| 		if m.Deadline != nil && !m.Deadline.IsZero() { |  | ||||||
| 			deadline = FormatTime(*m.Deadline, isMachineReadable(output)) |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		item := []string{ |  | ||||||
| 			m.Title, |  | ||||||
| 		} |  | ||||||
| 		if state == gitea.StateAll { |  | ||||||
| 			item = append(item, string(m.State)) |  | ||||||
| 		} |  | ||||||
| 		item = append(item, |  | ||||||
| 			fmt.Sprintf("%d/%d", m.OpenIssues, m.ClosedIssues), |  | ||||||
| 			deadline, |  | ||||||
| 		) |  | ||||||
| 		t.addRowSlice(item) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	t.sort(0, true) | 	t.sort(0, true) | ||||||
| 	t.print(output) | 	t.print(output) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | // MilestoneFields are all available fields to print with MilestonesList | ||||||
|  | var MilestoneFields = []string{ | ||||||
|  | 	"title", | ||||||
|  | 	"state", | ||||||
|  | 	"items_open", | ||||||
|  | 	"items_closed", | ||||||
|  | 	"items", | ||||||
|  | 	"duedate", | ||||||
|  | 	"description", | ||||||
|  | 	"created", | ||||||
|  | 	"updated", | ||||||
|  | 	"closed", | ||||||
|  | 	"id", | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type printableMilestone struct { | ||||||
|  | 	*gitea.Milestone | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (m printableMilestone) FormatField(field string, machineReadable bool) string { | ||||||
|  | 	switch field { | ||||||
|  | 	case "title": | ||||||
|  | 		return m.Title | ||||||
|  | 	case "state": | ||||||
|  | 		return string(m.State) | ||||||
|  | 	case "items_open": | ||||||
|  | 		return fmt.Sprintf("%d", m.OpenIssues) | ||||||
|  | 	case "items_closed": | ||||||
|  | 		return fmt.Sprintf("%d", m.ClosedIssues) | ||||||
|  | 	case "items": | ||||||
|  | 		return fmt.Sprintf("%d/%d", m.OpenIssues, m.ClosedIssues) | ||||||
|  | 	case "duedate": | ||||||
|  | 		if m.Deadline != nil && !m.Deadline.IsZero() { | ||||||
|  | 			return FormatTime(*m.Deadline, machineReadable) | ||||||
|  | 		} | ||||||
|  | 	case "id": | ||||||
|  | 		return fmt.Sprintf("%d", m.ID) | ||||||
|  | 	case "description": | ||||||
|  | 		return m.Description | ||||||
|  | 	case "created": | ||||||
|  | 		return FormatTime(m.Created, machineReadable) | ||||||
|  | 	case "updated": | ||||||
|  | 		if m.Updated != nil { | ||||||
|  | 			return FormatTime(*m.Updated, machineReadable) | ||||||
|  | 		} | ||||||
|  | 	case "closed": | ||||||
|  | 		if m.Closed != nil { | ||||||
|  | 			return FormatTime(*m.Closed, machineReadable) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return "" | ||||||
|  | } | ||||||
|   | |||||||
| @@ -12,26 +12,51 @@ import ( | |||||||
| ) | ) | ||||||
|  |  | ||||||
| // NotificationsList prints a listing of notification threads | // NotificationsList prints a listing of notification threads | ||||||
| func NotificationsList(news []*gitea.NotificationThread, output string, showRepository bool) { | func NotificationsList(news []*gitea.NotificationThread, output string, fields []string) { | ||||||
| 	headers := []string{ | 	var printables = make([]printable, len(news)) | ||||||
| 		"ID", | 	for i, x := range news { | ||||||
| 		"Status", | 		printables[i] = &printableNotification{x} | ||||||
| 		"Type", |  | ||||||
| 		"State", |  | ||||||
| 		"Index", |  | ||||||
| 		"Title", |  | ||||||
| 	} |  | ||||||
| 	if showRepository { |  | ||||||
| 		headers = append(headers, "Repository") |  | ||||||
| 	} | 	} | ||||||
|  | 	t := tableFromItems(fields, printables, isMachineReadable(output)) | ||||||
|  | 	t.print(output) | ||||||
|  | } | ||||||
|  |  | ||||||
| 	t := table{headers: headers} | // NotificationFields are all available fields to print with NotificationsList | ||||||
|  | var NotificationFields = []string{ | ||||||
|  | 	"id", | ||||||
|  | 	"status", | ||||||
|  | 	"updated", | ||||||
|  |  | ||||||
| 	for _, n := range news { | 	// these are about the notification subject | ||||||
| 		if n.Subject == nil { | 	"index", | ||||||
| 			continue | 	"type", | ||||||
|  | 	"state", | ||||||
|  | 	"title", | ||||||
|  | 	"repository", | ||||||
|  | } | ||||||
|  |  | ||||||
|  | type printableNotification struct { | ||||||
|  | 	*gitea.NotificationThread | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func (n printableNotification) FormatField(field string, machineReadable bool) string { | ||||||
|  | 	switch field { | ||||||
|  | 	case "id": | ||||||
|  | 		return fmt.Sprintf("%d", n.ID) | ||||||
|  |  | ||||||
|  | 	case "status": | ||||||
|  | 		status := "read" | ||||||
|  | 		if n.Pinned { | ||||||
|  | 			status = "pinned" | ||||||
|  | 		} else if n.Unread { | ||||||
|  | 			status = "unread" | ||||||
| 		} | 		} | ||||||
| 		// if pull or Issue get Index | 		return status | ||||||
|  |  | ||||||
|  | 	case "updated": | ||||||
|  | 		return FormatTime(n.UpdatedAt, machineReadable) | ||||||
|  |  | ||||||
|  | 	case "index": | ||||||
| 		var index string | 		var index string | ||||||
| 		if n.Subject.Type == "Issue" || n.Subject.Type == "Pull" { | 		if n.Subject.Type == "Issue" || n.Subject.Type == "Pull" { | ||||||
| 			index = n.Subject.URL | 			index = n.Subject.URL | ||||||
| @@ -39,31 +64,20 @@ func NotificationsList(news []*gitea.NotificationThread, output string, showRepo | |||||||
| 			if len(urlParts) != 0 { | 			if len(urlParts) != 0 { | ||||||
| 				index = urlParts[len(urlParts)-1] | 				index = urlParts[len(urlParts)-1] | ||||||
| 			} | 			} | ||||||
| 			index = "#" + index |  | ||||||
| 		} | 		} | ||||||
|  | 		return index | ||||||
|  |  | ||||||
| 		status := "read" | 	case "type": | ||||||
| 		if n.Pinned { | 		return string(n.Subject.Type) | ||||||
| 			status = "pinned" |  | ||||||
| 		} else if n.Unread { |  | ||||||
| 			status = "unread" |  | ||||||
| 		} |  | ||||||
|  |  | ||||||
| 		item := []string{ | 	case "state": | ||||||
| 			fmt.Sprint(n.ID), | 		return string(n.Subject.State) | ||||||
| 			status, |  | ||||||
| 			string(n.Subject.Type), | 	case "title": | ||||||
| 			string(n.Subject.State), | 		return n.Subject.Title | ||||||
| 			index, |  | ||||||
| 			n.Subject.Title, | 	case "repo", "repository": | ||||||
| 		} | 		return n.Repository.FullName | ||||||
| 		if showRepository { |  | ||||||
| 			item = append(item, n.Repository.FullName) |  | ||||||
| 		} |  | ||||||
| 		t.addRowSlice(item) |  | ||||||
| 	} |  | ||||||
|  |  | ||||||
| 	if t.Len() != 0 { |  | ||||||
| 		t.print(output) |  | ||||||
| 	} | 	} | ||||||
|  | 	return "" | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 Norwin
					Norwin