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
d68ca848
Commit
d68ca848
authored
Jan 05, 2026
by
Johnny
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fix: delete unused attachments by using filter
parent
4b110d0d
Changes
4
Show whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
36 additions
and
4 deletions
+36
-4
render.go
plugin/filter/render.go
+11
-0
schema.go
plugin/filter/schema.go
+1
-1
attachment_filter_test.go
store/test/attachment_filter_test.go
+10
-1
Attachments.tsx
web/src/pages/Attachments.tsx
+14
-2
No files found.
plugin/filter/render.go
View file @
d68ca848
...
@@ -207,6 +207,17 @@ func (r *renderer) renderScalarComparison(field Field, op ComparisonOperator, ri
...
@@ -207,6 +207,17 @@ func (r *renderer) renderScalarComparison(field Field, op ComparisonOperator, ri
}
}
columnExpr
:=
field
.
columnExpr
(
r
.
dialect
)
columnExpr
:=
field
.
columnExpr
(
r
.
dialect
)
if
lit
==
nil
{
switch
op
{
case
CompareEq
:
return
renderResult
{
sql
:
fmt
.
Sprintf
(
"%s IS NULL"
,
columnExpr
)},
nil
case
CompareNeq
:
return
renderResult
{
sql
:
fmt
.
Sprintf
(
"%s IS NOT NULL"
,
columnExpr
)},
nil
default
:
return
renderResult
{},
errors
.
Errorf
(
"operator %s not supported for null comparison"
,
op
)
}
}
placeholder
:=
""
placeholder
:=
""
switch
field
.
Type
{
switch
field
.
Type
{
case
FieldTypeString
:
case
FieldTypeString
:
...
...
plugin/filter/schema.go
View file @
d68ca848
...
@@ -297,7 +297,7 @@ func NewAttachmentSchema() Schema {
...
@@ -297,7 +297,7 @@ func NewAttachmentSchema() Schema {
cel
.
Variable
(
"filename"
,
cel
.
StringType
),
cel
.
Variable
(
"filename"
,
cel
.
StringType
),
cel
.
Variable
(
"mime_type"
,
cel
.
StringType
),
cel
.
Variable
(
"mime_type"
,
cel
.
StringType
),
cel
.
Variable
(
"create_time"
,
cel
.
IntType
),
cel
.
Variable
(
"create_time"
,
cel
.
IntType
),
cel
.
Variable
(
"memo_id"
,
cel
.
Int
Type
),
cel
.
Variable
(
"memo_id"
,
cel
.
Any
Type
),
nowFunction
,
nowFunction
,
}
}
...
...
store/test/attachment_filter_test.go
View file @
d68ca848
...
@@ -328,9 +328,18 @@ func TestAttachmentFilterNullMemoId(t *testing.T) {
...
@@ -328,9 +328,18 @@ func TestAttachmentFilterNullMemoId(t *testing.T) {
tc
.
CreateAttachment
(
NewAttachmentBuilder
(
tc
.
CreatorID
)
.
Filename
(
"with_memo.png"
)
.
MimeType
(
"image/png"
)
.
MemoID
(
&
memo
.
ID
))
tc
.
CreateAttachment
(
NewAttachmentBuilder
(
tc
.
CreatorID
)
.
Filename
(
"with_memo.png"
)
.
MimeType
(
"image/png"
)
.
MemoID
(
&
memo
.
ID
))
tc
.
CreateAttachment
(
NewAttachmentBuilder
(
tc
.
CreatorID
)
.
Filename
(
"no_memo.png"
)
.
MimeType
(
"image/png"
))
tc
.
CreateAttachment
(
NewAttachmentBuilder
(
tc
.
CreatorID
)
.
Filename
(
"no_memo.png"
)
.
MimeType
(
"image/png"
))
attachments
:=
tc
.
ListWithFilter
(
`memo_id == `
+
formatInt32
(
memo
.
ID
))
// Test: memo_id == null
attachments
:=
tc
.
ListWithFilter
(
`memo_id == null`
)
require
.
Len
(
t
,
attachments
,
1
)
require
.
Equal
(
t
,
"no_memo.png"
,
attachments
[
0
]
.
Filename
)
require
.
Nil
(
t
,
attachments
[
0
]
.
MemoID
)
// Test: memo_id != null
attachments
=
tc
.
ListWithFilter
(
`memo_id != null`
)
require
.
Len
(
t
,
attachments
,
1
)
require
.
Len
(
t
,
attachments
,
1
)
require
.
Equal
(
t
,
"with_memo.png"
,
attachments
[
0
]
.
Filename
)
require
.
Equal
(
t
,
"with_memo.png"
,
attachments
[
0
]
.
Filename
)
require
.
NotNil
(
t
,
attachments
[
0
]
.
MemoID
)
require
.
Equal
(
t
,
memo
.
ID
,
*
attachments
[
0
]
.
MemoID
)
}
}
func
TestAttachmentFilterEmptyFilename
(
t
*
testing
.
T
)
{
func
TestAttachmentFilterEmptyFilename
(
t
*
testing
.
T
)
{
...
...
web/src/pages/Attachments.tsx
View file @
d68ca848
...
@@ -156,7 +156,19 @@ const Attachments = () => {
...
@@ -156,7 +156,19 @@ const Attachments = () => {
// Delete all unused attachments
// Delete all unused attachments
const
handleDeleteUnusedAttachments
=
useCallback
(
async
()
=>
{
const
handleDeleteUnusedAttachments
=
useCallback
(
async
()
=>
{
try
{
try
{
await
Promise
.
all
(
unusedAttachments
.
map
((
attachment
)
=>
deleteAttachment
(
attachment
.
name
)));
let
allUnusedAttachments
:
Attachment
[]
=
[];
let
nextPageToken
=
""
;
do
{
const
response
=
await
attachmentServiceClient
.
listAttachments
({
pageSize
:
1000
,
pageToken
:
nextPageToken
,
filter
:
"memo_id == null"
,
});
allUnusedAttachments
=
[...
allUnusedAttachments
,
...
response
.
attachments
];
nextPageToken
=
response
.
nextPageToken
;
}
while
(
nextPageToken
);
await
Promise
.
all
(
allUnusedAttachments
.
map
((
attachment
)
=>
deleteAttachment
(
attachment
.
name
)));
toast
.
success
(
t
(
"resource.delete-all-unused-success"
));
toast
.
success
(
t
(
"resource.delete-all-unused-success"
));
}
catch
(
error
)
{
}
catch
(
error
)
{
handleError
(
error
,
toast
.
error
,
{
handleError
(
error
,
toast
.
error
,
{
...
@@ -166,7 +178,7 @@ const Attachments = () => {
...
@@ -166,7 +178,7 @@ const Attachments = () => {
}
finally
{
}
finally
{
await
handleRefetch
();
await
handleRefetch
();
}
}
},
[
unusedAttachments
,
t
,
handleRefetch
,
deleteAttachment
]);
},
[
t
,
handleRefetch
,
deleteAttachment
]);
// Handle search input change
// Handle search input change
const
handleSearchChange
=
useCallback
((
e
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
handleSearchChange
=
useCallback
((
e
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
...
...
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