Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
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
Vũ Hoàng Anh
canifa_note
Commits
04595a5f
Commit
04595a5f
authored
Sep 13, 2023
by
Steven
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
chore: update resource icons
parent
9a0ada67
Changes
8
Show whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
57 additions
and
237 deletions
+57
-237
ResourceListView.tsx
web/src/components/MemoEditor/ResourceListView.tsx
+7
-4
ResourceCard.tsx
web/src/components/ResourceCard.tsx
+7
-19
ResourceCover.tsx
web/src/components/ResourceCover.tsx
+0
-49
ResourceIcon.tsx
web/src/components/ResourceIcon.tsx
+40
-19
ResourceItem.tsx
web/src/components/ResourceItem.tsx
+0
-31
useEvent.ts
web/src/hooks/useEvent.ts
+0
-23
resource-cover.less
web/src/less/resource-cover.less
+0
-3
ResourcesDashboard.tsx
web/src/pages/ResourcesDashboard.tsx
+3
-89
No files found.
web/src/components/MemoEditor/ResourceListView.tsx
View file @
04595a5f
...
...
@@ -21,11 +21,14 @@ const ResourceListView = (props: Props) => {
return
(
<
div
key=
{
resource
.
id
}
className=
"max-w-full flex flex-row justify-start items-center flex-nowrap bg-gray-100 dark:bg-zinc-800 px-2 py-1 rounded text-gray-500"
className=
"max-w-full flex flex-row justify-start items-center flex-nowrap
gap-x-1
bg-gray-100 dark:bg-zinc-800 px-2 py-1 rounded text-gray-500"
>
<
ResourceIcon
resource=
{
resource
}
className=
"w-4 h-auto mr-1"
/>
<
span
className=
"text-sm max-w-xs truncate"
>
{
resource
.
filename
}
</
span
>
<
Icon
.
X
className=
"w-4 h-auto ml-1 cursor-pointer hover:opacity-80"
onClick=
{
()
=>
handleDeleteResource
(
resource
.
id
)
}
/>
<
ResourceIcon
resource=
{
resource
}
className=
"!w-4 !h-auto !opacity-100"
/>
<
span
className=
"text-sm max-w-[8rem] truncate"
>
{
resource
.
filename
}
</
span
>
<
Icon
.
X
className=
"w-4 h-auto cursor-pointer opacity-60 hover:opacity-100"
onClick=
{
()
=>
handleDeleteResource
(
resource
.
id
)
}
/>
</
div
>
);
})
}
...
...
web/src/components/ResourceCard.tsx
View file @
04595a5f
import
{
useState
}
from
"react"
;
import
{
getDateTimeString
}
from
"@/helpers/datetime"
;
import
Icon
from
"./Icon"
;
import
ResourceCover
from
"./ResourceCover"
;
import
ResourceIcon
from
"./ResourceIcon"
;
import
ResourceItemDropdown
from
"./ResourceItemDropdown"
;
import
"@/less/resource-card.less"
;
const
ResourceCard
=
({
resource
,
handleCheckClick
,
handleUncheckClick
}:
ResourceItemType
)
=>
{
const
[
isSelected
,
setIsSelected
]
=
useState
<
boolean
>
(
false
);
const
handleSelectBtnClick
=
()
=>
{
if
(
isSelected
)
{
handleUncheckClick
();
}
else
{
handleCheckClick
();
}
setIsSelected
(
!
isSelected
);
};
interface
Props
{
resource
:
Resource
;
}
const
ResourceCard
=
({
resource
}:
Props
)
=>
{
return
(
<
div
className=
"resource-card"
>
<
div
className=
"w-full p-2 flex flex-row justify-between items-center absolute top-0 left-0"
>
<
div
onClick=
{
()
=>
handleSelectBtnClick
()
}
>
{
isSelected
?
<
Icon
.
CheckCircle2
className=
"resource-checkbox !flex"
/>
:
<
Icon
.
Circle
className=
"resource-checkbox"
/>
}
</
div
>
<
div
className=
"w-full p-2 flex flex-row justify-end items-center absolute top-0 left-0"
>
<
div
className=
"more-action-btn"
>
<
ResourceItemDropdown
resource=
{
resource
}
/>
</
div
>
</
div
>
<
div
className=
"w-full flex flex-row justify-center items-center pb-2 pt-4 px-2"
>
<
Resource
Cover
resource=
{
resource
}
/>
<
Resource
Icon
resource=
{
resource
}
strokeWidth=
{
1
}
/>
</
div
>
<
div
className=
"w-full flex flex-col justify-start items-center px-1 select-none"
>
<
div
className=
"w-full text-base text-center text-ellipsis overflow-hidden line-clamp-3"
>
{
resource
.
filename
}
</
div
>
...
...
web/src/components/ResourceCover.tsx
deleted
100644 → 0
View file @
9a0ada67
import
React
from
"react"
;
import
{
getResourceType
,
getResourceUrl
}
from
"@/utils/resource"
;
import
Icon
from
"./Icon"
;
import
showPreviewImageDialog
from
"./PreviewImageDialog"
;
import
SquareDiv
from
"./kit/SquareDiv"
;
import
"@/less/resource-cover.less"
;
interface
ResourceCoverProps
{
resource
:
Resource
;
}
const
ResourceCover
=
({
resource
}:
ResourceCoverProps
)
=>
{
const
resourceType
=
getResourceType
(
resource
);
const
resourceUrl
=
getResourceUrl
(
resource
);
switch
(
resourceType
)
{
case
"image/*"
:
return
(
<
SquareDiv
className=
"h-20 w-20 flex items-center justify-center overflow-clip"
>
<
img
className=
"max-w-full max-h-full object-cover shadow"
src=
{
resource
.
externalLink
?
resourceUrl
:
resourceUrl
+
"?thumbnail=1"
}
onClick=
{
()
=>
showPreviewImageDialog
(
resourceUrl
)
}
/>
</
SquareDiv
>
);
case
"video/*"
:
return
<
Icon
.
FileVideo2
className=
"resource-cover"
/>;
case
"audio/*"
:
return
<
Icon
.
FileAudio
className=
"resource-cover"
/>;
case
"text/*"
:
return
<
Icon
.
FileText
className=
"resource-cover"
/>;
case
"application/epub+zip"
:
return
<
Icon
.
Book
className=
"resource-cover"
/>;
case
"application/pdf"
:
return
<
Icon
.
Book
className=
"resource-cover"
/>;
case
"application/msword"
:
return
<
Icon
.
FileEdit
className=
"resource-cover"
/>;
case
"application/msexcel"
:
return
<
Icon
.
SheetIcon
className=
"resource-cover"
/>;
case
"application/zip"
:
return
<
Icon
.
FileArchiveIcon
className=
"resource-cover"
/>;
case
"application/x-java-archive"
:
return
<
Icon
.
BinaryIcon
className=
"resource-cover"
/>;
default
:
return
<
Icon
.
File
className=
"resource-cover"
/>;
}
};
export
default
React
.
memo
(
ResourceCover
);
web/src/components/ResourceIcon.tsx
View file @
04595a5f
import
classNames
from
"classnames"
;
import
React
from
"react"
;
import
{
getResourceType
,
getResourceUrl
}
from
"@/utils/resource"
;
import
Icon
from
"./Icon"
;
import
showPreviewImageDialog
from
"./PreviewImageDialog"
;
import
SquareDiv
from
"./kit/SquareDiv"
;
interface
Props
{
className
:
string
;
resource
:
Resource
;
className
?:
string
;
strokeWidth
?:
number
;
}
const
ResourceIcon
=
(
props
:
Props
)
=>
{
const
{
className
,
resource
}
=
props
;
const
{
resource
}
=
props
;
const
resourceType
=
getResourceType
(
resource
);
const
resourceUrl
=
getResourceUrl
(
resource
);
const
className
=
classNames
(
"w-full h-auto"
,
props
.
className
);
const
strokeWidth
=
props
.
strokeWidth
;
if
(
getResourceType
(
resource
).
startsWith
(
"image"
)
)
{
c
onst
url
=
getResourceUrl
(
resource
);
switch
(
resourceType
)
{
c
ase
"image/*"
:
return
(
<
SquareDiv
key=
{
resource
.
id
}
className=
{
classNames
(
"cursor-pointer rounded hover:shadow"
,
className
)
}
>
<
SquareDiv
className=
{
classNames
(
className
,
"flex items-center justify-center overflow-clip"
)
}
>
<
img
className=
"min-h-full min-w-full w-auto h-auto rounded"
src=
{
resource
.
externalLink
?
url
:
url
+
"?thumbnail=1"
}
onClick=
{
()
=>
showPreviewImageDialog
([
url
],
0
)
}
decoding=
"async"
loading=
"lazy"
className=
"max-w-full max-h-full object-cover shadow"
src=
{
resource
.
externalLink
?
resourceUrl
:
resourceUrl
+
"?thumbnail=1"
}
onClick=
{
()
=>
showPreviewImageDialog
(
resourceUrl
)
}
/>
</
SquareDiv
>
);
case
"video/*"
:
return
<
Icon
.
FileVideo2
strokeWidth=
{
strokeWidth
}
className=
{
classNames
(
className
,
"opacity-50"
)
}
/>;
case
"audio/*"
:
return
<
Icon
.
FileAudio
strokeWidth=
{
strokeWidth
}
className=
{
classNames
(
className
,
"opacity-50"
)
}
/>;
case
"text/*"
:
return
<
Icon
.
FileText
strokeWidth=
{
strokeWidth
}
className=
{
classNames
(
className
,
"opacity-50"
)
}
/>;
case
"application/epub+zip"
:
return
<
Icon
.
Book
strokeWidth=
{
strokeWidth
}
className=
{
classNames
(
className
,
"opacity-50"
)
}
/>;
case
"application/pdf"
:
return
<
Icon
.
Book
strokeWidth=
{
strokeWidth
}
className=
{
classNames
(
className
,
"opacity-50"
)
}
/>;
case
"application/msword"
:
return
<
Icon
.
FileEdit
strokeWidth=
{
strokeWidth
}
className=
{
classNames
(
className
,
"opacity-50"
)
}
/>;
case
"application/msexcel"
:
return
<
Icon
.
SheetIcon
strokeWidth=
{
strokeWidth
}
className=
{
classNames
(
className
,
"opacity-50"
)
}
/>;
case
"application/zip"
:
return
<
Icon
.
FileArchiveIcon
strokeWidth=
{
strokeWidth
}
className=
{
classNames
(
className
,
"opacity-50"
)
}
/>;
case
"application/x-java-archive"
:
return
<
Icon
.
BinaryIcon
strokeWidth=
{
strokeWidth
}
className=
{
classNames
(
className
,
"opacity-50"
)
}
/>;
default
:
return
<
Icon
.
File
strokeWidth=
{
strokeWidth
}
className=
{
classNames
(
className
,
"opacity-50"
)
}
/>;
}
const
ResourceIcon
=
Icon
.
FileText
;
return
<
ResourceIcon
className=
{
className
}
/>;
};
export
default
Re
sourceIcon
;
export
default
Re
act
.
memo
(
ResourceIcon
)
;
web/src/components/ResourceItem.tsx
deleted
100644 → 0
View file @
9a0ada67
import
{
Checkbox
}
from
"@mui/joy"
;
import
{
useState
}
from
"react"
;
import
ResourceItemDropdown
from
"./ResourceItemDropdown"
;
const
ResourceItem
=
({
resource
,
handleCheckClick
,
handleUncheckClick
}:
ResourceItemType
)
=>
{
const
[
isSelected
,
setIsSelected
]
=
useState
<
boolean
>
(
false
);
const
handleSelectBtnClick
=
()
=>
{
if
(
isSelected
)
{
handleUncheckClick
();
}
else
{
handleCheckClick
();
}
setIsSelected
(
!
isSelected
);
};
return
(
<
div
key=
{
resource
.
id
}
className=
"px-2 py-2 w-full grid grid-cols-10"
>
<
span
className=
"col-span-1 w-full flex justify-center m-auto truncate "
>
<
Checkbox
checked=
{
isSelected
}
onChange=
{
handleSelectBtnClick
}
/>
</
span
>
<
span
className=
"col-span-2 w-full m-auto truncate text-base pr-2"
>
{
resource
.
id
}
</
span
>
<
span
className=
"col-span-6 w-full m-auto truncate text-base pr-2"
>
{
resource
.
filename
}
</
span
>
<
div
className=
"col-span-1 w-full flex flex-row justify-end items-center pr-2"
>
<
ResourceItemDropdown
resource=
{
resource
}
/>
</
div
>
</
div
>
);
};
export
default
ResourceItem
;
web/src/hooks/useEvent.ts
deleted
100644 → 0
View file @
9a0ada67
import
React
,
{
DependencyList
,
EffectCallback
,
useEffect
,
useRef
}
from
"react"
;
const
useIsoMorphicEffect
=
(
effect
:
EffectCallback
,
deps
?:
DependencyList
|
undefined
)
=>
{
useEffect
(
effect
,
deps
);
};
function
useLatestValue
<
T
>
(
value
:
T
)
{
const
cache
=
useRef
(
value
);
useIsoMorphicEffect
(()
=>
{
cache
.
current
=
value
;
},
[
value
]);
return
cache
;
}
// TODO: Add React.useEvent ?? once the useEvent hook is available
function
useEvent
<
F
extends
(...
args
:
any
[])
=>
any
,
P
extends
any
[]
=
Parameters
<
F
>
,
R
=
ReturnType
<
F
>>
(
cb
:
(...
args
:
P
)
=>
R
)
{
const
cache
=
useLatestValue
(
cb
);
return
React
.
useCallback
((...
args
:
P
)
=>
cache
.
current
(...
args
),
[
cache
]);
}
export
default
useEvent
;
web/src/less/resource-cover.less
deleted
100644 → 0
View file @
9a0ada67
.resource-cover {
@apply w-20 h-auto ml-auto mr-auto opacity-40;
}
web/src/pages/ResourcesDashboard.tsx
View file @
04595a5f
...
...
@@ -7,12 +7,10 @@ import Empty from "@/components/Empty";
import
Icon
from
"@/components/Icon"
;
import
MobileHeader
from
"@/components/MobileHeader"
;
import
ResourceCard
from
"@/components/ResourceCard"
;
import
ResourceItem
from
"@/components/ResourceItem"
;
import
ResourceSearchBar
from
"@/components/ResourceSearchBar"
;
import
Dropdown
from
"@/components/kit/Dropdown"
;
import
{
DEFAULT_MEMO_LIMIT
}
from
"@/helpers/consts"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useEvent
from
"@/hooks/useEvent"
;
import
useLoading
from
"@/hooks/useLoading"
;
import
{
useResourceStore
}
from
"@/store/module"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
...
...
@@ -23,8 +21,6 @@ const ResourcesDashboard = () => {
const
user
=
useCurrentUser
();
const
resourceStore
=
useResourceStore
();
const
resources
=
resourceStore
.
state
.
resources
;
const
[
selectedList
,
setSelectedList
]
=
useState
<
Array
<
ResourceId
>>
([]);
const
[
listStyle
,
setListStyle
]
=
useState
<
"GRID"
|
"TABLE"
>
(
"TABLE"
);
const
[
queryText
,
setQueryText
]
=
useState
<
string
>
(
""
);
const
[
dragActive
,
setDragActive
]
=
useState
(
false
);
const
[
isComplete
,
setIsComplete
]
=
useState
<
boolean
>
(
false
);
...
...
@@ -50,19 +46,6 @@ const ResourcesDashboard = () => {
});
},
[]);
const
handleCheckBtnClick
=
useEvent
((
resourceId
:
ResourceId
)
=>
{
setSelectedList
([...
selectedList
,
resourceId
]);
});
const
handleUncheckBtnClick
=
useEvent
((
resourceId
:
ResourceId
)
=>
{
setSelectedList
(
selectedList
.
filter
((
id
)
=>
id
!==
resourceId
));
});
const
handleStyleChangeBtnClick
=
(
listStyle
:
"GRID"
|
"TABLE"
)
=>
{
setListStyle
(
listStyle
);
setSelectedList
([]);
};
const
handleDeleteUnusedResourcesBtnClick
=
async
()
=>
{
let
warningText
=
t
(
"resource.warning-text-unused"
);
const
allResources
=
await
fetchAllResources
();
...
...
@@ -91,27 +74,6 @@ const ResourcesDashboard = () => {
});
};
const
handleDeleteSelectedBtnClick
=
()
=>
{
if
(
selectedList
.
length
==
0
)
{
toast
.
error
(
t
(
"resource.no-files-selected"
));
}
else
{
const
warningText
=
t
(
"resource.warning-text"
);
showCommonDialog
({
title
:
t
(
"resource.delete-resource"
),
content
:
warningText
,
style
:
"warning"
,
dialogName
:
"delete-resource-dialog"
,
onConfirm
:
async
()
=>
{
for
(
const
resourceId
of
selectedList
)
{
await
resourceStore
.
deleteResourceById
(
resourceId
);
}
setSelectedList
([]);
},
});
}
};
const
handleFetchMoreResourceBtnClick
=
async
()
=>
{
try
{
const
fetchedResource
=
await
resourceStore
.
fetchResourceListWithLimit
(
DEFAULT_MEMO_LIMIT
,
resources
.
length
);
...
...
@@ -149,7 +111,6 @@ const ResourcesDashboard = () => {
if
(
query
===
queryText
)
return
;
await
fetchAllResources
();
setQueryText
(
query
);
setSelectedList
([]);
};
const
handleDrag
=
(
e
:
React
.
DragEvent
<
HTMLDivElement
>
)
=>
{
...
...
@@ -166,24 +127,8 @@ const ResourcesDashboard = () => {
()
=>
resources
.
filter
((
res
:
Resource
)
=>
(
queryText
===
""
?
true
:
res
.
filename
.
toLowerCase
().
includes
(
queryText
.
toLowerCase
())))
.
map
((
resource
)
=>
listStyle
===
"TABLE"
?
(
<
ResourceItem
key=
{
resource
.
id
}
resource=
{
resource
}
handleCheckClick=
{
()
=>
handleCheckBtnClick
(
resource
.
id
)
}
handleUncheckClick=
{
()
=>
handleUncheckBtnClick
(
resource
.
id
)
}
></
ResourceItem
>
)
:
(
<
ResourceCard
key=
{
resource
.
id
}
resource=
{
resource
}
handleCheckClick=
{
()
=>
handleCheckBtnClick
(
resource
.
id
)
}
handleUncheckClick=
{
()
=>
handleUncheckBtnClick
(
resource
.
id
)
}
></
ResourceCard
>
)
),
[
resources
,
queryText
,
listStyle
]
.
map
((
resource
)
=>
<
ResourceCard
key=
{
resource
.
id
}
resource=
{
resource
}
></
ResourceCard
>),
[
resources
,
queryText
]
);
const
handleDrop
=
async
(
e
:
React
.
DragEvent
<
HTMLDivElement
>
)
=>
{
...
...
@@ -230,11 +175,6 @@ const ResourcesDashboard = () => {
<
ResourceSearchBar
setQuery=
{
handleSearchResourceInputChange
}
/>
</
div
>
<
div
className=
"w-full flex flex-row justify-end items-center space-x-2 mt-3 z-1"
>
{
selectedList
.
length
>
0
&&
(
<
Button
onClick=
{
()
=>
handleDeleteSelectedBtnClick
()
}
color=
"danger"
>
<
Icon
.
Trash2
className=
"w-4 h-auto"
/>
</
Button
>
)
}
<
Button
onClick=
{
()
=>
showCreateResourceDialog
({
...
...
@@ -267,24 +207,6 @@ const ResourcesDashboard = () => {
</>
}
/>
<
div
className=
"flex rounded-lg cursor-pointer h-8 overflow-clip border dark:border-zinc-600"
>
<
div
className=
{
`flex justify-center items-center px-3 ${
listStyle === "GRID" ? "bg-white dark:bg-zinc-700" : "bg-gray-200 dark:bg-zinc-800 opacity-60"
}`
}
onClick=
{
()
=>
handleStyleChangeBtnClick
(
"GRID"
)
}
>
<
Icon
.
Grid
className=
"w-4 h-auto opacity-80"
/>
</
div
>
<
div
className=
{
`flex justify-center items-center px-3 ${
listStyle === "TABLE" ? "bg-white dark:bg-zinc-700" : "bg-gray-200 dark:bg-zinc-800 opacity-60"
}`
}
onClick=
{
()
=>
handleStyleChangeBtnClick
(
"TABLE"
)
}
>
<
Icon
.
List
className=
"w-4 h-auto opacity-80"
/>
</
div
>
</
div
>
</
div
>
<
div
className=
"w-full flex flex-col justify-start items-start mt-4 mb-6"
>
{
loadingState
.
isLoading
?
(
...
...
@@ -294,19 +216,11 @@ const ResourcesDashboard = () => {
)
:
(
<
div
className=
{
listStyle
===
"TABLE"
||
resourceList
.
length
===
0
resourceList
.
length
===
0
?
"flex flex-col justify-start items-start w-full"
:
"w-full h-auto grid grid-cols-2 md:grid-cols-4 md:px-6 gap-6"
}
>
{
listStyle
===
"TABLE"
&&
(
<
div
className=
"px-2 py-2 w-full grid grid-cols-10 border-b dark:border-b-zinc-600"
>
<
span
></
span
>
<
span
className=
"col-span-2"
>
ID
</
span
>
<
span
className=
"col-span-6"
>
{
t
(
"common.name"
)
}
</
span
>
<
span
></
span
>
</
div
>
)
}
{
resourceList
.
length
===
0
?
(
<
div
className=
"w-full mt-8 mb-8 flex flex-col justify-center items-center italic"
>
<
Empty
/>
...
...
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