UNPKG

mirakurun

Version:

DVR Tuner Server for Japanese TV.

606 lines (581 loc) 216 kB
/******/ (() => { // webpackBootstrap /******/ "use strict"; /******/ var __webpack_modules__ = ({ /***/ "./node_modules/css-loader/dist/cjs.js!./src/ui/components/HeartView.css": /*!*******************************************************************************!*\ !*** ./node_modules/css-loader/dist/cjs.js!./src/ui/components/HeartView.css ***! \*******************************************************************************/ /***/ ((module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../node_modules/css-loader/dist/runtime/cssWithMappingToString.js */ "./node_modules/css-loader/dist/runtime/cssWithMappingToString.js"); /* harmony import */ var _node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../node_modules/css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js"); /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__); // Imports var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0___default())); // Module ___CSS_LOADER_EXPORT___.push([module.id, "/*\r\n Copyright 2021 kanreisa\r\n\r\n Licensed under the Apache License, Version 2.0 (the \"License\");\r\n you may not use this file except in compliance with the License.\r\n You may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n Unless required by applicable law or agreed to in writing, software\r\n distributed under the License is distributed on an \"AS IS\" BASIS,\r\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n See the License for the specific language governing permissions and\r\n limitations under the License.\r\n*/\r\n.heart-view > div.consent {\r\n margin: 16px 32px;\r\n max-width: 450px;\r\n}\r\n\r\n.heart-view > .ms-Stack > span,\r\n.heart-view > .ms-Stack img {\r\n margin: 8px 16px;\r\n}\r\n\r\n.heart-view img {\r\n display: inline-block;\r\n}\r\n", "",{"version":3,"sources":["webpack://./src/ui/components/HeartView.css"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;CAcC;AACD;IACI,iBAAiB;IACjB,gBAAgB;AACpB;;AAEA;;IAEI,gBAAgB;AACpB;;AAEA;IACI,qBAAqB;AACzB","sourcesContent":["/*\r\n Copyright 2021 kanreisa\r\n\r\n Licensed under the Apache License, Version 2.0 (the \"License\");\r\n you may not use this file except in compliance with the License.\r\n You may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n Unless required by applicable law or agreed to in writing, software\r\n distributed under the License is distributed on an \"AS IS\" BASIS,\r\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n See the License for the specific language governing permissions and\r\n limitations under the License.\r\n*/\r\n.heart-view > div.consent {\r\n margin: 16px 32px;\r\n max-width: 450px;\r\n}\r\n\r\n.heart-view > .ms-Stack > span,\r\n.heart-view > .ms-Stack img {\r\n margin: 8px 16px;\r\n}\r\n\r\n.heart-view img {\r\n display: inline-block;\r\n}\r\n"],"sourceRoot":""}]); // Exports /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___); /***/ }), /***/ "./node_modules/css-loader/dist/cjs.js!./src/ui/components/Logs.css": /*!**************************************************************************!*\ !*** ./node_modules/css-loader/dist/cjs.js!./src/ui/components/Logs.css ***! \**************************************************************************/ /***/ ((module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../../node_modules/css-loader/dist/runtime/cssWithMappingToString.js */ "./node_modules/css-loader/dist/runtime/cssWithMappingToString.js"); /* harmony import */ var _node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../../node_modules/css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js"); /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__); // Imports var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0___default())); // Module ___CSS_LOADER_EXPORT___.push([module.id, "/*\r\n Copyright 2020 kanreisa\r\n\r\n Licensed under the Apache License, Version 2.0 (the \"License\");\r\n you may not use this file except in compliance with the License.\r\n You may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n Unless required by applicable law or agreed to in writing, software\r\n distributed under the License is distributed on an \"AS IS\" BASIS,\r\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n See the License for the specific language governing permissions and\r\n limitations under the License.\r\n*/\r\ndiv.logs {\r\n overflow: scroll;\r\n height: calc(100vh - 300px);\r\n box-sizing: border-box;\r\n padding: 8px 0;\r\n font-family: 'Courier New', Courier, monospace;\r\n font-size: 12px;\r\n border: 2px solid #605e5c;\r\n background: #292827;\r\n color: #bbb;\r\n}\r\n\r\ndiv.logs > div {\r\n padding: 2px 16px;\r\n word-break: break-all;\r\n white-space: break-spaces;\r\n}\r\n\r\ndiv.logs > div.latest {\r\n padding: 0;\r\n}\r\n\r\ndiv.logs > div:hover {\r\n background: #1b1a19;\r\n}\r\n\r\ndiv.logs > div.level-debug {\r\n color: #a098e5;\r\n}\r\n\r\ndiv.logs > div.level-info {\r\n color: #eee;\r\n}\r\n\r\ndiv.logs > div.type-create {\r\n color: #c3d825;\r\n}\r\n\r\ndiv.logs > div.level-warn,\r\ndiv.logs > div.type-update {\r\n color: #f6ad49;\r\n}\r\n\r\ndiv.logs > div.level-error,\r\ndiv.logs > div.type-remove {\r\n color: #e95464;\r\n}\r\n\r\ndiv.logs > div.level-fatal {\r\n color: #fff;\r\n background: #c9171e;\r\n}\r\n", "",{"version":3,"sources":["webpack://./src/ui/components/Logs.css"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;CAcC;AACD;IACI,gBAAgB;IAChB,2BAA2B;IAC3B,sBAAsB;IACtB,cAAc;IACd,8CAA8C;IAC9C,eAAe;IACf,yBAAyB;IACzB,mBAAmB;IACnB,WAAW;AACf;;AAEA;IACI,iBAAiB;IACjB,qBAAqB;IACrB,yBAAyB;AAC7B;;AAEA;IACI,UAAU;AACd;;AAEA;IACI,mBAAmB;AACvB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,WAAW;AACf;;AAEA;IACI,cAAc;AAClB;;AAEA;;IAEI,cAAc;AAClB;;AAEA;;IAEI,cAAc;AAClB;;AAEA;IACI,WAAW;IACX,mBAAmB;AACvB","sourcesContent":["/*\r\n Copyright 2020 kanreisa\r\n\r\n Licensed under the Apache License, Version 2.0 (the \"License\");\r\n you may not use this file except in compliance with the License.\r\n You may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n Unless required by applicable law or agreed to in writing, software\r\n distributed under the License is distributed on an \"AS IS\" BASIS,\r\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n See the License for the specific language governing permissions and\r\n limitations under the License.\r\n*/\r\ndiv.logs {\r\n overflow: scroll;\r\n height: calc(100vh - 300px);\r\n box-sizing: border-box;\r\n padding: 8px 0;\r\n font-family: 'Courier New', Courier, monospace;\r\n font-size: 12px;\r\n border: 2px solid #605e5c;\r\n background: #292827;\r\n color: #bbb;\r\n}\r\n\r\ndiv.logs > div {\r\n padding: 2px 16px;\r\n word-break: break-all;\r\n white-space: break-spaces;\r\n}\r\n\r\ndiv.logs > div.latest {\r\n padding: 0;\r\n}\r\n\r\ndiv.logs > div:hover {\r\n background: #1b1a19;\r\n}\r\n\r\ndiv.logs > div.level-debug {\r\n color: #a098e5;\r\n}\r\n\r\ndiv.logs > div.level-info {\r\n color: #eee;\r\n}\r\n\r\ndiv.logs > div.type-create {\r\n color: #c3d825;\r\n}\r\n\r\ndiv.logs > div.level-warn,\r\ndiv.logs > div.type-update {\r\n color: #f6ad49;\r\n}\r\n\r\ndiv.logs > div.level-error,\r\ndiv.logs > div.type-remove {\r\n color: #e95464;\r\n}\r\n\r\ndiv.logs > div.level-fatal {\r\n color: #fff;\r\n background: #c9171e;\r\n}\r\n"],"sourceRoot":""}]); // Exports /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___); /***/ }), /***/ "./node_modules/css-loader/dist/cjs.js!./src/ui/index.css": /*!****************************************************************!*\ !*** ./node_modules/css-loader/dist/cjs.js!./src/ui/index.css ***! \****************************************************************/ /***/ ((module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var _node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/cssWithMappingToString.js */ "./node_modules/css-loader/dist/runtime/cssWithMappingToString.js"); /* harmony import */ var _node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ../../node_modules/css-loader/dist/runtime/api.js */ "./node_modules/css-loader/dist/runtime/api.js"); /* harmony import */ var _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(_node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1__); /* harmony import */ var _node_modules_css_loader_dist_cjs_js_node_modules_fluentui_react_dist_css_fabric_min_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! -!../../node_modules/css-loader/dist/cjs.js!../../node_modules/@fluentui/react/dist/css/fabric.min.css */ "./node_modules/css-loader/dist/cjs.js!./node_modules/@fluentui/react/dist/css/fabric.min.css"); // Imports var ___CSS_LOADER_EXPORT___ = _node_modules_css_loader_dist_runtime_api_js__WEBPACK_IMPORTED_MODULE_1___default()((_node_modules_css_loader_dist_runtime_cssWithMappingToString_js__WEBPACK_IMPORTED_MODULE_0___default())); ___CSS_LOADER_EXPORT___.i(_node_modules_css_loader_dist_cjs_js_node_modules_fluentui_react_dist_css_fabric_min_css__WEBPACK_IMPORTED_MODULE_2__["default"]); // Module ___CSS_LOADER_EXPORT___.push([module.id, "/*\r\n Copyright 2020 kanreisa\r\n\r\n Licensed under the Apache License, Version 2.0 (the \"License\");\r\n you may not use this file except in compliance with the License.\r\n You may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n Unless required by applicable law or agreed to in writing, software\r\n distributed under the License is distributed on an \"AS IS\" BASIS,\r\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n See the License for the specific language governing permissions and\r\n limitations under the License.\r\n*/\r\n\r\nbody {\r\n background: #25272e;\r\n}\r\n\r\n.ms-Fabric {\r\n color: #ebebeb;\r\n}\r\n\r\n.ms-layer {\r\n display: none;\r\n}\r\n\r\ninput::placeholder {\r\n color: #686b77 !important;\r\n}\r\n", "",{"version":3,"sources":["webpack://./src/ui/index.css"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;CAcC;;AAGD;IACI,mBAAmB;AACvB;;AAEA;IACI,cAAc;AAClB;;AAEA;IACI,aAAa;AACjB;;AAEA;IACI,yBAAyB;AAC7B","sourcesContent":["/*\r\n Copyright 2020 kanreisa\r\n\r\n Licensed under the Apache License, Version 2.0 (the \"License\");\r\n you may not use this file except in compliance with the License.\r\n You may obtain a copy of the License at\r\n\r\n http://www.apache.org/licenses/LICENSE-2.0\r\n\r\n Unless required by applicable law or agreed to in writing, software\r\n distributed under the License is distributed on an \"AS IS\" BASIS,\r\n WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r\n See the License for the specific language governing permissions and\r\n limitations under the License.\r\n*/\r\n@import \"@fluentui/react/dist/css/fabric.min.css\";\r\n\r\nbody {\r\n background: #25272e;\r\n}\r\n\r\n.ms-Fabric {\r\n color: #ebebeb;\r\n}\r\n\r\n.ms-layer {\r\n display: none;\r\n}\r\n\r\ninput::placeholder {\r\n color: #686b77 !important;\r\n}\r\n"],"sourceRoot":""}]); // Exports /* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (___CSS_LOADER_EXPORT___); /***/ }), /***/ "./src/ui/components/ChannelsConfigurator.tsx": /*!****************************************************!*\ !*** ./src/ui/components/ChannelsConfigurator.tsx ***! \****************************************************/ /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { __webpack_require__.r(__webpack_exports__); /* harmony export */ __webpack_require__.d(__webpack_exports__, { /* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__) /* harmony export */ }); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! react */ "./node_modules/react/index.js"); /* harmony import */ var react__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_0__); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/utilities/lib/selection/Selection.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Toggle/Toggle.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/TextField/TextField.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Dropdown/Dropdown.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Stack/Stack.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Button/IconButton/IconButton.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Button/ActionButton/ActionButton.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Spinner/Spinner.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Spinner/Spinner.types.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/ProgressIndicator/ProgressIndicator.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/DetailsList/DetailsList.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/utilities/lib/selection/Selection.types.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Button/PrimaryButton/PrimaryButton.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Button/DefaultButton/DefaultButton.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Dialog/Dialog.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Dialog/DialogContent.types.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/Dialog/DialogFooter.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_18__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/MessageBar/MessageBar.js"); /* harmony import */ var _fluentui_react__WEBPACK_IMPORTED_MODULE_19__ = __webpack_require__(/*! @fluentui/react */ "./node_modules/@fluentui/react/lib/components/MessageBar/MessageBar.types.js"); const configAPI = "/api/config/channels"; const columns = [ { key: "col-enable", name: "Enable", fieldName: "enable", minWidth: 44, maxWidth: 44 }, { key: "col-name", name: "Name", fieldName: "name", minWidth: 100, maxWidth: 100 }, { key: "col-type", name: "Type", fieldName: "type", minWidth: 65, maxWidth: 65 }, { key: "col-channel", name: "Channel", fieldName: "channel", minWidth: 70, maxWidth: 70 }, { key: "col-options", name: "Options", fieldName: "options", minWidth: 200, }, { key: "col-controls", name: "", fieldName: "controls", minWidth: 120, maxWidth: 120 } ]; const dummySelection = new _fluentui_react__WEBPACK_IMPORTED_MODULE_1__.Selection(); const typesIndex = ["GR", "BS", "CS", "SKY"]; function sortTypes(types) { return types.sort((a, b) => typesIndex.indexOf(a) - typesIndex.indexOf(b)); } const Configurator = ({ uiState, uiStateEvents }) => { const [current, setCurrent] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null); const [editing, setEditing] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null); const [showSaveDialog, setShowSaveDialog] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); const [saved, setSaved] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); const [showScanDialog, setShowScanDialog] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); const [scanType, setScanType] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)("GR"); const [scanMinCh, setScanMinCh] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)("13"); const [scanMaxCh, setScanMaxCh] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)("62"); const [scanSkipCh, setScanSkipCh] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(""); const [scanMinSubCh, setScanMinSubCh] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)("0"); const [scanMaxSubCh, setScanMaxSubCh] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)("3"); const [scanUseSubCh, setScanUseSubCh] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(true); const [scanChannelNameFormatEnabled, setScanChannelNameFormatEnabled] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); const [scanChannelNameFormat, setScanChannelNameFormat] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(""); const [scanSetDisabledOnAdd, setScanSetDisabledOnAdd] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); const [scanAutoApply, setScanAutoApply] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); const [scanRefresh, setScanRefresh] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); const [scanStatus, setScanStatus] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(null); const [scanInProgress, setScanInProgress] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); const [showScanResultDialog, setShowScanResultDialog] = (0,react__WEBPACK_IMPORTED_MODULE_0__.useState)(false); const listContainerRef = (0,react__WEBPACK_IMPORTED_MODULE_0__.useRef)(null); const fetchScanStatus = async () => { try { const res = await (await fetch("/api/config/channels/scan")).json(); console.log("ChannelsConfigurator", "GET", "/api/config/channels/scan", "->", res); setScanStatus(res); setScanInProgress(res.isScanning); if (res.status === "completed" && scanInProgress && !res.isScanning) { setShowScanResultDialog(true); setScanInProgress(false); } } catch (e) { console.error("Failed to fetch scan status:", e); } }; const expandChannelRanges = (input) => { if (!input) return ""; const parts = input.split(","); const result = []; for (const part of parts) { if (part.includes("-")) { const [start, end] = part.split("-").map(n => parseInt(n.trim(), 10)); if (!isNaN(start) && !isNaN(end)) { for (let i = start; i <= end; i++) { result.push(i); } } } else { const num = parseInt(part.trim(), 10); if (!isNaN(num)) { result.push(num); } } } return [...new Set(result)].sort((a, b) => a - b).join(","); }; const startScan = async () => { try { const params = new URLSearchParams(); params.append("type", scanType); params.append("minCh", scanMinCh); params.append("maxCh", scanMaxCh); if (scanSkipCh.trim()) { const expandedSkipCh = expandChannelRanges(scanSkipCh.trim()); params.append("skipCh", expandedSkipCh); } if (scanType === "BS" && scanUseSubCh) { params.append("minSubCh", scanMinSubCh); params.append("maxSubCh", scanMaxSubCh); params.append("useSubCh", "true"); } if (!scanAutoApply) { params.append("dryRun", "true"); } if (scanChannelNameFormatEnabled && scanChannelNameFormat.trim()) { params.append("channelNameFormat", scanChannelNameFormat.trim()); } params.append("setDisabledOnAdd", scanSetDisabledOnAdd ? "true" : "false"); if (scanRefresh) { params.append("refresh", "true"); } params.append("async", "true"); const url = `/api/config/channels/scan?${params.toString()}`; console.log("ChannelsConfigurator", "PUT", url); const response = await fetch(url, { method: "PUT" }); const result = await response.json(); if (response.status === 202) { console.log("Scan started:", result); setScanInProgress(true); setShowScanDialog(false); await fetchScanStatus(); } else { console.error("Failed to start scan:", result); } } catch (e) { console.error("Error starting scan:", e); } }; const stopScan = async () => { try { const response = await fetch("/api/config/channels/scan", { method: "DELETE" }); console.log("ChannelsConfigurator", "DELETE", "/api/config/channels/scan", "->", await response.json()); setScanInProgress(false); } catch (e) { console.error("Error stopping scan:", e); } }; const applyScanResult = () => { if (scanStatus && scanStatus.result) { setEditing(JSON.parse(JSON.stringify(scanStatus.result))); setShowScanResultDialog(false); } }; (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { if (saved === true) { setTimeout(() => { uiStateEvents.emit("notify:restart-required"); }, 500); setSaved(false); return; } (async () => { try { const res = await (await fetch(configAPI)).json(); console.log("ChannelsConfigurator", "GET", configAPI, "->", res); setEditing(JSON.parse(JSON.stringify(res))); setCurrent(JSON.parse(JSON.stringify(res))); } catch (e) { console.error(e); } })(); }, [saved]); (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { fetchScanStatus(); }, [current]); (0,react__WEBPACK_IMPORTED_MODULE_0__.useEffect)(() => { let intervalId; if (scanInProgress) { intervalId = setInterval(fetchScanStatus, 5000); } else { intervalId = setInterval(fetchScanStatus, 30000); } return () => { if (intervalId) { clearInterval(intervalId); } }; }, [scanInProgress]); const items = []; editing?.forEach((ch, i) => { const item = { key: `item${i}`, enable: (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_2__.Toggle, { label: ch.isDisabled ? "OFF" : "ON", checked: !ch.isDisabled, onChange: (ev, checked) => { ch.isDisabled = !checked; setEditing([...editing]); }, style: { marginTop: 6 } })), name: (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_3__.TextField, { label: "Name", value: ch.name, onChange: (ev, newValue) => { ch.name = newValue; setEditing([...editing]); }, onBlur: () => { if (ch.name === "") { ch.name = `ch${i}`; setEditing([...editing]); } } })), type: (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_4__.Dropdown, { label: "Type", options: [ { key: "GR", text: "GR" }, { key: "BS", text: "BS" }, { key: "CS", text: "CS" }, { key: "SKY", text: "SKY" } ], selectedKey: ch.type, onChange: (ev, option) => { ch.type = option.key; setEditing([...editing]); } })), channel: (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_3__.TextField, { label: "Channel", value: ch.channel, onChange: (ev, newValue) => { ch.channel = newValue; setEditing([...editing]); }, onBlur: () => { if (ch.channel === "") { ch.channel = "0"; setEditing([...editing]); } } })), options: (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack, { tokens: { childrenGap: "8 0" } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack, { horizontal: true, tokens: { childrenGap: "0 8" } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_3__.TextField, { style: { width: 55 }, label: "Service ID", value: `${ch.serviceId || ""}`, onChange: (ev, newValue) => { if (newValue === "") { delete ch.serviceId; } else if (/^[0-9]+$/.test(newValue)) { const sid = parseInt(newValue, 10); if (sid <= 65535 && sid > 0) { ch.serviceId = sid; } } setEditing([...editing]); } }), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_3__.TextField, { style: { width: 55 }, label: "TsmfRelTs", value: `${ch.tsmfRelTs || ""}`, onChange: (ev, newValue) => { if (newValue === "") { delete ch.tsmfRelTs; } else if (/^[0-9]+$/.test(newValue)) { const tsmfRelTs = parseInt(newValue, 10); ch.tsmfRelTs = tsmfRelTs; } setEditing([...editing]); } }), react__WEBPACK_IMPORTED_MODULE_0__.createElement("div", { style: { flexGrow: 1 } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement("div", { style: { marginBottom: 5 } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement("label", { style: { fontSize: 14, fontWeight: 600, paddingTop: 5, paddingBottom: 0, display: "block" } }, "Command Vars")), (() => { if ((ch.satellite || ch.space !== undefined || ch.freq !== undefined || ch.polarity) && (!ch.commandVars || Object.keys(ch.commandVars).length === 0)) { if (!ch.commandVars) ch.commandVars = {}; if (ch.satellite) { ch.commandVars["satellite"] = ch.satellite; } if (ch.space !== undefined) { ch.commandVars["space"] = ch.space; } if (ch.freq !== undefined) { ch.commandVars["freq"] = ch.freq; } if (ch.polarity) { ch.commandVars["polarity"] = ch.polarity; } } return null; })(), react__WEBPACK_IMPORTED_MODULE_0__.createElement("div", { style: { display: "flex", flexWrap: "wrap", gap: 4, marginTop: 1 } }, ch.commandVars && Object.entries(ch.commandVars).map(([key, value], idx) => (react__WEBPACK_IMPORTED_MODULE_0__.createElement("div", { key: `cmd-arg-${idx}`, style: { display: "inline-flex", alignItems: "center", marginBottom: 4 } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement("div", { style: { border: "1px solid #f3f2f1", padding: "0 4px", borderRadius: 2, display: "flex", backgroundColor: "#ffffff" } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_3__.TextField, { borderless: true, style: { width: 70, display: "inline-block", margin: 0 }, value: key, onChange: (ev, newKey) => { if (!ch.commandVars) ch.commandVars = {}; const updatedVars = {}; Object.entries(ch.commandVars).forEach(([k, v]) => { if (k === key) { updatedVars[newKey || ""] = v; } else { updatedVars[k] = v; } }); ch.commandVars = updatedVars; setEditing([...editing]); } }), react__WEBPACK_IMPORTED_MODULE_0__.createElement("span", { style: { margin: "0 4px", display: "flex", alignItems: "center" } }, ":"), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_3__.TextField, { borderless: true, style: { width: 70, display: "inline-block", margin: 0 }, value: `${value}`, onChange: (ev, newValue) => { if (!ch.commandVars) ch.commandVars = {}; if (newValue === "") { ch.commandVars[key] = ""; } else if (newValue === "0") { ch.commandVars[key] = 0; } else if (/^[0-9]+(\.[0-9]+)?$/.test(newValue)) { ch.commandVars[key] = parseFloat(newValue); } else { ch.commandVars[key] = newValue; } setEditing([...editing]); } })), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_6__.IconButton, { iconProps: { iconName: "Cancel" }, title: "Remove", style: { height: 24, width: 24 }, onClick: () => { if (!ch.commandVars) return; delete ch.commandVars[key]; if (Object.keys(ch.commandVars).length === 0) { delete ch.commandVars; } setEditing([...editing]); } })))), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_7__.ActionButton, { iconProps: { iconName: "Add" }, text: "Add", style: { height: 32, padding: "0 8px" }, onClick: () => { if (!ch.commandVars) { ch.commandVars = {}; } let newKey = "arg"; let counter = 1; while (ch.commandVars[newKey] !== undefined) { newKey = `arg${counter}`; counter++; } ch.commandVars[newKey] = ""; setEditing([...editing]); } })))))), controls: (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack, { horizontal: true, horizontalAlign: "end" }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_6__.IconButton, { disabled: i === 0, style: { opacity: i === 0 ? 0 : 1 }, title: "Up", iconProps: { iconName: "Up" }, onClick: () => { editing.splice(i, 1); editing.splice(i - 1, 0, ch); setEditing([...editing]); } }), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_6__.IconButton, { disabled: i === editing.length - 1, style: { opacity: i === editing.length - 1 ? 0 : 1 }, title: "Down", iconProps: { iconName: "Down" }, onClick: () => { editing.splice(i, 1); editing.splice(i + 1, 0, ch); setEditing([...editing]); } }), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_6__.IconButton, { title: "Controls", iconProps: { iconName: "More" }, menuProps: { items: [{ key: "remove", text: "Remove Channel", iconProps: { iconName: "Delete" }, onClick: () => { editing.splice(i, 1); setEditing([...editing]); } }] } }))) }; items.push(item); }); const changed = JSON.stringify(current) !== JSON.stringify(editing); if (listContainerRef.current) { listContainerRef.current.style.maxHeight = "calc(100vh - 410px)"; } return (react__WEBPACK_IMPORTED_MODULE_0__.createElement(react__WEBPACK_IMPORTED_MODULE_0__.Fragment, null, !current && react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_8__.Spinner, { size: _fluentui_react__WEBPACK_IMPORTED_MODULE_9__.SpinnerSize.large }), editing && react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack, { tokens: { childrenGap: "8 0" } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack, { horizontal: true, tokens: { childrenGap: "0 8" } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack.Item, null, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_7__.ActionButton, { text: "Add Channel", iconProps: { iconName: "Add" }, onClick: () => { const i = editing.length; editing.push({ name: `ch${i}`, type: "GR", channel: "0", isDisabled: true }); setEditing([...editing]); setTimeout(() => { listContainerRef.current.scrollTop = listContainerRef.current.scrollHeight; }, 0); } })), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack.Item, null, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_7__.ActionButton, { text: "Channel Scan", iconProps: { iconName: "Search" }, onClick: () => setShowScanDialog(true), disabled: scanInProgress })), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack.Item, null, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_7__.ActionButton, { text: scanInProgress ? "Scanning..." : "Get Scan Status", iconProps: { iconName: "Refresh" }, onClick: fetchScanStatus })), scanStatus && scanStatus.scanLog && scanStatus.scanLog.length > 0 && (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack.Item, null, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_7__.ActionButton, { text: "View Scan Results", iconProps: { iconName: "TextDocument" }, onClick: () => setShowScanResultDialog(true) }))), scanStatus?.status === "completed" && scanStatus.result && !scanInProgress && (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack.Item, null, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_7__.ActionButton, { text: "Apply Scan Results", iconProps: { iconName: "CheckMark" }, onClick: applyScanResult }))), scanInProgress && (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack.Item, null, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_7__.ActionButton, { text: "Stop Scan", iconProps: { iconName: "Stop" }, onClick: stopScan })))), scanInProgress && scanStatus && (react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack, { tokens: { childrenGap: "8 0" } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_10__.ProgressIndicator, { label: `Scanning ${scanStatus.type} channels...`, description: `Current Channel: ${scanStatus.currentChannel || "Initializing..."}`, percentComplete: scanStatus.progress / 100 }), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack, { horizontal: true, verticalAlign: "center" }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_8__.Spinner, { size: _fluentui_react__WEBPACK_IMPORTED_MODULE_9__.SpinnerSize.small, labelPosition: "right", label: `New: ${scanStatus.newCount}, Takeover: ${scanStatus.takeoverCount}` })))), react__WEBPACK_IMPORTED_MODULE_0__.createElement("div", { ref: listContainerRef, style: { overflowY: "scroll" } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_11__.DetailsList, { setKey: "items", items: items, columns: columns, selection: dummySelection, selectionMode: _fluentui_react__WEBPACK_IMPORTED_MODULE_12__.SelectionMode.none, isHeaderVisible: false })), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack, { horizontal: true, tokens: { childrenGap: "0 8" }, style: { marginTop: 16 } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_13__.PrimaryButton, { text: "Save", disabled: !changed, onClick: () => setShowSaveDialog(true) }), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_14__.DefaultButton, { text: "Cancel", disabled: !changed, onClick: () => setEditing(JSON.parse(JSON.stringify(current))) }))), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_15__.Dialog, { hidden: !showSaveDialog, onDismiss: () => setShowSaveDialog(false), dialogContentProps: { type: _fluentui_react__WEBPACK_IMPORTED_MODULE_16__.DialogType.largeHeader, title: "Save", subText: "Restart is required to apply configuration." } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_17__.DialogFooter, null, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_13__.PrimaryButton, { text: "Save", onClick: () => { setShowSaveDialog(false); (async () => { console.log("ChannelsConfigurator", "PUT", configAPI, "<-", editing); await fetch(configAPI, { method: "PUT", headers: { "Content-Type": "application/json; charset=utf-8" }, body: JSON.stringify(editing) }); setSaved(true); })(); } }), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_14__.DefaultButton, { text: "Cancel", onClick: () => setShowSaveDialog(false) }))), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_15__.Dialog, { hidden: !showScanDialog, onDismiss: () => setShowScanDialog(false), dialogContentProps: { type: _fluentui_react__WEBPACK_IMPORTED_MODULE_16__.DialogType.largeHeader, title: "Channel Scan", subText: "Configure scan parameters and click Start to begin scanning." }, modalProps: { isBlocking: true, styles: { main: { maxWidth: 450 } } } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack, { tokens: { childrenGap: "12 0" } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_4__.Dropdown, { label: "Channel Type", options: [ { key: "GR", text: "GR" }, { key: "BS", text: "BS" }, { key: "CS", text: "CS" } ], selectedKey: scanType, onChange: (ev, option) => { const newType = option.key; setScanType(newType); switch (newType) { case "GR": setScanMinCh("13"); setScanMaxCh("62"); break; case "BS": setScanMinCh("1"); setScanMaxCh("23"); break; case "CS": setScanMinCh("2"); setScanMaxCh("24"); break; } } }), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_5__.Stack, { horizontal: true, tokens: { childrenGap: "0 8" } }, react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_3__.TextField, { label: "Min Channel", value: scanMinCh, onChange: (ev, val) => setScanMinCh(val), styles: { root: { width: 100 } } }), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_3__.TextField, { label: "Max Channel", value: scanMaxCh, onChange: (ev, val) => setScanMaxCh(val), styles: { root: { width: 100 } } })), react__WEBPACK_IMPORTED_MODULE_0__.createElement(_fluentui_react__WEBPACK_IMPORTED_MODULE_3__.TextField, { label: "Skip Channels (comma separated integers)", placeholder: "Example: 13,14-16,18", value: scanSkipCh, onChange: (ev, val) => { if (val === "" || /^[0-9,\-]+$/.test(val)) { setScanSkipCh(val);