aboutsummaryrefslogtreecommitdiffstats
path: root/app/Issue/Render.hs
blob: 39249aef74e1fd4a7737b3e96b04d6f55120ed73 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
{-# OPTIONS_GHC -fno-warn-orphans #-}

module Issue.Render
  ( IssueTitle (..),
    IssueDescription (..),
    IssueTags (..),
    IssueComments (..),
    IssueOpenedOn (..),
    IssueOpenedBy (..),
  )
where

import Data.List (intersperse)
import Data.List.NonEmpty qualified as N
import Data.Map qualified as M
import Data.Text qualified as T
import Data.Time.Clock (UTCTime (utctDay))
import Git (Author (..), Commit (..))
import Issue (Issue (..))
import Issue.Provenance (Provenance (..))
import Render ((<<<))
import Render qualified as P

-- TODO Easily separate renderables by newlines
--
-- For convenience, the (<<<) combinator adds spaces between renderable entities, **if** those renderables are non-empty.
--
-- We should similarly allow for a combinator that similarly adds empty lines between renderable entities.
--
-- @topic rendering
instance P.Render (P.Detailed Issue) where
  render (P.Detailed issue) =
    IssueTitle issue
      <<< P.hardline @P.AnsiStyle
      <<< IssueDescription issue
      <<< P.hardline @P.AnsiStyle
      <<< IssueTags issue
      <<< P.hardline @P.AnsiStyle
      <<< IssueComments issue

instance P.Render Issue where
  render = P.render . P.Detailed

newtype IssueTitle = IssueTitle {unIssueTitle :: Issue}

instance P.Render IssueTitle where
  render (IssueTitle issue)
    | issue.closed = P.styled [P.colorDull P.Red] $ P.render issue.title
    | otherwise = P.styled [(P.color P.Green)] $ P.render issue.title

newtype IssueDescription = IssueDescription {unIssueDescription :: Issue}

instance P.Render IssueDescription where
  render (IssueDescription issue) =
    maybe P.emptyDoc (P.render . N.toList) $
      issue.description

instance P.Render (P.Linked Issue) where
  render (P.Linked issue)
    | issue.closed =
        P.styled [P.underlined, P.colorDull P.Red] $
          ("(closed)" :: T.Text) <<< P.render issue.id
    | otherwise =
        P.styled [P.underlined, (P.color P.Green)] $
          P.render issue.id

instance P.Render (P.Summarized Issue) where
  render (P.Summarized issue) =
    P.nest 4 $
      IssueTitle issue
        <<< IssueTags issue
        <<< IssueOpenedOn issue
        <<< IssueOpenedBy issue

newtype IssueTags = IssueTags {unIssueTags :: Issue}

instance P.Render IssueTags where
  render (IssueTags issue) = P.render issue.tags

newtype IssueComments = IssueComments {unIssueComments :: Issue}

instance P.Render IssueComments where
  render (IssueComments issue) =
    maybe P.emptyDoc (P.vsep . map P.render . N.toList) $
      issue.comments

newtype IssueOpenedBy = IssueOpenedBy {unIssueOpenedBy :: Issue}

instance P.Render IssueOpenedBy where
  render (IssueOpenedBy issue) =
    ("by" :: T.Text) <<< issue.provenance.first.author.name

newtype IssueOpenedOn = IssueOpenedOn {unIssueOpenedOn :: Issue}

instance P.Render IssueOpenedOn where
  render (IssueOpenedOn issue) =
    ("on" :: T.Text) <<< utctDay issue.provenance.first.date

instance P.Render (T.Text, M.Map T.Text [Issue]) where
  render (tagKey, groupedIssues) =
    (P.vsep . intersperse ("" :: P.Doc ann)) $
      concatMap
        ( \(name, issues) ->
            ( P.styled [P.underlined] $
                ("@" <> tagKey)
                  <<< name
                  <<< P.parens @P.AnsiStyle (P.pretty (length issues))
            )
              : map
                (P.indent 4)
                ( map (P.render . IssueTitle) issues
                )
        )
        (M.toList groupedIssues)