Merge branch 'feature/datasourcesDraft' into 'release'
Feature/datasources draft Add drafts for the datasource pane. See merge request theappsmith/internal-tools-client!600
This commit is contained in:
commit
7e173fc2a7
|
|
@ -22,6 +22,13 @@ export const updateDatasource = (payload: Datasource) => {
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const changeDatasource = (payload: Datasource) => {
|
||||||
|
return {
|
||||||
|
type: ReduxActionTypes.CHANGE_DATASOURCE,
|
||||||
|
payload,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
export const testDatasource = (payload: Partial<Datasource>) => {
|
export const testDatasource = (payload: Partial<Datasource>) => {
|
||||||
return {
|
return {
|
||||||
type: ReduxActionTypes.TEST_DATASOURCE_INIT,
|
type: ReduxActionTypes.TEST_DATASOURCE_INIT,
|
||||||
|
|
|
||||||
|
|
@ -26,16 +26,6 @@ const KeyValueRow = (props: Props & WrappedFieldArrayProps) => {
|
||||||
}
|
}
|
||||||
}, [props.fields]);
|
}, [props.fields]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (typeof props.fields.getAll() === "string") {
|
|
||||||
const fieldsValue: [] = JSON.parse(`${props.fields.getAll()}`);
|
|
||||||
props.fields.removeAll();
|
|
||||||
fieldsValue.forEach((value, index) => {
|
|
||||||
props.fields.insert(index, value);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}, [props.fields]);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
{typeof props.fields.getAll() === "object" && (
|
{typeof props.fields.getAll() === "object" && (
|
||||||
|
|
|
||||||
|
|
@ -67,9 +67,12 @@ export const ReduxActionTypes: { [key: string]: string } = {
|
||||||
CREATE_DATASOURCE_FROM_FORM_INIT: "CREATE_DATASOURCE_FROM_FORM_INIT",
|
CREATE_DATASOURCE_FROM_FORM_INIT: "CREATE_DATASOURCE_FROM_FORM_INIT",
|
||||||
UPDATE_DATASOURCE_INIT: "UPDATE_DATASOURCE_INIT",
|
UPDATE_DATASOURCE_INIT: "UPDATE_DATASOURCE_INIT",
|
||||||
UPDATE_DATASOURCE_SUCCESS: "UPDATE_DATASOURCE_SUCCESS",
|
UPDATE_DATASOURCE_SUCCESS: "UPDATE_DATASOURCE_SUCCESS",
|
||||||
|
CHANGE_DATASOURCE: "CHANGE_DATASOURCE",
|
||||||
SELECT_PLUGIN: "SELECT_PLUGIN",
|
SELECT_PLUGIN: "SELECT_PLUGIN",
|
||||||
TEST_DATASOURCE_INIT: "TEST_DATASOURCE_INIT",
|
TEST_DATASOURCE_INIT: "TEST_DATASOURCE_INIT",
|
||||||
TEST_DATASOURCE_SUCCESS: "TEST_DATASOURCE_SUCCESS",
|
TEST_DATASOURCE_SUCCESS: "TEST_DATASOURCE_SUCCESS",
|
||||||
|
DELETE_DATASOURCE_DRAFT: "DELETE_DATASOURCE_DRAFT",
|
||||||
|
UPDATE_DATASOURCE_DRAFT: "UPDATE_DATASOURCE_DRAFT",
|
||||||
FETCH_PUBLISHED_PAGE_INIT: "FETCH_PUBLISHED_PAGE_INIT",
|
FETCH_PUBLISHED_PAGE_INIT: "FETCH_PUBLISHED_PAGE_INIT",
|
||||||
FETCH_PUBLISHED_PAGE_SUCCESS: "FETCH_PUBLISHED_PAGE_SUCCESS",
|
FETCH_PUBLISHED_PAGE_SUCCESS: "FETCH_PUBLISHED_PAGE_SUCCESS",
|
||||||
DELETE_DATASOURCE_INIT: "DELETE_DATASOURCE_INIT",
|
DELETE_DATASOURCE_INIT: "DELETE_DATASOURCE_INIT",
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,7 @@ import {
|
||||||
initDatasourcePane,
|
initDatasourcePane,
|
||||||
storeDatastoreRefs,
|
storeDatastoreRefs,
|
||||||
deleteDatasource,
|
deleteDatasource,
|
||||||
|
changeDatasource,
|
||||||
} from "actions/datasourceActions";
|
} from "actions/datasourceActions";
|
||||||
import { ControlIcons } from "icons/ControlIcons";
|
import { ControlIcons } from "icons/ControlIcons";
|
||||||
import { theme } from "constants/DefaultTheme";
|
import { theme } from "constants/DefaultTheme";
|
||||||
|
|
@ -25,10 +26,7 @@ import ImageAlt from "assets/images/placeholder-image.svg";
|
||||||
import Postgres from "assets/images/Postgress.png";
|
import Postgres from "assets/images/Postgress.png";
|
||||||
import MongoDB from "assets/images/MongoDB.png";
|
import MongoDB from "assets/images/MongoDB.png";
|
||||||
import RestTemplateImage from "assets/images/RestAPI.png";
|
import RestTemplateImage from "assets/images/RestAPI.png";
|
||||||
import {
|
import { DATA_SOURCES_EDITOR_URL } from "constants/routes";
|
||||||
DATA_SOURCES_EDITOR_ID_URL,
|
|
||||||
DATA_SOURCES_EDITOR_URL,
|
|
||||||
} from "constants/routes";
|
|
||||||
import { REST_PLUGIN_PACKAGE_NAME } from "constants/ApiEditorConstants";
|
import { REST_PLUGIN_PACKAGE_NAME } from "constants/ApiEditorConstants";
|
||||||
import {
|
import {
|
||||||
PLUGIN_PACKAGE_POSTGRES,
|
PLUGIN_PACKAGE_POSTGRES,
|
||||||
|
|
@ -44,6 +42,7 @@ interface ReduxDispatchProps {
|
||||||
storeDatastoreRefs: (refsList: []) => void;
|
storeDatastoreRefs: (refsList: []) => void;
|
||||||
fetchFormConfig: (id: string) => void;
|
fetchFormConfig: (id: string) => void;
|
||||||
deleteDatasource: (id: string) => void;
|
deleteDatasource: (id: string) => void;
|
||||||
|
onDatasourceChange: (datasource: Datasource) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ReduxStateProps {
|
interface ReduxStateProps {
|
||||||
|
|
@ -51,6 +50,7 @@ interface ReduxStateProps {
|
||||||
plugins: Plugin[];
|
plugins: Plugin[];
|
||||||
datastoreRefs: Record<string, any>;
|
datastoreRefs: Record<string, any>;
|
||||||
formConfigs: Record<string, []>;
|
formConfigs: Record<string, []>;
|
||||||
|
drafts: Record<string, Datasource>;
|
||||||
}
|
}
|
||||||
|
|
||||||
type DataSourceSidebarProps = {};
|
type DataSourceSidebarProps = {};
|
||||||
|
|
@ -172,6 +172,15 @@ const Container = styled.div`
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const DraftIconIndicator = styled.span<{ isHidden: boolean }>`
|
||||||
|
width: 8px;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: 8px;
|
||||||
|
background-color: #f2994a;
|
||||||
|
margin: 0 5px;
|
||||||
|
opacity: ${({ isHidden }) => (isHidden ? 0 : 1)};
|
||||||
|
`;
|
||||||
|
|
||||||
type Props = DataSourceSidebarProps &
|
type Props = DataSourceSidebarProps &
|
||||||
RouteComponentProps<{
|
RouteComponentProps<{
|
||||||
pageId: string;
|
pageId: string;
|
||||||
|
|
@ -202,6 +211,13 @@ class DataSourceSidebar extends React.Component<Props, State> {
|
||||||
storeDatastoreRefs(this.refsCollection);
|
storeDatastoreRefs(this.refsCollection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
shouldComponentUpdate(nextProps: Readonly<Props>): boolean {
|
||||||
|
if (Object.keys(nextProps.drafts) !== Object.keys(this.props.drafts)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return nextProps.dataSources !== this.props.dataSources;
|
||||||
|
}
|
||||||
|
|
||||||
handleCreateNewDatasource = () => {
|
handleCreateNewDatasource = () => {
|
||||||
const { history } = this.props;
|
const { history } = this.props;
|
||||||
const { pageId, applicationId } = this.props.match.params;
|
const { pageId, applicationId } = this.props.match.params;
|
||||||
|
|
@ -210,17 +226,7 @@ class DataSourceSidebar extends React.Component<Props, State> {
|
||||||
};
|
};
|
||||||
|
|
||||||
handleItemSelected = (datasource: Datasource) => {
|
handleItemSelected = (datasource: Datasource) => {
|
||||||
const { history, formConfigs } = this.props;
|
this.props.onDatasourceChange(datasource);
|
||||||
const { pageId, applicationId } = this.props.match.params;
|
|
||||||
|
|
||||||
this.props.initializeForm(datasource);
|
|
||||||
this.props.selectPlugin(datasource.pluginId);
|
|
||||||
if (!formConfigs[datasource.pluginId]) {
|
|
||||||
this.props.fetchFormConfig(datasource.pluginId);
|
|
||||||
}
|
|
||||||
history.push(
|
|
||||||
DATA_SOURCES_EDITOR_ID_URL(applicationId, pageId, datasource.id),
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
handleSearchChange = (e: React.ChangeEvent<{ value: string }>) => {
|
handleSearchChange = (e: React.ChangeEvent<{ value: string }>) => {
|
||||||
|
|
@ -253,6 +259,7 @@ class DataSourceSidebar extends React.Component<Props, State> {
|
||||||
},
|
},
|
||||||
datastoreRefs,
|
datastoreRefs,
|
||||||
deleteDatasource,
|
deleteDatasource,
|
||||||
|
drafts,
|
||||||
} = this.props;
|
} = this.props;
|
||||||
|
|
||||||
return datasources.map(datasource => {
|
return datasources.map(datasource => {
|
||||||
|
|
@ -272,6 +279,7 @@ class DataSourceSidebar extends React.Component<Props, State> {
|
||||||
/>
|
/>
|
||||||
<ActionName>{datasource.name}</ActionName>
|
<ActionName>{datasource.name}</ActionName>
|
||||||
</ActionItem>
|
</ActionItem>
|
||||||
|
<DraftIconIndicator isHidden={!(datasource.id in drafts)} />
|
||||||
<TreeDropdown
|
<TreeDropdown
|
||||||
defaultText=""
|
defaultText=""
|
||||||
onSelect={() => {
|
onSelect={() => {
|
||||||
|
|
@ -335,17 +343,21 @@ class DataSourceSidebar extends React.Component<Props, State> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = (state: AppState): ReduxStateProps => {
|
const mapStateToProps = (state: AppState): ReduxStateProps => {
|
||||||
|
const { drafts } = state.ui.datasourcePane;
|
||||||
return {
|
return {
|
||||||
formConfigs: state.entities.plugins.formConfigs,
|
formConfigs: state.entities.plugins.formConfigs,
|
||||||
dataSources: getDataSources(state),
|
dataSources: getDataSources(state),
|
||||||
plugins: getPlugins(state),
|
plugins: getPlugins(state),
|
||||||
datastoreRefs: state.ui.datasourcePane.datasourceRefs,
|
datastoreRefs: state.ui.datasourcePane.datasourceRefs,
|
||||||
|
drafts,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = (dispatch: Function): ReduxDispatchProps => ({
|
const mapDispatchToProps = (dispatch: Function): ReduxDispatchProps => ({
|
||||||
initDatasourcePane: (pluginType: string, urlId?: string) =>
|
initDatasourcePane: (pluginType: string, urlId?: string) =>
|
||||||
dispatch(initDatasourcePane(pluginType, urlId)),
|
dispatch(initDatasourcePane(pluginType, urlId)),
|
||||||
|
onDatasourceChange: (datasource: Datasource) =>
|
||||||
|
dispatch(changeDatasource(datasource)),
|
||||||
fetchFormConfig: (id: string) => dispatch(fetchPluginForm({ id })),
|
fetchFormConfig: (id: string) => dispatch(fetchPluginForm({ id })),
|
||||||
selectPlugin: (pluginId: string) => dispatch(selectPlugin(pluginId)),
|
selectPlugin: (pluginId: string) => dispatch(selectPlugin(pluginId)),
|
||||||
initializeForm: (data: Record<string, any>) =>
|
initializeForm: (data: Record<string, any>) =>
|
||||||
|
|
|
||||||
|
|
@ -2,15 +2,18 @@ import React from "react";
|
||||||
import { createReducer } from "utils/AppsmithUtils";
|
import { createReducer } from "utils/AppsmithUtils";
|
||||||
import { ReduxActionTypes, ReduxAction } from "constants/ReduxActionConstants";
|
import { ReduxActionTypes, ReduxAction } from "constants/ReduxActionConstants";
|
||||||
import { Datasource } from "api/DatasourcesApi";
|
import { Datasource } from "api/DatasourcesApi";
|
||||||
|
import _ from "lodash";
|
||||||
|
|
||||||
const initialState: DatasourcePaneReduxState = {
|
const initialState: DatasourcePaneReduxState = {
|
||||||
selectedPlugin: "",
|
selectedPlugin: "",
|
||||||
datasourceRefs: {},
|
datasourceRefs: {},
|
||||||
|
drafts: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface DatasourcePaneReduxState {
|
export interface DatasourcePaneReduxState {
|
||||||
selectedPlugin: string;
|
selectedPlugin: string;
|
||||||
datasourceRefs: {};
|
datasourceRefs: {};
|
||||||
|
drafts: Record<string, Datasource>;
|
||||||
}
|
}
|
||||||
|
|
||||||
const datasourcePaneReducer = createReducer(initialState, {
|
const datasourcePaneReducer = createReducer(initialState, {
|
||||||
|
|
@ -42,6 +45,25 @@ const datasourcePaneReducer = createReducer(initialState, {
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
[ReduxActionTypes.UPDATE_DATASOURCE_DRAFT]: (
|
||||||
|
state: DatasourcePaneReduxState,
|
||||||
|
action: ReduxAction<{ id: string; draft: Partial<Datasource> }>,
|
||||||
|
) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
drafts: {
|
||||||
|
...state.drafts,
|
||||||
|
[action.payload.id]: action.payload.draft,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[ReduxActionTypes.DELETE_DATASOURCE_DRAFT]: (
|
||||||
|
state: DatasourcePaneReduxState,
|
||||||
|
action: ReduxAction<{ id: string }>,
|
||||||
|
) => ({
|
||||||
|
...state,
|
||||||
|
drafts: _.omit(state.drafts, action.payload.id),
|
||||||
|
}),
|
||||||
});
|
});
|
||||||
|
|
||||||
export default datasourcePaneReducer;
|
export default datasourcePaneReducer;
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,25 @@
|
||||||
import { all, put, takeEvery, select } from "redux-saga/effects";
|
import { all, put, takeEvery, select, call } from "redux-saga/effects";
|
||||||
import { change, initialize } from "redux-form";
|
import { change, initialize, getFormValues } from "redux-form";
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import {
|
import {
|
||||||
ReduxAction,
|
ReduxAction,
|
||||||
ReduxActionErrorTypes,
|
ReduxActionErrorTypes,
|
||||||
ReduxActionTypes,
|
ReduxActionTypes,
|
||||||
|
ReduxFormActionTypes,
|
||||||
|
ReduxActionWithMeta,
|
||||||
} from "constants/ReduxActionConstants";
|
} from "constants/ReduxActionConstants";
|
||||||
import {
|
import {
|
||||||
getCurrentApplicationId,
|
getCurrentApplicationId,
|
||||||
getCurrentPageId,
|
getCurrentPageId,
|
||||||
} from "selectors/editorSelectors";
|
} from "selectors/editorSelectors";
|
||||||
import { getDatasourceRefs, getPluginForm } from "selectors/entitiesSelector";
|
import {
|
||||||
|
getDatasourceRefs,
|
||||||
|
getPluginForm,
|
||||||
|
getDatasource,
|
||||||
|
getDatasourceDraft,
|
||||||
|
} from "selectors/entitiesSelector";
|
||||||
|
import { selectPlugin } from "actions/datasourceActions";
|
||||||
|
import { fetchPluginForm } from "actions/pluginActions";
|
||||||
import { GenericApiResponse } from "api/ApiResponses";
|
import { GenericApiResponse } from "api/ApiResponses";
|
||||||
import DatasourcesApi, {
|
import DatasourcesApi, {
|
||||||
CreateDatasourceConfig,
|
CreateDatasourceConfig,
|
||||||
|
|
@ -99,6 +108,12 @@ export function* deleteDatasourceSaga(
|
||||||
type: ReduxActionTypes.DELETE_DATASOURCE_SUCCESS,
|
type: ReduxActionTypes.DELETE_DATASOURCE_SUCCESS,
|
||||||
payload: response.data,
|
payload: response.data,
|
||||||
});
|
});
|
||||||
|
yield put({
|
||||||
|
type: ReduxActionTypes.DELETE_DATASOURCE_DRAFT,
|
||||||
|
payload: {
|
||||||
|
id: response.data.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
history.push(DATA_SOURCES_EDITOR_URL(applicationId, pageId));
|
history.push(DATA_SOURCES_EDITOR_URL(applicationId, pageId));
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
|
|
@ -125,6 +140,12 @@ function* updateDatasourceSaga(actionPayload: ReduxAction<Datasource>) {
|
||||||
type: ReduxActionTypes.UPDATE_DATASOURCE_SUCCESS,
|
type: ReduxActionTypes.UPDATE_DATASOURCE_SUCCESS,
|
||||||
payload: response.data,
|
payload: response.data,
|
||||||
});
|
});
|
||||||
|
yield put({
|
||||||
|
type: ReduxActionTypes.DELETE_DATASOURCE_DRAFT,
|
||||||
|
payload: {
|
||||||
|
id: response.data.id,
|
||||||
|
},
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
yield put({
|
yield put({
|
||||||
|
|
@ -269,6 +290,60 @@ function* createDatasourceFromFormSaga(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function* updateDraftsSaga() {
|
||||||
|
const values = yield select(getFormValues(DATASOURCE_DB_FORM));
|
||||||
|
|
||||||
|
if (!values.id) return;
|
||||||
|
const datasource = yield select(getDatasource, values.id);
|
||||||
|
|
||||||
|
if (_.isEqual(values, datasource)) {
|
||||||
|
yield put({
|
||||||
|
type: ReduxActionTypes.DELETE_DATASOURCE_DRAFT,
|
||||||
|
payload: { id: values.id },
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
yield put({
|
||||||
|
type: ReduxActionTypes.UPDATE_DATASOURCE_DRAFT,
|
||||||
|
payload: { id: values.id, draft: values },
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function* changeDatasourceSaga(actionPayload: ReduxAction<Datasource>) {
|
||||||
|
const { id, pluginId } = actionPayload.payload;
|
||||||
|
const datasource = actionPayload.payload;
|
||||||
|
const state = yield select();
|
||||||
|
const draft = yield select(getDatasourceDraft, id);
|
||||||
|
const formConfigs = state.entities.plugins.formConfigs;
|
||||||
|
const applicationId = yield select(getCurrentApplicationId);
|
||||||
|
const pageId = yield select(getCurrentPageId);
|
||||||
|
let data;
|
||||||
|
|
||||||
|
if (_.isEmpty(draft)) {
|
||||||
|
data = actionPayload.payload;
|
||||||
|
} else {
|
||||||
|
data = draft;
|
||||||
|
}
|
||||||
|
|
||||||
|
yield put(initialize(DATASOURCE_DB_FORM, data));
|
||||||
|
yield put(selectPlugin(pluginId));
|
||||||
|
|
||||||
|
if (!formConfigs[pluginId]) {
|
||||||
|
yield put(fetchPluginForm({ id: pluginId }));
|
||||||
|
}
|
||||||
|
history.push(
|
||||||
|
DATA_SOURCES_EDITOR_ID_URL(applicationId, pageId, datasource.id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function* formValueChangeSaga(
|
||||||
|
actionPayload: ReduxActionWithMeta<string, { field: string; form: string }>,
|
||||||
|
) {
|
||||||
|
const { form } = actionPayload.meta;
|
||||||
|
if (form !== DATASOURCE_DB_FORM) return;
|
||||||
|
yield all([call(updateDraftsSaga)]);
|
||||||
|
}
|
||||||
|
|
||||||
export function* watchDatasourcesSagas() {
|
export function* watchDatasourcesSagas() {
|
||||||
yield all([
|
yield all([
|
||||||
takeEvery(ReduxActionTypes.FETCH_DATASOURCES_INIT, fetchDatasourcesSaga),
|
takeEvery(ReduxActionTypes.FETCH_DATASOURCES_INIT, fetchDatasourcesSaga),
|
||||||
|
|
@ -280,5 +355,8 @@ export function* watchDatasourcesSagas() {
|
||||||
takeEvery(ReduxActionTypes.UPDATE_DATASOURCE_INIT, updateDatasourceSaga),
|
takeEvery(ReduxActionTypes.UPDATE_DATASOURCE_INIT, updateDatasourceSaga),
|
||||||
takeEvery(ReduxActionTypes.TEST_DATASOURCE_INIT, testDatasourceSaga),
|
takeEvery(ReduxActionTypes.TEST_DATASOURCE_INIT, testDatasourceSaga),
|
||||||
takeEvery(ReduxActionTypes.DELETE_DATASOURCE_INIT, deleteDatasourceSaga),
|
takeEvery(ReduxActionTypes.DELETE_DATASOURCE_INIT, deleteDatasourceSaga),
|
||||||
|
takeEvery(ReduxActionTypes.CHANGE_DATASOURCE, changeDatasourceSaga),
|
||||||
|
// Intercepting the redux-form change actionType
|
||||||
|
takeEvery(ReduxFormActionTypes.VALUE_CHANGE, formValueChangeSaga),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import { QUERY_CONSTANT } from "constants/QueryEditorConstants";
|
||||||
import { API_CONSTANT } from "constants/ApiEditorConstants";
|
import { API_CONSTANT } from "constants/ApiEditorConstants";
|
||||||
import { createSelector } from "reselect";
|
import { createSelector } from "reselect";
|
||||||
import { Page } from "constants/ReduxActionConstants";
|
import { Page } from "constants/ReduxActionConstants";
|
||||||
|
import { Datasource } from "api/DatasourcesApi";
|
||||||
|
|
||||||
export const getEntities = (state: AppState): AppState["entities"] =>
|
export const getEntities = (state: AppState): AppState["entities"] =>
|
||||||
state.entities;
|
state.entities;
|
||||||
|
|
@ -107,6 +108,20 @@ export const getActions = (state: AppState): ActionDataState =>
|
||||||
export const getDatasourceRefs = (state: AppState): any =>
|
export const getDatasourceRefs = (state: AppState): any =>
|
||||||
state.ui.datasourcePane.datasourceRefs;
|
state.ui.datasourcePane.datasourceRefs;
|
||||||
|
|
||||||
|
export const getDatasource = (
|
||||||
|
state: AppState,
|
||||||
|
datasourceId: string,
|
||||||
|
): Partial<Datasource> | undefined =>
|
||||||
|
state.entities.datasources.list.find(
|
||||||
|
datasource => datasource.id === datasourceId,
|
||||||
|
);
|
||||||
|
|
||||||
|
export const getDatasourceDraft = (state: AppState, id: string) => {
|
||||||
|
const drafts = state.ui.datasourcePane.drafts;
|
||||||
|
if (id in drafts) return drafts[id];
|
||||||
|
return {};
|
||||||
|
};
|
||||||
|
|
||||||
export const getPlugins = (state: AppState) => state.entities.plugins.list;
|
export const getPlugins = (state: AppState) => state.entities.plugins.list;
|
||||||
|
|
||||||
export const getApiActions = (state: AppState): ActionDataState => {
|
export const getApiActions = (state: AppState): ActionDataState => {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user