github.com/pf-qiu/concourse/v6@v6.7.3-0.20201207032516-1f455d73275f/web/elm/src/Pipeline/PinMenu/PinMenu.elm (about)

     1  module Pipeline.PinMenu.PinMenu exposing
     2      ( TableRow
     3      , View
     4      , pinMenu
     5      , update
     6      , viewPinMenu
     7      )
     8  
     9  import Colors
    10  import Concourse
    11  import Dict
    12  import EffectTransformer exposing (ET)
    13  import HoverState
    14  import Html exposing (Html)
    15  import Html.Attributes exposing (id, style)
    16  import Html.Events exposing (onClick, onMouseEnter, onMouseLeave)
    17  import Message.Message exposing (DomID(..), Message(..))
    18  import Pipeline.PinMenu.Styles as Styles
    19  import Pipeline.PinMenu.Views as Views
    20  import Routes
    21  import SideBar.Styles as SS
    22  import Views.Styles
    23  
    24  
    25  type alias Model b =
    26      { b
    27          | fetchedResources : Maybe (List Concourse.Resource)
    28          , pipelineLocator : Concourse.PipelineIdentifier
    29          , pinMenuExpanded : Bool
    30      }
    31  
    32  
    33  type alias View =
    34      { hoverable : Bool
    35      , clickable : Bool
    36      , background : Views.Background
    37      , opacity : SS.Opacity
    38      , badge : Maybe Badge
    39      , dropdown : Maybe Dropdown
    40      }
    41  
    42  
    43  type alias Dropdown =
    44      { position : Views.Position
    45      , items : List DropdownItem
    46      }
    47  
    48  
    49  type alias DropdownItem =
    50      { title : Text
    51      , table : List TableRow
    52      , paddingPx : Int
    53      , background : String
    54      , onClick : Message
    55      , hoverable : Bool
    56      }
    57  
    58  
    59  type alias Badge =
    60      { color : String
    61      , diameterPx : Int
    62      , position : Views.Position
    63      , text : String
    64      }
    65  
    66  
    67  type alias Text =
    68      { content : String
    69      , fontWeight : String
    70      , color : String
    71      }
    72  
    73  
    74  type alias TableRow =
    75      { left : String
    76      , right : String
    77      , color : String
    78      }
    79  
    80  
    81  update : Message -> ET (Model b)
    82  update message ( model, effects ) =
    83      case message of
    84          Click PinIcon ->
    85              ( { model | pinMenuExpanded = not model.pinMenuExpanded }
    86              , effects
    87              )
    88  
    89          _ ->
    90              ( model, effects )
    91  
    92  
    93  pinMenu :
    94      { a | hovered : HoverState.HoverState }
    95      -> Model b
    96      -> View
    97  pinMenu { hovered } model =
    98      let
    99          pinnedResources =
   100              getPinnedResources model.fetchedResources
   101  
   102          pipeline =
   103              model.pipelineLocator
   104  
   105          pinCount =
   106              List.length pinnedResources
   107  
   108          hasPinnedResources =
   109              pinCount > 0
   110  
   111          isHovered =
   112              hovered == HoverState.Hovered PinIcon
   113      in
   114      { hoverable = hasPinnedResources
   115      , clickable = hasPinnedResources
   116      , opacity =
   117          if isHovered || model.pinMenuExpanded then
   118              SS.Bright
   119  
   120          else if hasPinnedResources then
   121              SS.GreyedOut
   122  
   123          else
   124              SS.Dim
   125      , background =
   126          if model.pinMenuExpanded then
   127              Views.Light
   128  
   129          else
   130              Views.Dark
   131      , badge =
   132          if hasPinnedResources then
   133              Just
   134                  { color = Colors.pinned
   135                  , diameterPx = 15
   136                  , position = Views.TopRight (Views.Px 10) (Views.Px 10)
   137                  , text = String.fromInt pinCount
   138                  }
   139  
   140          else
   141              Nothing
   142      , dropdown =
   143          if model.pinMenuExpanded then
   144              Just
   145                  { position =
   146                      Views.TopRight (Views.Percent 100) (Views.Percent 0)
   147                  , items =
   148                      List.map
   149                          (\( resourceName, pinnedVersion ) ->
   150                              { title =
   151                                  { content = resourceName
   152                                  , fontWeight = Views.Styles.fontWeightDefault
   153                                  , color = Colors.text
   154                                  }
   155                              , table =
   156                                  pinnedVersion
   157                                      |> Dict.toList
   158                                      |> List.map
   159                                          (\( k, v ) ->
   160                                              { left = k
   161                                              , right = v
   162                                              , color = Colors.text
   163                                              }
   164                                          )
   165                              , paddingPx = 10
   166                              , background =
   167                                  if
   168                                      hovered
   169                                          == HoverState.Hovered
   170                                              (PinMenuDropDown resourceName)
   171                                  then
   172                                      Colors.pinMenuHover
   173  
   174                                  else
   175                                      Colors.pinMenuBackground
   176                              , hoverable = True
   177                              , onClick =
   178                                  GoToRoute <|
   179                                      Routes.Resource
   180                                          { id =
   181                                              { teamName = pipeline.teamName
   182                                              , pipelineName = pipeline.pipelineName
   183                                              , resourceName = resourceName
   184                                              }
   185                                          , page = Nothing
   186                                          }
   187                              }
   188                          )
   189                          pinnedResources
   190                  }
   191  
   192          else
   193              Nothing
   194      }
   195  
   196  
   197  viewPinMenu :
   198      { a | hovered : HoverState.HoverState }
   199      -> Model b
   200      -> Html Message
   201  viewPinMenu session m =
   202      pinMenu session m
   203          |> viewView
   204  
   205  
   206  getPinnedResources : Maybe (List Concourse.Resource) -> List ( String, Concourse.Version )
   207  getPinnedResources fetchedResources =
   208      case fetchedResources of
   209          Nothing ->
   210              []
   211  
   212          Just resources ->
   213              resources
   214                  |> List.filterMap
   215                      (\r ->
   216                          Maybe.map (\v -> ( r.name, v )) r.pinnedVersion
   217                      )
   218  
   219  
   220  viewView : View -> Html Message
   221  viewView view =
   222      Html.div
   223          (([ ( id "pin-icon", True )
   224            , ( onMouseEnter <| Hover <| Just PinIcon, view.hoverable )
   225            , ( onMouseLeave <| Hover Nothing, view.hoverable )
   226            , ( onClick <| Click PinIcon, view.clickable )
   227            ]
   228              |> List.filter Tuple.second
   229              |> List.map Tuple.first
   230           )
   231              ++ Styles.pinIconBackground view
   232          )
   233          (Html.div
   234              (Styles.pinIcon view)
   235              []
   236              :: ([ Maybe.map viewBadge view.badge
   237                  , Maybe.map viewDropdown view.dropdown
   238                  ]
   239                      |> List.filterMap identity
   240                 )
   241          )
   242  
   243  
   244  viewBadge : Badge -> Html Message
   245  viewBadge badge =
   246      Html.div
   247          (id "pin-badge" :: Styles.pinBadge badge)
   248          [ Html.div [] [ Html.text badge.text ] ]
   249  
   250  
   251  viewDropdown : Dropdown -> Html Message
   252  viewDropdown dropdown =
   253      Html.ul
   254          (Styles.pinIconDropdown dropdown)
   255          (List.map viewDropdownItem dropdown.items)
   256  
   257  
   258  viewDropdownItem : DropdownItem -> Html Message
   259  viewDropdownItem item =
   260      Html.li
   261          (onClick item.onClick
   262              :: (if item.hoverable then
   263                      [ onMouseEnter <|
   264                          Hover <|
   265                              Just <|
   266                                  PinMenuDropDown item.title.content
   267                      , onMouseLeave <| Hover Nothing
   268                      ]
   269  
   270                  else
   271                      []
   272                 )
   273              ++ Styles.pinIconDropdownItem item
   274          )
   275          [ viewTitle item.title
   276          , Html.table [] (List.map viewTableRow item.table)
   277          ]
   278  
   279  
   280  viewTitle : Text -> Html Message
   281  viewTitle title =
   282      Html.div
   283          (Styles.title title)
   284          [ Html.text title.content ]
   285  
   286  
   287  viewTableRow : TableRow -> Html Message
   288  viewTableRow { left, right, color } =
   289      Html.tr
   290          [ style "color" color ]
   291          [ Html.td [] [ Html.text left ]
   292          , Html.td [] [ Html.text right ]
   293          ]