Esempio n. 1
0
class Dependencies:
    styles = """    classDef ToDo fill:#fff,stroke:#999,stroke-width:1px,color:#777;
    classDef InProgress fill:#7a7,stroke:#060,stroke-width:3px,color:#000;
    classDef Done fill:#999,stroke:#222,stroke-width:3px,color:#000;
    """

    def __init__(self, my_config):
        self.conf = my_config
        self.model = JiraModel(my_config)
        self.mermaid = Mermaid(my_config)
        self.project = self.mermaid.project
        self.base = self.mermaid.base

    def get_and_draw(self):
        epics = self.model.get_epics()

        markup = self.draw_group(epics)
        self.mermaid.exec_mermaid(markup)

    def draw_group(self, graph):
        output = "graph RL;\n"
        groupby = self.conf.args.groupby
        # Mermaid Gantt chart must have sections. Default section name when no grouping used.
        groups = {"Epics"}
        if groupby:
            groups = self.model.get_groups(groupby=groupby)

        urls = ""
        classes = ""
        start_node = "start"

        for component in groups:
            #if component == "*":
            #continue
            output += f"    subgraph {component}\n"

            for key, obj in graph.items():
                if groupby and obj[groupby] != component:
                    continue

                urls += f"    click {key} \"{obj['url']}\" \"{obj['summary']}\"\n"
                classes += f"    class {key} {self._get_css_class(obj)}\n"
                if obj['deps']:
                    for dep in obj['deps']:
                        output += f"    {key}[{key} {obj['epic_name']}]-->{dep}\n"
                else:
                    output += f"    {key}[{key} {obj['epic_name']}]-->{start_node}(({start_node}))\n"

            output += "    end\n"

        output += urls + classes + self.styles
        #print(output)
        return output

    def _get_css_class(self, obj):
        css_class = obj['statusCategory'].replace(" ", "")
        return css_class
Esempio n. 2
0
class Grid:
    def __init__(self, my_config):
        self.conf = my_config
        self.model = JiraModel(my_config)
        self.releases = self.model.get_versions()
        self.writer = Writer(my_config)
        self.project = self.writer.project

    def get_and_draw(self):
        epics = self.model.get_epics()
        by_epic = self.model.get_issues_per_epic()

        grid = self.grid_obj(epics, self.project)

        csv = self.grid_csv(grid, self.project)
        self.writer.csv(csv)

        html = self.grid_html(grid, by_epic, self.project)
        self.writer.html(html)

    def grid_obj(self, epics, project):
        groups = self.model.get_groups(groupby='components')

        grid = {}
        for group in groups:
            grid[group] = {}
            for rel in self.releases:
                #print(rel)
                grid[group][rel] = {}

        for key, obj in epics.items():
            grid[obj['components']][obj['fixVersions']][key] = obj

        return grid

    def grid_csv(self, grid, project):
        csv = project + "\t" + "\t".join(self.releases) + "\n"

        cells = {}
        for component in grid.keys():
            cells[component] = {}
            for rel in self.releases:
                cells[component][rel] = []
                if rel in grid[component]:
                    for key in sorted(grid[component][rel].keys()):
                        obj = grid[component][rel][key]
                        cells[component][rel].append(obj)

        for component in grid.keys():
            csv += component + "\n"
            done_columns = [False] * len(self.releases)
            while not all(done_columns):
                col = 0
                for rel in self.releases:
                    cell = cells[component][rel]
                    obj = cell.pop() if cell else None
                    if obj:
                        csv += "\t" + obj['key'] + " " + obj['epic_name']
                    else:
                        done_columns[col] = True
                        csv += "\t"
                    col += 1
                csv += "\n"

        return csv

    def grid_html(self, grid, by_epic, project):
        colwidth = 15
        tablewidth = str(int(colwidth * (len(self.releases) + 1)))
        head = f"<html>\n<head><title>{project}</title>\n"
        style = """<style type="text/css">
    table {width: """ + tablewidth + """em;}
    table td {padding: 5px; font-family: sans-serif; border-top: 1px solid #ddd; width: """ + str(
            colwidth) + """em;}
    foo td div {overflow: hidden; height: 2em;}
    td div a {overflow: hidden; height: 1.4em; display: inline-block;}
    a.ToDo {text-decoration: none; color: #666;}
    a.InProgress {text-decoration: none; color: #090;}
    a.Done {text-decoration: line-through; color: #333;}

    td div span {width: 5px; height: 5px; margin-left: 1px; margin-right: 1px; display: inline-block;}
    td div span.ToDo {border: solid 1px #666; margin-bottom: 2px;}
    td div span.InProgress {border: solid 1px #090; background-color: #090;margin-bottom: 2px;}
    td div span.Done {border: solid 1px #333; background-color: #333;margin-bottom: 2px;}
    td div span a {text-decoration: none;}
</style>
"""

        table = f"<table>\n<tr><th>{project}</th><th>" + "</th><th>".join(
            self.releases) + "</th></tr>\n"

        for component in grid.keys():
            table += f"<tr><th>{component}</th>"
            for rel in self.releases:
                table += "<td>"
                for key in sorted(grid[component][rel].keys()):
                    obj = grid[component][rel][key]

                    table += "<div>\n"
                    table += f"<a href=\"{obj['url']}\" title=\"{obj['summary']}\" class=\"{obj['statusCategory'].replace(' ','')}\">{obj['key']} {obj['epic_name']}</a><br>\n"
                    table += self._grid_issues(by_epic, key)
                    table += "</div>\n"

                table += "</td>\n"
        table += "</tr>\n</table>\n"

        return head + style + "</head>\n<body style=\"overflow-x: auto;\">\n" + table + "</body>\n</html>"

    def _grid_issues(self, by_epic, epic_key):
        html = ""
        if epic_key in by_epic:
            for issue in by_epic[epic_key]:
                title = f"{issue['key']} {issue['summary']} [{issue['assignee']}]"
                html += f"<span class=\"{issue['statusCategory'].replace(' ', '')}\" title=\"{title}\"><a href=\"{issue['url']}\">&nbsp;</a></span>"

        return html
Esempio n. 3
0
class Gantt:
    styles = """    classDef ToDo fill:#fff,stroke:#999,stroke-width:1px,color:#777;
    classDef InProgress fill:#7a7,stroke:#060,stroke-width:3px,color:#000;
    classDef Done fill:#999,stroke:#222,stroke-width:3px,color:#000;
    """

    def __init__(self, my_config):
        self.conf = my_config
        self.model = JiraModel(my_config)
        self.mermaid = Mermaid(my_config)
        self.writer = self.mermaid
        self.project = self.mermaid.project
        self.base = self.mermaid.base

    def get_and_draw(self):
        epics = self.model.get_epics()

        markup = self.draw_group(epics, self.project)
        self.mermaid.exec_mermaid(markup)

        csv = self.gantt_csv(epics, self.project)
        self.writer.csv(csv)

        csv = self.groups_csv(epics, self.project)
        self.writer.csv(csv, base=f"{self.base}_components")

    def draw_group(self, graph, project):
        output = """gantt
    dateFormat  YYYY-MM-DD
    title       """ + project + """

"""
        groupby = self.conf.args.groupby
        # Mermaid Gantt chart must have sections. Default section name when no grouping used.
        groups = {"Epics"}
        if groupby:
            groups = self.model.get_groups(groupby=groupby)

        urls = ""
        classes = ""
        start_node = "start"

        for group in groups:
            output += f"    section {group}\n"

            for key in self.model.get_epics_by_depth(group, groupby=groupby):
                obj = graph[key]
                if groupby and obj[groupby] != group:
                    continue

                line = "    %-50s:" % f"{key} {obj['epic_name']}"
                status = ""
                if obj['statusCategory'] == "Done":
                    status = "done, "
                elif obj['statusCategory'] == "In Progress":
                    status = "active, "

                line += "%-10s" % status
                line += key + ", "

                deps = ""
                if obj['deps']:
                    deps += "after"
                    for dep in obj['deps']:
                        deps += " " + dep
                    deps += ", "
                line += deps

                if not deps:
                    if obj['start_date']:
                        line += obj['start_date'].strftime("%Y-%m-%d") + ", "
                        #line += datetime.datetime.isoformat(obj['start_date']) + ", "
                        if obj['resolution_date']:
                            line += obj['resolution_date'].strftime("%Y-%m-%d")
                            #line += datetime.datetime.isoformat(obj['resolution_date'])
                        else:
                            line += str(int(obj['points'] * 30)) + "d"
                    else:
                        line += str(int(obj['points'] * 30)) + "d"
                else:
                    line += str(int(obj['points'] * 30)) + "d"

                output += line + "\n"

                urls += f"    click {key} href \"{obj['url']}\"\n"

            output += "\n"

        output += urls
        #print(output)
        return output

    def _get_css_class(self, obj):
        css_class = obj['statusCategory'].replace(" ", "")
        return css_class

    def gantt_csv(self, graph, project):
        groupby = self.conf.args.groupby
        groups = {"Epics"}
        if groupby:
            groups = self.model.get_groups(groupby=groupby)

        head = f"{project}\n{groupby}\tEpic\tFix version\tEstimate\tResources allocated\tSprints->\n"
        sprints = "\t\t\t\t\n"  # Add sprints when we know how many there are

        body = ""
        for group in groups:
            body += f"\n{group}\n"
            for key in self.model.get_epics_by_depth(group, groupby=groupby):
                obj = graph[key]
                line = f"\t{key} {obj['epic_name']}\t{str(obj['fixVersions'])}\t{obj['points']}\n"
                body += line

        return head + sprints + body

    def groups_csv(self, graph, project):
        groupby = self.conf.args.groupby
        groups = {"Epics"}
        if groupby:
            groups = self.model.get_groups(groupby=groupby)
        print(groups)

        head = f"{project}\n{groupby}\tEstimate\tResources allocated\tSprints->\n"
        sprints = "\t\t\t\t\n"  # Add sprints when we know how many there are

        body = "Totals:\n"
        for group in groups:
            points = 0.0
            for key in self.model.get_epics_by_depth(group, groupby=groupby):
                points += graph[key]['points']
            body += f"{group}\t{points}\n"

        return head + sprints + body