seeder-st2110-components 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { useState, useCallback, useEffect, memo, useMemo, useRef } from 'react';
2
2
  import { useWebSocket, useInterval } from 'ahooks';
3
- import { Tooltip, Space, Flex, Divider, App, Modal, Form, Input, Alert, message, Dropdown, Spin } from 'antd';
3
+ import { Tooltip, Space, Flex, Divider, App, Modal, Form, Input, Alert, message, Dropdown, Spin, InputNumber, ConfigProvider, Badge, Switch, Select, Typography } from 'antd';
4
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import { LoadingOutlined, ExclamationCircleFilled } from '@ant-design/icons';
6
6
  import axios from 'axios';
@@ -54,14 +54,15 @@ const UsageItem = /*#__PURE__*/memo(_ref => {
54
54
  iconClass,
55
55
  text,
56
56
  children,
57
- ram
57
+ showRam,
58
+ ramValue
58
59
  } = _ref;
59
60
  const tooltipContent = useMemo(() => /*#__PURE__*/jsx(Tooltip, {
60
61
  title: /*#__PURE__*/jsxs(Fragment, {
61
62
  children: [/*#__PURE__*/jsx("div", {
62
63
  children: text
63
- }), ram && /*#__PURE__*/jsxs("div", {
64
- children: ["Total Memory: ", ram, "GB"]
64
+ }), showRam && /*#__PURE__*/jsxs("div", {
65
+ children: ["Total Memory: ", ramValue, "GB"]
65
66
  })]
66
67
  }),
67
68
  destroyOnHidden: false,
@@ -86,7 +87,8 @@ const UsageItem = /*#__PURE__*/memo(_ref => {
86
87
  const getTemperature = (supermicro, sensors) => {
87
88
  return supermicro?.cpu_temperature ?? sensors?.temperatures?.coretemp?.[0]?.current;
88
89
  };
89
- const useHardwareUsage = ps_status => {
90
+ const useHardwareUsage = function (ps_status) {
91
+ let showRam = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
90
92
  return useMemo(() => {
91
93
  if (!ps_status || typeof ps_status !== 'object') return null;
92
94
  const {
@@ -109,7 +111,8 @@ const useHardwareUsage = ps_status => {
109
111
  }), mem && /*#__PURE__*/jsxs(UsageItem, {
110
112
  text: "Memory Usage",
111
113
  iconClass: "icon-shiyongshuai",
112
- ram: false,
114
+ showRam: showRam,
115
+ ramValue: (mem.total / (1024 * 1024 * 1024)).toFixed(1),
113
116
  children: [mem.percent, "%"]
114
117
  }), supermicro?.nic_temperature && /*#__PURE__*/jsxs(UsageItem, {
115
118
  text: "NIC Temperature",
@@ -1971,5 +1974,504 @@ SystemOperations.propTypes = {
1971
1974
  okText: PropTypes.string
1972
1975
  };
1973
1976
 
1974
- export { AuthorizationModal, SystemOperations, UpgradeManager, useAuth, useHardwareUsage, useHardwareWebSocket, useSystemOperations, useUpgrade };
1977
+ const defaultFieldConfigs = {
1978
+ clock_class: {
1979
+ label: 'Clock Class',
1980
+ formType: 'select',
1981
+ options: [{
1982
+ value: 6,
1983
+ label: 'Atomic Clock (6)'
1984
+ }, {
1985
+ value: 7,
1986
+ label: 'GPS (7)'
1987
+ }, {
1988
+ value: 248,
1989
+ label: 'Slave-Only (248)'
1990
+ }],
1991
+ readOnly: true
1992
+ },
1993
+ clock_accuracy: {
1994
+ label: 'Clock Accuracy',
1995
+ formType: 'number',
1996
+ readOnly: true
1997
+ },
1998
+ offset_scaled_log_variance: {
1999
+ label: 'Offset Scaled Log Variance',
2000
+ formType: 'number',
2001
+ readOnly: true
2002
+ },
2003
+ grandmaster_priority1: {
2004
+ label: 'Priority 1',
2005
+ formType: 'number',
2006
+ readOnly: true
2007
+ },
2008
+ grandmaster_priority2: {
2009
+ label: 'Priority 2',
2010
+ formType: 'number',
2011
+ readOnly: true
2012
+ },
2013
+ grandmaster_identity: {
2014
+ label: 'Grandmaster Identity',
2015
+ formType: 'text',
2016
+ readOnly: true
2017
+ },
2018
+ master_port_id: {
2019
+ label: 'Port Identity',
2020
+ formType: 'text',
2021
+ readOnly: true
2022
+ },
2023
+ t1_domain_number: {
2024
+ label: 'Domain',
2025
+ formType: 'number',
2026
+ min: 0,
2027
+ max: 127,
2028
+ readOnly: false
2029
+ },
2030
+ master_utc_offset: {
2031
+ label: 'UTC Offset',
2032
+ formType: 'number',
2033
+ readOnly: true
2034
+ },
2035
+ is_connected: {
2036
+ label: 'Connected Status',
2037
+ formType: 'badge',
2038
+ statusMap: {
2039
+ 0: {
2040
+ text: 'Disconnected',
2041
+ color: 'red'
2042
+ },
2043
+ 1: {
2044
+ text: 'Connected',
2045
+ color: 'green'
2046
+ }
2047
+ }
2048
+ },
2049
+ is_locked: {
2050
+ label: 'Locked Status',
2051
+ formType: 'badge',
2052
+ statusMap: {
2053
+ 0: {
2054
+ text: 'Unlocked',
2055
+ color: 'red'
2056
+ },
2057
+ 1: {
2058
+ text: 'Locked',
2059
+ color: 'green'
2060
+ }
2061
+ }
2062
+ }
2063
+ };
2064
+
2065
+ // 默认字段顺序
2066
+ const defaultFieldOrder = ['t1_domain_number', 'grandmaster_priority1', 'grandmaster_priority2', 'grandmaster_identity', 'master_port_id', 'clock_class', 'clock_accuracy', 'offset_scaled_log_variance', 'master_utc_offset', 'is_connected', 'is_locked'];
2067
+
2068
+ /**
2069
+ * 转换PTP状态为表单字段数组
2070
+ * @param {Object} ptpStatus PTP状态对象
2071
+ * @param {Object} fieldConfigs 字段配置
2072
+ * @param {Array} fieldOrder 字段顺序
2073
+ * @returns {Array} 表单字段数组
2074
+ */
2075
+ function convertPtpStatusToArray(ptpStatus, fieldConfigs, fieldOrder) {
2076
+ return fieldOrder.filter(key => key in ptpStatus).map(key => {
2077
+ const config = fieldConfigs[key] || {
2078
+ label: key,
2079
+ formType: 'text'
2080
+ };
2081
+ const value = ptpStatus[key];
2082
+ return {
2083
+ key,
2084
+ value,
2085
+ ...config,
2086
+ rawData: ptpStatus
2087
+ };
2088
+ });
2089
+ }
2090
+ const PtpModal = _ref => {
2091
+ let {
2092
+ open,
2093
+ onClose,
2094
+ getPtpInfo,
2095
+ updatePtpInfo,
2096
+ fieldConfigs = defaultFieldConfigs,
2097
+ fieldOrder = defaultFieldOrder,
2098
+ modalProps = {},
2099
+ formProps = {}
2100
+ } = _ref;
2101
+ const [ptpStatus, setPtpStatus] = useState(null);
2102
+ const [form] = Form.useForm();
2103
+ const {
2104
+ message
2105
+ } = App.useApp();
2106
+ useEffect(() => {
2107
+ if (open) {
2108
+ getPtpInfo().then(data => {
2109
+ if (data?.[0]) {
2110
+ setPtpStatus(data[0]);
2111
+ form.setFieldsValue(data[0]);
2112
+ }
2113
+ });
2114
+ }
2115
+ }, [open, form, getPtpInfo]);
2116
+ const ptpStatusArray = useMemo(() => {
2117
+ if (!ptpStatus) return [];
2118
+ return convertPtpStatusToArray(ptpStatus, fieldConfigs, fieldOrder);
2119
+ }, [ptpStatus]);
2120
+ const handleValueChange = changedValues => {
2121
+ if ('t1_domain_number' in changedValues) {
2122
+ setPtpStatus(prev => ({
2123
+ ...prev,
2124
+ t1_domain_number: changedValues.t1_domain_number
2125
+ }));
2126
+ }
2127
+ };
2128
+ const handleSubmit = async () => {
2129
+ try {
2130
+ const values = await form.validateFields();
2131
+ const response = await updatePtpInfo(values);
2132
+ if (response) {
2133
+ message.success('Success');
2134
+ setTimeout(() => {
2135
+ onClose();
2136
+ }, 1500);
2137
+ }
2138
+ } catch (error) {
2139
+ console.error('Update failed:', error);
2140
+ }
2141
+ };
2142
+ const renderFormItem = item => {
2143
+ switch (item.formType) {
2144
+ case 'select':
2145
+ return /*#__PURE__*/jsx(Select, {
2146
+ options: item.options,
2147
+ disabled: item.readOnly
2148
+ });
2149
+ case 'switch':
2150
+ return /*#__PURE__*/jsx(Switch, {});
2151
+ case 'badge':
2152
+ const normalizedValue = typeof item.value === 'boolean' ? item.value ? 1 : 0 : item.value;
2153
+ const status = item.statusMap?.[normalizedValue] || {
2154
+ text: 'Unknown',
2155
+ color: 'gray'
2156
+ };
2157
+ return /*#__PURE__*/jsx(ConfigProvider, {
2158
+ theme: {
2159
+ components: {
2160
+ Badge: {
2161
+ statusSize: 10
2162
+ }
2163
+ }
2164
+ },
2165
+ children: /*#__PURE__*/jsx(Badge, {
2166
+ color: status.color,
2167
+ text: status.text
2168
+ })
2169
+ });
2170
+ case 'number':
2171
+ return /*#__PURE__*/jsx(InputNumber, {
2172
+ disabled: item.readOnly,
2173
+ controls: false,
2174
+ keyboard: false,
2175
+ min: item.min ?? Number.MIN_SAFE_INTEGER,
2176
+ max: item.max ?? Number.MAX_SAFE_INTEGER
2177
+ });
2178
+ default:
2179
+ return /*#__PURE__*/jsx(Input, {
2180
+ disabled: item.readOnly
2181
+ });
2182
+ }
2183
+ };
2184
+ if (!open || !ptpStatus) return null;
2185
+
2186
+ // 合并默认模态框属性和传入的属性
2187
+ const mergedModalProps = {
2188
+ title: "PTP",
2189
+ width: 650,
2190
+ open,
2191
+ okText: "Apply",
2192
+ cancelText: "Close",
2193
+ onCancel: onClose,
2194
+ onOk: handleSubmit,
2195
+ ...modalProps
2196
+ };
2197
+
2198
+ // 合并默认表单属性和传入的属性
2199
+ const mergedFormProps = {
2200
+ form: form,
2201
+ name: "ptpForm",
2202
+ labelCol: {
2203
+ span: 8
2204
+ },
2205
+ wrapperCol: {
2206
+ span: 16
2207
+ },
2208
+ autoComplete: "off",
2209
+ onValuesChange: handleValueChange,
2210
+ ...formProps
2211
+ };
2212
+ return /*#__PURE__*/jsx(Modal, {
2213
+ ...mergedModalProps,
2214
+ children: /*#__PURE__*/jsx(Form, {
2215
+ ...mergedFormProps,
2216
+ children: ptpStatusArray.map(item => /*#__PURE__*/jsx(Form.Item, {
2217
+ label: item.label,
2218
+ name: item.key,
2219
+ initialValue: item.value,
2220
+ children: renderFormItem(item)
2221
+ }, item.key))
2222
+ })
2223
+ });
2224
+ };
2225
+ var PtpModal$1 = /*#__PURE__*/memo(PtpModal);
2226
+
2227
+ const NetworkFieldGroup = _ref => {
2228
+ let {
2229
+ prefix,
2230
+ interfaces,
2231
+ fieldConfig = {}
2232
+ } = _ref;
2233
+ const defaultFieldConfig = {
2234
+ name: {
2235
+ label: "Name",
2236
+ enabled: true
2237
+ },
2238
+ ip: {
2239
+ label: "IP Address",
2240
+ enabled: true
2241
+ },
2242
+ netmask: {
2243
+ label: "Netmask",
2244
+ enabled: prefix === "LAN"
2245
+ }
2246
+ };
2247
+ const mergedFieldConfig = {
2248
+ ...defaultFieldConfig,
2249
+ ...fieldConfig
2250
+ };
2251
+ return /*#__PURE__*/jsxs(Fragment, {
2252
+ children: [/*#__PURE__*/jsx(Typography.Title, {
2253
+ level: 5,
2254
+ style: {
2255
+ display: 'flex',
2256
+ justifyContent: 'space-between',
2257
+ alignItems: 'center',
2258
+ marginBottom: 16
2259
+ },
2260
+ children: prefix
2261
+ }), interfaces.map((iface, index) => /*#__PURE__*/jsxs("div", {
2262
+ children: [mergedFieldConfig.name.enabled && /*#__PURE__*/jsx(Form.Item, {
2263
+ label: mergedFieldConfig.name.label,
2264
+ name: [prefix, index, "display_name"],
2265
+ children: /*#__PURE__*/jsx(Input, {
2266
+ disabled: true
2267
+ })
2268
+ }), mergedFieldConfig.ip.enabled && /*#__PURE__*/jsx(Form.Item, {
2269
+ label: mergedFieldConfig.ip.label,
2270
+ name: [prefix, index, "ip_address"],
2271
+ children: /*#__PURE__*/jsx(Input, {})
2272
+ }), mergedFieldConfig.netmask.enabled && /*#__PURE__*/jsx(Form.Item, {
2273
+ label: mergedFieldConfig.netmask.label,
2274
+ name: [prefix, index, "netmask"],
2275
+ children: /*#__PURE__*/jsx(Input, {})
2276
+ }), index < interfaces.length - 1 && /*#__PURE__*/jsx(Divider, {
2277
+ style: {
2278
+ marginBlock: 16
2279
+ }
2280
+ })]
2281
+ }, iface.id || index))]
2282
+ });
2283
+ };
2284
+ const NetworkSettingsModal = _ref2 => {
2285
+ let {
2286
+ open,
2287
+ onClose,
2288
+ getLanConfig,
2289
+ getSysConfig,
2290
+ updateLanConfig,
2291
+ updateSysConfig,
2292
+ restart,
2293
+ modalProps = {},
2294
+ formProps = {},
2295
+ fieldConfig = {},
2296
+ sections = ['LAN', 'QSFP']
2297
+ } = _ref2;
2298
+ const {
2299
+ message,
2300
+ modal
2301
+ } = App.useApp();
2302
+ const [form] = Form.useForm();
2303
+ const [st2110Interfaces, setSt2110Interfaces] = useState([]);
2304
+ const [lanConfigs, setLanConfigs] = useState([]);
2305
+ const [submitLoading, setSubmitLoading] = useState(false);
2306
+ useEffect(() => {
2307
+ const fetchInitialData = async () => {
2308
+ try {
2309
+ const promises = [];
2310
+ if (sections.includes('LAN')) {
2311
+ promises.push(getLanConfig());
2312
+ }
2313
+ if (sections.includes('QSFP')) {
2314
+ promises.push(getSysConfig());
2315
+ }
2316
+ const results = await Promise.allSettled(promises);
2317
+ if (sections.includes('LAN')) {
2318
+ const lanResult = results[sections.indexOf('LAN')];
2319
+ if (lanResult.status === 'fulfilled') {
2320
+ setLanConfigs(lanResult.value);
2321
+ }
2322
+ }
2323
+ if (sections.includes('QSFP')) {
2324
+ const sysResult = results[sections.indexOf('QSFP')];
2325
+ if (sysResult.status === 'fulfilled' && sysResult.value) {
2326
+ setSt2110Interfaces(sysResult.value.st2110_interfaces || []);
2327
+ }
2328
+ }
2329
+ } catch (error) {
2330
+ console.error('Failed to fetch data:', error);
2331
+ }
2332
+ };
2333
+ if (open) {
2334
+ fetchInitialData();
2335
+ }
2336
+ }, [open, getLanConfig, getSysConfig, sections]);
2337
+
2338
+ // 动态初始值配置
2339
+ const initialValues = useMemo(() => {
2340
+ const values = {};
2341
+ if (sections.includes('LAN')) {
2342
+ values.LAN = lanConfigs.map(config => ({
2343
+ connection_id: config.connection_id,
2344
+ display_name: config.display_name,
2345
+ ip_address: config.ip_address,
2346
+ netmask: config.netmask
2347
+ })) ?? [];
2348
+ }
2349
+ if (sections.includes('QSFP')) {
2350
+ values.QSFP = st2110Interfaces?.map(iface => ({
2351
+ id: iface.id,
2352
+ display_name: iface.display_name,
2353
+ ip_address: iface.ip_address
2354
+ })) ?? [];
2355
+ }
2356
+ return values;
2357
+ }, [lanConfigs, st2110Interfaces, sections]);
2358
+ const handleSuccess = async function () {
2359
+ let isPopup = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : true;
2360
+ let messageText = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'Success';
2361
+ message.success(messageText);
2362
+ if (isPopup) {
2363
+ try {
2364
+ const updatedConfig = await getSysConfig();
2365
+ if (updatedConfig && updatedConfig.is_restart_required) {
2366
+ modal.confirm({
2367
+ icon: /*#__PURE__*/jsx(ExclamationCircleFilled, {}),
2368
+ title: "Configuration modified. Restart to apply changes?",
2369
+ cancelText: "No",
2370
+ okText: "Yes",
2371
+ onOk: () => restart()
2372
+ });
2373
+ }
2374
+ } catch (error) {
2375
+ console.error('Failed to check restart status:', error);
2376
+ }
2377
+ }
2378
+ onClose();
2379
+ };
2380
+ const handleSubmit = async () => {
2381
+ setSubmitLoading(true);
2382
+ try {
2383
+ const values = await form.validateFields();
2384
+ const updatePromises = [];
2385
+
2386
+ // 更新LAN配置
2387
+ if (sections.includes('LAN') && values.LAN) {
2388
+ const lanData = values.LAN.map((item, index) => ({
2389
+ connection_id: lanConfigs[index]?.connection_id,
2390
+ ip_address: item.ip_address,
2391
+ netmask: item.netmask
2392
+ }));
2393
+ updatePromises.push(updateLanConfig(lanData));
2394
+ }
2395
+
2396
+ // 更新QSFP配置
2397
+ if (sections.includes('QSFP') && values.QSFP) {
2398
+ const st2110Data = {
2399
+ st2110_interfaces: values.QSFP.map((item, index) => ({
2400
+ id: st2110Interfaces?.[index]?.id,
2401
+ ip_address: item.ip_address,
2402
+ enable_rx_video_demand_start: st2110Interfaces?.[index]?.enable_rx_video_demand_start
2403
+ }))
2404
+ };
2405
+ updatePromises.push(updateSysConfig(st2110Data));
2406
+ }
2407
+ const results = await Promise.allSettled(updatePromises);
2408
+
2409
+ // 检查所有更新是否成功
2410
+ const allSucceeded = results.every(result => result.status === 'fulfilled');
2411
+ if (allSucceeded) {
2412
+ handleSuccess();
2413
+ } else {
2414
+ message.error('Some configurations failed to update');
2415
+ }
2416
+ } catch (error) {
2417
+ console.error('Failed to update configurations: ', error);
2418
+ message.error('Failed to update configurations');
2419
+ } finally {
2420
+ setSubmitLoading(false);
2421
+ }
2422
+ };
2423
+
2424
+ // 合并默认模态框属性和传入的属性
2425
+ const mergedModalProps = {
2426
+ title: "Network Settings",
2427
+ width: 650,
2428
+ open,
2429
+ confirmLoading: submitLoading,
2430
+ onOk: handleSubmit,
2431
+ onCancel: onClose,
2432
+ okText: "Apply",
2433
+ cancelText: "Close",
2434
+ centered: true,
2435
+ styles: {
2436
+ body: {
2437
+ padding: "16px 24px 8px 24px"
2438
+ }
2439
+ },
2440
+ ...modalProps
2441
+ };
2442
+
2443
+ // 合并默认表单属性和传入的属性
2444
+ const mergedFormProps = {
2445
+ form: form,
2446
+ initialValues: initialValues,
2447
+ labelCol: {
2448
+ span: 6
2449
+ },
2450
+ wrapperCol: {
2451
+ span: 18
2452
+ },
2453
+ autoComplete: "off",
2454
+ ...formProps
2455
+ };
2456
+ return /*#__PURE__*/jsx(Modal, {
2457
+ ...mergedModalProps,
2458
+ children: /*#__PURE__*/jsxs(Form, {
2459
+ ...mergedFormProps,
2460
+ children: [sections.includes('LAN') && initialValues.LAN && initialValues.LAN.length > 0 && /*#__PURE__*/jsxs(Fragment, {
2461
+ children: [/*#__PURE__*/jsx(NetworkFieldGroup, {
2462
+ prefix: "LAN",
2463
+ interfaces: initialValues.LAN,
2464
+ fieldConfig: fieldConfig.LAN
2465
+ }), sections.includes('QSFP') && /*#__PURE__*/jsx(Divider, {})]
2466
+ }), sections.includes('QSFP') && initialValues.QSFP && initialValues.QSFP.length > 0 && /*#__PURE__*/jsx(NetworkFieldGroup, {
2467
+ prefix: "QSFP",
2468
+ interfaces: initialValues.QSFP,
2469
+ fieldConfig: fieldConfig.QSFP
2470
+ })]
2471
+ })
2472
+ });
2473
+ };
2474
+ var NetworkSettingsModal$1 = /*#__PURE__*/memo(NetworkSettingsModal);
2475
+
2476
+ export { AuthorizationModal, NetworkSettingsModal$1 as NetworkSettingsModal, PtpModal$1 as PtpModal, SystemOperations, UpgradeManager, useAuth, useHardwareUsage, useHardwareWebSocket, useSystemOperations, useUpgrade };
1975
2477
  //# sourceMappingURL=index.esm.js.map