Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
P
purescript-gargantext
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
148
Issues
148
List
Board
Labels
Milestones
Merge Requests
2
Merge Requests
2
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
gargantext
purescript-gargantext
Commits
e7d216fa
Commit
e7d216fa
authored
Jan 28, 2021
by
Przemyslaw Kaminski
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'dev' into dev-tree-reload
parents
2a74df72
66c58ed7
Changes
34
Hide whitespace changes
Inline
Side-by-side
Showing
34 changed files
with
993 additions
and
745 deletions
+993
-745
sass.css
dist/styles/sass.css
+11
-15
sass.css.map
dist/styles/sass.css.map
+1
-1
package.json
package.json
+1
-1
App.purs
src/Gargantext/Components/App.purs
+1
-1
CodeEditor.purs
src/Gargantext/Components/CodeEditor.purs
+28
-26
FacetsTable.purs
src/Gargantext/Components/FacetsTable.purs
+107
-65
Settings.purs
src/Gargantext/Components/Forest/Tree/Node/Settings.purs
+1
-0
Graph.purs
src/Gargantext/Components/Graph.purs
+4
-4
Sidebar.purs
src/Gargantext/Components/GraphExplorer/Sidebar.purs
+36
-29
ToggleButton.purs
src/Gargantext/Components/GraphExplorer/ToggleButton.purs
+11
-6
InputWithEnter.purs
src/Gargantext/Components/InputWithEnter.purs
+4
-1
NgramsTable.purs
src/Gargantext/Components/NgramsTable.purs
+145
-158
Core.purs
src/Gargantext/Components/NgramsTable/Core.purs
+31
-0
Annuaire.purs
src/Gargantext/Components/Nodes/Annuaire.purs
+15
-14
Contacts.purs
src/Gargantext/Components/Nodes/Annuaire/User/Contacts.purs
+64
-10
Tabs.purs
...gantext/Components/Nodes/Annuaire/User/Contacts/Tabs.purs
+10
-9
Corpus.purs
src/Gargantext/Components/Nodes/Corpus.purs
+75
-82
Dashboard.purs
src/Gargantext/Components/Nodes/Corpus/Dashboard.purs
+87
-48
Types.purs
src/Gargantext/Components/Nodes/Corpus/Types.purs
+17
-191
Types.purs
src/Gargantext/Components/Nodes/Dashboard/Types.purs
+8
-2
Home.purs
src/Gargantext/Components/Nodes/Home.purs
+3
-3
Lists.purs
src/Gargantext/Components/Nodes/Lists.purs
+18
-18
Tabs.purs
src/Gargantext/Components/Nodes/Lists/Tabs.purs
+2
-2
Types.purs
src/Gargantext/Components/Nodes/Types.purs
+189
-0
Search.purs
src/Gargantext/Components/Search.purs
+3
-3
Tab.purs
src/Gargantext/Components/Tab.purs
+12
-6
Table.purs
src/Gargantext/Components/Table.purs
+22
-21
Ends.purs
src/Gargantext/Ends.purs
+1
-0
Routes.purs
src/Gargantext/Routes.purs
+13
-15
Types.purs
src/Gargantext/Types.purs
+5
-2
_annotation.sass
src/sass/_annotation.sass
+58
-0
_code_editor.sass
src/sass/_code_editor.sass
+3
-11
_styles.sass
src/sass/_styles.sass
+6
-0
_tree.sass
src/sass/_tree.sass
+1
-1
No files found.
dist/styles/sass.css
View file @
e7d216fa
...
@@ -362,6 +362,7 @@ body > .tree ul > li:first-child::before {
...
@@ -362,6 +362,7 @@ body > .tree ul > li:first-child::before {
li
.leaf
{
li
.leaf
{
display
:
flex
;
display
:
flex
;
flex-direction
:
row
;
flex-direction
:
row
;
color
:
#005a9a
ff
;
}
}
li
.leaf
.folder-icon
{
li
.leaf
.folder-icon
{
padding
:
0
2
0
2
;
padding
:
0
2
0
2
;
...
@@ -474,7 +475,6 @@ li .leaf:hover a.settings {
...
@@ -474,7 +475,6 @@ li .leaf:hover a.settings {
margin-top
:
1px
;
margin-top
:
1px
;
}
}
.tree
.node.node-type-valid
.text
{
.tree
.node.node-type-valid
.text
{
color
:
blue
;
text-decoration
:
underline
;
text-decoration
:
underline
;
}
}
...
@@ -533,7 +533,9 @@ li .leaf:hover a.settings {
...
@@ -533,7 +533,9 @@ li .leaf:hover a.settings {
}
}
.code-editor-heading
{
.code-editor-heading
{
display
:
flex
;
/* .buttons-right */
/* display: flex */
/* justify-content: flex-end */
}
}
.code-editor-heading
.renameable
{
.code-editor-heading
.renameable
{
flex-grow
:
2
;
flex-grow
:
2
;
...
@@ -541,20 +543,7 @@ li .leaf:hover a.settings {
...
@@ -541,20 +543,7 @@ li .leaf:hover a.settings {
.code-editor-heading
.renameable
.text
{
.code-editor-heading
.renameable
.text
{
padding-right
:
10px
;
padding-right
:
10px
;
}
}
.code-editor-heading
.buttons-right
{
display
:
flex
;
justify-content
:
flex-end
;
}
.code-editor
.toolbar
{
display
:
flex
;
justify-content
:
flex-start
;
width
:
100%
;
}
.code-editor
.editor
{
display
:
flex
;
width
:
100%
;
}
.code-editor
.editor
.code-area
{
.code-editor
.editor
.code-area
{
flex-grow
:
1
;
flex-grow
:
1
;
max-height
:
200px
;
max-height
:
200px
;
...
@@ -690,6 +679,9 @@ li .leaf:hover a.settings {
...
@@ -690,6 +679,9 @@ li .leaf:hover a.settings {
top
:
50%
;
top
:
50%
;
}
}
.table
tr
td
{
color
:
#005a9a
ff
;
}
.table
tr
td
.active
{
.table
tr
td
.active
{
font-weight
:
bold
;
font-weight
:
bold
;
text-decoration
:
underline
;
text-decoration
:
underline
;
...
@@ -716,6 +708,10 @@ li .leaf:hover a.settings {
...
@@ -716,6 +708,10 @@ li .leaf:hover a.settings {
margin
:
10px
;
margin
:
10px
;
}
}
.body
ul
li
{
color
:
#005a9a
ff
;
}
.range
{
.range
{
width
:
400px
;
width
:
400px
;
/* some space for the right knob */
/* some space for the right knob */
...
...
dist/styles/sass.css.map
View file @
e7d216fa
{"version":3,"sourceRoot":"","sources":["../../src/sass/_menu.sass","../../src/sass/_context_menu.sass","../../src/sass/_graph.sass","../../src/sass/_login.sass","../../src/sass/_tree.sass","../../src/sass/_code_editor.sass","../../src/sass/_styles.sass","../../src/sass/_range_slider.sass"],"names":[],"mappings":"AAAA;AAEA;AACA;AACA;AACA;AACA;AAEA;EACI;EACA;;;AAEJ;EACI;EACA;EACA;EACA;;;AAEJ;EACE;;;AAEF;AACI;EACA;;;AAEJ;AACI;EACA;;;AAGJ;AACA;EACI;;;AAEJ;EACI;EACA;EACA;EACA;;;AAEJ;EACE;EACA;;;AAEF;EACE;;;AC7CF;EACE;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AClBF;EACE;EACA;EACA;;;AAEF;AAkCE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAxCA;EAZA;EACA;EAEA;EAWE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAEF;EACE;EACA;;AAGA;EACE;EACA;;AACN;EACE;;AACF;EACE;;AAEF;EApCA;EACA;EAEA;EAmCE;EACA;;AACF;EACE;;AACF;EACE;;AAWF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEJ;EACE;;AAEA;EACE;;AAEJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;ACpFJ;EACE;;;AAOF;EACE;;AACA;EACE;EACA;;;AAEJ;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAGF;EACE;;AAEE;EACE;EACA;;AACA;EACE;;;AAIJ;EACE;EACA;EACA;EACA;;;AAKJ;EACE;EACA;EACA;;;AAGJ;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;;AACF;EACE;EACA;;AACA;EACE;EACA;EACA;EACA;;AACA;EACE;;AACF;EACE;EACA;EACA;EACA;;AACA;EACE;;AACN;EACE;EACA;EACA;EACA;;;AAGN;EACE;EACA;EACA;EACA;EACA;;AAGE;EACE;;;AAEN;EACE;EACA;EACA;EACA;EACA;;AAGE;EACE;;;AAEN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;;AAEJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;;;AAGF;EACE;;;AAEJ;EACI;EACA;;;AAGF;EACE;;;AAEJ;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;;;ACvKF;EACE;;;AAGA;EACE;EACA;;AAEA;EACE;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAER;EACE;;AAEE;EACE;;AACA;EACE;EACA;EACA;EACA;;AACF;EACE;EACA;EACA;EACA;EACA;;AACF;EACE;;AACF;EACE;EACA;EACA;EAEA;EACA;EACA;;AAEA;EACE;;AACF;EACE;;AAGN;EACE;;AACF;EACE;;AACA;EACE;EACA;;AAEE;EACE;EACA;;AACF;EACE;EACA;;AAIR;EACE;;AACF;EACE;;AACA;EACE;EACA;;AAEE;EACE;EACA;;AACF;EACE;EACA;;AACF;EACE;EACA;;AAEV;EACE;;AACF;EACE;;AAEE;EACE;;AACF;EACE;;AACN;EACE;;AAEE;EACE;EACA;;;AAGR;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;;AAEF;EACE;;;AAIF;EACE;;AAEA;EACE;;;AAGN;EACE;;AACF;EACE;;AACF;EACE;;;AC7IJ;EACE;;AAEA;EACE;;AACA;EACE;;AACJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;;AACF;EACE;EACA;;AACA;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EArDR;EACA;EACA;EACA;EACA;EACA;EACA;EAlBA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AA2DM;EACE;EACA;EACA;EACA;EACA;EA7DR;EACA;EACA;EACA;EACA;EACA;EACA;EAlBA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAmEE;EACE;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;EACA;EACA;;AACA;EACE;EACA;;AACF;EACE;EACA;;AACF;EACE;EACA;;AAGE;EACE;;AAEF;EACE;;;ACtGV;EACE;;AACF;EACE;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAGE;EACE;EACA;;AAEF;EACE;EACA;;;AAEV;EACE;;AACA;EACE;EACA;EACA;;;AAKE;EACE;EACA;;AACF;EACE;;AACA;EACE;;AACJ;EACE;;;AAER;EACE;;;AAEF;EACE;;;AAEF;EACE;;;ACjDF;EACE;AACA;EACA;;AAEA;EACE;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EAEA;EAEA;;AAEA;EACE;EAEA;EACA;EACA;;;AAGN;EACE","file":"sass.css"}
{"version":3,"sourceRoot":"","sources":["../../src/sass/_menu.sass","../../src/sass/_context_menu.sass","../../src/sass/_graph.sass","../../src/sass/_login.sass","../../src/sass/_tree.sass","../../src/sass/_code_editor.sass","../../src/sass/_styles.sass","../../src/sass/_range_slider.sass"],"names":[],"mappings":"AAAA;AAEA;AACA;AACA;AACA;AACA;AAEA;EACI;EACA;;;AAEJ;EACI;EACA;EACA;EACA;;;AAEJ;EACE;;;AAEF;AACI;EACA;;;AAEJ;AACI;EACA;;;AAGJ;AACA;EACI;;;AAEJ;EACI;EACA;EACA;EACA;;;AAEJ;EACE;EACA;;;AAEF;EACE;;;AC7CF;EACE;EACA;EACA;EACA;EACA;;;AAEF;EACE;;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;;;AClBF;EACE;EACA;EACA;;;AAEF;AAkCE;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;AAxCA;EAZA;EACA;EAEA;EAWE;EACA;EACA;EACA;;AAEA;EACE;EACA;;AAEF;EACE;EACA;;AAGA;EACE;EACA;;AACN;EACE;;AACF;EACE;;AAEF;EApCA;EACA;EAEA;EAmCE;EACA;;AACF;EACE;;AACF;EACE;;AAWF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;AAEJ;EACE;;AAEA;EACE;;AAEJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;EACA;;;ACpFJ;EACE;;;AAOF;EACE;;AACA;EACE;EACA;;;AAEJ;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAGF;EACE;;AAEE;EACE;EACA;;AACA;EACE;;;AAIJ;EACE;EACA;EACA;EACA;;;AAKJ;EACE;EACA;EACA;;;AAGJ;EACE;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;;AACF;EACE;EACA;;AACA;EACE;EACA;EACA;EACA;;AACA;EACE;;AACF;EACE;EACA;EACA;EACA;;AACA;EACE;;AACN;EACE;EACA;EACA;EACA;;;AAGN;EACE;EACA;EACA;EACA;EACA;;AAGE;EACE;;;AAEN;EACE;EACA;EACA;EACA;EACA;;AAGE;EACE;;;AAEN;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;;;AAEJ;EACE;EACA;;;AAGF;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;;;AAGF;EACE;;;AAEJ;EACI;EACA;;;AAGF;EACE;;;AAEJ;EACE;;;AAEF;EACE;EACA;;;AAEF;EACE;EACA;EACA;;;AAEF;EACE;EACA;;;AAEF;EACE;;;ACvKF;EACE;;;AAGA;EACE;EACA;EACA;;AAEA;EACE;EACA;;AAEF;EACE;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;;;AAER;EACE;;AAEE;EACE;;AACA;EACE;EACA;EACA;EACA;;AACF;EACE;EACA;EACA;EACA;EACA;;AACF;EACE;;AACF;EACE;EACA;EACA;EAEA;EACA;EACA;;AAEA;EACE;;AACF;EACE;;AAGN;EACE;;AACF;EACE;;AACA;EACE;EACA;;AAEE;EACE;EACA;;AACF;EACE;EACA;;AAIR;EACE;;AACF;EACE;;AACA;EACE;EACA;;AAEE;EACE;EACA;;AACF;EACE;EACA;;AACF;EACE;EACA;;AAEV;EACE;;AACF;EACE;;AAEE;EACE;;AACF;EACE;;AACN;EACE;;AAEE;EACE;;;AAGR;EACE;EACA;EACA;EACA;EACA;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAEA;EAEE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;;AAEF;EACE;;;AAIF;EACE;;AAEA;EACE;;;AAGN;EACE;;AACF;EACE;;AACF;EACE;;;AC7IJ;AAKE;AACA;AACA;;AANA;EACE;;AACA;EACE;;;AAOF;EACE;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EA7CR;EACA;EACA;EACA;EACA;EACA;EACA;EAlBA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AAmDM;EACE;EACA;EACA;EACA;EACA;EArDR;EACA;EACA;EACA;EACA;EACA;EACA;EAlBA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;AA2DE;EACE;EACA;EACA;EACA;EACA;EACA;;AACF;EACE;EACA;EACA;;AACA;EACE;EACA;;AACF;EACE;EACA;;AACF;EACE;EACA;;AAGE;EACE;;AAEF;EACE;;;AC9FV;EACE;;AACF;EACE;EACA;EACA;EACA;EACA;EACA;;AACA;EACE;;AAGE;EACE;EACA;;AAEF;EACE;EACA;;;AAEV;EACE;;AACA;EACE;EACA;EACA;;;AAIA;EACE;;AACA;EACE;EACA;;AACF;EACE;;AACA;EACE;;AACJ;EACE;;;AAER;EACE;;;AAEF;EACE;;;AAEF;EACE;;;AAIE;EACE;;;ACvDN;EACE;AACA;EACA;;AAEA;EACE;EACA;;AAEA;EACE;EACA;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;;AAEF;EACE;EACA;EACA;EACA;EACA;EACA;EACA;EAEA;EAEA;EAEA;;AAEA;EACE;EAEA;EACA;EACA;;;AAGN;EACE","file":"sass.css"}
\ No newline at end of file
\ No newline at end of file
package.json
View file @
e7d216fa
{
{
"name"
:
"Gargantext"
,
"name"
:
"Gargantext"
,
"version"
:
"0.0.2.
5
"
,
"version"
:
"0.0.2.
6
"
,
"scripts"
:
{
"scripts"
:
{
"rebase-set"
:
"spago package-set-upgrade && spago psc-package-insdhall"
,
"rebase-set"
:
"spago package-set-upgrade && spago psc-package-insdhall"
,
"rebuild-set"
:
"spago psc-package-insdhall"
,
"rebuild-set"
:
"spago psc-package-insdhall"
,
...
...
src/Gargantext/Components/App.purs
View file @
e7d216fa
...
@@ -123,7 +123,7 @@ appCpt = R.hooksComponentWithModule thisModule "app" cpt where
...
@@ -123,7 +123,7 @@ appCpt = R.hooksComponentWithModule thisModule "app" cpt where
documentMainLayout { listId, mCorpusId: Just corpusId, nodeId, session } []
documentMainLayout { listId, mCorpusId: Just corpusId, nodeId, session } []
]
]
Dashboard sid nodeId -> withSession sid $ \session -> forested [
Dashboard sid nodeId -> withSession sid $ \session -> forested [
dashboardLayout { nodeId, session }
dashboardLayout { nodeId, session }
[]
]
]
Document sid listId nodeId ->
Document sid listId nodeId ->
withSession sid $
withSession sid $
...
...
src/Gargantext/Components/CodeEditor.purs
View file @
e7d216fa
...
@@ -117,25 +117,24 @@ codeEditorCpt = R.hooksComponentWithModule thisModule "codeEditor" cpt
...
@@ -117,25 +117,24 @@ codeEditorCpt = R.hooksComponentWithModule thisModule "codeEditor" cpt
setCodeOverlay controls code'
setCodeOverlay controls code'
renderHtml code' controls
renderHtml code' controls
pure $ H.div { className: "code-editor" } [
pure $ H.div { className: "code-editor" }
toolbar {controls, onChange}
[ toolbar {controls, onChange}
, H.div { className: "row error" } [
, H.div { className: "row error" }
errorComponent {error: controls.error}
[ errorComponent {error: controls.error} ]
]
, H.div { className: "row editor" }
, H.div { className: "row editor" } [
[ H.div { className: "code-area " <> (codeHidden $ fst controls.viewType) }
H.div { className: "code-area " <> (codeHidden $ fst controls.viewType) } [
[ H.div { className: "code-container" }
H.div { className: "code-container" } [
[ H.textarea { defaultValue: code
H.textarea { defaultValue: code
, on: { change: onEditChange controls onChange }
, on: { change: onEditChange controls onChange }
, placeholder: "Type some code..."
, placeholder: "Type some code..."
, ref: controls.codeElRef } [ ]
, ref: controls.codeElRef } [ ]
, H.pre { className: (langClass $ fst controls.codeType)
, H.pre { className: (langClass $ fst controls.codeType)
-- , contentEditable: "true"
-- , contentEditable: "true"
, ref: controls.codeOverlayElRef
, ref: controls.codeOverlayElRef
, rows: 30
, rows: 30
--, on: { input: onEditChange (fst codeType) codeElRef htmlRef codeRef error }
--, on: { input: onEditChange (fst codeType) codeElRef htmlRef codeRef error }
} []
} []
]
]
]
]
, H.div { className: "v-divider " <> (dividerHidden $ fst controls.viewType) } [ H.text " " ]
, H.div { className: "v-divider " <> (dividerHidden $ fst controls.viewType) } [ H.text " " ]
, H.div { className: "html " <> (langClass $ fst controls.codeType) <> (previewHidden $ fst controls.viewType)
, H.div { className: "html " <> (langClass $ fst controls.codeType) <> (previewHidden $ fst controls.viewType)
...
@@ -208,13 +207,16 @@ toolbarCpt = R.hooksComponentWithModule thisModule "toolbar" cpt
...
@@ -208,13 +207,16 @@ toolbarCpt = R.hooksComponentWithModule thisModule "toolbar" cpt
where
where
cpt props@{controls: {codeType, error, viewType}} _ = do
cpt props@{controls: {codeType, error, viewType}} _ = do
pure $
pure $
H.div { className: "row toolbar" } [
H.div { className: "row toolbar" }
codeTypeSelector {
[ H.div { className: "col-2" }
codeType
[ codeTypeSelector {
, onChange: onChangeCodeType props
codeType
}
, onChange: onChangeCodeType props
, viewTypeSelector {state: viewType}
}
]
]
, H.div { className: "col-1" }
[ viewTypeSelector {state: viewType} ]
]
-- Handle rerendering of preview when viewType changed
-- Handle rerendering of preview when viewType changed
onChangeCodeType :: forall e. Record ToolbarProps -> e -> Effect Unit
onChangeCodeType :: forall e. Record ToolbarProps -> e -> Effect Unit
...
...
src/Gargantext/Components/FacetsTable.purs
View file @
e7d216fa
...
@@ -13,6 +13,7 @@ import Data.Sequence (Seq)
...
@@ -13,6 +13,7 @@ import Data.Sequence (Seq)
import Data.Sequence as Seq
import Data.Sequence as Seq
import Data.Set (Set)
import Data.Set (Set)
import Data.Set as Set
import Data.Set as Set
import Data.String (Pattern(..), split)
import Data.String as String
import Data.String as String
import Data.Tuple (fst, snd)
import Data.Tuple (fst, snd)
import Data.Tuple.Nested ((/\))
import Data.Tuple.Nested ((/\))
...
@@ -59,6 +60,7 @@ type Deletions = { pending :: Set Int
...
@@ -59,6 +60,7 @@ type Deletions = { pending :: Set Int
initialDeletions :: Deletions
initialDeletions :: Deletions
initialDeletions = { pending: mempty, deleted: mempty }
initialDeletions = { pending: mempty, deleted: mempty }
----------------------------------------------------------------------
newtype Pair =
newtype Pair =
Pair { id :: Int
Pair { id :: Int
, label :: String
, label :: String
...
@@ -69,6 +71,7 @@ derive instance genericPair :: Generic Pair _
...
@@ -69,6 +71,7 @@ derive instance genericPair :: Generic Pair _
instance showPair :: Show Pair where
instance showPair :: Show Pair where
show = genericShow
show = genericShow
----------------------------------------------------------------------
newtype DocumentsView =
newtype DocumentsView =
DocumentsView
DocumentsView
{ id :: Int
{ id :: Int
...
@@ -85,15 +88,32 @@ newtype DocumentsView =
...
@@ -85,15 +88,32 @@ newtype DocumentsView =
, publication_day :: Int
, publication_day :: Int
}
}
publicationDate :: DocumentsView -> String
publicationDate (DocumentsView {publication_year, publication_month, publication_day}) =
(zeroPad 2 publication_year) <> "-" <> (zeroPad 2 publication_month) <> "-" <> (zeroPad 2 publication_day)
derive instance genericDocumentsView :: Generic DocumentsView _
derive instance genericDocumentsView :: Generic DocumentsView _
instance showDocumentsView :: Show DocumentsView where
instance showDocumentsView :: Show DocumentsView where
show = genericShow
show = genericShow
----------------------------------------------------------------------
newtype ContactsView =
ContactsView
{ id :: Int
, hyperdata :: HyperdataRowContact
, score :: Int
, annuaireId :: Int
, delete :: Boolean
}
derive instance genericContactsView :: Generic ContactsView _
instance showContactsView :: Show ContactsView where
show = genericShow
----------------------------------------------------------------------
data Rows = Docs { docs :: Seq DocumentsView }
| Contacts { contacts :: Seq ContactsView }
----------------------------------------------------------------------
-- | Main layout of the Documents Tab of a Corpus
-- | Main layout of the Documents Tab of a Corpus
docView :: Record Props -> R.Element
docView :: Record Props -> R.Element
docView props = R.createElement docViewCpt props []
docView props = R.createElement docViewCpt props []
...
@@ -117,11 +137,14 @@ docViewCpt = R.hooksComponentWithModule thisModule "docView" cpt
...
@@ -117,11 +137,14 @@ docViewCpt = R.hooksComponentWithModule thisModule "docView" cpt
[ chart
[ chart
, H.div { className: "col-md-12" }
, H.div { className: "col-md-12" }
[ pageLayout { deletions, frontends, totalRecords, container, session, path } ]
[ pageLayout { deletions, frontends, totalRecords, container, session, path } ]
, H.div { className: "col-md-12" }
{-
, H.div { className: "col-md-12" }
[ H.button { style: buttonStyle, on: { click: trashClick deletions } }
[ H.button { style: buttonStyle, on: { click: trashClick deletions } }
[ H.i { className: "glyphitem fa fa-trash"
[ H.i { className: "glyphitem fa fa-trash"
, style: { marginRight : "9px" }} []
, style: { marginRight : "9px" }} []
, H.text "Delete document!" ] ] ] ]
, H.text "Delete document!" ]
]
-} ]
]
where
where
buttonStyle =
buttonStyle =
{ backgroundColor: "peru", padding: "9px", color: "white"
{ backgroundColor: "peru", padding: "9px", color: "white"
...
@@ -160,7 +183,7 @@ docViewGraphCpt = R.hooksComponentWithModule thisModule "docViewGraph" cpt
...
@@ -160,7 +183,7 @@ docViewGraphCpt = R.hooksComponentWithModule thisModule "docViewGraph" cpt
path <- R.useState' $ initialPagePath { nodeId, listId, query, session }
path <- R.useState' $ initialPagePath { nodeId, listId, query, session }
pure $ R.fragment
pure $ R.fragment
[ H.br {}
[ H.br {}
, H.p {} [ H.text "" ]
, H.p
{} [ H.text "" ]
, H.br {}
, H.br {}
, H.div { className: "container-fluid" }
, H.div { className: "container-fluid" }
[ R2.row
[ R2.row
...
@@ -187,7 +210,7 @@ type PagePath = { nodeId :: Int
...
@@ -187,7 +210,7 @@ type PagePath = { nodeId :: Int
initialPagePath :: {session :: Session, nodeId :: Int, listId :: Int, query :: SearchQuery} -> PagePath
initialPagePath :: {session :: Session, nodeId :: Int, listId :: Int, query :: SearchQuery} -> PagePath
initialPagePath {session, nodeId, listId, query} = {session, nodeId, listId, query, params: T.initialParams}
initialPagePath {session, nodeId, listId, query} = {session, nodeId, listId, query, params: T.initialParams}
loadPage :: PagePath -> Aff
(Seq DocumentsView)
loadPage :: PagePath -> Aff
Rows
loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy, searchType}} = do
loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy, searchType}} = do
let
let
convOrderBy (T.ASC (T.ColumnName "Date")) = DateAsc
convOrderBy (T.ASC (T.ColumnName "Date")) = DateAsc
...
@@ -203,21 +226,21 @@ loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy, searc
...
@@ -203,21 +226,21 @@ loadPage {session, nodeId, listId, query, params: {limit, offset, orderBy, searc
--SearchResult {result} <- post session p $ SearchQuery {query: concat query, expected:searchType}
--SearchResult {result} <- post session p $ SearchQuery {query: concat query, expected:searchType}
SearchResult {result} <- post session p query
SearchResult {result} <- post session p query
-- $ SearchQuery {query: concat query, expected: SearchDoc}
-- $ SearchQuery {query: concat query, expected: SearchDoc}
pure case result of
pure
$
case result of
SearchResultDoc {docs} ->
doc2view <$> Seq.fromFoldable docs
SearchResultDoc {docs} ->
Docs {docs: doc2view <$> Seq.fromFoldable docs}
SearchResultContact {contacts} ->
contact2view <$> Seq.fromFoldable contacts
SearchResultContact {contacts} ->
Contacts {contacts: contact2view <$> Seq.fromFoldable contacts}
errMessage ->
pure $ err2view errMessage
errMessage ->
Docs {docs: Seq.fromFoldable [err2view errMessage]} -- TODO better error view
doc2view :: Document -> DocumentsView
doc2view :: Document -> DocumentsView
doc2view ( Document { id
doc2view ( Document { id
, created: date
, created: date
, hyperdata: HyperdataRowDocument { authors
, hyperdata: HyperdataRowDocument { authors
, title
, title
, source
, source
, publication_year
, publication_year
, publication_month
, publication_month
, publication_day
, publication_day
}
}
, category
, category
, score
, score
}
}
...
@@ -235,36 +258,27 @@ doc2view ( Document { id
...
@@ -235,36 +258,27 @@ doc2view ( Document { id
, publication_day : fromMaybe 1 publication_day
, publication_day : fromMaybe 1 publication_day
}
}
contact2view :: Contact ->
Documen
tsView
contact2view :: Contact ->
Contac
tsView
contact2view (Contact { c_id
contact2view (Contact { c_id
, c_created: date
, c_created: date
, c_hyperdata: HyperdataRowContact { firstname
, c_hyperdata
, lastname
, c_annuaireId
, labs
}
, c_score
, c_score
}
}
) = DocumentsView { id: c_id
) = ContactsView { id: c_id
, date
, hyperdata: c_hyperdata
, title : firstname <> lastname
, score: c_score
, source: labs
, annuaireId : c_annuaireId
, score: c_score
, delete: false
, authors: labs
}
, category: decodeCategory 1
, pairs: []
, delete: false
, publication_year: 2020
, publication_month: 10
, publication_day: 1
}
err2view message =
err2view message =
DocumentsView { id: 1
DocumentsView { id: 1
, date: "
2020-01-01
"
, date: ""
, title : "SearchNoResult"
, title : "SearchNoResult"
, source: "
Source
"
, source: ""
, score: 1
, score: 1
, authors: "
Authors
"
, authors: ""
, category: decodeCategory 1
, category: decodeCategory 1
, pairs: []
, pairs: []
, delete: false
, delete: false
...
@@ -273,9 +287,6 @@ err2view message =
...
@@ -273,9 +287,6 @@ err2view message =
, publication_day: 1
, publication_day: 1
}
}
type PageLayoutProps =
type PageLayoutProps =
( frontends :: Frontends
( frontends :: Frontends
, totalRecords :: Int
, totalRecords :: Int
...
@@ -285,7 +296,7 @@ type PageLayoutProps =
...
@@ -285,7 +296,7 @@ type PageLayoutProps =
, path :: R.State PagePath
, path :: R.State PagePath
)
)
type PageProps = (
documents :: Seq DocumentsView
| PageLayoutProps )
type PageProps = (
rowsLoaded :: Rows
| PageLayoutProps )
-- | Loads and renders a page
-- | Loads and renders a page
pageLayout :: Record PageLayoutProps -> R.Element
pageLayout :: Record PageLayoutProps -> R.Element
...
@@ -295,8 +306,8 @@ pageLayoutCpt :: R.Component PageLayoutProps
...
@@ -295,8 +306,8 @@ pageLayoutCpt :: R.Component PageLayoutProps
pageLayoutCpt = R.hooksComponentWithModule thisModule "pageLayout" cpt
pageLayoutCpt = R.hooksComponentWithModule thisModule "pageLayout" cpt
where
where
cpt {frontends, totalRecords, deletions, container, session, path} _ = do
cpt {frontends, totalRecords, deletions, container, session, path} _ = do
useLoader (fst path) loadPage $ \
documents
->
useLoader (fst path) loadPage $ \
rowsLoaded
->
page {frontends, totalRecords, deletions, container, session, path,
documents
}
page {frontends, totalRecords, deletions, container, session, path,
rowsLoaded
}
page :: Record PageProps -> R.Element
page :: Record PageProps -> R.Element
page props = R.createElement pageCpt props []
page props = R.createElement pageCpt props []
...
@@ -304,7 +315,7 @@ page props = R.createElement pageCpt props []
...
@@ -304,7 +315,7 @@ page props = R.createElement pageCpt props []
pageCpt :: R.Component PageProps
pageCpt :: R.Component PageProps
pageCpt = R.hooksComponentWithModule thisModule "page" cpt
pageCpt = R.hooksComponentWithModule thisModule "page" cpt
where
where
cpt {frontends, totalRecords, container, deletions,
documents
, session, path: path@({nodeId, listId, query} /\ setPath)} _ = do
cpt {frontends, totalRecords, container, deletions,
rowsLoaded
, session, path: path@({nodeId, listId, query} /\ setPath)} _ = do
pure $ T.table { syncResetButton : [ H.div {} [] ]
pure $ T.table { syncResetButton : [ H.div {} [] ]
, rows, container, colNames
, rows, container, colNames
, totalRecords, params, wrapColElts
, totalRecords, params, wrapColElts
...
@@ -312,44 +323,75 @@ pageCpt = R.hooksComponentWithModule thisModule "page" cpt
...
@@ -312,44 +323,75 @@ pageCpt = R.hooksComponentWithModule thisModule "page" cpt
where
where
setParams f = setPath $ \p@{params: ps} -> p {params = f ps}
setParams f = setPath $ \p@{params: ps} -> p {params = f ps}
params = (fst path).params /\ setParams
params = (fst path).params /\ setParams
colNames = T.ColumnName <$> [ "", "Date", "Title", "Source", "Authors", "Delete" ]
colNames = case rowsLoaded of
Docs _ -> T.ColumnName <$> [ "", "Date", "Title", "Journal", "", "" ]
Contacts _ -> T.ColumnName <$> [ "", "Contact", "Organization", "", "", "" ]
wrapColElts = const identity
wrapColElts = const identity
-- TODO: how to interprete other scores?
-- TODO: how to interprete other scores?
gi
Favorite
= "fa fa-star-empty"
gi
Trash
= "fa fa-star-empty"
gi _ = "fa fa-star"
gi _ = "fa fa-star"
isChecked id = Set.member id (fst deletions).pending
isChecked id = Set.member id (fst deletions).pending
isDeleted (DocumentsView {id}) = Set.member id (fst deletions).deleted
isDeleted (DocumentsView {id}) = Set.member id (fst deletions).deleted
pairUrl (Pair {id,label})
pairUrl (Pair {id,label})
| id > 1 = H.a { href, target: "blank" } [ H.text label ]
| id > 1 = H.a { href, target: "blank" } [ H.text label ]
where href = url session $ NodePath (sessionId session) NodeContact (Just id)
where href = url session $ NodePath (sessionId session) NodeContact (Just id)
| otherwise = H.text label
| otherwise = H.text label
documentUrl id =
documentUrl id =
url frontends $ Routes.CorpusDocument (sessionId session) nodeId listId id
url frontends $ Routes.CorpusDocument (sessionId session) nodeId listId id
comma = H.span {} [ H.text ", " ]
rows = row <$> Seq.filter (not <<< isDeleted) documents
rows = case rowsLoaded of
row dv@(DocumentsView {id, score, title, source, authors, pairs, delete, category}) =
Docs {docs} -> docRow <$> Seq.filter (not <<< isDeleted) docs
Contacts {contacts} -> contactRow <$> contacts
contactRow (ContactsView { id, hyperdata: HyperdataRowContact { firstname, lastname, labs}
, score, annuaireId, delete
}) =
{ row:
{ row:
T.makeRow [
T.makeRow [ H.div {} [ H.a { className: gi Favorite, on: {click: markClick} } [] ]
H.div {} [ H.a { className: gi category, on: {click: markClick} } [] ]
, maybeStricken delete [ H.a {target: "_blank", href: contactUrl annuaireId id}
-- TODO show date: Year-Month-Day only
[ H.text $ firstname <> " " <> lastname ]
, maybeStricken delete [ H.text $ publicationDate dv ]
]
, maybeStricken delete [ H.a {target: "_blank", href: documentUrl id} [ H.text title ] ]
, maybeStricken delete [ H.text labs ]
, maybeStricken delete [ H.text source ]
]
, maybeStricken delete [ H.text authors ]
, delete: true
-- , maybeStricken $ intercalate [comma] (pairUrl <$> pairs)
}
, H.input { defaultChecked: isChecked id
where
, on: { click: toggleClick }
markClick _ = markCategory session nodeId Favorite [id]
, type: "checkbox"
contactUrl aId id = url frontends $ Routes.ContactPage (sessionId session) annuaireId id
}
]
docRow dv@(DocumentsView {id, score, title, source, authors, pairs, delete, category}) =
{ row:
T.makeRow [ H.div {} [ H.a { className: gi category, on: {click: markClick} } [] ]
, maybeStricken delete [ H.text $ publicationDate dv ]
, maybeStricken delete [ H.a {target: "_blank", href: documentUrl id} [ H.text title ] ]
, maybeStricken delete [ H.text source ]
-- , maybeStricken delete [ H.text authors ]
-- , maybeStricken $ intercalate [comma] (pairUrl <$> pairs)
{-, H.input { defaultChecked: isChecked id
, on: { click: toggleClick }
, type: "checkbox"
}
-}
]
, delete: true }
, delete: true }
where
where
markClick _ = markCategory session nodeId category [id]
markClick _ = markCategory session nodeId category [id]
toggleClick _ = togglePendingDeletion deletions id
toggleClick _ = togglePendingDeletion deletions id
-- comma = H.span {} [ H.text ", " ]
maybeStricken delete
maybeStricken delete
| delete = H.div { style: { textDecoration: "line-through" } }
| delete
= H.div { style: { textDecoration: "line-through" } }
| otherwise = H.div {}
| otherwise = H.div {}
publicationDate :: DocumentsView -> String
publicationDate (DocumentsView {publication_year, publication_month, publication_day}) =
(zeroPad 2 publication_year) <> "-" <> (zeroPad 2 publication_month)
-- <> "-" <> (zeroPad 2 publication_day)
---------------------------------------------------------
---------------------------------------------------------
newtype DeleteDocumentQuery = DeleteDocumentQuery { documents :: Array Int }
newtype DeleteDocumentQuery = DeleteDocumentQuery { documents :: Array Int }
...
...
src/Gargantext/Components/Forest/Tree/Node/Settings.purs
View file @
e7d216fa
...
@@ -132,6 +132,7 @@ settingsBox Team =
...
@@ -132,6 +132,7 @@ settingsBox Team =
, NodeFrameCalc
, NodeFrameCalc
, NodeFrameNotebook
, NodeFrameNotebook
, Team
, Team
, FolderShared
]
]
, Share
, Share
, Delete
, Delete
...
...
src/Gargantext/Components/Graph.purs
View file @
e7d216fa
...
@@ -252,10 +252,10 @@ sigmaSettings =
...
@@ -252,10 +252,10 @@ sigmaSettings =
, font: "arial" -- font params
, font: "arial" -- font params
, fontStyle: "bold"
, fontStyle: "bold"
, hideEdgesOnMove: true
, hideEdgesOnMove: true
--
, labelSize : "proportional" -- alt : proportional, fixed
, labelSize : "proportional" -- alt : proportional, fixed
, labelSize: "fixed"
--
, labelSize: "fixed"
, labelSizeRatio:
2
.0 -- label size in ratio of node size
, labelSizeRatio:
3
.0 -- label size in ratio of node size
, labelThreshold:
7
.0 -- min node cam size to start showing label
, labelThreshold:
6
.0 -- min node cam size to start showing label
, maxEdgeSize: 1.0
, maxEdgeSize: 1.0
, maxNodeSize: 8.0
, maxNodeSize: 8.0
, minEdgeSize: 0.5 -- in fact used in tina as edge size
, minEdgeSize: 0.5 -- in fact used in tina as edge size
...
...
src/Gargantext/Components/GraphExplorer/Sidebar.purs
View file @
e7d216fa
...
@@ -70,7 +70,7 @@ sidebar props = R.createElement sidebarCpt props []
...
@@ -70,7 +70,7 @@ sidebar props = R.createElement sidebarCpt props []
sideTabNav :: R.State SidePanelState -> Array SideTab -> R.Element
sideTabNav :: R.State SidePanelState -> Array SideTab -> R.Element
sideTabNav (sidePanel /\ setSidePanel) sideTabs =
sideTabNav (sidePanel /\ setSidePanel) sideTabs =
R.fragment [ H.div { className: "text-primary center"} [H.text "
SideTab
"]
R.fragment [ H.div { className: "text-primary center"} [H.text ""]
, H.div {className: "nav nav-tabs"} (liItem <$> sideTabs)
, H.div {className: "nav nav-tabs"} (liItem <$> sideTabs)
-- , H.div {className: "center"} [ H.text "Doc sideTabs"]
-- , H.div {className: "center"} [ H.text "Doc sideTabs"]
]
]
...
@@ -133,36 +133,46 @@ sideTab _ _ = H.div {} []
...
@@ -133,36 +133,46 @@ sideTab _ _ = H.div {} []
-------------------------------------------
-------------------------------------------
-- TODO
-- TODO
-- selectedNodes :: Record Props -> Map.Map String Nodes -> R.Element
-- selectedNodes :: Record Props -> Map.Map String Nodes -> R.Element
selectedNodes props nodesMap = R2.row [ R2.col 12
selectedNodes props nodesMap =
[ RH.ul { id: "myTab", className: "nav nav-tabs", role: "tablist"}
R2.row [ R2.col 12
[ RH.div { className: "tab-content" }
[ RH.ul { className: "nav nav-tabs d-flex justify-content-center"
[ RH.div { className: "", role: "tabpanel" }
, id: "myTab"
( Seq.toUnfoldable
, role: "tablist" }
$ ( Seq.map (badge props.selectedNodeIds)
[ RH.div { className: "tab-content" }
(badges props.graph props.selectedNodeIds)
[ RH.div { className: "d-flex flex-wrap justify-content-center"
)
, role: "tabpanel" }
)
( Seq.toUnfoldable
]
$ ( Seq.map (badge props.selectedNodeIds)
, RH.div { className: "tab-content flex-space-between" }
(badges props.graph props.selectedNodeIds)
[ removeButton "Move as candidate" CandidateTerm props nodesMap
)
, removeButton "Move as stop" StopTerm props nodesMap
)
]
, H.br {}
]
]
]
]
]
, RH.div { className: "tab-content flex-space-between" }
[ removeButton "primary" "Move as candidate" CandidateTerm props nodesMap
, H.br {}
, removeButton "danger" "Move as stop" StopTerm props nodesMap
]
]
]
neighborhood props = RH.div { className: "tab-content", id: "myTabContent" }
neighborhood props = RH.div { className: "tab-content", id: "myTabContent" }
[ RH.div { className: "", id: "home", role: "tabpanel" }
[ RH.div { -- className: "flex-space-around d-flex justify-content-center"
className: "d-flex flex-wrap flex-space-around"
, id: "home"
, role: "tabpanel"
}
(Seq.toUnfoldable $ Seq.map (badge props.selectedNodeIds)
(Seq.toUnfoldable $ Seq.map (badge props.selectedNodeIds)
$ neighbourBadges props.graph props.selectedNodeIds
$ neighbourBadges props.graph props.selectedNodeIds
)
)
]
]
removeButton text rType props' nodesMap' =
removeButton
btnType
text rType props' nodesMap' =
if Set.isEmpty $ fst props'.selectedNodeIds then
if Set.isEmpty $ fst props'.selectedNodeIds then
RH.div {} []
RH.div {} []
else
else
RH.button { className: "btn btn-
info"
RH.button { className: "btn btn-
sm btn-" <> btnType
, on: { click: onClickRemove rType props' nodesMap' }
, on: { click: onClickRemove rType props' nodesMap' }
}
}
[ RH.text text ]
[ RH.text text ]
...
@@ -200,11 +210,11 @@ neighbourBadges graph (selectedNodeIds /\ _) = SigmaxT.neighbours graph selected
...
@@ -200,11 +210,11 @@ neighbourBadges graph (selectedNodeIds /\ _) = SigmaxT.neighbours graph selected
type DeleteNodes =
type DeleteNodes =
( graphId :: Int
( graphId
:: Int
, metaData :: GET.MetaData
, metaData
:: GET.MetaData
, nodes :: Array (Record SigmaxT.Node)
, nodes
:: Array (Record SigmaxT.Node)
, session :: Session
, session
:: Session
, termList :: TermList
, termList
:: TermList
, treeReload :: GUR.ReloadS
, treeReload :: GUR.ReloadS
)
)
...
@@ -332,6 +342,3 @@ Global/local view:
...
@@ -332,6 +342,3 @@ Global/local view:
To explore the neighborhood of a selection click on the 'change level' button.
To explore the neighborhood of a selection click on the 'change level' button.
-}
-}
src/Gargantext/Components/GraphExplorer/ToggleButton.purs
View file @
e7d216fa
...
@@ -28,6 +28,7 @@ type Props = (
...
@@ -28,6 +28,7 @@ type Props = (
state :: R.State Boolean
state :: R.State Boolean
, onMessage :: String
, onMessage :: String
, offMessage :: String
, offMessage :: String
, style :: String
, onClick :: forall e. e -> Effect Unit
, onClick :: forall e. e -> Effect Unit
)
)
...
@@ -37,10 +38,10 @@ toggleButton props = R.createElement toggleButtonCpt props []
...
@@ -37,10 +38,10 @@ toggleButton props = R.createElement toggleButtonCpt props []
toggleButtonCpt :: R.Component Props
toggleButtonCpt :: R.Component Props
toggleButtonCpt = R.hooksComponentWithModule thisModule "toggleButton" cpt
toggleButtonCpt = R.hooksComponentWithModule thisModule "toggleButton" cpt
where
where
cpt {state, onMessage, offMessage, onClick} _ = do
cpt {state, onMessage, offMessage, onClick
, style
} _ = do
let (toggled /\ _) = state
let (toggled /\ _) = state
pure $ H.button { className: "btn btn-outline-
light
" <> cls toggled
pure $ H.button { className: "btn btn-outline-
" <> style <> "
" <> cls toggled
, on: {click: onClick}
, on: {click: onClick}
} [ R2.small {} [ H.text (text onMessage offMessage toggled) ] ]
} [ R2.small {} [ H.text (text onMessage offMessage toggled) ] ]
...
@@ -56,6 +57,7 @@ controlsToggleButton state =
...
@@ -56,6 +57,7 @@ controlsToggleButton state =
, onMessage: "Hide Controls"
, onMessage: "Hide Controls"
, offMessage: "Show Controls"
, offMessage: "Show Controls"
, onClick: \_ -> snd state not
, onClick: \_ -> snd state not
, style: "light"
}
}
type EdgesButtonProps = (
type EdgesButtonProps = (
...
@@ -69,14 +71,14 @@ edgesToggleButtonCpt :: R.Component EdgesButtonProps
...
@@ -69,14 +71,14 @@ edgesToggleButtonCpt :: R.Component EdgesButtonProps
edgesToggleButtonCpt = R.hooksComponentWithModule thisModule "edgesToggleButton" cpt
edgesToggleButtonCpt = R.hooksComponentWithModule thisModule "edgesToggleButton" cpt
where
where
cpt {state: (state /\ setState)} _ = do
cpt {state: (state /\ setState)} _ = do
pure $ H.button { className: "btn btn-outline-
light
" <> cls state
pure $ H.button { className: "btn btn-outline-
primary
" <> cls state
, on: { click: onClick setState }
, on: { click: onClick setState }
} [ R2.small {} [ H.text (text state) ] ]
} [ R2.small {} [ H.text (text state) ] ]
text s = if SigmaxTypes.edgeStateHidden s then "Show edges" else "Hide edges"
text s = if SigmaxTypes.edgeStateHidden s then "Show edges" else "Hide edges"
cls SigmaxTypes.EShow = "
active
"
cls SigmaxTypes.EShow = ""
cls _ = ""
cls _ = "
active
"
-- TODO: Move this to Graph.purs to the R.useEffect handler which renders nodes/edges
-- TODO: Move this to Graph.purs to the R.useEffect handler which renders nodes/edges
onClick setState _ = setState SigmaxTypes.toggleShowEdgesState
onClick setState _ = setState SigmaxTypes.toggleShowEdgesState
...
@@ -88,6 +90,7 @@ louvainToggleButton state =
...
@@ -88,6 +90,7 @@ louvainToggleButton state =
, onMessage: "Louvain off"
, onMessage: "Louvain off"
, offMessage: "Louvain on"
, offMessage: "Louvain on"
, onClick: \_ -> snd state not
, onClick: \_ -> snd state not
, style: "primary"
}
}
multiSelectEnabledButton :: R.State Boolean -> R.Element
multiSelectEnabledButton :: R.State Boolean -> R.Element
...
@@ -97,6 +100,7 @@ multiSelectEnabledButton state =
...
@@ -97,6 +100,7 @@ multiSelectEnabledButton state =
, onMessage: "Single-node"
, onMessage: "Single-node"
, offMessage: "Multi-node"
, offMessage: "Multi-node"
, onClick: \_ -> snd state not
, onClick: \_ -> snd state not
, style : "primary"
}
}
type ForceAtlasProps = (
type ForceAtlasProps = (
...
@@ -110,7 +114,7 @@ pauseForceAtlasButtonCpt :: R.Component ForceAtlasProps
...
@@ -110,7 +114,7 @@ pauseForceAtlasButtonCpt :: R.Component ForceAtlasProps
pauseForceAtlasButtonCpt = R.hooksComponentWithModule thisModule "forceAtlasToggleButton" cpt
pauseForceAtlasButtonCpt = R.hooksComponentWithModule thisModule "forceAtlasToggleButton" cpt
where
where
cpt {state: (state /\ setState)} _ = do
cpt {state: (state /\ setState)} _ = do
pure $ H.button { className: "btn btn-outline-
light
" <> cls state
pure $ H.button { className: "btn btn-outline-
primary
" <> cls state
, on: { click: onClick setState }
, on: { click: onClick setState }
} [ R2.small {} [ H.text (text state) ] ]
} [ R2.small {} [ H.text (text state) ] ]
...
@@ -132,6 +136,7 @@ treeToggleButton state =
...
@@ -132,6 +136,7 @@ treeToggleButton state =
, onMessage: "Hide Tree"
, onMessage: "Hide Tree"
, offMessage: "Show Tree"
, offMessage: "Show Tree"
, onClick: \_ -> snd state not
, onClick: \_ -> snd state not
, style: "light"
}
}
sidebarToggleButton :: R.State GET.SidePanelState -> R.Element
sidebarToggleButton :: R.State GET.SidePanelState -> R.Element
...
...
src/Gargantext/Components/InputWithEnter.purs
View file @
e7d216fa
...
@@ -42,7 +42,10 @@ inputWithEnter props = R.createElement inputWithEnterCpt props []
...
@@ -42,7 +42,10 @@ inputWithEnter props = R.createElement inputWithEnterCpt props []
where
where
onInput e = do
onInput e = do
onValueChanged $ R.unsafeEventValue e
if autoSave then
onValueChanged $ R.unsafeEventValue e
else
pure unit
onKeyPress e = do
onKeyPress e = do
char <- R2.keyCode e
char <- R2.keyCode e
...
...
src/Gargantext/Components/NgramsTable.purs
View file @
e7d216fa
...
@@ -14,22 +14,19 @@ import Data.Lens.Index (ix)
...
@@ -14,22 +14,19 @@ import Data.Lens.Index (ix)
import Data.Lens.Record (prop)
import Data.Lens.Record (prop)
import Data.Map (Map)
import Data.Map (Map)
import Data.Map as Map
import Data.Map as Map
import Data.Maybe (Maybe(..), isNothing, maybe)
import Data.Maybe (Maybe(..),
fromMaybe,
isNothing, maybe)
import Data.Monoid.Additive (Additive(..))
import Data.Monoid.Additive (Additive(..))
import Data.Ord.Down (Down(..))
import Data.Ord.Down (Down(..))
import Data.Sequence (Seq, length) as Seq
import Data.Sequence (Seq, length) as Seq
import Data.Set (Set)
import Data.Set (Set)
import Data.Set as Set
import Data.Set as Set
import Data.Symbol (SProxy(..))
import Data.Symbol (SProxy(..))
import Data.Tuple (Tuple(..), fst
, snd
)
import Data.Tuple (Tuple(..), fst)
import Data.Tuple.Nested ((/\))
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log, log2)
import Effect (Effect)
import Effect (Effect)
import Effect.Aff (Aff, launchAff_)
import Effect.Aff (Aff)
import Effect.Class (liftEffect)
import Reactix (Component, Element, Ref, State, createElement, fragment, hooksComponentWithModule, unsafeEventValue, useState') as R
import Reactix as R
import Reactix.DOM.HTML as H
import Reactix.DOM.HTML as H
import Record as Record
import Unsafe.Coerce (unsafeCoerce)
import Unsafe.Coerce (unsafeCoerce)
import Gargantext.Prelude
import Gargantext.Prelude
...
@@ -37,12 +34,12 @@ import Gargantext.Prelude
...
@@ -37,12 +34,12 @@ import Gargantext.Prelude
import Gargantext.AsyncTasks as GAT
import Gargantext.AsyncTasks as GAT
import Gargantext.Components.AutoUpdate (autoUpdateElt)
import Gargantext.Components.AutoUpdate (autoUpdateElt)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Components.Table as T
import Gargantext.Components.Table.Types as T
import Gargantext.Components.Table.Types as T
import Gargantext.Components.NgramsTable.Components as NTC
import Gargantext.Components.NgramsTable.Components as NTC
import Gargantext.Components.NgramsTable.Core
import Gargantext.Components.NgramsTable.Core
(Action(..), CoreAction(..), CoreState, Dispatch, NgramsElement(..), NgramsPatch(..), NgramsTable, NgramsTerm, PageParams, PatchMap(..), Version, Versioned(..), VersionedNgramsTable, VersionedWithCountNgramsTable, _NgramsElement, _NgramsRepoElement, _NgramsTable, _children, _list, _ngrams, _ngrams_repo_elements, _ngrams_scores, _occurrences, _root, addNewNgramA, applyNgramsPatches, applyPatchSet, chartsAfterSync, commitPatch, convOrderBy, coreDispatch, filterTermSize, fromNgramsPatches, ngramsRepoElementToNgramsElement, ngramsTermText, normNgram, patchSetFromMap, replace, rootsOf, singletonNgramsTablePatch, syncResetButtons, toVersioned)
import Gargantext.Components.NgramsTable.Loader (useLoaderWithCacheAPI)
import Gargantext.Components.NgramsTable.Loader (useLoaderWithCacheAPI)
import Gargantext.Components.Nodes.Lists.Types as NT
import Gargantext.Components.Nodes.Lists.Types as NT
import Gargantext.Components.Table as T
import Gargantext.Routes (SessionRoute(..)) as R
import Gargantext.Routes (SessionRoute(..)) as R
import Gargantext.Sessions (Session, get)
import Gargantext.Sessions (Session, get)
import Gargantext.Types (CTabNgramType, OrderBy(..), SearchQuery, TabType, TermList(..), TermSize, termLists, termSizes)
import Gargantext.Types (CTabNgramType, OrderBy(..), SearchQuery, TabType, TermList(..), TermSize, termLists, termSizes)
...
@@ -50,40 +47,17 @@ import Gargantext.Utils (queryMatchesLabel, toggleSet, sortWith)
...
@@ -50,40 +47,17 @@ import Gargantext.Utils (queryMatchesLabel, toggleSet, sortWith)
import Gargantext.Utils.CacheAPI as GUC
import Gargantext.Utils.CacheAPI as GUC
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reload as GUR
import Gargantext.Utils.Reload as GUR
import Gargantext.Utils.Seq
(mapMaybe)
as Seq
import Gargantext.Utils.Seq as Seq
thisModule :: String
thisModule :: String
thisModule = "Gargantext.Components.NgramsTable"
thisModule = "Gargantext.Components.NgramsTable"
type State' =
CoreState
( ngramsParent :: Maybe NgramsTerm -- Nothing means we are not currently grouping terms
, ngramsChildren :: Map NgramsTerm Boolean
-- ^ Used only when grouping.
-- This updates the children of `ngramsParent`,
-- ngrams set to `true` are to be added, and `false` to
-- be removed.
, ngramsSelection :: Set NgramsTerm
-- ^ The set of selected checkboxes of the first column.
)
_ngramsChildren :: forall row. Lens' { ngramsChildren :: Map NgramsTerm Boolean | row } (Map NgramsTerm Boolean)
_ngramsChildren :: forall row. Lens' { ngramsChildren :: Map NgramsTerm Boolean | row } (Map NgramsTerm Boolean)
_ngramsChildren = prop (SProxy :: SProxy "ngramsChildren")
_ngramsChildren = prop (SProxy :: SProxy "ngramsChildren")
_ngramsSelection :: forall row. Lens' { ngramsSelection :: Set NgramsTerm | row } (Set NgramsTerm)
_ngramsSelection :: forall row. Lens' { ngramsSelection :: Set NgramsTerm | row } (Set NgramsTerm)
_ngramsSelection = prop (SProxy :: SProxy "ngramsSelection")
_ngramsSelection = prop (SProxy :: SProxy "ngramsSelection")
initialState' :: VersionedNgramsTable -> State'
initialState' (Versioned {version}) =
{ ngramsChildren: mempty
, ngramsLocalPatch: mempty
, ngramsParent: Nothing
, ngramsSelection: mempty
, ngramsStagePatch: mempty
, ngramsValidPatch: mempty
, ngramsVersion: version
}
type State =
type State =
CoreState (
CoreState (
ngramsChildren :: Map NgramsTerm Boolean
ngramsChildren :: Map NgramsTerm Boolean
...
@@ -290,32 +264,36 @@ type CommonProps = (
...
@@ -290,32 +264,36 @@ type CommonProps = (
)
)
type Props = (
type Props = (
path :: R.State PageParams
cacheState :: NT.CacheState
, mTotalRows :: Maybe Int
, path :: R.State PageParams
, state :: R.State State
, state :: R.State State
, versioned :: VersionedNgramsTable
, versioned :: VersionedNgramsTable
| CommonProps
| CommonProps
)
)
loadedNgramsTable :: Record Props -> R.Element
loadedNgramsTable :: R2.Component Props
loadedNgramsTable p = R.createElement loadedNgramsTableCpt p []
loadedNgramsTable = R.createElement loadedNgramsTableCpt
loadedNgramsTableCpt :: R.Component Props
loadedNgramsTableCpt = R.hooksComponentWithModule thisModule "loadedNgramsTable" cpt
where
where
cpt { afterSync
loadedNgramsTableCpt :: R.Component Props
, appReload
loadedNgramsTableCpt = R.hooksComponentWithModule thisModule "loadedNgramsTable" cpt
, asyncTasksRef
, path: path@(path'@{ listIds, nodeId, params, searchQuery, scoreType, termListFilter, termSizeFilter } /\ setPath)
cpt props@{ afterSync
, sidePanelTriggers
, appReload
, state: (state@{ ngramsChildren
, asyncTasksRef
, ngramsLocalPatch
, cacheState
, ngramsParent
, mTotalRows
, ngramsSelection
, path: path@(path'@{ listIds, nodeId, params, searchQuery, scoreType, termListFilter, termSizeFilter } /\ setPath)
, ngramsVersion } /\ setState)
, sidePanelTriggers
, tabNgramType
, state: (state@{ ngramsChildren
, treeReloadRef
, ngramsLocalPatch
, versioned: Versioned { data: initTable }
, ngramsParent
, withAutoUpdate } _ = do
, ngramsSelection
, ngramsVersion } /\ setState)
, tabNgramType
, treeReloadRef
, versioned: Versioned { data: initTable }
, withAutoUpdate } _ = do
pure $ R.fragment $
pure $ R.fragment $
autoUpdate <> [
autoUpdate <> [
...
@@ -325,19 +303,19 @@ loadedNgramsTableCpt = R.hooksComponentWithModule thisModule "loadedNgramsTable"
...
@@ -325,19 +303,19 @@ loadedNgramsTableCpt = R.hooksComponentWithModule thisModule "loadedNgramsTable"
]
]
, search ]
, search ]
<>
<>
[ T.table { syncResetButton: [ syncResetButton ]
[ T.table { colNames
, colNames
, container: tableContainer { dispatch: performAction
, container: tableContainer { dispatch: performAction
, ngramsChildren
, ngramsChildren
, ngramsParent
, ngramsParent
, ngramsSelection
, ngramsSelection
, ngramsTable
, ngramsTable
, path
, path
, tabNgramType
, syncResetButton: [ syncResetButton ]
, syncResetButton: [ syncResetButton ]
, tabNgramType
}
}
, params: params
/\ setParams
-- TODO-LENS
, params: params
S
-- TODO-LENS
, rows: filteredConvertedRows
, rows: filteredConvertedRows
, syncResetButton: [ syncResetButton ]
, totalRecords
, totalRecords
, wrapColElts: wrapColElts { allNgramsSelected
, wrapColElts: wrapColElts { allNgramsSelected
, dispatch: performAction
, dispatch: performAction
...
@@ -347,13 +325,16 @@ loadedNgramsTableCpt = R.hooksComponentWithModule thisModule "loadedNgramsTable"
...
@@ -347,13 +325,16 @@ loadedNgramsTableCpt = R.hooksComponentWithModule thisModule "loadedNgramsTable"
, syncResetButton ]
, syncResetButton ]
where
where
afterSync = chartsAfterSync path' asyncTasksRef nodeId treeReloadRef
afterSync' _ = do
chartsAfterSync path' asyncTasksRef nodeId treeReloadRef unit
afterSync unit
performAction = mkDispatch { filteredRows, path: path', state: state /\ setState }
syncResetButton = syncResetButtons { afterSync
syncResetButton = syncResetButtons { afterSync
: afterSync'
, ngramsLocalPatch
, ngramsLocalPatch
, performAction: performAction <<< CoreAction }
, performAction: performAction <<< CoreAction }
autoUpdate :: Array R.Element
autoUpdate :: Array R.Element
autoUpdate = if withAutoUpdate then
autoUpdate = if withAutoUpdate then
[ R2.buff
[ R2.buff
...
@@ -361,49 +342,17 @@ loadedNgramsTableCpt = R.hooksComponentWithModule thisModule "loadedNgramsTable"
...
@@ -361,49 +342,17 @@ loadedNgramsTableCpt = R.hooksComponentWithModule thisModule "loadedNgramsTable"
{ duration: 5000
{ duration: 5000
, effect: performAction
, effect: performAction
$ CoreAction
$ CoreAction
$ Synchronize { afterSync }
$ Synchronize { afterSync
: afterSync'
}
}
}
]
]
else []
else []
setParentResetChildren :: Maybe NgramsTerm -> State -> State
totalRecords = fromMaybe (Seq.length rows) mTotalRows
setParentResetChildren p = _ { ngramsParent = p, ngramsChildren = mempty }
performAction :: Action -> Effect Unit
performAction (SetParentResetChildren p) =
setState $ setParentResetChildren p
performAction (ToggleChild b c) =
setState $ \s@{ ngramsChildren: nc } -> s { ngramsChildren = newNC nc }
where
newNC nc = Map.alter (maybe (Just b) (const Nothing)) c nc
performAction (ToggleSelect c) =
setState $ \s@{ ngramsSelection: ns } -> s { ngramsSelection = toggleSet c ns }
performAction ToggleSelectAll =
setState toggler
where
toggler s =
if allNgramsSelected then
s { ngramsSelection = Set.empty :: Set NgramsTerm }
else
s { ngramsSelection = selectNgramsOnFirstPage filteredRows }
performAction AddTermChildren =
case ngramsParent of
Nothing ->
-- impossible but harmless
pure unit
Just parent -> do
let pc = patchSetFromMap ngramsChildren
pe = NgramsPatch { patch_list: mempty, patch_children: pc }
pt = singletonNgramsTablePatch parent pe
setState $ setParentResetChildren Nothing
commitPatch (Versioned {version: ngramsVersion, data: pt}) (state /\ setState)
performAction (CoreAction a) = coreDispatch path' (state /\ setState) a
totalRecords = Seq.length rows
filteredConvertedRows :: T.Rows
filteredConvertedRows :: T.Rows
filteredConvertedRows = convertRow <$> filteredRows
filteredConvertedRows = convertRow <$> filteredRows
filteredRows :: PreConversionRows
filteredRows :: PreConversionRows
filteredRows = T.filterRows { params } rows
-- no need to filter offset if cache is off
filteredRows = if cacheState == NT.CacheOn then T.filterRows { params } rows else rows
ng_scores :: Map NgramsTerm (Additive Int)
ng_scores :: Map NgramsTerm (Additive Int)
ng_scores = ngramsTable ^. _NgramsTable <<< _ngrams_scores
ng_scores = ngramsTable ^. _NgramsTable <<< _ngrams_scores
rows :: PreConversionRows
rows :: PreConversionRows
...
@@ -461,13 +410,66 @@ loadedNgramsTableCpt = R.hooksComponentWithModule thisModule "loadedNgramsTable"
...
@@ -461,13 +410,66 @@ loadedNgramsTableCpt = R.hooksComponentWithModule thisModule "loadedNgramsTable"
wrapColElts _ (T.ColumnName "Score") = (_ <> [H.text ("(" <> show scoreType <> ")")])
wrapColElts _ (T.ColumnName "Score") = (_ <> [H.text ("(" <> show scoreType <> ")")])
wrapColElts _ _ = identity
wrapColElts _ _ = identity
setParams f = setPath $ \p@{params: ps} -> p {params = f ps}
setParams f = setPath $ \p@{params: ps} -> p {params = f ps}
paramsS = params /\ setParams
search :: R.Element
search :: R.Element
search = NTC.searchInput { key: "search-input"
search = NTC.searchInput { key: "search-input"
, onSearch: setSearchQuery
, onSearch: setSearchQuery
, searchQuery: searchQuery }
, searchQuery: searchQuery }
setSearchQuery :: String -> Effect Unit
setSearchQuery :: String -> Effect Unit
setSearchQuery x = setPath $ _ { searchQuery = x }
setSearchQuery x = do
setPath $ _ { searchQuery = x }
T.changePage 1 paramsS
type MkDispatchProps = (
filteredRows :: PreConversionRows
, path :: PageParams
, state :: R.State State
)
mkDispatch :: Record MkDispatchProps -> (Action -> Effect Unit)
mkDispatch { filteredRows
, path
, state: (state@{ ngramsChildren
, ngramsLocalPatch
, ngramsParent
, ngramsSelection
, ngramsVersion } /\ setState) } = performAction
where
allNgramsSelected = allNgramsSelectedOnFirstPage ngramsSelection filteredRows
setParentResetChildren :: Maybe NgramsTerm -> State -> State
setParentResetChildren p = _ { ngramsParent = p, ngramsChildren = mempty }
performAction :: Action -> Effect Unit
performAction (SetParentResetChildren p) =
setState $ setParentResetChildren p
performAction (ToggleChild b c) =
setState $ \s@{ ngramsChildren: nc } -> s { ngramsChildren = newNC nc }
where
newNC nc = Map.alter (maybe (Just b) (const Nothing)) c nc
performAction (ToggleSelect c) =
setState $ \s@{ ngramsSelection: ns } -> s { ngramsSelection = toggleSet c ns }
performAction ToggleSelectAll =
setState toggler
where
toggler s =
if allNgramsSelected then
s { ngramsSelection = Set.empty :: Set NgramsTerm }
else
s { ngramsSelection = selectNgramsOnFirstPage filteredRows }
performAction AddTermChildren =
case ngramsParent of
Nothing ->
-- impossible but harmless
pure unit
Just parent -> do
let pc = patchSetFromMap ngramsChildren
pe = NgramsPatch { patch_list: mempty, patch_children: pc }
pt = singletonNgramsTablePatch parent pe
setState $ setParentResetChildren Nothing
commitPatch (Versioned {version: ngramsVersion, data: pt}) (state /\ setState)
performAction (CoreAction a) = coreDispatch path (state /\ setState) a
displayRow :: State -> SearchQuery -> NgramsTable -> Maybe NgramsTerm -> Maybe TermList -> Maybe TermSize -> NgramsElement -> Boolean
displayRow :: State -> SearchQuery -> NgramsTable -> Maybe NgramsTerm -> Maybe TermList -> Maybe TermSize -> NgramsElement -> Boolean
...
@@ -520,12 +522,12 @@ type MainNgramsTableProps = (
...
@@ -520,12 +522,12 @@ type MainNgramsTableProps = (
| CommonProps
| CommonProps
)
)
mainNgramsTable :: Record MainNgramsTableProps -> R.Element
mainNgramsTable :: R2.Component MainNgramsTableProps
mainNgramsTable props = R.createElement mainNgramsTableCpt props []
mainNgramsTable = R.createElement mainNgramsTableCpt
mainNgramsTableCpt :: R.Component MainNgramsTableProps
mainNgramsTableCpt = R.hooksComponentWithModule thisModule "mainNgramsTable" cpt
where
where
mainNgramsTableCpt :: R.Component MainNgramsTableProps
mainNgramsTableCpt = R.hooksComponentWithModule thisModule "mainNgramsTable" cpt
cpt props@{ afterSync
cpt props@{ afterSync
, appReload
, appReload
, asyncTasksRef
, asyncTasksRef
...
@@ -547,12 +549,13 @@ mainNgramsTableCpt = R.hooksComponentWithModule thisModule "mainNgramsTable" cpt
...
@@ -547,12 +549,13 @@ mainNgramsTableCpt = R.hooksComponentWithModule thisModule "mainNgramsTable" cpt
let render versioned = mainNgramsTablePaint { afterSync
let render versioned = mainNgramsTablePaint { afterSync
, appReload
, appReload
, asyncTasksRef
, asyncTasksRef
, cacheState: fst cacheState
, path: fst pathS
, path: fst pathS
, sidePanelTriggers
, sidePanelTriggers
, tabNgramType
, tabNgramType
, treeReloadRef
, treeReloadRef
, versioned
, versioned
, withAutoUpdate }
, withAutoUpdate }
[]
useLoaderWithCacheAPI {
useLoaderWithCacheAPI {
cacheEndpoint: versionEndpoint props
cacheEndpoint: versionEndpoint props
, handleResponse
, handleResponse
...
@@ -562,22 +565,24 @@ mainNgramsTableCpt = R.hooksComponentWithModule thisModule "mainNgramsTable" cpt
...
@@ -562,22 +565,24 @@ mainNgramsTableCpt = R.hooksComponentWithModule thisModule "mainNgramsTable" cpt
}
}
(NT.CacheOff /\ _) -> do
(NT.CacheOff /\ _) -> do
-- pathS <- R.useState' path
-- pathS <- R.useState' path
let render versioned = mainNgramsTablePaintNoCache { afterSync
let render versionedWithCount = mainNgramsTablePaintNoCache { afterSync
, appReload
, appReload
, asyncTasksRef
, asyncTasksRef
, pathS
, cacheState: fst cacheState
, sidePanelTriggers
, pathS
, tabNgramType
, sidePanelTriggers
, treeReloadRef
, tabNgramType
, versioned
, treeReloadRef
, withAutoUpdate }
, versionedWithCount
, withAutoUpdate } []
useLoader (fst pathS) loader render
useLoader (fst pathS) loader render
-- NOTE With cache on
versionEndpoint :: Record MainNgramsTableProps -> PageParams -> Aff Version
versionEndpoint :: Record MainNgramsTableProps -> PageParams -> Aff Version
versionEndpoint { defaultListId, nodeId, session, tabType } _ = get session $ R.GetNgramsTableVersion { listId: defaultListId, tabType } (Just nodeId)
versionEndpoint { defaultListId, nodeId, session, tabType } _ = get session $ R.GetNgramsTableVersion { listId: defaultListId, tabType } (Just nodeId)
-- NOTE With cache off
-- NOTE With cache off
loader :: PageParams -> Aff VersionedNgramsTable
loader :: PageParams -> Aff Versioned
WithCount
NgramsTable
loader path@{ listIds
loader path@{ listIds
, nodeId
, nodeId
, params: { limit, offset, orderBy }
, params: { limit, offset, orderBy }
...
@@ -618,20 +623,22 @@ mainNgramsTableCpt = R.hooksComponentWithModule thisModule "mainNgramsTable" cpt
...
@@ -618,20 +623,22 @@ mainNgramsTableCpt = R.hooksComponentWithModule thisModule "mainNgramsTable" cpt
handleResponse v = v
handleResponse v = v
type MainNgramsTablePaintProps = (
type MainNgramsTablePaintProps = (
path :: PageParams
cacheState :: NT.CacheState
, path :: PageParams
, versioned :: VersionedNgramsTable
, versioned :: VersionedNgramsTable
| CommonProps
| CommonProps
)
)
mainNgramsTablePaint :: Record MainNgramsTablePaintProps -> R.Element
mainNgramsTablePaint :: R2.Component MainNgramsTablePaintProps
mainNgramsTablePaint p = R.createElement mainNgramsTablePaintCpt p []
mainNgramsTablePaint = R.createElement mainNgramsTablePaintCpt
mainNgramsTablePaintCpt :: R.Component MainNgramsTablePaintProps
mainNgramsTablePaintCpt = R.hooksComponentWithModule thisModule "mainNgramsTablePaint" cpt
where
where
mainNgramsTablePaintCpt :: R.Component MainNgramsTablePaintProps
mainNgramsTablePaintCpt = R.hooksComponentWithModule thisModule "mainNgramsTablePaint" cpt
cpt props@{ afterSync
cpt props@{ afterSync
, appReload
, appReload
, asyncTasksRef
, asyncTasksRef
, cacheState
, path
, path
, sidePanelTriggers
, sidePanelTriggers
, tabNgramType
, tabNgramType
...
@@ -643,6 +650,8 @@ mainNgramsTablePaintCpt = R.hooksComponentWithModule thisModule "mainNgramsTable
...
@@ -643,6 +650,8 @@ mainNgramsTablePaintCpt = R.hooksComponentWithModule thisModule "mainNgramsTable
pure $ loadedNgramsTable { afterSync
pure $ loadedNgramsTable { afterSync
, appReload
, appReload
, asyncTasksRef
, asyncTasksRef
, cacheState
, mTotalRows: Nothing
, path: pathS
, path: pathS
, sidePanelTriggers
, sidePanelTriggers
, state
, state
...
@@ -650,35 +659,41 @@ mainNgramsTablePaintCpt = R.hooksComponentWithModule thisModule "mainNgramsTable
...
@@ -650,35 +659,41 @@ mainNgramsTablePaintCpt = R.hooksComponentWithModule thisModule "mainNgramsTable
, treeReloadRef
, treeReloadRef
, versioned
, versioned
, withAutoUpdate
, withAutoUpdate
}
}
[]
type MainNgramsTablePaintNoCacheProps =
type MainNgramsTablePaintNoCacheProps = (
( pathS :: R.State PageParams
cacheState :: NT.CacheState
, versioned :: VersionedNgramsTable
, pathS :: R.State PageParams
, versionedWithCount :: VersionedWithCountNgramsTable
| CommonProps
| CommonProps
)
)
mainNgramsTablePaintNoCache :: Record MainNgramsTablePaintNoCacheProps -> R.Element
mainNgramsTablePaintNoCache :: R2.Component MainNgramsTablePaintNoCacheProps
mainNgramsTablePaintNoCache p = R.createElement mainNgramsTablePaintNoCacheCpt p []
mainNgramsTablePaintNoCache = R.createElement mainNgramsTablePaintNoCacheCpt
mainNgramsTablePaintNoCacheCpt :: R.Component MainNgramsTablePaintNoCacheProps
mainNgramsTablePaintNoCacheCpt = R.hooksComponentWithModule thisModule "mainNgramsTablePaintNoCache" cpt
where
where
mainNgramsTablePaintNoCacheCpt :: R.Component MainNgramsTablePaintNoCacheProps
mainNgramsTablePaintNoCacheCpt = R.hooksComponentWithModule thisModule "mainNgramsTablePaintNoCache" cpt
cpt props@{ afterSync
cpt props@{ afterSync
, appReload
, appReload
, asyncTasksRef
, asyncTasksRef
, cacheState
, pathS
, pathS
, sidePanelTriggers
, sidePanelTriggers
, tabNgramType
, tabNgramType
, treeReloadRef
, treeReloadRef
, versioned
, versioned
WithCount
, withAutoUpdate } _ = do
, withAutoUpdate } _ = do
let count /\ versioned = toVersioned versionedWithCount
state <- R.useState' $ initialState versioned
state <- R.useState' $ initialState versioned
pure $ loadedNgramsTable {
pure $ loadedNgramsTable {
afterSync
afterSync
, appReload
, appReload
, asyncTasksRef
, asyncTasksRef
, cacheState
, mTotalRows: Just count
, path: pathS
, path: pathS
, sidePanelTriggers
, sidePanelTriggers
, state
, state
...
@@ -686,35 +701,7 @@ mainNgramsTablePaintNoCacheCpt = R.hooksComponentWithModule thisModule "mainNgra
...
@@ -686,35 +701,7 @@ mainNgramsTablePaintNoCacheCpt = R.hooksComponentWithModule thisModule "mainNgra
, treeReloadRef
, treeReloadRef
, versioned
, versioned
, withAutoUpdate
, withAutoUpdate
}
} []
-- type MainNgramsTablePaintWithStateProps = (
-- afterSync :: Unit -> Aff Unit
-- , asyncTasksRef :: R.Ref (Maybe GAT.Reductor)
-- , path :: R.State PageParams
-- , tabNgramType :: CTabNgramType
-- , versioned :: VersionedNgramsTable
-- , withAutoUpdate :: Boolean
-- )
-- mainNgramsTablePaintWithState :: Record MainNgramsTablePaintWithStateProps -> R.Element
-- mainNgramsTablePaintWithState p = R.createElement mainNgramsTablePaintWithStateCpt p []
-- mainNgramsTablePaintWithStateCpt :: R.Component MainNgramsTablePaintWithStateProps
-- mainNgramsTablePaintWithStateCpt = R.hooksComponentWithModule thisModule "mainNgramsTablePaintWithState" cpt
-- where
-- cpt { afterSync, asyncTasksRef, path, tabNgramType, versioned, withAutoUpdate } _ = do
-- state <- R.useState' $ initialState versioned
-- pure $ loadedNgramsTable {
-- afterSync
-- , asyncTasksRef
-- , path
-- , state
-- , tabNgramType
-- , versioned
-- , withAutoUpdate
-- }
type NgramsOcc = { occurrences :: Additive Int, children :: Set NgramsTerm }
type NgramsOcc = { occurrences :: Additive Int, children :: Set NgramsTerm }
...
...
src/Gargantext/Components/NgramsTable/Core.purs
View file @
e7d216fa
...
@@ -18,9 +18,13 @@ module Gargantext.Components.NgramsTable.Core
...
@@ -18,9 +18,13 @@ module Gargantext.Components.NgramsTable.Core
, findNgramTermList
, findNgramTermList
, Version
, Version
, Versioned(..)
, Versioned(..)
, Count
, VersionedWithCount(..)
, toVersioned
, VersionedNgramsPatches
, VersionedNgramsPatches
, AsyncNgramsChartsUpdate
, AsyncNgramsChartsUpdate
, VersionedNgramsTable
, VersionedNgramsTable
, VersionedWithCountNgramsTable
, NgramsTablePatch
, NgramsTablePatch
, NgramsPatch(..)
, NgramsPatch(..)
, CoreState
, CoreState
...
@@ -164,6 +168,32 @@ instance decodeJsonVersioned :: DecodeJson a => DecodeJson (Versioned a) where
...
@@ -164,6 +168,32 @@ instance decodeJsonVersioned :: DecodeJson a => DecodeJson (Versioned a) where
version <- obj .: "version"
version <- obj .: "version"
data_ <- obj .: "data"
data_ <- obj .: "data"
pure $ Versioned {version, data: data_}
pure $ Versioned {version, data: data_}
------------------------------------------------------------------------
type Count = Int
newtype VersionedWithCount a = VersionedWithCount
{ version :: Version
, count :: Count
, data :: a
}
instance encodeJsonVersionedWithCount :: EncodeJson a => EncodeJson (VersionedWithCount a) where
encodeJson (VersionedWithCount {count, version, data: data_})
= "version" := version
~> "count" := count
~> "data" := data_
~> jsonEmptyObject
instance decodeJsonVersionedWithCount :: DecodeJson a => DecodeJson (VersionedWithCount a) where
decodeJson json = do
obj <- decodeJson json
count <- obj .: "count"
data_ <- obj .: "data"
version <- obj .: "version"
pure $ VersionedWithCount {count, version, data: data_}
toVersioned :: forall a. VersionedWithCount a -> Tuple Count (Versioned a)
toVersioned (VersionedWithCount { count, data: d, version }) = Tuple count $ Versioned { data: d, version }
------------------------------------------------------------------------
------------------------------------------------------------------------
-- TODO replace by NgramsPatches directly
-- TODO replace by NgramsPatches directly
...
@@ -535,6 +565,7 @@ highlightNgrams ntype table@(NgramsTable {ngrams_repo_elements: elts}) input0 =
...
@@ -535,6 +565,7 @@ highlightNgrams ntype table@(NgramsTable {ngrams_repo_elements: elts}) input0 =
-----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
type VersionedNgramsTable = Versioned NgramsTable
type VersionedNgramsTable = Versioned NgramsTable
type VersionedWithCountNgramsTable = VersionedWithCount NgramsTable
-----------------------------------------------------------------------------------
-----------------------------------------------------------------------------------
data Replace a
data Replace a
...
...
src/Gargantext/Components/Nodes/Annuaire.purs
View file @
e7d216fa
...
@@ -104,8 +104,7 @@ annuaireCpt = R.hooksComponentWithModule thisModule "annuaire" cpt
...
@@ -104,8 +104,7 @@ annuaireCpt = R.hooksComponentWithModule thisModule "annuaire" cpt
, title: name
, title: name
, user: "" }
, user: "" }
, H.p {} []
, H.p {} []
, H.div {className: "col-md-3"}
-- , H.div {className: "col-md-3"} [ H.text " Filter ", H.input { className: "form-control", style } ]
[ H.text " Filter ", H.input { className: "form-control", style } ]
, H.br {}
, H.br {}
, pageLayout { info, session, pagePath, frontends} ]
, pageLayout { info, session, pagePath, frontends} ]
where
where
...
@@ -164,7 +163,7 @@ pageCpt = R.hooksComponentWithModule thisModule "page" cpt
...
@@ -164,7 +163,7 @@ pageCpt = R.hooksComponentWithModule thisModule "page" cpt
, session }
, session }
, delete: false }) <$> Seq.fromFoldable docs
, delete: false }) <$> Seq.fromFoldable docs
container = T.defaultContainer { title: "Annuaire" } -- TODO
container = T.defaultContainer { title: "Annuaire" } -- TODO
colNames = T.ColumnName <$> [ "", "First Name", "Last Name", "Company", "
Lab", "
Role"]
colNames = T.ColumnName <$> [ "", "First Name", "Last Name", "Company", "Role"]
wrapColElts = const identity
wrapColElts = const identity
setParams f = snd pagePath $ \pp@{params: ps} ->
setParams f = snd pagePath $ \pp@{params: ps} ->
pp {params = f ps}
pp {params = f ps}
...
@@ -199,26 +198,27 @@ contactCellsCpt = R.hooksComponentWithModule thisModule "contactCells" cpt
...
@@ -199,26 +198,27 @@ contactCellsCpt = R.hooksComponentWithModule thisModule "contactCells" cpt
]
]
cpt { annuaireId
cpt { annuaireId
, contact: (CT.NodeContact { id
, contact: (CT.NodeContact { id
, hyperdata: ( CT.HyperdataContact { who : Just (CT.ContactWho { firstName
, hyperdata: ( CT.HyperdataContact
, lastName
{ who : Just (CT.ContactWho { firstName
}
, lastName
)
}
}
)
)
, ou : ou
}
}
)
}
)
)
, frontends
, frontends
, session } _ = do
, session } _ = do
pure $ T.makeRow [
pure $ T.makeRow [
H.text ""
H.text ""
, H.
text $ fromMaybe "First Name" firstName
, H.
a { target: "_blank", href: contactUrl annuaireId id} [H.text $ fromMaybe "First Name" firstName]
, H.text $ fromMaybe "First Name" lastName
, H.text $ fromMaybe "First Name" lastName
, H.text "CNRS"
-- , H.a { href } [ H.text $ fromMaybe "name" contact.title ]
-- , H.a { href } [ H.text $ fromMaybe "name" contact.title ]
--, H.a { href, target: "blank" } [ H.text $ fromMaybe "name" contact.title ]
--, H.a { href, target: "blank" } [ H.text $ fromMaybe "name" contact.title ]
--, H.text $ maybe "No ContactWhere"
contactWhereOrg (A.head $ ou)
, H.text $ maybe "No ContactWhere"
contactWhereOrg (A.head $ ou)
--
, H.text $ maybe "No ContactWhereDept" contactWhereDept (A.head $ ou)
, H.text $ maybe "No ContactWhereDept" contactWhereDept (A.head $ ou)
-- , H.div {className: "nooverflow"} [
-- , H.div {className: "nooverflow"} [
-- H.text $ maybe "No ContactWhereRole" contactWhereRole (A.head $ ou)
-- H.text $ maybe "No ContactWhereRole" contactWhereRole (A.head $ ou)
]
]
...
@@ -226,6 +226,7 @@ contactCellsCpt = R.hooksComponentWithModule thisModule "contactCells" cpt
...
@@ -226,6 +226,7 @@ contactCellsCpt = R.hooksComponentWithModule thisModule "contactCells" cpt
--nodepath = NodePath (sessionId session) NodeContact (Just id)
--nodepath = NodePath (sessionId session) NodeContact (Just id)
nodepath = Routes.ContactPage (sessionId session) annuaireId id
nodepath = Routes.ContactPage (sessionId session) annuaireId id
href = url frontends nodepath
href = url frontends nodepath
contactUrl aId id = url frontends $ Routes.ContactPage (sessionId session) annuaireId id
contactWhereOrg (CT.ContactWhere { organization: [] }) = "No Organization"
contactWhereOrg (CT.ContactWhere { organization: [] }) = "No Organization"
contactWhereOrg (CT.ContactWhere { organization: orga }) =
contactWhereOrg (CT.ContactWhere { organization: orga }) =
...
...
src/Gargantext/Components/Nodes/Annuaire/User/Contacts.purs
View file @
e7d216fa
...
@@ -150,8 +150,8 @@ contactInfoItemCpt = R.hooksComponentWithModule thisModule "contactInfoItem" cpt
...
@@ -150,8 +150,8 @@ contactInfoItemCpt = R.hooksComponentWithModule thisModule "contactInfoItem" cpt
listElement :: Array R.Element -> R.Element
listElement :: Array R.Element -> R.Element
listElement = H.li { className: "list-group-item justify-content-between" }
listElement = H.li { className: "list-group-item justify-content-between" }
type LayoutProps =
(
type LayoutProps =
appReload :: GUR.ReloadS
(
appReload :: GUR.ReloadS
, asyncTasksRef :: R.Ref (Maybe GAT.Reductor)
, asyncTasksRef :: R.Ref (Maybe GAT.Reductor)
, frontends :: Frontends
, frontends :: Frontends
, nodeId :: Int
, nodeId :: Int
...
@@ -219,7 +219,7 @@ userLayoutWithKeyCpt = R.hooksComponentWithModule thisModule "userLayoutWithKey"
...
@@ -219,7 +219,7 @@ userLayoutWithKeyCpt = R.hooksComponentWithModule thisModule "userLayoutWithKey"
_ <- saveContactHyperdata session nodeId hd
_ <- saveContactHyperdata session nodeId hd
liftEffect $ GUR.bump reload
liftEffect $ GUR.bump reload
-- | toUrl to get data
-- | toUrl to get data
XXX
getContact :: Session -> Int -> Aff ContactData
getContact :: Session -> Int -> Aff ContactData
getContact session id = do
getContact session id = do
contactNode <- get session $ Routes.NodeAPI Node (Just id) ""
contactNode <- get session $ Routes.NodeAPI Node (Just id) ""
...
@@ -240,9 +240,8 @@ saveContactHyperdata session id h = do
...
@@ -240,9 +240,8 @@ saveContactHyperdata session id h = do
put session (Routes.NodeAPI Node (Just id) "") h
put session (Routes.NodeAPI Node (Just id) "") h
type AnnuaireLayoutProps = (
type AnnuaireLayoutProps = ( annuaireId :: Int | LayoutProps )
annuaireId :: Int
type AnnuaireKeyLayoutProps = ( key :: String | AnnuaireLayoutProps )
| LayoutProps )
annuaireUserLayout :: Record AnnuaireLayoutProps -> R.Element
annuaireUserLayout :: Record AnnuaireLayoutProps -> R.Element
...
@@ -251,6 +250,21 @@ annuaireUserLayout props = R.createElement annuaireUserLayoutCpt props []
...
@@ -251,6 +250,21 @@ annuaireUserLayout props = R.createElement annuaireUserLayoutCpt props []
annuaireUserLayoutCpt :: R.Component AnnuaireLayoutProps
annuaireUserLayoutCpt :: R.Component AnnuaireLayoutProps
annuaireUserLayoutCpt = R.hooksComponentWithModule thisModule "annuaireUserLayout" cpt
annuaireUserLayoutCpt = R.hooksComponentWithModule thisModule "annuaireUserLayout" cpt
where
where
cpt { annuaireId, appReload, asyncTasksRef, frontends, nodeId, session, treeReloadRef } _ = do
let sid = sessionId session
pure $ annuaireUserLayoutWithKey { annuaireId,
appReload
, asyncTasksRef
, frontends
, key: show sid <> "-" <> show nodeId
, nodeId
, session
, treeReloadRef
}
{-
cpt { annuaireId, appReload, asyncTasksRef, frontends, nodeId, session, treeReloadRef } _ = do
cpt { annuaireId, appReload, asyncTasksRef, frontends, nodeId, session, treeReloadRef } _ = do
cacheState <- R.useState' LT.CacheOn
cacheState <- R.useState' LT.CacheOn
...
@@ -260,6 +274,40 @@ annuaireUserLayoutCpt = R.hooksComponentWithModule thisModule "annuaireUserLayou
...
@@ -260,6 +274,40 @@ annuaireUserLayoutCpt = R.hooksComponentWithModule thisModule "annuaireUserLayou
\contactData@{contactNode: Contact {name, hyperdata}} ->
\contactData@{contactNode: Contact {name, hyperdata}} ->
H.ul { className: "col-md-12 list-group" } [
H.ul { className: "col-md-12 list-group" } [
display { title: fromMaybe "no name" name } (contactInfos hyperdata onUpdateHyperdata)
display { title: fromMaybe "no name" name } (contactInfos hyperdata onUpdateHyperdata)
, Tabs.tabs { appReload
, asyncTasksRef
, cacheState
, contactData
, frontends
, nodeId
, session
, sidePanelTriggers
, treeReloadRef
}
]
where
onUpdateHyperdata :: HyperdataUser -> Effect Unit
onUpdateHyperdata _ = pure unit
-}
annuaireUserLayoutWithKey :: Record AnnuaireKeyLayoutProps -> R.Element
annuaireUserLayoutWithKey props = R.createElement annuaireUserLayoutWithKeyCpt props []
annuaireUserLayoutWithKeyCpt :: R.Component AnnuaireKeyLayoutProps
annuaireUserLayoutWithKeyCpt = R.hooksComponentWithModule thisModule "annuaireUserLayoutWithKey" cpt
where
cpt { annuaireId, appReload, asyncTasksRef, frontends, nodeId, session, treeReloadRef } _ = do
reload <- GUR.new
cacheState <- R.useState' LT.CacheOn
sidePanelTriggers <- LT.emptySidePanelTriggers
useLoader nodeId (getAnnuaireContact session annuaireId) $
\contactData@{contactNode: Contact {name, hyperdata}} ->
H.ul { className: "col-md-12 list-group" } [
display { title: fromMaybe "no name" name } (contactInfos hyperdata (onUpdateHyperdata reload))
, Tabs.tabs {
, Tabs.tabs {
appReload
appReload
, asyncTasksRef
, asyncTasksRef
...
@@ -272,14 +320,20 @@ annuaireUserLayoutCpt = R.hooksComponentWithModule thisModule "annuaireUserLayou
...
@@ -272,14 +320,20 @@ annuaireUserLayoutCpt = R.hooksComponentWithModule thisModule "annuaireUserLayou
, treeReloadRef
, treeReloadRef
}
}
]
]
where
where
onUpdateHyperdata :: HyperdataUser -> Effect Unit
onUpdateHyperdata :: GUR.ReloadS -> HyperdataUser -> Effect Unit
onUpdateHyperdata _ = pure unit
onUpdateHyperdata reload hd = do
launchAff_ $ do
_ <- saveContactHyperdata session nodeId hd
liftEffect $ GUR.bump reload
getAnnuaireContact :: Session -> Int -> Int -> Aff ContactData
getAnnuaireContact :: Session -> Int -> Int -> Aff ContactData
getAnnuaireContact session annuaireId id = do
getAnnuaireContact session annuaireId id = do
contactNode <- get session $ Routes.NodeAPI Annuaire (Just annuaireId) $
"contact/" <> (show id)
contactNode <- get session $ Routes.NodeAPI Annuaire (Just annuaireId) $
show id
-- TODO: we need a default list for the pairings
-- TODO: we need a default list for the pairings
--defaultListIds <- get $ toUrl endConfigStateful Back (Children NodeList 0 1 Nothing) $ Just id
--defaultListIds <- get $ toUrl endConfigStateful Back (Children NodeList 0 1 Nothing) $ Just id
--case (head defaultListIds :: Maybe (NodePoly HyperdataList)) of
--case (head defaultListIds :: Maybe (NodePoly HyperdataList)) of
...
...
src/Gargantext/Components/Nodes/Annuaire/User/Contacts/Tabs.purs
View file @
e7d216fa
...
@@ -21,6 +21,7 @@ import Gargantext.Components.Nodes.Texts.Types as TTypes
...
@@ -21,6 +21,7 @@ import Gargantext.Components.Nodes.Texts.Types as TTypes
import Gargantext.Ends (Frontends)
import Gargantext.Ends (Frontends)
import Gargantext.Sessions (Session)
import Gargantext.Sessions (Session)
import Gargantext.Types (CTabNgramType(..), NodeID, PTabNgramType(..), TabType(..), TabSubType(..))
import Gargantext.Types (CTabNgramType(..), NodeID, PTabNgramType(..), TabType(..), TabSubType(..))
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reload as GUR
import Gargantext.Utils.Reload as GUR
thisModule :: String
thisModule :: String
...
@@ -80,9 +81,9 @@ tabsCpt = R.hooksComponentWithModule thisModule "tabs" cpt
...
@@ -80,9 +81,9 @@ tabsCpt = R.hooksComponentWithModule thisModule "tabs" cpt
where
where
tabs' trg =
tabs' trg =
[ "Documents" /\ docs trg
[ "Documents" /\ docs trg
, "Patents" /\ ngramsView patentsView
, "Patents" /\ ngramsView patentsView
[]
, "Books" /\ ngramsView booksView
, "Books" /\ ngramsView booksView
[]
, "Communication" /\ ngramsView commView
, "Communication" /\ ngramsView commView
[]
, "Trash" /\ docs trg -- TODO pass-in trash mode
, "Trash" /\ docs trg -- TODO pass-in trash mode
]
]
where
where
...
@@ -141,12 +142,12 @@ type NgramsViewTabsProps = (
...
@@ -141,12 +142,12 @@ type NgramsViewTabsProps = (
, treeReloadRef :: GUR.ReloadWithInitializeRef
, treeReloadRef :: GUR.ReloadWithInitializeRef
)
)
ngramsView :: Record NgramsViewTabsProps -> R.Element
ngramsView :: R2.Component NgramsViewTabsProps
ngramsView props = R.createElement ngramsViewCpt props []
ngramsView = R.createElement ngramsViewCpt
ngramsViewCpt :: R.Component NgramsViewTabsProps
ngramsViewCpt = R.hooksComponentWithModule thisModule "ngramsView" cpt
where
where
ngramsViewCpt :: R.Component NgramsViewTabsProps
ngramsViewCpt = R.hooksComponentWithModule thisModule "ngramsView" cpt
cpt { appReload
cpt { appReload
, asyncTasksRef
, asyncTasksRef
, cacheState
, cacheState
...
@@ -172,7 +173,7 @@ ngramsViewCpt = R.hooksComponentWithModule thisModule "ngramsView" cpt
...
@@ -172,7 +173,7 @@ ngramsViewCpt = R.hooksComponentWithModule thisModule "ngramsView" cpt
, tabNgramType
, tabNgramType
, treeReloadRef
, treeReloadRef
, withAutoUpdate: false
, withAutoUpdate: false
}
}
[]
where
where
tabNgramType = modeTabType' mode
tabNgramType = modeTabType' mode
tabType = TabPairing $ TabNgramType $ modeTabType mode
tabType = TabPairing $ TabNgramType $ modeTabType mode
src/Gargantext/Components/Nodes/Corpus.purs
View file @
e7d216fa
...
@@ -21,7 +21,8 @@ import Gargantext.Prelude
...
@@ -21,7 +21,8 @@ import Gargantext.Prelude
import Gargantext.Components.CodeEditor as CE
import Gargantext.Components.CodeEditor as CE
import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Components.InputWithEnter (inputWithEnter)
import Gargantext.Components.Node (NodePoly(..), HyperdataList)
import Gargantext.Components.Node (NodePoly(..), HyperdataList)
import Gargantext.Components.Nodes.Corpus.Types (CorpusData, FTField, Field(..), FieldType(..), Hash, Hyperdata(..), defaultField, defaultHaskell', defaultPython', defaultJSON', defaultMarkdown')
import Gargantext.Components.Nodes.Types
import Gargantext.Components.Nodes.Corpus.Types (CorpusData, Hyperdata(..))
import Gargantext.Data.Array as GDA
import Gargantext.Data.Array as GDA
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Routes (SessionRoute(NodeAPI, Children))
import Gargantext.Routes (SessionRoute(NodeAPI, Children))
...
@@ -46,10 +47,10 @@ type KeyProps =
...
@@ -46,10 +47,10 @@ type KeyProps =
corpusLayout :: Record Props -> R.Element
corpusLayout :: Record Props -> R.Element
corpusLayout props = R.createElement corpusLayoutCpt props []
corpusLayout props = R.createElement corpusLayoutCpt props []
corpusLayoutCpt :: R.Component Props
corpusLayoutCpt = R.hooksComponentWithModule thisModule "corpusLayout" cpt
where
where
corpusLayoutCpt :: R.Component Props
corpusLayoutCpt = R.hooksComponentWithModule thisModule "corpusLayout" cpt
cpt { nodeId, session } _ = do
cpt { nodeId, session } _ = do
let sid = sessionId session
let sid = sessionId session
...
@@ -58,10 +59,10 @@ corpusLayoutCpt = R.hooksComponentWithModule thisModule "corpusLayout" cpt
...
@@ -58,10 +59,10 @@ corpusLayoutCpt = R.hooksComponentWithModule thisModule "corpusLayout" cpt
corpusLayoutWithKey :: Record KeyProps -> R.Element
corpusLayoutWithKey :: Record KeyProps -> R.Element
corpusLayoutWithKey props = R.createElement corpusLayoutWithKeyCpt props []
corpusLayoutWithKey props = R.createElement corpusLayoutWithKeyCpt props []
corpusLayoutWithKeyCpt :: R.Component KeyProps
corpusLayoutWithKeyCpt = R.hooksComponentWithModule thisModule "corpusLayoutWithKey" cpt
where
where
corpusLayoutWithKeyCpt :: R.Component KeyProps
corpusLayoutWithKeyCpt = R.hooksComponentWithModule thisModule "corpusLayoutWithKey" cpt
cpt { nodeId, session } _ = do
cpt { nodeId, session } _ = do
reload <- GUR.new
reload <- GUR.new
...
@@ -74,18 +75,12 @@ type ViewProps =
...
@@ -74,18 +75,12 @@ type ViewProps =
| Props
| Props
)
)
-- We need FTFields with indices because it's the only way to identify the
-- FTField element inside a component (there are no UUIDs and such)
type Index = Int
type FTFieldWithIndex = Tuple Index FTField
type FTFieldsWithIndex = List.List FTFieldWithIndex
corpusLayoutView :: Record ViewProps -> R.Element
corpusLayoutView :: Record ViewProps -> R.Element
corpusLayoutView props = R.createElement corpusLayoutViewCpt props []
corpusLayoutView props = R.createElement corpusLayoutViewCpt props []
corpusLayoutViewCpt :: R.Component ViewProps
corpusLayoutViewCpt = R.hooksComponentWithModule thisModule "corpusLayoutView" cpt
where
where
corpusLayoutViewCpt :: R.Component ViewProps
corpusLayoutViewCpt = R.hooksComponentWithModule thisModule "corpusLayoutView" cpt
cpt {corpus: (NodePoly {hyperdata: Hyperdata {fields}}), nodeId, reload, session} _ = do
cpt {corpus: (NodePoly {hyperdata: Hyperdata {fields}}), nodeId, reload, session} _ = do
let fieldsWithIndex = List.mapWithIndex (\idx -> \t -> Tuple idx t) fields
let fieldsWithIndex = List.mapWithIndex (\idx -> \t -> Tuple idx t) fields
fieldsS <- R.useState' fieldsWithIndex
fieldsS <- R.useState' fieldsWithIndex
...
@@ -99,24 +94,25 @@ corpusLayoutViewCpt = R.hooksComponentWithModule thisModule "corpusLayoutView" c
...
@@ -99,24 +94,25 @@ corpusLayoutViewCpt = R.hooksComponentWithModule thisModule "corpusLayoutView" c
R.setRef fieldsRef fields
R.setRef fieldsRef fields
snd fieldsS $ const fieldsWithIndex
snd fieldsS $ const fieldsWithIndex
pure $ H.div {} [
pure $ H.div {}
H.div { className: "row" } [
[ H.div { className: "row" }
H.div { className: "btn btn-secondary " <> (saveEnabled fieldsWithIndex fieldsS)
[ H.div { className: "btn btn-secondary " <> (saveEnabled fieldsWithIndex fieldsS)
, on: { click: onClickSave {fields: fieldsS, nodeId, reload, session} }
, on: { click: onClickSave {fields: fieldsS, nodeId, reload, session} }
} [
}
H.span { className: "fa fa-floppy-o" } [ ]
[ H.span { className: "fa fa-floppy-o" } [ ]
]
]
]
]
, H.div {} [ fieldsCodeEditor { fields: fieldsS
, H.div {}
, nodeId
[ fieldsCodeEditor { fields: fieldsS
, session } ]
, nodeId
, H.div { className: "row" } [
, session } ]
H.div { className: "btn btn-secondary"
, H.div { className: "row" }
, on: { click: onClickAdd fieldsS }
[ H.div { className: "btn btn-secondary"
} [
, on: { click: onClickAdd fieldsS }
H.span { className: "fa fa-plus" } [ ]
}
]
[ H.span { className: "fa fa-plus" } [ ]
]
]
]
]
]
saveEnabled :: FTFieldsWithIndex -> R.State FTFieldsWithIndex -> String
saveEnabled :: FTFieldsWithIndex -> R.State FTFieldsWithIndex -> String
...
@@ -127,7 +123,6 @@ corpusLayoutViewCpt = R.hooksComponentWithModule thisModule "corpusLayoutView" c
...
@@ -127,7 +123,6 @@ corpusLayoutViewCpt = R.hooksComponentWithModule thisModule "corpusLayoutView" c
, reload :: GUR.ReloadS
, reload :: GUR.ReloadS
, session :: Session } -> e -> Effect Unit
, session :: Session } -> e -> Effect Unit
onClickSave {fields: (fieldsS /\ _), nodeId, reload, session} _ = do
onClickSave {fields: (fieldsS /\ _), nodeId, reload, session} _ = do
log2 "[corpusLayoutViewCpt] onClickSave fieldsS" fieldsS
launchAff_ do
launchAff_ do
saveCorpus $ { hyperdata: Hyperdata {fields: (\(Tuple _ f) -> f) <$> fieldsS}
saveCorpus $ { hyperdata: Hyperdata {fields: (\(Tuple _ f) -> f) <$> fieldsS}
, nodeId
, nodeId
...
@@ -146,10 +141,10 @@ type FieldsCodeEditorProps =
...
@@ -146,10 +141,10 @@ type FieldsCodeEditorProps =
fieldsCodeEditor :: Record FieldsCodeEditorProps -> R.Element
fieldsCodeEditor :: Record FieldsCodeEditorProps -> R.Element
fieldsCodeEditor props = R.createElement fieldsCodeEditorCpt props []
fieldsCodeEditor props = R.createElement fieldsCodeEditorCpt props []
fieldsCodeEditorCpt :: R.Component FieldsCodeEditorProps
fieldsCodeEditorCpt = R.hooksComponentWithModule thisModule "fieldsCodeEditorCpt" cpt
where
where
fieldsCodeEditorCpt :: R.Component FieldsCodeEditorProps
fieldsCodeEditorCpt = R.hooksComponentWithModule thisModule "fieldsCodeEditorCpt" cpt
cpt {nodeId, fields: fS@(fields /\ _), session} _ = do
cpt {nodeId, fields: fS@(fields /\ _), session} _ = do
masterKey <- R.useState' 0
masterKey <- R.useState' 0
...
@@ -215,27 +210,25 @@ type FieldCodeEditorProps =
...
@@ -215,27 +210,25 @@ type FieldCodeEditorProps =
fieldCodeEditorWrapper :: Record FieldCodeEditorProps -> R.Element
fieldCodeEditorWrapper :: Record FieldCodeEditorProps -> R.Element
fieldCodeEditorWrapper props = R.createElement fieldCodeEditorWrapperCpt props []
fieldCodeEditorWrapper props = R.createElement fieldCodeEditorWrapperCpt props []
fieldCodeEditorWrapperCpt :: R.Component FieldCodeEditorProps
fieldCodeEditorWrapperCpt = R.hooksComponentWithModule thisModule "fieldCodeEditorWrapperCpt" cpt
where
where
fieldCodeEditorWrapperCpt :: R.Component FieldCodeEditorProps
fieldCodeEditorWrapperCpt = R.hooksComponentWithModule thisModule "fieldCodeEditorWrapperCpt" cpt
cpt props@{canMoveDown, canMoveUp, field: Field {name, typ}, onMoveDown, onMoveUp, onRemove, onRename} _ = do
cpt props@{canMoveDown, canMoveUp, field: Field {name, typ}, onMoveDown, onMoveUp, onRemove, onRename} _ = do
pure $ H.div { className: "row card" } [
pure $ H.div { className: "row card" } [
H.div { className: "card-header" } [
H.div { className: "card-header" } [
H.div { className: "code-editor-heading row" } [
H.div { className: "code-editor-heading row" } [
H.div { className: "col-
sm-
4" } [
H.div { className: "col-4" } [
renameable {onRename, text: name}
renameable {onRename, text: name}
]
]
, H.div { className: "col-
sm-
7" } []
, H.div { className: "col-7" } []
, H.div { className: "buttons-right col-
sm-1" }
[
, H.div { className: "buttons-right col-
1" } (
[
H.div { className: "btn btn-danger"
H.div { className: "btn btn-danger"
, on: { click: \_ -> onRemove unit }
, on: { click: \_ -> onRemove unit }
} [
} [
H.span { className: "fa fa-trash" } [ ]
H.span { className: "fa fa-trash" } [ ]
]
]
, moveDownButton canMoveDown
] <> moveButtons)
, moveUpButton canMoveUp
]
]
]
]
]
, H.div { className: "card-body" } [
, H.div { className: "card-body" } [
...
@@ -243,15 +236,15 @@ fieldCodeEditorWrapperCpt = R.hooksComponentWithModule thisModule "fieldCodeEdit
...
@@ -243,15 +236,15 @@ fieldCodeEditorWrapperCpt = R.hooksComponentWithModule thisModule "fieldCodeEdit
]
]
]
]
where
where
moveDownButton false = H.div {} []
moveButtons = [] <> (if canMoveDown then [moveDownButton] else [])
moveDownButton true =
<> (if canMoveUp then [moveUpButton] else [])
moveDownButton =
H.div { className: "btn btn-secondary"
H.div { className: "btn btn-secondary"
, on: { click: \_ -> onMoveDown unit }
, on: { click: \_ -> onMoveDown unit }
} [
} [
H.span { className: "fa fa-arrow-down" } [ ]
H.span { className: "fa fa-arrow-down" } [ ]
]
]
moveUpButton false = H.div {} []
moveUpButton =
moveUpButton true =
H.div { className: "btn btn-secondary"
H.div { className: "btn btn-secondary"
, on: { click: \_ -> onMoveUp unit }
, on: { click: \_ -> onMoveUp unit }
} [
} [
...
@@ -266,10 +259,10 @@ type RenameableProps =
...
@@ -266,10 +259,10 @@ type RenameableProps =
renameable :: Record RenameableProps -> R.Element
renameable :: Record RenameableProps -> R.Element
renameable props = R.createElement renameableCpt props []
renameable props = R.createElement renameableCpt props []
renameableCpt :: R.Component RenameableProps
renameableCpt = R.hooksComponentWithModule thisModule "renameableCpt" cpt
where
where
renameableCpt :: R.Component RenameableProps
renameableCpt = R.hooksComponentWithModule thisModule "renameableCpt" cpt
cpt {onRename, text} _ = do
cpt {onRename, text} _ = do
isEditing <- R.useState' false
isEditing <- R.useState' false
state <- R.useState' text
state <- R.useState' text
...
@@ -296,37 +289,37 @@ type RenameableTextProps =
...
@@ -296,37 +289,37 @@ type RenameableTextProps =
renameableText :: Record RenameableTextProps -> R.Element
renameableText :: Record RenameableTextProps -> R.Element
renameableText props = R.createElement renameableTextCpt props []
renameableText props = R.createElement renameableTextCpt props []
renameableTextCpt :: R.Component RenameableTextProps
renameableTextCpt = R.hooksComponentWithModule thisModule "renameableTextCpt" cpt
where
where
renameableTextCpt :: R.Component RenameableTextProps
renameableTextCpt = R.hooksComponentWithModule thisModule "renameableTextCpt" cpt
cpt {isEditing: (false /\ setIsEditing), state: (text /\ _)} _ = do
cpt {isEditing: (false /\ setIsEditing), state: (text /\ _)} _ = do
pure $ H.div { className: "input-group" }
[
pure $ H.div { className: "input-group" }
H.input { className: "form-control"
[
H.input { className: "form-control"
, defaultValue: text
, defaultValue: text
, disabled: 1
, disabled: 1
, type: "text" }
, type: "text" }
, H.div { className: "btn input-group-append"
, H.div { className: "btn input-group-append"
, on: { click: \_ -> setIsEditing $ const true } }
[
, on: { click: \_ -> setIsEditing $ const true } }
H.span { className: "fa fa-pencil" } []
[
H.span { className: "fa fa-pencil" } []
]
]
]
]
cpt {isEditing: (true /\ setIsEditing), onRename, state: (text /\ setText)} _ = do
cpt {isEditing: (true /\ setIsEditing), onRename, state: (text /\ setText)} _ = do
pure $ H.div { className: "input-group" }
[
pure $ H.div { className: "input-group" }
inputWithEnter {
[
inputWithEnter {
autoFocus: false
autoFocus: false
, autoSave: false
, autoSave: false
, className: "form-control text"
, className: "form-control text"
, defaultValue: text
, defaultValue: text
, onEnter: submit
, onEnter: submit
, onValueChanged: setText <<< const
, onValueChanged: setText <<< const
, placeholder: ""
, placeholder: ""
, type: "text"
, type: "text"
}
}
, H.div { className: "btn input-group-append"
, H.div { className: "btn input-group-append"
, on: { click: submit } } [
, on: { click: submit } }
H.span { className: "fa fa-floppy-o" } []
[
H.span { className: "fa fa-floppy-o" } []
]
]
]
]
where
where
submit _ = do
submit _ = do
...
@@ -335,10 +328,10 @@ renameableTextCpt = R.hooksComponentWithModule thisModule "renameableTextCpt" cp
...
@@ -335,10 +328,10 @@ renameableTextCpt = R.hooksComponentWithModule thisModule "renameableTextCpt" cp
fieldCodeEditor :: Record FieldCodeEditorProps -> R.Element
fieldCodeEditor :: Record FieldCodeEditorProps -> R.Element
fieldCodeEditor props = R.createElement fieldCodeEditorCpt props []
fieldCodeEditor props = R.createElement fieldCodeEditorCpt props []
fieldCodeEditorCpt :: R.Component FieldCodeEditorProps
fieldCodeEditorCpt = R.hooksComponentWithModule thisModule "fieldCodeEditorCpt" cpt
where
where
fieldCodeEditorCpt :: R.Component FieldCodeEditorProps
fieldCodeEditorCpt = R.hooksComponentWithModule thisModule "fieldCodeEditorCpt" cpt
cpt {field: Field {typ: typ@(Haskell {haskell})}, onChange} _ = do
cpt {field: Field {typ: typ@(Haskell {haskell})}, onChange} _ = do
pure $ CE.codeEditor {code: haskell, defaultCodeType: CE.Haskell, onChange: changeCode onChange typ}
pure $ CE.codeEditor {code: haskell, defaultCodeType: CE.Haskell, onChange: changeCode onChange typ}
...
...
src/Gargantext/Components/Nodes/Corpus/Dashboard.purs
View file @
e7d216fa
...
@@ -2,8 +2,9 @@ module Gargantext.Components.Nodes.Corpus.Dashboard where
...
@@ -2,8 +2,9 @@ module Gargantext.Components.Nodes.Corpus.Dashboard where
import DOM.Simple.Console (log2)
import DOM.Simple.Console (log2)
import Data.Array as A
import Data.Array as A
import Data.List as List
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Maybe (Maybe(..), fromMaybe)
import Data.Tuple (
fst
)
import Data.Tuple (
Tuple(..), snd
)
import Data.Tuple.Nested ((/\))
import Data.Tuple.Nested ((/\))
import Effect (Effect)
import Effect (Effect)
import Effect.Aff (launchAff_)
import Effect.Aff (launchAff_)
...
@@ -11,8 +12,10 @@ import Effect.Class (liftEffect)
...
@@ -11,8 +12,10 @@ import Effect.Class (liftEffect)
import Reactix as R
import Reactix as R
import Reactix.DOM.HTML as H
import Reactix.DOM.HTML as H
import Gargantext.Components.Nodes.Corpus (fieldsCodeEditor)
import Gargantext.Components.Nodes.Corpus.Chart.Predefined as P
import Gargantext.Components.Nodes.Corpus.Chart.Predefined as P
import Gargantext.Components.Nodes.Dashboard.Types as DT
import Gargantext.Components.Nodes.Dashboard.Types as DT
import Gargantext.Components.Nodes.Types
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Hooks.Loader (useLoader)
import Gargantext.Prelude
import Gargantext.Prelude
import Gargantext.Sessions (Session, sessionId)
import Gargantext.Sessions (Session, sessionId)
...
@@ -20,6 +23,7 @@ import Gargantext.Types (NodeID)
...
@@ -20,6 +23,7 @@ import Gargantext.Types (NodeID)
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reload as GUR
import Gargantext.Utils.Reload as GUR
thisModule :: String
thisModule = "Gargantext.Components.Nodes.Corpus.Dashboard"
thisModule = "Gargantext.Components.Nodes.Corpus.Dashboard"
type Props =
type Props =
...
@@ -27,42 +31,42 @@ type Props =
...
@@ -27,42 +31,42 @@ type Props =
, session :: Session
, session :: Session
)
)
dashboardLayout :: Record Props -> R.Element
dashboardLayout :: R2.Component Props
dashboardLayout props = R.createElement dashboardLayoutCpt props []
dashboardLayout = R.createElement dashboardLayoutCpt
dashboardLayoutCpt :: R.Component Props
dashboardLayoutCpt = R.hooksComponentWithModule thisModule "dashboardLayout" cpt
where
where
dashboardLayoutCpt :: R.Component Props
dashboardLayoutCpt = R.hooksComponentWithModule thisModule "dashboardLayout" cpt
cpt { nodeId, session } _ = do
cpt { nodeId, session } _ = do
let sid = sessionId session
let sid = sessionId session
pure $ dashboardLayoutWithKey { key: show sid <> "-" <> show nodeId, nodeId, session }
pure $ dashboardLayoutWithKey { key: show sid <> "-" <> show nodeId, nodeId, session }
[]
type KeyProps = (
type KeyProps = (
key :: String
key :: String
| Props
| Props
)
)
dashboardLayoutWithKey :: Record KeyProps -> R.Element
dashboardLayoutWithKey :: R2.Component KeyProps
dashboardLayoutWithKey props = R.createElement dashboardLayoutWithKeyCpt props []
dashboardLayoutWithKey = R.createElement dashboardLayoutWithKeyCpt
dashboardLayoutWithKeyCpt :: R.Component KeyProps
dashboardLayoutWithKeyCpt = R.hooksComponentWithModule thisModule "dashboardLayoutWithKey" cpt
where
where
dashboardLayoutWithKeyCpt :: R.Component KeyProps
dashboardLayoutWithKeyCpt = R.hooksComponentWithModule thisModule "dashboardLayoutWithKey" cpt
cpt { nodeId, session } _ = do
cpt { nodeId, session } _ = do
reload <- GUR.new
reload <- GUR.new
useLoader {nodeId, reload: GUR.value reload, session} DT.loadDashboardWithReload $
useLoader {nodeId, reload: GUR.value reload, session} DT.loadDashboardWithReload $
\dashboardData@{hyperdata: DT.Hyperdata h, parentId} -> do
\dashboardData@{hyperdata: DT.Hyperdata h, parentId} -> do
let { charts } = h
let { charts
, fields
} = h
dashboardLayoutLoaded { charts
dashboardLayoutLoaded { charts
, corpusId: parentId
, corpusId: parentId
, defaultListId: 0
, defaultListId: 0
, fields
, key: show $ GUR.value reload
, key: show $ GUR.value reload
, nodeId
, nodeId
, onChange: onChange nodeId reload (DT.Hyperdata h)
, onChange: onChange nodeId reload (DT.Hyperdata h)
, session }
, session } []
where
where
onChange :: NodeID -> GUR.ReloadS -> DT.Hyperdata -> Array P.PredefinedChart -> Effect Unit
onChange :: NodeID -> GUR.ReloadS -> DT.Hyperdata -> Array P.PredefinedChart -> Effect Unit
onChange nodeId' reload (DT.Hyperdata h) charts = do
onChange nodeId' reload (DT.Hyperdata h) charts = do
...
@@ -76,38 +80,69 @@ type LoadedProps =
...
@@ -76,38 +80,69 @@ type LoadedProps =
( charts :: Array P.PredefinedChart
( charts :: Array P.PredefinedChart
, corpusId :: NodeID
, corpusId :: NodeID
, defaultListId :: Int
, defaultListId :: Int
, fields :: List.List FTField
, key :: String
, key :: String
, onChange :: Array P.PredefinedChart -> Effect Unit
, onChange :: Array P.PredefinedChart -> Effect Unit
| Props
| Props
)
)
dashboardLayoutLoaded :: Record LoadedProps -> R.Element
dashboardLayoutLoaded :: R2.Component LoadedProps
dashboardLayoutLoaded props = R.createElement dashboardLayoutLoadedCpt props []
dashboardLayoutLoaded = R.createElement dashboardLayoutLoadedCpt
dashboardLayoutLoadedCpt :: R.Component LoadedProps
dashboardLayoutLoadedCpt = R.hooksComponentWithModule thisModule "dashboardLayoutLoaded" cpt
where
where
cpt props@{ charts, corpusId, defaultListId, onChange, session } _ = do
dashboardLayoutLoadedCpt :: R.Component LoadedProps
pure $
dashboardLayoutLoadedCpt = R.hooksComponentWithModule thisModule "dashboardLayoutLoaded" cpt
H.div {} ([ H.h1 {} [ H.text "Board" ]
, H.p {} [ H.text "Summary of all your charts here" ]
cpt props@{ charts, corpusId, defaultListId, fields, nodeId, onChange, session } _ = do
] <> chartsEls <> [addNew])
let fieldsWithIndex = List.mapWithIndex (\idx -> \t -> Tuple idx t) fields
fieldsS <- R.useState' fieldsWithIndex
fieldsRef <- R.useRef fields
-- handle props change of fields
R.useEffect1' fields $ do
if R.readRef fieldsRef == fields then
pure unit
else do
R.setRef fieldsRef fields
snd fieldsS $ const fieldsWithIndex
pure $ H.div {}
[ H.div { className: "row" }
[ H.div { className: "col-12" }
([ H.h1 {} [ H.text "Board" ]
, H.p {} [ H.text "Summary of all your charts here" ]
] <> chartsEls <> [addNew])
]
, H.div { className: "row" }
[ H.div { className: "col-12" }
[ fieldsCodeEditor { fields: fieldsS
, nodeId
, session } ]
]
, H.div { className: "row" }
[ H.div { className: "btn btn-secondary"
, on: { click: onClickAddField fieldsS }
}
[ H.span { className: "fa fa-plus" } [ ]
]
]
]
where
where
addNew = H.div { className: "row" } [
addNew = H.div { className: "row" } [
H.span { className: "btn btn-secondary"
H.span { className: "btn btn-secondary"
, on: { click: onClickAdd }} [ H.span { className: "fa fa-plus" } [] ]
, on: { click: onClickAdd
Chart
}} [ H.span { className: "fa fa-plus" } [] ]
]
]
where
where
onClickAdd _ = onChange $ A.cons P.CDocsHistogram charts
onClickAdd
Chart
_ = onChange $ A.cons P.CDocsHistogram charts
chartsEls = A.mapWithIndex chartIdx charts
chartsEls = A.mapWithIndex chartIdx charts
chartIdx idx chart =
chartIdx idx chart =
renderChart { chart, corpusId, defaultListId, onChange: onChangeChart, onRemove, session }
renderChart { chart, corpusId, defaultListId, onChange: onChangeChart, onRemove, session }
[]
where
where
onChangeChart c = do
onChangeChart c = do
log2 "[dashboardLayout] idx" idx
log2 "[dashboardLayout] new chart" c
onChange $ fromMaybe charts (A.modifyAt idx (\_ -> c) charts)
onChange $ fromMaybe charts (A.modifyAt idx (\_ -> c) charts)
onRemove _ = onChange $ fromMaybe charts $ A.deleteAt idx charts
onRemove _ = onChange $ fromMaybe charts $ A.deleteAt idx charts
onClickAddField :: forall e. R.State FTFieldsWithIndex -> e -> Effect Unit
onClickAddField (_ /\ setFieldsS) _ = do
setFieldsS $ \fieldsS -> List.snoc fieldsS $ Tuple (List.length fieldsS) defaultField
type PredefinedChartProps =
type PredefinedChartProps =
( chart :: P.PredefinedChart
( chart :: P.PredefinedChart
...
@@ -118,28 +153,32 @@ type PredefinedChartProps =
...
@@ -118,28 +153,32 @@ type PredefinedChartProps =
, session :: Session
, session :: Session
)
)
renderChart :: Record PredefinedChartProps -> R.Element
renderChart :: R2.Component PredefinedChartProps
renderChart props = R.createElement renderChartCpt props []
renderChart = R.createElement renderChartCpt
renderChartCpt :: R.Component PredefinedChartProps
renderChartCpt = R.hooksComponentWithModule thisModule "renderChart" cpt
where
where
renderChartCpt :: R.Component PredefinedChartProps
renderChartCpt = R.hooksComponentWithModule thisModule "renderChart" cpt
cpt { chart, corpusId, defaultListId, onChange, onRemove, session } _ = do
cpt { chart, corpusId, defaultListId, onChange, onRemove, session } _ = do
pure $ H.div { className: "chart" }
pure $ H.div { className: "row chart card" }
[ H.div { className: "row" }
[ H.div { className: "card-header" }
[ H.div { className: "col-2" }
[ H.div { className: "row" }
[ R2.select { defaultValue: show chart
[ H.div { className: "col-2" }
, on: { change: onSelectChange }
[ R2.select { defaultValue: show chart
} (option <$> P.allPredefinedCharts)
, on: { change: onSelectChange }
]
} (option <$> P.allPredefinedCharts)
, H.div { className: "col-1" }
]
[ H.span { className: "btn btn-danger"
, H.div { className: "col-1" }
, on: { click: onRemoveClick }} [ H.span { className: "fa fa-trash" } [] ]
[ H.span { className: "btn btn-danger"
, on: { click: onRemoveClick }} [ H.span { className: "fa fa-trash" } [] ]
]
]
]
]
]
, H.div { className: "row" }
, H.div { className: "card-body" }
[ H.div { className: "col-12 chart" }
[ H.div { className: "row" }
[ P.render chart params ]
[ H.div { className: "col-12 chart" }
[ P.render chart params ]
]
]
]
]
]
where
where
...
...
src/Gargantext/Components/Nodes/Corpus/Types.purs
View file @
e7d216fa
module Gargantext.Components.Nodes.Corpus.Types where
module Gargantext.Components.Nodes.Corpus.Types where
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, (.:), (:=), (~>), jsonEmptyObject)
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, (.:), (:=), (~>), jsonEmptyObject)
import Data.Argonaut.Decode.Error (JsonDecodeError(..))
import Data.List as List
import Data.List as List
import Data.Either (Either(..))
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Eq (genericEq)
import Data.Generic.Rep.Show (genericShow)
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Gargantext.Components.Node (NodePoly)
import Gargantext.Components.Node (NodePoly)
import Gargantext.Prelude
import Gargantext.Components.Nodes.Types (FTField, Field(..), FieldType(..), isJSON)
import Gargantext.Prelude (bind, pure, ($))
type Author = String
type Description = String
type Query = String
type Tag = String
type Title = String
type HaskellCode = String
type MarkdownText = String
type Hash = String
newtype Hyperdata =
newtype Hyperdata =
Hyperdata { fields :: List.List FTField }
Hyperdata { fields :: List.List FTField }
...
@@ -35,182 +22,6 @@ instance encodeHyperdata :: EncodeJson Hyperdata where
...
@@ -35,182 +22,6 @@ instance encodeHyperdata :: EncodeJson Hyperdata where
"fields" := fields
"fields" := fields
~> jsonEmptyObject
~> jsonEmptyObject
newtype Field a =
Field { name :: String
, typ :: a
}
type FTField = Field FieldType
derive instance genericFTField :: Generic (Field FieldType) _
instance eqFTField :: Eq (Field FieldType) where
eq = genericEq
instance showFTField :: Show (Field FieldType) where
show = genericShow
data FieldType =
Haskell { haskell :: HaskellCode
, tag :: Tag
}
| Python { python :: HaskellCode
, tag :: Tag
}
| JSON { authors :: Author
, desc :: Description
, query :: Query
, tag :: Tag
, title :: Title
}
| Markdown { tag :: Tag
, text :: MarkdownText
}
isJSON :: FTField -> Boolean
isJSON (Field {typ}) = isJSON' typ
where
isJSON' (JSON _) = true
isJSON' _ = false
getCorpusInfo :: List.List FTField -> CorpusInfo
getCorpusInfo as = case List.head (List.filter isJSON as) of
Just (Field {typ: JSON {authors, desc, query, title}}) -> CorpusInfo { title
, desc
, query
, authors
, totalRecords: 0
}
_ -> CorpusInfo { title:"Empty"
, desc:""
, query:""
, authors:""
, totalRecords: 0
}
derive instance genericFieldType :: Generic FieldType _
instance eqFieldType :: Eq FieldType where
eq = genericEq
instance showFieldType :: Show FieldType where
show = genericShow
instance decodeFTField :: DecodeJson (Field FieldType) where
decodeJson json = do
obj <- decodeJson json
name <- obj .: "name"
type_ <- obj .: "type"
data_ <- obj .: "data"
typ <- case type_ of
"Haskell" -> do
haskell <- data_ .: "haskell"
tag <- data_ .: "tag"
pure $ Haskell {haskell, tag}
"Python" -> do
python <- data_ .: "python"
tag <- data_ .: "tag"
pure $ Python {python, tag}
"JSON" -> do
authors <- data_ .: "authors"
desc <- data_ .: "desc"
query <- data_ .: "query"
tag <- data_ .: "tag"
title <- data_ .: "title"
pure $ JSON {authors, desc, query, tag, title}
"Markdown" -> do
tag <- data_ .: "tag"
text <- data_ .: "text"
pure $ Markdown {tag, text}
_ -> Left $ TypeMismatch $ "Unsupported 'type' " <> type_
pure $ Field {name, typ}
instance encodeFTField :: EncodeJson (Field FieldType) where
encodeJson (Field {name, typ}) =
"data" := typ
~> "name" := name
~> "type" := typ' typ
~> jsonEmptyObject
where
typ' (Haskell _) = "Haskell"
typ' (Python _) = "Python"
typ' (JSON _) = "JSON"
typ' (Markdown _) = "Markdown"
instance encodeFieldType :: EncodeJson FieldType where
encodeJson (Haskell {haskell}) =
"haskell" := haskell
~> "tag" := "HaskellField"
~> jsonEmptyObject
encodeJson (Python {python}) =
"python" := python
~> "tag" := "PythonField"
~> jsonEmptyObject
encodeJson (JSON {authors, desc, query, tag, title}) =
"authors" := authors
~> "desc" := desc
~> "query" := query
~> "tag" := "JsonField"
~> "title" := title
~> jsonEmptyObject
encodeJson (Markdown {text}) =
"tag" := "MarkdownField"
~> "text" := text
~> jsonEmptyObject
defaultPython :: FieldType
defaultPython = Python defaultPython'
defaultPython' :: { python :: String, tag :: String }
defaultPython' = { python: "import Foo"
, tag : "PythonField"
}
defaultHaskell :: FieldType
defaultHaskell = Haskell defaultHaskell'
defaultHaskell' :: { haskell :: String, tag :: String }
defaultHaskell' = { haskell: ""
, tag : "HaskellField"
}
defaultJSON :: FieldType
defaultJSON = JSON defaultJSON'
defaultJSON' :: { authors :: String
, desc :: String
, query :: String
, tag :: String
, title :: String
}
defaultJSON' = { authors: ""
, desc: ""
, query: ""
, tag: "JSONField"
, title: ""
}
defaultMarkdown :: FieldType
defaultMarkdown = Markdown defaultMarkdown'
defaultMarkdown' :: { tag :: String
, text :: String
}
defaultMarkdown' = { tag: "MarkdownField"
, text: "# New file"
}
defaultField :: FTField
defaultField = Field { name: "New file"
, typ: defaultMarkdown
}
newtype CorpusInfo =
newtype CorpusInfo =
CorpusInfo { title :: String
CorpusInfo { title :: String
, authors :: String
, authors :: String
...
@@ -232,3 +43,18 @@ instance decodeCorpusInfo :: DecodeJson CorpusInfo where
...
@@ -232,3 +43,18 @@ instance decodeCorpusInfo :: DecodeJson CorpusInfo where
type CorpusData = { corpusId :: Int
type CorpusData = { corpusId :: Int
, corpusNode :: NodePoly Hyperdata -- CorpusInfo
, corpusNode :: NodePoly Hyperdata -- CorpusInfo
, defaultListId :: Int }
, defaultListId :: Int }
getCorpusInfo :: List.List FTField -> CorpusInfo
getCorpusInfo as = case List.head (List.filter isJSON as) of
Just (Field {typ: JSON {authors, desc, query, title}}) -> CorpusInfo { title
, desc
, query
, authors
, totalRecords: 0
}
_ -> CorpusInfo { title:"Empty"
, desc:""
, query:""
, authors:""
, totalRecords: 0
}
src/Gargantext/Components/Nodes/Dashboard/Types.purs
View file @
e7d216fa
module Gargantext.Components.Nodes.Dashboard.Types where
module Gargantext.Components.Nodes.Dashboard.Types where
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, (.:), (.:?), (:=), (~>), jsonEmptyObject)
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, (.:), (.:?), (:=), (~>), jsonEmptyObject)
import Data.List as List
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Effect.Aff (Aff)
import Effect.Aff (Aff)
import Gargantext.Components.Nodes.Corpus.Chart.Predefined as P
import Gargantext.Components.Nodes.Corpus.Chart.Predefined as P
import Gargantext.Components.Nodes.Types (FTField, Field(..), FieldType(..), isJSON)
import Gargantext.Prelude
import Gargantext.Prelude
import Gargantext.Routes (SessionRoute(NodeAPI))
import Gargantext.Routes (SessionRoute(NodeAPI))
import Gargantext.Sessions (Session, get, put)
import Gargantext.Sessions (Session, get, put)
...
@@ -14,17 +17,20 @@ type Preferences = Maybe String
...
@@ -14,17 +17,20 @@ type Preferences = Maybe String
newtype Hyperdata =
newtype Hyperdata =
Hyperdata
Hyperdata
{ charts :: Array P.PredefinedChart
{ charts :: Array P.PredefinedChart
, fields :: List.List FTField
, preferences :: Preferences
, preferences :: Preferences
}
}
instance decodeHyperdata :: DecodeJson Hyperdata where
instance decodeHyperdata :: DecodeJson Hyperdata where
decodeJson json = do
decodeJson json = do
obj <- decodeJson json
obj <- decodeJson json
charts <- obj .: "charts"
charts <- obj .: "charts"
fields <- obj .: "fields"
preferences <- obj .:? "preferences"
preferences <- obj .:? "preferences"
pure $ Hyperdata {charts, preferences}
pure $ Hyperdata {charts,
fields,
preferences}
instance encodeHyperdata :: EncodeJson Hyperdata where
instance encodeHyperdata :: EncodeJson Hyperdata where
encodeJson (Hyperdata {charts, preferences}) = do
encodeJson (Hyperdata {charts,
fields,
preferences}) = do
"charts" := charts
"charts" := charts
~> "fields" := fields
~> "preferences" := preferences
~> "preferences" := preferences
~> jsonEmptyObject
~> jsonEmptyObject
...
...
src/Gargantext/Components/Nodes/Home.purs
View file @
e7d216fa
...
@@ -84,7 +84,7 @@ homeLayoutCpt = R.hooksComponentWithModule thisModule "homeLayout" cpt
...
@@ -84,7 +84,7 @@ homeLayoutCpt = R.hooksComponentWithModule thisModule "homeLayout" cpt
}
}
]
]
, H.div {className:"center"}
, H.div {className:"c
ol-12 d-flex justify-content-c
enter"}
[ H.h1 {} [ -- H.span {className: "fa fa-star-o"} []
[ H.h1 {} [ -- H.span {className: "fa fa-star-o"} []
H.text ""
H.text ""
]
]
...
@@ -281,7 +281,7 @@ homeLayoutCpt = R.hooksComponentWithModule thisModule "homeLayout" cpt
...
@@ -281,7 +281,7 @@ homeLayoutCpt = R.hooksComponentWithModule thisModule "homeLayout" cpt
--}
--}
video fileDuration = H.div {className:"center"}
video fileDuration = H.div {className:"c
ol-12 d-flex justify-content-c
enter"}
[ H.video { src: "http://dl.gargantext.org/" <> fileDuration
[ H.video { src: "http://dl.gargantext.org/" <> fileDuration
, title: "tutorial video here"
, title: "tutorial video here"
, id: "source_" <> fileDuration
, id: "source_" <> fileDuration
...
@@ -292,7 +292,7 @@ homeLayoutCpt = R.hooksComponentWithModule thisModule "homeLayout" cpt
...
@@ -292,7 +292,7 @@ homeLayoutCpt = R.hooksComponentWithModule thisModule "homeLayout" cpt
} [H.text "Sorry your browser is not compatible: use Firefox or Chromium instead."]
} [H.text "Sorry your browser is not compatible: use Firefox or Chromium instead."]
]
]
joinButton = H.div { className:"flex-space-around center"
joinButton = H.div { className:"flex-space-around
d-flex justify-content-
center"
, paddingTop: "100px"
, paddingTop: "100px"
, paddingBottom: "100px"
, paddingBottom: "100px"
}
}
...
...
src/Gargantext/Components/Nodes/Lists.purs
View file @
e7d216fa
...
@@ -35,10 +35,10 @@ type ListsWithForest = (
...
@@ -35,10 +35,10 @@ type ListsWithForest = (
listsWithForest :: R2.Component ListsWithForest
listsWithForest :: R2.Component ListsWithForest
listsWithForest = R.createElement listsWithForestCpt
listsWithForest = R.createElement listsWithForestCpt
listsWithForestCpt :: R.Component ListsWithForest
listsWithForestCpt = R.hooksComponentWithModule thisModule "listsWithForest" cpt
where
where
listsWithForestCpt :: R.Component ListsWithForest
listsWithForestCpt = R.hooksComponentWithModule thisModule "listsWithForest" cpt
cpt { forestProps
cpt { forestProps
, listsProps: listsProps@{ session } } _ = do
, listsProps: listsProps@{ session } } _ = do
controls <- initialControls
controls <- initialControls
...
@@ -58,10 +58,10 @@ type TopBarProps = (
...
@@ -58,10 +58,10 @@ type TopBarProps = (
topBar :: R2.Component TopBarProps
topBar :: R2.Component TopBarProps
topBar = R.createElement topBarCpt
topBar = R.createElement topBarCpt
topBarCpt :: R.Component TopBarProps
topBarCpt = R.hooksComponentWithModule thisModule "topBar" cpt
where
where
topBarCpt :: R.Component TopBarProps
topBarCpt = R.hooksComponentWithModule thisModule "topBar" cpt
cpt { controls } _ = do
cpt { controls } _ = do
-- empty for now because the button is moved to the side panel
-- empty for now because the button is moved to the side panel
pure $ H.div {} []
pure $ H.div {} []
...
@@ -93,10 +93,10 @@ type WithTreeProps = (
...
@@ -93,10 +93,10 @@ type WithTreeProps = (
listsLayout :: R2.Component Props
listsLayout :: R2.Component Props
listsLayout = R.createElement listsLayoutCpt
listsLayout = R.createElement listsLayoutCpt
listsLayoutCpt :: R.Component Props
listsLayoutCpt = R.hooksComponentWithModule thisModule "listsLayout" cpt
where
where
listsLayoutCpt :: R.Component Props
listsLayoutCpt = R.hooksComponentWithModule thisModule "listsLayout" cpt
cpt path@{ nodeId, session } _ = do
cpt path@{ nodeId, session } _ = do
let sid = sessionId session
let sid = sessionId session
...
@@ -109,10 +109,10 @@ type KeyProps = (
...
@@ -109,10 +109,10 @@ type KeyProps = (
listsLayoutWithKey :: Record KeyProps -> R.Element
listsLayoutWithKey :: Record KeyProps -> R.Element
listsLayoutWithKey props = R.createElement listsLayoutWithKeyCpt props []
listsLayoutWithKey props = R.createElement listsLayoutWithKeyCpt props []
listsLayoutWithKeyCpt :: R.Component KeyProps
listsLayoutWithKeyCpt = R.hooksComponentWithModule thisModule "listsLayoutWithKey" cpt
where
where
listsLayoutWithKeyCpt :: R.Component KeyProps
listsLayoutWithKeyCpt = R.hooksComponentWithModule thisModule "listsLayoutWithKey" cpt
cpt { appReload
cpt { appReload
, asyncTasksRef
, asyncTasksRef
, controls
, controls
...
@@ -164,10 +164,10 @@ type SidePanelProps = (
...
@@ -164,10 +164,10 @@ type SidePanelProps = (
sidePanel :: R2.Component SidePanelProps
sidePanel :: R2.Component SidePanelProps
sidePanel = R.createElement sidePanelCpt
sidePanel = R.createElement sidePanelCpt
sidePanelCpt :: R.Component SidePanelProps
sidePanelCpt = R.hooksComponentWithModule thisModule "sidePanel" cpt
where
where
sidePanelCpt :: R.Component SidePanelProps
sidePanelCpt = R.hooksComponentWithModule thisModule "sidePanel" cpt
cpt { controls: { triggers: { toggleSidePanel
cpt { controls: { triggers: { toggleSidePanel
, triggerSidePanel
, triggerSidePanel
} }
} }
...
@@ -208,10 +208,10 @@ type SidePanelDocView = (
...
@@ -208,10 +208,10 @@ type SidePanelDocView = (
sidePanelDocView :: R2.Component SidePanelDocView
sidePanelDocView :: R2.Component SidePanelDocView
sidePanelDocView = R.createElement sidePanelDocViewCpt
sidePanelDocView = R.createElement sidePanelDocViewCpt
sidePanelDocViewCpt :: R.Component SidePanelDocView
sidePanelDocViewCpt = R.hooksComponentWithModule thisModule "sidePanelDocView" cpt
where
where
sidePanelDocViewCpt :: R.Component SidePanelDocView
sidePanelDocViewCpt = R.hooksComponentWithModule thisModule "sidePanelDocView" cpt
cpt { session } _ = do
cpt { session } _ = do
-- pure $ H.h4 {} [ H.text txt ]
-- pure $ H.h4 {} [ H.text txt ]
pure $ H.div {} [ H.text "Hello ngrams" ]
pure $ H.div {} [ H.text "Hello ngrams" ]
src/Gargantext/Components/Nodes/Lists/Tabs.purs
View file @
e7d216fa
...
@@ -130,7 +130,7 @@ ngramsViewCpt = R.hooksComponentWithModule thisModule "ngramsView" cpt
...
@@ -130,7 +130,7 @@ ngramsViewCpt = R.hooksComponentWithModule thisModule "ngramsView" cpt
, tabType
, tabType
, treeReloadRef
, treeReloadRef
, withAutoUpdate: false
, withAutoUpdate: false
}
}
[]
]
]
)
)
where
where
...
@@ -156,7 +156,7 @@ ngramsViewCpt = R.hooksComponentWithModule thisModule "ngramsView" cpt
...
@@ -156,7 +156,7 @@ ngramsViewCpt = R.hooksComponentWithModule thisModule "ngramsView" cpt
charts params CTabTerms (chartType /\ setChartType) _ = [
charts params CTabTerms (chartType /\ setChartType) _ = [
H.div {className: "row"}
H.div {className: "row"}
[ H.div {className: "col-
6 ml-auto mr-auto
"}
[ H.div {className: "col-
12 d-flex justify-content-center
"}
[ H.img { src: "images/Gargantextuel-212x300.jpg"
[ H.img { src: "images/Gargantextuel-212x300.jpg"
, id: "funnyimg"
, id: "funnyimg"
}
}
...
...
src/Gargantext/Components/Nodes/Types.purs
0 → 100644
View file @
e7d216fa
module Gargantext.Components.Nodes.Types where
import Data.Argonaut (class DecodeJson, class EncodeJson, decodeJson, (.:), (:=), (~>), jsonEmptyObject)
import Data.Argonaut.Decode.Error (JsonDecodeError(..))
import Data.Either (Either(..))
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Eq (genericEq)
import Data.Generic.Rep.Show (genericShow)
import Data.List as List
import Data.Tuple (Tuple)
import Gargantext.Prelude
type Author = String
type Description = String
type HaskellCode = String
type Hash = String
type MarkdownText = String
type Query = String
type Tag = String
type Title = String
-- We need FTFields with indices because it's the only way to identify the
-- FTField element inside a component (there are no UUIDs and such)
type Index = Int
type FTFieldWithIndex = Tuple Index FTField
type FTFieldsWithIndex = List.List FTFieldWithIndex
newtype Field a =
Field { name :: String
, typ :: a
}
type FTField = Field FieldType
derive instance genericFTField :: Generic (Field FieldType) _
instance eqFTField :: Eq (Field FieldType) where
eq = genericEq
instance showFTField :: Show (Field FieldType) where
show = genericShow
data FieldType =
Haskell { haskell :: HaskellCode
, tag :: Tag
}
| Python { python :: HaskellCode
, tag :: Tag
}
| JSON { authors :: Author
, desc :: Description
, query :: Query
, tag :: Tag
, title :: Title
}
| Markdown { tag :: Tag
, text :: MarkdownText
}
isJSON :: FTField -> Boolean
isJSON (Field {typ}) = isJSON' typ
where
isJSON' (JSON _) = true
isJSON' _ = false
derive instance genericFieldType :: Generic FieldType _
instance eqFieldType :: Eq FieldType where
eq = genericEq
instance showFieldType :: Show FieldType where
show = genericShow
instance decodeFTField :: DecodeJson (Field FieldType) where
decodeJson json = do
obj <- decodeJson json
name <- obj .: "name"
type_ <- obj .: "type"
data_ <- obj .: "data"
typ <- case type_ of
"Haskell" -> do
haskell <- data_ .: "haskell"
tag <- data_ .: "tag"
pure $ Haskell {haskell, tag}
"Python" -> do
python <- data_ .: "python"
tag <- data_ .: "tag"
pure $ Python {python, tag}
"JSON" -> do
authors <- data_ .: "authors"
desc <- data_ .: "desc"
query <- data_ .: "query"
tag <- data_ .: "tag"
title <- data_ .: "title"
pure $ JSON {authors, desc, query, tag, title}
"Markdown" -> do
tag <- data_ .: "tag"
text <- data_ .: "text"
pure $ Markdown {tag, text}
_ -> Left $ TypeMismatch $ "Unsupported 'type' " <> type_
pure $ Field {name, typ}
instance encodeFTField :: EncodeJson (Field FieldType) where
encodeJson (Field {name, typ}) =
"data" := typ
~> "name" := name
~> "type" := typ' typ
~> jsonEmptyObject
where
typ' (Haskell _) = "Haskell"
typ' (Python _) = "Python"
typ' (JSON _) = "JSON"
typ' (Markdown _) = "Markdown"
instance encodeFieldType :: EncodeJson FieldType where
encodeJson (Haskell {haskell}) =
"haskell" := haskell
~> "tag" := "HaskellField"
~> jsonEmptyObject
encodeJson (Python {python}) =
"python" := python
~> "tag" := "PythonField"
~> jsonEmptyObject
encodeJson (JSON {authors, desc, query, tag, title}) =
"authors" := authors
~> "desc" := desc
~> "query" := query
~> "tag" := "JsonField"
~> "title" := title
~> jsonEmptyObject
encodeJson (Markdown {text}) =
"tag" := "MarkdownField"
~> "text" := text
~> jsonEmptyObject
defaultPython :: FieldType
defaultPython = Python defaultPython'
defaultPython' :: { python :: String, tag :: String }
defaultPython' = { python: "import Foo"
, tag : "PythonField"
}
defaultHaskell :: FieldType
defaultHaskell = Haskell defaultHaskell'
defaultHaskell' :: { haskell :: String, tag :: String }
defaultHaskell' = { haskell: ""
, tag : "HaskellField"
}
defaultJSON :: FieldType
defaultJSON = JSON defaultJSON'
defaultJSON' :: { authors :: String
, desc :: String
, query :: String
, tag :: String
, title :: String
}
defaultJSON' = { authors: ""
, desc: ""
, query: ""
, tag: "JSONField"
, title: ""
}
defaultMarkdown :: FieldType
defaultMarkdown = Markdown defaultMarkdown'
defaultMarkdown' :: { tag :: String
, text :: String
}
defaultMarkdown' = { tag: "MarkdownField"
, text: "# New file"
}
defaultField :: FTField
defaultField = Field { name: "New file"
, typ: defaultMarkdown
}
src/Gargantext/Components/Search.purs
View file @
e7d216fa
...
@@ -58,9 +58,8 @@ instance encodeJsonSearchResult :: Argonaut.EncodeJson SearchResult where
...
@@ -58,9 +58,8 @@ instance encodeJsonSearchResult :: Argonaut.EncodeJson SearchResult where
------------------------------------------------------------------------
------------------------------------------------------------------------
data SearchResultTypes =
data SearchResultTypes = SearchResultDoc { docs :: Array Document}
SearchResultDoc { docs :: Array Document}
| SearchNoResult { message :: String }
| SearchNoResult { message :: String }
| SearchResultContact { contacts :: Array Contact }
| SearchResultContact { contacts :: Array Contact }
derive instance eqSearchResultTypes :: Eq SearchResultTypes
derive instance eqSearchResultTypes :: Eq SearchResultTypes
...
@@ -132,6 +131,7 @@ data Contact =
...
@@ -132,6 +131,7 @@ data Contact =
, c_created :: String
, c_created :: String
, c_hyperdata :: HyperdataRowContact
, c_hyperdata :: HyperdataRowContact
, c_score :: Int
, c_score :: Int
, c_annuaireId :: Int
}
}
derive instance eqContact :: Eq Contact
derive instance eqContact :: Eq Contact
...
...
src/Gargantext/Components/Tab.purs
View file @
e7d216fa
...
@@ -14,7 +14,7 @@ thisModule = "Gargantext.Components.Tab"
...
@@ -14,7 +14,7 @@ thisModule = "Gargantext.Components.Tab"
type TabsProps = (
type TabsProps = (
selected :: Int
selected :: Int
, tabs :: Array (Tuple String R.Element)
, tabs
:: Array (Tuple String R.Element)
)
)
tabs :: Record TabsProps -> R.Element
tabs :: Record TabsProps -> R.Element
...
@@ -29,17 +29,23 @@ tabsCpt = R.hooksComponentWithModule thisModule "tabs" cpt
...
@@ -29,17 +29,23 @@ tabsCpt = R.hooksComponentWithModule thisModule "tabs" cpt
pure $
pure $
H.div {}
H.div {}
[ H.nav {}
[ H.nav {}
[ H.div { className: "nav nav-tabs"
[ H.br {}
, title : "Tab for ngrams"
, H.div { className: "nav nav-tabs"
}
, title : "Search result"
(mapWithIndex (button setActiveTab activeTab) props.tabs) ]
} -- [H.text "" ]
, H.div { className: "tab-content" } $ mapWithIndex (item activeTab) props.tabs ]
(mapWithIndex (button setActiveTab activeTab) props.tabs)
]
, H.div { className: "tab-content" }
$ mapWithIndex (item activeTab) props.tabs
]
--{-
button setActiveTab selected index (name /\ _) =
button setActiveTab selected index (name /\ _) =
H.a { className, on: { click } } [ H.text name ]
H.a { className, on: { click } } [ H.text name ]
where
where
eq = index == selected
eq = index == selected
className = "nav-item nav-link" <> (if eq then " active" else "")
className = "nav-item nav-link" <> (if eq then " active" else "")
click e = setActiveTab (const index)
click e = setActiveTab (const index)
--}
item selected index (_ /\ cpt') = tab { selected, index } [ cpt' ]
item selected index (_ /\ cpt') = tab { selected, index } [ cpt' ]
-- TODO: document what these are (selection, item indices)
-- TODO: document what these are (selection, item indices)
...
...
src/Gargantext/Components/Table.purs
View file @
e7d216fa
module Gargantext.Components.Table where
module Gargantext.Components.Table where
import Prelude
import Data.Array as A
import Data.Array as A
import Data.Generic.Rep (class Generic)
import Data.Generic.Rep.Show (genericShow)
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Data.Sequence as Seq
import Data.Sequence as Seq
import Data.Tuple (fst, snd)
import Data.Tuple (fst, snd)
import Effect.Aff (Aff, launchAff_)
import Data.Tuple.Nested ((/\))
import Data.Tuple.Nested ((/\))
import DOM.Simple.Console (log2)
import Effect (Effect)
import Effect (Effect)
import Gargantext.Sessions (Session, get)
import Reactix as R
import Reactix as R
import Reactix.DOM.HTML as H
import Reactix.DOM.HTML as H
import Gargantext.Components.Table.Types
import Gargantext.Prelude
import Gargantext.Components.Table.Types (ColumnName, OrderBy, OrderByDirection(..), Params, Props, TableContainerProps, columnName)
import Gargantext.Components.Nodes.Lists.Types as NT
import Gargantext.Components.Nodes.Lists.Types as NT
import Gargantext.Components.Search
import Gargantext.Components.Search
(SearchType(..))
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix as R2
import Gargantext.Utils.Reactix (effectLink)
import Gargantext.Utils.Reactix (effectLink)
thisModule :: String
thisModule :: String
thisModule = "Gargantext.Components.Table"
thisModule = "Gargantext.Components.Table"
type Page = Int
type State =
type State =
{ page ::
Int
{ page ::
Page
, pageSize :: PageSizes
, pageSize :: PageSizes
, orderBy :: OrderBy
, orderBy :: OrderBy
, searchType :: SearchType
, searchType :: SearchType
...
@@ -60,10 +58,10 @@ initialParams = stateParams {page: 1, pageSize: PS10, orderBy: Nothing, searchTy
...
@@ -60,10 +58,10 @@ initialParams = stateParams {page: 1, pageSize: PS10, orderBy: Nothing, searchTy
tableHeaderLayout :: Record TableHeaderLayoutProps -> R.Element
tableHeaderLayout :: Record TableHeaderLayoutProps -> R.Element
tableHeaderLayout props = R.createElement tableHeaderLayoutCpt props []
tableHeaderLayout props = R.createElement tableHeaderLayoutCpt props []
tableHeaderLayoutCpt :: R.Component TableHeaderLayoutProps
tableHeaderLayoutCpt = R.hooksComponentWithModule thisModule "tableHeaderLayout" cpt
where
where
tableHeaderLayoutCpt :: R.Component TableHeaderLayoutProps
tableHeaderLayoutCpt = R.hooksComponentWithModule thisModule "tableHeaderLayout" cpt
cpt { afterCacheStateChange, cacheState, date, desc, query, title, user } _ =
cpt { afterCacheStateChange, cacheState, date, desc, query, title, user } _ =
pure $ R.fragment
pure $ R.fragment
[ R2.row
[ R2.row
...
@@ -117,10 +115,10 @@ tableHeaderLayoutCpt = R.hooksComponentWithModule thisModule "tableHeaderLayout"
...
@@ -117,10 +115,10 @@ tableHeaderLayoutCpt = R.hooksComponentWithModule thisModule "tableHeaderLayout"
table :: Record Props -> R.Element
table :: Record Props -> R.Element
table props = R.createElement tableCpt props []
table props = R.createElement tableCpt props []
tableCpt :: R.Component Props
tableCpt = R.hooksComponentWithModule thisModule "table" cpt
where
where
tableCpt :: R.Component Props
tableCpt = R.hooksComponentWithModule thisModule "table" cpt
cpt {container, syncResetButton, colNames, wrapColElts, totalRecords, rows, params} _ = do
cpt {container, syncResetButton, colNames, wrapColElts, totalRecords, rows, params} _ = do
let
let
state = paramsState $ fst params
state = paramsState $ fst params
...
@@ -196,10 +194,10 @@ type SizeDDProps =
...
@@ -196,10 +194,10 @@ type SizeDDProps =
sizeDD :: Record SizeDDProps -> R.Element
sizeDD :: Record SizeDDProps -> R.Element
sizeDD p = R.createElement sizeDDCpt p []
sizeDD p = R.createElement sizeDDCpt p []
sizeDDCpt :: R.Component SizeDDProps
sizeDDCpt = R.hooksComponentWithModule thisModule "sizeDD" cpt
where
where
sizeDDCpt :: R.Component SizeDDProps
sizeDDCpt = R.hooksComponentWithModule thisModule "sizeDD" cpt
cpt {params: params /\ setParams} _ = do
cpt {params: params /\ setParams} _ = do
pure $ H.span {} [
pure $ H.span {} [
R2.select { className, defaultValue: show pageSize, on: {change} } sizes
R2.select { className, defaultValue: show pageSize, on: {change} } sizes
...
@@ -223,8 +221,12 @@ textDescription currPage pageSize totalRecords =
...
@@ -223,8 +221,12 @@ textDescription currPage pageSize totalRecords =
end = if end' > totalRecords then totalRecords else end'
end = if end' > totalRecords then totalRecords else end'
msg = "Showing " <> show start <> " to " <> show end <> " of " <> show totalRecords
msg = "Showing " <> show start <> " to " <> show end <> " of " <> show totalRecords
changePage :: Page -> R.State Params -> Effect Unit
changePage page (_ /\ setParams) =
setParams $ \p -> stateParams $ (paramsState p) { page = page }
pagination :: R.State Params -> Int -> R.Element
pagination :: R.State Params -> Int -> R.Element
pagination (params /\ setParams) tp =
pagination
p@
(params /\ setParams) tp =
H.span {} $
H.span {} $
[ H.text " ", prev, first, ldots]
[ H.text " ", prev, first, ldots]
<>
<>
...
@@ -237,7 +239,6 @@ pagination (params /\ setParams) tp =
...
@@ -237,7 +239,6 @@ pagination (params /\ setParams) tp =
[ rdots, last, next ]
[ rdots, last, next ]
where
where
{page} = paramsState params
{page} = paramsState params
changePage page = setParams $ \p -> stateParams $ (paramsState p) { page = page }
prev = if page == 1 then
prev = if page == 1 then
H.text " Prev. "
H.text " Prev. "
else
else
...
@@ -269,7 +270,7 @@ pagination (params /\ setParams) tp =
...
@@ -269,7 +270,7 @@ pagination (params /\ setParams) tp =
changePageLink i s =
changePageLink i s =
H.span {}
H.span {}
[ H.text " "
[ H.text " "
, effectLink (changePage i) s
, effectLink (changePage i
p
) s
, H.text " "
, H.text " "
]
]
...
...
src/Gargantext/Ends.purs
View file @
e7d216fa
...
@@ -222,6 +222,7 @@ sessionPath (R.ChartHash { chartType, listId, tabType } i) =
...
@@ -222,6 +222,7 @@ sessionPath (R.ChartHash { chartType, listId, tabType } i) =
<> defaultListAddMaybe listId
<> defaultListAddMaybe listId
-- sessionPath (R.NodeAPI (NodeContact s a i) i) = sessionPath $ "annuaire/" <> show a <> "/contact/" <> show i
-- sessionPath (R.NodeAPI (NodeContact s a i) i) = sessionPath $ "annuaire/" <> show a <> "/contact/" <> show i
------- misc routing stuff
------- misc routing stuff
defaultList :: Int -> String
defaultList :: Int -> String
...
...
src/Gargantext/Routes.purs
View file @
e7d216fa
...
@@ -5,39 +5,36 @@ import Prelude
...
@@ -5,39 +5,36 @@ import Prelude
import Data.Maybe (Maybe(..))
import Data.Maybe (Maybe(..))
import Gargantext.Types (ChartOpts, ChartType, CorpusMetricOpts, CTabNgramType, Id, Limit,
import Gargantext.Types (ChartOpts, ChartType, CorpusMetricOpts, CTabNgramType, Id, Limit,
ListId, NgramsGetOpts, NgramsGetTableAllOpts, NodeType,
ListId,
DocId, ContactId,
NgramsGetOpts, NgramsGetTableAllOpts, NodeType,
Offset, OrderBy, SearchOpts, SessionId, TabSubType, TabType, TermList)
Offset, OrderBy, SearchOpts, SessionId, TabSubType, TabType, TermList)
import Gargantext.Types as GT
import Gargantext.Types as GT
data AppRoute
data AppRoute
= Annuaire SessionId Int
= Annuaire
SessionId Int
| ContactPage SessionId Int Int
| ContactPage SessionId Int Int
| Corpus SessionId Int
| Corpus
SessionId Int
| CorpusDocument SessionId Int Int Int
| CorpusDocument SessionId Int Int Int
| Dashboard SessionId Int
| Dashboard SessionId Int
| Document SessionId Int Int
| Document SessionId Int Int
| Folder SessionId Int
| Folder
SessionId Int
| FolderPrivate SessionId Int
| FolderPrivate
SessionId Int
| FolderPublic SessionId Int
| FolderPublic
SessionId Int
| FolderShared SessionId Int
| FolderShared
SessionId Int
| Home
| Home
| Lists SessionId Int
| Lists SessionId Int
| Login
| Login
| PGraphExplorer SessionId Int
| PGraphExplorer
SessionId Int
| RouteFile SessionId Int
| RouteFile SessionId Int
| RouteFrameCalc SessionId Int
| RouteFrameCalc SessionId Int
| RouteFrameCode SessionId Int
| RouteFrameCode SessionId Int
| RouteFrameWrite SessionId Int
| RouteFrameWrite SessionId Int
| Team SessionId Int
| Team
SessionId Int
| Texts SessionId Int
| Texts
SessionId Int
| UserPage SessionId Int
| UserPage
SessionId Int
derive instance eqAppRoute :: Eq AppRoute
derive instance eqAppRoute :: Eq AppRoute
type AnnuaireId = Int
type ContactId = Int
data SessionRoute
data SessionRoute
= Tab TabType (Maybe Id)
= Tab TabType (Maybe Id)
| Children NodeType Offset Limit (Maybe OrderBy) (Maybe Id)
| Children NodeType Offset Limit (Maybe OrderBy) (Maybe Id)
...
@@ -53,12 +50,13 @@ data SessionRoute
...
@@ -53,12 +50,13 @@ data SessionRoute
| TreeFirstLevel (Maybe Id) String
| TreeFirstLevel (Maybe Id) String
| GraphAPI Id String
| GraphAPI Id String
| ListsRoute ListId
| ListsRoute ListId
| ListDocument (Maybe ListId) (Maybe Id)
| ListDocument (Maybe ListId) (Maybe
Doc
Id)
| Search SearchOpts (Maybe Id)
| Search SearchOpts (Maybe Id)
| CorpusMetrics CorpusMetricOpts (Maybe Id)
| CorpusMetrics CorpusMetricOpts (Maybe Id)
| CorpusMetricsHash { listId :: ListId, tabType :: TabType } (Maybe Id)
| CorpusMetricsHash { listId :: ListId, tabType :: TabType } (Maybe Id)
| Chart ChartOpts (Maybe Id)
| Chart ChartOpts (Maybe Id)
| ChartHash { chartType :: ChartType, listId :: Maybe ListId, tabType :: TabType } (Maybe Id)
| ChartHash { chartType :: ChartType, listId :: Maybe ListId, tabType :: TabType } (Maybe Id)
-- | AnnuaireContact AnnuaireId DocId
instance showAppRoute :: Show AppRoute where
instance showAppRoute :: Show AppRoute where
show Home = "Home"
show Home = "Home"
...
...
src/Gargantext/Types.purs
View file @
e7d216fa
...
@@ -333,8 +333,11 @@ nodeTypePath (NodePublic nt) = nodeTypePath nt
...
@@ -333,8 +333,11 @@ nodeTypePath (NodePublic nt) = nodeTypePath nt
nodeTypePath NodeFile = "file"
nodeTypePath NodeFile = "file"
------------------------------------------------------------
------------------------------------------------------------
type CorpusId = Int
type ListId = Int
type DocId = Int
type ListId = Int
type AnnuaireId = Int
type ContactId = Int
data ScoreType = Occurrences
data ScoreType = Occurrences
...
...
src/sass/_annotation.sass
0 → 100644
View file @
e7d216fa
// $annotation-candidate-color: #aaa
// $annotation-graph-color: #0f0
// $annotation-stop-color: #f00
// Copied from bootstrap's bg-warning, bg-success, bg-danger:
$annotation-candidate-color
:
#FF9800
$annotation-graph-color
:
#43A047
$annotation-stop-color
:
#E53935
@mixin
lg2
(
$color1
,
$color2
)
background-image
:
linear-gradient
(
rgba
(
$color1
,
0
.5
)
,
rgba
(
$color1
,
0
.5
))
,
linear-gradient
(
rgba
(
$color2
,
0
.5
)
,
rgba
(
$color2
,
0
.5
))
@mixin
lg3
(
$color1
,
$color2
,
$color3
)
background-image
:
linear-gradient
(
rgba
(
$color1
,
0
.34
)
,
rgba
(
$color1
,
0
.34
))
,
linear-gradient
(
rgba
(
$color2
,
0
.33
)
,
rgba
(
$color2
,
0
.33
))
,
linear-gradient
(
rgba
(
$color3
,
0
.33
)
,
rgba
(
$color3
,
0
.33
))
.annotation-run
cursor
:
pointer
&
.candidate-term.graph-term.stop-term
color
:
#000
@include
lg3
(
$annotation-candidate-color
,
$annotation-graph-color
,
$annotation-stop-color
)
&
.candidate-term.graph-term
color
:
#000
@include
lg2
(
$annotation-candidate-color
,
$annotation-graph-color
)
&
.candidate-term.stop-term
color
:
#000
@include
lg2
(
$annotation-candidate-color
,
$annotation-stop-color
)
&
.graph-term.stop-term
color
:
#000
@include
lg2
(
$annotation-graph-color
,
$annotation-stop-color
)
&
.candidate-term
color
:
#000
background-color
:
$annotation-candidate-color
&
.graph-term
color
:
#000
background-color
:
$annotation-graph-color
&
.stop-term
color
:
#000
background-color
:
$annotation-stop-color
.context-menu
.candidate-term
color
:
#000
background-color
:
$annotation-candidate-color
.graph-term
color
:
#000
background-color
:
$annotation-graph-color
.stop-term
color
:
#000
background-color
:
$annotation-stop-color
src/sass/_code_editor.sass
View file @
e7d216fa
...
@@ -20,24 +20,16 @@
...
@@ -20,24 +20,16 @@
word-break
:
keep-all
word-break
:
keep-all
.code-editor-heading
.code-editor-heading
display
:
flex
//justify-content: space-between
.renameable
.renameable
flex-grow
:
2
flex-grow
:
2
.text
.text
padding-right
:
10px
padding-right
:
10px
.buttons-right
/*
.buttons-right
display
:
flex
/*
display: flex
justify-content
:
flex-end
/*
justify-content: flex-end
.code-editor
.code-editor
.toolbar
display
:
flex
justify-content
:
flex-start
width
:
100%
.editor
.editor
display
:
flex
width
:
100%
.code-area
.code-area
flex-grow
:
1
flex-grow
:
1
max-height
:
200px
max-height
:
200px
...
...
src/sass/_styles.sass
View file @
e7d216fa
...
@@ -30,6 +30,7 @@
...
@@ -30,6 +30,7 @@
.table
.table
tr
tr
td
td
color
:
#005a9a
ff
.active
.active
font-weight
:
bold
font-weight
:
bold
text-decoration
:
underline
text-decoration
:
underline
...
@@ -48,3 +49,8 @@
...
@@ -48,3 +49,8 @@
.search-bar
.search-bar
margin
:
10px
margin
:
10px
.body
ul
li
color
:
#005a9a
ff
src/sass/_tree.sass
View file @
e7d216fa
...
@@ -5,6 +5,7 @@ li
...
@@ -5,6 +5,7 @@ li
.leaf
.leaf
display
:
flex
display
:
flex
flex-direction
:
row
flex-direction
:
row
color
:
#005a9a
ff
.folder-icon
.folder-icon
padding
:
0
2
0
2
padding
:
0
2
0
2
...
@@ -105,7 +106,6 @@ li
...
@@ -105,7 +106,6 @@ li
margin-top
:
1px
margin-top
:
1px
&
.node-type-valid
&
.node-type-valid
.text
.text
color
:
blue
text-decoration
:
underline
text-decoration
:
underline
// based on https://codeburst.io/how-to-pure-css-pie-charts-w-css-variables-38287aea161e
// based on https://codeburst.io/how-to-pure-css-pie-charts-w-css-variables-38287aea161e
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment