+
+
{
+ adjustTimeRange("backward");
+ }}
+ attachedSide={'r'}
+ emptySide={'l'}
+ className={"date-time-selector"}
+ >
+
+
+
+
+
+
: ""}
>
@@ -241,6 +376,41 @@ export function DateRangePickerMain(props) {
+
+
+
+
+
+
{
+ adjustTimeRange("forward");
+ }}
+ attachedSide={'l'}
+ className={"date-time-selector"}
+ >
+
+
{rangeOpen ? (
diff --git a/src/components/StatusBar/components/timepickerbutton/actions/setTimePickerOpen.js b/src/components/StatusBar/components/timepickerbutton/actions/setTimePickerOpen.ts
similarity index 60%
rename from src/components/StatusBar/components/timepickerbutton/actions/setTimePickerOpen.js
rename to src/components/StatusBar/components/timepickerbutton/actions/setTimePickerOpen.ts
index ef661528..1bc374a4 100644
--- a/src/components/StatusBar/components/timepickerbutton/actions/setTimePickerOpen.js
+++ b/src/components/StatusBar/components/timepickerbutton/actions/setTimePickerOpen.ts
@@ -1,4 +1,4 @@
-const setTimePickerOpen = (timePickerOpen) => (dispatch) => {
+const setTimePickerOpen = (timePickerOpen: any) => (dispatch: Function) => {
dispatch({
type: 'SET_TIME_PICKER_OPEN',
timePickerOpen
diff --git a/src/components/StatusBar/styled/index.js b/src/components/StatusBar/styled/index.js
index 6ae18770..a619c967 100644
--- a/src/components/StatusBar/styled/index.js
+++ b/src/components/StatusBar/styled/index.js
@@ -135,11 +135,22 @@ export const DatePickerButton = styled(BtnSmall)`
background: ${(props) => props.theme.buttonDefault};
border: 1px solid ${(props) => props.theme.buttonBorder};
color: ${(props) => props.theme.textColor};
+ border-top-left-radius: ${(props) => props.attachedSide === 'l' || props.attachedSide === 'both' ? '0' : ''};
+ border-top-right-radius: ${(props) => props.attachedSide === 'r' || props.attachedSide === 'both' ? '0' : ''};
+ border-bottom-left-radius: ${(props) => props.attachedSide === 'l' || props.attachedSide === 'both' ? '0' : ''};
+ border-bottom-right-radius: ${(props) => props.attachedSide === 'r' || props.attachedSide === 'both' ? '0' : ''};
+ border-right: ${(props) => props.attachedSide === 'r' || props.attachedSide === 'both' ? 'unset' : ''};
height: 26px;
- margin-left: 10px;
+ margin-left: ${(props) => props.emptySide === 'l' || props.emptySide === 'both' ? '10px' : ''};
+ margin-right: ${(props) => props.emptySide === 'r' || props.emptySide === 'both' ? '10px' : ''};
+ padding: ${(props) => props.size === 'small' ? '3px 5px' : ''};
span {
margin-left: 5px;
}
+ svg {
+ margin: 0;
+ padding: 0;
+ }
&:hover {
color: orange;
}
diff --git a/src/components/TraceSearch/helpers.js b/src/components/TraceSearch/helpers.ts
similarity index 85%
rename from src/components/TraceSearch/helpers.js
rename to src/components/TraceSearch/helpers.ts
index 15bdabb4..1e489ce3 100644
--- a/src/components/TraceSearch/helpers.js
+++ b/src/components/TraceSearch/helpers.ts
@@ -1,4 +1,4 @@
-export function getHeaders(dataSource) {
+export function getHeaders(dataSource: any) {
const options = {
method: "GET",
headers: { "Content-Type": "application/json" },
@@ -6,9 +6,9 @@ export function getHeaders(dataSource) {
const basicAuth = dataSource?.auth?.basicAuth.value;
- let reqHeaders = {};
+ let reqHeaders: any = {};
- let auth = {};
+ let auth: any = {};
if (basicAuth) {
const authfields = dataSource?.auth?.fields?.basicAuth;
diff --git a/src/components/TraceSearch/tracesSearchUrl.js b/src/components/TraceSearch/tracesSearchUrl.ts
similarity index 94%
rename from src/components/TraceSearch/tracesSearchUrl.js
rename to src/components/TraceSearch/tracesSearchUrl.ts
index 5d4aa025..b9edc701 100644
--- a/src/components/TraceSearch/tracesSearchUrl.js
+++ b/src/components/TraceSearch/tracesSearchUrl.ts
@@ -1,4 +1,4 @@
-export function formatUrl(state) {
+export function formatUrl(state: any) {
const { searchName, name, minDuration, maxDuration, tags, limit } = state;
let sn = "";
diff --git a/src/components/TraceSearch/useTraceNames.js b/src/components/TraceSearch/useTraceNames.ts
similarity index 88%
rename from src/components/TraceSearch/useTraceNames.js
rename to src/components/TraceSearch/useTraceNames.ts
index 19c6552f..8e33d9f3 100644
--- a/src/components/TraceSearch/useTraceNames.js
+++ b/src/components/TraceSearch/useTraceNames.ts
@@ -3,15 +3,15 @@ import { useEffect, useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { getHeaders } from "./helpers";
-export function useTraceNames({ id }) {
- const dataSources = useSelector((store) => store.dataSources);
+export function useTraceNames({ id }: any) {
+ const dataSources = useSelector(({ dataSources }: any) => dataSources);
const [traceNames, settraceNames] = useState(
{ data: { tagValues: [] } } || {}
);
const dataSource = useMemo(() => {
- return dataSources.find((f) => f.id === id);
+ return dataSources.find((f: any) => f.id === id);
}, [dataSources, id]);
// get the auth headers in here \
diff --git a/src/components/TraceSearch/useTraceServiceName.js b/src/components/TraceSearch/useTraceServiceName.ts
similarity index 81%
rename from src/components/TraceSearch/useTraceServiceName.js
rename to src/components/TraceSearch/useTraceServiceName.ts
index 91293c8a..3f5f9196 100644
--- a/src/components/TraceSearch/useTraceServiceName.js
+++ b/src/components/TraceSearch/useTraceServiceName.ts
@@ -3,13 +3,13 @@ import { useEffect, useMemo, useState } from "react";
import { useSelector } from "react-redux";
import { getHeaders } from "./helpers";
-export function useTraceServiceName({ id }) {
- const dataSources = useSelector((store) => store.dataSources);
+export function useTraceServiceName({ id }: any) {
+ const dataSources = useSelector(({ dataSources }: any) => dataSources);
const [serviceNames, setserviceNames] = useState(
{ data: { tagValues: [] } } || {}
);
const dataSource = useMemo(() => {
- return dataSources.find((f) => f.id === id);
+ return dataSources.find((f: any) => f.id === id);
}, [dataSources, id]);
useEffect(() => {
@@ -35,9 +35,9 @@ export function useTraceServiceName({ id }) {
}, []);
return useMemo(() => {
- if (serviceNames?.["data"]?.["tagValues"]) {
+ if (serviceNames?.data?.tagValues) {
return [{ name: "Select Service Name", value: "" }].concat(
- serviceNames["data"]["tagValues"].map((m) => ({
+ serviceNames.data.tagValues.map((m) => ({
name: m,
value: m,
}))
diff --git a/src/components/TraceSearch/useTraceTags.js b/src/components/TraceSearch/useTraceTags.js
deleted file mode 100644
index e69de29b..00000000
diff --git a/src/components/styles/index.js b/src/components/styles.ts
similarity index 74%
rename from src/components/styles/index.js
rename to src/components/styles.ts
index 1f81093e..9b2f19a6 100644
--- a/src/components/styles/index.js
+++ b/src/components/styles.ts
@@ -1,51 +1,51 @@
-import styled from "@emotion/styled";
-
-export const MainViewStyled = styled.div`
- padding-top: 5px;
- height: 100%;
- width: 100%;
- display: flex;
- flex:1;
- flex-direction: column;
- background-color: ${(props) => props.theme.mainBgColor} !important;
- &::-webkit-scrollbar-corner {
- background: transparent;
- }
- &::-webkit-scrollbar-thumb {
- border-radius: 5px;
- background: ${(props) => props.theme.scrollbarThumb} !important;
- }
-`;
-
-export const InputGroup = styled.div`
- display: flex;
- align-items:center;
-`;
-export const InlineGroup = styled.div`
- display: flex;
- align-items: center;
-`;
-
-export const SettingCont = styled.div`
- display: flex;
- flex: 1;
- flex-direction: column;
-
-
- background: ${({ theme }) => theme.widgetContainer};
-`;
-
-export const SettingsInputContainer = styled.div`
- margin: 20px;
- display: flex;
- flex-direction: column;
- flex: 1;
-`;
-
-
-export const SettingLabel = styled.label`
- font-size: 12px;
- color: ${({ theme }) => theme.textColor};
- margin-left: 10px;
-`;
-
+import styled from "@emotion/styled";
+
+export const MainViewStyled = styled.div`
+ padding-top: 5px;
+ height: 100%;
+ width: 100%;
+ display: flex;
+ flex:1;
+ flex-direction: column;
+ background-color: ${({theme}: any) => theme.mainBgColor} !important;
+ &::-webkit-scrollbar-corner {
+ background: transparent;
+ }
+ &::-webkit-scrollbar-thumb {
+ border-radius: 5px;
+ background: ${({theme}: any) => theme.scrollbarThumb} !important;
+ }
+`;
+
+export const InputGroup = styled.div`
+ display: flex;
+ align-items:center;
+`;
+export const InlineGroup = styled.div`
+ display: flex;
+ align-items: center;
+`;
+
+export const SettingCont = styled.div`
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+
+
+ background: ${({ theme }: any) => theme.widgetContainer};
+`;
+
+export const SettingsInputContainer = styled.div`
+ margin: 20px;
+ display: flex;
+ flex-direction: column;
+ flex: 1;
+`;
+
+
+export const SettingLabel = styled.label`
+ font-size: 12px;
+ color: ${({ theme }: any) => theme.textColor};
+ margin-left: 10px;
+`;
+
diff --git a/src/helpers/UpdateStateFromQueryParams.js b/src/helpers/UpdateStateFromQueryParams.ts
similarity index 84%
rename from src/helpers/UpdateStateFromQueryParams.js
rename to src/helpers/UpdateStateFromQueryParams.ts
index a0f583aa..1db4a002 100644
--- a/src/helpers/UpdateStateFromQueryParams.js
+++ b/src/helpers/UpdateStateFromQueryParams.ts
@@ -1,232 +1,232 @@
-import * as moment from "moment";
-import { useEffect, useMemo, useState } from "react";
-import { useDispatch, useSelector } from "react-redux";
-import { useLocation } from "react-router-dom";
-
-import {
- setIsSubmit,
- setQueryTime,
- setQueryStep,
- setStartTime,
- setStopTime,
- setTheme,
- setAutoTheme
-} from "../actions";
-
-import setFromTime from "../actions/setFromTime";
-import setIsEmbed from "../actions/setIsEmbed";
-import { setLeftPanel } from "../actions/setLeftPanel";
-import { setRightPanel } from "../actions/setRightPanel";
-import setToTime from "../actions/setToTime";
-import { setUrlLocation } from "../actions/setUrlLocation";
-import { setUrlQueryParams } from "../actions/setUrlQueryParams";
-import { setSplitView } from "../components/StatusBar/components/SplitViewButton/setSplitView";
-import { environment } from "../environment/env.dev";
-
-
-export const STRING_VALUES = ["step", "theme", "time"];
-export const ARRAY_VALUES = ["left", "right"];
-
-export const TIME_VALUES = ["start", "stop"];
-
-export const BOOLEAN_VALUES = ["isSubmit", "isSplit", "autoTheme", "isEmbed"];
-
-export function UpdateStateFromQueryParams() {
- const isLightTheme = useMemo(() => {
- return window.matchMedia("(prefers-color-scheme: light)").matches;
- }, []);
-
- const dispatch = useDispatch();
- const urlQueryParams = useSelector((store) => store.urlQueryParams);
- const start = useSelector((store) => store.start);
- const stop = useSelector((store) => store.stop);
- const from = useSelector((store) => store.from);
- const to = useSelector((store) => store.to);
- const step = useSelector((store) => store.step);
- const isSubmit = useSelector((store) => store.isSubmit);
- const isEmbed = useSelector((store) => store.isEmbed);
- const time = useSelector((store) => store.time);
- const left = useSelector((store) => store.left);
- const right = useSelector((store) => store.right);
- const theme = useSelector((store) => store.theme);
- const autoTheme = useSelector((store) => store.autoTheme);
- const isSplit = useSelector((store) => store.isSplit);
- const [themeSet, setThemeSet] = useState(isLightTheme ? "light" : theme);
-
- useEffect(() => {
- setThemeSet(theme);
- }, [theme]);
- const STORE_KEYS = {
- start,
- step,
- stop,
- from,
- to,
- time,
- isSubmit,
- isEmbed,
- theme,
- autoTheme,
- left,
- right,
- isSplit,
- };
-
- const STORE_ACTIONS = {
- start: setStartTime,
- step: setQueryStep,
- stop: setStopTime,
- from: setFromTime,
- to: setToTime,
- time: setQueryTime,
- isSubmit: setIsSubmit,
- isEmbed: setIsEmbed,
- theme: setTheme,
- left: setLeftPanel,
- right: setRightPanel,
- isSplit: setSplitView,
- autoTheme: setAutoTheme
- };
-
- const encodeTs = (ts) => {
- return ts?.getTime() + "000000";
- };
-
- const { hash } = useLocation();
- useEffect(() => {
- const urlFromHash = new URLSearchParams(hash.replace("#", ""));
- // !if there is some params set them first on UI
-
- if (hash.length > 0) {
- const startParams = urlQueryParams;
-
- for (let [key, value] of urlFromHash.entries()) {
- startParams[key] = value;
- }
-
- if (Object.keys(startParams).length > 0) {
- dispatch(setUrlQueryParams({ ...urlQueryParams, startParams }));
-
- dispatch(setUrlLocation(hash));
-
- Object.keys(startParams).forEach((param) => {
- if (
- STRING_VALUES.includes(param) &&
- startParams[param] !== ""
- ) {
- dispatch(STORE_ACTIONS[param](startParams[param]));
- } else if (param === "theme") {
- dispatch(STORE_ACTIONS[param](themeSet));
- } else if (
- TIME_VALUES.includes(param) &&
- startParams[param] !== ""
- ) {
- const croppedTime = startParams[param] / 1000000;
- const paramDate = new Date(
- moment(croppedTime).format(
- "YYYY-MM-DDTHH:mm:ss.SSSZ"
- )
- );
-
- dispatch(STORE_ACTIONS[param](paramDate));
- } else if (BOOLEAN_VALUES.includes(param)) {
- try {
- const val = JSON.parse(startParams[param]);
- dispatch(STORE_ACTIONS[param](val));
- } catch (e) {
- console.log(e);
- }
- } else if (ARRAY_VALUES.includes(param)) {
- try {
-
- const parsed = JSON.parse(
- decodeURIComponent(startParams[param])
- );
-
- dispatch(STORE_ACTIONS[param](parsed));
- } catch (e) {
- console.log(e);
- }
- }
- });
- }
- } else {
- const allParams = STRING_VALUES.concat(TIME_VALUES)
- .concat(BOOLEAN_VALUES)
- .concat(ARRAY_VALUES);
- allParams.forEach((param) => {
- if (STRING_VALUES.includes(param)) {
- urlFromHash.set(param, STORE_KEYS[param]?.toString());
- } else if (param === "theme") {
- urlFromHash.set(param, themeSet.toString());
- } else if (TIME_VALUES.includes(param)) {
- const time_value = STORE_KEYS[param]?.getTime() * 1000000;
- urlFromHash.set(param, time_value.toString());
- } else if (BOOLEAN_VALUES.includes(param)) {
- try {
- urlFromHash.set(param, JSON.parse(STORE_KEYS[param]));
- } catch (e) {
- console.log(e);
- }
- } else if (ARRAY_VALUES.includes(param)) {
- try {
- const encodedArray = encodeURIComponent(
- JSON.stringify(STORE_KEYS[param])
- );
- urlFromHash.set(param, encodedArray);
- } catch (e) {
- console.log(e);
- }
- }
- });
- window.location.hash = urlFromHash;
- }
- }, []);
-
- useEffect(() => {
- if (hash.length > 0) {
- const paramsFromHash = new URLSearchParams(hash.replace("#", ""));
- let previousParams = {};
- for (let [key, value] of paramsFromHash.entries()) {
- previousParams[key] = value;
- }
-
- Object.keys(STORE_KEYS).forEach((store_key) => {
- if (
- STRING_VALUES.includes(store_key) &&
- previousParams[store_key] !== STORE_KEYS[store_key]
- ) {
- const updated = STORE_KEYS[store_key].toString().trim();
-
- paramsFromHash.set(store_key, updated);
- } else if (
- TIME_VALUES.includes(store_key) &&
- previousParams[store_key] !==
- encodeTs(STORE_KEYS[store_key])
- ) {
- const encodedTs = encodeTs(STORE_KEYS[store_key]);
- paramsFromHash.set(store_key, encodedTs);
- } else if (
- BOOLEAN_VALUES.includes(store_key) &&
- previousParams[store_key] !== STORE_KEYS[store_key]
- ) {
- try {
- paramsFromHash.set(
- store_key,
- JSON.parse(STORE_KEYS[store_key])
- );
- } catch (e) {
- console.error(e);
- }
- } else if (store_key === "left") {
- const parsed = encodeURIComponent(JSON.stringify(left));
- paramsFromHash.set("left", parsed);
- } else if (store_key === "right") {
- const parsed = encodeURIComponent(JSON.stringify(right));
- paramsFromHash.set("right", parsed);
- }
- });
- window.location.hash = paramsFromHash;
- }
- }, [STORE_KEYS]);
-}
+import * as moment from "moment";
+import { useEffect, useMemo, useState } from "react";
+import { useDispatch, useSelector } from "react-redux";
+import { useLocation } from "react-router-dom";
+
+import {
+ setIsSubmit,
+ setQueryTime,
+ setQueryStep,
+ setStartTime,
+ setStopTime,
+ setTheme,
+ setAutoTheme
+} from "../actions";
+
+import setFromTime from "../actions/setFromTime";
+import setIsEmbed from "../actions/setIsEmbed";
+import { setLeftPanel } from "../actions/setLeftPanel";
+import { setRightPanel } from "../actions/setRightPanel";
+import setToTime from "../actions/setToTime";
+import { setUrlLocation } from "../actions/setUrlLocation";
+import { setUrlQueryParams } from "../actions/setUrlQueryParams";
+import { setSplitView } from "../components/StatusBar/components/SplitViewButton/setSplitView";
+// import { environment } from "../environment/env.dev";
+
+
+export const STRING_VALUES = ["step", "theme", "time"];
+export const ARRAY_VALUES = ["left", "right"];
+
+export const TIME_VALUES = ["start", "stop"];
+
+export const BOOLEAN_VALUES = ["isSubmit", "isSplit", "autoTheme", "isEmbed"];
+
+export function UpdateStateFromQueryParams() {
+ const isLightTheme = useMemo(() => {
+ return window.matchMedia("(prefers-color-scheme: light)").matches;
+ }, []);
+
+ const dispatch = useDispatch();
+ const urlQueryParams = useSelector(({urlQueryParams}: any) => urlQueryParams);
+ const start = useSelector(({start}: any) => start);
+ const stop = useSelector(({stop}: any) => stop);
+ const from = useSelector(({from}: any) => from);
+ const to = useSelector(({to}: any) => to);
+ const step = useSelector(({step}: any) => step);
+ const isSubmit = useSelector(({isSubmit}: any) => isSubmit);
+ const isEmbed = useSelector(({isEmbed}: any) => isEmbed);
+ const time = useSelector(({time}: any) => time);
+ const left = useSelector(({left}: any) => left);
+ const right = useSelector(({right}: any) => right);
+ const theme = useSelector(({theme}: any) => theme);
+ const autoTheme = useSelector(({autoTheme}: any) => autoTheme);
+ const isSplit = useSelector(({isSplit}: any) => isSplit);
+ const [themeSet, setThemeSet] = useState(isLightTheme ? "light" : theme);
+
+ useEffect(() => {
+ setThemeSet(theme);
+ }, [theme]);
+ const STORE_KEYS: any = {
+ start,
+ step,
+ stop,
+ from,
+ to,
+ time,
+ isSubmit,
+ isEmbed,
+ theme,
+ autoTheme,
+ left,
+ right,
+ isSplit,
+ };
+
+ const STORE_ACTIONS: any = {
+ start: setStartTime,
+ step: setQueryStep,
+ stop: setStopTime,
+ from: setFromTime,
+ to: setToTime,
+ time: setQueryTime,
+ isSubmit: setIsSubmit,
+ isEmbed: setIsEmbed,
+ theme: setTheme,
+ left: setLeftPanel,
+ right: setRightPanel,
+ isSplit: setSplitView,
+ autoTheme: setAutoTheme
+ };
+
+ const encodeTs = (ts: any) => {
+ return ts?.getTime() + "000000";
+ };
+
+ const { hash } = useLocation();
+ useEffect(() => {
+ const urlFromHash = new URLSearchParams(hash.replace("#", ""));
+ // !if there is some params set them first on UI
+
+ if (hash.length > 0) {
+ const startParams = urlQueryParams;
+
+ for (let [key, value] of urlFromHash.entries()) {
+ startParams[key] = value;
+ }
+
+ if (Object.keys(startParams).length > 0) {
+ dispatch(setUrlQueryParams({ ...urlQueryParams, startParams }));
+
+ dispatch(setUrlLocation(hash));
+
+ Object.keys(startParams).forEach((param) => {
+ if (
+ STRING_VALUES.includes(param) &&
+ startParams[param] !== ""
+ ) {
+ dispatch(STORE_ACTIONS[param](startParams[param]));
+ } else if (param === "theme") {
+ dispatch(STORE_ACTIONS[param](themeSet));
+ } else if (
+ TIME_VALUES.includes(param) &&
+ startParams[param] !== ""
+ ) {
+ const croppedTime = startParams[param] / 1000000;
+ const paramDate = new Date(
+ (moment as any)(croppedTime).format(
+ "YYYY-MM-DDTHH:mm:ss.SSSZ"
+ )
+ );
+
+ dispatch(STORE_ACTIONS[param](paramDate));
+ } else if (BOOLEAN_VALUES.includes(param)) {
+ try {
+ const val = JSON.parse(startParams[param]);
+ dispatch(STORE_ACTIONS[param](val));
+ } catch (e) {
+ console.log(e);
+ }
+ } else if (ARRAY_VALUES.includes(param)) {
+ try {
+
+ const parsed = JSON.parse(
+ decodeURIComponent(startParams[param])
+ );
+
+ dispatch(STORE_ACTIONS[param](parsed));
+ } catch (e) {
+ console.log(e);
+ }
+ }
+ });
+ }
+ } else {
+ const allParams = STRING_VALUES.concat(TIME_VALUES)
+ .concat(BOOLEAN_VALUES)
+ .concat(ARRAY_VALUES);
+ allParams.forEach((param) => {
+ if (STRING_VALUES.includes(param)) {
+ urlFromHash.set(param, STORE_KEYS[param]?.toString());
+ } else if (param === "theme") {
+ urlFromHash.set(param, themeSet.toString());
+ } else if (TIME_VALUES.includes(param)) {
+ const time_value = STORE_KEYS[param]?.getTime() * 1000000;
+ urlFromHash.set(param, time_value.toString());
+ } else if (BOOLEAN_VALUES.includes(param)) {
+ try {
+ urlFromHash.set(param, JSON.parse(STORE_KEYS[param]));
+ } catch (e) {
+ console.log(e);
+ }
+ } else if (ARRAY_VALUES.includes(param)) {
+ try {
+ const encodedArray = encodeURIComponent(
+ JSON.stringify(STORE_KEYS[param])
+ );
+ urlFromHash.set(param, encodedArray);
+ } catch (e) {
+ console.log(e);
+ }
+ }
+ });
+ (window as any).location.hash = urlFromHash;
+ }
+ }, []);
+
+ useEffect(() => {
+ if (hash.length > 0) {
+ const paramsFromHash = new URLSearchParams(hash.replace("#", ""));
+ let previousParams: any = {};
+ for (let [key, value] of paramsFromHash.entries()) {
+ previousParams[key] = value;
+ }
+
+ Object.keys(STORE_KEYS).forEach((store_key) => {
+ if (
+ STRING_VALUES.includes(store_key) &&
+ previousParams[store_key] !== STORE_KEYS[store_key]
+ ) {
+ const updated = STORE_KEYS[store_key].toString().trim();
+
+ paramsFromHash.set(store_key, updated);
+ } else if (
+ TIME_VALUES.includes(store_key) &&
+ previousParams[store_key] !==
+ encodeTs(STORE_KEYS[store_key])
+ ) {
+ const encodedTs = encodeTs(STORE_KEYS[store_key]);
+ paramsFromHash.set(store_key, encodedTs);
+ } else if (
+ BOOLEAN_VALUES.includes(store_key) &&
+ previousParams[store_key] !== STORE_KEYS[store_key]
+ ) {
+ try {
+ paramsFromHash.set(
+ store_key,
+ JSON.parse(STORE_KEYS[store_key])
+ );
+ } catch (e) {
+ console.error(e);
+ }
+ } else if (store_key === "left") {
+ const parsed = encodeURIComponent(JSON.stringify(left));
+ paramsFromHash.set("left", parsed);
+ } else if (store_key === "right") {
+ const parsed = encodeURIComponent(JSON.stringify(right));
+ paramsFromHash.set("right", parsed);
+ }
+ });
+ (window as any).location.hash = paramsFromHash;
+ }
+ }, [STORE_KEYS]);
+}
diff --git a/src/helpers/decodeQuery.js b/src/helpers/decodeQuery.ts
similarity index 78%
rename from src/helpers/decodeQuery.js
rename to src/helpers/decodeQuery.ts
index 1bcbb87e..a3071a86 100644
--- a/src/helpers/decodeQuery.js
+++ b/src/helpers/decodeQuery.ts
@@ -1,195 +1,200 @@
-import { setLabels } from "../actions";
-import loadLabelValues from "../actions/loadLabelValues";
-import store from "../store/store";
-
-export function decodeQuery(query, apiUrl, labels = [], datasourceId = '') {
-
- if(typeof query !== 'string'){
- return
- }
- const queryArr = query
- ?.match(/[^{\}]+(?=})/g, "$1")
- ?.map((m) => m.split(","))
- ?.flat();
-
- const labelsFromQuery = [];
-
- queryArr?.forEach((label) => {
- const regexQuery = label.match(/([^{}=,~!]+)/gm);
- if (!regexQuery) {
- return;
- }
- if (label.includes("!=")) {
- const labelObj = {
- name: regexQuery[0],
- values: [],
- };
- const valueObj = {
- name: regexQuery[1]?.replaceAll('"', ""),
- selected: true,
- inverted: true,
- };
-
- labelObj.values.push(valueObj);
- labelsFromQuery.push(labelObj);
- } else if (label.includes("=~")) {
- const values = regexQuery[1]?.split("|");
- const labelObj = {
- name: regexQuery[0],
- values: [],
- };
-
- values.forEach((value) => {
- const valueObj = {
- name: value?.replaceAll('"', ""),
- selected: true,
- inverted: false,
- };
-
- labelObj.values.push(valueObj);
- });
-
- labelsFromQuery.push(labelObj);
- } else {
- const labelObj = {
- name: regexQuery[0],
- values: [],
- };
- const valueObj = {
- name: regexQuery[1]?.replaceAll('"', ""),
- selected: true,
- inverted: false,
- };
- labelObj.values.push(valueObj);
- labelsFromQuery.push(labelObj);
- }
- });
-
- const newLabels = [...labels] || [];
-
- newLabels?.forEach((label) => {
- if (label.selected && label.values.length > 0) {
- label.selected = false;
- label.values.forEach((value) => {
- if (value.selected) {
- value.selected = false;
- }
- });
- }
- });
-
- if (labelsFromQuery.length > 0) {
- let labelsWithValues = [];
-
- labelsFromQuery.forEach(async (label) => {
- const cleanLabel = newLabels?.find(
- (item) => item?.name === label?.name
- );
- if (!cleanLabel) {
- return;
- }
-
- await store.dispatch(
- loadLabelValues(datasourceId,cleanLabel, newLabels, apiUrl)
- );
-
- const labelsWithValues = labels;
- const labelWithValues = labelsWithValues.find(
- (item) => item?.name === label?.name
- );
- let values = labelWithValues?.values;
-
- values = label?.values?.concat(values);
-
- values = values
- .sort((a, b) => a.name.localeCompare(b.name))
- .filter((value, index, arr) => {
- return value?.name !== arr?.[index - 1]?.name;
- })
- .filter((value) => !!value);
-
- labelWithValues.values = values;
- labelWithValues.selected = true;
- });
-
- /// here we should update the labels from actual query
-
- store.dispatch(setLabels(labelsWithValues));
- }
-}
-
-/// key label separator group
-
-// it returns the labels to update at query state
-export function decodeExpr(expr) {
-
- let labelsFromQuery = [];
-
- if (expr.length > 7) {
- const exprArr = expr
- ?.match(/[^{\}]+(?=})/g, "$1")
- ?.map((m) => m.split(","))
- ?.flat();
-
- exprArr?.forEach((label) => {
- const regexQuery = label.match(/([^{}=,~!]+)/gm);
-
- if (!regexQuery) {
- return;
- }
-
- if (label.includes("!=")) {
- const labelObj = {
- name: regexQuery[0].trim(),
- selected: false,
- values: [],
- };
-
- const valueObj = {
- name: regexQuery[1]?.replaceAll('"', ""),
- selected: true,
- inverted: true,
- };
-
- labelObj.values.push(valueObj);
- labelsFromQuery.push(labelObj);
- } else if (label.includes("=~")) {
- const values = regexQuery[1]?.trim().split("|");
- const labelObj = {
- name: regexQuery[0].trim(),
- selected: true,
- values: [],
- };
-
- values.forEach((value) => {
- const valueObj = {
- name: value?.replaceAll('"', ""),
- selected: true,
- inverted: false,
- };
-
- labelObj.values.push(valueObj);
- });
-
- labelsFromQuery.push(labelObj);
- } else {
- const labelObj = {
- name: regexQuery[0].trim(),
- selected: true,
- values: [],
- };
-
- const valueObj = {
- name: regexQuery[1]?.replaceAll('"', ""),
- selected: true,
- inverted: false,
- };
- labelObj.values.push(valueObj);
- labelsFromQuery.push(labelObj);
- }
- });
- }
-
-
- return labelsFromQuery;
-}
+import { setLabels } from "../actions";
+import loadLabelValues from "../actions/loadLabelValues";
+import store from "../store/store";
+
+export function decodeQuery(
+ query: any,
+ apiUrl: string,
+ labels: any[] = [],
+ datasourceId: string = ''
+) {
+
+ if(typeof query !== 'string'){
+ return
+ }
+ const queryArr = query
+ .match(/[^{\}]+(?=})/g)
+ ?.map((m) => m.split(","))
+ ?.flat();
+
+ const labelsFromQuery: any[] = [];
+
+ queryArr?.forEach((label) => {
+ const regexQuery = label.match(/([^{}=,~!]+)/gm);
+ if (!regexQuery) {
+ return;
+ }
+ if (label.includes("!=")) {
+ const labelObj: any = {
+ name: regexQuery[0],
+ values: [],
+ };
+ const valueObj: any = {
+ name: regexQuery[1]?.replaceAll('"', ""),
+ selected: true,
+ inverted: true,
+ };
+
+ labelObj.values.push(valueObj);
+ labelsFromQuery.push(labelObj);
+ } else if (label.includes("=~")) {
+ const values = regexQuery[1]?.split("|");
+ const labelObj: any = {
+ name: regexQuery[0],
+ values: [],
+ };
+
+ values.forEach((value) => {
+ const valueObj = {
+ name: value?.replaceAll('"', ""),
+ selected: true,
+ inverted: false,
+ };
+
+ labelObj.values.push(valueObj);
+ });
+
+ labelsFromQuery.push(labelObj);
+ } else {
+ const labelObj: any = {
+ name: regexQuery[0],
+ values: [],
+ };
+ const valueObj = {
+ name: regexQuery[1]?.replaceAll('"', ""),
+ selected: true,
+ inverted: false,
+ };
+ labelObj.values.push(valueObj);
+ labelsFromQuery.push(labelObj);
+ }
+ });
+
+ const newLabels: any = [...labels] || [];
+
+ newLabels?.forEach((label: any) => {
+ if (label.selected && label.values.length > 0) {
+ label.selected = false;
+ label.values.forEach((value: any) => {
+ if (value.selected) {
+ value.selected = false;
+ }
+ });
+ }
+ });
+
+ if (labelsFromQuery.length > 0) {
+ let labelsWithValues: any[] = [];
+
+ labelsFromQuery.forEach(async (label) => {
+ const cleanLabel = newLabels?.find(
+ (item: any) => item?.name === label?.name
+ );
+ if (!cleanLabel) {
+ return;
+ }
+
+ await store.dispatch(
+ loadLabelValues(datasourceId,cleanLabel, newLabels, apiUrl)
+ );
+
+ const labelsWithValues = labels;
+ const labelWithValues = labelsWithValues.find(
+ (item) => item?.name === label?.name
+ );
+ let values = labelWithValues?.values;
+
+ values = label?.values?.concat(values);
+
+ values = values
+ .sort((a: any, b: any) => a.name.localeCompare(b.name))
+ .filter((value: any, index: any, arr: any[]) => {
+ return value?.name !== arr[index - 1]?.name;
+ })
+ .filter((value: any) => !!value);
+
+ labelWithValues.values = values;
+ labelWithValues.selected = true;
+ });
+
+ /// here we should update the labels from actual query
+
+ store.dispatch(setLabels(labelsWithValues));
+ }
+}
+
+/// key label separator group
+
+// it returns the labels to update at query state
+export function decodeExpr(expr: string) {
+
+ let labelsFromQuery: any[] = [];
+
+ if (expr.length > 7) {
+ const exprArr = expr
+ ?.match(/[^{\}]+(?=})/g)
+ ?.map((m) => m.split(","))
+ ?.flat();
+
+ exprArr?.forEach((label) => {
+ const regexQuery = label.match(/([^{}=,~!]+)/gm);
+
+ if (!regexQuery) {
+ return;
+ }
+
+ if (label.includes("!=")) {
+ const labelObj: any = {
+ name: regexQuery[0].trim(),
+ selected: false,
+ values: [],
+ };
+
+ const valueObj: any = {
+ name: regexQuery[1]?.replaceAll('"', ""),
+ selected: true,
+ inverted: true,
+ };
+
+ labelObj.values.push(valueObj);
+ labelsFromQuery.push(labelObj);
+ } else if (label.includes("=~")) {
+ const values = regexQuery[1]?.trim().split("|");
+ const labelObj: any = {
+ name: regexQuery[0].trim(),
+ selected: true,
+ values: [],
+ };
+
+ values.forEach((value) => {
+ const valueObj: any = {
+ name: value?.replaceAll('"', ""),
+ selected: true,
+ inverted: false,
+ };
+
+ labelObj.values.push(valueObj);
+ });
+
+ labelsFromQuery.push(labelObj);
+ } else {
+ const labelObj: any = {
+ name: regexQuery[0].trim(),
+ selected: true,
+ values: [],
+ };
+
+ const valueObj: any = {
+ name: regexQuery[1]?.replaceAll('"', ""),
+ selected: true,
+ inverted: false,
+ };
+ labelObj.values.push(valueObj);
+ labelsFromQuery.push(labelObj);
+ }
+ });
+ }
+
+
+ return labelsFromQuery;
+}
diff --git a/src/helpers/error.interceptor.js b/src/helpers/error.interceptor.ts
similarity index 92%
rename from src/helpers/error.interceptor.js
rename to src/helpers/error.interceptor.ts
index bd761a8e..7bc8d5e8 100644
--- a/src/helpers/error.interceptor.js
+++ b/src/helpers/error.interceptor.ts
@@ -1,83 +1,82 @@
-import store from '../store/store'
-import { errorHandler, createAlert } from "../actions/";
-import setApiWarning from '../actions/setApiWarning';
-
-const errorInterceptor = (axiosInstance) => {
- axiosInstance.interceptors.response.use(
- (response) => {
-
- return response;
- },
-
- (error) => {
-
- if (error.response) {
- const handler = errorHandler(error)
-
- if (error?.response?.status === 401) {
-
- }
- else if (handler.status === 500 && handler.type === 'labels') {
-
- if (store.getState().notifications.length < 1 && store.getState().debugMode === true) {
- store.dispatch(createAlert({
- type: "error",
- message: (handler.message + " for " + handler.type || handler.status + handler.type + 'Error')
- }))
- }
- }
-
- else if (handler.status === 404 && handler.type === 'labels') {
-
- if (store.getState().notifications.length < 1) {
- store.dispatch(createAlert({
- type: "error",
- message: (handler.message || handler.status + handler.type + 'Error')
- }))
- }
-
- }
- else {
-
- if (store.getState().notifications.length < 1) {
- store.dispatch(createAlert({
- type: "error",
- message: (handler.message + " for " + handler.type || handler.status + handler.type + 'Error')
- }))
- }
- }
- } else {
-
-
- // 1- get error by parsing json
-
- const error_parsed = JSON.parse(JSON.stringify(error));
- const networkError = {
- url: error_parsed.config.url,
- message: error_parsed.message,
- name: error_parsed.name
- }
-
- // 2-
- store.dispatch(setApiWarning({ type: 'labels', message: 'Labels not available', }))
- const { url } = networkError
-
- const apiWarning = store.getState().apiWarning
- if (apiWarning && url.includes('query') && store.getState().notifications.length < 1) {
- apiWarning.num++
- store.dispatch(createAlert({
- type: 'error',
- message: `API not found, please adjust API URL`
- }))
- } else if( url.includes('labels') && store.getState().notifications.length < 1) {
- store.dispatch(createAlert({
- type: 'error',
- message: 'API not found, please adjust API URL'
- }))
- }
-
- }
- }
- );
-};
-export default errorInterceptor;
+import store from '../store/store'
+import { errorHandler, createAlert } from "../actions";
+import setApiWarning from '../actions/setApiWarning';
+
+const errorInterceptor = (axiosInstance: any) => {
+ axiosInstance.interceptors.response.use(
+ (response: any) => {
+ return response;
+ },
+
+ (error: any) => {
+
+ if (error.response) {
+ const handler = errorHandler(error)
+
+ if (error?.response?.status === 401) {
+
+ }
+ else if (handler.status === 500 && handler.type === 'labels') {
+
+ if (store.getState().notifications.length < 1 && store.getState().debugMode === true) {
+ store.dispatch(createAlert({
+ type: "error",
+ message: (handler.message + " for " + handler.type || handler.status + handler.type + 'Error')
+ }))
+ }
+ }
+
+ else if (handler.status === 404 && handler.type === 'labels') {
+
+ if (store.getState().notifications.length < 1) {
+ store.dispatch(createAlert({
+ type: "error",
+ message: (handler.message || handler.status + handler.type + 'Error')
+ }))
+ }
+
+ }
+ else {
+
+ if (store.getState().notifications.length < 1) {
+ store.dispatch(createAlert({
+ type: "error",
+ message: (handler.message + " for " + handler.type || handler.status + handler.type + 'Error')
+ }))
+ }
+ }
+ } else {
+
+
+ // 1- get error by parsing json
+
+ const error_parsed = JSON.parse(JSON.stringify(error));
+ const networkError = {
+ url: error_parsed.config.url,
+ message: error_parsed.message,
+ name: error_parsed.name
+ }
+
+ // 2-
+ store.dispatch(setApiWarning({ type: 'labels', message: 'Labels not available', }))
+ const { url } = networkError
+
+ const apiWarning = store.getState().apiWarning
+ if (apiWarning && url.includes('query') && store.getState().notifications.length < 1) {
+ apiWarning.num++
+ store.dispatch(createAlert({
+ type: 'error',
+ message: `API not found, please adjust API URL`
+ }))
+ } else if( url.includes('labels') && store.getState().notifications.length < 1) {
+ store.dispatch(createAlert({
+ type: 'error',
+ message: 'API not found, please adjust API URL'
+ }))
+ }
+
+ }
+ }
+ );
+};
+export default errorInterceptor;
diff --git a/src/helpers/httpclient.js b/src/helpers/httpclient.ts
similarity index 88%
rename from src/helpers/httpclient.js
rename to src/helpers/httpclient.ts
index 64051714..5962e513 100644
--- a/src/helpers/httpclient.js
+++ b/src/helpers/httpclient.ts
@@ -2,7 +2,7 @@ import axios from "axios";
import { environment } from "../environment/env.dev";
import errorInterceptor from "./error.interceptor";
const httpClient = axios.create({
-baseURL: environment.API_URL,
+baseURL: environment.apiUrl,
});
errorInterceptor(httpClient);
export default httpClient;
\ No newline at end of file
diff --git a/src/helpers/setDebug.js b/src/helpers/setDebug.ts
similarity index 62%
rename from src/helpers/setDebug.js
rename to src/helpers/setDebug.ts
index 5dfe48ac..81a91675 100644
--- a/src/helpers/setDebug.js
+++ b/src/helpers/setDebug.ts
@@ -1,4 +1,4 @@
-export default function setDebug (envSetting) {
+export default function setDebug (envSetting: string) {
if (envSetting === 'dev') {
return false
} else {
diff --git a/src/helpers/stateFromQueryParams.js b/src/helpers/stateFromQueryParams.ts
similarity index 88%
rename from src/helpers/stateFromQueryParams.js
rename to src/helpers/stateFromQueryParams.ts
index 3cb1eb1f..021e9ca5 100644
--- a/src/helpers/stateFromQueryParams.js
+++ b/src/helpers/stateFromQueryParams.ts
@@ -1,114 +1,116 @@
-import { environment } from "../environment/env.dev";
-import setDebug from "./setDebug";
-import * as moment from "moment";
-import { nanoid } from "nanoid";
-import { BOOLEAN_VALUES } from "./UpdateStateFromQueryParams";
-export const initialUrlState = {
- query: "",
- queryType: "range",
- start: "",
- time: "",
- to: "",
- stop: "",
- from: "",
- left: [
- {
- id: nanoid(),
- idRef: "L-A",
- lastIdx: 1,
- panel: "left",
- queryType: "range",
- dataSourceType: "logs",
- dataSourceURL: "",
- dataSourceId: "cHI2SqPzH_kxYRXj",
- limit: 100,
- step: 5,
- tableView: false,
- chartView: false,
- isShowTs: true,
- browserOpen: false,
- expr: "",
- labels: [], // name: selected:
- values: [], // label name selected
- response: {}, // the target should be just the last one
- },
- ],
-
- right: [
- {
- id: nanoid(),
- idRef: "R-A",
- lastIdx: 1,
- panel: "right",
- queryType: "range",
- dataSourceType: "logs",
- dataSourceURL: "",
- dataSourceId: "cHI2SqPzH_kxYRXj",
- limit: 100,
- step: 5,
- tableView: false,
- chartView: false,
- isShowTs: true,
- browserOpen: false,
- expr: "",
- labels: [], // name: selected:
- values: [], // label name selected
- response: {}, // the target should be just the last one
- },
- ],
-
- label: "",
- limit: 100,
- step: 5,
- apiUrl: "",
- isSubmit: false,
- isEmbed: false,
- autoTheme: true,
- theme: "",
- isSplit: false,
-};
-
-export default function stateFromQueryParams() {
- const debug = setDebug(environment.environment);
- if (debug) console.group("🚧 LOGIC/InitialState/FromQuery");
-
- const { hash } = window.location;
- if (debug) console.log("🚧 LOGIC/FromQuery Hash", hash);
-
- const urlFromHash = new URLSearchParams(hash.replace("#", ""));
-
- if (debug) console.log("🚧 LOGIC/urlFromHash", urlFromHash, hash.length);
-
- if (hash.length > 0) {
- const startParams = { ...initialUrlState };
- if (debug)
- console.log("🚧 LOGIC/startParams/BeforeURLFromHash", startParams);
- for (let [key, value] of urlFromHash.entries()) {
- if (debug) console.log("🚧 LOGIC/startParams/", key, value);
-
- if (key === "stop" || key === "start") {
- const croppedTime = parseInt(value) / 1000000;
- startParams[key] = new Date(
- moment(croppedTime).format("YYYY-MM-DDTHH:mm:ss.SSSZ")
- );
- } else if (key === "left" || key === "right") {
- const parsedQuery = JSON.parse(decodeURIComponent(value));
- startParams[key] = parsedQuery;
- } else if (BOOLEAN_VALUES.includes(key)) {
- try {
- startParams[key] = JSON.parse(value);
- } catch(e) {
- console.error(key);
- startParams[key] = false;
- }
- } else {
- startParams[key] = value;
- }
- }
-
- return startParams || initialUrlState;
- } else {
- if (debug) console.groupEnd("🚧 LOGIC/InitialState/FromQuery");
- return initialUrlState;
- }
-}
+import { environment } from "../environment/env.dev";
+import setDebug from "./setDebug";
+import * as moment from "moment";
+import { nanoid } from "nanoid";
+import { BOOLEAN_VALUES } from "./UpdateStateFromQueryParams";
+export const initialUrlState = {
+ query: "",
+ queryType: "range",
+ start: "",
+ time: "",
+ to: "",
+ stop: "",
+ from: "",
+ left: [
+ {
+ id: nanoid(),
+ idRef: "L-A",
+ lastIdx: 1,
+ panel: "left",
+ queryType: "range",
+ dataSourceType: "logs",
+ dataSourceURL: "",
+ dataSourceId: "cHI2SqPzH_kxYRXj",
+ limit: 100,
+ step: 5,
+ tableView: false,
+ chartView: false,
+ isShowTs: true,
+ browserOpen: false,
+ expr: "",
+ labels: [], // name: selected:
+ values: [], // label name selected
+ response: {}, // the target should be just the last one
+ },
+ ],
+
+ right: [
+ {
+ id: nanoid(),
+ idRef: "R-A",
+ lastIdx: 1,
+ panel: "right",
+ queryType: "range",
+ dataSourceType: "traces",
+ dataSourceId:"32D16h5uYBqUUzhD",
+ dataSourceURL: "",
+ limit: 100,
+ step: 5,
+ tableView: false,
+ chartView: false,
+ isShowTs: true,
+ browserOpen: false,
+ expr: "",
+ labels: [], // name: selected:
+ values: [], // label name selected
+ response: {}, // the target should be just the last one
+ },
+ ],
+
+ label: "",
+ limit: 100,
+ step: 5,
+ apiUrl: "",
+ isSubmit: false,
+ isEmbed: false,
+ autoTheme: true,
+ theme: "",
+ isSplit: false,
+};
+
+export default function stateFromQueryParams() {
+ const debug = setDebug(environment.environment);
+ if (debug) console.group("🚧 LOGIC/InitialState/FromQuery");
+
+ const { hash } = window.location;
+ if (debug) console.log("🚧 LOGIC/FromQuery Hash", hash);
+
+ const urlFromHash = new URLSearchParams(hash.replace("#", ""));
+
+ if (debug) console.log("🚧 LOGIC/urlFromHash", urlFromHash, hash.length);
+
+ if (hash.length > 0) {
+ const startParams: any = { ...initialUrlState };
+ if (debug)
+ console.log("🚧 LOGIC/startParams/BeforeURLFromHash", startParams);
+ for (let [key, value] of urlFromHash.entries()) {
+ if (debug) console.log("🚧 LOGIC/startParams/", key, value);
+ if (key === "stop" || key === "start") {
+ const croppedTime = parseInt(value) / 1000000;
+ startParams[key] = new Date(
+ (moment as any)(croppedTime).format("YYYY-MM-DDTHH:mm:ss.SSSZ")
+ );
+ } else if (key === "left" || key === "right") {
+ const parsedQuery = JSON.parse(decodeURIComponent(value));
+ startParams[key] = parsedQuery;
+ } else if (BOOLEAN_VALUES.includes(key)) {
+ try {
+ startParams[key] = JSON.parse(value);
+ } catch(e) {
+ console.error(key);
+ startParams[key] = false;
+ }
+ } else {
+ startParams[key] = value;
+ }
+ if (startParams.theme) {
+ localStorage.setItem("theme", JSON.stringify({ theme: startParams.theme, auto: !!startParams.autoTheme }));
+ }
+ }
+
+ return startParams || initialUrlState;
+ } else {
+ if (debug) console.groupEnd();
+ return initialUrlState;
+ }
+}
diff --git a/src/helpers/useQueryParams.js b/src/helpers/useQueryParams.ts
similarity index 97%
rename from src/helpers/useQueryParams.js
rename to src/helpers/useQueryParams.ts
index ddcab750..54f5156b 100644
--- a/src/helpers/useQueryParams.js
+++ b/src/helpers/useQueryParams.ts
@@ -9,7 +9,7 @@ export function useQueryParams() {
const paramsFromUrl = useMemo(() => {
if (hash) {
const searchParams = new URLSearchParams(hash.replace("#", ""));
- let memoParams = {};
+ let memoParams: any = {};
for (let [key, value] of searchParams.entries()) {
memoParams[key] = value;
diff --git a/src/hooks/useLabels.js b/src/hooks/useLabels.ts
similarity index 79%
rename from src/hooks/useLabels.js
rename to src/hooks/useLabels.ts
index 1b7a7d06..68a00344 100644
--- a/src/hooks/useLabels.js
+++ b/src/hooks/useLabels.ts
@@ -1,87 +1,92 @@
-import axios from "axios";
-import store from "../store/store";
-
-function getTimeParsed(time) {
- return time.getTime() + "000000";
-}
-
-const getUrlFromType = (apiUrl, type, startNs, stopNs) => {
- if (type === "metrics") {
- return `${apiUrl}/api/v1/labels`;
- } else {
- return `${apiUrl}/loki/api/v1/label?start=${startNs}&end=${stopNs}`;
- }
-};
-
-export const sendLabels = async (id, type, apiUrl, start, stop) => {
- const { dataSources } = store.getState();
-
- const actDataSource = dataSources.find((f) => f.id === id);
-
- const basicAuth = actDataSource?.auth?.basicAuth.value;
-
- let auth = {};
-
- let labelHeaders = {};
-
- if (basicAuth) {
- const authfields = actDataSource?.auth?.fields?.basicAuth;
-
- for (let field of authfields) {
- if (field.name === "user") {
- auth.username = field.value;
- }
- if (field.name === "password") {
- auth.password = field.value;
- }
- }
-
- labelHeaders.auth = auth;
- }
-
- const startNs = type === "metrics" ? start : getTimeParsed(start);
- const stopNs = type === "metrics" ? stop : getTimeParsed(stop);
- const headers = {
- "Content-Type": "application/json",
- };
-
- const options = {
- method: "GET",
- headers: headers,
- };
-
- labelHeaders.options = options;
-
- if (type !=='flux' && type !== 'traces' && labelHeaders && apiUrl) {
- const res = await axios
- .get(getUrlFromType(apiUrl, type, startNs, stopNs), labelHeaders)
- .then((response) => {
- if (response) {
- if (response?.data?.data === []) {
- console.log("no labels found");
- }
-
- if (response?.data?.data?.length > 0) {
- const labels = response?.data?.data
- .sort()
- .map((label) => ({
- name: label,
- selected: false,
- values: [],
- }));
- return labels || [];
- }
- } else {
- return [];
- }
- })
- .catch((e) => {
- console.log("error from useLabels");
- console.log(e);
- });
-
- return res;
- }
-
-
-};
+import axios from "axios";
+import store from "../store/store";
+
+function getTimeParsed(time: Date) {
+ return time.getTime() + "000000";
+}
+
+const getUrlFromType = (
+ apiUrl: string,
+ type: string,
+ startNs: string,
+ stopNs: string
+) => {
+ if (type === "metrics") {
+ return `${apiUrl}/api/v1/labels`;
+ } else {
+ return `${apiUrl}/loki/api/v1/label?start=${startNs}&end=${stopNs}`;
+ }
+};
+
+export const sendLabels = async (id: string, type: string, apiUrl: string, start: any, stop: any) => {
+ const { dataSources } = store.getState();
+
+ const actDataSource = dataSources.find((f: any) => f.id === id);
+
+ const basicAuth = actDataSource?.auth?.basicAuth.value;
+
+ const auth: any = {};
+
+ const labelHeaders: any = {};
+
+ if (basicAuth) {
+ const authfields = actDataSource?.auth?.fields?.basicAuth;
+
+ for (let field of authfields) {
+ if (field.name === "user") {
+ auth.username = field.value;
+ }
+ if (field.name === "password") {
+ auth.password = field.value;
+ }
+ }
+
+ labelHeaders.auth = auth;
+ }
+
+ const startNs = type === "metrics" ? start : getTimeParsed(start);
+ const stopNs = type === "metrics" ? stop : getTimeParsed(stop);
+ const headers = {
+ "Content-Type": "application/json",
+ };
+
+ const options = {
+ method: "GET",
+ headers: headers,
+ };
+
+ labelHeaders.options = options;
+
+ if (type !=='flux' && type !== 'traces' && labelHeaders && apiUrl) {
+ const res = await axios
+ .get(getUrlFromType(apiUrl, type, startNs, stopNs), labelHeaders)
+ .then((response: any) => {
+ if (response) {
+ if (response?.data?.data?.length === 0) {
+ console.log("no labels found");
+ }
+
+ if (response?.data?.data?.length > 0) {
+ const labels = response?.data?.data
+ .sort()
+ .map((label: any) => ({
+ name: label,
+ selected: false,
+ values: [],
+ }));
+ return labels || [];
+ }
+ } else {
+ return [];
+ }
+ })
+ .catch((e) => {
+ console.log("error from useLabels");
+ console.log(e);
+ });
+
+ return res;
+ }
+
+
+};
diff --git a/src/index.js b/src/index.js
deleted file mode 100644
index 6b005f88..00000000
--- a/src/index.js
+++ /dev/null
@@ -1,32 +0,0 @@
-import React from 'react';
-import ReactDOM from 'react-dom';
-import './scss/app.scss';
-import App from './App';
-import {
- BrowserRouter,
- Routes,
- Route,
-} from 'react-router-dom';
-import axios from 'axios';
-import errorInterceptor from './helpers/error.interceptor';
-import { Provider } from 'react-redux';
-import store from './store/store';
-import DataSources from './views/DataSources/DataSources';
-
-errorInterceptor(axios)
-
-ReactDOM.render(
-
-
-
-
- } />
- } />
- }/>
-
-
-
-
- ,
- document.getElementById('root')
-);
diff --git a/src/index.tsx b/src/index.tsx
new file mode 100644
index 00000000..36138ac6
--- /dev/null
+++ b/src/index.tsx
@@ -0,0 +1,35 @@
+import React from "react";
+import ReactDOM from "react-dom";
+import "./scss/app.scss";
+import App from "./App";
+import { BrowserRouter, Routes, Route } from "react-router-dom";
+import axios from "axios";
+import errorInterceptor from "./helpers/error.interceptor";
+import { Provider } from "react-redux";
+import store from "./store/store";
+import DataSources from "./views/DataSources/DataSources";
+
+import { CookiesProvider } from "react-cookie";
+errorInterceptor(axios);
+const showDs = store.getState()["showDataSourceSetting"] || false;
+ReactDOM.render(
+
+
+
+
+
+ } />
+ } />
+ {showDs && (
+ : }
+ />
+ )}
+
+
+
+
+ ,
+ document.getElementById("root")
+);
diff --git a/src/plugins/queryhistory/index.js b/src/plugins/queryhistory/index.js
index 86edcb6f..8110b686 100644
--- a/src/plugins/queryhistory/index.js
+++ b/src/plugins/queryhistory/index.js
@@ -1,6 +1,6 @@
import { ThemeProvider, Tooltip } from "@mui/material";
import localService from "../../services/localService";
-import { useState, useEffect } from "react";
+import { useState, useEffect, useMemo } from "react";
import { useSelector, useDispatch } from "react-redux";
import setQueryHistory from "../../actions/setQueryHistory";
import getData from "../../actions/getData";
@@ -116,6 +116,7 @@ function HistoryLinkParams({
handleSubmit,
}) {
const [open, setOpen] = useState(false);
+ const { fromDate, toDate, type, url, queryInput, limit } = item;
const openParams = () => {
setOpen((opened) => (opened ? false : true));
@@ -149,13 +150,11 @@ function HistoryLinkParams({
fontSize="14px"
style={{ marginRight: "3px" }}
/>{" "}
- {item?.params?.apiUrl}
+ {url}
-
- limit: {item?.params?.limit}
-
+ limit: {limit}
step: {item?.params?.step}
@@ -168,16 +167,16 @@ function HistoryLinkParams({
}}
>
{" "}
-
+
{" "}
- {item?.fromDate}
+ {fromDate}
{" - "}
- {item?.toDate}
+ {toDate}
@@ -185,25 +184,27 @@ function HistoryLinkParams({
Query:{" "}
-
- {decodeURIComponent(item.params.query)}
- {" "}
+ {queryInput}{" "}
API URL:{" "}
- {item.params.apiUrl}{" "}
+ {url}{" "}
+
+
+ Data Source Type:{" "}
+ {type}{" "}
From: {" "}
- {item?.fromDate}{" "}
+ {fromDate}{" "}
To: {" "}
- {item?.toDate}{" "}
+ {toDate}{" "}
Limit: {" "}
- {item.params.limit}{" "}
+ {limit}{" "}
Step:{" "}
@@ -638,7 +639,7 @@ const QueryHistory = (props) => {
const [linksStarredFiltered, setLinksStarredFiltered] = useState([]);
const [starredFiltered, setStarredFiltered] = useState([]);
const [linksStarredItems, setLinksStarredItems] = useState(false);
-
+ const { start, stop } = useSelector((store) => store);
function handleDelete(id) {
const removed = historyService.remove(id);
dispatch(setQueryHistory(removed));
@@ -677,18 +678,50 @@ const QueryHistory = (props) => {
panel,
queryInput,
queryType,
- dataSourceType,
+ type,
+ dataSourceId,
+ url,
+
direction,
} = logData;
+
+ let querySubmit = "";
+
+ let customStep = 0;
+
+ if (queryInput.includes(`$__interval`)) {
+ const timeDiff = (stop.getTime() - start.getTime()) / 1000;
+
+ const timeProportion = timeDiff / 30;
+
+ const screenProportion = (1).toFixed(1);
+
+ const intval = timeProportion / screenProportion;
+
+ const ratiointval = Math.round(
+ intval * window.devicePixelRatio.toFixed(2)
+ );
+ querySubmit = queryInput.replace(
+ "[$__interval]",
+ `[${ratiointval}s]`
+ );
+ customStep = ratiointval;
+ } else {
+ querySubmit = queryInput;
+ }
+
dispatch(
getData(
- dataSourceType,
- queryInput,
+ type,
+ querySubmit,
queryType,
limit,
panel,
id,
- direction
+ direction || "forward",
+ dataSourceId,
+ url,
+ customStep
)
);
}
@@ -907,10 +940,10 @@ const QueryHistory = (props) => {
filteredQueries={starredFiltered}
filteredLinks={linksStarredFiltered}
emptyQueryMessage={
- "Click the ‘Star’ icon to save links and find them here to reuse again"
+ "Click the 'Star' icon to save links and find them here to reuse again"
}
emptyLinkMessage={
- "Click the ‘Star’ icon to save queries and find them here to reuse again"
+ "Click the 'Star' icon to save queries and find them here to reuse again"
}
copyQuery={copyQuery}
/>
diff --git a/src/plugins/settingsdialog/SettingsDialog.js b/src/plugins/settingsdialog/SettingsDialog.js
index e8b4adfc..892f5c68 100644
--- a/src/plugins/settingsdialog/SettingsDialog.js
+++ b/src/plugins/settingsdialog/SettingsDialog.js
@@ -6,7 +6,7 @@ import {
setAutoTheme
} from "../../actions";
-import setSettingsDialogOpen from "../../actions/setSettingsDialogOpen.js";
+import setSettingsDialogOpen from "../../actions/setSettingsDialogOpen";
import { useEffect, useState } from "react";
@@ -59,13 +59,16 @@ export default function SettingsDialog({ open, onClose }) {
function handleThemeSwitch() {
- dispatch(setTheme(themeSet === "light" ? "dark" : "light"));
- setThemeSet(theme);
- localStorage.setItem("theme", JSON.stringify({ theme }));
+ const switchedTheme = themeSet === "light" ? "dark" : "light"
+ dispatch(setTheme(switchedTheme));
+ setThemeSet(switchedTheme);
+ localStorage.setItem("theme", JSON.stringify({ theme: switchedTheme, auto: autoThemeLocal }));
}
const handleAutoTheme = (val) => {
- dispatch(setAutoTheme(!autoThemeLocal))
- setLocalAutoTheme(autoTheme);
+ const switchedAutoTheme = !autoThemeLocal
+ dispatch(setAutoTheme(switchedAutoTheme))
+ setLocalAutoTheme(switchedAutoTheme);
+ localStorage.setItem("theme", JSON.stringify({ theme: theme, auto: switchedAutoTheme }));
}
function handleClose() {
dispatch(setSettingsDialogOpen(false));
diff --git a/src/plugins/settingsmenu/Menu.js b/src/plugins/settingsmenu/Menu.js
index 7fa0ef93..f2a25110 100644
--- a/src/plugins/settingsmenu/Menu.js
+++ b/src/plugins/settingsmenu/Menu.js
@@ -51,6 +51,7 @@ const StyledMenu = styled((props) => (
export default function ClokiMenu() {
const dispatch = useDispatch();
+ const showDs = useSelector((store) => store.showDataSourceSetting);
const [anchorEl, setAnchorEl] = React.useState(null);
const open = Boolean(anchorEl);
const storeTheme = useSelector((store) => store.theme);
@@ -97,12 +98,17 @@ export default function ClokiMenu() {
/>{" "}
Query Settings
-
-
-
+ {showDs && (
+
+
+
+ )}
);
diff --git a/src/qryn-ui/Switch/styles/index.js b/src/qryn-ui/Switch/Switch.styles.tsx
similarity index 68%
rename from src/qryn-ui/Switch/styles/index.js
rename to src/qryn-ui/Switch/Switch.styles.tsx
index 3bbe9ad3..e0c58473 100644
--- a/src/qryn-ui/Switch/styles/index.js
+++ b/src/qryn-ui/Switch/Switch.styles.tsx
@@ -1,8 +1,8 @@
import styled from "@emotion/styled";
const Label = styled.div`
- color: ${(props) => props.theme.textColor};
- background: ${(props) => props.theme.buttonInactive};
+ color: ${(props: any) => props.theme.textColor};
+ background: ${(props: any) => props.theme.buttonInactive};
display: flex;
align-items: center;
justify-content: center;
@@ -14,31 +14,31 @@ const SwitchCont = styled.div`
display: flex;
align-items: center;
font-size: 12px;
- background-color: ${(props) => props.theme.buttonInactive};
+ background-color: ${(props: any) => props.theme.buttonInactive};
- border: 1px solid ${(props) => props.theme.buttonBorder};
- color: ${(props) => props.theme.textColor};
+ border: 1px solid ${(props: any) => props.theme.buttonBorder};
+ color: ${(props: any) => props.theme.textColor};
border-radius: 3px;
margin-right: 10px;
`;
-const SwitchBtn = styled.div`
+const SwitchBtn: any = styled.div`
cursor: pointer;
display: flex;
align-items: center;
- background: ${(props) =>
+ background: ${(props: any) =>
props.selected
? props.theme.buttonDefault
: props.theme.buttonInactive};
- border-left: ${(props) =>
+ border-left: ${(props: any) =>
props.position === "last"
? `1px solid ${props.theme.buttonBorder}`
: "none"};
- border-right: ${(props) =>
+ border-right: ${(props: any) =>
props.position === "first"
? `1px solid ${props.theme.buttonBorder}`
: "none"};
- border-radius: ${({ position }) =>
+ border-radius: ${({ position }: any) =>
position === "first"
? "3px 0px 0px 3px"
: position === "last"
@@ -56,5 +56,4 @@ export const styles = {
Label,
SwitchCont,
SwitchBtn,
-
-}
\ No newline at end of file
+}
diff --git a/src/qryn-ui/Switch/Switch.js b/src/qryn-ui/Switch/Switch.tsx
similarity index 71%
rename from src/qryn-ui/Switch/Switch.js
rename to src/qryn-ui/Switch/Switch.tsx
index 57ccc6b9..40a5101c 100644
--- a/src/qryn-ui/Switch/Switch.js
+++ b/src/qryn-ui/Switch/Switch.tsx
@@ -1,39 +1,39 @@
-import { useState } from "react";
-
-import { styles } from "./styles";
-
-const getBtnPos = (key, arr) => {
- const arrLen = arr.length;
- return key === 0 ? "first" : key === arrLen - 1 ? "last" : "center";
-};
-
-export default function QueryTypeSwitch(props) {
- const { Label, SwitchCont, SwitchBtn } = styles;
- const { options, defaultActive, onChange, label } = props;
-
- const [activeBtn, setActiveBtn] = useState(defaultActive);
-
- function setButtonValue(value) {
- setActiveBtn(value);
- onChange(value);
- }
-
- return (
- <>
-
-
- {options &&
- options.map((value, key, arr) => (
- setButtonValue(value.value)}
- >
- {value.label}
-
- ))}
-
- >
- );
-}
+import { useState } from "react";
+
+import { styles } from "./Switch.styles";
+
+const getBtnPos = (key: number, arr: any[]) => {
+ const arrLen = arr.length;
+ return key === 0 ? "first" : key === arrLen - 1 ? "last" : "center";
+};
+
+export default function QueryTypeSwitch(props: any) {
+ const { Label, SwitchCont, SwitchBtn } = styles;
+ const { options, defaultActive, onChange, label } = props;
+
+ const [activeBtn, setActiveBtn] = useState(defaultActive);
+
+ function setButtonValue(value: any) {
+ setActiveBtn(value);
+ onChange(value);
+ }
+
+ return (
+ <>
+
+
+ {options &&
+ options.map((value: any, key: number, arr: any[]) => (
+ setButtonValue(value.value)}
+ >
+ {value.label}
+
+ ))}
+
+ >
+ );
+}
diff --git a/src/qryn-ui/notifications/consts.js b/src/qryn-ui/notifications/consts.ts
similarity index 100%
rename from src/qryn-ui/notifications/consts.js
rename to src/qryn-ui/notifications/consts.ts
diff --git a/src/qryn-ui/notifications/index.js b/src/qryn-ui/notifications/index.tsx
similarity index 89%
rename from src/qryn-ui/notifications/index.js
rename to src/qryn-ui/notifications/index.tsx
index 2d354e50..058856b7 100644
--- a/src/qryn-ui/notifications/index.js
+++ b/src/qryn-ui/notifications/index.tsx
@@ -1,48 +1,48 @@
-import { useEffect } from "react";
-
-import { useSelector, useDispatch } from "react-redux";
-import { Alert } from "@mui/material";
-import { removeAlert } from "../../actions";
-
-export function Notification() {
- const { notifications } = useSelector((state) => state);
- const dispatch = useDispatch();
- const handleClose = (index) => {
- dispatch(removeAlert(index));
- };
- const Expire = (props) => {
- useEffect(() => {
- setTimeout(() => {
- dispatch(removeAlert(props.index));
- }, props.delay);
- }, [props]);
-
- return
{props.children}
;
- };
-
- return (
-
- {notifications.map((notification, index) => {
- if (notification.visible) {
- return (
-
-
-
handleClose(index)}
- severity={notification.type}
- sx={{ width: "100%" }}
- >
- {notification.message}
-
-
-
- );
- } else {
- return undefined;
- }
- })}
-
- );
-}
+import { useEffect } from "react";
+
+import { useSelector, useDispatch } from "react-redux";
+import { Alert } from "@mui/material";
+import { removeAlert } from "../../actions";
+
+export function Notification() {
+ const { notifications }: {notifications: any[]} = useSelector((state) => state) as any;
+ const dispatch = useDispatch();
+ const handleClose = (index: any) => {
+ dispatch(removeAlert(index));
+ };
+ const Expire = (props: any) => {
+ useEffect(() => {
+ setTimeout(() => {
+ dispatch(removeAlert(props.index));
+ }, props.delay);
+ }, [props]);
+
+ return
{props.children}
;
+ };
+
+ return (
+
+ {notifications.map((notification, index) => {
+ if (notification.visible) {
+ return (
+
+
+
handleClose(index)}
+ severity={notification.type}
+ sx={{ width: "100%" }}
+ >
+ {notification.message}
+
+
+
+ );
+ } else {
+ return undefined;
+ }
+ })}
+
+ );
+}
diff --git a/src/services/consts.js b/src/services/consts.js
deleted file mode 100644
index 631e2c7d..00000000
--- a/src/services/consts.js
+++ /dev/null
@@ -1,16 +0,0 @@
-const _APP = "qryn-query";
-const _HISTORY_ITEM = _APP + "-history-item";
-const _TIMERANGE_ITEM = _APP + "-time-range-item";
-const _CHART_ITEM = _APP + "-chart-item";
-const _LABELS_ITEM = _APP + '-labels-item';
-const _URL_ITEM = _APP + "-url-item";
-const _QUERY_ITEM = _APP + "-url-item";
-
-module.exports = {
- _HISTORY_ITEM,
- _CHART_ITEM,
- _LABELS_ITEM,
- _TIMERANGE_ITEM,
- _URL_ITEM,
- _QUERY_ITEM
-}
diff --git a/src/services/consts.ts b/src/services/consts.ts
new file mode 100644
index 00000000..803534b1
--- /dev/null
+++ b/src/services/consts.ts
@@ -0,0 +1,16 @@
+export const _APP = "qryn-query";
+export const _HISTORY_ITEM = _APP + "-history-item";
+export const _TIMERANGE_ITEM = _APP + "-time-range-item";
+export const _CHART_ITEM = _APP + "-chart-item";
+export const _LABELS_ITEM = _APP + '-labels-item';
+export const _URL_ITEM = _APP + "-url-item";
+export const _QUERY_ITEM = _APP + "-url-item";
+
+// module.exports = {
+// _HISTORY_ITEM,
+// _CHART_ITEM,
+// _LABELS_ITEM,
+// _TIMERANGE_ITEM,
+// _URL_ITEM,
+// _QUERY_ITEM
+// }
diff --git a/src/services/index.js b/src/services/index.ts
similarity index 100%
rename from src/services/index.js
rename to src/services/index.ts
diff --git a/src/services/localHistory.js b/src/services/localHistory.ts
similarity index 67%
rename from src/services/localHistory.js
rename to src/services/localHistory.ts
index d3865184..f10b659e 100644
--- a/src/services/localHistory.js
+++ b/src/services/localHistory.ts
@@ -1,13 +1,15 @@
import { nanoid } from "nanoid";
import { _HISTORY_ITEM } from "./consts";
-import { l_set, l_get, j_parse, j_string, cleanup } from "./localService";
+import localService from "./localService";
+
+const { l_set, l_get, j_parse, j_string, cleanup } = localService();
const localHistory = () => {
const get = () => {
- return j_parse(l_get(_HISTORY_ITEM));
+ return j_parse(l_get(_HISTORY_ITEM) || 'null');
};
- const set = (data) => {
+ const set = (data: any) => {
l_set(_HISTORY_ITEM, j_string(data));
};
@@ -18,10 +20,10 @@ const localHistory = () => {
const historyStorage = get();
- const findById = (item) =>
- historyStorage.find(({ id }) => item.id === id) || {};
+ const findById = (item: any) =>
+ historyStorage.find(({ id }: any) => item.id === id) || {};
- const add = (item) => {
+ const add = (item: any) => {
let previousData = get() || [];
try {
const newItem = {
@@ -39,13 +41,13 @@ const localHistory = () => {
}
};
- const update = (item) => {
+ const update = (item: any) => {
const { id } = item;
let newStorage = [];
try {
- newStorage = historyStorage.map((m) =>
+ newStorage = historyStorage.map((m: any) =>
m.id === id ? { ...m, ...item } : m
);
set(newStorage);
@@ -56,18 +58,18 @@ const localHistory = () => {
};
function getAll() {
- const actualStorage = j_parse(l_get(_HISTORY_ITEM)) || [];
+ const actualStorage = j_parse(l_get(_HISTORY_ITEM) || 'null') || [];
return (
- actualStorage?.map((m) => ({
+ actualStorage?.map((m: any) => ({
...m,
data: decodeURI(m.data),
})) || []
);
}
- const remove = (item) => {
- const filtered = historyStorage.filter(({ id }) => id !== item.id);
+ const remove = (item: any) => {
+ const filtered = historyStorage.filter(({ id }: any) => id !== item.id);
set(filtered);
return getAll();
diff --git a/src/services/localLabels.js b/src/services/localLabels.ts
similarity index 68%
rename from src/services/localLabels.js
rename to src/services/localLabels.ts
index 77d7eab0..b321f11f 100644
--- a/src/services/localLabels.js
+++ b/src/services/localLabels.ts
@@ -1,12 +1,14 @@
import { nanoid } from "nanoid";
import { _LABELS_ITEM } from "./consts";
-import { l_get, l_set, j_string, j_parse, cleanup } from "./localService";
+import localService from "./localService";
+
+const { l_get, l_set, j_string, j_parse, cleanup } = localService();
const localLabels = () => {
const get = () => {
return l_get(_LABELS_ITEM);
};
- const set = (item) => {
+ const set = (item: any) => {
l_set(_LABELS_ITEM, item);
};
@@ -15,13 +17,13 @@ const localLabels = () => {
return getAll() || [];
};
- const labelsStorage = get();
+ const labelsStorage: any = get();
- const findById = (item) =>
- labelsStorage.find(({ id }) => item.id === id) || {};
+ const findById = (item: any) =>
+ labelsStorage.find(({ id }: any) => item.id === id) || {};
// add
- const add = (item) => {
- let previousData = get() || [];
+ const add = (item: any) => {
+ let previousData: any = get() || [];
try {
const newItem = {
id: item.id || nanoid(),
@@ -36,13 +38,13 @@ const localLabels = () => {
}
};
// update
- const update = (item) => {
+ const update = (item: any) => {
const { id } = item;
let newStorage = [];
try {
- newStorage = labelsStorage.map((m) =>
+ newStorage = labelsStorage.map((m: any) =>
m.id === id ? { ...m, ...item } : m
);
set(newStorage);
@@ -53,7 +55,7 @@ const localLabels = () => {
};
// remove
function getAll() {
- const actualStorage = j_parse(l_get(_LABELS_ITEM)) || [];
+ const actualStorage = j_parse(l_get(_LABELS_ITEM) || 'null') || [];
return actualStorage;
}
return { get, set, clean, add, update, findById, getAll };
diff --git a/src/services/localQuery.js b/src/services/localQuery.js
deleted file mode 100644
index b67c368b..00000000
--- a/src/services/localQuery.js
+++ /dev/null
@@ -1,8 +0,0 @@
-import { nanoid } from "nanoid";
-import { _QUERY_ITEM } from "./consts";
-
-import { getStorageItem, setStorageItem, cleanup } from "./localService";
-
-const localQuery = () => {};
-
-export default localQuery;
diff --git a/src/services/localQuery.ts b/src/services/localQuery.ts
new file mode 100644
index 00000000..16d4d981
--- /dev/null
+++ b/src/services/localQuery.ts
@@ -0,0 +1,8 @@
+// import { nanoid } from "nanoid";
+// import { _QUERY_ITEM } from "./consts";
+
+// import { getStorageItem, setStorageItem, cleanup } from "./localService";
+
+const localQuery = () => {};
+
+export default localQuery;
diff --git a/src/services/localService.js b/src/services/localService.ts
similarity index 70%
rename from src/services/localService.js
rename to src/services/localService.ts
index 8cc08a2b..ffef7a51 100644
--- a/src/services/localService.js
+++ b/src/services/localService.ts
@@ -1,31 +1,31 @@
import { nanoid } from "nanoid";
-function localService(item = null) {
+function localService(item: any = null) {
const _APP = "qryn-query";
const _HISTORY_ITEM = _APP + "-history-item";
const _LABELS_ITEM = _APP + '-labels-item';
- const cleanup = [];
+ const cleanup: any[] = [];
- const getStorageItem = (name) => {
- return localStorage.getItem(name);
+ const getStorageItem = (name: string): string => {
+ return localStorage.getItem(name) || 'null';
};
- const setStorageItem = (name, data) => {
+ const setStorageItem = (name: string, data: string) => {
localStorage.setItem(name, data);
};
- const j_parse = (item) => JSON.parse(item)
- const j_string = (item) => JSON.stringify(item)
- const l_set = (item,value) => { localStorage.setItem(item,value) }
- const l_get = (item) => localStorage.getItem(item)
+ const j_parse = (item: string) => JSON.parse(item)
+ const j_string = (item: any) => JSON.stringify(item)
+ const l_set = (item: string, value: string) => { localStorage.setItem(item,value) }
+ const l_get = (item: string) => localStorage.getItem(item)
const historyStore = () => {
const get = () => {
return JSON.parse(getStorageItem(_HISTORY_ITEM));
};
- const set = (data) => {
+ const set = (data: any) => {
setStorageItem(_HISTORY_ITEM, JSON.stringify(data));
};
@@ -36,20 +36,20 @@ function localService(item = null) {
const historyStorage = get();
- const findById = () => historyStorage.find(({ id }) => item.id === id);
+ const findById = () => historyStorage.find(({ id }: any) => item.id === id);
const getById = () => {
const historyItem = findById();
return historyItem || {};
};
- const update = (item) => {
+ const update = (item: any) => {
const { id } = item;
let newStorage = [];
try {
- newStorage = historyStorage.map((m) =>
+ newStorage = historyStorage.map((m: any) =>
m.id === id ? { ...m, ...item } : m
);
set(newStorage);
@@ -59,7 +59,7 @@ function localService(item = null) {
}
};
- const add = (item) => {
+ const add = (item: any) => {
let previousData = get() || [];
try {
const newItem = {
@@ -78,18 +78,18 @@ function localService(item = null) {
};
function getAll() {
- const actualStorage = JSON.parse(localStorage.getItem(_HISTORY_ITEM))||[]
+ const actualStorage = JSON.parse(localStorage.getItem(_HISTORY_ITEM) || 'null')||[]
return (
- actualStorage?.map((m) => ({
+ actualStorage?.map((m: any) => ({
...m,
data: decodeURI(m.data),
})) || []
);
};
- const remove = (item) => {
- const filtered = historyStorage.filter(({ id }) => id !== item.id);
+ const remove = (item: any) => {
+ const filtered = historyStorage.filter(({ id }: any) => id !== item.id);
set(filtered);
return getAll()
@@ -100,7 +100,7 @@ function localService(item = null) {
const labelsStore = () => {
return function getAll(){
- const actualStorage = JSON.parse(localStorage.getItem(_LABELS_ITEM))||[]
+ const actualStorage = JSON.parse(localStorage.getItem(_LABELS_ITEM) || 'null')||[]
return actualStorage;
}
diff --git a/src/services/localUrl.js b/src/services/localUrl.ts
similarity index 71%
rename from src/services/localUrl.js
rename to src/services/localUrl.ts
index e1a0c6d3..9cc3fc34 100644
--- a/src/services/localUrl.js
+++ b/src/services/localUrl.ts
@@ -7,10 +7,10 @@ const localUrl = () => {
const { l_set, l_get, j_parse, j_string } = localService();
const get = () => {
- return j_parse(l_get(_URL_ITEM));
+ return j_parse(l_get(_URL_ITEM) || "null");
};
- const set = (item) => {
+ const set = (item: any) => {
return l_set(_URL_ITEM, j_string(item));
};
@@ -21,14 +21,14 @@ const localUrl = () => {
const urlStorage = get();
- const findById = (item) =>
- urlStorage.find(({ id }) => item.id === id) || {};
+ const findById = (item: any) =>
+ urlStorage.find(({ id }: any) => item.id === id) || {};
- const update = (item) => {
+ const update = (item: any) => {
const { id } = item;
let newStorage = [];
try {
- newStorage = urlStorage.map((m) =>
+ newStorage = urlStorage.map((m: any) =>
m.id === id ? { ...m, ...item } : m
);
set(newStorage);
@@ -38,14 +38,16 @@ const localUrl = () => {
}
};
- const add = (item) => {
+ const add = (item: any) => {
let previousData = get() || [];
+ const { href, url, type, queryInput, queryType, limit, panel } =
+ item.data;
const { hash } = window.location;
const origin = window.location.origin;
const urlParams = new URLSearchParams(hash.replace("#", ""));
- let paramsData = {};
- urlParams.set("isSubmit", true);
+ let paramsData: any = {};
+ urlParams.set("isSubmit", "true");
for (let [key, value] of urlParams) {
paramsData[key] = value;
}
@@ -60,6 +62,13 @@ const localUrl = () => {
try {
const newItem = {
+ url,
+ href,
+ type,
+ queryInput,
+ queryType,
+ limit,
+ panel,
id: item.id || nanoid(),
timestamp: item.timestamp || Date.now(),
starred: false,
@@ -77,19 +86,20 @@ const localUrl = () => {
}
};
- const remove = (item) => {
- const filtered = urlStorage?.filter(({ id }) => id !== item.id);
+ const remove = (item: any) => {
+ const filtered = urlStorage?.filter(({ id }: any) => id !== item.id);
set(filtered);
return getAll();
};
- const share = (item) => {
+ const share = (item: any) => {
const hash = item.urlParams;
const origin = item.origin;
return `${origin}/#${hash.toString()}`;
};
function getAll() {
- const actualStorage = JSON.parse(localStorage.getItem(_URL_ITEM)) || [];
+ const actualStorage =
+ JSON.parse(localStorage.getItem(_URL_ITEM) || "null") || [];
return actualStorage;
}
diff --git a/src/setupTests.js b/src/setupTests.js
deleted file mode 100644
index 8f2609b7..00000000
--- a/src/setupTests.js
+++ /dev/null
@@ -1,5 +0,0 @@
-// jest-dom adds custom jest matchers for asserting on DOM nodes.
-// allows you to do things like:
-// expect(element).toHaveTextContent(/react/i)
-// learn more: https://github.com/testing-library/jest-dom
-import '@testing-library/jest-dom';
diff --git a/src/store/createInitialState.ts b/src/store/createInitialState.ts
index a97c50c8..a7bc8ef0 100644
--- a/src/store/createInitialState.ts
+++ b/src/store/createInitialState.ts
@@ -195,9 +195,9 @@ export default function initialState() {
lastIdx: 1,
panel: "right",
queryType: "range",
- dataSourceType: "logs",
- dataSourceId:'cHI2SqPzH_kxYRXj',
- dataSourceURL:getDatasourceURL('cHI2SqPzH_kxYRXj'),
+ dataSourceType: "traces",
+ dataSourceId:"32D16h5uYBqUUzhD",
+ dataSourceURL:getDatasourceURL("32D16h5uYBqUUzhD"),
limit: 100,
step: 100,
tableView: false,
@@ -230,6 +230,7 @@ export default function initialState() {
theme: urlState.theme || "light",
isEmptyView: false,
isSplit: false,
+ showDataSourceSetting: true,
};
const debug = state.debugMode;
diff --git a/src/store/reducer.js b/src/store/reducer.ts
similarity index 96%
rename from src/store/reducer.js
rename to src/store/reducer.ts
index 7239056b..a475d9c9 100644
--- a/src/store/reducer.js
+++ b/src/store/reducer.ts
@@ -1,109 +1,111 @@
-const reducer = (state, action) => {
- switch (action.type) {
- case "SET_LABELS":
- return { ...state, labels: action.labels };
- case "SET_LOADING":
- return { ...state, loading: action.loading };
- case "SET_LOGS":
- return { ...state, logs: action.logs };
- case "SET_LABEL_VALUES":
- return { ...state, labelValues: action.labelValues };
- case "SET_START_TIME":
- return { ...state, start: action.start };
- case "SET_STOP_TIME":
- return { ...state, stop: action.stop };
- case "SET_FROM_TIME":
- return { ...state, from: action.from };
- case "SET_TO_TIME":
- return { ...state, to: action.to };
- case "SET_TIME_RANGE_LABEL":
- return { ...state, label: action.label };
- case "SET_QUERY_LIMIT":
- return { ...state, limit: action.limit };
- case "SET_RANGE_OPEN":
- return { ...state, rangeOpen: action.rangeOpen };
- case "SET_BROWSER_OPEN":
- return { ...state, labelsBrowserOpen: action.labelsBrowserOpen };
- case "SET_SETTINGS_MENU_OPEN":
- return { ...state, settingsMenuOpen: action.settingsMenuOpen };
- case "SET_TIME_PICKER_OPEN":
- return { ...state, timePickerOpen: action.timePickerOpen };
- case "SET_SETTINGS_DIALOG_OPEN":
- return { ...state, settingsDialogOpen: action.settingsDialogOpen };
- case "SET_QUERY":
- return { ...state, query: action.query };
- case "SET_QUERY_STEP":
- return { ...state, step: action.step };
- case "SET_API_URL":
- return { ...state, apiUrl: action.apiUrl };
- case "SET_API_ERRORS":
- return { ...state, apiErrors: action.apiErrors };
- case "SET_URL_QUERY_PARAMS":
- return { ...state, urlQueryParams: action.urlQueryParams };
- case "SET_QUERY_TYPE":
- return { ...state, queryType: action.queryType };
- case "SET_URL_LOCATION":
- return { ...state, urlLocation: action.urlLocation };
- case "SET_IS_SUBMIT":
- return { ...state, isSubmit: action.isSubmit };
- case "SET_IS_EMBED":
- return { ...state, isEmbed: action.isEmbed };
- case "SET_MATRIX_DATA":
- return { ...state, matrixData: action.matrixData };
- case "SET_CHART_TYPE":
- return { ...state, chartType: action.setChartType };
- case "SET_QUERY_HISTORY":
- return { ...state, queryHistory: action.queryHistory };
- case "SET_LINKS_HISTORY":
- return { ...state, linksHistory: action.linksHistory };
- case "SET_HISTORY_OPEN":
- return { ...state, historyOpen: action.historyOpen };
- case "ADD_NOTIFICATION":
- return { ...state, notifications: action.payload };
- case "REMOVE_NOTIFICATION":
- return { ...state, notifications: action.payload };
- case "SET_DEBUG_MODE":
- return { ...state, debugMode: action.debugMode };
- case "SET_THEME":
- return { ...state, theme: action.theme };
- case "SET_AUTO_THEME":
- return { ...state, autoTheme: action.autoTheme };
- case "SET_TABLE_DATA":
- return { ...state, tableData: action.tableData };
- case "SET_QUERY_TIME":
- return { ...state, time: action.time };
- case "SET_QUERY_RESOLUTION":
- return { ...state, queryResolution: action.queryResolution };
- case "SET_IS_EMPTY_VIEW":
- return { ...state, isEmptyView: action.isEmptyView };
- case "SET_VECTOR_DATA":
- return { ...state, vectorData: action.vectorData };
- case "SET_RESPONSE_TYPE":
- return { ...state, responseType: action.responseType };
- case "SET_IS_TABLE_VIEW":
- return { ...state, isTableView: action.isTableView };
- case "SET_SPLIT_VIEW":
- return { ...state, isSplit: action.isSplit };
- case "SET_PANELS_DATA":
- return { ...state, panels: action.panels };
- case "SET_DATA_VIEWS":
- return { ...state, dataViews: action.dataViews };
- case "SET_RIGHT_DATAVIEW":
- return { ...state, rightDataView: action.rightDataView };
- case "SET_LEFT_DATAVIEW":
- return { ...state, leftDataView: action.leftDataView };
- case "SET_RIGHT_PANEL":
- return { ...state, right: action.right };
- case "SET_LEFT_PANEL":
- return { ...state, left: action.left };
- case "SET_DATA_SOURCES":
- return { ...state, dataSources: action.dataSources };
- case "SET_IS_DATASOURCE_SAVED":
- return {...state, isDsSaved: action.isDsSaved};
- default:
- return { ...state };
- }
-};
-
-export default reducer;
-
+const reducer = (state: any, action: any) => {
+ switch (action.type) {
+ case "SET_LABELS":
+ return { ...state, labels: action.labels };
+ case "SET_LOADING":
+ return { ...state, loading: action.loading };
+ case "SET_LOGS":
+ return { ...state, logs: action.logs };
+ case "SET_LABEL_VALUES":
+ return { ...state, labelValues: action.labelValues };
+ case "SET_START_TIME":
+ return { ...state, start: action.start };
+ case "SET_STOP_TIME":
+ return { ...state, stop: action.stop };
+ case "SET_FROM_TIME":
+ return { ...state, from: action.from };
+ case "SET_TO_TIME":
+ return { ...state, to: action.to };
+ case "SET_TIME_RANGE_LABEL":
+ return { ...state, label: action.label };
+ case "SET_QUERY_LIMIT":
+ return { ...state, limit: action.limit };
+ case "SET_RANGE_OPEN":
+ return { ...state, rangeOpen: action.rangeOpen };
+ case "SET_BROWSER_OPEN":
+ return { ...state, labelsBrowserOpen: action.labelsBrowserOpen };
+ case "SET_SETTINGS_MENU_OPEN":
+ return { ...state, settingsMenuOpen: action.settingsMenuOpen };
+ case "SET_TIME_PICKER_OPEN":
+ return { ...state, timePickerOpen: action.timePickerOpen };
+ case "SET_SETTINGS_DIALOG_OPEN":
+ return { ...state, settingsDialogOpen: action.settingsDialogOpen };
+ case "SET_QUERY":
+ return { ...state, query: action.query };
+ case "SET_QUERY_STEP":
+ return { ...state, step: action.step };
+ case "SET_API_URL":
+ return { ...state, apiUrl: action.apiUrl };
+ case "SET_API_ERRORS":
+ return { ...state, apiErrors: action.apiErrors };
+ case "SET_URL_QUERY_PARAMS":
+ return { ...state, urlQueryParams: action.urlQueryParams };
+ case "SET_QUERY_TYPE":
+ return { ...state, queryType: action.queryType };
+ case "SET_URL_LOCATION":
+ return { ...state, urlLocation: action.urlLocation };
+ case "SET_IS_SUBMIT":
+ return { ...state, isSubmit: action.isSubmit };
+ case "SET_IS_EMBED":
+ return { ...state, isEmbed: action.isEmbed };
+ case "SET_MATRIX_DATA":
+ return { ...state, matrixData: action.matrixData };
+ case "SET_CHART_TYPE":
+ return { ...state, chartType: action.setChartType };
+ case "SET_QUERY_HISTORY":
+ return { ...state, queryHistory: action.queryHistory };
+ case "SET_LINKS_HISTORY":
+ return { ...state, linksHistory: action.linksHistory };
+ case "SET_HISTORY_OPEN":
+ return { ...state, historyOpen: action.historyOpen };
+ case "ADD_NOTIFICATION":
+ return { ...state, notifications: action.payload };
+ case "REMOVE_NOTIFICATION":
+ return { ...state, notifications: action.payload };
+ case "SET_DEBUG_MODE":
+ return { ...state, debugMode: action.debugMode };
+ case "SET_THEME":
+ return { ...state, theme: action.theme };
+ case "SET_AUTO_THEME":
+ return { ...state, autoTheme: action.autoTheme };
+ case "SET_TABLE_DATA":
+ return { ...state, tableData: action.tableData };
+ case "SET_QUERY_TIME":
+ return { ...state, time: action.time };
+ case "SET_QUERY_RESOLUTION":
+ return { ...state, queryResolution: action.queryResolution };
+ case "SET_IS_EMPTY_VIEW":
+ return { ...state, isEmptyView: action.isEmptyView };
+ case "SET_VECTOR_DATA":
+ return { ...state, vectorData: action.vectorData };
+ case "SET_RESPONSE_TYPE":
+ return { ...state, responseType: action.responseType };
+ case "SET_IS_TABLE_VIEW":
+ return { ...state, isTableView: action.isTableView };
+ case "SET_SPLIT_VIEW":
+ return { ...state, isSplit: action.isSplit };
+ case "SET_PANELS_DATA":
+ return { ...state, panels: action.panels };
+ case "SET_DATA_VIEWS":
+ return { ...state, dataViews: action.dataViews };
+ case "SET_RIGHT_DATAVIEW":
+ return { ...state, rightDataView: action.rightDataView };
+ case "SET_LEFT_DATAVIEW":
+ return { ...state, leftDataView: action.leftDataView };
+ case "SET_RIGHT_PANEL":
+ return { ...state, right: action.right };
+ case "SET_LEFT_PANEL":
+ return { ...state, left: action.left };
+ case "SET_DATA_SOURCES":
+ return { ...state, dataSources: action.dataSources };
+ case "SET_IS_DATASOURCE_SAVED":
+ return {...state, isDsSaved: action.isDsSaved};
+ case "SHOW_DATA_SOURCE_SETTING":
+ return {...state, showDataSourceSetting: action.showDataSourceSetting}
+ default:
+ return { ...state };
+ }
+};
+
+export default reducer;
+
diff --git a/src/store/store.model.ts b/src/store/store.model.ts
index ef6db82f..542cdeb3 100644
--- a/src/store/store.model.ts
+++ b/src/store/store.model.ts
@@ -35,8 +35,8 @@ export interface Store {
isEmbed: string;
left: Panel[];
right: Panel[];
- leftDataView: any[];
- rightDataView: any[];
+ leftDataView: DataViews;
+ rightDataView: DataViews;
chartType: string;
resposeType: string;
notifications: any[];
@@ -108,3 +108,49 @@ export interface URLQueryParams {
isSplit: string;
autoTheme: string;
}
+export type DataViews = DataView[];
+
+export interface DataView {
+ id: string;
+ type: string;
+ tableData: TableData;
+ data: Datum[];
+ labels: string[];
+ total: number;
+ loading: boolean;
+}
+
+export interface Datum {
+ type: string;
+ timestamp: number;
+ text: string;
+ tags: Tags;
+ isShowTs: boolean;
+ showLabels: boolean;
+ id: string;
+}
+
+export interface Tags {
+ job: string;
+ level: string;
+}
+
+export interface TableData {
+ columnsData: ColumnsDatum[];
+ dataRows: DataRow[];
+ length: number;
+}
+
+export interface ColumnsDatum {
+ Header: string;
+ accessor: string;
+ width?: number;
+ minWidth?: number;
+ maxWidth?: number;
+}
+
+export interface DataRow {
+ time: string;
+ stream: string;
+ log: string;
+}
diff --git a/src/store/store.js b/src/store/store.ts
similarity index 100%
rename from src/store/store.js
rename to src/store/store.ts
diff --git a/src/views/DataSources/DataSource.js b/src/views/DataSources/DataSource.js
index 2116fa9e..bad1dcda 100644
--- a/src/views/DataSources/DataSource.js
+++ b/src/views/DataSources/DataSource.js
@@ -1,6 +1,7 @@
import { css, cx } from "@emotion/css";
import { ThemeProvider } from "@emotion/react";
import { useMemo } from "react";
+import { useCookies } from "react-cookie";
import { useDispatch, useSelector } from "react-redux";
import { useParams } from "react-router-dom";
import { createAlert } from "../../actions";
@@ -30,6 +31,8 @@ export function DataSourceSetting(props) {
},
} = props;
+ const [cookie, setCookie] = useCookies(["qryn-dev-cookie"]); // for testing cookies feature
+
const dispatch = useDispatch();
const dataSources = useSelector((store) => store.dataSources);
const useForAll = () => {
@@ -56,29 +59,61 @@ export function DataSourceSetting(props) {
},
},
}));
+
+ // uncomment for testing cookies feature
+
localStorage.setItem("dataSources", JSON.stringify(newDs));
dispatch(setDataSources(newDs));
- dispatch(createAlert({
- type:'success',
- message:'Set same URL and Basic Auth for All Data Sources'
- }))
+ dispatch(
+ createAlert({
+ type: "success",
+ message: "Set same URL and Basic Auth for All Data Sources",
+ })
+ );
};
+
+ function addCookie() {
+ var today = new Date();
+ var tomorrow = new Date();
+ tomorrow.setDate(today.getDate() + 1);
+ const parsedDs = JSON.stringify({ url });
+ try {
+ setCookie(
+ `qryn-settings`,
+ `${btoa(user.value)}:${btoa(password.value)}@${btoa(parsedDs)}`,
+ { path: "/" }
+ );
+ } catch (e) {
+ console.log(e);
+ }
+ }
+
return (
);
@@ -122,7 +157,6 @@ export function DataSource() {
-