diff --git a/packages/web/src/appobj/SavedFileAppObject.js b/packages/web/src/appobj/SavedFileAppObject.js
new file mode 100644
index 000000000..7b6751679
--- /dev/null
+++ b/packages/web/src/appobj/SavedFileAppObject.js
@@ -0,0 +1,79 @@
+import React from 'react';
+import axios from '../utility/axios';
+import _ from 'lodash';
+import { DropDownMenuItem } from '../modals/DropDownMenu';
+import { AppObjectCore } from './AppObjectCore';
+import useNewQuery from '../query/useNewQuery';
+import { openNewTab } from '../utility/common';
+import { useSetOpenedTabs } from '../utility/globalState';
+
+function Menu({ data }) {
+ const handleDelete = () => {
+ axios.post('files/delete', data);
+ };
+ return (
+ <>
+ Delete
+ >
+ );
+}
+
+export function SavedFileAppObjectBase({ data, commonProps, format, icon, onLoad }) {
+ const { file, folder } = data;
+
+ const onClick = async () => {
+ const resp = await axios.post('files/load', { folder, file, format });
+ onLoad(resp.data);
+ };
+
+ return ;
+}
+
+export function SavedSqlFileAppObject({ data, commonProps }) {
+ const { file, folder } = data;
+ const newQuery = useNewQuery();
+
+ return (
+ {
+ newQuery({
+ title: file,
+ // @ts-ignore
+ initialScript: data,
+ });
+ }}
+ />
+ );
+}
+
+export function SavedShellFileAppObject({ data, commonProps }) {
+ const { file, folder } = data;
+ const setOpenedTabs = useSetOpenedTabs();
+ return (
+ {
+ openNewTab(setOpenedTabs, {
+ title: file,
+ icon: 'img shell',
+ tabComponent: 'ShellTab',
+ props: {
+ initialScript: data,
+ },
+ });
+ }}
+ />
+ );
+}
+
+[SavedSqlFileAppObject, SavedShellFileAppObject].forEach((fn) => {
+ // @ts-ignore
+ fn.extractKey = (data) => data.file;
+});
diff --git a/packages/web/src/appobj/SavedSqlFileAppObject.js b/packages/web/src/appobj/SavedSqlFileAppObject.js
deleted file mode 100644
index 891badf29..000000000
--- a/packages/web/src/appobj/SavedSqlFileAppObject.js
+++ /dev/null
@@ -1,37 +0,0 @@
-import React from 'react';
-import axios from '../utility/axios';
-import _ from 'lodash';
-import { DropDownMenuItem } from '../modals/DropDownMenu';
-import { AppObjectCore } from './AppObjectCore';
-import useNewQuery from '../query/useNewQuery';
-
-function Menu({ data }) {
- const handleDelete = () => {
- axios.post('files/delete', { folder: 'sql', file: data.name });
- };
- return (
- <>
- Delete
- >
- );
-}
-
-function SavedSqlFileAppObject({ data, commonProps }) {
- const { file } = data;
- const newQuery = useNewQuery();
-
- const onClick = async () => {
- const resp = await axios.post('files/load', { folder: 'sql', file, format: 'text' });
- newQuery({
- title: file,
- // @ts-ignore
- initialScript: resp.data,
- });
- };
-
- return ;
-}
-
-SavedSqlFileAppObject.extractKey = (data) => data.file;
-
-export default SavedSqlFileAppObject;
diff --git a/packages/web/src/widgets/FilesWidget.js b/packages/web/src/widgets/FilesWidget.js
index eb1ac80e3..65bb0aeef 100644
--- a/packages/web/src/widgets/FilesWidget.js
+++ b/packages/web/src/widgets/FilesWidget.js
@@ -5,7 +5,7 @@ import { AppObjectList } from '../appobj/AppObjectList';
import { useOpenedTabs } from '../utility/globalState';
import ClosedTabAppObject from '../appobj/ClosedTabAppObject';
import { WidgetsInnerContainer } from './WidgetStyles';
-import SavedSqlFileAppObject from '../appobj/SavedSqlFileAppObject';
+import { SavedSqlFileAppObject } from '../appobj/SavedFileAppObject';
import WidgetColumnBar, { WidgetColumnBarItem } from './WidgetColumnBar';
import { useFiles } from '../utility/metadataLoaders';