Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
U
upgrade-data-crawler-fe
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
ThinhNC
upgrade-data-crawler-fe
Commits
751a54e2
Commit
751a54e2
authored
Sep 10, 2026
by
ThinhNC
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat(system-config): add sync from .env button and update 7-day retention UI
parent
be29c7a3
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
111 additions
and
15 deletions
+111
-15
system-configs-management-view.tsx
...mponents/system-config/system-configs-management-view.tsx
+76
-13
use-system-config.ts
src/hooks/use-system-config.ts
+16
-0
translations.ts
src/lib/i18n/translations.ts
+6
-2
system-config.service.ts
src/services/system-config.service.ts
+13
-0
No files found.
src/components/system-config/system-configs-management-view.tsx
View file @
751a54e2
...
...
@@ -13,7 +13,9 @@ import {
AlertCircle
,
RefreshCw
,
Lock
,
FileCode
,
}
from
"lucide-react"
;
import
{
toast
}
from
"sonner"
;
import
{
Button
}
from
"@/components/ui/button"
;
import
{
Input
}
from
"@/components/ui/input"
;
import
{
useLanguage
}
from
"@/providers/language-provider"
;
...
...
@@ -24,6 +26,7 @@ import {
useUpdateSystemConfig
,
useToggleFeatureFlag
,
useDeleteSystemConfig
,
useSyncEnvConfigs
,
}
from
"@/hooks/use-system-config"
;
import
{
CreateSystemConfigDto
,
...
...
@@ -99,6 +102,7 @@ export function SystemConfigsManagementView({
const
updateMutation
=
useUpdateSystemConfig
();
const
toggleMutation
=
useToggleFeatureFlag
();
const
deleteMutation
=
useDeleteSystemConfig
();
const
syncEnvMutation
=
useSyncEnvConfigs
();
// Sort toggle handler
const
handleToggleSort
=
(
column
:
string
)
=>
{
...
...
@@ -173,23 +177,53 @@ export function SystemConfigsManagementView({
}
};
const
handleSyncEnv
=
async
()
=>
{
try
{
const
res
=
await
syncEnvMutation
.
mutateAsync
();
toast
.
success
(
res
?.
syncedCount
!==
undefined
?
`
${
t
.
systemConfigs
.
toast
.
syncEnvSuccess
}
(
${
res
.
syncedCount
}
)`
:
t
.
systemConfigs
.
toast
.
syncEnvSuccess
,
);
}
catch
(
err
:
unknown
)
{
const
errorMsg
=
err
instanceof
Error
?
err
.
message
:
t
.
systemConfigs
.
toast
.
error
;
toast
.
error
(
errorMsg
);
}
};
const
handleSubmitCreate
=
async
(
dto
:
CreateSystemConfigDto
)
=>
{
await
createMutation
.
mutateAsync
(
dto
);
setIsFormModalOpen
(
false
);
try
{
await
createMutation
.
mutateAsync
(
dto
);
toast
.
success
(
t
.
systemConfigs
.
toast
.
createSuccess
);
setIsFormModalOpen
(
false
);
}
catch
{
toast
.
error
(
t
.
systemConfigs
.
toast
.
error
);
}
};
const
handleSubmitUpdate
=
async
(
key
:
string
,
dto
:
UpdateSystemConfigDto
,
)
=>
{
await
updateMutation
.
mutateAsync
({
key
,
dto
});
setIsFormModalOpen
(
false
);
try
{
await
updateMutation
.
mutateAsync
({
key
,
dto
});
toast
.
success
(
t
.
systemConfigs
.
toast
.
updateSuccess
);
setIsFormModalOpen
(
false
);
}
catch
{
toast
.
error
(
t
.
systemConfigs
.
toast
.
error
);
}
};
const
handleConfirmDelete
=
async
()
=>
{
if
(
!
deletingConfig
)
return
;
await
deleteMutation
.
mutateAsync
(
deletingConfig
.
key
);
setDeletingConfig
(
null
);
try
{
await
deleteMutation
.
mutateAsync
(
deletingConfig
.
key
);
toast
.
success
(
t
.
systemConfigs
.
toast
.
deleteSuccess
);
setDeletingConfig
(
null
);
}
catch
{
toast
.
error
(
t
.
systemConfigs
.
toast
.
error
);
}
};
return
(
...
...
@@ -211,13 +245,26 @@ export function SystemConfigsManagementView({
</
div
>
{
canManage
&&
(
<
Button
onClick=
{
handleOpenCreate
}
className=
"rounded-2xl bg-emerald-600 hover:bg-emerald-700 text-white text-xs font-bold px-4 py-2.5 shadow-md shadow-emerald-600/20 cursor-pointer transition-all hover:scale-[1.02] flex items-center gap-2"
>
<
Plus
className=
"h-4 w-4"
/>
<
span
>
{
t
.
systemConfigs
.
createBtn
}
</
span
>
</
Button
>
<
div
className=
"flex items-center gap-2"
>
<
Button
type=
"button"
variant=
"outline"
onClick=
{
handleSyncEnv
}
disabled=
{
syncEnvMutation
.
isPending
}
className=
"rounded-2xl border-emerald-500/30 hover:bg-emerald-500/10 text-emerald-600 dark:text-emerald-400 text-xs font-bold px-4 py-2.5 shadow-sm cursor-pointer transition-all hover:scale-[1.02] flex items-center gap-2"
>
<
FileCode
className=
{
`h-4 w-4 ${syncEnvMutation.isPending ? "animate-spin" : ""}`
}
/>
<
span
>
{
t
.
systemConfigs
.
syncEnvBtn
}
</
span
>
</
Button
>
<
Button
type=
"button"
onClick=
{
handleOpenCreate
}
className=
"rounded-2xl bg-emerald-600 hover:bg-emerald-700 text-white text-xs font-bold px-4 py-2.5 shadow-md shadow-emerald-600/20 cursor-pointer transition-all hover:scale-[1.02] flex items-center gap-2"
>
<
Plus
className=
"h-4 w-4"
/>
<
span
>
{
t
.
systemConfigs
.
createBtn
}
</
span
>
</
Button
>
</
div
>
)
}
</
div
>
)
}
...
...
@@ -315,6 +362,22 @@ export function SystemConfigsManagementView({
</
button
>
</
div
>
{
canManage
&&
(
<
button
onClick=
{
handleSyncEnv
}
disabled=
{
syncEnvMutation
.
isPending
}
className=
"flex items-center gap-1.5 h-9 px-3 rounded-2xl border border-emerald-500/30 bg-emerald-500/10 text-xs font-semibold text-emerald-600 dark:text-emerald-400 hover:bg-emerald-500/20 transition-all cursor-pointer disabled:opacity-50"
title=
{
t
.
systemConfigs
.
syncEnvBtn
}
>
<
FileCode
className=
{
`h-4 w-4 ${syncEnvMutation.isPending ? "animate-spin" : ""}`
}
/>
<
span
className=
"hidden sm:inline"
>
{
t
.
systemConfigs
.
syncEnvBtn
}
</
span
>
</
button
>
)
}
<
button
onClick=
{
()
=>
refetch
()
}
disabled=
{
isFetching
}
...
...
src/hooks/use-system-config.ts
View file @
751a54e2
...
...
@@ -136,3 +136,19 @@ export function useDeleteSystemConfig() {
},
});
}
/**
* Hook đồng bộ toàn bộ giá trị cấu hình từ file .env
*/
export
function
useSyncEnvConfigs
()
{
const
queryClient
=
useQueryClient
();
return
useMutation
({
mutationFn
:
()
=>
systemConfigService
.
syncFromEnv
(),
onSuccess
:
()
=>
{
queryClient
.
invalidateQueries
({
queryKey
:
SYSTEM_CONFIG_QUERY_KEYS
.
all
,
});
},
});
}
src/lib/i18n/translations.ts
View file @
751a54e2
...
...
@@ -1348,6 +1348,7 @@ export const translations = {
editBtn
:
"Chỉnh sửa"
,
deleteBtn
:
"Xóa cấu hình"
,
refreshBtn
:
"Làm mới"
,
syncEnvBtn
:
"Đồng bộ từ .env"
,
table
:
{
key
:
"Khóa cấu hình"
,
value
:
"Giá trị"
,
...
...
@@ -1399,6 +1400,7 @@ export const translations = {
updateSuccess
:
"Đã cập nhật cấu hình thành công"
,
toggleSuccess
:
"Đã thay đổi trạng thái cờ tính năng"
,
deleteSuccess
:
"Đã xóa cấu hình thành công"
,
syncEnvSuccess
:
"Đã đồng bộ toàn bộ giá trị cấu hình từ file .env thành công"
,
error
:
"Đã có lỗi xảy ra, vui lòng thử lại"
,
},
},
...
...
@@ -1447,7 +1449,7 @@ export const translations = {
jobLabel
:
"Tác vụ đang chọn:"
,
cronLabel
:
"Lịch biểu:"
,
paramsLabel
:
"Tham số tùy biến:"
,
paramsPlaceholder
:
'{
\
n "retentionDays":
30
\
n}'
,
paramsPlaceholder
:
'{
\
n "retentionDays":
7
\
n}'
,
paramsHint
:
"Để trống nếu muốn sử dụng tham số mặc định của hệ thống."
,
executing
:
"Đang thực thi tác vụ..."
,
runBtn
:
"Bắt Đầu Chạy"
,
...
...
@@ -2813,6 +2815,7 @@ export const translations = {
editBtn
:
"Edit"
,
deleteBtn
:
"Delete configuration"
,
refreshBtn
:
"Refresh"
,
syncEnvBtn
:
"Sync from .env"
,
table
:
{
key
:
"Configuration Key"
,
value
:
"Current Value"
,
...
...
@@ -2864,6 +2867,7 @@ export const translations = {
updateSuccess
:
"Configuration updated successfully"
,
toggleSuccess
:
"Feature flag state toggled successfully"
,
deleteSuccess
:
"Configuration deleted successfully"
,
syncEnvSuccess
:
"Configurations synchronized from .env successfully"
,
error
:
"An error occurred, please try again"
,
},
},
...
...
@@ -2912,7 +2916,7 @@ export const translations = {
jobLabel
:
"Selected Task:"
,
cronLabel
:
"Cron Schedule:"
,
paramsLabel
:
"Custom Parameters:"
,
paramsPlaceholder
:
'{
\
n "retentionDays":
30
\
n}'
,
paramsPlaceholder
:
'{
\
n "retentionDays":
7
\
n}'
,
paramsHint
:
"Leave blank to use the system default parameters."
,
executing
:
"Executing task..."
,
runBtn
:
"Execute Now"
,
...
...
src/services/system-config.service.ts
View file @
751a54e2
...
...
@@ -96,4 +96,17 @@ export const systemConfigService = {
async
deleteConfig
(
key
:
string
):
Promise
<
void
>
{
await
apiClient
.
delete
(
`/system/configs/
${
encodeURIComponent
(
key
)}
`
);
},
/**
* Đồng bộ toàn bộ cấu hình từ biến môi trường (.env) vào Database
* POST /api/proxy/system/configs/sync-env
*/
async
syncFromEnv
():
Promise
<
{
syncedCount
:
number
;
keys
:
string
[]
}
>
{
const
response
=
await
apiClient
.
post
<
{
success
:
boolean
;
data
:
{
syncedCount
:
number
;
keys
:
string
[]
};
message
?:
string
;
}
>
(
"/system/configs/sync-env"
);
return
response
.
data
.
data
;
},
};
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