chore: analytic events added for gsheet (#23171)

## Description
This PR adds:
- Analytics events for google sheet datasource.

#### PR fixes following issue(s)
Fixes #22805 
> if no issue exists, please create an issue and ask the maintainers
about this first
>
>
#### 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
- Chore (housekeeping or task changes that don't impact user perception)
>
>
>
## Testing
>
#### How Has This Been Tested?
> Please describe the tests that you ran to verify your changes. Also
list any relevant details for your test configuration.
> Delete anything that is not relevant
- [ ] Manual
- [ ] Jest
- [ ] Cypress
>
>
#### 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
- [ ] 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
- [ ] PR is being merged under a feature flag


#### QA activity:
- [ ] [Speedbreak
features](https://github.com/appsmithorg/TestSmith/wiki/Test-plan-implementation#speedbreaker-features-to-consider-for-every-change)
have been covered
- [ ] Test plan covers all impacted features and [areas of
interest](https://github.com/appsmithorg/TestSmith/wiki/Guidelines-for-test-plans/_edit#areas-of-interest)
- [ ] Test plan has been peer reviewed by project stakeholders and other
QA members
- [ ] Manually tested functionality on DP
- [ ] We had an implementation alignment call with stakeholders post QA
Round 2
- [ ] Cypress test cases have been added and approved by SDET/manual QA
- [ ] Added `Test Plan Approved` label after Cypress tests were reviewed
- [ ] Added `Test Plan Approved` label after JUnit tests were reviewed

---------

Co-authored-by: “sneha122” <“sneha@appsmith.com”>
This commit is contained in:
sneha122 2023-05-12 20:34:38 +05:30 committed by GitHub
parent 8ee9da291c
commit 885de0466b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 93 additions and 27 deletions

View File

@ -366,6 +366,7 @@ export const GSHEET_AUTHORIZATION_ERROR =
"Authorisation failed, to continue using this data source authorize now.";
export const GSHEET_FILES_NOT_SELECTED =
"Datasource does not have access to any files, please authorize google sheets to use this data source";
export const FILES_NOT_SELECTED_EVENT = () => "Files not selected";
export const LOCAL_STORAGE_QUOTA_EXCEEDED_MESSAGE = () =>
"Error saving a key in localStorage. You have exceeded the allowed storage size limit";

View File

@ -16,6 +16,7 @@ import {
getDatasourceFormButtonConfig,
getPlugin,
getPluginDocumentationLinks,
getDatasourceScopeValue,
} from "selectors/entitiesSelector";
import type { ActionDataState } from "reducers/entityReducers/actionsReducer";
import type { JSONtoFormProps } from "../DataSourceEditor/JSONtoForm";
@ -97,6 +98,7 @@ interface StateProps extends JSONtoFormProps {
gsheetToken?: string;
gsheetProjectID?: string;
documentationLink: string | undefined;
scopeValue?: string;
}
interface DatasourceFormFunctions {
discardTempDatasource: () => void;
@ -286,6 +288,7 @@ class DatasourceSaaSEditor extends JSONtoForm<Props, State> {
pageId,
plugin,
pluginPackageName,
scopeValue,
} = this.props;
const params: string = location.search;
const viewMode =
@ -426,17 +429,15 @@ class DatasourceSaaSEditor extends JSONtoForm<Props, State> {
}
showDatasourceSavedText={!isGoogleSheetPlugin}
/>
<div style={{ marginTop: "30px" }}>
{!_.isNil(formConfig) &&
!_.isNil(datasource) &&
!hideDatasourceSection ? (
<DatasourceInformation
config={formConfig[0]}
datasource={datasource}
viewMode={!!viewMode}
/>
) : undefined}
</div>
{!_.isNil(formConfig) &&
!_.isNil(datasource) &&
!hideDatasourceSection ? (
<DatasourceInformation
config={formConfig[0]}
datasource={datasource}
viewMode={!!viewMode}
/>
) : undefined}
</ViewModeWrapper>
)}
{/* Render datasource form call-to-actions */}
@ -449,6 +450,7 @@ class DatasourceSaaSEditor extends JSONtoForm<Props, State> {
getSanitizedFormData={_.memoize(this.getSanitizedData)}
isInvalid={this.validate()}
pageId={pageId}
scopeValue={scopeValue}
shouldDisplayAuthMessage={!isGoogleSheetPlugin}
shouldRender={!viewMode}
triggerSave={this.props.isDatasourceBeingSavedFromPopup}
@ -496,6 +498,13 @@ const mapStateToProps = (state: AppState, props: any) => {
merge(initialValues, datasource);
// get scopeValue to be shown in analytical events
const scopeValue = getDatasourceScopeValue(
state,
datasourceId,
DATASOURCE_SAAS_FORM,
);
const datasourceButtonConfiguration = getDatasourceFormButtonConfig(
state,
formData?.pluginId,
@ -551,6 +560,7 @@ const mapStateToProps = (state: AppState, props: any) => {
canCreateDatasourceActions,
gsheetToken,
gsheetProjectID,
scopeValue,
};
};

View File

@ -335,20 +335,21 @@ function ReconnectDatasourceModal() {
const status = queryParams.get("response_status");
const display_message = queryParams.get("display_message");
const variant = Variant.danger;
const oauthReason = status;
const isReconnectDS = true;
AnalyticsUtil.logEvent("DATASOURCE_AUTHORIZE_RESULT", {
dsName,
oauthReason,
orgId,
pluginName,
isReconnectDS,
});
if (status !== AuthorizationStatus.SUCCESS) {
const message =
status === AuthorizationStatus.APPSMITH_ERROR
? OAUTH_AUTHORIZATION_APPSMITH_ERROR
: OAUTH_AUTHORIZATION_FAILED;
Toaster.show({ text: display_message || message, variant });
const oAuthStatus = status;
AnalyticsUtil.logEvent("UPDATE_DATASOURCE", {
dsName,
oAuthStatus,
orgId,
pluginName,
});
} else if (queryDatasourceId) {
dispatch(loadFilePickerAction());
dispatch(getOAuthAccessToken(queryDatasourceId));

View File

@ -58,6 +58,7 @@ interface Props {
triggerSave?: boolean;
isFormDirty?: boolean;
datasourceDeleteTrigger: () => void;
scopeValue?: string;
}
export type DatasourceFormButtonTypes = Record<string, string[]>;
@ -121,6 +122,7 @@ function DatasourceAuth({
shouldDisplayAuthMessage = true,
triggerSave,
isFormDirty,
scopeValue,
}: Props) {
const authType =
formData && "authType" in formData
@ -181,20 +183,19 @@ function DatasourceAuth({
if (status && shouldNotify) {
const display_message = search.get("display_message");
const variant = Variant.danger;
const oauthReason = status;
AnalyticsUtil.logEvent("DATASOURCE_AUTHORIZE_RESULT", {
dsName,
oauthReason,
orgId,
pluginName,
});
if (status !== AuthorizationStatus.SUCCESS) {
const message =
status === AuthorizationStatus.APPSMITH_ERROR
? OAUTH_AUTHORIZATION_APPSMITH_ERROR
: OAUTH_AUTHORIZATION_FAILED;
Toaster.show({ text: display_message || message, variant });
const oAuthStatus = status;
AnalyticsUtil.logEvent("UPDATE_DATASOURCE", {
dsName,
oAuthStatus,
orgId,
pluginName,
});
} else {
dispatch(getOAuthAccessToken(datasourceId));
}
@ -295,6 +296,12 @@ function DatasourceAuth({
),
);
}
AnalyticsUtil.logEvent("DATASOURCE_AUTHORIZE_CLICK", {
dsName,
orgId,
pluginName,
scopeValue,
});
};
const createMode = datasourceId === TEMP_DATASOURCE_ID;

View File

@ -40,6 +40,7 @@ import {
getDatasourceActionRouteInfo,
getPlugin,
getEditorConfig,
getPluginNameFromId,
} from "selectors/entitiesSelector";
import type {
UpdateDatasourceSuccessAction,
@ -88,6 +89,7 @@ import {
DATASOURCE_DELETE,
DATASOURCE_UPDATE,
DATASOURCE_VALID,
FILES_NOT_SELECTED_EVENT,
GSHEET_AUTHORISED_FILE_IDS_KEY,
OAUTH_APPSMITH_TOKEN_NOT_FOUND,
OAUTH_AUTHORIZATION_APPSMITH_ERROR,
@ -1232,6 +1234,23 @@ function* filePickerActionCallbackSaga(
// Once files are selected in case of import, set this flag
set(datasource, "isConfigured", true);
// event in case files are not selected
if (action === FilePickerActionStatus.CANCEL) {
const oauthReason = createMessage(FILES_NOT_SELECTED_EVENT);
const dsName = datasource?.name;
const orgId = datasource?.workspaceId;
const pluginName: string = yield select(
getPluginNameFromId,
datasource?.pluginId,
);
AnalyticsUtil.logEvent("DATASOURCE_AUTHORIZE_RESULT", {
dsName,
oauthReason,
orgId,
pluginName,
});
}
// Once users selects/cancels the file selection,
// Sending sheet ids selected as part of datasource
// config properties in order to save it in database

View File

@ -41,6 +41,7 @@ import { InstallState } from "reducers/uiReducers/libraryReducer";
import recommendedLibraries from "pages/Editor/Explorer/Libraries/recommendedLibraries";
import type { TJSLibrary } from "workers/common/JSLibrary";
import { getEntityNameAndPropertyPath } from "@appsmith/workers/Evaluation/evaluationUtils";
import { getFormValues } from "redux-form";
export const getEntities = (state: AppState): AppState["entities"] =>
state.entities;
@ -1037,3 +1038,28 @@ export const getAllDatasourceTableKeys = createSelector(
return tables;
},
);
export const getDatasourceScopeValue = (
state: AppState,
datasourceId: string,
formName: string,
) => {
const formData = getFormValues(formName)(state) as Datasource;
const { plugins } = state.entities;
const { formConfigs } = plugins;
const datasource = getDatasource(state, datasourceId);
const pluginId = get(datasource, "pluginId", "");
const formConfig = formConfigs[pluginId];
if (!formConfig || (!!formConfig && formConfig.length === 0)) {
return null;
}
const configProperty = "datasourceConfiguration.authentication.scopeString";
const scopeValue = get(formData, configProperty);
const options = formConfig[0]?.children?.find(
(child: any) => child?.configProperty === configProperty,
)?.options;
const label = options?.find(
(option: any) => option.value === scopeValue,
)?.label;
return label;
};

View File

@ -299,6 +299,8 @@ export type EventName =
| "CONVERSION_FAILURE"
| "CONVERT_AUTO_TO_FIXED"
| "CONVERT_FIXED_TO_AUTO"
| "DATASOURCE_AUTHORIZE_CLICK"
| "DATASOURCE_AUTHORIZE_RESULT"
| AI_EVENTS;
export type AI_EVENTS =