seeder-st2110-components 1.0.2 → 1.0.4

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