Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
purescript-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
152
Issues
152
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
purescript-gargantext
Commits
b2775d1d
Commit
b2775d1d
authored
Mar 02, 2022
by
arturo
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
>>> continue
parent
a339e7d9
Pipeline
#2530
failed with stage
in 0 seconds
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
237 additions
and
202 deletions
+237
-202
Update.purs
...Gargantext/Components/Forest/Tree/Node/Action/Update.purs
+47
-23
API.purs
src/Gargantext/Components/PhyloExplorer/API.purs
+1
-0
ConfigForm.purs
src/Gargantext/Components/PhyloExplorer/ConfigForm.purs
+29
-179
ConfigFormContainer.purs
...gantext/Components/PhyloExplorer/ConfigFormContainer.purs
+160
-0
No files found.
src/Gargantext/Components/Forest/Tree/Node/Action/Update.purs
View file @
b2775d1d
...
@@ -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
...
...
src/Gargantext/Components/PhyloExplorer/API.purs
View file @
b2775d1d
...
@@ -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
...
...
src/Gargantext/Components/PhyloExplorer/ConfigForm.purs
View file @
b2775d1d
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
, log
3)
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
...
...
src/Gargantext/Components/PhyloExplorer/ConfigFormContainer.purs
0 → 100644
View file @
b2775d1d
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
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment