This is an automated email from the ASF dual-hosted git repository.

jedcunningham pushed a commit to branch v2-9-test
in repository https://gitbox.apache.org/repos/asf/airflow.git

commit d5d8b588f72fc8b91a7a5a7a16bcbe4cf82b1fe8
Author: Brent Bovenzi <br...@astronomer.io>
AuthorDate: Thu Apr 25 13:21:17 2024 -0400

    Add workaround for datetime-local input in firefox (#39261)
    
    (cherry picked from commit 5638bc3f502e656b1b3c8b765ad1c84434017b41)
---
 .../static/js/cluster-activity/nav/FilterBar.tsx   |  9 ++-
 airflow/www/static/js/components/DateTimeInput.tsx | 84 ++++++++++++++++++++++
 airflow/www/static/js/dag/nav/FilterBar.tsx        |  6 +-
 3 files changed, 91 insertions(+), 8 deletions(-)

diff --git a/airflow/www/static/js/cluster-activity/nav/FilterBar.tsx 
b/airflow/www/static/js/cluster-activity/nav/FilterBar.tsx
index b4f840cb5f..7e458ab5ab 100644
--- a/airflow/www/static/js/cluster-activity/nav/FilterBar.tsx
+++ b/airflow/www/static/js/cluster-activity/nav/FilterBar.tsx
@@ -19,7 +19,7 @@
 
 /* global moment */
 
-import { Box, Button, Flex, Input, Text } from "@chakra-ui/react";
+import { Box, Button, Flex, Text } from "@chakra-ui/react";
 import React from "react";
 
 import { useTimezone } from "src/context/timezone";
@@ -29,6 +29,7 @@ import {
   getDuration,
 } from "src/datetime_utils";
 import useFilters from "src/cluster-activity/useFilters";
+import DateTimeInput from "src/components/DateTimeInput";
 
 const FilterBar = () => {
   const { filters, onStartDateChange, onEndDateChange, clearFilters } =
@@ -61,9 +62,8 @@ const FilterBar = () => {
           <Text fontSize="sm" as="b" position="absolute" mt="-14px" ml={1}>
             Start Date
           </Text>
-          <Input
+          <DateTimeInput
             {...inputStyles}
-            type="datetime-local"
             value={formattedStartDate || ""}
             onChange={(e) => onStartDateChange(e.target.value)}
           />
@@ -72,9 +72,8 @@ const FilterBar = () => {
           <Text fontSize="sm" as="b" position="absolute" mt="-14px" ml={1}>
             End Date
           </Text>
-          <Input
+          <DateTimeInput
             {...inputStyles}
-            type="datetime-local"
             value={formattedEndDate || ""}
             onChange={(e) => onEndDateChange(e.target.value)}
           />
diff --git a/airflow/www/static/js/components/DateTimeInput.tsx 
b/airflow/www/static/js/components/DateTimeInput.tsx
new file mode 100644
index 0000000000..1d6b32ef1c
--- /dev/null
+++ b/airflow/www/static/js/components/DateTimeInput.tsx
@@ -0,0 +1,84 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* global moment */
+
+import React from "react";
+import { Flex, Input, InputProps } from "@chakra-ui/react";
+
+const DateTimeInput = (props: InputProps) => {
+  // Firefox and safari do not support datetime-local so we need to put a date 
and time input next to each other
+  const userAgent = navigator.userAgent.toLowerCase();
+  const unsupportedBrowser =
+    userAgent.includes("firefox") || userAgent.includes("safari");
+
+  if (!unsupportedBrowser) return <Input type="datetime-local" {...props} />;
+
+  const { value, onChange, ...rest } = props;
+  // @ts-ignore
+  let datetime = moment(value as string);
+  // @ts-ignore
+  datetime = datetime.isValid() ? datetime : moment();
+  // @ts-ignore
+  const date = moment(datetime).format("YYYY-MM-DD");
+  // @ts-ignore
+  const time = moment(datetime).format("HH:mm:ss");
+  return (
+    <Flex>
+      <Input
+        type="date"
+        value={date}
+        onChange={(e) => {
+          if (onChange)
+            onChange({
+              ...e,
+              target: {
+                ...e.target,
+                value: `${e.target.value}T${time}`,
+              },
+            });
+        }}
+        {...rest}
+        borderRightWidth={0}
+        borderRightRadius={0}
+        paddingInlineEnd={0}
+      />
+      <Input
+        type="time"
+        value={time}
+        onChange={(e) => {
+          if (onChange)
+            onChange({
+              ...e,
+              target: {
+                ...e.target,
+                value: `${date}T${e.target.value}`,
+              },
+            });
+        }}
+        {...rest}
+        borderLeftWidth={0}
+        borderLeftRadius={0}
+        paddingInlineStart={0}
+      />
+    </Flex>
+  );
+};
+
+export default DateTimeInput;
diff --git a/airflow/www/static/js/dag/nav/FilterBar.tsx 
b/airflow/www/static/js/dag/nav/FilterBar.tsx
index f03ea734b8..2a0b356893 100644
--- a/airflow/www/static/js/dag/nav/FilterBar.tsx
+++ b/airflow/www/static/js/dag/nav/FilterBar.tsx
@@ -19,7 +19,7 @@
 
 /* global moment */
 
-import { Box, Button, Flex, Input, Select } from "@chakra-ui/react";
+import { Box, Button, Flex, Select } from "@chakra-ui/react";
 import MultiSelect from "src/components/MultiSelect";
 import React from "react";
 import type { DagRun, RunState, TaskState } from "src/types";
@@ -30,6 +30,7 @@ import { useChakraSelectProps } from "chakra-react-select";
 import { useTimezone } from "src/context/timezone";
 import { isoFormatWithoutTZ } from "src/datetime_utils";
 import useFilters from "src/dag/useFilters";
+import DateTimeInput from "src/components/DateTimeInput";
 
 declare const filtersOptions: {
   dagStates: RunState[];
@@ -124,9 +125,8 @@ const FilterBar = () => {
     <Flex backgroundColor="blackAlpha.200" p={4} 
justifyContent="space-between">
       <Flex ml={10}>
         <Box px={2}>
-          <Input
+          <DateTimeInput
             {...inputStyles}
-            type="datetime-local"
             value={formattedTime || ""}
             onChange={(e) => onBaseDateChange(e.target.value)}
             {...(isBaseDateDefault ? {} : filteredStyles)}

Reply via email to