diff --git a/dist/styles/bootstrap-darkster.css b/dist/styles/bootstrap-darkster.css index fabb7b28ddd688137ae007b85f3b4968552c2ca8..8ce4cb6fcc007f591aaae3128733167e5550e0f5 100644 --- a/dist/styles/bootstrap-darkster.css +++ b/dist/styles/bootstrap-darkster.css @@ -9030,6 +9030,9 @@ a:focus { .range-slider__knob:focus { outline: 0; } +.range-slider__knob.disabled { + cursor: not-allowed; +} .range-slider__knob:hover { background-color: #0a0a0a; } @@ -9064,6 +9067,9 @@ a:focus { .range-simple__field { position: relative; } +.range-simple input[disabled] { + cursor: not-allowed; +} input[type=range] { cursor: pointer; diff --git a/dist/styles/bootstrap-default.css b/dist/styles/bootstrap-default.css index 683f05899641b25e7a6b4d4fd17d746a5396c82b..5f7f684145dcabfbb635a35e8931595ae388a495 100644 --- a/dist/styles/bootstrap-default.css +++ b/dist/styles/bootstrap-default.css @@ -8983,6 +8983,9 @@ a:focus { .range-slider__knob:focus { outline: 0; } +.range-slider__knob.disabled { + cursor: not-allowed; +} .range-slider__knob:hover { background-color: #0056b3; } @@ -9017,6 +9020,9 @@ a:focus { .range-simple__field { position: relative; } +.range-simple input[disabled] { + cursor: not-allowed; +} input[type=range] { cursor: pointer; diff --git a/dist/styles/bootstrap-greyson.css b/dist/styles/bootstrap-greyson.css index 03b8ed6a1167069952b83c7271e5738eddb7ec99..8bde86adcaf1bdaa90b4633b4b3e96a6ade4940c 100644 --- a/dist/styles/bootstrap-greyson.css +++ b/dist/styles/bootstrap-greyson.css @@ -8739,6 +8739,9 @@ a:focus { .range-slider__knob:focus { outline: 0; } +.range-slider__knob.disabled { + cursor: not-allowed; +} .range-slider__knob:hover { background-color: #4d5861; } @@ -8773,6 +8776,9 @@ a:focus { .range-simple__field { position: relative; } +.range-simple input[disabled] { + cursor: not-allowed; +} input[type=range] { cursor: pointer; diff --git a/dist/styles/bootstrap-herbie.css b/dist/styles/bootstrap-herbie.css index 53aa372cdba75d86e38b807cf4da715e3bfae6bc..951120659cce5b1b6908b857c75fc24693913f13 100644 --- a/dist/styles/bootstrap-herbie.css +++ b/dist/styles/bootstrap-herbie.css @@ -8987,6 +8987,9 @@ a:focus { .range-slider__knob:focus { outline: 0; } +.range-slider__knob.disabled { + cursor: not-allowed; +} .range-slider__knob:hover { background-color: #f12a3f; } @@ -9021,6 +9024,9 @@ a:focus { .range-simple__field { position: relative; } +.range-simple input[disabled] { + cursor: not-allowed; +} input[type=range] { cursor: pointer; diff --git a/dist/styles/bootstrap-monotony.css b/dist/styles/bootstrap-monotony.css index 815354ccd3f49c9766e0ccf9f88c211d4da657b5..d265d21a4ecf8689b56160b60f66bf3ce133d3b3 100644 --- a/dist/styles/bootstrap-monotony.css +++ b/dist/styles/bootstrap-monotony.css @@ -8988,6 +8988,9 @@ a:focus { .range-slider__knob:focus { outline: 0; } +.range-slider__knob.disabled { + cursor: not-allowed; +} .range-slider__knob:hover { background-color: #404040; } @@ -9022,6 +9025,9 @@ a:focus { .range-simple__field { position: relative; } +.range-simple input[disabled] { + cursor: not-allowed; +} input[type=range] { cursor: pointer; diff --git a/src/Gargantext/Components/GraphExplorer/Toolbar/Controls.purs b/src/Gargantext/Components/GraphExplorer/Toolbar/Controls.purs index 0a45d0728c21f4ad745b5248e24889c8cf473294..481c592ce10b5629ceb0b36f31a880ab926cc5a7 100644 --- a/src/Gargantext/Components/GraphExplorer/Toolbar/Controls.purs +++ b/src/Gargantext/Components/GraphExplorer/Toolbar/Controls.purs @@ -252,11 +252,13 @@ controlsCpt = R.memo' $ here.component "controls" cpt where { className: "d-flex justify-content-between mb-3" } [ edgeConfluenceControl - { range: edgeConfluenceRange + { forceAtlasState + , range: edgeConfluenceRange , state: edgeConfluence } , edgeWeightControl - { range: edgeWeightRange + { forceAtlasState + , range: edgeWeightRange , state: edgeWeight } ] , @@ -274,7 +276,8 @@ controlsCpt = R.memo' $ here.component "controls" cpt where , -- labels size: 1-4 nodeSizeControl - { range: nodeSizeRange + { forceAtlasState + , range: nodeSizeRange , state: nodeSize } ] diff --git a/src/Gargantext/Components/GraphExplorer/Toolbar/RangeControl.purs b/src/Gargantext/Components/GraphExplorer/Toolbar/RangeControl.purs index 8305a9686abe694fb520993e7282b6a00a4c9a6c..a50bacb551bbb2ab1e847ca76558c1e6b6d7c6bd 100644 --- a/src/Gargantext/Components/GraphExplorer/Toolbar/RangeControl.purs +++ b/src/Gargantext/Components/GraphExplorer/Toolbar/RangeControl.purs @@ -12,6 +12,7 @@ import Reactix.DOM.HTML as H import Toestand as T import Gargantext.Components.RangeSlider as RS +import Gargantext.Hooks.Sigmax.Types as SigmaxTypes import Gargantext.Utils.Range as Range import Gargantext.Utils.Reactix as R2 @@ -28,23 +29,23 @@ rangeControl = R2.leaf rangeControlCpt rangeControlCpt :: R.Component Props rangeControlCpt = here.component "rangeButton" cpt where - cpt {caption, sliderProps} _ = pure $ - - H.span - { className: "range-control" } - [ - H.label - { className: "range-control__label" } - [ H.text caption ] - , - RS.rangeSlider sliderProps - ] + cpt { caption, sliderProps } _ = do + pure $ H.span + { className: "range-control" } + [ + H.label + { className: "range-control__label" } + [ H.text caption ] + , + RS.rangeSlider sliderProps + ] ---------------------------------------- type EdgeConfluenceControlProps = - ( range :: Range.NumberRange - , state :: T.Box Range.NumberRange + ( forceAtlasState :: T.Box SigmaxTypes.ForceAtlasState + , range :: Range.NumberRange + , state :: T.Box Range.NumberRange ) edgeConfluenceControl :: R2.Leaf EdgeConfluenceControlProps @@ -52,28 +53,32 @@ edgeConfluenceControl = R2.leaf edgeConfluenceControlCpt edgeConfluenceControlCpt :: R.Component EdgeConfluenceControlProps edgeConfluenceControlCpt = here.component "edgeConfluenceControl" cpt where - cpt { range: Range.Closed { min, max } + cpt { forceAtlasState + , range: Range.Closed { min, max } , state } _ = do + forceAtlasState' <- R2.useLive' forceAtlasState state' <- T.useLive T.unequal state pure $ rangeControl { caption: "Edge Confluence Weight" , sliderProps: { - bounds: Range.Closed { min, max } - , initialValue: state' + bounds: Range.Closed { min, max } , epsilon: 0.01 - , step: 1.0 - , width: 10.0 , height: 5.0 + , initialValue: state' , onChange: \rng -> T.write_ rng state + , status: SigmaxTypes.forceAtlasComponentStatus forceAtlasState' + , step: 1.0 + , width: 10.0 } } -------------------------------------- type EdgeWeightControlProps = - ( range :: Range.NumberRange + ( forceAtlasState :: T.Box SigmaxTypes.ForceAtlasState + , range :: Range.NumberRange , state :: T.Box Range.NumberRange ) @@ -82,9 +87,11 @@ edgeWeightControl = R2.leaf edgeWeightControlCpt edgeWeightControlCpt :: R.Component EdgeWeightControlProps edgeWeightControlCpt = here.component "edgeWeightControl" cpt where - cpt { range: Range.Closed { min, max } + cpt { forceAtlasState + , range: Range.Closed { min, max } , state } _ = do + forceAtlasState' <- R2.useLive' forceAtlasState state' <- T.useLive T.unequal state pure $ rangeControl { @@ -93,19 +100,20 @@ edgeWeightControlCpt = here.component "edgeWeightControl" cpt bounds: Range.Closed { min, max } , initialValue: state' , epsilon: 1.0 + , height: 5.0 + , onChange: \rng -> T.write_ rng state + , status: SigmaxTypes.forceAtlasComponentStatus forceAtlasState' , step: 1.0 , width: 10.0 - , height: 5.0 - , onChange: \rng -> do - T.write_ rng state } } -------------------------------------- type NodeSideControlProps = - ( range :: Range.NumberRange - , state :: T.Box Range.NumberRange + ( forceAtlasState :: T.Box SigmaxTypes.ForceAtlasState + , range :: Range.NumberRange + , state :: T.Box Range.NumberRange ) nodeSizeControl :: R2.Leaf NodeSideControlProps @@ -113,10 +121,12 @@ nodeSizeControl = R2.leaf nodeSizeControlCpt nodeSizeControlCpt :: R.Component NodeSideControlProps nodeSizeControlCpt = here.component "nodeSizeControl" cpt where - cpt { range: Range.Closed { min, max } + cpt { forceAtlasState + , range: Range.Closed { min, max } , state } _ = do - state' <- T.useLive T.unequal state + forceAtlasState' <- R2.useLive' forceAtlasState + state' <- R2.useLive' state pure $ rangeControl { caption: "Node Size" @@ -124,9 +134,10 @@ nodeSizeControlCpt = here.component "nodeSizeControl" cpt bounds: Range.Closed { min, max } , initialValue: state' , epsilon: 0.1 - , step: 1.0 - , width: 10.0 , height: 5.0 , onChange: \rng -> T.write_ rng state + , status: SigmaxTypes.forceAtlasComponentStatus forceAtlasState' + , step: 1.0 + , width: 10.0 } } diff --git a/src/Gargantext/Components/GraphExplorer/Toolbar/SlideButton.purs b/src/Gargantext/Components/GraphExplorer/Toolbar/SlideButton.purs index 3f32627d38c7bf7d83a04ffa801f54bfcab6058b..61a08237e89884d68f745d7ba429771cce7fd4b0 100644 --- a/src/Gargantext/Components/GraphExplorer/Toolbar/SlideButton.purs +++ b/src/Gargantext/Components/GraphExplorer/Toolbar/SlideButton.purs @@ -68,8 +68,8 @@ sizeButtonCpt = here.component "sizeButton" cpt where type LabelSizeButtonProps = ( forceAtlasState :: T.Box SigmaxTypes.ForceAtlasState - , sigmaRef :: R.Ref Sigmax.Sigma - , state :: T.Box Number) + , sigmaRef :: R.Ref Sigmax.Sigma + , state :: T.Box Number) labelSizeButton :: R2.Leaf LabelSizeButtonProps labelSizeButton = R2.leaf labelSizeButtonCpt diff --git a/src/Gargantext/Components/Nodes/Graph.purs b/src/Gargantext/Components/Nodes/Graph.purs index d82af04ab85c188ecad648efdf48fbbc0867bde5..7faefbed13c2397027356ed02172800d4d8ef82c 100644 --- a/src/Gargantext/Components/Nodes/Graph.purs +++ b/src/Gargantext/Components/Nodes/Graph.purs @@ -13,7 +13,6 @@ import Data.Tuple.Nested ((/\)) import Gargantext.Components.App.Store as AppStore import Gargantext.Components.Bootstrap as B import Gargantext.Components.GraphExplorer.API as GraphAPI -import Gargantext.Components.GraphExplorer.GraphTypes as GEGT import Gargantext.Components.GraphExplorer.Layout (convert, layout) import Gargantext.Components.GraphExplorer.Store as GraphStore import Gargantext.Components.GraphExplorer.Types as GET diff --git a/src/Gargantext/Components/RangeSlider.purs b/src/Gargantext/Components/RangeSlider.purs index 34fe61237ead8bf0757b5755a2597d29fc634b2b..41dcafc867be067f0701aa07ec95fd5880bc1410 100644 --- a/src/Gargantext/Components/RangeSlider.purs +++ b/src/Gargantext/Components/RangeSlider.purs @@ -27,6 +27,7 @@ import Toestand as T import Gargantext.Prelude +import Gargantext.Components.Bootstrap.Types (ComponentStatus(..)) import Gargantext.Utils.Math (roundToMultiple) import Gargantext.Utils.Range as Range import Gargantext.Utils.Reactix as R2 @@ -42,14 +43,15 @@ type Epsilon = Number -- and 'max' as being the bounds of the scale and 'low' and 'high' as -- being the selected values type Props = - ( bounds :: Bounds -- The minimum and maximum values it is possible to select + ( bounds :: Bounds -- The minimum and maximum values it is possible to select , initialValue :: Range.NumberRange -- The user's selection of minimum and maximum values - , epsilon :: Number -- The smallest possible change (for mouse) - , step :: Number -- The 'standard' change (for keyboard) - -- , axis :: Axis -- Which direction to move in - , width :: Number - , height :: Number - , onChange :: Range.NumberRange -> Effect Unit ) + , epsilon :: Number -- The smallest possible change (for mouse) + , step :: Number -- The 'standard' change (for keyboard) + -- , axis :: Axis -- Which direction to move in + , width :: Number + , height :: Number + , onChange :: Range.NumberRange -> Effect Unit + , status :: ComponentStatus ) data Knob = MinKnob | MaxKnob derive instance Generic Knob _ @@ -129,8 +131,8 @@ rangeSliderCpt = here.component "rangeSlider" cpt pure $ H.div { className, aria } [ renderScale scaleElem props value' , renderScaleSel scaleSelElem props value' - , renderKnob MinKnob lowElem value' props.bounds dragKnob precision - , renderKnob MaxKnob highElem value' props.bounds dragKnob precision + , renderKnob MinKnob lowElem value' props.bounds dragKnob precision props.status + , renderKnob MaxKnob highElem value' props.bounds dragKnob precision props.status ] className = "range-slider" aria = { label: "Range Slider Control. Expresses filtering data by a minimum and maximum value range through two slider knobs. Knobs can be adjusted with the arrow keys." } @@ -184,22 +186,24 @@ renderScaleSel ref props (Range.Closed {min, max}) = formatter n = (DNF.toStringWith (DNF.fixed 0) n) <> "%" -renderKnob :: Knob -> R.Ref (Nullable DOM.Element) -> Range.NumberRange -> Bounds -> T.Box (Maybe Knob) -> Int -> R.Element -renderKnob knob ref (Range.Closed value) bounds set precision = +renderKnob :: Knob -> R.Ref (Nullable DOM.Element) -> Range.NumberRange -> Bounds -> T.Box (Maybe Knob) -> Int -> ComponentStatus -> R.Element +renderKnob knob ref (Range.Closed value) bounds set precision status = H.div { ref, tabIndex, className, aria, on: { mouseDown: onMouseDown }, style } [ - H.div { className: "range-slider__placeholder" } + H.div { className: "range-slider__placeholder " } [ H.text $ DNF.toStringWith (DNF.precision precision) val ] ] where tabIndex = 0 - className = "range-slider__knob" + className = "range-slider__knob " <> (show status) aria = { label: labelPrefix knob <> "value: " <> show val } labelPrefix :: Knob -> String labelPrefix MinKnob = "Minimum " labelPrefix MaxKnob = "Maximum " - onMouseDown _ = T.write_ (Just knob) set + onMouseDown _ = case status of + Disabled -> pure unit + _ -> T.write_ (Just knob) set percOffset = Range.normalise bounds val style = { left: (show $ 100.0 * percOffset) <> "%" } val :: Number diff --git a/src/sass/base/_range_slider.sass b/src/sass/base/_range_slider.sass index a0daf9309bf32a89eace4f47b9fb4c082ed57840..9dcde385911d8024e69d92190183804a97be9532 100644 --- a/src/sass/base/_range_slider.sass +++ b/src/sass/base/_range_slider.sass @@ -64,6 +64,9 @@ $knob-size: 14px // alignement with the bar transform: translateX(-5px) translateY(-3px) + &.disabled + cursor: not-allowed + &:hover background-color: darken($range-bg-progress-color, 15%) @@ -102,6 +105,9 @@ $knob-size: 14px &__field position: relative + & input[disabled] + cursor: not-allowed + //////////////////////////////////////////// // Cross browser rules