Skip to content
GitLab
Menu
Projects
Groups
Snippets
/
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
dotgreg
tiro-notes
Commits
e4f4bd79
Commit
e4f4bd79
authored
May 24, 2022
by
greg@1m
Browse files
wip on doc generation + bug fix
parent
efcf7026
Changes
11
Hide whitespace changes
Inline
Side-by-side
client/src/components/TreeView.Component.tsx
View file @
e4f4bd79
...
...
@@ -12,50 +12,50 @@ export type onFolderClickedFn = (folderPath: string) => void
export
type
onFolderDragStartFn
=
(
folder
:
iFolder
)
=>
void
export
type
onFolderDropFn
=
(
folder
:
iFolder
)
=>
void
export
type
onFolderMenuActionFn
=
(
action
:
'
rename
'
|
'
create
'
|
'
moveToTrash
'
|
'
delete
'
,
folder
:
iFolder
,
newName
?:
string
action
:
'
rename
'
|
'
create
'
|
'
moveToTrash
'
|
'
delete
'
,
folder
:
iFolder
,
newName
?:
string
)
=>
void
export
const
TreeView
=
(
p
:
{
folder
:
iFolder
,
current
:
string
,
onFolderMenuAction
:
onFolderMenuActionFn
onFolderClicked
:
onFolderClickedFn
onFolderOpen
:
onFolderClickedFn
onFolderClose
:
onFolderClickedFn
onFolderDragStart
:
onFolderDragStartFn
onFolderDragEnd
:
()
=>
void
onFolderDrop
:
onFolderDropFn
})
=>
{
const
api
=
useContext
(
ClientApiContext
);
const
fApi
=
api
?
api
.
ui
.
browser
.
folders
:
null
return
(
<
div
className
=
"folder-tree-view-component"
>
<
h3
className
=
'subtitle'
>
{
strings
.
folders
}
</
h3
>
<
FolderView
folder
:
iFolder
,
current
:
string
,
onFolderMenuAction
:
onFolderMenuActionFn
onFolderClicked
:
onFolderClickedFn
onFolderOpen
:
onFolderClickedFn
onFolderClose
:
onFolderClickedFn
onFolderDragStart
:
onFolderDragStartFn
onFolderDragEnd
:
()
=>
void
onFolderDrop
:
onFolderDropFn
})
=>
{
const
api
=
useContext
(
ClientApiContext
);
const
fApi
=
api
?
api
.
ui
.
browser
.
folders
:
null
return
(
<
div
className
=
"folder-tree-view-component"
>
<
h3
className
=
'subtitle'
>
{
strings
.
folders
}
</
h3
>
<
FolderView
folder
=
{
p
.
folder
}
current
=
{
p
.
current
}
onFolderClicked
=
{
p
.
onFolderClicked
}
onFolderMenuAction
=
{
p
.
onFolderMenuAction
}
onFolderOpen
=
{
folderPath
=>
{
fApi
&&
fApi
.
open
.
add
(
folderPath
)
p
.
onFolderOpen
(
folderPath
)
}
}
fApi
&&
fApi
.
open
.
add
(
folderPath
)
p
.
onFolderOpen
(
folderPath
)
}
}
onFolderClose
=
{
folderPath
=>
{
fApi
&&
fApi
.
open
.
remove
(
folderPath
)
p
.
onFolderClose
(
folderPath
)
}
}
fApi
&&
fApi
.
open
.
remove
(
folderPath
)
p
.
onFolderClose
(
folderPath
)
}
}
onFolderDragStart
=
{
p
.
onFolderDragStart
}
onFolderDragEnd
=
{
p
.
onFolderDragEnd
}
onFolderDrop
=
{
p
.
onFolderDrop
}
/>
</
div
>
)
/>
</
div
>
)
}
...
...
@@ -66,226 +66,239 @@ export const TreeView = (p: {
export
const
FolderView
=
(
p
:
{
folder
:
iFolder
,
current
:
string
,
onFolderMenuAction
:
onFolderMenuActionFn
onFolderClicked
:
onFolderClickedFn
onFolderOpen
:
onFolderClickedFn
onFolderClose
:
onFolderClickedFn
onFolderDragStart
:
onFolderDragStartFn
onFolderDragEnd
:
()
=>
void
onFolderDrop
:
onFolderDropFn
})
=>
{
const
api
=
useContext
(
ClientApiContext
);
const
[
isOpen
,
setIsOpen
]
=
useLocalStorage
(
`treeview-
${(
p
.
folder
.
key
===
'
/
'
||
p
.
folder
.
key
===
''
)
?
'
root
'
:
p
.
folder
.
key
}
`
,
false
)
const
[
isMenuOpened
,
setIsMenuOpened
]
=
useState
(
false
)
const
isCurrentFolder
=
areSamePaths
(
p
.
current
,
p
.
folder
.
key
)
return
(
<
li
className
=
{
`folder-wrapper
${
isCurrentFolder
?
'
current
'
:
''
}
`
}
draggable
=
{
true
}
onDrop
=
{
(
e
)
=>
{
if
(
!
p
.
folder
.
key
)
return
p
.
onFolderDrop
(
p
.
folder
)
e
.
stopPropagation
()
}
}
onDragStart
=
{
(
e
)
=>
{
if
(
!
p
.
folder
.
key
)
return
p
.
onFolderDragStart
(
p
.
folder
)
e
.
stopPropagation
()
}
}
onDragEnd
=
{
()
=>
{
if
(
!
p
.
folder
.
key
)
return
p
.
onFolderDragEnd
()
}
}
onMouseLeave
=
{
()
=>
{
isMenuOpened
&&
setIsMenuOpened
(
false
)
}
}
>
<
div
className
=
"folder-title"
>
folder
:
iFolder
,
current
:
string
,
onFolderMenuAction
:
onFolderMenuActionFn
onFolderClicked
:
onFolderClickedFn
onFolderOpen
:
onFolderClickedFn
onFolderClose
:
onFolderClickedFn
onFolderDragStart
:
onFolderDragStartFn
onFolderDragEnd
:
()
=>
void
onFolderDrop
:
onFolderDropFn
})
=>
{
const
api
=
useContext
(
ClientApiContext
);
const
[
isOpen
,
setIsOpen
]
=
useLocalStorage
(
`treeview-
${(
p
.
folder
.
key
===
'
/
'
||
p
.
folder
.
key
===
''
)
?
'
root
'
:
p
.
folder
.
key
}
`
,
false
)
const
[
isMenuOpened
,
setIsMenuOpened
]
=
useState
(
false
)
const
isCurrentFolder
=
areSamePaths
(
p
.
current
,
p
.
folder
.
key
)
return
(
<
li
className
=
{
`folder-wrapper
${
isCurrentFolder
?
'
current
'
:
''
}
`
}
draggable
=
{
true
}
onDrop
=
{
(
e
)
=>
{
if
(
!
p
.
folder
.
key
)
return
p
.
onFolderDrop
(
p
.
folder
)
e
.
stopPropagation
()
}
}
onDragStart
=
{
(
e
)
=>
{
if
(
!
p
.
folder
.
key
)
return
p
.
onFolderDragStart
(
p
.
folder
)
e
.
stopPropagation
()
}
}
onDragEnd
=
{
()
=>
{
if
(
!
p
.
folder
.
key
)
return
p
.
onFolderDragEnd
()
}
}
onMouseLeave
=
{
()
=>
{
isMenuOpened
&&
setIsMenuOpened
(
false
)
}
}
>
<
div
className
=
"folder-title"
>
<
span
className
=
"icon"
onClick
=
{
e
=>
{
isOpen
?
p
.
onFolderClose
(
p
.
folder
.
key
)
:
p
.
onFolderOpen
(
p
.
folder
.
key
)
setIsOpen
(
!
isOpen
)
}
}
>
{
isOpen
?
p
.
onFolderClose
(
p
.
folder
.
key
)
:
p
.
onFolderOpen
(
p
.
folder
.
key
)
setIsOpen
(
!
isOpen
)
}
}
>
{
p
.
folder
.
hasChildren
&&
<
Icon
name
=
{
isOpen
?
'
faCaretDown
'
:
'
faCaretRight
'
}
color
=
{
cssVars
.
colors
.
main
}
name
=
{
isOpen
?
'
faCaretDown
'
:
'
faCaretRight
'
}
color
=
{
cssVars
.
colors
.
main
}
/>
}
}
</
span
>
<
span
className
=
"title"
onClick
=
{
e
=>
{
p
.
onFolderClicked
(
p
.
folder
.
key
)
}
}
>
{
p
.
folder
.
title
}
{
p
.
folder
.
title
}
</
span
>
<
span
onClick
=
{
()
=>
{
// alert(p.folder.title)
setIsMenuOpened
(
!
isMenuOpened
)
}
}
className
=
"context-menu-wrapper"
>
<
Icon
name
=
"faEllipsisH"
color
=
{
cssVars
.
colors
.
l1
.
font
}
/>
{
isMenuOpened
&&
<
div
className
=
"context-menu"
>
<
ul
>
<
li
onClick
=
{
()
=>
{
if
(
p
.
folder
.
path
===
''
)
return
setIsMenuOpened
(
false
)
const
newFolderName
=
prompt
(
`
${
strings
.
renameFolderPrompt
}
`
,
p
.
folder
.
title
);
if
(
newFolderName
&&
newFolderName
!==
''
&&
newFolderName
!==
p
.
folder
.
title
)
{
p
.
onFolderMenuAction
(
'
rename
'
,
p
.
folder
,
newFolderName
)
}
setIsMenuOpened
(
false
)
}
}
>
{
strings
.
renameFolder
}
</
li
>
<
li
onClick
=
{
()
=>
{
if
(
p
.
folder
.
path
===
''
)
return
setIsMenuOpened
(
false
)
const
createdFolderName
=
prompt
(
`
${
strings
.
createFolderPrompt
}
${
p
.
folder
.
path
}
`
,
''
);
if
(
createdFolderName
&&
createdFolderName
!==
''
)
p
.
onFolderMenuAction
(
'
create
'
,
p
.
folder
,
createdFolderName
)
setIsMenuOpened
(
false
)
}
}
>
{
strings
.
createFolder
}
</
li
>
{
p
.
folder
.
path
.
indexOf
(
'
.tiro/.trash
'
)
===
-
1
&&
<
li
onClick
=
{
()
=>
{
if
(
!
api
)
return
if
(
p
.
folder
.
path
===
''
)
return
setIsMenuOpened
(
false
)
setIsMenuOpened
(
false
)
api
.
popup
.
confirm
(
`
${
strings
.
moveToTrash
}
"
${
p
.
folder
.
path
}
"?`
,
()
=>
{
p
.
onFolderMenuAction
(
'
moveToTrash
'
,
p
.
folder
)
});
}
}
>
{
strings
.
moveToTrash
}
</
li
>
}
{
p
.
folder
.
path
.
indexOf
(
'
.tiro/.trash
'
)
!==
-
1
&&
<
li
onClick
=
{
()
=>
{
if
(
!
api
)
return
if
(
p
.
folder
.
path
===
''
)
return
setIsMenuOpened
(
false
)
setIsMenuOpened
(
false
)
api
.
popup
.
confirm
(
`
${
strings
.
deleteFolderPrompt
}
"
${
p
.
folder
.
path
}
"?`
,
()
=>
{
p
.
onFolderMenuAction
(
'
delete
'
,
p
.
folder
)
});
}
}
>
{
strings
.
deleteFolder
}
</
li
>
}
</
ul
>
</
div
>
}
onClick
=
{
()
=>
{
// alert(p.folder.title)
setIsMenuOpened
(
!
isMenuOpened
)
}
}
className
=
"context-menu-wrapper"
>
<
Icon
name
=
"faEllipsisH"
color
=
{
cssVars
.
colors
.
l1
.
font
}
/>
{
isMenuOpened
&&
<
div
className
=
"context-menu"
>
<
ul
>
<
li
onClick
=
{
()
=>
{
if
(
p
.
folder
.
path
===
''
)
return
setIsMenuOpened
(
false
)
const
newFolderName
=
prompt
(
`
${
strings
.
renameFolderPrompt
}
`
,
p
.
folder
.
title
);
if
(
newFolderName
&&
newFolderName
!==
''
&&
newFolderName
!==
p
.
folder
.
title
)
{
p
.
onFolderMenuAction
(
'
rename
'
,
p
.
folder
,
newFolderName
)
}
setIsMenuOpened
(
false
)
}
}
>
{
strings
.
renameFolder
}
</
li
>
<
li
onClick
=
{
()
=>
{
if
(
p
.
folder
.
path
===
''
)
return
setIsMenuOpened
(
false
)
const
createdFolderName
=
prompt
(
`
${
strings
.
createFolderPrompt
}
${
p
.
folder
.
path
}
`
,
''
);
if
(
createdFolderName
&&
createdFolderName
!==
''
)
p
.
onFolderMenuAction
(
'
create
'
,
p
.
folder
,
createdFolderName
)
setIsMenuOpened
(
false
)
}
}
>
{
strings
.
createFolder
}
</
li
>
{
p
.
folder
.
path
.
indexOf
(
'
.tiro/.trash
'
)
===
-
1
&&
<
li
onClick
=
{
()
=>
{
if
(
!
api
)
return
if
(
p
.
folder
.
path
===
''
)
return
setIsMenuOpened
(
false
)
setIsMenuOpened
(
false
)
api
.
popup
.
confirm
(
`
${
strings
.
moveToTrash
}
"
${
p
.
folder
.
path
}
"?`
,
()
=>
{
p
.
onFolderMenuAction
(
'
moveToTrash
'
,
p
.
folder
)
});
}
}
>
{
strings
.
moveToTrash
}
</
li
>
}
{
p
.
folder
.
path
.
indexOf
(
'
.tiro/.trash
'
)
!==
-
1
&&
<
li
onClick
=
{
()
=>
{
if
(
!
api
)
return
if
(
p
.
folder
.
path
===
''
)
return
setIsMenuOpened
(
false
)
setIsMenuOpened
(
false
)
api
.
popup
.
confirm
(
`
${
strings
.
deleteFolderPrompt
}
"
${
p
.
folder
.
path
}
"?`
,
()
=>
{
p
.
onFolderMenuAction
(
'
delete
'
,
p
.
folder
)
});
}
}
>
{
strings
.
deleteFolder
}
</
li
>
}
</
ul
>
</
div
>
}
</
span
>
</
div
>
{
isOpen
&&
<
ul
className
=
"folder-children"
>
{
p
.
folder
.
children
&&
p
.
folder
.
children
.
map
((
child
,
key
)
=>
<
FolderView
key
=
{
key
}
folder
=
{
child
}
current
=
{
p
.
current
}
onFolderOpen
=
{
p
.
onFolderOpen
}
onFolderMenuAction
=
{
p
.
onFolderMenuAction
}
onFolderClose
=
{
p
.
onFolderClose
}
onFolderClicked
=
{
p
.
onFolderClicked
}
onFolderDragStart
=
{
p
.
onFolderDragStart
}
onFolderDragEnd
=
{
p
.
onFolderDragEnd
}
onFolderDrop
=
{
p
.
onFolderDrop
}
/>
)
}
</
ul
>
}
</
li
>
)
</
div
>
{
isOpen
&&
<
ul
className
=
"folder-children"
>
{
p
.
folder
.
children
&&
p
.
folder
.
children
.
map
((
child
,
key
)
=>
<
FolderView
key
=
{
key
}
folder
=
{
child
}
current
=
{
p
.
current
}
onFolderOpen
=
{
p
.
onFolderOpen
}
onFolderMenuAction
=
{
p
.
onFolderMenuAction
}
onFolderClose
=
{
p
.
onFolderClose
}
onFolderClicked
=
{
p
.
onFolderClicked
}
onFolderDragStart
=
{
p
.
onFolderDragStart
}
onFolderDragEnd
=
{
p
.
onFolderDragEnd
}
onFolderDrop
=
{
p
.
onFolderDrop
}
/>
)
}
</
ul
>
}
</
li
>
)
}
export
const
l1Subtitle
=
`
.title {
.title {
padding-left: 4px;
cursor: pointer;
padding: 0px 20px 0px 0px;
}
}
`
export
const
folderTreeCss
=
()
=>
`
.folder-tree-view-component {
padding:
${
cssVars
.
sizes
.
block
}
px;
padding-right: 0px;
margin: 0px 0px 100px 0px;
width: calc(100% -
${
cssVars
.
sizes
.
block
*
(
isA
(
'
desktop
'
)
&&
!
isIpad
()
?
1
:
2
)}
px);
ul.folder-children {
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 10px;
}
li.folder-wrapper {
position: relative;
list-style: none;
font-size: 13px;
font-weight: 600;
cursor: pointer;
&.device-view-mobile {
.folder-tree-view-component {
li.folder-wrapper {
.context-menu-wrapper {
right: -18px;
.context-menu {
right: 5px;
}
}
}
}
}
.context-menu-wrapper {
position: absolute;
right: 0px;
top: -10px;
padding: 10px;
display:none;
.context-menu {
position: absolute;
right: 0px;
top: 15px;
background: white;
box-shadow: 0px 0px 4px rgb(0 0 0 / 10%);
color: black;
padding: 0px 0px;
width: 100px;
z-index: 10;
border-radius: 4px;
font-size: 10px;
ul {
list-style: none;
padding: 0px;
margin: 0px;
li {
padding: 4px 11px;
&:hover {
background:
${
cssVars
.
colors
.
main
}
;
}
}
}
}
}
.folder-title:hover > .context-menu-wrapper {
cursor:pointer;
display:block;
}
&.current > .folder-title {
color:
${
cssVars
.
colors
.
main
}
;
text-decoration: underline;
}
.folder-title {
padding: 1px;
position:relative;
padding-left: 20px;
.icon {
position: absolute;
left: 2px;
cursor: pointer;
padding: 1px;
top: 0px;
}
}
}
.folder-tree-view-component {
padding:
${
cssVars
.
sizes
.
block
}
px;
padding-right: 0px;
margin: 0px 0px 100px 0px;
width: calc(100% -
${
cssVars
.
sizes
.
block
*
(
isA
(
'
desktop
'
)
&&
!
isIpad
()
?
1
:
2
)}
px);
ul.folder-children {
margin: 0px 0px 0px 0px;
padding: 0px 0px 0px 10px;
}
li.folder-wrapper {
position: relative;
list-style: none;
font-size: 13px;
font-weight: 600;
cursor: pointer;
.context-menu-wrapper {
position: absolute;
right: 20px;
top: -10px;
padding: 10px;
display:none;
.context-menu {
position: absolute;
right: 0px;
top: 15px;
background: white;
box-shadow: 0px 0px 4px rgb(0 0 0 / 10%);
color: black;
padding: 0px 0px;
width: 100px;
z-index: 10;
border-radius: 4px;
font-size: 10px;
ul {
list-style: none;
padding: 0px;
margin: 0px;
li {
padding: 4px 11px;
&:hover {
background:
${
cssVars
.
colors
.
main
}
;
}
}
}
}
}
.folder-title:hover > .context-menu-wrapper {
cursor:pointer;
display:block;
}
&.current > .folder-title {
color:
${
cssVars
.
colors
.
main
}
;
text-decoration: underline;
}
.folder-title {
padding: 1px;
position:relative;
padding-left: 20px;
.icon {
position: absolute;
left: 2px;
cursor: pointer;
padding: 1px;
top: 0px;
}
}
}
}
`
client/src/components/dualView/PreviewArea.component.tsx
View file @
e4f4bd79
...
...
@@ -13,111 +13,111 @@ import { ContentBlock } from '../ContentBlock.component';
export
const
PreviewArea
=
(
p
:
{
windowId
:
string
file
:
iFile
posY
:
number
fileContent
:
string
onMaxYUpdate
:
(
maxY
:
number
)
=>
void
})
=>
{
windowId
:
string
file
:
iFile
posY
:
number
fileContent
:
string
onMaxYUpdate
:
(
maxY
:
number
)
=>
void
})
=>
{
const
api
=
useContext
(
ClientApiContext
);
const
api
=
useContext
(
ClientApiContext
);
const
previewAreaRefs
=
{
wrapper
:
useRef
<
HTMLDivElement
>
(
null
),
main
:
useRef
<
HTMLDivElement
>
(
null
),
}
const
previewAreaRefs
=
{
wrapper
:
useRef
<
HTMLDivElement
>
(
null
),
main
:
useRef
<
HTMLDivElement
>
(
null
),
}
let
currentFolderArr
=
p
.
file
.
path
.
split
(
'
/
'
)
currentFolderArr
.
pop
()
let
currentFolder
=
currentFolderArr
.
join
(
'
/
'
)
let
currentFolderArr
=
p
.
file
.
path
.
split
(
'
/
'
)
currentFolderArr
.
pop
()
let
currentFolder
=
currentFolderArr
.
join
(
'
/
'
)
useEffect
(()
=>
{
useEffect
(()
=>
{
setTimeout
(()
=>
{
p
.
onMaxYUpdate
(
calculateYMax
())
},
1000
)
},
[
p
.
fileContent
])
p
.
onMaxYUpdate
(
calculateYMax
())
},
1000
)
},
[
p
.
fileContent
])
const
calculateYMax
=
()
=>
{
const
d
=
previewAreaRefs
.
main
.
current
const
height
=
d
?.
clientHeight
const
max
=
height
||
3000
return
max
*
2
}
const
calculateYMax
=
()
=>
{
const
d
=
previewAreaRefs
.
main
.
current
const
height
=
d
?.
clientHeight
const
max
=
height
||
3000
return
max
*
2
}
const
calculateYPos
=
()
=>
{
const
max
=
calculateYMax
();
return
clamp
(
p
.
posY
,
0
,
max
)
}
const
calculateYPos
=
()
=>
{
const
max
=
calculateYMax
();
return
clamp
(
p
.
posY
,
0
,
max
)