+
+
+
+
+
+
+ {clusterTotal?.value}
+
+
+
+
+
+
+
+ {overview?.total_host}
+
+
+
+
+
+
+
+ {overview?.total_node}
+
+
+
+
+
+
+
+ {totalStoreSize.size || '-'}{totalStoreSize.unit}
+
+
+
+
+
{}}
@@ -31,4 +92,10 @@ const NewOverview = ()=>{
);
}
-export default NewOverview;
\ No newline at end of file
+export default connect(({
+ clusterOverview,
+ global
+})=>({
+ overview: clusterOverview.overview,
+ clusterTotal: global.clusterTotal,
+}))(NewOverview)
\ No newline at end of file
diff --git a/web/src/pages/DataManagement/Discover.jsx b/web/src/pages/DataManagement/Discover.jsx
index 48a61c16..32ea97a3 100644
--- a/web/src/pages/DataManagement/Discover.jsx
+++ b/web/src/pages/DataManagement/Discover.jsx
@@ -7,8 +7,8 @@ import React, {
createContext,
useContext,
useRef,
-} from 'react';
-import classNames from 'classnames';
+} from "react";
+import classNames from "classnames";
import {
EuiDataGrid,
@@ -25,56 +25,71 @@ import {
EuiPage,
EuiPageBody,
EuiPageContent,
-} from '@elastic/eui';
-import '@elastic/eui/dist/eui_theme_amsterdam_light.css';
-import * as styles from './discover.scss';
-import { Subscription } from 'rxjs';
-import { connect } from 'dva';
+ EuiSelect,
+} from "@elastic/eui";
+import "@elastic/eui/dist/eui_theme_amsterdam_light.css";
+import * as styles from "./discover.scss";
+import { Subscription } from "rxjs";
+import { connect } from "dva";
-import { Card, Spin, message } from 'antd';
+import { Card, Spin, message, Select, Icon, Popover } from "antd";
// import DiscoverGrid from './Components/discover_grid';
-import {flattenHitWrapper} from '../../components/kibana/data/common/index_patterns/index_patterns';
-import {getStateColumnActions} from '../../components/kibana/discover/public/application/angular/doc_table/actions/columns';
-import { DiscoverSidebar } from '../../components/kibana/discover/public/application/components/sidebar/discover_sidebar';
-import {HitsCounter } from '../../components/kibana/discover/public/application/components/hits_counter';
-import {TimechartHeader } from '../../components/kibana/discover/public/application/components/timechart_header';
-import {DiscoverHistogram} from '../../components/kibana/discover/public/application/components/histogram/histogram';
-import moment from 'moment';
-import {getContext} from './context';
-import {createSearchBar} from '../../components/kibana/data/public/ui/search_bar/create_search_bar';
-import { LoadingSpinner } from '../../components/kibana/discover/public/application/components/loading_spinner/loading_spinner';
-import { DiscoverNoResults } from '../../components/kibana/discover/public/application/angular/directives/no_results';
-import { buildPointSeriesData } from '../../components/kibana/discover/public/application/angular/helpers/';
-import {generateFilters} from '../../components/kibana/data/public/query/filter_manager/lib/generate_filters';
-import Table from '../../components/kibana/discover/public/application/components/discover_table/table';
+import { flattenHitWrapper } from "../../components/kibana/data/common/index_patterns/index_patterns";
+import { getStateColumnActions } from "../../components/kibana/discover/public/application/angular/doc_table/actions/columns";
+import { DiscoverSidebar } from "../../components/kibana/discover/public/application/components/sidebar/discover_sidebar";
+import { HitsCounter } from "../../components/kibana/discover/public/application/components/hits_counter";
+import { TimechartHeader } from "../../components/kibana/discover/public/application/components/timechart_header";
+import { DiscoverHistogram } from "../../components/kibana/discover/public/application/components/histogram/histogram";
+import moment from "moment";
+import { getContext } from "./context";
+import { createSearchBar } from "../../components/kibana/data/public/ui/search_bar/create_search_bar";
+import { LoadingSpinner } from "../../components/kibana/discover/public/application/components/loading_spinner/loading_spinner";
+import { DiscoverNoResults } from "../../components/kibana/discover/public/application/angular/directives/no_results";
+import { buildPointSeriesData } from "../../components/kibana/discover/public/application/angular/helpers/";
+import { generateFilters } from "../../components/kibana/data/public/query/filter_manager/lib/generate_filters";
+import Table from "../../components/kibana/discover/public/application/components/discover_table/table";
+import { SettingContent } from "./SettingContent";
+import TimeFieldExampleImage from "@/assets/time_field_exmaple.jpg";
+
+import {
+ useQueryParam,
+ StringParam,
+ QueryParamProvider,
+ ArrayParam,
+} from "use-query-params";
+import { Route } from "umi";
+import { ESPrefix } from "@/services/common";
-import {useQueryParam, StringParam, QueryParamProvider, ArrayParam} from 'use-query-params';
-import {Route} from 'umi';
-import {ESPrefix} from '@/services/common';
-
const SidebarMemoized = React.memo(DiscoverSidebar);
-const {filterManager, queryStringManager, timefilter, storage, getEsQuery, getSearchParams,
- intervalOptions, getTimeBuckets, fetchESRequest, services} = getContext();
+const {
+ filterManager,
+ queryStringManager,
+ timefilter,
+ storage,
+ getEsQuery,
+ getSearchParams,
+ intervalOptions,
+ getTimeBuckets,
+ fetchESRequest,
+ services,
+} = getContext();
const SearchBar = createSearchBar();
+const Discover = (props) => {
+ const [columnsParam, setColumnsParam] = useQueryParam("columns", ArrayParam);
+ const [queryParam, setQueryParam] = useQueryParam("query", StringParam);
-const Discover = (props)=>{
-
- const [columnsParam, setColumnsParam] = useQueryParam('columns', ArrayParam);
- const [queryParam, setQueryParam] = useQueryParam('query', StringParam);
-
- //const indexPatternList = [{"type":"index-pattern","id":"c7fbafd0-34a9-11eb-925f-9db57376c4ce","attributes":{"title":".monitoring-es-7-mb-*"},"references":[],"migrationVersion":{"index-pattern":"7.6.0"},"updated_at":"2020-12-02T14:34:38.010Z","version":"WzgyNCw3XQ==","namespaces":["default"],"score":0},{"type":"index-pattern","id":"861ea7f0-3a9b-11eb-9b55-45d33507027a","attributes":{"title":"mock_log*"},"references":[],"migrationVersion":{"index-pattern":"7.6.0"},"updated_at":"2020-12-10T04:09:09.044Z","version":"WzE3NTgsMTBd","namespaces":["default"],"score":0},{"type":"index-pattern","id":"1a28c950-0f6b-11eb-9512-2d0c0eda237d","attributes":{"title":"gateway_requests*"},"references":[],"migrationVersion":{"index-pattern":"7.6.0"},"updated_at":"2021-05-22T11:04:23.811Z","version":"WzkxMTgsNDhd","namespaces":["default"],"score":0},{"type":"index-pattern","id":"1ccce5c0-bb9a-11eb-957b-939add21a246","attributes":{"title":"test-custom*"},"references":[],"migrationVersion":{"index-pattern":"7.6.0"},"updated_at":"2021-05-23T07:40:14.747Z","version":"WzkxOTEsNDhd","namespaces":["default"],"score":0}];
+ //const indexPatternList = [{"type":"index-pattern","id":"c7fbafd0-34a9-11eb-925f-9db57376c4ce","attributes":{"title":".monitoring-es-7-mb-*"},"references":[],"migrationVersion":{"index-pattern":"7.6.0"},"updated_at":"2020-12-02T14:34:38.010Z","version":"WzgyNCw3XQ==","namespaces":["default"],"score":0},{"type":"index-pattern","id":"861ea7f0-3a9b-11eb-9b55-45d33507027a","attributes":{"title":"mock_log*"},"references":[],"migrationVersion":{"index-pattern":"7.6.0"},"updated_at":"2020-12-10T04:09:09.044Z","version":"WzE3NTgsMTBd","namespaces":["default"],"score":0},{"type":"index-pattern","id":"1a28c950-0f6b-11eb-9512-2d0c0eda237d","attributes":{"title":"gateway_requests*"},"references":[],"migrationVersion":{"index-pattern":"7.6.0"},"updated_at":"2021-05-22T11:04:23.811Z","version":"WzkxMTgsNDhd","namespaces":["default"],"score":0},{"type":"index-pattern","id":"1ccce5c0-bb9a-11eb-957b-939add21a246","attributes":{"title":"test-custom*"},"references":[],"migrationVersion":{"index-pattern":"7.6.0"},"updated_at":"2021-05-23T07:40:14.747Z","version":"WzkxOTEsNDhd","namespaces":["default"],"score":0}];
const [state, setState] = useState({
- columns: columnsParam||['_source'],//['name', 'address'],
- interval: 'auto',
- });
-
+ columns: columnsParam || ["_source"], //['name', 'address'],
+ interval: "auto",
+ });
// const [sort, setSort] = useState(null);
- const subscriptions = useMemo(()=>{
+ const subscriptions = useMemo(() => {
const subscriptions = new Subscription();
subscriptions.add(
timefilter.getAutoRefreshFetch$().subscribe({
@@ -84,105 +99,126 @@ const Discover = (props)=>{
})
);
return subscriptions;
- },[props.indexPattern]);
- const setIndexPattern = async (id)=>{
- const IP = await services.indexPatternService.get(id);
- subscriptions.unsubscribe();
- props.changeIndexPattern(IP);
- setState({
- ...state,
- columns: ['_source'],
- sort: [],
- })
- }
-
- //const indexPatterns = [{"id":"1ccce5c0-bb9a-11eb-957b-939add21a246","type":"index-pattern","namespaces":["default"],"updated_at":"2021-05-23T07:40:14.747Z","version":"WzkxOTEsNDhd","attributes":{"title":"test-custom*","timeFieldName":"created_at","fields":"[{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"address\"}}},{\"count\":0,\"conflictDescriptions\":{\"text\":[\"test-custom1\"],\"long\":[\"test-custom\",\"test-custom8\",\"test-custom9\"]},\"name\":\"age\",\"type\":\"conflict\",\"esTypes\":[\"text\",\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"age.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"age\"}}},{\"count\":0,\"name\":\"created_at\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"email\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"email.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"email\"}}},{\"count\":0,\"name\":\"hobbies\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"hobbies.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"hobbies\"}}},{\"count\":0,\"name\":\"id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"id\"}}},{\"count\":0,\"name\":\"name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"name\"}}}]"},"references":[],"migrationVersion":{"index-pattern":"7.6.0"}}];
- const indexPattern = props.indexPattern;
- const indexPatterns = [indexPattern];
- const indexPatternList = props.indexPatternList
- const contentCentered = false; //resultState != 'ready';
+ }, [props.indexPattern]);
+ const setIndexPattern = async (id, typ) => {
+ const IP = await services.indexPatternService.get(id, typ);
+ subscriptions.unsubscribe();
+ props.changeIndexPattern(IP);
+ setState({
+ ...state,
+ columns: ["_source"],
+ sort: [],
+ });
+ };
+ const onTimeFieldChange = async (id, timeField) => {
+ const IP = await services.indexPatternService.get(id, "index");
+ IP.timeFieldName = timeField;
+ props.changeIndexPattern(IP);
+ };
+
+ //const indexPatterns = [{"id":"1ccce5c0-bb9a-11eb-957b-939add21a246","type":"index-pattern","namespaces":["default"],"updated_at":"2021-05-23T07:40:14.747Z","version":"WzkxOTEsNDhd","attributes":{"title":"test-custom*","timeFieldName":"created_at","fields":"[{\"count\":0,\"name\":\"_id\",\"type\":\"string\",\"esTypes\":[\"_id\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_index\",\"type\":\"string\",\"esTypes\":[\"_index\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_score\",\"type\":\"number\",\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_source\",\"type\":\"_source\",\"esTypes\":[\"_source\"],\"scripted\":false,\"searchable\":false,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"_type\",\"type\":\"string\",\"esTypes\":[\"_type\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"address\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"address.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"address\"}}},{\"count\":0,\"conflictDescriptions\":{\"text\":[\"test-custom1\"],\"long\":[\"test-custom\",\"test-custom8\",\"test-custom9\"]},\"name\":\"age\",\"type\":\"conflict\",\"esTypes\":[\"text\",\"long\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":false},{\"count\":0,\"name\":\"age.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"age\"}}},{\"count\":0,\"name\":\"created_at\",\"type\":\"date\",\"esTypes\":[\"date\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true},{\"count\":0,\"name\":\"email\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"email.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"email\"}}},{\"count\":0,\"name\":\"hobbies\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"hobbies.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"hobbies\"}}},{\"count\":0,\"name\":\"id\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"id.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"id\"}}},{\"count\":0,\"name\":\"name\",\"type\":\"string\",\"esTypes\":[\"text\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":false,\"readFromDocValues\":false},{\"count\":0,\"name\":\"name.keyword\",\"type\":\"string\",\"esTypes\":[\"keyword\"],\"scripted\":false,\"searchable\":true,\"aggregatable\":true,\"readFromDocValues\":true,\"subType\":{\"multi\":{\"parent\":\"name\"}}}]"},"references":[],"migrationVersion":{"index-pattern":"7.6.0"}}];
+ const indexPattern = props.indexPattern;
+ const indexPatterns = [indexPattern];
+ const indexPatternList = props.indexPatternList;
+ const contentCentered = false; //resultState != 'ready';
+
+ indexPatterns.get = (id) => {
+ return Promise.resolve(indexPatterns.find((ip) => ip.id == id));
+ };
+ getContext().setIndexPatterns(indexPatterns);
- indexPatterns.get = (id)=>{
- return Promise.resolve(indexPatterns.find(ip=>ip.id==id));
- }
- getContext().setIndexPatterns(indexPatterns)
-
const [expandedDoc, setExpandedDoc] = useState(undefined);
const scrollableDesktop = useRef(null);
-
+
const columns = state.columns;
const updateQuery = useCallback(
async (_payload) => {
- if(!indexPattern){
- return
+ if (!indexPattern) {
+ return;
}
- setResultState('loading');
- const params = getSearchParams(_payload?.indexPattern || indexPattern, _payload?.interval || state.interval, _payload?.sort);
- const res = await fetchESRequest(params, props.selectedCluster.id)
- if(!res.hits.hits){
- res.hits.hits=[];
+ setResultState("loading");
+ const params = getSearchParams(
+ _payload?.indexPattern || indexPattern,
+ _payload?.interval || state.interval,
+ _payload?.sort
+ );
+ const res = await fetchESRequest(params, props.selectedCluster.id);
+ if (!res.hits.hits) {
+ res.hits.hits = [];
}
setSearchRes(res);
- const {query} = queryStringManager.getQuery();
- if(query != queryParam){
+ const { query } = queryStringManager.getQuery();
+ if (query != queryParam) {
setQueryParam(query);
}
// let filters = filterManager.getFilters();
// const tfilter = timefilter.createFilter(indexPattern);
// filters = [...filterManager.getFilters(), ...(tfilter ? [tfilter] : [])],
-
+
// console.log(filters)
// console.log(res)
//console.log(JSON.stringify(params));
- //console.log(getEsQuery(indexPattern))
+ // console.log(getEsQuery(indexPattern));
+ // console.log(timefilter.createFilter(indexPattern));
},
- [indexPattern, state.interval,]
+ [indexPattern, state.interval]
);
const onChangeInterval = useCallback(
(interval) => {
if (interval) {
//console.log(calculateInterval(interval))
- setState({...state, interval });
+ setState({ ...state, interval });
}
},
[setState, indexPattern]
);
- const [searchRes, setSearchRes] = useState(
- {"took":11,"timed_out":false,"_shards":{"total":4,"successful":4,"skipped":3,"failed":0},"hits":{"total":0,"max_score":null,"hits":[]},"aggregations":{"2":{"buckets":[]}}}
- );
+ const [searchRes, setSearchRes] = useState({
+ took: 11,
+ timed_out: false,
+ _shards: { total: 4, successful: 4, skipped: 3, failed: 0 },
+ hits: { total: 0, max_score: null, hits: [] },
+ aggregations: { "2": { buckets: [] } },
+ });
-
- const [resultState, setResultState] = useState('loading');
- const {histogramData, timeChartProps} = useMemo(()=>{
- if(!searchRes.hits.hits || searchRes.hits.hits.length == 0){
- setResultState('none');
+ const [resultState, setResultState] = useState("loading");
+ const { histogramData, timeChartProps } = useMemo(() => {
+ if (!searchRes.hits.hits || searchRes.hits.hits.length == 0) {
+ setResultState("none");
return {};
}
- if(!indexPattern.timeFieldName || !searchRes.aggregations){
- setResultState('ready');
- return {histogramData:null, timeChartProps:null}
+ if (!indexPattern.timeFieldName || !searchRes.aggregations) {
+ setResultState("ready");
+ return { histogramData: null, timeChartProps: null };
}
const buckets = getTimeBuckets(state.interval);
const interval = buckets.getInterval(true);
const chartTable = {
- columns: [{id:"key", name: `${indexPattern?.getTimeField().displayName} per ${interval.description}`},{id:"doc_count", name:"count"}],
+ columns: [
+ {
+ id: "key",
+ name: `${indexPattern?.getTimeField().displayName} per ${
+ interval.description
+ }`,
+ },
+ { id: "doc_count", name: "count" },
+ ],
rows: [],
};
let aggregations = searchRes.aggregations;
-
- aggregations["2"].buckets.forEach((bk)=>{
+
+ aggregations["2"].buckets.forEach((bk) => {
chartTable.rows.push(bk);
- })
-
+ });
+
//console.log(interval, moment.duration('1', 'd'))
const dimensions = {
x: {
accessor: 0,
format: {
- id: 'date',
+ id: "date",
params: {
pattern: buckets.getScaledDateFormat(),
//pattern: 'YYYY-MM-DD',
@@ -190,7 +226,7 @@ const Discover = (props)=>{
},
params: {
date: true,
- interval: moment.duration(interval.esValue, interval.esUnit),
+ interval: moment.duration(interval.esValue, interval.esUnit),
intervalESValue: interval.esValue,
intervalESUnit: interval.esUnit,
bounds: buckets.getBounds(),
@@ -199,12 +235,12 @@ const Discover = (props)=>{
y: {
accessor: 1,
format: {
- id: 'number',
+ id: "number",
},
- label: 'Count',
- }
+ label: "Count",
+ },
};
- setResultState('ready');
+ setResultState("ready");
const timeChartProps = {
timeRange: {
from: timefilter.getBounds().min,
@@ -217,30 +253,35 @@ const Discover = (props)=>{
// scaled: true,
// description: 'day',
// scale: undefined,
- ...interval
+ ...interval,
+ timeFieldName: indexPattern.timeFieldName,
},
- }
+ };
const histogramData = buildPointSeriesData(chartTable, dimensions);
- return {histogramData, timeChartProps}
- }, [searchRes, indexPattern])
+ return { histogramData, timeChartProps };
+ }, [searchRes, indexPattern, indexPattern.timeFieldName]);
- const setAppState = (newState)=>{
- if(state.columns[0] === '_source' || newState.columns[0] === '_source' || (state.columns.length != newState.columns.length)){
+ const setAppState = (newState) => {
+ if (
+ state.columns[0] === "_source" ||
+ newState.columns[0] === "_source" ||
+ state.columns.length != newState.columns.length
+ ) {
setColumnsParam(newState.columns);
}
- setState(newState)
- }
-
+ setState(newState);
+ };
+
const { onAddColumn, onRemoveColumn, onMoveColumn, onSetColumns } = useMemo(
() =>
getStateColumnActions({
indexPattern,
- indexPatterns:[indexPattern],
+ indexPatterns: [indexPattern],
setAppState: setAppState,
state,
- useNewFieldsApi:false,
+ useNewFieldsApi: false,
}),
- [indexPattern,state]
+ [indexPattern, state]
);
const collapseIcon = useRef(null);
@@ -250,18 +291,19 @@ const Discover = (props)=>{
}, [state]);
const hideChart = useMemo(() => state.hideChart, [state]);
const [isSidebarClosed, setIsSidebarClosed] = useState(false);
- const useNewFieldsApi = false
-
+ const useNewFieldsApi = false;
+
const onSort = useCallback(
(nsort) => {
- setState({...state, sort: nsort})
- updateQuery({sort: nsort});
- },[state, indexPattern]
+ setState({ ...state, sort: nsort });
+ updateQuery({ sort: nsort });
+ },
+ [state, indexPattern]
);
const onAddFilter = useCallback(
(field, values, operation) => {
- const fieldName = typeof field === 'string' ? field : field.name;
+ const fieldName = typeof field === "string" ? field : field.name;
const newFilters = generateFilters(
filterManager,
field,
@@ -270,7 +312,7 @@ const Discover = (props)=>{
String(indexPattern.id)
);
filterManager.addFilters(newFilters);
- updateQuery()
+ updateQuery();
},
[indexPattern]
);
@@ -281,96 +323,110 @@ const Discover = (props)=>{
timefilter.setTime({
from: moment(ranges.from).toISOString(),
to: moment(ranges.to).toISOString(),
- mode: 'absolute',
+ mode: "absolute",
});
},
[timefilter]
);
- const rows = searchRes.hits.hits;
-
+ const rows = searchRes.hits.hits;
- const opts = {
- savedSearch:{},
- timefield: indexPattern?.getTimeField()?.displayName,
- chartAggConfigs: {},
- };
- const fieldCounts = {};
- for (const hit of rows) {
- for (const key of Object.keys(indexPattern.flattenHit(hit, true))) {
- fieldCounts[key] = (fieldCounts[key] || 0) + 1;
- }
+ const opts = {
+ savedSearch: {},
+ timefield: indexPattern?.getTimeField()?.displayName,
+ chartAggConfigs: {},
+ };
+ const fieldCounts = {};
+ for (const hit of rows) {
+ for (const key of Object.keys(indexPattern.flattenHit(hit, true))) {
+ fieldCounts[key] = (fieldCounts[key] || 0) + 1;
}
- const hits = searchRes.hits.total?.value || searchRes.hits.total;
- const resetQuery = ()=>{};
- const showDatePicker = indexPattern.timeFieldName != "";
+ }
+ const hits = searchRes.hits.total?.value || searchRes.hits.total;
+ const resetQuery = () => {};
+ const showDatePicker = indexPattern.timeFieldName != "";
- const saveDocument = useCallback(async ({_index, _id, _type, _source, is_new})=>{
- const {http} = getContext();
- const res = await http.put(`/elasticsearch/${props.selectedCluster.id}/doc/${_index}/${_id}`, {
- prependBasePath: false,
- query: {
- _type,
- is_new,
- },
- body: JSON.stringify(_source),
- });
- if(res.error){
- message.error(res.error)
- return res
- }
- message.success('saved successfully');
- updateQuery()
- return res;
- },[props.selectedCluster, updateQuery])
-
- const deleteDocument = useCallback(async ({_index, _id, _type})=>{
- const {http} = getContext();
- const res = await http.delete(`/elasticsearch/${props.selectedCluster.id}/doc/${_index}/${_id}`, {
- prependBasePath: false,
- query: {
- _type,
+ const saveDocument = useCallback(
+ async ({ _index, _id, _type, _source, is_new }) => {
+ const { http } = getContext();
+ const res = await http.put(
+ `/elasticsearch/${props.selectedCluster.id}/doc/${_index}/${_id}`,
+ {
+ prependBasePath: false,
+ query: {
+ _type,
+ is_new,
+ },
+ body: JSON.stringify(_source),
}
- });
- if(res.error){
- message.error(res.error)
- return res
- }
- message.success('deleted successfully');
- updateQuery()
- return res
- },[props.selectedCluster, updateQuery])
-
- return (
-
-
+ );
+ if (res.error) {
+ message.error(res.error);
+ return res;
+ }
+ message.success("saved successfully");
+ updateQuery();
+ return res;
+ },
+ [props.selectedCluster, updateQuery]
+ );
-
-
- {indexPattern &&
+ const deleteDocument = useCallback(
+ async ({ _index, _id, _type }) => {
+ const { http } = getContext();
+ const res = await http.delete(
+ `/elasticsearch/${props.selectedCluster.id}/doc/${_index}/${_id}`,
+ {
+ prependBasePath: false,
+ query: {
+ _type,
+ },
+ }
+ );
+ if (res.error) {
+ message.error(res.error);
+ return res;
+ }
+ message.success("deleted successfully");
+ updateQuery();
+ return res;
+ },
+ [props.selectedCluster, updateQuery]
+ );
+
+ const [settingsVisible, setSettingsVisible] = React.useState(false);
+
+ return (
+
+
+
+
+
+ {indexPattern && (
+
{
isClosed={isSidebarClosed}
//unmappedFieldsConfig={unmappedFieldsConfig}
//useNewFieldsApi={useNewFieldsApi}
+ indices={props.indices}
/>
- }
-
-
- setIsSidebarClosed(!isSidebarClosed)}
- data-test-subj="collapseSideBarButton"
- aria-controls="discover-sidebar"
- aria-expanded={isSidebarClosed ? 'false' : 'true'}
- aria-label={'Toggle sidebar'}
- buttonRef={collapseIcon}
- />
-
-
- {resultState === 'none' && (
-
- )}
- {resultState !== 'none' && (
-
+
+ )}
+
+
+ {
+ setIsSidebarClosed(!isSidebarClosed);
+ setTimeout(() => {
+ window.dispatchEvent(new Event("resize"));
+ }, 50);
+ }}
+ data-test-subj="collapseSideBarButton"
+ aria-controls="discover-sidebar"
+ aria-expanded={isSidebarClosed ? "false" : "true"}
+ aria-label={"Toggle sidebar"}
+ buttonRef={collapseIcon}
+ />
+
+
+ {resultState === "none" && (
+
+ )}
+ {resultState !== "none" && (
+
-
+ {/* todo add settings icon */}
+ {props.timeFields.length > 0 && (
+
{
+ setSettingsVisible(!settingsVisible);
+ }}
+ >
+
+
+ )}
+ {settingsVisible ? (
+
{
+ setSettingsVisible(visible);
+ }}
+ onTimeFieldChange={onTimeFieldChange}
+ />
+ ) : null}
+
{/* {resultState === 'loading' && } */}
- { (
+ {
{
gutterSize="none"
responsive={false}
>
- {hits > 0 &&
-
- 0 && (
+
+ {/*
- 0 ? hits : 0}
- showResetButton={!!(opts.savedSearch && opts.savedSearch.id)}
- onResetQuery={resetQuery}
- />
-
-
-
- {!hideChart && (
-
-
+ 0 ? hits : 0}
+ showResetButton={
+ !!(opts.savedSearch && opts.savedSearch.id)
+ }
+ onResetQuery={resetQuery}
/>
- )}
-
- }
- {!hideChart && opts.timefield && (
-
- */}
+
+
- {opts.chartAggConfigs && histogramData && rows.length !== 0 && (
-
- 0 ? hits : 0}
+ dateFormat={"YYYY-MM-DD H:mm"}
+ {...timeChartProps}
+ />
+
+ {props.timeFields.length > 0 &&
+ indexPattern.timeFieldName == "" && (
+
+
+ Click the button of right corner to select a
+ time field
+
+
)}
+
+ )}
+ {!hideChart && opts.timefield && (
+
+
+ {opts.chartAggConfigs &&
+ histogramData &&
+ rows.length !== 0 && (
+
+
+
+ )}
@@ -491,131 +609,187 @@ const Discover = (props)=>{
ref={scrollableDesktop}
tabIndex={-1}
>
-
- Documents
+
+ Documents
-
- {(rows && rows.length > 0) ? (
+
+ {rows && rows.length > 0 ? (
- {/*
*/}
-
+ document={{ saveDocument, deleteDocument }}
+ hits={rows}
+ />
- ):null}
+ ) : null}
- )}
+ }
- )}
-
-
-
+
+ )}
+
+
+
);
-}
+};
-const DiscoverUI = (props)=>{
- const [viewID, setViewID] = useQueryParam('viewID', StringParam);
- const [queryParam, setQueryParam] = useQueryParam('query', StringParam);
+const DiscoverUI = (props) => {
+ const [viewID, setViewID] = useQueryParam("viewID", StringParam);
+ const [index, setIndex] = useQueryParam("index", StringParam);
+ // const [type, setType] = useQueryParam('type', StringParam);
+ const [queryParam, setQueryParam] = useQueryParam("query", StringParam);
const [state, setState] = useState({
+ indices: [],
+ timeFields: [],
});
- useMemo(()=>{
- const {http} = getContext();
- http.getServerBasePath = ()=>{
- return `${ESPrefix}/`+ props.selectedCluster.id;
- }
- }, [props.selectedCluster])
- useEffect(()=>{
- if(queryParam){
+ useMemo(() => {
+ const { http } = getContext();
+ http.getServerBasePath = () => {
+ return `${ESPrefix}/` + props.selectedCluster.id;
+ };
+ }, [props.selectedCluster]);
+
+ const getTimeFields = (IP) => {
+ const timeFields = [];
+ IP.fields.forEach((field) => {
+ if (field.spec.type == "date") {
+ timeFields.push(field.displayName);
+ }
+ });
+ return timeFields;
+ };
+ useEffect(() => {
+ if (queryParam) {
queryStringManager.setQuery({
query: queryParam,
- language: 'kuery'
+ language: "kuery",
});
}
- const {http} = getContext();
- const initialFetch = async ()=>{
+ const { http } = getContext();
+ const initialFetch = async () => {
+ const indices = await http.fetch(
+ http.getServerBasePath() + "/_cat/indices"
+ );
+ const indexNames = Object.keys(indices); //.filter(key=>!key.startsWith("."));
const ils = await services.savedObjects.savedObjectsClient.find({
- type: 'index-pattern',
- fields: ['title'],
- search:'',
- searchFields: ['title'],
+ type: "view",
+ fields: ["title"],
+ search: "",
+ searchFields: ["title"],
perPage: 100,
});
- if(ils.length === 0){
- props.history.push('/data/views/');
- return
+
+ if (ils.length === 0 && indexNames.length === 0) {
+ props.history.push("/data/views/");
+ return;
}
- const defaultIndex = viewID || await http.fetch(http.getServerBasePath()+'/setting/defaultIndex')
- const targetIndex = ils.filter(il=>il.id == defaultIndex);
- const defaultIP = await services.indexPatternService.get(targetIndex.length > 0 ? defaultIndex : ils[0]?.id)
+ let defaultIndex = viewID;
+ let defaultIP = null;
+ if (indexNames.includes(index)) {
+ defaultIP = await services.indexPatternService.get(
+ index,
+ "index",
+ props.selectedCluster.id
+ );
+ } else {
+ if (ils.length > 0) {
+ defaultIndex =
+ viewID ||
+ (await http.fetch(
+ http.getServerBasePath() + "/setting/defaultIndex"
+ ));
+ let targetIndex = ils.filter((il) => il.id == defaultIndex);
+ defaultIP = await services.indexPatternService.get(
+ targetIndex.length > 0 ? defaultIndex : ils[0]?.id
+ );
+ if (targetIndex.length === 0) {
+ setViewID(ils[0]?.id);
+ }
+ } else {
+ defaultIP = await services.indexPatternService.get(
+ indexNames[0],
+ "index"
+ );
+ setIndex(indexNames[0]);
+ }
+ }
+ const timeFields = getTimeFields(defaultIP);
setState({
indexPatternList: ils,
- indexPattern: defaultIP
+ indexPattern: defaultIP,
+ indices: indexNames,
+ timeFields,
});
- if(!viewID){
- setViewID(defaultIP.id);
- }
- }
+ // if (!viewID) {
+ // setViewID(defaultIP.id);
+ // }
+ };
initialFetch();
// return ()=>{
// queryStringManager.setQuery('');
// }
- },[props.selectedCluster]);
+ }, [props.selectedCluster]);
- function changeIndexPattern(indexPattern){
- setState({
- ...state,
- indexPattern,
- });
- setViewID(indexPattern.id);
- }
-
- return (
- state.indexPatternList && state.indexPatternList.length > 0 ?
- :
- )
-}
+ const changeIndexPattern = React.useCallback(
+ (indexPattern) => {
+ const timeFields = getTimeFields(indexPattern);
+ setState({
+ ...state,
+ indexPattern,
+ timeFields,
+ });
+ if (indexPattern.type == "index") {
+ setIndex(indexPattern.id);
+ setViewID(undefined);
+ } else {
+ setViewID(indexPattern.id);
+ setIndex(undefined);
+ }
+ },
+ [state]
+ );
-const DiscoverContainer = (props)=>{
- if(props.selectedCluster.id == ""){
+ return (state.indexPatternList && state.indexPatternList.length > 0) ||
+ state.indices.length > 0 ? (
+
+ ) : (
+
+
+
+ );
+};
+
+const DiscoverContainer = (props) => {
+ if (props.selectedCluster.id == "") {
return null;
}
- return
-
-
-}
+ return (
+
+
+
+ );
+};
-export default connect(({
- global
-})=>({
+export default connect(({ global }) => ({
selectedCluster: global.selectedCluster,
-}))(DiscoverContainer)
\ No newline at end of file
+}))(DiscoverContainer);
diff --git a/web/src/pages/DataManagement/Index.js b/web/src/pages/DataManagement/Index.js
index 0e0f5f10..32d63b5c 100644
--- a/web/src/pages/DataManagement/Index.js
+++ b/web/src/pages/DataManagement/Index.js
@@ -135,12 +135,7 @@ class Index extends PureComponent {
title: '索引名称',
dataIndex: 'index',
render: (text, record) => (
- {
- this.setState({
- editingIndex: record,
- drawerVisible: true,
- });
- }}>{text}
+ {text}
)
},
{
@@ -162,8 +157,13 @@ class Index extends PureComponent {
title: '操作',
render: (text, record) => (
- {/* this.handleUpdateModalVisible(true, record)}>设置
- */}
+ {
+ this.setState({
+ editingIndex: record,
+ drawerVisible: true,
+ });
+ }}>设置
+
this.handleDeleteClick(record.index)}>
删除
diff --git a/web/src/pages/DataManagement/SettingContent.jsx b/web/src/pages/DataManagement/SettingContent.jsx
new file mode 100644
index 00000000..433daa93
--- /dev/null
+++ b/web/src/pages/DataManagement/SettingContent.jsx
@@ -0,0 +1,98 @@
+import { EuiToolTip, EuiSelect, EuiIconTip } from "@elastic/eui";
+import { useOnClickOutside } from "@/lib/hooks/use_click_outsize";
+import { useEffect, useState } from "react";
+
+export const SettingContent = ({
+ onVisibleChange,
+ bucketInterval = {},
+ options = [],
+ onChangeInterval,
+ stateInterval,
+ indexPattern,
+ timeFields,
+ onTimeFieldChange,
+}) => {
+ const [interval, setInterval] = useState(stateInterval);
+ useEffect(() => {
+ setInterval(stateInterval);
+ }, [stateInterval]);
+
+ const [settingRef] = useOnClickOutside(() => {
+ if (typeof onVisibleChange == "function") {
+ onVisibleChange(false);
+ }
+ });
+
+ const handleIntervalChange = (e) => {
+ setInterval(e.target.value);
+ onChangeInterval(e.target.value);
+ };
+
+ return (
+
+
+
+
Time Field
+
+ {
+ return {
+ value: tf,
+ text: tf,
+ };
+ })}
+ onChange={(e) => {
+ onTimeFieldChange(indexPattern.id, e.target.value);
+ }}
+ />
+
+
+ {indexPattern.timeFieldName ? (
+
+
Time Interval
+
+ val !== "custom")
+ .map(({ display, val }) => {
+ return {
+ text: display,
+ value: val,
+ label: display,
+ };
+ })}
+ value={interval}
+ onChange={handleIntervalChange}
+ append={
+ bucketInterval.scaled ? (
+ 1
+ ? "buckets that are too large"
+ : "too many buckets"
+ } to show in the selected time range, so it has been scaled to ${
+ bucketInterval.description
+ }.`}
+ color="warning"
+ size="s"
+ type="alert"
+ />
+ ) : (
+ undefined
+ )
+ }
+ />
+
+
+ ) : null}
+
+
+ );
+};
diff --git a/web/src/pages/DataManagement/discover.scss b/web/src/pages/DataManagement/discover.scss
index 691e54bd..221aca2a 100644
--- a/web/src/pages/DataManagement/discover.scss
+++ b/web/src/pages/DataManagement/discover.scss
@@ -21,17 +21,18 @@
.dscPageContent__wrapper {
padding: 0 5 5 0;
overflow: hidden; // Ensures horizontal scroll of table
- box-shadow: 0 2px 2px -1px rgb(152 162 179 / 30%), 0 1px 5px -2px rgb(152 162 179 / 30%);
+ box-shadow: 0 2px 2px -1px rgb(152 162 179 / 30%),
+ 0 1px 5px -2px rgb(152 162 179 / 30%);
// border: 1px solid #D3DAE6;
- border-radius: 4px;
- flex-grow: 1;
+ border-radius: 4px;
+ flex-grow: 1;
}
.dscPageContent {
//border: $euiBorderThin;
// text-align: center;
box-shadow: none !important;
- .euiDataGrid--fullScreen{
+ .euiDataGrid--fullScreen {
z-index: 801;
}
position: relative;
@@ -57,7 +58,7 @@
// SASSTODO: the visualizing component should have an option or a modifier
.series > rect {
- fill-opacity: .5;
+ fill-opacity: 0.5;
stroke-width: 1;
}
}
@@ -75,23 +76,24 @@
// padding: 5 5 0 5;
// }
.euiDataGrid--headerUnderline .euiDataGridHeaderCell {
- border-bottom: 1px solid #D3DAE6 !important;
+ border-bottom: 1px solid #d3dae6 !important;
border-top: none !important;
}
-.dscSidebar{
- .euiButton--text, .euiButton--text:hover{
+.dscSidebar {
+ .euiButton--text,
+ .euiButton--text:hover {
background-color: #fff;
}
}
-.sidebar-list{
+.sidebar-list {
max-width: 200px;
}
.euiSuperUpdateButton.euiButton--success {
- background-color: #017D73 !important;
- border-color: #017D73 !important;
- color: #FFF !important;
+ background-color: #017d73 !important;
+ border-color: #017d73 !important;
+ color: #fff !important;
border-radius: 0 !important;
}
@@ -109,6 +111,64 @@
background-color: transparent;
}
-.kbnQueryBar__wrap{
+.kbnQueryBar__wrap {
box-shadow: none;
-}
\ No newline at end of file
+}
+
+.dscSetting {
+ position: absolute;
+ right: 0px;
+ top: 0;
+ &.setting-icon {
+ cursor: pointer;
+ padding: 0 4px;
+ &:hover {
+ background-color: #d3dae6;
+ }
+ }
+ &.setting-content {
+ background-color: #fff;
+ box-shadow: 0 2px 8px rgb(0 0 0 / 15%);
+ width: 300px;
+ max-height: 200px;
+ overflow-y: scroll;
+ z-index: 2;
+ .setting-wrapper {
+ padding: 10px;
+ }
+ .setting-row {
+ display: flex;
+ align-items: center;
+ margin-bottom: 10px;
+ &:last-child {
+ margin-bottom: 0;
+ }
+ .label {
+ // font-size: 12px;
+ width: 90px;
+ flex: none;
+ text-align: right;
+ margin-right: 5px;
+ }
+ }
+ }
+}
+
+.fake-chart {
+ position: relative;
+ .fake-mask {
+ position: absolute;
+ left: 0;
+ top: 0;
+ bottom: 0;
+ z-index: 1;
+ right: 0;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ color: #fff;
+ font-size: 24px;
+ font-weight: 600;
+ background-color: rgba($color: #000000, $alpha: 0.15);
+ }
+}
diff --git a/web/src/pages/DevTool/Console.tsx b/web/src/pages/DevTool/Console.tsx
index c4d08384..72b423c2 100644
--- a/web/src/pages/DevTool/Console.tsx
+++ b/web/src/pages/DevTool/Console.tsx
@@ -1,25 +1,40 @@
-import Console from '../../components/kibana/console/components/Console';
-import {connect} from 'dva';
-import {Button, Icon, Menu, Dropdown, } from 'antd';
-import Tabs from '@/components/infini/tabs';
-import {DraggableTabs} from '@/components/infini/tabs/DraggableTabs';
-import {useState, useReducer, useCallback, useEffect, useMemo, useRef, useLayoutEffect} from 'react';
-import {useLocalStorage} from '@/lib/hooks/storage';
-import {setClusterID} from '../../components/kibana/console/modules/mappings/mappings';
-import {TabTitle} from './console_tab_title';
-import '@/assets/utility.scss';
+import Console from "../../components/kibana/console/components/Console";
+import { connect } from "dva";
+import { Button, Icon, Menu, Dropdown } from "antd";
+import Tabs from "@/components/infini/tabs";
+import { DraggableTabs } from "@/components/infini/tabs/DraggableTabs";
+import {
+ useState,
+ useReducer,
+ useCallback,
+ useEffect,
+ useMemo,
+ useRef,
+ useLayoutEffect,
+} from "react";
+import { useLocalStorage } from "@/lib/hooks/storage";
+import { setClusterID } from "../../components/kibana/console/modules/mappings/mappings";
+import { TabTitle } from "./console_tab_title";
+import "@/assets/utility.scss";
import { Resizable } from "re-resizable";
-import {ResizeBar} from '@/components/infini/resize_bar';
-import NewTabMenu from './NewTabMenu';
+import { ResizeBar } from "@/components/infini/resize_bar";
+import NewTabMenu from "./NewTabMenu";
+
+import maximizeSvg from "@/assets/window-maximize.svg";
+import restoreSvg from "@/assets/window-restore.svg";
+
+const MaximizeIcon = (props = {}) => {
+ return
;
+};
+const RestoreIcon = (props = {}) => {
+ return
;
+};
const { TabPane } = Tabs;
-const TabConsole = (props:any)=>{
- return (
-
- )
-}
-
+const TabConsole = (props: any) => {
+ return ;
+};
// export default connect(({
// global
@@ -29,331 +44,381 @@ const TabConsole = (props:any)=>{
const addTab = (state: any, action: any) => {
const { panes } = state;
- const {cluster} = action.payload;
+ const { cluster } = action.payload;
const activeKey = `${cluster.id}:${new Date().valueOf()}`;
- panes.push({ key: activeKey, cluster_id: cluster.id, title: cluster.name});
+ panes.push({ key: activeKey, cluster_id: cluster.id, title: cluster.name });
return {
...state,
panes,
activeKey,
- }
-}
-const removeTab = (state: any, action: any) =>{
+ };
+};
+const removeTab = (state: any, action: any) => {
const { activeKey, panes } = state;
- const {targetKey} = action.payload;
- const newPanes = panes.filter(pane => pane.key !== targetKey);
+ const { targetKey } = action.payload;
+
+ const newPanes = panes.filter((pane) => pane.key !== targetKey);
return {
...state,
panes: newPanes,
- activeKey: panes[0]?.key,
- }
-}
+ activeKey: activeKey == targetKey ? newPanes[0]?.key : activeKey,
+ };
+};
const consoleTabReducer = (state: any, action: any) => {
- const {type, payload} = action;
+ const { type, payload } = action;
let newState = state;
- switch(type){
- case 'add':
+ switch (type) {
+ case "add":
newState = addTab(state, action);
break;
- case 'remove':
- newState = removeTab(state, action);
+ case "remove":
+ newState = removeTab(state, action);
break;
- case 'change':
+ case "change":
newState = {
...state,
activeKey: payload.activeKey,
- }
+ };
break;
- case 'saveTitle':
- const {key, title} = action.payload;
- const newPanes = state.panes.map((pane: any)=>{
- if(pane.key == key){
+ case "saveTitle":
+ const { key, title } = action.payload;
+ const newPanes = state.panes.map((pane: any) => {
+ if (pane.key == key) {
return {
...pane,
title,
- }
+ };
}
return pane;
});
newState = {
...state,
panes: newPanes,
- }
+ };
break;
- case 'saveContent':
- const panes = state.panes.map((pane)=>{
- if(pane.key == state.activeKey){
+ case "saveContent":
+ const panes = state.panes.map((pane) => {
+ if (pane.key == state.activeKey) {
return {
...pane,
content: action.payload.content,
- }
+ };
}
return pane;
});
- newState = ({
+ newState = {
...state,
panes,
- });
+ };
break;
- case 'saveOrder':
- newState = ({
+ case "saveOrder":
+ newState = {
...state,
order: action.payload.order,
- });
+ };
default:
}
// setLocalState(newState);
return newState;
-}
+};
-function calcHeightToPX(height: string){
- const intHeight = parseInt(height)
- if(height.endsWith('vh')){
- return Math.max(document.documentElement.clientHeight || 0, window.innerHeight || 0) * intHeight / 100;
- }else{
+function calcHeightToPX(height: string) {
+ const intHeight = parseInt(height);
+ if (height.endsWith("vh")) {
+ return (
+ (Math.max(
+ document.documentElement.clientHeight || 0,
+ window.innerHeight || 0
+ ) *
+ intHeight) /
+ 100
+ );
+ } else {
return intHeight;
}
}
-export const ConsoleUI = ({selectedCluster,
- clusterList,
- clusterStatus,
- minimize=false,
+export const ConsoleUI = ({
+ selectedCluster,
+ clusterList,
+ clusterStatus,
+ minimize = false,
onMinimizeClick,
- resizeable=false,
- height='50vh'
-}: any)=>{
- const clusterMap = useMemo(()=>{
+ resizeable = false,
+ height = "50vh",
+}: any) => {
+ const clusterMap = useMemo(() => {
let cm = {};
- if(!clusterStatus){
+ if (!clusterStatus) {
return cm;
}
- (clusterList || []).map((cluster: any)=>{
+ (clusterList || []).map((cluster: any) => {
cluster.status = clusterStatus[cluster.id]?.health?.status;
- if(!clusterStatus[cluster.id]?.available){
- cluster.status = 'unavailable';
- }
+ if (!clusterStatus[cluster.id]?.available) {
+ cluster.status = "unavailable";
+ }
cm[cluster.id] = cluster;
});
return cm;
- }, [clusterList, clusterStatus])
- const initialDefaultState = ()=>{
+ }, [clusterList, clusterStatus]);
+ const initialDefaultState = () => {
let defaultCluster = selectedCluster;
- if(!defaultCluster.id){
- defaultCluster = clusterList[0] ;
+ if (!defaultCluster.id) {
+ defaultCluster = clusterList[0];
}
- const defaultActiveKey = `${defaultCluster.id || ''}:${new Date().valueOf()}`;
- const defaultState = defaultCluster? {
- panes:[{
- key: defaultActiveKey, cluster_id: defaultCluster.id, title: defaultCluster.name
- }],
- activeKey: defaultActiveKey,
- }: {panes:[],activeKey:''};
- return defaultState
- }
-
- const [localState, setLocalState, removeLocalState] = useLocalStorage("console:state", initialDefaultState, {
- encode: JSON.stringify,
- decode: JSON.parse,
- })
- const [tabState, dispatch] = useReducer(consoleTabReducer, localState)
-
- useEffect(()=>{
- if(tabState.panes.length == 0){
- removeLocalState()
- return
- }
- setLocalState(tabState)
- }, [tabState])
-
- const saveEditorContent = useCallback((content)=>{
- dispatch({
- type: 'saveContent',
- payload: {
- content
- }
- })
- }, [dispatch])
-
- const onChange = (activeKey:string) => {
- dispatch({
- type: 'change',
- payload: {
- activeKey
- }
- })
+ const defaultActiveKey = `${defaultCluster.id ||
+ ""}:${new Date().valueOf()}`;
+ const defaultState = defaultCluster
+ ? {
+ panes: [
+ {
+ key: defaultActiveKey,
+ cluster_id: defaultCluster.id,
+ title: defaultCluster.name,
+ },
+ ],
+ activeKey: defaultActiveKey,
+ }
+ : { panes: [], activeKey: "" };
+ return defaultState;
};
- const onEdit = (targetKey: string | React.MouseEvent, action:string) => {
+ const [localState, setLocalState, removeLocalState] = useLocalStorage(
+ "console:state",
+ initialDefaultState,
+ {
+ encode: JSON.stringify,
+ decode: JSON.parse,
+ }
+ );
+ const [tabState, dispatch] = useReducer(consoleTabReducer, localState);
+
+ useEffect(() => {
+ if (tabState.panes.length == 0) {
+ removeLocalState();
+ return;
+ }
+ setLocalState(tabState);
+ }, [tabState]);
+
+ const saveEditorContent = useCallback(
+ (content) => {
+ dispatch({
+ type: "saveContent",
+ payload: {
+ content,
+ },
+ });
+ },
+ [dispatch]
+ );
+
+ const onChange = (activeKey: string) => {
+ dispatch({
+ type: "change",
+ payload: {
+ activeKey,
+ },
+ });
+ };
+
+ const onEdit = (
+ targetKey: string | React.MouseEvent,
+ action: string
+ ) => {
dispatch({
type: action,
payload: {
targetKey,
- }
- })
+ },
+ });
};
- const newTabClick = useCallback((param: any)=>{
- const cluster = clusterList.find(item=>item.id == param.id);
- if(!cluster){
- console.log('cluster not found')
- return;
- }
- dispatch({
- type:'add',
- payload: {
- cluster,
+ const newTabClick = useCallback(
+ (param: any) => {
+ const cluster = clusterList.find((item) => item.id == param.id);
+ if (!cluster) {
+ console.log("cluster not found");
+ return;
}
- })
- },[clusterList])
-
- const menu = (
- //
-
+ dispatch({
+ type: "add",
+ payload: {
+ cluster,
+ },
+ });
+ },
+ [clusterList]
);
-
+
+ // const menu = (
+ // //
+ //
+ // );
+
const rootRef = useRef(null);
const [isFullscreen, setIsFullscreen] = useState(false);
- const fullscreenClick = ()=>{
- if(rootRef.current != null){
- if(!isFullscreen){
+ const fullscreenClick = () => {
+ if (rootRef.current != null) {
+ if (!isFullscreen) {
rootRef.current.className = rootRef.current.className + " fullscreen";
// rootRef.current.style.overflow = 'scroll';
- }else{
- rootRef.current.className = rootRef.current.className.replace(' fullscreen', '');
+ } else {
+ rootRef.current.className = rootRef.current.className.replace(
+ " fullscreen",
+ ""
+ );
}
}
- setEditorHeight(rootRef.current.clientHeight)
- setIsFullscreen(!isFullscreen)
- }
+ setEditorHeight(rootRef.current.clientHeight);
+ setIsFullscreen(!isFullscreen);
+ };
- const tabBarExtra ={
- left:
- {minimize? :null}
-
,
- right:(
-
- {isFullscreen?
-
:
-
- }
+ const tabBarExtra = {
+ left: (
+
+ {minimize ? : null}
- ),
- append:(
-
-
-
-
-
- )
-};
+ ),
+ right: (
+ <>
+
+ {minimize ? : null}
+
+
+ {isFullscreen ? : }
+
+ >
+ ),
+ append: (
+
+
+
+
+
+ ),
+ };
- setClusterID(tabState.activeKey?.split(':')[0]);
- const panes = tabState.panes.filter((pane: any)=>{
- return typeof clusterMap[pane.cluster_id] != 'undefined';
- })
+ setClusterID(tabState.activeKey?.split(":")[0]);
+ const panes = tabState.panes.filter((pane: any) => {
+ return typeof clusterMap[pane.cluster_id] != "undefined";
+ });
- const saveTitle = (key: string, title: string)=>{
+ const saveTitle = (key: string, title: string) => {
dispatch({
- type:'saveTitle',
+ type: "saveTitle",
payload: {
key,
title,
- }
- })
- }
- const [editorHeight, setEditorHeight] = useState(calcHeightToPX(height))
- const onResize = (_env, _dir, refToElement, delta)=>{
+ },
+ });
+ };
+ const [editorHeight, setEditorHeight] = useState(calcHeightToPX(height));
+ const onResize = (_env, _dir, refToElement, delta) => {
// console.log(refToElement.offsetHeight, delta)
- setEditorHeight(refToElement.clientHeight)
- }
+ setEditorHeight(refToElement.clientHeight);
+ };
- const disableWindowScroll = ()=>{
- document.body.style.overflow = 'hidden'
- }
+ const disableWindowScroll = () => {
+ document.body.style.overflow = "hidden";
+ };
- const enableWindowScroll = ()=>{
- document.body.style.overflow = '';
- }
- const onTabNodeMoved=(newOrder:string[])=>{
+ const enableWindowScroll = () => {
+ document.body.style.overflow = "";
+ };
+ const onTabNodeMoved = (newOrder: string[]) => {
dispatch({
- type:'saveOrder',
+ type: "saveOrder",
payload: {
- order: newOrder,
- }
- })
- }
-
-
+ order: newOrder,
+ },
+ });
+ };
+
return (
}}
- onResize={onResize}
- enable={{
- top: resizeable,
- right: false,
- bottom: false,
- left: false,
- topRight: false,
- bottomRight: false,
- bottomLeft: false,
- topLeft: false,
- }}>
-
-
}}
+ onResize={onResize}
+ enable={{
+ top: resizeable,
+ right: false,
+ bottom: false,
+ left: false,
+ topRight: false,
+ bottomRight: false,
+ bottomLeft: false,
+ topLeft: false,
+ }}
+ >
+
- {panes.map(pane => (
- {saveTitle(pane.key, title)}}/>} key={pane.key} closable={pane.closable}>
-
- {/* {pane.content} */}
-
- ))}
-
-
-
+
+ {panes.map((pane) => (
+ {
+ saveTitle(pane.key, title);
+ }}
+ />
+ }
+ key={pane.key}
+ closable={pane.closable}
+ >
+
+ {/* {pane.content} */}
+
+ ))}
+
+
+
);
-}
+};
-export default connect(({
- global
-})=>({
+export default connect(({ global }) => ({
selectedCluster: global.selectedCluster,
clusterList: global.clusterList,
clusterStatus: global.clusterStatus,
- height: window.innerHeight - 75 + 'px',
-}))(ConsoleUI);
\ No newline at end of file
+ height: window.innerHeight - 75 + "px",
+}))(ConsoleUI);
diff --git a/web/src/pages/DevTool/NewTabMenu.jsx b/web/src/pages/DevTool/NewTabMenu.jsx
index 43511351..b017a8dc 100644
--- a/web/src/pages/DevTool/NewTabMenu.jsx
+++ b/web/src/pages/DevTool/NewTabMenu.jsx
@@ -22,11 +22,16 @@ class NewTabMenu extends React.Component{
initialLoad: true,
dataSource: [...props.data],
dataSourceKey: 1,
+ selectedIndex: -1,
+ overlayVisible: false,
}
}
componentDidMount(){
+
}
+
+
handleInfiniteOnLoad = (current) => {
let {size } = this.props;
let targetLength = current * size;
@@ -54,17 +59,56 @@ class NewTabMenu extends React.Component{
dataSource: newData,
data: newData,
hasMore: newData.length > this.props.size,
+ selectedIndex: -1,
})
}
+ selectOffset = (offset)=> {
+ let {selectedIndex, data} = this.state;
+ const len = data.length;
+ selectedIndex = (selectedIndex + offset + len) % len;
+ // const item = data[selectedIndex];
+ this.setState({
+ selectedIndex,
+ })
+ }
+
+ onKeyDown = (e) => {
+ const { which } = e;
+ // e.preventDefault();
+
+ switch (which) {
+ case 38:
+ this.selectOffset(-1);
+ e.preventDefault();
+ e.stopPropagation()
+ break;
+ case 40:
+ this.selectOffset(1);
+ e.stopPropagation()
+ break;
+ case 13:
+ const {data, selectedIndex} = this.state;
+ if(selectedIndex > -1){
+ this.handleItemClick(data[selectedIndex]);
+ this.setState({ overlayVisible: false })
+ }
+ break;
+ }
+ }
+
render(){
const {clusterStatus} = this.props;
- return (
-
+ const menu = (
+
);
+ return (
+
+ {
+ this.setState({ overlayVisible: flag });
+ }}>
+ {this.props.children}
+
+
+ )
}
}
diff --git a/web/src/pages/DevTool/console_tab_title.scss b/web/src/pages/DevTool/console_tab_title.scss
index 9d20d107..398ddfc9 100644
--- a/web/src/pages/DevTool/console_tab_title.scss
+++ b/web/src/pages/DevTool/console_tab_title.scss
@@ -1,15 +1,28 @@
.tab-title{
display: inline-block;
+ height: 30px;
+ overflow: hidden;
.input-eidtor{
border-radius: 0;
border:none;
- border-bottom: 1px solid #ccc;
+ // border-bottom: 1px solid #ccc;
border-right: none;
padding-left: 1em;
+ color:rgba(0, 0, 0, 0.65);
+ height: 28px;
+ line-height: 28px;
+ background-color: #939ea0;
+ color: #fff;
&:focus{
outline: none;
}
}
+ .icon-cont{
+ overflow: hidden;
+ height: 100%;
+ display: flex;
+ align-items: center;
+ }
}
#console{
diff --git a/web/src/pages/DevTool/console_tab_title.tsx b/web/src/pages/DevTool/console_tab_title.tsx
index 99121e07..788de017 100644
--- a/web/src/pages/DevTool/console_tab_title.tsx
+++ b/web/src/pages/DevTool/console_tab_title.tsx
@@ -26,16 +26,26 @@ export const TabTitle = ({title, onTitleChange}: TabTitleProps)=>{
}
},[editable])
const inputRef = useRef(null);
+ const onKeyDown = (e: any)=>{
+ const { which } = e;
+
+ switch (which) {
+ case 13:
+ e.target.blur();
+ break;
+ }
+ }
+
return (
{
setEditable(true)
}}>
- {editable ?
{
setEditable(false)
}}
onChange={onValueChange}/>:
-
{value}
}
+
{value}
}
)
}