diff --git a/.version b/.version index 71172b43ae..142464bf22 100644 --- a/.version +++ b/.version @@ -1 +1 @@ -0.10.1 \ No newline at end of file +0.11.0 \ No newline at end of file diff --git a/docs/docusaurus.config.js b/docs/docusaurus.config.js index eda2baa4ea..d2c33763cf 100644 --- a/docs/docusaurus.config.js +++ b/docs/docusaurus.config.js @@ -115,6 +115,7 @@ module.exports = { theme: { customCss: require.resolve('./src/css/custom.css'), }, + sitemap: {}, }, ], ], diff --git a/frontend/assets/images/icons/editor/datasources/runjs.svg b/frontend/assets/images/icons/editor/datasources/runjs.svg new file mode 100644 index 0000000000..5fee305989 --- /dev/null +++ b/frontend/assets/images/icons/editor/datasources/runjs.svg @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/frontend/assets/images/icons/editor/left-sidebar/settings.svg b/frontend/assets/images/icons/editor/left-sidebar/settings.svg new file mode 100644 index 0000000000..e0c2acb711 --- /dev/null +++ b/frontend/assets/images/icons/editor/left-sidebar/settings.svg @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 9338cb42bc..61cbb9f565 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -20,6 +20,7 @@ "@testing-library/user-event": "^7.2.1", "@uiw/react-codemirror": "^3.0.6", "array-move": "^3.0.1", + "axios": "^0.24.0", "babel-loader": "^8.0.5", "babel-plugin-console-source": "^2.0.5", "babel-plugin-import": "^1.13.3", @@ -4749,6 +4750,14 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, + "node_modules/axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "dependencies": { + "follow-redirects": "^1.14.4" + } + }, "node_modules/axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -10425,9 +10434,9 @@ } }, "node_modules/follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==", + "version": "1.14.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz", + "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==", "funding": [ { "type": "individual", @@ -28075,6 +28084,14 @@ "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz", "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==" }, + "axios": { + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.24.0.tgz", + "integrity": "sha512-Q6cWsys88HoPgAaFAVUb0WpPk0O8iTeisR9IMqy9G8AbO4NlpVknrnQS03zzF9PGAWgO3cgletO3VjV/P7VztA==", + "requires": { + "follow-redirects": "^1.14.4" + } + }, "axobject-query": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-2.2.0.tgz", @@ -32609,9 +32626,9 @@ "integrity": "sha1-UhTXU3pNBqSjAcDMJi/rhBiAAuc=" }, "follow-redirects": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.1.tgz", - "integrity": "sha512-HWqDgT7ZEkqRzBvc2s64vSZ/hfOceEol3ac/7tKwzuvEyWx3/4UegXh5oBOIotkGsObyk3xznnSRVADBgWSQVg==" + "version": "1.14.5", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.14.5.tgz", + "integrity": "sha512-wtphSXy7d4/OR+MvIFbCVBDzZ5520qV8XfPklSN5QtxuMUJZ+b0Wnst1e1lCDocfzuCkHqj8k0FpZqO+UIaKNA==" }, "for-in": { "version": "1.0.2", diff --git a/frontend/package.json b/frontend/package.json index 42d388b3fd..bffee674b7 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -16,6 +16,7 @@ "@testing-library/user-event": "^7.2.1", "@uiw/react-codemirror": "^3.0.6", "array-move": "^3.0.1", + "axios": "^0.24.0", "babel-loader": "^8.0.5", "babel-plugin-console-source": "^2.0.5", "babel-plugin-import": "^1.13.3", diff --git a/frontend/src/Editor/DataSourceManager/SourceComponents/Api/Runjs.schema.json b/frontend/src/Editor/DataSourceManager/SourceComponents/Api/Runjs.schema.json new file mode 100644 index 0000000000..652a934f5a --- /dev/null +++ b/frontend/src/Editor/DataSourceManager/SourceComponents/Api/Runjs.schema.json @@ -0,0 +1,18 @@ +{ + "$schema": "https://json-schema.org/", + "$id": "https://tooljet.io/Runjs.schema.json", + "title": "Runjs datasource", + "description": "A schema defining runjs datasource", + "type": "object", + "source": { + "name": "Run JavaScript", + "kind": "runjs", + "exposedVariables": { + "isLoading": {}, + "data": {}, + "rawData": {} + }, + "customTesting": true, + "disableTransformations": true + } +} \ No newline at end of file diff --git a/frontend/src/Editor/DataSourceManager/SourceComponents/Api/Stripe.schema.json b/frontend/src/Editor/DataSourceManager/SourceComponents/Api/Stripe.schema.json index 053a12c0a3..14e5a32b55 100644 --- a/frontend/src/Editor/DataSourceManager/SourceComponents/Api/Stripe.schema.json +++ b/frontend/src/Editor/DataSourceManager/SourceComponents/Api/Stripe.schema.json @@ -13,12 +13,17 @@ "rawData": {} }, "options": { - "api_key": { "type": "string", "encrypted": true } + "api_key": { + "type": "string", + "encrypted": true + } }, "customTesting": true }, "defaults": { - "api_key": { "value": "" } + "api_key": { + "value": "" + } }, "properties": { "api_key": { @@ -28,5 +33,7 @@ "description": "Api key for stripe" } }, - "required": ["api_key"] -} + "required": [ + "api_key" + ] +} \ No newline at end of file diff --git a/frontend/src/Editor/DataSourceManager/SourceComponents/index.js b/frontend/src/Editor/DataSourceManager/SourceComponents/index.js index 6ff97c81cb..1fd32c9c51 100644 --- a/frontend/src/Editor/DataSourceManager/SourceComponents/index.js +++ b/frontend/src/Editor/DataSourceManager/SourceComponents/index.js @@ -24,6 +24,9 @@ import MssqlSchema from './Database/Mssql.schema.json'; import S3Schema from './Database/S3.schema.json'; import GcsSchema from './Database/Gcs.schema.json'; +// Other sources +import RunjsSchema from './Api/Runjs.schema.json'; + const Airtable = ({ ...rest }) => ; const Restapi = ({ ...rest }) => ; const Graphql = ({ ...rest }) => ; @@ -59,8 +62,10 @@ export const ApiSources = [ GooglesheetSchema.source, SlackSchema.source, ]; + +export const OtherSources = [RunjsSchema.source]; export const CloudStorageSources = [S3Schema.source, GcsSchema.source]; -export const DataSourceTypes = [...DataBaseSources, ...ApiSources, ...CloudStorageSources]; +export const DataSourceTypes = [...DataBaseSources, ...ApiSources, ...CloudStorageSources, ...OtherSources]; export const SourceComponents = { Elasticsearch, diff --git a/frontend/src/Editor/Editor.jsx b/frontend/src/Editor/Editor.jsx index cf992983f9..be5197b7a1 100644 --- a/frontend/src/Editor/Editor.jsx +++ b/frontend/src/Editor/Editor.jsx @@ -30,6 +30,10 @@ import { WidgetManager } from './WidgetManager'; import Fuse from 'fuse.js'; import config from 'config'; import queryString from 'query-string'; +import Logo from './Icons/logo.svg'; +import EditIcon from './Icons/edit.svg'; +import MobileSelectedIcon from './Icons/mobile-selected.svg'; +import DesktopSelectedIcon from './Icons/desktop-selected.svg'; class Editor extends React.Component { constructor(props) { @@ -67,6 +71,11 @@ class Editor extends React.Component { deviceWindowWidth: 450, appDefinition: { components: {}, + globalSettings: { + hideHeader: false, + canvasMaxWidth: 1292, + canvasBackgroundColor: props.darkMode ? '#2f3c4c' : '#edeff5', + }, }, currentState: { queries: {}, @@ -236,7 +245,7 @@ class Editor extends React.Component { const appId = this.props.match.params.id; appService.getApp(appId).then((data) => { - const dataDefinition = data.definition || { components: {} }; + const dataDefinition = data.definition || {}; this.setState( { app: data, @@ -256,7 +265,7 @@ class Editor extends React.Component { }; setAppDefinitionFromVersion = (version) => { - this.appDefinitionChanged(version.definition || { components: {} }); + this.appDefinitionChanged(version.definition || {}); this.setState({ editingVersion: version, }); @@ -360,6 +369,15 @@ class Editor extends React.Component { }); }; + globalSettingsChanged = (key, value) => { + const appDefinition = { ...this.state.appDefinition }; + + appDefinition.globalSettings[key] = value; + this.setState({ + appDefinition, + }); + }; + saveApp = (id, attributes, notify = false) => { appService.saveApp(id, attributes).then(() => { if (notify) { @@ -578,6 +596,21 @@ class Editor extends React.Component { return canvasBoundingRect?.width; }; + renderLayoutIcon = (isDesktopSelected) => { + if (isDesktopSelected) + return ( + this.setState({ currentLayout: isDesktopSelected ? 'mobile' : 'desktop' })}> + + + ); + + return ( + this.setState({ currentLayout: isDesktopSelected ? 'mobile' : 'desktop' })}> + + + ); + }; + render() { const { currentSidebarTab, @@ -610,6 +643,7 @@ class Editor extends React.Component { defaultComponentStateComputed, showComments, } = this.state; + const appLink = slug ? `/applications/${slug}` : ''; return ( @@ -645,36 +679,28 @@ class Editor extends React.Component {

- +

{this.state.app && ( - this.setState({ oldName: e.target.value })} - onChange={(e) => this.onNameChanged(e.target.value)} - onBlur={(e) => this.saveAppName(this.state.app.id, e.target.value)} - className="form-control-plaintext form-control-plaintext-sm" - value={this.state.app.name} - /> - )} - {this.state.editingVersion && `App version: ${this.state.editingVersion.name}`} -
- - + this.setState({ oldName: e.target.value })} + onChange={(e) => this.onNameChanged(e.target.value)} + onBlur={(e) => this.saveAppName(this.state.app.id, e.target.value)} + className="form-control-plaintext form-control-plaintext-sm" + value={this.state.app.name} /> - + + + +
+ )} + {this.state.editingVersion && ( + {`App version: ${this.state.editingVersion.name}`} + )} +
-
-
- - -
+
+ {this.renderLayoutIcon(currentLayout === 'desktop')}
@@ -728,7 +735,7 @@ class Editor extends React.Component { Launch @@ -767,6 +774,8 @@ class Editor extends React.Component { onZoomChanged={this.onZoomChanged} toggleComments={this.toggleComments} switchDarkMode={this.props.switchDarkMode} + globalSettingsChanged={this.globalSettingsChanged} + globalSettings={appDefinition.globalSettings} />
{defaultComponentStateComputed && ( <> @@ -822,7 +835,43 @@ class Editor extends React.Component {
+
QUERIES
+ + + + + +
+
+ + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/Editor/Icons/edit.svg b/frontend/src/Editor/Icons/edit.svg new file mode 100644 index 0000000000..5f90000354 --- /dev/null +++ b/frontend/src/Editor/Icons/edit.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/frontend/src/Editor/Icons/logo.svg b/frontend/src/Editor/Icons/logo.svg new file mode 100644 index 0000000000..638458ebee --- /dev/null +++ b/frontend/src/Editor/Icons/logo.svg @@ -0,0 +1,30 @@ + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/Editor/Icons/maximize.svg b/frontend/src/Editor/Icons/maximize.svg new file mode 100644 index 0000000000..a7464d8ca5 --- /dev/null +++ b/frontend/src/Editor/Icons/maximize.svg @@ -0,0 +1,6 @@ + + + \ No newline at end of file diff --git a/frontend/src/Editor/Icons/minimize.svg b/frontend/src/Editor/Icons/minimize.svg new file mode 100644 index 0000000000..9e2445f6ac --- /dev/null +++ b/frontend/src/Editor/Icons/minimize.svg @@ -0,0 +1,10 @@ + + + + + + + \ No newline at end of file diff --git a/frontend/src/Editor/Icons/mobile-selected.svg b/frontend/src/Editor/Icons/mobile-selected.svg new file mode 100644 index 0000000000..a136da50e3 --- /dev/null +++ b/frontend/src/Editor/Icons/mobile-selected.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/frontend/src/Editor/LeftSidebar/SidebarComment.jsx b/frontend/src/Editor/LeftSidebar/SidebarComment.jsx index dee858bdd1..f1b7d7ccff 100644 --- a/frontend/src/Editor/LeftSidebar/SidebarComment.jsx +++ b/frontend/src/Editor/LeftSidebar/SidebarComment.jsx @@ -6,7 +6,6 @@ export const LeftSidebarComment = ({ toggleComments, appVersionsId }) => { const [isActive, toggleActive] = React.useState(false); return ( { + const [open, trigger, content] = usePopover(false); + const { hideHeader, canvasMaxWidth, canvasBackgroundColor } = globalSettings; + const [showPicker, setShowPicker] = React.useState(false); + const coverStyles = { + position: 'fixed', + top: '0px', + right: '0px', + bottom: '0px', + left: '0px', + }; + return ( + <> + +
+
+
+
+ Hide header for launched apps +
+ globalSettingsChanged('hideHeader', e.target.checked)} + /> +
+
+
+ Max width of canvas +
+
+ { + globalSettingsChanged('canvasMaxWidth', e.target.value); + }} + value={canvasMaxWidth} + /> + px +
+
+
+
+ Background color of canvas +
+ {showPicker && ( +
+
setShowPicker(false)} /> + setShowPicker(true)} + color={canvasBackgroundColor} + onChangeComplete={(color) => globalSettingsChanged('canvasBackgroundColor', color.hex)} + /> +
+ )} + +
setShowPicker(true)} + > +
+
{canvasBackgroundColor}
+
+
+
+
+
+
+ + ); +}; diff --git a/frontend/src/Editor/LeftSidebar/index.js b/frontend/src/Editor/LeftSidebar/index.js index a816c5b953..c1d997b2df 100644 --- a/frontend/src/Editor/LeftSidebar/index.js +++ b/frontend/src/Editor/LeftSidebar/index.js @@ -9,6 +9,7 @@ import { DarkModeToggle } from '../../_components/DarkModeToggle'; import useRouter from '../../_hooks/use-router'; import { LeftSidebarDebugger } from './SidebarDebugger'; import { LeftSidebarComment } from './SidebarComment'; +import { LeftSidebarGlobalSettings } from './SidebarGlobalSettings'; import { ConfirmDialog } from '@/_components'; import config from 'config'; @@ -24,7 +25,10 @@ export const LeftSidebar = ({ dataSourcesChanged, errorLogs, appVersionsId, + globalSettingsChanged, + globalSettings, }) => { + console.log('11', globalSettings); const router = useRouter(); const [showLeaveDialog, setShowLeaveDialog] = useState(false); return ( @@ -40,6 +44,7 @@ export const LeftSidebar = ({ {config.COMMENT_FEATURE_ENABLE && ( )} + setShowLeaveDialog(true)} tip="Back to home" diff --git a/frontend/src/Editor/ManageAppUsers.jsx b/frontend/src/Editor/ManageAppUsers.jsx index 69219ccd13..bfa51686fc 100644 --- a/frontend/src/Editor/ManageAppUsers.jsx +++ b/frontend/src/Editor/ManageAppUsers.jsx @@ -7,6 +7,7 @@ import { CopyToClipboard } from 'react-copy-to-clipboard'; import 'react-toastify/dist/ReactToastify.css'; import Skeleton from 'react-loading-skeleton'; import { debounce } from 'lodash'; +import Textarea from '@/_ui/Textarea'; class ManageAppUsers extends React.Component { constructor(props) { @@ -134,10 +135,11 @@ class ManageAppUsers extends React.Component { const appLink = `${window.location.origin}/applications/`; const shareableLink = appLink + (this.props.slug || appId); const slugButtonClass = isSlugVerificationInProgress ? '' : slugError !== null ? 'is-invalid' : 'is-valid'; + const embeddableLink = ``; return (
- @@ -220,6 +222,27 @@ class ManageAppUsers extends React.Component {

+
+ +
+