diff --git a/.babelrc b/.babelrc index e708c7a2..e6ff02c9 100644 --- a/.babelrc +++ b/.babelrc @@ -2,7 +2,8 @@ "plugins": [ "transform-class-properties", "react-hot-loader/babel", - "syntax-dynamic-import" + "syntax-dynamic-import", + "@babel/plugin-transform-runtime" ], "presets": [ diff --git a/package-lock.json b/package-lock.json index 095c8b2d..a2be0c56 100644 --- a/package-lock.json +++ b/package-lock.json @@ -38,6 +38,7 @@ "@babel/core": "^7.16.12", "@babel/plugin-proposal-class-properties": "^7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.16.7", + "@babel/plugin-transform-runtime": "^7.17.0", "@babel/preset-env": "^7.16.11", "@babel/preset-react": "^7.16.7", "babel-loader": "^8.2.3", diff --git a/package.json b/package.json index e01c9752..bdc320c8 100644 --- a/package.json +++ b/package.json @@ -69,6 +69,7 @@ "@babel/core": "^7.16.12", "@babel/plugin-proposal-class-properties": "^7.16.7", "@babel/plugin-proposal-object-rest-spread": "^7.16.7", + "@babel/plugin-transform-runtime": "^7.17.0", "@babel/preset-env": "^7.16.11", "@babel/preset-react": "^7.16.7", "babel-loader": "^8.2.3", diff --git a/src/actions/LoadLabels.js b/src/actions/LoadLabels.js index 8065dcd4..a6957094 100644 --- a/src/actions/LoadLabels.js +++ b/src/actions/LoadLabels.js @@ -1,5 +1,5 @@ import axios from "axios"; -import setLabels from "./setLabels"; +import { setLabels } from "./setLabels"; import setLoading from "./setLoading"; import { setApiError } from "./setApiError"; import { errorHandler } from "./errorHandler"; @@ -21,11 +21,11 @@ export default function loadLabels(apiUrl) { mode: "cors", }; - return function (dispatch) { + return async (dispatch) => { - axios.get(`${url.trim()}/loki/api/v1/labels`, options) + await axios.get(`${url.trim()}/loki/api/v1/labels`, options) ?.then((response) => { if(response){ if(response?.data?.data === []) console.log('no labels found') @@ -39,7 +39,6 @@ export default function loadLabels(apiUrl) { hidden: false, facets: 0, })); - dispatch(setLabels(labels || [])); dispatch(setApiError('')) diff --git a/src/actions/index.js b/src/actions/index.js index bbc9d601..2b3e08d9 100644 --- a/src/actions/index.js +++ b/src/actions/index.js @@ -9,3 +9,4 @@ export * from "./setApiUrl"; export * from "./setQuery"; export * from "./setIsSubmit"; export * from "./setMatrixData"; +export * from "./setLabels"; \ No newline at end of file diff --git a/src/actions/loadLabelValues.js b/src/actions/loadLabelValues.js index 036b9052..ecab3020 100644 --- a/src/actions/loadLabelValues.js +++ b/src/actions/loadLabelValues.js @@ -1,14 +1,14 @@ import axios from "axios"; import { errorHandler } from "./errorHandler"; import { setApiError } from "./setApiError"; -import setLabels from "./setLabels"; +import { setLabels } from "./setLabels"; import setLabelValues from "./setLabelValues"; import setLoading from "./setLoading"; -export default function loadLaebelValues(label, labelList, apiUrl) { - if (label?.length <= 0 && label.lsList.length <= 0) { - return; +export default function loadLabelValues(label, labelList, apiUrl) { + if (!label || (label?.length <= 0 && label.lsList.length <= 0)) { + return () => {}; }; const url = apiUrl; @@ -28,11 +28,10 @@ export default function loadLaebelValues(label, labelList, apiUrl) { }; - return function (dispatch) { - + return async (dispatch) => { dispatch(setLoading(true)) - axios.get(`${url}/loki/api/v1/label/${label.name}/values`, options) + await axios.get(`${url}/loki/api/v1/label/${label.name}/values`, options) ?.then(response => { if (response?.data?.data) { const values = response?.data?.data?.map?.((value) => ({ @@ -40,6 +39,7 @@ export default function loadLaebelValues(label, labelList, apiUrl) { selected: false, loading: false, hidden: false, + inverted: false })); const lsList = [...labelList]; @@ -62,7 +62,7 @@ export default function loadLaebelValues(label, labelList, apiUrl) { const { message } = errorHandler(url, error) dispatch(setApiError(message)) - console.log(error) + console.err(error) }) } diff --git a/src/actions/setLabelValues.js b/src/actions/setLabelValues.js index d0c0fa5f..4e82dd8d 100644 --- a/src/actions/setLabelValues.js +++ b/src/actions/setLabelValues.js @@ -1,6 +1,7 @@ -export default (labelValues) => (dispatch) => { +const setLabelValues = (labelValues) => (dispatch) => { dispatch({ type: 'SET_LABEL_VALUES', labelValues }); } +export default setLabelValues; diff --git a/src/actions/setLabels.js b/src/actions/setLabels.js index 8a839e50..0c8a8437 100644 --- a/src/actions/setLabels.js +++ b/src/actions/setLabels.js @@ -1,6 +1,6 @@ -export default (labels) => (dispatch) => { +export const setLabels = (labels) => (dispatch) => { dispatch({ type: 'SET_LABELS', labels: labels }); -} +}; diff --git a/src/components/LabelBrowser/ValuesList.js b/src/components/LabelBrowser/ValuesList.js index fb1b26d1..6e568144 100644 --- a/src/components/LabelBrowser/ValuesList.js +++ b/src/components/LabelBrowser/ValuesList.js @@ -94,6 +94,7 @@ export const ValuesList = (props) => { const onLabelValueClick = (e, value) => { e.preventDefault() value.selected = !value.selected; + value.inverted = false; onLabelValueChange(); }; diff --git a/src/components/LabelBrowser/helpers/querybuilder.js b/src/components/LabelBrowser/helpers/querybuilder.js index eee88732..81cf2d77 100644 --- a/src/components/LabelBrowser/helpers/querybuilder.js +++ b/src/components/LabelBrowser/helpers/querybuilder.js @@ -1,11 +1,17 @@ +import { setQuery } from "../../../actions"; +import store from "../../../store/store"; export function queryBuilder(labels) { const selectedLabels = []; for (const label of labels) { if (label.selected && label.values && label.values.length > 0) { const selectedValues = label.values - .filter((value) => value.selected) + .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("|")}"` @@ -13,7 +19,17 @@ export function queryBuilder(labels) { } else if (selectedValues.length === 1) { selectedLabels.push(`${label.name}="${selectedValues[0]}"`); } + invertedSelectedValues.forEach(value => { + selectedLabels.push(`${label.name}!="${value}"`) + }); + } } return ["{", selectedLabels.join(","), "}"].join(""); } +export function queryBuilderWithLabels() { + const labels = store.getState().labels; + console.log(labels) + const query = queryBuilder(labels) + store.dispatch(setQuery(query)); +} \ No newline at end of file diff --git a/src/components/LogView.js b/src/components/LogView.js index 151795fa..9cca7ae0 100644 --- a/src/components/LogView.js +++ b/src/components/LogView.js @@ -1,9 +1,15 @@ +import { ZoomIn, ZoomOut } from "@mui/icons-material/"; +import { CircularProgress, IconButton } from "@mui/material"; +import * as moment from "moment"; import React, { Component } from "react"; import { connect } from "react-redux"; -import { CircularProgress } from "@mui/material"; -import * as moment from "moment"; +import { setLabels } from "../actions"; +import loadLabelValues from '../actions/loadLabelValues'; import ClokiChart from "../plugins/charts"; +import store from "../store/store"; +import { queryBuilderWithLabels } from "./LabelBrowser/helpers/querybuilder"; +import loadLogs from "../actions/loadLogs" const TAGS_LEVEL = { critical: ['emerg', 'fatal', 'alert', 'crit', 'critical'], error: ['err', 'eror', 'error', 'warning'], @@ -13,11 +19,42 @@ const TAGS_LEVEL = { trace: ['trace'] } export const ValueTags = (props) => { - + const addLabel = async (e, key, value, isInverted = false) => { + e.preventDefault(); + e.stopPropagation(); + const {labels, apiUrl} = store.getState(); + const label = labels.find(label => label.name === key); + if (label) { + const labelValue = label.values.find(tag => tag.name === value); + if (labelValue) { + labelValue.selected = !labelValue.selected || (labelValue.inverted !== isInverted); + labelValue.inverted = !labelValue.inverted && isInverted; + label.selected = label.values.some(value => value.selected); + store.dispatch(setLabels(labels)); + } else { + await store.dispatch(loadLabelValues(label,labels,apiUrl)); + const updatedLabels = store.getState().labels; + const updatedLabel = updatedLabels.find(label => label.name === key); + const labelValue = updatedLabel.values.find(tag => tag.name === value); + labelValue.selected = !labelValue.selected || (labelValue.inverted !== isInverted); + labelValue.inverted = !labelValue.inverted && isInverted; + updatedLabel.selected = updatedLabel.values.some(value => value.selected); + store.dispatch(setLabels(updatedLabels)); + } + queryBuilderWithLabels() + store.dispatch(loadLogs()) + } + } const getTags = (tags) => { return Object.entries(tags).map( ([key, value], k) => (