dheerajturaga commented on code in PR #55301:
URL: https://github.com/apache/airflow/pull/55301#discussion_r2326506699


##########
providers/edge3/src/airflow/providers/edge3/plugins/www/src/pages/WorkerPage.tsx:
##########
@@ -16,22 +16,178 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-import { Box, Table } from "@chakra-ui/react";
+import { Box, Button, Table, Textarea, VStack, HStack } from 
"@chakra-ui/react";
 import { useUiServiceWorker } from "openapi/queries";
+import type { Worker } from "openapi/requests/types.gen";
+import { useState } from "react";
 
 import { ErrorAlert } from "src/components/ErrorAlert";
 import { WorkerStateBadge } from "src/components/WorkerStateBadge";
 import { autoRefreshInterval } from "src/utils";
 
+interface MaintenanceFormProps {
+  onSubmit: (comment: string) => void;
+  onCancel: () => void;
+}
+
+const MaintenanceForm = ({ onCancel, onSubmit }: MaintenanceFormProps) => {
+  const [comment, setComment] = useState("");
+
+  const handleSubmit = () => {
+    if (comment.trim()) {
+      onSubmit(comment.trim());
+    }
+  };
+
+  return (
+    <VStack gap={2} align="stretch">
+      <Textarea
+        placeholder="Enter maintenance comment (required)"
+        value={comment}
+        onChange={(e) => setComment(e.target.value)}
+        required
+        maxLength={1024}
+        size="sm"
+      />
+      <HStack gap={2}>
+        <Button size="sm" colorScheme="blue" onClick={handleSubmit} 
disabled={!comment.trim()}>
+          Confirm Maintenance
+        </Button>
+        <Button size="sm" variant="outline" onClick={onCancel}>
+          Cancel
+        </Button>
+      </HStack>
+    </VStack>
+  );
+};
+
 export const WorkerPage = () => {
-  const { data, error } = useUiServiceWorker(undefined, {
+  const { data, error, refetch } = useUiServiceWorker(undefined, {
     enabled: true,
     refetchInterval: autoRefreshInterval,
   });
+  const [activeMaintenanceForm, setActiveMaintenanceForm] = useState<string | 
null>(null);
+
+  const requestMaintenance = async (workerName: string, comment: string) => {
+    try {
+      console.log(`Requesting maintenance for worker: ${workerName}, comment: 
${comment}`);
+
+      // Get CSRF token from meta tag (common Airflow pattern)
+      const csrfToken =
+        
document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") ||
+        
document.querySelector('input[name="csrf_token"]')?.getAttribute("value");
+
+      const headers: Record<string, string> = {
+        "Content-Type": "application/json",
+      };
+
+      // Add CSRF token if available
+      if (csrfToken) {
+        headers["X-CSRFToken"] = csrfToken;
+      }
+
+      const response = await 
fetch(`/edge_worker/ui/worker/${workerName}/maintenance`, {
+        body: JSON.stringify({ maintenance_comment: comment }),
+        credentials: "same-origin",
+        headers,
+        method: "POST",
+      });
+
+      if (!response.ok) {
+        const errorText = await response.text();
+        console.error("Maintenance request failed:", response.status, 
errorText);
+        throw new Error(`Failed to request maintenance: ${response.status} 
${errorText}`);
+      }
+
+      console.log("Maintenance request successful");
+      setActiveMaintenanceForm(null);
+      refetch();
+    } catch (error) {
+      console.error("Error requesting maintenance:", error);
+      alert(`Error requesting maintenance: ${error}`);
+    }
+  };
+
+  const exitMaintenance = async (workerName: string) => {
+    try {
+      console.log(`Exiting maintenance for worker: ${workerName}`);
+
+      // Get CSRF token from meta tag (common Airflow pattern)
+      const csrfToken =
+        
document.querySelector('meta[name="csrf-token"]')?.getAttribute("content") ||
+        
document.querySelector('input[name="csrf_token"]')?.getAttribute("value");
+
+      const headers: Record<string, string> = {};
+
+      // Add CSRF token if available
+      if (csrfToken) {
+        headers["X-CSRFToken"] = csrfToken;
+      }
+
+      const response = await 
fetch(`/edge_worker/ui/worker/${workerName}/maintenance`, {
+        credentials: "same-origin",
+        headers,
+        method: "DELETE",
+      });
+
+      if (!response.ok) {
+        const errorText = await response.text();
+        console.error("Exit maintenance failed:", response.status, errorText);
+        throw new Error(`Failed to exit maintenance: ${response.status} 
${errorText}`);
+      }
+
+      console.log("Exit maintenance successful");
+      refetch();
+    } catch (error) {
+      console.error("Error exiting maintenance:", error);
+      alert(`Error exiting maintenance: ${error}`);
+    }
+  };
+
+  const renderOperationsCell = (worker: Worker) => {
+    const workerName = worker.worker_name;
+    const state = worker.state;
+
+    if (state === "idle" || state === "running") {
+      if (activeMaintenanceForm === workerName) {
+        return (
+          <MaintenanceForm
+            onSubmit={(comment) => requestMaintenance(workerName, comment)}
+            onCancel={() => setActiveMaintenanceForm(null)}
+          />
+        );
+      }
+      return (
+        <Button size="sm" colorScheme="blue" onClick={() => 
setActiveMaintenanceForm(workerName)}>
+          Enter Maintenance

Review Comment:
   I've updated to use the icons but I was not able to get tooltips working. It 
seems causing a Minified React Error 130



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: commits-unsubscr...@airflow.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org

Reply via email to