Merge branch 'feature/rem-events' into 'release'
More events See merge request theappsmith/internal-tools-client!346
This commit is contained in:
commit
8c13eafde3
|
|
@ -70,7 +70,7 @@ export const updateActionSuccess = (payload: { data: RestAction }) => {
|
|||
};
|
||||
};
|
||||
|
||||
export const deleteAction = (payload: { id: string }) => {
|
||||
export const deleteAction = (payload: { id: string; name: string }) => {
|
||||
return {
|
||||
type: ReduxActionTypes.DELETE_ACTION_INIT,
|
||||
payload,
|
||||
|
|
|
|||
|
|
@ -12,3 +12,18 @@ export const setDefaultApplicationPageSuccess = (
|
|||
},
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchApplications = () => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_APPLICATION_LIST_INIT,
|
||||
};
|
||||
};
|
||||
|
||||
export const fetchApplication = (applicationId: string) => {
|
||||
return {
|
||||
type: ReduxActionTypes.FETCH_APPLICATION_INIT,
|
||||
payload: {
|
||||
applicationId,
|
||||
},
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -23,6 +23,10 @@ export interface ApplicationResponsePayload {
|
|||
pages?: ApplicationPagePayload[];
|
||||
}
|
||||
|
||||
export interface FetchApplicationResponse extends ApiResponse {
|
||||
data: ApplicationResponsePayload & { pages: ApplicationPagePayload[] };
|
||||
}
|
||||
|
||||
export interface FetchApplicationsResponse extends ApiResponse {
|
||||
data: Array<ApplicationResponsePayload & { pages: ApplicationPagePayload[] }>;
|
||||
}
|
||||
|
|
@ -62,6 +66,11 @@ class ApplicationApi extends Api {
|
|||
static fetchApplications(): AxiosPromise<FetchApplicationsResponse> {
|
||||
return Api.get(ApplicationApi.baseURL);
|
||||
}
|
||||
static fetchApplication(
|
||||
applicationId: string,
|
||||
): AxiosPromise<FetchApplicationsResponse> {
|
||||
return Api.get(ApplicationApi.baseURL + applicationId);
|
||||
}
|
||||
static createApplication(
|
||||
request: CreateApplicationRequest,
|
||||
): AxiosPromise<CreateApplicationResponse> {
|
||||
|
|
|
|||
|
|
@ -26,6 +26,8 @@ export interface CreateDatasourceConfig {
|
|||
datasourceConfiguration: {
|
||||
url: string;
|
||||
};
|
||||
//Passed for logging purposes.
|
||||
appName: string;
|
||||
}
|
||||
|
||||
class DatasourcesApi extends API {
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import _ from "lodash";
|
|||
import { parseDynamicString } from "utils/DynamicBindingUtils";
|
||||
import { DataTree } from "entities/DataTree/dataTreeFactory";
|
||||
import { Theme } from "constants/DefaultTheme";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
require("codemirror/mode/javascript/javascript");
|
||||
|
||||
const getBorderStyle = (
|
||||
|
|
@ -277,8 +278,13 @@ class DynamicAutocompleteInput extends Component<Props, State> {
|
|||
}
|
||||
};
|
||||
|
||||
handleChange = () => {
|
||||
handleChange = (instance?: any, changeObj?: any) => {
|
||||
const value = this.editor.getValue();
|
||||
if (changeObj && changeObj.origin === "complete") {
|
||||
AnalyticsUtil.logEvent("AUTO_COMPLETE_SELECT", {
|
||||
searchString: changeObj.text[0],
|
||||
});
|
||||
}
|
||||
const inputValue = this.props.input.value;
|
||||
if (this.props.input.onChange && value !== inputValue) {
|
||||
this.props.input.onChange(value);
|
||||
|
|
@ -312,6 +318,7 @@ class DynamicAutocompleteInput extends Component<Props, State> {
|
|||
});
|
||||
const shouldShow = cursorBetweenBinding && !cm.state.completionActive;
|
||||
if (shouldShow) {
|
||||
AnalyticsUtil.logEvent("AUTO_COMPELTE_SHOW", {});
|
||||
cm.showHint(cm);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import React from "react";
|
||||
import styled from "styled-components";
|
||||
import { NavLink } from "react-router-dom";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
|
||||
type MenuBarItemProps = {
|
||||
icon: Function;
|
||||
|
|
@ -62,7 +63,16 @@ class NavBarItem extends React.Component<Props> {
|
|||
const { title, icon, path, exact } = this.props;
|
||||
return (
|
||||
<ItemContainer>
|
||||
<NavLink exact={exact} to={path} className={this.props.className}>
|
||||
<NavLink
|
||||
exact={exact}
|
||||
to={path}
|
||||
className={this.props.className}
|
||||
onClick={() => {
|
||||
AnalyticsUtil.logEvent("SIDEBAR_NAVIGATION", {
|
||||
navPage: this.props.title.toUpperCase(),
|
||||
});
|
||||
}}
|
||||
>
|
||||
<React.Fragment>
|
||||
<IconContainer>{icon({ width: 24, height: 24 })}</IconContainer>
|
||||
{title}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { AppState } from "reducers";
|
|||
import { DatasourceDataState } from "reducers/entityReducers/datasourceReducer";
|
||||
import _ from "lodash";
|
||||
import { createDatasource } from "actions/datasourcesActions";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
|
||||
interface ReduxStateProps {
|
||||
datasources: DatasourceDataState;
|
||||
|
|
@ -17,6 +18,7 @@ interface ReduxActionProps {
|
|||
interface ComponentProps {
|
||||
name: string;
|
||||
pluginId: string;
|
||||
appName: string;
|
||||
}
|
||||
|
||||
const DatasourcesField = (
|
||||
|
|
@ -55,7 +57,11 @@ const mapDispatchToProps = (
|
|||
dispatch: any,
|
||||
ownProps: ComponentProps,
|
||||
): ReduxActionProps => ({
|
||||
createDatasource: (value: string) =>
|
||||
createDatasource: (value: string) => {
|
||||
AnalyticsUtil.logEvent("CREATE_DATA_SOURCE_CLICK", {
|
||||
appName: ownProps.appName,
|
||||
dataSource: value,
|
||||
});
|
||||
dispatch(
|
||||
createDatasource({
|
||||
// Datasource name should not end with /
|
||||
|
|
@ -65,8 +71,10 @@ const mapDispatchToProps = (
|
|||
url: value.endsWith("/") ? value : `${value}/`,
|
||||
},
|
||||
pluginId: ownProps.pluginId,
|
||||
appName: ownProps.appName,
|
||||
}),
|
||||
),
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(DatasourcesField);
|
||||
|
|
|
|||
|
|
@ -73,6 +73,8 @@ export const ReduxActionTypes: { [key: string]: string } = {
|
|||
INITIALIZE_PAGE_VIEWER_SUCCESS: "INITIALIZE_PAGE_VIEWER_SUCCESS",
|
||||
FETCH_APPLICATION_LIST_INIT: "FETCH_APPLICATION_LIST_INIT",
|
||||
FETCH_APPLICATION_LIST_SUCCESS: "FETCH_APPLICATION_LIST_SUCCESS",
|
||||
FETCH_APPLICATION_INIT: "FETCH_APPLICATION_INIT",
|
||||
FETCH_APPLICATION_SUCCESS: "FETCH_APFETCH_APPLICATION_SUCCESSPLICATION_INIT",
|
||||
CREATE_APPLICATION_INIT: "CREATE_APPLICATION_INIT",
|
||||
CREATE_APPLICATION_SUCCESS: "CREATE_APPLICATION_SUCCESS",
|
||||
UPDATE_WIDGET_PROPERTY_VALIDATION: "UPDATE_WIDGET_PROPERTY_VALIDATION",
|
||||
|
|
@ -180,6 +182,7 @@ export const ReduxActionErrorTypes: { [key: string]: string } = {
|
|||
CREATE_PAGE_ERROR: "CREATE_PAGE_ERROR",
|
||||
FETCH_PAGE_LIST_ERROR: "FETCH_PAGE_LIST_ERROR",
|
||||
FETCH_APPLICATION_LIST_ERROR: "FETCH_APPLICATION_LIST_ERROR",
|
||||
FETCH_APPLICATION_ERROR: "FETCH_APPLICATION_ERROR",
|
||||
CREATE_APPLICATION_ERROR: "CREATE_APPLICATION_ERROR",
|
||||
LOGIN_USER_ERROR: "LOGIN_USER_ERROR",
|
||||
CREATE_USER_ERROR: "CREATE_USER_ERROR",
|
||||
|
|
|
|||
|
|
@ -22,6 +22,7 @@ import CreateApplicationForm from "./CreateApplicationForm";
|
|||
import { CREATE_APPLICATION_FORM_NAME } from "constants/forms";
|
||||
import { DELETING_APPLICATION } from "constants/messages";
|
||||
import { AppToaster } from "components/editorComponents/ToastComponent";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
|
||||
const ApplicationCardsWrapper = styled.div`
|
||||
display: flex;
|
||||
|
|
@ -64,6 +65,9 @@ class Applications extends Component<ApplicationProps> {
|
|||
isAdding: this.props.isCreatingApplication,
|
||||
errorAdding: this.props.createApplicationError,
|
||||
formSubmitText: "Create",
|
||||
onClick: () => {
|
||||
AnalyticsUtil.logEvent("CREATE_APP_CLICK", {});
|
||||
},
|
||||
}}
|
||||
search={{
|
||||
placeholder: "Search",
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ interface APIFormProps {
|
|||
isRunning: boolean;
|
||||
isDeleting: boolean;
|
||||
paginationType: PaginationType;
|
||||
appName: string;
|
||||
}
|
||||
|
||||
type Props = APIFormProps & InjectedFormProps<RestAction, APIFormProps>;
|
||||
|
|
@ -153,7 +154,11 @@ const ApiEditorForm: React.FC<Props> = (props: Props) => {
|
|||
options={HTTP_METHOD_OPTIONS}
|
||||
/>
|
||||
<DatasourceWrapper>
|
||||
<DatasourcesField name="datasource.id" pluginId={pluginId} />
|
||||
<DatasourcesField
|
||||
name="datasource.id"
|
||||
pluginId={pluginId}
|
||||
appName={props.appName}
|
||||
/>
|
||||
</DatasourceWrapper>
|
||||
<DynamicTextField
|
||||
placeholder="v1/method"
|
||||
|
|
|
|||
|
|
@ -18,18 +18,21 @@ import styled from "styled-components";
|
|||
import { HTTP_METHODS, PLUGIN_NAME } from "constants/ApiEditorConstants";
|
||||
import _ from "lodash";
|
||||
import { getPluginIdOfName } from "selectors/entitiesSelector";
|
||||
import { getCurrentApplication } from "selectors/applicationSelectors";
|
||||
import { ApplicationPayload } from "constants/ReduxActionConstants";
|
||||
|
||||
interface ReduxStateProps {
|
||||
actions: ActionDataState;
|
||||
apiPane: ApiPaneReduxState;
|
||||
formData: RestAction;
|
||||
pluginId: string | undefined;
|
||||
currentApplication?: ApplicationPayload;
|
||||
}
|
||||
interface ReduxActionProps {
|
||||
submitForm: (name: string) => void;
|
||||
createAction: (values: RestAction) => void;
|
||||
runAction: (id: string, paginationField: PaginationField) => void;
|
||||
deleteAction: (id: string) => void;
|
||||
deleteAction: (id: string, name: string) => void;
|
||||
updateAction: (data: RestAction) => void;
|
||||
}
|
||||
|
||||
|
|
@ -55,7 +58,10 @@ class ApiEditor extends React.Component<Props> {
|
|||
this.props.submitForm(API_EDITOR_FORM_NAME);
|
||||
};
|
||||
handleDeleteClick = () => {
|
||||
this.props.deleteAction(this.props.match.params.apiId);
|
||||
this.props.deleteAction(
|
||||
this.props.match.params.apiId,
|
||||
this.props.formData.name,
|
||||
);
|
||||
};
|
||||
handleRunClick = (paginationField?: PaginationField) => {
|
||||
this.props.runAction(this.props.match.params.apiId, paginationField);
|
||||
|
|
@ -96,6 +102,11 @@ class ApiEditor extends React.Component<Props> {
|
|||
onSaveClick={this.handleSaveClick}
|
||||
onDeleteClick={this.handleDeleteClick}
|
||||
onRunClick={this.handleRunClick}
|
||||
appName={
|
||||
this.props.currentApplication
|
||||
? this.props.currentApplication.name
|
||||
: ""
|
||||
}
|
||||
/>
|
||||
) : (
|
||||
<EmptyStateContainer>
|
||||
|
|
@ -111,6 +122,7 @@ const mapStateToProps = (state: AppState): ReduxStateProps => ({
|
|||
pluginId: getPluginIdOfName(state, PLUGIN_NAME),
|
||||
actions: state.entities.actions,
|
||||
apiPane: state.ui.apiPane,
|
||||
currentApplication: getCurrentApplication(state),
|
||||
formData: getFormValues(API_EDITOR_FORM_NAME)(state) as RestAction,
|
||||
});
|
||||
|
||||
|
|
@ -119,7 +131,8 @@ const mapDispatchToProps = (dispatch: any): ReduxActionProps => ({
|
|||
createAction: (action: RestAction) => dispatch(createActionRequest(action)),
|
||||
runAction: (id: string, paginationField: PaginationField) =>
|
||||
dispatch(runApiAction(id, paginationField)),
|
||||
deleteAction: (id: string) => dispatch(deleteAction({ id })),
|
||||
deleteAction: (id: string, name: string) =>
|
||||
dispatch(deleteAction({ id, name })),
|
||||
updateAction: (data: RestAction) => dispatch(updateAction({ data })),
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@ import { getPluginIdOfName } from "selectors/entitiesSelector";
|
|||
import { DEFAULT_API_ACTION, PLUGIN_NAME } from "constants/ApiEditorConstants";
|
||||
import EditorSidebar from "pages/Editor/EditorSidebar";
|
||||
import { getNextEntityName } from "utils/AppsmithUtils";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
|
||||
const HTTPMethod = styled.span<{ method?: string }>`
|
||||
flex: 1;
|
||||
|
|
@ -69,7 +70,7 @@ interface ReduxDispatchProps {
|
|||
originalPageId: string,
|
||||
) => void;
|
||||
copyAction: (id: string, pageId: string, name: string) => void;
|
||||
deleteAction: (id: string) => void;
|
||||
deleteAction: (id: string, name: string) => void;
|
||||
}
|
||||
|
||||
type Props = ReduxStateProps &
|
||||
|
|
@ -99,6 +100,9 @@ class ApiSidebar extends React.Component<Props> {
|
|||
.map(a => a.config.name);
|
||||
const newName = getNextEntityName("Api", pageApiNames);
|
||||
this.props.createAction({ ...DEFAULT_API_ACTION, name: newName, pageId });
|
||||
AnalyticsUtil.logEvent("CREATE_API_CLICK", {
|
||||
apiName: newName,
|
||||
});
|
||||
};
|
||||
|
||||
handleApiChange = (actionId: string) => {
|
||||
|
|
@ -134,13 +138,20 @@ class ApiSidebar extends React.Component<Props> {
|
|||
this.props.copyAction(itemId, destinationPageId, name);
|
||||
};
|
||||
|
||||
handleDelete = (itemId: string) => {
|
||||
this.props.deleteAction(itemId);
|
||||
handleDelete = (itemId: string, itemName: string) => {
|
||||
this.props.deleteAction(itemId, itemName);
|
||||
};
|
||||
|
||||
renderItem = (action: RestAction) => {
|
||||
return (
|
||||
<ActionItem>
|
||||
<ActionItem
|
||||
onClick={() => {
|
||||
AnalyticsUtil.logEvent("API_SELECT", {
|
||||
apiId: action.id,
|
||||
apiName: action.name,
|
||||
});
|
||||
}}
|
||||
>
|
||||
{action.actionConfiguration ? (
|
||||
<HTTPMethod method={action.actionConfiguration.httpMethod}>
|
||||
{action.actionConfiguration.httpMethod}
|
||||
|
|
@ -203,7 +214,8 @@ const mapDispatchToProps = (dispatch: Function): ReduxDispatchProps => ({
|
|||
),
|
||||
copyAction: (id: string, destinationPageId: string, name: string) =>
|
||||
dispatch(copyActionRequest({ id, destinationPageId, name })),
|
||||
deleteAction: (id: string) => dispatch(deleteAction({ id })),
|
||||
deleteAction: (id: string, name: string) =>
|
||||
dispatch(deleteAction({ id, name })),
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ApiSidebar);
|
||||
|
|
|
|||
|
|
@ -159,7 +159,7 @@ type EditorSidebarComponentProps = {
|
|||
onItemSelected: (itemId: string) => void;
|
||||
moveItem: (itemId: string, destinationPageId: string) => void;
|
||||
copyItem: (itemId: string, destinationPageId: string) => void;
|
||||
deleteItem: (itemId: string) => void;
|
||||
deleteItem: (itemId: string, itemName: string) => void;
|
||||
};
|
||||
|
||||
type Props = ReduxStateProps &
|
||||
|
|
@ -389,6 +389,7 @@ class EditorSidebar extends React.Component<Props, State> {
|
|||
onSelect: () =>
|
||||
this.props.deleteItem(
|
||||
item.id,
|
||||
item.name,
|
||||
),
|
||||
label: "Delete",
|
||||
intent: "danger",
|
||||
|
|
|
|||
|
|
@ -27,9 +27,12 @@ import {
|
|||
import {
|
||||
ReduxActionTypes,
|
||||
PageListPayload,
|
||||
ApplicationPayload,
|
||||
} from "constants/ReduxActionConstants";
|
||||
import { Dialog, Classes, AnchorButton } from "@blueprintjs/core";
|
||||
import { initEditor } from "actions/initActions";
|
||||
import { getCurrentApplication } from "selectors/applicationSelectors";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
|
||||
type EditorProps = {
|
||||
currentPageName?: string;
|
||||
|
|
@ -49,6 +52,7 @@ type EditorProps = {
|
|||
errorPublishing: boolean;
|
||||
publishedTime?: string;
|
||||
isPageSwitching: boolean;
|
||||
currentApplication?: ApplicationPayload;
|
||||
} & RouteComponentProps<BuilderRouteParams>;
|
||||
|
||||
class Editor extends Component<EditorProps> {
|
||||
|
|
@ -80,6 +84,14 @@ class Editor extends Component<EditorProps> {
|
|||
handlePublish = () => {
|
||||
if (this.props.currentApplicationId) {
|
||||
this.props.publishApplication(this.props.currentApplicationId);
|
||||
|
||||
const appName = this.props.currentApplication
|
||||
? this.props.currentApplication.name
|
||||
: "";
|
||||
AnalyticsUtil.logEvent("PUBLISH_APP", {
|
||||
appId: this.props.currentApplicationId,
|
||||
appName: appName,
|
||||
});
|
||||
}
|
||||
};
|
||||
handleCreatePage = (pageName: string) => {
|
||||
|
|
@ -152,6 +164,7 @@ const mapStateToProps = (state: AppState) => ({
|
|||
currentPageName: state.ui.editor.currentPageName,
|
||||
isSaving: getIsPageSaving(state),
|
||||
currentApplicationId: getCurrentApplicationId(state),
|
||||
currentApplication: getCurrentApplication(state),
|
||||
currentPageId: getCurrentPageId(state),
|
||||
currentLayoutId: getCurrentLayoutId(state),
|
||||
pages: getPageList(state),
|
||||
|
|
|
|||
|
|
@ -28,6 +28,7 @@ type SubHeaderProps = {
|
|||
formSubmitIntent: string;
|
||||
errorAdding?: string;
|
||||
formSubmitText: string;
|
||||
onClick: () => void;
|
||||
};
|
||||
search?: {
|
||||
placeholder: string;
|
||||
|
|
@ -50,6 +51,7 @@ export const ApplicationsSubHeader = (props: SubHeaderProps) => {
|
|||
text={props.add.title}
|
||||
icon="plus"
|
||||
title={props.add.title}
|
||||
onClick={props.add.onClick}
|
||||
filled
|
||||
intent="primary"
|
||||
/>
|
||||
|
|
|
|||
|
|
@ -49,6 +49,17 @@ const applicationsReducer = createReducer(initialState, {
|
|||
applicationList: action.payload,
|
||||
isFetchingApplications: false,
|
||||
}),
|
||||
[ReduxActionTypes.FETCH_APPLICATION_INIT]: (
|
||||
state: ApplicationsReduxState,
|
||||
) => ({ ...state, isFetchingApplication: true }),
|
||||
[ReduxActionTypes.FETCH_APPLICATION_SUCCESS]: (
|
||||
state: ApplicationsReduxState,
|
||||
action: ReduxAction<{ applicationList: ApplicationPayload[] }>,
|
||||
) => ({
|
||||
...state,
|
||||
currentApplication: action.payload,
|
||||
isFetchingApplication: false,
|
||||
}),
|
||||
[ReduxActionTypes.CREATE_APPLICATION_INIT]: (
|
||||
state: ApplicationsReduxState,
|
||||
) => ({
|
||||
|
|
@ -93,6 +104,7 @@ export interface ApplicationsReduxState {
|
|||
creatingApplication: boolean;
|
||||
createApplicationError?: string;
|
||||
deletingApplication: boolean;
|
||||
currentApplication?: ApplicationPayload;
|
||||
}
|
||||
|
||||
export default applicationsReducer;
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@ import {
|
|||
getApplicationViewerPageURL,
|
||||
} from "constants/routes";
|
||||
import { ToastType } from "react-toastify";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
|
||||
export const getAction = (
|
||||
state: AppState,
|
||||
|
|
@ -85,6 +86,25 @@ const createActionResponse = (response: ActionApiResponse): ActionResponse => ({
|
|||
...response.clientMeta,
|
||||
});
|
||||
|
||||
function getCurrentPageNameByActionId(
|
||||
state: AppState,
|
||||
actionId: string,
|
||||
): string {
|
||||
const action = state.entities.actions.find(action => {
|
||||
return action.config.id === actionId;
|
||||
});
|
||||
const pageId = action ? action.config.pageId : "";
|
||||
return getPageNameByPageId(state, pageId);
|
||||
}
|
||||
|
||||
function getPageNameByPageId(state: AppState, pageId: string): string {
|
||||
const page = state.entities.pageList.pages.find(
|
||||
page => page.pageId === pageId,
|
||||
);
|
||||
const pageName = page ? page.pageName : "";
|
||||
return pageName;
|
||||
}
|
||||
|
||||
const createActionErrorResponse = (
|
||||
response: ActionApiResponse,
|
||||
): ActionResponse => ({
|
||||
|
|
@ -284,6 +304,17 @@ export function* createActionSaga(actionPayload: ReduxAction<RestAction>) {
|
|||
message: `${actionPayload.payload.name} Action created`,
|
||||
type: ToastType.SUCCESS,
|
||||
});
|
||||
|
||||
const pageName = yield select(
|
||||
getCurrentPageNameByActionId,
|
||||
response.data.id,
|
||||
);
|
||||
|
||||
AnalyticsUtil.logEvent("CREATE_API", {
|
||||
apiId: response.data.id,
|
||||
apiName: response.data.name,
|
||||
pageName: pageName,
|
||||
});
|
||||
yield put(createActionSuccess(response.data));
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -351,6 +382,17 @@ export function* updateActionSaga(
|
|||
message: `${actionPayload.payload.data.name} Action updated`,
|
||||
type: ToastType.SUCCESS,
|
||||
});
|
||||
|
||||
const pageName = yield select(
|
||||
getCurrentPageNameByActionId,
|
||||
response.data.id,
|
||||
);
|
||||
|
||||
AnalyticsUtil.logEvent("SAVE_API", {
|
||||
apiId: response.data.id,
|
||||
apiName: response.data.name,
|
||||
pageName: pageName,
|
||||
});
|
||||
yield put(updateActionSuccess({ data: response.data }));
|
||||
yield put(runApiAction(data.id));
|
||||
}
|
||||
|
|
@ -362,9 +404,12 @@ export function* updateActionSaga(
|
|||
}
|
||||
}
|
||||
|
||||
export function* deleteActionSaga(actionPayload: ReduxAction<{ id: string }>) {
|
||||
export function* deleteActionSaga(
|
||||
actionPayload: ReduxAction<{ id: string; name: string }>,
|
||||
) {
|
||||
try {
|
||||
const id = actionPayload.payload.id;
|
||||
const name = actionPayload.payload.name;
|
||||
const response: GenericApiResponse<RestAction> = yield ActionAPI.deleteAction(
|
||||
id,
|
||||
);
|
||||
|
|
@ -374,6 +419,12 @@ export function* deleteActionSaga(actionPayload: ReduxAction<{ id: string }>) {
|
|||
message: `${response.data.name} Action deleted`,
|
||||
type: ToastType.SUCCESS,
|
||||
});
|
||||
const pageName = yield select(getCurrentPageNameByActionId, id);
|
||||
AnalyticsUtil.logEvent("DELETE_API", {
|
||||
apiName: name,
|
||||
pageName: pageName,
|
||||
apiID: id,
|
||||
});
|
||||
yield put(deleteActionSuccess({ id }));
|
||||
}
|
||||
} catch (error) {
|
||||
|
|
@ -432,6 +483,17 @@ export function* runApiActionSaga(
|
|||
payload = createActionErrorResponse(response);
|
||||
}
|
||||
const id = values.id || "DRY_RUN";
|
||||
|
||||
const pageName = yield select(getCurrentPageNameByActionId, values.id);
|
||||
|
||||
AnalyticsUtil.logEvent("RUN_API", {
|
||||
apiId: values.id,
|
||||
apiName: values.name,
|
||||
pageName: pageName,
|
||||
responseTime: response.clientMeta.duration,
|
||||
apiType: "INTERNAL",
|
||||
});
|
||||
|
||||
yield put({
|
||||
type: ReduxActionTypes.RUN_API_SUCCESS,
|
||||
payload: { [id]: payload },
|
||||
|
|
@ -496,6 +558,12 @@ function* moveActionSaga(
|
|||
type: ToastType.SUCCESS,
|
||||
});
|
||||
}
|
||||
const pageName = yield select(getPageNameByPageId, response.data.pageId);
|
||||
AnalyticsUtil.logEvent("MOVE_API", {
|
||||
apiName: response.data.name,
|
||||
pageName: pageName,
|
||||
apiID: response.data.id,
|
||||
});
|
||||
yield put(moveActionSuccess(response.data));
|
||||
} catch (e) {
|
||||
AppToaster.show({
|
||||
|
|
@ -537,6 +605,13 @@ function* copyActionSaga(
|
|||
type: ToastType.SUCCESS,
|
||||
});
|
||||
}
|
||||
|
||||
const pageName = yield select(getPageNameByPageId, response.data.pageId);
|
||||
AnalyticsUtil.logEvent("DUPLICATE_API", {
|
||||
apiName: response.data.name,
|
||||
pageName: pageName,
|
||||
apiID: response.data.id,
|
||||
});
|
||||
yield put(copyActionSuccess(response.data));
|
||||
} catch (e) {
|
||||
AppToaster.show({
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ import history from "utils/history";
|
|||
import { BUILDER_PAGE_URL } from "constants/routes";
|
||||
import { AppState } from "reducers";
|
||||
import { setDefaultApplicationPageSuccess } from "actions/applicationActions";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
export function* publishApplicationSaga(
|
||||
requestAction: ReduxAction<PublishApplicationRequest>,
|
||||
) {
|
||||
|
|
@ -85,6 +86,32 @@ export function* fetchApplicationListSaga() {
|
|||
}
|
||||
}
|
||||
|
||||
export function* fetchApplicationSaga(
|
||||
action: ReduxAction<{
|
||||
applicationId: string;
|
||||
}>,
|
||||
) {
|
||||
try {
|
||||
const applicationId: string = action.payload.applicationId;
|
||||
const response: FetchApplicationsResponse = yield call(
|
||||
ApplicationApi.fetchApplication,
|
||||
applicationId,
|
||||
);
|
||||
|
||||
yield put({
|
||||
type: ReduxActionTypes.FETCH_APPLICATION_SUCCESS,
|
||||
payload: response.data,
|
||||
});
|
||||
} catch (error) {
|
||||
yield put({
|
||||
type: ReduxActionErrorTypes.FETCH_APPLICATION_ERROR,
|
||||
payload: {
|
||||
error,
|
||||
},
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function* setDefaultApplicationPageSaga(
|
||||
action: ReduxAction<SetDefaultPageRequest>,
|
||||
) {
|
||||
|
|
@ -188,6 +215,9 @@ export function* createApplicationSaga(
|
|||
pageCount: response.data.pages ? response.data.pages.length : 0,
|
||||
defaultPageId: getDefaultPageId(response.data.pages),
|
||||
};
|
||||
AnalyticsUtil.logEvent("CREATE_APP", {
|
||||
appName: application.name,
|
||||
});
|
||||
yield put({
|
||||
type: ReduxActionTypes.CREATE_APPLICATION_SUCCESS,
|
||||
payload: application,
|
||||
|
|
@ -224,6 +254,7 @@ export default function* applicationSagas() {
|
|||
ReduxActionTypes.FETCH_APPLICATION_LIST_INIT,
|
||||
fetchApplicationListSaga,
|
||||
),
|
||||
takeLatest(ReduxActionTypes.FETCH_APPLICATION_INIT, fetchApplicationSaga),
|
||||
takeLatest(ReduxActionTypes.CREATE_APPLICATION_INIT, createApplicationSaga),
|
||||
takeLatest(
|
||||
ReduxActionTypes.SET_DEFAULT_APPLICATION_PAGE_INIT,
|
||||
|
|
|
|||
|
|
@ -12,6 +12,7 @@ import DatasourcesApi, {
|
|||
} from "api/DatasourcesApi";
|
||||
import { API_EDITOR_FORM_NAME } from "constants/forms";
|
||||
import { validateResponse } from "./ErrorSagas";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
|
||||
function* fetchDatasourcesSaga() {
|
||||
try {
|
||||
|
|
@ -40,6 +41,10 @@ function* createDatasourceSaga(
|
|||
);
|
||||
const isValidResponse = yield validateResponse(response);
|
||||
if (isValidResponse) {
|
||||
AnalyticsUtil.logEvent("SAVE_DATA_SOURCE", {
|
||||
dataSourceName: actionPayload.payload.name,
|
||||
appName: actionPayload.payload.appName,
|
||||
});
|
||||
yield put({
|
||||
type: ReduxActionTypes.CREATE_DATASOURCE_SUCCESS,
|
||||
payload: response.data,
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { all, put, takeLatest, take } from "redux-saga/effects";
|
||||
import { all, put, takeLatest, take, select } from "redux-saga/effects";
|
||||
import {
|
||||
ReduxAction,
|
||||
ReduxActionTypes,
|
||||
|
|
@ -10,6 +10,9 @@ import { fetchPageList } from "actions/pageActions";
|
|||
import { fetchDatasources } from "actions/datasourcesActions";
|
||||
import { fetchPlugins } from "actions/pluginActions";
|
||||
import { fetchActions } from "actions/actionActions";
|
||||
import { fetchApplication } from "actions/applicationActions";
|
||||
import { AppState } from "reducers";
|
||||
import AnalyticsUtil from "utils/AnalyticsUtil";
|
||||
|
||||
function* initializeEditorSaga(
|
||||
initializeEditorAction: ReduxAction<InitializeEditorPayload>,
|
||||
|
|
@ -18,6 +21,7 @@ function* initializeEditorSaga(
|
|||
// Step 1: Start getting all the data needed by the
|
||||
yield all([
|
||||
put(fetchPlugins()),
|
||||
put(fetchApplication(applicationId)),
|
||||
put(fetchPageList(applicationId)),
|
||||
put(fetchEditorConfigs()),
|
||||
put(fetchActions(applicationId)),
|
||||
|
|
@ -26,11 +30,25 @@ function* initializeEditorSaga(
|
|||
// Step 2: Wait for all data to be in the state
|
||||
yield all([
|
||||
take(ReduxActionTypes.FETCH_PLUGINS_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_APPLICATION_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_PAGE_LIST_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_ACTIONS_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_DATASOURCES_SUCCESS),
|
||||
]);
|
||||
|
||||
const currentApplication = yield select(
|
||||
(state: AppState) => state.ui.applications.currentApplication,
|
||||
);
|
||||
|
||||
const appName = currentApplication ? currentApplication.name : "";
|
||||
const appId = currentApplication ? currentApplication.id : "";
|
||||
|
||||
AnalyticsUtil.setAppData(appId, appName);
|
||||
AnalyticsUtil.logEvent("EDITOR_OPEN", {
|
||||
appId: appId,
|
||||
appName: appName,
|
||||
});
|
||||
|
||||
// Step 6: Notify UI that the editor is ready to go
|
||||
yield put({
|
||||
type: ReduxActionTypes.INITIALIZE_EDITOR_SUCCESS,
|
||||
|
|
@ -44,13 +62,27 @@ export function* initializeAppViewerSaga(
|
|||
yield all([
|
||||
put(fetchActions(applicationId)),
|
||||
put(fetchPageList(applicationId)),
|
||||
put(fetchApplication(applicationId)),
|
||||
]);
|
||||
|
||||
yield all([
|
||||
take(ReduxActionTypes.FETCH_ACTIONS_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_PAGE_LIST_SUCCESS),
|
||||
take(ReduxActionTypes.FETCH_APPLICATION_SUCCESS),
|
||||
]);
|
||||
|
||||
const currentApplication = yield select(
|
||||
(state: AppState) => state.ui.applications.currentApplication,
|
||||
);
|
||||
|
||||
const appName = currentApplication ? currentApplication.name : "";
|
||||
const appId = currentApplication ? currentApplication.id : "";
|
||||
AnalyticsUtil.setAppData(appId, appName);
|
||||
AnalyticsUtil.logEvent("PREVIEW_APP", {
|
||||
appId: appId,
|
||||
appName: appName,
|
||||
});
|
||||
|
||||
yield put({
|
||||
type: ReduxActionTypes.INITIALIZE_PAGE_VIEWER_SUCCESS,
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,6 +15,8 @@ const fuzzySearchOptions = {
|
|||
const getApplicationsState = (state: AppState) => state.ui.applications;
|
||||
const getApplications = (state: AppState) =>
|
||||
state.ui.applications.applicationList;
|
||||
export const getCurrentApplication = (state: AppState) =>
|
||||
state.ui.applications.currentApplication;
|
||||
const getApplicationSearchKeyword = (state: AppState) =>
|
||||
state.ui.applications.searchKeyword;
|
||||
export const getIsDeletingApplication = (state: AppState) =>
|
||||
|
|
|
|||
|
|
@ -16,7 +16,25 @@ export type EventName =
|
|||
| "CREATE_PAGE"
|
||||
| "PAGE_RENAME"
|
||||
| "PAGE_SWITCH"
|
||||
| "DELETE_PAGE";
|
||||
| "DELETE_PAGE"
|
||||
| "SIDEBAR_NAVIGATION"
|
||||
| "PUBLISH_APP"
|
||||
| "PREVIEW_APP"
|
||||
| "EDITOR_OPEN"
|
||||
| "CREATE_API"
|
||||
| "SAVE_API"
|
||||
| "RUN_API"
|
||||
| "DELETE_API"
|
||||
| "DUPLICATE_API"
|
||||
| "MOVE_API"
|
||||
| "API_SELECT"
|
||||
| "CREATE_API_CLICK"
|
||||
| "AUTO_COMPELTE_SHOW"
|
||||
| "AUTO_COMPLETE_SELECT"
|
||||
| "CREATE_APP_CLICK"
|
||||
| "CREATE_APP"
|
||||
| "CREATE_DATA_SOURCE_CLICK"
|
||||
| "SAVE_DATA_SOURCE";
|
||||
|
||||
export type Gender = "MALE" | "FEMALE";
|
||||
export interface User {
|
||||
|
|
@ -27,6 +45,14 @@ export interface User {
|
|||
}
|
||||
|
||||
class AnalyticsUtil {
|
||||
static user: any = {};
|
||||
static appData: {
|
||||
appId: string;
|
||||
appName: string;
|
||||
} = {
|
||||
appId: "",
|
||||
appName: "",
|
||||
};
|
||||
static initializeHotjar(id: string, sv: string) {
|
||||
(function init(h: any, o: any, t: any, j: any, a?: any, r?: any) {
|
||||
h.hj =
|
||||
|
|
@ -105,19 +131,40 @@ class AnalyticsUtil {
|
|||
|
||||
static logEvent(eventName: EventName, eventData: any) {
|
||||
const windowDoc: any = window;
|
||||
let finalEventData = eventData;
|
||||
const userData = AnalyticsUtil.user;
|
||||
const appData = AnalyticsUtil.appData;
|
||||
|
||||
if (userData) {
|
||||
finalEventData = {
|
||||
...finalEventData,
|
||||
userData: {
|
||||
email: userData.email,
|
||||
currentOrgId: userData.currentOrganizationId,
|
||||
...appData,
|
||||
},
|
||||
};
|
||||
}
|
||||
if (windowDoc.analytics) {
|
||||
windowDoc.analytics.track(eventName, eventData);
|
||||
windowDoc.analytics.track(eventName, finalEventData);
|
||||
} else {
|
||||
console.log("Event fired", eventName, eventData);
|
||||
console.log("Event fired", eventName, finalEventData);
|
||||
}
|
||||
}
|
||||
|
||||
static identifyUser(userId: string, userData: User) {
|
||||
const windowDoc: any = window;
|
||||
AnalyticsUtil.user = userData;
|
||||
if (windowDoc.analytics) {
|
||||
windowDoc.analytics.identify(userId, userData);
|
||||
}
|
||||
}
|
||||
static setAppData(appId: string, appName: string) {
|
||||
AnalyticsUtil.appData = {
|
||||
appId: appId,
|
||||
appName: appName,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export default AnalyticsUtil;
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user