Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
F
frontend
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
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
vicotor
frontend
Commits
9201965e
Commit
9201965e
authored
Feb 03, 2023
by
tom
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
drag-and-drop folders
parent
b1f8e17a
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
66 additions
and
3 deletions
+66
-3
tsconfig.json
tsconfig.json
+1
-1
ContractVerificationFieldSources.tsx
...tVerification/fields/ContractVerificationFieldSources.tsx
+1
-1
DragAndDropArea.tsx
ui/shared/forms/DragAndDropArea.tsx
+5
-1
files.ts
ui/shared/forms/utils/files.ts
+59
-0
No files found.
tsconfig.json
View file @
9201965e
{
{
"compilerOptions"
:
{
"compilerOptions"
:
{
"target"
:
"es
5
"
,
"target"
:
"es
6
"
,
"lib"
:
[
"dom"
,
"dom.iterable"
,
"esnext"
],
"lib"
:
[
"dom"
,
"dom.iterable"
,
"esnext"
],
"allowJs"
:
true
,
"allowJs"
:
true
,
"skipLibCheck"
:
true
,
"skipLibCheck"
:
true
,
...
...
ui/contractVerification/fields/ContractVerificationFieldSources.tsx
View file @
9201965e
...
@@ -41,7 +41,7 @@ const ContractVerificationFieldSources = ({ accept, multiple, title, className,
...
@@ -41,7 +41,7 @@ const ContractVerificationFieldSources = ({ accept, multiple, title, className,
<
Box
display=
"grid"
gridTemplateColumns=
{
{
base
:
'
1fr
'
,
lg
:
'
1fr 1fr
'
}
}
columnGap=
{
3
}
rowGap=
{
3
}
>
<
Box
display=
"grid"
gridTemplateColumns=
{
{
base
:
'
1fr
'
,
lg
:
'
1fr 1fr
'
}
}
columnGap=
{
3
}
rowGap=
{
3
}
>
{
files
.
map
((
file
,
index
)
=>
(
{
files
.
map
((
file
,
index
)
=>
(
<
FileSnippet
<
FileSnippet
key=
{
file
.
name
+
file
.
lastModified
}
key=
{
file
.
name
+
file
.
lastModified
+
index
}
file=
{
file
}
file=
{
file
}
maxW=
"initial"
maxW=
"initial"
onRemove=
{
handleFileRemove
}
onRemove=
{
handleFileRemove
}
...
...
ui/shared/forms/DragAndDropArea.tsx
View file @
9201965e
...
@@ -2,6 +2,8 @@ import { Box } from '@chakra-ui/react';
...
@@ -2,6 +2,8 @@ import { Box } from '@chakra-ui/react';
import
type
{
DragEvent
}
from
'
react
'
;
import
type
{
DragEvent
}
from
'
react
'
;
import
React
from
'
react
'
;
import
React
from
'
react
'
;
import
{
getAllFileEntries
,
convertFileEntryToFile
}
from
'
./utils/files
'
;
interface
Props
{
interface
Props
{
onDrop
:
(
files
:
Array
<
File
>
)
=>
void
;
onDrop
:
(
files
:
Array
<
File
>
)
=>
void
;
}
}
...
@@ -11,7 +13,9 @@ const DragAndDropArea = ({ onDrop }: Props) => {
...
@@ -11,7 +13,9 @@ const DragAndDropArea = ({ onDrop }: Props) => {
const
handleDrop
=
React
.
useCallback
(
async
(
event
:
DragEvent
<
HTMLDivElement
>
)
=>
{
const
handleDrop
=
React
.
useCallback
(
async
(
event
:
DragEvent
<
HTMLDivElement
>
)
=>
{
event
.
preventDefault
();
event
.
preventDefault
();
const
files
=
Array
.
from
(
event
.
dataTransfer
.
files
);
const
fileEntries
=
await
getAllFileEntries
(
event
.
dataTransfer
.
items
);
const
files
=
await
Promise
.
all
(
fileEntries
.
map
(
convertFileEntryToFile
));
onDrop
(
files
);
onDrop
(
files
);
setIsDragOver
(
false
);
setIsDragOver
(
false
);
...
...
ui/shared/forms/utils/files.ts
0 → 100644
View file @
9201965e
// Function to get all files in drop directory
export
async
function
getAllFileEntries
(
dataTransferItemList
:
DataTransferItemList
):
Promise
<
Array
<
FileSystemFileEntry
>>
{
const
fileEntries
:
Array
<
FileSystemFileEntry
>
=
[];
// Use BFS to traverse entire directory/file structure
const
queue
:
Array
<
FileSystemEntry
|
FileSystemDirectoryEntry
|
null
>
=
[];
// Unfortunately dataTransferItemList is not iterable i.e. no forEach
for
(
let
i
=
0
;
i
<
dataTransferItemList
.
length
;
i
++
)
{
// Note webkitGetAsEntry a non-standard feature and may change
// Usage is necessary for handling directories
// + typescript types are kinda wrong - https://developer.mozilla.org/en-US/docs/Web/API/DataTransferItem/webkitGetAsEntry
const
item
=
dataTransferItemList
[
i
].
webkitGetAsEntry
();
queue
.
push
(
item
);
}
while
(
queue
.
length
>
0
)
{
const
entry
=
queue
.
shift
();
if
(
entry
?.
isFile
)
{
fileEntries
.
push
(
entry
as
FileSystemFileEntry
);
}
else
if
(
entry
?.
isDirectory
&&
'
createReader
'
in
entry
)
{
queue
.
push
(...
await
readAllDirectoryEntries
(
entry
.
createReader
()));
}
}
return
fileEntries
;
}
// Get all the entries (files or sub-directories) in a directory
// by calling readEntries until it returns empty array
async
function
readAllDirectoryEntries
(
directoryReader
:
DirectoryReader
)
{
const
entries
:
Array
<
FileSystemEntry
>
=
[];
let
readEntries
=
await
readEntriesPromise
(
directoryReader
);
while
(
readEntries
&&
readEntries
.
length
>
0
)
{
entries
.
push
(...
readEntries
);
readEntries
=
await
readEntriesPromise
(
directoryReader
);
}
return
entries
;
}
// Wrap readEntries in a promise to make working with readEntries easier
// readEntries will return only some of the entries in a directory
// e.g. Chrome returns at most 100 entries at a time
async
function
readEntriesPromise
(
directoryReader
:
DirectoryReader
):
Promise
<
Array
<
FileSystemEntry
>
|
undefined
>
{
try
{
return
await
new
Promise
((
resolve
,
reject
)
=>
{
directoryReader
.
readEntries
(
resolve
,
reject
);
});
}
catch
(
err
)
{}
}
export
function
convertFileEntryToFile
(
entry
:
FileSystemFileEntry
):
Promise
<
File
>
{
return
new
Promise
((
resolve
)
=>
{
entry
.
file
(
async
(
file
:
File
)
=>
{
// const newFile = new File([ file ], entry.fullPath, { lastModified: file.lastModified, type: file.type });
resolve
(
file
);
});
});
}
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