Commit 3ac13e92 authored by arturo's avatar arturo

[NoteBook] UI/UX improvements

* #387
parent a0974175
......@@ -6220,6 +6220,19 @@ h3 {
background-image: radial-gradient(circle, #000000 10%, transparent 10%);
}
.b-preloader {
width: 100%;
height: 100%;
}
.b-preloader__spinner {
position: absolute;
font-size: 6px;
height: 100px;
width: 100px;
top: calc( 50% - 50px );
left: calc( 50% - 50px );
}
.echarts-for-react {
height: 300px;
}
......@@ -7368,20 +7381,6 @@ input[type=range]:-moz-focusring {
display: none;
}
/* Grid constants */
.graph-loader {
width: 100%;
height: 100%;
}
.graph-loader__spinner {
position: absolute;
font-size: 6px;
height: 100px;
width: 100px;
top: calc( 50% - 50px );
left: calc( 50% - 50px );
}
.graph-layout {
position: relative;
width: 100%;
......@@ -8544,13 +8543,6 @@ a:focus, a:hover {
}
/* */
.frame {
height: 100vh;
}
.frame iframe {
border: 0;
}
.join-button {
padding-bottom: 100px;
padding-top: 100px;
......@@ -9260,6 +9252,12 @@ select.form-control {
margin-left: 20px;
}
.frame-layout {
position: relative;
width: 100%;
height: calc(100vh - 56px );
}
.navbar-dark.bg-primary {
background-color: #111111 !important;
}
......
......@@ -6173,6 +6173,19 @@ h3 {
background-image: radial-gradient(circle, #343a40 10%, transparent 10%);
}
.b-preloader {
width: 100%;
height: 100%;
}
.b-preloader__spinner {
position: absolute;
font-size: 6px;
height: 100px;
width: 100px;
top: calc( 50% - 50px );
left: calc( 50% - 50px );
}
.echarts-for-react {
height: 300px;
}
......@@ -7321,20 +7334,6 @@ input[type=range]:-moz-focusring {
display: none;
}
/* Grid constants */
.graph-loader {
width: 100%;
height: 100%;
}
.graph-loader__spinner {
position: absolute;
font-size: 6px;
height: 100px;
width: 100px;
top: calc( 50% - 50px );
left: calc( 50% - 50px );
}
.graph-layout {
position: relative;
width: 100%;
......@@ -8497,13 +8496,6 @@ a:focus, a:hover {
}
/* */
.frame {
height: 100vh;
}
.frame iframe {
border: 0;
}
.join-button {
padding-bottom: 100px;
padding-top: 100px;
......@@ -9213,6 +9205,12 @@ select.form-control {
margin-left: 20px;
}
.frame-layout {
position: relative;
width: 100%;
height: calc(100vh - 56px );
}
.btn-secondary,
.btn-secondary:hover,
.btn-outline-secondary:not(:disabled):not(.disabled):hover,
......
......@@ -5929,6 +5929,19 @@ h3 {
background-image: radial-gradient(circle, #1e2b37 10%, transparent 10%);
}
.b-preloader {
width: 100%;
height: 100%;
}
.b-preloader__spinner {
position: absolute;
font-size: 6px;
height: 100px;
width: 100px;
top: calc( 50% - 50px );
left: calc( 50% - 50px );
}
.echarts-for-react {
height: 300px;
}
......@@ -7077,20 +7090,6 @@ input[type=range]:-moz-focusring {
display: none;
}
/* Grid constants */
.graph-loader {
width: 100%;
height: 100%;
}
.graph-loader__spinner {
position: absolute;
font-size: 6px;
height: 100px;
width: 100px;
top: calc( 50% - 50px );
left: calc( 50% - 50px );
}
.graph-layout {
position: relative;
width: 100%;
......@@ -8253,13 +8252,6 @@ a:focus, a:hover {
}
/* */
.frame {
height: 100vh;
}
.frame iframe {
border: 0;
}
.join-button {
padding-bottom: 100px;
padding-top: 100px;
......@@ -8969,4 +8961,10 @@ select.form-control {
margin-left: 20px;
}
.frame-layout {
position: relative;
width: 100%;
height: calc(100vh - 56px );
}
/*# sourceMappingURL=bootstrap-greyson.css.map */
......@@ -6177,6 +6177,19 @@ h3 {
background-image: radial-gradient(circle, #072247 10%, transparent 10%);
}
.b-preloader {
width: 100%;
height: 100%;
}
.b-preloader__spinner {
position: absolute;
font-size: 6px;
height: 100px;
width: 100px;
top: calc( 50% - 50px );
left: calc( 50% - 50px );
}
.echarts-for-react {
height: 300px;
}
......@@ -7325,20 +7338,6 @@ input[type=range]:-moz-focusring {
display: none;
}
/* Grid constants */
.graph-loader {
width: 100%;
height: 100%;
}
.graph-loader__spinner {
position: absolute;
font-size: 6px;
height: 100px;
width: 100px;
top: calc( 50% - 50px );
left: calc( 50% - 50px );
}
.graph-layout {
position: relative;
width: 100%;
......@@ -8501,13 +8500,6 @@ a:focus, a:hover {
}
/* */
.frame {
height: 100vh;
}
.frame iframe {
border: 0;
}
.join-button {
padding-bottom: 100px;
padding-top: 100px;
......@@ -9217,4 +9209,10 @@ select.form-control {
margin-left: 20px;
}
.frame-layout {
position: relative;
width: 100%;
height: calc(100vh - 56px );
}
/*# sourceMappingURL=bootstrap-herbie.css.map */
......@@ -6178,6 +6178,19 @@ h3 {
background-image: radial-gradient(circle, #111111 10%, transparent 10%);
}
.b-preloader {
width: 100%;
height: 100%;
}
.b-preloader__spinner {
position: absolute;
font-size: 6px;
height: 100px;
width: 100px;
top: calc( 50% - 50px );
left: calc( 50% - 50px );
}
.echarts-for-react {
height: 300px;
}
......@@ -7326,20 +7339,6 @@ input[type=range]:-moz-focusring {
display: none;
}
/* Grid constants */
.graph-loader {
width: 100%;
height: 100%;
}
.graph-loader__spinner {
position: absolute;
font-size: 6px;
height: 100px;
width: 100px;
top: calc( 50% - 50px );
left: calc( 50% - 50px );
}
.graph-layout {
position: relative;
width: 100%;
......@@ -8502,13 +8501,6 @@ a:focus, a:hover {
}
/* */
.frame {
height: 100vh;
}
.frame iframe {
border: 0;
}
.join-button {
padding-bottom: 100px;
padding-top: 100px;
......@@ -9218,4 +9210,10 @@ select.form-control {
margin-left: 20px;
}
.frame-layout {
position: relative;
width: 100%;
height: calc(100vh - 56px );
}
/*# sourceMappingURL=bootstrap-monotony.css.map */
module Gargantext.Components.Bootstrap.Preloader(preloader) where
import Gargantext.Prelude
import Data.Foldable (intercalate)
import Gargantext.Components.Bootstrap.Spinner (spinner)
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
type Props = ( | Options)
type Options =
( className :: String
)
options :: Record Options
options =
{ className : ""
}
-- | Structural Component wrapping our <Spinner.BorderTheme> within
-- | a basic layout
preloader :: forall r. R2.OptLeaf Options Props r
preloader = R2.optLeaf component options
componentName :: String
componentName = "b-preloader"
component :: R.Component Props
component = R.hooksComponent componentName cpt where
cpt props _ = do
-- Computed
let
className = intercalate " "
-- provided custom className
[ props.className
-- BEM classNames
, componentName
]
-- Render
pure $
H.div
{ className }
[
spinner
{ className: componentName <> "__spinner" }
]
......@@ -36,14 +36,15 @@ component :: R.Component Props
component = R.hooksComponent componentName cpt where
cpt props _ = do
-- Computed
className <- pure $ intercalate " "
-- provided custom className
[ props.className
-- BEM classNames
, componentName
-- Bootstrap specific classNames
, bootstrapName <> "-" <> show props.theme
]
let
className = intercalate " "
-- provided custom className
[ props.className
-- BEM classNames
, componentName
-- Bootstrap specific classNames
, bootstrapName <> "-" <> show props.theme
]
-- Render
pure $
......
......@@ -12,6 +12,7 @@ import Gargantext.Components.Bootstrap.FormSelect(formSelect, formSelect') as Ex
import Gargantext.Components.Bootstrap.FormTextarea(formTextarea) as Exports
import Gargantext.Components.Bootstrap.Icon(icon) as Exports
import Gargantext.Components.Bootstrap.IconButton(iconButton) as Exports
import Gargantext.Components.Bootstrap.Preloader(preloader) as Exports
import Gargantext.Components.Bootstrap.ProgressBar(progressBar) as Exports
import Gargantext.Components.Bootstrap.Ripple(ripple) as Exports
import Gargantext.Components.Bootstrap.Spinner(spinner) as Exports
......@@ -32,4 +33,5 @@ import Gargantext.Components.Bootstrap.Shortcut(
, b', b_
, code', code_
, label', label_
, p', p_
) as Exports
......@@ -11,6 +11,7 @@ module Gargantext.Components.Bootstrap.Shortcut
, b', b_
, code', code_
, label', label_
, p', p_
) where
import Reactix as R
......@@ -112,3 +113,11 @@ label' props content = H.label props [ H.text content ]
-- | Shorthand for using HTML <label> without writing its text node nor props
label_ :: String -> R.Element
label_ content = H.label {} [ H.text content ]
-- | Shorthand for using HTML <p> without writing its text node
p' :: forall r. Record r -> String -> R.Element
p' props content = H.p props [ H.text content ]
-- | Shorthand for using HTML <p> without writing its text node nor props
p_ :: String -> R.Element
p_ content = H.p {} [ H.text content ]
module Gargantext.Components.Frame.Layout
( layout
) where
import Gargantext.Prelude
import DOM.Simple (document, querySelector)
import DOM.Simple as DOM
import Data.Maybe (Maybe(..))
import Data.Nullable (Nullable, null, toMaybe)
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Bootstrap.Types (Variant(..))
import Gargantext.Components.FolderView as FV
import Gargantext.Components.Frame.Types (Base, Hyperdata(..), FrameId)
import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Types (NodeType(..))
import Gargantext.Utils.JitsiMeet as JM
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2
import Reactix as R
import Reactix.DOM.HTML as H
import Web.URL as WURL
here :: R2.Here
here = R2.here "Gargantext.Components.Frame.Layout"
type Props =
( frame :: NodePoly Hyperdata
, reload :: T2.ReloadS
, nodeId :: Int
, nodeType :: NodeType
)
layout :: R2.Leaf Props
layout = R2.leaf layoutCpt
layoutCpt :: R.Component Props
layoutCpt = here.component "main" cpt where
cpt { frame: NodePoly { hyperdata: h@(Hyperdata { base, frame_id }) }
, nodeId
, nodeType
, reload
} _ = case nodeType of
-- Visio Node
NodeFrameVisio ->
case WURL.fromAbsolute base of
Nothing ->
pure $
B.caveat
{ variant: Warning }
[
H.text $ "Wrong base url: " <> base
]
Just url ->
-- pure $ nodeFrameVisio' { frame_id, reload, url }
pure $
H.div
{}
[
B.h1_ "Visio Room"
,
H.a
{ className : "fa fa-video-camera fa-5x"
, href : hframeUrl nodeType base frame_id
, target: "_blank"
}
[]
,
B.p_ "Click on the Camera logo to access to your room"
,
B.p_ "This a unique room dedicated to your team"
,
B.p_ "Works with Chromium/Chrome only for now."
]
-- Other Frame Nodes
_ -> do
-- @XXX: Runtime odd behavior
-- cannot use the `useEffect` + its cleanup function within the
-- same `Effect`, otherwise the below cleanup example will be
-- execute at mount
-- @XXX: inopinent <div> (see Gargantext.Components.Router) (@TODO?)
R.useEffectOnce' do
mEl <- querySelector document ".main-page__main-route .container"
case mEl of
Nothing -> R.nothing
Just el -> R2.addClass el [ "d-none" ]
R.useEffectOnce do
pure do
mEl <- querySelector document ".main-page__main-route .container"
case mEl of
Nothing -> R.nothing
Just el -> R2.removeClass el [ "d-none" ]
-- @XXX: reset "main-page__main-route" wrapper margin
-- see Gargantext.Components.Router) (@TODO?)
R.useEffectOnce' do
mEl <- querySelector document ".main-page__main-route"
case mEl of
Nothing -> R.nothing
Just el -> R2.addClass el [ "p-0" ]
R.useEffectOnce do
pure do
mEl <- querySelector document ".main-page__main-route"
case mEl of
Nothing -> R.nothing
Just el -> R2.removeClass el [ "p-0" ]
pure $
H.div
{ className: "frame-layout"
, rows: "100%,*"
}
[
-- H.script { src: "https://visio.gargantext.org/external_api.js"} [],
H.iframe
{ src: hframeUrl nodeType base frame_id
, width: "100%"
, height: "100%"
}
[]
]
--------------------------------------------------------------
type NodeFrameVisioProps =
( frame_id :: String
, reload :: T2.ReloadS
, url :: WURL.URL
)
nodeFrameVisio :: R2.Leaf NodeFrameVisioProps
nodeFrameVisio = R2.leaf nodeFrameVisioCpt
nodeFrameVisioCpt :: R.Component NodeFrameVisioProps
nodeFrameVisioCpt = here.component "nodeFrameVisio" cpt where
cpt { frame_id
, url
} _ = do
ref <- R.useRef (null :: Nullable DOM.Element)
R.useEffect' $ do
here.log2 "[nodeFrameVisio] ref" $ R.readRef ref
here.log2 "[nodeFrameVisio] JM.api" JM._api
case toMaybe (R.readRef ref) of
Nothing -> pure unit
Just r -> do
api <- JM.jitsiMeetAPI (WURL.host url) { parentNode: r
, roomName: frame_id
, width: "100%"
, height: "100%" }
here.log2 "[nodeFrameVisio] api" api
pure $ H.div { ref, className: "jitsi-iframe" } [ ]
--------------------------------------------------------------
hframeUrl :: NodeType -> Base -> FrameId -> String
hframeUrl NodeFrameNotebook _ frame_id = frame_id -- Temp fix : frame_id is currently the whole url created
hframeUrl NodeFrameCalc base frame_id = base <> "/" <> frame_id
hframeUrl NodeFrameVisio base frame_id = base <> "/" <> frame_id
hframeUrl _ base frame_id = base <> "/" <> frame_id <> "?view" -- "?both"
module Gargantext.Components.Frame.Types
( Hyperdata(..)
, Base, FrameId
) where
import Gargantext.Prelude
import Data.Eq.Generic (genericEq)
import Data.Generic.Rep (class Generic)
import Data.Newtype (class Newtype)
import Data.Show.Generic (genericShow)
import Simple.JSON as JSON
type Base = String
type FrameId = String
newtype Hyperdata = Hyperdata
{ base :: String
, frame_id :: String
}
derive instance Generic Hyperdata _
derive instance Newtype Hyperdata _
instance Eq Hyperdata where eq = genericEq
instance Show Hyperdata where show = genericShow
derive newtype instance JSON.ReadForeign Hyperdata
derive newtype instance JSON.WriteForeign Hyperdata
------------------------------------------------
module Gargantext.Components.Nodes.Frame where
module Gargantext.Components.Nodes.Frame
( frameLayout
) where
import Gargantext.Prelude
import DOM.Simple as DOM
import Data.Eq.Generic (genericEq)
import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype)
import Data.Nullable (Nullable, null, toMaybe)
import Data.Show.Generic (genericShow)
import Gargantext.Components.FolderView as FV
import Gargantext.Components.Node (NodePoly(..))
import Data.Maybe (Maybe(..), isJust)
import Data.Tuple.Nested ((/\))
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Frame.Layout (layout)
import Gargantext.Components.Frame.Types (Hyperdata)
import Gargantext.Components.Node (NodePoly)
import Gargantext.Config.REST (AffRESTError, logRESTError)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Hooks.Loader (useLoaderEffect)
import Gargantext.Hooks.Session (useSession)
import Gargantext.Routes (SessionRoute(NodeAPI))
import Gargantext.Sessions (Session, get, sessionId)
import Gargantext.Sessions (Session, get)
import Gargantext.Types (NodeType(..))
import Gargantext.Utils.JitsiMeet as JM
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2
import Reactix as R
import Reactix.DOM.HTML as H
import Simple.JSON as JSON
import Toestand as T
import Web.URL as WURL
here :: R2.Here
here = R2.here "Gargantext.Components.Nodes.Frame"
newtype Hyperdata = Hyperdata { base :: String, frame_id :: String }
derive instance Generic Hyperdata _
derive instance Newtype Hyperdata _
instance Eq Hyperdata where eq = genericEq
instance Show Hyperdata where show = genericShow
derive newtype instance JSON.ReadForeign Hyperdata
derive newtype instance JSON.WriteForeign Hyperdata
type Props =
( nodeId :: Int
, nodeType :: NodeType
, session :: Session
)
type KeyProps =
( key :: String
| Props
)
here :: R2.Here
here = R2.here "Gargantext.Components.Nodes.Frame"
frameLayout :: R2.Leaf Props
frameLayout = R2.leafComponent frameLayoutCpt
frameLayoutCpt :: R.Component Props
frameLayoutCpt = here.component "frameLayout" cpt where
cpt { nodeId, nodeType, session } _ = do
pure $ frameLayoutWithKey { key, nodeId, nodeType, session }
where
key = show (sessionId session) <> "-" <> show nodeId
frameLayoutWithKey :: R2.Leaf KeyProps
frameLayoutWithKey = R2.leafComponent frameLayoutWithKeyCpt
frameLayoutWithKeyCpt :: R.Component KeyProps
frameLayoutWithKeyCpt = here.component "frameLayoutWithKey" cpt where
cpt { nodeId, session, nodeType} _ = do
reload <- T.useBox T2.newReload
reload' <- T.useLive T.unequal reload
useLoader { errorHandler
, loader: loadframeWithReload
, path: {nodeId, reload: reload', session}
, render: \frame -> frameLayoutView {frame, nodeId, reload, session, nodeType} }
where
errorHandler = logRESTError here "[frameLayoutWithKey]"
type ViewProps =
( frame :: NodePoly Hyperdata
, reload :: T2.ReloadS
, nodeId :: Int
, nodeType :: NodeType
, session :: Session
frameLayout :: R2.Leaf ( key :: String | Props )
frameLayout = R2.leaf frameLayoutCpt
frameLayoutCpt :: R.Component ( key :: String | Props )
frameLayoutCpt = here.component "main" cpt where
cpt { nodeId
, nodeType
} _ = do
-- | States
-- |