{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}

-- |
-- Module      : Issues
-- Description : Queries about issues created against projects
-- Copyright   : (c) Rob Stewart, Heriot-Watt University, 2019
-- License     : BSD3
-- Maintainer  : robstewart57@gmail.com
-- Stability   : stable
module GitLab.API.Issues
  ( defaultIssueFilters,
    IssueAttrs (..),
    DueDate (..),
    IssueSearchIn (..),
    IssueOrderBy (..),
    IssueScope (..),
    IssueSortBy (..),
    IssueState (..),
    projectIssues,
    projectIssues',
    issueStatisticsUser,
    issueStatisticsGroup,
    issueStatisticsGroup',
    issueStatisticsProject,
    issueStatisticsProject',
    userIssues,
    newIssue,
    newIssue',
    editIssue,
  )
where

import qualified Data.Aeson as J
import Data.Either
import Data.Maybe
import Data.Text (Text)
import qualified Data.Text as T
import qualified Data.Text.Lazy
import qualified Data.Text.Lazy.Encoding
import Data.Time.Clock
import Data.Time.Format.ISO8601
import GitLab.Types
import GitLab.WebRequests.GitLabWebCalls
import Network.HTTP.Types.Status

-- | No issue filters, thereby returning all issues. Default scope is "all".
defaultIssueFilters :: IssueAttrs
defaultIssueFilters :: IssueAttrs
defaultIssueFilters =
  Maybe Int
-> Maybe String
-> Maybe Int
-> Maybe String
-> Maybe Bool
-> Maybe UTCTime
-> Maybe UTCTime
-> Maybe DueDate
-> Maybe Int
-> Maybe IssueSearchIn
-> Maybe Int
-> Maybe String
-> Maybe String
-> Maybe String
-> Maybe String
-> Maybe Bool
-> Maybe IssueOrderBy
-> Maybe IssueScope
-> Maybe String
-> Maybe IssueSortBy
-> Maybe IssueState
-> Maybe UTCTime
-> Maybe UTCTime
-> Maybe Bool
-> IssueAttrs
IssueAttrs Maybe Int
forall a. Maybe a
Nothing Maybe String
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing Maybe String
forall a. Maybe a
Nothing Maybe Bool
forall a. Maybe a
Nothing Maybe UTCTime
forall a. Maybe a
Nothing Maybe UTCTime
forall a. Maybe a
Nothing Maybe DueDate
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing Maybe IssueSearchIn
forall a. Maybe a
Nothing Maybe Int
forall a. Maybe a
Nothing Maybe String
forall a. Maybe a
Nothing Maybe String
forall a. Maybe a
Nothing Maybe String
forall a. Maybe a
Nothing Maybe String
forall a. Maybe a
Nothing Maybe Bool
forall a. Maybe a
Nothing Maybe IssueOrderBy
forall a. Maybe a
Nothing (IssueScope -> Maybe IssueScope
forall a. a -> Maybe a
Just IssueScope
All) Maybe String
forall a. Maybe a
Nothing Maybe IssueSortBy
forall a. Maybe a
Nothing Maybe IssueState
forall a. Maybe a
Nothing Maybe UTCTime
forall a. Maybe a
Nothing Maybe UTCTime
forall a. Maybe a
Nothing Maybe Bool
forall a. Maybe a
Nothing

data DueDate
  = NoDueDate
  | Overdue
  | Week
  | Month
  | NextMonthPreviousTwoWeeks

instance Show DueDate where
  show :: DueDate -> String
show DueDate
NoDueDate = String
"0"
  show DueDate
Overdue = String
"overdue"
  show DueDate
Week = String
"week"
  show DueDate
Month = String
"month"
  show DueDate
NextMonthPreviousTwoWeeks = String
"next_month_and_previous_two_weeks"

data IssueSearchIn
  = JustTitle
  | JustDescription
  | TitleAndDescription

instance Show IssueSearchIn where
  show :: IssueSearchIn -> String
show IssueSearchIn
JustTitle = String
"title"
  show IssueSearchIn
JustDescription = String
"description"
  show IssueSearchIn
TitleAndDescription = String
"title,description"

data IssueOrderBy
  = CreatedAt
  | UpdatedAt
  | Priority
  | DueDate
  | RelativePosition
  | LabelPriority
  | MilestoneDue
  | Popularity
  | Weight

instance Show IssueOrderBy where
  show :: IssueOrderBy -> String
show IssueOrderBy
CreatedAt = String
"created_at"
  show IssueOrderBy
UpdatedAt = String
"updated_at"
  show IssueOrderBy
Priority = String
"priority"
  show IssueOrderBy
DueDate = String
"due_date"
  show IssueOrderBy
RelativePosition = String
"relative_position"
  show IssueOrderBy
LabelPriority = String
"label_priority"
  show IssueOrderBy
MilestoneDue = String
"milestone_due"
  show IssueOrderBy
Popularity = String
"popularity"
  show IssueOrderBy
Weight = String
"weight"

data IssueScope
  = CreatedByMe
  | AssignedToMe
  | All

instance Show IssueScope where
  show :: IssueScope -> String
show IssueScope
CreatedByMe = String
"created_by_me"
  show IssueScope
AssignedToMe = String
"assigned_to_me"
  show IssueScope
All = String
"all"

data IssueSortBy
  = Ascending
  | Descending

instance Show IssueSortBy where
  show :: IssueSortBy -> String
show IssueSortBy
Ascending = String
"asc"
  show IssueSortBy
Descending = String
"desc"

data IssueState
  = IssueOpen
  | IssueClosed

instance Show IssueState where
  show :: IssueState -> String
show IssueState
IssueOpen = String
"opened"
  show IssueState
IssueClosed = String
"closed"

projectIssues ::
  -- | the project
  Project ->
  -- | filter the issues, see https://docs.gitlab.com/ee/api/issues.html#list-issues
  IssueAttrs ->
  -- the GitLab issues
  GitLab [Issue]
projectIssues :: Project -> IssueAttrs -> GitLab [Issue]
projectIssues Project
p IssueAttrs
filters = do
  Either Status [Issue]
result <- Int -> IssueAttrs -> GitLab (Either Status [Issue])
projectIssues' (Project -> Int
project_id Project
p) IssueAttrs
filters
  [Issue] -> GitLab [Issue]
forall (m :: * -> *) a. Monad m => a -> m a
return ([Issue] -> Either Status [Issue] -> [Issue]
forall b a. b -> Either a b -> b
fromRight (String -> [Issue]
forall a. HasCallStack => String -> a
error String
"projectIssues error") Either Status [Issue]
result)

projectIssues' ::
  -- | the project ID
  Int ->
  -- | filter the issues, see https://docs.gitlab.com/ee/api/issues.html#list-issues
  IssueAttrs ->
  -- | the GitLab issues
  GitLab (Either Status [Issue])
projectIssues' :: Int -> IssueAttrs -> GitLab (Either Status [Issue])
projectIssues' Int
projectId IssueAttrs
attrs =
  Text -> GitLab (Either Status [Issue])
forall a. FromJSON a => Text -> GitLab (Either Status [a])
gitlab Text
path
  where
    path :: Text
path =
      String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$
        String
"/projects/"
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
projectId
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"/issues"
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> IssueAttrs -> String
issuesAttrs IssueAttrs
attrs

-- | Gets issues count statistics on all issues the authenticated user has access to.
issueStatisticsUser ::
  -- | filter the issues, see https://docs.gitlab.com/ee/api/issues_statistics.html#get-issues-statistics
  IssueAttrs ->
  -- | the issue statistics
  GitLab IssueStatistics
issueStatisticsUser :: IssueAttrs -> GitLab IssueStatistics
issueStatisticsUser IssueAttrs
attrs =
  Text -> GitLab IssueStatistics
forall a. FromJSON a => Text -> GitLab a
gitlabOneUnsafe Text
path
  where
    path :: Text
path =
      String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$
        String
"/issues_statistics"
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> IssueAttrs -> String
issuesAttrs IssueAttrs
attrs

-- | Gets issues count statistics for a given group.
issueStatisticsGroup ::
  -- | the group
  Group ->
  -- | filter the issues, see https://docs.gitlab.com/ee/api/issues_statistics.html#get-issues-statistics
  IssueAttrs ->
  -- | the issue statistics
  GitLab IssueStatistics
issueStatisticsGroup :: Group -> IssueAttrs -> GitLab IssueStatistics
issueStatisticsGroup Group
group IssueAttrs
filters = do
  Either Status (Maybe IssueStatistics)
result <- Int -> IssueAttrs -> GitLab (Either Status (Maybe IssueStatistics))
issueStatisticsGroup' (Group -> Int
group_id Group
group) IssueAttrs
filters
  case Either Status (Maybe IssueStatistics)
result of
    Left Status
_s -> String -> GitLab IssueStatistics
forall a. HasCallStack => String -> a
error String
"issueStatisticsGroup error"
    Right Maybe IssueStatistics
Nothing -> String -> GitLab IssueStatistics
forall a. HasCallStack => String -> a
error String
"issueStatisticsGroup error"
    Right (Just IssueStatistics
stats) -> IssueStatistics -> GitLab IssueStatistics
forall (m :: * -> *) a. Monad m => a -> m a
return IssueStatistics
stats

-- | Gets issues count statistics for a given group.
issueStatisticsGroup' ::
  -- | the group ID
  Int ->
  -- | filter the issues, see https://docs.gitlab.com/ee/api/issues_statistics.html#get-issues-statistics
  IssueAttrs ->
  -- | the issue statistics
  GitLab (Either Status (Maybe IssueStatistics))
issueStatisticsGroup' :: Int -> IssueAttrs -> GitLab (Either Status (Maybe IssueStatistics))
issueStatisticsGroup' Int
groupId IssueAttrs
attrs =
  Text -> GitLab (Either Status (Maybe IssueStatistics))
forall a. FromJSON a => Text -> GitLab (Either Status (Maybe a))
gitlabOne Text
path
  where
    path :: Text
path =
      String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$
        String
"/groups/"
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
groupId
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"/issues_statistics"
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> IssueAttrs -> String
issuesAttrs IssueAttrs
attrs

-- | Gets issues count statistics for a given group.
issueStatisticsProject ::
  -- | the project
  Project ->
  -- | filter the issues, see https://docs.gitlab.com/ee/api/issues_statistics.html#get-issues-statistics
  IssueAttrs ->
  -- | the issue statistics
  GitLab IssueStatistics
issueStatisticsProject :: Project -> IssueAttrs -> GitLab IssueStatistics
issueStatisticsProject Project
proj IssueAttrs
filters = do
  Either Status (Maybe IssueStatistics)
result <- Int -> IssueAttrs -> GitLab (Either Status (Maybe IssueStatistics))
issueStatisticsGroup' (Project -> Int
project_id Project
proj) IssueAttrs
filters
  case Either Status (Maybe IssueStatistics)
result of
    Left Status
_s -> String -> GitLab IssueStatistics
forall a. HasCallStack => String -> a
error String
"issueStatisticsProject error"
    Right Maybe IssueStatistics
Nothing -> String -> GitLab IssueStatistics
forall a. HasCallStack => String -> a
error String
"issueStatisticsProject error"
    Right (Just IssueStatistics
stats) -> IssueStatistics -> GitLab IssueStatistics
forall (m :: * -> *) a. Monad m => a -> m a
return IssueStatistics
stats

-- | Gets issues count statistics for a given project.
issueStatisticsProject' ::
  -- | the project ID
  Int ->
  -- | filter the issues, see https://docs.gitlab.com/ee/api/issues_statistics.html#get-issues-statistics
  IssueAttrs ->
  -- | the issue statistics
  GitLab (Either Status (Maybe IssueStatistics))
issueStatisticsProject' :: Int -> IssueAttrs -> GitLab (Either Status (Maybe IssueStatistics))
issueStatisticsProject' Int
projId IssueAttrs
attrs =
  Text -> GitLab (Either Status (Maybe IssueStatistics))
forall a. FromJSON a => Text -> GitLab (Either Status (Maybe a))
gitlabOne Text
path
  where
    path :: Text
path =
      String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$
        String
"/projects/"
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
projId
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"/issues_statistics"
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> IssueAttrs -> String
issuesAttrs IssueAttrs
attrs

-- | gets all issues create by a user.
userIssues ::
  -- | the user
  User ->
  GitLab [Issue]
userIssues :: User -> GitLab [Issue]
userIssues User
usr =
  Text -> Text -> GitLab [Issue]
forall a. FromJSON a => Text -> Text -> GitLab [a]
gitlabWithAttrsUnsafe Text
addr Text
attrs
  where
    addr :: Text
addr = Text
"/issues"
    attrs :: Text
attrs =
      String -> Text
T.pack (String -> Text) -> String -> Text
forall a b. (a -> b) -> a -> b
$
        String
"&author_id="
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show (User -> Int
user_id User
usr)
          String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
"&scope=all"

-- | create a new issue.
newIssue ::
  -- | project
  Project ->
  -- | issue title
  Text ->
  -- | issue description
  Text ->
  GitLab (Either Status (Maybe Issue))
newIssue :: Project -> Text -> Text -> GitLab (Either Status (Maybe Issue))
newIssue Project
project =
  Int -> Text -> Text -> GitLab (Either Status (Maybe Issue))
newIssue' (Project -> Int
project_id Project
project)

-- | create a new issue.
newIssue' ::
  -- | project ID
  Int ->
  -- | issue title
  Text ->
  -- | issue description
  Text ->
  GitLab (Either Status (Maybe Issue))
newIssue' :: Int -> Text -> Text -> GitLab (Either Status (Maybe Issue))
newIssue' Int
projectId Text
issueTitle Text
issueDescription =
  Text -> Text -> GitLab (Either Status (Maybe Issue))
forall b.
FromJSON b =>
Text -> Text -> GitLab (Either Status (Maybe b))
gitlabPost Text
addr Text
dataBody
  where
    dataBody :: Text
    dataBody :: Text
dataBody =
      Text
"title="
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
issueTitle
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"&description="
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
issueDescription
    addr :: Text
addr =
      Text
"/projects/"
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
projectId)
        Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/issues"

-- | edits an issue. see <https://docs.gitlab.com/ee/api/issues.html#edit-issue>
editIssue ::
  ProjectId ->
  IssueId ->
  EditIssueReq ->
  GitLab (Either Status Issue)
editIssue :: Int -> Int -> EditIssueReq -> GitLab (Either Status Issue)
editIssue Int
projId Int
issueId EditIssueReq
editIssueReq = do
  let path :: Text
path =
        Text
"/projects/" Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
projId)
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"/issues/"
          Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
T.pack (Int -> String
forall a. Show a => a -> String
show Int
issueId)
  Text -> Text -> GitLab (Either Status Issue)
forall b. FromJSON b => Text -> Text -> GitLab (Either Status b)
gitlabPut
    Text
path
    ( Text -> Text
Data.Text.Lazy.toStrict
        ( ByteString -> Text
Data.Text.Lazy.Encoding.decodeUtf8
            (EditIssueReq -> ByteString
forall a. ToJSON a => a -> ByteString
J.encode EditIssueReq
editIssueReq)
        )
    )

-------------------------------
-- Internal functions and types

data IssueAttrs = IssueAttrs
  { IssueAttrs -> Maybe Int
issueFilter_assignee_id :: Maybe Int,
    IssueAttrs -> Maybe String
issueFilter_assignee_username :: Maybe String,
    IssueAttrs -> Maybe Int
issueFilter_author_id :: Maybe Int,
    IssueAttrs -> Maybe String
issueFilter_author_username :: Maybe String,
    IssueAttrs -> Maybe Bool
issueFilter_confidential :: Maybe Bool,
    IssueAttrs -> Maybe UTCTime
issueFilter_created_after :: Maybe UTCTime,
    IssueAttrs -> Maybe UTCTime
issueFilter_created_before :: Maybe UTCTime,
    IssueAttrs -> Maybe DueDate
issueFilter_due_date :: Maybe DueDate,
    IssueAttrs -> Maybe Int
issueFilter_iids :: Maybe Int,
    IssueAttrs -> Maybe IssueSearchIn
issueFilter_in :: Maybe IssueSearchIn,
    IssueAttrs -> Maybe Int
issueFilter_iteration_id :: Maybe Int,
    IssueAttrs -> Maybe String
issueFilter_iteration_title :: Maybe String,
    IssueAttrs -> Maybe String
issueFilter_milestone :: Maybe String,
    IssueAttrs -> Maybe String
issueFilter_labels :: Maybe String,
    IssueAttrs -> Maybe String
issueFilter_my_reaction_emoji :: Maybe String,
    IssueAttrs -> Maybe Bool
issueFilter_non_archived :: Maybe Bool,
    IssueAttrs -> Maybe IssueOrderBy
issueFilter_order_by :: Maybe IssueOrderBy,
    IssueAttrs -> Maybe IssueScope
issueFilter_scope :: Maybe IssueScope,
    IssueAttrs -> Maybe String
issueFilter_search :: Maybe String,
    IssueAttrs -> Maybe IssueSortBy
issueFilter_sort :: Maybe IssueSortBy,
    IssueAttrs -> Maybe IssueState
issueFilter_state :: Maybe IssueState,
    IssueAttrs -> Maybe UTCTime
issueFilter_updated_after :: Maybe UTCTime,
    IssueAttrs -> Maybe UTCTime
issueFilter_updated_before :: Maybe UTCTime,
    IssueAttrs -> Maybe Bool
issueFilter_with_labels_details :: Maybe Bool
  }

issuesAttrs :: IssueAttrs -> String
issuesAttrs :: IssueAttrs -> String
issuesAttrs IssueAttrs
filters =
  case [String]
attrsUrl of
    [] -> String
""
    (String
x : [String]
xs) -> String
"?" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
x String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ShowS -> [String] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (Char
'&' Char -> ShowS
forall a. a -> [a] -> [a]
:) [String]
xs
  where
    attrsUrl :: [String]
attrsUrl =
      [Maybe String] -> [String]
forall a. [Maybe a] -> [a]
catMaybes
        [ (\Int
i -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"assignee_id=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
i)) (Int -> Maybe String) -> Maybe Int -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe Int
issueFilter_assignee_id IssueAttrs
filters,
          (\String
t -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"assignee_username=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
t)) (String -> Maybe String) -> Maybe String -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe String
issueFilter_assignee_username IssueAttrs
filters,
          (\Int
i -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"author_id=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
i)) (Int -> Maybe String) -> Maybe Int -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe Int
issueFilter_author_id IssueAttrs
filters,
          (\String
i -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"author_username=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> ShowS
forall a. Show a => a -> String
show String
i)) (String -> Maybe String) -> Maybe String -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe String
issueFilter_author_username IssueAttrs
filters,
          (\Bool
b -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"confidential=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Bool -> String
showBool Bool
b)) (Bool -> Maybe String) -> Maybe Bool -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe Bool
issueFilter_confidential IssueAttrs
filters,
          (\UTCTime
t -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"created_after=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> UTCTime -> String
showTime UTCTime
t)) (UTCTime -> Maybe String) -> Maybe UTCTime -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe UTCTime
issueFilter_created_after IssueAttrs
filters,
          (\UTCTime
t -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"created_before=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> UTCTime -> String
showTime UTCTime
t)) (UTCTime -> Maybe String) -> Maybe UTCTime -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe UTCTime
issueFilter_created_before IssueAttrs
filters,
          (\DueDate
due -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"due_date=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> DueDate -> String
forall a. Show a => a -> String
show DueDate
due)) (DueDate -> Maybe String) -> Maybe DueDate -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe DueDate
issueFilter_due_date IssueAttrs
filters,
          (\Int
iids -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"iids[]=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
iids)) (Int -> Maybe String) -> Maybe Int -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe Int
issueFilter_iids IssueAttrs
filters,
          (\IssueSearchIn
issueIn -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"assignee_id=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> IssueSearchIn -> String
forall a. Show a => a -> String
show IssueSearchIn
issueIn)) (IssueSearchIn -> Maybe String)
-> Maybe IssueSearchIn -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe IssueSearchIn
issueFilter_in IssueAttrs
filters,
          (\Int
i -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"iteration_id=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Int -> String
forall a. Show a => a -> String
show Int
i)) (Int -> Maybe String) -> Maybe Int -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe Int
issueFilter_iteration_id IssueAttrs
filters,
          (\String
s -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"iteration_title=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
s)) (String -> Maybe String) -> Maybe String -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe String
issueFilter_iteration_title IssueAttrs
filters,
          (\String
s -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"milestone=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
s)) (String -> Maybe String) -> Maybe String -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe String
issueFilter_milestone IssueAttrs
filters,
          (\String
s -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"labels=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
s)) (String -> Maybe String) -> Maybe String -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe String
issueFilter_labels IssueAttrs
filters,
          (\String
s -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"my_reaction_emoji=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
s)) (String -> Maybe String) -> Maybe String -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe String
issueFilter_my_reaction_emoji IssueAttrs
filters,
          (\Bool
b -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"non_archived=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Bool -> String
showBool Bool
b)) (Bool -> Maybe String) -> Maybe Bool -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe Bool
issueFilter_non_archived IssueAttrs
filters,
          (\IssueOrderBy
x -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"order_by=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> IssueOrderBy -> String
forall a. Show a => a -> String
show IssueOrderBy
x)) (IssueOrderBy -> Maybe String)
-> Maybe IssueOrderBy -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe IssueOrderBy
issueFilter_order_by IssueAttrs
filters,
          (\IssueScope
x -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"scope=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> IssueScope -> String
forall a. Show a => a -> String
show IssueScope
x)) (IssueScope -> Maybe String) -> Maybe IssueScope -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe IssueScope
issueFilter_scope IssueAttrs
filters,
          (\String
s -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"search=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
s)) (String -> Maybe String) -> Maybe String -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe String
issueFilter_search IssueAttrs
filters,
          (\IssueSortBy
x -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"sort=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> IssueSortBy -> String
forall a. Show a => a -> String
show IssueSortBy
x)) (IssueSortBy -> Maybe String) -> Maybe IssueSortBy -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe IssueSortBy
issueFilter_sort IssueAttrs
filters,
          (\IssueState
x -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"state=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> IssueState -> String
forall a. Show a => a -> String
show IssueState
x)) (IssueState -> Maybe String) -> Maybe IssueState -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe IssueState
issueFilter_state IssueAttrs
filters,
          (\UTCTime
t -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"updated_after=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> UTCTime -> String
showTime UTCTime
t)) (UTCTime -> Maybe String) -> Maybe UTCTime -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe UTCTime
issueFilter_updated_after IssueAttrs
filters,
          (\UTCTime
t -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"updated_before=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> UTCTime -> String
showTime UTCTime
t)) (UTCTime -> Maybe String) -> Maybe UTCTime -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe UTCTime
issueFilter_updated_before IssueAttrs
filters,
          (\Bool
b -> String -> Maybe String
forall a. a -> Maybe a
Just (String
"with_labels_details=" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> Bool -> String
showBool Bool
b)) (Bool -> Maybe String) -> Maybe Bool -> Maybe String
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IssueAttrs -> Maybe Bool
issueFilter_with_labels_details IssueAttrs
filters
        ]
      where
        showBool :: Bool -> String
        showBool :: Bool -> String
showBool Bool
True = String
"true"
        showBool Bool
False = String
"false"
        showTime :: UTCTime -> String
        showTime :: UTCTime -> String
showTime = UTCTime -> String
forall t. ISO8601 t => t -> String
iso8601Show