Commit af97f328 authored by Karen Konou's avatar Karen Konou

Merge branch 'dev' into 405-dev-lost-password-design

parents b5f53d17 24534017
Pipeline #2932 failed with stage
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level of experience,
nationality, personal appearance, race, religion, or sexual identity and
orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at [sos AT gargantext DOT org]. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at [http://contributor-covenant.org/version/1/4][version]
[homepage]: http://contributor-covenant.org
[version]: http://contributor-covenant.org/version/1/4/
# GarganText "Code of Conduct"
The GarganText Project, the contributors of the GarganText eco-system,
have adopted a code of conduct for participants to any modes of
communication within the project.
## Be respectful
In a project the size of GarganText, inevitably there will be people
with whom you may disagree, or find it difficult to cooperate. Accept
that, but even so, remain respectful. Disagreement is no excuse for poor
behaviour or personal attacks, and a community in which people feel
threatened is not a healthy community.
## Assume good faith
GarganText Contributors have many ways of reaching our common goal of
a free digital ecosystem which may differ from your ways. Assume that
other people are working towards this goal.
Note that many of our Contributors are not native English speakers
or may have different cultural backgrounds.
## Be collaborative
GarganText is a large and complex project; there is always more to
learn within GarganText. It's good to ask for help when you need it.
Similarly, offers for help should be seen in the context of our shared
goal of improving GarganText.
When you make something for the benefit of the project, be willing
to explain to others how it works, so that they can build on your work
to make it even better.
## Try to be concise
Keep in mind that what you write once will be read by many others
persons. Writing a short email means people can understand the
conversation as efficiently as possible. When a long explanation is
necessary, consider adding a summary.
Try to bring new arguments to a conversation so that each comment
adds something unique to the thread, keeping in mind that the rest of
the thread still contains the other messages with arguments that have
already been made.
Try to stay on topic, especially in discussions that are already
fairly large.
## Be open
Most ways of communication used within GarganText allow for public and
private communication. You should preferably use public methods of
communication for GarganText-related messages, unless posting something
sensitive.
This applies to messages for help or GarganText-related support,
too; not only is a public support request much more likely to
result in an answer to your question, it also makes sure that any
inadvertent mistakes made by people answering your question will be
more easily detected and corrected.
While this code of conduct should be adhered to by participants,
we recognize that sometimes people may have a bad day, or be unaware
of some of the guidelines in this code of conduct. When that happens,
you may reply to them and point out this code of conduct. Such messages
may be in public or in private, whatever is most appropriate. However,
regardless of whether the message is public or not, it should still
adhere to the relevant parts of this code of conduct; in particular, it
should not be abusive or disrespectful. Assume good faith; it is more
likely that participants are unaware of their bad behaviour than that
they intentionally try to degrade the quality of the discussion.
Serious or persistent offenders will be temporarily or permanently
banned from communicating through GarganText's ecosystem. Complaints
should be made (in private) to the administrators of the GarganText
communication forum in question. To find contact information for these
administrators, please see the page on GarganText's organizational
structure.
......@@ -7864,14 +7864,15 @@ input[type=range]:-moz-focusring {
background-color: #121212;
}
.graph-doc-list__item--selected::before {
top: 0;
right: 0;
bottom: 0;
left: 0;
content: "";
position: absolute;
z-index: 1;
width: 2px;
background-color: #0F81C7;
left: 0;
top: 0;
bottom: 0;
}
.graph-doc-list__item--selected:first-child::before {
border-top-left-radius: 0.25rem;
......@@ -8999,7 +9000,7 @@ select.form-control {
text-shadow: 0 0 4px;
}
.b-icon.candidate-term {
color: #5a90b6;
color: #5A90B6;
text-shadow: 0 0 4px;
}
.b-icon.stop-term {
......@@ -9280,6 +9281,20 @@ select.form-control {
border-right: 1px solid #dee2e6;
}
.phylo__focus {
flex-grow: 1;
pointer-events: all;
position: relative;
}
.phylo__focus__inner {
top: 0;
right: 0;
bottom: 0;
left: 0;
position: absolute;
background-color: #000000;
}
.phylo-isoline {
display: flex;
position: relative;
......@@ -9443,7 +9458,7 @@ select.form-control {
font-weight: bold;
}
.phylo-selection-tab__selection {
margin: 16px 20px 0;
margin: 16px 20px;
}
.phylo-selection-tab__selection__item {
white-space: normal;
......@@ -9463,6 +9478,11 @@ select.form-control {
.phylo-selection-tab__counter__value {
color: #0F81C7;
}
.phylo-selection-tab__counter__expand {
position: absolute;
right: 1.25rem;
bottom: 1rem;
}
.phylo-selection-tab__nil {
margin: 16px 20px;
}
......@@ -9470,6 +9490,55 @@ select.form-control {
color: #ADB5BD;
text-align: center;
}
.phylo-selection-tab__extracted-docs {
margin: 16px 20px;
}
.phylo-doc-list__item {
cursor: pointer;
display: flex;
align-items: flex-start;
transition: all 0.2s ease-in-out;
}
.phylo-doc-list__item:focus {
outline: 0;
}
.phylo-doc-list__item:hover {
background-color: #121212;
}
.phylo-doc-list__item--selected::before {
top: 0;
right: 0;
bottom: 0;
left: 0;
content: "";
position: absolute;
z-index: 1;
width: 2px;
background-color: #0F81C7;
}
.phylo-doc-list__item--selected:first-child::before {
border-top-left-radius: 0.25rem;
}
.phylo-doc-list__item--selected:last-child::before {
border-bottom-left-radius: 0.25rem;
}
.phylo-doc-list__item__main {
flex-grow: 1;
padding-right: 1.25rem;
}
.phylo-doc-list__item__title, .phylo-doc-list__item__source, .phylo-doc-list__item__date {
line-height: 1.3;
margin-bottom: 4px;
}
.phylo-doc-list__item__source {
font-size: 15px;
color: #DEE2E6;
}
.phylo-doc-list__item__date {
font-size: 14px;
color: #CED4DA;
}
.phylo-toolbar {
display: flex;
......
......@@ -7817,14 +7817,15 @@ input[type=range]:-moz-focusring {
background-color: #FCFCFC;
}
.graph-doc-list__item--selected::before {
top: 0;
right: 0;
bottom: 0;
left: 0;
content: "";
position: absolute;
z-index: 1;
width: 2px;
background-color: #17a2b8;
left: 0;
top: 0;
bottom: 0;
}
.graph-doc-list__item--selected:first-child::before {
border-top-left-radius: 0.25rem;
......@@ -8952,7 +8953,7 @@ select.form-control {
text-shadow: 0 0 4px;
}
.b-icon.candidate-term {
color: #5a90b6;
color: #5A90B6;
text-shadow: 0 0 4px;
}
.b-icon.stop-term {
......@@ -9233,6 +9234,20 @@ select.form-control {
border-right: 1px solid #dee2e6;
}
.phylo__focus {
flex-grow: 1;
pointer-events: all;
position: relative;
}
.phylo__focus__inner {
top: 0;
right: 0;
bottom: 0;
left: 0;
position: absolute;
background-color: #fff;
}
.phylo-isoline {
display: flex;
position: relative;
......@@ -9396,7 +9411,7 @@ select.form-control {
font-weight: bold;
}
.phylo-selection-tab__selection {
margin: 16px 20px 0;
margin: 16px 20px;
}
.phylo-selection-tab__selection__item {
white-space: normal;
......@@ -9416,6 +9431,11 @@ select.form-control {
.phylo-selection-tab__counter__value {
color: #17a2b8;
}
.phylo-selection-tab__counter__expand {
position: absolute;
right: 1.25rem;
bottom: 1rem;
}
.phylo-selection-tab__nil {
margin: 16px 20px;
}
......@@ -9423,6 +9443,55 @@ select.form-control {
color: #ADB5BD;
text-align: center;
}
.phylo-selection-tab__extracted-docs {
margin: 16px 20px;
}
.phylo-doc-list__item {
cursor: pointer;
display: flex;
align-items: flex-start;
transition: all 0.2s ease-in-out;
}
.phylo-doc-list__item:focus {
outline: 0;
}
.phylo-doc-list__item:hover {
background-color: #FCFCFC;
}
.phylo-doc-list__item--selected::before {
top: 0;
right: 0;
bottom: 0;
left: 0;
content: "";
position: absolute;
z-index: 1;
width: 2px;
background-color: #17a2b8;
}
.phylo-doc-list__item--selected:first-child::before {
border-top-left-radius: 0.25rem;
}
.phylo-doc-list__item--selected:last-child::before {
border-bottom-left-radius: 0.25rem;
}
.phylo-doc-list__item__main {
flex-grow: 1;
padding-right: 1.25rem;
}
.phylo-doc-list__item__title, .phylo-doc-list__item__source, .phylo-doc-list__item__date {
line-height: 1.3;
margin-bottom: 4px;
}
.phylo-doc-list__item__source {
font-size: 15px;
color: #495057;
}
.phylo-doc-list__item__date {
font-size: 14px;
color: #6C757D;
}
.phylo-toolbar {
display: flex;
......
......@@ -7573,14 +7573,15 @@ input[type=range]:-moz-focusring {
background-color: #FCFCFC;
}
.graph-doc-list__item--selected::before {
top: 0;
right: 0;
bottom: 0;
left: 0;
content: "";
position: absolute;
z-index: 1;
width: 2px;
background-color: #5c8f94;
left: 0;
top: 0;
bottom: 0;
}
.graph-doc-list__item--selected:first-child::before {
border-top-left-radius: 0.25rem;
......@@ -8708,7 +8709,7 @@ select.form-control {
text-shadow: 0 0 4px;
}
.b-icon.candidate-term {
color: #5a90b6;
color: #5A90B6;
text-shadow: 0 0 4px;
}
.b-icon.stop-term {
......@@ -8989,6 +8990,20 @@ select.form-control {
border-right: 1px solid #dee2e6;
}
.phylo__focus {
flex-grow: 1;
pointer-events: all;
position: relative;
}
.phylo__focus__inner {
top: 0;
right: 0;
bottom: 0;
left: 0;
position: absolute;
background-color: #fff;
}
.phylo-isoline {
display: flex;
position: relative;
......@@ -9152,7 +9167,7 @@ select.form-control {
font-weight: bold;
}
.phylo-selection-tab__selection {
margin: 16px 20px 0;
margin: 16px 20px;
}
.phylo-selection-tab__selection__item {
white-space: normal;
......@@ -9172,6 +9187,11 @@ select.form-control {
.phylo-selection-tab__counter__value {
color: #5c8f94;
}
.phylo-selection-tab__counter__expand {
position: absolute;
right: 1.25rem;
bottom: 1rem;
}
.phylo-selection-tab__nil {
margin: 16px 20px;
}
......@@ -9179,6 +9199,55 @@ select.form-control {
color: #ADB5BD;
text-align: center;
}
.phylo-selection-tab__extracted-docs {
margin: 16px 20px;
}
.phylo-doc-list__item {
cursor: pointer;
display: flex;
align-items: flex-start;
transition: all 0.2s ease-in-out;
}
.phylo-doc-list__item:focus {
outline: 0;
}
.phylo-doc-list__item:hover {
background-color: #FCFCFC;
}
.phylo-doc-list__item--selected::before {
top: 0;
right: 0;
bottom: 0;
left: 0;
content: "";
position: absolute;
z-index: 1;
width: 2px;
background-color: #5c8f94;
}
.phylo-doc-list__item--selected:first-child::before {
border-top-left-radius: 0.25rem;
}
.phylo-doc-list__item--selected:last-child::before {
border-bottom-left-radius: 0.25rem;
}
.phylo-doc-list__item__main {
flex-grow: 1;
padding-right: 1.25rem;
}
.phylo-doc-list__item__title, .phylo-doc-list__item__source, .phylo-doc-list__item__date {
line-height: 1.3;
margin-bottom: 4px;
}
.phylo-doc-list__item__source {
font-size: 15px;
color: #495057;
}
.phylo-doc-list__item__date {
font-size: 14px;
color: #6C757D;
}
.phylo-toolbar {
display: flex;
......
......@@ -7821,14 +7821,15 @@ input[type=range]:-moz-focusring {
background-color: #FCFCFC;
}
.graph-doc-list__item--selected::before {
top: 0;
right: 0;
bottom: 0;
left: 0;
content: "";
position: absolute;
z-index: 1;
width: 2px;
background-color: #74DBEF;
left: 0;
top: 0;
bottom: 0;
}
.graph-doc-list__item--selected:first-child::before {
border-top-left-radius: 0.25rem;
......@@ -8956,7 +8957,7 @@ select.form-control {
text-shadow: 0 0 4px;
}
.b-icon.candidate-term {
color: #5a90b6;
color: #5A90B6;
text-shadow: 0 0 4px;
}
.b-icon.stop-term {
......@@ -9237,6 +9238,20 @@ select.form-control {
border-right: 1px solid #dee2e6;
}
.phylo__focus {
flex-grow: 1;
pointer-events: all;
position: relative;
}
.phylo__focus__inner {
top: 0;
right: 0;
bottom: 0;
left: 0;
position: absolute;
background-color: #fff;
}
.phylo-isoline {
display: flex;
position: relative;
......@@ -9400,7 +9415,7 @@ select.form-control {
font-weight: bold;
}
.phylo-selection-tab__selection {
margin: 16px 20px 0;
margin: 16px 20px;
}
.phylo-selection-tab__selection__item {
white-space: normal;
......@@ -9420,6 +9435,11 @@ select.form-control {
.phylo-selection-tab__counter__value {
color: #74DBEF;
}
.phylo-selection-tab__counter__expand {
position: absolute;
right: 1.25rem;
bottom: 1rem;
}
.phylo-selection-tab__nil {
margin: 16px 20px;
}
......@@ -9427,6 +9447,55 @@ select.form-control {
color: #ADB5BD;
text-align: center;
}
.phylo-selection-tab__extracted-docs {
margin: 16px 20px;
}
.phylo-doc-list__item {
cursor: pointer;
display: flex;
align-items: flex-start;
transition: all 0.2s ease-in-out;
}
.phylo-doc-list__item:focus {
outline: 0;
}
.phylo-doc-list__item:hover {
background-color: #FCFCFC;
}
.phylo-doc-list__item--selected::before {
top: 0;
right: 0;
bottom: 0;
left: 0;
content: "";
position: absolute;
z-index: 1;
width: 2px;
background-color: #74DBEF;
}
.phylo-doc-list__item--selected:first-child::before {
border-top-left-radius: 0.25rem;
}
.phylo-doc-list__item--selected:last-child::before {
border-bottom-left-radius: 0.25rem;
}
.phylo-doc-list__item__main {
flex-grow: 1;
padding-right: 1.25rem;
}
.phylo-doc-list__item__title, .phylo-doc-list__item__source, .phylo-doc-list__item__date {
line-height: 1.3;
margin-bottom: 4px;
}
.phylo-doc-list__item__source {
font-size: 15px;
color: #495057;
}
.phylo-doc-list__item__date {
font-size: 14px;
color: #6C757D;
}
.phylo-toolbar {
display: flex;
......
......@@ -7822,14 +7822,15 @@ input[type=range]:-moz-focusring {
background-color: #FCFCFC;
}
.graph-doc-list__item--selected::before {
top: 0;
right: 0;
bottom: 0;
left: 0;
content: "";
position: absolute;
z-index: 1;
width: 2px;
background-color: #515151;
left: 0;
top: 0;
bottom: 0;
}
.graph-doc-list__item--selected:first-child::before {
border-top-left-radius: 0.25rem;
......@@ -8957,7 +8958,7 @@ select.form-control {
text-shadow: 0 0 4px;
}
.b-icon.candidate-term {
color: #5a90b6;
color: #5A90B6;
text-shadow: 0 0 4px;
}
.b-icon.stop-term {
......@@ -9238,6 +9239,20 @@ select.form-control {
border-right: 1px solid #dee2e6;
}
.phylo__focus {
flex-grow: 1;
pointer-events: all;
position: relative;
}
.phylo__focus__inner {
top: 0;
right: 0;
bottom: 0;
left: 0;
position: absolute;
background-color: #fff;
}
.phylo-isoline {
display: flex;
position: relative;
......@@ -9401,7 +9416,7 @@ select.form-control {
font-weight: bold;
}
.phylo-selection-tab__selection {
margin: 16px 20px 0;
margin: 16px 20px;
}
.phylo-selection-tab__selection__item {
white-space: normal;
......@@ -9421,6 +9436,11 @@ select.form-control {
.phylo-selection-tab__counter__value {
color: #515151;
}
.phylo-selection-tab__counter__expand {
position: absolute;
right: 1.25rem;
bottom: 1rem;
}
.phylo-selection-tab__nil {
margin: 16px 20px;
}
......@@ -9428,6 +9448,55 @@ select.form-control {
color: #ADB5BD;
text-align: center;
}
.phylo-selection-tab__extracted-docs {
margin: 16px 20px;
}
.phylo-doc-list__item {
cursor: pointer;
display: flex;
align-items: flex-start;
transition: all 0.2s ease-in-out;
}
.phylo-doc-list__item:focus {
outline: 0;
}
.phylo-doc-list__item:hover {
background-color: #FCFCFC;
}
.phylo-doc-list__item--selected::before {
top: 0;
right: 0;
bottom: 0;
left: 0;
content: "";
position: absolute;
z-index: 1;
width: 2px;
background-color: #515151;
}
.phylo-doc-list__item--selected:first-child::before {
border-top-left-radius: 0.25rem;
}
.phylo-doc-list__item--selected:last-child::before {
border-bottom-left-radius: 0.25rem;
}
.phylo-doc-list__item__main {
flex-grow: 1;
padding-right: 1.25rem;
}
.phylo-doc-list__item__title, .phylo-doc-list__item__source, .phylo-doc-list__item__date {
line-height: 1.3;
margin-bottom: 4px;
}
.phylo-doc-list__item__source {
font-size: 15px;
color: #495057;
}
.phylo-doc-list__item__date {
font-size: 14px;
color: #6C757D;
}
.phylo-toolbar {
display: flex;
......
{
"name": "Gargantext",
"version": "0.0.5.8.9.2",
"version": "0.0.5.8.9.8",
"scripts": {
"generate-purs-packages-nix": "./nix/generate-purs-packages.nix",
"generate-psc-packages-nix": "./nix/generate-packages-json.bash",
......
......@@ -23,7 +23,8 @@ import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Gargantext.Components.Annotation.Menu (annotationMenu, AnnotationMenu)
import Gargantext.Components.Annotation.Types (termClass, MenuType(..))
import Gargantext.Components.NgramsTable.Core (NgramsTable, NgramsTerm, findNgramTermList, highlightNgrams, normNgram)
import Gargantext.Core.NgramsTable.Functions (findNgramTermList, highlightNgrams, normNgram)
import Gargantext.Core.NgramsTable.Types (NgramsTable, NgramsTerm)
import Gargantext.Types (CTabNgramType(..), TermList)
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Selection as Sel
......
......@@ -7,7 +7,7 @@ import Gargantext.Prelude
import Data.Either (Either(..))
import Data.Maybe (Maybe(..))
import Gargantext.Components.Document.Types (DocPath, LoadedData, NodeDocument)
import Gargantext.Components.NgramsTable.Core (loadNgramsTable)
import Gargantext.Core.NgramsTable.Functions (loadNgramsTable)
import Gargantext.Components.Search (SearchType(..))
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Routes (SessionRoute(..))
......
......@@ -12,8 +12,10 @@ import Gargantext.Components.AutoUpdate (autoUpdate)
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Bootstrap.Types (SpinnerTheme(..))
import Gargantext.Components.Document.Types (DocPath, Document(..), LoadedData, initialState)
import Gargantext.Components.NgramsTable.Core (CoreAction(..), Versioned(..), addNewNgramA, applyNgramsPatches, coreDispatch, findNgramRoot, replace, setTermListA, syncResetButtons, useAutoSync)
import Gargantext.Core.NgramsTable.Functions (addNewNgramA, applyNgramsPatches, coreDispatch, findNgramRoot, setTermListA)
import Gargantext.Components.NgramsTable.AutoSync (useAutoSync)
import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Core.NgramsTable.Types (CoreAction(..), Versioned(..), replace)
import Gargantext.Utils as U
import Gargantext.Utils.Reactix as R2
import Reactix as R
......
......@@ -10,7 +10,7 @@ import Simple.JSON as JSON
import Gargantext.Prelude
import Gargantext.Components.Node (NodePoly(..))
import Gargantext.Components.NgramsTable.Core (CoreState, Versioned(..) , VersionedNgramsTable)
import Gargantext.Core.NgramsTable.Types (CoreState, Versioned(..) , VersionedNgramsTable)
import Gargantext.Sessions (Session)
import Gargantext.Types (ListId, NodeID, TabType)
......@@ -86,7 +86,7 @@ defaultNodeDocumentV3 =
NodePoly { id : 0
, typename : 0
, userId : 0
, parentId : 0
, parentId : Just 0
, name : "Default name"
, date : "Default date"
, hyperdata : defaultDocumentV3
......@@ -148,7 +148,7 @@ defaultNodeDocument =
NodePoly { id : 0
, typename : 0
, userId : 0
, parentId : 0
, parentId : Just 0
, name : "Default name"
, date : "Default date"
, hyperdata : defaultDocument
......
......@@ -61,12 +61,15 @@ forestLayoutCpt = here.component "forest" cpt where
H.div
{ className: "forest-layout__tree" }
[
treeLoader { boxes
, frontends
, handed: handed'
, reload: reloadForest
, root: treeId
, session: s } []
treeLoader
{ boxes
, frontends
, handed: handed'
, reload: reloadForest
, root: treeId
, session: s
, key: "tree-" <> (show treeId)
}
]
type Plus = ( boxes :: Boxes )
......
......@@ -106,9 +106,10 @@ type PerformActionProps =
| PACommon )
-- | Loads and renders the tree starting at the given root node id.
treeLoader :: R2.Component LoaderProps
treeLoader = R.createElement treeLoaderCpt
treeLoaderCpt :: R.Component LoaderProps
treeLoader :: R2.Leaf ( key :: String | LoaderProps )
treeLoader = R2.leaf treeLoaderCpt
treeLoaderCpt :: R.Component ( key :: String | LoaderProps )
treeLoaderCpt = here.component "treeLoader" cpt where
-- treeLoaderCpt :: R.Memo LoaderProps
-- treeLoaderCpt = R.memo (here.component "treeLoader" cpt) memoCmp where
......
......@@ -90,7 +90,7 @@ updateGraphCpt = here.component "updateGraph" cpt where
, default: methodGraphMetric'
, callback: \val -> T.write_ val methodGraphMetric
, print: show } []
, formChoiceSafe { items: [Spinglass, Confluence]
, formChoiceSafe { items: [Infomap, Spinglass, Confluence]
, default: methodGraphClustering'
, callback: \val -> T.write_ val methodGraphClustering
, print: show } []
......
......@@ -71,7 +71,7 @@ instance Read GraphMetric where
instance JSON.ReadForeign GraphMetric where readImpl = JSONG.enumSumRep
instance JSON.WriteForeign GraphMetric where writeImpl = JSON.writeImpl <<< show
data PartitionMethod = Spinglass | Confluence
data PartitionMethod = Spinglass | Infomap | Confluence
derive instance Generic PartitionMethod _
derive instance Eq PartitionMethod
instance Show PartitionMethod where show = genericShow
......
......@@ -4,8 +4,8 @@ import Gargantext.Prelude
import Data.Maybe (Maybe(..))
import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Components.NgramsTable.Core as NTC
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Core.NgramsTable.Types as CNT
import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Routes (SessionRoute(..))
import Gargantext.Routes as GR
......@@ -20,7 +20,7 @@ type GraphAsyncUpdateParams =
, nodes :: Array (Record SigmaxT.Node)
, session :: Session
, termList :: GT.TermList
, version :: NTC.Version
, version :: CNT.Version
)
graphAsyncUpdate :: Record GraphAsyncUpdateParams -> AffRESTError GT.AsyncTaskWithType
......
......@@ -28,14 +28,16 @@ import Gargantext.Components.GraphExplorer.Sidebar.Legend as Legend
import Gargantext.Components.GraphExplorer.Store as GraphStore
import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Components.Lang (Lang(..))
import Gargantext.Components.NgramsTable.Core as NTC
import Gargantext.Core.NgramsTable.Functions as NTC
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Core.NgramsTable.Types as CNT
import Gargantext.Data.Array (mapMaybe)
import Gargantext.Ends (Frontends)
import Gargantext.Hooks.FirstEffect (useFirstEffect')
import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Sessions (Session)
import Gargantext.Types (CTabNgramType, FrontendError(..), NodeID, TabSubType(..), TabType(..), TermList(..), modeTabType)
import Gargantext.Utils (nbsp, (?))
import Gargantext.Utils (nbsp, setter, (?))
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Toestand as T2
import Math as Math
......@@ -258,23 +260,33 @@ selectedNodes = R2.leaf selectedNodesCpt
selectedNodesCpt :: R.Component SelectedNodesProps
selectedNodesCpt = here.component "selectedNodes" cpt where
cpt props _ = do
-- States
-- | States
-- |
{ selectedNodeIds
, graph
, showNGramsActions
, expandSelection
} <- GraphStore.use
showNGramsActions' <- R2.useLive' showNGramsActions
selectedNodeIds' <- R2.useLive' selectedNodeIds
graph' <- R2.useLive' graph
expandSelection' <- R2.useLive' expandSelection
-- Behaviors
-- | Effects
-- |
-- transfer local Component change to Local Storage cache
useFirstEffect' $
flip T.listen expandSelection onExpandSelectionChange
-- | Behaviors
-- |
let
onBadgeClick id _ = T.write_ (Set.singleton id) selectedNodeIds
onExpandClick _ = T.modify_ (not) showNGramsActions
onExpandClick _ = T.modify_ (not) expandSelection
-- Render
-- | Render
-- |
pure $
H.ul
......@@ -308,7 +320,7 @@ selectedNodesCpt = here.component "selectedNodes" cpt where
,
-- Expand NGrams actions
B.iconButton
{ name: showNGramsActions' ?
{ name: expandSelection' ?
"caret-up" $
"caret-down"
, className: "graph-selected-nodes__expand"
......@@ -317,7 +329,7 @@ selectedNodesCpt = here.component "selectedNodes" cpt where
]
,
-- NGrams actions
R2.when showNGramsActions' $
R2.when expandSelection' $
H.li
{ className: intercalate " "
......@@ -362,6 +374,12 @@ selectedNodesCpt = here.component "selectedNodes" cpt where
]
]
onExpandSelectionChange :: T.Change Boolean -> Effect Unit
onExpandSelectionChange { new } = do
cache <- R2.loadLocalStorageState' R2.graphParamsKey GET.defaultCacheParams
let update = setter (_ { expandSelection = new }) cache
R2.setLocalStorageState R2.graphParamsKey update
---------------------------------------------------------
neighborhood :: R2.Leaf ()
......@@ -370,17 +388,18 @@ neighborhood = R2.leaf neighborhoodCpt
neighborhoodCpt :: R.Memo ()
neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where
cpt _ _ = do
-- States
-- | States
-- |
{ selectedNodeIds
, graph
, showWordCloud
, expandNeighborhood
} <- GraphStore.use
selectedNodeIds' <-
R2.useLive' selectedNodeIds
showWordCloud' <-
R2.useLive' showWordCloud
expandNeighborhood' <-
R2.useLive' expandNeighborhood
graph' <-
R2.useLive' graph
......@@ -394,7 +413,8 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where
termCount /\ termCountBox <-
R2.useBox' 0
-- Computed
-- | Computed
-- |
let
minSize = F.foldl Math.min 0.0 (Seq.map _.size (SigmaxT.graphNodes graph'))
......@@ -405,13 +425,20 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where
withTruncateResults = (termCount > maxTruncateResult) && (not showMore)
-- Behaviors
-- | Behaviors
-- |
let
onBadgeClick id _ = T.write_ (Set.singleton id) selectedNodeIds
onExpandClick _ = T.modify_ (not) showWordCloud
onExpandClick _ = T.modify_ (not) expandNeighborhood
-- | Effects
-- |
-- transfer local Component change to Local Storage cache
useFirstEffect' $
flip T.listen expandNeighborhood onExpandNeighborhoodChange
-- Effects
R.useEffect1' selectedNodeIds' do
let refreshed = neighbourBadges graph' selectedNodeIds'
let count = Seq.length refreshed
......@@ -420,7 +447,8 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where
T.write_ ordered termListBox
T.write_ false showMoreBox
-- Render
-- | Render
-- |
pure $
H.ul
......@@ -446,7 +474,7 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where
,
-- Expand word cloud
B.iconButton
{ name: showWordCloud' ?
{ name: expandNeighborhood' ?
"caret-up" $
"caret-down"
, className: "graph-neighborhood__expand"
......@@ -456,7 +484,7 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where
]
,
-- Word cloud
R2.when showWordCloud' $
R2.when expandNeighborhood' $
H.li
{ className: "list-group-item"}
......@@ -505,6 +533,12 @@ neighborhoodCpt = R.memo' $ here.component "neighborhood" cpt where
]
]
onExpandNeighborhoodChange :: T.Change Boolean -> Effect Unit
onExpandNeighborhoodChange { new } = do
cache <- R2.loadLocalStorageState' R2.graphParamsKey GET.defaultCacheParams
let update = setter (_ { expandNeighborhood = new }) cache
R2.setLocalStorageState R2.graphParamsKey update
---------------------------------------------------------
type UpdateTermButtonProps =
......@@ -601,14 +635,14 @@ type SendPatches =
sendPatches :: Record SendPatches -> Effect Unit
sendPatches { errors, metaData, nodes, reloadForest, session, termList } = do
launchAff_ do
patches <- (parTraverse (sendPatch termList session metaData) nodes) -- :: Aff (Array NTC.VersionedNgramsPatches)
patches <- (parTraverse (sendPatch termList session metaData) nodes) -- :: Aff (Array CNT.VersionedNgramsPatches)
let mPatch = last patches
case mPatch of
Nothing -> pure unit
Just (Left err) -> liftEffect $ do
T.modify_ (A.cons $ FRESTError { error: err }) errors
here.warn2 "[sendPatches] RESTError" err
Just (Right (NTC.Versioned _patch)) -> do
Just (Right (CNT.Versioned _patch)) -> do
liftEffect $ T2.reload reloadForest
-- Why is this called delete node?
......@@ -616,7 +650,7 @@ sendPatch :: TermList
-> Session
-> GET.MetaData
-> Record SigmaxT.Node
-> AffRESTError NTC.VersionedNgramsPatches
-> AffRESTError CNT.VersionedNgramsPatches
sendPatch termList session (GET.MetaData metaData) node = do
eRet <- NTC.putNgramsPatches coreParams versioned
case eRet of
......@@ -628,10 +662,10 @@ sendPatch termList session (GET.MetaData metaData) node = do
nodeId :: NodeID
nodeId = unsafePartial $ fromJust $ fromString node.id
versioned :: NTC.VersionedNgramsPatches
versioned = NTC.Versioned {version: metaData.list.version, data: np}
versioned :: CNT.VersionedNgramsPatches
versioned = CNT.Versioned {version: metaData.list.version, data: np}
coreParams :: NTC.CoreParams ()
coreParams :: CNT.CoreParams ()
coreParams = {session, nodeId, listIds: [metaData.list.listId], tabType}
tabNgramType :: CTabNgramType
......@@ -640,14 +674,14 @@ sendPatch termList session (GET.MetaData metaData) node = do
tabType :: TabType
tabType = TabCorpus (TabNgramType tabNgramType)
term :: NTC.NgramsTerm
term :: CNT.NgramsTerm
term = NTC.normNgram tabNgramType node.label
np :: NTC.NgramsPatches
np = NTC.singletonPatchMap term $ NTC.NgramsPatch { patch_children: mempty, patch_list }
np :: CNT.NgramsPatches
np = NTC.singletonPatchMap term $ CNT.NgramsPatch { patch_children: mempty, patch_list }
patch_list :: NTC.Replace TermList
patch_list = NTC.Replace { new: termList, old: MapTerm }
patch_list :: CNT.Replace TermList
patch_list = CNT.Replace { new: termList, old: MapTerm }
......
......@@ -14,6 +14,7 @@ import Data.Set as Set
import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Types as GT
import Gargantext.Utils (getter)
import Gargantext.Utils.Range as Range
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Stores as Stores
......@@ -35,8 +36,8 @@ type Store =
, sideTab :: T.Box GET.SideTab
, showSidebar :: T.Box GT.SidePanelState
, showDoc :: T.Box (Maybe GET.GraphSideDoc)
, showWordCloud :: T.Box Boolean
, showNGramsActions :: T.Box Boolean
, expandSelection :: T.Box Boolean
, expandNeighborhood :: T.Box Boolean
-- Controls
, multiSelectEnabled :: T.Box Boolean
, edgeConfluence :: T.Box Range.NumberRange
......@@ -65,8 +66,8 @@ type State =
, sideTab :: GET.SideTab
, showSidebar :: GT.SidePanelState
, showDoc :: Maybe GET.GraphSideDoc
, showWordCloud :: Boolean
, showNGramsActions :: Boolean
, expandSelection :: Boolean
, expandNeighborhood :: Boolean
-- Controls
, multiSelectEnabled :: Boolean
, edgeConfluence :: Range.NumberRange
......@@ -90,8 +91,8 @@ options ::
, showDoc :: Maybe GET.GraphSideDoc
, showSidebar :: GT.SidePanelState
, sideTab :: GET.SideTab
, showWordCloud :: Boolean
, showNGramsActions :: Boolean
, expandSelection :: Boolean
, expandNeighborhood :: Boolean
-- Controls
, labelSize :: Number
, mouseSelectorSize :: Number
......@@ -111,8 +112,8 @@ options =
, sideTab : GET.SideTabLegend
, showSidebar : GT.InitialClosed
, showDoc : Nothing
, showWordCloud : true
, showNGramsActions : true
, expandSelection : getter _.expandSelection GET.defaultCacheParams
, expandNeighborhood : getter _.expandNeighborhood GET.defaultCacheParams
-- Controls
, multiSelectEnabled : false
, labelSize : 14.0
......
......@@ -3,11 +3,12 @@ module Gargantext.Components.GraphExplorer.Types where
import Gargantext.Prelude
import Data.Array ((!!), length)
import Data.Generic.Rep (class Generic)
import Data.Eq.Generic (genericEq)
import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..), fromJust)
import Data.Newtype (class Newtype)
import Data.Ord.Generic (genericCompare)
import Data.Show.Generic (genericShow)
import Data.Symbol (SProxy(..))
import Partial.Unsafe (unsafePartial)
import Record as Record
......@@ -267,3 +268,26 @@ instance JSON.WriteForeign HyperdataGraph where
data Stage = Init | Ready | Cleanup
derive instance Generic Stage _
derive instance Eq Stage
-----------------------------------------------------------------------
newtype CacheParams = CacheParams
{ expandSelection :: Boolean
, expandNeighborhood :: Boolean
}
derive instance Newtype CacheParams _
derive instance Generic CacheParams _
derive instance Eq CacheParams
instance Show CacheParams where show = genericShow
derive newtype instance JSON.ReadForeign CacheParams
derive newtype instance JSON.WriteForeign CacheParams
-- (!) in case cache storage (ie. JavaScript Local Storage) returns an invalid
-- objects (eg. possible data migration), this will safely set new default
-- values
defaultCacheParams :: CacheParams
defaultCacheParams = CacheParams
{ expandSelection : true
, expandNeighborhood: true
}
......@@ -71,8 +71,8 @@ formCpt = here.component "form" cpt where
[ passwordInput cursors.password
, clearfix ]
, termsCheckbox cursors.agreed
, forgotPassword { formType }
, submitButton { backend, formType, sessions, visible, cell }
, forgotPassword { formType }
]]
-- might be wrong, all we care about is preventDefault
......@@ -175,8 +175,8 @@ forgotPassword = R2.leaf forgotPasswordCpt
forgotPasswordCpt :: R.Component ForgotPasswordProps
forgotPasswordCpt = here.component "forgotPassword" cpt where
cpt { formType } _ = do
pure $ H.div { className: "form-group text-center" }
[ H.a { className: "text-primary",
pure $ H.div { className: "" }
[ H.a { className: "",
on: { click } } [ H.text "Forgot password?" ]
]
where
......
This diff is collapsed.
module Gargantext.Components.NgramsTable.AutoSync where
import Data.Maybe (Maybe(..))
import Effect.Class (liftEffect)
import Gargantext.Core.NgramsTable.Types (CoreAction(..), CoreDispatch, CoreState)
import Gargantext.Prelude
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Toestand as T
------------------------------------------------------------------
here :: R2.Here
here = R2.here "Gargantext.Components.NgramsTable.AutoSync"
type AutoSyncInput s =
( state :: T.Box (CoreState s)
, action :: CoreDispatch
)
type AutoSyncOutput =
-- @XXX: cannot use an Either here due to the mecanism of `syncPatches` only
-- returning an `Aff Unit`
-- ( result :: T.Box (Maybe (Either RESTError Unit))
( result :: T.Box (Maybe Unit)
, onPending :: T.Box Boolean
)
useAutoSync :: forall s.
Record (AutoSyncInput s)
-> R.Hooks (Record AutoSyncOutput)
useAutoSync { state, action } = do
-- States
onPending <- T.useBox false
result <- T.useBox Nothing
ngramsLocalPatch <-
T.useFocused
(_.ngramsLocalPatch)
(\a b -> b { ngramsLocalPatch = a }) state
-- Computed
let
exec { new } =
let hasChanges = new /= mempty
in when hasChanges do
T.write_ true onPending
T.write_ Nothing result
action $ Synchronize
{ afterSync: onSuccess
}
onSuccess _ = liftEffect do
T.write_ false onPending
T.write_ (Just unit) result
-- Hooks
R.useEffectOnce' $ T.listen exec ngramsLocalPatch
-- Output
pure
{ onPending
, result
}
......@@ -10,8 +10,8 @@ import Effect.Aff (Aff, launchAff_, throwError)
import Effect.Class (liftEffect)
import Effect.Exception (error)
import Gargantext.Components.LoadingSpinner (loadingSpinner)
import Gargantext.Components.NgramsTable.Core (Version, Versioned(..))
import Gargantext.Config.REST (RESTError(..), AffRESTError)
import Gargantext.Core.NgramsTable.Types (Version, Versioned(..))
import Gargantext.Utils.CacheAPI as GUC
import Reactix as R
import Simple.JSON as JSON
......
module Gargantext.Components.NgramsTable.Search where
import Data.Nullable (Nullable, null)
import DOM.Simple as DOM
import Gargantext.Prelude
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
here :: R2.Here
here = R2.here "Gargantext.Components.NgramsTable.Search"
type SearchInputProps =
( searchQuery :: T.Box String
)
-- "key": to prevent refreshing & losing input
searchInput :: R2.Leaf ( key :: String | SearchInputProps )
searchInput = R2.leafComponent searchInputCpt
searchInputCpt :: R.Component ( key :: String | SearchInputProps )
searchInputCpt = here.component "searchInput" cpt
where
cpt { searchQuery } _ = do
inputRef <- R.useRef null
pure $ R2.row
[ H.div { className: "col-12" }
[ H.div { className: "input-group" }
[ searchButton { inputRef, searchQuery } []
, searchFieldInput { inputRef, searchQuery } []
]
]
]
type SearchButtonProps =
( inputRef :: R.Ref (Nullable DOM.Element)
, searchQuery :: T.Box String
)
searchButton :: R2.Component SearchButtonProps
searchButton = R.createElement searchButtonCpt
searchButtonCpt :: R.Component SearchButtonProps
searchButtonCpt = here.component "searchButton" cpt where
cpt { inputRef, searchQuery } _ = do
searchQuery' <- T.useLive T.unequal searchQuery
pure $ H.div { className: "input-group-prepend" }
[ if searchQuery' /= ""
then
H.button { className: "btn btn-danger"
, on: { click: \_ -> R2.setInputValue inputRef "" } }
-- T.write "" searchQuery } }
[ H.span {className: "fa fa-times"} []]
else H.span { className: "fa fa-search input-group-text" } []
]
type SearchFieldInputProps =
( inputRef :: R.Ref (Nullable DOM.Element)
, searchQuery :: T.Box String
)
searchFieldInput :: R2.Component SearchFieldInputProps
searchFieldInput = R.createElement searchFieldInputCpt
searchFieldInputCpt :: R.Component SearchFieldInputProps
searchFieldInputCpt = here.component "searchFieldInput" cpt where
cpt { inputRef, searchQuery } _ = do
-- searchQuery' <- T.useLive T.unequal searchQuery
pure $ H.input { className: "form-control"
-- , defaultValue: searchQuery'
, name: "search"
, on: { input: \e -> T.write (R.unsafeEventValue e) searchQuery }
, placeholder: "Search"
, ref: inputRef
, type: "value"
}
module Gargantext.Components.NgramsTable.SelectionCheckbox where
import Data.Maybe (Maybe(..))
import Data.Nullable (null, toMaybe)
import Data.Set (Set)
import Data.Set as Set
import FFI.Simple (delay)
import Gargantext.Core.NgramsTable.Types (Action(..), Dispatch, NgramsTerm)
import Gargantext.Prelude
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
here :: R2.Here
here = R2.here "Gargantext.Components.NgramsTable.SelectionCheckbox"
type SelectionCheckboxProps =
( allNgramsSelected :: Boolean
, dispatch :: Dispatch
, ngramsSelection :: Set NgramsTerm
)
selectionCheckbox :: Record SelectionCheckboxProps -> R.Element
selectionCheckbox props = R.createElement selectionCheckboxCpt props []
selectionCheckboxCpt :: R.Component SelectionCheckboxProps
selectionCheckboxCpt = here.component "selectionCheckbox" cpt
where
cpt { allNgramsSelected, dispatch, ngramsSelection } _ = do
ref <- R.useRef null
R.useEffect' $ delay unit $ \_ -> do
let mCb = toMaybe $ R.readRef ref
case mCb of
Nothing -> pure unit
Just cb -> do
_ <- if allNgramsSelected || (Set.isEmpty ngramsSelection) then
R2.setIndeterminateCheckbox cb false
else
R2.setIndeterminateCheckbox cb true
pure unit
pure $ H.input { checked: allNgramsSelected
, className: "checkbox"
, on: { change: const $ dispatch $ ToggleSelectAll }
, ref
, type: "checkbox" }
module Gargantext.Components.NgramsTable.SyncResetButton where
import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import FFI.Simple.Functions (delay)
import Gargantext.Core.NgramsTable.Types (CoreAction(..), CoreDispatch, NgramsTablePatch)
import Gargantext.Prelude
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
import Toestand as T
here :: R2.Here
here = R2.here "Gargantext.Components.NgramsTable.SyncResetButton"
-- | Reset Button
type SyncResetButtonsProps =
( afterSync :: Unit -> Aff Unit
, ngramsLocalPatch :: NgramsTablePatch
, performAction :: CoreDispatch
)
syncResetButtons :: Record SyncResetButtonsProps -> R.Element
syncResetButtons p = R.createElement syncResetButtonsCpt p []
syncResetButtonsCpt :: R.Component SyncResetButtonsProps
syncResetButtonsCpt = here.component "syncResetButtons" cpt
where
cpt { afterSync, ngramsLocalPatch, performAction } _ = do
synchronizing <- T.useBox false
synchronizing' <- T.useLive T.unequal synchronizing
let
hasChanges = ngramsLocalPatch /= mempty
hasChangesClass = if hasChanges then "" else " disabled"
synchronizingClass = if synchronizing' then " disabled" else ""
resetClick _ = do
performAction ResetPatches
synchronizeClick _ = delay unit $ \_ -> do
T.write_ true synchronizing
performAction $ Synchronize { afterSync: newAfterSync }
newAfterSync x = do
afterSync x
liftEffect $ T.write_ false synchronizing
pure $ H.div { className: "btn-toolbar" }
[ H.div { className: "btn-group mr-2" }
[ H.button { className: "btn btn-danger " <> hasChangesClass <> synchronizingClass
, on: { click: resetClick }
} [ H.text "Reset" ]
]
, H.div { className: "btn-group mr-2" }
[ H.button { className: "btn btn-primary " <> hasChangesClass <> synchronizingClass
, on: { click: synchronizeClick }
} [ H.text "Sync" ]
]
]
module Gargantext.Components.Node
where
import Data.Generic.Rep (class Generic)
import Gargantext.Prelude
import Data.Eq.Generic (genericEq)
import Data.Maybe (Maybe)
import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype)
import Simple.JSON as JSON
import Gargantext.Prelude
type NodePolyCommon a =
( id :: Int
, typename :: Int
......@@ -18,7 +18,7 @@ type NodePolyCommon a =
newtype NodePoly a =
NodePoly { userId :: Int
, parentId :: Int
, parentId :: Maybe Int
| NodePolyCommon a
}
derive instance Generic (NodePoly a) _
......@@ -26,7 +26,7 @@ derive instance Newtype (NodePoly a) _
instance Eq a => Eq (NodePoly a) where eq = genericEq
instance JSON.ReadForeign a => JSON.ReadForeign (NodePoly a) where
readImpl f = do
inst :: { user_id :: Int, parent_id :: Int | NodePolyCommon a } <- JSON.readImpl f
inst :: { user_id :: Int, parent_id :: Maybe Int | NodePolyCommon a } <- JSON.readImpl f
pure $ NodePoly { id: inst.id
, typename: inst.typename
, userId: inst.user_id
......
......@@ -151,16 +151,15 @@ pageLayoutCpt = here.component "pageLayout" cpt
errorHandler = logRESTError here "[pageLayout]"
type PageProps =
( session :: Session
, frontends :: Frontends
( frontends :: Frontends
, pagePath :: T.Box PagePath
-- , info :: AnnuaireInfo
, session :: Session
, table :: TableResult CT.NodeContact
)
page :: Record PageProps -> R.Element
page props = R.createElement pageCpt props []
pageCpt :: R.Component PageProps
pageCpt = here.component "page" cpt
where
......
......@@ -12,7 +12,7 @@ import Gargantext.Components.App.Store (Boxes)
import Gargantext.Components.DocsTable as DT
import Gargantext.Components.DocsTable.Types (Year)
import Gargantext.Components.NgramsTable as NT
import Gargantext.Components.NgramsTable.Core as NTC
import Gargantext.Core.NgramsTable.Functions as NTC
import Gargantext.Components.Nodes.Lists.Types as LTypes
import Gargantext.Components.Nodes.Texts.Types as TextsT
import Gargantext.Components.Tab as Tab
......@@ -113,18 +113,29 @@ ngramsViewCpt = here.component "ngramsView" cpt where
NTC.initialPageParams session nodeId
[ defaultListId ] (TabDocument TabDocs)
pure $ NT.mainNgramsTable (props' path) [] where
most = RX.pick props :: Record NTCommon
props' path =
(Record.merge most
{ afterSync
, path
, tabType: TabPairing (TabNgramType $ modeTabType mode)
, tabNgramType: modeTabType' mode
, withAutoUpdate: false }) :: Record NT.MainNgramsTableProps
where
afterSync :: Unit -> Aff Unit
afterSync _ = pure unit
onCancelRef <- R.useRef Nothing
onNgramsClickRef <- R.useRef Nothing
onSaveRef <- R.useRef Nothing
treeEditBox <- T.useBox NT.initialTreeEdit
let most = RX.pick props :: Record NTCommon
props' =
(Record.merge most
{ afterSync
, path
, tabType: TabPairing (TabNgramType $ modeTabType mode)
, tabNgramType: modeTabType' mode
, treeEdit: { box: treeEditBox
, getNgramsChildren: \_ -> pure []
, onCancelRef
, onNgramsClickRef
, onSaveRef }
, withAutoUpdate: false }) :: Record NT.MainNgramsTableProps
afterSync :: Unit -> Aff Unit
afterSync _ = pure unit
pure $ NT.mainNgramsTable props' []
type NTCommon =
( boxes :: Boxes
......
......@@ -11,7 +11,7 @@ import Gargantext.Components.App.Store (Boxes)
import Gargantext.Components.DocsTable as DT
import Gargantext.Components.DocsTable.Types (Year)
import Gargantext.Components.NgramsTable as NT
import Gargantext.Components.NgramsTable.Core as NTC
import Gargantext.Core.NgramsTable.Functions as NTC
import Gargantext.Components.Nodes.Lists.Types as LTypes
import Gargantext.Components.Nodes.Texts.Types as TTypes
import Gargantext.Components.Tab as Tab
......@@ -146,6 +146,10 @@ ngramsViewCpt = here.component "ngramsView" cpt
, nodeId
, session } _ = do
path <- T.useBox $ NTC.initialPageParams session nodeId [defaultListId] (TabDocument TabDocs)
onCancelRef <- R.useRef Nothing
onNgramsClickRef <- R.useRef Nothing
onSaveRef <- R.useRef Nothing
treeEditBox <- T.useBox NT.initialTreeEdit
pure $ NT.mainNgramsTable {
afterSync: \_ -> pure unit
......@@ -156,6 +160,11 @@ ngramsViewCpt = here.component "ngramsView" cpt
, session
, tabNgramType
, tabType
, treeEdit: { box: treeEditBox
, getNgramsChildren: \_ -> pure []
, onCancelRef
, onNgramsClickRef
, onSaveRef }
, withAutoUpdate: false
} []
where
......
......@@ -387,8 +387,8 @@ loadCorpus {nodeId, session} = do
case res of
Left err -> pure $ Left err
Right (NodePoly {parentId: corpusId} :: NodePoly {}) -> do
eCorpusNode <- get session $ corpusNodeRoute corpusId ""
eDefaultListIds <- (get session $ defaultListIdsRoute corpusId)
eCorpusNode <- get session $ corpusNodeRoute (fromMaybe 0 corpusId) ""
eDefaultListIds <- (get session $ defaultListIdsRoute (fromMaybe 0 corpusId))
:: forall a. JSON.ReadForeign a => AffETableResult (NodePoly a)
case eCorpusNode of
Left err -> pure $ Left err
......@@ -398,7 +398,7 @@ loadCorpus {nodeId, session} = do
Right defaultListIds -> do
case (A.head defaultListIds.docs :: Maybe (NodePoly HyperdataList)) of
Just (NodePoly { id: defaultListId }) ->
pure $ Right { corpusId, corpusNode, defaultListId }
pure $ Right { corpusId: (fromMaybe 0 corpusId), corpusNode, defaultListId }
Nothing ->
pure $ Left $ CustomError "Missing default list"
......@@ -425,18 +425,18 @@ loadCorpusWithChild { nodeId: childId, session } = do
Left err -> pure $ Left err
Right listNode -> do
let (NodePoly {parentId: corpusId} :: NodePoly {}) = listNode
eCorpusNode <- get session $ corpusNodeRoute corpusId ""
eCorpusNode <- get session $ corpusNodeRoute (fromMaybe 0 corpusId) ""
case eCorpusNode of
Left err -> pure $ Left err
Right corpusNode -> do
eDefaultListIds <- (get session $ defaultListIdsRoute corpusId)
eDefaultListIds <- (get session $ defaultListIdsRoute (fromMaybe 0 corpusId))
:: forall a. JSON.ReadForeign a => AffETableResult (NodePoly a)
case eDefaultListIds of
Left err -> pure $ Left err
Right defaultListIds -> do
case (A.head defaultListIds.docs :: Maybe (NodePoly HyperdataList)) of
Just (NodePoly { id: defaultListId }) ->
pure $ Right { corpusId, corpusNode, defaultListId }
pure $ Right { corpusId: fromMaybe 0 corpusId, corpusNode, defaultListId }
Nothing ->
throwError $ error "Missing default list"
where
......
......@@ -11,7 +11,7 @@ import Gargantext.Components.App.Store (Boxes)
import Gargantext.Components.Charts.Options.Type (EChartsInstance, MouseEvent)
import Gargantext.Components.Nodes.Corpus.Chart.Histo (histo)
import Gargantext.Components.Nodes.Corpus.Chart.Metrics (metrics)
import Gargantext.Components.Nodes.Corpus.Chart.Pie (pie)
import Gargantext.Components.Nodes.Corpus.Chart.Pie (bar, pie)
import Gargantext.Components.Nodes.Corpus.Chart.Tree (tree)
import Gargantext.Sessions (Session)
import Gargantext.Types (Mode(..), NodeID, TabSubType(..), TabType(..), modeTabType)
......@@ -99,7 +99,7 @@ render CTermsMetrics { boxes, corpusId, limit, listId, session, onClick, onInit
, tabType: TabCorpus (TabNgramType $ modeTabType Terms)
}
render CSourcesBar { boxes, corpusId, limit, listId, session, onClick, onInit } =
metrics { boxes, path, session, onClick, onInit }
bar { boxes, path, session, onClick, onInit }
where
path = { corpusId
, limit
......
......@@ -11,11 +11,13 @@ import Gargantext.Components.Bootstrap as B
import Gargantext.Components.PhyloExplorer.API (get)
import Gargantext.Components.PhyloExplorer.Layout (layout)
import Gargantext.Components.PhyloExplorer.Store as PhyloStore
import Gargantext.Components.PhyloExplorer.Types (PhyloDataSet)
import Gargantext.Components.PhyloExplorer.Types (CacheParams, PhyloSet(..), defaultCacheParams)
import Gargantext.Config.REST (logRESTError)
import Gargantext.Hooks.FirstEffect (useFirstEffect')
import Gargantext.Hooks.Loader (useLoaderEffect)
import Gargantext.Hooks.Session (useSession)
import Gargantext.Types (NodeID)
import Gargantext.Utils (getter)
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
......@@ -38,7 +40,8 @@ nodeCpt = here.component "node" cpt where
-- |
session <- useSession
state' /\ state <- R2.useBox' Nothing
state' /\ state <- R2.useBox' (Nothing :: Maybe PhyloSet)
cache' /\ cache <- R2.useBox' (defaultCacheParams :: CacheParams)
-- | Computed
-- |
......@@ -47,6 +50,10 @@ nodeCpt = here.component "node" cpt where
-- | Hooks
-- |
-- load Local Storage cache (if exists)
useFirstEffect' $
R2.loadLocalStorageState R2.phyloParamsKey cache
useLoaderEffect
{ errorHandler
, loader: get session
......@@ -85,14 +92,19 @@ nodeCpt = here.component "node" cpt where
]
]
, defaultSlot:
R2.fromMaybe state' \(phyloDataSet :: PhyloDataSet) ->
R2.fromMaybe state' \(PhyloSet { corpusId, listId, phyloData }) ->
let
state_ :: Record PhyloStore.State
state_ =
-- Data
{ phyloDataSet
{ phyloData
, corpusId
, listId
, phyloId: nodeId
-- (cache params)
, expandSelection: getter _.expandSelection cache'
, expandNeighborhood: getter _.expandNeighborhood cache'
-- (default options)
} `Record.merge` PhyloStore.options
......
......@@ -17,10 +17,12 @@ import Gargantext.Components.GraphExplorer.Layout (convert, layout)
import Gargantext.Components.GraphExplorer.Store as GraphStore
import Gargantext.Components.GraphExplorer.Types as GET
import Gargantext.Config.REST (logRESTError)
import Gargantext.Hooks.FirstEffect (useFirstEffect')
import Gargantext.Hooks.Loader (useLoaderEffect)
import Gargantext.Hooks.Session (useSession)
import Gargantext.Hooks.Sigmax as Sigmax
import Gargantext.Hooks.Sigmax.Types as SigmaxT
import Gargantext.Utils (getter)
import Gargantext.Utils.Range as Range
import Gargantext.Utils.Reactix as R2
import Reactix as R
......@@ -48,9 +50,19 @@ nodeCpt = here.component "node" cpt where
graphVersion' <- R2.useLive' graphVersion
state' /\ state <- R2.useBox' Nothing
cache' /\ cache <- R2.useBox' (GET.defaultCacheParams :: GET.CacheParams)
-- | Computed
-- |
let errorHandler = logRESTError here "[explorerLayout]"
-- | Hooks
-- |
-- load Local Storage cache (if exists)
useFirstEffect' $
R2.loadLocalStorageState R2.graphParamsKey cache
useLoaderEffect
{ errorHandler
, loader: GraphAPI.getNodes session graphVersion'
......@@ -80,21 +92,20 @@ nodeCpt = here.component "node" cpt where
{}
, defaultSlot:
R2.fromMaybe state' handler
R2.fromMaybe state' \loaded ->
let
GET.HyperdataGraph { graph: hyperdataGraph } = loaded
Tuple mMetaData graph = convert hyperdataGraph
in
hydrateStore
{ graph
, hyperdataGraph: loaded
, mMetaData
, graphId
, cacheParams: cache'
}
}
where
errorHandler = logRESTError here "[explorerLayout]"
handler loaded@(GET.HyperdataGraph { graph: hyperdataGraph }) =
hydrateStore
{ graph
, hyperdataGraph: loaded
, mMetaData
, graphId
}
where
Tuple mMetaData graph = convert hyperdataGraph
--------------------------------------------------------
type HydrateStoreProps =
......@@ -102,6 +113,7 @@ type HydrateStoreProps =
, graph :: SigmaxT.SGraph
, hyperdataGraph :: GET.HyperdataGraph
, graphId :: GET.GraphId
, cacheParams :: GET.CacheParams
)
hydrateStore:: R2.Leaf HydrateStoreProps
......@@ -113,6 +125,7 @@ hydrateStoreCpt = here.component "hydrateStore" cpt where
, graph
, graphId
, hyperdataGraph
, cacheParams
} _ = do
-- | Computed
-- |
......@@ -144,6 +157,9 @@ hydrateStoreCpt = here.component "hydrateStore" cpt where
{ min: 0.0
, max: I.toNumber $ Seq.length $ SigmaxT.graphEdges graph
}
-- (cache options)
, expandSelection: getter _.expandSelection cacheParams
, expandNeighborhood: getter _.expandNeighborhood cacheParams
-- (default options)
} `Record.merge` GraphStore.options
......
......@@ -8,8 +8,7 @@ import Data.Tuple.Nested ((/\))
import Effect.Class (liftEffect)
import Gargantext.Components.App.Store (Boxes)
import Gargantext.Components.NgramsTable as NT
import Gargantext.Components.NgramsTable.Core (PageParams)
import Gargantext.Components.NgramsTable.Core as NTC
import Gargantext.Core.NgramsTable.Functions as NTC
import Gargantext.Components.Nodes.Corpus.Chart.Metrics (metrics)
import Gargantext.Components.Nodes.Corpus.Chart.Pie (pie, bar)
import Gargantext.Components.Nodes.Corpus.Chart.Tree (tree)
......@@ -17,6 +16,7 @@ import Gargantext.Components.Nodes.Corpus.Chart.Utils (mNgramsTypeFromTabType)
import Gargantext.Components.Nodes.Corpus.Types (CorpusData)
import Gargantext.Components.Tab as Tab
import Gargantext.Components.Table.Types (Params)
import Gargantext.Core.NgramsTable.Types (PageParams)
import Gargantext.Prelude (bind, pure, unit, ($))
import Gargantext.Sessions (Session)
import Gargantext.Types (CTabNgramType(..), Mode(..), TabSubType(..), TabType(..), modeTabType)
......@@ -89,6 +89,10 @@ ngramsViewCpt = here.component "ngramsView" cpt where
, session
, path } _ = do
chartsReload <- T.useBox T2.newReload
onCancelRef <- R.useRef Nothing
onNgramsClickRef <- R.useRef Nothing
onSaveRef <- R.useRef Nothing
treeEditBox <- T.useBox NT.initialTreeEdit
{ listIds, nodeId, params } <- T.useLive T.unequal path
......@@ -96,13 +100,13 @@ ngramsViewCpt = here.component "ngramsView" cpt where
R.fragment
[
ngramsView'
{ mode
, boxes
, session
, params
{ boxes
, corpusData: props.corpusData
, listIds
, mode
, nodeId
, corpusData: props.corpusData
, params
, session
} []
,
NT.mainNgramsTable
......@@ -114,6 +118,11 @@ ngramsViewCpt = here.component "ngramsView" cpt where
, session
, tabNgramType
, tabType
, treeEdit: { box: treeEditBox
, getNgramsChildren: NT.getNgramsChildrenAff session nodeId listIds tabType
, onCancelRef
, onNgramsClickRef
, onSaveRef }
, withAutoUpdate: false
} []
]
......@@ -139,26 +148,28 @@ ngramsViewCpt = here.component "ngramsView" cpt where
-- @XXX re-render issue -> clone component
type NgramsViewProps' =
( mode :: Mode
, boxes :: Boxes
, session :: Session
( boxes :: Boxes
, corpusData :: CorpusData
, listIds :: Array Int
, params :: Params
, mode :: Mode
, nodeId :: Int
, corpusData :: CorpusData
, params :: Params
, session :: Session
)
ngramsView' :: R2.Component NgramsViewProps'
ngramsView' = R.createElement ngramsViewCpt'
ngramsViewCpt' :: R.Memo NgramsViewProps'
ngramsViewCpt' = R.memo' $ here.component "ngramsView_clone" cpt where
cpt { mode
, boxes
, session
--ngramsViewCpt' :: R.Memo NgramsViewProps'
--ngramsViewCpt' = R.memo' $ here.component "ngramsView_clone" cpt where
ngramsViewCpt' :: R.Component NgramsViewProps'
ngramsViewCpt' = here.component "ngramsView_clone" cpt where
cpt { boxes
, corpusData: { defaultListId }
, listIds
, params
, mode
, nodeId
, corpusData: { defaultListId }
, params
, session
} _ = do
let path' = {
......
......@@ -6,7 +6,6 @@ import Data.Generic.Rep (class Generic)
import Data.Maybe (Maybe(..))
import Data.Show.Generic (genericShow)
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect.Aff (launchAff_)
import Gargantext.Components.App.Store (Boxes)
import Gargantext.Components.App.Store as AppStore
......@@ -128,7 +127,7 @@ textsLayoutWithKeyCpt = here.component "textsLayoutWithKey" cpt where
}
where
errorHandler = logRESTError here "[textsLayoutWithKey]"
afterCacheStateChange cacheState = do
afterCacheStateChange _cacheState = do
launchAff_ $ clearCache unit
-- TODO
--sessionUpdate $ setCacheState session nodeId cacheState
......@@ -248,7 +247,7 @@ histoRender = R.createElement histoRenderCpt
histoRenderCpt :: R.Component HistoProps
histoRenderCpt = here.component "histoRender" cpt where
cpt { boxes, path, onClick, onInit, reload, session } _ = do
reload' <- T.useLive T.unequal reload
_ <- T.useLive T.unequal reload
pure $ histo { boxes, path, onClick, onInit, session }
......
......@@ -16,8 +16,8 @@ import Data.Maybe (Maybe(..))
import Data.Newtype (class Newtype)
import Data.Show.Generic (genericShow)
import Data.Symbol (SProxy(..))
import Gargantext.Components.PhyloExplorer.JSON (PhyloJSONSet)
import Gargantext.Components.PhyloExplorer.Types (PhyloDataSet, parsePhyloJSONSet)
import Gargantext.Components.PhyloExplorer.JSON (PhyloJSON)
import Gargantext.Components.PhyloExplorer.Types (PhyloSet, parseToPhyloSet)
import Gargantext.Config.REST (AffRESTError)
import Gargantext.Routes (SessionRoute(..))
import Gargantext.Routes as GR
......@@ -30,10 +30,10 @@ import Simple.JSON as JSON
import Simple.JSON.Generics as JSONG
get :: S.Session -> NodeID -> AffRESTError (PhyloDataSet)
get session nodeId = request >>= (_ <#> parsePhyloJSONSet) >>> pure
get :: S.Session -> NodeID -> AffRESTError (PhyloSet)
get session nodeId = request >>= (_ <#> parseToPhyloSet) >>> pure
where
request :: AffRESTError (PhyloJSONSet)
request :: AffRESTError (PhyloJSON)
request = S.get session $ PhyloAPI nodeId
----------------------------------------------------------
......
module Gargantext.Components.PhyloExplorer.Frame.DocFocus
( docFocus
) where
import Gargantext.Prelude
import Data.Maybe (Maybe(..))
import Effect (Effect)
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Bootstrap.Types (Elevation(..))
import Gargantext.Components.Nodes.Corpus.Document (node)
import Gargantext.Components.PhyloExplorer.Types (FrameDoc(..))
import Gargantext.Sessions (Session, sessionId)
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
here :: R2.Here
here = R2.here "Gargantext.Components.GraphExplorer.Frame.DocFocus"
type Props =
( frameDoc :: FrameDoc
, session :: Session
, closeCallback :: Unit -> Effect Unit
)
docFocus :: R2.Leaf Props
docFocus = R2.leaf docFocusCpt
docFocusCpt :: R.Component Props
docFocusCpt = here.component "main" cpt where
cpt { frameDoc: FrameDoc { docId, listId, corpusId }
, session
, closeCallback
} _ = do
-- | Render
-- |
pure $
H.div
{ className: "graph-doc-focus" }
[
H.div
{ className: "graph-doc-focus__header" }
[
B.iconButton
{ name: "times"
, elevation: Level2
, callback: closeCallback
}
]
,
H.div
{ className: "graph-doc-focus__body" }
[
-- print the document node
node
{ listId
, mCorpusId: Just corpusId
, nodeId: docId
, key: show (sessionId session) <> "-" <> show docId
}
]
]
module Gargantext.Components.PhyloExplorer.JSON where
module Gargantext.Components.PhyloExplorer.JSON
( PhyloJSON(..)
, GraphData(..)
, NodeData(..), RawObject(..)
, EdgeData(..), RawEdge(..)
) where
import Gargantext.Prelude
......@@ -10,6 +15,26 @@ import Gargantext.Utils.SimpleJSON (untaggedSumRep)
import Simple.JSON as JSON
newtype PhyloJSON = PhyloJSON
{ pd_corpusId :: Int
, pd_listId :: Int
, pd_data ::
{ _subgraph_cnt :: Int
, directed :: Boolean
, edges :: Array RawEdge
, objects :: Array RawObject
, strict :: Boolean
| GraphData
}
}
derive instance Generic PhyloJSON _
derive instance Eq PhyloJSON
instance Show PhyloJSON where show = genericShow
derive newtype instance JSON.ReadForeign PhyloJSON
--------------------------------------------------
type GraphData =
( bb :: String
, color :: String
......@@ -39,22 +64,6 @@ type GraphData =
--------------------------------------------------
newtype PhyloJSONSet = PhyloJSONSet
{ _subgraph_cnt :: Int
, directed :: Boolean
, edges :: Array RawEdge
, objects :: Array RawObject
, strict :: Boolean
| GraphData
}
derive instance Generic PhyloJSONSet _
derive instance Eq PhyloJSONSet
instance Show PhyloJSONSet where show = genericShow
derive newtype instance JSON.ReadForeign PhyloJSONSet
--------------------------------------------------
type NodeData =
( height :: String
, label :: String
......@@ -125,7 +134,6 @@ instance Show RawObject where show = genericShow
instance JSON.ReadForeign RawObject where
readImpl f = GR.to <$> untaggedSumRep f
--------------------------------------------------
type EdgeData =
......
......@@ -13,14 +13,16 @@ import Data.String (null)
import Effect (Effect)
import FFI.Simple ((..), (.=))
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.PhyloExplorer.Frame.DocFocus (docFocus)
import Gargantext.Components.PhyloExplorer.Resources (PubSubEvent(..))
import Gargantext.Components.PhyloExplorer.Resources as RS
import Gargantext.Components.PhyloExplorer.SideBar (sideBar)
import Gargantext.Components.PhyloExplorer.Store as PhyloStore
import Gargantext.Components.PhyloExplorer.ToolBar (toolBar)
import Gargantext.Components.PhyloExplorer.TopBar (topBar)
import Gargantext.Components.PhyloExplorer.Types (DisplayView, ExtractedCount, FrameDoc, PhyloDataSet(..), TabView(..), Term, sortSources)
import Gargantext.Components.PhyloExplorer.Types (DisplayView, ExtractedCount, FrameDoc, PhyloData(..), TabView(..), Term, sortSources)
import Gargantext.Hooks.FirstEffect (useFirstEffect')
import Gargantext.Hooks.Session (useSession)
import Gargantext.Hooks.UpdateEffect (useUpdateEffect1', useUpdateEffect3')
import Gargantext.Types (SidePanelState(..))
import Gargantext.Utils (getter, (?))
......@@ -59,11 +61,11 @@ layoutCpt = here.component "layout" cpt where
, selectedSource
, extractedCount
, phyloId
, phyloDataSet
, phyloData
, frameDoc
} <- PhyloStore.use
(PhyloDataSet o) <- R2.useLive' phyloDataSet
(PhyloData o) <- R2.useLive' phyloData
phyloId' <- R2.useLive' phyloId
sources' <- R2.useLive' sources
terms' <- R2.useLive' terms
......@@ -77,6 +79,8 @@ layoutCpt = here.component "layout" cpt where
selectedSource' <- R2.useLive' selectedSource
frameDoc' <- R2.useLive' frameDoc
session <- useSession
-- | Hooks
-- |
let topBarPortalKey = "portal-topbar::" <> show phyloId'
......@@ -143,6 +147,9 @@ layoutCpt = here.component "layout" cpt where
mTerm <- RS.autocompleteSearch terms' s
RS.autocompleteSubmit displayView mTerm
closeDocCallback :: Unit -> Effect Unit
closeDocCallback _ = T.write_ Nothing frameDoc
-- | Effects
-- |
......@@ -150,7 +157,7 @@ layoutCpt = here.component "layout" cpt where
useFirstEffect' do
(sortSources >>> flip T.write_ sources) o.sources
RS.setGlobalD3Reference window d3
RS.setGlobalDependencies window (PhyloDataSet o)
RS.setGlobalDependencies window (PhyloData o)
RS.drawPhylo
o.branches
o.periods
......@@ -256,7 +263,7 @@ layoutCpt = here.component "layout" cpt where
{ className: "phylo__frame" }
[
-- Doc focus
R2.fromMaybe frameDoc' \(f :: FrameDoc) ->
R2.fromMaybe frameDoc' \(frameDoc_ :: FrameDoc) ->
H.div
{ className: "phylo__focus" }
......@@ -264,7 +271,11 @@ layoutCpt = here.component "layout" cpt where
H.div
{ className: "phylo__focus__inner" }
[
H.text $ "hello"
docFocus
{ session
, frameDoc: frameDoc_
, closeCallback: closeDocCallback
}
]
]
,
......
......@@ -25,7 +25,7 @@ import Data.String as String
import Effect (Effect)
import Effect.Uncurried (EffectFn1, EffectFn2, EffectFn4, EffectFn7, runEffectFn1, runEffectFn2, runEffectFn4, runEffectFn7)
import FFI.Simple ((..), (.=), (.?))
import Gargantext.Components.PhyloExplorer.Types (AncestorLink, Branch, BranchLink, DisplayView(..), Group(..), Link, Period, PhyloDataSet(..), Source(..), Term(..))
import Gargantext.Components.PhyloExplorer.Types (AncestorLink, Branch, BranchLink, DisplayView(..), Group(..), Link, Period, PhyloData(..), Source(..), Term(..))
import Gargantext.Utils (getter)
import Gargantext.Utils.Reactix ((~~))
import Gargantext.Utils.Reactix as R2
......@@ -203,8 +203,8 @@ selectionNodes = ffi ["selection", ""] "selection.nodes()"
-----------------------------------------------------------
setGlobalDependencies :: Window -> PhyloDataSet -> Effect Unit
setGlobalDependencies w (PhyloDataSet o)
setGlobalDependencies :: Window -> PhyloData -> Effect Unit
setGlobalDependencies w (PhyloData o)
= do
_ <- pure $ (w .= "freq") {}
_ <- pure $ (w .= "nbBranches") o.nbBranches
......
......@@ -5,7 +5,7 @@ module Gargantext.Components.PhyloExplorer.DetailsTab
import Gargantext.Prelude
import Gargantext.Components.PhyloExplorer.Store as PhyloStore
import Gargantext.Components.PhyloExplorer.Types (PhyloDataSet(..))
import Gargantext.Components.PhyloExplorer.Types (PhyloData(..))
import Gargantext.Utils (nbsp)
import Gargantext.Utils.Reactix as R2
import Reactix as R
......@@ -25,7 +25,7 @@ detailsTabCpt = here.component "" cpt where
-- |
store <- PhyloStore.use
(PhyloDataSet o) <- R2.useLive' store.phyloDataSet
(PhyloData o) <- R2.useLive' store.phyloData
-- | Render
-- |
......
......@@ -12,9 +12,11 @@ import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Gargantext.Components.Bootstrap as B
import Gargantext.Components.Bootstrap.Types (ButtonVariant(..), Variant(..))
import Gargantext.Components.PhyloExplorer.Sidebar.DocList (docListWrapper)
import Gargantext.Components.PhyloExplorer.Store as PhyloStore
import Gargantext.Components.PhyloExplorer.Types (ExtractedCount(..), ExtractedTerm(..))
import Gargantext.Utils (nbsp, (?))
import Gargantext.Components.PhyloExplorer.Types (ExtractedCount(..), ExtractedTerm(..), defaultCacheParams)
import Gargantext.Hooks.FirstEffect (useFirstEffect')
import Gargantext.Utils (nbsp, setter, (?))
import Gargantext.Utils.Reactix as R2
import Reactix as R
import Reactix.DOM.HTML as H
......@@ -28,22 +30,23 @@ type Props =
selectionTab :: R2.Leaf Props
selectionTab = R2.leaf component
componentName :: String
componentName = "Gargantext.Components.PhyloExplorer.SideBar.SelectionTab"
here :: R2.Here
here = R2.here "Gargantext.Components.PhyloExplorer.SideBar.SelectionTab"
component :: R.Component Props
component = R.hooksComponent componentName cpt where
component = here.component "main" cpt where
cpt { selectTermCallback
} _ = do
-- | State
-- |
store <- PhyloStore.use
extractedTerms <- R2.useLive' store.extractedTerms
extractedCount <- R2.useLive' store.extractedCount
selectedTerm <- R2.useLive' store.selectedTerm
selectedBranch <- R2.useLive' store.selectedBranch
selectedSource <- R2.useLive' store.selectedSource
extractedTerms <- R2.useLive' store.extractedTerms
extractedCount <- R2.useLive' store.extractedCount
selectedTerm <- R2.useLive' store.selectedTerm
selectedBranch <- R2.useLive' store.selectedBranch
selectedSource <- R2.useLive' store.selectedSource
expandNeighborhood <- R2.useLive' store.expandNeighborhood
showMore' /\ showMore <- R2.useBox' false
......@@ -68,6 +71,17 @@ component = R.hooksComponent componentName cpt where
R.useEffect1' extractedTerms $
T.write_ false showMore
-- transfer local Component change to Local Storage cache
useFirstEffect' $
flip T.listen store.expandNeighborhood onExpandNeighborhoodChange
-- | Behaviors
-- |
let
onExpandClick _ = T.modify_ (not) store.expandNeighborhood
-- | Render
-- |
pure $
......@@ -249,68 +263,86 @@ component = R.hooksComponent componentName cpt where
,
detailsCount count.branchCount "branches" false
]
,
-- Expand word cloud
B.iconButton
{ name: expandNeighborhood ?
"caret-up" $
"caret-down"
, className: "phylo-selection-tab__counter__expand"
, callback: onExpandClick
}
]
,
-- Term word cloud
H.li
{ className: "list-group-item" }
[
H.ul
{} $
flip mapWithIndex extractedTerms
\index (ExtractedTerm { label, ratio }) ->
R2.when
(
truncateResults == false
|| index < maxTruncateResult
) $
H.li
{ className: "phylo-selection-tab__selection__item"}
[
H.a
{ className: "badge badge-light"
-- adjust font size according to term frequency
, style:
{ fontSize: termFontSize ratio
, lineHeight: termFontSize ratio
R2.when expandNeighborhood $
H.li
{ className: "list-group-item" }
[
H.ul
{} $
flip mapWithIndex extractedTerms
\index (ExtractedTerm { label, ratio }) ->
R2.when
(
truncateResults == false
|| index < maxTruncateResult
) $
H.li
{ className: "phylo-selection-tab__selection__item"}
[
H.a
{ className: "badge badge-light"
-- adjust font size according to term frequency
, style:
{ fontSize: termFontSize ratio
, lineHeight: termFontSize ratio
}
, on:
{ click: \_ -> selectTermCallback label
}
, on:
{ click: \_ -> selectTermCallback label
}
}
[
H.text label
[
H.text label
]
]
]
,
R2.when (truncateResults) $
B.button
{ variant: ButtonVariant Light
, callback: \_ -> T.modify_ not showMore
, block: true
, className: "phylo-selection-tab__selection__show-more"
}
[
H.text "Show more"
]
]
,
R2.when (truncateResults) $
B.button
{ variant: ButtonVariant Light
, callback: \_ -> T.modify_ not showMore
, block: true
, className: "phylo-selection-tab__selection__show-more"
}
[
H.text "Show more"
]
]
]
]
-- ,
,
-- (separator)
-- R2.when (not null extractedTerms) $
-- H.div
-- { className: "phylo-selection-tab__separator" }
-- [
-- B.icon
-- { name: "angle-double-down" }
-- ]
-- ,
R2.when (not null extractedTerms) $
H.div
{ className: "phylo-selection-tab__separator" }
[
B.icon
{ name: "angle-double-down" }
]
,
-- Extracted Docs
-- R2.when (not null extractedTerms) $
R2.when (not null extractedTerms) $
H.div
{ className: "phylo-selection-tab__extracted-docs" }
[
docListWrapper
{}
]
]
termFontSize :: Number -> String
......@@ -346,3 +378,9 @@ detailsCount value label weighty =
H.text $ nbsp 1 <> label
]
]
onExpandNeighborhoodChange :: T.Change Boolean -> Effect Unit
onExpandNeighborhoodChange { new } = do
cache <- R2.loadLocalStorageState' R2.phyloParamsKey defaultCacheParams
let update = setter (_ { expandNeighborhood = new }) cache
R2.setLocalStorageState R2.phyloParamsKey update
......@@ -11,8 +11,9 @@ module Gargantext.Components.PhyloExplorer.Store
import Gargantext.Prelude
import Data.Maybe (Maybe(..))
import Gargantext.Components.PhyloExplorer.Types (DisplayView(..), ExtractedCount, ExtractedTerm, FrameDoc, PhyloDataSet, Source, TabView(..), Term)
import Gargantext.Components.PhyloExplorer.Types (CorpusId, DisplayView(..), ExtractedCount, ExtractedTerm, FrameDoc, PhyloData, Source, TabView(..), Term, ListId, defaultCacheParams)
import Gargantext.Types (NodeID, SidePanelState(..))
import Gargantext.Utils (getter)
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Stores as Stores
import Reactix as R
......@@ -24,104 +25,116 @@ here = R2.here "Gargantext.Components.GraphExplorer.Store"
type Store =
-- Data
( phyloDataSet :: T.Box PhyloDataSet
, phyloId :: T.Box NodeID
, isBuilt :: T.Box Boolean
( phyloData :: T.Box PhyloData
, phyloId :: T.Box NodeID
, corpusId :: T.Box CorpusId
, listId :: T.Box ListId
, isBuilt :: T.Box Boolean
-- Layout
, toolBarDisplayed :: T.Box Boolean
, isIsolineDisplayed :: T.Box Boolean
, sideBarDisplayed :: T.Box SidePanelState
, sideBarTabView :: T.Box TabView
, frameDoc :: T.Box (Maybe FrameDoc)
, toolBarDisplayed :: T.Box Boolean
, isIsolineDisplayed :: T.Box Boolean
, sideBarDisplayed :: T.Box SidePanelState
, sideBarTabView :: T.Box TabView
, frameDoc :: T.Box (Maybe FrameDoc)
, expandSelection :: T.Box Boolean
, expandNeighborhood :: T.Box Boolean
-- Topbar
, source :: T.Box String
, sources :: T.Box (Array Source)
, terms :: T.Box (Array Term)
, search :: T.Box String
, result :: T.Box (Maybe Term)
, source :: T.Box String
, sources :: T.Box (Array Source)
, terms :: T.Box (Array Term)
, search :: T.Box String
, result :: T.Box (Maybe Term)
-- Sidebar
, extractedTerms :: T.Box (Array ExtractedTerm)
, selectedTerm :: T.Box (Maybe String)
, selectedBranch :: T.Box (Maybe String)
, selectedSource :: T.Box (Maybe String)
, extractedCount :: T.Box (Maybe ExtractedCount)
, extractedTerms :: T.Box (Array ExtractedTerm)
, selectedTerm :: T.Box (Maybe String)
, selectedBranch :: T.Box (Maybe String)
, selectedSource :: T.Box (Maybe String)
, extractedCount :: T.Box (Maybe ExtractedCount)
-- Toolbar
, displayView :: T.Box DisplayView
, displayView :: T.Box DisplayView
)
type State =
-- Data
( phyloDataSet :: PhyloDataSet
, phyloId :: NodeID
, isBuilt :: Boolean
( phyloData :: PhyloData
, phyloId :: NodeID
, corpusId :: CorpusId
, listId :: ListId
, isBuilt :: Boolean
-- Layout
, toolBarDisplayed :: Boolean
, isIsolineDisplayed :: Boolean
, sideBarDisplayed :: SidePanelState
, sideBarTabView :: TabView
, frameDoc :: Maybe FrameDoc
, toolBarDisplayed :: Boolean
, isIsolineDisplayed :: Boolean
, sideBarDisplayed :: SidePanelState
, sideBarTabView :: TabView
, frameDoc :: Maybe FrameDoc
, expandSelection :: Boolean
, expandNeighborhood :: Boolean
-- Topbar
, source :: String
, sources :: Array Source
, terms :: Array Term
, search :: String
, result :: Maybe Term
, source :: String
, sources :: Array Source
, terms :: Array Term
, search :: String
, result :: Maybe Term
-- Sidebar
, extractedTerms :: Array ExtractedTerm
, selectedTerm :: Maybe String
, selectedBranch :: Maybe String
, selectedSource :: Maybe String
, extractedCount :: Maybe ExtractedCount
, extractedTerms :: Array ExtractedTerm
, selectedTerm :: Maybe String
, selectedBranch :: Maybe String
, selectedSource :: Maybe String
, extractedCount :: Maybe ExtractedCount
-- Toolbar
, displayView :: DisplayView
, displayView :: DisplayView
)
options ::
{ isBuilt :: Boolean
{ isBuilt :: Boolean
-- Layout
, toolBarDisplayed :: Boolean
, isIsolineDisplayed :: Boolean
, sideBarDisplayed :: SidePanelState
, sideBarTabView :: TabView
, frameDoc :: Maybe FrameDoc
, toolBarDisplayed :: Boolean
, isIsolineDisplayed :: Boolean
, sideBarDisplayed :: SidePanelState
, sideBarTabView :: TabView
, frameDoc :: Maybe FrameDoc
, expandSelection :: Boolean
, expandNeighborhood :: Boolean
-- Topbar
, source :: String
, sources :: Array Source
, terms :: Array Term
, search :: String
, result :: Maybe Term
, source :: String
, sources :: Array Source
, terms :: Array Term
, search :: String
, result :: Maybe Term
-- Sidebar
, extractedTerms :: Array ExtractedTerm
, selectedTerm :: Maybe String
, selectedBranch :: Maybe String
, selectedSource :: Maybe String
, extractedCount :: Maybe ExtractedCount
, extractedTerms :: Array ExtractedTerm
, selectedTerm :: Maybe String
, selectedBranch :: Maybe String
, selectedSource :: Maybe String
, extractedCount :: Maybe ExtractedCount
-- Toolbar
, displayView :: DisplayView
, displayView :: DisplayView
}
options =
-- Data
{ isBuilt : false
{ isBuilt : false
-- Layout
, toolBarDisplayed : false
, isIsolineDisplayed : false
, sideBarDisplayed : InitialClosed
, sideBarTabView : DetailsTab
, frameDoc : Nothing
, toolBarDisplayed : false
, isIsolineDisplayed : false
, sideBarDisplayed : InitialClosed
, sideBarTabView : DetailsTab
, frameDoc : Nothing
, expandSelection : getter _.expandSelection defaultCacheParams
, expandNeighborhood : getter _.expandNeighborhood defaultCacheParams
-- Topbar
, source : ""
, sources : mempty
, terms : mempty
, search : ""
, result : Nothing
, source : ""
, sources : mempty
, terms : mempty
, search : ""
, result : Nothing
-- Sidebar
, extractedTerms : mempty
, selectedTerm : Nothing
, selectedBranch : Nothing
, selectedSource : Nothing
, extractedCount : Nothing
, extractedTerms : mempty
, selectedTerm : Nothing
, selectedBranch : Nothing
, selectedSource : Nothing
, extractedCount : Nothing
-- Toolbar
, displayView : HeadingMode
, displayView : HeadingMode
}
context :: R.Context (Record Store)
......
module Gargantext.Components.PhyloExplorer.Types
( PhyloDataSet(..)
, parsePhyloJSONSet
( PhyloSet(..), parseToPhyloSet
, CorpusId, ListId, DocId
, PhyloData(..)
, Branch(..), Period(..), Group(..)
, Link(..), AncestorLink(..), BranchLink(..)
, Term(..)
......@@ -11,6 +12,7 @@ module Gargantext.Components.PhyloExplorer.Types
, ExtractedTerm(..)
, ExtractedCount(..)
, FrameDoc(..)
, CacheParams(..), defaultCacheParams
) where
import Gargantext.Prelude
......@@ -27,18 +29,72 @@ import Data.String as String
import Data.String.Extra (camelCase)
import Data.Tuple as Tuple
import Data.Tuple.Nested ((/\))
import Gargantext.Components.PhyloExplorer.JSON (PhyloJSONSet(..), RawEdge(..), RawObject(..))
import Gargantext.Components.PhyloExplorer.JSON (PhyloJSON(..), RawEdge(..), RawObject(..))
import Gargantext.Types (NodeID)
import Simple.JSON as JSON
-- @NOTE #219: PureScript Date or stick to JavaScript foreign?
foreign import yearToDate :: String -> Date.Date
foreign import stringToDate :: String -> Date.Date
foreign import utcStringToDate :: String -> Date.Date
type CorpusId = Int
type ListId = Int
type DocId = Int
------------------------------------------------------------------
data PhyloSet = PhyloSet
{ corpusId :: CorpusId
, listId :: ListId
, phyloData :: PhyloData
}
derive instance Generic PhyloSet _
derive instance Eq PhyloSet
instance Show PhyloSet where show = genericShow
parseToPhyloSet :: PhyloJSON -> PhyloSet
parseToPhyloSet (PhyloJSON o) = PhyloSet
{ corpusId : o.pd_corpusId
, listId : o.pd_listId
, phyloData : PhyloData
{ ancestorLinks
, bb : parseBB p.bb
, branchLinks
, branches
, groups
, links
, name : p.name
, nbBranches : parseInt p.phyloBranches
-- @NOTE #219: remotely stringify as a Double instead of an Int (reason?)
, nbDocs : (parseFloat >>> parseInt') p.phyloDocs
, nbFoundations : parseInt p.phyloFoundations
, nbGroups : parseInt p.phyloGroups
, nbPeriods : parseInt p.phyloPeriods
, nbTerms : parseInt p.phyloTerms
, periods
, sources : parseSources p.phyloSources
, timeScale : p.phyloTimeScale
, weighted : getGlobalWeightedValue groups
}
}
where
p = o.pd_data
epochTS = p.phyloTimeScale == "epoch"
ancestorLinks = parseAncestorLinks p.edges
branchLinks = parseBranchLinks p.edges
branches = parseBranches p.objects
groups = parseGroups epochTS p.objects
links = parseLinks p.edges
periods = parsePeriods epochTS p.objects
data PhyloDataSet = PhyloDataSet
----------------------------------------------------------------------
data PhyloData = PhyloData
{ ancestorLinks :: Array AncestorLink
, bb :: Array Number
, branchLinks :: Array BranchLink
......@@ -58,41 +114,9 @@ data PhyloDataSet = PhyloDataSet
, weighted :: Boolean
}
derive instance Generic PhyloDataSet _
derive instance Eq PhyloDataSet
instance Show PhyloDataSet where show = genericShow
parsePhyloJSONSet :: PhyloJSONSet -> PhyloDataSet
parsePhyloJSONSet (PhyloJSONSet o) = PhyloDataSet
{ ancestorLinks
, bb : parseBB o.bb
, branchLinks
, branches
, groups
, links
, name : o.name
, nbBranches : parseInt o.phyloBranches
-- @NOTE #219: remotely stringify as a Double instead of an Int (reason?)
, nbDocs : (parseFloat >>> parseInt') o.phyloDocs
, nbFoundations : parseInt o.phyloFoundations
, nbGroups : parseInt o.phyloGroups
, nbPeriods : parseInt o.phyloPeriods
, nbTerms : parseInt o.phyloTerms
, periods
, sources : parseSources o.phyloSources
, timeScale : o.phyloTimeScale
, weighted : getGlobalWeightedValue groups
}
where
epochTS = o.phyloTimeScale == "epoch"
ancestorLinks = parseAncestorLinks o.edges
branchLinks = parseBranchLinks o.edges
branches = parseBranches o.objects
groups = parseGroups epochTS o.objects
links = parseLinks o.edges
periods = parsePeriods epochTS o.objects
derive instance Generic PhyloData _
derive instance Eq PhyloData
instance Show PhyloData where show = genericShow
-----------------------------------------------------------
......@@ -491,10 +515,33 @@ derive newtype instance JSON.ReadForeign ExtractedCount
-----------------------------------------------------------
newtype FrameDoc = FrameDoc
{ docId :: NodeID
, corpusId :: NodeID
, listId :: NodeID
{ docId :: DocId
, corpusId :: CorpusId
, listId :: ListId
}
derive instance Generic FrameDoc _
derive instance Eq FrameDoc
----------------------------------------------------------------
newtype CacheParams = CacheParams
{ expandSelection :: Boolean
, expandNeighborhood :: Boolean
}
derive instance Newtype CacheParams _
derive instance Generic CacheParams _
derive instance Eq CacheParams
instance Show CacheParams where show = genericShow
derive newtype instance JSON.ReadForeign CacheParams
derive newtype instance JSON.WriteForeign CacheParams
-- (!) in case cache storage (ie. JavaScript Local Storage) returns an invalid
-- objects (eg. possible data migration), this will safely set new default
-- values
defaultCacheParams :: CacheParams
defaultCacheParams = CacheParams
{ expandSelection : true
, expandNeighborhood: true
}
This diff is collapsed.
......@@ -39,6 +39,16 @@ function blur(el) {
return el.blur();
}
function triggerEvent(el, evtType) {
// https://stackoverflow.com/questions/8789423/trigger-onchange-event
var event = new UIEvent(evtType, {
view: window,
bubbles: true,
cancelable: true
});
el.dispatchEvent(event);
}
exports._addRootElement = addRootElement;
exports._getSelection = getSelection;
exports._stringify = stringify;
......@@ -53,3 +63,4 @@ exports._keyCode = function(e) {
// https://www.w3schools.com/jsref/event_key_keycode.asp
return e.which || e.keyCode;
}
exports._triggerEvent = triggerEvent;
......@@ -3,25 +3,25 @@ module Gargantext.Utils.Reactix where
import Prelude
import ConvertableOptions as CO
import DOM.Simple as DOM
import DOM.Simple.Console (log2)
import DOM.Simple.Document (document)
import DOM.Simple.Element as Element
import DOM.Simple.Event as DE
import DOM.Simple.Types (class IsNode, class IsElement, DOMRect)
import Data.Array as A
import Data.Either (hush)
import Data.Function.Uncurried (Fn1, runFn1, Fn2, runFn2)
import Data.Maybe as Maybe
import Data.Maybe (Maybe(..), fromJust, fromMaybe)
import Data.Nullable (Nullable, null, toMaybe)
import Data.Maybe as Maybe
import Data.Nullable (Nullable, notNull, null, toMaybe)
import Data.Tuple (Tuple)
import Data.Tuple.Nested ((/\))
import DOM.Simple as DOM
import DOM.Simple.Console (log2)
import DOM.Simple.Document (document)
import DOM.Simple.Element as Element
import DOM.Simple.Event as DE
import DOM.Simple.Types (class IsNode, class IsElement, DOMRect)
import Effect (Effect)
import Effect.Aff (Aff, launchAff, launchAff_, killFiber)
import Effect.Class (liftEffect)
import Effect.Exception (error)
import Effect.Uncurried (EffectFn1, EffectFn3, mkEffectFn1, mkEffectFn2, runEffectFn1, runEffectFn3)
import Effect.Uncurried (EffectFn1, EffectFn2, EffectFn3, mkEffectFn1, mkEffectFn2, runEffectFn1, runEffectFn2, runEffectFn3)
import FFI.Simple (applyTo, args2, args3, defineProperty, delay, getProperty, (..), (...), (.=))
import Gargantext.Utils.Console (RowConsole)
import Gargantext.Utils.Console as Console
......@@ -397,6 +397,12 @@ getls = window >>= localStorage
openNodesKey :: LocalStorageKey
openNodesKey = "garg-open-nodes"
graphParamsKey :: LocalStorageKey
graphParamsKey = "garg-graph-params"
phyloParamsKey :: LocalStorageKey
phyloParamsKey = "garg-phylo-params"
type LocalStorageKey = String
loadLocalStorageState :: forall s. JSON.ReadForeign s => LocalStorageKey -> T.Box s -> Effect Unit
......@@ -410,6 +416,16 @@ loadLocalStorageState key cell = do
Nothing -> pure unit
Just p -> void $ T.write p cell
loadLocalStorageState' :: forall s.
JSON.ReadForeign s
=> LocalStorageKey
-> s
-> Effect s
loadLocalStorageState' key default = do
(item :: Maybe String) <- getls >>= getItem key
let parsed = hush <<< JSON.readJSON $ Maybe.fromMaybe "" item
pure $ Maybe.fromMaybe default parsed
listenLocalStorageState :: forall s. JSON.WriteForeign s => LocalStorageKey -> T.Change s -> Effect Unit
listenLocalStorageState key { old, new } = do
--let json = Json.stringify $ Argonaut.encodeJson new
......@@ -417,6 +433,15 @@ listenLocalStorageState key { old, new } = do
storage <- getls
setItem key json storage
setLocalStorageState :: forall s.
JSON.WriteForeign s
=> LocalStorageKey
-> s
-> Effect Unit
setLocalStorageState key s =
let json = JSON.writeJSON s
in getls >>= setItem key json
getMessageDataStr :: DE.MessageEvent -> String
getMessageDataStr = getMessageData
......@@ -576,3 +601,17 @@ externalOpeningFlag event = ado
metaKey <- SE.metaKey event
middleClick <- SE.button event
in ctrlKey || shiftKey || metaKey || (middleClick == 1.0)
foreign import _triggerEvent
:: forall e. EffectFn2 e String Unit
triggerEvent :: forall el. el -> String -> Effect Unit
triggerEvent = runEffectFn2 _triggerEvent
-------------------------------------------------------
setInputValue :: R.Ref (Nullable DOM.Element) -> String -> Effect Unit
setInputValue elNullableRef val = case toMaybe (R.readRef elNullableRef) of
Nothing -> pure unit
Just el -> do
_ <- pure $ (el .= "value") val
triggerEvent el "change"
triggerEvent el "input"
......@@ -55,4 +55,3 @@ useMemberBox val box = T.useFocused (Set.member val) (toggleSet val) box
toggleSet :: forall s. Ord s => s -> Boolean -> Set s -> Set s
toggleSet val true set = Set.insert val set
toggleSet val false set = Set.delete val set
......@@ -252,14 +252,13 @@
background-color: $gray-50
&--selected::before
@include fit-positions
content: ""
position: absolute
z-index: 1
width: 2px
background-color: $info
left: 0
top: 0
bottom: 0
// (following list group item border radius)
&--selected:first-child::before
......
This diff is collapsed.
$annotation-graph-color : #11AA11;
// $annotation-candidate-color : #33AAEE;
$annotation-candidate-color : rgb(90, 144, 182);
$annotation-candidate-color : #5A90B6;
$annotation-stop-color : #EE3311;
$annotation-field-base-alpha: 17.5%;
......
......@@ -12,7 +12,8 @@ import Test.Spec (Spec, describe, it)
import Test.Utils (shouldEqualArray)
import Gargantext.Components.NgramsTable.Core (highlightNgrams, HighlightElement, NgramsElement(..), NgramsRepoElement(..), NgramsTable(..), NgramsTerm, normNgram)
import Gargantext.Core.NgramsTable.Functions (highlightNgrams, normNgram)
import Gargantext.Core.NgramsTable.Types (HighlightElement, NgramsElement(..), NgramsRepoElement(..), NgramsTable(..), NgramsTerm)
import Gargantext.Types (CTabNgramType(..), TermList(..))
......
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