diff --git a/webui/src/components/OperationRow.tsx b/webui/src/components/OperationRow.tsx index 218a45ec..5cf03d3f 100644 --- a/webui/src/components/OperationRow.tsx +++ b/webui/src/components/OperationRow.tsx @@ -623,7 +623,7 @@ const BackupOperationStatus = ({ console.error("GOT UNEXPECTED STATUS: ", status); return ( <> - {m.op_row_unexpected_status} {status} + {m.op_row_unexpected_status() + JSON.stringify(status)} ); } diff --git a/webui/src/components/ScheduleFormItem.tsx b/webui/src/components/ScheduleFormItem.tsx index ca4aa27c..017c3aa2 100644 --- a/webui/src/components/ScheduleFormItem.tsx +++ b/webui/src/components/ScheduleFormItem.tsx @@ -1,9 +1,9 @@ import { Checkbox, + Flex, Form, InputNumber, Radio, - Row, Tooltip, Typography, } from "antd"; @@ -169,8 +169,8 @@ export const ScheduleFormItem = ({ } return ( - <> - + +
{ @@ -217,26 +217,25 @@ export const ScheduleFormItem = ({ - - Clock for schedule:{" "} - +
+ + Clock for schedule: - Clock provides the time that the schedule is evaluated relative - to. + Clock provides the time that the schedule is evaluated relative to.
  • Local - current time in the local timezone.
  • UTC - current time in the UTC timezone.
  • - Last Run Time - relative to the last time the task ran. Good - for devices that aren't always powered on e.g. laptops. + Last Run Time - relative to the last time the task ran. Good for + devices that aren't always powered on e.g. laptops.
} > - +
-
-
- - {elem} - - + + {elem && ( +
+ {elem} +
+ )} + ); }; diff --git a/webui/src/views/AddPlanModal.tsx b/webui/src/views/AddPlanModal.tsx index 65501daa..02558018 100644 --- a/webui/src/views/AddPlanModal.tsx +++ b/webui/src/views/AddPlanModal.tsx @@ -13,6 +13,7 @@ import { Collapse, Checkbox, AutoComplete, + Flex, } from "antd"; import React, { useEffect, useMemo, useRef, useState } from "react"; import { useShowModal } from "../components/ModalManager"; @@ -53,112 +54,7 @@ import * as m from "../paraglide/messages"; const { TextArea } = Input; const sep = isWindows ? "\\" : "/"; -const PathsTextArea = ({ value, onChange, ...props }: any) => { - const [options, setOptions] = useState<{ value: string }[]>([]); - const [currentLine, setCurrentLine] = useState(""); - const [cursorPosition, setCursorPosition] = useState(0); - // selectingRef acts as a lock to prevent the AutoComplete's default behavior (replacing the entire value) - // from overwriting the multi-line merge logic in onSelect. - const selectingRef = useRef(false); - // eslint-disable-next-line react-hooks/exhaustive-deps - const handleSearch = useMemo( - () => - debounce((searchValue: string) => { - if (!searchValue) { - setOptions([]); - return; - } - - const lastSlash = searchValue.lastIndexOf(sep); - let searchPath = searchValue; - if (lastSlash !== -1) { - searchPath = searchValue.substring(0, lastSlash); - } - - backrestService - .pathAutocomplete({ value: searchPath + sep }) - .then((res: StringList) => { - if (!res.values) { - return; - } - const vals = res.values.map((v) => { - return { - value: searchPath + sep + v, - }; - }); - setOptions(vals.filter((o) => o.value.indexOf(searchValue) !== -1)); - }) - .catch((e) => { - console.log("Path autocomplete error: ", e); - }); - }, 200), - [] - ); - - const handleTextAreaChange = (e: React.ChangeEvent) => { - // If we are currently handling a selection, ignore the change event that AutoComplete triggers - // to replace the text with the selected item. - if (selectingRef.current) { - selectingRef.current = false; - return; - } - - const newValue = e.target.value; - const cursorPos = e.target.selectionStart || 0; - - // Find the current line based on cursor position - const lines = newValue.substring(0, cursorPos).split("\n"); - const currentLineValue = lines[lines.length - 1]; - - setCurrentLine(currentLineValue); - setCursorPosition(cursorPos); - - // Trigger autocomplete for the current line - handleSearch(currentLineValue); - - // Update the form value - if (onChange) { - onChange(newValue); - } - }; - - const onSelect = (selectedValue: string) => { - // Set the flag to ignore the next onChange event (which contains the raw selected value) - selectingRef.current = true; - - const lines = (value || "").split("\n"); - const beforeCursor = (value || "").substring(0, cursorPosition); - const afterCursor = (value || "").substring(cursorPosition); - const linesBeforeCursor = beforeCursor.split("\n"); - - // Replace the current line with the selected value - linesBeforeCursor[linesBeforeCursor.length - 1] = selectedValue; - const newValue = linesBeforeCursor.join("\n") + afterCursor; - - if (onChange) { - onChange(newValue); - } - setOptions([]); - }; - - return ( - {}} // We handle search in textarea change - {...props} - > -