2019-01-21 15:11:10 +00:00
<!DOCTYPE html>
< html lang = "en" >
2019-09-06 09:30:22 +00:00
2019-11-06 12:12:41 +00:00
< head >
2020-05-05 12:16:51 +00:00
< meta charset = "utf-8" / >
2019-11-06 12:12:41 +00:00
< meta name = "viewport" content = "width=device-width, initial-scale=1, shrink-to-fit=no" / >
< title > Appsmith< / title >
2020-05-05 12:16:51 +00:00
< style >
#loader {
position: fixed;
left: 0;
top: 0;
height: 4px;
2022-12-09 14:43:47 +00:00
background: #D7D7D7;
2020-05-05 12:16:51 +00:00
transition: all ease-in 0.3s;
}
< / style >
2023-05-11 05:26:03 +00:00
< %=
(function () {
// This code emits additional `link rel="preload"` tags for edit.html and view.html.
// This helps to load edit and view modes faster.
//
// If you code-split some code and need to preload it as well, here’ s how to do that:
// 1) Give your import a name (use the `webpackChunkName` comment: `import(/* webpackChunkName: "my-name" */ "./my-file")`)
// 2) Add the name into the `chunksToPreload` array below
let chunksToPreload = [];
if (htmlWebpackPlugin.options.appsmithHtmlTarget === 'edit-mode') {
chunksToPreload = [
...compilation.namedChunkGroups.get("editor").chunks,
...compilation.namedChunkGroups.get("global-search").chunks,
]
} else if (htmlWebpackPlugin.options.appsmithHtmlTarget === 'view-mode') {
chunksToPreload = [...compilation.namedChunkGroups.get("AppViewer").chunks]
}
return chunksToPreload.flatMap(i => [...i.files])
.map(url => `< link rel = "preload" as = "${getPreloadValueForFile(url)}" href = "${webpackConfig.output.publicPath + url}" / > `)
.join('\n')
function getPreloadValueForFile(fileName) {
if (fileName.endsWith('.js')) {
return 'script';
} else if (fileName.endsWith('.css')) {
return 'style';
}
throw new Error(`Unknown preload type for file: ${fileName}`);
}
})()
%>
2021-10-18 06:18:27 +00:00
< script >
// '' (empty strings), 'false' are falsy
// could return either boolean or string based on value
const parseConfig = (config) => {
if (config.indexOf("__") === 0 || config.indexOf("$") === 0 || config.indexOf("%") === 0)
return "";
const result = config.trim();
if (result.toLowerCase() === "false" || result === "") {
return false;
} else if (result.toLowerCase() === "true") {
return true;
}
return result;
}
const CLOUD_HOSTING = parseConfig("__APPSMITH_CLOUD_HOSTING__");
2022-02-25 03:28:03 +00:00
const ZIPY_KEY = parseConfig("__APPSMITH_ZIPY_SDK_KEY__");
2023-03-15 10:03:27 +00:00
if (CLOUD_HOSTING & & ZIPY_KEY) {
2022-02-25 03:28:03 +00:00
const script = document.createElement('script');
script.crossOrigin = "anonymous";
script.defer = true;
script.src = "https://cdn.zipy.ai/sdk/v1.0/zipy.min.umd.js";
script.onload = () => {
window.zipy & & window.zipy.init(ZIPY_KEY);
}
const head = document.getElementsByTagName('head')[0];
head & & head.appendChild(script);
}
2023-03-15 11:03:14 +00:00
// This function is triggered on load of google apis javascript library
// Even though the script is loaded asynchronously, in case of firefox run on windows
// The gapi script is getting loaded even before the last script of index.html
// Hence defining this function before loading gapi
// For more info: https://github.com/appsmithorg/appsmith/issues/21033
gapiLoaded = () => {
window.googleAPIsLoaded = true;
}
2023-04-27 06:24:38 +00:00
onError = () => {
window.googleAPIsLoaded = false;
};
2021-10-18 06:18:27 +00:00
< / script >
feat: file picker added and access token generation (#20778)
## Description
This PR includes following changes:
- In case of limiting google sheet access project, when user selects specific sheets as an option, they should be shown file picker UI once the authorisation is complete, In this file picker UI, users can select the google sheet files that they want to use with appsmith application and allow access to only those files.
- This PR contains the changes for file picker UI and updating datasource auth state based on the files selected by user.
TL;DR
Steps to test this PR:
- Create Google Sheet datasource
- In the datasource config form, select specific sheets as an option from the scope dropdown.
- Click on save and authorise
- This will take you to google oauth process
<img width="467" alt="Screenshot 2023-02-20 at 1 24 24 PM" src="https://user-images.githubusercontent.com/30018882/220045493-57b0ca6c-3f08-4963-af55-d603cf79bc43.png">
- Select the google account
- This will take you to google oauth2 consent screen
<img width="451" alt="Screenshot 2023-02-20 at 1 24 55 PM" src="https://user-images.githubusercontent.com/30018882/220045641-9f70dd29-6664-489a-b77b-df65445491df.png">
- Click on allow for all requested permissions
- This will take you back to appsmith's datasource config page in view mode and load the file picker UI
<img width="425" alt="Screenshot 2023-02-20 at 1 25 47 PM" src="https://user-images.githubusercontent.com/30018882/220045828-8b3e3e46-4ddc-4e30-b2f8-f12865395817.png">
- Select the files that you want to share with appsmith app
- Click on select
- You should see the new query button in enabled state, as datasource authorisation is complete
<img width="800" alt="Screenshot 2023-02-20 at 1 27 28 PM" src="https://user-images.githubusercontent.com/30018882/220046131-6ce99a85-cddc-4529-ae45-f9833aefd71b.png">
- In case you select cancel on google oauth2 consent screen, you should error message on datasource config page with new query button being disabled
<img width="810" alt="Screenshot 2023-02-20 at 1 28 49 PM" src="https://user-images.githubusercontent.com/30018882/220046385-6b8d636c-b517-44c3-a596-b52bc0084b94.png">
- In case you do give all the permissions but do not select any files in google file picker, then also you should see error message on datasource config page with new query button disabled.
Fixes #20163, #20290, #20160, #20162
Media
> A video or a GIF is preferred. when using Loom, don’t embed because it looks like it’s a GIF. instead, just link to the video
## Type of change
> Please delete options that are not relevant.
- New feature (non-breaking change which adds functionality)
## How Has This Been Tested?
- Manual
### Test Plan
> Add Testsmith test cases links that relate to this PR
### Issues raised during DP testing
> Link issues raised during DP testing for better visiblity and tracking (copy link from comments dropped on this PR)
## Checklist:
### Dev activity
- [x] My code follows the style guidelines of this project
- [x] I have performed a self-review of my own code
- [x] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [x] My changes generate no new warnings
- [ ] I have added tests that prove my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [x] PR is being merged under a feature flag
### QA activity:
- [ ] Test plan has been approved by relevant developers
- [ ] Test plan has been peer reviewed by QA
- [ ] Cypress test cases have been added and approved by either SDET or manual QA
- [ ] Organized project review call with relevant stakeholders after Round 1/2 of QA
- [ ] Added Test Plan Approved label after reveiwing all Cypress test
Co-authored-by: “sneha122” <“sneha@appsmith.com”>
2023-03-08 05:25:17 +00:00
<!-- Adding this Library to access google file picker API in case of limiting google sheet access -->
2023-04-27 06:24:38 +00:00
< script async defer id = "googleapis" src = "https://apis.google.com/js/api.js" onload = "gapiLoaded()" onerror = "onError()" > < / script >
2019-11-06 12:12:41 +00:00
< / head >
2020-07-06 13:36:42 +00:00
2021-12-24 07:25:25 +00:00
< body class = "appsmith-light-theme" >
2019-11-06 12:12:41 +00:00
< noscript > You need to enable JavaScript to run this app.< / noscript >
2020-05-05 12:16:51 +00:00
< div id = "loader" style = "width: 30vw;" > < / div >
2021-05-20 12:03:08 +00:00
<!--
2021-07-05 05:49:43 +00:00
To keep zIndex for tooltips higher than app comments, todo remove when migrating to Tooltip2
2021-05-20 12:03:08 +00:00
Currently the className does not apply to the portal root, so we're unable to work with z-indexes based on that
-->
2020-12-30 09:06:24 +00:00
< div id = "header-root" > < / div >
2019-11-06 12:12:41 +00:00
< div id = "root" > < / div >
2023-05-19 18:37:06 +00:00
< div id = "date-picker-control" style = "position: relative; z-index: 1000;" > < / div >
2020-01-22 12:26:25 +00:00
< script type = "text/javascript" >
2021-04-26 09:18:39 +00:00
// Ref: https://github.com/Modernizr/Modernizr/blob/94592f279a410436530c7c06acc42a6e90c20150/feature-detects/storage/localstorage.js
const getIsLocalStorageSupported = () => {
try {
window.localStorage.setItem("test", "testA");
window.localStorage.removeItem("test");
return true;
} catch (e) {
return false;
}
};
const isLocalStorageSupported = getIsLocalStorageSupported();
const handleLocalStorageNotSupportedError = () => {
console.error("Localstorage storage is not supported on your device.");
}
const localStorageUtil = {
getItem: (key) => {
if (!isLocalStorageSupported) {
handleLocalStorageNotSupportedError();
return;
}
return window.localStorage.getItem(key);
},
removeItem: (key) => {
if (!isLocalStorageSupported) {
handleLocalStorageNotSupportedError();
return
}
return window.localStorage.removeItem(key);
},
setItem: (key, value) => {
if (!isLocalStorageSupported) {
handleLocalStorageNotSupportedError();
return;
}
return window.localStorage.setItem(key, value);
}
};
2020-05-05 12:16:51 +00:00
window.addEventListener("DOMContentLoaded", (event) => {
document.getElementById("loader").style.width = "50vw";
});
2020-10-15 16:46:01 +00:00
2020-05-05 12:16:51 +00:00
const registerPageServiceWorker = () => {
2023-05-11 05:26:03 +00:00
if (
"serviceWorker" in navigator
// Disable the service worker in Cypress tests. We primarily do this to make
// the Performance/LinkRelPreload_Spec.js test work (as it collects URLs all network requests,
// and service worker requests fail it.) But, anecdotally, disabling the service worker
// also seems to make the tests a bit faster, as the network load is lower.
& & !window.Cypress
) {
2020-05-05 12:16:51 +00:00
window.addEventListener("load", function () {
navigator.serviceWorker.register("/pageService.js").catch(error => {
2021-07-05 05:49:43 +00:00
console.error("Service Worker Registration failed: " + error);
2020-05-05 12:16:51 +00:00
});
});
}
};
registerPageServiceWorker();
2020-07-07 10:22:17 +00:00
< / script >
< script type = "text/javascript" >
const LOG_LEVELS = ["debug", "error"];
const CONFIG_LOG_LEVEL_INDEX = LOG_LEVELS.indexOf(parseConfig("__APPSMITH_CLIENT_LOG_LEVEL__"));
2020-12-02 10:42:51 +00:00
2021-07-19 10:04:15 +00:00
const INTERCOM_APP_ID = parseConfig("%REACT_APP_INTERCOM_APP_ID%") || parseConfig("__APPSMITH_INTERCOM_APP_ID__");
2021-08-30 16:41:55 +00:00
const DISABLE_INTERCOM = parseConfig("__APPSMITH_DISABLE_INTERCOM__");
2020-11-11 18:24:19 +00:00
2020-11-11 10:19:21 +00:00
// Initialize the Intercom library
2021-08-30 16:41:55 +00:00
if (INTERCOM_APP_ID.length & & !DISABLE_INTERCOM) {
2021-07-19 10:04:15 +00:00
(function () { var w = window; var ic = w.Intercom; if (typeof ic === "function") { ic('reattach_activator'); ic('update', w.intercomSettings); } else { var d = document; var i = function () { i.c(arguments); }; i.q = []; i.c = function (args) { i.q.push(args); }; w.Intercom = i; var l = function () { var s = d.createElement('script'); s.type = 'text/javascript'; s.async = true; s.src = 'https://widget.intercom.io/widget/' + INTERCOM_APP_ID; var x = d.getElementsByTagName('script')[0]; x.parentNode.insertBefore(s, x); }; if (document.readyState === 'complete') { l(); } else if (w.attachEvent) { w.attachEvent('onload', l); } else { w.addEventListener('load', l, false); } } })();
2020-11-11 10:19:21 +00:00
}
2020-07-07 10:22:17 +00:00
window.SENTRY_CONFIG = parseConfig("__APPSMITH_SENTRY_DSN__");
window.APPSMITH_FEATURE_CONFIGS = {
2020-08-13 04:46:06 +00:00
sentry: {
dsn: parseConfig("__APPSMITH_SENTRY_DSN__"),
release: parseConfig("__APPSMITH_SENTRY_RELEASE__"),
environment: parseConfig("__APPSMITH_SENTRY_ENVIRONMENT__"),
},
2020-08-27 12:54:03 +00:00
smartLook: {
id: parseConfig("__APPSMITH_SMART_LOOK_ID__"),
2020-07-07 10:22:17 +00:00
},
2020-12-09 05:52:50 +00:00
enableRapidAPI: parseConfig("__APPSMITH_MARKETPLACE_ENABLED__"),
2020-11-05 05:24:30 +00:00
segment: {
apiKey: parseConfig("__APPSMITH_SEGMENT_KEY__"),
ceKey: parseConfig("__APPSMITH_SEGMENT_CE_KEY__"),
},
2020-12-02 10:42:51 +00:00
fusioncharts: {
licenseKey: parseConfig("__APPSMITH_FUSIONCHARTS_LICENSE_KEY__")
},
2020-12-09 05:52:50 +00:00
enableMixpanel: parseConfig("__APPSMITH_SEGMENT_KEY__"),
2020-07-07 10:22:17 +00:00
algolia: {
apiId: parseConfig("__APPSMITH_ALGOLIA_API_ID__"),
apiKey: parseConfig("__APPSMITH_ALGOLIA_API_KEY__"),
indexName: parseConfig("__APPSMITH_ALGOLIA_SEARCH_INDEX_NAME__"),
},
logLevel: CONFIG_LOG_LEVEL_INDEX > -1 ? LOG_LEVELS[CONFIG_LOG_LEVEL_INDEX] : LOG_LEVELS[1],
2020-11-11 10:19:21 +00:00
cloudHosting: CLOUD_HOSTING,
2020-12-09 05:52:50 +00:00
enableTNCPP: parseConfig("__APPSMITH_TNC_PP__"),
2020-08-14 09:47:47 +00:00
appVersion: {
id: parseConfig("__APPSMITH_VERSION_ID__"),
releaseDate: parseConfig("__APPSMITH_VERSION_RELEASE_DATE__")
},
2021-07-19 10:04:15 +00:00
intercomAppID: INTERCOM_APP_ID,
2020-12-09 05:52:50 +00:00
mailEnabled: parseConfig("__APPSMITH_MAIL_ENABLED__"),
2021-06-08 05:40:11 +00:00
cloudServicesBaseUrl: parseConfig("__APPSMITH_CLOUD_SERVICES_BASE_URL__") || "https://cs.appsmith.com",
googleRecaptchaSiteKey: parseConfig("__APPSMITH_RECAPTCHA_SITE_KEY__"),
2022-10-04 09:50:45 +00:00
hideWatermark: parseConfig("__APPSMITH_HIDE_WATERMARK__"),
disableIframeWidgetSandbox: parseConfig("__APPSMITH_DISABLE_IFRAME_WIDGET_SANDBOX__"),
2023-03-15 10:03:27 +00:00
customerPortalUrl: parseConfig("__APPSMITH_CUSTOMER_PORTAL_URL__") || "https://customer.appsmith.com",
pricingUrl: parseConfig("__APPSMITH_PRICING_URL__") || "https://www.appsmith.com/pricing",
2020-07-07 10:22:17 +00:00
};
2020-01-22 12:26:25 +00:00
< / script >
2019-11-06 12:12:41 +00:00
< / body >
2020-05-05 12:16:51 +00:00
2023-05-16 09:04:48 +00:00
< / html >