Commit b2775d1d authored by arturo's avatar arturo

>>> continue

parent a339e7d9
Pipeline #2530 failed with stage
in 0 seconds
...@@ -3,25 +3,34 @@ module Gargantext.Components.Forest.Tree.Node.Action.Update where ...@@ -3,25 +3,34 @@ module Gargantext.Components.Forest.Tree.Node.Action.Update where
import Gargantext.Components.Forest.Tree.Node.Action.Update.Types import Gargantext.Components.Forest.Tree.Node.Action.Update.Types
import Gargantext.Prelude import Gargantext.Prelude
import DOM.Simple.Console (log) import DOM.Simple.Console (log, log3)
import Data.Array as Array
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Maybe (Maybe(..)) import Data.Int as Int
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Newtype (unwrap)
import Data.Number as Number
import Effect (Effect)
import Effect.Aff (Aff, launchAff, launchAff_) import Effect.Aff (Aff, launchAff, launchAff_)
import Effect.Class (liftEffect) import Effect.Class (liftEffect)
import Gargantext.Components.Bootstrap.Types (ComponentStatus(..)) import Gargantext.Components.Bootstrap.Types (ComponentStatus(..))
import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..)) import Gargantext.Components.Forest.Tree.Node.Action.Types (Action(..))
import Gargantext.Components.Forest.Tree.Node.Tools (formChoiceSafe, submitButton, panel) import Gargantext.Components.Forest.Tree.Node.Tools (formChoiceSafe, submitButton, panel)
import Gargantext.Components.PhyloExplorer.API (Clique(..), CliqueFilter(..), TimeUnit(..), TimeUnitCriteria(..)) import Gargantext.Components.PhyloExplorer.API (Clique(..), CliqueFilter(..), TimeUnit(..), TimeUnitCriteria(..), UpdateData(..), toReflexiveTimeUnit)
import Gargantext.Components.PhyloExplorer.API as Phylo import Gargantext.Components.PhyloExplorer.API as Phylo
import Gargantext.Components.PhyloExplorer.ConfigForm (configForm) import Gargantext.Components.PhyloExplorer.ConfigForm as PhyloForm
import Gargantext.Components.PhyloExplorer.ConfigFormParser (useConfigFormParser)
import Gargantext.Components.PhyloExplorer.ConfigFormParser as PhyloHook
import Gargantext.Config.REST (RESTError, AffRESTError) import Gargantext.Config.REST (RESTError, AffRESTError)
import Gargantext.Routes as GR import Gargantext.Routes as GR
import Gargantext.Sessions (Session, post) import Gargantext.Sessions (Session, post)
import Gargantext.Types (ID, NodeType(..)) import Gargantext.Types (ID, NodeType(..))
import Gargantext.Types as GT import Gargantext.Types as GT
import Gargantext.Utils (getter)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
import Record (merge)
import Toestand as T import Toestand as T
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
...@@ -90,36 +99,51 @@ updatePhylo = R2.leaf updatePhyloCpt ...@@ -90,36 +99,51 @@ updatePhylo = R2.leaf updatePhyloCpt
updatePhyloCpt :: R.Component UpdateProps updatePhyloCpt :: R.Component UpdateProps
updatePhyloCpt = here.component "updatePhylo" cpt where updatePhyloCpt = here.component "updatePhylo" cpt where
cpt { dispatch } _ = do cpt { dispatch } _ = do
-- Behavior -- Hooks
parser <- PhyloHook.useConfigFormParser
-- Helpers
let let
params :: Action
params defaultData :: Phylo.UpdateData
= UpdateNode $ UpdateNodeParamsPhylo defaultData = Phylo.UpdateData
{ methodPhylo: paramsValue
}
paramsValue :: Phylo.UpdateData
paramsValue = Phylo.UpdateData
{ proximity: 0.1 { proximity: 0.1
, synchrony: 0.1 , synchrony: 0.1
, quality: 0.1 , quality: 0.1
, exportFilter: 0.1 , exportFilter: 0.1
, timeUnit: Year $ TimeUnitCriteria , timeUnit: Phylo.Year $ Phylo.TimeUnitCriteria
{ period: 3 { period: 3
, step: 1 , step: 1
, matchingFrame: 5 , matchingFrame: 5
}
, clique: FIS
{ support: 1
, size: 1
} }
, clique: FIS
{ support: 1
, size: 2
}
} }
-- Behaviors
onSubmit :: Record PhyloForm.FormData -> Effect Unit
onSubmit r = case parser.fromFormData r of
Left error -> log3 "[handleFormError]" error r
Right r' -> do
opts <- pure $ options r'
launchAff_ $ dispatch opts
where
options :: Phylo.UpdateData -> Action
options params
= UpdateNode $ UpdateNodeParamsPhylo
{ methodPhylo: params
}
-- Render -- Render
pure $ pure $
configForm PhyloForm.configForm $
{ callback: \_ -> launchAff_ $ dispatch $ params { callback: onSubmit
, status: Enabled , status: Enabled
} } `merge` parser.toFormData defaultData
updateNodeList :: R2.Component UpdateProps updateNodeList :: R2.Component UpdateProps
updateNodeList = R.createElement updateNodeListCpt updateNodeList = R.createElement updateNodeListCpt
......
...@@ -49,6 +49,7 @@ newtype UpdateData = UpdateData ...@@ -49,6 +49,7 @@ newtype UpdateData = UpdateData
derive instance Generic UpdateData _ derive instance Generic UpdateData _
derive instance Eq UpdateData derive instance Eq UpdateData
derive instance Newtype UpdateData _
instance Show UpdateData where show = genericShow instance Show UpdateData where show = genericShow
derive newtype instance JSON.ReadForeign UpdateData derive newtype instance JSON.ReadForeign UpdateData
instance JSON.WriteForeign UpdateData where instance JSON.WriteForeign UpdateData where
......
module Gargantext.Components.PhyloExplorer.ConfigForm module Gargantext.Components.PhyloExplorer.ConfigForm
( configForm ( configForm
, FormData
) where ) where
import Gargantext.Prelude import Gargantext.Prelude
import DOM.Simple.Console (log, log3) import DOM.Simple.Console (log3)
import Data.Either (Either(..)) import Data.Either (Either(..))
import Data.Foldable (foldl, intercalate) import Data.Foldable (intercalate)
import Data.Generic.Rep (class Generic)
import Data.Int as Int
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Newtype (unwrap)
import Data.Number as Number
import Data.Show.Generic (genericShow)
import Effect (Effect) import Effect (Effect)
import Gargantext.Components.Bootstrap as B import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Bootstrap.Types (ButtonVariant(..), ComponentStatus(..), Variant(..)) import Gargantext.Components.Bootstrap.Types (ButtonVariant(..), ComponentStatus(..), Variant(..))
import Gargantext.Components.PhyloExplorer.API (Clique(..), CliqueFilter(..), ReflexiveClique(..), ReflexiveTimeUnit(..), TimeUnit(..), TimeUnitCriteria(..), UpdateData(..), extractCriteria, fromReflexiveTimeUnit, toReflexiveTimeUnit) import Gargantext.Components.PhyloExplorer.API (CliqueFilter(..), ReflexiveClique(..), ReflexiveTimeUnit(..))
import Gargantext.Config.REST (AffRESTError) import Gargantext.Hooks.FormValidation (useFormValidation)
import Gargantext.Hooks.FormValidation (VForm, useFormValidation)
import Gargantext.Hooks.FormValidation.Unboxed as FV
import Gargantext.Hooks.StateRecord (useStateRecord) import Gargantext.Hooks.StateRecord (useStateRecord)
import Gargantext.Hooks.StateRecord.Behaviors (setter) import Gargantext.Hooks.StateRecord.Behaviors (setter)
import Gargantext.Routes as GR import Gargantext.Utils ((?))
import Gargantext.Sessions (Session, post, get)
import Gargantext.Types as GT
import Gargantext.Utils (getter, nbsp, (?))
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
import Record (merge) import Record (merge)
import Record as Record import Record as Record
import Record.Extra (pick) import Record.Extra (pick)
import Toestand as T
import Type.Proxy (Proxy(..))
import Unsafe.Coerce (unsafeCoerce)
type Props = type Props =
( callback :: Record FormData -> Effect Unit ( callback :: Record FormData -> Effect Unit
...@@ -58,11 +45,9 @@ component = R.hooksComponent "configForm" cpt where ...@@ -58,11 +45,9 @@ component = R.hooksComponent "configForm" cpt where
{ state { state
, bindStateKey , bindStateKey
, stateBox , stateBox
, setStateKey } <- useStateRecord (pick props :: Record FormData)
} <- useStateRecord $ parseFormData (pick props :: Record FormData)
fv <- useFormValidation
R.useEffect1' state $ log state fv <- useFormValidation
-- Behaviors -- Behaviors
let let
...@@ -74,7 +59,7 @@ component = R.hooksComponent "configForm" cpt where ...@@ -74,7 +59,7 @@ component = R.hooksComponent "configForm" cpt where
result <- pure $ Right state result <- pure $ Right state
case result of case result of
Left err -> log3 "configForm validation error" state err Left err -> log3 "configForm validation error" state err
Right _ -> props.callback $ parseRawData state Right _ -> props.callback state
-- Render -- Render
...@@ -376,7 +361,7 @@ component = R.hooksComponent "configForm" cpt where ...@@ -376,7 +361,7 @@ component = R.hooksComponent "configForm" cpt where
} }
[ [
B.button B.button
{ callback: \_ -> setter stateBox "cliqueType" FIS_ { callback: \_ -> setter stateBox "cliqueType" $ show FIS_
, variant: OutlinedButtonVariant Secondary , variant: OutlinedButtonVariant Secondary
, className: state.cliqueType == show FIS_ ? , className: state.cliqueType == show FIS_ ?
"active" $ "active" $
...@@ -387,7 +372,7 @@ component = R.hooksComponent "configForm" cpt where ...@@ -387,7 +372,7 @@ component = R.hooksComponent "configForm" cpt where
] ]
, ,
B.button B.button
{ callback: \_ -> setter stateBox "cliqueType" MaxClique_ { callback: \_ -> setter stateBox "cliqueType" $ show MaxClique_
, variant: OutlinedButtonVariant Secondary , variant: OutlinedButtonVariant Secondary
, className: state.cliqueType == show MaxClique_ ? , className: state.cliqueType == show MaxClique_ ?
"active" $ "active" $
...@@ -401,7 +386,7 @@ component = R.hooksComponent "configForm" cpt where ...@@ -401,7 +386,7 @@ component = R.hooksComponent "configForm" cpt where
] ]
, ,
-- TYPE::FIS_ -- TYPE::FIS_
R2.if' (state.cliqueType == show FIS_) $R.fragment R2.if' (state.cliqueType == show FIS_) $ R.fragment
[ [
-- Support -- Support
H.div H.div
...@@ -467,7 +452,7 @@ component = R.hooksComponent "configForm" cpt where ...@@ -467,7 +452,7 @@ component = R.hooksComponent "configForm" cpt where
] ]
, ,
-- TYPE::MaxClique_ -- TYPE::MaxClique_
R2.if' (state.cliqueType == show MaxClique_) $R.fragment R2.if' (state.cliqueType == show MaxClique_) $ R.fragment
[ [
-- Size -- Size
H.div H.div
...@@ -579,49 +564,8 @@ component = R.hooksComponent "configForm" cpt where ...@@ -579,49 +564,8 @@ component = R.hooksComponent "configForm" cpt where
] ]
] ]
type FormData =
( proximity :: Number
, synchrony :: Number
, quality :: Number
, exportFilter :: Number
-- TimeUnit
, timeUnit :: TimeUnit
-- Clique
type FormData =
-- , cliqueType :: ReflexiveClique
-- , support :: Int
-- , size :: Int
-- , threshold :: Number
-- , cliqueFilter :: CliqueFilter
, clique :: Clique
)
defaultData :: Record FormData
defaultData =
{ proximity: 0.1
, synchrony: 0.1
, quality: 0.1
, exportFilter: 0.1
-- TimeUnit
, timeUnit: Year $ TimeUnitCriteria
{ period: 3
, step: 1
, matchingFrame: 5
}
-- Clique
-- , cliqueType: FIS_
-- , support: 1
-- , size: 1
-- , threshold: 0.5
-- , cliqueFilter: ByThreshold
, clique: FIS
{ support: 1
, size: 1
}
}
type RawData =
( proximity :: String ( proximity :: String
, synchrony :: String , synchrony :: String
, quality :: String , quality :: String
...@@ -639,116 +583,22 @@ type RawData = ...@@ -639,116 +583,22 @@ type RawData =
, cliqueFilter :: String , cliqueFilter :: String
) )
-- (?) due to `Clique` multi constructors nature, we have to relying on a defaultData :: Record FormData
-- set of default data for every constructor property defaultData =
defaultCliqueData :: { proximity : ""
{ cliqueType :: String , synchrony : ""
, support :: String , quality : ""
, size :: String , exportFilter : ""
, threshold :: String , granularity : ""
, cliqueFilter :: String , period : ""
} , step : ""
defaultCliqueData = , matchingFrame : ""
{ cliqueType: "FIS_" , cliqueType : show FIS_
, support: "1" , support : ""
, size: "1" , size : ""
, threshold: "0.5" , threshold : ""
, cliqueFilter: "ByThreshold" , cliqueFilter : show ByThreshold
}
parseFormData :: Record FormData -> Record RawData
parseFormData { proximity
, synchrony
, quality
, exportFilter
, timeUnit
, clique
}
= { proximity: show proximity
, synchrony: show synchrony
, quality: show quality
, exportFilter: show exportFilter
-- Time unit
, granularity: timeUnit #
(show <<< toReflexiveTimeUnit)
, period: timeUnit #
(show <<< getter _.period <<< extractCriteria)
, step: timeUnit #
(show <<< getter _.step <<< extractCriteria)
, matchingFrame: timeUnit #
(show <<< getter _.matchingFrame <<< extractCriteria)
-- Clique
} `merge` (parseClique clique)
where
parseClique :: Clique ->
{ cliqueType :: String
, support :: String
, size :: String
, threshold :: String
, cliqueFilter :: String
}
parseClique (FIS o) =
{ support: show o.support
, size: show o.size
} `merge` defaultCliqueData
parseClique (MaxClique o) =
{ size: show o.size
, threshold: show o.threshold
, cliqueFilter: show o.filter
} `merge` defaultCliqueData
parseRawData :: Record RawData -> Record FormData
parseRawData raw@{ proximity
, synchrony
, quality
, exportFilter
, granularity
, period
, step
, matchingFrame
}
= { proximity: fromMaybe 0.0 (Number.fromString proximity)
, synchrony: fromMaybe 0.0 (Number.fromString synchrony)
, quality: fromMaybe 0.0 (Number.fromString quality)
, exportFilter: fromMaybe 0.0 (Number.fromString exportFilter)
-- Time unit
, timeUnit: parseTimeUnit
(parseCriteria period step matchingFrame)
granularity
-- Clique
, clique: parseClique raw raw.cliqueType
} }
where
parseCriteria :: String -> String -> String -> TimeUnitCriteria
parseCriteria a b c = TimeUnitCriteria
{ period : fromMaybe 0 (Int.fromString a)
, step : fromMaybe 0 (Int.fromString b)
, matchingFrame: fromMaybe 0 (Int.fromString c)
}
parseTimeUnit :: TimeUnitCriteria -> String -> TimeUnit
parseTimeUnit criteria = read >>> case _ of
Nothing -> Year criteria
Just (r :: ReflexiveTimeUnit) -> fromReflexiveTimeUnit r criteria
parseClique :: Record RawData -> String -> Clique
parseClique o = read >>> case _ of
Nothing -> FIS
{ support: 1
, size: 1
}
Just (r :: ReflexiveClique) -> case r of
FIS_ -> FIS
{ support: fromMaybe 0 (Int.fromString o.support)
, size: fromMaybe 0 (Int.fromString o.size)
}
MaxClique_ -> MaxClique
{ size: fromMaybe 0 (Int.fromString o.support)
, threshold: fromMaybe 0.0 (Number.fromString o.threshold)
, filter: fromMaybe ByThreshold (read o.cliqueFilter)
}
-- formValidation :: Record FormData -> Effect VForm -- formValidation :: Record FormData -> Effect VForm
-- formValidation r = foldl append mempty rules -- formValidation r = foldl append mempty rules
......
module Gargantext.Components.PhyloExplorer.ConfigFormParser
( useConfigFormParser
) where
import Gargantext.Prelude
import Data.Either (Either(..))
import Data.Int as Int
import Data.Maybe (Maybe(..))
import Data.Newtype (unwrap)
import Data.Number as Number
import Gargantext.Components.PhyloExplorer.API (Clique(..), CliqueFilter, ReflexiveClique(..), ReflexiveTimeUnit, TimeUnitCriteria(..), UpdateData(..), extractCriteria, fromReflexiveTimeUnit, toReflexiveTimeUnit)
import Gargantext.Components.PhyloExplorer.ConfigForm (FormData)
import Gargantext.Types (FrontendError(..))
import Gargantext.Utils (getter)
import Reactix as R
import Record (merge)
import Unsafe.Coerce (unsafeCoerce)
type Methods =
-- | Parse `PhyloExplorer.API.UpdateData` to hydrate optional properties of
-- | `ConfigForm.FormData`
-- |
-- | (!) I/O as `UpdateData` type can be changed to anything, it has been
-- | chosen this way for simplification (KISS choice: API ⟷ FormData)
( toFormData :: UpdateData -> Record ()
-- | Parse callback returned data from `ConfigForm.FormData` into the
-- | `PhyloExplorer.API.UpdateData`
, fromFormData :: Record FormData -> Either FrontendError UpdateData
)
useConfigFormParser :: R.Hooks (Record Methods)
useConfigFormParser = do
let
castError ::
Either String UpdateData
-> Either FrontendError UpdateData
castError (Left error) = Left $ FOtherError { error }
castError (Right a) = pure a
pure
{ toFormData
, fromFormData: (_ # fromFormData) >>> castError
}
toFormData :: UpdateData -> Record ()
toFormData nt =
let r = unwrap nt
in unsafeCoerce $
{ proximity:
show r.proximity
, synchrony:
show r.synchrony
, quality:
show r.quality
, exportFilter:
show r.exportFilter
-- Time unit
, granularity: r #
(show <<< toReflexiveTimeUnit <<< _.timeUnit)
, period: r #
(show <<< getter _.period <<< extractCriteria <<< _.timeUnit)
, step: r #
(show <<< getter _.step <<< extractCriteria <<< _.timeUnit)
, matchingFrame: r #
(show <<< getter _.matchingFrame <<< extractCriteria <<< _.timeUnit)
-- Clique
} `merge` parseClique r.clique
where
parseClique :: Clique -> Record ()
parseClique (FIS o) = unsafeCoerce $
{ support : show o.support
, size : show o.size
, cliqueType : show FIS_
}
parseClique (MaxClique o) = unsafeCoerce $
{ size : show o.size
, threshold : show o.threshold
, cliqueFilter: show o.filter
, cliqueType : show MaxClique_
}
fromFormData :: Record FormData -> Either String UpdateData
fromFormData r = do
-- Common params
proximity <-
Number.fromString r.proximity `orDie` "Invalid proximity"
synchrony <-
Number.fromString r.synchrony `orDie` "Invalid synchrony"
quality <-
Number.fromString r.quality `orDie` "Invalid quality"
exportFilter <-
Number.fromString r.exportFilter `orDie` "Invalid exportFilter"
-- Time unit params
(granularity :: ReflexiveTimeUnit) <-
read r.granularity `orDie` "Invalid granularity"
period <-
Int.fromString r.period `orDie` "Invalid period"
step <-
Int.fromString r.step `orDie` "Invalid step"
matchingFrame <-
Int.fromString r.matchingFrame `orDie` "Invalid matchingFrame"
criteria <- pure $
parseCriteria period step matchingFrame
timeUnit <- pure $
fromReflexiveTimeUnit granularity criteria
-- Clique params
(cliqueType :: ReflexiveClique) <-
read r.cliqueType `orDie` "Invalid cliqueType"
clique <-
parseClique r cliqueType
-- Constructor
pure $ UpdateData
{ proximity
, synchrony
, quality
, exportFilter
, timeUnit
, clique
}
where
parseCriteria :: Int -> Int -> Int -> TimeUnitCriteria
parseCriteria period step matchingFrame = TimeUnitCriteria
{ period
, step
, matchingFrame
}
parseClique ::
Record FormData
-> ReflexiveClique
-> Either String Clique
parseClique o = case _ of
FIS_ -> ado
support <-
Int.fromString o.support `orDie` "Invalid support"
size <-
Int.fromString o.size `orDie` "Invalid size"
in
FIS { support, size }
MaxClique_ -> ado
size <-
Int.fromString o.size `orDie` "Invalid size"
threshold <-
Number.fromString o.threshold `orDie` "Invalid threshold"
(filter :: CliqueFilter) <-
read o.cliqueFilter `orDie` "Invalid cliqueFilter"
in
MaxClique { size, threshold, filter }
orDie :: forall err a. Maybe a -> err -> Either err a
orDie (Just a) _ = pure a
orDie Nothing err = Left err
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment