From d01b6589a3ae9a59318b57d904cfcd9584cd0201 Mon Sep 17 00:00:00 2001 From: jacovinus Date: Tue, 13 Dec 2022 00:25:46 +0100 Subject: [PATCH 01/40] feat: #131 --- .../SpanDetail/AccordianLogs.tsx | 31 ++++++++++++++----- .../SpanDetail/DetailState.tsx | 23 ++++++++++++++ .../TraceTimelineViewer/SpanDetail/index.tsx | 14 +++++++++ .../src/TraceTimelineViewer/SpanDetailRow.tsx | 3 ++ .../VirtualizedTraceView.tsx | 3 ++ .../src/TraceTimelineViewer/index.tsx | 1 + .../Traces/Jaeger-ui/src/types/trace.ts | 1 + .../Traces/Jaeger-ui/src/uberUtilityStyles.ts | 2 +- .../DataViews/components/Traces/TraceView.tsx | 2 ++ .../components/Traces/mapTracesResponse.js | 1 + .../components/Traces/useDetailState.ts | 27 ++++++++++++++++ 11 files changed, 100 insertions(+), 8 deletions(-) diff --git a/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx b/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx index e7e168bd..5516c3f4 100644 --- a/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx +++ b/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx @@ -39,9 +39,12 @@ const AccordianLogsContent = styled.div` padding: 0.5rem 0.5rem 0.25rem 0.5rem; `; const AccordianLogsHeader = css` + display: flex; + align-items: center; background: #e4e4e4; color: inherit; - display: block; + + font-size: 12px; padding: 0.25rem 0.5rem; &:hover { background: #dadada; @@ -77,9 +80,15 @@ export default function AccordianLogs(props: AccordianLogsProps) { let headerProps: {} | null = null; if (interactive) { arrow = isOpen ? ( - + ) : ( - + ); HeaderComponent = "a"; headerProps = { @@ -88,20 +97,28 @@ export default function AccordianLogs(props: AccordianLogsProps) { role: "switch", }; } - + const logsMemo = React.useMemo(() => { + return logs.map((t: any) => { + const fields = Object.keys(t)?.filter((f) => f !== "timeUnixNano"); + return { + timestamp: parseInt(t.timeUnixNano) / 1000, + fields: fields.map((m) => ({ key: m, value: t[m] })), + }; + }); + }, [logs]); // const styles = useStyles2(getStyles); return ( - {arrow} Events ({logs.length}) + {arrow} Events ({logsMemo.length}) {isOpen && ( - {_sortBy(logs, "timestamp").map((log, i) => ( + {_sortBy(logsMemo, "timestamp").map((log, i) => ( }; + events: {isOpen: boolean; openedItems: Set} references: { isOpen: boolean; openedItems: Set }; isWarningsOpen: boolean; isStackTracesOpen: boolean; @@ -29,14 +31,17 @@ export default class DetailState { constructor(oldState?: DetailState) { const { isTagsOpen, + isEventsOpen, isProcessOpen, isReferencesOpen, isWarningsOpen, isStackTracesOpen, logs, references, + events, }: DetailState | Record = oldState || {}; this.isTagsOpen = Boolean(isTagsOpen); + this.isEventsOpen = Boolean(isEventsOpen) this.isProcessOpen = Boolean(isProcessOpen); this.isReferencesOpen = Boolean(isReferencesOpen); this.isWarningsOpen = Boolean(isWarningsOpen); @@ -45,6 +50,10 @@ export default class DetailState { isOpen: Boolean(logs && logs.isOpen), openedItems: logs && logs.openedItems ? new Set(logs.openedItems) : new Set(), }; + this.events = { + isOpen: Boolean(events && events.isOpen), + openedItems: events && events.openedItems ? new Set(events.openedItems) : new Set(), + } this.references = { isOpen: Boolean(references && references.isOpen), openedItems: references && references.openedItems ? new Set(references.openedItems) : new Set(), @@ -57,6 +66,20 @@ export default class DetailState { return next; } + toggleEvents() { + const next = new DetailState(this); + next.isEventsOpen = !this.isEventsOpen; + return next; + } + toggleEventItem(eventItem:any){ + const next = new DetailState(this); + if(next.events.openedItems.has(eventItem)) { + next.events.openedItems.delete(eventItem) + } else { + next.events.openedItems.add(eventItem) + } + return next + } toggleProcess() { const next = new DetailState(this); next.isProcessOpen = !this.isProcessOpen; diff --git a/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/index.tsx b/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/index.tsx index 436785a0..46caa3af 100644 --- a/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/index.tsx +++ b/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/index.tsx @@ -91,6 +91,7 @@ type SpanDetailProps = { logItemToggle: (spanID: string, log: TraceLog) => void; logsToggle: (spanID: string) => void; processToggle: (spanID: string) => void; + eventsToggle: (spanID:string) => void; span: TraceSpan; // timeZone: TimeZone; tagsToggle: (spanID: string) => void; @@ -209,6 +210,19 @@ export default function SpanDetail(props: SpanDetailProps) { /> )} + {span?.events?.length > 0 && ( + logsToggle(spanID)} + onItemToggle={(logItem) => + logItemToggle(spanID, logItem) + } + timestamp={traceStartTime} + /> + )} {logs && logs.length > 0 && ( TraceLink[]; logItemToggle: (spanID: string, log: TraceLog) => void; logsToggle: (spanID: string) => void; + eventsToggle: (spanID: string) => void; processToggle: (spanID: string) => void; referenceItemToggle: ( spanID: string, @@ -117,6 +118,7 @@ export class UnthemedSpanDetailRow extends React.PureComponent void; detailLogItemToggle: (spanID: string, log: TraceLog) => void; detailLogsToggle: (spanID: string) => void; + detailEventsToggle: (spanID: string) => void; detailWarningsToggle: (spanID: string) => void; detailStackTracesToggle: (spanID: string) => void; detailReferencesToggle: (spanID: string) => void; @@ -518,6 +519,7 @@ export class UnthemedVirtualizedTraceView extends React.Component void; clearShouldScrollToFirstUiFindMatch: () => void; + detailEventsToggle: (spanID: string) => void; detailLogItemToggle: (spanID: string, log: TraceLog) => void; detailLogsToggle: (spanID: string) => void; detailWarningsToggle: (spanID: string) => void; diff --git a/src/components/DataViews/components/Traces/Jaeger-ui/src/types/trace.ts b/src/components/DataViews/components/Traces/Jaeger-ui/src/types/trace.ts index 4e180189..9b87124d 100644 --- a/src/components/DataViews/components/Traces/Jaeger-ui/src/types/trace.ts +++ b/src/components/DataViews/components/Traces/Jaeger-ui/src/types/trace.ts @@ -73,6 +73,7 @@ export type TraceSpan = TraceSpanData & { relativeStartTime: number; tags: NonNullable; references: NonNullable; + events:any; warnings: NonNullable; subsidiarilyReferencedBy: TraceSpanReference[]; }; diff --git a/src/components/DataViews/components/Traces/Jaeger-ui/src/uberUtilityStyles.ts b/src/components/DataViews/components/Traces/Jaeger-ui/src/uberUtilityStyles.ts index ff8f8585..a9040ee0 100644 --- a/src/components/DataViews/components/Traces/Jaeger-ui/src/uberUtilityStyles.ts +++ b/src/components/DataViews/components/Traces/Jaeger-ui/src/uberUtilityStyles.ts @@ -57,7 +57,7 @@ export const ubInlineBlock = css` `; export const uAlignIcon = css` - margin: -0.2rem 0.25rem 0 0; + // margin: -0.2rem 0.25rem 0 0; `; export const uTxEllipsis = css` diff --git a/src/components/DataViews/components/Traces/TraceView.tsx b/src/components/DataViews/components/Traces/TraceView.tsx index 45c4c8a9..7609f0c0 100644 --- a/src/components/DataViews/components/Traces/TraceView.tsx +++ b/src/components/DataViews/components/Traces/TraceView.tsx @@ -87,6 +87,7 @@ export function TraceView(props: any) { toggleDetail, detailLogItemToggle, detailLogsToggle, + detailEventsToggle, detailProcessToggle, detailReferencesToggle, detailReferenceItemToggle, @@ -176,6 +177,7 @@ export function TraceView(props: any) { clearShouldScrollToFirstUiFindMatch={noop} detailLogItemToggle={detailLogItemToggle} detailLogsToggle={detailLogsToggle} + detailEventsToggle={detailEventsToggle} detailWarningsToggle={detailWarningsToggle} detailStackTracesToggle={detailStackTracesToggle} detailReferencesToggle={detailReferencesToggle} diff --git a/src/components/DataViews/components/Traces/mapTracesResponse.js b/src/components/DataViews/components/Traces/mapTracesResponse.js index 0e1600f5..9191c3fd 100644 --- a/src/components/DataViews/components/Traces/mapTracesResponse.js +++ b/src/components/DataViews/components/Traces/mapTracesResponse.js @@ -202,6 +202,7 @@ export function mapTracesResponse(data) { startTime, duration, relativeStartTime: 0, + events:m?.events || [], logs: [], references: [], tags, diff --git a/src/components/DataViews/components/Traces/useDetailState.ts b/src/components/DataViews/components/Traces/useDetailState.ts index 479b8b34..e5c5877e 100644 --- a/src/components/DataViews/components/Traces/useDetailState.ts +++ b/src/components/DataViews/components/Traces/useDetailState.ts @@ -31,6 +31,20 @@ export function useDetailState(frame: any) { [detailStates] ); + const detailEventsItemToggle = useCallback( + function detailEventsItemToggle(spanID:string, event: any) { + const old = detailStates.get(spanID); + if(!old){ + return; + } + const detailState = old.toggleEventItem(event); + const newDetailStates = new Map(detailStates); + newDetailStates.set(spanID, detailState); + return setDetailStates(newDetailStates); + }, + [detailStates] + ) + const detailLogItemToggle = useCallback( function detailLogItemToggle(spanID: string, log: TraceLog) { const old = detailStates.get(spanID); @@ -75,6 +89,16 @@ export function useDetailState(frame: any) { )(spanID), [detailStates] ), + detailEventsItemToggle, + detailEventsToggle: useCallback( + (spanID: string) => + makeDetailSubsectionToggle( + 'events', + detailStates, + setDetailStates + )(spanID), + [detailStates] + ), detailWarningsToggle: useCallback( (spanID: string) => makeDetailSubsectionToggle( @@ -129,6 +153,7 @@ function makeDetailSubsectionToggle( | "tags" | "process" | "logs" + | "events" | "warnings" | "references" | "stackTraces", @@ -145,6 +170,8 @@ function makeDetailSubsectionToggle( detailState = old.toggleTags(); } else if (subSection === "process") { detailState = old.toggleProcess(); + } else if (subSection === "events") { + detailState = old.toggleEvents(); } else if (subSection === "warnings") { detailState = old.toggleWarnings(); } else if (subSection === "references") { From bb27c4b7b14556f8f0ef3a4624b5fe683380ce8e Mon Sep 17 00:00:00 2001 From: jacovinus Date: Tue, 13 Dec 2022 11:01:59 +0100 Subject: [PATCH 02/40] fix: trace events styles --- .../SpanDetail/AccordianKeyValues.tsx | 35 ++++++++++++------- .../SpanDetail/AccordianLogs.tsx | 14 ++++---- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianKeyValues.tsx b/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianKeyValues.tsx index 7ccb85cd..822955d6 100644 --- a/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianKeyValues.tsx +++ b/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianKeyValues.tsx @@ -27,14 +27,14 @@ import styled from "@emotion/styled"; const header = css` cursor: pointer; overflow: hidden; - display:flex; - align-items:center; + display: flex; + align-items: center; padding: 0.25em 0.1em; - font-size:12px; + font-size: 12px; text-overflow: ellipsis; white-space: nowrap; &:hover { - // background: #e8e8e8; + // background: #e8e8e8; } `; const headerEmpty = css` @@ -43,11 +43,11 @@ const headerEmpty = css` `; const headerHighContrast = css` &:hover { - // background: #ddd; + // background: #ddd; } `; export const emptyIcon = css` - // color: #aaa; + // color: #aaa; `; const Summary = styled.ul` display: inline; @@ -110,10 +110,7 @@ KeyValuesSummary.defaultProps = { data: null, }; -export default function AccordianKeyValues(props:any) { - - - +export default function AccordianKeyValues(props: any) { const { className, data, @@ -130,9 +127,15 @@ export default function AccordianKeyValues(props:any) { let headerProps: {} | null = null; if (interactive) { arrow = isOpen ? ( - + ) : ( - + ); headerProps = { "aria-checked": isOpen, @@ -158,7 +161,13 @@ export default function AccordianKeyValues(props:any) { {!isOpen && } - {isOpen && } + {isOpen && ( + + )} ); } diff --git a/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx b/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx index 5516c3f4..45e0b36b 100644 --- a/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx +++ b/src/components/DataViews/components/Traces/Jaeger-ui/src/TraceTimelineViewer/SpanDetail/AccordianLogs.tsx @@ -25,29 +25,29 @@ import { formatDuration } from "../utils"; import AccordianKeyValues from "./AccordianKeyValues"; import styled from "@emotion/styled"; const AccordianLogsStyled = styled.div` - border: 1px solid #d8d8d8; + // border: 1px solid #d8d8d8; position: relative; margin-bottom: 0.25rem; `; const AccordianLogsFooter = styled.small` - color: #999; +// color: #999; font-size: 80%; `; const AccordianLogsContent = styled.div` - background: #f0f0f0; - border-top: 1px solid #d8d8d8; - padding: 0.5rem 0.5rem 0.25rem 0.5rem; + // background: #f0f0f0; + // border-top: 1px solid #d8d8d8; + // padding: 0.5rem 0.5rem 0.25rem 0.5rem; `; const AccordianLogsHeader = css` display: flex; align-items: center; - background: #e4e4e4; + // background: #e4e4e4; color: inherit; font-size: 12px; padding: 0.25rem 0.5rem; &:hover { - background: #dadada; + // background: #dadada; } `; From 99d6c87d13037bf6bf4b7b43badbce1e38c0ca07 Mon Sep 17 00:00:00 2001 From: Eduard Klimenko Date: Tue, 13 Dec 2022 16:57:52 +0200 Subject: [PATCH 03/40] .js to .ts(tsx) for actions & helper --- .../{createAlert.js => createAlert.ts} | 0 .../{errorHandler.js => errorHandler.ts} | 138 +++--- src/actions/helpers/boscoRequest.js | 32 -- src/actions/helpers/boscoRequest.ts | 30 ++ .../{convertFlux.js => convertFlux.ts} | 18 +- src/actions/helpers/{index.js => index.ts} | 12 +- .../{prepareCols.js => prepareCols.ts} | 80 ++-- ...pareVectorRows.js => prepareVectorRows.ts} | 94 ++-- .../{scrollbarWidth.js => scrollbarWidth.ts} | 34 +- .../{setColumnsData.js => setColumnsData.ts} | 46 +- ...setColumnsValue.js => setColumnsValue.tsx} | 422 +++++++++--------- src/actions/helpers/timeParser.ts | 6 +- src/actions/{index.js => index.ts} | 54 +-- ...{loadLabelValues.js => loadLabelValues.ts} | 164 +++---- .../{removeAlert.js => removeAlert.ts} | 0 .../{setApiError.js => setApiError.ts} | 0 src/actions/{setApiUrl.js => setApiUrl.ts} | 0 .../{setApiWarning.js => setApiWarning.ts} | 14 +- .../{setDataViews.js => setDataViews.ts} | 0 .../{setDebugMode.js => setDebugMode.ts} | 0 .../{setDirection.js => setDirection.ts} | 0 .../{setFromTime.js => setFromTime.ts} | 14 +- .../{setHistoryOpen.js => setHistoryOpen.ts} | 0 src/actions/{setIsEmbed.js => setIsEmbed.ts} | 0 .../{setIsEmptyView.js => setIsEmptyView.ts} | 14 +- .../{setIsSubmit.js => setIsSubmit.ts} | 0 .../{setIsTableView.js => setIsTableView.ts} | 0 .../{setLabelValues.js => setLabelValues.ts} | 14 +- src/actions/{setLabels.js => setLabels.ts} | 12 +- ...{setLeftDataView.js => setLeftDataView.ts} | 0 .../{setLeftPanel.js => setLeftPanel.ts} | 0 ...{setLinksHistory.js => setLinksHistory.ts} | 0 src/actions/{setLoading.js => setLoading.ts} | 0 src/actions/{setLogs.js => setLogs.ts} | 0 .../{setMatrixData.js => setMatrixData.ts} | 0 ...etPanelResponse.js => setPanelResponse.ts} | 0 .../{setPanelsData.js => setPanelsData.ts} | 0 ...{setQueryHistory.js => setQueryHistory.ts} | 0 .../{setQueryLimit.js => setQueryLimit.ts} | 12 +- .../{setQueryStep.js => setQueryStep.ts} | 0 .../{setQueryTime.js => setQueryTime.ts} | 12 +- .../{setQueryType.js => setQueryType.ts} | 12 +- .../{setRangeOpen.js => setRangeOpen.ts} | 0 ...{setResponseType.js => setResponseType.ts} | 0 ...etRightDataView.js => setRightDataView.ts} | 0 .../{setRightPanel.js => setRightPanel.ts} | 0 ...DialogOpen.js => setSettingsDialogOpen.ts} | 0 .../{setStartTime.js => setStartTime.ts} | 0 .../{setStopTime.js => setStopTime.ts} | 0 .../{setTableData.js => setTableData.ts} | 12 +- src/actions/{setTheme.js => setTheme.ts} | 0 ...TimeRangeLabel.js => setTimeRangeLabel.ts} | 0 src/actions/{setToTime.js => setToTime.ts} | 0 .../{setUrlLocation.js => setUrlLocation.ts} | 0 ...UrlQueryParams.js => setUrlQueryParams.ts} | 0 .../{setVectorData.js => setVectorData.ts} | 12 +- 56 files changed, 630 insertions(+), 628 deletions(-) rename src/actions/{createAlert.js => createAlert.ts} (100%) rename src/actions/{errorHandler.js => errorHandler.ts} (96%) delete mode 100644 src/actions/helpers/boscoRequest.js create mode 100644 src/actions/helpers/boscoRequest.ts rename src/actions/helpers/{convertFlux.js => convertFlux.ts} (81%) rename src/actions/helpers/{index.js => index.ts} (96%) rename src/actions/helpers/{prepareCols.js => prepareCols.ts} (83%) rename src/actions/helpers/{prepareVectorRows.js => prepareVectorRows.ts} (89%) rename src/actions/helpers/{scrollbarWidth.js => scrollbarWidth.ts} (97%) rename src/actions/helpers/{setColumnsData.js => setColumnsData.ts} (71%) rename src/actions/helpers/{setColumnsValue.js => setColumnsValue.tsx} (81%) rename src/actions/{index.js => index.ts} (97%) rename src/actions/{loadLabelValues.js => loadLabelValues.ts} (96%) rename src/actions/{removeAlert.js => removeAlert.ts} (100%) rename src/actions/{setApiError.js => setApiError.ts} (100%) rename src/actions/{setApiUrl.js => setApiUrl.ts} (100%) rename src/actions/{setApiWarning.js => setApiWarning.ts} (96%) rename src/actions/{setDataViews.js => setDataViews.ts} (100%) rename src/actions/{setDebugMode.js => setDebugMode.ts} (100%) rename src/actions/{setDirection.js => setDirection.ts} (100%) rename src/actions/{setFromTime.js => setFromTime.ts} (95%) rename src/actions/{setHistoryOpen.js => setHistoryOpen.ts} (100%) rename src/actions/{setIsEmbed.js => setIsEmbed.ts} (100%) rename src/actions/{setIsEmptyView.js => setIsEmptyView.ts} (95%) rename src/actions/{setIsSubmit.js => setIsSubmit.ts} (100%) rename src/actions/{setIsTableView.js => setIsTableView.ts} (100%) rename src/actions/{setLabelValues.js => setLabelValues.ts} (95%) rename src/actions/{setLabels.js => setLabels.ts} (95%) rename src/actions/{setLeftDataView.js => setLeftDataView.ts} (100%) rename src/actions/{setLeftPanel.js => setLeftPanel.ts} (100%) rename src/actions/{setLinksHistory.js => setLinksHistory.ts} (100%) rename src/actions/{setLoading.js => setLoading.ts} (100%) rename src/actions/{setLogs.js => setLogs.ts} (100%) rename src/actions/{setMatrixData.js => setMatrixData.ts} (100%) rename src/actions/{setPanelResponse.js => setPanelResponse.ts} (100%) rename src/actions/{setPanelsData.js => setPanelsData.ts} (100%) rename src/actions/{setQueryHistory.js => setQueryHistory.ts} (100%) rename src/actions/{setQueryLimit.js => setQueryLimit.ts} (95%) rename src/actions/{setQueryStep.js => setQueryStep.ts} (100%) rename src/actions/{setQueryTime.js => setQueryTime.ts} (95%) rename src/actions/{setQueryType.js => setQueryType.ts} (95%) rename src/actions/{setRangeOpen.js => setRangeOpen.ts} (100%) rename src/actions/{setResponseType.js => setResponseType.ts} (100%) rename src/actions/{setRightDataView.js => setRightDataView.ts} (100%) rename src/actions/{setRightPanel.js => setRightPanel.ts} (100%) rename src/actions/{setSettingsDialogOpen.js => setSettingsDialogOpen.ts} (100%) rename src/actions/{setStartTime.js => setStartTime.ts} (100%) rename src/actions/{setStopTime.js => setStopTime.ts} (100%) rename src/actions/{setTableData.js => setTableData.ts} (95%) rename src/actions/{setTheme.js => setTheme.ts} (100%) rename src/actions/{setTimeRangeLabel.js => setTimeRangeLabel.ts} (100%) rename src/actions/{setToTime.js => setToTime.ts} (100%) rename src/actions/{setUrlLocation.js => setUrlLocation.ts} (100%) rename src/actions/{setUrlQueryParams.js => setUrlQueryParams.ts} (100%) rename src/actions/{setVectorData.js => setVectorData.ts} (95%) diff --git a/src/actions/createAlert.js b/src/actions/createAlert.ts similarity index 100% rename from src/actions/createAlert.js rename to src/actions/createAlert.ts diff --git a/src/actions/errorHandler.js b/src/actions/errorHandler.ts similarity index 96% rename from src/actions/errorHandler.js rename to src/actions/errorHandler.ts index 2d1f8942..1f8b9fea 100644 --- a/src/actions/errorHandler.js +++ b/src/actions/errorHandler.ts @@ -1,69 +1,69 @@ -export const errorHandler = (error) => { - - const LABELS_URL = "/loki/api/v1/label"; - const QUERY_URL = "/loki/api/v1/query_range"; - - const { request, response } = error; - const url = error?.response?.request?.responseURL - - - let type = () => { - switch(url) { - case url?.includes(LABELS_URL): - return 'label'; - case url?.includes(QUERY_URL): - return 'query' - default: return 'label' - } - } - - if (response?.statusText) { - const status = response?.status; - - return { - message: "API " + response.statusText + ", Please adjust API URL", - status, - type: type() - }; - } else if (url && !url.includes(window.location.protocol)) { - - return { - message: "Mixed Content Error, your View should be over same protocol as your API", - status: 500, - type : type() - }; - } else if (request) { - if (error.stack.includes('Network Error')) { - return { - message: "Invalid API URL, please adjust API URL", - status: 500, - type: type() - } - } - return { - message: "server time out", - status: response?.status, - type: type() - }; - } else if (error?.stack?.includes("Invalid URL")) { - return { - message: "Invalid API URL, please adjust API URL", - stauts: response?.status, - type: type() - }; - } else if (error?.response?.status === 404) { - return { - message: "Invalid API URL, please adjust API URL", - status: response?.status, - type: type() - }; - } else { - if (type === 'labels') return; - - return { - message: "something went wrong with request", - status: response?.status, - type: type() - }; - } -}; +export const errorHandler = (error) => { + + const LABELS_URL = "/loki/api/v1/label"; + const QUERY_URL = "/loki/api/v1/query_range"; + + const { request, response } = error; + const url = error?.response?.request?.responseURL + + + let type = () => { + switch(url) { + case url?.includes(LABELS_URL): + return 'label'; + case url?.includes(QUERY_URL): + return 'query' + default: return 'label' + } + } + + if (response?.statusText) { + const status = response?.status; + + return { + message: "API " + response.statusText + ", Please adjust API URL", + status, + type: type() + }; + } else if (url && !url.includes(window.location.protocol)) { + + return { + message: "Mixed Content Error, your View should be over same protocol as your API", + status: 500, + type : type() + }; + } else if (request) { + if (error.stack.includes('Network Error')) { + return { + message: "Invalid API URL, please adjust API URL", + status: 500, + type: type() + } + } + return { + message: "server time out", + status: response?.status, + type: type() + }; + } else if (error?.stack?.includes("Invalid URL")) { + return { + message: "Invalid API URL, please adjust API URL", + stauts: response?.status, + type: type() + }; + } else if (error?.response?.status === 404) { + return { + message: "Invalid API URL, please adjust API URL", + status: response?.status, + type: type() + }; + } else { + if (type === 'labels') return; + + return { + message: "something went wrong with request", + status: response?.status, + type: type() + }; + } +}; diff --git a/src/actions/helpers/boscoRequest.js b/src/actions/helpers/boscoRequest.js deleted file mode 100644 index 2dbf343d..00000000 --- a/src/actions/helpers/boscoRequest.js +++ /dev/null @@ -1,32 +0,0 @@ - - -const boscoInit = (params) => { - window.bosco.init( - { - endpoint: params.url, - } - ) - - -} - -export default function boscoRequest(src, params){ - - return new Promise((resolve, reject)=> { - const script = document.createElement('script') - script.setAttribute('src', src) - - script.addEventListener('load', () => { - resolve( boscoInit(params)) - }) - script.addEventListener('error', reject) - document.body.appendChild(script) - }) - -} - - - -export function boscoSend(data,id) { - window.bosco.send(data,id) -} \ No newline at end of file diff --git a/src/actions/helpers/boscoRequest.ts b/src/actions/helpers/boscoRequest.ts new file mode 100644 index 00000000..719ac38a --- /dev/null +++ b/src/actions/helpers/boscoRequest.ts @@ -0,0 +1,30 @@ + + +const boscoInit = (params: any) => { + (window as any).bosco.init( + { + endpoint: params.url, + } + ) +} + +export default function boscoRequest(src: any, params: any) { + + return new Promise((resolve, reject) => { + const script = document.createElement('script') + script.setAttribute('src', src) + + script.addEventListener('load', () => { + resolve(boscoInit(params)) + }) + script.addEventListener('error', reject) + document.body.appendChild(script) + }) + +} + + + +export function boscoSend(data: any, id: any) { + (window as any).bosco.send(data, id) +} \ No newline at end of file diff --git a/src/actions/helpers/convertFlux.js b/src/actions/helpers/convertFlux.ts similarity index 81% rename from src/actions/helpers/convertFlux.js rename to src/actions/helpers/convertFlux.ts index 88e443b4..e01170f7 100644 --- a/src/actions/helpers/convertFlux.js +++ b/src/actions/helpers/convertFlux.ts @@ -1,20 +1,20 @@ import Papa from "papaparse"; -export async function convertFlux(csv) { +export async function convertFlux(csv: any) { try { - var response = { + var response: any = { meta: [], data: [], statistics: { elapsed: 0.360986682, rows_read: 0, bytes_read: 0 }, }; - var json = Papa.parse(csv, { + var json: any = Papa.parse(csv, { header: true, comments: true, dynamicTyping: true, - }); + } as any); - response.data = await json.data.map(function (item) { + response.data = await json.data.map(function (item: any) { delete item[""]; delete item.table; delete item.result; @@ -34,11 +34,11 @@ export async function convertFlux(csv) { } } -export function csvJSON(csvText) { - let lines = []; +export function csvJSON(csvText: any) { + let lines: any[] = []; const linesArray = csvText.split('\n'); // for trimming and deleting extra space - linesArray.forEach((e) => { + linesArray.forEach((e: any) => { const row = e.replace(/[\s]+[,]+|[,]+[\s]+/g, ',').trim(); lines.push(row); }); @@ -49,7 +49,7 @@ export function csvJSON(csvText) { for (let i = 1; i < lines.length; i++) { - const obj = {}; + const obj: any = {}; const currentline = lines[i].split(","); for (let j = 0; j < headers.length; j++) { diff --git a/src/actions/helpers/index.js b/src/actions/helpers/index.ts similarity index 96% rename from src/actions/helpers/index.js rename to src/actions/helpers/index.ts index 8083c848..d0c77db6 100644 --- a/src/actions/helpers/index.js +++ b/src/actions/helpers/index.ts @@ -1,6 +1,6 @@ -export * from "./scrollbarWidth"; -export * from "./prepareCols"; -export * from "./prepareVectorRows"; -export * from "./setColumnsData"; -export * from "./setColumnsValue"; - +export * from "./scrollbarWidth"; +export * from "./prepareCols"; +export * from "./prepareVectorRows"; +export * from "./setColumnsData"; +export * from "./setColumnsValue"; + diff --git a/src/actions/helpers/prepareCols.js b/src/actions/helpers/prepareCols.ts similarity index 83% rename from src/actions/helpers/prepareCols.js rename to src/actions/helpers/prepareCols.ts index 689b9f6f..9cf67b6a 100644 --- a/src/actions/helpers/prepareCols.js +++ b/src/actions/helpers/prepareCols.ts @@ -1,41 +1,41 @@ -/** - * - * @param {*} data query result - * @returns table column names extracted from response - */ - -export function prepareCols(data) { - let colNames = []; - try { - for (let header of data) { - let metricKeys = Object.keys(header.metric); - - for (let metric in metricKeys) { - if (!colNames.includes(metricKeys[metric])) { - colNames.push(metricKeys[metric]); - } - } - } - } catch (e) { - console.log(e); - } - - return colNames; -} - -export function prepareFluxCols(data) { - let colNames = []; - try { - for (let header of data) { - let metricKeys = Object.keys(header); - for(let metric of metricKeys){ - if(!colNames.includes(metric)) - colNames.push(metric) - } - } - }catch(e) { - console.log(e) - } - - return colNames +/** + * + * @param {*} data query result + * @returns table column names extracted from response + */ + +export function prepareCols(data: any) { + let colNames: any[] = []; + try { + for (let header of data) { + let metricKeys = Object.keys(header.metric); + + for (let metric in metricKeys) { + if (!colNames.includes(metricKeys[metric])) { + colNames.push(metricKeys[metric]); + } + } + } + } catch (e) { + console.log(e); + } + + return colNames; +} + +export function prepareFluxCols(data: any) { + let colNames: any[] = []; + try { + for (let header of data) { + let metricKeys = Object.keys(header); + for(let metric of metricKeys){ + if(!colNames.includes(metric)) + colNames.push(metric) + } + } + }catch(e) { + console.log(e) + } + + return colNames } \ No newline at end of file diff --git a/src/actions/helpers/prepareVectorRows.js b/src/actions/helpers/prepareVectorRows.ts similarity index 89% rename from src/actions/helpers/prepareVectorRows.js rename to src/actions/helpers/prepareVectorRows.ts index d2c1fd16..55daaeff 100644 --- a/src/actions/helpers/prepareVectorRows.js +++ b/src/actions/helpers/prepareVectorRows.ts @@ -1,47 +1,47 @@ -import { sortBy } from "lodash"; -import { prepareCols } from "./prepareCols"; - -/** - * - * @param {*} data // the raw data - * @returns the data parsed for react-table use - */ - -export function prepareVectorRows(data, type = "logs") { - if (type === "flux" || type === "traces") { - try { - return data; - } catch (e) { - console.log(e); - } - } else { - const cols = prepareCols(data); - - try { - let rows = []; - const dataLength = data.length; - const colsLength = cols.length; - - for (let i = 0; i < dataLength; i++) { - let dataRow = data[i]; - let metric = dataRow.metric; - let [time, value] = dataRow.value; - let row = {}; - for (let j = 0; j < colsLength; j++) { - let col = cols[j]; - - row[col] = metric[col] || ""; - } - row.time = time; - row.value = value; - rows.push(row); - } - - const sorted = sortBy(rows, (row) => row.time); - - return sorted; - } catch (e) { - console.log(e); - } - } -} +import { sortBy } from "lodash"; +import { prepareCols } from "./prepareCols"; + +/** + * + * @param {*} data // the raw data + * @returns the data parsed for react-table use + */ + +export function prepareVectorRows(data: any, type = "logs") { + if (type === "flux" || type === "traces") { + try { + return data; + } catch (e) { + console.log(e); + } + } else { + const cols = prepareCols(data); + + try { + let rows = []; + const dataLength = data.length; + const colsLength = cols.length; + + for (let i = 0; i < dataLength; i++) { + let dataRow = data[i]; + let metric = dataRow.metric; + let [time, value] = dataRow.value; + let row: any = {}; + for (let j = 0; j < colsLength; j++) { + let col = cols[j]; + + row[col] = metric[col] || ""; + } + row.time = time; + row.value = value; + rows.push(row); + } + + const sorted = sortBy(rows, (row) => row.time); + + return sorted; + } catch (e) { + console.log(e); + } + } +} diff --git a/src/actions/helpers/scrollbarWidth.js b/src/actions/helpers/scrollbarWidth.ts similarity index 97% rename from src/actions/helpers/scrollbarWidth.js rename to src/actions/helpers/scrollbarWidth.ts index b8b79740..0d38d8f1 100644 --- a/src/actions/helpers/scrollbarWidth.js +++ b/src/actions/helpers/scrollbarWidth.ts @@ -1,17 +1,17 @@ -/** - * - * @returns the scrollBarWidth for infinite scroll use - */ - -export const scrollbarWidth = () => { - // thanks too https://davidwalsh.name/detect-scrollbar-width - const scrollDiv = document.createElement("div"); - scrollDiv.setAttribute( - "style", - "width: 100px; height: 100px; overflow: scroll; position:absolute; top:-9999px;" - ); - document.body.appendChild(scrollDiv); - const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; - document.body.removeChild(scrollDiv); - return scrollbarWidth; -}; +/** + * + * @returns the scrollBarWidth for infinite scroll use + */ + +export const scrollbarWidth = () => { + // thanks too https://davidwalsh.name/detect-scrollbar-width + const scrollDiv = document.createElement("div"); + scrollDiv.setAttribute( + "style", + "width: 100px; height: 100px; overflow: scroll; position:absolute; top:-9999px;" + ); + document.body.appendChild(scrollDiv); + const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth; + document.body.removeChild(scrollDiv); + return scrollbarWidth; +}; diff --git a/src/actions/helpers/setColumnsData.js b/src/actions/helpers/setColumnsData.ts similarity index 71% rename from src/actions/helpers/setColumnsData.js rename to src/actions/helpers/setColumnsData.ts index b7370930..04d789b7 100644 --- a/src/actions/helpers/setColumnsData.js +++ b/src/actions/helpers/setColumnsData.ts @@ -1,23 +1,23 @@ -import { setColumnsTsValue } from "./setColumnsValue"; - -/** - * - * @param {*} columns : the table columns ; - * @returns the columns formatted for react-table - */ - -export function setColumnsData( - columns, - type = "logs", - timeAccessor, - data = {} -) { - const columnsData = columns?.map((row) => ({ Header: row, accessor: row })); - const columnsDated = setColumnsTsValue( - columnsData, - type, - timeAccessor, - data - ); - return columnsDated; -} +import { setColumnsTsValue } from "./setColumnsValue"; + +/** + * + * @param {*} columns : the table columns ; + * @returns the columns formatted for react-table + */ + +export function setColumnsData( + columns: any, + type = "logs", + timeAccessor: any, + data: any = {} +) { + const columnsData = columns?.map((row: any) => ({ Header: row, accessor: row })); + const columnsDated = setColumnsTsValue( + columnsData, + type, + timeAccessor, + data + ); + return columnsDated; +} diff --git a/src/actions/helpers/setColumnsValue.js b/src/actions/helpers/setColumnsValue.tsx similarity index 81% rename from src/actions/helpers/setColumnsValue.js rename to src/actions/helpers/setColumnsValue.tsx index 0922e544..ccce7f3d 100644 --- a/src/actions/helpers/setColumnsValue.js +++ b/src/actions/helpers/setColumnsValue.tsx @@ -1,209 +1,213 @@ -/** - * - * @param {*} columns : Table columns ; - * @returns Default Time and Value column headers with time formatter - */ - -import * as moment from "moment"; -import TimeAgo from "javascript-time-ago"; -import en from "javascript-time-ago/locale/en"; -import { themes } from "../../theme/themes"; -import store from "../../store/store"; -import getData from "../getData"; -import { cx, css } from "@emotion/css"; -import { setSplitView } from "../../components/StatusBar/components/SplitViewButton/setSplitView"; -import { setRightPanel } from "../setRightPanel"; - -const TraceLink = (theme) => css` - border: none; - background: none; - color: ${theme.primaryLight}; - cursor: pointer; - &:hover { - text-decoration: underline; - } -`; - -TimeAgo.addDefaultLocale(en); -// format time colum -function timeFormatter(props) { - return moment(parseInt(props.value + "000")).format( - "YYYY-MM-DDTHH:mm:ss.SSZ" - ); -} - -function traceTimeFormatter(props) { - return props.value + " ms"; -} - -function traceStartTimeFormatter(props) { - - const timeAgo = new TimeAgo("en-US"); - - return timeAgo.format(props.value / 1_000_000); -} - -function traceRequest(data, value) { - const dispatch = store.dispatch; - const actPanel = store.getState()[data.panel]; - const rightPanel = store.getState()["right"]; - - const isTabletOrMobile = window.innerWidth <= 914 - const actQuery = actPanel.find((f) => f.id === data.id); - - if (data.panel === "left" && !isTabletOrMobile) { - - dispatch(setSplitView(true)); - } - - let previousRight = JSON.parse(JSON.stringify(rightPanel)); - - const panelCP = JSON.parse(JSON.stringify(actQuery)); - - try { - const newRight = { - ...previousRight[0], - id: previousRight[0].id, - idRef: "Trace " + value, - panel: "right", - queryType: "range", - dataSourceType: "traces", - dataSourceId: data.dataSourceId, - dataSourceURL: data.url, - expr: value, - limit: 100, - step: 100, - tableView: false, - chartView: false, - isShowTs: false, - browserOpen: false, - labels: [], - values: [], - direction: "forward", - }; - - dispatch(setRightPanel([newRight])); - dispatch( - getData( - "traces", - value, - "range", - panelCP.limit || 100, - "right", - newRight.id, - "forward", - data.dataSourceId, // datasourceid - data.url - ) - ); - } catch (e) { - console.log(e); - } -} - -function fluxTimeFormatter(props) { - return moment(props.value).format("YYYY-MM-DDTHH:mm:ss.SSZ"); -} - -export function setColumnsTsValue( - columns, - type = "logs", - timeAccessor, - data = {} -) { - const query = store.getState()?.[data.panel]?.find((f) => f.id === data.id); - - if (query) { - data.dataSourceId = query.dataSourceId; - data.url = query.dataSourceURL; - } - - const storeTheme = store.getState()?.["theme"]; - - const theme = themes[storeTheme]; - - if (columns.length > 0 && type === "traces") { - return columns?.map((m) => { - if (m.accessor === "durationMs") { - return { - Header: "Duration Ms", - accessor: m.accessor, - Cell: (props) => traceTimeFormatter(props), - width: 90, - }; - } - if (m.accessor === "startTimeUnixNano") { - - return { - Header: "Start Time", - accessor: m.accessor, - Cell: (props) => traceStartTimeFormatter(props), - width: 90, - }; - } - if (m.accessor === "traceID" || m.accessor === "traceId") { - return { - Header: "Trace Id", - accessor: m.accessor, - Cell: (props) => ( - - ), - width: 180, - }; - } - if (m.accessor === "rootServiceName") { - return { - Header: "Service Name", - accessor: m.accessor, - Cell: (props) => props.value, - width: 90, - }; - } - if (m.accessor === "rootTraceName") { - return { - Header: "Trace Name", - accessor: m.accessor, - Cell: (props) => props.value, - width: 90, - }; - } - - return m; - }); - } - - if (columns.length > 0 && type === "flux") { - return columns?.map((m) => { - if (m.accessor === timeAccessor || m.accessor === "_time") { - return { - Header: "Time", - accessor: m.accessor, - Cell: (props) => fluxTimeFormatter(props), - width: 190, - }; - } - return m; - }); - } - - if (columns.length > 0) { - return [ - { - Header: "Time", - accessor: "time", - Cell: (props) => timeFormatter(props), - width: 190, - }, - ...columns, - { - Header: "Value", - accessor: "value", - }, - ]; - } else return []; -} +/** + * + * @param {*} columns : Table columns ; + * @returns Default Time and Value column headers with time formatter + */ + +import React from "react"; +import * as _moment from "moment"; +import TimeAgo from "javascript-time-ago"; +import en from "javascript-time-ago/locale/en"; +import { themes } from "../../theme/themes"; +import store from "../../store/store"; +import getData from "../getData"; +import { cx, css } from "@emotion/css"; +import { setSplitView } from "../../components/StatusBar/components/SplitViewButton/setSplitView"; +import { setRightPanel } from "../setRightPanel"; + +const moment: any = _moment; + +const TraceLink = (theme: any) => css` + border: none; + background: none; + color: ${theme.primaryLight}; + cursor: pointer; + &:hover { + text-decoration: underline; + } +`; + +TimeAgo.addDefaultLocale(en); +// format time colum +function timeFormatter(props: any) { + return moment(parseInt(props.value + "000")).format( + "YYYY-MM-DDTHH:mm:ss.SSZ" + ); +} + +function traceTimeFormatter(props: any) { + return props.value + " ms"; +} + +function traceStartTimeFormatter(props: any) { + + const timeAgo = new TimeAgo("en-US"); + + return timeAgo.format(props.value / 1_000_000); +} + +function traceRequest(data: any, value: any) { + const dispatch = store.dispatch; + const actPanel = store.getState()[data.panel]; + const rightPanel = store.getState()["right"]; + + const isTabletOrMobile = window.innerWidth <= 914 + const actQuery = actPanel.find((f: any) => f.id === data.id); + + if (data.panel === "left" && !isTabletOrMobile) { + + dispatch(setSplitView(true)); + } + + let previousRight = JSON.parse(JSON.stringify(rightPanel)); + + const panelCP = JSON.parse(JSON.stringify(actQuery)); + + try { + const newRight = { + ...previousRight[0], + id: previousRight[0].id, + idRef: "Trace " + value, + panel: "right", + queryType: "range", + dataSourceType: "traces", + dataSourceId: data.dataSourceId, + dataSourceURL: data.url, + expr: value, + limit: 100, + step: 100, + tableView: false, + chartView: false, + isShowTs: false, + browserOpen: false, + labels: [], + values: [], + direction: "forward", + }; + + dispatch(setRightPanel([newRight])); + dispatch( + getData( + "traces", + value, + "range", + panelCP.limit || 100, + "right", + newRight.id, + "forward", + data.dataSourceId, // datasourceid + data.url + ) + ); + } catch (e) { + console.log(e); + } +} + +function fluxTimeFormatter(props: any) { + return moment(props.value).format("YYYY-MM-DDTHH:mm:ss.SSZ"); +} + +export function setColumnsTsValue( + columns: any, + type = "logs", + timeAccessor: any, + data: any = {} +) { + const query = store.getState()?.[data.panel]?.find((f: any) => f.id === data.id); + + if (query) { + data.dataSourceId = query.dataSourceId; + data.url = query.dataSourceURL; + } + + const storeTheme = store.getState()?.["theme"]; + + const _themes: any = themes; + const theme = _themes[storeTheme]; + + if (columns.length > 0 && type === "traces") { + return columns?.map((m: any) => { + if (m.accessor === "durationMs") { + return { + Header: "Duration Ms", + accessor: m.accessor, + Cell: (props: any) => traceTimeFormatter(props), + width: 90, + }; + } + if (m.accessor === "startTimeUnixNano") { + + return { + Header: "Start Time", + accessor: m.accessor, + Cell: (props: any) => traceStartTimeFormatter(props), + width: 90, + }; + } + if (m.accessor === "traceID" || m.accessor === "traceId") { + return { + Header: "Trace Id", + accessor: m.accessor, + Cell: (props: any) => ( + + ), + width: 180, + }; + } + if (m.accessor === "rootServiceName") { + return { + Header: "Service Name", + accessor: m.accessor, + Cell: (props: any) => props.value, + width: 90, + }; + } + if (m.accessor === "rootTraceName") { + return { + Header: "Trace Name", + accessor: m.accessor, + Cell: (props: any) => props.value, + width: 90, + }; + } + + return m; + }); + } + + if (columns.length > 0 && type === "flux") { + return columns?.map((m: any) => { + if (m.accessor === timeAccessor || m.accessor === "_time") { + return { + Header: "Time", + accessor: m.accessor, + Cell: (props: any) => fluxTimeFormatter(props), + width: 190, + }; + } + return m; + }); + } + + if (columns.length > 0) { + return [ + { + Header: "Time", + accessor: "time", + Cell: (props: any) => timeFormatter(props), + width: 190, + }, + ...columns, + { + Header: "Value", + accessor: "value", + }, + ]; + } else return []; +} diff --git a/src/actions/helpers/timeParser.ts b/src/actions/helpers/timeParser.ts index 01bac219..bf105483 100644 --- a/src/actions/helpers/timeParser.ts +++ b/src/actions/helpers/timeParser.ts @@ -4,7 +4,7 @@ * @returns timestamp Sec */ - function fromNanoSec( +function fromNanoSec( ts: number // :timestamp ) { return ts / 1000000; @@ -16,11 +16,11 @@ * @returns timestamp Ns */ - function getTimeParsed(time: Date) { +function getTimeParsed(time: Date) { return time.getTime() + "000000"; } -function getTimeSec(time:Date) { +function getTimeSec(time: Date) { return Math.round(time.getTime() / 1000) } diff --git a/src/actions/index.js b/src/actions/index.ts similarity index 97% rename from src/actions/index.js rename to src/actions/index.ts index 69c91e6b..ff9e8b30 100644 --- a/src/actions/index.js +++ b/src/actions/index.ts @@ -1,28 +1,28 @@ -export * from "./setStartTime"; -export * from "./setStopTime"; -export * from "./setQueryLimit"; -export * from "./setQueryStep"; -export * from "./setRangeOpen"; -export * from "./setTimeRangeLabel"; -export * from "./setApiUrl"; -export * from "./setQueryTime"; -export * from "./setQueryType"; -export * from "./setIsSubmit"; -export * from "./setMatrixData"; -export * from "./setQueryHistory"; -export * from "./setHistoryOpen"; -export * from "./setApiError"; -export * from "./errorHandler"; -export * from "./setLabels"; -export * from "./createAlert"; -export * from "./removeAlert"; -export * from "./setFromTime"; -export * from "./setToTime"; -export * from "./setTheme"; -export * from "./setAutoTheme"; -export * from "./setIsEmptyView"; -export * from "./setTableData"; -export * from "./setVectorData"; -export * from "./setTableData"; -export * from "./setResponseType"; +export * from "./setStartTime"; +export * from "./setStopTime"; +export * from "./setQueryLimit"; +export * from "./setQueryStep"; +export * from "./setRangeOpen"; +export * from "./setTimeRangeLabel"; +export * from "./setApiUrl"; +export * from "./setQueryTime"; +export * from "./setQueryType"; +export * from "./setIsSubmit"; +export * from "./setMatrixData"; +export * from "./setQueryHistory"; +export * from "./setHistoryOpen"; +export * from "./setApiError"; +export * from "./errorHandler"; +export * from "./setLabels"; +export * from "./createAlert"; +export * from "./removeAlert"; +export * from "./setFromTime"; +export * from "./setToTime"; +export * from "./setTheme"; +export * from "./setAutoTheme"; +export * from "./setIsEmptyView"; +export * from "./setTableData"; +export * from "./setVectorData"; +export * from "./setTableData"; +export * from "./setResponseType"; export * from "./setIsTableView"; \ No newline at end of file diff --git a/src/actions/loadLabelValues.js b/src/actions/loadLabelValues.ts similarity index 96% rename from src/actions/loadLabelValues.js rename to src/actions/loadLabelValues.ts index 32f66c3d..6561110b 100644 --- a/src/actions/loadLabelValues.js +++ b/src/actions/loadLabelValues.ts @@ -1,82 +1,82 @@ -import axios from "axios"; -import store from "../store/store"; -import { errorHandler } from "./errorHandler"; -import { setApiError } from "./setApiError"; - -export default function loadLabelValues(id,label, labelList='', url ) { - if (!label || (label?.length <= 0 && label.lsList.length <= 0)) { - return () => {}; - } - - 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 headers = { - "Content-Type": "application/json", - }; - - const options = { - method: "GET", - headers: headers, - }; - - labelHeaders.options = options - if(url) { - - return async (dispatch) => { - await axios - .get(`${url}/loki/api/v1/label/${label.name}/values`, labelHeaders) - ?.then((response) => { - if (response?.data?.data) { - const values = response?.data?.data?.map?.((value) => ({ - label: label.name, - name: value, - selected: false, - inverted: false, - })); - - return values; - } else if (!response) { - dispatch(setApiError("URL NOT FOUND")); - - return []; - } - dispatch(setApiError("")); - return response?.data?.data; - }) - .catch((error) => { - const { message } = errorHandler(url, error, "lavelValues"); - dispatch(setApiError(message || "API NOT FOUND")); - - console.log(error); - return []; - }); - }; - } - return [] - -} +import axios from "axios"; +import store from "../store/store"; +import { errorHandler } from "./errorHandler"; +import { setApiError } from "./setApiError"; + +export default function loadLabelValues(id,label, labelList='', url ) { + if (!label || (label?.length <= 0 && label.lsList.length <= 0)) { + return () => {}; + } + + 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 headers = { + "Content-Type": "application/json", + }; + + const options = { + method: "GET", + headers: headers, + }; + + labelHeaders.options = options + if(url) { + + return async (dispatch) => { + await axios + .get(`${url}/loki/api/v1/label/${label.name}/values`, labelHeaders) + ?.then((response) => { + if (response?.data?.data) { + const values = response?.data?.data?.map?.((value) => ({ + label: label.name, + name: value, + selected: false, + inverted: false, + })); + + return values; + } else if (!response) { + dispatch(setApiError("URL NOT FOUND")); + + return []; + } + dispatch(setApiError("")); + return response?.data?.data; + }) + .catch((error) => { + const { message } = errorHandler(url, error, "lavelValues"); + dispatch(setApiError(message || "API NOT FOUND")); + + console.log(error); + return []; + }); + }; + } + return [] + +} diff --git a/src/actions/removeAlert.js b/src/actions/removeAlert.ts similarity index 100% rename from src/actions/removeAlert.js rename to src/actions/removeAlert.ts diff --git a/src/actions/setApiError.js b/src/actions/setApiError.ts similarity index 100% rename from src/actions/setApiError.js rename to src/actions/setApiError.ts diff --git a/src/actions/setApiUrl.js b/src/actions/setApiUrl.ts similarity index 100% rename from src/actions/setApiUrl.js rename to src/actions/setApiUrl.ts diff --git a/src/actions/setApiWarning.js b/src/actions/setApiWarning.ts similarity index 96% rename from src/actions/setApiWarning.js rename to src/actions/setApiWarning.ts index d82f2361..32dabc04 100644 --- a/src/actions/setApiWarning.js +++ b/src/actions/setApiWarning.ts @@ -1,8 +1,8 @@ -export default function setApiWarning(apiWarning){ - return function(dispatch){ - dispatch({ - type:'SET_API_WARNING', - apiWarning - }) - } +export default function setApiWarning(apiWarning){ + return function(dispatch){ + dispatch({ + type:'SET_API_WARNING', + apiWarning + }) + } } \ No newline at end of file diff --git a/src/actions/setDataViews.js b/src/actions/setDataViews.ts similarity index 100% rename from src/actions/setDataViews.js rename to src/actions/setDataViews.ts diff --git a/src/actions/setDebugMode.js b/src/actions/setDebugMode.ts similarity index 100% rename from src/actions/setDebugMode.js rename to src/actions/setDebugMode.ts diff --git a/src/actions/setDirection.js b/src/actions/setDirection.ts similarity index 100% rename from src/actions/setDirection.js rename to src/actions/setDirection.ts diff --git a/src/actions/setFromTime.js b/src/actions/setFromTime.ts similarity index 95% rename from src/actions/setFromTime.js rename to src/actions/setFromTime.ts index 1ecccc78..a6d016b7 100644 --- a/src/actions/setFromTime.js +++ b/src/actions/setFromTime.ts @@ -1,8 +1,8 @@ -export default function setFromTime(toTime){ - return function (dispatch){ - dispatch({ - type:"SET_FROM_TIME", - toTime - }) - } +export default function setFromTime(toTime){ + return function (dispatch){ + dispatch({ + type:"SET_FROM_TIME", + toTime + }) + } } \ No newline at end of file diff --git a/src/actions/setHistoryOpen.js b/src/actions/setHistoryOpen.ts similarity index 100% rename from src/actions/setHistoryOpen.js rename to src/actions/setHistoryOpen.ts diff --git a/src/actions/setIsEmbed.js b/src/actions/setIsEmbed.ts similarity index 100% rename from src/actions/setIsEmbed.js rename to src/actions/setIsEmbed.ts diff --git a/src/actions/setIsEmptyView.js b/src/actions/setIsEmptyView.ts similarity index 95% rename from src/actions/setIsEmptyView.js rename to src/actions/setIsEmptyView.ts index 0b2c461e..a31ede90 100644 --- a/src/actions/setIsEmptyView.js +++ b/src/actions/setIsEmptyView.ts @@ -1,8 +1,8 @@ -const setIsEmptyView = (isEmptyView) => (dispatch) => { - dispatch({ - type: 'SET_IS_EMPTY_VIEW', - isEmptyView, - }) -} - +const setIsEmptyView = (isEmptyView) => (dispatch) => { + dispatch({ + type: 'SET_IS_EMPTY_VIEW', + isEmptyView, + }) +} + export default setIsEmptyView; \ No newline at end of file diff --git a/src/actions/setIsSubmit.js b/src/actions/setIsSubmit.ts similarity index 100% rename from src/actions/setIsSubmit.js rename to src/actions/setIsSubmit.ts diff --git a/src/actions/setIsTableView.js b/src/actions/setIsTableView.ts similarity index 100% rename from src/actions/setIsTableView.js rename to src/actions/setIsTableView.ts diff --git a/src/actions/setLabelValues.js b/src/actions/setLabelValues.ts similarity index 95% rename from src/actions/setLabelValues.js rename to src/actions/setLabelValues.ts index 98ab8da2..4e82dd8d 100644 --- a/src/actions/setLabelValues.js +++ b/src/actions/setLabelValues.ts @@ -1,7 +1,7 @@ -const setLabelValues = (labelValues) => (dispatch) => { - dispatch({ - type: 'SET_LABEL_VALUES', - labelValues - }); -} -export default setLabelValues; +const setLabelValues = (labelValues) => (dispatch) => { + dispatch({ + type: 'SET_LABEL_VALUES', + labelValues + }); +} +export default setLabelValues; diff --git a/src/actions/setLabels.js b/src/actions/setLabels.ts similarity index 95% rename from src/actions/setLabels.js rename to src/actions/setLabels.ts index c97659f3..0c8a8437 100644 --- a/src/actions/setLabels.js +++ b/src/actions/setLabels.ts @@ -1,6 +1,6 @@ -export const setLabels = (labels) => (dispatch) => { - dispatch({ - type: 'SET_LABELS', - labels: labels - }); -}; +export const setLabels = (labels) => (dispatch) => { + dispatch({ + type: 'SET_LABELS', + labels: labels + }); +}; diff --git a/src/actions/setLeftDataView.js b/src/actions/setLeftDataView.ts similarity index 100% rename from src/actions/setLeftDataView.js rename to src/actions/setLeftDataView.ts diff --git a/src/actions/setLeftPanel.js b/src/actions/setLeftPanel.ts similarity index 100% rename from src/actions/setLeftPanel.js rename to src/actions/setLeftPanel.ts diff --git a/src/actions/setLinksHistory.js b/src/actions/setLinksHistory.ts similarity index 100% rename from src/actions/setLinksHistory.js rename to src/actions/setLinksHistory.ts diff --git a/src/actions/setLoading.js b/src/actions/setLoading.ts similarity index 100% rename from src/actions/setLoading.js rename to src/actions/setLoading.ts diff --git a/src/actions/setLogs.js b/src/actions/setLogs.ts similarity index 100% rename from src/actions/setLogs.js rename to src/actions/setLogs.ts diff --git a/src/actions/setMatrixData.js b/src/actions/setMatrixData.ts similarity index 100% rename from src/actions/setMatrixData.js rename to src/actions/setMatrixData.ts diff --git a/src/actions/setPanelResponse.js b/src/actions/setPanelResponse.ts similarity index 100% rename from src/actions/setPanelResponse.js rename to src/actions/setPanelResponse.ts diff --git a/src/actions/setPanelsData.js b/src/actions/setPanelsData.ts similarity index 100% rename from src/actions/setPanelsData.js rename to src/actions/setPanelsData.ts diff --git a/src/actions/setQueryHistory.js b/src/actions/setQueryHistory.ts similarity index 100% rename from src/actions/setQueryHistory.js rename to src/actions/setQueryHistory.ts diff --git a/src/actions/setQueryLimit.js b/src/actions/setQueryLimit.ts similarity index 95% rename from src/actions/setQueryLimit.js rename to src/actions/setQueryLimit.ts index b05e042e..e8af27d4 100644 --- a/src/actions/setQueryLimit.js +++ b/src/actions/setQueryLimit.ts @@ -1,6 +1,6 @@ -export const setQueryLimit = (limit) => (dispatch) => { - dispatch({ - type: 'SET_QUERY_LIMIT', - limit - }); -} +export const setQueryLimit = (limit) => (dispatch) => { + dispatch({ + type: 'SET_QUERY_LIMIT', + limit + }); +} diff --git a/src/actions/setQueryStep.js b/src/actions/setQueryStep.ts similarity index 100% rename from src/actions/setQueryStep.js rename to src/actions/setQueryStep.ts diff --git a/src/actions/setQueryTime.js b/src/actions/setQueryTime.ts similarity index 95% rename from src/actions/setQueryTime.js rename to src/actions/setQueryTime.ts index 7f77f45a..6c6b1916 100644 --- a/src/actions/setQueryTime.js +++ b/src/actions/setQueryTime.ts @@ -1,6 +1,6 @@ -export const setQueryTime = (time) => (dispatch)=>{ - dispatch({ - type: 'SET_QUERY_TIME', - time - }) -} +export const setQueryTime = (time) => (dispatch)=>{ + dispatch({ + type: 'SET_QUERY_TIME', + time + }) +} diff --git a/src/actions/setQueryType.js b/src/actions/setQueryType.ts similarity index 95% rename from src/actions/setQueryType.js rename to src/actions/setQueryType.ts index 22b71896..4b9d5749 100644 --- a/src/actions/setQueryType.js +++ b/src/actions/setQueryType.ts @@ -1,6 +1,6 @@ -export const setQueryType = (queryType) => (dispatch) => { - dispatch({ - type: "SET_QUERY_TYPE", - queryType, - }); -}; +export const setQueryType = (queryType) => (dispatch) => { + dispatch({ + type: "SET_QUERY_TYPE", + queryType, + }); +}; diff --git a/src/actions/setRangeOpen.js b/src/actions/setRangeOpen.ts similarity index 100% rename from src/actions/setRangeOpen.js rename to src/actions/setRangeOpen.ts diff --git a/src/actions/setResponseType.js b/src/actions/setResponseType.ts similarity index 100% rename from src/actions/setResponseType.js rename to src/actions/setResponseType.ts diff --git a/src/actions/setRightDataView.js b/src/actions/setRightDataView.ts similarity index 100% rename from src/actions/setRightDataView.js rename to src/actions/setRightDataView.ts diff --git a/src/actions/setRightPanel.js b/src/actions/setRightPanel.ts similarity index 100% rename from src/actions/setRightPanel.js rename to src/actions/setRightPanel.ts diff --git a/src/actions/setSettingsDialogOpen.js b/src/actions/setSettingsDialogOpen.ts similarity index 100% rename from src/actions/setSettingsDialogOpen.js rename to src/actions/setSettingsDialogOpen.ts diff --git a/src/actions/setStartTime.js b/src/actions/setStartTime.ts similarity index 100% rename from src/actions/setStartTime.js rename to src/actions/setStartTime.ts diff --git a/src/actions/setStopTime.js b/src/actions/setStopTime.ts similarity index 100% rename from src/actions/setStopTime.js rename to src/actions/setStopTime.ts diff --git a/src/actions/setTableData.js b/src/actions/setTableData.ts similarity index 95% rename from src/actions/setTableData.js rename to src/actions/setTableData.ts index 0f703510..29af4ad5 100644 --- a/src/actions/setTableData.js +++ b/src/actions/setTableData.ts @@ -1,6 +1,6 @@ -export const setTableData = (tableData) => (dispatch) => { - dispatch({ - type: "SET_TABLE_DATA", - tableData, - }); -}; +export const setTableData = (tableData) => (dispatch) => { + dispatch({ + type: "SET_TABLE_DATA", + tableData, + }); +}; diff --git a/src/actions/setTheme.js b/src/actions/setTheme.ts similarity index 100% rename from src/actions/setTheme.js rename to src/actions/setTheme.ts diff --git a/src/actions/setTimeRangeLabel.js b/src/actions/setTimeRangeLabel.ts similarity index 100% rename from src/actions/setTimeRangeLabel.js rename to src/actions/setTimeRangeLabel.ts diff --git a/src/actions/setToTime.js b/src/actions/setToTime.ts similarity index 100% rename from src/actions/setToTime.js rename to src/actions/setToTime.ts diff --git a/src/actions/setUrlLocation.js b/src/actions/setUrlLocation.ts similarity index 100% rename from src/actions/setUrlLocation.js rename to src/actions/setUrlLocation.ts diff --git a/src/actions/setUrlQueryParams.js b/src/actions/setUrlQueryParams.ts similarity index 100% rename from src/actions/setUrlQueryParams.js rename to src/actions/setUrlQueryParams.ts diff --git a/src/actions/setVectorData.js b/src/actions/setVectorData.ts similarity index 95% rename from src/actions/setVectorData.js rename to src/actions/setVectorData.ts index 75210ccd..dc9730e8 100644 --- a/src/actions/setVectorData.js +++ b/src/actions/setVectorData.ts @@ -1,6 +1,6 @@ -export const setVectorData = (vectorData) => (dispatch) => { - dispatch({ - type: "SET_VECTOR_DATA", - vectorData, - }); -}; +export const setVectorData = (vectorData) => (dispatch) => { + dispatch({ + type: "SET_VECTOR_DATA", + vectorData, + }); +}; From 17e4f0e5c2d872e2461921836ffbaa2078c4b58e Mon Sep 17 00:00:00 2001 From: Eduard Klimenko Date: Tue, 13 Dec 2022 17:59:17 +0200 Subject: [PATCH 04/40] fix types on TS's files --- src/actions/createAlert.ts | 2 +- src/actions/errorHandler.ts | 4 ++-- src/actions/loadLabelValues.ts | 24 +++++++++---------- src/actions/removeAlert.ts | 2 +- src/actions/setApiError.ts | 2 +- src/actions/setApiUrl.ts | 2 +- src/actions/setApiWarning.ts | 6 ++--- src/actions/setDataViews.ts | 2 +- src/actions/setDebugMode.ts | 6 ++--- src/actions/setDirection.ts | 4 ++-- src/actions/setFromTime.ts | 4 ++-- src/actions/setHistoryOpen.ts | 2 +- src/actions/setIsEmbed.ts | 2 +- src/actions/setIsEmptyView.ts | 2 +- src/actions/setIsSubmit.ts | 2 +- src/actions/setIsTableView.ts | 2 +- src/actions/setLabelValues.ts | 2 +- src/actions/setLabels.ts | 2 +- src/actions/setLeftDataView.ts | 2 +- src/actions/setLeftPanel.ts | 2 +- src/actions/setLinksHistory.ts | 2 +- src/actions/setLoading.ts | 2 +- src/actions/setLogs.ts | 2 +- src/actions/setMatrixData.ts | 2 +- src/actions/setPanelResponse.ts | 2 +- src/actions/setPanelsData.ts | 2 +- src/actions/setQueryHistory.ts | 2 +- src/actions/setQueryLimit.ts | 2 +- src/actions/setQueryStep.ts | 2 +- src/actions/setQueryTime.ts | 2 +- src/actions/setQueryType.ts | 2 +- src/actions/setRangeOpen.ts | 2 +- src/actions/setResponseType.ts | 6 ++--- src/actions/setRightDataView.ts | 2 +- src/actions/setRightPanel.ts | 2 +- src/actions/setSettingsDialogOpen.ts | 2 +- src/actions/setStartTime.ts | 2 +- src/actions/setStopTime.ts | 2 +- src/actions/setTableData.ts | 2 +- src/actions/setTheme.ts | 2 +- src/actions/setTimeRangeLabel.ts | 2 +- src/actions/setToTime.ts | 6 ++--- src/actions/setUrlLocation.ts | 2 +- src/actions/setUrlQueryParams.ts | 2 +- src/actions/setVectorData.ts | 2 +- .../components/Charts/actions/setChartType.js | 6 ----- .../components/Charts/actions/setChartType.ts | 6 +++++ ...eryResolution.js => setQueryResolution.ts} | 12 +++++----- .../StatusBar/actions/setMenuSettingsOpen.js | 6 ----- .../StatusBar/actions/setMenuSettingsOpen.ts | 6 +++++ .../SplitViewButton/setSplitView.js | 6 ----- .../SplitViewButton/setSplitView.ts | 6 +++++ ...TimePickerOpen.js => setTimePickerOpen.ts} | 2 +- src/plugins/settingsdialog/SettingsDialog.js | 2 +- .../{setDataSources.js => setDataSources.ts} | 2 +- ...SourceSaved.js => setIsDataSourceSaved.ts} | 2 +- ...{setLinkedFields.js => setLinkedFields.ts} | 2 +- 57 files changed, 96 insertions(+), 96 deletions(-) delete mode 100644 src/components/DataViews/components/Charts/actions/setChartType.js create mode 100644 src/components/DataViews/components/Charts/actions/setChartType.ts rename src/components/QueryTypeBar/actions/{setQueryResolution.js => setQueryResolution.ts} (50%) delete mode 100644 src/components/StatusBar/actions/setMenuSettingsOpen.js create mode 100644 src/components/StatusBar/actions/setMenuSettingsOpen.ts delete mode 100644 src/components/StatusBar/components/SplitViewButton/setSplitView.js create mode 100644 src/components/StatusBar/components/SplitViewButton/setSplitView.ts rename src/components/StatusBar/components/timepickerbutton/actions/{setTimePickerOpen.js => setTimePickerOpen.ts} (60%) rename src/views/DataSources/store/{setDataSources.js => setDataSources.ts} (60%) rename src/views/DataSources/store/{setIsDataSourceSaved.js => setIsDataSourceSaved.ts} (61%) rename src/views/DataSources/store/{setLinkedFields.js => setLinkedFields.ts} (60%) diff --git a/src/actions/createAlert.ts b/src/actions/createAlert.ts index c6f7629c..53fa3f40 100644 --- a/src/actions/createAlert.ts +++ b/src/actions/createAlert.ts @@ -1,6 +1,6 @@ import store from '../store/store'; -export const createAlert = ( action) => (dispatch) => { +export const createAlert = (action: any) => (dispatch: Function) => { const notifications = store.getState().notifications notifications.push({ message: action.message, diff --git a/src/actions/errorHandler.ts b/src/actions/errorHandler.ts index 1f8b9fea..fe42e552 100644 --- a/src/actions/errorHandler.ts +++ b/src/actions/errorHandler.ts @@ -1,4 +1,4 @@ -export const errorHandler = (error) => { +export const errorHandler = (error: any) => { const LABELS_URL = "/loki/api/v1/label"; const QUERY_URL = "/loki/api/v1/query_range"; @@ -58,7 +58,7 @@ export const errorHandler = (error) => { type: type() }; } else { - if (type === 'labels') return; + // if (type === 'labels') return; return { message: "something went wrong with request", diff --git a/src/actions/loadLabelValues.ts b/src/actions/loadLabelValues.ts index 6561110b..86a2608f 100644 --- a/src/actions/loadLabelValues.ts +++ b/src/actions/loadLabelValues.ts @@ -3,20 +3,20 @@ import store from "../store/store"; import { errorHandler } from "./errorHandler"; import { setApiError } from "./setApiError"; -export default function loadLabelValues(id,label, labelList='', url ) { +export default function loadLabelValues(id: any, label: any, labelList: string = '', url: any) { if (!label || (label?.length <= 0 && label.lsList.length <= 0)) { - return () => {}; + return () => { }; } const { dataSources } = store.getState(); - const actDataSource = dataSources.find((f) => f.id === id); + const actDataSource = dataSources.find((f: any) => f.id === id); const basicAuth = actDataSource?.auth?.basicAuth.value; - let auth = {}; + let auth: any = {}; - let labelHeaders = {} + let labelHeaders: any = {} if (basicAuth) { @@ -45,33 +45,33 @@ export default function loadLabelValues(id,label, labelList='', url ) { }; labelHeaders.options = options - if(url) { + if (url) { - return async (dispatch) => { + return async (dispatch: Function) => { await axios .get(`${url}/loki/api/v1/label/${label.name}/values`, labelHeaders) ?.then((response) => { if (response?.data?.data) { - const values = response?.data?.data?.map?.((value) => ({ + const values = response?.data?.data?.map?.((value: any) => ({ label: label.name, name: value, selected: false, inverted: false, })); - + return values; } else if (!response) { dispatch(setApiError("URL NOT FOUND")); - + return []; } dispatch(setApiError("")); return response?.data?.data; }) .catch((error) => { - const { message } = errorHandler(url, error, "lavelValues"); + const { message } = errorHandler(url); dispatch(setApiError(message || "API NOT FOUND")); - + console.log(error); return []; }); diff --git a/src/actions/removeAlert.ts b/src/actions/removeAlert.ts index 9ff78a0f..9a924be8 100644 --- a/src/actions/removeAlert.ts +++ b/src/actions/removeAlert.ts @@ -1,6 +1,6 @@ import store from '../store/store'; -export const removeAlert = ( index) => (dispatch) => { +export const removeAlert = ( index: any) => (dispatch: Function) => { let notifications = store.getState().notifications notifications[index].visible = false; dispatch({ diff --git a/src/actions/setApiError.ts b/src/actions/setApiError.ts index 6b9fb8d6..eb5e134c 100644 --- a/src/actions/setApiError.ts +++ b/src/actions/setApiError.ts @@ -1,4 +1,4 @@ -export const setApiError = (apiErrors) => (dispatch) => { +export const setApiError = (apiErrors: any) => (dispatch: Function) => { dispatch({ type: 'SET_API_ERRORS', apiErrors diff --git a/src/actions/setApiUrl.ts b/src/actions/setApiUrl.ts index b3ed8e1e..29fffbb8 100644 --- a/src/actions/setApiUrl.ts +++ b/src/actions/setApiUrl.ts @@ -1,4 +1,4 @@ -export const setApiUrl = ( apiUrl ) => (dispatch) => { +export const setApiUrl = ( apiUrl : any) => (dispatch: Function) => { dispatch({ type: 'SET_API_URL', apiUrl:apiUrl.trim() diff --git a/src/actions/setApiWarning.ts b/src/actions/setApiWarning.ts index 32dabc04..123f8a68 100644 --- a/src/actions/setApiWarning.ts +++ b/src/actions/setApiWarning.ts @@ -1,7 +1,7 @@ -export default function setApiWarning(apiWarning){ - return function(dispatch){ +export default function setApiWarning(apiWarning: any) { + return function (dispatch: Function) { dispatch({ - type:'SET_API_WARNING', + type: 'SET_API_WARNING', apiWarning }) } diff --git a/src/actions/setDataViews.ts b/src/actions/setDataViews.ts index d1e6cb27..459b983c 100644 --- a/src/actions/setDataViews.ts +++ b/src/actions/setDataViews.ts @@ -1,4 +1,4 @@ -const setDataViews = (dataViews) => (dispatch) => { +const setDataViews = (dataViews: any) => (dispatch: Function) => { dispatch({ type: 'SET_DATA_VIEWS', dataViews diff --git a/src/actions/setDebugMode.ts b/src/actions/setDebugMode.ts index 43b475ba..8018c27f 100644 --- a/src/actions/setDebugMode.ts +++ b/src/actions/setDebugMode.ts @@ -1,7 +1,7 @@ -export default function setDebugMode( debugMode) { - return function (dispatch){ +export default function setDebugMode(debugMode: any) { + return function (dispatch: Function) { dispatch({ - type:"SET_DEBUG_MODE", + type: "SET_DEBUG_MODE", debugMode }) } diff --git a/src/actions/setDirection.ts b/src/actions/setDirection.ts index a1f911c8..1867a0ae 100644 --- a/src/actions/setDirection.ts +++ b/src/actions/setDirection.ts @@ -1,5 +1,5 @@ -export default function setDirection(direction) { -return function (dispatch) { +export default function setDirection(direction: any) { +return function (dispatch: Function) { dispatch({ type:"SET_DIRECTION", direction diff --git a/src/actions/setFromTime.ts b/src/actions/setFromTime.ts index a6d016b7..13667440 100644 --- a/src/actions/setFromTime.ts +++ b/src/actions/setFromTime.ts @@ -1,5 +1,5 @@ -export default function setFromTime(toTime){ - return function (dispatch){ +export default function setFromTime(toTime: any){ + return function (dispatch: Function){ dispatch({ type:"SET_FROM_TIME", toTime diff --git a/src/actions/setHistoryOpen.ts b/src/actions/setHistoryOpen.ts index 564dc166..7b8f7da8 100644 --- a/src/actions/setHistoryOpen.ts +++ b/src/actions/setHistoryOpen.ts @@ -1,4 +1,4 @@ - const setHistoryOpen = (historyOpen) => (dispatch)=>{ + const setHistoryOpen = (historyOpen: any) => (dispatch: Function)=>{ dispatch({ type: 'SET_HISTORY_OPEN', historyOpen diff --git a/src/actions/setIsEmbed.ts b/src/actions/setIsEmbed.ts index 086026b3..cbb85dc6 100644 --- a/src/actions/setIsEmbed.ts +++ b/src/actions/setIsEmbed.ts @@ -1,4 +1,4 @@ -const setIsEmbed = (isEmbed) => (dispatch) => { +const setIsEmbed = (isEmbed: any) => (dispatch: Function) => { dispatch({ type: 'SET_IS_EMBED', isEmbed, diff --git a/src/actions/setIsEmptyView.ts b/src/actions/setIsEmptyView.ts index a31ede90..93211caf 100644 --- a/src/actions/setIsEmptyView.ts +++ b/src/actions/setIsEmptyView.ts @@ -1,4 +1,4 @@ -const setIsEmptyView = (isEmptyView) => (dispatch) => { +const setIsEmptyView = (isEmptyView: any) => (dispatch: Function) => { dispatch({ type: 'SET_IS_EMPTY_VIEW', isEmptyView, diff --git a/src/actions/setIsSubmit.ts b/src/actions/setIsSubmit.ts index 7c3cd2ce..c8833a98 100644 --- a/src/actions/setIsSubmit.ts +++ b/src/actions/setIsSubmit.ts @@ -1,4 +1,4 @@ -export const setIsSubmit = (isSubmit) => (dispatch)=>{ +export const setIsSubmit = (isSubmit: any) => (dispatch: Function)=>{ dispatch({ type: 'SET_IS_SUBMIT', isSubmit diff --git a/src/actions/setIsTableView.ts b/src/actions/setIsTableView.ts index 654022a6..d7919a1c 100644 --- a/src/actions/setIsTableView.ts +++ b/src/actions/setIsTableView.ts @@ -1,4 +1,4 @@ -export const setIsTableView = (isTableView) => (dispatch) => { +export const setIsTableView = (isTableView: any) => (dispatch: Function) => { dispatch({ type: 'SET_IS_TABLE_VIEW', isTableView diff --git a/src/actions/setLabelValues.ts b/src/actions/setLabelValues.ts index 4e82dd8d..503e7e1f 100644 --- a/src/actions/setLabelValues.ts +++ b/src/actions/setLabelValues.ts @@ -1,4 +1,4 @@ -const setLabelValues = (labelValues) => (dispatch) => { +const setLabelValues = (labelValues: any) => (dispatch: Function) => { dispatch({ type: 'SET_LABEL_VALUES', labelValues diff --git a/src/actions/setLabels.ts b/src/actions/setLabels.ts index 0c8a8437..2000b535 100644 --- a/src/actions/setLabels.ts +++ b/src/actions/setLabels.ts @@ -1,4 +1,4 @@ -export const setLabels = (labels) => (dispatch) => { +export const setLabels = (labels: any) => (dispatch: Function) => { dispatch({ type: 'SET_LABELS', labels: labels diff --git a/src/actions/setLeftDataView.ts b/src/actions/setLeftDataView.ts index 7ea08637..dde5ed61 100644 --- a/src/actions/setLeftDataView.ts +++ b/src/actions/setLeftDataView.ts @@ -1,4 +1,4 @@ -export const setLeftDataView = (leftDataView) => (dispatch) => { +export const setLeftDataView = (leftDataView: any) => (dispatch: Function) => { dispatch({ type: 'SET_LEFT_DATAVIEW', leftDataView diff --git a/src/actions/setLeftPanel.ts b/src/actions/setLeftPanel.ts index 3bc68980..69e76319 100644 --- a/src/actions/setLeftPanel.ts +++ b/src/actions/setLeftPanel.ts @@ -1,4 +1,4 @@ -export const setLeftPanel = ( left ) => (dispatch) => { +export const setLeftPanel = ( left : any) => (dispatch: Function) => { dispatch({ type: 'SET_LEFT_PANEL', left diff --git a/src/actions/setLinksHistory.ts b/src/actions/setLinksHistory.ts index c47c9391..de02ced3 100644 --- a/src/actions/setLinksHistory.ts +++ b/src/actions/setLinksHistory.ts @@ -1,4 +1,4 @@ -const setLinksHistory = (linksHistory) => (dispatch) => { +const setLinksHistory = (linksHistory: any) => (dispatch: Function) => { dispatch({ type: 'SET_LINKS_HISTORY', linksHistory diff --git a/src/actions/setLoading.ts b/src/actions/setLoading.ts index 674493ae..53ba8af1 100644 --- a/src/actions/setLoading.ts +++ b/src/actions/setLoading.ts @@ -1,4 +1,4 @@ -const setLoading = (loading) => (dispatch) => { +const setLoading = (loading: any) => (dispatch: Function) => { dispatch({ type: "SET_LOADING", loading, diff --git a/src/actions/setLogs.ts b/src/actions/setLogs.ts index 49aaa7a5..634d59cc 100644 --- a/src/actions/setLogs.ts +++ b/src/actions/setLogs.ts @@ -1,4 +1,4 @@ -const setLogs = (logs) => (dispatch) => { +const setLogs = (logs: any) => (dispatch: Function) => { dispatch({ type: "SET_LOGS", logs, diff --git a/src/actions/setMatrixData.ts b/src/actions/setMatrixData.ts index 6b78bf04..32d0fee2 100644 --- a/src/actions/setMatrixData.ts +++ b/src/actions/setMatrixData.ts @@ -1,4 +1,4 @@ -const setMatrixData = (matrixData) => (dispatch) => { +const setMatrixData = (matrixData: any) => (dispatch: Function) => { dispatch({ type: 'SET_MATRIX_DATA', matrixData diff --git a/src/actions/setPanelResponse.ts b/src/actions/setPanelResponse.ts index 9cc10429..2205c5a7 100644 --- a/src/actions/setPanelResponse.ts +++ b/src/actions/setPanelResponse.ts @@ -1,5 +1,5 @@ - export const setPanelResponse = (panel,response) => (dispatch) => { +export const setPanelResponse = (panel: any, response: any) => (dispatch: Function) => { dispatch({ type: 'SET_PANEL_RESPONSE', panel, diff --git a/src/actions/setPanelsData.ts b/src/actions/setPanelsData.ts index 0729d35a..483ce5de 100644 --- a/src/actions/setPanelsData.ts +++ b/src/actions/setPanelsData.ts @@ -1,4 +1,4 @@ - export const setPanelsData = (panels) => (dispatch) => { + export const setPanelsData = (panels: any) => (dispatch: Function) => { dispatch({ type: 'SET_PANELS_DATA', panels diff --git a/src/actions/setQueryHistory.ts b/src/actions/setQueryHistory.ts index 8daaf2be..a924fc2d 100644 --- a/src/actions/setQueryHistory.ts +++ b/src/actions/setQueryHistory.ts @@ -1,4 +1,4 @@ -const setQueryHistory = (queryHistory) => (dispatch) => { +const setQueryHistory = (queryHistory: any) => (dispatch: Function) => { dispatch({ type: 'SET_QUERY_HISTORY', queryHistory diff --git a/src/actions/setQueryLimit.ts b/src/actions/setQueryLimit.ts index e8af27d4..4f2b2097 100644 --- a/src/actions/setQueryLimit.ts +++ b/src/actions/setQueryLimit.ts @@ -1,4 +1,4 @@ -export const setQueryLimit = (limit) => (dispatch) => { +export const setQueryLimit = (limit: any) => (dispatch: Function) => { dispatch({ type: 'SET_QUERY_LIMIT', limit diff --git a/src/actions/setQueryStep.ts b/src/actions/setQueryStep.ts index 6bc6a526..d32f0a1e 100644 --- a/src/actions/setQueryStep.ts +++ b/src/actions/setQueryStep.ts @@ -1,4 +1,4 @@ -export const setQueryStep = (step) => (dispatch)=>{ +export const setQueryStep = (step: any) => (dispatch: Function)=>{ dispatch({ type: 'SET_QUERY_STEP', step diff --git a/src/actions/setQueryTime.ts b/src/actions/setQueryTime.ts index 6c6b1916..8ba68d26 100644 --- a/src/actions/setQueryTime.ts +++ b/src/actions/setQueryTime.ts @@ -1,4 +1,4 @@ -export const setQueryTime = (time) => (dispatch)=>{ +export const setQueryTime = (time: any) => (dispatch: Function)=>{ dispatch({ type: 'SET_QUERY_TIME', time diff --git a/src/actions/setQueryType.ts b/src/actions/setQueryType.ts index 4b9d5749..6ea4025c 100644 --- a/src/actions/setQueryType.ts +++ b/src/actions/setQueryType.ts @@ -1,4 +1,4 @@ -export const setQueryType = (queryType) => (dispatch) => { +export const setQueryType = (queryType: any) => (dispatch: Function) => { dispatch({ type: "SET_QUERY_TYPE", queryType, diff --git a/src/actions/setRangeOpen.ts b/src/actions/setRangeOpen.ts index c4685419..b684ebb1 100644 --- a/src/actions/setRangeOpen.ts +++ b/src/actions/setRangeOpen.ts @@ -1,4 +1,4 @@ -export const setRangeOpen = ( rangeOpen ) => (dispatch) => { +export const setRangeOpen = ( rangeOpen : any) => (dispatch: Function) => { dispatch({ type: 'SET_RANGE_OPEN', rangeOpen diff --git a/src/actions/setResponseType.ts b/src/actions/setResponseType.ts index 3234e01e..c8503e8c 100644 --- a/src/actions/setResponseType.ts +++ b/src/actions/setResponseType.ts @@ -1,7 +1,7 @@ -export default function setResponseType( responseType) { - return function (dispatch){ +export default function setResponseType(responseType: any) { + return function (dispatch: Function) { dispatch({ - type:"SET_RESPONSE_TYPE", + type: "SET_RESPONSE_TYPE", responseType }) } diff --git a/src/actions/setRightDataView.ts b/src/actions/setRightDataView.ts index 9dcb0513..080b3b0b 100644 --- a/src/actions/setRightDataView.ts +++ b/src/actions/setRightDataView.ts @@ -1,4 +1,4 @@ -export const setRightDataView = (rightDataView) => (dispatch) => { +export const setRightDataView = (rightDataView: any) => (dispatch: Function) => { dispatch({ type: 'SET_RIGHT_DATAVIEW', rightDataView diff --git a/src/actions/setRightPanel.ts b/src/actions/setRightPanel.ts index 734400eb..fafb21bd 100644 --- a/src/actions/setRightPanel.ts +++ b/src/actions/setRightPanel.ts @@ -1,4 +1,4 @@ -export const setRightPanel = ( right ) => (dispatch) => { +export const setRightPanel = ( right : any) => (dispatch: Function) => { dispatch({ type: 'SET_RIGHT_PANEL', right diff --git a/src/actions/setSettingsDialogOpen.ts b/src/actions/setSettingsDialogOpen.ts index 226941d4..465a656a 100644 --- a/src/actions/setSettingsDialogOpen.ts +++ b/src/actions/setSettingsDialogOpen.ts @@ -1,4 +1,4 @@ -const setSettingsDialogOpen = (settingsDialogOpen) => (dispatch) => { +const setSettingsDialogOpen = (settingsDialogOpen: any) => (dispatch: Function) => { dispatch({ type: 'SET_SETTINGS_DIALOG_OPEN', settingsDialogOpen diff --git a/src/actions/setStartTime.ts b/src/actions/setStartTime.ts index 8b349e56..2cfff34c 100644 --- a/src/actions/setStartTime.ts +++ b/src/actions/setStartTime.ts @@ -1,4 +1,4 @@ -export const setStartTime = (start) => (dispatch) => { +export const setStartTime = (start: any) => (dispatch: Function) => { dispatch({ type: 'SET_START_TIME', start diff --git a/src/actions/setStopTime.ts b/src/actions/setStopTime.ts index 119d9ae8..4f6fd966 100644 --- a/src/actions/setStopTime.ts +++ b/src/actions/setStopTime.ts @@ -1,4 +1,4 @@ -export const setStopTime = (stop) => (dispatch) => { +export const setStopTime = (stop: any) => (dispatch: Function) => { dispatch({ type: 'SET_STOP_TIME', stop diff --git a/src/actions/setTableData.ts b/src/actions/setTableData.ts index 29af4ad5..e336c914 100644 --- a/src/actions/setTableData.ts +++ b/src/actions/setTableData.ts @@ -1,4 +1,4 @@ -export const setTableData = (tableData) => (dispatch) => { +export const setTableData = (tableData: any) => (dispatch: Function) => { dispatch({ type: "SET_TABLE_DATA", tableData, diff --git a/src/actions/setTheme.ts b/src/actions/setTheme.ts index 7f9281d2..74e695af 100644 --- a/src/actions/setTheme.ts +++ b/src/actions/setTheme.ts @@ -1,4 +1,4 @@ -export const setTheme = (theme) => (dispatch) => { +export const setTheme = (theme: any) => (dispatch: Function) => { dispatch({ type: 'SET_THEME', theme diff --git a/src/actions/setTimeRangeLabel.ts b/src/actions/setTimeRangeLabel.ts index febccaf3..0b16d161 100644 --- a/src/actions/setTimeRangeLabel.ts +++ b/src/actions/setTimeRangeLabel.ts @@ -1,4 +1,4 @@ -export const setTimeRangeLabel = (label) => (dispatch) => { +export const setTimeRangeLabel = (label: any) => (dispatch: Function) => { dispatch({ type: 'SET_TIME_RANGE_LABEL', label diff --git a/src/actions/setToTime.ts b/src/actions/setToTime.ts index 86fbc0d0..6598fbd3 100644 --- a/src/actions/setToTime.ts +++ b/src/actions/setToTime.ts @@ -1,7 +1,7 @@ -export default function setToTime(toTime){ - return function (dispatch){ +export default function setToTime(toTime: any) { + return function (dispatch: Function) { dispatch({ - type:"SET_TO_TIME" + type: "SET_TO_TIME" }) } } \ No newline at end of file diff --git a/src/actions/setUrlLocation.ts b/src/actions/setUrlLocation.ts index 0c392c8a..2377f7a6 100644 --- a/src/actions/setUrlLocation.ts +++ b/src/actions/setUrlLocation.ts @@ -1,4 +1,4 @@ -export const setUrlLocation = (urlLocation) => (dispatch) => { +export const setUrlLocation = (urlLocation: any) => (dispatch: Function) => { dispatch({ type: 'SET_URL_LOCATION', urlLocation diff --git a/src/actions/setUrlQueryParams.ts b/src/actions/setUrlQueryParams.ts index 48dc7fe9..35d30bc5 100644 --- a/src/actions/setUrlQueryParams.ts +++ b/src/actions/setUrlQueryParams.ts @@ -1,4 +1,4 @@ -export const setUrlQueryParams = (urlQueryParams) => (dispatch) => { +export const setUrlQueryParams = (urlQueryParams: any) => (dispatch: Function) => { dispatch({ type: 'SET_URL_QUERY_PARAMS', urlQueryParams diff --git a/src/actions/setVectorData.ts b/src/actions/setVectorData.ts index dc9730e8..f5e704d3 100644 --- a/src/actions/setVectorData.ts +++ b/src/actions/setVectorData.ts @@ -1,4 +1,4 @@ -export const setVectorData = (vectorData) => (dispatch) => { +export const setVectorData = (vectorData: any) => (dispatch: Function) => { dispatch({ type: "SET_VECTOR_DATA", vectorData, diff --git a/src/components/DataViews/components/Charts/actions/setChartType.js b/src/components/DataViews/components/Charts/actions/setChartType.js deleted file mode 100644 index 9e6f465e..00000000 --- a/src/components/DataViews/components/Charts/actions/setChartType.js +++ /dev/null @@ -1,6 +0,0 @@ -export const setChartType = ( chartType ) => (dispatch) => { - dispatch({ - type: 'SET_CHART_TYPE', - chartType - }) -} \ No newline at end of file diff --git a/src/components/DataViews/components/Charts/actions/setChartType.ts b/src/components/DataViews/components/Charts/actions/setChartType.ts new file mode 100644 index 00000000..04140696 --- /dev/null +++ b/src/components/DataViews/components/Charts/actions/setChartType.ts @@ -0,0 +1,6 @@ +export const setChartType = ( chartType : any) => (dispatch: Function) => { + dispatch({ + type: 'SET_CHART_TYPE', + chartType + }) +} \ No newline at end of file diff --git a/src/components/QueryTypeBar/actions/setQueryResolution.js b/src/components/QueryTypeBar/actions/setQueryResolution.ts similarity index 50% rename from src/components/QueryTypeBar/actions/setQueryResolution.js rename to src/components/QueryTypeBar/actions/setQueryResolution.ts index 8eea64f5..25720375 100644 --- a/src/components/QueryTypeBar/actions/setQueryResolution.js +++ b/src/components/QueryTypeBar/actions/setQueryResolution.ts @@ -1,6 +1,6 @@ -export const setQueryResolution = (queryResolution) => (dispatch) => { - dispatch({ - type: "SET_QUERY_RESOLUTION", - queryResolution, - }); -}; +export const setQueryResolution = (queryResolution: any) => (dispatch: Function) => { + dispatch({ + type: "SET_QUERY_RESOLUTION", + queryResolution, + }); +}; diff --git a/src/components/StatusBar/actions/setMenuSettingsOpen.js b/src/components/StatusBar/actions/setMenuSettingsOpen.js deleted file mode 100644 index 354b190a..00000000 --- a/src/components/StatusBar/actions/setMenuSettingsOpen.js +++ /dev/null @@ -1,6 +0,0 @@ -export const setSettingsMenuOpen = ( settingsMenuOpen ) => (dispatch) => { - dispatch({ - type: 'SET_SETTINGS_MENU_OPEN', - settingsMenuOpen - }) -} \ No newline at end of file diff --git a/src/components/StatusBar/actions/setMenuSettingsOpen.ts b/src/components/StatusBar/actions/setMenuSettingsOpen.ts new file mode 100644 index 00000000..6919ba9b --- /dev/null +++ b/src/components/StatusBar/actions/setMenuSettingsOpen.ts @@ -0,0 +1,6 @@ +export const setSettingsMenuOpen = ( settingsMenuOpen : any) => (dispatch: Function) => { + dispatch({ + type: 'SET_SETTINGS_MENU_OPEN', + settingsMenuOpen + }) +} \ No newline at end of file diff --git a/src/components/StatusBar/components/SplitViewButton/setSplitView.js b/src/components/StatusBar/components/SplitViewButton/setSplitView.js deleted file mode 100644 index c3e811fe..00000000 --- a/src/components/StatusBar/components/SplitViewButton/setSplitView.js +++ /dev/null @@ -1,6 +0,0 @@ -export const setSplitView = ( isSplit ) => (dispatch) => { - dispatch({ - type: 'SET_SPLIT_VIEW', - isSplit - }) -} \ No newline at end of file diff --git a/src/components/StatusBar/components/SplitViewButton/setSplitView.ts b/src/components/StatusBar/components/SplitViewButton/setSplitView.ts new file mode 100644 index 00000000..176d2210 --- /dev/null +++ b/src/components/StatusBar/components/SplitViewButton/setSplitView.ts @@ -0,0 +1,6 @@ +export const setSplitView = ( isSplit : any) => (dispatch: Function) => { + dispatch({ + type: 'SET_SPLIT_VIEW', + isSplit + }) +} \ No newline at end of file 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/plugins/settingsdialog/SettingsDialog.js b/src/plugins/settingsdialog/SettingsDialog.js index e8b4adfc..f3b4edba 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"; diff --git a/src/views/DataSources/store/setDataSources.js b/src/views/DataSources/store/setDataSources.ts similarity index 60% rename from src/views/DataSources/store/setDataSources.js rename to src/views/DataSources/store/setDataSources.ts index 89d4ac91..1eb5b6ea 100644 --- a/src/views/DataSources/store/setDataSources.js +++ b/src/views/DataSources/store/setDataSources.ts @@ -1,4 +1,4 @@ -const setDataSources = (dataSources) => (dispatch) => { +const setDataSources = (dataSources: any) => (dispatch: Function) => { dispatch({ type: 'SET_DATA_SOURCES', dataSources diff --git a/src/views/DataSources/store/setIsDataSourceSaved.js b/src/views/DataSources/store/setIsDataSourceSaved.ts similarity index 61% rename from src/views/DataSources/store/setIsDataSourceSaved.js rename to src/views/DataSources/store/setIsDataSourceSaved.ts index d30fc3fa..22a35b73 100644 --- a/src/views/DataSources/store/setIsDataSourceSaved.js +++ b/src/views/DataSources/store/setIsDataSourceSaved.ts @@ -1,4 +1,4 @@ -const setIsDatasourceSaved = (isDsSaved) => (dispatch) => { +const setIsDatasourceSaved = (isDsSaved: any) => (dispatch: Function) => { dispatch({ type: 'SET_IS_DATASOURCE_SAVED', isDsSaved diff --git a/src/views/DataSources/store/setLinkedFields.js b/src/views/DataSources/store/setLinkedFields.ts similarity index 60% rename from src/views/DataSources/store/setLinkedFields.js rename to src/views/DataSources/store/setLinkedFields.ts index 338006d3..0e66aeae 100644 --- a/src/views/DataSources/store/setLinkedFields.js +++ b/src/views/DataSources/store/setLinkedFields.ts @@ -1,4 +1,4 @@ -const setLinkedFields = (linkedFields) => (dispatch) => { +const setLinkedFields = (linkedFields: any) => (dispatch: Function) => { dispatch({ type: 'SET_LINKED_FIELDS', linkedFields From a3a98c4bf6930a620c1d0caecb7ad6bcfcd72f1e Mon Sep 17 00:00:00 2001 From: jacovinus Date: Tue, 13 Dec 2022 18:04:45 +0100 Subject: [PATCH 05/40] feat: Use tabs for different vis types #127 --- src/components/DataViews/hooks/index.js | 2 +- src/components/DataViews/views/LogsView.js | 93 ++++++++++++------- src/components/DataViews/views/MatrixView.js | 38 +++++++- src/components/DataViews/views/styled.js | 76 ++++++++++++++- .../LabelBrowser/components/QuerySetting.js | 4 +- src/components/QueryTypeBar/index.js | 4 +- 6 files changed, 173 insertions(+), 44 deletions(-) diff --git a/src/components/DataViews/hooks/index.js b/src/components/DataViews/hooks/index.js index 996a0793..29aed7e4 100644 --- a/src/components/DataViews/hooks/index.js +++ b/src/components/DataViews/hooks/index.js @@ -30,7 +30,7 @@ export const useViewHeight = ({ type, actualQuery, total, dataView }) => { if (type === "stream" && !actualQuery?.tableView) { const regRows = total * 25; - const regCalc = regRows < 350 ? "fit-content" : "350px"; + const regCalc = regRows < 350 ? "fit-content" : "inherit"; regularCont = regCalc; regularView = regCalc; maxCont = "fit-content"; diff --git a/src/components/DataViews/views/LogsView.js b/src/components/DataViews/views/LogsView.js index 363723e8..a516c587 100644 --- a/src/components/DataViews/views/LogsView.js +++ b/src/components/DataViews/views/LogsView.js @@ -1,38 +1,65 @@ +import { TabsUnstyled } from "@mui/base"; + import { LogRows } from "../components/Logs/LogRows"; import { VectorTable } from "../components/Table/VectorTable/VectorTable"; import { ViewHeader } from "../components/ViewHeader"; -import { ViewStyled } from "./styled"; +import { TabsList, Tab, TabPanel, ViewStyled } from "./styled"; - - export default function LogsView(props){ +export default function LogsView(props) { + const { + viewRef, + panelSize, + viewHeight, + setStreamClose, + setMaxHeight, + setMinimize, + actualQuery, + total, + type, + theight, + tableData, + streamData, + } = props; - const { - viewRef, - panelSize, - viewHeight, - setStreamClose, - setMaxHeight, - setMinimize, - actualQuery, - total, - type, - theight, - tableData, - streamData - } = props + return ( + + - return ( - - -
+ + + Logs + Table + + +
+ +
+
+ +
+ +
+
+
+ {/*
{actualQuery?.tableView ? ( )} -
- - ); - } \ No newline at end of file +
*/} +
+ ); +} diff --git a/src/components/DataViews/views/MatrixView.js b/src/components/DataViews/views/MatrixView.js index 9ff04557..01137200 100644 --- a/src/components/DataViews/views/MatrixView.js +++ b/src/components/DataViews/views/MatrixView.js @@ -2,8 +2,8 @@ import QrynChart from "../components/Charts"; import { VectorTable } from "../components/Table/VectorTable/VectorTable"; import { ViewHeader } from "../components/ViewHeader"; -import { ViewStyled } from "./styled"; - +import { TabsUnstyled } from "@mui/base"; +import { TabsList, Tab, TabPanel, ViewStyled } from "./styled"; export const MatrixView = (props) => { const { viewRef, @@ -32,7 +32,37 @@ export const MatrixView = (props) => { type={type} {...props} /> -
+ + + Chart + Table + + + + + + + + + + + + + + + + {/*
{actualQuery?.tableView ? ( { actualQuery={actualQuery} /> )} -
+
*/}
); }; \ No newline at end of file diff --git a/src/components/DataViews/views/styled.js b/src/components/DataViews/views/styled.js index 311f32dc..915f3a68 100644 --- a/src/components/DataViews/views/styled.js +++ b/src/components/DataViews/views/styled.js @@ -1,5 +1,7 @@ import styled from "@emotion/styled"; - +import { TabPanelUnstyled, TabsListUnstyled, TabsUnstyled, TabUnstyled } from "@mui/base"; +import { tabUnstyledClasses } from "@mui/base/TabUnstyled"; +import { buttonUnstyledClasses } from "@mui/base/ButtonUnstyled"; export const ViewStyled = styled.div` margin: 4px; @@ -34,4 +36,74 @@ export const ViewStyled = styled.div` props.size === "regular" ? "column" : "column"}; flex:1; } -`; \ No newline at end of file +`; + + + +export const TabPanel = styled(TabPanelUnstyled)` + width: 100%; + background: ${({ theme }) => theme.widgetContainer}; + height:100%; + flex:1; +`; +export const TabsContainer = styled(TabsUnstyled)` +display:flex; +height:100%; +` +export const TabsList = styled(TabsListUnstyled)` + + min-width: 320px; + background: ${({ theme }) => theme.tabHeader}; + border-bottom: 4px solid ${({ theme }) => theme.historyRow}; + display: ${({panelsize})=> panelsize === 'min' ? 'none' : 'flex'}; + align-items: center; + align-content: space-between; + +`; + +export const Tab = styled(TabUnstyled)` + color: ${(props) => props.theme.textColor}; + background: ${(props) => props.theme.buttonDefault}; + border:1px solid ${(props)=>props.theme.buttonBorder}; + cursor: pointer; + font-size: 13px; + background-color: transparent; + padding: 6px 10px; + border: none; + border-radius: 3px 3px 0px 0px; + display: flex; + justify-content: center; + align-items: center; + border-bottom: 1px solid transparent; + transition: 0.2s all; + + &:hover { + background-color: ${({ theme }) => theme.buttonHover}; + } + + &:focus { + color: ${({ theme }) => theme.textColor}; + background: ${({ theme }) => theme.buttonDefault}; + border-radius: 3px 3px 0px 0px; + + outline-offset: 2px; + } + + &.${tabUnstyledClasses.selected} { + border-bottom: 1px solid ${({ theme }) => theme.primaryDark}; + } + + &.${buttonUnstyledClasses.disabled} { + opacity: 0.5; + cursor: not-allowed; + } + @media screen and (max-width: 360px) { + span { + display: none; + } + padding: 5px 20px; + } +`; + + + diff --git a/src/components/LabelBrowser/components/QuerySetting.js b/src/components/LabelBrowser/components/QuerySetting.js index b2aa5392..0fc6b412 100644 --- a/src/components/LabelBrowser/components/QuerySetting.js +++ b/src/components/LabelBrowser/components/QuerySetting.js @@ -193,7 +193,7 @@ export const QuerySetting = (props) => { )} {responseType !== "vector" && (
- + {/* Table View { onChange={handleTableViewSwitch} inputProps={{ "aria-label": "controlled" }} /> - + */} Timestamp - + {/* Table View - + */} Timestamp Date: Thu, 15 Dec 2022 10:38:12 +0200 Subject: [PATCH 06/40] .js to .ts(tsx) for index / helpers --- ...arams.js => UpdateStateFromQueryParams.ts} | 464 +++++++++--------- .../{decodeQuery.js => decodeQuery.ts} | 395 +++++++-------- ...or.interceptor.js => error.interceptor.ts} | 165 ++++--- src/helpers/{httpclient.js => httpclient.ts} | 0 src/helpers/{setDebug.js => setDebug.ts} | 2 +- ...QueryParams.js => stateFromQueryParams.ts} | 228 ++++----- .../{useQueryParams.js => useQueryParams.ts} | 2 +- src/hooks/{useLabels.js => useLabels.ts} | 179 +++---- src/{index.js => index.tsx} | 18 +- src/services/consts.js | 16 - src/services/consts.ts | 16 + src/setupTests.js | 5 - webpack.config.js | 2 +- webpack.config.prod.js | 2 +- 14 files changed, 749 insertions(+), 745 deletions(-) rename src/helpers/{UpdateStateFromQueryParams.js => UpdateStateFromQueryParams.ts} (84%) rename src/helpers/{decodeQuery.js => decodeQuery.ts} (78%) rename src/helpers/{error.interceptor.js => error.interceptor.ts} (92%) rename src/helpers/{httpclient.js => httpclient.ts} (100%) rename src/helpers/{setDebug.js => setDebug.ts} (62%) rename src/helpers/{stateFromQueryParams.js => stateFromQueryParams.ts} (91%) rename src/helpers/{useQueryParams.js => useQueryParams.ts} (97%) rename src/hooks/{useLabels.js => useLabels.ts} (79%) rename src/{index.js => index.tsx} (61%) delete mode 100644 src/services/consts.js create mode 100644 src/services/consts.ts delete mode 100644 src/setupTests.js 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 100% rename from src/helpers/httpclient.js rename to src/helpers/httpclient.ts 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 91% rename from src/helpers/stateFromQueryParams.js rename to src/helpers/stateFromQueryParams.ts index 3cb1eb1f..67dcb557 100644 --- a/src/helpers/stateFromQueryParams.js +++ b/src/helpers/stateFromQueryParams.ts @@ -1,114 +1,114 @@ -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: "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: 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; + } + } + + 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.tsx similarity index 61% rename from src/index.js rename to src/index.tsx index 6b005f88..1f2e1486 100644 --- a/src/index.js +++ b/src/index.tsx @@ -17,15 +17,15 @@ errorInterceptor(axios) ReactDOM.render( - - - - } /> - } /> - }/> - - - + + + + {/* // react router v6 doesn't support [exact] anymore. */} + } /> + } /> + } /> + + , document.getElementById('root') 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/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/webpack.config.js b/webpack.config.js index f06776e7..8998fd0e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -5,7 +5,7 @@ const webpack = require("webpack"); module.exports = { mode: "development", - entry: "./src/index.js", + entry: "./src/index.tsx", output: { path: path.resolve(__dirname, "build"), filename: "bundled.js", diff --git a/webpack.config.prod.js b/webpack.config.prod.js index 092ca77a..bc0b14fd 100644 --- a/webpack.config.prod.js +++ b/webpack.config.prod.js @@ -6,7 +6,7 @@ const path = require("path") const TerserPlugin = require('terser-webpack-plugin') module.exports = { mode: 'production', - entry: './src/index.js', + entry: './src/index.tsx', output: { path: path.resolve(__dirname, "build"), filename: "bundle.js", From 245731d99804427d2ecfeccae87429deb5c0b766 Mon Sep 17 00:00:00 2001 From: Eduard Klimenko Date: Thu, 15 Dec 2022 10:47:21 +0200 Subject: [PATCH 07/40] fix httpclient.ts --- src/helpers/httpclient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/httpclient.ts b/src/helpers/httpclient.ts index 64051714..5962e513 100644 --- a/src/helpers/httpclient.ts +++ 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 From 0983a6808b11abb3a90c076a44d7770471597c8b Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Thu, 15 Dec 2022 11:07:31 +0200 Subject: [PATCH 08/40] Fix: #156 --- .../LabelBrowser/components/LabelsSelector/LabelsList.js | 5 +++-- src/components/QueryItem/QueryItem.js | 2 ++ src/components/QueryItem/QueryItemToolbar.js | 7 +++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js b/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js index 18526025..20f727ea 100644 --- a/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js +++ b/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js @@ -2,7 +2,7 @@ import { useMemo } from "react"; import styled from "@emotion/styled"; import ShowLogsButton from "../Buttons/ShowLogsButton"; import { queryBuilder } from "../../helpers/querybuilder"; -import { useDispatch } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { setLeftPanel } from "../../../../actions/setLeftPanel"; import { setRightPanel } from "../../../../actions/setRightPanel"; import store from "../../../../store/store"; @@ -54,6 +54,7 @@ export default function LabelsList(props) { const dispatch = useDispatch(); const { labels, data, name } = props; const { dataSourceType } = data; + const panelQuery = useSelector((store) => store[name]); const onClick = (e) => { if (e === "Select Metric") { @@ -77,7 +78,7 @@ export default function LabelsList(props) { const useQuery = () => { const qu = queryBuilder(data.labels, data.expr) - const panel = [data]; + const panel = [...panelQuery]; panel.forEach((query) => { if (query.id === props.data.id) { query.expr = qu; diff --git a/src/components/QueryItem/QueryItem.js b/src/components/QueryItem/QueryItem.js index cd56b0e9..fcfe85df 100644 --- a/src/components/QueryItem/QueryItem.js +++ b/src/components/QueryItem/QueryItem.js @@ -123,6 +123,8 @@ export default function QueryItem(props) { ...props.data, id: nanoid(), idRef, + labels: [], + expr: "", lastIdx: lastIdx + 1, cp: 0, }; diff --git a/src/components/QueryItem/QueryItemToolbar.js b/src/components/QueryItem/QueryItemToolbar.js index a76bd7ac..e227adcd 100644 --- a/src/components/QueryItem/QueryItemToolbar.js +++ b/src/components/QueryItem/QueryItemToolbar.js @@ -12,6 +12,7 @@ import AddOutlinedIcon from "@mui/icons-material/AddOutlined"; import { useEffect, useMemo, useState } from "react"; import { QueryId } from "./QueryId"; import { DataSourceSelect } from "./DataSourceSelect"; +import { Tooltip } from "@mui/material"; export function QueryItemToolbar(props) { const dispatch = useDispatch(); // update panel on id change @@ -170,6 +171,8 @@ export function QueryItemToolbar(props) { opts={dataSourceOptions} label={""} /> + + + + + +
)} From df62fb61bbbcfad9b9789015c6386345acf2facd Mon Sep 17 00:00:00 2001 From: Eduard Klimenko Date: Thu, 15 Dec 2022 14:22:05 +0200 Subject: [PATCH 09/40] .js to .ts(tsx) for services / store --- src/services/{index.js => index.ts} | 0 .../{localHistory.js => localHistory.ts} | 26 ++- .../{localLabels.js => localLabels.ts} | 22 +- src/services/localQuery.js | 8 - src/services/localQuery.ts | 8 + .../{localService.js => localService.ts} | 38 +-- src/services/{localUrl.js => localUrl.ts} | 26 +-- src/store/{reducer.js => reducer.ts} | 218 +++++++++--------- src/store/{store.js => store.ts} | 0 9 files changed, 175 insertions(+), 171 deletions(-) rename src/services/{index.js => index.ts} (100%) rename src/services/{localHistory.js => localHistory.ts} (67%) rename src/services/{localLabels.js => localLabels.ts} (68%) delete mode 100644 src/services/localQuery.js create mode 100644 src/services/localQuery.ts rename src/services/{localService.js => localService.ts} (70%) rename src/services/{localUrl.js => localUrl.ts} (80%) rename src/store/{reducer.js => reducer.ts} (97%) rename src/store/{store.js => store.ts} (100%) 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 80% rename from src/services/localUrl.js rename to src/services/localUrl.ts index e1a0c6d3..4844ca11 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,14 @@ const localUrl = () => { } }; - const add = (item) => { + const add = (item: any) => { let previousData = get() || []; 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; } @@ -77,19 +77,19 @@ 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/store/reducer.js b/src/store/reducer.ts similarity index 97% rename from src/store/reducer.js rename to src/store/reducer.ts index 7239056b..e580167a 100644 --- a/src/store/reducer.js +++ b/src/store/reducer.ts @@ -1,109 +1,109 @@ -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}; + default: + return { ...state }; + } +}; + +export default reducer; + 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 From 615e4c577303fe5cf1f49234f6f68dd8ba8fd031 Mon Sep 17 00:00:00 2001 From: Eduard Klimenko Date: Thu, 15 Dec 2022 19:08:59 +0200 Subject: [PATCH 10/40] .js to .ts(tsx) for notifications / Switch --- .../{styles/index.js => Switch.styles.tsx} | 23 +++-- src/qryn-ui/Switch/{Switch.js => Switch.tsx} | 78 +++++++-------- .../notifications/{consts.js => consts.ts} | 0 .../notifications/{index.js => index.tsx} | 96 +++++++++---------- 4 files changed, 98 insertions(+), 99 deletions(-) rename src/qryn-ui/Switch/{styles/index.js => Switch.styles.tsx} (68%) rename src/qryn-ui/Switch/{Switch.js => Switch.tsx} (71%) rename src/qryn-ui/notifications/{consts.js => consts.ts} (100%) rename src/qryn-ui/notifications/{index.js => index.tsx} (89%) 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; + } + })} +
+ ); +} From 1121532b9726dec908f44339a3c4b5f91f8c36bc Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Thu, 15 Dec 2022 19:11:08 +0200 Subject: [PATCH 11/40] WIP: Adjustable timewindow --- .../components/daterangepicker/index.js | 181 +++++++++++++++++- src/components/StatusBar/styled/index.js | 12 +- 2 files changed, 187 insertions(+), 6 deletions(-) diff --git a/src/components/StatusBar/components/daterangepicker/index.js b/src/components/StatusBar/components/daterangepicker/index.js index f16e377c..a6fb4488 100644 --- a/src/components/StatusBar/components/daterangepicker/index.js +++ b/src/components/StatusBar/components/daterangepicker/index.js @@ -13,6 +13,9 @@ import { min, format, isValid, + add, + sub, + intervalToDuration } from "date-fns"; import { PickerNav } from "./components/Nav"; @@ -33,18 +36,62 @@ import { import { useSelector, useDispatch } from "react-redux"; import useOutsideRef from "./hooks/useOutsideRef"; import AccessTimeOutlinedIcon from "@mui/icons-material/AccessTimeOutlined"; -import { Tooltip } from "@mui/material"; +import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; +import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos'; +import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined'; +import Menu from '@mui/material/Menu'; +import MenuItem from '@mui/material/MenuItem'; +import { Tooltip, IconButton } from "@mui/material"; import TimeLabel from "./components/TimeLabel"; import { DatePickerButton } from "../../styled"; import { themes } from "../../../../theme/themes"; +import { styled } from "@mui/material/styles"; - +const StyledMenu = styled((props) => ( + +))(({ theme, qryntheme }) => ({ + "& .MuiPaper-root": { + borderRadius: 6, + marginTop: theme.spacing(1), + color: qryntheme.textColor, + border: `1px solid ${qryntheme.buttonBorder}`, + backgroundColor: qryntheme.buttonDefault, + "& .MuiMenu-list": { + padding: "4px 0", + }, + "& .MuiMenuItem-root": { + fontSize: 12, + "& .MuiSvgIcon-root": { + fontSize: 12, + color: qryntheme.textColor, + marginRight: theme.spacing(1.5), + }, + "&:active": { + backgroundColor: qryntheme.buttonDefault, + }, + }, + }, +})); +const timeAdjustmentOptions = ['1m', '5m', '10m', '30m', '1h', '3h', '6h', '12h', '24h'] export function DateRangePickerMain(props) { const today = Date.now(); const { isOpen, minDate, maxDate } = props; const startTs = useSelector((store) => store.start); const stopTs = useSelector((store) => store.stop); + const storeTheme = useSelector((store) => store.theme); + const qrynTheme = themes[storeTheme]; const initialDateRange = () => { try { const ls = JSON.parse(localStorage.getItem(DATE_TIME_RANGE)); @@ -206,15 +253,104 @@ export function DateRangePickerMain(props) { } }; - + const adjustTimeRange = (direction, adjustment = 'range') => { + const directionFunc = direction === 'backward' ? sub : add; + let duration = { + years: 0, + months: 0, + days: 0, + hours: 0, + minutes: 0, + seconds: 0 + }; + if (adjustment === 'range') { + duration = intervalToDuration({start:dateStart, end: dateEnd}) + } else { + + if (adjustment.includes('d')) { + duration.days = parseInt(adjustment); + } else if(adjustment.includes('h')) { + duration.hours = parseInt(adjustment); + } else if(adjustment.includes('m')) { + duration.minutes = parseInt(adjustment); + } else if(adjustment.includes('s')) { + duration.seconds = parseInt(adjustment); + } + } + console.log(duration) + const adjustedStart = directionFunc(dateStart, duration); + const adjustedStop = directionFunc(dateEnd, duration); + const dateRange = { + dateStart: adjustedStart, + dateEnd: adjustedStop, + label: '' + } + setDateRange(dateRange); + saveDateRange(dateRange); + onChange(dateRange); + } const theme = useSelector(store => store.theme); + + // Handle menus + const [anchorEl, setAnchorEl] = useState(null); + const open = Boolean(anchorEl); + const [anchorElRight, setAnchorElRight] = useState(null); + const openRight = Boolean(anchorElRight); + const handleClick = (event) => { + setAnchorEl(event.currentTarget); + }; + const handleClickRight = (event) => { + setAnchorElRight(event.currentTarget) + } + const handleClose = (e, direction, option) => { + console.log(direction, option) + setAnchorEl(null); + setAnchorElRight(null); + if (direction && option) { + adjustTimeRange(direction, option) + } + }; return ( -
+
+ { + adjustTimeRange("backward"); + }} + attachedSide={'r'} + emptySide={'l'} + className={"date-time-selector"} + > + + + + + + + {timeAdjustmentOptions.map(option => ( + handleClose(e, 'backward', option)}> + {option} + + ))} + : ""} > @@ -241,6 +377,41 @@ export function DateRangePickerMain(props) { + + + + + {timeAdjustmentOptions.map(option => ( + handleClose(e, 'forward', option)}> + {option} + + ))} + + { + adjustTimeRange("forward"); + }} + attachedSide={'l'} + className={"date-time-selector"} + > + + {rangeOpen ? (
diff --git a/src/components/StatusBar/styled/index.js b/src/components/StatusBar/styled/index.js index 6ae18770..452f60c4 100644 --- a/src/components/StatusBar/styled/index.js +++ b/src/components/StatusBar/styled/index.js @@ -135,11 +135,21 @@ 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' ? '0' : ''}; + border-top-right-radius: ${(props) => props.attachedSide === 'r' ? '0' : ''}; + border-bottom-left-radius: ${(props) => props.attachedSide === 'l' ? '0' : ''}; + border-bottom-right-radius: ${(props) => props.attachedSide === 'r' ? '0' : ''}; + border-right: ${(props) => props.attachedSide === 'r' ? 'unset' : ''}; height: 26px; - margin-left: 10px; + margin-left: ${(props) => props.attachedSide && !props.emptySide ? '' : '10px'}; + padding: ${(props) => props.size === 'small' ? '3px 5px' : ''}; span { margin-left: 5px; } + svg { + margin: 0; + padding: 0; + } &:hover { color: orange; } From 985babe4fc12af6c208d5d89a5f62e2cc81d435d Mon Sep 17 00:00:00 2001 From: jacovinus Date: Thu, 15 Dec 2022 18:27:02 +0100 Subject: [PATCH 12/40] feat: #160 and #161 --- package.json | 7 +- src/index.js | 4 +- src/views/DataSources/DataSource.js | 7 + src/views/DataSources/store/defaults.ts | 2 - src/views/Main.js | 169 ++++++++++++++++++++++-- 5 files changed, 172 insertions(+), 17 deletions(-) diff --git a/package.json b/package.json index d5f7efae..211e3a25 100644 --- a/package.json +++ b/package.json @@ -50,6 +50,7 @@ "papaparse": "^5.3.2", "prismjs": "^1.27.0", "react": "^17.0.2", + "react-cookie": "^4.1.1", "react-custom-scrollbars-2": "^4.4.0", "react-dom": "^17.0.2", "react-flot": "^1.3.0", @@ -122,8 +123,8 @@ "@types/moment": "^2.13.0", "@types/papaparse": "^5.3.5", "@types/react-redux": "^7.1.24", - "@types/tinycolor2": "^1.4.3", "@types/react-resizable": "^3.0.3", + "@types/tinycolor2": "^1.4.3", "babel-loader": "^8.2.3", "babel-plugin-syntax-dynamic-import": "^6.18.0", "babel-plugin-transform-class-properties": "^6.24.1", @@ -134,6 +135,7 @@ "file-loader": "^6.2.0", "html-loader": "^3.1.0", "html-webpack-plugin": "^5.5.0", + "http-proxy-middleware": "^2.0.6", "mini-css-extract-plugin": "^2.5.3", "react-hot-loader": "^4.13.0", "react-scripts": "^5.0.0", @@ -147,7 +149,6 @@ "webpack": "^5.67.0", "webpack-cli": "^4.9.2", "webpack-dev-server": "^4.7.3", - "webpack-merge": "^5.8.0", - "http-proxy-middleware": "^2.0.6" + "webpack-merge": "^5.8.0" } } diff --git a/src/index.js b/src/index.js index 6b005f88..d34654e8 100644 --- a/src/index.js +++ b/src/index.js @@ -12,11 +12,12 @@ 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) ReactDOM.render( + @@ -27,6 +28,7 @@ ReactDOM.render( + , document.getElementById('root') ); diff --git a/src/views/DataSources/DataSource.js b/src/views/DataSources/DataSource.js index 2116fa9e..12fa7d78 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"; @@ -29,6 +30,7 @@ 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); @@ -56,6 +58,11 @@ export function DataSourceSetting(props) { }, }, })); + // var today = new Date() + // var tomorrow = new Date(); + // tomorrow.setDate(today.getDate()+1); + // setCookie('qryn-session', `${btoa('harry')}:${btoa('potter')}`, {path:'/',expires:tomorrow} ) // uncomment for testing cookies feature + localStorage.setItem("dataSources", JSON.stringify(newDs)); dispatch(setDataSources(newDs)); dispatch(createAlert({ diff --git a/src/views/DataSources/store/defaults.ts b/src/views/DataSources/store/defaults.ts index 361e944f..3576cb6c 100644 --- a/src/views/DataSources/store/defaults.ts +++ b/src/views/DataSources/store/defaults.ts @@ -33,8 +33,6 @@ export const defaultFluxDataSourceHeaders = [ } ]; -// 'Authorization' : 'Basic ZGVmYXVsdDo=' - export const defaultLogsLinkedFields = [ { id: nanoid(), diff --git a/src/views/Main.js b/src/views/Main.js index cc58d9c5..c9f59465 100644 --- a/src/views/Main.js +++ b/src/views/Main.js @@ -12,6 +12,9 @@ import { useMediaQuery } from "react-responsive"; import MainTabs from "./MainTabs.js"; import { setTheme } from "../actions"; import { useMemo, useState, useEffect, useRef } from "react"; +import { useCookies } from "react-cookie"; +import { useLocation } from "react-router-dom"; +import setDataSources from "./DataSources/store/setDataSources"; export const MainContainer = styled.div` position: absolute; @@ -75,16 +78,20 @@ export function DesktopView({ theme, isEmbed, isSplit, settingsDialogOpen }) { const [maxWidth, setMaxWidth] = useState(0); const refTotal = useRef(null); useEffect(() => { - const widthTotal = refTotal.current.clientWidth + const widthTotal = refTotal.current.clientWidth; setHeight(refTotal.current.clientHeight); setWidthTotal(refTotal.current.clientWidth); setWidthLeft(widthTotal / (isSplit ? 2 : 1)); if (isSplit) { setWidthRight(widthTotal / 2); } - const realMinWidth = !isSplit ? widthTotal : widthTotal / 4 > 370 ? widthTotal / 4 : 370; + const realMinWidth = !isSplit + ? widthTotal + : widthTotal / 4 > 370 + ? widthTotal / 4 + : 370; setMinWidth(realMinWidth); - const realMaxWidth = !isSplit ? widthTotal : widthTotal - realMinWidth + const realMaxWidth = !isSplit ? widthTotal : widthTotal - realMinWidth; setMaxWidth(realMaxWidth); }, [ setWidthLeft, @@ -97,7 +104,7 @@ export function DesktopView({ theme, isEmbed, isSplit, settingsDialogOpen }) { isSplit, ]); useEffect(() => { - const widthTotal = refTotal.current.clientWidth + const widthTotal = refTotal.current.clientWidth; setWidthLeftPercent(widthLeft / widthTotal); if (isSplit) { setWidthRightercent(widthRight / widthTotal); @@ -105,7 +112,7 @@ export function DesktopView({ theme, isEmbed, isSplit, settingsDialogOpen }) { }, [widthLeft, widthRight]); useEffect(() => { const onWindowResize = () => { - const widthTotal = refTotal.current.clientWidth + const widthTotal = refTotal.current.clientWidth; setWidthTotal(widthTotal); setWidthLeft(widthTotal * widthLeftPercent); if (isSplit) { @@ -156,7 +163,7 @@ export function DesktopView({ theme, isEmbed, isSplit, settingsDialogOpen }) { handleSize={[10, 10]} onResize={onSplitResize} > */} - + {/* */} {isSplit && ( // - + // )}
@@ -185,10 +192,150 @@ export function DesktopView({ theme, isEmbed, isSplit, settingsDialogOpen }) { ); } +// useCookiesAvailable: + +export function useCookiesAvailable(urlParams) { + let cookieAuth = ""; + let cookiesAvailable = false; + + const hasCookie = useMemo(() => { + return urlParams.has("cookie") || false; + }, [urlParams]); + + const cookieParam = useMemo(() => { + if (hasCookie) { + return urlParams.get("cookie"); + } + return ""; + }, [urlParams, hasCookie]); + + const [cookie, _] = useCookies([cookieParam]); + + if (cookie[cookieParam] && cookie[cookieParam] !== "") { + cookieAuth = cookie[cookieParam]; + cookiesAvailable = true; + } + return { cookieAuth, cookiesAvailable }; +} + +// useUrlAvailable: + +export function useUrlAvailable(urlParams) { + const hasOneForAll = useMemo(() => { + return urlParams.has("url"); + }, [urlParams]); + + const oneForAllParam = useMemo(() => { + if (hasOneForAll) { + return urlParams.get("url"); + } + return ""; + }, [urlParams, hasOneForAll]); + + return { url: oneForAllParam, urlAvailable: hasOneForAll }; +} + +// updateDataSources: + +export function updateDataSourcesWithUrl( + dispatch, + url, + cookies, + haveUrl, + haveCookies, + dataSources +) { + let apiUrl = ""; + let basicAuth = false; + let urlApi = false; + let cookieAuth = {}; + + if (haveUrl) { + urlApi = true; + } + + if (haveCookies) { + let [user, pass] = cookies.split(":"); + if (user !== "" && pass !== "") { + cookieAuth = { user, password: pass }; + basicAuth = true; + } + } + + if (!haveUrl && basicAuth) { + apiUrl = window.location.protocol + "//" + window.location.host; + urlApi = true; + } else { + apiUrl = url; + } + + const dsCP = [...dataSources]; + const prevDs = JSON.parse(JSON.stringify(dsCP)); + + const newDs = prevDs?.map((m) => ({ + ...m, + url: urlApi ? apiUrl : m.url, + auth: { + ...m.auth, + basicAuth: { ...m.auth.basicAuth, value: basicAuth }, + fields: { + ...m.auth.fields, + basicAuth: basicAuth + ? [...m.auth.fields.basicAuth]?.map((ba) => { + if (ba.name === "user") { + return { ...ba, value: cookieAuth.user }; + } + if (ba.name === "password") { + return { ...ba, value: cookieAuth.password }; + } + return ba; + }) + : [...m.auth.fields.basicAuth], + }, + }, + })); + dispatch(setDataSources(newDs)); +} + export default function Main() { UpdateStateFromQueryParams(); + + const dataSources = useSelector((store) => store.dataSources); + // get hash from current location + const { hash } = useLocation(); + // get url params as object + const paramsMemo = useMemo(() => { + return new URLSearchParams(hash.replace("#", "")); + }, [hash]); + // + + const { cookiesAvailable, cookieAuth } = useCookiesAvailable(paramsMemo); + const { urlAvailable, url } = useUrlAvailable(paramsMemo); + + useEffect(() => { + const onlyCookie = cookiesAvailable && !urlAvailable; + const onlyUrl = !cookiesAvailable && urlAvailable; + const urlAndCookie = + cookiesAvailable && + cookieAuth !== "" && + urlAvailable && + urlAvailable !== ""; + + if (onlyCookie || onlyUrl || urlAndCookie) { + // update datasources with url and basic auth + updateDataSourcesWithUrl( + dispatch, + url, + cookieAuth, + urlAvailable, + cookiesAvailable, + dataSources + ); + } + }, []); + const isTabletOrMobile = useMediaQuery({ query: "(max-width: 914px)" }); - const isAutoDark = useMediaQuery({query: "(prefers-color-scheme: dark)"}); + const isAutoDark = useMediaQuery({ query: "(prefers-color-scheme: dark)" }); const dispatch = useDispatch(); const isSplit = useSelector((store) => store.isSplit); const isEmbed = useSelector((store) => store.isEmbed); @@ -196,12 +343,12 @@ export default function Main() { const autoTheme = useSelector((store) => store.autoTheme); const settingsDialogOpen = useSelector((store) => store.settingsDialogOpen); const themeMemo = useMemo(() => themes[theme], [theme]); - useEffect(()=>{ + useEffect(() => { if (autoTheme) { - const theme = isAutoDark ? 'dark' : 'light'; + const theme = isAutoDark ? "dark" : "light"; dispatch(setTheme(theme)); } - },[isAutoDark, autoTheme, dispatch]) + }, [isAutoDark, autoTheme, dispatch]); if (!isTabletOrMobile) { // desktop view return ( From 7c9c7069db395f310c511eee02e84892e127eb4d Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Thu, 15 Dec 2022 11:07:31 +0200 Subject: [PATCH 13/40] Fix: #156 --- .../LabelBrowser/components/LabelsSelector/LabelsList.js | 5 +++-- src/components/QueryItem/QueryItem.js | 2 ++ src/components/QueryItem/QueryItemToolbar.js | 7 +++++++ 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js b/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js index 18526025..20f727ea 100644 --- a/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js +++ b/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js @@ -2,7 +2,7 @@ import { useMemo } from "react"; import styled from "@emotion/styled"; import ShowLogsButton from "../Buttons/ShowLogsButton"; import { queryBuilder } from "../../helpers/querybuilder"; -import { useDispatch } from "react-redux"; +import { useDispatch, useSelector } from "react-redux"; import { setLeftPanel } from "../../../../actions/setLeftPanel"; import { setRightPanel } from "../../../../actions/setRightPanel"; import store from "../../../../store/store"; @@ -54,6 +54,7 @@ export default function LabelsList(props) { const dispatch = useDispatch(); const { labels, data, name } = props; const { dataSourceType } = data; + const panelQuery = useSelector((store) => store[name]); const onClick = (e) => { if (e === "Select Metric") { @@ -77,7 +78,7 @@ export default function LabelsList(props) { const useQuery = () => { const qu = queryBuilder(data.labels, data.expr) - const panel = [data]; + const panel = [...panelQuery]; panel.forEach((query) => { if (query.id === props.data.id) { query.expr = qu; diff --git a/src/components/QueryItem/QueryItem.js b/src/components/QueryItem/QueryItem.js index cd56b0e9..fcfe85df 100644 --- a/src/components/QueryItem/QueryItem.js +++ b/src/components/QueryItem/QueryItem.js @@ -123,6 +123,8 @@ export default function QueryItem(props) { ...props.data, id: nanoid(), idRef, + labels: [], + expr: "", lastIdx: lastIdx + 1, cp: 0, }; diff --git a/src/components/QueryItem/QueryItemToolbar.js b/src/components/QueryItem/QueryItemToolbar.js index a76bd7ac..e227adcd 100644 --- a/src/components/QueryItem/QueryItemToolbar.js +++ b/src/components/QueryItem/QueryItemToolbar.js @@ -12,6 +12,7 @@ import AddOutlinedIcon from "@mui/icons-material/AddOutlined"; import { useEffect, useMemo, useState } from "react"; import { QueryId } from "./QueryId"; import { DataSourceSelect } from "./DataSourceSelect"; +import { Tooltip } from "@mui/material"; export function QueryItemToolbar(props) { const dispatch = useDispatch(); // update panel on id change @@ -170,6 +171,8 @@ export function QueryItemToolbar(props) { opts={dataSourceOptions} label={""} /> + + + + + +
)} From 66aeac9e989e5d1193ff1b4758f075c70618ce79 Mon Sep 17 00:00:00 2001 From: Eduard Klimenko Date: Thu, 15 Dec 2022 10:38:12 +0200 Subject: [PATCH 14/40] .js to .ts(tsx) for index / helpers --- ...arams.js => UpdateStateFromQueryParams.ts} | 464 +++++++++--------- .../{decodeQuery.js => decodeQuery.ts} | 395 +++++++-------- ...or.interceptor.js => error.interceptor.ts} | 165 ++++--- src/helpers/{httpclient.js => httpclient.ts} | 0 src/helpers/{setDebug.js => setDebug.ts} | 2 +- ...QueryParams.js => stateFromQueryParams.ts} | 228 ++++----- .../{useQueryParams.js => useQueryParams.ts} | 2 +- src/hooks/{useLabels.js => useLabels.ts} | 179 +++---- src/{index.js => index.tsx} | 4 +- src/services/consts.js | 16 - src/services/consts.ts | 16 + src/setupTests.js | 5 - webpack.config.js | 2 +- webpack.config.prod.js | 2 +- 14 files changed, 742 insertions(+), 738 deletions(-) rename src/helpers/{UpdateStateFromQueryParams.js => UpdateStateFromQueryParams.ts} (84%) rename src/helpers/{decodeQuery.js => decodeQuery.ts} (78%) rename src/helpers/{error.interceptor.js => error.interceptor.ts} (92%) rename src/helpers/{httpclient.js => httpclient.ts} (100%) rename src/helpers/{setDebug.js => setDebug.ts} (62%) rename src/helpers/{stateFromQueryParams.js => stateFromQueryParams.ts} (91%) rename src/helpers/{useQueryParams.js => useQueryParams.ts} (97%) rename src/hooks/{useLabels.js => useLabels.ts} (79%) rename src/{index.js => index.tsx} (88%) delete mode 100644 src/services/consts.js create mode 100644 src/services/consts.ts delete mode 100644 src/setupTests.js 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 100% rename from src/helpers/httpclient.js rename to src/helpers/httpclient.ts 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 91% rename from src/helpers/stateFromQueryParams.js rename to src/helpers/stateFromQueryParams.ts index 3cb1eb1f..67dcb557 100644 --- a/src/helpers/stateFromQueryParams.js +++ b/src/helpers/stateFromQueryParams.ts @@ -1,114 +1,114 @@ -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: "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: 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; + } + } + + 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.tsx similarity index 88% rename from src/index.js rename to src/index.tsx index d34654e8..63f15203 100644 --- a/src/index.js +++ b/src/index.tsx @@ -21,8 +21,8 @@ ReactDOM.render( - } /> - } /> + } /> + } /> }/> 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/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/webpack.config.js b/webpack.config.js index f06776e7..8998fd0e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -5,7 +5,7 @@ const webpack = require("webpack"); module.exports = { mode: "development", - entry: "./src/index.js", + entry: "./src/index.tsx", output: { path: path.resolve(__dirname, "build"), filename: "bundled.js", diff --git a/webpack.config.prod.js b/webpack.config.prod.js index 092ca77a..bc0b14fd 100644 --- a/webpack.config.prod.js +++ b/webpack.config.prod.js @@ -6,7 +6,7 @@ const path = require("path") const TerserPlugin = require('terser-webpack-plugin') module.exports = { mode: 'production', - entry: './src/index.js', + entry: './src/index.tsx', output: { path: path.resolve(__dirname, "build"), filename: "bundle.js", From c98f9039bb0c9e98934a03197d8060e21676ab1d Mon Sep 17 00:00:00 2001 From: Eduard Klimenko Date: Thu, 15 Dec 2022 10:47:21 +0200 Subject: [PATCH 15/40] fix httpclient.ts --- src/helpers/httpclient.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/helpers/httpclient.ts b/src/helpers/httpclient.ts index 64051714..5962e513 100644 --- a/src/helpers/httpclient.ts +++ 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 From 783df458620e454ec45d458a04354344a710acf1 Mon Sep 17 00:00:00 2001 From: Eduard Klimenko Date: Thu, 15 Dec 2022 19:44:45 +0200 Subject: [PATCH 16/40] .js to .ts(tsx) for Panel & components/QueryItem --- src/components/Panel/{Panel.js => Panel.tsx} | 12 +++---- ...taSourceSelect.js => DataSourceSelect.tsx} | 8 ++--- .../QueryItem/{QueryId.js => QueryId.tsx} | 13 ++++---- .../QueryItem/{QueryItem.js => QueryItem.tsx} | 30 +++++++++-------- ...eryItemToolbar.js => QueryItemToolbar.tsx} | 33 +++++++++---------- .../QueryItem/{style.js => style.tsx} | 16 ++++----- 6 files changed, 57 insertions(+), 55 deletions(-) rename src/components/Panel/{Panel.js => Panel.tsx} (87%) rename src/components/QueryItem/{DataSourceSelect.js => DataSourceSelect.tsx} (83%) rename src/components/QueryItem/{QueryId.js => QueryId.tsx} (82%) rename src/components/QueryItem/{QueryItem.js => QueryItem.tsx} (82%) rename src/components/QueryItem/{QueryItemToolbar.js => QueryItemToolbar.tsx} (84%) rename src/components/QueryItem/{style.js => style.tsx} (74%) diff --git a/src/components/Panel/Panel.js b/src/components/Panel/Panel.tsx similarity index 87% rename from src/components/Panel/Panel.js rename to src/components/Panel/Panel.tsx index 976f5882..1741989a 100644 --- a/src/components/Panel/Panel.js +++ b/src/components/Panel/Panel.tsx @@ -7,28 +7,28 @@ import { setRightPanel } from "../../actions/setRightPanel"; import { setLeftPanel } from "../../actions/setLeftPanel"; import DataViews from "../DataViews"; -const PanelCont = styled.div` +const PanelCont: any = styled.div` display: flex; flex-direction: column; flex: 1; width: 100%; `; // Panel should have injected data -export default function Panel(props) { +export default function Panel(props: any) { - const ref = useRef(null); + const ref: any = useRef(null); const [width, setWidth] = useState(0); const dispatch = useDispatch(); const { name } = props; - const panelDispatch = (name, data) => { + const panelDispatch = (name: string, data: any) => { if (name === "left") return setLeftPanel(data); return setRightPanel(data); }; - const panel = useSelector((store) => store[name]); - const isSplit = useSelector((store) => store.isSplit); + const panel = useSelector((store: any) => store[name]); + const isSplit = useSelector((store: any) => store.isSplit); const { hash } = useLocation(); useEffect(() => { diff --git a/src/components/QueryItem/DataSourceSelect.js b/src/components/QueryItem/DataSourceSelect.tsx similarity index 83% rename from src/components/QueryItem/DataSourceSelect.js rename to src/components/QueryItem/DataSourceSelect.tsx index 02d874e8..94240755 100644 --- a/src/components/QueryItem/DataSourceSelect.js +++ b/src/components/QueryItem/DataSourceSelect.tsx @@ -3,10 +3,10 @@ import { InputGroup } from "../../views/DataSources/styles"; import { Label } from "./style"; -export const DataSourceSelect = (props) => { +export const DataSourceSelect = (props: any) => { const { value, onChange, opts, label, extValue } = props; - const selectRef = useRef(null); + const selectRef: any = useRef(null); useEffect(() => { if (value.value !== extValue) { @@ -22,7 +22,7 @@ export const DataSourceSelect = (props) => { const formattedSelect = useMemo(() => { if (typeof opts[0] === "string") { - return opts.map((k) => ({ value: k, name: k })); + return opts.map((k: any) => ({ value: k, name: k })); } else return opts; }, [opts]); @@ -35,7 +35,7 @@ export const DataSourceSelect = (props) => { defaultValue={extValue} onChange={onChange} > - {formattedSelect?.map((field, key) => ( + {formattedSelect?.map((field: any, key: number) => ( diff --git a/src/components/QueryItem/QueryId.js b/src/components/QueryItem/QueryId.tsx similarity index 82% rename from src/components/QueryItem/QueryId.js rename to src/components/QueryItem/QueryId.tsx index b4b66cc2..5b031c98 100644 --- a/src/components/QueryItem/QueryId.js +++ b/src/components/QueryItem/QueryId.tsx @@ -2,25 +2,26 @@ import { useMemo, useState } from "react"; import { useSelector } from "react-redux"; import { themes } from "../../theme/themes"; -export function QueryId(props) { +export function QueryId(props: any) { const [isEditing, setIsEditing] = useState(false); const [idText, setIdText] = useState(props.data.idRef); - const storeTheme = useSelector(({ theme }) => theme); + const storeTheme = useSelector(({ theme }: any) => theme); const theme = useMemo(() => { - return themes[storeTheme]; + const _themes: any = themes + return _themes[storeTheme]; }, [storeTheme]); - function onIdTextChange(e) { + function onIdTextChange(e: any) { e.preventDefault(); const txt = e.target.value; setIdText(txt); } - function closeInput(e) { + function closeInput(e: any) { props.onIdRefUpdate(idText); setIsEditing(false); } - function handleKeydown(e) { + function handleKeydown(e: any) { if (e.key === "Enter") { props.onIdRefUpdate(idText); setIsEditing(false); diff --git a/src/components/QueryItem/QueryItem.js b/src/components/QueryItem/QueryItem.tsx similarity index 82% rename from src/components/QueryItem/QueryItem.js rename to src/components/QueryItem/QueryItem.tsx index cd56b0e9..e1a560d9 100644 --- a/src/components/QueryItem/QueryItem.js +++ b/src/components/QueryItem/QueryItem.tsx @@ -16,7 +16,7 @@ import { QueryItemToolbar } from "./QueryItemToolbar"; const QueryContainer = styled.div``; -const panelAction = (panel, data) => { +const panelAction = (panel: any, data: any) => { if (panel === "left") { return setLeftPanel(data); } else { @@ -24,7 +24,7 @@ const panelAction = (panel, data) => { } }; -const dataViewAction = (panel, data) => { +const dataViewAction = (panel: any, data: any) => { if (panel === "left") { return setLeftDataView(data); } else { @@ -32,7 +32,7 @@ const dataViewAction = (panel, data) => { } }; -export default function QueryItem(props) { +export default function QueryItem(props: any) { const { name } = props; const { expr, @@ -72,14 +72,14 @@ export default function QueryItem(props) { }, []); const dispatch = useDispatch(); - const theme = useSelector((store) => store.theme); - const dataView = useSelector((store) => store[`${name}DataView`]); - const panelSelected = useSelector((store) => store[name]); + const theme = useSelector((store: any) => store.theme); + const dataView = useSelector((store: any) => store[`${name}DataView`]); + const panelSelected = useSelector((store: any) => store[name]); const isQueryOpen = useState(true); - function filterPanel(panel) { + function filterPanel(panel: any) { if (panel?.length > 1) { - return panel?.filter((query) => query?.id !== props?.data?.id); + return panel?.filter((query: any) => query?.id !== props?.data?.id); } else { return panel; } @@ -106,7 +106,7 @@ export default function QueryItem(props) { }; const onAddQuery = () => { - const getIdref = (lastIdx) => { + const getIdref = (lastIdx: any) => { if (lastIdx > idRefs.length - 1) { return `${idRefs[0]}${lastIdx}`; } else { @@ -114,11 +114,11 @@ export default function QueryItem(props) { } }; - const getLastIndex = (panel) => { + const getLastIndex = (panel: any) => { return panel[panel.length - 1].lastIdx; }; - const setNewPanel = (lastIdx, panel, idRef) => { + const setNewPanel = (lastIdx: any, panel: any, idRef: any) => { const newQuery = { ...props.data, id: nanoid(), @@ -129,7 +129,7 @@ export default function QueryItem(props) { return [...panel, newQuery]; }; - const setNewPanelData = (panel) => { + const setNewPanelData = (panel: any) => { const lastIdx = getLastIndex(panel); const idRef = getIdref(lastIdx); return setNewPanel(lastIdx, panel, idRef); @@ -139,9 +139,11 @@ export default function QueryItem(props) { dispatch(panelAction(name, panelData)); }; - + + const _themes: any = themes; + return ( - + store[props.name]); - const isEmbed = useSelector((store) => store.isEmbed); + const panel = useSelector((store: any) => store[props.name]); + const isEmbed = useSelector((store: any) => store.isEmbed); - const dataSources = useSelector((store) => store.dataSources); + const dataSources = useSelector((store: any) => store.dataSources); const [extValue, setExtValue] = useState(props.data.dataSourceId); @@ -36,7 +36,7 @@ export function QueryItemToolbar(props) { const dataSourceOptions = useMemo(() => { if (dataSources.length > 0) { - return dataSources.map((m) => ({ + return dataSources.map((m: any) => ({ value: m.id, name: m.name, type: m.type, @@ -49,17 +49,17 @@ export function QueryItemToolbar(props) { const [dataSourceValue, setDataSourceValue] = useState({ value: props.data.dataSourceId, name: - dataSources.find((f) => f.id === props?.data?.dataSourceId)?.[ + dataSources.find((f: any) => f.id === props?.data?.dataSourceId)?.[ "name" ] || props.data.dataSourceId, type: props.data.dataSourceType, icon: - dataSources.find((f) => f.id === props?.data?.dataSourceId)?.[ + dataSources.find((f: any) => f.id === props?.data?.dataSourceId)?.[ "icon" ] || props.data.dataSourceId, }); - const panelAction = (panel, data) => { + const panelAction = (panel: string, data: any) => { if (panel === "left") { return setLeftPanel(data); } else { @@ -67,7 +67,7 @@ export function QueryItemToolbar(props) { } }; - function onIdRefUpdate(e) { + function onIdRefUpdate(e: any) { const cPanel = [...panel]; cPanel.forEach((panel) => { if (panel.id === props.data.id) { @@ -79,9 +79,8 @@ export function QueryItemToolbar(props) { } const getPrevDsLocal = () => { - let localDataSources = []; try { - localDataSources = localStorage.getItem("dsSelected"); + const localDataSources: any = localStorage.getItem("dsSelected"); if (localDataSources) { return JSON.parse(localDataSources); } else { @@ -92,19 +91,19 @@ export function QueryItemToolbar(props) { } }; - const onDataSourceChange = (e) => { + const onDataSourceChange = (e: any) => { const value = e.target.value; - const dataSource = dataSources.find((f) => f.id === value); + const dataSource = dataSources.find((f: any) => f.id === value); const panelCP = JSON.parse(JSON.stringify(panel)); - const optSelected = dataSourceOptions.find((f) => f.value === value); + const optSelected = dataSourceOptions.find((f: any) => f.value === value); const currentLocal = getPrevDsLocal(); let newDsLocal = []; if (currentLocal?.length > 0) { const hasPrevQuery = - currentLocal?.find((s) => s.queryId === props.data.id) || false; + currentLocal?.find((s: any) => s.queryId === props.data.id) || false; if (hasPrevQuery) { - newDsLocal = currentLocal.map((m) => { + newDsLocal = currentLocal.map((m: any) => { if (m.queryId === props.data.id) { return { queryId: m.queryId, @@ -129,7 +128,7 @@ export function QueryItemToolbar(props) { setDataSourceValue((_) => optSelected); - panelCP.forEach((panelCP) => { + panelCP.forEach((panelCP: any) => { if (panelCP.id === props.data.id) { panelCP.dataSourceId = dataSource.id; panelCP.dataSourceType = dataSource.type; diff --git a/src/components/QueryItem/style.js b/src/components/QueryItem/style.tsx similarity index 74% rename from src/components/QueryItem/style.js rename to src/components/QueryItem/style.tsx index 53c07fe4..30c6cc65 100644 --- a/src/components/QueryItem/style.js +++ b/src/components/QueryItem/style.tsx @@ -4,8 +4,8 @@ import styled from "@emotion/styled"; export const QueryItemToolbarStyled = styled.div` - background: ${({ theme }) => `${theme.secondaryWidgetContainer}`}; - color: ${({ theme }) => `${theme.textColor}`}; + background: ${({ theme }: any) => `${theme.secondaryWidgetContainer}`}; + color: ${({ theme }: any) => `${theme.textColor}`}; display: flex; justify-content: space-between; align-items: center; @@ -35,12 +35,12 @@ export const ShowQueryButton = styled.button` export const OpenQuery = styled(KeyboardArrowDownOutlinedIcon)` font-size: 13px; - color: ${({ theme }) => theme.textColor}; + color: ${({ theme }: any) => theme.textColor}; `; export const CloseQuery = styled(KeyboardArrowRightOutlinedIcon)` font-size: 13px; - color: ${({ theme }) => theme.textColor}; + color: ${({ theme }: any) => theme.textColor}; `; export const InputGroup = styled.div` @@ -50,9 +50,9 @@ export const InputGroup = styled.div` margin-top: 5px; align-items: center; select { - background: ${(props) => props.theme.inputBg}; - color: ${(props) => props.theme.textColor}; - border: 1px solid ${(props) => props.theme.buttonBorder}; + background: ${(props: any) => props.theme.inputBg}; + color: ${(props: any) => props.theme.textColor}; + border: 1px solid ${(props: any) => props.theme.buttonBorder}; border-radius:3px; font-size:12px; height:26px; @@ -60,7 +60,7 @@ export const InputGroup = styled.div` `; export const Label = styled.div` - color: ${(props) => props.theme.textColor}; + color: ${(props: any) => props.theme.textColor}; display: flex; align-items: center; font-size: 12px; From 66e5209e9af38706ad81961baa81543ba3aee55f Mon Sep 17 00:00:00 2001 From: Eduard Klimenko Date: Thu, 15 Dec 2022 20:25:37 +0200 Subject: [PATCH 17/40] fix: components/QueryItemToolBar.tsx --- src/components/QueryItem/QueryItemToolbar.tsx | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/src/components/QueryItem/QueryItemToolbar.tsx b/src/components/QueryItem/QueryItemToolbar.tsx index a76bd7ac..2246d919 100644 --- a/src/components/QueryItem/QueryItemToolbar.tsx +++ b/src/components/QueryItem/QueryItemToolbar.tsx @@ -12,17 +12,17 @@ import AddOutlinedIcon from "@mui/icons-material/AddOutlined"; import { useEffect, useMemo, useState } from "react"; import { QueryId } from "./QueryId"; import { DataSourceSelect } from "./DataSourceSelect"; -export function QueryItemToolbar(props) { +export function QueryItemToolbar(props: any) { const dispatch = useDispatch(); // update panel on id change const { data: { expr }, } = props; - const panel = useSelector((store) => store[props.name]); - const isEmbed = useSelector((store) => store.isEmbed); + const panel = useSelector((store: any) => store[props.name]); + const isEmbed = useSelector((store: any) => store.isEmbed); - const dataSources = useSelector((store) => store.dataSources); + const dataSources = useSelector((store: any) => store.dataSources); const [extValue, setExtValue] = useState(props.data.dataSourceId); @@ -36,7 +36,7 @@ export function QueryItemToolbar(props) { const dataSourceOptions = useMemo(() => { if (dataSources.length > 0) { - return dataSources.map((m) => ({ + return dataSources.map((m: any) => ({ value: m.id, name: m.name, type: m.type, @@ -49,17 +49,17 @@ export function QueryItemToolbar(props) { const [dataSourceValue, setDataSourceValue] = useState({ value: props.data.dataSourceId, name: - dataSources.find((f) => f.id === props?.data?.dataSourceId)?.[ + dataSources.find((f: any) => f.id === props?.data?.dataSourceId)?.[ "name" ] || props.data.dataSourceId, type: props.data.dataSourceType, icon: - dataSources.find((f) => f.id === props?.data?.dataSourceId)?.[ + dataSources.find((f: any) => f.id === props?.data?.dataSourceId)?.[ "icon" ] || props.data.dataSourceId, }); - const panelAction = (panel, data) => { + const panelAction = (panel: any, data: any) => { if (panel === "left") { return setLeftPanel(data); } else { @@ -67,7 +67,7 @@ export function QueryItemToolbar(props) { } }; - function onIdRefUpdate(e) { + function onIdRefUpdate(e: any) { const cPanel = [...panel]; cPanel.forEach((panel) => { if (panel.id === props.data.id) { @@ -79,8 +79,8 @@ export function QueryItemToolbar(props) { } const getPrevDsLocal = () => { - let localDataSources = []; try { + let localDataSources: any = ''; localDataSources = localStorage.getItem("dsSelected"); if (localDataSources) { return JSON.parse(localDataSources); @@ -92,19 +92,19 @@ export function QueryItemToolbar(props) { } }; - const onDataSourceChange = (e) => { + const onDataSourceChange = (e: any) => { const value = e.target.value; - const dataSource = dataSources.find((f) => f.id === value); + const dataSource = dataSources.find((f: any) => f.id === value); const panelCP = JSON.parse(JSON.stringify(panel)); - const optSelected = dataSourceOptions.find((f) => f.value === value); + const optSelected = dataSourceOptions.find((f: any) => f.value === value); const currentLocal = getPrevDsLocal(); let newDsLocal = []; if (currentLocal?.length > 0) { const hasPrevQuery = - currentLocal?.find((s) => s.queryId === props.data.id) || false; + currentLocal?.find((s: any) => s.queryId === props.data.id) || false; if (hasPrevQuery) { - newDsLocal = currentLocal.map((m) => { + newDsLocal = currentLocal.map((m: any) => { if (m.queryId === props.data.id) { return { queryId: m.queryId, @@ -129,7 +129,7 @@ export function QueryItemToolbar(props) { setDataSourceValue((_) => optSelected); - panelCP.forEach((panelCP) => { + panelCP.forEach((panelCP: any) => { if (panelCP.id === props.data.id) { panelCP.dataSourceId = dataSource.id; panelCP.dataSourceType = dataSource.type; From 3398956d6137004e86a9231c1ce948d694a55122 Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Fri, 16 Dec 2022 12:35:25 +0200 Subject: [PATCH 18/40] Fixed remaining bugs in #105 --- src/components/StatusBar/components/daterangepicker/index.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/components/StatusBar/components/daterangepicker/index.js b/src/components/StatusBar/components/daterangepicker/index.js index a6fb4488..23375a9b 100644 --- a/src/components/StatusBar/components/daterangepicker/index.js +++ b/src/components/StatusBar/components/daterangepicker/index.js @@ -379,9 +379,9 @@ export function DateRangePickerMain(props) { + Date: Fri, 16 Dec 2022 13:48:26 +0100 Subject: [PATCH 19/40] feat: Feat get data sources data from cookie #170 --- src/actions/getData.ts | 2 +- .../components/Buttons/ShowLogsButton.tsx | 17 ++--- .../components/LabelsSelector/LabelsList.js | 1 + .../LabelBrowser/components/QueryBar.js | 14 ++--- .../components/apiselector/ApiSelector.js | 40 +++++++----- src/index.tsx | 63 ++++++++++--------- src/plugins/settingsmenu/Menu.js | 18 ++++-- src/store/createInitialState.ts | 1 + src/store/reducer.ts | 2 + src/views/DataSources/DataSource.js | 63 +++++++++++++------ src/views/Main.js | 26 +++++++- src/views/Main/setShowDataSourceSetting.ts | 7 +++ 12 files changed, 167 insertions(+), 87 deletions(-) create mode 100644 src/views/Main/setShowDataSourceSetting.ts diff --git a/src/actions/getData.ts b/src/actions/getData.ts index 2d926086..83b14bfc 100644 --- a/src/actions/getData.ts +++ b/src/actions/getData.ts @@ -40,7 +40,7 @@ function panelDispatch(panel: string, dispatch: Function, data: any) { function changeLoadingState(panel: any[], id: string, state: boolean) { return [...panel].map((m) => { if (m.id === id) { - return { ...m, loading: state }; + return { ...m, loading: state || false }; } return m; }); diff --git a/src/components/LabelBrowser/components/Buttons/ShowLogsButton.tsx b/src/components/LabelBrowser/components/Buttons/ShowLogsButton.tsx index 83295185..d7ca0e2e 100644 --- a/src/components/LabelBrowser/components/Buttons/ShowLogsButton.tsx +++ b/src/components/LabelBrowser/components/Buttons/ShowLogsButton.tsx @@ -5,13 +5,14 @@ import { useSelector } from "react-redux"; import { Button } from "./Button.model"; import { Store } from "../../../../store/store.model"; const _themes = themes as any; -export default function ShowLogsButton({ - isDisabled, - onClick, - isMobile, - alterText, - loading, -}: Button) { +export default function ShowLogsButton(props:any) { + const { + isDisabled, + onClick, + isMobile, + alterText, + loading = false, + } = props const SHOW_LOGS = "Show Results"; const theme = useSelector((store: Store) => store.theme); return ( @@ -21,7 +22,7 @@ export default function ShowLogsButton({ type="submit" onClick={onClick} isMobile={isMobile} - loading={loading} + loading={loading || false} > {loading ? <>Loading... : <>{alterText || SHOW_LOGS}} diff --git a/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js b/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js index 20f727ea..37b30f7a 100644 --- a/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js +++ b/src/components/LabelBrowser/components/LabelsSelector/LabelsList.js @@ -114,6 +114,7 @@ export default function LabelsList(props) { onClick={useQuery} isMobile={false} alterText={"Use Query"} + loading={false} /> } diff --git a/src/components/LabelBrowser/components/QueryBar.js b/src/components/LabelBrowser/components/QueryBar.js index 5db62487..cf12d94f 100644 --- a/src/components/LabelBrowser/components/QueryBar.js +++ b/src/components/LabelBrowser/components/QueryBar.js @@ -766,7 +766,7 @@ export const QueryBar = (props) => { onSubmit={onSubmit} onSubmitRate={onSubmitRate} labels={labels} - loading={loading} + loading={loading||false} hasStats={hasStats} showStatsOpen={showStatsOpen} handleStatsOpen={handleStatsOpen} @@ -794,14 +794,14 @@ export const QueryBar = (props) => { onSubmitRate={onSubmitRate} isTabletOrMobile={isTabletOrMobile} labels={labels} - loading={loading} + loading={loading||false} />, { @@ -912,7 +912,7 @@ export const QueryBarCont = (props) => { disabled={!queryValid} onClick={onSubmit} isMobile={false} - loading={loading} + loading={loading||false} /> )} @@ -924,7 +924,7 @@ export const QueryBarCont = (props) => { disabled={!queryValid} onClick={onSubmit} isMobile={false} - loading={loading} + loading={loading||false} /> )} @@ -1023,7 +1023,7 @@ export const MobileTopQueryMenuCont = (props) => { disabled={!queryValid} onClick={onSubmit} isMobile={true} - loading={loading} + loading={loading||false} /> {dataSourceType === "flux" && ( diff --git a/src/components/StatusBar/components/apiselector/ApiSelector.js b/src/components/StatusBar/components/apiselector/ApiSelector.js index 1b08ad5a..fc066e84 100644 --- a/src/components/StatusBar/components/apiselector/ApiSelector.js +++ b/src/components/StatusBar/components/apiselector/ApiSelector.js @@ -2,22 +2,32 @@ import { ApiSelectorButton, ApiSelectorStyled } from "../../styled"; import { useNavigate } from "react-router-dom"; -import TuneOutlinedIcon from '@mui/icons-material/TuneOutlined'; - +import TuneOutlinedIcon from "@mui/icons-material/TuneOutlined"; +import { useSelector } from "react-redux"; export function ApiSelector() { const navigate = useNavigate(); - return ( - - navigate("datasources")} - > - - Data Sources - - - ); + const showDs = useSelector((store) => store.showDataSourceSetting); + if (showDs) { + return ( + + navigate("datasources")} + > + + Data Sources + + + ); + } + return null; } diff --git a/src/index.tsx b/src/index.tsx index 7db7f530..36138ac6 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,34 +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) +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( - - - - - - } /> - } /> - }/> - - - - - , - document.getElementById('root') + + + + + + } /> + } /> + {showDs && ( + : } + /> + )} + + + + + , + document.getElementById("root") ); 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 - - - - Datasources - - + {showDs && ( + + + + Datasources + + + )}
); diff --git a/src/store/createInitialState.ts b/src/store/createInitialState.ts index a97c50c8..a0ea76b8 100644 --- a/src/store/createInitialState.ts +++ b/src/store/createInitialState.ts @@ -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.ts b/src/store/reducer.ts index e580167a..a475d9c9 100644 --- a/src/store/reducer.ts +++ b/src/store/reducer.ts @@ -100,6 +100,8 @@ const reducer = (state: any, action: any) => { 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 }; } diff --git a/src/views/DataSources/DataSource.js b/src/views/DataSources/DataSource.js index 12fa7d78..bad1dcda 100644 --- a/src/views/DataSources/DataSource.js +++ b/src/views/DataSources/DataSource.js @@ -30,7 +30,8 @@ export function DataSourceSetting(props) { }, }, } = props; - // const [cookie, setCookie] = useCookies(['qryn-dev-cookie']) // for testing cookies feature + + const [cookie, setCookie] = useCookies(["qryn-dev-cookie"]); // for testing cookies feature const dispatch = useDispatch(); const dataSources = useSelector((store) => store.dataSources); @@ -58,34 +59,61 @@ export function DataSourceSetting(props) { }, }, })); - // var today = new Date() - // var tomorrow = new Date(); - // tomorrow.setDate(today.getDate()+1); - // setCookie('qryn-session', `${btoa('harry')}:${btoa('potter')}`, {path:'/',expires:tomorrow} ) // uncomment for testing cookies feature - + + // 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 (
+
+
- +
); @@ -129,7 +157,6 @@ export function DataSource() {
- diff --git a/src/views/Main.js b/src/views/Main.js index c9f59465..79cbd32f 100644 --- a/src/views/Main.js +++ b/src/views/Main.js @@ -15,6 +15,8 @@ import { useMemo, useState, useEffect, useRef } from "react"; import { useCookies } from "react-cookie"; import { useLocation } from "react-router-dom"; import setDataSources from "./DataSources/store/setDataSources"; +import { setShowDataSourceSetting } from "./Main/setShowDataSourceSetting"; + export const MainContainer = styled.div` position: absolute; @@ -255,7 +257,23 @@ export function updateDataSourcesWithUrl( } if (haveCookies) { - let [user, pass] = cookies.split(":"); + let [auth, dsData] = cookies.split("@"); + let cookieDsData = ""; + if (dsData !== "") { + cookieDsData = atob(dsData); + try { + cookieDsData = JSON.parse(cookieDsData); + if (typeof cookieDsData === "object" && cookieDsData["url"]) { + apiUrl = cookieDsData["url"]; + haveUrl = true; + } + } catch (e) { + console.log(e); + } + } + + let [user, pass] = auth.split(":"); + if (user !== "" && pass !== "") { cookieAuth = { user, password: pass }; basicAuth = true; @@ -294,6 +312,12 @@ export function updateDataSourcesWithUrl( }, }, })); + + if(cookies && cookieAuth) { + + dispatch(setShowDataSourceSetting(false)) + } + dispatch(setDataSources(newDs)); } diff --git a/src/views/Main/setShowDataSourceSetting.ts b/src/views/Main/setShowDataSourceSetting.ts new file mode 100644 index 00000000..aefdaa4c --- /dev/null +++ b/src/views/Main/setShowDataSourceSetting.ts @@ -0,0 +1,7 @@ +export const setShowDataSourceSetting = + (showDataSourceSetting: any) => (dispatch: Function) => { + dispatch({ + type: "SHOW_DATA_SOURCE_SETTING", + showDataSourceSetting, + }); + }; From 18dc769e4187eb0253d9ceabed50f5dbf07b8836 Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Fri, 16 Dec 2022 15:15:38 +0200 Subject: [PATCH 20/40] Cleaned up console, added keys to menuitems --- .../StatusBar/components/daterangepicker/index.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/components/StatusBar/components/daterangepicker/index.js b/src/components/StatusBar/components/daterangepicker/index.js index 23375a9b..eabd7dfb 100644 --- a/src/components/StatusBar/components/daterangepicker/index.js +++ b/src/components/StatusBar/components/daterangepicker/index.js @@ -277,7 +277,6 @@ export function DateRangePickerMain(props) { duration.seconds = parseInt(adjustment); } } - console.log(duration) const adjustedStart = directionFunc(dateStart, duration); const adjustedStop = directionFunc(dateEnd, duration); const dateRange = { @@ -303,7 +302,6 @@ export function DateRangePickerMain(props) { setAnchorElRight(event.currentTarget) } const handleClose = (e, direction, option) => { - console.log(direction, option) setAnchorEl(null); setAnchorElRight(null); if (direction && option) { @@ -341,7 +339,7 @@ export function DateRangePickerMain(props) { qryntheme={qrynTheme} > {timeAdjustmentOptions.map(option => ( - handleClose(e, 'backward', option)}> {option} @@ -398,7 +396,7 @@ export function DateRangePickerMain(props) { qryntheme={qrynTheme} > {timeAdjustmentOptions.map(option => ( - handleClose(e, 'forward', option)}> {option} From e1be98e0ccf2d50716ce196d58da02e5a11e99a4 Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Fri, 16 Dec 2022 18:57:00 +0200 Subject: [PATCH 21/40] Style adjustments for timewindow --- .../StatusBar/components/daterangepicker/index.js | 14 +++++++------- src/components/StatusBar/styled/index.js | 13 +++++++------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/components/StatusBar/components/daterangepicker/index.js b/src/components/StatusBar/components/daterangepicker/index.js index eabd7dfb..94a29470 100644 --- a/src/components/StatusBar/components/daterangepicker/index.js +++ b/src/components/StatusBar/components/daterangepicker/index.js @@ -36,8 +36,8 @@ import { import { useSelector, useDispatch } from "react-redux"; import useOutsideRef from "./hooks/useOutsideRef"; import AccessTimeOutlinedIcon from "@mui/icons-material/AccessTimeOutlined"; -import ArrowBackIosIcon from '@mui/icons-material/ArrowBackIos'; -import ArrowForwardIosIcon from '@mui/icons-material/ArrowForwardIos'; +import KeyboardArrowLeft from '@mui/icons-material/KeyboardArrowLeft'; +import KeyboardArrowRight from '@mui/icons-material/KeyboardArrowRight'; import KeyboardArrowDownOutlinedIcon from '@mui/icons-material/KeyboardArrowDownOutlined'; import Menu from '@mui/material/Menu'; import MenuItem from '@mui/material/MenuItem'; @@ -318,11 +318,11 @@ export function DateRangePickerMain(props) { emptySide={'l'} className={"date-time-selector"} > - + @@ -377,8 +378,7 @@ export function DateRangePickerMain(props) { - + {rangeOpen ? (
diff --git a/src/components/StatusBar/styled/index.js b/src/components/StatusBar/styled/index.js index 452f60c4..a619c967 100644 --- a/src/components/StatusBar/styled/index.js +++ b/src/components/StatusBar/styled/index.js @@ -135,13 +135,14 @@ 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' ? '0' : ''}; - border-top-right-radius: ${(props) => props.attachedSide === 'r' ? '0' : ''}; - border-bottom-left-radius: ${(props) => props.attachedSide === 'l' ? '0' : ''}; - border-bottom-right-radius: ${(props) => props.attachedSide === 'r' ? '0' : ''}; - border-right: ${(props) => props.attachedSide === 'r' ? 'unset' : ''}; + 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: ${(props) => props.attachedSide && !props.emptySide ? '' : '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; From 42dbae0be8ab689d32c654c587f0ece45ae097db Mon Sep 17 00:00:00 2001 From: Eduard Klimenko Date: Fri, 16 Dec 2022 18:58:07 +0200 Subject: [PATCH 22/40] .js to .ts(tsx) for TraceSearch & LabelBrowser --- package-lock.json | 56 +- .../helpers/{debugLog.js => debugLog.ts} | 28 +- .../{onQueryValid.js => onQueryValid.ts} | 20 +- .../{querybuilder.js => querybuilder.ts} | 547 +++++++++--------- ...Selector.js => TraceQueryTypeSelector.tsx} | 2 +- .../TraceSearch/{helpers.js => helpers.ts} | 6 +- ...{tracesSearchUrl.js => tracesSearchUrl.ts} | 2 +- .../{useTraceNames.js => useTraceNames.ts} | 6 +- ...eServiceName.js => useTraceServiceName.ts} | 10 +- src/components/TraceSearch/useTraceTags.js | 0 src/components/{styles/index.js => styles.ts} | 102 ++-- 11 files changed, 413 insertions(+), 366 deletions(-) rename src/components/LabelBrowser/helpers/{debugLog.js => debugLog.ts} (87%) rename src/components/LabelBrowser/helpers/{onQueryValid.js => onQueryValid.ts} (78%) rename src/components/LabelBrowser/helpers/{querybuilder.js => querybuilder.ts} (82%) rename src/components/QueryItem/{TraceQueryTypeSelector.js => TraceQueryTypeSelector.tsx} (91%) rename src/components/TraceSearch/{helpers.js => helpers.ts} (85%) rename src/components/TraceSearch/{tracesSearchUrl.js => tracesSearchUrl.ts} (94%) rename src/components/TraceSearch/{useTraceNames.js => useTraceNames.ts} (88%) rename src/components/TraceSearch/{useTraceServiceName.js => useTraceServiceName.ts} (81%) delete mode 100644 src/components/TraceSearch/useTraceTags.js rename src/components/{styles/index.js => styles.ts} (74%) diff --git a/package-lock.json b/package-lock.json index e3326acc..b5797cfb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,6 +49,7 @@ "papaparse": "^5.3.2", "prismjs": "^1.27.0", "react": "^17.0.2", + "react-cookie": "^4.1.1", "react-custom-scrollbars-2": "^4.4.0", "react-dom": "^17.0.2", "react-flot": "^1.3.0", @@ -4588,6 +4589,11 @@ "@types/node": "*" } }, + "node_modules/@types/cookie": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", + "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==" + }, "node_modules/@types/deep-freeze": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/deep-freeze/-/deep-freeze-0.1.2.tgz", @@ -7299,7 +7305,6 @@ "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true, "engines": { "node": ">= 0.6" } @@ -17502,6 +17507,19 @@ "url": "https://opencollective.com/core-js" } }, + "node_modules/react-cookie": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.1.1.tgz", + "integrity": "sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A==", + "dependencies": { + "@types/hoist-non-react-statics": "^3.0.1", + "hoist-non-react-statics": "^3.0.0", + "universal-cookie": "^4.0.0" + }, + "peerDependencies": { + "react": ">= 16.3.0" + } + }, "node_modules/react-custom-scrollbars-2": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/react-custom-scrollbars-2/-/react-custom-scrollbars-2-4.4.0.tgz", @@ -20478,6 +20496,15 @@ "node": ">=8" } }, + "node_modules/universal-cookie": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz", + "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==", + "dependencies": { + "@types/cookie": "^0.3.3", + "cookie": "^0.4.0" + } + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -24921,6 +24948,11 @@ "@types/node": "*" } }, + "@types/cookie": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.3.3.tgz", + "integrity": "sha512-LKVP3cgXBT9RYj+t+9FDKwS5tdI+rPBXaNSkma7hvqy35lc7mAokC2zsqWJH0LaqIt3B962nuYI77hsJoT1gow==" + }, "@types/deep-freeze": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/@types/deep-freeze/-/deep-freeze-0.1.2.tgz", @@ -27133,8 +27165,7 @@ "cookie": { "version": "0.4.2", "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", - "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", - "dev": true + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==" }, "cookie-signature": { "version": "1.0.6", @@ -34715,6 +34746,16 @@ } } }, + "react-cookie": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/react-cookie/-/react-cookie-4.1.1.tgz", + "integrity": "sha512-ffn7Y7G4bXiFbnE+dKhHhbP+b8I34mH9jqnm8Llhj89zF4nPxPutxHT1suUqMeCEhLDBI7InYwf1tpaSoK5w8A==", + "requires": { + "@types/hoist-non-react-statics": "^3.0.1", + "hoist-non-react-statics": "^3.0.0", + "universal-cookie": "^4.0.0" + } + }, "react-custom-scrollbars-2": { "version": "4.4.0", "resolved": "https://registry.npmjs.org/react-custom-scrollbars-2/-/react-custom-scrollbars-2-4.4.0.tgz", @@ -36963,6 +37004,15 @@ "crypto-random-string": "^2.0.0" } }, + "universal-cookie": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/universal-cookie/-/universal-cookie-4.0.4.tgz", + "integrity": "sha512-lbRVHoOMtItjWbM7TwDLdl8wug7izB0tq3/YVKhT/ahB4VDvWMyvnADfnJI8y6fSvsjh51Ix7lTGC6Tn4rMPhw==", + "requires": { + "@types/cookie": "^0.3.3", + "cookie": "^0.4.0" + } + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", diff --git a/src/components/LabelBrowser/helpers/debugLog.js b/src/components/LabelBrowser/helpers/debugLog.ts similarity index 87% rename from src/components/LabelBrowser/helpers/debugLog.js rename to src/components/LabelBrowser/helpers/debugLog.ts index de339638..2c60387b 100644 --- a/src/components/LabelBrowser/helpers/debugLog.js +++ b/src/components/LabelBrowser/helpers/debugLog.ts @@ -1,14 +1,14 @@ -export default function debugLog(query) { - const logicQueryBar = () => { - console.log("🚧 LOGIC/QueryBar/", typeof query, query.length); - }; - const queryBarDispatch = () => { - console.log( - "🚧 LOGIC/QueryBar/ dispatch ", - query !== "{}", - query.length > 0, - query !== "{}" || query.length > 1 - ); - }; - return { logicQueryBar, queryBarDispatch }; -} +export default function debugLog(query: any) { + const logicQueryBar = () => { + console.log("🚧 LOGIC/QueryBar/", typeof query, query.length); + }; + const queryBarDispatch = () => { + console.log( + "🚧 LOGIC/QueryBar/ dispatch ", + query !== "{}", + query.length > 0, + query !== "{}" || query.length > 1 + ); + }; + return { logicQueryBar, queryBarDispatch }; +} diff --git a/src/components/LabelBrowser/helpers/onQueryValid.js b/src/components/LabelBrowser/helpers/onQueryValid.ts similarity index 78% rename from src/components/LabelBrowser/helpers/onQueryValid.js rename to src/components/LabelBrowser/helpers/onQueryValid.ts index 550da877..c50ae65e 100644 --- a/src/components/LabelBrowser/helpers/onQueryValid.js +++ b/src/components/LabelBrowser/helpers/onQueryValid.ts @@ -1,10 +1,10 @@ -export default function onQueryValid(query) { - return ( - query && - query !== "{" && - query !== "}" && - query !== "{}" && - query !== "" && - query?.length >= 7 - ); // TODO: make a proper query validation -} +export default function onQueryValid(query: any) { + return ( + query && + query !== "{" && + query !== "}" && + query !== "{}" && + query !== "" && + query?.length >= 7 + ); // TODO: make a proper query validation +} diff --git a/src/components/LabelBrowser/helpers/querybuilder.js b/src/components/LabelBrowser/helpers/querybuilder.ts similarity index 82% rename from src/components/LabelBrowser/helpers/querybuilder.js rename to src/components/LabelBrowser/helpers/querybuilder.ts index d6d4c11d..11fdb761 100644 --- a/src/components/LabelBrowser/helpers/querybuilder.js +++ b/src/components/LabelBrowser/helpers/querybuilder.ts @@ -1,275 +1,272 @@ -import { setLeftPanel } from "../../../actions/setLeftPanel"; -import { setRightPanel } from "../../../actions/setRightPanel"; -import { useQueryParams } from "../../../helpers/useQueryParams"; -import store from "../../../store/store"; - -export const PIPE_PARSE = [ - { - label: "json", - }, - { - label: "regexp", - text: 'regexp ""', - }, - { - label: "logfmt", - }, - { - label: "pattern", - }, -]; - -const pipeParseOpts = ["json", "regexp", "logfmt", "pattern", "~", "="]; - -const STREAM_SELECTOR_REGEX = /{[^}]*}/; -const parseLog = { - newQuery: (keyValue, op, tags) => { - const [key, value] = keyValue; - return `${tags[0] || ""}{${key}${op}"${value}"}${tags[2] || ""}`; - }, - equalLabels: (keyValue, op, tags) => { - if (op === "!=") { - return parseLog.newQuery(keyValue, op, tags); - } - - return "{}"; - }, - formatQuery: (queryString, tags) => { - return `${tags[0] || ""}{${queryString || ""}}${tags[2] || ""}`; - }, - splitLabels: (query) => - query - ?.match(/[^{}]+(?=})/g) - ?.map((m) => m.split(",")) - ?.flat() || [], - addLabel: (op, keySubtValue, keyValue) => { - if (op === "!=") { - return keySubtValue; - } - return keyValue; - }, - rmValueFromLabel: (label, value) => { - const [lb, val] = label?.split("=~"); - let lvalue = val?.split(/[""]/)[1]; - let values = lvalue?.split("|"); - let filtered = values?.filter((f) => f.trim() !== value?.trim()); - - if (filtered?.length > 1) { - const lvalues = filtered?.join("|")?.trim(); - return lb?.trim() + "=~" + '"' + lvalues + '"'; - } - const lvalues = filtered?.join("")?.trim(); - return lb?.trim() + "=" + '"' + lvalues + '"'; - }, - addValueToLabel: (label, value, isEquals) => { - const sign = isEquals ? "=" : "=~"; - const [lb, val] = label?.split(sign); - const values = val?.split(/[""]/)[1]; - const labelmod = `${lb}=~"${values?.trim()}|${value?.trim()}"`; - return labelmod; - }, - isEqualsQuery: (query, keyValue) => { - const [key, value] = keyValue; - return query === `{${key}="${value}"}`; - }, - editQuery: (query, keyValue, op, tags) => { - if (parseLog.isEqualsQuery(query, keyValue) && keyValue !== null) { - return parseLog.equalLabels(keyValue, op, tags); - } - - return parseQuery.fromLabels(query, keyValue, op, tags); - }, -}; -const parseQuery = { - fromLabels: (query, keyVal, op, tags) => { - const queryString = parseQueryLabels(keyVal, query, op); - return parseLog.formatQuery(queryString, tags); - }, -}; - -function parseQueryLabels(keyVal, query, op) { - const [key, value] = keyVal; - const keyValue = `${key}="${value}"`; - const keySubtValue = `${key}!="${value}"`; - let queryArr = parseLog.splitLabels(query); - if (!queryArr) { - return ""; - } - - for (let label of queryArr) { - const regexQuery = label.match(/([^{}=,~!]+)/gm); - const querySplitted = parseLog.splitLabels(query); - if (!regexQuery) { - return ""; - } - - if ( value !== null && - !label.includes(key?.trim()) && - !querySplitted?.some((s) => s.includes(key)) - ) { - // add new label - let labelMod = op === "!=" ? keySubtValue : label; - const parsed = parseLog.addLabel(op, labelMod, keyValue); - const regs = parseLog.splitLabels(query).concat(parsed); - return regs.join(","); - } - - if ( value !== null && - label?.includes("=") && - label?.split("=")?.[0]?.trim() === key?.trim() && - !label?.includes(value) - ) { - // values group from existing label - let labelMod = parseLog.addValueToLabel(label, value, true); - return parseLog - .splitLabels(query) - ?.join(",") - ?.replace(`${label}`, labelMod); - } - - if ( value !== null && - label?.includes("=~") && - label?.split("=~")?.[0]?.trim() === key?.trim() && - label?.includes(value) - ) { - // filter value from existing values group from label - const labelMod = parseLog.rmValueFromLabel(label, value); - return parseLog - .splitLabels(query) - .join(",") - .replace(`${label}`, labelMod); - } - - if ( value !== null && - label?.includes("=~") && - label?.split("=~")?.[0]?.trim() === key?.trim() && - !label?.includes(value?.trim()) - ) { - // add value to existing values group from label - return parseLog.addValueToLabel(label, value, false); - } - - // value === null is used for clear - if ( - label?.includes("=") && - label?.split("=")?.[0]?.trim() === key?.trim() && - (label?.split('"')?.[1]?.trim() === value?.trim() || value === null) && - querySplitted?.some((s) => s === label) - ) { - // remove label from query - const filtered = querySplitted?.filter((f) => f !== label); - return filtered?.join(","); - } - } - return ""; -} - -export function decodeQuery(query, key, value, op, type) { - const { newQuery, editQuery } = parseLog; - - let keyValue = [key, value]; - let tags = query?.split(/[{}]/); - const isQuery = query?.match(STREAM_SELECTOR_REGEX) && tags[1].length > 7; - - if (tags[1]?.length < 1 && type === "metrics") { - return `${value}{}`; - } - - if (tags[1]?.length > 1 && type === "metrics") { - return `${value}{${tags[1]}}`; - } - - if (!isQuery && key !== "__name__") { - return newQuery(keyValue, op, tags); - } - - return editQuery(query, keyValue, op, tags); -} -export function queryBuilder(labels, expr, hasPipe = false, pipeLabels = []) { - const actualQuery = expr; - const preTags = actualQuery.split("{")[0]; - let postTags = ""; - - const isRate = expr.startsWith('rate(') && expr.endsWith('[$__interval])') - if (hasPipe) { - postTags = actualQuery.split("}")[1]; - const json = /[|json]/; - const expParse = actualQuery.split(json); - if (pipeParseOpts.some((s) => expParse[1].includes(s))) { - const pipeTags = ` | ${pipeLabels}`; - postTags = postTags.toString().concat(pipeTags.toString()); - } - } else { - postTags = actualQuery.split("}")[1]; - } - - const selectedLabels = []; - - for (const label of labels) { - if (label.selected && label.values && label.values.length > 0) { - const selectedValues = label.values - .filter((value) => value.selected && !value.inverted) - .map((value) => value.name); - - const invertedSelectedValues = label.values - .filter((value) => value.selected && value.inverted) - .map((value) => value.name); - - if (selectedValues.length > 1) { - selectedLabels.push( - `${label.name}=~"${selectedValues.join("|")}"` - ); - } else if (selectedValues.length === 1) { - selectedLabels.push(`${label.name}="${selectedValues[0]}"`); - } - invertedSelectedValues.forEach((value) => { - selectedLabels.push(`${label.name}!="${value}"`); - }); - } - } - return [preTags, "{", selectedLabels.join(","), "}", postTags].join(""); -} - -export function queryBuilderWithLabels( - expr, // query expression - name, // panel name - id, // query id - keyVal, // key / value - isInverted = false, - hasPipe = false, - pipeLabels = [] -) { - const [key, val] = keyVal; - const dispatch = store.dispatch; - const operator = () => { - if (isInverted) { - return "!="; - } - return "="; - }; - const { left, right } = store.getState(); - const queryStr = decodeQuery(expr, key, val, operator()); - // here will return without braces\ - // - // return [preTags, "{", selectedLabels.join(","), "}", postTags].join(""); - - if (name === "left") { - const leftC = [...left]; - leftC.forEach((query) => { - if (query.id === id) { - query.expr = queryStr; - } - }); - dispatch(setLeftPanel(leftC)); - } - - if (name === "right") { - const rightC = [...right]; - rightC.forEach((query) => { - if (query.id === id) { - query.expr = queryStr; - } - }); - dispatch(setRightPanel(rightC)); - } -} +import { setLeftPanel } from "../../../actions/setLeftPanel"; +import { setRightPanel } from "../../../actions/setRightPanel"; +import { useQueryParams } from "../../../helpers/useQueryParams"; +import store from "../../../store/store"; + +export const PIPE_PARSE = [ + { + label: "json", + }, + { + label: "regexp", + text: 'regexp ""', + }, + { + label: "logfmt", + }, + { + label: "pattern", + }, +]; + +const pipeParseOpts = ["json", "regexp", "logfmt", "pattern", "~", "="]; + +const STREAM_SELECTOR_REGEX = /{[^}]*}/; +const parseLog = { + newQuery: (keyValue: any[], op: any, tags: any[]) => { + const [key, value] = keyValue; + return `${tags[0] || ""}{${key}${op}"${value}"}${tags[2] || ""}`; + }, + equalLabels: (keyValue: any[], op: any, tags: any[]) => { + if (op === "!=") { + return parseLog.newQuery(keyValue, op, tags); + } + + return "{}"; + }, + formatQuery: (queryString: any, tags: any) => { + return `${tags[0] || ""}{${queryString || ""}}${tags[2] || ""}`; + }, + splitLabels: (query: string) => + query + ?.match(/[^{}]+(?=})/g) + ?.map((m) => m.split(",")) + ?.flat() || [], + addLabel: (op: any, keySubtValue: any, keyValue: any) => + op === "!=" ? keyValue : keySubtValue + , + rmValueFromLabel: (label: any, value: any) => { + const [lb, val] = label?.split("=~"); + let lvalue = val?.split(/[""]/)[1]; + let values = lvalue?.split("|"); + let filtered = values?.filter((f: any) => f.trim() !== value?.trim()); + + if (filtered?.length > 1) { + const lvalues = filtered?.join("|")?.trim(); + return lb?.trim() + "=~" + '"' + lvalues + '"'; + } + const lvalues = filtered?.join("")?.trim(); + return lb?.trim() + "=" + '"' + lvalues + '"'; + }, + addValueToLabel: (label: string, value: string, isEquals: boolean) => { + const sign = isEquals ? "=" : "=~"; + const [lb, val] = label?.split(sign); + const values = val?.split(/[""]/)[1]; + const labelmod = `${lb}=~"${values?.trim()}|${value?.trim()}"`; + return labelmod; + }, + isEqualsQuery: (query: string, keyValue: any[]) => { + const [key, value] = keyValue; + return query === `{${key}="${value}"}`; + }, + editQuery: (query: string, keyValue: any[], op: string, tags: any[]) => { + if (parseLog.isEqualsQuery(query, keyValue) && keyValue !== null) { + return parseLog.equalLabels(keyValue, op, tags); + } + + return parseQuery.fromLabels(query, keyValue, op, tags); + }, +}; +const parseQuery = { + fromLabels: (query: string, keyVal: any[], op: string, tags: any[]) => { + const queryString = parseQueryLabels(keyVal, query, op); + return parseLog.formatQuery(queryString, tags); + }, +}; + +function parseQueryLabels(keyVal: any[], query: string, op: string) { + const [key, value] = keyVal; + const keyValue = `${key}="${value}"`; + const keySubtValue = `${key}!="${value}"`; + let queryArr = parseLog.splitLabels(query); + if (!queryArr) { + return ""; + } + + for (let label of queryArr) { + const regexQuery = label.match(/([^{}=,~!]+)/gm); + const querySplitted = parseLog.splitLabels(query); + if (!regexQuery) { + return ""; + } + + if ( value !== null && + !label.includes(key?.trim()) && + !querySplitted?.some((s) => s.includes(key)) + ) { + // add new label + let labelMod = op === "!=" ? keySubtValue : label; + const parsed = parseLog.addLabel(op, labelMod, keyValue); + const regs = parseLog.splitLabels(query).concat(parsed); + return regs.join(","); + } + + if ( value !== null && + label?.includes("=") && + label?.split("=")?.[0]?.trim() === key?.trim() && + !label?.includes(value) + ) { + // values group from existing label + let labelMod = parseLog.addValueToLabel(label, value, true); + return parseLog + .splitLabels(query) + ?.join(",") + ?.replace(`${label}`, labelMod); + } + + if ( value !== null && + label?.includes("=~") && + label?.split("=~")?.[0]?.trim() === key?.trim() && + label?.includes(value) + ) { + // filter value from existing values group from label + const labelMod = parseLog.rmValueFromLabel(label, value); + return parseLog + .splitLabels(query) + .join(",") + .replace(`${label}`, labelMod); + } + + if ( value !== null && + label?.includes("=~") && + label?.split("=~")?.[0]?.trim() === key?.trim() && + !label?.includes(value?.trim()) + ) { + // add value to existing values group from label + return parseLog.addValueToLabel(label, value, false); + } + + // value === null is used for clear + if ( + label?.includes("=") && + label?.split("=")?.[0]?.trim() === key?.trim() && + (label?.split('"')?.[1]?.trim() === value?.trim() || value === null) && + querySplitted?.some((s) => s === label) + ) { + // remove label from query + const filtered = querySplitted?.filter((f) => f !== label); + return filtered?.join(","); + } + } + return ""; +} + +export function decodeQuery(query: any, key: any, value: any, op: any, type: any) { + const { newQuery, editQuery } = parseLog; + + let keyValue = [key, value]; + let tags = query?.split(/[{}]/); + const isQuery = query?.match(STREAM_SELECTOR_REGEX) && tags[1].length > 7; + + if (tags[1]?.length < 1 && type === "metrics") { + return `${value}{}`; + } + + if (tags[1]?.length > 1 && type === "metrics") { + return `${value}{${tags[1]}}`; + } + + if (!isQuery && key !== "__name__") { + return newQuery(keyValue, op, tags); + } + + return editQuery(query, keyValue, op, tags); +} +export function queryBuilder(labels: any, expr: any, hasPipe = false, pipeLabels = []) { + const actualQuery = expr; + const preTags = actualQuery.split("{")[0]; + let postTags = ""; + + // const isRate = expr.startsWith('rate(') && expr.endsWith('[$__interval])') + if (hasPipe) { + postTags = actualQuery.split("}")[1]; + const json = /[|json]/; + const expParse = actualQuery.split(json); + if (pipeParseOpts.some((s) => expParse[1].includes(s))) { + const pipeTags = ` | ${pipeLabels}`; + postTags = postTags.toString().concat(pipeTags.toString()); + } + } else { + postTags = actualQuery.split("}")[1]; + } + + const selectedLabels = []; + + for (const label of labels) { + if (label.selected && label.values && label.values.length > 0) { + const selectedValues = label.values + .filter((value: any) => value.selected && !value.inverted) + .map((value: any) => value.name); + + const invertedSelectedValues = label.values + .filter((value: any) => value.selected && value.inverted) + .map((value: any) => value.name); + + if (selectedValues.length > 1) { + selectedLabels.push( + `${label.name}=~"${selectedValues.join("|")}"` + ); + } else if (selectedValues.length === 1) { + selectedLabels.push(`${label.name}="${selectedValues[0]}"`); + } + invertedSelectedValues.forEach((value: any) => { + selectedLabels.push(`${label.name}!="${value}"`); + }); + } + } + return [preTags, "{", selectedLabels.join(","), "}", postTags].join(""); +} + +export function queryBuilderWithLabels( + expr: any, // query expression + name: any, // panel name + id: any, // query id + keyVal: any, // key / value + isInverted = false, + hasPipe = false, + pipeLabels = [] +) { + const [key, val] = keyVal; + const dispatch = store.dispatch; + const operator = () => { + if (isInverted) { + return "!="; + } + return "="; + }; + const { left, right } = store.getState(); + const queryStr = decodeQuery(expr, key, val, operator(), null); + // here will return without braces\ + // + // return [preTags, "{", selectedLabels.join(","), "}", postTags].join(""); + + if (name === "left") { + const leftC = [...left]; + leftC.forEach((query) => { + if (query.id === id) { + query.expr = queryStr; + } + }); + dispatch(setLeftPanel(leftC)); + } + + if (name === "right") { + const rightC = [...right]; + rightC.forEach((query) => { + if (query.id === id) { + query.expr = queryStr; + } + }); + dispatch(setRightPanel(rightC)); + } +} diff --git a/src/components/QueryItem/TraceQueryTypeSelector.js b/src/components/QueryItem/TraceQueryTypeSelector.tsx similarity index 91% rename from src/components/QueryItem/TraceQueryTypeSelector.js rename to src/components/QueryItem/TraceQueryTypeSelector.tsx index c9817538..674392d5 100644 --- a/src/components/QueryItem/TraceQueryTypeSelector.js +++ b/src/components/QueryItem/TraceQueryTypeSelector.tsx @@ -5,7 +5,7 @@ const QUERY_TYPE_SELECTOR_OPTIONS = [ { value: "search", label: "Search" }, ]; -export function TraceQueryTypeSelector(props) { +export function TraceQueryTypeSelector(props: any) { const { onQueryTypeSelectorChange, queryTypeSelectorSelected } = props; return ( 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; +`; + From 132e26868f1c6d0fb6d130014793b792c31a5731 Mon Sep 17 00:00:00 2001 From: jacovinus Date: Fri, 16 Dec 2022 18:06:16 +0100 Subject: [PATCH 23/40] fix: url from cookie --- src/views/Main.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/views/Main.js b/src/views/Main.js index 79cbd32f..18f481de 100644 --- a/src/views/Main.js +++ b/src/views/Main.js @@ -266,6 +266,7 @@ export function updateDataSourcesWithUrl( if (typeof cookieDsData === "object" && cookieDsData["url"]) { apiUrl = cookieDsData["url"]; haveUrl = true; + urlApi = true; } } catch (e) { console.log(e); @@ -283,7 +284,10 @@ export function updateDataSourcesWithUrl( if (!haveUrl && basicAuth) { apiUrl = window.location.protocol + "//" + window.location.host; urlApi = true; - } else { + } + + if(apiUrl === '') { + urlApi = true; apiUrl = url; } @@ -335,7 +339,6 @@ export default function Main() { const { cookiesAvailable, cookieAuth } = useCookiesAvailable(paramsMemo); const { urlAvailable, url } = useUrlAvailable(paramsMemo); - useEffect(() => { const onlyCookie = cookiesAvailable && !urlAvailable; const onlyUrl = !cookiesAvailable && urlAvailable; @@ -367,6 +370,7 @@ export default function Main() { const autoTheme = useSelector((store) => store.autoTheme); const settingsDialogOpen = useSelector((store) => store.settingsDialogOpen); const themeMemo = useMemo(() => themes[theme], [theme]); + useEffect(() => { if (autoTheme) { const theme = isAutoDark ? "dark" : "light"; From 052985fbadec087544fb5b1c09ee2c70faee2493 Mon Sep 17 00:00:00 2001 From: jacovinus Date: Mon, 19 Dec 2022 12:22:31 +0100 Subject: [PATCH 24/40] fix:First Link from logs To traces, shows 'Logs' at data source selector instead of Traces #177 --- .../LabelBrowser/components/QueryBar.js | 89 ++++++++++--------- src/components/Panel/Panel.tsx | 5 +- src/components/QueryItem/DataSourceSelect.tsx | 4 +- src/components/QueryItem/QueryItemToolbar.tsx | 15 ++-- src/helpers/stateFromQueryParams.ts | 4 +- src/store/createInitialState.ts | 6 +- 6 files changed, 60 insertions(+), 63 deletions(-) diff --git a/src/components/LabelBrowser/components/QueryBar.js b/src/components/LabelBrowser/components/QueryBar.js index cf12d94f..a9f6bb3b 100644 --- a/src/components/LabelBrowser/components/QueryBar.js +++ b/src/components/LabelBrowser/components/QueryBar.js @@ -90,6 +90,7 @@ export const QueryBar = (props) => { } = props; const { hash } = useLocation(); const dispatch = useDispatch(); + const saveUrl = localUrl(); const historyService = localService().historyStore(); const { historyOpen, isEmbed, theme, queryHistory, start, stop } = useSelector((store) => store); @@ -130,28 +131,6 @@ export const QueryBar = (props) => { } }, [id, dataSourceId]); - // const actLocalDsSelected = useMemo(() => { - // try { - // const localData = JSON.parse(localStorage.getItem("dsSelected")); - - // if(localData?.length > 0) { - // const localStored = localData?.find((f) => f.queryId === id) ; - // if(localStored) { - // return localStored - // } else { - // return {queryId:id,dataSourceId}; - // } - - // } else { - // return {queryId:id,dataSourceId}; - // } - - // } catch (e) { - // console.log(e); - // return {queryId:id,dataSourceId}; - // } - // }, [id]); - const actLocalDs = useMemo(() => { try { const localData = JSON.parse(localStorage.getItem("dataSources")); @@ -160,22 +139,14 @@ export const QueryBar = (props) => { return {}; } }, [dataSourceId]); - - const initialDefault = useMemo(() => { - return defaultDataSources.find((f) => f.id === dataSourceId); - }, [dataSourceId]); - - useEffect(() => { - if (isTabletOrMobile && isSplit) { - dispatch(setSplitView(false)); - } - }, [isTabletOrMobile]); - - const saveUrl = localUrl(); const expr = useMemo(() => { return data.expr; }, [data.expr]); + const initialDefault = useMemo(() => { + return defaultDataSources.find((f) => f.id === dataSourceId); + }, [dataSourceId]); + // on init useEffect(() => { setQueryInput(actLocalQuery.expr); setQueryValue([{ children: [{ text: actLocalQuery.expr }] }]); @@ -284,14 +255,18 @@ export const QueryBar = (props) => { } }, []); + // force single view from small width + useEffect(() => { - setQueryInput(expr); - setQueryValue([{ children: [{ text: expr }] }]); - setQueryValid(onQueryValid(expr)); - decodeQueryAndUpdatePanel(queryInput, false); - saveQuery(); - setLocalStorage(); - }, [expr]); + if (isTabletOrMobile && isSplit) { + dispatch(setSplitView(false)); + } + }, [isTabletOrMobile]); + + + + + // changes on changin dataSource Id useEffect(() => { setQueryInput(actLocalQuery.expr); @@ -400,6 +375,20 @@ export const QueryBar = (props) => { } }, [dataSourceId, id]); + + // changes on changing exp + + useEffect(() => { + setQueryInput(expr); + setQueryValue([{ children: [{ text: expr }] }]); + setQueryValid(onQueryValid(expr)); + decodeQueryAndUpdatePanel(queryInput, false); + saveQuery(); + setLocalStorage(); + }, [expr]); + + // handlers + function handleQueryChange(e) { setQueryValue(e); saveQuery(e); @@ -483,6 +472,7 @@ export const QueryBar = (props) => { } localStorage.setItem("queryData", JSON.stringify(newData)); }; + const saveQuery = (e = []) => { const queryParams = new URLSearchParams(hash.replace("#", "")); const multiline = e?.map((text) => text.children[0].text).join("\n"); @@ -498,6 +488,7 @@ export const QueryBar = (props) => { queryParams.set(name, encodeURIComponent(JSON.stringify(panel))); setLocalStorage(); }; + const onSubmitRate = (e, type = "logs") => { e.preventDefault(); const isEmptyQuery = queryInput.length === 0; @@ -669,6 +660,12 @@ export const QueryBar = (props) => { dispatch(panelAction(name, newPanel)); } + const switchTraceQueryType = (e) => { + setTraceQueryType((_) => e); + }; + + // renderers + const inlineQueryOptionsRenderer = (type, isSplit, isMobile, typeBar) => { const isFullView = !isMobile && !isSplit; const isMetrics = type === "metrics" || type === "logs"; @@ -700,9 +697,7 @@ export const QueryBar = (props) => { return null; } - const switchTraceQueryType = (e) => { - setTraceQueryType((_) => e); - }; + const queryTypeRenderer = ( type, @@ -746,6 +741,8 @@ export const QueryBar = (props) => { return querySearch; }; + // render + if (isEmbed) { return null; } @@ -861,6 +858,8 @@ export const QueryBar = (props) => { ); }; +// query bar container (full view) + export const QueryBarCont = (props) => { const { isSplit, @@ -932,6 +931,8 @@ export const QueryBarCont = (props) => { ); }; + +// mobile top query view (mobile view or splitted view) export const MobileTopQueryMenuCont = (props) => { const dispatch = useDispatch(); const { diff --git a/src/components/Panel/Panel.tsx b/src/components/Panel/Panel.tsx index 1741989a..45771ff1 100644 --- a/src/components/Panel/Panel.tsx +++ b/src/components/Panel/Panel.tsx @@ -15,7 +15,6 @@ const PanelCont: any = styled.div` `; // Panel should have injected data export default function Panel(props: any) { - const ref: any = useRef(null); const [width, setWidth] = useState(0); @@ -61,12 +60,10 @@ export default function Panel(props: any) { }, []); // CHECK ALSO THAT DATAVIEWS IS AN ARRAY - const panelData = useMemo(() => panel, [panel]); - //console.log(panelData) return ( <> - + diff --git a/src/components/QueryItem/DataSourceSelect.tsx b/src/components/QueryItem/DataSourceSelect.tsx index 94240755..891edf91 100644 --- a/src/components/QueryItem/DataSourceSelect.tsx +++ b/src/components/QueryItem/DataSourceSelect.tsx @@ -9,13 +9,13 @@ export const DataSourceSelect = (props: any) => { const selectRef: any = useRef(null); useEffect(() => { - if (value.value !== extValue) { + if (value.value !== extValue && extValue !== '') { selectRef.current.value = extValue; } }, []); useEffect(() => { - if (value.value !== extValue) { + if (value.value !== extValue && extValue !== '') { selectRef.current.value = extValue; } }, [extValue]); diff --git a/src/components/QueryItem/QueryItemToolbar.tsx b/src/components/QueryItem/QueryItemToolbar.tsx index 2246d919..8742eb6a 100644 --- a/src/components/QueryItem/QueryItemToolbar.tsx +++ b/src/components/QueryItem/QueryItemToolbar.tsx @@ -26,14 +26,6 @@ export function QueryItemToolbar(props: any) { const [extValue, setExtValue] = useState(props.data.dataSourceId); - useEffect(() => { - setExtValue(props.data.dataSourceId); - }, []); - - useEffect(() => { - setExtValue(props.data.dataSourceId); - }, [props.data.dataSourceId]); - const dataSourceOptions = useMemo(() => { if (dataSources.length > 0) { return dataSources.map((m: any) => ({ @@ -46,6 +38,13 @@ export function QueryItemToolbar(props: any) { return null; }, [dataSources]); + useEffect(() => { + setExtValue(props.data.dataSourceId); + }, []); + + useEffect(() => { + setExtValue(props.data.dataSourceId); + }, [props.data.dataSourceId]); const [dataSourceValue, setDataSourceValue] = useState({ value: props.data.dataSourceId, name: diff --git a/src/helpers/stateFromQueryParams.ts b/src/helpers/stateFromQueryParams.ts index 67dcb557..c2d91552 100644 --- a/src/helpers/stateFromQueryParams.ts +++ b/src/helpers/stateFromQueryParams.ts @@ -41,9 +41,9 @@ export const initialUrlState = { lastIdx: 1, panel: "right", queryType: "range", - dataSourceType: "logs", + dataSourceType: "traces", + dataSourceId:"32D16h5uYBqUUzhD", dataSourceURL: "", - dataSourceId: "cHI2SqPzH_kxYRXj", limit: 100, step: 5, tableView: false, diff --git a/src/store/createInitialState.ts b/src/store/createInitialState.ts index a0ea76b8..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, From 387053bb9d22575d2bd93ad9ac7fbef926f8b2ca Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Mon, 19 Dec 2022 13:39:30 +0200 Subject: [PATCH 25/40] #178 fixed --- src/views/DataSources/views/List.js | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/views/DataSources/views/List.js b/src/views/DataSources/views/List.js index 8047d0a2..d06487bf 100644 --- a/src/views/DataSources/views/List.js +++ b/src/views/DataSources/views/List.js @@ -13,17 +13,24 @@ export function List() { const { icon, id, name, type, url } = item; return (
-
- -
- -
{name}
- - - {type} | {url}{" "} - + +
+ +
+ +
{name}
+ + + {type} | {" "} + + + {url} + + + +
-
+
); })} From 2e3cf37bb4ed1ec3971d88757940922b7410f3e4 Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Mon, 19 Dec 2022 14:35:40 +0200 Subject: [PATCH 26/40] #181 fix --- src/views/DataSources/DataSources.js | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/views/DataSources/DataSources.js b/src/views/DataSources/DataSources.js index 4868edbe..129378c6 100644 --- a/src/views/DataSources/DataSources.js +++ b/src/views/DataSources/DataSources.js @@ -1,6 +1,6 @@ import { ThemeProvider } from "@emotion/react"; -import { useMemo } from "react"; -import { useSelector } from "react-redux"; +import { useEffect, useMemo } from "react"; +import { useDispatch, useSelector } from "react-redux"; import { themes } from "../../theme/themes"; import { PageContainer } from "./styles"; import { Route, Routes } from "react-router-dom"; @@ -8,6 +8,8 @@ import { DataSource } from "./DataSource"; import { List } from "./views/List"; import { Header } from "./components"; import { DataSourcesFiller } from "./components/DataSourcesFiller"; +import { setTheme } from "../../actions"; +import { useMediaQuery } from "react-responsive"; export function getURlParams(params) { @@ -26,7 +28,16 @@ export function getURlParams(params) { export default function DataSources() { const themeState = useSelector((store) => store.theme) || "light"; + const isAutoDark = useMediaQuery({ query: "(prefers-color-scheme: dark)" }); + const dispatch = useDispatch(); + const autoTheme = useSelector((store) => store.autoTheme); + useEffect(() => { + if (autoTheme) { + const theme = isAutoDark ? "dark" : "light"; + dispatch(setTheme(theme)); + } + }, [isAutoDark, autoTheme, dispatch]); const theme = useMemo(() => { return themes[themeState]; }, [themeState]); From b6124a5162b69a60f30cd390ab1d34a4ee3aad28 Mon Sep 17 00:00:00 2001 From: jacovinus Date: Mon, 19 Dec 2022 14:38:09 +0100 Subject: [PATCH 27/40] fix: default theme text color --- src/views/DataSources/styles.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/views/DataSources/styles.js b/src/views/DataSources/styles.js index 5549cf16..3cf05b95 100644 --- a/src/views/DataSources/styles.js +++ b/src/views/DataSources/styles.js @@ -49,6 +49,7 @@ export const PageContainer = styled.div` margin-bottom: 10px; border: 1px solid ${({ theme }) => theme.buttonBorder}; border-radius: 3px; + color: ${({theme})=> theme.textColor}; } .ds-item { @@ -58,6 +59,7 @@ export const PageContainer = styled.div` border-radius: 3px 3px 0px 0px; padding-bottom: 14px; display: flex; + color: ${({theme})=> theme.textColor}; .logo { padding: 10px; padding-right: 20px; From bc57aec7b49be2968354c9f74be7e824f463fad9 Mon Sep 17 00:00:00 2001 From: jacovinus Date: Mon, 19 Dec 2022 16:31:10 +0100 Subject: [PATCH 28/40] fix: Undefined data at History Link Tab #184 --- .../LabelBrowser/components/QueryBar.js | 12 ++++++- src/plugins/queryhistory/index.js | 31 ++++++++++--------- src/services/localUrl.ts | 14 +++++++-- 3 files changed, 39 insertions(+), 18 deletions(-) diff --git a/src/components/LabelBrowser/components/QueryBar.js b/src/components/LabelBrowser/components/QueryBar.js index a9f6bb3b..56ded42a 100644 --- a/src/components/LabelBrowser/components/QueryBar.js +++ b/src/components/LabelBrowser/components/QueryBar.js @@ -623,8 +623,18 @@ export const QueryBar = (props) => { } }; const updateLinksHistory = () => { + const ds = dataSources.find( f => f.id === dataSourceId) const storedUrl = saveUrl.add({ - data: window.location.href, + data: { + href: window.location.href, + url: ds.url, + type: dataSourceType, + queryInput, + queryType, + limit, + panel: name, + id, + }, description: "From Query Submit", }); diff --git a/src/plugins/queryhistory/index.js b/src/plugins/queryhistory/index.js index 86edcb6f..f02605ae 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:{" "} diff --git a/src/services/localUrl.ts b/src/services/localUrl.ts index 4844ca11..9cc3fc34 100644 --- a/src/services/localUrl.ts +++ b/src/services/localUrl.ts @@ -7,7 +7,7 @@ const localUrl = () => { const { l_set, l_get, j_parse, j_string } = localService(); const get = () => { - return j_parse(l_get(_URL_ITEM) || 'null'); + return j_parse(l_get(_URL_ITEM) || "null"); }; const set = (item: any) => { @@ -40,6 +40,8 @@ const localUrl = () => { 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; @@ -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, @@ -89,7 +98,8 @@ const localUrl = () => { }; function getAll() { - const actualStorage = JSON.parse(localStorage.getItem(_URL_ITEM) || 'null') || []; + const actualStorage = + JSON.parse(localStorage.getItem(_URL_ITEM) || "null") || []; return actualStorage; } From 96be81b563087fc0bd33ef40195120f0ff5ea5ad Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Tue, 20 Dec 2022 11:31:50 +0200 Subject: [PATCH 29/40] Synced localstorage value with value stored in Redux --- src/plugins/settingsdialog/SettingsDialog.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/plugins/settingsdialog/SettingsDialog.js b/src/plugins/settingsdialog/SettingsDialog.js index f3b4edba..59e5f4a8 100644 --- a/src/plugins/settingsdialog/SettingsDialog.js +++ b/src/plugins/settingsdialog/SettingsDialog.js @@ -59,9 +59,10 @@ 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 })); } const handleAutoTheme = (val) => { dispatch(setAutoTheme(!autoThemeLocal)) From 952677fb8581dbe7d24f0182387f504e7be91896 Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Tue, 20 Dec 2022 11:34:22 +0200 Subject: [PATCH 30/40] Added auto-theme to Localstorage --- src/plugins/settingsdialog/SettingsDialog.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/plugins/settingsdialog/SettingsDialog.js b/src/plugins/settingsdialog/SettingsDialog.js index 59e5f4a8..892f5c68 100644 --- a/src/plugins/settingsdialog/SettingsDialog.js +++ b/src/plugins/settingsdialog/SettingsDialog.js @@ -62,11 +62,13 @@ export default function SettingsDialog({ open, onClose }) { const switchedTheme = themeSet === "light" ? "dark" : "light" dispatch(setTheme(switchedTheme)); setThemeSet(switchedTheme); - localStorage.setItem("theme", JSON.stringify({ theme: 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)); From f5de0a355b048c2560ddbc02528b3049156831a1 Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Tue, 20 Dec 2022 11:49:31 +0200 Subject: [PATCH 31/40] Set theme LS when query params are set --- src/helpers/stateFromQueryParams.ts | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/helpers/stateFromQueryParams.ts b/src/helpers/stateFromQueryParams.ts index c2d91552..021e9ca5 100644 --- a/src/helpers/stateFromQueryParams.ts +++ b/src/helpers/stateFromQueryParams.ts @@ -85,7 +85,6 @@ export default function stateFromQueryParams() { 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( @@ -104,6 +103,9 @@ export default function stateFromQueryParams() { } else { startParams[key] = value; } + if (startParams.theme) { + localStorage.setItem("theme", JSON.stringify({ theme: startParams.theme, auto: !!startParams.autoTheme })); + } } return startParams || initialUrlState; From a90cda3c6536753f726983f634d94834835645a7 Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Tue, 20 Dec 2022 11:49:55 +0200 Subject: [PATCH 32/40] Set them LS when autotheme detects change in preferred theme --- src/views/DataSources/DataSources.js | 1 + src/views/Main.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/views/DataSources/DataSources.js b/src/views/DataSources/DataSources.js index 129378c6..28b0f83d 100644 --- a/src/views/DataSources/DataSources.js +++ b/src/views/DataSources/DataSources.js @@ -36,6 +36,7 @@ export default function DataSources() { if (autoTheme) { const theme = isAutoDark ? "dark" : "light"; dispatch(setTheme(theme)); + localStorage.setItem("theme", JSON.stringify({ theme: theme, auto: autoTheme })); } }, [isAutoDark, autoTheme, dispatch]); const theme = useMemo(() => { diff --git a/src/views/Main.js b/src/views/Main.js index 18f481de..a5d78055 100644 --- a/src/views/Main.js +++ b/src/views/Main.js @@ -375,6 +375,7 @@ export default function Main() { if (autoTheme) { const theme = isAutoDark ? "dark" : "light"; dispatch(setTheme(theme)); + localStorage.setItem("theme", JSON.stringify({ theme: theme, auto: autoTheme })); } }, [isAutoDark, autoTheme, dispatch]); if (!isTabletOrMobile) { From f765ab8248da64f1687a8d628e50952e60111d14 Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Tue, 20 Dec 2022 12:29:49 +0200 Subject: [PATCH 33/40] Fixed ordering of data views --- src/components/DataViews/index.js | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/components/DataViews/index.js b/src/components/DataViews/index.js index f2a09f32..90de630b 100644 --- a/src/components/DataViews/index.js +++ b/src/components/DataViews/index.js @@ -1,6 +1,7 @@ import { ThemeProvider } from "@emotion/react"; import { useMemo, useState } from "react"; import { useSelector } from "react-redux"; +import store from "../../store/store"; import { themes } from "../../theme/themes"; import { DataViewItem } from "./components/DataViewItem"; import { DataviewsContainer } from "./styled"; @@ -10,9 +11,12 @@ export default function DataViews(props) { const theme = useSelector((store) => store.theme); const [side] = useState(name); const dataViews = useSelector((store) => store[`${side}DataView`]); + const queries = useSelector((store) => store[side]); const viewsMemo = useMemo(()=>{ - return dataViews - },[dataViews]) + return dataViews.sort((a,b) => { + return queries.findIndex((query) => query.id === a.id) - queries.findIndex((query) => query.id === b.id) + }) + },[dataViews, queries]) if (viewsMemo.length > 0 ) { return ( From 5486d25b147709e0a6334c95399b9f2ae9118001 Mon Sep 17 00:00:00 2001 From: jacovinus Date: Tue, 20 Dec 2022 13:42:52 +0100 Subject: [PATCH 34/40] fix:show results button action inside history #185 --- .../LabelBrowser/components/QueryBar.js | 73 +++++++++++++------ src/plugins/queryhistory/index.js | 46 ++++++++++-- 2 files changed, 89 insertions(+), 30 deletions(-) diff --git a/src/components/LabelBrowser/components/QueryBar.js b/src/components/LabelBrowser/components/QueryBar.js index 56ded42a..5006c471 100644 --- a/src/components/LabelBrowser/components/QueryBar.js +++ b/src/components/LabelBrowser/components/QueryBar.js @@ -263,9 +263,6 @@ export const QueryBar = (props) => { } }, [isTabletOrMobile]); - - - // changes on changin dataSource Id useEffect(() => { @@ -375,7 +372,6 @@ export const QueryBar = (props) => { } }, [dataSourceId, id]); - // changes on changing exp useEffect(() => { @@ -407,9 +403,19 @@ export const QueryBar = (props) => { const onSubmit = (e) => { e.preventDefault(); - if (onQueryValid(queryInput)) { + const ds = dataSources.find((f) => f.id === dataSourceId); + if (onQueryValid(queryInput) && ds) { try { - updateHistory(queryInput, queryType, limit, id); + updateHistory( + ds.type, + queryInput, + queryType, + limit, + id, + direction, + ds.id, + ds.url + ); // Decode query to translate into labels selection decodeQueryAndUpdatePanel(queryInput, true); @@ -489,14 +495,14 @@ export const QueryBar = (props) => { setLocalStorage(); }; - const onSubmitRate = (e, type = "logs") => { + const onSubmitRate = (e) => { e.preventDefault(); const isEmptyQuery = queryInput.length === 0; let query = ""; if (!isEmptyQuery) { const isRate = queryInput.startsWith(`rate(`); - if (type === "metrics") { + if (dataSourceType === "metrics") { if (isRate) { query = queryInput.replace(/{([^}]+)}/g, "{}"); query = query.replace(/\[\d+ms\]/, "[$__interval]"); @@ -520,9 +526,21 @@ export const QueryBar = (props) => { setQueryValid(onQueryValid(query)); } + if (onQueryValid(query)) { + const ds = dataSources.find((f) => f.id === dataSourceId); + try { - updateHistory(query, queryType, limit, id); + updateHistory( + ds.type, + query, + queryType, + limit, + id, + direction, + ds.id, + ds.url + ); // Decode query to translate into labels selection decodeQueryAndUpdatePanel(query, true); @@ -536,13 +554,25 @@ export const QueryBar = (props) => { } }; - const updateHistory = (queryInput, queryType, limit, id) => { + const updateHistory = ( + type, + queryInput, + queryType, + limit, + id, + direction, + dataSourceId, + url + ) => { const historyUpdated = historyService.add({ data: JSON.stringify({ - type: dataSourceType, + type, queryInput, queryType, limit, + direction, + dataSourceId: dataSourceId, + url, panel: name, id, }), @@ -623,7 +653,7 @@ export const QueryBar = (props) => { } }; const updateLinksHistory = () => { - const ds = dataSources.find( f => f.id === dataSourceId) + const ds = dataSources.find((f) => f.id === dataSourceId); const storedUrl = saveUrl.add({ data: { href: window.location.href, @@ -707,8 +737,6 @@ export const QueryBar = (props) => { return null; } - - const queryTypeRenderer = ( type, traceSearch, @@ -771,9 +799,9 @@ export const QueryBar = (props) => { handleHistoryClick={handleHistoryClick} queryValid={queryValid} onSubmit={onSubmit} - onSubmitRate={onSubmitRate} + onSubmitRate={onSubmitRate} labels={labels} - loading={loading||false} + loading={loading || false} hasStats={hasStats} showStatsOpen={showStatsOpen} handleStatsOpen={handleStatsOpen} @@ -801,7 +829,7 @@ export const QueryBar = (props) => { onSubmitRate={onSubmitRate} isTabletOrMobile={isTabletOrMobile} labels={labels} - loading={loading||false} + loading={loading || false} />, { logsRateButton={ onSubmitRate(e, "metrics")} + onClick={onSubmitRate} isMobile={false} alterText={"Use as Rate Query"} /> @@ -838,7 +866,7 @@ export const QueryBar = (props) => { @@ -921,7 +949,7 @@ export const QueryBarCont = (props) => { disabled={!queryValid} onClick={onSubmit} isMobile={false} - loading={loading||false} + loading={loading || false} /> )} @@ -933,7 +961,7 @@ export const QueryBarCont = (props) => { disabled={!queryValid} onClick={onSubmit} isMobile={false} - loading={loading||false} + loading={loading || false} /> )} @@ -941,7 +969,6 @@ export const QueryBarCont = (props) => { ); }; - // mobile top query view (mobile view or splitted view) export const MobileTopQueryMenuCont = (props) => { const dispatch = useDispatch(); @@ -1034,7 +1061,7 @@ export const MobileTopQueryMenuCont = (props) => { disabled={!queryValid} onClick={onSubmit} isMobile={true} - loading={loading||false} + loading={loading || false} /> {dataSourceType === "flux" && ( diff --git a/src/plugins/queryhistory/index.js b/src/plugins/queryhistory/index.js index f02605ae..8110b686 100644 --- a/src/plugins/queryhistory/index.js +++ b/src/plugins/queryhistory/index.js @@ -639,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)); @@ -678,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 ) ); } @@ -908,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} /> From a207abcb53c2cab5cd4d0bf07314a364768122d2 Mon Sep 17 00:00:00 2001 From: jacovinus Date: Tue, 20 Dec 2022 19:31:24 +0100 Subject: [PATCH 35/40] fix: #195 remove query stored --- src/components/QueryItem/QueryItem.tsx | 43 ++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 3 deletions(-) diff --git a/src/components/QueryItem/QueryItem.tsx b/src/components/QueryItem/QueryItem.tsx index c0a4952f..0138c9b2 100644 --- a/src/components/QueryItem/QueryItem.tsx +++ b/src/components/QueryItem/QueryItem.tsx @@ -85,11 +85,48 @@ export default function QueryItem(props: any) { } } - const onDeleteQuery = () => { + const getStoredQueries = (): Array => { + let stored = []; + try { + const fromStore = + JSON.parse(localStorage.getItem("queryData") || "[]") || []; + stored = [...fromStore]; + return stored; + } catch (e) { + return []; + } + }; + + const setStoredQuery = (queries: Array): void => { + localStorage.setItem("queryData", JSON.stringify(queries)); + }; + const filterQuery = (query: any) => query.queryId !== props.data.id; + + const filterLocal = (queries: Array): Array => { + return queries.filter((f: any) => filterQuery(f)); + }; + + const deleteStoredQuery = (): void => { + const prevStored = getStoredQueries(); + + if (prevStored?.length > 0) { + const filtered = filterLocal(prevStored); + setStoredQuery(filtered); + } + }; + + const onDeleteQuery = ():void => { + const filtered = filterPanel(panelSelected); const viewFiltered = filterPanel(dataView); + const prevStoredQuery = getStoredQueries(); + + if (prevStoredQuery?.length > 0) { + deleteStoredQuery(); + } + if (filtered) { dispatch(panelAction(name, filtered)); } @@ -141,9 +178,9 @@ export default function QueryItem(props: any) { dispatch(panelAction(name, panelData)); }; - + const _themes: any = themes; - + return ( From 58cb6c40e3513d558be740466de2268e925ddaa7 Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Wed, 21 Dec 2022 11:04:09 +0200 Subject: [PATCH 36/40] DataView model --- src/store/store.model.ts | 50 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 48 insertions(+), 2 deletions(-) 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; +} From af719493754389cba43c48f6c9fa277413e947c1 Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Wed, 21 Dec 2022 12:55:02 +0200 Subject: [PATCH 37/40] Fixed: #193 Fixed: #193 --- src/actions/getData.ts | 29 ++++++++++++++----- src/actions/helpers/resetParams.ts | 1 - .../DataViews/components/DataViewItem.js | 4 +-- .../DataViews/components/EmptyViewCont.js | 4 +-- src/components/DataViews/views/EmptyView.js | 3 +- 5 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/actions/getData.ts b/src/actions/getData.ts index 83b14bfc..12caa8c2 100644 --- a/src/actions/getData.ts +++ b/src/actions/getData.ts @@ -13,6 +13,9 @@ import { getTimeSpan } from "./helpers/getTimeSpan"; import { boscoSend } from "./helpers/boscoRequest"; import { setLeftPanel } from "./setLeftPanel"; import { setRightPanel } from "./setRightPanel"; +import { DataViews } from "../store/store.model"; +import { setLeftDataView } from "./setLeftDataView"; +import { setRightDataView } from "./setRightDataView"; /** * @@ -36,7 +39,12 @@ function panelDispatch(panel: string, dispatch: Function, data: any) { return dispatch(setRightPanel(data)); } } - +export function dataViewDispatch(panel: string, dataViews: DataViews, dispatch: Function) { + if (panel === "left") { + return dispatch(setLeftDataView(dataViews)); + } + return dispatch(setRightDataView(dataViews)); +} function changeLoadingState(panel: any[], id: string, state: boolean) { return [...panel].map((m) => { if (m.id === id) { @@ -150,10 +158,17 @@ export default function getData( ); const endpoint = getEndpoint(type, queryType, params); - + const setLoading = (state: boolean, dispatch: Function) => { + const dataViews: DataViews = store.getState()?.[`${panel}DataView`]; + const dataView = dataViews?.find((view) => view.id === id); + if (dataView) { + dataView.loading = state; + } + dataViewDispatch(panel, dataViews, dispatch); + } return async function (dispatch: Function) { await resetParams(dispatch, panel); - dispatch(setLoading(true)); + setLoading(true, dispatch); loadingState(dispatch, true); let cancelToken: any; @@ -187,13 +202,13 @@ export default function getData( .catch((error) => { resetNoData(dispatch); dispatch(setIsEmptyView(true)); - dispatch(setLoading(false)); + setLoading(false, dispatch) if (debugMode) { console.log("Error loading flux data", error); } }) .finally(() => { - dispatch(setLoading(false)); + setLoading(false, dispatch) loadingState(dispatch, false); }); } else if (options?.method === "GET") { @@ -224,7 +239,7 @@ export default function getData( .catch((error) => { resetNoData(dispatch); dispatch(setIsEmptyView(true)); - dispatch(setLoading(false)); + setLoading(false, dispatch) loadingState(dispatch, false); if (debugMode) { boscoSend( @@ -240,7 +255,7 @@ export default function getData( }) .finally(() => { loadingState(dispatch, false); - dispatch(setLoading(false)); + setLoading(false, dispatch) }); } } catch (e) { diff --git a/src/actions/helpers/resetParams.ts b/src/actions/helpers/resetParams.ts index eab01cc7..63456632 100644 --- a/src/actions/helpers/resetParams.ts +++ b/src/actions/helpers/resetParams.ts @@ -8,7 +8,6 @@ import { setVectorData } from "../setVectorData"; export async function resetParams(dispatch: Function,panel:string) { - dispatch(setLoading(true)); dispatch(setIsEmptyView(false)); dispatch(setLogs([])); diff --git a/src/components/DataViews/components/DataViewItem.js b/src/components/DataViews/components/DataViewItem.js index 36861efe..afc08515 100644 --- a/src/components/DataViews/components/DataViewItem.js +++ b/src/components/DataViews/components/DataViewItem.js @@ -9,8 +9,7 @@ import { TraceView } from "./Traces/TraceView.tsx"; export function DataViewItem(props) { // add a header for table view / json view const { dataView, name, vHeight } = props; - const { type, total } = dataView; - + const { type, total, loading } = dataView; const viewRef = useRef(null); const isSplit = useSelector((store) => store.isSplit); const panel = useSelector((store) => store[name]); @@ -153,6 +152,7 @@ export function DataViewItem(props) { setMaxHeight, actualQuery, total, + loading, ...props, }; diff --git a/src/components/DataViews/components/EmptyViewCont.js b/src/components/DataViews/components/EmptyViewCont.js index 463bb206..fccf150e 100644 --- a/src/components/DataViews/components/EmptyViewCont.js +++ b/src/components/DataViews/components/EmptyViewCont.js @@ -3,9 +3,9 @@ import { useSelector } from "react-redux"; import { themes } from "../../../theme/themes"; import { EmptyViewContainer } from "../styled"; -export default function EmptyViewCont() { +export default function EmptyViewCont(props) { const theme = useSelector((store) => store.theme); - const loading = useSelector((store) => store.loading); + const { loading } = props; return ( !loading && ( diff --git a/src/components/DataViews/views/EmptyView.js b/src/components/DataViews/views/EmptyView.js index b6a2cfaa..b66f3d8c 100644 --- a/src/components/DataViews/views/EmptyView.js +++ b/src/components/DataViews/views/EmptyView.js @@ -11,6 +11,7 @@ export function EmptyView(props) { setMaxHeight, actualQuery, total, + loading } = props; return ( @@ -25,7 +26,7 @@ export function EmptyView(props) { fixedSize={true} {...props} /> - + ); } From 550ea3acac2b2a100dc7038fc148dc592a334222 Mon Sep 17 00:00:00 2001 From: Alexey Oplachko Date: Wed, 21 Dec 2022 13:20:38 +0200 Subject: [PATCH 38/40] Fixed: Warning: Received `false` for a non-boolean attribute `loading`. --- src/components/LabelBrowser/components/styled/index.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/components/LabelBrowser/components/styled/index.ts b/src/components/LabelBrowser/components/styled/index.ts index 1f616c59..2cd12e3b 100644 --- a/src/components/LabelBrowser/components/styled/index.ts +++ b/src/components/LabelBrowser/components/styled/index.ts @@ -1,4 +1,5 @@ import styled from "@emotion/styled"; +import isPropValid from '@emotion/is-prop-valid' import HistoryIcon from "@mui/icons-material/History"; import { BtnSmall as btnSmall } from "../../../../theme/styles/Button"; @@ -52,7 +53,9 @@ export const QueryBarContainer = styled.div` flex-wrap: wrap; border-radius: 3px; `; -export const ShowLogsBtn = styled(BtnSmall)` +export const ShowLogsBtn = styled(BtnSmall, { + shouldForwardProp: prop => isPropValid(prop) && prop !== 'loading' +})` background: ${(props) => props.loading ? '#44bcd8' : props.theme.primaryDark}; border: 1px solid ${(props) => props.theme.buttonBorder}; color: ${(props) => props.theme.buttonText}; From eb81d9cdebda4802f7e91f60478591d8a13fcf2d Mon Sep 17 00:00:00 2001 From: jacovinus Date: Wed, 21 Dec 2022 15:08:19 +0100 Subject: [PATCH 39/40] fix: Adding Labels inside Log row... #194 --- .../DataViews/components/ValueTags.js | 16 +++++--- .../LabelBrowser/helpers/querybuilder.ts | 38 ++++++++++++++++--- 2 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/components/DataViews/components/ValueTags.js b/src/components/DataViews/components/ValueTags.js index 7145e091..412a627d 100644 --- a/src/components/DataViews/components/ValueTags.js +++ b/src/components/DataViews/components/ValueTags.js @@ -48,9 +48,6 @@ function alreadyExists(exp, op, k, v) { export function ValueTagsCont(props) { const { showLabels, tags, actQuery } = props; - - - if (showLabels) { return (

@@ -65,7 +62,7 @@ export async function addLabel(e, key, value, isExcluded = false, queryObj) { e.preventDefault(); e.stopPropagation(); - const { expr, panel, id } = queryObj; + const { expr, panel, id, dataSourceType } = queryObj; const isAlreadyExcluded = alreadyExists(expr, "!=", key, value); @@ -78,7 +75,14 @@ export async function addLabel(e, key, value, isExcluded = false, queryObj) { return; } - queryBuilderWithLabels(expr, panel, id, [key, value], isExcluded); + queryBuilderWithLabels( + expr, + panel, + id, + [key, value], + isExcluded, + dataSourceType + ); } export class Panel { @@ -103,7 +107,7 @@ export default function ValueTags(props) { const openTraces = (e, key, value, linkID, currentUrl, linkType) => { e.stopPropagation(); - if (props?.actQuery?.panel === "left" && !isTabletOrMobile ) { + if (props?.actQuery?.panel === "left" && !isTabletOrMobile) { dispatch(setSplitView(true)); } diff --git a/src/components/LabelBrowser/helpers/querybuilder.ts b/src/components/LabelBrowser/helpers/querybuilder.ts index 11fdb761..e5b17a42 100644 --- a/src/components/LabelBrowser/helpers/querybuilder.ts +++ b/src/components/LabelBrowser/helpers/querybuilder.ts @@ -22,6 +22,7 @@ export const PIPE_PARSE = [ const pipeParseOpts = ["json", "regexp", "logfmt", "pattern", "~", "="]; const STREAM_SELECTOR_REGEX = /{[^}]*}/; + const parseLog = { newQuery: (keyValue: any[], op: any, tags: any[]) => { const [key, value] = keyValue; @@ -43,7 +44,7 @@ const parseLog = { ?.map((m) => m.split(",")) ?.flat() || [], addLabel: (op: any, keySubtValue: any, keyValue: any) => - op === "!=" ? keyValue : keySubtValue + op === "!=" ? keySubtValue : keyValue , rmValueFromLabel: (label: any, value: any) => { const [lb, val] = label?.split("=~"); @@ -70,7 +71,12 @@ const parseLog = { return query === `{${key}="${value}"}`; }, editQuery: (query: string, keyValue: any[], op: string, tags: any[]) => { + + //console.log(query,"QUERY", keyValue,"KEYVALUE", op,"OPERATOR", tags,"TAGS" ) + + if (parseLog.isEqualsQuery(query, keyValue) && keyValue !== null) { + return parseLog.equalLabels(keyValue, op, tags); } @@ -79,7 +85,9 @@ const parseLog = { }; const parseQuery = { fromLabels: (query: string, keyVal: any[], op: string, tags: any[]) => { + const queryString = parseQueryLabels(keyVal, query, op); + console.log(queryString) return parseLog.formatQuery(queryString, tags); }, }; @@ -93,20 +101,26 @@ function parseQueryLabels(keyVal: any[], query: string, op: string) { return ""; } + console.log(queryArr) + for (let label of queryArr) { const regexQuery = label.match(/([^{}=,~!]+)/gm); + console.log(regexQuery) const querySplitted = parseLog.splitLabels(query); if (!regexQuery) { return ""; } - + //console.log("VALUE", value, "LABEL: ", label, "KEY:", key,"QUERYSPLITTED:", querySplitted) if ( value !== null && !label.includes(key?.trim()) && !querySplitted?.some((s) => s.includes(key)) ) { // add new label + console.log('first case') let labelMod = op === "!=" ? keySubtValue : label; + console.log(labelMod, keyValue) const parsed = parseLog.addLabel(op, labelMod, keyValue); + console.log(parsed) const regs = parseLog.splitLabels(query).concat(parsed); return regs.join(","); } @@ -116,6 +130,7 @@ function parseQueryLabels(keyVal: any[], query: string, op: string) { label?.split("=")?.[0]?.trim() === key?.trim() && !label?.includes(value) ) { + console.log('second case') // values group from existing label let labelMod = parseLog.addValueToLabel(label, value, true); return parseLog @@ -129,6 +144,7 @@ function parseQueryLabels(keyVal: any[], query: string, op: string) { label?.split("=~")?.[0]?.trim() === key?.trim() && label?.includes(value) ) { + console.log('third case') // filter value from existing values group from label const labelMod = parseLog.rmValueFromLabel(label, value); return parseLog @@ -142,7 +158,9 @@ function parseQueryLabels(keyVal: any[], query: string, op: string) { label?.split("=~")?.[0]?.trim() === key?.trim() && !label?.includes(value?.trim()) ) { + console.log('forth case') // add value to existing values group from label + console.log('adding value to label') return parseLog.addValueToLabel(label, value, false); } @@ -153,6 +171,7 @@ function parseQueryLabels(keyVal: any[], query: string, op: string) { (label?.split('"')?.[1]?.trim() === value?.trim() || value === null) && querySplitted?.some((s) => s === label) ) { + console.log('fifth case') // remove label from query const filtered = querySplitted?.filter((f) => f !== label); return filtered?.join(","); @@ -161,13 +180,14 @@ function parseQueryLabels(keyVal: any[], query: string, op: string) { return ""; } -export function decodeQuery(query: any, key: any, value: any, op: any, type: any) { +export function decodeQuery(query: any, key: any, value: any, op: any, type: any) { const { newQuery, editQuery } = parseLog; let keyValue = [key, value]; + let tags = query?.split(/[{}]/); const isQuery = query?.match(STREAM_SELECTOR_REGEX) && tags[1].length > 7; - + // if (tags[1]?.length < 1 && type === "metrics") { return `${value}{}`; } @@ -177,6 +197,7 @@ export function decodeQuery(query: any, key: any, value: any, op: any, type: any } if (!isQuery && key !== "__name__") { + console.log('going inside newQuery') return newQuery(keyValue, op, tags); } @@ -233,9 +254,11 @@ export function queryBuilderWithLabels( id: any, // query id keyVal: any, // key / value isInverted = false, + dataSourceType='logs', hasPipe = false, pipeLabels = [] ) { + // const [key, val] = keyVal; const dispatch = store.dispatch; const operator = () => { @@ -244,8 +267,13 @@ export function queryBuilderWithLabels( } return "="; }; + const op = operator() const { left, right } = store.getState(); - const queryStr = decodeQuery(expr, key, val, operator(), null); + + // decodeQuery(query: any, key: any, value: any, op: any, type: any) + + const queryStr = decodeQuery(expr, key, val,op, dataSourceType); // this one should be the problem + // // here will return without braces\ // // return [preTags, "{", selectedLabels.join(","), "}", postTags].join(""); From 0295067597c3b7f947a196c62e70a781d4ce6aa5 Mon Sep 17 00:00:00 2001 From: jacovinus Date: Wed, 21 Dec 2022 17:41:25 +0100 Subject: [PATCH 40/40] fix:Sum not equals regex at logs row with '-' button cleans query #198 --- .../LabelBrowser/helpers/querybuilder.ts | 153 +++++++++++++----- 1 file changed, 109 insertions(+), 44 deletions(-) diff --git a/src/components/LabelBrowser/helpers/querybuilder.ts b/src/components/LabelBrowser/helpers/querybuilder.ts index e5b17a42..eb1206d6 100644 --- a/src/components/LabelBrowser/helpers/querybuilder.ts +++ b/src/components/LabelBrowser/helpers/querybuilder.ts @@ -43,9 +43,8 @@ const parseLog = { ?.match(/[^{}]+(?=})/g) ?.map((m) => m.split(",")) ?.flat() || [], - addLabel: (op: any, keySubtValue: any, keyValue: any) => - op === "!=" ? keySubtValue : keyValue - , + addLabel: (op: any, keySubtValue: any, keyValue: any) => + op === "!=" ? keySubtValue : keyValue, rmValueFromLabel: (label: any, value: any) => { const [lb, val] = label?.split("=~"); let lvalue = val?.split(/[""]/)[1]; @@ -59,35 +58,48 @@ const parseLog = { const lvalues = filtered?.join("")?.trim(); return lb?.trim() + "=" + '"' + lvalues + '"'; }, + rmNonEqValueFromLabel: (label: any, value: any) => { + const [lb, val] = label?.split("!~"); + let lvalue = val?.split(/[""]/)[1]; + let values = lvalue?.split("|"); + let filtered = values?.filter((f: any) => f.trim() !== value?.trim()); + + if (filtered?.length > 1) { + const lvalues = filtered?.join("|")?.trim(); + return lb?.trim() + "!~" + '"' + lvalues + '"'; + } + const lvalues = filtered?.join("")?.trim(); + return lb?.trim() + "!=" + '"' + lvalues + '"'; + }, addValueToLabel: (label: string, value: string, isEquals: boolean) => { - const sign = isEquals ? "=" : "=~"; + let sign = isEquals ? "=" : "=~"; const [lb, val] = label?.split(sign); const values = val?.split(/[""]/)[1]; const labelmod = `${lb}=~"${values?.trim()}|${value?.trim()}"`; return labelmod; }, + addNonEqValueToLabel: (label: string, value: string, isEquals: boolean) => { + let sign = isEquals ? "!=" : "!~"; + const [lb, val] = label?.split(sign); + const values = val?.split(/[""]/)[1]; + const labelmod = `${lb}!~"${values?.trim()}|${value?.trim()}"`; + return labelmod; + }, isEqualsQuery: (query: string, keyValue: any[]) => { const [key, value] = keyValue; return query === `{${key}="${value}"}`; }, editQuery: (query: string, keyValue: any[], op: string, tags: any[]) => { - - //console.log(query,"QUERY", keyValue,"KEYVALUE", op,"OPERATOR", tags,"TAGS" ) - - if (parseLog.isEqualsQuery(query, keyValue) && keyValue !== null) { - return parseLog.equalLabels(keyValue, op, tags); } - return parseQuery.fromLabels(query, keyValue, op, tags); }, }; const parseQuery = { fromLabels: (query: string, keyVal: any[], op: string, tags: any[]) => { - const queryString = parseQueryLabels(keyVal, query, op); - console.log(queryString) + return parseLog.formatQuery(queryString, tags); }, }; @@ -97,54 +109,55 @@ function parseQueryLabels(keyVal: any[], query: string, op: string) { const keyValue = `${key}="${value}"`; const keySubtValue = `${key}!="${value}"`; let queryArr = parseLog.splitLabels(query); + if (!queryArr) { return ""; } - console.log(queryArr) - for (let label of queryArr) { const regexQuery = label.match(/([^{}=,~!]+)/gm); - console.log(regexQuery) + const querySplitted = parseLog.splitLabels(query); + if (!regexQuery) { return ""; } - //console.log("VALUE", value, "LABEL: ", label, "KEY:", key,"QUERYSPLITTED:", querySplitted) - if ( value !== null && + + if ( + value !== null && !label.includes(key?.trim()) && !querySplitted?.some((s) => s.includes(key)) ) { // add new label - console.log('first case') + let labelMod = op === "!=" ? keySubtValue : label; - console.log(labelMod, keyValue) + const parsed = parseLog.addLabel(op, labelMod, keyValue); - console.log(parsed) + const regs = parseLog.splitLabels(query).concat(parsed); return regs.join(","); } - if ( value !== null && + if ( + value !== null && label?.includes("=") && label?.split("=")?.[0]?.trim() === key?.trim() && !label?.includes(value) ) { - console.log('second case') // values group from existing label - let labelMod = parseLog.addValueToLabel(label, value, true); + let labelMod = parseLog.addValueToLabel(label, value, true); // use this one for != return parseLog .splitLabels(query) ?.join(",") ?.replace(`${label}`, labelMod); } - if ( value !== null && + if ( + value !== null && label?.includes("=~") && label?.split("=~")?.[0]?.trim() === key?.trim() && label?.includes(value) ) { - console.log('third case') // filter value from existing values group from label const labelMod = parseLog.rmValueFromLabel(label, value); return parseLog @@ -153,14 +166,13 @@ function parseQueryLabels(keyVal: any[], query: string, op: string) { .replace(`${label}`, labelMod); } - if ( value !== null && + if ( + value !== null && label?.includes("=~") && label?.split("=~")?.[0]?.trim() === key?.trim() && !label?.includes(value?.trim()) ) { - console.log('forth case') // add value to existing values group from label - console.log('adding value to label') return parseLog.addValueToLabel(label, value, false); } @@ -168,23 +180,77 @@ function parseQueryLabels(keyVal: any[], query: string, op: string) { if ( label?.includes("=") && label?.split("=")?.[0]?.trim() === key?.trim() && - (label?.split('"')?.[1]?.trim() === value?.trim() || value === null) && + (label?.split('"')?.[1]?.trim() === value?.trim() || + value === null) && + querySplitted?.some((s) => s === label) + ) { + // remove label from query + const filtered = querySplitted?.filter((f) => f !== label); + return filtered?.join(","); + } + if ( + label?.includes("!=") && + label?.split("!=")?.[0]?.trim() === key?.trim() && + (label?.split('"')?.[1]?.trim() === value?.trim() || + value === null) && + querySplitted?.some((s) => s === label) + ) { + // remove label from query + const filtered = querySplitted?.filter((f) => f !== label); + return filtered?.join(","); + } + + if ( + label?.includes("!=") && // left all negative cases + label?.split("!=")[0]?.trim() === key?.trim() + ) { + // values group from existing label + let labelMod = parseLog.addNonEqValueToLabel(label, value, true); // use this one for != + return parseLog + .splitLabels(query) + ?.join(",") + ?.replace(`${label}`, labelMod); + } + if ( + value !== null && + label?.includes("!~") && + label?.split("!~")?.[0]?.trim() === key?.trim() && + label?.includes(value) + ) { + // filter value from existing values group from label + const labelMod = parseLog.rmNonEqValueFromLabel(label, value); + return parseLog + .splitLabels(query) + .join(",") + .replace(`${label}`, labelMod); + } + if ( + label?.includes("!=") && + label?.split("!=")?.[0]?.trim() === key?.trim() && + (label?.split('"')?.[1]?.trim() === value?.trim() || + value === null) && querySplitted?.some((s) => s === label) ) { - console.log('fifth case') // remove label from query const filtered = querySplitted?.filter((f) => f !== label); return filtered?.join(","); } } + return ""; } -export function decodeQuery(query: any, key: any, value: any, op: any, type: any) { +export function decodeQuery( + query: any, + key: any, + value: any, + op: any, + type: any +) { const { newQuery, editQuery } = parseLog; let keyValue = [key, value]; - + let tags = query?.split(/[{}]/); const isQuery = query?.match(STREAM_SELECTOR_REGEX) && tags[1].length > 7; // @@ -197,18 +263,22 @@ export function decodeQuery(query: any, key: any, value: any, op: any, type: any } if (!isQuery && key !== "__name__") { - console.log('going inside newQuery') return newQuery(keyValue, op, tags); } return editQuery(query, keyValue, op, tags); } -export function queryBuilder(labels: any, expr: any, hasPipe = false, pipeLabels = []) { +export function queryBuilder( + labels: any, + expr: any, + hasPipe = false, + pipeLabels = [] +) { const actualQuery = expr; const preTags = actualQuery.split("{")[0]; let postTags = ""; - // const isRate = expr.startsWith('rate(') && expr.endsWith('[$__interval])') + if (hasPipe) { postTags = actualQuery.split("}")[1]; const json = /[|json]/; @@ -254,11 +324,10 @@ export function queryBuilderWithLabels( id: any, // query id keyVal: any, // key / value isInverted = false, - dataSourceType='logs', + dataSourceType = "logs", hasPipe = false, pipeLabels = [] ) { - // const [key, val] = keyVal; const dispatch = store.dispatch; const operator = () => { @@ -267,16 +336,12 @@ export function queryBuilderWithLabels( } return "="; }; - const op = operator() + const op = operator(); const { left, right } = store.getState(); - // decodeQuery(query: any, key: any, value: any, op: any, type: any) - const queryStr = decodeQuery(expr, key, val,op, dataSourceType); // this one should be the problem - // - // here will return without braces\ - // - // return [preTags, "{", selectedLabels.join(","), "}", postTags].join(""); + const queryStr = decodeQuery(expr, key, val, op, dataSourceType); // this one should be the problem + // here will return without braces if (name === "left") { const leftC = [...left];