-- TODO: this module should be replaced by FacetsTable module Gargantext.Components.Category where import Gargantext.Prelude import Data.Array as A import Data.Enum (fromEnum) import Data.Generic.Rep (class Generic) import Data.Map as Map import Data.Maybe (Maybe(..), fromMaybe) import Data.Tuple.Nested ((/\)) import Effect.Aff (launchAff_) import Effect.Class (liftEffect) import Gargantext.Components.Bootstrap as B import Gargantext.Components.Bootstrap.Types (Variant(..)) import Gargantext.Components.Category.Types (Category(..), Star(..), cat2score, cat2star, categories, categoryNextState, decodeCategory, stars) import Gargantext.Components.DocsTable.Types (DocumentsView(..), LocalCategories) import Gargantext.Components.GraphQL.Context (NodeContext) import Gargantext.Components.GraphQL.Endpoints (getNodeContext, updateNodeContextCategory) import Gargantext.Config.REST (AffRESTError, RESTError(..)) import Gargantext.Hooks.Loader (useLoader) import Gargantext.Routes (SessionRoute(NodeAPI)) import Gargantext.Sessions (Session, put) import Gargantext.Types (NodeID, NodeType(..)) import Gargantext.Utils ((?)) import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Toestand as T2 import Reactix as R import Reactix.DOM.HTML as H import Simple.JSON as JSON import Toestand as T here :: R2.Here here = R2.here "Gargantext.Components.Category" type RatingProps = ( chartReload :: T2.ReloadS , nodeId :: NodeID , row :: DocumentsView , score :: Category , session :: Session -- , setLocalCategories :: R.Setter LocalCategories ) rating :: R2.Component RatingProps rating = R.createElement ratingCpt ratingCpt :: R.Component RatingProps ratingCpt = here.component "rating" cpt where cpt { chartReload , nodeId , row: DocumentsView r , score , session -- , setLocalCategories } _ = do pure $ renderRatingSimple { docId: r._id , corpusId: nodeId , category: score , session } [] -- -- | Behaviors -- -- | -- let -- onClick c _ = do -- let c' = score == c ? clickAgain c $ c -- setLocalCategories $ Map.insert r._id c' -- launchAff_ do -- _ <- putRating session nodeId $ RatingQuery -- { nodeIds: [r._id] -- , rating: c' -- } -- liftEffect $ T2.reload chartReload -- -- | Render -- -- | -- pure $ -- H.div -- { className: "rating-group" } $ -- stars <#> \s -> -- B.iconButton -- { name: ratingIcon score s -- , callback: onClick s -- , overlay: false -- , variant: ratingVariant score s -- , className: ratingClassName score s -- } ratingIcon :: Category -> Star -> String ratingIcon Trash Star_0 = "recycle" ratingIcon _ Star_0 = "trash" ratingIcon c s = fromEnum (cat2star c) < fromEnum s ? "star-o" $ "star" ratingVariant :: Star -> Star -> Variant ratingVariant Star_0 Star_0 = Dark ratingVariant _ Star_0 = Dark ratingVariant _ _ = Dark ratingClassName :: Star -> Star -> String ratingClassName Star_0 Star_0 = "rating-group__action" ratingClassName _ Star_0 = "rating-group__action" ratingClassName _ _ = "rating-group__star" ------------------------------------------------ type RatingSimpleLoaderProps = ( docId :: NodeID , corpusId :: NodeID , session :: Session ) ratingSimpleLoader :: R2.Component RatingSimpleLoaderProps ratingSimpleLoader = R.createElement ratingSimpleLoaderCpt ratingSimpleLoaderCpt :: R.Component RatingSimpleLoaderProps ratingSimpleLoaderCpt = here.component "ratingSimpleLoader" cpt where cpt { docId , corpusId , session } _ = do useLoader { errorHandler , loader: loadDocumentContext session , path: { docId, corpusId } , render: \{ nc_category } -> do let category = fromMaybe UnRead $ decodeCategory <$> nc_category renderRatingSimple { docId , corpusId , category , session } [] } where errorHandler err = do here.warn2 "[pageLayout] RESTError" err case err of ReadJSONError err' -> here.warn2 "[pageLayout] ReadJSONError" $ show err' _ -> pure unit type ContextParams = ( docId :: NodeID , corpusId :: NodeID ) loadDocumentContext :: Session -> Record ContextParams -> AffRESTError NodeContext loadDocumentContext session { docId, corpusId } = getNodeContext session docId corpusId type RenderRatingSimpleProps = ( docId :: NodeID , corpusId :: NodeID , category :: Category , session :: Session ) renderRatingSimple :: R2.Component RenderRatingSimpleProps renderRatingSimple = R.createElement renderRatingSimpleCpt renderRatingSimpleCpt :: R.Component RenderRatingSimpleProps renderRatingSimpleCpt = here.component "renderRatingSimple" cpt where cpt { docId , corpusId , category , session } _ = do categoryS <- T.useBox category pure $ ratingSimple { docId , corpusId , category: categoryS , session } [] type RatingSimpleProps = ( docId :: NodeID , corpusId :: NodeID , category :: T.Box Category , session :: Session ) ratingSimple :: R2.Component RatingSimpleProps ratingSimple = R.createElement ratingSimpleCpt ratingSimpleCpt :: R.Component RatingSimpleProps ratingSimpleCpt = here.component "ratingSimple" cpt where cpt { docId , corpusId , category , session } _ = do category' <- T.useLive T.unequal category let star' = cat2star category' let onClick c _ = do -- let c' = score' == c ? clickAgain c $ c let c' = categoryNextState category' c -- setLocalCategories $ Map.insert r._id c' launchAff_ do _ <- updateNodeContextCategory session docId corpusId $ cat2score c' liftEffect $ T.write_ c' category pure unit pure $ H.div { className: "rating-group" } $ stars <#> \s -> B.iconButton { name: ratingIcon category' s , callback: onClick s , overlay: false , variant: ratingVariant star' s , className: ratingClassName star' s } newtype RatingQuery = RatingQuery { nodeIds :: Array Int , rating :: Category } derive instance Generic RatingQuery _ instance JSON.WriteForeign RatingQuery where writeImpl (RatingQuery post) = JSON.writeImpl { ntc_nodesId: post.nodeIds , ntc_category: post.rating } putRating :: Session -> Int -> RatingQuery -> AffRESTError (Array Int) putRating session nodeId = put session $ ratingRoute where ratingRoute = NodeAPI Node (Just nodeId) "category" type CarousselProps = ( category :: Category , nodeId :: NodeID , row :: DocumentsView , session :: Session , setLocalCategories :: R.Setter LocalCategories ) caroussel :: R2.Component CarousselProps caroussel = R.createElement carousselCpt carousselCpt :: R.Component CarousselProps carousselCpt = here.component "caroussel" cpt where cpt { category, nodeId, row: DocumentsView r, session, setLocalCategories } _ = do pure $ H.div {className:"d-flex"} divs where divs = map (\c -> if category == c then H.div { className : icon c (category == c) } [] else H.div { className : icon c (category == c) , on: { click: onClick c} } [] ) (caroussel' category) caroussel' :: Category -> Array Category caroussel' Trash = A.take 2 categories caroussel' c = A.take 3 $ A.drop (cat2score c - 1 ) categories onClick c = \_-> do setLocalCategories $ Map.insert r._id c launchAff_ $ do _ <- putCategories session nodeId $ CategoryQuery {nodeIds: [r._id], category: c} pure unit icon :: Category -> Boolean -> String icon cat b = btn b $ "fa fa-" <> (color $ size b $ icon' cat b) where icon' :: Category -> Boolean -> String icon' Trash false = "times" icon' Trash true = "times-circle" icon' UnRead false = "question" icon' UnRead true = "question-circle" icon' Checked false = "check" icon' Checked true = "check-circle" icon' Topic false = "star-o" icon' Topic true = "star" icon' Favorite false = "heart-o" icon' Favorite true = "heart" icon' ToCite false = "quote-left-o" icon' ToCite true = "quote-left" size :: Boolean -> String -> String size true s = s <> " btn-lg" size false s = s <> " btn-sm" color :: String -> String color x = x <> " text-primary" btn :: Boolean -> String -> String btn true s = s btn false s = "btn " <> s ------------------------------------------------------------------------- newtype CategoryQuery = CategoryQuery { nodeIds :: Array Int , category :: Category } derive instance Generic CategoryQuery _ instance JSON.WriteForeign CategoryQuery where writeImpl (CategoryQuery post) = JSON.writeImpl { ntc_nodesId: post.nodeIds , ntc_category: post.category } categoryRoute :: Int -> SessionRoute categoryRoute nodeId = NodeAPI Node (Just nodeId) "category" putCategories :: Session -> Int -> CategoryQuery -> AffRESTError (Array Int) putCategories session nodeId = put session $ categoryRoute nodeId