{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} module Data.Connect.Modules ( Modules(..) , JIRAModules(..) , emptyJIRAModules , ConfluenceModules(..) , emptyConfluenceModules , WebPanel(..) , WebPanelLayout(..) , GeneralPage(..) , JIRAProjectAdminTabPanel(..) ) where import Data.Aeson import Data.Aeson.Types import Data.Connect.AesonHelpers import Data.Connect.BaseTypes import Data.Connect.Conditions import Data.Connect.Webhooks import qualified Data.HashMap.Strict as HM import qualified Data.Text as T import GHC.Generics -- | 'Modules' are perhaps the most important part of your Atlassian Connect descriptor. They specify which parts of the -- host application you wish to inject content into. They provide your entry point into the host application. -- -- Atlassian Connect provides a large set of pre-defined entry points into the host application. Some of which are common -- to every application and some of which are unique to the particular application that you are targeting: -- -- * To see the JIRA modules: -- * To see the Confluence modules: -- -- Note: One important point about modules: they must all have a key and that key must be unique inside the same Atlassian -- Connect addon. data Modules = Modules { jiraModules :: JIRAModules -- ^ All of the JIRA Modules that you wish to define. , confluenceModules :: ConfluenceModules -- ^ All of the Confluence modules that you wish to define. } deriving (Show, Generic) instance ToJSON Modules where toJSON modules = case (jm, cm) of (Object jiraObject, Object confluenceObject) -> Object $ HM.union jiraObject confluenceObject _ -> Null where jm = toJSON . jiraModules $ modules cm = toJSON . confluenceModules $ modules -- TODO use Endo Modules to add modules for multiple different products to the modules list -- | A collection of all of the JIRA Modules that you can define. For more documentation on which Modules are supported -- the Atlassian Connect framework please see 'Modules'. You can also find more documentation on each of the modules. data JIRAModules = JIRAModules { jiraWebPanels :: [WebPanel] , jiraGeneralPages :: [GeneralPage] , jiraWebhooks :: [Webhook] , jiraJiraProjectAdminTabPanels :: [JIRAProjectAdminTabPanel] } deriving (Show, Generic) instance ToJSON JIRAModules where toJSON = genericToJSON baseOptions { fieldLabelModifier = stripFieldNamePrefix "jira" } -- | A collection of all of the Confluence Modules that you can define. For more documentation on which Modules are supported -- the Atlassian Connect framework please see 'Modules'. You can also find more documentation on each of the modules. data ConfluenceModules = ConfluenceModules { confluenceWebPanels :: [WebPanel] } deriving (Show, Generic) instance ToJSON ConfluenceModules where toJSON = genericToJSON baseOptions { fieldLabelModifier = stripFieldNamePrefix "confluence" } -- | Empty JIRA Modules; useful when you only want to define a few modules via Haskell record syntax. emptyJIRAModules :: JIRAModules emptyJIRAModules = JIRAModules [] [] [] [] -- | Empty Confluence Modules; useful when you only want to define a few modules via Haskell record syntax. emptyConfluenceModules :: ConfluenceModules emptyConfluenceModules = ConfluenceModules [] -- | A 'WebPanel' is an injectable segment of the host application that you can place content inside. Currently the -- WebPanel has the same structure for both JIRA and Confluence but, potentially, that could change in the future. -- You can read their Atlassian Connect documentation here: -- -- * JIRA Web panels: -- * Confluence Web panels: -- -- Here is what an example Hello World web panel might look like: -- -- > helloWorldWebPanel = WebPanel -- > { wpKey = "hello-world" -- > , wpName = Name "Hello world!" -- > , wpUrl = "/panel/show-hello-world" -- > , wpLocation = "atl.jira.view.issue.right.context" -- > , wpConditions = [staticJiraCondition UserIsLoggedInJiraCondition] -- > } -- > where -- > toURI = fromJust . parseRelativeReference -- -- WebPanels are a great way to inject your add-on's content into the host application. data WebPanel = WebPanel { wpKey :: T.Text -- ^ The add-on unique key for this module. , wpName :: Name WebPanel -- ^ The name of this panel, likely to appear in the User Interface. , wpUrl :: T.Text -- ^ The relative URI that the host product will hit to get HTML content. , wpLocation :: T.Text -- ^ The location that this content should be injected in the host product. , wpConditions :: [Condition] -- ^ The 'Condition's that need to be met for this module to be displayed. , wpWeight :: Maybe Integer , wpLayout :: Maybe WebPanelLayout } deriving (Show, Generic) instance ToJSON WebPanel where toJSON = genericToJSON baseOptions { fieldLabelModifier = stripFieldNamePrefix "wp" } -- | A 'WebPanelLayout' allows you to specify the dimensions of your Web Panel if that is required. data WebPanelLayout = WebPanelLayout { wplWidth :: Length , wplHeight :: Length } deriving (Show, Generic) instance ToJSON WebPanelLayout where toJSON = genericToJSON baseOptions { fieldLabelModifier = stripFieldNamePrefix "wpl" } data WebItem = WebItem { wiName :: Name WebItem , wiKey :: T.Text -- TODO add tooltip support , wiLocation :: T.Text , wiUrl :: T.Text , wiConditions :: [Condition] , wiContext :: Maybe WebItemContext , wiIcon :: Maybe IconDetails , wiStyleClasses :: [String] } deriving (Show, Generic) data WebItemContext = PageContext | AddonContext | ProductContext deriving(Show, Generic) instance ToJSON WebItemContext where toJSON PageContext = String . T.pack $ "page" toJSON AddonContext = String . T.pack $ "addon" toJSON ProductContext = String . T.pack $ "product" -- TODO update the docs for the JIRAProjectAdminTabPanel based on this question: http://goo.gl/c6QUdd -- | A 'JIRAProjectAdminTabPanel' is useful for when you want to add a page to the administration screens of a project. -- This module will create a web item in the sidebar of every project for you and provide a web panel in the JIRA Project -- Admin section. data JIRAProjectAdminTabPanel = JIRAProjectAdminTabPanel { jpatpKey :: T.Text , jpatpName :: Name JIRAProjectAdminTabPanel , jpatpUrl :: T.Text , jpatpLocation :: T.Text , jpatpConditions :: [Condition] , jpatpWeight :: Maybe Integer } deriving (Show, Generic) instance ToJSON JIRAProjectAdminTabPanel where toJSON = genericToJSON baseOptions { fieldLabelModifier = stripFieldNamePrefix "jpatp" } instance ToJSON (Name JIRAProjectAdminTabPanel) where toJSON = nameToValue -- | A 'GeneralPage' makes your add-on take a large section of screen realestate, with the intention of displaying -- your own page with no other distracting content. This is very useful for pages like Configuration screens or -- Statistics pages where you really want the user to be fully working with your add-on inside the host product. -- -- General pages, like Web Panels, are common to JIRA and Confluence and share the same json format. However they have -- separate documentation: -- -- * JIRA General Page: -- * Confluence General Page: -- -- Even though, at this point in time, the documentation looks identical. data GeneralPage = GeneralPage { generalPageKey :: T.Text -- ^ The add-on unique key for this module. , generalPageName :: Name GeneralPage -- ^ The name of this General Page. Likely to be used in the page title. , generalPageUrl :: T.Text -- ^ The relative URI that the host product will hit to get the HTML content for the page. , generalPageLocation :: Maybe T.Text -- ^ The location for this General Page to display; see the docs for your options. , generalPageIcon :: Maybe IconDetails -- ^ The optional icon to use for this general page. , generalPageWeight :: Maybe Integer -- ^ Determines the order that this item appears in any menu or list. -- Lower numbers mean that it will appear higher in the list. , generalPageConditions :: [Condition] -- ^ The 'Condition's that need to be met for this module to be displayed. } deriving (Show, Generic) instance ToJSON GeneralPage where toJSON = genericToJSON baseOptions { fieldLabelModifier = stripFieldNamePrefix "generalPage" } instance ToJSON (Name WebPanel) where toJSON = nameToValue instance ToJSON (Name GeneralPage) where toJSON = nameToValue nameToValue :: Name a -> Value nameToValue (Name name) = object [ T.pack "value" .= name ]