diff --git a/mage_ai/frontend/components/MultiColumnController/index.style.tsx b/mage_ai/frontend/components/MultiColumnController/index.style.tsx
index 64a7e4599f00..eef8688a46fe 100644
--- a/mage_ai/frontend/components/MultiColumnController/index.style.tsx
+++ b/mage_ai/frontend/components/MultiColumnController/index.style.tsx
@@ -5,7 +5,7 @@ import { DRAGGABLE_WIDTH as DRAGGABLE_WIDTH_INIT } from '@components/TripleLayou
import { transition } from '@oracle/styles/mixins';
import { ScrollbarStyledCss } from '@oracle/styles/scrollbars';
-export const DRAGGABLE_WIDTH = DRAGGABLE_WIDTH_INIT
+export const DRAGGABLE_WIDTH = DRAGGABLE_WIDTH_INIT;
export const DIVIDER_WIDTH = 2;
export const ColumnStyle = styled.div<{
diff --git a/mage_ai/frontend/components/PipelineDetail/FileHeaderMenu/FileHeaderMenuItem.tsx b/mage_ai/frontend/components/PipelineDetail/FileHeaderMenu/FileHeaderMenuItem.tsx
index 49821f108495..eef7e5b49ef3 100644
--- a/mage_ai/frontend/components/PipelineDetail/FileHeaderMenu/FileHeaderMenuItem.tsx
+++ b/mage_ai/frontend/components/PipelineDetail/FileHeaderMenu/FileHeaderMenuItem.tsx
@@ -11,6 +11,8 @@ type FileHeaderMenuItemProps = {
muted?: boolean;
};
+export const blankIcon =
;
+
function FileHeaderMenuItem({
beforeIcon,
checked,
@@ -23,7 +25,7 @@ function FileHeaderMenuItem({
? beforeIcon
: (checked
?
- :
+ : blankIcon
)
}
diff --git a/mage_ai/frontend/components/PipelineDetail/FileHeaderMenu/index.tsx b/mage_ai/frontend/components/PipelineDetail/FileHeaderMenu/index.tsx
index 10863e359ab1..966ec02a88fa 100644
--- a/mage_ai/frontend/components/PipelineDetail/FileHeaderMenu/index.tsx
+++ b/mage_ai/frontend/components/PipelineDetail/FileHeaderMenu/index.tsx
@@ -3,7 +3,7 @@ import { useEffect, useMemo, useRef, useState } from 'react';
import Button from '@oracle/elements/Button';
import ClickOutside from '@oracle/components/ClickOutside';
import FlexContainer from '@oracle/components/FlexContainer';
-import FileHeaderMenuItem from './FileHeaderMenuItem';
+import FileHeaderMenuItem, { blankIcon } from './FileHeaderMenuItem';
import FlyoutMenu from '@oracle/components/FlyoutMenu';
import KernelOutputType from '@interfaces/KernelOutputType';
import PipelineType, {
@@ -14,6 +14,7 @@ import Text from '@oracle/elements/Text';
import useKernel from '@utils/models/kernel/useKernel';
import useProject from '@utils/models/project/useProject';
import {
+ Check,
LayoutSplit,
LayoutStacked,
} from '@oracle/icons';
@@ -31,7 +32,6 @@ import {
KEY_CODE_ARROW_RIGHT,
} from '@utils/hooks/keyboardShortcuts/constants';
import { SHARED_FILE_HEADER_BUTTON_PROPS } from './constants';
-import { ViewKeyEnum } from '@components/Sidekick/constants';
import { isMac } from '@utils/os';
import { randomNameGenerator } from '@utils/string';
import { useKeyboardContext } from '@context/Keyboard';
@@ -44,6 +44,7 @@ type FileHeaderMenuProps = {
children?: any;
collapseAllBlockOutputs?: (state: boolean) => void;
createPipeline: (data: any) => void;
+ disableAutosave?: boolean;
executePipeline: () => void;
hideOutputOnExecution?: boolean;
interruptKernel: () => void;
@@ -52,16 +53,13 @@ type FileHeaderMenuProps = {
restartKernel: () => void;
savePipelineContent: () => void;
scrollTogether?: boolean;
- setActiveSidekickView: (
- newView: ViewKeyEnum,
- pushHistory?: boolean,
- ) => void;
setMessages: (message: {
[uuid: string]: KernelOutputType[];
}) => void;
setScrollTogether?: (prev: any) => void;
setSideBySideEnabled?: (prev: any) => void;
sideBySideEnabled?: boolean;
+ toggleDisableAutosave?: () => void;
toggleHideOutputOnExecution?: () => void;
updatePipelineMetadata: (name: string, type?: string) => void;
};
@@ -71,6 +69,7 @@ function FileHeaderMenu({
children,
collapseAllBlockOutputs,
createPipeline,
+ disableAutosave,
executePipeline,
hideOutputOnExecution,
interruptKernel,
@@ -79,11 +78,11 @@ function FileHeaderMenu({
restartKernel,
savePipelineContent,
scrollTogether,
- setActiveSidekickView,
setMessages,
setScrollTogether,
setSideBySideEnabled,
sideBySideEnabled,
+ toggleDisableAutosave,
toggleHideOutputOnExecution,
updatePipelineMetadata,
}: FileHeaderMenuProps) {
@@ -102,6 +101,7 @@ function FileHeaderMenu({
const fileItems = [
{
+ beforeIcon: blankIcon,
label: () => 'New standard pipeline',
// @ts-ignore
onClick: () => createPipeline({
@@ -112,6 +112,7 @@ function FileHeaderMenu({
uuid: 'new_standard_pipeline',
},
{
+ beforeIcon: blankIcon,
label: () => 'New streaming pipeline',
// @ts-ignore
onClick: () => createPipeline({
@@ -123,6 +124,7 @@ function FileHeaderMenu({
uuid: 'new_streaming_pipeline',
},
{
+ beforeIcon: blankIcon,
keyTextGroups: [[
isMac() ? KEY_SYMBOL_META : KEY_SYMBOL_CONTROL,
KEY_SYMBOL_S,
@@ -131,6 +133,12 @@ function FileHeaderMenu({
onClick: () => savePipelineContent(),
uuid: 'save_pipeline',
},
+ {
+ beforeIcon: disableAutosave ? : blankIcon,
+ label: () => 'Disable autosave',
+ onClick: toggleDisableAutosave,
+ uuid: 'Disable_autosave',
+ },
];
const runItems = useMemo(() => {
const items = [
@@ -149,20 +157,20 @@ function FileHeaderMenu({
// uuid: 'Delete selected block',
// },
{
- label: () => 'Interrupt kernel',
keyTextGroups: [
[KEY_SYMBOL_I],
[KEY_SYMBOL_I],
],
+ label: () => 'Interrupt kernel',
onClick: () => interruptKernel(),
uuid: 'Interrupt kernel',
},
{
- label: () => 'Restart kernel',
keyTextGroups: [
[KEY_CODE_NUMBERS_TO_NUMBER[KEY_CODE_NUMBER_0]],
[KEY_CODE_NUMBERS_TO_NUMBER[KEY_CODE_NUMBER_0]],
],
+ label: () => 'Restart kernel',
onClick: () => restartKernel(),
uuid: 'Restart kernel',
},
diff --git a/mage_ai/frontend/components/PipelineDetail/StatusFooter/index.tsx b/mage_ai/frontend/components/PipelineDetail/StatusFooter/index.tsx
index c30f3ce0943b..e48334e268fa 100644
--- a/mage_ai/frontend/components/PipelineDetail/StatusFooter/index.tsx
+++ b/mage_ai/frontend/components/PipelineDetail/StatusFooter/index.tsx
@@ -1,11 +1,8 @@
import React from 'react';
-import moment from 'moment';
import { useMemo } from 'react';
import Divider from '@oracle/elements/Divider';
-import Flex from '@oracle/components/Flex';
import FlexContainer from '@oracle/components/FlexContainer';
-import KernelType from '@interfaces/KernelType';
import KeyboardText from '@oracle/elements/KeyboardText';
import Spacing from '@oracle/elements/Spacing';
import Text from '@oracle/elements/Text';
@@ -13,8 +10,6 @@ import Tooltip from '@oracle/components/Tooltip';
import useKernel from '@utils/models/kernel/useKernel';
import { AlertTriangle, File as FileIcon, HexagonAll, Lightning } from '@oracle/icons';
import {
- KEY_CODE_ENTER,
- KEY_CODE_META,
KEY_SYMBOL_CONTROL,
KEY_SYMBOL_META,
KEY_SYMBOL_S,
@@ -84,7 +79,6 @@ function StatusFooter({
-
{usage && (
<>
@@ -105,8 +99,8 @@ function StatusFooter({
small
>
CPU: = 90}
+ inline
muted={cpu < 50}
small
warning={cpu >= 50 && cpu < 90}
@@ -171,7 +165,7 @@ function StatusFooter({
- Or, go to
+ Or go to
File
{' › '}
Save pipeline
@@ -192,8 +186,8 @@ function StatusFooter({
)}
{!pipelineContentTouched && (
)}
diff --git a/mage_ai/frontend/components/PipelineDetail/index.tsx b/mage_ai/frontend/components/PipelineDetail/index.tsx
index 523cced4d749..0349c2a553ae 100644
--- a/mage_ai/frontend/components/PipelineDetail/index.tsx
+++ b/mage_ai/frontend/components/PipelineDetail/index.tsx
@@ -125,6 +125,7 @@ type PipelineDetailProps = {
};
dataProviders: DataProviderType[];
deleteBlock: (block: BlockType) => Promise;
+ disableAutosave?: boolean;
disableShortcuts: boolean;
fetchFileTree: () => void;
fetchPipeline: () => void;
@@ -223,6 +224,7 @@ function PipelineDetail({
blocksThatNeedToRefresh,
dataProviders,
deleteBlock,
+ disableAutosave,
disableShortcuts,
fetchFileTree,
fetchPipeline,
@@ -679,7 +681,7 @@ df = get_variable('${pipeline.uuid}', '${block.uuid}', 'output_0')
useEffect(() => {
const autoSaveInterval = setInterval(() => {
- if (pipelineContentTouched) {
+ if (pipelineContentTouched && !disableAutosave) {
savePipelineContent();
}
}, 1000 * 10);
@@ -688,6 +690,7 @@ df = get_variable('${pipeline.uuid}', '${block.uuid}', 'output_0')
clearInterval(autoSaveInterval);
};
}, [
+ disableAutosave,
pipelineContentTouched,
savePipelineContent,
]);
diff --git a/mage_ai/frontend/pages/pipelines/[pipeline]/edit.tsx b/mage_ai/frontend/pages/pipelines/[pipeline]/edit.tsx
index 6ddc43054d9f..9032fce58df2 100644
--- a/mage_ai/frontend/pages/pipelines/[pipeline]/edit.tsx
+++ b/mage_ai/frontend/pages/pipelines/[pipeline]/edit.tsx
@@ -98,6 +98,7 @@ import { DEBUG } from '@utils/environment';
import { ErrorProvider } from '@context/Error';
import { INTERNAL_OUTPUT_REGEX } from '@utils/models/output';
import {
+ LOCAL_STORAGE_KEY_DISABLE_AUTOSAVE,
LOCAL_STORAGE_KEY_PIPELINE_EDIT_BEFORE_TAB_SELECTED,
LOCAL_STORAGE_KEY_PIPELINE_EDIT_BLOCK_OUTPUT_LOGS,
LOCAL_STORAGE_KEY_PIPELINE_EDIT_HIDDEN_BLOCKS,
@@ -489,6 +490,17 @@ function PipelineDetailPage({
hideBlockOutputOnExecutionUpdated,
);
}, [hideBlockOutputOnExecution]);
+ const [disableAutosave, setDisableAutosave] = useState(
+ get(LOCAL_STORAGE_KEY_DISABLE_AUTOSAVE, false),
+ );
+ const toggleDisableAutosave = useCallback(() => {
+ const disableAutosaveUpdated = !disableAutosave;
+ setDisableAutosave(disableAutosaveUpdated);
+ set(
+ LOCAL_STORAGE_KEY_DISABLE_AUTOSAVE,
+ disableAutosaveUpdated,
+ );
+ }, [disableAutosave]);
const dispatchEventChanged = useCallback(() => {
const evt = new CustomEvent(CUSTOM_EVENT_CODE_BLOCK_CHANGED, {
@@ -3119,6 +3131,7 @@ function PipelineDetailPage({
blocksThatNeedToRefresh={blocksThatNeedToRefresh}
dataProviders={dataProviders}
deleteBlock={deleteBlock}
+ disableAutosave={disableAutosave}
disableShortcuts={disableShortcuts}
fetchFileTree={fetchFiles}
fetchPipeline={fetchPipeline}
@@ -3126,9 +3139,9 @@ function PipelineDetailPage({
files={files}
globalDataProducts={globalDataProducts}
globalVariables={globalVariables}
- hideOutputOnExecution={hideBlockOutputOnExecution}
// @ts-ignore
hiddenBlocks={hiddenBlocks}
+ hideOutputOnExecution={hideBlockOutputOnExecution}
interactionsMapping={interactionsMapping}
interruptKernel={interruptKernel}
mainContainerRef={mainContainerRef}
@@ -3185,6 +3198,7 @@ function PipelineDetailPage({
blocksThatNeedToRefresh,
dataProviders,
deleteBlock,
+ disableAutosave,
disableShortcuts,
fetchFiles,
fetchPipeline,
@@ -3236,6 +3250,7 @@ function PipelineDetailPage({
@@ -3257,6 +3272,7 @@ function PipelineDetailPage({
}, [
cancelPipeline,
createPipeline,
+ disableAutosave,
executePipeline,
hideBlockOutputOnExecution,
interruptKernel,
@@ -3270,6 +3286,7 @@ function PipelineDetailPage({
setScrollTogether,
setSideBySideEnabled,
sideBySideEnabled,
+ toggleDisableAutosave,
toggleHideBlockOutputOnExecution,
updatePipelineMetadata,
]);
diff --git a/mage_ai/frontend/storage/constants.ts b/mage_ai/frontend/storage/constants.ts
index 50587531e3ba..8aefc7caa406 100644
--- a/mage_ai/frontend/storage/constants.ts
+++ b/mage_ai/frontend/storage/constants.ts
@@ -23,3 +23,4 @@ export const LOCAL_STORAGE_KEY_INCLUDE_SERVER_TIME_SECONDS =
export const LOCAL_STORAGE_KEY_PIPELINE_EDITOR_SIDE_BY_SIDE_ENABLED = 'pipeline_editor_side_by_side_enabled';
export const LOCAL_STORAGE_KEY_PIPELINE_EDITOR_SIDE_BY_SIDE_SCROLL_TOGETHER = 'pipeline_editor_side_by_side_scroll_together';
export const LOCAL_STORAGE_KEY_HIDE_BLOCK_OUTPUT_ON_EXECUTION = 'hide_block_output_on_execution';
+export const LOCAL_STORAGE_KEY_DISABLE_AUTOSAVE = 'disable_autosave';