Category.purs 5.09 KB
Newer Older
1 2 3 4
-- TODO: this module should be replaced by FacetsTable
module Gargantext.Components.Category where

import Data.Array as A
5
import Data.Generic.Rep (class Generic)
6
import Data.Map as Map
7
import Data.Maybe (Maybe(..))
8 9 10
import Effect.Aff (Aff, launchAff)
import Reactix as R
import Reactix.DOM.HTML as H
11 12 13
import Simple.JSON as JSON

import Gargantext.Prelude
14 15

import Gargantext.Components.Category.Types
16
  ( Category(..), Star(..), cat2score, categories, clickAgain, star2score, stars )
17 18
import Gargantext.Components.DocsTable.Types
  ( DocumentsView(..), LocalCategories, LocalUserScore )
19 20
import Gargantext.Utils.Reactix as R2
import Gargantext.Routes (SessionRoute(NodeAPI))
21 22
import Gargantext.Sessions (Session, put)
import Gargantext.Types (NodeID, NodeType(..))
23

24 25
here :: R2.Here
here = R2.here "Gargantext.Components.Category"
26

27 28 29 30 31 32 33 34 35 36 37 38
type RatingProps =
  ( score              :: Star
  , nodeId             :: NodeID
  , row                :: DocumentsView
  , session            :: Session
  , setLocalCategories :: R.Setter LocalUserScore
  )

rating :: R2.Component RatingProps
rating = R.createElement ratingCpt

ratingCpt :: R.Component RatingProps
39
ratingCpt = here.component "rating" cpt where
40 41 42 43
  cpt { nodeId, row: DocumentsView r, score, session, setLocalCategories } _ =
    pure $ H.div { className:"flex" } divs where
      divs = map (\s -> H.div { className : icon' score s
                              , on: { click: onClick s } } []) stars
44 45 46
      icon' Star_0 Star_0  = "fa fa-times-circle"
      icon' _ Star_0       = "fa fa-times"
      icon' c s = if star2score c < star2score s then "fa fa-star-o" else "fa fa-star"
47 48 49 50 51 52
      onClick c _ = do
        let c' = if score == c
                  then clickAgain c
                  else c

        setLocalCategories $ Map.insert r._id c'
53 54
        void $ launchAff
             $ putRating session nodeId
55
             $ RatingQuery { nodeIds: [r._id], rating: c' }
56

57 58 59 60
newtype RatingQuery =
  RatingQuery { nodeIds :: Array Int
              , rating  :: Star
              }
61 62 63 64
derive instance Generic RatingQuery _
instance JSON.WriteForeign RatingQuery where
  writeImpl (RatingQuery post) = JSON.writeImpl { ntc_nodesId: post.nodeIds
                                                , ntc_category: post.rating }
65 66

putRating :: Session -> Int -> RatingQuery -> Aff (Array Int)
67 68
putRating session nodeId = put session $ ratingRoute where
  ratingRoute = NodeAPI Node (Just nodeId) "category"
69

70 71
type CarousselProps =
  ( category           :: Category
72 73 74 75 76
  , nodeId             :: NodeID
  , row                :: DocumentsView
  , session            :: Session
  , setLocalCategories :: R.Setter LocalCategories
  )
77

78 79 80 81
caroussel :: R2.Component CarousselProps
caroussel = R.createElement carousselCpt

carousselCpt :: R.Component CarousselProps
82
carousselCpt = here.component "caroussel" cpt
83
  where
84 85 86 87 88 89
    cpt { category, nodeId, row: DocumentsView r, session, setLocalCategories } _ = do
      pure $ H.div {className:"flex"} divs
      where
        divs = map (\c -> if category == c
                            then
                              H.div { className : icon c (category == c) } []
90

91 92 93 94 95
                            else
                              H.div { className : icon c (category == c)
                                , on: { click: onClick c}
                                } []
                        ) (caroussel' category)
96

97 98 99
        caroussel' :: Category -> Array Category
        caroussel' Trash = A.take 2 categories
        caroussel' c   = A.take 3 $ A.drop (cat2score c - 1 ) categories
100

101 102
        onClick c = \_-> do
          setLocalCategories $ Map.insert r._id c
103 104 105
          void $ launchAff
               $ putCategories session nodeId
               $ CategoryQuery {nodeIds: [r._id], category: c}
106 107

icon :: Category -> Boolean -> String
108
icon cat b = btn b $ "fa fa-" <> (color $ size b $ icon' cat b)
109 110
  where
    icon' :: Category -> Boolean -> String
111 112
    icon' Trash   false = "times"
    icon' Trash   true  = "times-circle"
113

114 115
    icon' UnRead  false = "question"
    icon' UnRead  true  = "question-circle"
116

117 118
    icon' Checked false = "check"
    icon' Checked true  = "check-circle"
119

120
    icon' Topic  false = "star-o"
121 122
    icon' Topic  true  = "star"

123
    icon' Favorite false = "heart-o"
124 125 126 127
    icon' Favorite true = "heart"

    size :: Boolean -> String -> String
    size true  s = s <> " btn-lg"
128
    size false s = s <> " btn-sm"
129 130 131 132 133 134 135 136

    color :: String -> String
    color x = x <> " text-primary"

    btn :: Boolean -> String -> String
    btn true s = s
    btn false s = "btn " <> s

137
-------------------------------------------------------------------------
138 139 140 141
newtype CategoryQuery = CategoryQuery {
    nodeIds :: Array Int
  , category :: Category
  }
142 143 144 145
derive instance Generic CategoryQuery _
instance JSON.WriteForeign CategoryQuery where
  writeImpl (CategoryQuery post) = JSON.writeImpl { ntc_nodesId: post.nodeIds
                                                  , ntc_category: post.category }
146 147 148 149 150 151

categoryRoute :: Int -> SessionRoute
categoryRoute nodeId = NodeAPI Node (Just nodeId) "category"

putCategories :: Session -> Int -> CategoryQuery -> Aff (Array Int)
putCategories session nodeId = put session $ categoryRoute nodeId