Skip to content
This repository has been archived by the owner on Feb 21, 2024. It is now read-only.

Commit

Permalink
Generate story list with same tag in ideas
Browse files Browse the repository at this point in the history
  • Loading branch information
falconandy committed Jul 7, 2018
1 parent a850f95 commit e4fd955
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 50 deletions.
11 changes: 10 additions & 1 deletion backlog/backlog_idea.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io/ioutil"
"os"
"path/filepath"
"regexp"
"sort"
"strings"
"time"
Expand All @@ -16,6 +17,10 @@ const (
BacklogIdeaRankMetadataKey = "Rank"
)

var (
RelatedItemsRegex = regexp.MustCompile(`(?i)^#+\s*stories\s*$`)
)

type BacklogIdea struct {
name string
markdown *MarkdownContent
Expand All @@ -25,7 +30,7 @@ func LoadBacklogIdea(ideaPath string) (*BacklogIdea, error) {
markdown, err := LoadMarkdown(ideaPath,
[]string{CreatedMetadataKey, ModifiedMetadataKey, BacklogIdeaAuthorMetadataKey, BacklogIdeaTagsMetadataKey, BacklogIdeaRankMetadataKey},
nil,
"", nil)
"", RelatedItemsRegex)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -54,6 +59,10 @@ func (idea *BacklogIdea) SetTitle(title string) {
idea.markdown.SetTitle(title)
}

func (idea *BacklogIdea) SetFooter(footer []string) {
idea.markdown.SetFooter(footer)
}

func (idea *BacklogIdea) SetCreated(timestamp string) {
idea.markdown.SetMetadataValue(CreatedMetadataKey, timestamp)
}
Expand Down
13 changes: 13 additions & 0 deletions backlog/backlog_view.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,19 @@ func (bv BacklogView) WriteMarkdownItemsWithProject(overviews map[*BacklogItem]*
return result
}

func (bv BacklogView) WriteMarkdownItemsWithProjectAndStatus(overviews map[*BacklogItem]*BacklogOverview, items []*BacklogItem, baseDir, tagsDir string) []string {
result := make([]string, 0, 50)
headers := make([]string, 0, 2)
headers = append(headers, fmt.Sprintf("| User | Project | Title | Status | Points | Tags |"))
headers = append(headers, "|---|---|---|---|:---:|---|")
result = append(result, headers...)
for _, item := range items {
line := fmt.Sprintf("| %s | %s | %s | %s | %s | %s |", item.Assigned(), MakeOverviewLink(overviews[item], baseDir), MakeItemLink(item, baseDir), item.Status(), item.Estimate(), MakeTagLinks(item.Tags(), tagsDir, baseDir))
result = append(result, line)
}
return result
}

func (bv BacklogView) VelocityText(bck *Backlog, weekCount, width int) (string, error) {
items := bck.AllItemsByStatus(FinishedStatus.Code)
currentDate := time.Now().UTC()
Expand Down
12 changes: 10 additions & 2 deletions backlog/markdown.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,9 +146,17 @@ func NewMarkdown(data, markdownPath string, topMetadataKeys, bottomMetadataKeys
content.addGroup(currentGroup)
}
} else {
content.freeText = lines[parsed:]
}
for _, line := range lines[parsed:] {
if len(content.footer) == 0 && footerRe != nil && footerRe.MatchString(line) {
content.footer = append(content.footer, line)
} else if len(content.footer) > 0 {
content.footer = append(content.footer, line)
} else {
content.freeText = append(content.freeText, line)
}

}
}
}
content.isDirty = false
return content
Expand Down
146 changes: 99 additions & 47 deletions commands/sync_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,6 +288,11 @@ func (a *SyncAction) backlogDirs(rootDir string) ([]string, error) {
}

func (a *SyncAction) updateIdeas(rootDir string) error {
_, itemsTags, ideasTags, overviews, err := a.getItemsAndIdeasTags(rootDir)
if err != nil {
return err
}

ideasDir := filepath.Join(rootDir, backlog.IdeasDirectoryName)
ideas, err := backlog.LoadIdeas(ideasDir)
if err != nil {
Expand All @@ -296,8 +301,9 @@ func (a *SyncAction) updateIdeas(rootDir string) error {

ideasByRank := make(map[string][]*backlog.BacklogIdea)
var ranks []string
tagsDir := filepath.Join(rootDir, backlog.TagsDirectoryName)
for _, idea := range ideas {
err := a.updateIdea(rootDir, idea)
err := a.updateIdea(rootDir, tagsDir, idea, ideasTags, itemsTags, overviews)
if err != nil {
fmt.Printf("can't update idea '%s'\n", err)
}
Expand Down Expand Up @@ -331,7 +337,7 @@ func (a *SyncAction) updateIdeas(rootDir string) error {
return ioutil.WriteFile(filepath.Join(rootDir, backlog.IdeasFileName), []byte(strings.Join(lines, "\n")), 0644)
}

func (a *SyncAction) updateIdea(rootDir string, idea *backlog.BacklogIdea) error {
func (a *SyncAction) updateIdea(rootDir, tagsDir string, idea *backlog.BacklogIdea, ideasTags map[string][]*backlog.BacklogIdea, itemsTags map[string][]*backlog.BacklogItem, overviews map[*backlog.BacklogItem]*backlog.BacklogOverview) error {
if !idea.HasMetadata() {
author, created, err := git.InitCommitInfo(idea.Path())
if err != nil {
Expand All @@ -356,6 +362,42 @@ func (a *SyncAction) updateIdea(rootDir string, idea *backlog.BacklogIdea) error
idea.Save()
}
idea.UpdateLinks(rootDir)

ideaTags := make(map[string]struct{})
NextTag:
for tag, tagIdeas := range ideasTags {
for _, tagIdea := range tagIdeas {
if tagIdea.Path() == idea.Path() {
ideaTags[tag] = struct{}{}
continue NextTag
}
}
}

itemsByStatus := make(map[string][]*backlog.BacklogItem)
for tag := range ideaTags {
for _, item := range itemsTags[tag] {
itemStatus := strings.ToLower(item.Status())
itemsByStatus[itemStatus] = append(itemsByStatus[itemStatus], item)
}
}
for _, statusItems := range itemsByStatus {
sorter := backlog.NewBacklogItemsSorter()
sorter.SortItemsByModifiedDesc(statusItems)
}

var items []*backlog.BacklogItem
for _, status := range backlog.AllStatuses {
items = append(items, itemsByStatus[strings.ToLower(status.Name)]...)
}

itemsLines := []string{"## Stories", ""}
if len(items) > 0 {
itemsLines = append(itemsLines, backlog.BacklogView{}.WriteMarkdownItemsWithProjectAndStatus(overviews, items, filepath.Dir(idea.Path()), tagsDir)...)
}
idea.SetFooter(itemsLines)
idea.Save()

return nil
}

Expand Down Expand Up @@ -383,58 +425,14 @@ func (a *SyncAction) moveItemsToActiveAndArchiveDirectory(backlogDir string) err
}

func (a *SyncAction) updateTags(rootDir string) error {
backlogDirs, err := a.backlogDirs(rootDir)
if err != nil {
return err
}
tagsDir := filepath.Join(rootDir, backlog.TagsDirectoryName)
os.MkdirAll(tagsDir, 0777)

ideasDir := filepath.Join(rootDir, backlog.IdeasDirectoryName)
ideas, err := backlog.LoadIdeas(ideasDir)
allTags, itemsTags, ideasTags, overviews, err := a.getItemsAndIdeasTags(rootDir)
if err != nil {
return err
}

allTags := make(map[string]struct{})
itemsTags := make(map[string][]*backlog.BacklogItem)
ideasTags := make(map[string][]*backlog.BacklogIdea)

overviews := make(map[*backlog.BacklogItem]*backlog.BacklogOverview)
for _, backlogDir := range backlogDirs {
overviewPath, ok := findOverviewFileInRootDirectory(backlogDir)
if !ok {
return fmt.Errorf("the overview file isn't found for %s", backlogDir)
}
overview, err := backlog.LoadBacklogOverview(overviewPath)
if err != nil {
return err
}

bck, err := backlog.LoadBacklog(backlogDir)
if err != nil {
return err
}

items := bck.ActiveItems()
for _, item := range items {
for _, tag := range item.Tags() {
tag = strings.ToLower(tag)
allTags[tag] = struct{}{}
itemsTags[tag] = append(itemsTags[tag], item)
overviews[item] = overview
}
}
}

for _, idea := range ideas {
for _, tag := range idea.Tags() {
tag = strings.ToLower(tag)
allTags[tag] = struct{}{}
ideasTags[tag] = append(ideasTags[tag], idea)
}
}

tagsFileNames := make(map[string]bool)
for tag := range allTags {
tagItems := itemsTags[tag]
Expand Down Expand Up @@ -674,3 +672,57 @@ func (a *SyncAction) updateItemsFileNames(rootDir string) error {
}
return nil
}

func (a *SyncAction) getItemsAndIdeasTags(rootDir string) (allTags map[string]struct{}, itemsTags map[string][]*backlog.BacklogItem, ideasTags map[string][]*backlog.BacklogIdea, itemsOverviews map[*backlog.BacklogItem]*backlog.BacklogOverview, err error) {
backlogDirs, err := a.backlogDirs(rootDir)
if err != nil {
return nil, nil, nil, nil, err
}

ideasDir := filepath.Join(rootDir, backlog.IdeasDirectoryName)
ideas, err := backlog.LoadIdeas(ideasDir)
if err != nil {
return nil, nil, nil, nil, err
}

allTags = make(map[string]struct{})
itemsTags = make(map[string][]*backlog.BacklogItem)
ideasTags = make(map[string][]*backlog.BacklogIdea)
itemsOverviews = make(map[*backlog.BacklogItem]*backlog.BacklogOverview)

for _, backlogDir := range backlogDirs {
overviewPath, ok := findOverviewFileInRootDirectory(backlogDir)
if !ok {
return nil, nil, nil, nil, fmt.Errorf("the overview file isn't found for %s", backlogDir)
}
overview, err := backlog.LoadBacklogOverview(overviewPath)
if err != nil {
return nil, nil, nil, nil, err
}

bck, err := backlog.LoadBacklog(backlogDir)
if err != nil {
return nil, nil, nil, nil, err
}

items := bck.ActiveItems()
for _, item := range items {
for _, tag := range item.Tags() {
tag = strings.ToLower(tag)
allTags[tag] = struct{}{}
itemsTags[tag] = append(itemsTags[tag], item)
itemsOverviews[item] = overview
}
}
}

for _, idea := range ideas {
for _, tag := range idea.Tags() {
tag = strings.ToLower(tag)
allTags[tag] = struct{}{}
ideasTags[tag] = append(ideasTags[tag], idea)
}
}

return allTags, itemsTags, ideasTags, itemsOverviews, nil
}

0 comments on commit e4fd955

Please sign in to comment.