You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airflow.apache.org by ep...@apache.org on 2023/08/03 12:36:03 UTC
[airflow] 01/09: Only load task action modal if user can edit (#32992)
This is an automated email from the ASF dual-hosted git repository.
ephraimanierobi pushed a commit to branch v2-7-test
in repository https://gitbox.apache.org/repos/asf/airflow.git
commit 9d4848dce7529662567dae0fac65aeb45bedbdf8
Author: Brent Bovenzi <br...@astronomer.io>
AuthorDate: Thu Aug 3 16:29:03 2023 +0800
Only load task action modal if user can edit (#32992)
(cherry picked from commit 943b97850a1e82e4da22e8489c4ede958a42213d)
---
.../taskInstance/taskActions/ClearInstance.tsx | 222 +++++++++++--------
.../taskInstance/taskActions/MarkInstanceAs.tsx | 244 ++++++++++++---------
2 files changed, 265 insertions(+), 201 deletions(-)
diff --git a/airflow/www/static/js/dag/details/taskInstance/taskActions/ClearInstance.tsx b/airflow/www/static/js/dag/details/taskInstance/taskActions/ClearInstance.tsx
index 885310f41f..d935f99e65 100644
--- a/airflow/www/static/js/dag/details/taskInstance/taskActions/ClearInstance.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/taskActions/ClearInstance.tsx
@@ -41,7 +41,7 @@ import ActionModal from "./ActionModal";
const canEdit = getMetaValue("can_edit") === "True";
const dagId = getMetaValue("dag_id");
-interface Props extends ButtonProps {
+interface Props {
runId: string;
taskId: string;
executionDate: string;
@@ -50,17 +50,21 @@ interface Props extends ButtonProps {
mapIndex?: number;
}
-const ClearInstance = ({
+interface ClearModalProps extends Props {
+ isOpen: boolean;
+ onClose: () => void;
+}
+
+const ClearModal = ({
runId,
taskId,
mapIndex,
executionDate,
isGroup,
isMapped,
- ...otherProps
-}: Props) => {
- const { onOpen, onClose, isOpen } = useDisclosure();
-
+ isOpen,
+ onClose,
+}: ClearModalProps) => {
const [past, setPast] = useState(false);
const onTogglePast = () => setPast(!past);
@@ -81,8 +85,6 @@ const ClearInstance = ({
const initialClearButtonFocusRef = useRef<HTMLButtonElement>(null);
- useKeysPress(keyboardShortcutIdentifier.taskRunClear, onOpen);
-
const mapIndexes =
mapIndex !== undefined && mapIndex !== -1 ? [mapIndex] : undefined;
@@ -134,6 +136,110 @@ const ClearInstance = ({
resetModal();
};
+ return (
+ <ActionModal
+ isOpen={isOpen}
+ onClose={resetModal}
+ header="Clear and Retry"
+ subheader={
+ <>
+ <Text>
+ <Text as="strong" mr={1}>
+ Task:
+ </Text>
+ {taskId}
+ </Text>
+ <Text>
+ <Text as="strong" mr={1}>
+ Run:
+ </Text>
+ {runId}
+ </Text>
+ {isMapped && (
+ <Text>
+ <Text as="strong" mr={1}>
+ Map Index:
+ </Text>
+ {mapIndex !== undefined ? mapIndex : `All mapped tasks`}
+ </Text>
+ )}
+ </>
+ }
+ affectedTasks={affectedTasks}
+ submitButton={
+ <Button
+ ref={initialClearButtonFocusRef}
+ colorScheme="blue"
+ isLoading={isLoading || isLoadingDryRun}
+ isDisabled={!affectedTasks?.length}
+ onClick={onClear}
+ >
+ Clear
+ </Button>
+ }
+ initialFocusRef={initialClearButtonFocusRef}
+ >
+ <Box>
+ <Text>Include: </Text>
+ <ButtonGroup isAttached variant="outline" isDisabled={!canEdit}>
+ <ActionButton
+ bg={past ? "gray.100" : undefined}
+ onClick={onTogglePast}
+ name="Past"
+ />
+ <ActionButton
+ bg={future ? "gray.100" : undefined}
+ onClick={onToggleFuture}
+ name="Future"
+ />
+ <ActionButton
+ bg={upstream ? "gray.100" : undefined}
+ onClick={onToggleUpstream}
+ name="Upstream"
+ />
+ <ActionButton
+ bg={downstream ? "gray.100" : undefined}
+ onClick={onToggleDownstream}
+ name="Downstream"
+ />
+ <ActionButton
+ bg={recursive ? "gray.100" : undefined}
+ onClick={onToggleRecursive}
+ name="Recursive"
+ />
+ <ActionButton
+ bg={failed ? "gray.100" : undefined}
+ onClick={onToggleFailed}
+ name="Failed"
+ />
+ </ButtonGroup>
+ </Box>
+ {isGroup && (past || future) && (
+ <Alert status="warning" my={3}>
+ <AlertIcon />
+ Clearing a TaskGroup in the future and/or past will affect all the
+ tasks of this group across multiple dag runs.
+ <br />
+ This can take a while to complete.
+ </Alert>
+ )}
+ </ActionModal>
+ );
+};
+
+const ClearInstance = ({
+ runId,
+ taskId,
+ mapIndex,
+ executionDate,
+ isGroup,
+ isMapped,
+ ...otherProps
+}: Props & ButtonProps) => {
+ const { onOpen, onClose, isOpen } = useDisclosure();
+
+ useKeysPress(keyboardShortcutIdentifier.taskRunClear, onOpen);
+
const clearLabel = "Clear and retry task.";
return (
@@ -148,93 +254,19 @@ const ClearInstance = ({
>
Clear task
</Button>
- <ActionModal
- isOpen={isOpen}
- onClose={resetModal}
- header="Clear and Retry"
- subheader={
- <>
- <Text>
- <Text as="strong" mr={1}>
- Task:
- </Text>
- {taskId}
- </Text>
- <Text>
- <Text as="strong" mr={1}>
- Run:
- </Text>
- {runId}
- </Text>
- {isMapped && (
- <Text>
- <Text as="strong" mr={1}>
- Map Index:
- </Text>
- {mapIndex !== undefined ? mapIndex : `All mapped tasks`}
- </Text>
- )}
- </>
- }
- affectedTasks={affectedTasks}
- submitButton={
- <Button
- ref={initialClearButtonFocusRef}
- colorScheme="blue"
- isLoading={isLoading || isLoadingDryRun}
- isDisabled={!affectedTasks?.length}
- onClick={onClear}
- >
- Clear
- </Button>
- }
- initialFocusRef={initialClearButtonFocusRef}
- >
- <Box>
- <Text>Include: </Text>
- <ButtonGroup isAttached variant="outline" isDisabled={!canEdit}>
- <ActionButton
- bg={past ? "gray.100" : undefined}
- onClick={onTogglePast}
- name="Past"
- />
- <ActionButton
- bg={future ? "gray.100" : undefined}
- onClick={onToggleFuture}
- name="Future"
- />
- <ActionButton
- bg={upstream ? "gray.100" : undefined}
- onClick={onToggleUpstream}
- name="Upstream"
- />
- <ActionButton
- bg={downstream ? "gray.100" : undefined}
- onClick={onToggleDownstream}
- name="Downstream"
- />
- <ActionButton
- bg={recursive ? "gray.100" : undefined}
- onClick={onToggleRecursive}
- name="Recursive"
- />
- <ActionButton
- bg={failed ? "gray.100" : undefined}
- onClick={onToggleFailed}
- name="Failed"
- />
- </ButtonGroup>
- </Box>
- {isGroup && (past || future) && (
- <Alert status="warning" my={3}>
- <AlertIcon />
- Clearing a TaskGroup in the future and/or past will affect all the
- tasks of this group across multiple dag runs.
- <br />
- This can take a while to complete.
- </Alert>
- )}
- </ActionModal>
+ {/* Only mount modal if user can edit */}
+ {canEdit && (
+ <ClearModal
+ runId={runId}
+ taskId={taskId}
+ mapIndex={mapIndex}
+ executionDate={executionDate}
+ isGroup={isGroup}
+ isMapped={isMapped}
+ isOpen={isOpen}
+ onClose={onClose}
+ />
+ )}
</>
);
};
diff --git a/airflow/www/static/js/dag/details/taskInstance/taskActions/MarkInstanceAs.tsx b/airflow/www/static/js/dag/details/taskInstance/taskActions/MarkInstanceAs.tsx
index 09045877d0..e88108e098 100644
--- a/airflow/www/static/js/dag/details/taskInstance/taskActions/MarkInstanceAs.tsx
+++ b/airflow/www/static/js/dag/details/taskInstance/taskActions/MarkInstanceAs.tsx
@@ -53,7 +53,7 @@ import ActionModal from "./ActionModal";
const canEdit = getMetaValue("can_edit") === "True";
const dagId = getMetaValue("dag_id");
-interface Props extends MenuButtonProps {
+interface Props {
runId: string;
taskId: string;
state?: TaskState;
@@ -62,19 +62,22 @@ interface Props extends MenuButtonProps {
isMapped?: boolean;
}
-const MarkInstanceAs = ({
+interface ModalProps extends Props {
+ isOpen: boolean;
+ onClose: () => void;
+ state: TaskState;
+}
+
+const MarkAsModal = ({
runId,
taskId,
isGroup,
mapIndex,
isMapped,
- state: currentState,
- ...otherProps
-}: Props) => {
- const { onOpen, onClose, isOpen } = useDisclosure();
-
- const [newState, setNewState] = useState<"failed" | "success">("success");
-
+ state,
+ isOpen,
+ onClose,
+}: ModalProps) => {
const [past, setPast] = useState(false);
const onTogglePast = () => setPast(!past);
@@ -89,16 +92,6 @@ const MarkInstanceAs = ({
const initialMarkAsButtonFocusRef = useRef<HTMLButtonElement>(null);
- const markAsFailed = () => {
- setNewState("failed");
- onOpen();
- };
-
- const markAsSuccess = () => {
- setNewState("success");
- onOpen();
- };
-
const mapIndexes =
mapIndex !== undefined && mapIndex !== -1 ? [mapIndex] : undefined;
@@ -107,7 +100,7 @@ const MarkInstanceAs = ({
dagId,
runId,
taskId,
- state: newState,
+ state,
isGroup: !!isGroup,
past,
future,
@@ -142,7 +135,7 @@ const MarkInstanceAs = ({
};
const onMarkState = () => {
- if (newState === "success") {
+ if (state === "success") {
markSuccessMutation({
past,
future,
@@ -150,7 +143,7 @@ const MarkInstanceAs = ({
downstream,
mapIndexes,
});
- } else if (newState === "failed") {
+ } else if (state === "failed") {
markFailedMutation({
past,
future,
@@ -162,6 +155,116 @@ const MarkInstanceAs = ({
resetModal();
};
+ return (
+ <ActionModal
+ isOpen={isOpen}
+ onClose={resetModal}
+ header={`Mark as ${capitalize(state || "")}`}
+ subheader={
+ <>
+ <Text>
+ <Text as="strong" mr={1}>
+ Task:
+ </Text>
+ {taskId}
+ </Text>
+ <Text>
+ <Text as="strong" mr={1}>
+ Run:
+ </Text>
+ {runId}
+ </Text>
+ {isMapped && (
+ <Text>
+ <Text as="strong" mr={1}>
+ Map Index:
+ </Text>
+ {mapIndex !== undefined ? mapIndex : `All mapped tasks`}
+ </Text>
+ )}
+ </>
+ }
+ affectedTasks={affectedTasks}
+ submitButton={
+ <Button
+ ref={initialMarkAsButtonFocusRef}
+ colorScheme={
+ (state === "success" && "green") ||
+ (state === "failed" && "red") ||
+ "grey"
+ }
+ isLoading={
+ isLoadingDryRun || isMarkSuccessLoading || isMarkFailedLoading
+ }
+ isDisabled={!affectedTasks?.length || !state}
+ onClick={onMarkState}
+ >
+ Mark as {state}
+ </Button>
+ }
+ initialFocusRef={initialMarkAsButtonFocusRef}
+ >
+ <Box>
+ <Text>Include: </Text>
+ <ButtonGroup isAttached variant="outline" isDisabled={!canEdit}>
+ <ActionButton
+ bg={past ? "gray.100" : undefined}
+ onClick={onTogglePast}
+ name="Past"
+ />
+ <ActionButton
+ bg={future ? "gray.100" : undefined}
+ onClick={onToggleFuture}
+ name="Future"
+ />
+ <ActionButton
+ bg={upstream ? "gray.100" : undefined}
+ onClick={onToggleUpstream}
+ name="Upstream"
+ />
+ <ActionButton
+ bg={downstream ? "gray.100" : undefined}
+ onClick={onToggleDownstream}
+ name="Downstream"
+ />
+ </ButtonGroup>
+ </Box>
+ {isGroup && (past || future) && (
+ <Alert status="warning" my={3}>
+ <AlertIcon />
+ Marking a TaskGroup as {capitalize(state || "")} in the future and/or
+ past will affect all the tasks of this group across multiple dag runs.
+ <br />
+ This can take a while to complete.
+ </Alert>
+ )}
+ </ActionModal>
+ );
+};
+
+const MarkInstanceAs = ({
+ runId,
+ taskId,
+ isGroup,
+ mapIndex,
+ isMapped,
+ state: currentState,
+ ...otherProps
+}: Props & MenuButtonProps) => {
+ const { onOpen, onClose, isOpen } = useDisclosure();
+
+ const [newState, setNewState] = useState<"failed" | "success">("success");
+
+ const markAsFailed = () => {
+ setNewState("failed");
+ onOpen();
+ };
+
+ const markAsSuccess = () => {
+ setNewState("success");
+ onOpen();
+ };
+
const markLabel = "Manually set task instance state";
const isMappedSummary = isMapped && mapIndex === undefined;
@@ -209,90 +312,19 @@ const MarkInstanceAs = ({
</MenuItem>
</MenuList>
</Menu>
- <ActionModal
- isOpen={isOpen}
- onClose={resetModal}
- header={`Mark as ${capitalize(newState)}`}
- subheader={
- <>
- <Text>
- <Text as="strong" mr={1}>
- Task:
- </Text>
- {taskId}
- </Text>
- <Text>
- <Text as="strong" mr={1}>
- Run:
- </Text>
- {runId}
- </Text>
- {isMapped && (
- <Text>
- <Text as="strong" mr={1}>
- Map Index:
- </Text>
- {mapIndex !== undefined ? mapIndex : `All mapped tasks`}
- </Text>
- )}
- </>
- }
- affectedTasks={affectedTasks}
- submitButton={
- <Button
- ref={initialMarkAsButtonFocusRef}
- colorScheme={
- (newState === "success" && "green") ||
- (newState === "failed" && "red") ||
- "grey"
- }
- isLoading={
- isLoadingDryRun || isMarkSuccessLoading || isMarkFailedLoading
- }
- isDisabled={!affectedTasks?.length || !newState}
- onClick={onMarkState}
- >
- Mark as {newState}
- </Button>
- }
- initialFocusRef={initialMarkAsButtonFocusRef}
- >
- <Box>
- <Text>Include: </Text>
- <ButtonGroup isAttached variant="outline" isDisabled={!canEdit}>
- <ActionButton
- bg={past ? "gray.100" : undefined}
- onClick={onTogglePast}
- name="Past"
- />
- <ActionButton
- bg={future ? "gray.100" : undefined}
- onClick={onToggleFuture}
- name="Future"
- />
- <ActionButton
- bg={upstream ? "gray.100" : undefined}
- onClick={onToggleUpstream}
- name="Upstream"
- />
- <ActionButton
- bg={downstream ? "gray.100" : undefined}
- onClick={onToggleDownstream}
- name="Downstream"
- />
- </ButtonGroup>
- </Box>
- {isGroup && (past || future) && (
- <Alert status="warning" my={3}>
- <AlertIcon />
- Marking a TaskGroup as {capitalize(newState)} in the future and/or
- past will affect all the tasks of this group across multiple dag
- runs.
- <br />
- This can take a while to complete.
- </Alert>
- )}
- </ActionModal>
+ {/* Only load modal is user can edit */}
+ {canEdit && (
+ <MarkAsModal
+ runId={runId}
+ taskId={taskId}
+ isGroup={isGroup}
+ mapIndex={mapIndex}
+ isMapped={isMapped}
+ state={newState}
+ isOpen={isOpen}
+ onClose={onClose}
+ />
+ )}
</>
);
};