my eye

Introduce issue posts

Committed 5b0275

--- a/webint_code/__init__.py
+++ b/webint_code/__init__.py

         "filename": r"[\w./\-]+",
         "package": r"[\w.-]+",
         "namespace": r"[\w._/]+",
+        "issue": r"\d+",
     },
     model={
         "projects": {
     ]
 
 
+@app.query
+def get_issues(db, project=None):
+    """Return a list of issues by project."""
+    scope = "/code/projects"
+    if project:
+        scope += f"/{project}"
+    return [
+        p
+        for p in web.application("webint_posts").model.get_posts()
+        if p.get("in_reply_to", [""])[0].startswith(scope)
+    ]
+
+
 @app.query
 def get_pypi_projects(db):
     """Return a list of PyPI project names."""
             )
         except FileNotFoundError:
             test_coverage = {}
+        issues = len(app.model.get_issues(project))
         return app.view.project.index(
             project,
             gmpg.get_repo(project_dir / "working"),
             test_results,
             test_coverage,
             mentions,
+            issues,
         )
 
     def post(self, project):
 
     def get(self, project):
         """Return a view of the package's issues."""
+        issues = app.model.get_issues(project)
         mentions = web.application(
             "webint_mentions"
         ).model.get_received_mentions_by_target(
             f"{web.tx.origin}/{web.tx.request.uri.path}"
         )
-        return [dict(r) for r in mentions]
-        # files = sorted((code_dir / project / "releases" / release).iterdir())
-        # return app.view.project.release(project, release, files)
+        return app.view.project.issues.index(project, issues, mentions)
+
+    def post(self, project):
+        form = web.form("title", "description")
+        issues = app.model.get_issues(project)
+        issue = len(issues) + 1  # TODO wrap in a transaction
+        permalink = f"/code/projects/{project}/issues/{issue}"
+        web.application("webint_posts").model.create(
+            "entry",
+            url=permalink,
+            in_reply_to=f"/code/projects/{project}",
+            name=form.title,
+            content=form.description,
+            visibility="public",
+        )
+        raise web.Created("Issue has been created.", permalink)
+
+
+@app.control("projects/{project}/issues/new")
+class ProjectIssueNew:
+    """A project's issue creator."""
+
+    def get(self, project):
+        return app.view.project.issues.create(project)
+
+
+@app.control("projects/{project}/issues/{issue}")
+class ProjectIssue:
+    """A project's issue."""
+
+    def get(self, project, issue):
+        issue = list(app.model.get_issues(project))[int(issue)]
+        return app.view.project.issues.issue(project, issue)
 
 
 def split_release(release) -> tuple:

--- a/webint_code/templates/project/index.html
+++ b/webint_code/templates/project/index.html

-$def with (project, repo, readme, package_releases, pyproject, api_python, test_results, test_coverage, mentions)
+$def with (project, repo, readme, package_releases, pyproject, api_python, test_results, test_coverage, mentions, issues)
 $var breadcrumbs = ("projects", "Projects")
 $ title = project
 $var title_classes = ["p-name"]
   text-transform: small-caps; }
 </style>
 
-$ issues = 0
 $ likes = 0
 $for mention in mentions:
     $if mention["data"]["comment_type"][0] == "like":
     $elif mention["data"]["comment_type"][0] == "like":
          $ likes += 1
 
-<p>
+<p><a href=/projects/$project/issues>Issues</a>
 $if issues:
-    $emoji.emojize(":note:")
-$if likes:
-    $emoji.emojize(":red_heart:") <sub>$likes</sub>
+    <sub><small>$issues</small></sub>
+</p>
 </p>
+$if likes:
+    <p>$emoji.emojize(":red_heart:") <sub>$likes</sub></p>
 
 $# <div>
 $# $ data = mention["data"]

index 0000000..9e4a256
--- /dev/null

+$def with (project)
+$var breadcrumbs = ("projects", "Projects", project, f"<b>{project}</b>", "issues", "Issues")
+$var title: New Issue
+
+<form method=post action=/projects/$project/issues>
+    <label>Title<br>
+        <label class=bounding><input type=text name=title style=width:30em></label></label>
+    <label>Description<br>
+        <label class=bounding><textarea name=description rows=10 cols=60></textarea></label></label>
+    <button type=submit>Create Issue</button>
+</form>

rename from webint_code/templates/project/issues.html
rename to webint_code/templates/project/issues/index.html

-$def with (mentions)
+$def with (project, issues, mentions)
+$var breadcrumbs = ("projects", "Projects", project, f"<b>{project}</b>")
+$var title: Issues
+
+<form action=/projects/$project/issues/new>
+<button type=submit>New Issue</button>
+</form>
+
+$for issue in issues:
+    <div>$issue</div>
+
+<h4>Elsewhere</h4>
 
 $for mention in mentions:
     <div>

index 0000000..f8346b5
--- /dev/null

+$def with (project, issue)
+$var breadcrumbs = ("projects", "Projects", project, f"<b>{project}</b>", "issues", "Issues")
+$var title: Issue
+
+$issue