Document.purs 14.6 KB
Newer Older
1
module Gargantext.Components.Nodes.Corpus.Document where
2

3
import Prelude (class Show, bind, identity, mempty, pure, ($), (<>))
4
import Data.Argonaut (class DecodeJson, decodeJson, (.:), (.:?))
5 6 7 8
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.Maybe (Maybe(..), maybe)
import Effect.Aff (Aff)
9
import React (ReactClass, Children)
10 11
import React.DOM (div, h4, li, p, span, text, ul)
import React.DOM.Props (className)
12
import Reactix as R
13
import Thermite (PerformAction, Render, Spec, simpleSpec, createClass)
14

15
import Gargantext.Components.AutoUpdate (autoUpdateElt)
16
import Gargantext.Components.Node (NodePoly(..))
17
import Gargantext.Components.NgramsTable.Core
18 19
  ( CoreState, NgramsPatch(..), NgramsTerm, Replace, Versioned(..)
  , VersionedNgramsTable, addNewNgram, applyNgramsTablePatch, commitPatch
20
  , loadNgramsTable, replace, singletonNgramsTablePatch, syncPatches )
James Laver's avatar
James Laver committed
21
import Gargantext.Components.Annotation.AnnotatedField as AnnotatedField
22
import Gargantext.Hooks.Loader (useLoader)
23
import Gargantext.Routes (SessionRoute(..))
24
import Gargantext.Sessions (Session, get)
25
import Gargantext.Types (CTabNgramType(..), NodeType(..), TabSubType(..), TabType(..), TermList, ScoreType(..))
26
import Gargantext.Utils as U
27
import Gargantext.Utils.Reactix as R2
28

29 30 31 32 33 34
type DocPath =
  { nodeId   :: Int
  , listIds  :: Array Int
  , corpusId :: Maybe Int
  , tabType  :: TabType
  , session  :: Session }
35 36 37 38 39

type NodeDocument = NodePoly Document

type LoadedData =
  { document    :: NodeDocument
40 41
  , ngramsTable :: VersionedNgramsTable
  }
42

43 44 45 46
type Props =
  { loaded :: LoadedData
  , path   :: DocPath
  }
47 48 49 50

-- This is a subpart of NgramsTable.State.
type State = CoreState ()

51 52 53 54 55
initialState
  :: forall props others
  .  { loaded :: { ngramsTable :: VersionedNgramsTable | others }
     | props }
  -> State
56
initialState {loaded: {ngramsTable: Versioned {version}}} =
57 58 59
  { ngramsLocalPatch: mempty
  , ngramsStagePatch: mempty
  , ngramsValidPatch: mempty
60
  , ngramsVersion:    version
61
  }
62

63
-- This is a subset of NgramsTable.Action.
64
data Action
65
  = SetTermListItem NgramsTerm (Replace TermList)
66
  | AddNewNgram NgramsTerm TermList
67
  | Synchronize
68

69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
newtype Status = Status { failed    :: Int
                        , succeeded :: Int
                        , remaining :: Int
                        }

newtype DocumentV3 =
  DocumentV3 { abstract           :: Maybe String
             , authors            :: Maybe String
             --, error              :: Maybe String
             , language_iso2      :: Maybe String
             , language_iso3      :: Maybe String
             , language_name      :: Maybe String
             , publication_date   :: Maybe String
             , publication_day    :: Maybe Int
             , publication_hour   :: Maybe Int
             , publication_minute :: Maybe Int
             , publication_month  :: Maybe Int
             , publication_second :: Maybe Int
             , publication_year   :: Maybe Int
             , realdate_full_     :: Maybe String
             , source             :: Maybe String
             , statuses           :: Maybe (Array Status)
             , title              :: Maybe String
             }

defaultNodeDocumentV3 :: NodePoly DocumentV3
defaultNodeDocumentV3 =
  NodePoly { id : 0
           , typename : 0
           , userId   : 0
           , parentId : 0
           , name     : "Default name"
           , date     : "Default date"
           , hyperdata : defaultDocumentV3
         }

defaultDocumentV3 :: DocumentV3
defaultDocumentV3 =
  DocumentV3 { abstract           : Nothing
             , authors            : Nothing
             --, error              : Nothing
             , language_iso2      : Nothing
             , language_iso3      : Nothing
             , language_name      : Nothing
             , publication_date   : Nothing
             , publication_day    : Nothing
             , publication_hour   : Nothing
             , publication_minute : Nothing
             , publication_month  : Nothing
             , publication_second : Nothing
             , publication_year   : Nothing
             , realdate_full_     : Nothing
             , source             : Nothing
             , statuses           : Nothing
             , title              : Nothing
             }

126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
data Document
  = Document
    { abstract           :: Maybe String
    , authors            :: Maybe String
    , bdd                :: Maybe String
    , doi                :: Maybe String
    , language_iso2      :: Maybe String
    -- , page               :: Maybe Int
    , publication_date   :: Maybe String
    --, publication_second :: Maybe Int
    --, publication_minute :: Maybe Int
    --, publication_hour   :: Maybe Int
    , publication_day    :: Maybe Int
    , publication_month  :: Maybe Int
    , publication_year   :: Maybe Int
    , source             :: Maybe String
    , institutes         :: Maybe String
    , title              :: Maybe String
    , uniqId             :: Maybe String
    --, url                :: Maybe String
    --, text               :: Maybe String
    }

149 150 151 152 153 154
publicationDate :: Document -> String
publicationDate (Document doc@{publication_year: Nothing}) = ""
publicationDate (Document doc@{publication_year: Just py, publication_month: Nothing}) = U.zeroPad 2 py
publicationDate (Document doc@{publication_year: Just py, publication_month: Just pm, publication_day: Nothing}) = (U.zeroPad 2 py) <> "-" <> (U.zeroPad 2 pm)
publicationDate (Document doc@{publication_year: Just py, publication_month: Just pm, publication_day: Just pd}) = (U.zeroPad 2 py) <> "-" <> (U.zeroPad 2 pm) <> "-" <> (U.zeroPad 2 pd)

155
defaultNodeDocument :: NodeDocument
156 157 158 159 160 161 162 163 164 165
defaultNodeDocument =
  NodePoly { id : 0
           , typename : 0
           , userId   : 0
           , parentId : 0
           , name     : "Default name"
           , date     : "Default date"
           , hyperdata : defaultDocument
         }

166
-- TODO: BUG if DOI does not exist, page is not shown
167 168 169 170 171 172 173
defaultDocument :: Document
defaultDocument =
  Document { abstract           : Nothing
           , authors            : Nothing
           , bdd                : Nothing
           , doi                : Nothing
           , language_iso2      : Nothing
174
           --, page               : Nothing
175
           , publication_date   : Nothing
176 177 178
           --, publication_second : Nothing
           --, publication_minute : Nothing
           --, publication_hour   : Nothing
179 180 181 182
           , publication_day    : Nothing
           , publication_month  : Nothing
           , publication_year   : Nothing
           , source             : Nothing
183
           , institutes         : Nothing
184 185
           , title              : Nothing
           , uniqId             : Nothing
186 187
           --, url                : Nothing
           --, text               : Nothing
188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206
           }

derive instance genericDocument   :: Generic Document   _
derive instance genericDocumentV3 :: Generic DocumentV3 _
derive instance genericStatus     :: Generic Status     _

instance showDocument :: Show Document where
  show = genericShow

instance showDocumentV3 :: Show DocumentV3 where
  show = genericShow

instance showStatus :: Show Status where
  show = genericShow

instance decodeStatus :: DecodeJson Status
  where
    decodeJson json = do
      obj <- decodeJson json
207 208 209
      failed <- obj .: "failed"
      succeeded <- obj .: "succeeded"
      remaining <- obj .: "remaining"
210 211 212 213 214 215 216
      pure $ Status {failed, succeeded, remaining}


instance decodeDocumentV3 :: DecodeJson DocumentV3
  where
    decodeJson json = do
      obj <- decodeJson json
217
      abstract <- obj .:? "abstract"
218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233
      authors  <- obj .: "authors"
      --error    <- obj .: "error"
      language_iso2 <- obj .: "language_iso2"
      language_iso3 <- obj .: "language_iso3"
      language_name <- obj .: "language_name"
      publication_date   <- obj .: "publication_date"
      publication_day    <- obj .: "publication_day"
      publication_hour   <- obj .: "publication_hour"
      publication_minute <- obj .: "publication_minute"
      publication_month  <- obj .: "publication_month"
      publication_second <- obj .: "publication_second"
      publication_year   <- obj .: "publication_year"
      realdate_full_     <- obj .: "realdate_full_"
      source   <- obj .: "source"
      statuses <- obj .: "statuses"
      title    <- obj .: "title"
234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256
      pure $ DocumentV3 { abstract
                        , authors
                        --, error
                        , language_iso2
                        , language_iso3
                        , language_name
                        , publication_date
                        , publication_day
                        , publication_hour
                        , publication_minute
                        , publication_month
                        , publication_second
                        , publication_year
                        , realdate_full_
                        , source
                        , statuses
                        , title
                        }

instance decodeDocument :: DecodeJson Document
  where
    decodeJson json = do
      obj <- decodeJson json
257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
      abstract <- obj .:? "abstract"
      authors  <- obj .:? "authors"
      bdd      <- obj .:? "bdd"
      doi      <- obj .:? "doi"
      language_iso2 <- obj .:? "language_iso2"
      -- page          <- obj .:? "page"
      publication_date   <- obj .:? "publication_date"
      --publication_second <- obj .:? "publication_second"
      --publication_minute <- obj .:? "publication_minute"
      --publication_hour   <- obj .:? "publication_hour"
      publication_day    <- obj .:? "publication_day"
      publication_month  <- obj .:? "publication_month"
      publication_year   <- obj .:? "publication_year"
      source             <- obj .:? "sources"
      institutes         <- obj .:? "institutes"
      title              <- obj .:? "title"
      uniqId             <- obj .:? "uniqId"
274 275
      --url                <- obj .: "url"
      --text               <- obj .: "text"
276 277 278 279 280
      pure $ Document { abstract
                      , authors
                      , bdd
                      , doi
                      , language_iso2
281
                      -- , page
282
                      , publication_date
283 284 285
                      --, publication_second
                      --, publication_minute
                      --, publication_hour
286 287 288 289
                      , publication_day
                      , publication_month
                      , publication_year
                      , source
290
                      , institutes
291 292
                      , title
                      , uniqId
293 294
                      --, url
                      --, text
295 296
                      }

297
docViewSpec :: Spec State Props Action
298
docViewSpec = simpleSpec performAction render
299
  where
300
    performAction :: PerformAction State Props Action
301 302 303 304
    performAction Synchronize {path} state = do
        syncPatches path state
    performAction (SetTermListItem n pl) _ {ngramsVersion} =
        commitPatch (Versioned {version: ngramsVersion, data: pt})
305 306
      where
        pe = NgramsPatch { patch_list: pl, patch_children: mempty }
307
        pt = singletonNgramsTablePatch n pe
308 309
    performAction (AddNewNgram ngram termList) _ {ngramsVersion} =
        commitPatch (Versioned {version: ngramsVersion, data: pt})
310
      where
311
        pt = addNewNgram ngram termList
312

313 314
    render :: Render State Props Action
    render dispatch { loaded: { ngramsTable: Versioned { data: initTable }, document } }
315 316 317
                    { ngramsLocalPatch
                    , ngramsValidPatch
                    }
318 319
                    _reactChildren =
      [ autoUpdateElt { duration: 3000
320
                      , effect:   dispatch Synchronize
321 322 323 324
                      }
      , div [className "container1"]
        [
          div [className "row"]
325
          [
326 327 328 329 330 331 332 333 334 335
            div [className "col-md-8"]
            [ h4 [] [annotate doc.title]
            , ul [className "list-group"]
              [ li' [ span [] [text' doc.source]
                    , badge "source"
                    ]
              -- TODO add href to /author/ if author present in
              , li' [ span [] [text' doc.authors]
                    , badge "authors"
                    ]
336
              , li' [ span [] [text $ publicationDate $ Document doc]
337 338 339 340 341 342 343
                    , badge "date"
                    ]
              ]
            , badge "abstract"
            , annotate doc.abstract
            , div [className "jumbotron"]
              [ p [] [text "Empty Full Text"]
344
              ]
345 346
            ]
          ]
347
        ]
348
      ]
349
        where
350
          ngramsTable = applyNgramsTablePatch (ngramsLocalPatch <> ngramsValidPatch) initTable
351 352
          setTermList ngram Nothing        newList = dispatch $ AddNewNgram ngram newList
          setTermList ngram (Just oldList) newList = dispatch $ SetTermListItem ngram (replace oldList newList)
353
          annotate text = R2.scuff $ AnnotatedField.annotatedField { ngrams: ngramsTable, setTermList, text }
354 355 356
          li' = li [className "list-group-item justify-content-between"]
          text' x = text $ maybe "Nothing" identity x
          badge s = span [className "badge badge-default badge-pill"] [text s]
357 358
          NodePoly {hyperdata : Document doc} = document

359 360
docViewClass :: ReactClass { children :: Children
                           , loaded   :: LoadedData
361 362
                           , path     :: DocPath
                           }
363 364
docViewClass = createClass "DocumentView" docViewSpec initialState

365
type LayoutProps = ( session :: Session, nodeId :: Int, listId :: Int, corpusId :: Maybe Int )
366 367 368 369 370 371

documentLayout :: Record LayoutProps -> R.Element
documentLayout props = R.createElement documentLayoutCpt props []

documentLayoutCpt :: R.Component LayoutProps
documentLayoutCpt = R.hooksComponent "G.P.Corpus.Document.documentLayout" cpt
372
  where
373
    cpt {session, nodeId, listId, corpusId} _ = do
374 375
      useLoader path loadData $ \loaded ->
        R2.createElement' docViewClass {path, loaded} []
376 377
      where
        tabType = TabDocument (TabNgramType CTabTerms)
378
        path = {session, nodeId, listIds: [listId], corpusId, tabType}
379 380 381

------------------------------------------------------------------------

382
loadDocument :: Session -> Int -> Aff NodeDocument
383
loadDocument session nodeId = get session $ NodeAPI Node (Just nodeId) ""
384

385 386
loadData :: DocPath -> Aff LoadedData
loadData {session, nodeId, listIds, tabType} = do
387
  document <- loadDocument session nodeId
388
  ngramsTable <- loadNgramsTable
389
    { session
390
    , nodeId
391
    , listIds
392 393
    , params: { offset : 0, limit : 100, orderBy: Nothing}
    , tabType
394 395 396 397
    , searchQuery: ""
    , termListFilter: Nothing
    , termSizeFilter: Nothing
    , scoreType: Occurrences
398 399
    }
  pure {document, ngramsTable}