Skip to content

Commit

Permalink
Adding some basic structure for the contract templates library. (#2748)
Browse files Browse the repository at this point in the history
  • Loading branch information
merivale committed Feb 19, 2021
1 parent 9672617 commit b377dc5
Show file tree
Hide file tree
Showing 10 changed files with 145 additions and 54 deletions.
6 changes: 3 additions & 3 deletions marlowe-dashboard-client/src/Contract/View.purs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ import Data.Map as Map
import Data.Maybe (Maybe(..))
import Halogen.HTML (HTML, button, div, div_, h2_, text)
import Halogen.HTML.Events (onClick)
import MainFrame.Types (ContractInstance, ContractStatus)
import MainFrame.Types (ContractStatus)
import Marlowe.Execution (ExecutionStep, NamedAction(..))
import Marlowe.Semantics (Accounts, ChoiceId(..), Input(..), Party, TransactionInput(..), _accounts)
import Marlowe.Semantics (Accounts, ChoiceId(..), Contract, Input(..), Party, TransactionInput(..), _accounts)

contractsScreen :: forall p. ContractStatus -> HTML p Action
contractsScreen contractStatus =
Expand All @@ -25,7 +25,7 @@ contractsScreen contractStatus =
[ text "Dashboard home" ]
]

contractDetailsCard :: forall p. ContractInstance -> HTML p Action
contractDetailsCard :: forall p. Contract -> HTML p Action
contractDetailsCard contractInstance =
div_
[ h2_
Expand Down
5 changes: 5 additions & 0 deletions marlowe-dashboard-client/src/MainFrame/Lenses.purs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
module MainFrame.Lenses
( _wallets
, _newWalletNicknameKey
, _templates
, _subState
, _pickupState
, _walletState
Expand All @@ -21,6 +22,7 @@ import Data.Lens.Record (prop)
import Data.Symbol (SProxy(..))
import MainFrame.Types (WalletState, PickupState, State)
import Marlowe.Semantics (PubKey)
import Template.Types (Template)
import Wallet.Types (WalletLibrary, WalletNicknameKey)

_wallets :: Lens' State WalletLibrary
Expand All @@ -29,6 +31,9 @@ _wallets = prop (SProxy :: SProxy "wallets")
_newWalletNicknameKey :: Lens' State WalletNicknameKey
_newWalletNicknameKey = prop (SProxy :: SProxy "newWalletNicknameKey")

_templates :: Lens' State (Array Template)
_templates = prop (SProxy :: SProxy "templates")

_subState :: Lens' State (Either PickupState WalletState)
_subState = prop (SProxy :: SProxy "subState")

Expand Down
6 changes: 5 additions & 1 deletion marlowe-dashboard-client/src/MainFrame/State.purs
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,13 @@ import Halogen (Component, HalogenM, liftEffect, mkComponent, mkEval, modify_, r
import Halogen.Extra (mapSubmodule)
import Halogen.HTML (HTML)
import LocalStorage (getItem, removeItem, setItem)
import MainFrame.Lenses (_card, _contractState, _walletState, _menuOpen, _newWalletNicknameKey, _on, _pickupState, _screen, _subState, _wallets)
import MainFrame.Lenses (_card, _contractState, _menuOpen, _newWalletNicknameKey, _on, _pickupState, _screen, _subState, _templates, _wallets, _walletState)
import MainFrame.Types (Action(..), ChildSlots, ContractStatus(..), WalletState, Msg(..), PickupCard(..), PickupScreen(..), PickupState, Query(..), Screen(..), State)
import MainFrame.View (render)
import Marlowe.Execution (_contract)
import Marlowe.Semantics (Contract(..), PubKey)
import StaticData (walletLocalStorageKey, walletsLocalStorageKey)
import Template.Library (templates)
import Wallet.Lenses (_key, _nickname)
import Wallet.Types (WalletDetails)
import WebSocket (StreamToClient(..), StreamToServer(..))
Expand All @@ -50,6 +51,7 @@ initialState :: State
initialState =
{ wallets: empty
, newWalletNicknameKey: mempty
, templates: mempty
, subState: Left initialPickupState
, contractState: Contract.initialState zero Close
}
Expand Down Expand Up @@ -90,6 +92,8 @@ handleAction Init = do
for_ mCachedWalletJson \json ->
for_ (runExcept $ decodeJSON json) \cachedWallet ->
assign _subState $ Right $ mkWalletState cachedWallet
-- TODO: fetch contract templates from the library ??
assign _templates templates

-- pickup actions
handleAction (SetPickupCard pickupCard) = assign (_pickupState <<< _card) pickupCard
Expand Down
16 changes: 4 additions & 12 deletions marlowe-dashboard-client/src/MainFrame/Types.purs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ module MainFrame.Types
, Screen(..)
, Card(..)
, ContractStatus(..)
, ContractTemplate
, ContractInstance
, ChildSlots
, Query(..)
, Msg(..)
Expand All @@ -21,6 +19,7 @@ import Contract.Types as Contract
import Data.Either (Either)
import Data.Maybe (Maybe(..))
import Marlowe.Semantics (Contract, PubKey)
import Template.Types (Template)
import Wallet.Types (WalletDetails, WalletLibrary, WalletNicknameKey)
import WebSocket (StreamToClient, StreamToServer)
import WebSocket.Support as WS
Expand All @@ -33,6 +32,7 @@ import WebSocket.Support as WS
type State
= { wallets :: WalletLibrary
, newWalletNicknameKey :: WalletNicknameKey
, templates :: Array Template
, subState :: Either PickupState WalletState
-- TODO: (work out how to) move contract state into wallet state
-- (the puzzle is how to handle contract actions in the mainframe if the
Expand Down Expand Up @@ -69,6 +69,7 @@ type WalletState
data Screen
= ContractsScreen ContractStatus
| WalletLibraryScreen
| ContractSetupScreen Template

derive instance eqScreen :: Eq Screen

Expand All @@ -77,8 +78,7 @@ data Card
| ViewWalletCard WalletNicknameKey WalletDetails
| PutdownWalletCard
| TemplateLibraryCard
| ContractTemplateCard ContractTemplate
| ContractInstanceCard ContractInstance
| ContractCard Contract

derive instance eqCard :: Eq Card

Expand All @@ -88,14 +88,6 @@ data ContractStatus

derive instance eqContractStatus :: Eq ContractStatus

-- contract templage type TBD
type ContractTemplate
= Int

-- contract instance type TBD
type ContractInstance
= Int

------------------------------------------------------------
type ChildSlots
= (
Expand Down
45 changes: 27 additions & 18 deletions marlowe-dashboard-client/src/MainFrame/View.purs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ import Halogen (ComponentHTML)
import Halogen.HTML (HTML, a, div, footer, h1, header, main, nav, span, text)
import Halogen.HTML.Events (onClick)
import Halogen.HTML.Properties (href)
import MainFrame.Lenses (_card, _menuOpen, _newWalletNicknameKey, _screen, _subState, _wallet, _wallets)
import MainFrame.Lenses (_card, _menuOpen, _newWalletNicknameKey, _templates, _screen, _subState, _wallet, _wallets)
import MainFrame.Types (Action(..), Card(..), ChildSlots, ContractStatus(..), WalletState, PickupCard(..), PickupScreen(..), PickupState, Screen(..), State)
import Marlowe.Semantics (PubKey)
import Material.Icons as Icon
import Prim.TypeError (class Warn, Text)
import Template.View (templateLibraryCard, templateDetailsCard)
import Template.View (templateLibraryCard, contractSetupScreen)
import Template.Types (Template)
import Wallet.Types (WalletNicknameKey, WalletLibrary)
import Wallet.View (contactDetailsCard, newContactCard, pickupLocalWalletCard, pickupNewWalletCard, pickupWalletScreen, putdownWalletCard, walletLibraryScreen)

Expand All @@ -26,10 +27,12 @@ render state =
wallets = view _wallets state

newWalletNicknameKey = view _newWalletNicknameKey state

templates = view _templates state
in
case view _subState state of
Left pickupState -> renderPickupState wallets newWalletNicknameKey pickupState
Right walletState -> renderWalletState wallets newWalletNicknameKey walletState
Right walletState -> renderWalletState wallets newWalletNicknameKey templates walletState

------------------------------------------------------------
renderPickupState :: forall p. WalletLibrary -> WalletNicknameKey -> PickupState -> HTML p Action
Expand Down Expand Up @@ -78,8 +81,8 @@ renderPickupScreen wallets screen = case screen of
[ pickupWalletScreen wallets ]

------------------------------------------------------------
renderWalletState :: forall p. WalletLibrary -> WalletNicknameKey -> WalletState -> HTML p Action
renderWalletState wallets newWalletNicknameKey walletState =
renderWalletState :: forall p. WalletLibrary -> WalletNicknameKey -> Array Template -> WalletState -> HTML p Action
renderWalletState wallets newWalletNicknameKey templates walletState =
let
wallet = view _wallet walletState

Expand All @@ -91,13 +94,13 @@ renderWalletState wallets newWalletNicknameKey walletState =
in
div
[ classNames [ "grid", "h-full", "grid-rows-main" ] ]
[ renderHeader wallet wallets menuOpen
, renderMain newWalletNicknameKey wallet wallets menuOpen screen card
[ renderHeader wallet menuOpen
, renderMain newWalletNicknameKey wallets templates wallet menuOpen screen card
, renderFooter
]

renderHeader :: forall p. PubKey -> WalletLibrary -> Boolean -> HTML p Action
renderHeader wallet wallets menuOpen =
renderHeader :: forall p. PubKey -> Boolean -> HTML p Action
renderHeader wallet menuOpen =
header
[ classNames [ "relative", "flex", "justify-between", "text-green" ] ]
[ h1
Expand Down Expand Up @@ -148,12 +151,12 @@ renderHeader wallet wallets menuOpen =
where
itemClasses = [ "flex", "items-center", "p-0.5" ]

renderMain :: forall p. WalletNicknameKey -> PubKey -> WalletLibrary -> Boolean -> Screen -> Maybe Card -> HTML p Action
renderMain newWalletNicknameKey wallet wallets menuOpen screen card =
renderMain :: forall p. WalletNicknameKey -> WalletLibrary -> Array Template -> PubKey -> Boolean -> Screen -> Maybe Card -> HTML p Action
renderMain newWalletNicknameKey wallets templates wallet menuOpen screen card =
main
[ classNames [ "relative", "bg-lightblue", "text-blue" ] ]
[ renderMobileMenu menuOpen
, renderCards newWalletNicknameKey wallets wallet card
, renderCards newWalletNicknameKey wallets templates wallet card
, renderScreen wallets screen
]

Expand All @@ -175,12 +178,12 @@ renderMobileMenu menuOpen =
]
]

renderCards :: forall p. WalletNicknameKey -> WalletLibrary -> PubKey -> Maybe Card -> HTML p Action
renderCards newWalletNicknameKey wallets wallet card =
renderCards :: forall p. WalletNicknameKey -> WalletLibrary -> Array Template -> PubKey -> Maybe Card -> HTML p Action
renderCards newWalletNicknameKey wallets templates wallet card =
div
[ classNames $ [ "absolute", "top-0", "bottom-0", "left-0", "right-0", "z-10", "flex", "flex-col", "justify-end", "md:justify-center", "bg-transgray" ] <> hideWhen (isNothing card) ]
[ div
[ classNames $ [ "shadow-md", "bg-white", "mx-1", "md:mx-auto", "md:w-card" ] <> hideWhen (isNothing card) ]
[ classNames cardClasses ]
[ div
[ classNames [ "flex", "justify-end" ] ]
[ a
Expand All @@ -194,12 +197,17 @@ renderCards newWalletNicknameKey wallets wallet card =
Just CreateWalletCard -> [ newContactCard newWalletNicknameKey wallets ]
Just (ViewWalletCard walletNicknameKey walletDetails) -> [ contactDetailsCard walletNicknameKey walletDetails ]
Just PutdownWalletCard -> [ putdownWalletCard wallet wallets ]
Just TemplateLibraryCard -> [ templateLibraryCard ]
Just (ContractTemplateCard contractTemplate) -> [ templateDetailsCard contractTemplate ]
Just (ContractInstanceCard contractInstance) -> [ ContractAction <$> contractDetailsCard contractInstance ]
Just TemplateLibraryCard -> [ templateLibraryCard templates ]
Just (ContractCard contract) -> [ ContractAction <$> contractDetailsCard contract ]
Nothing -> []
]
]
where
cardClasses = case card of
Just TemplateLibraryCard -> [ "max-h-full", "overflow-auto", "mt-3", "mx-1", "shadow-md", "bg-gray", "md:mb-3", "lg:mx-3" ]
Just (ContractCard _) -> [ "max-h-full", "overflow-auto", "mt-1", "mx-1", "shadow-md", "bg-gray", "md:mb-1", "lg:mx-3" ]
Just _ -> [ "mx-1", "shadow-md", "bg-white", "md:mx-auto", "md:w-card" ]
Nothing -> [ "hidden" ]

renderScreen :: forall p. WalletLibrary -> Screen -> HTML p Action
renderScreen wallets screen =
Expand All @@ -208,6 +216,7 @@ renderScreen wallets screen =
[ case screen of
ContractsScreen contractStatus -> ContractAction <$> contractsScreen contractStatus
WalletLibraryScreen -> walletLibraryScreen wallets
ContractSetupScreen template -> contractSetupScreen template
]

renderFooter :: forall p. HTML p Action
Expand Down
50 changes: 50 additions & 0 deletions marlowe-dashboard-client/src/Template/Library.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
module Template.Library (templates) where

import Template.Types (Template)

-- we could potentially just hard code these here for now, but it would be
-- better to fetch them from the library; in any case, I'm hard coding some
-- approximations of what these might look like to help get the ball rolling
templates :: Array Template
templates =
[ { name: "Sample escrow contract 1"
, type_: "Escrow"
, description: "Escrow is a financial arrangement where a third party holds and regulates payment of the funds required for two parties involved in a given transaction."
, contract: 0
}
, { name: "Sample escrow contract 2"
, type_: "Escrow"
, description: "Escrow is a financial arrangement where a third party holds and regulates payment of the funds required for two parties involved in a given transaction."
, contract: 0
}
, { name: "Sample zero coupon bond contract 1"
, type_: "Zero Coupon Bond"
, description: "A zero-coupon bond is a debt security that does not pay interest but instead trades at a deep discount, rendering a profit at maturity, when the bond is redeemed for its full face value."
, contract: 0
}
, { name: "Sample zero coupon bond contract 2"
, type_: "Zero Coupon Bond"
, description: "A zero-coupon bond is a debt security that does not pay interest but instead trades at a deep discount, rendering a profit at maturity, when the bond is redeemed for its full face value."
, contract: 0
}
, { name: "Sample coupon bond guaranteed contract 1"
, type_: "Coupon Bond Guaranteed"
, description: "A guaranteed bond is a debt security that offers a secondary guarantee that interest and principal payments will be made by a third party, should the issuer default. It can be backed by a bond insurance company, a fund or group entity, a government authority, or the corporate parents of subsidiaries or joint ventures that are issuing bonds."
, contract: 0
}
, { name: "Sample coupon bond guaranteed contract 2"
, type_: "Coupon Bond Guaranteed"
, description: "A guaranteed bond is a debt security that offers a secondary guarantee that interest and principal payments will be made by a third party, should the issuer default. It can be backed by a bond insurance company, a fund or group entity, a government authority, or the corporate parents of subsidiaries or joint ventures that are issuing bonds."
, contract: 0
}
, { name: "Sample swap contract 1"
, type_: "Swap"
, description: "A swap is a derivative contract through which two parties exchange the cash flows or liabilities from two different financial instruments. Most swaps involve cash flows based on a notional principal amount such as a loan or bond, although the instrument can be almost anything. Usually, the principal does not change hands. Each cash flow comprises one leg of the swap. One cash flow is generally fixed, while the other is variable and based on a benchmark interest rate, floating currency exchange rate or index price."
, contract: 0
}
, { name: "Sample swap contract 2"
, type_: "Swap"
, description: "A swap is a derivative contract through which two parties exchange the cash flows or liabilities from two different financial instruments. Most swaps involve cash flows based on a notional principal amount such as a loan or bond, although the instrument can be almost anything. Usually, the principal does not change hands. Each cash flow comprises one leg of the swap. One cash flow is generally fixed, while the other is variable and based on a benchmark interest rate, floating currency exchange rate or index price."
, contract: 0
}
]
15 changes: 15 additions & 0 deletions marlowe-dashboard-client/src/Template/Types.purs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module Template.Types
( Template
, Contract
) where

type Template
= { name :: String
, type_ :: String
, description :: String
, contract :: Contract
}

-- TODO: move Marlowe.Extended to web-common-marlowe and import Marlowe.Extended.Contract
type Contract
= Int
48 changes: 32 additions & 16 deletions marlowe-dashboard-client/src/Template/View.purs
Original file line number Diff line number Diff line change
@@ -1,28 +1,44 @@
module Template.View
( templateLibraryCard
, templateDetailsCard
, templateSetupScreen
, contractSetupScreen
) where

import Prelude hiding (div)
import Css (classNames)
import Halogen.HTML (HTML, div, text)
import MainFrame.Types (Action, ContractTemplate)
import Data.Maybe (Maybe(..))
import Halogen.HTML (HTML, button, div, div_, h2_, h3_, h4_, p_, text)
import Halogen.HTML.Events (onClick)
import MainFrame.Types (Action(..), Screen(..))
import Template.Types (Template)

templateLibraryCard :: forall p. HTML p Action
templateLibraryCard =
div
[ classNames [ "h-full", "overflow-auto" ] ]
[ text "Start new from template" ]
templateLibraryCard :: forall p. Array Template -> HTML p Action
templateLibraryCard templates =
div_
[ h2_ [ text "Start new from template" ]
, div
[ classNames [ "grid", "gap-1", "md:grid-cols-2", "lg:grid-cols-3" ] ]
(templateBox <$> templates)
]

templateDetailsCard :: forall p. ContractTemplate -> HTML p Action
templateDetailsCard contractTemplate =
templateBox :: forall p. Template -> HTML p Action
templateBox template =
div
[ classNames [ "h-full", "overflow-auto" ] ]
[ text "Contract Template" ]
[ classNames [ "bg-white", "p-1" ] ]
[ h4_
[ text template.type_ ]
, h3_
[ text template.name ]
, p_
[ text template.description ]
, button
[ classNames [ "bg-green", "text-white" ]
, onClick $ const $ Just $ SetScreen $ ContractSetupScreen template
]
[ text "Setup" ]
]

templateSetupScreen :: forall p. ContractTemplate -> HTML p Action
templateSetupScreen contractTemplate =
contractSetupScreen :: forall p. Template -> HTML p Action
contractSetupScreen template =
div
[ classNames [ "h-full", "overflow-auto" ] ]
[ classNames [ "p-1" ] ]
[ text "Setup Contract" ]
2 changes: 1 addition & 1 deletion marlowe-dashboard-client/src/Wallet/View.purs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import Wallet.Validation (keyError, nicknameError)
pickupWalletScreen :: forall p. WalletLibrary -> HTML p Action
pickupWalletScreen wallets =
div
[ classNames [ "flex", "flex-col", "justify-between", "h-full", "overflow-auto" ] ]
[ classNames [ "flex", "flex-col", "justify-between" ] ]
[ header
[ classNames [ "flex" ] ]
[ link Icon.navigateBefore "Back to marlowe.io" "" ]
Expand Down

0 comments on commit b377dc5

Please sign in to comment.