-
Filter Traces
- {/*
{JSON.stringify(props.traceFilters)}
*/}
-
+
Filter Traces
@@ -468,11 +454,9 @@ const _TraceFilter = (props: TraceFilterProps) => {
return { value: s.tagKeys };
})}
style={{ width: 200, textAlign: 'center' }}
- // onSelect={onSelect}
- // onSearch={onSearch}
onChange={onChangeTagKey}
- filterOption={(inputValue, option) =>
- option!.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
+ filterOption={(inputValue, option): boolean =>
+ option?.value.toUpperCase().indexOf(inputValue.toUpperCase()) !== -1
}
placeholder="Tag Key"
/>
@@ -505,7 +489,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
{
+ onCancel={(): void => {
setModalVisible(false);
}}
/>
@@ -515,7 +499,7 @@ const _TraceFilter = (props: TraceFilterProps) => {
};
const mapStateToProps = (
- state: StoreState,
+ state: AppState,
): { traceFilters: TraceFilters; globalTime: GlobalTime } => {
return { traceFilters: state.traceFilters, globalTime: state.globalTime };
};
diff --git a/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.tsx b/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.tsx
index 00163ce14b..fe6e98611d 100644
--- a/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.tsx
+++ b/frontend/src/modules/Traces/TraceGanttChart/TraceGanttChart.tsx
@@ -1,7 +1,7 @@
import './TraceGanttChart.css';
-import { Button, Col,Progress, Row, Table, Tabs } from 'antd';
-import { has,isEmpty, max } from 'lodash-es';
+import { Button, Col, Progress, Row, Table, Tabs } from 'antd';
+import { has, isEmpty, max } from 'lodash-es';
import traverseTreeData from 'modules/Traces/TraceGanttChart/TraceGanttChartHelpers';
import React, { useEffect, useRef, useState } from 'react';
import { pushDStree } from 'store/actions';
diff --git a/frontend/src/modules/Traces/TraceGanttChart/index.js b/frontend/src/modules/Traces/TraceGanttChart/index.tsx
similarity index 100%
rename from frontend/src/modules/Traces/TraceGanttChart/index.js
rename to frontend/src/modules/Traces/TraceGanttChart/index.tsx
diff --git a/frontend/src/modules/Traces/TraceGraph.tsx b/frontend/src/modules/Traces/TraceGraph.tsx
index e08e8a67a1..6840fc8322 100644
--- a/frontend/src/modules/Traces/TraceGraph.tsx
+++ b/frontend/src/modules/Traces/TraceGraph.tsx
@@ -1,19 +1,19 @@
import './TraceGraph.css';
-import { Affix,Card, Col, Row, Space } from 'antd';
+import { Affix, Card, Col, Row, Space } from 'antd';
import * as d3 from 'd3';
import { flamegraph } from 'd3-flame-graph';
import * as d3Tip from 'd3-tip';
import { isEmpty, sortBy } from 'lodash-es';
import React, { useEffect, useState } from 'react';
import { connect } from 'react-redux';
-import { useLocation,useParams } from 'react-router-dom';
+import { useLocation, useParams } from 'react-router-dom';
import {
fetchTraceItem,
pushDStree,
spansWSameTraceIDResponse,
} from 'store/actions';
-import { StoreState } from 'store/reducers';
+import { AppState } from 'store/reducers';
import styled from 'styled-components';
import { spanToTreeUtil } from 'utils/spanToTree';
@@ -204,7 +204,7 @@ const _TraceGraph = (props: TraceGraphProps) => {
};
const mapStateToProps = (
- state: StoreState,
+ state: AppState,
): { traceItem: spansWSameTraceIDResponse } => {
return { traceItem: state.traceItem };
};
diff --git a/frontend/src/modules/Traces/TraceGraphColumn.tsx b/frontend/src/modules/Traces/TraceGraphColumn.tsx
index 8b6b0ec75c..c32524580c 100644
--- a/frontend/src/modules/Traces/TraceGraphColumn.tsx
+++ b/frontend/src/modules/Traces/TraceGraphColumn.tsx
@@ -1,8 +1,8 @@
import { Table } from 'antd';
import React from 'react';
import { connect } from 'react-redux';
-import { pushDStree,traceResponseNew } from 'store/actions';
-import { StoreState } from 'store/reducers';
+import { pushDStree, traceResponseNew } from 'store/actions';
+import { AppState } from 'store/reducers';
interface TraceGraphColumnProps {
traces: traceResponseNew;
@@ -69,7 +69,7 @@ const _TraceGraphColumn = (props: TraceGraphColumnProps) => {
);
};
-const mapStateToProps = (state: StoreState): { traces: traceResponseNew } => {
+const mapStateToProps = (state: AppState): { traces: traceResponseNew } => {
return { traces: state.traces };
};
diff --git a/frontend/src/modules/Traces/TraceList.tsx b/frontend/src/modules/Traces/TraceList.tsx
index 25ec660450..c7329ed408 100644
--- a/frontend/src/modules/Traces/TraceList.tsx
+++ b/frontend/src/modules/Traces/TraceList.tsx
@@ -4,8 +4,8 @@ import moment from 'moment';
import React, { useEffect } from 'react';
import { connect } from 'react-redux';
import { useHistory } from 'react-router-dom';
-import { fetchTraces, pushDStree,traceResponseNew } from 'store/actions';
-import { StoreState } from 'store/reducers';
+import { fetchTraces, pushDStree, traceResponseNew } from 'store/actions';
+import { AppState } from 'store/reducers';
import styled from 'styled-components';
import { isOnboardingSkipped } from 'utils/app';
@@ -151,7 +151,7 @@ const _TraceList = (props: TraceListProps) => {
);
};
-const mapStateToProps = (state: StoreState): { traces: traceResponseNew } => {
+const mapStateToProps = (state: AppState): { traces: traceResponseNew } => {
return { traces: state.traces };
};
diff --git a/frontend/src/modules/Traces/styles.ts b/frontend/src/modules/Traces/styles.ts
new file mode 100644
index 0000000000..a16e487b3d
--- /dev/null
+++ b/frontend/src/modules/Traces/styles.ts
@@ -0,0 +1,16 @@
+import { Card as CardComponent, Typography } from 'antd';
+import styled from 'styled-components';
+
+export const CustomGraphContainer = styled.div`
+ min-height: 30vh;
+`;
+
+export const Card = styled(CardComponent)`
+ .ant-card-body {
+ padding-bottom: 0;
+ }
+`;
+
+export const CustomVisualizationsTitle = styled(Typography)`
+ margin-bottom: 1rem;
+`;
diff --git a/frontend/src/modules/Usage/UsageExplorer.tsx b/frontend/src/modules/Usage/UsageExplorer.tsx
index b78f720890..0259b96366 100644
--- a/frontend/src/modules/Usage/UsageExplorer.tsx
+++ b/frontend/src/modules/Usage/UsageExplorer.tsx
@@ -1,8 +1,9 @@
-import { Card, Select, Space } from 'antd';
+import { Select, Space } from 'antd';
+// import { Bar } from 'react-chartjs-2';
+import Graph from 'components/Graph';
import { useRoute } from 'modules/RouteProvider';
import moment from 'moment';
import React, { useEffect, useState } from 'react';
-import { Bar } from 'react-chartjs-2';
import { connect } from 'react-redux';
import {
getServicesList,
@@ -11,9 +12,10 @@ import {
usageDataItem,
} from 'store/actions';
import { servicesListItem } from 'store/actions/MetricsActions';
-import { StoreState } from 'store/reducers';
+import { AppState } from 'store/reducers';
import { isOnboardingSkipped } from 'utils/app';
const { Option } = Select;
+import { Card } from './styles';
interface UsageExplorerProps {
usageData: usageDataItem[];
@@ -188,15 +190,15 @@ const _UsageExplorer = (props: UsageExplorerProps) => {
)}
-
-
+
+
);
};
const mapStateToProps = (
- state: StoreState,
+ state: AppState,
): {
totalCount: number;
globalTime: GlobalTime;
diff --git a/frontend/src/modules/Usage/styles.ts b/frontend/src/modules/Usage/styles.ts
new file mode 100644
index 0000000000..26efebc856
--- /dev/null
+++ b/frontend/src/modules/Usage/styles.ts
@@ -0,0 +1,14 @@
+import { Card as CardComponent } from 'antd';
+import styled from 'styled-components';
+
+export const Card = styled(CardComponent)`
+ &&& {
+ width: 90%;
+ margin-top: 2rem;
+ }
+
+ .ant-card-body {
+ height: 100%;
+ min-height: 70vh;
+ }
+`;
diff --git a/frontend/src/modules/add-instrumentation/instrumentationPage.tsx b/frontend/src/modules/add-instrumentation/instrumentationPage.tsx
index fe12848d8a..b6e447c3be 100644
--- a/frontend/src/modules/add-instrumentation/instrumentationPage.tsx
+++ b/frontend/src/modules/add-instrumentation/instrumentationPage.tsx
@@ -2,14 +2,14 @@ import { Space } from 'antd';
import React from 'react';
import { useThemeSwitcher } from 'react-css-theme-switcher';
import { connect } from 'react-redux';
-import { StoreState } from 'store/reducers';
+import { AppState } from 'store/reducers';
import styled from 'styled-components';
const InstrumentCard = styled.div<{
currentThemeStatus: string | undefined;
}>`
border-radius: 4px;
- background: ${({ currentThemeStatus }) =>
+ background: ${({ currentThemeStatus }): string =>
currentThemeStatus === 'dark' ? '#313131' : '#ddd'};
padding: 33px 23px;
max-width: 800px;
@@ -34,7 +34,8 @@ const InstrumentationPage = (props: InstrumentationPageProps) => {
docs -
{' '}
https://signoz.io/docs/instrumentation/overview
@@ -45,7 +46,8 @@ const InstrumentationPage = (props: InstrumentationPageProps) => {
href={
'https://signoz-community.slack.com/join/shared_invite/zt-lrjknbbp-J_mI13rlw8pGF4EWBnorJA'
}
- target="_blank" rel="noreferrer"
+ target="_blank"
+ rel="noreferrer"
>
slack community
{' '}
@@ -59,7 +61,7 @@ const InstrumentationPage = (props: InstrumentationPageProps) => {
);
};
-const mapStateToProps = (state: StoreState): {} => {
+const mapStateToProps = (state: AppState): {} => {
return {};
};
diff --git a/frontend/src/pages/Dashboard/index.tsx b/frontend/src/pages/Dashboard/index.tsx
new file mode 100644
index 0000000000..b3a8e72530
--- /dev/null
+++ b/frontend/src/pages/Dashboard/index.tsx
@@ -0,0 +1,40 @@
+import Spinner from 'components/Spinner';
+import ListOfAllDashboard from 'container/ListOfDashboard';
+import React, { useEffect } from 'react';
+import { connect, useSelector } from 'react-redux';
+import { bindActionCreators } from 'redux';
+import { ThunkDispatch } from 'redux-thunk';
+import { GetAllDashboards } from 'store/actions';
+import { AppState } from 'store/reducers';
+import AppActions from 'types/actions';
+import DashboardReducer from 'types/reducer/dashboards';
+
+const Dashboard = ({ getAllDashboards }: DashboardProps): JSX.Element => {
+ const { loading } = useSelector(
+ (state) => state.dashboards,
+ );
+
+ useEffect(() => {
+ getAllDashboards();
+ }, [getAllDashboards]);
+
+ if (loading) {
+ return ;
+ }
+
+ return ;
+};
+
+interface DispatchProps {
+ getAllDashboards: () => void;
+}
+
+const mapDispatchToProps = (
+ dispatch: ThunkDispatch,
+): DispatchProps => ({
+ getAllDashboards: bindActionCreators(GetAllDashboards, dispatch),
+});
+
+type DashboardProps = DispatchProps;
+
+export default connect(null, mapDispatchToProps)(Dashboard);
diff --git a/frontend/src/pages/DashboardWidget/index.tsx b/frontend/src/pages/DashboardWidget/index.tsx
new file mode 100644
index 0000000000..b5e8853fb5
--- /dev/null
+++ b/frontend/src/pages/DashboardWidget/index.tsx
@@ -0,0 +1,101 @@
+import { Card, Typography } from 'antd';
+import Spinner from 'components/Spinner';
+import ROUTES from 'constants/routes';
+import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
+import NewWidget from 'container/NewWidget';
+import updateUrl from 'lib/updateUrl';
+import React, { useEffect, useRef, useState } from 'react';
+import { connect, useSelector } from 'react-redux';
+import { useHistory, useLocation, useParams } from 'react-router-dom';
+import { bindActionCreators, Dispatch } from 'redux';
+import { ThunkDispatch } from 'redux-thunk';
+import { GetDashboard, GetDashboardProps } from 'store/actions';
+import { AppState } from 'store/reducers';
+import AppActions from 'types/actions';
+import DashboardReducer from 'types/reducer/dashboards';
+
+const DashboardWidget = ({ getDashboard }: NewDashboardProps): JSX.Element => {
+ const { search } = useLocation();
+ const { dashboardId } = useParams();
+
+ const { push } = useHistory();
+ const [selectedGraph, setSelectedGraph] = useState();
+ const { loading, dashboards, error, errorMessage } = useSelector<
+ AppState,
+ DashboardReducer
+ >((state) => state.dashboards);
+ const [selectedDashboard] = dashboards;
+ const params = new URLSearchParams(search);
+
+ const widgetId = params.get('widgetId');
+ const { data } = selectedDashboard || {};
+ const { widgets } = data || {};
+
+ const selectedWidget = widgets?.find((e) => e.id === widgetId);
+
+ useEffect(() => {
+ const params = new URLSearchParams(search);
+ const graphType = params.get('graphType') as GRAPH_TYPES | null;
+
+ if (graphType === null) {
+ push(updateUrl(ROUTES.DASHBOARD, ':dashboardId', dashboardId));
+ } else {
+ setSelectedGraph(graphType);
+ }
+ }, [dashboardId, push, search]);
+
+ const counter = useRef(0);
+
+ useEffect(() => {
+ if (counter.current === 0 && selectedGraph && widgetId !== null) {
+ counter.current = 1;
+ getDashboard({
+ uuid: dashboardId,
+ graphType: selectedGraph,
+ widgetId,
+ });
+ }
+ }, [selectedGraph, dashboardId, getDashboard, search, widgetId]);
+
+ if (
+ selectedGraph === undefined ||
+ loading ||
+ dashboards.length === 0 ||
+ dashboards[0].data.widgets === undefined ||
+ selectedWidget === undefined
+ ) {
+ return ;
+ }
+
+ if (error) {
+ return (
+
+ {errorMessage}
+
+ );
+ }
+
+ return ;
+};
+
+export interface DashboardWidgetPageParams {
+ dashboardId: string;
+}
+
+interface DispatchProps {
+ getDashboard: ({
+ uuid,
+ widgetId,
+ graphType,
+ }: GetDashboardProps) => (dispatch: Dispatch) => void;
+}
+
+const mapDispatchToProps = (
+ dispatch: ThunkDispatch,
+): DispatchProps => ({
+ getDashboard: bindActionCreators(GetDashboard, dispatch),
+});
+
+type NewDashboardProps = DispatchProps;
+
+export default connect(null, mapDispatchToProps)(DashboardWidget);
diff --git a/frontend/src/pages/NewDashboard/index.tsx b/frontend/src/pages/NewDashboard/index.tsx
new file mode 100644
index 0000000000..577a563ec0
--- /dev/null
+++ b/frontend/src/pages/NewDashboard/index.tsx
@@ -0,0 +1,56 @@
+import Spinner from 'components/Spinner';
+import NewDashboard from 'container/NewDashboard';
+import React, { useEffect } from 'react';
+import { connect, useSelector } from 'react-redux';
+import { useParams } from 'react-router-dom';
+import { bindActionCreators, Dispatch } from 'redux';
+import { ThunkDispatch } from 'redux-thunk';
+import { GetDashboard, GetDashboardProps } from 'store/actions/dashboard';
+import { AppState } from 'store/reducers';
+import AppActions from 'types/actions';
+import DashboardReducer from 'types/reducer/dashboards';
+
+const NewDashboardPage = ({ getDashboard }: NewDashboardProps): JSX.Element => {
+ const { loading, dashboards, error, errorMessage } = useSelector<
+ AppState,
+ DashboardReducer
+ >((state) => state.dashboards);
+
+ const { dashboardId } = useParams();
+
+ useEffect(() => {
+ getDashboard({
+ uuid: dashboardId,
+ });
+ }, [getDashboard, dashboardId]);
+
+ if (error && !loading && dashboards.length === 0) {
+ return {errorMessage}
;
+ }
+
+ if (loading || dashboards.length === 0) {
+ return ;
+ }
+
+ return ;
+};
+
+interface Params {
+ dashboardId: string;
+}
+
+interface DispatchProps {
+ getDashboard: (
+ props: GetDashboardProps,
+ ) => (dispatch: Dispatch) => void;
+}
+
+const mapDispatchToProps = (
+ dispatch: ThunkDispatch,
+): DispatchProps => ({
+ getDashboard: bindActionCreators(GetDashboard, dispatch),
+});
+
+type NewDashboardProps = DispatchProps;
+
+export default connect(null, mapDispatchToProps)(NewDashboardPage);
diff --git a/frontend/src/store/actions/MetricsActions/metricsActions.ts b/frontend/src/store/actions/MetricsActions/metricsActions.ts
index d5a4ce392c..5a01c4e0de 100644
--- a/frontend/src/store/actions/MetricsActions/metricsActions.ts
+++ b/frontend/src/store/actions/MetricsActions/metricsActions.ts
@@ -1,4 +1,4 @@
-import api, { apiV1 } from 'api';
+import api from 'api';
import { Dispatch } from 'redux';
import { GlobalTime } from 'store/actions/global';
import { toUTCEpoch } from 'utils/timeUtils';
@@ -7,18 +7,17 @@ import { MetricsActionTypes } from './metricsActionTypes';
import * as MetricsInterfaces from './metricsInterfaces';
export const getServicesList = (globalTime: GlobalTime) => {
- return async (dispatch: Dispatch) => {
+ return async (dispatch: Dispatch): Promise => {
const request_string =
'/services?start=' + globalTime.minTime + '&end=' + globalTime.maxTime;
const response = await api.get(
- apiV1 + request_string,
+ request_string,
);
dispatch({
type: MetricsActionTypes.getServicesList,
payload: response.data,
- //PNOTE - response.data in the axios response has the actual API response
});
};
};
@@ -27,7 +26,7 @@ export const getDbOverViewMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
- return async (dispatch: Dispatch) => {
+ return async (dispatch: Dispatch): Promise => {
const request_string =
'/service/dbOverview?service=' +
serviceName +
@@ -37,7 +36,7 @@ export const getDbOverViewMetrics = (
globalTime.maxTime +
'&step=60';
const response = await api.get(
- apiV1 + request_string,
+ request_string,
);
dispatch({
type: MetricsActionTypes.getDbOverviewMetrics,
@@ -50,7 +49,7 @@ export const getExternalMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
- return async (dispatch: Dispatch) => {
+ return async (dispatch: Dispatch): Promise => {
const request_string =
'/service/external?service=' +
serviceName +
@@ -60,7 +59,7 @@ export const getExternalMetrics = (
globalTime.maxTime +
'&step=60';
const response = await api.get(
- apiV1 + request_string,
+ request_string,
);
dispatch({
type: MetricsActionTypes.getExternalMetrics,
@@ -73,7 +72,7 @@ export const getExternalAvgDurationMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
- return async (dispatch: Dispatch) => {
+ return async (dispatch: Dispatch): Promise => {
const request_string =
'/service/externalAvgDuration?service=' +
serviceName +
@@ -85,7 +84,7 @@ export const getExternalAvgDurationMetrics = (
const response = await api.get<
MetricsInterfaces.externalMetricsAvgDurationItem[]
- >(apiV1 + request_string);
+ >(request_string);
dispatch({
type: MetricsActionTypes.getAvgDurationMetrics,
payload: response.data,
@@ -96,7 +95,7 @@ export const getExternalErrCodeMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
- return async (dispatch: Dispatch) => {
+ return async (dispatch: Dispatch): Promise => {
const request_string =
'/service/externalErrors?service=' +
serviceName +
@@ -107,7 +106,7 @@ export const getExternalErrCodeMetrics = (
'&step=60';
const response = await api.get<
MetricsInterfaces.externalErrCodeMetricsItem[]
- >(apiV1 + request_string);
+ >(request_string);
dispatch({
type: MetricsActionTypes.getErrCodeMetrics,
@@ -120,7 +119,7 @@ export const getServicesMetrics = (
serviceName: string,
globalTime: GlobalTime,
) => {
- return async (dispatch: Dispatch) => {
+ return async (dispatch: Dispatch): Promise => {
const request_string =
'/service/overview?service=' +
serviceName +
@@ -130,13 +129,12 @@ export const getServicesMetrics = (
globalTime.maxTime +
'&step=60';
const response = await api.get(
- apiV1 + request_string,
+ request_string,
);
dispatch({
type: MetricsActionTypes.getServiceMetrics,
payload: response.data,
- //PNOTE - response.data in the axios response has the actual API response
});
};
};
@@ -145,7 +143,7 @@ export const getTopEndpoints = (
serviceName: string,
globalTime: GlobalTime,
) => {
- return async (dispatch: Dispatch) => {
+ return async (dispatch: Dispatch): Promise => {
const request_string =
'/service/top_endpoints?service=' +
serviceName +
@@ -154,13 +152,12 @@ export const getTopEndpoints = (
'&end=' +
globalTime.maxTime;
const response = await api.get(
- apiV1 + request_string,
+ request_string,
);
dispatch({
type: MetricsActionTypes.getTopEndpoints,
payload: response.data,
- //PNOTE - response.data in the axios response has the actual API response
});
};
};
@@ -169,7 +166,7 @@ export const getFilteredTraceMetrics = (
filter_params: string,
globalTime: GlobalTime,
) => {
- return async (dispatch: Dispatch) => {
+ return async (dispatch: Dispatch): Promise => {
const request_string =
'/spans/aggregates?start=' +
toUTCEpoch(globalTime.minTime) +
@@ -178,13 +175,117 @@ export const getFilteredTraceMetrics = (
'&' +
filter_params;
const response = await api.get(
- apiV1 + request_string,
+ request_string,
);
dispatch({
type: MetricsActionTypes.getFilteredTraceMetrics,
payload: response.data,
- //PNOTE - response.data in the axios response has the actual API response
});
};
};
+
+export const getInitialMerticData = ({
+ serviceName,
+ globalTime,
+}: getInitialMerticDataProps) => {
+ return async (dispatch: Dispatch): Promise => {
+ try {
+ const dbOverviewString =
+ '/service/dbOverview?service=' +
+ serviceName +
+ '&start=' +
+ globalTime.minTime +
+ '&end=' +
+ globalTime.maxTime +
+ '&step=60';
+
+ const externalServicesString =
+ '/service/external?service=' +
+ serviceName +
+ '&start=' +
+ globalTime.minTime +
+ '&end=' +
+ globalTime.maxTime +
+ '&step=60';
+
+ const topEndPointsString =
+ '/service/top_endpoints?service=' +
+ serviceName +
+ '&start=' +
+ globalTime.minTime +
+ '&end=' +
+ globalTime.maxTime;
+
+ const avgExternalDurationString =
+ '/service/externalAvgDuration?service=' +
+ serviceName +
+ '&start=' +
+ globalTime.minTime +
+ '&end=' +
+ globalTime.maxTime +
+ '&step=60';
+
+ const serviceOverviewString =
+ '/service/overview?service=' +
+ serviceName +
+ '&start=' +
+ globalTime.minTime +
+ '&end=' +
+ globalTime.maxTime +
+ '&step=60';
+
+ const externalErrorCodeMetricsString =
+ '/service/externalErrors?service=' +
+ serviceName +
+ '&start=' +
+ globalTime.minTime +
+ '&end=' +
+ globalTime.maxTime +
+ '&step=60';
+
+ dispatch({
+ type: 'UPDATE_INITIAL_VALUE_START',
+ });
+
+ const [
+ dbResponse,
+ externalServiceResponse,
+ topEndPointsResponse,
+ avgExternalDurationResponse,
+ serviceOverViewResponse,
+ externalErrorCodeMetricsResponse,
+ ] = await Promise.all([
+ api.get(dbOverviewString),
+ api.get(externalServicesString),
+ api.get(topEndPointsString),
+ api.get(
+ avgExternalDurationString,
+ ),
+ api.get(serviceOverviewString),
+ api.get(
+ externalErrorCodeMetricsString,
+ ),
+ ]);
+
+ dispatch({
+ type: 'UPDATE_INITIAL_VALUE',
+ payload: {
+ serviceOverViewResponse: serviceOverViewResponse.data,
+ topEndPointsResponse: topEndPointsResponse.data,
+ dbResponse: dbResponse.data,
+ externalServiceResponse: externalServiceResponse.data,
+ avgExternalDurationResponse: avgExternalDurationResponse.data,
+ externalErrorCodeMetricsResponse: externalErrorCodeMetricsResponse.data,
+ },
+ });
+ } catch (error) {
+ console.error(error);
+ }
+ };
+};
+
+export interface getInitialMerticDataProps {
+ serviceName: string;
+ globalTime: GlobalTime;
+}
diff --git a/frontend/src/store/actions/dashboard/applySettingsToPanel.ts b/frontend/src/store/actions/dashboard/applySettingsToPanel.ts
new file mode 100644
index 0000000000..f18dcf7052
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/applySettingsToPanel.ts
@@ -0,0 +1,24 @@
+import { Dispatch } from 'redux';
+import AppActions from 'types/actions';
+import { Widgets } from 'types/api/dashboard/getAll';
+
+export const ApplySettingsToPanel = (
+ props: ApplySettingsToPanelProps,
+): ((dispatch: Dispatch) => void) => {
+ return (dispatch: Dispatch): void => {
+ dispatch({
+ type: 'APPLY_SETTINGS_TO_PANEL',
+ payload: props,
+ });
+ };
+};
+
+export interface ApplySettingsToPanelProps {
+ title: Widgets['title'];
+ description: Widgets['description'];
+ opacity: Widgets['opacity'];
+ isStacked: Widgets['isStacked'];
+ timePreferance: Widgets['timePreferance'];
+ nullZeroValues: Widgets['nullZeroValues'];
+ widgetId: Widgets['id'];
+}
diff --git a/frontend/src/store/actions/dashboard/createQuery.ts b/frontend/src/store/actions/dashboard/createQuery.ts
new file mode 100644
index 0000000000..bd8947526e
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/createQuery.ts
@@ -0,0 +1,17 @@
+import { Dispatch } from 'redux';
+import AppActions from 'types/actions';
+
+export const CreateQuery = ({ widgetId }: CreateQueryProps) => (
+ dispatch: Dispatch,
+): void => {
+ dispatch({
+ type: 'CREATE_NEW_QUERY',
+ payload: {
+ widgetId,
+ },
+ });
+};
+
+export interface CreateQueryProps {
+ widgetId: string;
+}
diff --git a/frontend/src/store/actions/dashboard/deleteDashboard.ts b/frontend/src/store/actions/dashboard/deleteDashboard.ts
new file mode 100644
index 0000000000..b8fca59f66
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/deleteDashboard.ts
@@ -0,0 +1,43 @@
+import deleteDashboardApi from 'api/dashboard/delete';
+import { Dispatch } from 'redux';
+import AppActions from 'types/actions';
+import { Dashboard } from 'types/api/dashboard/getAll';
+
+export const DeleteDashboard = ({
+ uuid,
+}: DeleteDashboardProps): ((dispatch: Dispatch) => void) => {
+ return async (dispatch: Dispatch): Promise => {
+ try {
+ const response = await deleteDashboardApi({
+ uuid: uuid,
+ });
+
+ if (response.statusCode === 200) {
+ dispatch({
+ type: 'DELETE_DASHBOARD_SUCCESS',
+ payload: {
+ uuid: uuid,
+ },
+ });
+ } else {
+ dispatch({
+ type: 'DELETE_DASHBOARD_ERROR',
+ payload: {
+ errorMessage: response.error || 'Something went wrong',
+ },
+ });
+ }
+ } catch (error) {
+ dispatch({
+ type: 'DELETE_DASHBOARD_ERROR',
+ payload: {
+ errorMessage: error.toString() || 'Something went wrong',
+ },
+ });
+ }
+ };
+};
+
+export interface DeleteDashboardProps {
+ uuid: Dashboard['uuid'];
+}
diff --git a/frontend/src/store/actions/dashboard/deleteWidget.ts b/frontend/src/store/actions/dashboard/deleteWidget.ts
new file mode 100644
index 0000000000..d86ba2b086
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/deleteWidget.ts
@@ -0,0 +1,56 @@
+import updateDashboardApi from 'api/dashboard/update';
+import { AxiosError } from 'axios';
+import { Dispatch } from 'redux';
+import store from 'store';
+import AppActions from 'types/actions';
+import { Widgets } from 'types/api/dashboard/getAll';
+
+export const DeleteWidget = ({
+ widgetId,
+}: DeleteWidgetProps): ((dispatch: Dispatch) => void) => {
+ return async (dispatch: Dispatch): Promise => {
+ try {
+ const { dashboards } = store.getState();
+ const [selectedDashboard] = dashboards.dashboards;
+
+ const { widgets = [] } = selectedDashboard.data;
+ const updatedWidgets = widgets.filter((e) => e.id !== widgetId);
+
+ const response = await updateDashboardApi({
+ title: selectedDashboard.data.title,
+ uuid: selectedDashboard.uuid,
+ description: selectedDashboard.data.description,
+ name: selectedDashboard.data.name,
+ tags: selectedDashboard.data.tags,
+ widgets: updatedWidgets,
+ });
+
+ if (response.statusCode === 200) {
+ dispatch({
+ type: 'DELETE_WIDGET_SUCCESS',
+ payload: {
+ widgetId,
+ },
+ });
+ } else {
+ dispatch({
+ type: 'DELETE_WIDGET_ERROR',
+ payload: {
+ errorMessage: response.error || 'Something went wrong',
+ },
+ });
+ }
+ } catch (error) {
+ dispatch({
+ type: 'DELETE_WIDGET_ERROR',
+ payload: {
+ errorMessage: (error as AxiosError).toString() || 'Something went wrong',
+ },
+ });
+ }
+ };
+};
+
+export interface DeleteWidgetProps {
+ widgetId: Widgets['id'];
+}
diff --git a/frontend/src/store/actions/dashboard/getAllDashboard.ts b/frontend/src/store/actions/dashboard/getAllDashboard.ts
new file mode 100644
index 0000000000..2569436a62
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/getAllDashboard.ts
@@ -0,0 +1,38 @@
+import getAll from 'api/dashboard/getAll';
+import { AxiosError } from 'axios';
+import { Dispatch } from 'redux';
+import AppActions from 'types/actions';
+
+export const GetAllDashboards = (): ((
+ dispatch: Dispatch,
+) => void) => {
+ return async (dispatch: Dispatch): Promise => {
+ try {
+ dispatch({
+ type: 'GET_ALL_DASHBOARD_LOADING_START',
+ });
+ const response = await getAll();
+
+ if (response.statusCode === 200) {
+ dispatch({
+ type: 'GET_ALL_DASHBOARD_SUCCESS',
+ payload: response.payload,
+ });
+ } else {
+ dispatch({
+ type: 'GET_ALL_DASHBOARD_ERROR',
+ payload: {
+ errorMessage: response.error || 'Something went wrong',
+ },
+ });
+ }
+ } catch (error) {
+ dispatch({
+ type: 'GET_ALL_DASHBOARD_ERROR',
+ payload: {
+ errorMessage: (error as AxiosError).toString() || 'Something went wrong',
+ },
+ });
+ }
+ };
+};
diff --git a/frontend/src/store/actions/dashboard/getDashboard.ts b/frontend/src/store/actions/dashboard/getDashboard.ts
new file mode 100644
index 0000000000..5d64c87fff
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/getDashboard.ts
@@ -0,0 +1,78 @@
+import getDashboard from 'api/dashboard/get';
+import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
+import { Dispatch } from 'redux';
+import AppActions from 'types/actions';
+import { Props } from 'types/api/dashboard/get';
+
+export const GetDashboard = ({
+ uuid,
+ widgetId,
+ graphType,
+}: GetDashboardProps): ((dispatch: Dispatch) => void) => {
+ return async (dispatch: Dispatch): Promise => {
+ try {
+ dispatch({
+ type: 'GET_DASHBOARD_LOADING_START',
+ });
+
+ const response = await getDashboard({
+ uuid: uuid,
+ });
+
+ if (response.statusCode === 200) {
+ dispatch({
+ payload: response.payload,
+ type: 'GET_DASHBOARD_SUCCESS',
+ });
+
+ if (widgetId !== undefined) {
+ dispatch({
+ type: 'CREATE_DEFAULT_WIDGET',
+ payload: {
+ description: '',
+ id: widgetId,
+ isStacked: false,
+ nullZeroValues: 'zero',
+ opacity: '0',
+ panelTypes: graphType || 'TIME_SERIES',
+ timePreferance: 'GLOBAL_TIME',
+ title: '',
+ queryData: {
+ data: [],
+ error: false,
+ errorMessage: '',
+ loading: false,
+ },
+ query: [
+ {
+ query: '',
+ legend: '',
+ },
+ ],
+ },
+ });
+ }
+ } else {
+ dispatch({
+ type: 'GET_DASHBOARD_ERROR',
+ payload: {
+ errorMessage: response.error || 'Something went wrong',
+ },
+ });
+ }
+ } catch (error) {
+ dispatch({
+ type: 'GET_DASHBOARD_ERROR',
+ payload: {
+ errorMessage: error.toString() || 'Something went wrong',
+ },
+ });
+ }
+ };
+};
+
+export interface GetDashboardProps {
+ uuid: Props['uuid'];
+ widgetId?: string;
+ graphType?: GRAPH_TYPES;
+}
diff --git a/frontend/src/store/actions/dashboard/getQueryResults.ts b/frontend/src/store/actions/dashboard/getQueryResults.ts
new file mode 100644
index 0000000000..0912d424aa
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/getQueryResults.ts
@@ -0,0 +1,99 @@
+import getQueryResult from 'api/widgets/getQuery';
+import { AxiosError } from 'axios';
+import { ITEMS } from 'container/NewDashboard/ComponentsSlider/menuItems';
+import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
+import GetMaxMinTime from 'lib/getMaxMinTime';
+import GetStartAndEndTime from 'lib/getStartAndEndTime';
+import { Dispatch } from 'redux';
+import AppActions from 'types/actions';
+import { Query } from 'types/api/dashboard/getAll';
+
+export const GetQueryResults = (
+ props: GetQueryResultsProps,
+): ((dispatch: Dispatch) => void) => {
+ return async (dispatch: Dispatch): Promise => {
+ try {
+ const queryData = props.query;
+
+ const getMaxMinTime = GetMaxMinTime({
+ graphType: props.graphType,
+ maxTime: props.maxTime,
+ minTime: props.minTime,
+ });
+
+ const { end, start } = GetStartAndEndTime({
+ type: props.selectedTime,
+ maxTime: getMaxMinTime.maxTime,
+ minTime: getMaxMinTime.minTime,
+ });
+
+ const response = await Promise.all(
+ queryData
+ .filter((e) => e.query)
+ .map(async (query) => {
+ const result = await getQueryResult({
+ end,
+ query: encodeURIComponent(query.query),
+ start: start,
+ step: '30',
+ });
+ return {
+ query: query.query,
+ queryData: result,
+ legend: query.legend,
+ };
+ }),
+ );
+
+ const isError = response.find(
+ ({ queryData }) => queryData.statusCode !== 200,
+ );
+
+ // want to make sure query is not empty
+ const isEmptyQuery =
+ queryData.map((e) => e.query).filter((e) => e).length ===
+ queryData.map((e) => e.query).length;
+
+ if (isError !== undefined && isEmptyQuery) {
+ dispatch({
+ type: 'QUERY_ERROR',
+ payload: {
+ errorMessage: isError.queryData.error || '',
+ widgetId: props.widgetId,
+ },
+ });
+ }
+
+ const data = response.map((e) => ({
+ query: e.query,
+ legend: e.legend || '',
+ queryData: e.queryData.payload?.result || [],
+ }));
+
+ dispatch({
+ type: 'QUERY_SUCCESS',
+ payload: {
+ widgetId: props.widgetId,
+ data,
+ },
+ });
+ } catch (error) {
+ dispatch({
+ type: 'QUERY_ERROR',
+ payload: {
+ errorMessage: (error as AxiosError).toString(),
+ widgetId: props.widgetId,
+ },
+ });
+ }
+ };
+};
+
+export interface GetQueryResultsProps {
+ widgetId: string;
+ selectedTime: timePreferenceType;
+ maxTime: number;
+ minTime: number;
+ query: Query[];
+ graphType: ITEMS;
+}
diff --git a/frontend/src/store/actions/dashboard/index.ts b/frontend/src/store/actions/dashboard/index.ts
new file mode 100644
index 0000000000..4f0e75fa7d
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/index.ts
@@ -0,0 +1,7 @@
+export * from './applySettingsToPanel';
+export * from './createQuery';
+export * from './deleteDashboard';
+export * from './getAllDashboard';
+export * from './getDashboard';
+export * from './toggleEditMode';
+export * from './updateDashboardTitle';
diff --git a/frontend/src/store/actions/dashboard/saveDashboard.ts b/frontend/src/store/actions/dashboard/saveDashboard.ts
new file mode 100644
index 0000000000..33f1a03422
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/saveDashboard.ts
@@ -0,0 +1,116 @@
+import updateDashboardApi from 'api/dashboard/update';
+import { AxiosError } from 'axios';
+import ROUTES from 'constants/routes';
+import history from 'lib/history';
+import updateUrl from 'lib/updateUrl';
+import { Dispatch } from 'redux';
+import store from 'store';
+import AppActions from 'types/actions';
+import { Dashboard, Widgets } from 'types/api/dashboard/getAll';
+
+export const SaveDashboard = ({
+ uuid,
+ description,
+ isStacked,
+ nullZeroValues,
+ opacity,
+ timePreferance,
+ title,
+ widgetId,
+ dashboardId,
+}: SaveDashboardProps): ((dispatch: Dispatch) => void) => {
+ return async (dispatch: Dispatch): Promise => {
+ try {
+ const dashboard = store.getState();
+
+ const selectedDashboard = dashboard.dashboards.dashboards.find(
+ (e) => e.uuid === uuid,
+ );
+
+ if (selectedDashboard === undefined) {
+ throw new Error('Dashboard Not Found');
+ }
+
+ const data = selectedDashboard.data;
+
+ const updatedTitle = title;
+ const updatedDescription = description;
+ const updatedisStacked = isStacked;
+ const updatednullZeroValues = nullZeroValues;
+ const updatedopacity = opacity;
+ const updatedtimePreferance = timePreferance;
+
+ const selectedWidgetIndex = data.widgets?.findIndex(
+ (e) => e.id === widgetId,
+ );
+
+ const preWidget = data.widgets?.slice(0, selectedWidgetIndex) || [];
+ const afterWidget =
+ data.widgets?.slice(
+ (selectedWidgetIndex || 0) + 1, // this is never undefined
+ data.widgets?.length,
+ ) || [];
+ const selectedWidget = (selectedDashboard.data.widgets || [])[
+ selectedWidgetIndex || 0
+ ];
+
+ const response = await updateDashboardApi({
+ uuid,
+ // this is the data for the dashboard
+ title: selectedDashboard.data.title,
+ description: selectedDashboard.data.description,
+ tags: selectedDashboard.data.tags,
+ name: selectedDashboard.data.name,
+ // as we are updated the widget only
+ widgets: [
+ ...preWidget,
+ {
+ ...selectedWidget,
+ description: updatedDescription,
+ id: widgetId,
+ isStacked: updatedisStacked,
+ nullZeroValues: updatednullZeroValues,
+ opacity: updatedopacity,
+ title: updatedTitle,
+ timePreferance: updatedtimePreferance,
+ },
+ ...afterWidget,
+ ],
+ });
+
+ if (response.statusCode === 200) {
+ dispatch({
+ type: 'SAVE_SETTING_TO_PANEL_SUCCESS',
+ payload: response.payload,
+ });
+ history.push(updateUrl(ROUTES.DASHBOARD, ':dashboardId', dashboardId));
+ } else {
+ dispatch({
+ type: 'SAVE_SETTING_TO_PANEL_ERROR',
+ payload: {
+ errorMessage: response.error || 'Something went wrong',
+ },
+ });
+ }
+ } catch (error) {
+ dispatch({
+ type: 'SAVE_SETTING_TO_PANEL_ERROR',
+ payload: {
+ errorMessage: (error as AxiosError).toString() || 'Something went wrong',
+ },
+ });
+ }
+ };
+};
+
+export interface SaveDashboardProps {
+ uuid: Dashboard['uuid'];
+ title: Widgets['title'];
+ description: Widgets['description'];
+ opacity: Widgets['opacity'];
+ isStacked: Widgets['isStacked'];
+ timePreferance: Widgets['timePreferance'];
+ nullZeroValues: Widgets['nullZeroValues'];
+ widgetId: Widgets['id'];
+ dashboardId: string;
+}
diff --git a/frontend/src/store/actions/dashboard/toggleAddWidget.ts b/frontend/src/store/actions/dashboard/toggleAddWidget.ts
new file mode 100644
index 0000000000..efbae4ba02
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/toggleAddWidget.ts
@@ -0,0 +1,17 @@
+import { Dispatch } from 'redux';
+import AppActions from 'types/actions';
+
+export const ToggleAddWidget = (
+ props: ToggleAddWidgetProps,
+): ((dispatch: Dispatch) => void) => {
+ return (dispatch: Dispatch): void => {
+ dispatch({
+ type: 'IS_ADD_WIDGET',
+ payload: {
+ isAddWidget: props,
+ },
+ });
+ };
+};
+
+export type ToggleAddWidgetProps = boolean;
diff --git a/frontend/src/store/actions/dashboard/toggleEditMode.ts b/frontend/src/store/actions/dashboard/toggleEditMode.ts
new file mode 100644
index 0000000000..bcff35bb54
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/toggleEditMode.ts
@@ -0,0 +1,12 @@
+import { Dispatch } from 'react';
+import AppActions from 'types/actions';
+
+export const ToggleEditMode = (): ((
+ dispatch: Dispatch,
+) => void) => {
+ return (dispatch: Dispatch): void => {
+ dispatch({
+ type: 'TOGGLE_EDIT_MODE',
+ });
+ };
+};
diff --git a/frontend/src/store/actions/dashboard/updateDashboardTitle.ts b/frontend/src/store/actions/dashboard/updateDashboardTitle.ts
new file mode 100644
index 0000000000..071f063fe2
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/updateDashboardTitle.ts
@@ -0,0 +1,54 @@
+import update from 'api/dashboard/update';
+import { Dispatch } from 'redux';
+import AppActions from 'types/actions';
+import { Dashboard } from 'types/api/dashboard/getAll';
+
+export const UpdateDashboardTitleDescriptionTags = ({
+ dashboard, // @TODO need to grab the dashboard from the store
+}: UpdateDashboardTitleDescriptionTagsProps): ((
+ dispatch: Dispatch,
+) => void) => {
+ return async (dispatch: Dispatch): Promise => {
+ try {
+ const data = dashboard.data;
+
+ const response = await update({
+ ...dashboard.data,
+ title: dashboard.data.title,
+ uuid: dashboard.uuid,
+ });
+
+ if (response.statusCode === 200) {
+ dispatch({
+ type: 'UPDATE_TITLE_DESCRIPTION_TAGS_SUCCESS',
+ payload: {
+ description: data.description,
+ tags: data.tags,
+ title: dashboard.data.title,
+ },
+ });
+ dispatch({
+ type: 'TOGGLE_EDIT_MODE',
+ });
+ } else {
+ dispatch({
+ type: 'UPDATE_TITLE_DESCRIPTION_TAGS_ERROR',
+ payload: {
+ errorMessage: response.error || 'Something went wrong',
+ },
+ });
+ }
+ } catch (error) {
+ dispatch({
+ type: 'UPDATE_TITLE_DESCRIPTION_TAGS_ERROR',
+ payload: {
+ errorMessage: error.toString() || 'Something went wrong',
+ },
+ });
+ }
+ };
+};
+
+export interface UpdateDashboardTitleDescriptionTagsProps {
+ dashboard: Dashboard;
+}
diff --git a/frontend/src/store/actions/dashboard/updateQuery.ts b/frontend/src/store/actions/dashboard/updateQuery.ts
new file mode 100644
index 0000000000..c89895ca9a
--- /dev/null
+++ b/frontend/src/store/actions/dashboard/updateQuery.ts
@@ -0,0 +1,44 @@
+import { Dispatch } from 'redux';
+import store from 'store';
+import AppActions from 'types/actions';
+import { Query } from 'types/api/dashboard/getAll';
+
+export const UpdateQuery = (
+ props: UpdateQueryProps,
+): ((dispatch: Dispatch) => void) => {
+ return (dispatch: Dispatch): void => {
+ const state = store.getState();
+ const dashboards = state.dashboards.dashboards;
+ const [selectedDashboard] = dashboards;
+ const { data } = selectedDashboard;
+ const { widgets = [] } = data;
+ const selectedWidgetIndex = widgets.findIndex((e) => e.id === props.widgetId);
+ const selectedWidget = widgets[selectedWidgetIndex];
+ const { query } = selectedWidget;
+ const preQuery = query.slice(0, props.currentIndex);
+ const afterQuery = query.slice(props.currentIndex + 1, query.length);
+ const queryArray: Query[] = [
+ ...preQuery,
+ {
+ query: props.query,
+ legend: props.legend,
+ },
+ ...afterQuery,
+ ];
+
+ dispatch({
+ type: 'UPDATE_QUERY',
+ payload: {
+ query: queryArray,
+ widgetId: props.widgetId,
+ },
+ });
+ };
+};
+
+export interface UpdateQueryProps {
+ widgetId: string;
+ query: string;
+ legend: string;
+ currentIndex: number;
+}
diff --git a/frontend/src/store/actions/global.ts b/frontend/src/store/actions/global.ts
index 696c1c3ad8..fe8874297a 100644
--- a/frontend/src/store/actions/global.ts
+++ b/frontend/src/store/actions/global.ts
@@ -24,54 +24,54 @@ export const updateTimeInterval = (
// set directly based on that. Assuming datetimeRange values are in ms, and minTime is 0th element
switch (interval) {
- case '1min':
- maxTime = Date.now() * 1000000; // in nano sec
- minTime = (Date.now() - 1 * 60 * 1000) * 1000000;
- break;
- case '5min':
- maxTime = Date.now() * 1000000; // in nano sec
- minTime = (Date.now() - 5 * 60 * 1000) * 1000000;
- break;
+ case '1min':
+ maxTime = Date.now() * 1000000; // in nano sec
+ minTime = (Date.now() - 1 * 60 * 1000) * 1000000;
+ break;
+ case '5min':
+ maxTime = Date.now() * 1000000; // in nano sec
+ minTime = (Date.now() - 5 * 60 * 1000) * 1000000;
+ break;
- case '15min':
- maxTime = Date.now() * 1000000; // in nano sec
- minTime = (Date.now() - 15 * 60 * 1000) * 1000000;
- break;
+ case '15min':
+ maxTime = Date.now() * 1000000; // in nano sec
+ minTime = (Date.now() - 15 * 60 * 1000) * 1000000;
+ break;
- case '30min':
- maxTime = Date.now() * 1000000; // in nano sec
- minTime = (Date.now() - 30 * 60 * 1000) * 1000000;
- break;
+ case '30min':
+ maxTime = Date.now() * 1000000; // in nano sec
+ minTime = (Date.now() - 30 * 60 * 1000) * 1000000;
+ break;
- case '1hr':
- maxTime = Date.now() * 1000000; // in nano sec
- minTime = (Date.now() - 1 * 60 * 60 * 1000) * 1000000;
- break;
+ case '1hr':
+ maxTime = Date.now() * 1000000; // in nano sec
+ minTime = (Date.now() - 1 * 60 * 60 * 1000) * 1000000;
+ break;
- case '6hr':
- maxTime = Date.now() * 1000000; // in nano sec
- minTime = (Date.now() - 6 * 60 * 60 * 1000) * 1000000;
- break;
+ case '6hr':
+ maxTime = Date.now() * 1000000; // in nano sec
+ minTime = (Date.now() - 6 * 60 * 60 * 1000) * 1000000;
+ break;
- case '1day':
- maxTime = Date.now() * 1000000; // in nano sec
- minTime = (Date.now() - 24 * 60 * 60 * 1000) * 1000000;
- break;
+ case '1day':
+ maxTime = Date.now() * 1000000; // in nano sec
+ minTime = (Date.now() - 24 * 60 * 60 * 1000) * 1000000;
+ break;
- case '1week':
- maxTime = Date.now() * 1000000; // in nano sec
- minTime = (Date.now() - 7 * 24 * 60 * 60 * 1000) * 1000000;
- break;
+ case '1week':
+ maxTime = Date.now() * 1000000; // in nano sec
+ minTime = (Date.now() - 7 * 24 * 60 * 60 * 1000) * 1000000;
+ break;
- case 'custom':
- if (datetimeRange !== undefined) {
- maxTime = datetimeRange[1] * 1000000; // in nano sec
- minTime = datetimeRange[0] * 1000000; // in nano sec
- }
- break;
+ case 'custom':
+ if (datetimeRange !== undefined) {
+ maxTime = datetimeRange[1] * 1000000; // in nano sec
+ minTime = datetimeRange[0] * 1000000; // in nano sec
+ }
+ break;
- default:
- console.log('not found matching case');
+ default:
+ // console.log('not found matching case');
}
return {
diff --git a/frontend/src/store/actions/index.ts b/frontend/src/store/actions/index.ts
index 3233216204..977d8b8640 100644
--- a/frontend/src/store/actions/index.ts
+++ b/frontend/src/store/actions/index.ts
@@ -1,3 +1,4 @@
+export * from './dashboard';
export * from './global';
export * from './MetricsActions';
export * from './serviceMap';
diff --git a/frontend/src/store/actions/serviceMap.ts b/frontend/src/store/actions/serviceMap.ts
index ba7c6f46fb..617a91d225 100644
--- a/frontend/src/store/actions/serviceMap.ts
+++ b/frontend/src/store/actions/serviceMap.ts
@@ -1,4 +1,4 @@
-import api, { apiV1 } from 'api';
+import api from 'api';
import { Dispatch } from 'redux';
import { GlobalTime } from './global';
@@ -50,7 +50,7 @@ export const getServiceMapItems = (globalTime: GlobalTime) => {
'&end=' +
globalTime.maxTime;
- const response = await api.get(apiV1 + request_string);
+ const response = await api.get(request_string);
dispatch({
type: ActionTypes.getServiceMapItems,
@@ -69,7 +69,7 @@ export const getDetailedServiceMapItems = (globalTime: GlobalTime) => {
const request_string =
'/services?start=' + globalTime.minTime + '&end=' + globalTime.maxTime;
- const response = await api.get(apiV1 + request_string);
+ const response = await api.get(request_string);
dispatch({
type: ActionTypes.getServices,
diff --git a/frontend/src/store/actions/traces.ts b/frontend/src/store/actions/traces.ts
index 04f57aa411..c2ffef8f6e 100644
--- a/frontend/src/store/actions/traces.ts
+++ b/frontend/src/store/actions/traces.ts
@@ -1,4 +1,4 @@
-import api, { apiV1 } from 'api';
+import api from 'api';
import ROUTES from 'constants/routes';
import { Dispatch } from 'redux';
import { toUTCEpoch } from 'utils/timeUtils';
@@ -120,7 +120,7 @@ export interface FetchTraceItemAction {
}
export const fetchTraces = (globalTime: GlobalTime, filter_params: string) => {
- return async (dispatch: Dispatch) => {
+ return async (dispatch: Dispatch): void => {
if (globalTime) {
const request_string =
'/spans?limit=100&lookback=2d&start=' +
@@ -129,7 +129,7 @@ export const fetchTraces = (globalTime: GlobalTime, filter_params: string) => {
toUTCEpoch(globalTime.maxTime) +
'&' +
filter_params;
- const response = await api.get(apiV1 + request_string);
+ const response = await api.get(request_string);
dispatch({
type: ActionTypes.fetchTraces,
@@ -141,11 +141,9 @@ export const fetchTraces = (globalTime: GlobalTime, filter_params: string) => {
};
export const fetchTraceItem = (traceID: string) => {
- return async (dispatch: Dispatch) => {
+ return async (dispatch: Dispatch): Promise => {
const request_string = ROUTES.TRACES + '/' + traceID;
- const response = await api.get(
- apiV1 + request_string,
- );
+ const response = await api.get(request_string);
dispatch({
type: ActionTypes.fetchTraceItem,
diff --git a/frontend/src/store/actions/types.ts b/frontend/src/store/actions/types.ts
index 1b0ffa0966..639b66b060 100644
--- a/frontend/src/store/actions/types.ts
+++ b/frontend/src/store/actions/types.ts
@@ -1,7 +1,7 @@
import { updateTimeIntervalAction } from './global';
import { serviceMapItemAction, servicesAction } from './serviceMap';
import { updateTraceFiltersAction } from './traceFilters';
-import { FetchTraceItemAction,FetchTracesAction } from './traces';
+import { FetchTraceItemAction, FetchTracesAction } from './traces';
import { getUsageDataAction } from './usage';
export enum ActionTypes {
diff --git a/frontend/src/store/actions/usage.ts b/frontend/src/store/actions/usage.ts
index 57a457b8ba..c93fe9eb9c 100644
--- a/frontend/src/store/actions/usage.ts
+++ b/frontend/src/store/actions/usage.ts
@@ -1,4 +1,4 @@
-import api, { apiV1 } from 'api';
+import api from 'api';
import { Dispatch } from 'redux';
import { toUTCEpoch } from 'utils/timeUtils';
@@ -25,7 +25,7 @@ export const getUsageData = (
maxTime,
)}&step=${step}&service=${service ? service : ''}`;
//Step can only be multiple of 3600
- const response = await api.get(apiV1 + request_string);
+ const response = await api.get(request_string);
dispatch({
type: ActionTypes.getUsageData,
diff --git a/frontend/src/store/index.ts b/frontend/src/store/index.ts
index af77905949..ee3ab8b134 100644
--- a/frontend/src/store/index.ts
+++ b/frontend/src/store/index.ts
@@ -1,10 +1,15 @@
-import { applyMiddleware, compose,createStore } from 'redux';
-import thunk from 'redux-thunk';
+import { applyMiddleware, compose, createStore } from 'redux';
+import thunk, { ThunkMiddleware } from 'redux-thunk';
-import reducers from './reducers';
+import reducers, { AppState } from './reducers';
const composeEnhancers =
(window && (window as any).__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose;
-const store = createStore(reducers, composeEnhancers(applyMiddleware(thunk)));
+
+const store = createStore(
+ reducers,
+ // @TODO Add Type for AppActions also
+ composeEnhancers(applyMiddleware(thunk as ThunkMiddleware)),
+);
export default store;
diff --git a/frontend/src/store/reducers/dashboard.ts b/frontend/src/store/reducers/dashboard.ts
new file mode 100644
index 0000000000..a0a39de747
--- /dev/null
+++ b/frontend/src/store/reducers/dashboard.ts
@@ -0,0 +1,446 @@
+import {
+ APPLY_SETTINGS_TO_PANEL,
+ CREATE_DEFAULT_WIDGET,
+ CREATE_NEW_QUERY,
+ DashboardActions,
+ DELETE_DASHBOARD_SUCCESS,
+ DELETE_WIDGET_SUCCESS,
+ GET_ALL_DASHBOARD_ERROR,
+ GET_ALL_DASHBOARD_LOADING_START,
+ GET_ALL_DASHBOARD_SUCCESS,
+ GET_DASHBOARD_ERROR,
+ GET_DASHBOARD_LOADING_START,
+ GET_DASHBOARD_SUCCESS,
+ IS_ADD_WIDGET,
+ QUERY_ERROR,
+ QUERY_SUCCESS,
+ SAVE_SETTING_TO_PANEL_SUCCESS,
+ TOGGLE_EDIT_MODE,
+ UPDATE_QUERY,
+ UPDATE_TITLE_DESCRIPTION_TAGS_SUCCESS,
+} from 'types/actions/dashboard';
+import InitialValueTypes from 'types/reducer/dashboards';
+
+const InitialValue: InitialValueTypes = {
+ dashboards: [],
+ loading: false,
+ error: false,
+ errorMessage: '',
+ isEditMode: false,
+ isQueryFired: false,
+ isAddWidget: false,
+};
+
+const dashboard = (
+ state = InitialValue,
+ action: DashboardActions,
+): InitialValueTypes => {
+ switch (action.type) {
+ case GET_ALL_DASHBOARD_LOADING_START: {
+ return {
+ ...state,
+ loading: true,
+ };
+ }
+
+ case GET_DASHBOARD_LOADING_START: {
+ return {
+ ...state,
+ loading: true,
+ };
+ }
+
+ case GET_ALL_DASHBOARD_SUCCESS: {
+ return {
+ ...state,
+ loading: false,
+ dashboards: action.payload,
+ };
+ }
+
+ case GET_DASHBOARD_SUCCESS: {
+ const dashboard = action.payload;
+ const { data } = dashboard;
+ return {
+ ...state,
+ loading: false,
+ dashboards: [
+ {
+ ...dashboard,
+ data: {
+ ...data,
+ },
+ },
+ ],
+ };
+ }
+
+ case GET_ALL_DASHBOARD_ERROR: {
+ const { payload } = action;
+
+ return {
+ ...state,
+ loading: false,
+ error: true,
+ errorMessage: payload.errorMessage,
+ };
+ }
+
+ case GET_DASHBOARD_ERROR: {
+ return {
+ ...state,
+ loading: false,
+ errorMessage: action.payload.errorMessage,
+ error: true,
+ };
+ }
+
+ case UPDATE_TITLE_DESCRIPTION_TAGS_SUCCESS: {
+ const [dashboard] = state.dashboards;
+
+ const dashboardData = dashboard.data;
+ const { tags, title, description } = action.payload;
+
+ return {
+ ...state,
+ dashboards: [
+ {
+ created_at: dashboard.created_at,
+ id: dashboard.id,
+ updated_at: dashboard.updated_at,
+ uuid: dashboard.uuid,
+ data: {
+ ...dashboardData,
+ tags,
+ title,
+ description,
+ },
+ },
+ ],
+ };
+ }
+
+ case TOGGLE_EDIT_MODE: {
+ return {
+ ...state,
+ isEditMode: !state.isEditMode,
+ };
+ }
+
+ case DELETE_DASHBOARD_SUCCESS: {
+ return {
+ ...state,
+ dashboards: state.dashboards.filter((e) => e.uuid !== action.payload.uuid),
+ };
+ }
+
+ // NOTE: this action will will be dispatched in the single dashboard only
+ case CREATE_DEFAULT_WIDGET: {
+ const [selectedDashboard] = state.dashboards;
+
+ const data = selectedDashboard.data;
+ const widgets = data.widgets;
+ const defaultWidget = action.payload;
+ const query = action.payload.query;
+
+ const isPresent = widgets?.find((e) => e.id === action.payload.id);
+
+ if (isPresent !== undefined) {
+ return {
+ ...state,
+ };
+ }
+
+ return {
+ ...state,
+ dashboards: [
+ {
+ ...selectedDashboard,
+ data: {
+ ...data,
+ widgets: [
+ ...(widgets || []),
+ {
+ ...defaultWidget,
+ query: query,
+ id: action.payload.id,
+ },
+ ],
+ },
+ },
+ ],
+ };
+ }
+
+ case CREATE_NEW_QUERY: {
+ const [selectedDashboard] = state.dashboards;
+
+ const data = selectedDashboard.data;
+ const widgets = data.widgets;
+ const selectedWidgetId = action.payload.widgetId;
+ const selectedWidgetIndex = data.widgets?.findIndex(
+ (e) => e.id === selectedWidgetId,
+ );
+
+ const preWidget = data.widgets?.slice(0, selectedWidgetIndex);
+ const afterWidget = data.widgets?.slice(
+ (selectedWidgetIndex || 0) + 1, // this is never undefined
+ widgets?.length,
+ );
+
+ const selectedWidget = (data.widgets || [])[selectedWidgetIndex || 0];
+
+ // this condition will never run as there will a widget with this widgetId
+ if (selectedWidget === undefined) {
+ return {
+ ...state,
+ };
+ }
+
+ const newQuery = [...selectedWidget.query, { query: '', legend: '' }];
+
+ return {
+ ...state,
+ dashboards: [
+ {
+ ...selectedDashboard,
+ data: {
+ ...data,
+ widgets: [
+ ...(preWidget || []),
+ {
+ ...selectedWidget,
+ query: newQuery,
+ },
+ ...(afterWidget || []),
+ ],
+ },
+ },
+ ],
+ };
+ }
+
+ case QUERY_ERROR: {
+ const { widgetId, errorMessage } = action.payload;
+
+ const [selectedDashboard] = state.dashboards;
+ const data = selectedDashboard.data;
+
+ const selectedWidgetIndex = data.widgets?.findIndex(
+ (e) => e.id === widgetId,
+ );
+ const widgets = data.widgets;
+
+ const preWidget = data.widgets?.slice(0, selectedWidgetIndex);
+ const afterWidget = data.widgets?.slice(
+ (selectedWidgetIndex || 0) + 1, // this is never undefined
+ widgets?.length,
+ );
+ const selectedWidget =
+ (selectedDashboard.data.widgets || [])[selectedWidgetIndex || 0] || {};
+
+ return {
+ ...state,
+ dashboards: [
+ {
+ ...selectedDashboard,
+ data: {
+ ...data,
+ widgets: [
+ ...(preWidget || []),
+ {
+ ...selectedWidget,
+ queryData: {
+ ...selectedWidget.queryData,
+ error: true,
+ errorMessage,
+ },
+ },
+ ...(afterWidget || []),
+ ],
+ },
+ },
+ ],
+ isQueryFired: true,
+ };
+ }
+
+ case QUERY_SUCCESS: {
+ const { widgetId, data: queryDataResponse } = action.payload;
+ const { dashboards } = state;
+ const [selectedDashboard] = dashboards;
+ const { data } = selectedDashboard;
+ const { widgets = [] } = data;
+
+ const selectedWidgetIndex = widgets.findIndex((e) => e.id === widgetId) || 0;
+
+ const preWidget = widgets?.slice(0, selectedWidgetIndex) || [];
+ const afterWidget =
+ widgets.slice(
+ selectedWidgetIndex + 1, // this is never undefined
+ widgets.length,
+ ) || [];
+ const selectedWidget = widgets[selectedWidgetIndex];
+
+ return {
+ ...state,
+ dashboards: [
+ {
+ ...selectedDashboard,
+ data: {
+ ...data,
+ widgets: [
+ ...preWidget,
+ {
+ ...selectedWidget,
+ queryData: {
+ data: [...queryDataResponse],
+ error: selectedWidget.queryData.error,
+ errorMessage: selectedWidget.queryData.errorMessage,
+ loading: false,
+ },
+ },
+ ...afterWidget,
+ ],
+ },
+ },
+ ],
+ isQueryFired: true,
+ };
+ }
+
+ case APPLY_SETTINGS_TO_PANEL: {
+ const { widgetId } = action.payload;
+
+ const { dashboards } = state;
+ const [selectedDashboard] = dashboards;
+ const { data } = selectedDashboard;
+ const { widgets } = data;
+
+ const selectedWidgetIndex = data.widgets?.findIndex(
+ (e) => e.id === widgetId,
+ );
+
+ const preWidget = data.widgets?.slice(0, selectedWidgetIndex) || [];
+ const afterWidget =
+ data.widgets?.slice(
+ (selectedWidgetIndex || 0) + 1, // this is never undefined
+ widgets?.length,
+ ) || [];
+
+ const selectedWidget = (selectedDashboard.data.widgets || [])[
+ selectedWidgetIndex || 0
+ ];
+
+ return {
+ ...state,
+ dashboards: [
+ {
+ ...selectedDashboard,
+ data: {
+ ...data,
+ widgets: [
+ ...preWidget,
+ {
+ ...selectedWidget,
+ description: action.payload.description,
+ id: action.payload.widgetId,
+ isStacked: action.payload.isStacked,
+ nullZeroValues: action.payload.nullZeroValues,
+ opacity: action.payload.opacity,
+ timePreferance: action.payload.timePreferance,
+ title: action.payload.title,
+ },
+ ...afterWidget,
+ ],
+ },
+ },
+ ],
+ };
+ }
+
+ case SAVE_SETTING_TO_PANEL_SUCCESS: {
+ const selectedDashboard = action.payload;
+ return {
+ ...state,
+ dashboards: [
+ {
+ ...selectedDashboard,
+ },
+ ],
+ };
+ }
+
+ case DELETE_WIDGET_SUCCESS: {
+ const { widgetId } = action.payload;
+
+ const { dashboards } = state;
+ const [selectedDashboard] = dashboards;
+ const { data } = selectedDashboard;
+ const { widgets = [] } = data;
+
+ return {
+ ...state,
+ dashboards: [
+ {
+ ...selectedDashboard,
+ data: {
+ ...data,
+ widgets: widgets.filter((e) => e.id !== widgetId),
+ },
+ },
+ ],
+ };
+ }
+
+ case IS_ADD_WIDGET: {
+ return {
+ ...state,
+ isAddWidget: action.payload.isAddWidget,
+ };
+ }
+
+ case UPDATE_QUERY: {
+ const { query, widgetId } = action.payload;
+ const { dashboards } = state;
+ const [selectedDashboard] = dashboards;
+ const { data } = selectedDashboard;
+ const { widgets = [] } = data;
+
+ const selectedWidgetIndex = widgets.findIndex((e) => e.id === widgetId) || 0;
+
+ const preWidget = widgets?.slice(0, selectedWidgetIndex) || [];
+ const afterWidget =
+ widgets?.slice(
+ selectedWidgetIndex + 1, // this is never undefined
+ widgets.length,
+ ) || [];
+
+ const selectedWidget = widgets[selectedWidgetIndex];
+
+ return {
+ ...state,
+ dashboards: [
+ {
+ ...selectedDashboard,
+ data: {
+ ...data,
+ widgets: [
+ ...preWidget,
+ {
+ ...selectedWidget,
+ query,
+ },
+ ...afterWidget,
+ ],
+ },
+ },
+ ],
+ };
+ }
+ default:
+ return state;
+ }
+};
+
+export default dashboard;
diff --git a/frontend/src/store/reducers/global.ts b/frontend/src/store/reducers/global.ts
index 8b7c286aa5..9e6a8c6fc5 100644
--- a/frontend/src/store/reducers/global.ts
+++ b/frontend/src/store/reducers/global.ts
@@ -9,9 +9,9 @@ export const updateGlobalTimeReducer = (
) => {
// Initial global state is time now and 15 minute interval
switch (action.type) {
- case ActionTypes.updateTimeInterval:
- return action.payload;
- default:
- return state;
+ case ActionTypes.updateTimeInterval:
+ return action.payload;
+ default:
+ return state;
}
};
diff --git a/frontend/src/store/reducers/index.ts b/frontend/src/store/reducers/index.ts
index 4e1525bdd7..76153c0e6d 100644
--- a/frontend/src/store/reducers/index.ts
+++ b/frontend/src/store/reducers/index.ts
@@ -1,31 +1,14 @@
import { combineReducers } from 'redux';
-import {
- GlobalTime,
- serviceMapStore,
- spansWSameTraceIDResponse,
- TraceFilters,
- traceResponseNew,
- usageDataItem,
-} from 'store/actions';
+import dashboardReducer from './dashboard';
import { updateGlobalTimeReducer } from './global';
-import { MetricsInitialState, metricsReducer } from './metrics';
+import { metricsReducer } from './metrics';
import { ServiceMapReducer } from './serviceMap';
import TraceFilterReducer from './traceFilters';
import { traceItemReducer, tracesReducer } from './traces';
import { usageDataReducer } from './usage';
-export interface StoreState {
- metricsData: MetricsInitialState;
- traceFilters: TraceFilters;
- traces: traceResponseNew;
- traceItem: spansWSameTraceIDResponse;
- usageDate: usageDataItem[];
- globalTime: GlobalTime;
- serviceMap: serviceMapStore;
-}
-
-const reducers = combineReducers({
+const reducers = combineReducers({
traceFilters: TraceFilterReducer,
traces: tracesReducer,
traceItem: traceItemReducer,
@@ -33,6 +16,9 @@ const reducers = combineReducers({
globalTime: updateGlobalTimeReducer,
metricsData: metricsReducer,
serviceMap: ServiceMapReducer,
+ dashboards: dashboardReducer,
});
+export type AppState = ReturnType;
+
export default reducers;
diff --git a/frontend/src/store/reducers/metrics.ts b/frontend/src/store/reducers/metrics.ts
index 31ed55f702..130293dd85 100644
--- a/frontend/src/store/reducers/metrics.ts
+++ b/frontend/src/store/reducers/metrics.ts
@@ -19,78 +19,18 @@ export type MetricsInitialState = {
externalMetricsItem?: externalMetricsItem[];
dbOverviewMetricsItem?: dbOverviewMetricsItem[];
customMetricsItem?: customMetricsItem[];
+ loading: boolean;
};
export const metricsInitialState: MetricsInitialState = {
- serviceList: [
- {
- serviceName: '',
- p99: 0,
- avgDuration: 0,
- numCalls: 0,
- callRate: 0,
- numErrors: 0,
- errorRate: 0,
- },
- ],
- metricItems: [
- {
- timestamp: 0,
- p50: 0,
- p95: 0,
- p99: 0,
- numCalls: 0,
- callRate: 0.0,
- numErrors: 0,
- errorRate: 0,
- },
- ],
- topEndpointListItem: [
- {
- p50: 0,
- p95: 0,
- p99: 0,
- numCalls: 0,
- name: '',
- },
- ],
- externalMetricsAvgDurationItem: [
- {
- avgDuration: 0,
- timestamp: 0,
- },
- ],
- externalErrCodeMetricsItem: [
- {
- callRate: 0,
- externalHttpUrl: '',
- numCalls: 0,
- timestamp: 0,
- },
- ],
- externalMetricsItem: [
- {
- avgDuration: 0,
- callRate: 0,
- externalHttpUrl: '',
- numCalls: 0,
- timestamp: 0,
- },
- ],
- dbOverviewMetricsItem: [
- {
- avgDuration: 0,
- callRate: 0,
- dbSystem: '',
- numCalls: 0,
- timestamp: 0,
- },
- ],
- customMetricsItem: [
- {
- timestamp: 0,
- value: 0,
- },
- ],
+ serviceList: [],
+ metricItems: [],
+ topEndpointListItem: [],
+ externalMetricsAvgDurationItem: [],
+ externalErrCodeMetricsItem: [],
+ externalMetricsItem: [],
+ dbOverviewMetricsItem: [],
+ customMetricsItem: [],
+ loading: false,
};
type ActionType = {
@@ -103,50 +43,70 @@ export const metricsReducer = (
action: ActionType,
) => {
switch (action.type) {
- case ActionTypes.getFilteredTraceMetrics:
- return {
- ...state,
- customMetricsItem: action.payload,
- };
- case ActionTypes.getServiceMetrics:
- return {
- ...state,
- metricItems: action.payload,
- };
- case ActionTypes.getDbOverviewMetrics:
- return {
- ...state,
- dbOverviewMetricsItem: action.payload,
- };
- case ActionTypes.getExternalMetrics:
- return {
- ...state,
- externalMetricsItem: action.payload,
- };
- case ActionTypes.getTopEndpoints:
- return {
- ...state,
- topEndpointListItem: action.payload,
- };
- case ActionTypes.getErrCodeMetrics:
- return {
- ...state,
- externalErrCodeMetricsItem: action.payload,
- };
- case ActionTypes.getAvgDurationMetrics:
- return {
- ...state,
- externalMetricsAvgDurationItem: action.payload,
- };
+ case ActionTypes.getFilteredTraceMetrics:
+ return {
+ ...state,
+ customMetricsItem: action.payload,
+ };
+ case ActionTypes.getServiceMetrics:
+ return {
+ ...state,
+ metricItems: action.payload,
+ };
+ case ActionTypes.getDbOverviewMetrics:
+ return {
+ ...state,
+ dbOverviewMetricsItem: action.payload,
+ };
+ case ActionTypes.getExternalMetrics:
+ return {
+ ...state,
+ externalMetricsItem: action.payload,
+ };
+ case ActionTypes.getTopEndpoints:
+ return {
+ ...state,
+ topEndpointListItem: action.payload,
+ };
+ case ActionTypes.getErrCodeMetrics:
+ return {
+ ...state,
+ externalErrCodeMetricsItem: action.payload,
+ };
+ case ActionTypes.getAvgDurationMetrics:
+ return {
+ ...state,
+ externalMetricsAvgDurationItem: action.payload,
+ };
- case ActionTypes.getServicesList:
- return {
- ...state,
- serviceList: action.payload,
- };
- default:
- return {
- ...state,
- };
+ case ActionTypes.getServicesList:
+ return {
+ ...state,
+ serviceList: action.payload,
+ };
+
+ case 'UPDATE_INITIAL_VALUE_START': {
+ return {
+ ...state,
+ loading: true,
+ };
+ }
+
+ case 'UPDATE_INITIAL_VALUE': {
+ return {
+ ...state,
+ dbOverviewMetricsItem: action.payload.dbResponse,
+ topEndpointListItem: action.payload.topEndPointsResponse,
+ externalMetricsAvgDurationItem: action.payload.avgExternalDurationResponse,
+ externalErrCodeMetricsItem: action.payload.externalErrorCodeMetricsResponse,
+ metricItems: action.payload.serviceOverViewResponse,
+ externalMetricsItem: action.payload.externalServiceResponse,
+ loading: false,
+ };
+ }
+ default:
+ return {
+ ...state,
+ };
}
};
diff --git a/frontend/src/store/reducers/serviceMap.ts b/frontend/src/store/reducers/serviceMap.ts
index c0c712adb8..ebb7408069 100644
--- a/frontend/src/store/reducers/serviceMap.ts
+++ b/frontend/src/store/reducers/serviceMap.ts
@@ -7,17 +7,17 @@ const initialState: serviceMapStore = {
export const ServiceMapReducer = (state = initialState, action: Action) => {
switch (action.type) {
- case ActionTypes.getServiceMapItems:
- return {
- ...state,
- items: action.payload,
- };
- case ActionTypes.getServices:
- return {
- ...state,
- services: action.payload,
- };
- default:
- return state;
+ case ActionTypes.getServiceMapItems:
+ return {
+ ...state,
+ items: action.payload,
+ };
+ case ActionTypes.getServices:
+ return {
+ ...state,
+ services: action.payload,
+ };
+ default:
+ return state;
}
};
diff --git a/frontend/src/store/reducers/traceFilters.ts b/frontend/src/store/reducers/traceFilters.ts
index 50279ecb99..b18d031fbe 100644
--- a/frontend/src/store/reducers/traceFilters.ts
+++ b/frontend/src/store/reducers/traceFilters.ts
@@ -14,10 +14,10 @@ const initialState: TraceFilters = {
const TraceFilterReducer = (state = initialState, action: ACTION) => {
switch (action.type) {
- case ActionTypes.updateTraceFilters:
- return action.payload;
- default:
- return state;
+ case ActionTypes.updateTraceFilters:
+ return action.payload;
+ default:
+ return state;
}
};
diff --git a/frontend/src/store/reducers/traces.ts b/frontend/src/store/reducers/traces.ts
index 11c50a6ac6..97c18dd689 100644
--- a/frontend/src/store/reducers/traces.ts
+++ b/frontend/src/store/reducers/traces.ts
@@ -13,10 +13,10 @@ export const tracesReducer = (
action: Action,
) => {
switch (action.type) {
- case ActionTypes.fetchTraces:
- return action.payload;
- default:
- return state;
+ case ActionTypes.fetchTraces:
+ return action.payload;
+ default:
+ return state;
}
};
@@ -25,9 +25,9 @@ export const traceItemReducer = (
action: Action,
) => {
switch (action.type) {
- case ActionTypes.fetchTraceItem:
- return action.payload;
- default:
- return state;
+ case ActionTypes.fetchTraceItem:
+ return action.payload;
+ default:
+ return state;
}
};
diff --git a/frontend/src/store/reducers/usage.ts b/frontend/src/store/reducers/usage.ts
index d19b61fadb..d49be80a40 100644
--- a/frontend/src/store/reducers/usage.ts
+++ b/frontend/src/store/reducers/usage.ts
@@ -5,9 +5,9 @@ export const usageDataReducer = (
action: Action,
) => {
switch (action.type) {
- case ActionTypes.getUsageData:
- return action.payload;
- default:
- return state;
+ case ActionTypes.getUsageData:
+ return action.payload;
+ default:
+ return state;
}
};
diff --git a/frontend/src/types/actions/dashboard.ts b/frontend/src/types/actions/dashboard.ts
new file mode 100644
index 0000000000..965984b232
--- /dev/null
+++ b/frontend/src/types/actions/dashboard.ts
@@ -0,0 +1,180 @@
+import { ApplySettingsToPanelProps } from 'store/actions/dashboard/applySettingsToPanel';
+import { Dashboard, Query, Widgets } from 'types/api/dashboard/getAll';
+import { QueryData } from 'types/api/widgets/getQuery';
+
+export const GET_DASHBOARD = 'GET_DASHBOARD';
+export const UPDATE_DASHBOARD = 'UPDATE_DASHBOARD';
+
+export const GET_ALL_DASHBOARD_LOADING_START =
+ 'GET_ALL_DASHBOARD_LOADING_START';
+export const GET_ALL_DASHBOARD_SUCCESS = 'GET_ALL_DASHBOARD_SUCCESS';
+export const GET_ALL_DASHBOARD_ERROR = 'GET_ALL_DASHBOARD_ERROR';
+
+export const GET_DASHBOARD_LOADING_START = 'GET_DASHBOARD_LOADING_START';
+export const GET_DASHBOARD_SUCCESS = 'GET_DASHBOARD_SUCCESS';
+export const GET_DASHBOARD_ERROR = 'GET_DASHBOARD_ERROR';
+export const UPDATE_TITLE_DESCRIPTION_TAGS_SUCCESS =
+ 'UPDATE_TITLE_DESCRIPTION_TAGS_SUCCESS';
+export const UPDATE_TITLE_DESCRIPTION_TAGS_ERROR =
+ 'UPDATE_TITLE_DESCRIPTION_TAGS_ERROR';
+export const TOGGLE_EDIT_MODE = 'TOGGLE_EDIT_MODE';
+
+export const DELETE_DASHBOARD_SUCCESS = 'DELETE_DASHBOARD_SUCCESS';
+export const DELETE_DASHBOARD_ERROR = 'DELETE_DASHBOARD_ERROR';
+
+export const CREATE_DEFAULT_WIDGET = 'CREATE_DEFAULT_WIDGET';
+
+export const CREATE_NEW_QUERY = 'CREATE_NEW_QUERY';
+export const QUERY_SUCCESS = 'QUERY_SUCCESS';
+export const QUERY_ERROR = 'QUERY_ERROR';
+
+export const UPDATE_QUERY = 'UPDATE_QUERY';
+
+export const APPLY_SETTINGS_TO_PANEL = 'APPLY_SETTINGS_TO_PANEL';
+
+export const SAVE_SETTING_TO_PANEL_SUCCESS = 'SAVE_SETTING_TO_PANEL_SUCCESS';
+export const SAVE_SETTING_TO_PANEL_ERROR = 'SAVE_SETTING_TO_PANEL_ERROR';
+
+export const DELETE_WIDGET_SUCCESS = 'DELETE_WIDGET_SUCCESS';
+export const DELETE_WIDGET_ERROR = 'DELETE_WIDGET_ERROR';
+
+export const IS_ADD_WIDGET = 'IS_ADD_WIDGET';
+
+interface GetDashboard {
+ type: typeof GET_DASHBOARD;
+ payload: Dashboard;
+}
+interface UpdateDashboard {
+ type: typeof UPDATE_DASHBOARD;
+ payload: Dashboard;
+}
+
+interface DeleteDashboardSuccess {
+ type: typeof DELETE_DASHBOARD_SUCCESS;
+ payload: {
+ uuid: Dashboard['uuid'];
+ };
+}
+
+interface DashboardStart {
+ type:
+ | typeof GET_ALL_DASHBOARD_LOADING_START
+ | typeof GET_DASHBOARD_LOADING_START;
+}
+
+interface GetAllDashboardSuccess {
+ type: typeof GET_ALL_DASHBOARD_SUCCESS;
+ payload: Dashboard[];
+}
+
+interface GetDashboardSuccess {
+ type: typeof GET_DASHBOARD_SUCCESS;
+ payload: Dashboard;
+}
+
+interface ApplySettingsToPanel {
+ type: typeof APPLY_SETTINGS_TO_PANEL;
+ payload: ApplySettingsToPanelProps;
+}
+
+interface CreateDefaultWidget {
+ type: typeof CREATE_DEFAULT_WIDGET;
+ payload: Widgets;
+}
+
+interface CreateNewQuery {
+ type: typeof CREATE_NEW_QUERY;
+ payload: {
+ widgetId: string;
+ };
+}
+
+interface IsAddWidget {
+ type: typeof IS_ADD_WIDGET;
+ payload: {
+ isAddWidget: boolean;
+ };
+}
+
+interface DashboardError {
+ type:
+ | typeof GET_ALL_DASHBOARD_ERROR
+ | typeof GET_DASHBOARD_ERROR
+ | typeof UPDATE_TITLE_DESCRIPTION_TAGS_ERROR
+ | typeof DELETE_DASHBOARD_ERROR
+ | typeof SAVE_SETTING_TO_PANEL_ERROR
+ | typeof DELETE_WIDGET_ERROR;
+ payload: {
+ errorMessage: string;
+ };
+}
+
+interface UpdateDashboardTitle {
+ type: typeof UPDATE_TITLE_DESCRIPTION_TAGS_SUCCESS;
+ payload: {
+ title: Dashboard['data']['title'];
+ description: Dashboard['data']['description'];
+ tags: Dashboard['data']['tags'];
+ };
+}
+
+interface ToggleEditMode {
+ type: typeof TOGGLE_EDIT_MODE;
+}
+
+export interface QuerySuccessPayload {
+ widgetId: string;
+ data: { legend: string; queryData: QueryData[]; query: string }[];
+}
+interface QuerySuccess {
+ type: typeof QUERY_SUCCESS;
+ payload: QuerySuccessPayload;
+}
+
+interface UpdateQuery {
+ type: typeof UPDATE_QUERY;
+ payload: {
+ query: Query[];
+ widgetId: string;
+ };
+}
+
+interface QueryError {
+ type: typeof QUERY_ERROR;
+ payload: {
+ errorMessage: string;
+ widgetId: string;
+ };
+}
+
+interface SaveDashboardSuccess {
+ type: typeof SAVE_SETTING_TO_PANEL_SUCCESS;
+ payload: Dashboard;
+}
+
+interface WidgetDeleteSuccess {
+ type: typeof DELETE_WIDGET_SUCCESS;
+ payload: {
+ widgetId: Widgets['id'];
+ };
+}
+
+export type DashboardActions =
+ | GetDashboard
+ | UpdateDashboard
+ | DeleteDashboardSuccess
+ | DashboardError
+ | GetAllDashboardSuccess
+ | DashboardStart
+ | GetDashboardSuccess
+ | UpdateDashboardTitle
+ | ToggleEditMode
+ | CreateDefaultWidget
+ | CreateNewQuery
+ | QuerySuccess
+ | QueryError
+ | ApplySettingsToPanel
+ | SaveDashboardSuccess
+ | WidgetDeleteSuccess
+ | IsAddWidget
+ | UpdateQuery;
diff --git a/frontend/src/types/actions/index.ts b/frontend/src/types/actions/index.ts
new file mode 100644
index 0000000000..db68846802
--- /dev/null
+++ b/frontend/src/types/actions/index.ts
@@ -0,0 +1,5 @@
+import { DashboardActions } from './dashboard';
+
+type AppActions = DashboardActions;
+
+export default AppActions;
diff --git a/frontend/src/types/api/dashboard/create.ts b/frontend/src/types/api/dashboard/create.ts
new file mode 100644
index 0000000000..bd0996a0d6
--- /dev/null
+++ b/frontend/src/types/api/dashboard/create.ts
@@ -0,0 +1,8 @@
+import { Dashboard } from './getAll';
+
+export type Props = {
+ uuid: Dashboard['uuid'];
+ title: Dashboard['data']['title'];
+};
+
+export type PayloadProps = Dashboard;
diff --git a/frontend/src/types/api/dashboard/delete.ts b/frontend/src/types/api/dashboard/delete.ts
new file mode 100644
index 0000000000..78d3253d30
--- /dev/null
+++ b/frontend/src/types/api/dashboard/delete.ts
@@ -0,0 +1,5 @@
+import { Dashboard } from './getAll';
+
+export type Props = {
+ uuid: Dashboard['uuid'];
+};
diff --git a/frontend/src/types/api/dashboard/get.ts b/frontend/src/types/api/dashboard/get.ts
new file mode 100644
index 0000000000..2c440c2f02
--- /dev/null
+++ b/frontend/src/types/api/dashboard/get.ts
@@ -0,0 +1,7 @@
+import { Dashboard } from './getAll';
+
+export type Props = {
+ uuid: Dashboard['uuid'];
+};
+
+export type PayloadProps = Dashboard;
diff --git a/frontend/src/types/api/dashboard/getAll.ts b/frontend/src/types/api/dashboard/getAll.ts
new file mode 100644
index 0000000000..5bdca3f493
--- /dev/null
+++ b/frontend/src/types/api/dashboard/getAll.ts
@@ -0,0 +1,50 @@
+import { GRAPH_TYPES } from 'container/NewDashboard/ComponentsSlider';
+import { timePreferenceType } from 'container/NewWidget/RightContainer/timeItems';
+
+import { QueryData } from '../widgets/getQuery';
+
+export type PayloadProps = Dashboard[];
+
+export interface Dashboard {
+ id: number;
+ uuid: string;
+ created_at: string;
+ updated_at: string;
+ data: DashboardData;
+}
+
+export interface DashboardData {
+ description?: string;
+ tags?: string[];
+ name?: string;
+ widgets?: Widgets[];
+ title: string;
+}
+
+export interface Widgets {
+ isStacked: boolean;
+ id: string;
+ panelTypes: GRAPH_TYPES;
+ title: string;
+ description: string;
+ opacity: string;
+ nullZeroValues: string;
+ timePreferance: timePreferenceType;
+ query: Query[];
+ queryData: {
+ loading: boolean;
+ error: boolean;
+ errorMessage: string;
+ data: {
+ legend?: string;
+ queryData: QueryData[];
+ query: string;
+ }[];
+ };
+ stepSize?: number;
+}
+
+export interface Query {
+ query: string;
+ legend?: string;
+}
diff --git a/frontend/src/types/api/dashboard/update.ts b/frontend/src/types/api/dashboard/update.ts
new file mode 100644
index 0000000000..c58e3b5cd4
--- /dev/null
+++ b/frontend/src/types/api/dashboard/update.ts
@@ -0,0 +1,8 @@
+import { Dashboard, DashboardData } from './getAll';
+
+export type Props = {
+ title: Dashboard['data']['title'];
+ uuid: Dashboard['uuid'];
+} & DashboardData;
+
+export type PayloadProps = Dashboard;
diff --git a/frontend/src/types/api/index.ts b/frontend/src/types/api/index.ts
new file mode 100644
index 0000000000..fbd8db5bf1
--- /dev/null
+++ b/frontend/src/types/api/index.ts
@@ -0,0 +1,15 @@
+import { ErrorStatusCode, SuccessStatusCode } from 'types/common';
+
+export interface ErrorResponse {
+ statusCode: ErrorStatusCode;
+ payload: null;
+ error: string;
+ message: null;
+}
+
+export interface SuccessResponse {
+ statusCode: SuccessStatusCode;
+ message: string;
+ payload: T;
+ error: null;
+}
diff --git a/frontend/src/types/api/widgets/getQuery.ts b/frontend/src/types/api/widgets/getQuery.ts
new file mode 100644
index 0000000000..e6c3a3d504
--- /dev/null
+++ b/frontend/src/types/api/widgets/getQuery.ts
@@ -0,0 +1,19 @@
+export interface PayloadProps {
+ status: 'success' | 'error';
+ result: QueryData[];
+}
+
+export interface QueryData {
+ metric?: {
+ __name__: string;
+ [key: string]: string;
+ };
+ values: [number, string][];
+}
+
+export interface Props {
+ query: string;
+ step: string;
+ start: string;
+ end: string;
+}
diff --git a/frontend/src/types/common/index.ts b/frontend/src/types/common/index.ts
new file mode 100644
index 0000000000..7c5414ffc9
--- /dev/null
+++ b/frontend/src/types/common/index.ts
@@ -0,0 +1,22 @@
+export type Created = 201;
+
+export type Success = 200;
+
+export type Forbidden = 403;
+
+export type Unauthorized = 401;
+
+export type NotFound = 404;
+
+export type ServerError = 500;
+
+export type SuccessStatusCode = Created | Success;
+
+export type ErrorStatusCode =
+ | Forbidden
+ | Forbidden
+ | Unauthorized
+ | NotFound
+ | ServerError;
+
+export type StatusCode = SuccessStatusCode | ErrorStatusCode;
diff --git a/frontend/src/types/reducer/dashboards.ts b/frontend/src/types/reducer/dashboards.ts
new file mode 100644
index 0000000000..8e4871b0a3
--- /dev/null
+++ b/frontend/src/types/reducer/dashboards.ts
@@ -0,0 +1,11 @@
+import { PayloadProps } from 'types/api/dashboard/getAll';
+
+export default interface DashboardReducer {
+ dashboards: PayloadProps;
+ loading: boolean;
+ error: boolean;
+ errorMessage: string;
+ isEditMode: boolean;
+ isQueryFired: boolean;
+ isAddWidget: boolean;
+}
diff --git a/frontend/src/utils/spanToTree.ts b/frontend/src/utils/spanToTree.ts
index eb238da462..e56e9854ea 100644
--- a/frontend/src/utils/spanToTree.ts
+++ b/frontend/src/utils/spanToTree.ts
@@ -1,4 +1,4 @@
-import { pushDStree, RefItem,span } from 'store/actions';
+import { pushDStree, RefItem, span } from 'store/actions';
// PNOTE - should the data be taken from redux or only through props? - Directly as arguments
export const spanToTreeUtil = (spanlist: span[]): pushDStree => {
@@ -102,12 +102,12 @@ export const spanToTreeUtil = (spanlist: span[]): pushDStree => {
//checking for undefined [10] issue
mapped_array[parentID][10].push(push_object);
} else {
- console.log(
- `In SpanTreeUtil: mapped_array[parentID] is undefined, parentID is ${parentID}`,
- );
- console.log(
- `In SpanTreeUtil: mapped_array[parentID] is undefined, mapped_array[parentID] is ${mapped_array[parentID]}`,
- );
+ // console.log(
+ // `In SpanTreeUtil: mapped_array[parentID] is undefined, parentID is ${parentID}`,
+ // );
+ // console.log(
+ // `In SpanTreeUtil: mapped_array[parentID] is undefined, mapped_array[parentID] is ${mapped_array[parentID]}`,
+ // );
}
}
} else {
diff --git a/frontend/tsconfig.json b/frontend/tsconfig.json
index c07f2dcc81..1c644fc0f0 100644
--- a/frontend/tsconfig.json
+++ b/frontend/tsconfig.json
@@ -19,5 +19,7 @@
"noEmit": true,
"baseUrl": "./src",
"downlevelIteration": true
- }
+ },
+ "exclude": ["node_modules"],
+ "include": ["./src", "./cypress"]
}
diff --git a/frontend/webpack.config.js b/frontend/webpack.config.js
index 02965e0be7..095fa21cd7 100644
--- a/frontend/webpack.config.js
+++ b/frontend/webpack.config.js
@@ -28,7 +28,7 @@ module.exports = {
// then it will try to find another open port availble.
port: portFinderSync.getPort(3000),
},
- target: "web",
+ target: 'web',
output: {
filename: ({ chunk: { name, hash } }) => {
return `js/${name}-${hash}.js`;
diff --git a/frontend/yarn.lock b/frontend/yarn.lock
index 349dacbd81..75ff323b17 100644
--- a/frontend/yarn.lock
+++ b/frontend/yarn.lock
@@ -55,6 +55,17 @@
classnames "^2.2.6"
rc-util "^5.9.4"
+"@ant-design/icons@^4.6.3":
+ version "4.6.4"
+ resolved "https://registry.yarnpkg.com/@ant-design/icons/-/icons-4.6.4.tgz#21b037dbb90ee1bb7c632cca057006e57d992fd9"
+ integrity sha512-li02J8ym721E24N3bw1oXRzFDV7m2MYQWs+WtJgVVjhNRv4sc6vL2a2M7SS8rWX3Uc/3GJfrokIJnMrmbIMuXQ==
+ dependencies:
+ "@ant-design/colors" "^6.0.0"
+ "@ant-design/icons-svg" "^4.0.0"
+ "@babel/runtime" "^7.11.2"
+ classnames "^2.2.6"
+ rc-util "^5.9.4"
+
"@ant-design/react-slick@~0.28.1":
version "0.28.3"
resolved "https://registry.yarnpkg.com/@ant-design/react-slick/-/react-slick-0.28.3.tgz#ad5cf1cf50363c1a3842874d69d0ce1f26696e71"
@@ -2003,13 +2014,6 @@
dependencies:
"@babel/types" "^7.3.0"
-"@types/chart.js@^2.9.28":
- version "2.9.33"
- resolved "https://registry.yarnpkg.com/@types/chart.js/-/chart.js-2.9.33.tgz#59c6de80b8134379156f4ba7b96c0928a721c1ab"
- integrity sha512-vB6ZFx1cA91aiCoVpreLQwCQHS/Cj+9YtjBTwFlTjKXyY0douXV2KV4+fluxdI+grDZ6hTCQeg2HY/aQ9NeLHA==
- dependencies:
- moment "^2.10.2"
-
"@types/d3-array@^2":
version "2.12.3"
resolved "https://registry.yarnpkg.com/@types/d3-array/-/d3-array-2.12.3.tgz#8d16d51fb04ad5a5a8ebe14eb8263a579f1efdd1"
@@ -2169,6 +2173,13 @@
resolved "https://registry.yarnpkg.com/@types/d3-timer/-/d3-timer-2.0.1.tgz#ffb6620d290624f3726aa362c0c8a4b44c8d7200"
integrity sha512-TF8aoF5cHcLO7W7403blM7L1T+6NF3XMyN3fxyUolq2uOcFeicG/khQg/dGxiCJWoAcmYulYN7LYSRKO54IXaA==
+"@types/d3-tip@^3.5.5":
+ version "3.5.5"
+ resolved "https://registry.yarnpkg.com/@types/d3-tip/-/d3-tip-3.5.5.tgz#efaf942fa6984ddb8061db1023934598a76cbc8c"
+ integrity sha512-MWt1tlChRfHZtwBh8kIOrJo//TC5cdH5UN+KwcAs4wbFi6wnQJtk/MY4LBr/ZG7b2BQmRNJXu+EMI6NnH6VmxQ==
+ dependencies:
+ "@types/d3" "^3"
+
"@types/d3-transition@^2":
version "2.0.2"
resolved "https://registry.yarnpkg.com/@types/d3-transition/-/d3-transition-2.0.2.tgz#d5ba1c26a3daeb0c5527d573d44b4c5ca9fae027"
@@ -2184,6 +2195,11 @@
"@types/d3-interpolate" "^2"
"@types/d3-selection" "^2"
+"@types/d3@^3":
+ version "3.5.45"
+ resolved "https://registry.yarnpkg.com/@types/d3/-/d3-3.5.45.tgz#cceb1cd8f468b0ed1c96546ddefff3408d7463a7"
+ integrity sha512-wLICfMtjDEoAJie1MF6OuksAzOapRXgJy+l5HQVpyC1yMAlvHz2QKrrasUHru8xD6cbgQNGeO+CeyjOlKtly2A==
+
"@types/d3@^6.2.0":
version "6.7.5"
resolved "https://registry.yarnpkg.com/@types/d3/-/d3-6.7.5.tgz#6ae8034ea21db10fa3e31db1f670c5887d91d8a3"
@@ -2353,10 +2369,10 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.10.tgz#93f4b095af275a0427114579c10ec7aa696729d7"
integrity sha512-09x2d6kNBwjHgyh3jOUE2GE4DFoxDriDvWdu6mFhMP1ysynGYazt4ecZmJlL6/fe4Zi2vtYvTvtL7epjQQrBhA==
-"@types/node@^14.14.7":
- version "14.17.4"
- resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.4.tgz#218712242446fc868d0e007af29a4408c7765bc0"
- integrity sha512-8kQ3+wKGRNN0ghtEn7EGps/B8CzuBz1nXZEIGGLP2GnwbqYn4dbTs7k+VKLTq1HvZLRCIDtN3Snx1Ege8B7L5A==
+"@types/node@^14.17.12":
+ version "14.17.12"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-14.17.12.tgz#7a31f720b85a617e54e42d24c4ace136601656c7"
+ integrity sha512-vhUqgjJR1qxwTWV5Ps5txuy2XMdf7Fw+OrdChRboy8BmWUPkckOhphaohzFG6b8DW7CrxaBMdrdJ47SYFq1okw==
"@types/normalize-package-data@^2.4.0":
version "2.4.0"
@@ -2390,6 +2406,13 @@
dependencies:
"@types/react" "^16"
+"@types/react-grid-layout@^1.1.2":
+ version "1.1.2"
+ resolved "https://registry.yarnpkg.com/@types/react-grid-layout/-/react-grid-layout-1.1.2.tgz#be46ac453e5193f512b0c4c90f36342e9e82258c"
+ integrity sha512-jGpMO5VTXgrCsOoxGHSzfM/9sihlN6GDNyssaMdl73Q7Vtrbe0VVYxoavodommoRXS29hLW/2RLbQ/Oj5++slg==
+ dependencies:
+ "@types/react" "*"
+
"@types/react-redux@^7.1.11", "@types/react-redux@^7.1.16":
version "7.1.16"
resolved "https://registry.yarnpkg.com/@types/react-redux/-/react-redux-7.1.16.tgz#0fbd04c2500c12105494c83d4a3e45c084e3cb21"
@@ -2485,6 +2508,11 @@
dependencies:
"@types/jest" "*"
+"@types/uuid@^8.3.1":
+ version "8.3.1"
+ resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.1.tgz#1a32969cf8f0364b3d8c8af9cc3555b7805df14f"
+ integrity sha512-Y2mHTRAbqfFkpjldbkHGY8JIzRN6XqYRliG8/24FcHm2D2PwW24fl5xMRTVGdrb7iMrwCaIEbLWerGIkXuFWVg==
+
"@types/vis@^4.21.21":
version "4.21.22"
resolved "https://registry.yarnpkg.com/@types/vis/-/vis-4.21.22.tgz#0f15b8825cf4df7a02e66c96516b1d774e241847"
@@ -3037,13 +3065,13 @@ ansi-wrap@0.1.0, ansi-wrap@^0.1.0:
resolved "https://registry.yarnpkg.com/ansi-wrap/-/ansi-wrap-0.1.0.tgz#a82250ddb0015e9a27ca82e82ea603bbfa45efaf"
integrity sha1-qCJQ3bABXponyoLoLqYDu/pF768=
-antd@^4.8.0:
- version "4.16.6"
- resolved "https://registry.yarnpkg.com/antd/-/antd-4.16.6.tgz#5f79fa103bbd8be30fac74142ef1bbf8bc872491"
- integrity sha512-E7T+GClZPGjPUfmiuTbQK4+OfvsQ/Ksi5C71Bm4dwz1wlbJ4CqfxhIlpBypod9fe8mCI+bVAjtBoUpR1q/6Sow==
+antd@^4.16.13:
+ version "4.16.13"
+ resolved "https://registry.yarnpkg.com/antd/-/antd-4.16.13.tgz#e9b9b4a590db28747aae1cab98981649a35880af"
+ integrity sha512-EMPD3fzKe7oayx9keD/GA1oKatcx7j5CGlkJj5eLS0/eEDDEkxVj3DFmKOPuHYt4BK7ltTzMFS+quSTmqUXPiw==
dependencies:
"@ant-design/colors" "^6.0.0"
- "@ant-design/icons" "^4.6.2"
+ "@ant-design/icons" "^4.6.3"
"@ant-design/react-slick" "~0.28.1"
"@babel/runtime" "^7.12.5"
array-tree-filter "^2.1.0"
@@ -3054,17 +3082,17 @@ antd@^4.8.0:
rc-cascader "~1.4.0"
rc-checkbox "~2.3.0"
rc-collapse "~3.1.0"
- rc-dialog "~8.5.1"
+ rc-dialog "~8.6.0"
rc-drawer "~4.3.0"
rc-dropdown "~3.2.0"
rc-field-form "~1.20.0"
- rc-image "~5.2.4"
+ rc-image "~5.2.5"
rc-input-number "~7.1.0"
rc-mentions "~1.6.1"
rc-menu "~9.0.12"
rc-motion "^2.4.0"
rc-notification "~4.5.7"
- rc-pagination "~3.1.6"
+ rc-pagination "~3.1.9"
rc-picker "~2.5.10"
rc-progress "~3.1.0"
rc-rate "~2.9.0"
@@ -3074,16 +3102,15 @@ antd@^4.8.0:
rc-steps "~4.1.0"
rc-switch "~3.2.0"
rc-table "~7.15.1"
- rc-tabs "~11.9.1"
+ rc-tabs "~11.10.0"
rc-textarea "~0.3.0"
rc-tooltip "~5.1.1"
rc-tree "~4.2.1"
rc-tree-select "~4.3.0"
- rc-trigger "^5.2.1"
+ rc-trigger "^5.2.10"
rc-upload "~4.3.0"
rc-util "^5.13.1"
scroll-into-view-if-needed "^2.2.25"
- warning "^4.0.3"
anymatch@^2.0.0:
version "2.0.0"
@@ -4259,28 +4286,15 @@ char-regex@^1.0.2:
resolved "https://registry.yarnpkg.com/char-regex/-/char-regex-1.0.2.tgz#d744358226217f981ed58f479b1d6bcc29545dcf"
integrity sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==
-chart.js@^2.9.4:
- version "2.9.4"
- resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-2.9.4.tgz#0827f9563faffb2dc5c06562f8eb10337d5b9684"
- integrity sha512-B07aAzxcrikjAPyV+01j7BmOpxtQETxTSlQ26BEYJ+3iUkbNKaOJ/nDbT6JjyqYxseM0ON12COHYdU2cTIjC7A==
- dependencies:
- chartjs-color "^2.1.0"
- moment "^2.10.2"
+chart.js@^3.4.0:
+ version "3.5.1"
+ resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.5.1.tgz#73e24d23a4134a70ccdb5e79a917f156b6f3644a"
+ integrity sha512-m5kzt72I1WQ9LILwQC4syla/LD/N413RYv2Dx2nnTkRS9iv/ey1xLTt0DnPc/eWV4zI+BgEgDYBIzbQhZHc/PQ==
-chartjs-color-string@^0.6.0:
- version "0.6.0"
- resolved "https://registry.yarnpkg.com/chartjs-color-string/-/chartjs-color-string-0.6.0.tgz#1df096621c0e70720a64f4135ea171d051402f71"
- integrity sha512-TIB5OKn1hPJvO7JcteW4WY/63v6KwEdt6udfnDE9iCAZgy+V4SrbSxoIbTw/xkUIapjEI4ExGtD0+6D3KyFd7A==
- dependencies:
- color-name "^1.0.0"
-
-chartjs-color@^2.1.0:
- version "2.4.1"
- resolved "https://registry.yarnpkg.com/chartjs-color/-/chartjs-color-2.4.1.tgz#6118bba202fe1ea79dd7f7c0f9da93467296c3b0"
- integrity sha512-haqOg1+Yebys/Ts/9bLo/BqUcONQOdr/hoEr2LLTRl6C5LXctUdHxsCYfvQVg5JIxITrfCNUDr4ntqmQk9+/0w==
- dependencies:
- chartjs-color-string "^0.6.0"
- color-convert "^1.9.3"
+chartjs-adapter-date-fns@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/chartjs-adapter-date-fns/-/chartjs-adapter-date-fns-2.0.0.tgz#5e53b2f660b993698f936f509c86dddf9ed44c6b"
+ integrity sha512-rmZINGLe+9IiiEB0kb57vH3UugAtYw33anRiw5kS2Tu87agpetDDoouquycWc9pRsKtQo5j+vLsYHyr8etAvFw==
check-more-types@^2.24.0:
version "2.24.0"
@@ -4346,7 +4360,7 @@ class-utils@^0.3.5:
isobject "^3.0.0"
static-extend "^0.1.1"
-classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6:
+classnames@2.3.1, classnames@2.x, classnames@^2.2.1, classnames@^2.2.3, classnames@^2.2.5, classnames@^2.2.6:
version "2.3.1"
resolved "https://registry.yarnpkg.com/classnames/-/classnames-2.3.1.tgz#dfcfa3891e306ec1dad105d0e88f4417b8535e8e"
integrity sha512-OlQdbZ7gLfGarSqxesMesDa5uz7KFbID8Kpq/SxIoNGDqY8lSYs0D+hhtBXhcdB3rcbXArFr7vlHheLk1voeNA==
@@ -4498,7 +4512,7 @@ collection-visit@^1.0.0:
map-visit "^1.0.0"
object-visit "^1.0.0"
-color-convert@^1.9.0, color-convert@^1.9.3:
+color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==
@@ -4517,7 +4531,7 @@ color-name@1.1.3:
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25"
integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=
-color-name@^1.0.0, color-name@~1.1.4:
+color-name@~1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2"
integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==
@@ -6243,6 +6257,11 @@ escodegen@^2.0.0:
optionalDependencies:
source-map "~0.6.1"
+eslint-config-prettier@^8.3.0:
+ version "8.3.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.3.0.tgz#f7471b20b6fe8a9a9254cc684454202886a2dd7a"
+ integrity sha512-BgZuLUSeKzvlL/VUjx/Yb787VQ26RU3gGjA3iiFvdsp/2bMfVIWUVP7tjxtjS0e+HP409cPlPvNkQloz8C91ew==
+
eslint-config-react-app@^6.0.0:
version "6.0.0"
resolved "https://registry.yarnpkg.com/eslint-config-react-app/-/eslint-config-react-app-6.0.0.tgz#ccff9fc8e36b322902844cbd79197982be355a0e"
@@ -6344,6 +6363,13 @@ eslint-plugin-node@^11.1.0:
resolve "^1.10.1"
semver "^6.1.0"
+eslint-plugin-prettier@^4.0.0:
+ version "4.0.0"
+ resolved "https://registry.yarnpkg.com/eslint-plugin-prettier/-/eslint-plugin-prettier-4.0.0.tgz#8b99d1e4b8b24a762472b4567992023619cb98e0"
+ integrity sha512-98MqmCJ7vJodoQK359bqQWaxOE0CS8paAz/GgjaZLyex4TTk3g9HugoO89EqWCrFiOqn9EVvcoo7gZzONCWVwQ==
+ dependencies:
+ prettier-linter-helpers "^1.0.0"
+
eslint-plugin-promise@^5.1.0:
version "5.1.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-promise/-/eslint-plugin-promise-5.1.0.tgz#fb2188fb734e4557993733b41aa1a688f46c6f24"
@@ -6771,6 +6797,11 @@ fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3:
resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525"
integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==
+fast-diff@^1.1.2:
+ version "1.2.0"
+ resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.2.0.tgz#73ee11982d86caaf7959828d519cfe927fac5f03"
+ integrity sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==
+
fast-glob@^3.1.1, fast-glob@^3.2.4:
version "3.2.6"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.6.tgz#434dd9529845176ea049acc9343e8282765c6e1a"
@@ -7627,7 +7658,7 @@ he@^1.2.0:
resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f"
integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==
-history@^4.9.0:
+history@4.10.1, history@^4.9.0:
version "4.10.1"
resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3"
integrity sha512-36nwAD620w12kuzPAsyINPWJqlNbij+hpK1k9XRloDtym8mxzGYl2c17LnV6IAGB2Dmg4tEa7G7DlawS0+qjew==
@@ -9483,6 +9514,11 @@ lodash.flatten@^4.2.0:
resolved "https://registry.yarnpkg.com/lodash.flatten/-/lodash.flatten-4.4.0.tgz#f31c22225a9632d2bbf8e4addbef240aa765a61f"
integrity sha1-8xwiIlqWMtK7+OSt2+8kCqdlph8=
+lodash.isequal@^4.0.0:
+ version "4.5.0"
+ resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0"
+ integrity sha1-QVxEePK8wwEgwizhDtMib30+GOA=
+
lodash.merge@^4.4.0, lodash.merge@^4.6.2:
version "4.6.2"
resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a"
@@ -9869,7 +9905,7 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
-moment@>=2.13.0, moment@^2.10.2, moment@^2.24.0, moment@^2.25.3:
+moment@>=2.13.0, moment@^2.24.0, moment@^2.25.3:
version "2.29.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
@@ -11249,6 +11285,13 @@ present@0.0.6:
resolved "https://registry.yarnpkg.com/present/-/present-0.0.6.tgz#9eeff700daa9e998613352e47f7ac2324d4faf02"
integrity sha1-nu/3ANqp6ZhhM1Lkf3rCMk1PrwI=
+prettier-linter-helpers@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz#d23d41fe1375646de2d0104d3454a3008802cf7b"
+ integrity sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==
+ dependencies:
+ fast-diff "^1.1.2"
+
prettier@2.2.1:
version "2.2.1"
resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.2.1.tgz#795a1a78dd52f073da0cd42b21f9c91381923ff5"
@@ -11352,7 +11395,7 @@ prompts@^2.0.1:
kleur "^3.0.3"
sisteransi "^1.0.5"
-prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7, prop-types@^15.7.2:
+prop-types@15.x, prop-types@^15.0.0, prop-types@^15.5.10, prop-types@^15.5.8, prop-types@^15.6.0, prop-types@^15.6.1, prop-types@^15.6.2, prop-types@^15.7, prop-types@^15.7.2:
version "15.7.2"
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.7.2.tgz#52c41e75b8c87e72b9d9360e0206b99dcbffa6c5"
integrity sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==
@@ -11551,10 +11594,10 @@ rc-collapse@~3.1.0:
rc-util "^5.2.1"
shallowequal "^1.1.0"
-rc-dialog@~8.5.0, rc-dialog@~8.5.1:
- version "8.5.2"
- resolved "https://registry.yarnpkg.com/rc-dialog/-/rc-dialog-8.5.2.tgz#530e289c25a31c15c85a0e8a4ba3f33414bff418"
- integrity sha512-3n4taFcjqhTE9uNuzjB+nPDeqgRBTEGBfe46mb1e7r88DgDo0lL4NnxY/PZ6PJKd2tsCt+RrgF/+YeTvJ/Thsw==
+rc-dialog@~8.6.0:
+ version "8.6.0"
+ resolved "https://registry.yarnpkg.com/rc-dialog/-/rc-dialog-8.6.0.tgz#3b228dac085de5eed8c6237f31162104687442e7"
+ integrity sha512-GSbkfqjqxpZC5/zc+8H332+q5l/DKUhpQr0vdX2uDsxo5K0PhvaMEVjyoJUTkZ3+JstEADQji1PVLVb/2bJeOQ==
dependencies:
"@babel/runtime" "^7.10.1"
classnames "^2.2.6"
@@ -11588,14 +11631,14 @@ rc-field-form@~1.20.0:
async-validator "^3.0.3"
rc-util "^5.8.0"
-rc-image@~5.2.4:
- version "5.2.4"
- resolved "https://registry.yarnpkg.com/rc-image/-/rc-image-5.2.4.tgz#ff1059f937bde6ca918c6f1beb316beba911f255"
- integrity sha512-kWOjhZC1OoGKfvWqtDoO9r8WUNswBwnjcstI6rf7HMudz0usmbGvewcWqsOhyaBRJL9+I4eeG+xiAoxV1xi75Q==
+rc-image@~5.2.5:
+ version "5.2.5"
+ resolved "https://registry.yarnpkg.com/rc-image/-/rc-image-5.2.5.tgz#44e6ffc842626827960e7ab72e1c0d6f3a8ce440"
+ integrity sha512-qUfZjYIODxO0c8a8P5GeuclYXZjzW4hV/5hyo27XqSFo1DmTCs2HkVeQObkcIk5kNsJtgsj1KoPThVsSc/PXOw==
dependencies:
"@babel/runtime" "^7.11.2"
classnames "^2.2.6"
- rc-dialog "~8.5.0"
+ rc-dialog "~8.6.0"
rc-util "^5.0.6"
rc-input-number@~7.1.0:
@@ -11661,10 +11704,10 @@ rc-overflow@^1.0.0, rc-overflow@^1.2.0:
rc-resize-observer "^1.0.0"
rc-util "^5.5.1"
-rc-pagination@~3.1.6:
- version "3.1.7"
- resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-3.1.7.tgz#13ba071a7fcb0c79896076806f3944653e7bf29e"
- integrity sha512-sl0HGVhv6AsMzA5H3q7cBQcbAGj/sFjoiDSLvq3+/4IjihPqScZnSSiqR4Wu9G8RLgNjrBnGrSdTGO2Kyrt3IA==
+rc-pagination@~3.1.9:
+ version "3.1.9"
+ resolved "https://registry.yarnpkg.com/rc-pagination/-/rc-pagination-3.1.9.tgz#797ad75d85b1ef7a82801207ead410110337fdd6"
+ integrity sha512-IKBKaJ4icVPeEk9qRHrFBJmHxBUrCp3+nENBYob4Ofqsu3RXjBOy4N36zONO7oubgLyiG3PxVmyAuVlTkoc7Jg==
dependencies:
"@babel/runtime" "^7.10.1"
classnames "^2.2.1"
@@ -11763,10 +11806,10 @@ rc-table@~7.15.1:
rc-util "^5.13.0"
shallowequal "^1.1.0"
-rc-tabs@~11.9.1:
- version "11.9.1"
- resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-11.9.1.tgz#5b2e74da9a276978c2172ef9a05ae8af14da74cb"
- integrity sha512-CLNx3qaWnO8KBWPd+7r52Pfk0MoPyKtlr+2ltWq2I9iqAjd1nZu6iBpQP7wbWBwIomyeFNw/WjHdRN7VcX5Qtw==
+rc-tabs@~11.10.0:
+ version "11.10.1"
+ resolved "https://registry.yarnpkg.com/rc-tabs/-/rc-tabs-11.10.1.tgz#7b112f78bac998480c777ae160adc425e3fdb7cb"
+ integrity sha512-ey1i2uMyfnRNYbViLcUYGH+Y7hueJbdCVSLaXnXki9hxBcGqxJMPy9t5xR0n/3QFQspj7Tf6+2VTXVtmO7Yaug==
dependencies:
"@babel/runtime" "^7.11.2"
classnames "2.x"
@@ -11815,7 +11858,7 @@ rc-tree@^4.0.0, rc-tree@~4.2.1:
rc-util "^5.0.0"
rc-virtual-list "^3.0.1"
-rc-trigger@^5.0.0, rc-trigger@^5.0.4, rc-trigger@^5.1.2, rc-trigger@^5.2.1:
+rc-trigger@^5.0.0, rc-trigger@^5.0.4, rc-trigger@^5.1.2:
version "5.2.9"
resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-5.2.9.tgz#795a787d2b038347dcde27b89a4a5cec8fc40f3e"
integrity sha512-0Bxsh2Xe+etejMn73am+jZBcOpsueAZiEKLiGoDfA0fvm/JHLNOiiww3zJ0qgyPOTmbYxhsxFcGOZu+VcbaZhQ==
@@ -11826,6 +11869,17 @@ rc-trigger@^5.0.0, rc-trigger@^5.0.4, rc-trigger@^5.1.2, rc-trigger@^5.2.1:
rc-motion "^2.0.0"
rc-util "^5.5.0"
+rc-trigger@^5.2.10:
+ version "5.2.10"
+ resolved "https://registry.yarnpkg.com/rc-trigger/-/rc-trigger-5.2.10.tgz#8a0057a940b1b9027eaa33beec8a6ecd85cce2b1"
+ integrity sha512-FkUf4H9BOFDaIwu42fvRycXMAvkttph9AlbCZXssZDVzz2L+QZ0ERvfB/4nX3ZFPh1Zd+uVGr1DEDeXxq4J1TA==
+ dependencies:
+ "@babel/runtime" "^7.11.2"
+ classnames "^2.2.6"
+ rc-align "^4.0.0"
+ rc-motion "^2.0.0"
+ rc-util "^5.5.0"
+
rc-upload@~4.3.0:
version "4.3.1"
resolved "https://registry.yarnpkg.com/rc-upload/-/rc-upload-4.3.1.tgz#d6ee66b8bd1e1dd2f78526c486538423f7e7ed84"
@@ -11883,14 +11937,6 @@ react-autowhatever@^10.1.2:
react-themeable "^1.1.0"
section-iterator "^2.0.0"
-react-chartjs-2@^2.11.1:
- version "2.11.2"
- resolved "https://registry.yarnpkg.com/react-chartjs-2/-/react-chartjs-2-2.11.2.tgz#156c0d2618600561efc23bef278bd48a335cadb6"
- integrity sha512-hcPS9vmRJeAALPPf0uo02BiD8BDm0HNmneJYTZVR74UKprXOpql+Jy1rVuj93rKw0Jfx77mkcRfXPxTe5K83uw==
- dependencies:
- lodash "^4.17.19"
- prop-types "^15.7.2"
-
react-chips@^0.8.0:
version "0.8.0"
resolved "https://registry.yarnpkg.com/react-chips/-/react-chips-0.8.0.tgz#fc50c9fb469983989b356cf4595b86097ebacc25"
@@ -11944,6 +11990,14 @@ react-dom@17.0.0:
object-assign "^4.1.1"
scheduler "^0.20.0"
+react-draggable@^4.0.0, react-draggable@^4.0.3:
+ version "4.4.3"
+ resolved "https://registry.yarnpkg.com/react-draggable/-/react-draggable-4.4.3.tgz#0727f2cae5813e36b0e4962bf11b2f9ef2b406f3"
+ integrity sha512-jV4TE59MBuWm7gb6Ns3Q1mxX8Azffb7oTtDtBgFkxRvhDp38YAARmRplrj0+XGkhOJB5XziArX+4HUUABtyZ0w==
+ dependencies:
+ classnames "^2.2.5"
+ prop-types "^15.6.0"
+
react-error-overlay@^6.0.9:
version "6.0.9"
resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.9.tgz#3c743010c9359608c375ecd6bc76f35d93995b0a"
@@ -11972,6 +12026,17 @@ react-graph-vis@^1.0.5:
vis-data "^7.1.2"
vis-network "^9.0.0"
+react-grid-layout@^1.2.5:
+ version "1.2.5"
+ resolved "https://registry.yarnpkg.com/react-grid-layout/-/react-grid-layout-1.2.5.tgz#fa40288d5a1fa783484c44ce78b1e10eb5313d26"
+ integrity sha512-P/NNWAExTX/zEq+RUh6hrIG67UBicDNCOOg9LZe8BAtSdYtCnCGgVmWBS+sIbM0C8RJIiyGsFHh5dIfCddhS/w==
+ dependencies:
+ classnames "2.3.1"
+ lodash.isequal "^4.0.0"
+ prop-types "^15.0.0"
+ react-draggable "^4.0.0"
+ react-resizable "^3.0.1"
+
react-hot-loader@^4.13.0:
version "4.13.0"
resolved "https://registry.yarnpkg.com/react-hot-loader/-/react-hot-loader-4.13.0.tgz#c27e9408581c2a678f5316e69c061b226dc6a202"
@@ -12045,6 +12110,14 @@ react-refresh@^0.8.3:
resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.8.3.tgz#721d4657672d400c5e3c75d063c4a85fb2d5d68f"
integrity sha512-X8jZHc7nCMjaCqoU+V2I0cOhNW+QMBwSUkeXnTi8IPe6zaRWfn60ZzvFDZqWPfmSJfjub7dDW1SP0jaHWLu/hg==
+react-resizable@^3.0.1:
+ version "3.0.4"
+ resolved "https://registry.yarnpkg.com/react-resizable/-/react-resizable-3.0.4.tgz#aa20108eff28c52c6fddaa49abfbef8abf5e581b"
+ integrity sha512-StnwmiESiamNzdRHbSSvA65b0ZQJ7eVQpPusrSmcpyGKzC0gojhtO62xxH6YOBmepk9dQTBi9yxidL3W4s3EBA==
+ dependencies:
+ prop-types "15.x"
+ react-draggable "^4.0.3"
+
react-router-dom@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-5.2.0.tgz#9e65a4d0c45e13289e66c7b17c7e175d0ea15662"
@@ -14238,7 +14311,7 @@ uuid@^3.3.2, uuid@^3.4.0:
resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee"
integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==
-uuid@^8.3.0:
+uuid@^8.3.0, uuid@^8.3.2:
version "8.3.2"
resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2"
integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==