Skip to content

Commit

Permalink
Fix UI rendering when XCom is INT, FLOAT, BOOL or NULL (#41516) (#41605)
Browse files Browse the repository at this point in the history
  • Loading branch information
jscheffl authored Aug 20, 2024
1 parent a9c7d1a commit d4c5a98
Show file tree
Hide file tree
Showing 6 changed files with 134 additions and 21 deletions.
1 change: 1 addition & 0 deletions airflow/api_connexion/openapi/v1.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4143,6 +4143,7 @@ components:
- type: array
items: {}
- type: object
nullable: true
description: The value(s),

# Python objects
Expand Down
21 changes: 2 additions & 19 deletions airflow/www/static/js/components/RenderedJsonField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,32 +30,15 @@ import {
useTheme,
FlexProps,
} from "@chakra-ui/react";
import jsonParse from "./utils";

interface Props extends FlexProps {
content: string | object;
jsonProps?: Omit<ReactJsonViewProps, "src">;
}

const JsonParse = (content: string | object) => {
let contentJson = null;
let contentFormatted = "";
let isJson = false;
try {
if (typeof content === "string") {
contentJson = JSON.parse(content);
} else {
contentJson = content;
}
contentFormatted = JSON.stringify(contentJson, null, 4);
isJson = true;
} catch (e) {
// skip
}
return [isJson, contentJson, contentFormatted];
};

const RenderedJsonField = ({ content, jsonProps, ...rest }: Props) => {
const [isJson, contentJson, contentFormatted] = JsonParse(content);
const [isJson, contentJson, contentFormatted] = jsonParse(content);
const { onCopy, hasCopied } = useClipboard(contentFormatted);
const theme = useTheme();

Expand Down
84 changes: 84 additions & 0 deletions airflow/www/static/js/components/utils.test.ts
Original file line number Diff line number Diff line change
@@ -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.
*/

import jsonParse from "./utils";

/* global describe, test, expect */

describe("JSON Parsing.", () => {
test.each([
{
testName: "null",
testContent: null,
expectedIsJson: false,
},
{
testName: "boolean",
testContent: true,
expectedIsJson: false,
},
{
testName: "int",
testContent: 42,
expectedIsJson: false,
},
{
testName: "float",
testContent: 3.1415,
expectedIsJson: false,
},
{
testName: "string",
testContent: "hello world",
expectedIsJson: false,
},
{
testName: "array",
testContent: ["hello world", 42, 3.1515],
expectedIsJson: true,
},
{
testName: "array as string",
testContent: JSON.stringify(["hello world", 42, 3.1515]),
expectedIsJson: true,
},
{
testName: "dict",
testContent: { key: 42 },
expectedIsJson: true,
},
{
testName: "dict as string",
testContent: JSON.stringify({ key: 42 }),
expectedIsJson: true,
},
])(
"Input value is $testName",
({ testName, testContent, expectedIsJson }) => {
const [isJson, contentJson, contentFormatted] = jsonParse(testContent);

expect(testName).not.toBeNull();
expect(isJson).toEqual(expectedIsJson);
if (expectedIsJson) {
expect(contentJson).not.toBeNull();
expect(contentFormatted.length).toBeGreaterThan(0);
}
}
);
});
38 changes: 38 additions & 0 deletions airflow/www/static/js/components/utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*!
* 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.
*/

const jsonParse = (content: any) => {
let contentJson = null;
let contentFormatted = "";
let isJson = false;
try {
if (typeof content === "string") {
contentJson = JSON.parse(content);
} else {
contentJson = content;
}
contentFormatted = JSON.stringify(contentJson, null, 4);
isJson = contentJson != null && typeof contentJson === "object"; // ensure numbers/bool are not treated as JSON
} catch (e) {
// skip
}
return [isJson, contentJson, contentFormatted];
};

export default jsonParse;
Original file line number Diff line number Diff line change
Expand Up @@ -60,13 +60,20 @@ const XcomEntry = ({
content = <Spinner />;
} else if (error) {
content = <ErrorAlert error={error} />;
} else if (!xcom || !xcom.value) {
} else if (!xcom) {
content = (
<Alert status="info">
<AlertIcon />
No value found for XCom key
</Alert>
);
} else if (!xcom.value) {
content = (
<Alert status="info">
<AlertIcon />
Value is NULL
</Alert>
);
} else {
let xcomString = "";
if (typeof xcom.value !== "string") {
Expand Down
2 changes: 1 addition & 1 deletion airflow/www/static/js/types/api-generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1662,7 +1662,7 @@ export interface components {
Partial<number> &
Partial<boolean> &
Partial<unknown[]> &
Partial<{ [key: string]: unknown }>;
Partial<{ [key: string]: unknown } | null>;
};
/**
* @description DAG details.
Expand Down

0 comments on commit d4c5a98

Please sign in to comment.