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

4 5
import Gargantext.Prelude

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

16 17 18
import Gargantext.Components.Category.Types (Category(..), Star(..), cat2score, categories, clickAgain, star2score, stars)
import Gargantext.Components.DocsTable.Types (DocumentsView(..), LocalCategories, LocalUserScore)
import Gargantext.Config.REST (RESTError)
19
import Gargantext.Routes (SessionRoute(NodeAPI))
20 21
import Gargantext.Sessions (Session, put)
import Gargantext.Types (NodeID, NodeType(..))
22
import Gargantext.Utils.Reactix as R2
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 (Either RESTError (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

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

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