Commit c7304e4d authored by Przemyslaw Kaminski's avatar Przemyslaw Kaminski

[purty] purty-fied the whole src tree

Also, added 'yarn purty-format' command.
parent e2a6b681
...@@ -8,7 +8,8 @@ ...@@ -8,7 +8,8 @@
"sass": "sass dist/styles/", "sass": "sass dist/styles/",
"dev": "webpack-dev-server --env dev --mode development", "dev": "webpack-dev-server --env dev --mode development",
"repl": "pulp --psc-package repl", "repl": "pulp --psc-package repl",
"clean": "rm -Rf output" "clean": "rm -Rf output",
"purty-format": "find src -iname '*.purs' -exec yarn run purty {} --write \\;"
}, },
"dependencies": { "dependencies": {
"@babel/polyfill": "^7.0.0", "@babel/polyfill": "^7.0.0",
...@@ -17,8 +18,10 @@ ...@@ -17,8 +18,10 @@
"echarts": "^4.1.0", "echarts": "^4.1.0",
"echarts-for-react": "^2.0.14", "echarts-for-react": "^2.0.14",
"prop-types": "15.6.2", "prop-types": "15.6.2",
"purty": "^4.5.1",
"react": "^16.10", "react": "^16.10",
"react-dom": "^16.10", "react-dom": "^16.10",
"sass": "^1.22.9",
"sigma": "git://github.com/jjl/sigma.js#garg" "sigma": "git://github.com/jjl/sigma.js#garg"
}, },
"eslintConfig": { "eslintConfig": {
......
module Gargantext.BootstrapNative where module Gargantext.BootstrapNative where
import Effect (Effect) import Effect (Effect)
import Gargantext.Prelude import Gargantext.Prelude
foreign import createDropdown :: String -> Effect Unit foreign import createDropdown :: String -> Effect Unit
...@@ -12,61 +12,64 @@ ...@@ -12,61 +12,64 @@
module Gargantext.Components.Annotation.AnnotatedField where module Gargantext.Components.Annotation.AnnotatedField where
import Prelude import Prelude
import Data.Maybe ( Maybe(..), maybe ) import Data.Maybe (Maybe(..), maybe)
import Data.Tuple ( Tuple(..) ) import Data.Tuple (Tuple(..))
import Data.Tuple.Nested ( (/\) ) import Data.Tuple.Nested ((/\))
import DOM.Simple.Event as DE import DOM.Simple.Event as DE
import Effect ( Effect ) import Effect (Effect)
import Effect.Uncurried ( mkEffectFn1 ) import Effect.Uncurried (mkEffectFn1)
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as HTML import Reactix.DOM.HTML as HTML
import Reactix.SyntheticEvent as E import Reactix.SyntheticEvent as E
import Gargantext.Types (CTabNgramType(..), TermList) import Gargantext.Types (CTabNgramType(..), TermList)
import Gargantext.Components.Annotation.Utils ( termBootstrapClass ) import Gargantext.Components.Annotation.Utils (termBootstrapClass)
import Gargantext.Components.NgramsTable.Core (NgramsTable, NgramsTerm, findNgramTermList, highlightNgrams) import Gargantext.Components.NgramsTable.Core (NgramsTable, NgramsTerm, findNgramTermList, highlightNgrams)
import Gargantext.Components.Annotation.Menu ( AnnotationMenu, annotationMenu, MenuType(..) ) import Gargantext.Components.Annotation.Menu (AnnotationMenu, annotationMenu, MenuType(..))
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Selection as Sel import Gargantext.Utils.Selection as Sel
type Props = type Props
( ngrams :: NgramsTable = ( ngrams :: NgramsTable
, setTermList :: NgramsTerm -> Maybe TermList -> TermList -> Effect Unit , setTermList :: NgramsTerm -> Maybe TermList -> TermList -> Effect Unit
, text :: Maybe String , text :: Maybe String
) )
type MouseEvent = E.SyntheticEvent DE.MouseEvent
type MouseEvent
= E.SyntheticEvent DE.MouseEvent
-- UNUSED -- UNUSED
-- defaultProps :: Record Props -- defaultProps :: Record Props
-- defaultProps = { ngrams: NgramsTable Map.empty, text: Nothing, setTermList: \_ _ _ -> pure unit } -- defaultProps = { ngrams: NgramsTable Map.empty, text: Nothing, setTermList: \_ _ _ -> pure unit }
annotatedField :: Record Props -> R.Element annotatedField :: Record Props -> R.Element
annotatedField p = R.createElement annotatedFieldComponent p [] annotatedField p = R.createElement annotatedFieldComponent p []
annotatedFieldComponent :: R.Component Props annotatedFieldComponent :: R.Component Props
annotatedFieldComponent = R.hooksComponent "AnnotatedField" cpt annotatedFieldComponent = R.hooksComponent "AnnotatedField" cpt
where where
cpt {ngrams,setTermList,text} _ = do cpt { ngrams, setTermList, text } _ = do
menu /\ setMenu <- R.useState $ const Nothing menu /\ setMenu <- R.useState $ const Nothing
let wrapperProps = let
{ className: "annotated-field-wrapper" } wrapperProps = { className: "annotated-field-wrapper" }
onSelect _ Nothing event = maybeShowMenu setMenu setTermList ngrams event
onSelect _ Nothing event = maybeShowMenu setMenu setTermList ngrams event onSelect text' (Just list) event = do
onSelect text' (Just list) event = do let
let x = E.clientX event x = E.clientX event
y = E.clientY event
setList t = do
setTermList text' (Just list) t
setMenu (const Nothing)
setMenu (const $ Just {x, y, list: Just list, menuType: SetTermListItem, setList} )
mapCompile (Tuple t l) = {text: t, list: l, onSelect} y = E.clientY event
compiled = map mapCompile $ compile ngrams text
runs = setList t = do
HTML.div { className: "annotated-field-runs" } $ map annotateRun compiled setTermList text' (Just list) t
pure $ HTML.div wrapperProps [maybeAddMenu setMenu runs menu] setMenu (const Nothing)
setMenu (const $ Just { x, y, list: Just list, menuType: SetTermListItem, setList })
mapCompile (Tuple t l) = { text: t, list: l, onSelect }
compiled = map mapCompile $ compile ngrams text
runs = HTML.div { className: "annotated-field-runs" } $ map annotateRun compiled
pure $ HTML.div wrapperProps [ maybeAddMenu setMenu runs menu ]
-- forall e. IsMouseEvent e => R2.Setter (Maybe AnnotationMenu) -> R2.Setter ? -> ? -> e -> Effect Unit -- forall e. IsMouseEvent e => R2.Setter (Maybe AnnotationMenu) -> R2.Setter ? -> ? -> e -> Effect Unit
maybeShowMenu setMenu setTermList ngrams event = do maybeShowMenu setMenu setTermList ngrams event = do
...@@ -76,34 +79,38 @@ maybeShowMenu setMenu setTermList ngrams event = do ...@@ -76,34 +79,38 @@ maybeShowMenu setMenu setTermList ngrams event = do
case Sel.selectionToString sel of case Sel.selectionToString sel of
"" -> pure unit "" -> pure unit
sel' -> do sel' -> do
let x = E.clientX event let
y = E.clientY event x = E.clientX event
list = findNgramTermList CTabTerms ngrams sel'
setList t = do y = E.clientY event
setTermList sel' list t
setMenu (const Nothing) list = findNgramTermList CTabTerms ngrams sel'
setList t = do
setTermList sel' list t
setMenu (const Nothing)
E.preventDefault event E.preventDefault event
setMenu (const $ Just { x, y, list, menuType: NewNgram, setList }) setMenu (const $ Just { x, y, list, menuType: NewNgram, setList })
Nothing -> pure unit Nothing -> pure unit
maybeAddMenu maybeAddMenu ::
:: R2.Setter (Maybe AnnotationMenu) R2.Setter (Maybe AnnotationMenu) ->
-> R.Element R.Element ->
-> Maybe AnnotationMenu Maybe AnnotationMenu ->
-> R.Element R.Element
maybeAddMenu setMenu e (Just props) = annotationMenu setMenu props <> e maybeAddMenu setMenu e (Just props) = annotationMenu setMenu props <> e
maybeAddMenu _ e _ = e maybeAddMenu _ e _ = e
compile :: NgramsTable -> Maybe String -> Array (Tuple String (Maybe TermList)) compile :: NgramsTable -> Maybe String -> Array (Tuple String (Maybe TermList))
compile ngrams = maybe [] (highlightNgrams CTabTerms ngrams) compile ngrams = maybe [] (highlightNgrams CTabTerms ngrams)
-- Runs -- Runs
type Run
type Run = = ( text :: String
( text :: String , list :: (Maybe TermList)
, list :: (Maybe TermList) , onSelect :: String -> Maybe TermList -> MouseEvent -> Effect Unit
, onSelect :: String -> Maybe TermList -> MouseEvent -> Effect Unit )
)
annotateRun :: Record Run -> R.Element annotateRun :: Record Run -> R.Element
annotateRun p = R.createElement annotatedRunComponent p [] annotateRun p = R.createElement annotatedRunComponent p []
...@@ -111,13 +118,13 @@ annotateRun p = R.createElement annotatedRunComponent p [] ...@@ -111,13 +118,13 @@ annotateRun p = R.createElement annotatedRunComponent p []
annotatedRunComponent :: R.Component Run annotatedRunComponent :: R.Component Run
annotatedRunComponent = R.staticComponent "AnnotatedRun" cpt annotatedRunComponent = R.staticComponent "AnnotatedRun" cpt
where where
cpt { text, list: Nothing, onSelect } _ = cpt { text, list: Nothing, onSelect } _ = HTML.span { onMouseUp: mkEffectFn1 $ \e -> onSelect text Nothing e } [ HTML.text text ]
HTML.span { onMouseUp: mkEffectFn1 $ \e -> onSelect text Nothing e } [ HTML.text text ]
cpt { text, list: (Just list), onSelect } _ =
cpt { text, list: (Just list), onSelect } _ = HTML.span
HTML.span { className: className list { className: className list
, onClick: mkEffectFn1 $ \e -> onSelect text (Just list) e} [ HTML.text text ] , onClick: mkEffectFn1 $ \e -> onSelect text (Just list) e
where }
className list' = "annotation-run bg-" <> termBootstrapClass list' [ HTML.text text ]
where
className list' = "annotation-run bg-" <> termBootstrapClass list'
-- | A ContextMenU that allows you to add terms to a list -- | A ContextMenU that allows you to add terms to a list
module Gargantext.Components.Annotation.Menu where module Gargantext.Components.Annotation.Menu where
import Prelude (Unit, pure, ($), (<>), (==)) import Prelude (Unit, pure, ($), (<>), (==))
import Data.Array as A import Data.Array as A
import Data.Maybe (Maybe(..)) import Data.Maybe (Maybe(..))
...@@ -9,45 +8,52 @@ import Effect (Effect) ...@@ -9,45 +8,52 @@ import Effect (Effect)
import Effect.Uncurried (mkEffectFn1) import Effect.Uncurried (mkEffectFn1)
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as HTML import Reactix.DOM.HTML as HTML
import Gargantext.Types (TermList(..), termListName) import Gargantext.Types (TermList(..), termListName)
import Gargantext.Components.Annotation.Utils (termBootstrapClass) import Gargantext.Components.Annotation.Utils (termBootstrapClass)
import Gargantext.Components.ContextMenu.ContextMenu as CM import Gargantext.Components.ContextMenu.ContextMenu as CM
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
data MenuType = NewNgram | SetTermListItem data MenuType
= NewNgram
| SetTermListItem
type Props = type Props
( list :: Maybe TermList = ( list :: Maybe TermList
, menuType :: MenuType , menuType :: MenuType
, setList :: TermList -> Effect Unit -- not a state hook setter , setList :: TermList -> Effect Unit -- not a state hook setter
) )
type AnnotationMenu = { x :: Number, y :: Number | Props } type AnnotationMenu
= { x :: Number, y :: Number | Props }
-- | An Annotation Menu is parameterised by a Maybe Termlist of the -- | An Annotation Menu is parameterised by a Maybe Termlist of the
-- | TermList the currently selected text belongs to -- | TermList the currently selected text belongs to
annotationMenu :: R2.Setter (Maybe AnnotationMenu) -> AnnotationMenu -> R.Element annotationMenu :: R2.Setter (Maybe AnnotationMenu) -> AnnotationMenu -> R.Element
annotationMenu setMenu { x,y,list,menuType,setList } = annotationMenu setMenu { x, y, list, menuType, setList } =
CM.contextMenu { x,y,setMenu } [ CM.contextMenu { x, y, setMenu }
R.createElement annotationMenuCpt {list,menuType,setList} [] [ R.createElement annotationMenuCpt { list, menuType, setList } []
] ]
annotationMenuCpt :: R.Component Props annotationMenuCpt :: R.Component Props
annotationMenuCpt = R.hooksComponent "Annotation.Menu" cpt annotationMenuCpt = R.hooksComponent "Annotation.Menu" cpt
where where
cpt props _ = pure $ R.fragment $ children props cpt props _ = pure $ R.fragment $ children props
children props = A.mapMaybe (addToList props) [ GraphTerm, CandidateTerm, StopTerm ]
children props = A.mapMaybe (addToList props) [ GraphTerm, CandidateTerm, StopTerm ]
-- | Given the TermList to render the item for zand the Maybe TermList the item may belong to, possibly render the menuItem -- | Given the TermList to render the item for zand the Maybe TermList the item may belong to, possibly render the menuItem
addToList :: Record Props -> TermList -> Maybe R.Element addToList :: Record Props -> TermList -> Maybe R.Element
addToList {list: Just t'} t addToList { list: Just t' } t
| t == t' = Nothing | t == t' = Nothing
addToList {menuType, setList} t = Just $ CM.contextMenuItem [ link ]
addToList { menuType, setList } t = Just $ CM.contextMenuItem [ link ]
where where
link = HTML.a { onClick: click, className: className } [ HTML.text (label menuType) ] link = HTML.a { onClick: click, className: className } [ HTML.text (label menuType) ]
label NewNgram = "Add to " <> termListName t
label SetTermListItem = "Change to " <> termListName t label NewNgram = "Add to " <> termListName t
className = "list-group-item list-group-item-" <> (termBootstrapClass t)
click = mkEffectFn1 $ \_ -> setList t label SetTermListItem = "Change to " <> termListName t
className = "list-group-item list-group-item-" <> (termBootstrapClass t)
click = mkEffectFn1 $ \_ -> setList t
module Gargantext.Components.Annotation.Utils where module Gargantext.Components.Annotation.Utils where
import Gargantext.Types ( TermList(..) ) import Gargantext.Types (TermList(..))
termClass :: TermList -> String termClass :: TermList -> String
termClass GraphTerm = "graph-term" termClass GraphTerm = "graph-term"
termClass StopTerm = "stop-term" termClass StopTerm = "stop-term"
termClass CandidateTerm = "candidate-term" termClass CandidateTerm = "candidate-term"
termBootstrapClass :: TermList -> String termBootstrapClass :: TermList -> String
termBootstrapClass GraphTerm = "success" termBootstrapClass GraphTerm = "success"
termBootstrapClass StopTerm = "danger" termBootstrapClass StopTerm = "danger"
termBootstrapClass CandidateTerm = "warning" termBootstrapClass CandidateTerm = "warning"
This diff is collapsed.
...@@ -9,31 +9,38 @@ import Gargantext.Prelude ...@@ -9,31 +9,38 @@ import Gargantext.Prelude
import Effect (Effect) import Effect (Effect)
import Effect.Timer (IntervalId, setInterval, clearInterval) import Effect.Timer (IntervalId, setInterval, clearInterval)
data Action = Update data Action
= Update
type PropsRow = type PropsRow
( duration :: Int = ( duration :: Int
, effect :: Effect Unit , effect :: Effect Unit
) )
type Props = { | PropsRow } type Props
= { | PropsRow }
type State = { intervalId :: Maybe IntervalId } type State
= { intervalId :: Maybe IntervalId }
autoUpdateClass :: ReactClass { children :: Children | PropsRow } autoUpdateClass :: ReactClass { children :: Children | PropsRow }
autoUpdateClass = autoUpdateClass =
React.component "AutoUpdate" React.component "AutoUpdate"
(\this -> do ( \this -> do
pure { state: {intervalId: Nothing} pure
, render: pure $ div' [] { state: { intervalId: Nothing }
, componentDidMount: do , render: pure $ div' []
{duration,effect} <- React.getProps this , componentDidMount:
intervalId <- setInterval duration effect do
React.setState this {intervalId: Just intervalId} { duration, effect } <- React.getProps this
, componentWillUnmount: do intervalId <- setInterval duration effect
{intervalId} <- React.getState this React.setState this { intervalId: Just intervalId }
traverse_ clearInterval intervalId , componentWillUnmount:
}) do
{ intervalId } <- React.getState this
traverse_ clearInterval intervalId
}
)
autoUpdateElt :: Props -> ReactElement autoUpdateElt :: Props -> ReactElement
autoUpdateElt props = React.createElement autoUpdateClass props [] autoUpdateElt props = React.createElement autoUpdateClass props []
module Gargantext.Components.Charts.Options.Color module Gargantext.Components.Charts.Options.Color
( Color ( Color
, stringColor , stringColor
, cssColor , cssColor
, transparent , transparent
, red , red
, blue , blue
, magenta , magenta
, violet , violet
, black , black
, grey , grey
, green , green
) where ) where
import Prelude import Prelude
import CSS as CSS import CSS as CSS
import Color (rgba) import Color (rgba)
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
...@@ -34,8 +33,8 @@ red = stringColor "red" ...@@ -34,8 +33,8 @@ red = stringColor "red"
blue :: Color blue :: Color
blue = cssColor $ rgba 100 150 200 0.0 blue = cssColor $ rgba 100 150 200 0.0
-- stringColor "blue"
-- stringColor "blue"
magenta :: Color magenta :: Color
magenta = stringColor "magenta" magenta = stringColor "magenta"
......
...@@ -5,43 +5,48 @@ import Unsafe.Coerce (unsafeCoerce) ...@@ -5,43 +5,48 @@ import Unsafe.Coerce (unsafeCoerce)
import Gargantext.Types (class Optional) import Gargantext.Types (class Optional)
import Gargantext.Components.Charts.Options.Font (TextStyle, Icon, ItemStyle) import Gargantext.Components.Charts.Options.Font (TextStyle, Icon, ItemStyle)
type DataLegend = type DataLegend
{ name :: String = { name :: String
, icon :: Icon , icon :: Icon
, textStyle :: TextStyle , textStyle :: TextStyle
} }
type DataAxis
= Array String
type DataAxis = Array String {- value :: String
{- value :: String
, textStyle :: TextStyle , textStyle :: TextStyle
-} -}
type RequiredData v o
type RequiredData v o = = { value :: v
{ value :: v | o
| o }
}
type OptionalData
type OptionalData = = ( name :: String
( name :: String , symbolSize :: Number
, symbolSize :: Number , itemStyle :: ItemStyle
, itemStyle :: ItemStyle
-- ^ the style setting about single data point(bubble). -- ^ the style setting about single data point(bubble).
, label :: { show :: Boolean } , label :: { show :: Boolean }
) )
type DataSerie v = RequiredData v OptionalData type DataSerie v
= RequiredData v OptionalData
dataSerie :: forall v o. Optional o OptionalData => RequiredData v o -> DataSerie v dataSerie :: forall v o. Optional o OptionalData => RequiredData v o -> DataSerie v
dataSerie = unsafeCoerce dataSerie = unsafeCoerce
dataSerieV :: forall v. v -> DataSerie v dataSerieV :: forall v. v -> DataSerie v
dataSerieV value = dataSerie {value} dataSerieV value = dataSerie { value }
type DataD1
= DataSerie Number
type DataD1 = DataSerie Number type DataD2
type DataD2 = DataSerie (Array Number) = DataSerie (Array Number)
dataD1 :: forall o. Optional o OptionalData => Record o -> Number -> DataD1 dataD1 :: forall o. Optional o OptionalData => Record o -> Number -> DataD1
dataD1 o x = unsafeCoerce (unsafeSet "value" x o) dataD1 o x = unsafeCoerce (unsafeSet "value" x o)
dataD2 :: forall o. Optional o OptionalData => Record o -> Number -> Number -> DataD2 dataD2 :: forall o. Optional o OptionalData => Record o -> Number -> Number -> DataD2
dataD2 o x y = unsafeCoerce (unsafeSet "value" [x,y] o) dataD2 o x y = unsafeCoerce (unsafeSet "value" [ x, y ] o)
module Gargantext.Components.Charts.Options.ECharts where module Gargantext.Components.Charts.Options.ECharts where
import Prelude import Prelude
import CSS (italic) import CSS (italic)
import CSS.Common (normal) import CSS.Common (normal)
import Gargantext.Components.Charts.Options.Color (transparent, violet, black) import Gargantext.Components.Charts.Options.Color (transparent, violet, black)
...@@ -24,189 +23,201 @@ chart = echarts <<< chartWith <<< opts ...@@ -24,189 +23,201 @@ chart = echarts <<< chartWith <<< opts
chartWith :: Option -> Echarts chartWith :: Option -> Echarts
chartWith option = chartWith option =
{ option { option
--, className : Nothing --, className : Nothing
--, style : Nothing --, style : Nothing
--, theme : Nothing --, theme : Nothing
--, group : Nothing --, group : Nothing
--, initOpts : Nothing --, initOpts : Nothing
--, notMerge : Nothing --, notMerge : Nothing
--, lazyUpdate: Nothing --, lazyUpdate: Nothing
--, loading : Nothing --, loading : Nothing
--, optsLoading: Nothing --, optsLoading: Nothing
--, onReady : Nothing --, onReady : Nothing
--, resizable : Nothing --, resizable : Nothing
--, onEvents : Nothing --, onEvents : Nothing
} }
echarts :: Echarts -> R.Element echarts :: Echarts -> R.Element
echarts c = R2.buff $ unsafeCreateElementDynamic (unsafeCoerce eChartsClass) c [] echarts c = R2.buff $ unsafeCreateElementDynamic (unsafeCoerce eChartsClass) c []
type MainTitle = String type MainTitle
type SubTitle = String = String
type SubTitle
= String
title :: MainTitle -> SubTitle -> Title title :: MainTitle -> SubTitle -> Title
title mainTitle subTitle = title mainTitle subTitle =
{ { id: ""
id: "" , show: true
,show: true , text: mainTitle
,text: mainTitle , link: ""
,link: "" , target: "blank"
,target: "blank" , textStyle: textStyle
,textStyle: textStyle , subtext: subTitle
,subtext: subTitle , sublink: ""
,sublink: "" , subtarget: "blank"
,subtarget: "blank" , subtextStyle: textStyle2
,subtextStyle: textStyle2 , padding: 10.0
,padding: 10.0 , itemGap: 0.0
,itemGap: 0.0 , zlevel: 2.0
,zlevel: 2.0 , z: 2.0
,z: 2.0 , left: relativePosition (Relative RightPos)
,left: relativePosition (Relative RightPos) , top: relativePosition (Relative Top)
,top: relativePosition (Relative Top) , right: numberPosition 60.0
,right: numberPosition 60.0 , bottom: percentPosition 40.0
,bottom: percentPosition 40.0 , backgroundColor: transparent
,backgroundColor: transparent , borderColor: transparent
,borderColor: transparent , borderWidth: 0.0
,borderWidth: 0.0 , borderRadius: 0.0
,borderRadius: 0.0 , shadowBlur: 0.0
,shadowBlur: 0.0 , shadowColor: transparent
,shadowColor: transparent , shadowOffsetX: 0.0
,shadowOffsetX: 0.0 , shadowOffsetY: 0.0
,shadowOffsetY: 0.0
} }
legend :: Legend legend :: Legend
legend = legend =
{ { id: "Muda"
id: "Muda" , "type": legendType Plain
,"type": legendType Plain , show: true
, show: true , zlevel: 0.0
, zlevel: 0.0 , z: 2.0
, z: 2.0 , left: relativePosition Auto
, left: relativePosition Auto , top: relativePosition Auto
, top: relativePosition Auto , right: relativePosition Auto
, right: relativePosition Auto , bottom: relativePosition Auto
, bottom: relativePosition Auto , width: relativePosition Auto
, width: relativePosition Auto , height: relativePosition Auto
, height: relativePosition Auto , orient: orient Horizontal
, orient: orient Horizontal , align: relativePosition Auto
, align: relativePosition Auto , padding: 5.0
, padding: 5.0 , itemGap: 10.0
, itemGap: 10.0 , itemWidth: 25.0
, itemWidth: 25.0 , itemHeight: 14.0
, itemHeight: 14.0 --, formatter: Nothing
--, formatter: Nothing , selectedMode: selectedMode $ Bool true
, selectedMode: selectedMode $ Bool true , inactiveColor: violet
, inactiveColor: violet --- selected: Nothing
--- selected: Nothing , textStyle: textStyle
, textStyle: textStyle , "data": [ data1 ]
, "data": [data1]
} }
data1 :: DataLegend data1 :: DataLegend
data1 = {name: "Map terms coverage", icon: icon $ Shape Circle, textStyle: textStyle'} data1 = { name: "Map terms coverage", icon: icon $ Shape Circle, textStyle: textStyle' }
data2 :: DataLegend data2 :: DataLegend
data2 = {name: "Favorites", icon: icon $ Shape Circle, textStyle: textStyle'} data2 = { name: "Favorites", icon: icon $ Shape Circle, textStyle: textStyle' }
data3 :: DataLegend data3 :: DataLegend
data3 = {name: "Test", icon: icon $ Shape Diamond, textStyle: textStyle'} data3 = { name: "Test", icon: icon $ Shape Diamond, textStyle: textStyle' }
yAxisVoid :: YAxis yAxisVoid :: YAxis
yAxisVoid = yAxis yAxisVoid =
{ "type": "" yAxis
, name: "" { "type": ""
, min: 0 , name: ""
, position: "" , min: 0
, axisLabel: {formatter: ""} , position: ""
, show: false , axisLabel: { formatter: "" }
} , show: false
}
xAxis' :: Array String -> XAxis xAxis' :: Array String -> XAxis
xAxis' [] = unsafeCoerce {show:false} xAxis' [] = unsafeCoerce { show: false }
xAxis' xs = xAxis
{ "data": xs xAxis' xs =
, "type": "category" xAxis
, axisTick: {alignWithLabel: true} { "data": xs
, show: true , "type": "category"
, axisLabel: {formatter: "{value}"} , axisTick: { alignWithLabel: true }
} , show: true
, axisLabel: { formatter: "{value}" }
}
-- TODO try to use Optional -- TODO try to use Optional
yAxis' :: { position :: String yAxis' ::
, show :: Boolean { position :: String
, min :: Int , show :: Boolean
} -> YAxis , min :: Int
yAxis' {position, show, min} = yAxis } ->
{ "type": "value" YAxis
, name: "" yAxis' { position, show, min } =
, min: min yAxis
, axisLabel: {formatter: "{value}"} { "type": "value"
, position , name: ""
, show , min: min
} , axisLabel: { formatter: "{value}" }
, position
, show
}
data Options = Options data Options
{ mainTitle :: MainTitle = Options
, subTitle :: SubTitle { mainTitle :: MainTitle
, xAxis :: XAxis , subTitle :: SubTitle
, yAxis :: YAxis , xAxis :: XAxis
, series :: Array Series , yAxis :: YAxis
, addZoom :: Boolean , series :: Array Series
, tooltip :: Tooltip , addZoom :: Boolean
} , tooltip :: Tooltip
}
tooltipTriggerAxis :: Tooltip tooltipTriggerAxis :: Tooltip
tooltipTriggerAxis = mkTooltip { trigger: "axis"} tooltipTriggerAxis = mkTooltip { trigger: "axis" }
opts :: Options -> Option opts :: Options -> Option
opts (Options { mainTitle opts ( Options
, subTitle { mainTitle
, xAxis , subTitle
, yAxis , xAxis
, series , yAxis
, tooltip , series
, addZoom , tooltip
}) = , addZoom
}
) =
{ title: title mainTitle subTitle { title: title mainTitle subTitle
, legend , legend
, tooltip , tooltip
, grid: {containLabel: true} , grid: { containLabel: true }
, series , series
, xAxis , xAxis
, yAxis , yAxis
, dataZoom: if addZoom then [zoom Slider, zoom Inside] else [] , dataZoom: if addZoom then [ zoom Slider, zoom Inside ] else []
, children : unsafeCoerce [] -- TODO , children: unsafeCoerce [] -- TODO
, toolbox: mkToolBox , toolbox: mkToolBox
} }
data Zoom = Slider | Inside data Zoom
= Slider
| Inside
instance showZoom :: Show Zoom where instance showZoom :: Show Zoom where
show Slider = "slider" show Slider = "slider"
show Inside = "inside" show Inside = "inside"
zoom :: Zoom -> DataZoom zoom :: Zoom -> DataZoom
zoom z = { zoom z =
"type": show z { "type": show z
,xAxisIndex: 0 , xAxisIndex: 0
,filterMode: "empty" , filterMode: "empty"
,start: 0 , start: 0
,end: 100 , end: 100
} }
seriesPie :: Series seriesPie :: Series
seriesPie = seriesPieD1 seriesPie =
{ name: "Pie name" } seriesPieD1
(dataSerie <$> [ {name: "t1", value: 50.0} { name: "Pie name" }
, {name: "t2", value: 45.0} ( dataSerie
, {name: "t3", value: 65.0} <$> [ { name: "t1", value: 50.0 }
, {name: "t4", value: 15.0} , { name: "t2", value: 45.0 }
, {name: "t5", value: 23.0} , { name: "t3", value: 65.0 }
]) , { name: "t4", value: 15.0 }
, { name: "t5", value: 23.0 }
]
)
textStyle2 :: TextStyle textStyle2 :: TextStyle
textStyle2 = textStyle2 =
......
...@@ -28,7 +28,6 @@ module Gargantext.Components.Charts.Options.Font ...@@ -28,7 +28,6 @@ module Gargantext.Components.Charts.Options.Font
) where ) where
import Prelude (Unit, ($), (<<<), (<>)) import Prelude (Unit, ($), (<<<), (<>))
import Data.Generic.Rep import Data.Generic.Rep
import Data.Generic.Rep.Show (genericShow) import Data.Generic.Rep.Show (genericShow)
import CSS (FontStyle(..), FontWeight(..), Prefixed(..), Value(..)) import CSS (FontStyle(..), FontWeight(..), Prefixed(..), Value(..))
...@@ -38,63 +37,78 @@ import Gargantext.Components.Charts.Options.Position (LeftRelativePosition, Posi ...@@ -38,63 +37,78 @@ import Gargantext.Components.Charts.Options.Position (LeftRelativePosition, Posi
import Gargantext.Types (class Optional) import Gargantext.Types (class Optional)
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
type TextStyle
type TextStyle = = { color :: Color
{ color :: Color , fontStyle :: ChartFontStyle
, fontStyle :: ChartFontStyle , fontWeight :: ChartFontWeight
, fontWeight :: ChartFontWeight , fontFamily :: String
, fontFamily :: String , fontSize :: Int
, fontSize :: Int , align :: Position LeftRelativePosition
, align :: Position LeftRelativePosition , verticalAlign :: Position TopRelativePosition
, verticalAlign :: Position TopRelativePosition , lineHeight :: Position Unit
, lineHeight :: Position Unit , width :: Position Unit
, width :: Position Unit , height :: Position Unit
, height :: Position Unit , textBorderColor :: Color
, textBorderColor :: Color , textBorderWidth :: Number
, textBorderWidth :: Number , textShadowColor :: Color
, textShadowColor :: Color , textShadowBlur :: Color
, textShadowBlur :: Color , textShadowOffsetX :: Number
, textShadowOffsetX :: Number , textShadowOffsetY :: Number
, textShadowOffsetY :: Number }
}
newtype ChartFontStyle
= ChartFontStyle String
newtype ChartFontStyle = ChartFontStyle String
chartFontStyle :: FontStyle -> ChartFontStyle chartFontStyle :: FontStyle -> ChartFontStyle
chartFontStyle (FontStyle (Value (Plain "italic"))) = ChartFontStyle "italic" chartFontStyle (FontStyle (Value (Plain "italic"))) = ChartFontStyle "italic"
chartFontStyle (FontStyle (Value (Plain "oblique"))) = ChartFontStyle "oblique" chartFontStyle (FontStyle (Value (Plain "oblique"))) = ChartFontStyle "oblique"
chartFontStyle _ = ChartFontStyle "normal"
chartFontStyle _ = ChartFontStyle "normal"
newtype ChartFontWeight = ChartFontWeight String newtype ChartFontWeight
= ChartFontWeight String
chartFontWeight :: FontWeight -> ChartFontWeight chartFontWeight :: FontWeight -> ChartFontWeight
chartFontWeight (FontWeight (Value (Plain "bold"))) = ChartFontWeight "bold" chartFontWeight (FontWeight (Value (Plain "bold"))) = ChartFontWeight "bold"
chartFontWeight (FontWeight (Value (Plain "bolder"))) = ChartFontWeight "bolder" chartFontWeight (FontWeight (Value (Plain "bolder"))) = ChartFontWeight "bolder"
chartFontWeight (FontWeight (Value (Plain "lighter"))) = ChartFontWeight "lighter" chartFontWeight (FontWeight (Value (Plain "lighter"))) = ChartFontWeight "lighter"
chartFontWeight _ = ChartFontWeight "normal"
chartFontWeight _ = ChartFontWeight "normal"
newtype Icon
= Icon String
newtype Icon = Icon String newtype ImageURL
= ImageURL String
newtype ImageURL = ImageURL String data Shape
= Circle
| Rect
| RoundRect
| Triangle
| Diamond
| Pin
| Arrow
data Shape = Circle | Rect | RoundRect | Triangle | Diamond | Pin | Arrow
derive instance genericShape :: Generic Shape _ derive instance genericShape :: Generic Shape _
data IconOptions = Shape Shape | Image ImageURL data IconOptions
= Shape Shape
| Image ImageURL
icon :: IconOptions -> Icon icon :: IconOptions -> Icon
icon (Shape s) = Icon <<< toLower $ genericShow s icon (Shape s) = Icon <<< toLower $ genericShow s
icon (Image (ImageURL url)) = Icon $ "image://" <> url
icon (Image (ImageURL url)) = Icon $ "image://" <> url
data ItemStyle data ItemStyle
type ItemStyleOptional = type ItemStyleOptional
( color :: Color = ( color :: Color
) )
itemStyle :: forall o. Optional o ItemStyleOptional => Record o -> ItemStyle itemStyle :: forall o. Optional o ItemStyleOptional => Record o -> ItemStyle
itemStyle = unsafeCoerce itemStyle = unsafeCoerce
...@@ -105,63 +119,73 @@ templateFormatter :: String -> Formatter ...@@ -105,63 +119,73 @@ templateFormatter :: String -> Formatter
templateFormatter = unsafeCoerce templateFormatter = unsafeCoerce
-- TODO callbackFormatter :: (...) -> Formatter -- TODO callbackFormatter :: (...) -> Formatter
data Tooltip data Tooltip
type TooltipOptional = type TooltipOptional
( trigger :: String = ( trigger :: String
-- ^ Not all tooltips support triggers. -- ^ Not all tooltips support triggers.
-- Grid and legend tooltips : yes -- Grid and legend tooltips : yes
-- Series : no -- Series : no
, show :: Boolean , show :: Boolean
, formatter :: Formatter , formatter :: Formatter
) )
----------------------------------------------------------------- -----------------------------------------------------------------
-- | ToolBox -- | ToolBox
mkToolBox :: ToolBox mkToolBox :: ToolBox
mkToolBox = { feature: { dataView : { show: true, readOnly : false, title : "Data"} mkToolBox =
, saveAsImage : { show : true, pixelRatio : 10, title : "Image"} { feature:
--, magicType : { show : true, "type" : ["line", "bar", "pie", "stack", "tiled"], title : "Type"} { dataView: { show: true, readOnly: false, title: "Data" }
--, restore : {show : true, title : "Restore"} , saveAsImage: { show: true, pixelRatio: 10, title: "Image" }
--, brush : {"type" : ["rect", "polygon", "lineX", "lineY", "keep", "clear"]} --, magicType : { show : true, "type" : ["line", "bar", "pie", "stack", "tiled"], title : "Type"}
} --, restore : {show : true, title : "Restore"}
, orient : "vertical" --, brush : {"type" : ["rect", "polygon", "lineX", "lineY", "keep", "clear"]}
} }
, orient: "vertical"
}
--------------------------------------- ---------------------------------------
type ToolBox = { feature :: Feature type ToolBox
, orient :: String} = { feature :: Feature
type Feature = { dataView :: DataView , orient :: String
, saveAsImage :: Save }
--, magicType :: MagicType
--, restore :: Restore type Feature
--, brush :: Brush = { dataView :: DataView
} , saveAsImage :: Save
--, magicType :: MagicType
--, restore :: Restore
--, brush :: Brush
}
--------------------------------------- ---------------------------------------
type Save = { show :: Boolean type Save
, pixelRatio :: Int = { show :: Boolean
, title :: String , pixelRatio :: Int
} , title :: String
}
type Restore = { show :: Boolean
, title :: String} type Restore
= { show :: Boolean
type MagicType = { show :: Boolean , title :: String
, "type" :: Array String -- TODO use line bar types }
, title :: String
} type MagicType
= { show :: Boolean
, "type" :: Array String -- TODO use line bar types
, title :: String
}
--------------------------------------- ---------------------------------------
type DataView
= { show :: Boolean
, readOnly :: Boolean
, title :: String
}
type DataView = { show :: Boolean type Brush
, readOnly :: Boolean = { "type" :: Array String }
, title :: String
}
type Brush = { "type" :: Array String }
--------------------------------------- ---------------------------------------
mkTooltip :: forall o. Optional o TooltipOptional => Record o -> Tooltip mkTooltip :: forall o. Optional o TooltipOptional => Record o -> Tooltip
mkTooltip = unsafeCoerce mkTooltip = unsafeCoerce
module Gargantext.Components.Charts.Options.Legend module Gargantext.Components.Charts.Options.Legend
( ( LegendType(..)
LegendType(..), , PlainOrScroll(..)
PlainOrScroll(..), , legendType
legendType, , Orient()
Orient(), , Orientation(..)
Orientation(..), , orient
orient, , SelectedMode()
SelectedMode(), , LegendMode(..)
LegendMode(..), , selectedMode
selectedMode ) where
) where
import Prelude (class Show, show, (<<<)) import Prelude (class Show, show, (<<<))
import Data.Generic.Rep (class Generic) import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show import Data.Generic.Rep.Show
import Data.String (toLower) import Data.String (toLower)
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
newtype LegendType = LegendType String newtype LegendType
= LegendType String
data PlainOrScroll
= Plain
| Scroll
data PlainOrScroll = Plain | Scroll
instance showPlainOrScroll :: Show PlainOrScroll where instance showPlainOrScroll :: Show PlainOrScroll where
show (Plain) = "plain" show (Plain) = "plain"
show (Scroll) = "scroll" show (Scroll) = "scroll"
...@@ -28,22 +30,30 @@ instance showPlainOrScroll :: Show PlainOrScroll where ...@@ -28,22 +30,30 @@ instance showPlainOrScroll :: Show PlainOrScroll where
legendType :: PlainOrScroll -> LegendType legendType :: PlainOrScroll -> LegendType
legendType = LegendType <<< toLower <<< show legendType = LegendType <<< toLower <<< show
newtype Orient
= Orient String
newtype Orient = Orient String data Orientation
= Horizontal
| Vertical
data Orientation = Horizontal | Vertical
derive instance genericOrientation :: Generic Orientation _ derive instance genericOrientation :: Generic Orientation _
orient :: Orientation -> Orient orient :: Orientation -> Orient
orient = Orient <<< toLower <<< genericShow orient = Orient <<< toLower <<< genericShow
foreign import data SelectedMode :: Type foreign import data SelectedMode :: Type
data LegendMode = Bool Boolean | Single | Multiple data LegendMode
= Bool Boolean
| Single
| Multiple
derive instance genericLegendMode :: Generic LegendMode _ derive instance genericLegendMode :: Generic LegendMode _
selectedMode :: LegendMode -> SelectedMode selectedMode :: LegendMode -> SelectedMode
selectedMode (Bool b) = unsafeCoerce b selectedMode (Bool b) = unsafeCoerce b
selectedMode (Single) = unsafeCoerce "single" selectedMode (Single) = unsafeCoerce "single"
selectedMode (Multiple) = unsafeCoerce "multiple" selectedMode (Multiple) = unsafeCoerce "multiple"
module Gargantext.Components.Charts.Options.Position module Gargantext.Components.Charts.Options.Position
( ( Position()
Position(), , numberPosition
numberPosition, , percentPosition
percentPosition, , relativePosition
relativePosition, , Align(..)
Align(..), , TopRelativePosition(..)
TopRelativePosition(..), , LeftRelativePosition(..)
LeftRelativePosition(..) ) where
) where
import Prelude import Prelude
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
-- | The type `Position` is made to render a css position. -- | The type `Position` is made to render a css position.
...@@ -29,18 +27,29 @@ percentPosition n = unsafeCoerce $ (show n) <> "%" ...@@ -29,18 +27,29 @@ percentPosition n = unsafeCoerce $ (show n) <> "%"
-- | Smart constructor to build a JS String giving position's detail ("top", "left", ...) -- | Smart constructor to build a JS String giving position's detail ("top", "left", ...)
relativePosition :: forall a. Show a => Align a -> Position a relativePosition :: forall a. Show a => Align a -> Position a
relativePosition (Auto) = unsafeCoerce "auto" relativePosition (Auto) = unsafeCoerce "auto"
relativePosition (Relative r) = unsafeCoerce $ show r
data Align p = Auto | Relative p relativePosition (Relative r) = unsafeCoerce $ show r
data TopRelativePosition = Top | Middle | Bottom
instance showTopRelativePosition :: Show TopRelativePosition
where show (Top) = "top"
show (Middle) = "middle"
show (Bottom) = "bottom"
data LeftRelativePosition = LeftPos | Center | RightPos data Align p
instance showLeftRelativePosition :: Show LeftRelativePosition = Auto
where show (LeftPos) = "left" | Relative p
show (Center) = "center"
show (RightPos) = "right" data TopRelativePosition
= Top
| Middle
| Bottom
instance showTopRelativePosition :: Show TopRelativePosition where
show (Top) = "top"
show (Middle) = "middle"
show (Bottom) = "bottom"
data LeftRelativePosition
= LeftPos
| Center
| RightPos
instance showLeftRelativePosition :: Show LeftRelativePosition where
show (LeftPos) = "left"
show (Center) = "center"
show (RightPos) = "right"
...@@ -10,69 +10,71 @@ import Gargantext.Types (class Optional) ...@@ -10,69 +10,71 @@ import Gargantext.Types (class Optional)
import Gargantext.Components.Charts.Options.Font (ItemStyle, Tooltip) import Gargantext.Components.Charts.Options.Font (ItemStyle, Tooltip)
import Gargantext.Components.Charts.Options.Data (DataD1, DataD2) import Gargantext.Components.Charts.Options.Data (DataD1, DataD2)
newtype SeriesType = SeriesType String newtype SeriesType
= SeriesType String
type SeriesName = String
type SeriesName
= String
data Chart = Line
| Bar | PictorialBar data Chart
| Pie = Line
| Scatter | EffectScatter | Bar
| Radar | PictorialBar
| Trees | Pie
| Sunburst | Scatter
| Boxplot | EffectScatter
| Candlestick | Radar
| Heatmap | Trees
| Map | Sunburst
| Parallel | Boxplot
| Lines | Candlestick
| Graph | Heatmap
| Sankey | Map
| Funnel | Parallel
| Gauge | Lines
| ThemeRiver | Graph
-- Trees | Sankey
| Funnel
| Gauge
| ThemeRiver
-- Trees
instance showChart :: Show Chart where instance showChart :: Show Chart where
show Bar = "bar" show Bar = "bar"
show EffectScatter = "effectScatter" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter-effect show EffectScatter = "effectScatter" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter-effect
show Funnel = "funnel" show Funnel = "funnel"
show Heatmap = "heatmap" show Heatmap = "heatmap"
show Line = "line" show Line = "line"
show Pie = "pie" show Pie = "pie"
show Sankey = "sankey" show Sankey = "sankey"
show Scatter = "scatter" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter-simple show Scatter = "scatter" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter-simple
show Sunburst = "sunburst" show Sunburst = "sunburst"
show _ = "not implemented yet: should throw error here" show _ = "not implemented yet: should throw error here"
seriesType :: Chart -> SeriesType seriesType :: Chart -> SeriesType
seriesType = SeriesType <<< show seriesType = SeriesType <<< show
-- | Scatter Dimension 2 data -- | Scatter Dimension 2 data
type OptionalSeries = type OptionalSeries
( name :: String = ( name :: String
, symbolSize :: Number , symbolSize :: Number
, itemStyle :: ItemStyle , itemStyle :: ItemStyle
-- ^ Graphic style of, *emphasis* is the style when it is highlighted, like being hovered by mouse, or highlighted via legend connect. -- ^ Graphic style of, *emphasis* is the style when it is highlighted, like being hovered by mouse, or highlighted via legend connect.
-- https://ecomfe.github.io/echarts-doc/public/en/option.html#series-scatter.itemStyle -- https://ecomfe.github.io/echarts-doc/public/en/option.html#series-scatter.itemStyle
, tooltip :: Tooltip , tooltip :: Tooltip
-- many more...
-- many more... )
)
data Series data Series
unsafeSeries :: forall o. Record o -> Series unsafeSeries :: forall o. Record o -> Series
unsafeSeries = unsafeCoerce unsafeSeries = unsafeCoerce
type RequiredSeriesD1 o = type RequiredSeriesD1 o
{ "type" :: SeriesType = { "type" :: SeriesType
, "data" :: Array DataD1 , "data" :: Array DataD1
| o | o
} }
seriesD1 :: forall o. Optional o OptionalSeries => RequiredSeriesD1 o -> Series seriesD1 :: forall o. Optional o OptionalSeries => RequiredSeriesD1 o -> Series
seriesD1 = unsafeSeries seriesD1 = unsafeSeries
...@@ -86,36 +88,38 @@ seriesBarD1 o ds = unsafeSeries (unsafeSet "data" ds (unsafeSet "type" (seriesTy ...@@ -86,36 +88,38 @@ seriesBarD1 o ds = unsafeSeries (unsafeSet "data" ds (unsafeSet "type" (seriesTy
seriesPieD1 :: forall o. Optional o OptionalSeries => Record o -> Array DataD1 -> Series seriesPieD1 :: forall o. Optional o OptionalSeries => Record o -> Array DataD1 -> Series
seriesPieD1 o ds = unsafeSeries (unsafeSet "data" ds (unsafeSet "type" (seriesType Pie) o)) seriesPieD1 o ds = unsafeSeries (unsafeSet "data" ds (unsafeSet "type" (seriesType Pie) o))
type RequiredSeriesD2 o = type RequiredSeriesD2 o
{ "data" :: Array DataD2 = { "data" :: Array DataD2
, "type" :: SeriesType , "type" :: SeriesType
| o | o
} }
seriesD2 :: forall o. Optional o OptionalSeries => RequiredSeriesD2 o -> Series seriesD2 :: forall o. Optional o OptionalSeries => RequiredSeriesD2 o -> Series
seriesD2 = unsafeSeries seriesD2 = unsafeSeries
seriesScatterD2 :: forall o. Optional o OptionalSeries => Record o -> Array DataD2 -> Series seriesScatterD2 :: forall o. Optional o OptionalSeries => Record o -> Array DataD2 -> Series
seriesScatterD2 o ds = seriesScatterD2 o ds = unsafeCoerce (unsafeSet "data" ds (unsafeSet "type" (seriesType Scatter) o))
unsafeCoerce (unsafeSet "data" ds (unsafeSet "type" (seriesType Scatter) o))
type Node
= { name :: String }
type Node = { name :: String} type Link
type Link = { source :: String = { source :: String
, target :: String , target :: String
, value :: Number , value :: Number
} }
-- | Sankey Chart -- | Sankey Chart
-- https://ecomfe.github.io/echarts-examples/public/editor.html?c=sankey-simple -- https://ecomfe.github.io/echarts-examples/public/editor.html?c=sankey-simple
type RequiredSankey o = type RequiredSankey o
{ "data" :: Array Node = { "data" :: Array Node
, links :: Array Link , links :: Array Link
| o | o
} }
type OptionalSankey = type OptionalSankey
( layout :: String = ( layout :: String
) )
seriesSankey :: forall o. Optional o OptionalSankey => RequiredSankey o -> Series seriesSankey :: forall o. Optional o OptionalSankey => RequiredSankey o -> Series
seriesSankey o = unsafeSeries ((unsafeCoerce o) { "type" = seriesType Sankey }) seriesSankey o = unsafeSeries ((unsafeCoerce o) { "type" = seriesType Sankey })
...@@ -123,70 +127,72 @@ seriesSankey o = unsafeSeries ((unsafeCoerce o) { "type" = seriesType Sankey }) ...@@ -123,70 +127,72 @@ seriesSankey o = unsafeSeries ((unsafeCoerce o) { "type" = seriesType Sankey })
-- | * Trees Chart -- | * Trees Chart
-- All these Trees are hierarchical Trees structure (or diagram) -- All these Trees are hierarchical Trees structure (or diagram)
-- https://en.wikipedia.org/wiki/Tree_structure -- https://en.wikipedia.org/wiki/Tree_structure
-- Tree types -- Tree types
data Trees = TreeLine | TreeRadial | TreeMap data Trees
= TreeLine
| TreeRadial
| TreeMap
instance showTrees :: Show Trees where instance showTrees :: Show Trees where
show TreeLine = "tree" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=tree-radial show TreeLine = "tree" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=tree-radial
show TreeRadial = "tree" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter-simple show TreeRadial = "tree" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter-simple
show TreeMap = "treemap" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=treemap-simple show TreeMap = "treemap" -- ^ https://ecomfe.github.io/echarts-examples/public/editor.html?c=treemap-simple
-- TreeLine is a 1-Dimension horizontal hierchical Tree -- TreeLine is a 1-Dimension horizontal hierchical Tree
-- TreeRadial is 1-Dimension radial (as circle) Tree with no surface meaning -- TreeRadial is 1-Dimension radial (as circle) Tree with no surface meaning
-- https://en.wikipedia.org/wiki/Radial_tree -- https://en.wikipedia.org/wiki/Radial_tree
-- https://ecomfe.github.io/echarts-examples/public/editor.html?c=tree-radial -- https://ecomfe.github.io/echarts-examples/public/editor.html?c=tree-radial
-- TreeMap is a is 2-Dimension Tree with surface meaning -- TreeMap is a is 2-Dimension Tree with surface meaning
-- TreeMap example implementation: -- TreeMap example implementation:
-- https://ecomfe.github.io/echarts-examples/public/editor.html?c=treemap-simple -- https://ecomfe.github.io/echarts-examples/public/editor.html?c=treemap-simple
type RequiredTree o
= { "type" :: SeriesType
, "data" :: Array TreeNode
| o
}
type RequiredTree o = type OptionalTree
{ "type" :: SeriesType = ( layout :: String
, "data" :: Array TreeNode )
| o
}
type OptionalTree =
( layout :: String
)
seriesTree :: forall o. Optional o OptionalTree => RequiredTree o -> Series seriesTree :: forall o. Optional o OptionalTree => RequiredTree o -> Series
seriesTree = unsafeSeries seriesTree = unsafeSeries
mkTree :: Trees -> Array TreeNode -> Series mkTree :: Trees -> Array TreeNode -> Series
mkTree t ts = seriesTree { "type" : SeriesType (show t) mkTree t ts =
, "data" : map (toJsTree Nothing) ts seriesTree
, layout : layout { "type": SeriesType (show t)
} , "data": map (toJsTree Nothing) ts
where , layout: layout
layout = case t of }
TreeRadial -> "radial" where
_ -> "none" layout = case t of
TreeRadial -> "radial"
_ -> "none"
-- ** Data Structure of the Trees -- ** Data Structure of the Trees
data TreeData = Array TreeNode data TreeData
= Array TreeNode
treeValue :: TreeNode -> Int treeValue :: TreeNode -> Int
treeValue (TreeNode x) = foldl (+) 0 $ [x.value] <> map treeValue x.children treeValue (TreeNode x) = foldl (+) 0 $ [ x.value ] <> map treeValue x.children
toJsTree :: Maybe String -> TreeNode -> TreeNode toJsTree :: Maybe String -> TreeNode -> TreeNode
toJsTree maybeSurname (TreeNode x) = toJsTree maybeSurname (TreeNode x) =
unsafeCoerce { name : name unsafeCoerce
, value : foldl (+) 0 $ [x.value] <> map treeValue x.children { name: name
, children : (map (toJsTree (Just name)) x.children) , value: foldl (+) 0 $ [ x.value ] <> map treeValue x.children
} , children: (map (toJsTree (Just name)) x.children)
where }
name = maybe "" (\x' -> x' <> ">") maybeSurname <> x.name where
name = maybe "" (\x' -> x' <> ">") maybeSurname <> x.name
data TreeNode = TreeNode { name :: String
, value :: Int data TreeNode
, children :: Array TreeNode = TreeNode
} { name :: String
, value :: Int
, children :: Array TreeNode
}
instance decodeTreeNode :: DecodeJson TreeNode where instance decodeTreeNode :: DecodeJson TreeNode where
decodeJson json = do decodeJson json = do
...@@ -194,18 +200,11 @@ instance decodeTreeNode :: DecodeJson TreeNode where ...@@ -194,18 +200,11 @@ instance decodeTreeNode :: DecodeJson TreeNode where
name <- obj .: "label" name <- obj .: "label"
value <- obj .: "value" value <- obj .: "value"
children <- obj .: "children" children <- obj .: "children"
pure $ TreeNode {name, value, children} pure $ TreeNode { name, value, children }
treeNode :: String -> Int -> Array TreeNode -> TreeNode treeNode :: String -> Int -> Array TreeNode -> TreeNode
treeNode n v ts = TreeNode {name : n, value:v, children:ts} treeNode n v ts = TreeNode { name: n, value: v, children: ts }
treeLeaf :: String -> Int -> TreeNode treeLeaf :: String -> Int -> TreeNode
treeLeaf n v = TreeNode { name : n, value : v, children : []} treeLeaf n v = TreeNode { name: n, value: v, children: [] }
-- | TODO -- https://ecomfe.github.io/echarts-examples/public/data/asset/data/life-expectancy-table.json -- https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter3D-dataset&gl=1
\ No newline at end of file
-- | TODO
-- https://ecomfe.github.io/echarts-examples/public/data/asset/data/life-expectancy-table.json
-- https://ecomfe.github.io/echarts-examples/public/editor.html?c=scatter3D-dataset&gl=1
module Gargantext.Components.Charts.Options.Type where module Gargantext.Components.Charts.Options.Type where
import Prelude import Prelude
import Gargantext.Components.Charts.Options.Color (Color) import Gargantext.Components.Charts.Options.Color (Color)
import Gargantext.Components.Charts.Options.Data (DataLegend) import Gargantext.Components.Charts.Options.Data (DataLegend)
import Gargantext.Components.Charts.Options.Font (TextStyle, Tooltip, ToolBox) import Gargantext.Components.Charts.Options.Font (TextStyle, Tooltip, ToolBox)
...@@ -12,151 +11,151 @@ import Gargantext.Types (class Optional) ...@@ -12,151 +11,151 @@ import Gargantext.Types (class Optional)
import React as R import React as R
import Unsafe.Coerce (unsafeCoerce) import Unsafe.Coerce (unsafeCoerce)
newtype ChartAlign = ChartAlign String newtype ChartAlign
= ChartAlign String
-- TODO: Maybe is not working here => use Optional -- TODO: Maybe is not working here => use Optional
type Echarts
type Echarts = = { option :: Option -- PropTypes.object.isRequired,
{ option :: Option -- PropTypes.object.isRequired, --, className :: Maybe String
--, className :: Maybe String --, style :: Maybe String -- objealect-black-altdarkmincnaquadahherry-blossomect,
--, style :: Maybe String -- objealect-black-altdarkmincnaquadahherry-blossomect, --, theme :: Maybe String
--, theme :: Maybe String --, group :: Maybe String
--, group :: Maybe String --, initOpts :: Maybe String -- PropTypes.object,
--, initOpts :: Maybe String -- PropTypes.object, --, notMerge :: Maybe Boolean
--, notMerge :: Maybe Boolean --, lazyUpdate :: Maybe Boolean
--, lazyUpdate :: Maybe Boolean --, loading :: Maybe Boolean
--, loading :: Maybe Boolean --, optsLoading :: Maybe OptsLoading -- PropTypes.object,
--, optsLoading :: Maybe OptsLoading -- PropTypes.object, --, onReady :: Maybe String -- PropTypes.func,
--, onReady :: Maybe String -- PropTypes.func, --, resizable :: Maybe Boolean -- PropTypes.bool,
--, resizable :: Maybe Boolean -- PropTypes.bool, --, onEvents :: Maybe String -- PropTypes.object
--, onEvents :: Maybe String -- PropTypes.object }
}
type Option
type Option = = { title :: Title
{ title :: Title , legend :: Legend
, legend :: Legend , tooltip :: Tooltip
, tooltip :: Tooltip , grid :: Grid
, grid :: Grid , xAxis :: XAxis
, xAxis :: XAxis , yAxis :: YAxis
, yAxis :: YAxis , series :: Array Series
, series :: Array Series , dataZoom :: Array DataZoom
, dataZoom :: Array DataZoom , children :: R.Children
, children :: R.Children , toolbox :: ToolBox
, toolbox :: ToolBox }
}
type Title
type Title = = { id :: String -- None by default
{ id :: String -- None by default , show :: Boolean -- default True
, show :: Boolean -- default True , text :: String -- default ''
, text :: String -- default '' , link :: String -- default ''
, link :: String -- default '' , target :: String -- default 'blank'
, target :: String -- default 'blank' , textStyle :: TextStyle
, textStyle :: TextStyle , subtext :: String -- default ''
, subtext :: String -- default '' , sublink :: String -- default ''
, sublink :: String -- default '' , subtarget :: String -- default 'blank'
, subtarget :: String -- default 'blank' , subtextStyle :: TextStyle
, subtextStyle :: TextStyle , padding :: Number -- default '5'
, padding :: Number -- default '5' , itemGap :: Number -- default '10'
, itemGap :: Number -- default '10' , zlevel :: Number -- default '0'
, zlevel :: Number -- default '0' , z :: Number -- default '2'
, z :: Number -- default '2' , left :: Position LeftRelativePosition -- default 'auto'
, left :: Position LeftRelativePosition -- default 'auto' , top :: Position TopRelativePosition -- default 'auto'
, top :: Position TopRelativePosition -- default 'auto' , right :: Position Unit -- default 'auto'
, right :: Position Unit -- default 'auto' , bottom :: Position Unit -- default 'auto'
, bottom :: Position Unit -- default 'auto' , backgroundColor :: Color -- default 'transparent''
, backgroundColor :: Color -- default 'transparent'' , borderColor :: Color -- default '#ccc'
, borderColor :: Color -- default '#ccc' , borderWidth :: Number -- default '1'
, borderWidth :: Number -- default '1' , borderRadius :: Number -- default 0; data NumberOrArray = Number | Array Number
, borderRadius :: Number -- default 0; data NumberOrArray = Number | Array Number , shadowBlur :: Number
, shadowBlur :: Number , shadowColor :: Color
, shadowColor :: Color , shadowOffsetX :: Number
, shadowOffsetX :: Number , shadowOffsetY :: Number
, shadowOffsetY :: Number }
}
type OptsLoading
type OptsLoading = = { text :: String
{ text :: String , color :: Color --- color
, color :: Color --- color , textColor :: Color --color
, textColor :: Color --color , maskColor :: Color --color
, maskColor :: Color --color , zlevel :: Int
, zlevel :: Int }
}
type DataZoom
type DataZoom = = { "type" :: String
{"type" :: String , xAxisIndex :: Int
, xAxisIndex :: Int , filterMode :: String
, filterMode :: String , start :: Int
, start :: Int , end :: Int
, end :: Int }
}
type Grid
type Grid = = { containLabel :: Boolean
{containLabel :: Boolean }
}
type Legend
type Legend = = { id :: String
{ , "type" :: LegendType
id :: String , show :: Boolean
, "type" :: LegendType , zlevel :: Number
, show :: Boolean , z :: Number
, zlevel :: Number , left :: Position LeftRelativePosition -- default 'auto
, z :: Number , top :: Position TopRelativePosition
, left :: Position LeftRelativePosition -- default 'auto , right :: Position Unit
, top :: Position TopRelativePosition , bottom :: Position Unit
, right :: Position Unit , width :: Position Unit
, bottom :: Position Unit , height :: Position Unit
, width :: Position Unit , orient :: Orient
, height :: Position Unit , align :: Position LeftRelativePosition
, orient :: Orient , padding :: Number
, align :: Position LeftRelativePosition , itemGap :: Number
, padding :: Number , itemWidth :: Number
, itemGap :: Number , itemHeight :: Number
, itemWidth :: Number --, formatter :: Maybe String
, itemHeight :: Number , selectedMode :: SelectedMode
--, formatter :: Maybe String , inactiveColor :: Color
, selectedMode :: SelectedMode --, selected :: Maybe String -- object
, inactiveColor :: Color , textStyle :: TextStyle
--, selected :: Maybe String -- object , "data" :: Array DataLegend
, textStyle :: TextStyle }
, "data" :: Array DataLegend
} type AxisTick
= { alignWithLabel :: Boolean
type AxisTick = }
{ alignWithLabel :: Boolean
}
data XAxis data XAxis
type XAxisOptional = type XAxisOptional
( "data" :: Array String -- DataAxis = ( "data" :: Array String -- DataAxis
, "type" :: String , "type" :: String
, axisTick :: AxisTick , axisTick :: AxisTick
, name :: String , name :: String
, min :: Int , min :: Int
, position :: String , position :: String
, axisLabel :: AxisLabel , axisLabel :: AxisLabel
, show :: Boolean , show :: Boolean
) )
xAxis :: forall o. Optional o XAxisOptional => Record o -> XAxis xAxis :: forall o. Optional o XAxisOptional => Record o -> XAxis
xAxis = unsafeCoerce xAxis = unsafeCoerce
data YAxis data YAxis
type YAxisOptional = type YAxisOptional
( "type" :: String = ( "type" :: String
, name :: String , name :: String
, min :: Int , min :: Int
, position :: String , position :: String
, axisLabel :: AxisLabel , axisLabel :: AxisLabel
, show :: Boolean , show :: Boolean
) )
yAxis :: forall o. Optional o YAxisOptional => Record o -> YAxis yAxis :: forall o. Optional o YAxisOptional => Record o -> YAxis
yAxis = unsafeCoerce yAxis = unsafeCoerce
type AxisLabel = type AxisLabel
{ formatter :: String -- string or function = { formatter :: String -- string or function
} }
type Rich = {} type Rich
= {}
-- | The ContextMenu component renders a generic context menu -- | The ContextMenu component renders a generic context menu
module Gargantext.Components.ContextMenu.ContextMenu where module Gargantext.Components.ContextMenu.ContextMenu where
-- (MenuProps, Action(..), separator) where
-- (MenuProps, Action(..), separator) where
import Prelude hiding (div) import Prelude hiding (div)
import Data.Maybe ( Maybe(..) ) import Data.Maybe (Maybe(..))
import Data.Nullable ( Nullable, null, toMaybe ) import Data.Nullable (Nullable, null, toMaybe)
import Data.Tuple.Nested ( (/\) ) import Data.Tuple.Nested ((/\))
import Data.Traversable ( traverse_ ) import Data.Traversable (traverse_)
import DOM.Simple as DOM import DOM.Simple as DOM
import DOM.Simple.Event as DE import DOM.Simple.Event as DE
import DOM.Simple.EventListener ( Callback, callback ) import DOM.Simple.EventListener (Callback, callback)
import DOM.Simple.Element as Element import DOM.Simple.Element as Element
import DOM.Simple.Window ( window ) import DOM.Simple.Window (window)
import DOM.Simple.Document ( document ) import DOM.Simple.Document (document)
import DOM.Simple.Types ( DOMRect ) import DOM.Simple.Types (DOMRect)
import Effect (Effect) import Effect (Effect)
import FFI.Simple ((..)) import FFI.Simple ((..))
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as HTML import Reactix.DOM.HTML as HTML
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
type Props t = ( x :: Number, y :: Number, setMenu :: R2.Setter (Maybe t) ) type Props t
= ( x :: Number, y :: Number, setMenu :: R2.Setter (Maybe t) )
contextMenu :: forall t. Record (Props t) -> Array R.Element -> R.Element contextMenu :: forall t. Record (Props t) -> Array R.Element -> R.Element
contextMenu = R.createElement contextMenuCpt contextMenu = R.createElement contextMenuCpt
...@@ -29,96 +29,94 @@ contextMenu = R.createElement contextMenuCpt ...@@ -29,96 +29,94 @@ contextMenu = R.createElement contextMenuCpt
contextMenuCpt :: forall t. R.Component (Props t) contextMenuCpt :: forall t. R.Component (Props t)
contextMenuCpt = R.hooksComponent "ContextMenu" cpt contextMenuCpt = R.hooksComponent "ContextMenu" cpt
where where
cpt menu children = do cpt menu children = do
host <- R2.getPortalHost host <- R2.getPortalHost
root <- R.useRef null root <- R.useRef null
rect /\ setRect <- R.useState $ \_ -> Nothing rect /\ setRect <- R.useState $ \_ -> Nothing
R.useLayoutEffect1 (R.readRef root) $ do R.useLayoutEffect1 (R.readRef root)
traverse_ $ do
(\r -> setRect (\_ -> Just (Element.boundingRect r))) traverse_
(toMaybe $ R.readRef root) (\r -> setRect (\_ -> Just (Element.boundingRect r)))
pure $ pure unit (toMaybe $ R.readRef root)
R.useLayoutEffect2 root rect (contextMenuEffect menu.setMenu root) pure $ pure unit
let cs = [ R.useLayoutEffect2 root rect (contextMenuEffect menu.setMenu root)
HTML.div { className: "popover-content" } let
cs =
[ HTML.div { className: "popover-content" }
[ HTML.div { className: "panel panel-default" } [ HTML.div { className: "panel panel-default" }
[ HTML.ul { className: "list-group" } [ HTML.ul { className: "list-group" }
children children
] ]
] ]
] ]
pure $ R.createPortal [ elems root menu rect $ cs ] host pure $ R.createPortal [ elems root menu rect $ cs ] host
elems ref menu (Just rect) = HTML.div
{ ref elems ref menu (Just rect) =
, className: "context-menu" HTML.div
, style: position menu rect { ref
, data: {toggle: "popover", placement: "right"} , className: "context-menu"
} , style: position menu rect
elems ref _ _ = HTML.div , data: { toggle: "popover", placement: "right" }
{ ref }
, className: "context-menu"
, data: {toggle: "popover", placement: "right"} elems ref _ _ =
} HTML.div
{ ref
contextMenuEffect , className: "context-menu"
:: forall t , data: { toggle: "popover", placement: "right" }
. R2.Setter (Maybe t) }
-> R.Ref (Nullable DOM.Element)
-> Effect (Effect Unit) contextMenuEffect ::
contextMenuEffect setMenu rootRef = forall t.
case R.readNullableRef rootRef of R2.Setter (Maybe t) ->
Just root -> do R.Ref (Nullable DOM.Element) ->
let onClick = documentClickHandler setMenu root Effect (Effect Unit)
let onScroll = documentScrollHandler setMenu contextMenuEffect setMenu rootRef = case R.readNullableRef rootRef of
DOM.addEventListener document "click" onClick Just root -> do
DOM.addEventListener document "scroll" onScroll let
pure $ do onClick = documentClickHandler setMenu root
DOM.removeEventListener document "click" onClick let
DOM.removeEventListener document "scroll" onScroll onScroll = documentScrollHandler setMenu
Nothing -> pure R.nothing DOM.addEventListener document "click" onClick
DOM.addEventListener document "scroll" onScroll
pure
$ do
DOM.removeEventListener document "click" onClick
DOM.removeEventListener document "scroll" onScroll
Nothing -> pure R.nothing
documentClickHandler :: forall t. R2.Setter (Maybe t) -> DOM.Element -> Callback DE.MouseEvent documentClickHandler :: forall t. R2.Setter (Maybe t) -> DOM.Element -> Callback DE.MouseEvent
documentClickHandler hide menu = documentClickHandler hide menu =
R2.named "hideMenuOnClickOutside" $ callback $ \e -> R2.named "hideMenuOnClickOutside" $ callback
if Element.contains menu (DE.target e) $ \e ->
then pure unit if Element.contains menu (DE.target e) then
else hide (const Nothing) pure unit
else
hide (const Nothing)
documentScrollHandler :: forall t. R2.Setter (Maybe t) -> Callback DE.MouseEvent documentScrollHandler :: forall t. R2.Setter (Maybe t) -> Callback DE.MouseEvent
documentScrollHandler hide = documentScrollHandler hide = R2.named "hideMenuOnScroll" $ callback $ \e -> hide (const Nothing)
R2.named "hideMenuOnScroll" $ callback $ \e -> hide (const Nothing)
position :: forall t. Record (Props t) -> DOMRect -> { left :: Number, top :: Number } position :: forall t. Record (Props t) -> DOMRect -> { left :: Number, top :: Number }
position mouse {width: menuWidth, height: menuHeight} = {left, top} position mouse { width: menuWidth, height: menuHeight } = { left, top }
where left = if isRight then mouse.x else mouse.x - menuWidth
top = if isAbove then mouse.y else mouse.y - menuHeight
isRight = screenWidth - mouse.x > menuWidth -- is there enough space to show above
isAbove = screenHeight - mouse.y > menuHeight -- is there enough space to show to the right?
screenWidth = window .. "innerWidth"
screenHeight = window .. "innerHeight"
contextMenuItem :: Array R.Element -> R.Element
contextMenuItem = R.createElement contextMenuItemCpt {}
contextMenuItemCpt :: R.Component ()
contextMenuItemCpt = R.hooksComponent "ContextMenuItem" cpt
where where
cpt _props children = pure $ HTML.li { className: "context-menu-item" } children left = if isRight then mouse.x else mouse.x - menuWidth
-- -- CSS Classes top = if isAbove then mouse.y else mouse.y - menuHeight
-- menuClass :: String isRight = screenWidth - mouse.x > menuWidth -- is there enough space to show above
-- menuClass = "context-menu"
-- menuShownClass :: String isAbove = screenHeight - mouse.y > menuHeight -- is there enough space to show to the right?
-- menuShownClass = "context-menu-shown"
-- menuHiddenClass :: String screenWidth = window .. "innerWidth"
-- menuHiddenClass = "context-menu-hidden"
-- itemClass :: String screenHeight = window .. "innerHeight"
-- itemClass = "context-menu-item"
-- separatorClass :: String contextMenuItem :: Array R.Element -> R.Element
-- separatorClass = "context-menu-item" contextMenuItem = R.createElement contextMenuItemCpt {}
contextMenuItemCpt :: R.Component ()
contextMenuItemCpt = R.hooksComponent "ContextMenuItem" cpt
where
cpt _props children = pure $ HTML.li { className: "context-menu-item" } children
-- -- CSS Classes -- menuClass :: String -- menuClass = "context-menu" -- menuShownClass :: String -- menuShownClass = "context-menu-shown" -- menuHiddenClass :: String -- menuHiddenClass = "context-menu-hidden" -- itemClass :: String -- itemClass = "context-menu-item" -- separatorClass :: String -- separatorClass = "context-menu-item"
\ No newline at end of file
-- | The SimpleItem is a simple context menu item consisting of a link -- | The SimpleItem is a simple context menu item consisting of a link
-- | It handles automatically closing the context menu for you -- | It handles automatically closing the context menu for you
module Gargantext.Component.ContextMenu.SimpleItem where module Gargantext.Component.ContextMenu.SimpleItem where
-- (MenuProps, Action(..), separator) where
-- (MenuProps, Action(..), separator) where
import Prelude hiding (div) import Prelude hiding (div)
-- separator :: ReactElement -- separator = div [ className "context-menu-separator" ] [] -- type State' = { open :: Boolean } -- newtype State = State State' -- defaultState :: State -- defaultState = State { open: false } -- type MenuProps = { classes :: String } -- type ItemProps p = { hideMenu :: Effect () | p } -- data Action = Show | Hide -- menuClass :: String -- menuClass = "context-menu" -- menuShownClass :: String -- menuShownClass = "context-menu-shown" -- menuHiddenClass :: String -- menuHiddenClass = "context-menu-hidden" -- itemClass :: String -- itemClass = "context-menu-item" -- contextMenu :: MenuProps -> Array ReactElement -> ReactElement -- contextMenu = createElement contextMenuClass -- -- TODO: register callbacks -- componentDidMount :: Effect Unit -- componentDidMount = pure unit -- -- TODO: unregister callbacks -- componentWillUnmount :: Effect Unit -- componentWillUnmount = pure unit -- -- -- childRender :: forall s p a. Spec s p a -> Spec s p a -- childRender = over _render (\c -> wrapItem <<< c) -- -- | Wraps an item in an li tag with the item classname -- wrapItem :: ReactElement -> ReactElement -- wrapItem = wrap $ li [ className itemClass ] -- renderMenuItem :: Render State MenuItem Action MenuItem -- renderMenuItem _ Separator _ _ = li [ className "menu-item-separator" ] -- renderMenuItem d (MenuItem i) _ _ = wrap outer inner -- where outer = li [ className "context-menu-item" ] -- inner = a [ onClick callback, style i.style ] [text i.label] -- callback _ = d Hide *> i.callback -- -- TODO: Aria and accessibility -- renderMenu :: Render State MenuProps Action -- renderMenu d m s c = pure $ wrap outer $ ul' inner -- where outer = div [className (classes s.open m.classes)] -- inner = map (\i -> renderMenuItem d i ) c -- visibilityClass :: Boolean -> String -- visibilityClass true = contextMenuShown -- visibilityClass false = contextMenuHidden -- classes :: Boolean -> String -> String -- classes visible user = joinWith " " [menuClass, visibilityClass visible, user] -- -- Class -- contextMenuClass :: ReactClass (WithChildren State') -- contextMenuClass = component "ContextMenu" createContextMenuClass -- createContextMenuClass :: -- forall given snapshot spec. -- ReactComponentSpec MenuProps State snapshot given spec -- => ReactClassConstructor MenuProps State given -- -> ReactClass MenuProps -- createContextMenuClass this = pure -- { state: defaultState -- , render: renderMenu -- , componentDidMount: componentDidMount -- , componentWillUnmount: componentWillUnmount -- } -- type Label = String -- type ClassName = String -- -- Items -- simpleItem :: Label -> ClassName -> Effect Unit -> Effect Unit -> ReactElement -- simpleItem label cls cb hide = a [ onClick (hide *> cb), className cls ] [ text label ] -- separator :: ReactElement -- separator = li [ className "menu-item-separator" ] []
-- separator :: ReactElement \ No newline at end of file
-- separator = div [ className "context-menu-separator" ] []
-- type State' = { open :: Boolean }
-- newtype State = State State'
-- defaultState :: State
-- defaultState = State { open: false }
-- type MenuProps = { classes :: String }
-- type ItemProps p = { hideMenu :: Effect () | p }
-- data Action = Show | Hide
-- menuClass :: String
-- menuClass = "context-menu"
-- menuShownClass :: String
-- menuShownClass = "context-menu-shown"
-- menuHiddenClass :: String
-- menuHiddenClass = "context-menu-hidden"
-- itemClass :: String
-- itemClass = "context-menu-item"
-- contextMenu :: MenuProps -> Array ReactElement -> ReactElement
-- contextMenu = createElement contextMenuClass
-- -- TODO: register callbacks
-- componentDidMount :: Effect Unit
-- componentDidMount = pure unit
-- -- TODO: unregister callbacks
-- componentWillUnmount :: Effect Unit
-- componentWillUnmount = pure unit
-- --
-- childRender :: forall s p a. Spec s p a -> Spec s p a
-- childRender = over _render (\c -> wrapItem <<< c)
-- -- | Wraps an item in an li tag with the item classname
-- wrapItem :: ReactElement -> ReactElement
-- wrapItem = wrap $ li [ className itemClass ]
-- renderMenuItem :: Render State MenuItem Action MenuItem
-- renderMenuItem _ Separator _ _ = li [ className "menu-item-separator" ]
-- renderMenuItem d (MenuItem i) _ _ = wrap outer inner
-- where outer = li [ className "context-menu-item" ]
-- inner = a [ onClick callback, style i.style ] [text i.label]
-- callback _ = d Hide *> i.callback
-- -- TODO: Aria and accessibility
-- renderMenu :: Render State MenuProps Action
-- renderMenu d m s c = pure $ wrap outer $ ul' inner
-- where outer = div [className (classes s.open m.classes)]
-- inner = map (\i -> renderMenuItem d i ) c
-- visibilityClass :: Boolean -> String
-- visibilityClass true = contextMenuShown
-- visibilityClass false = contextMenuHidden
-- classes :: Boolean -> String -> String
-- classes visible user = joinWith " " [menuClass, visibilityClass visible, user]
-- -- Class
-- contextMenuClass :: ReactClass (WithChildren State')
-- contextMenuClass = component "ContextMenu" createContextMenuClass
-- createContextMenuClass ::
-- forall given snapshot spec.
-- ReactComponentSpec MenuProps State snapshot given spec
-- => ReactClassConstructor MenuProps State given
-- -> ReactClass MenuProps
-- createContextMenuClass this = pure
-- { state: defaultState
-- , render: renderMenu
-- , componentDidMount: componentDidMount
-- , componentWillUnmount: componentWillUnmount
-- }
-- type Label = String
-- type ClassName = String
-- -- Items
-- simpleItem :: Label -> ClassName -> Effect Unit -> Effect Unit -> ReactElement
-- simpleItem label cls cb hide = a [ onClick (hide *> cb), className cls ] [ text label ]
-- separator :: ReactElement
-- separator = li [ className "menu-item-separator" ] []
This diff is collapsed.
This diff is collapsed.
...@@ -4,15 +4,14 @@ import Reactix as R ...@@ -4,15 +4,14 @@ import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
-- TODO : get REST informations -- TODO : get REST informations
folder :: {} -> R.Element folder :: {} -> R.Element
folder props = R.createElement folderCpt props [] folder props = R.createElement folderCpt props []
folderCpt :: R.Component () folderCpt :: R.Component ()
folderCpt = R.staticComponent "G.C.Folder.folder" cpt folderCpt = R.staticComponent "G.C.Folder.folder" cpt
where where
cpt _ _ = cpt _ _ =
R.fragment R.fragment
[ H.h1 {} [ H.text "Folder" ] [ H.h1 {} [ H.text "Folder" ]
, H.text "Some description of the folder here" ] , H.text "Some description of the folder here"
]
...@@ -10,37 +10,39 @@ import Gargantext.Sessions (Session(..), Sessions, unSessions) ...@@ -10,37 +10,39 @@ import Gargantext.Sessions (Session(..), Sessions, unSessions)
import Gargantext.Components.Tree (treeView) import Gargantext.Components.Tree (treeView)
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
type Props = type Props
( sessions :: Sessions = ( sessions :: Sessions
, route :: AppRoute , route :: AppRoute
, frontends :: Frontends , frontends :: Frontends
, showLogin :: R2.Setter Boolean , showLogin :: R2.Setter Boolean
) )
forest :: Record Props -> R.Element forest :: Record Props -> R.Element
forest props = R.createElement forestCpt props [] forest props = R.createElement forestCpt props []
forestCpt :: R.Component Props forestCpt :: R.Component Props
forestCpt = R.staticComponent "G.C.Forest.forest" cpt where forestCpt = R.staticComponent "G.C.Forest.forest" cpt
cpt {sessions, route, frontends, showLogin} _ = where
R.fragment [ plus showLogin, trees ] cpt { sessions, route, frontends, showLogin } _ = R.fragment [ plus showLogin, trees ]
where where
trees = trees = case unSessions sessions of
case unSessions sessions of Nothing -> R.fragment []
Nothing -> R.fragment [] Just s@(Session { treeId }) ->
Just s@(Session {treeId}) -> R.fragment
R.fragment [ treeView
[ treeView { root: treeId { root: treeId
, frontends , frontends
, mCurrentRoute: Just route , mCurrentRoute: Just route
, session: s } , session: s
] }
]
plus :: R2.Setter Boolean -> R.Element plus :: R2.Setter Boolean -> R.Element
plus showLogin = H.button {on: {click}} plus showLogin =
[ H.i { className: "glyphicon glyphicon-log-in"} H.button { on: { click } }
[] [ H.i { className: "glyphicon glyphicon-log-in" }
] []
]
where where
click _ = do click _ = do
showLogin (const true) showLogin (const true)
...@@ -4,19 +4,19 @@ import Reactix as R ...@@ -4,19 +4,19 @@ import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
clearfix :: {} -> R.Element clearfix :: {} -> R.Element
clearfix _ = H.div {className: "clearfix"} [] clearfix _ = H.div { className: "clearfix" } []
formGroup :: Array R.Element -> R.Element formGroup :: Array R.Element -> R.Element
formGroup = H.div {className: "form-group"} formGroup = H.div { className: "form-group" }
center :: Array R.Element -> R.Element center :: Array R.Element -> R.Element
center = H.div {className: "center"} center = H.div { className: "center" }
card :: Array R.Element -> R.Element card :: Array R.Element -> R.Element
card = H.div {className: "card"} card = H.div { className: "card" }
cardBlock :: Array R.Element -> R.Element cardBlock :: Array R.Element -> R.Element
cardBlock = H.div {className: "card-block"} cardBlock = H.div { className: "card-block" }
cardGroup :: Array R.Element -> R.Element cardGroup :: Array R.Element -> R.Element
cardGroup = H.div {className: "card-group"} cardGroup = H.div { className: "card-group" }
This diff is collapsed.
...@@ -10,14 +10,13 @@ import DOM.Simple.Console (log2) ...@@ -10,14 +10,13 @@ import DOM.Simple.Console (log2)
import Effect (Effect) import Effect (Effect)
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
import Gargantext.Hooks.Sigmax as Sigmax import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Sigma as Sigma import Gargantext.Hooks.Sigmax.Sigma as Sigma
type Props = ( type Props
onClick :: forall e. e -> Effect Unit = ( onClick :: forall e. e -> Effect Unit
, text :: String , text :: String
) )
simpleButton :: Record Props -> R.Element simpleButton :: Record Props -> R.Element
simpleButton props = R.createElement simpleButtonCpt props [] simpleButton props = R.createElement simpleButtonCpt props []
...@@ -25,22 +24,24 @@ simpleButton props = R.createElement simpleButtonCpt props [] ...@@ -25,22 +24,24 @@ simpleButton props = R.createElement simpleButtonCpt props []
simpleButtonCpt :: R.Component Props simpleButtonCpt :: R.Component Props
simpleButtonCpt = R.hooksComponent "SimpleButton" cpt simpleButtonCpt = R.hooksComponent "SimpleButton" cpt
where where
cpt {onClick, text} _ = do cpt { onClick, text } _ = do
pure $ pure
H.span {} $ H.span {}
[ [ H.button
H.button { className: "btn btn-primary", on: { click: onClick } }
{ className: "btn btn-primary", on: {click: onClick} }
[ H.text text ] [ H.text text ]
] ]
centerButton :: R.Ref (Maybe Sigmax.Sigma) -> R.Element centerButton :: R.Ref (Maybe Sigmax.Sigma) -> R.Element
centerButton sigmaRef = simpleButton { centerButton sigmaRef =
onClick: \_ -> do simpleButton
let mSigma = Sigmax.readSigma <$> R.readRef sigmaRef { onClick:
log2 "[centerButton] mSigma" mSigma \_ -> do
case mSigma of let
Just (Just s) -> Sigma.goToAllCameras s {x: 0.0, y: 0.0, ratio: 1.0, angle: 0.0} mSigma = Sigmax.readSigma <$> R.readRef sigmaRef
_ -> pure unit log2 "[centerButton] mSigma" mSigma
, text: "Center" case mSigma of
} Just (Just s) -> Sigma.goToAllCameras s { x: 0.0, y: 0.0, ratio: 1.0, angle: 0.0 }
_ -> pure unit
, text: "Center"
}
module Gargantext.Components.GraphExplorer.Controls module Gargantext.Components.GraphExplorer.Controls
( Controls ( Controls
, controlsToSigmaSettings , controlsToSigmaSettings
, useGraphControls , useGraphControls
, controls , controls
, controlsCpt , controlsCpt
, getShowTree, setShowTree , getShowTree
, getShowControls, setShowControls , setShowTree
, getShowSidePanel, setShowSidePanel , getShowControls
, getCursorSize, setCursorSize , setShowControls
, getMultiNodeSelect, setMultiNodeSelect , getShowSidePanel
) where , setShowSidePanel
, getCursorSize
, setCursorSize
, getMultiNodeSelect
, setMultiNodeSelect
) where
import Data.Maybe (Maybe) import Data.Maybe (Maybe)
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
...@@ -17,7 +22,6 @@ import Effect (Effect) ...@@ -17,7 +22,6 @@ import Effect (Effect)
import Prelude import Prelude
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as RH import Reactix.DOM.HTML as RH
import Gargantext.Components.Graph as Graph import Gargantext.Components.Graph as Graph
import Gargantext.Components.GraphExplorer.Button (centerButton) import Gargantext.Components.GraphExplorer.Button (centerButton)
import Gargantext.Components.GraphExplorer.RangeControl (edgeSizeControl, nodeSizeControl) import Gargantext.Components.GraphExplorer.RangeControl (edgeSizeControl, nodeSizeControl)
...@@ -27,26 +31,25 @@ import Gargantext.Hooks.Sigmax as Sigmax ...@@ -27,26 +31,25 @@ import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Utils.Range as Range import Gargantext.Utils.Range as Range
import Gargantext.Utils.Reactix as R2 import Gargantext.Utils.Reactix as R2
type Controls
type Controls = = ( cursorSize :: R.State Number
( cursorSize :: R.State Number , multiNodeSelect :: R.Ref Boolean
, multiNodeSelect :: R.Ref Boolean , showControls :: R.State Boolean
, showControls :: R.State Boolean , showSidePanel :: R.State Boolean
, showSidePanel :: R.State Boolean , showTree :: R.State Boolean
, showTree :: R.State Boolean , sigmaRef :: R.Ref (Maybe Sigmax.Sigma)
, sigmaRef :: R.Ref (Maybe Sigmax.Sigma) )
)
controlsToSigmaSettings :: Record Controls -> Record Graph.SigmaSettings controlsToSigmaSettings :: Record Controls -> Record Graph.SigmaSettings
controlsToSigmaSettings { cursorSize: (cursorSize /\ _)} = Graph.sigmaSettings controlsToSigmaSettings { cursorSize: (cursorSize /\ _) } = Graph.sigmaSettings
type LocalControls = type LocalControls
( edgeSize :: R.State Range.NumberRange = ( edgeSize :: R.State Range.NumberRange
, labelSize :: R.State Number , labelSize :: R.State Number
, nodeSize :: R.State Range.NumberRange , nodeSize :: R.State Range.NumberRange
, pauseForceAtlas :: R.State Boolean , pauseForceAtlas :: R.State Boolean
, showEdges :: R.State Boolean , showEdges :: R.State Boolean
) )
initialLocalControls :: R.Hooks (Record LocalControls) initialLocalControls :: R.Hooks (Record LocalControls)
initialLocalControls = do initialLocalControls = do
...@@ -55,14 +58,13 @@ initialLocalControls = do ...@@ -55,14 +58,13 @@ initialLocalControls = do
nodeSize <- R.useState' $ Range.Closed { min: 5.0, max: 10.0 } nodeSize <- R.useState' $ Range.Closed { min: 5.0, max: 10.0 }
pauseForceAtlas <- R.useState' true pauseForceAtlas <- R.useState' true
showEdges <- R.useState' true showEdges <- R.useState' true
pure
pure $ { $ { edgeSize
edgeSize , labelSize
, labelSize , nodeSize
, nodeSize , pauseForceAtlas
, pauseForceAtlas , showEdges
, showEdges }
}
controls :: Record Controls -> R.Element controls :: Record Controls -> R.Element
controls props = R.createElement controlsCpt props [] controls props = R.createElement controlsCpt props []
...@@ -70,77 +72,77 @@ controls props = R.createElement controlsCpt props [] ...@@ -70,77 +72,77 @@ controls props = R.createElement controlsCpt props []
controlsCpt :: R.Component Controls controlsCpt :: R.Component Controls
controlsCpt = R.hooksComponent "GraphControls" cpt controlsCpt = R.hooksComponent "GraphControls" cpt
where where
cpt props _ = do cpt props _ = do
localControls <- initialLocalControls localControls <- initialLocalControls
pure
pure $ case getShowControls props of $ case getShowControls props of
false -> RH.div {} [] false -> RH.div {} []
true -> RH.div { className: "col-md-12", style: { paddingBottom: "10px" } } true ->
[ R2.menu { id: "toolbar" } RH.div { className: "col-md-12", style: { paddingBottom: "10px" } }
[ RH.ul {} [ R2.menu { id: "toolbar" }
[ -- change type button (?) [ RH.ul {}
RH.li {} [ centerButton props.sigmaRef ] [ -- change type button (?) RH.li {} [ centerButton props.sigmaRef ]
, RH.li {} [ pauseForceAtlasButton props.sigmaRef localControls.pauseForceAtlas ] -- spatialization (pause ForceAtlas2) , RH.li {} [ pauseForceAtlasButton props.sigmaRef localControls.pauseForceAtlas ] -- spatialization (pause ForceAtlas2)
, RH.li {} [ edgesToggleButton props.sigmaRef localControls.showEdges ] , RH.li {} [ edgesToggleButton props.sigmaRef localControls.showEdges ]
, RH.li {} [ edgeSizeControl props.sigmaRef localControls.edgeSize ] -- edge size : 0-3 , RH.li {} [ edgeSizeControl props.sigmaRef localControls.edgeSize ] -- edge size : 0-3
-- change level -- change level
-- file upload -- file upload
-- run demo -- run demo
-- search button -- search button
-- search topics -- search topics
, RH.li {} [ cursorSizeButton props.cursorSize ] -- cursor size: 0-100 , RH.li {} [ cursorSizeButton props.cursorSize ] -- cursor size: 0-100
, RH.li {} [ labelSizeButton props.sigmaRef localControls.labelSize ] -- labels size: 1-4 , RH.li {} [ labelSizeButton props.sigmaRef localControls.labelSize ] -- labels size: 1-4
, RH.li {} [ nodeSizeControl props.sigmaRef localControls.nodeSize ] -- node size : 5-15 , RH.li {} [ nodeSizeControl props.sigmaRef localControls.nodeSize ] -- node size : 5-15
-- zoom: 0 -100 - calculate ratio -- zoom: 0 -100 - calculate ratio
-- toggle multi node selection -- toggle multi node selection
-- save button -- save button
] ]
]
] ]
]
useGraphControls :: R.Hooks (Record Controls) useGraphControls :: R.Hooks (Record Controls)
useGraphControls = do useGraphControls = do
cursorSize <- R.useState' 10.0 cursorSize <- R.useState' 10.0
multiNodeSelect <- R.useRef false multiNodeSelect <- R.useRef false
showControls <- R.useState' false showControls <- R.useState' false
showSidePanel <- R.useState' false showSidePanel <- R.useState' false
showTree <- R.useState' false showTree <- R.useState' false
sigmaRef <- R2.nothingRef sigmaRef <- R2.nothingRef
pure
pure { cursorSize { cursorSize
, multiNodeSelect , multiNodeSelect
, showControls , showControls
, showSidePanel , showSidePanel
, showTree , showTree
, sigmaRef , sigmaRef
} }
getShowControls :: Record Controls -> Boolean getShowControls :: Record Controls -> Boolean
getShowControls { showControls: ( should /\ _ ) } = should getShowControls { showControls: (should /\ _) } = should
getShowSidePanel :: Record Controls -> Boolean getShowSidePanel :: Record Controls -> Boolean
getShowSidePanel { showSidePanel: ( should /\ _ ) } = should getShowSidePanel { showSidePanel: (should /\ _) } = should
getShowTree :: Record Controls -> Boolean getShowTree :: Record Controls -> Boolean
getShowTree { showTree: ( should /\ _ ) } = should getShowTree { showTree: (should /\ _) } = should
getCursorSize :: Record Controls -> Number getCursorSize :: Record Controls -> Number
getCursorSize { cursorSize: ( size /\ _ ) } = size getCursorSize { cursorSize: (size /\ _) } = size
getMultiNodeSelect :: Record Controls -> Boolean getMultiNodeSelect :: Record Controls -> Boolean
getMultiNodeSelect { multiNodeSelect } = R.readRef multiNodeSelect getMultiNodeSelect { multiNodeSelect } = R.readRef multiNodeSelect
setShowControls :: Record Controls -> Boolean -> Effect Unit setShowControls :: Record Controls -> Boolean -> Effect Unit
setShowControls { showControls: ( _ /\ set ) } v = set $ const v setShowControls { showControls: (_ /\ set) } v = set $ const v
setShowSidePanel :: Record Controls -> Boolean -> Effect Unit setShowSidePanel :: Record Controls -> Boolean -> Effect Unit
setShowSidePanel { showSidePanel: ( _ /\ set ) } v = set $ const v setShowSidePanel { showSidePanel: (_ /\ set) } v = set $ const v
setShowTree :: Record Controls -> Boolean -> Effect Unit setShowTree :: Record Controls -> Boolean -> Effect Unit
setShowTree { showTree: ( _ /\ set ) } v = set $ not <<< const v setShowTree { showTree: (_ /\ set) } v = set $ not <<< const v
setCursorSize :: Record Controls -> Number -> Effect Unit setCursorSize :: Record Controls -> Number -> Effect Unit
setCursorSize { cursorSize: ( _ /\ setSize ) } v = setSize $ const v setCursorSize { cursorSize: (_ /\ setSize) } v = setSize $ const v
setMultiNodeSelect :: Record Controls -> Boolean -> Effect Unit setMultiNodeSelect :: Record Controls -> Boolean -> Effect Unit
setMultiNodeSelect { multiNodeSelect } = R.setRef multiNodeSelect setMultiNodeSelect { multiNodeSelect } = R.setRef multiNodeSelect
...@@ -7,7 +7,8 @@ import Prelude ...@@ -7,7 +7,8 @@ import Prelude
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
type Props = ( state :: R.State Boolean ) type Props
= ( state :: R.State Boolean )
controlsToggleButton :: Record Props -> R.Element controlsToggleButton :: Record Props -> R.Element
controlsToggleButton props = R.createElement controlsToggleButtonCpt props [] controlsToggleButton props = R.createElement controlsToggleButtonCpt props []
...@@ -15,11 +16,14 @@ controlsToggleButton props = R.createElement controlsToggleButtonCpt props [] ...@@ -15,11 +16,14 @@ controlsToggleButton props = R.createElement controlsToggleButtonCpt props []
controlsToggleButtonCpt :: R.Component Props controlsToggleButtonCpt :: R.Component Props
controlsToggleButtonCpt = R.hooksComponent "GraphControlsToggleButton" cpt controlsToggleButtonCpt = R.hooksComponent "GraphControlsToggleButton" cpt
where where
cpt {state} _ = do cpt { state } _ = do
let (open /\ setOpen) = state let
pure $ (open /\ setOpen) = state
H.button pure
{ className: "btn btn-primary", on: {click: \_ -> setOpen not } } $ H.button
{ className: "btn btn-primary", on: { click: \_ -> setOpen not } }
[ H.text (text open) ] [ H.text (text open) ]
text true = "Hide Controls"
text false = "Show Controls" text true = "Hide Controls"
text false = "Show Controls"
...@@ -3,14 +3,14 @@ module Gargantext.Components.GraphExplorer.Legend ...@@ -3,14 +3,14 @@ module Gargantext.Components.GraphExplorer.Legend
) where ) where
import Prelude hiding (map) import Prelude hiding (map)
import Data.Sequence (Seq) import Data.Sequence (Seq)
import Data.Traversable (foldMap) import Data.Traversable (foldMap)
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as RH import Reactix.DOM.HTML as RH
import Gargantext.Components.GraphExplorer.Types (Legend(..), intColor) import Gargantext.Components.GraphExplorer.Types (Legend(..), intColor)
type Props = ( items :: Seq Legend ) type Props
= ( items :: Seq Legend )
legend :: Record Props -> R.Element legend :: Record Props -> R.Element
legend props = R.createElement legendCpt props [] legend props = R.createElement legendCpt props []
...@@ -18,11 +18,11 @@ legend props = R.createElement legendCpt props [] ...@@ -18,11 +18,11 @@ legend props = R.createElement legendCpt props []
legendCpt :: R.Component Props legendCpt :: R.Component Props
legendCpt = R.hooksComponent "Legend" cpt legendCpt = R.hooksComponent "Legend" cpt
where where
cpt {items} _ = pure $ RH.div {} [foldMap entry items] cpt { items } _ = pure $ RH.div {} [ foldMap entry items ]
entry :: Legend -> R.Element entry :: Legend -> R.Element
entry (Legend {id_, label}) = entry (Legend { id_, label }) =
RH.p {} RH.p {}
[ RH.span { style: { width: 10, height: 10, backgroundColor: intColor id_, display: "inline-block" } } [] [ RH.span { style: { width: 10, height: 10, backgroundColor: intColor id_, display: "inline-block" } } []
, RH.text $ " " <> label , RH.text $ " " <> label
] ]
...@@ -10,16 +10,15 @@ import Data.Maybe (Maybe(..)) ...@@ -10,16 +10,15 @@ import Data.Maybe (Maybe(..))
import Data.Tuple.Nested ((/\)) import Data.Tuple.Nested ((/\))
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
import Gargantext.Components.RangeSlider as RS import Gargantext.Components.RangeSlider as RS
import Gargantext.Hooks.Sigmax as Sigmax import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Sigma as Sigma import Gargantext.Hooks.Sigmax.Sigma as Sigma
import Gargantext.Utils.Range as Range import Gargantext.Utils.Range as Range
type Props = ( type Props
caption :: String = ( caption :: String
, sliderProps :: Record RS.Props , sliderProps :: Record RS.Props
) )
rangeControl :: Record Props -> R.Element rangeControl :: Record Props -> R.Element
rangeControl props = R.createElement rangeControlCpt props [] rangeControl props = R.createElement rangeControlCpt props []
...@@ -27,55 +26,61 @@ rangeControl props = R.createElement rangeControlCpt props [] ...@@ -27,55 +26,61 @@ rangeControl props = R.createElement rangeControlCpt props []
rangeControlCpt :: R.Component Props rangeControlCpt :: R.Component Props
rangeControlCpt = R.hooksComponent "RangeButton" cpt rangeControlCpt = R.hooksComponent "RangeButton" cpt
where where
cpt {caption, sliderProps} _ = do cpt { caption, sliderProps } _ = do
pure $ pure
H.span {className: "range text-center"} $ H.span { className: "range text-center" }
[ H.label {} [ H.text caption ] [ H.label {} [ H.text caption ]
, RS.rangeSlider sliderProps , RS.rangeSlider sliderProps
] ]
edgeSizeControl :: R.Ref (Maybe Sigmax.Sigma) -> R.State Range.NumberRange -> R.Element edgeSizeControl :: R.Ref (Maybe Sigmax.Sigma) -> R.State Range.NumberRange -> R.Element
edgeSizeControl sigmaRef (state /\ setState) = edgeSizeControl sigmaRef (state /\ setState) =
rangeControl { rangeControl
caption: "Edge Size" { caption: "Edge Size"
, sliderProps: { , sliderProps:
bounds: Range.Closed { min: 0.0, max: 3.0 } { bounds: Range.Closed { min: 0.0, max: 3.0 }
, initialValue: state , initialValue: state
, epsilon: 0.1 , epsilon: 0.1
, step: 1.0 , step: 1.0
, width: 10.0 , width: 10.0
, height: 5.0 , height: 5.0
, onChange: \range@(Range.Closed {min, max}) -> do , onChange:
let mSigma = Sigmax.readSigma <$> R.readRef sigmaRef \range@(Range.Closed { min, max }) -> do
let
mSigma = Sigmax.readSigma <$> R.readRef sigmaRef
case mSigma of case mSigma of
Just (Just s) -> Sigma.setSettings s { Just (Just s) ->
minEdgeSize: min Sigma.setSettings s
, maxEdgeSize: max { minEdgeSize: min
} , maxEdgeSize: max
_ -> pure unit }
_ -> pure unit
setState $ const range setState $ const range
} }
} }
nodeSizeControl :: R.Ref (Maybe Sigmax.Sigma) -> R.State Range.NumberRange -> R.Element nodeSizeControl :: R.Ref (Maybe Sigmax.Sigma) -> R.State Range.NumberRange -> R.Element
nodeSizeControl sigmaRef (state /\ setState) = nodeSizeControl sigmaRef (state /\ setState) =
rangeControl { rangeControl
caption: "Node Size" { caption: "Node Size"
, sliderProps: { , sliderProps:
bounds: Range.Closed { min: 5.0, max: 15.0 } { bounds: Range.Closed { min: 5.0, max: 15.0 }
, initialValue: state , initialValue: state
, epsilon: 0.1 , epsilon: 0.1
, step: 1.0 , step: 1.0
, width: 10.0 , width: 10.0
, height: 5.0 , height: 5.0
, onChange: \range@(Range.Closed {min, max}) -> do , onChange:
let mSigma = Sigmax.readSigma <$> R.readRef sigmaRef \range@(Range.Closed { min, max }) -> do
let
mSigma = Sigmax.readSigma <$> R.readRef sigmaRef
case mSigma of case mSigma of
Just (Just s) -> Sigma.setSettings s { Just (Just s) ->
minNodeSize: min Sigma.setSettings s
, maxNodeSize: max { minNodeSize: min
} , maxNodeSize: max
_ -> pure unit }
_ -> pure unit
setState $ const range setState $ const range
} }
} }
module Gargantext.Components.GraphExplorer.Sidebar module Gargantext.Components.GraphExplorer.Sidebar (Props, sidebar) where
(Props, sidebar)
where
import Prelude import Prelude
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as RH import Reactix.DOM.HTML as RH
type Props = ( showSidePanel :: Boolean ) type Props
= ( showSidePanel :: Boolean )
sidebar :: Record Props -> R.Element sidebar :: Record Props -> R.Element
sidebar props = R.createElement sidebarCpt props [] sidebar props = R.createElement sidebarCpt props []
...@@ -14,48 +13,66 @@ sidebar props = R.createElement sidebarCpt props [] ...@@ -14,48 +13,66 @@ sidebar props = R.createElement sidebarCpt props []
sidebarCpt :: R.Component Props sidebarCpt :: R.Component Props
sidebarCpt = R.hooksComponent "Sidebar" cpt sidebarCpt = R.hooksComponent "Sidebar" cpt
where where
cpt {showSidePanel: false} _children = do cpt { showSidePanel: false } _children = do
pure $ RH.div {} [] pure $ RH.div {} []
cpt props _children = do
pure $ cpt props _children = do
RH.div { id: "sp-container", className: "col-md-2" } pure
[ RH.div {} $ RH.div { id: "sp-container", className: "col-md-2" }
[ RH.div { className: "row" } [ RH.div {}
[ RH.div { className: "col-md-12" } [ RH.div { className: "row" }
[ RH.ul { id: "myTab", className: "nav nav-tabs", role: "tablist"} [ RH.div { className: "col-md-12" }
[ RH.li { className: "nav-item" } [ RH.ul { id: "myTab", className: "nav nav-tabs", role: "tablist" }
[ RH.a { id: "home-tab" [ RH.li { className: "nav-item" }
, className: "nav-link active" [ RH.a
, data: {toggle: "tab"} { id: "home-tab"
, href: "#home" , className: "nav-link active"
, role: "tab" , data: { toggle: "tab" }
, aria: {controls: "home", selected: "true"}} , href: "#home"
[ RH.text "Neighbours" ] ] ] , role: "tab"
, RH.div { className: "tab-content", id: "myTabContent" } , aria: { controls: "home", selected: "true" }
[ RH.div { className: "", id: "home", role: "tabpanel" } }
(badge <$> badges) ] ] [ RH.text "Neighbours" ]
, RH.div { className: "col-md-12", id: "horizontal-checkbox" } ]
[ RH.ul {} ]
[ checkbox "Pubs" , RH.div { className: "tab-content", id: "myTabContent" }
, checkbox "Projects" [ RH.div { className: "", id: "home", role: "tabpanel" }
, checkbox "Patents" (badge <$> badges)
, checkbox "Others" ] ] ] ] ] ]
badge text = ]
RH.a { className: "badge badge-light" } [ RH.text text ] , RH.div { className: "col-md-12", id: "horizontal-checkbox" }
checkbox text = [ RH.ul {}
RH.li {} [ checkbox "Pubs"
, checkbox "Projects"
, checkbox "Patents"
, checkbox "Others"
]
]
]
]
]
badge text = RH.a { className: "badge badge-light" } [ RH.text text ]
checkbox text =
RH.li {}
[ RH.span {} [ RH.text text ] [ RH.span {} [ RH.text text ]
, RH.input { type: "checkbox" , RH.input
, className: "checkbox" { type: "checkbox"
, checked: true , className: "checkbox"
, title: "Mark as completed" } ] , checked: true
badges = , title: "Mark as completed"
[ "objects" }
, "evaluation" ]
, "dynamics"
, "virtual environments" badges =
, "virtual reality" [ "objects"
, "performance analysis" , "evaluation"
, "software engineering" , "dynamics"
, "complex systems" , "virtual environments"
, "wireless communications" ] , "virtual reality"
, "performance analysis"
, "software engineering"
, "complex systems"
, "wireless communications"
]
module Gargantext.Components.Data.Lang where module Gargantext.Components.Data.Lang where
data Lang = EN | FR data Lang
= EN
| FR
This diff is collapsed.
...@@ -3,7 +3,8 @@ module Gargantext.Components.LoadingSpinner where ...@@ -3,7 +3,8 @@ module Gargantext.Components.LoadingSpinner where
import Reactix as R import Reactix as R
import Reactix.DOM.HTML as H import Reactix.DOM.HTML as H
type Props = () type Props
= ()
loadingSpinner :: Record Props -> R.Element loadingSpinner :: Record Props -> R.Element
loadingSpinner props = R.createElement loadingSpinnerCpt props [] loadingSpinner props = R.createElement loadingSpinnerCpt props []
...@@ -11,4 +12,4 @@ loadingSpinner props = R.createElement loadingSpinnerCpt props [] ...@@ -11,4 +12,4 @@ loadingSpinner props = R.createElement loadingSpinnerCpt props []
loadingSpinnerCpt :: R.Component Props loadingSpinnerCpt :: R.Component Props
loadingSpinnerCpt = R.staticComponent "LoadingSpinner" cpt loadingSpinnerCpt = R.staticComponent "LoadingSpinner" cpt
where where
cpt _ _ = H.span {} [H.text "[Loading]"] cpt _ _ = H.span {} [ H.text "[Loading]" ]
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
module Gargantext.Components.Modals.Modal where module Gargantext.Components.Modals.Modal where
import Prelude (Unit) import Prelude (Unit)
import Effect (Effect) import Effect (Effect)
foreign import modalShow :: String -> Effect Unit foreign import modalShow :: String -> Effect Unit
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -13,4 +13,3 @@ useHashRouter routes init = do ...@@ -13,4 +13,3 @@ useHashRouter routes init = do
route@(_ /\ setRoute) <- R.useState' init route@(_ /\ setRoute) <- R.useState' init
R.useEffectOnce $ matches routes $ \_old new -> setRoute (const new) R.useEffectOnce $ matches routes $ \_old new -> setRoute (const new)
pure route pure route
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
...@@ -16,4 +16,5 @@ main = paint $ toMaybe (document ... "getElementById" $ [ "app" ]) ...@@ -16,4 +16,5 @@ main = paint $ toMaybe (document ... "getElementById" $ [ "app" ])
paint :: Maybe Element -> Effect Unit paint :: Maybe Element -> Effect Unit
paint Nothing = log "[main] Container not found" paint Nothing = log "[main] Container not found"
paint (Just c) = R2.render (app {}) c paint (Just c) = R2.render (app {}) c
This diff is collapsed.
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