Skip to content

Commit 52e5430

Browse files
committed
Optimize page performance and Added new features(backup\monitor\php)
1 parent 0589f25 commit 52e5430

20 files changed

Lines changed: 2812 additions & 279 deletions

build.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
#!/bin/bash
22
yarn build
3+
rm -rf /usr/share/cockpit/myapps/*
34
cp -r /data/plugin-cockpit/plugin-myapps/build/* /usr/share/cockpit/myapps/

public/po.zh_CN.js

Lines changed: 181 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ cockpit.locale({
454454
],
455455
"Volumes": [
456456
null,
457-
"卷存"
457+
"数据"
458458
],
459459
"Driver": [
460460
null,
@@ -1103,6 +1103,186 @@ cockpit.locale({
11031103
"Request submission failed": [
11041104
null,
11051105
"申请提交失败"
1106+
],
1107+
"Monitor": [
1108+
null,
1109+
"监控"
1110+
],
1111+
"Monitor URL": [
1112+
null,
1113+
"监控网站"
1114+
],
1115+
"Monitor website uptime and performance with real-time alerts": [
1116+
null,
1117+
"监控网站的正常运行时间和性能,并提供实时警报"
1118+
],
1119+
"Notification Email": [
1120+
null,
1121+
"通知邮箱"
1122+
],
1123+
"Enable": [
1124+
null,
1125+
"启用"
1126+
],
1127+
"Enabled": [
1128+
null,
1129+
"已启用"
1130+
],
1131+
"Note:": [
1132+
null,
1133+
"注意:"
1134+
],
1135+
"Please bind a domain name to the application before enabling monitoring.": [
1136+
null,
1137+
"启用监控前请先为应用绑定域名。"
1138+
],
1139+
"Select monitor URL": [
1140+
null,
1141+
"选择监控网址"
1142+
],
1143+
"No domain names available": [
1144+
null,
1145+
"无可用域名"
1146+
],
1147+
"Invalid email": [
1148+
null,
1149+
"无效邮箱"
1150+
],
1151+
"Monitor website uptime and performance with real-time alerts and email notifications": [
1152+
null,
1153+
"监控网站的正常运行时间和性能,并提供实时警报和电子邮件通知。"
1154+
],
1155+
"Enabling...": [
1156+
null,
1157+
"启用中..."
1158+
],
1159+
"Edit": [
1160+
null,
1161+
"修改"
1162+
],
1163+
"Disable": [
1164+
null,
1165+
"禁用"
1166+
],
1167+
"Disabling...": [
1168+
null,
1169+
"禁用中..."
1170+
],
1171+
"Updating...": [
1172+
null,
1173+
"更新中..."
1174+
],
1175+
"Backups": [
1176+
null,
1177+
"备份"
1178+
],
1179+
"Create": [
1180+
null,
1181+
"创建"
1182+
],
1183+
"Create Backup": [
1184+
null,
1185+
"创建备份"
1186+
],
1187+
"Restore": [
1188+
null,
1189+
"恢复"
1190+
],
1191+
"The following volumes will be backed up:": [
1192+
null,
1193+
"以下数据卷将被备份:"
1194+
],
1195+
"Tips:": [
1196+
null,
1197+
"提示:"
1198+
],
1199+
"All application volumes will be included in this backup": [
1200+
null,
1201+
"所有应用程序卷将包含在此备份中"
1202+
],
1203+
"The backup process may take several minutes depending on data size": [
1204+
null,
1205+
"备份过程可能需要几分钟,具体取决于数据大小"
1206+
],
1207+
"Applications will remain accessible during backup": [
1208+
null,
1209+
"所有应用程序卷将在备份期间保持可访问"
1210+
],
1211+
"ID": [
1212+
null,
1213+
"编号"
1214+
],
1215+
"Size": [
1216+
null,
1217+
"大小"
1218+
],
1219+
"Action": [
1220+
null,
1221+
"操作"
1222+
],
1223+
"Are you sure you want to delete this backup? This action cannot be undone.": [
1224+
null,
1225+
"您确定要删除此备份吗?此操作无法撤消。"
1226+
],
1227+
"I confirm that the backup cannot be recovered after deletion, and the data cannot be retrieved.": [
1228+
null,
1229+
"我确认删除后备份无法恢复,数据无法找回。"
1230+
],
1231+
"Delete Backup": [
1232+
null,
1233+
"删除备份"
1234+
],
1235+
"Restore Backup": [
1236+
null,
1237+
"恢复备份"
1238+
],
1239+
"Are you sure you want to restore this backup? This action will roll back your volumes to the state of this backup.": [
1240+
null,
1241+
"您确定要恢复此备份吗?此操作将使您的数据回滚到此备份的状态。"
1242+
],
1243+
"The application will be automatically stopped before restoration and restarted after completion.": [
1244+
null,
1245+
"应用程序将在恢复之前自动停止,并在完成后重新启动。"
1246+
],
1247+
"Restoring a backup will replace your current volume data. All data and changes made after this backup was created will be lost.": [
1248+
null,
1249+
"恢复备份将替换您当前的卷数据。所有在此备份创建后所做的数据和更改将丢失。"
1250+
],
1251+
"The restoration process may take several minutes depending on the data size.": [
1252+
null,
1253+
"恢复过程可能需要几分钟,具体取决于数据大小。"
1254+
],
1255+
"Applications may be temporarily unavailable during the restoration process.": [
1256+
null,
1257+
"在恢复过程中,应用程序可能会暂时不可用。"
1258+
],
1259+
"Restoration carries risks. Please ensure you understand the implications before proceeding.": [
1260+
null,
1261+
"恢复操作存在风险。请确保在继续之前了解其影响。"
1262+
],
1263+
"I understand the risks and confirm to restore this backup, knowing that all data and changes after this backup will be lost and cannot be recovered.": [
1264+
null,
1265+
"我理解风险并确认恢复此备份,知道此备份之后的所有数据和更改将丢失且无法恢复。"
1266+
],
1267+
"Backup restoration may encounter unexpected errors or failures, which could potentially render the application unavailable.": [
1268+
null,
1269+
"备份恢复可能会遇到意外错误或故障,这可能会导致应用程序不可用。"
1270+
],
1271+
"Failed to create backup": [
1272+
null,
1273+
"备份创建失败"
1274+
],
1275+
"Backup restored successfully! Application has been restarted and is now available.": [
1276+
null,
1277+
"备份恢复成功!应用程序已重新启动并且现在可用。"
1278+
],
1279+
"Backup deleted successfully!": [
1280+
null,
1281+
"备份删除成功!"
1282+
],
1283+
"Backup created successfully!": [
1284+
null,
1285+
"备份创建成功!"
11061286
]
11071287
});
11081288

src/assets/scss/app.scss

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,84 @@ File: Main Css File
142142
overflow: hidden;
143143
text-overflow: ellipsis;
144144
white-space: nowrap;
145+
}
146+
147+
.skeleton-card {
148+
background: #f8f9fa;
149+
border-radius: 8px;
150+
padding: 20px;
151+
margin-bottom: 20px;
152+
border: 1px solid #e9ecef;
153+
min-height: 200px;
154+
}
155+
156+
.skeleton-header {
157+
display: flex;
158+
justify-content: flex-end;
159+
margin-bottom: 10px;
160+
}
161+
162+
.skeleton-icon {
163+
width: 20px;
164+
height: 20px;
165+
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
166+
background-size: 200% 100%;
167+
animation: loading 1.5s infinite;
168+
border-radius: 4px;
169+
}
170+
171+
.skeleton-image {
172+
width: 60px;
173+
height: 60px;
174+
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
175+
background-size: 200% 100%;
176+
animation: loading 1.5s infinite;
177+
border-radius: 8px;
178+
margin: 20px auto;
179+
}
180+
181+
.skeleton-title {
182+
width: 80%;
183+
height: 20px;
184+
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
185+
background-size: 200% 100%;
186+
animation: loading 1.5s infinite;
187+
border-radius: 4px;
188+
margin: 10px auto;
189+
}
190+
191+
.skeleton-badge {
192+
width: 60px;
193+
height: 24px;
194+
background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
195+
background-size: 200% 100%;
196+
animation: loading 1.5s infinite;
197+
border-radius: 12px;
198+
margin: 10px auto;
199+
}
200+
201+
@keyframes loading {
202+
0% {
203+
background-position: 200% 0;
204+
}
205+
206+
100% {
207+
background-position: -200% 0;
208+
}
209+
}
210+
211+
/* 暗色主题适配 */
212+
@media (prefers-color-scheme: dark) {
213+
.skeleton-card {
214+
background: #2d3748;
215+
border-color: #4a5568;
216+
}
217+
218+
.skeleton-icon,
219+
.skeleton-image,
220+
.skeleton-title,
221+
.skeleton-badge {
222+
background: linear-gradient(90deg, #4a5568 25%, #718096 50%, #4a5568 75%);
223+
background-size: 200% 100%;
224+
}
145225
}

src/components/AppSkeleton.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
import React from 'react';
2+
import { Col, Row } from 'react-bootstrap';
3+
4+
const AppSkeleton = ({ count = 6 }) => {
5+
return (
6+
<Row>
7+
{Array.from({ length: count }).map((_, index) => (
8+
<Col xxl={2} md={3} key={index} className="appstore-item">
9+
<div className="appstore-item-content skeleton-card">
10+
<div className="skeleton-header">
11+
<div className="skeleton-icon"></div>
12+
</div>
13+
<div className="skeleton-image"></div>
14+
<div className="skeleton-title"></div>
15+
<div className="skeleton-badge"></div>
16+
</div>
17+
</Col>
18+
))}
19+
</Row>
20+
);
21+
};
22+
23+
export default AppSkeleton;

src/components/TagsInput.js

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import { Button, Modal } from 'react-bootstrap';
1212
import ReactDOM from 'react-dom';
1313
import Spinner from '../components/Spinner';
1414
import { AppDomainCreateByAppID, AppDomainDeleteByProxyID, AppDomainUpdateByProxyID } from '../helpers';
15+
import { checkAndDisableMonitoring, checkAndDisableMonitoringForDeletedDomains } from '../utils/monitorUtils';
1516

1617
const _ = cockpit.gettext;
1718

@@ -38,6 +39,22 @@ const DeleteDomainConform = (props) => {
3839
const [showCloseButton, setShowCloseButton] = useState(true);//用于是否显示关闭按钮
3940
const [alertType, setAlertType] = useState(""); //用于确定弹窗的类型:error\success
4041

42+
// 检查删除的域名是否正在被监控
43+
const checkAndDisableMonitoringForDomains = async (appId, domains) => {
44+
if (!appId || !domains || domains.length === 0) {
45+
return;
46+
}
47+
48+
try {
49+
// 检查被删除的域名是否正在被监控,如果是则禁用监控
50+
await checkAndDisableMonitoringForDeletedDomains(appId, domains);
51+
console.log(`Checked monitoring for deleted domains: ${domains.join(', ')}`);
52+
} catch (error) {
53+
// 监控检查失败不应该阻止域名删除
54+
console.warn(`Failed to check/disable monitoring for deleted domains:`, error.message || error);
55+
}
56+
};
57+
4158
const handleClose = (event, reason) => {
4259
if (reason === 'clickaway') {
4360
return;
@@ -69,6 +86,12 @@ const DeleteDomainConform = (props) => {
6986
setDisable(true);
7087
setShowCloseButton(false);
7188
try {
89+
// 首先检查并禁用监控(如果使用了被删除的域名)
90+
if (props.app_id && props.isMonitorApp) {
91+
await checkAndDisableMonitoringForDomains(props.app_id, props.domains);
92+
}
93+
94+
// 然后删除域名
7295
await AppDomainDeleteByProxyID(props.proxy_id);
7396
props.onDataChange();
7497
props.onClose();
@@ -259,8 +282,9 @@ const TagsInput = forwardRef(({
259282
defaultEditable = false,
260283
onDeleteRow,
261284
onSaveRow,
262-
onDataChange
263-
}, ref): React$Element<React$FragmentType> => {
285+
onDataChange,
286+
isMonitorApp = false
287+
}, ref) => {
264288
const [tags, setTags] = useState(initialTags);
265289
const [tempTags, setTempTags] = useState(initialTags);
266290
const [inputValue, setInputValue] = useState('');
@@ -510,7 +534,7 @@ const TagsInput = forwardRef(({
510534
}
511535
{
512536
showRemoveDomain &&
513-
<DeleteDomainConform proxy_id={proxy_id} domains={tags} showConform={handleDeleteClick} onClose={handleCloseClick} onDataChange={onDataChange} />
537+
<DeleteDomainConform proxy_id={proxy_id} domains={tags} showConform={handleDeleteClick} onClose={handleCloseClick} onDataChange={onDataChange} app_id={app_id} isMonitorApp={isMonitorApp} />
514538
}
515539
{
516540
showUpdateDomain &&

0 commit comments

Comments
 (0)