ydb-embedded-ui 4.15.1 → 4.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +21 -0
- package/dist/components/BasicNodeViewer/BasicNodeViewer.tsx +2 -2
- package/dist/components/DiagnosticCard/DiagnosticCard.scss +5 -0
- package/dist/components/DiagnosticCard/DiagnosticCard.tsx +17 -0
- package/dist/components/EntityStatus/EntityStatus.js +2 -2
- package/dist/components/EntityStatus/EntityStatus.scss +15 -0
- package/dist/components/NodeHostWrapper/NodeHostWrapper.tsx +2 -1
- package/dist/containers/Cluster/Cluster.tsx +2 -2
- package/dist/containers/Node/Node.tsx +3 -1
- package/dist/containers/Node/NodeStructure/NodeStructure.tsx +3 -1
- package/dist/containers/Node/NodeStructure/Pdisk.tsx +2 -2
- package/dist/containers/Nodes/Nodes.tsx +3 -2
- package/dist/containers/Nodes/getNodesColumns.tsx +3 -1
- package/dist/containers/Storage/Storage.tsx +3 -2
- package/dist/containers/Storage/StorageNodes/StorageNodes.tsx +2 -2
- package/dist/containers/Tenant/Diagnostics/DetailedOverview/DetailedOverview.tsx +5 -12
- package/dist/containers/Tenant/Diagnostics/Diagnostics.tsx +3 -2
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Details/Details.tsx +20 -11
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.scss +14 -1
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Healthcheck.tsx +26 -37
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/Preview.tsx +37 -25
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.tsx +155 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/en.json +7 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/index.ts +11 -0
- package/dist/containers/Tenant/Diagnostics/TenantOverview/i18n/ru.json +7 -0
- package/dist/containers/Tenant/ObjectGeneral/ObjectGeneral.tsx +3 -2
- package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.scss +4 -1
- package/dist/containers/Tenant/Query/QueriesHistory/QueriesHistory.tsx +42 -11
- package/dist/containers/Tenant/Query/QueryEditor/QueryEditor.js +1 -1
- package/dist/containers/Tenant/Query/QueryEditorControls/QueryEditorControls.tsx +11 -7
- package/dist/containers/Tenant/Query/i18n/en.json +3 -0
- package/dist/containers/Tenant/Query/i18n/ru.json +3 -0
- package/dist/containers/Tenant/Tenant.tsx +3 -2
- package/dist/containers/UserSettings/Setting.tsx +9 -2
- package/dist/containers/UserSettings/i18n/en.json +5 -1
- package/dist/containers/UserSettings/i18n/ru.json +5 -1
- package/dist/containers/UserSettings/settings.ts +25 -0
- package/dist/services/api.ts +16 -16
- package/dist/store/reducers/executeQuery.ts +33 -7
- package/dist/store/reducers/explainQuery.ts +12 -4
- package/dist/store/reducers/healthcheckInfo.ts +27 -11
- package/dist/store/reducers/settings/settings.ts +4 -10
- package/dist/store/reducers/tenant/tenant.ts +19 -1
- package/dist/store/reducers/tenant/types.ts +3 -1
- package/dist/store/reducers/tenants/selectors.ts +1 -1
- package/dist/store/reducers/tenants/utils.ts +2 -2
- package/dist/types/additionalProps.ts +8 -1
- package/dist/types/api/tenant.ts +19 -20
- package/dist/types/store/executeQuery.ts +11 -1
- package/dist/types/store/query.ts +2 -1
- package/dist/utils/autofetcher.ts +7 -7
- package/dist/utils/constants.ts +2 -1
- package/dist/utils/hooks/i18n/en.json +1 -1
- package/dist/utils/hooks/i18n/ru.json +1 -1
- package/dist/utils/hooks/useQueryModes.ts +4 -2
- package/dist/utils/i18n/i18n.ts +10 -4
- package/dist/utils/nodes.ts +0 -6
- package/dist/utils/query.ts +14 -0
- package/dist/utils/settings.ts +10 -0
- package/package.json +1 -1
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/PreviewItem/PreviewItem.tsx +0 -33
- package/dist/containers/Tenant/Diagnostics/Healthcheck/Preview/PreviewItem/index.ts +0 -1
- package/dist/containers/Tenant/Diagnostics/TenantOverview/TenantOverview.js +0 -213
package/dist/services/api.ts
CHANGED
@@ -28,6 +28,7 @@ import type {DescribeTopicResult} from '../types/api/topic';
|
|
28
28
|
import type {TEvPDiskStateResponse} from '../types/api/pdisk';
|
29
29
|
import type {TEvVDiskStateResponse} from '../types/api/vdisk';
|
30
30
|
import type {TUserToken} from '../types/api/whoami';
|
31
|
+
import type {QuerySyntax} from '../types/store/query';
|
31
32
|
import type {ComputeApiRequestParams, NodesApiRequestParams} from '../store/reducers/nodes/types';
|
32
33
|
import type {StorageApiRequestParams} from '../store/reducers/storage/types';
|
33
34
|
|
@@ -75,12 +76,16 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
75
76
|
cluster_name: clusterName,
|
76
77
|
});
|
77
78
|
}
|
78
|
-
getTenantInfo({path}: {path: string}) {
|
79
|
-
return this.get<TTenantInfo>(
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
79
|
+
getTenantInfo({path}: {path: string}, {concurrentId}: AxiosOptions = {}) {
|
80
|
+
return this.get<TTenantInfo>(
|
81
|
+
this.getPath('/viewer/json/tenantinfo'),
|
82
|
+
{
|
83
|
+
path,
|
84
|
+
tablets: true,
|
85
|
+
storage: true,
|
86
|
+
},
|
87
|
+
{concurrentId: concurrentId || `getTenantInfo|${path}`},
|
88
|
+
);
|
84
89
|
}
|
85
90
|
getNodes(
|
86
91
|
{
|
@@ -281,17 +286,15 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
281
286
|
}
|
282
287
|
sendQuery<Action extends Actions, Schema extends Schemas = undefined>(
|
283
288
|
{
|
284
|
-
query,
|
285
|
-
database,
|
286
|
-
action,
|
287
|
-
stats,
|
288
289
|
schema,
|
290
|
+
...params
|
289
291
|
}: {
|
290
292
|
query?: string;
|
291
293
|
database?: string;
|
292
294
|
action?: Action;
|
293
295
|
stats?: string;
|
294
296
|
schema?: Schema;
|
297
|
+
syntax?: QuerySyntax;
|
295
298
|
},
|
296
299
|
{concurrentId}: AxiosOptions = {},
|
297
300
|
) {
|
@@ -303,12 +306,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
303
306
|
this.getPath(
|
304
307
|
`/viewer/json/query?timeout=${backendTimeout}${schema ? `&schema=${schema}` : ''}`,
|
305
308
|
),
|
306
|
-
|
307
|
-
query,
|
308
|
-
database,
|
309
|
-
action,
|
310
|
-
stats,
|
311
|
-
},
|
309
|
+
params,
|
312
310
|
{},
|
313
311
|
{
|
314
312
|
concurrentId,
|
@@ -320,6 +318,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
320
318
|
query: string,
|
321
319
|
database: string,
|
322
320
|
action: Action,
|
321
|
+
syntax?: QuerySyntax,
|
323
322
|
) {
|
324
323
|
return this.post<ExplainResponse<Action>>(
|
325
324
|
this.getPath('/viewer/json/query'),
|
@@ -327,6 +326,7 @@ export class YdbEmbeddedAPI extends AxiosWrapper {
|
|
327
326
|
query,
|
328
327
|
database,
|
329
328
|
action: action || 'explain',
|
329
|
+
syntax,
|
330
330
|
timeout: 600000,
|
331
331
|
},
|
332
332
|
{},
|
@@ -4,12 +4,14 @@ import type {ExecuteActions} from '../../types/api/query';
|
|
4
4
|
import type {
|
5
5
|
ExecuteQueryAction,
|
6
6
|
ExecuteQueryState,
|
7
|
+
ExecuteQueryStateSlice,
|
7
8
|
MonacoHotKeyAction,
|
9
|
+
QueryInHistory,
|
8
10
|
} from '../../types/store/executeQuery';
|
9
|
-
import type {QueryRequestParams, QueryMode} from '../../types/store/query';
|
11
|
+
import type {QueryRequestParams, QueryMode, QuerySyntax} from '../../types/store/query';
|
10
12
|
import {getValueFromLS, parseJson} from '../../utils/utils';
|
11
13
|
import {QUERIES_HISTORY_KEY} from '../../utils/constants';
|
12
|
-
import {parseQueryAPIExecuteResponse} from '../../utils/query';
|
14
|
+
import {QUERY_MODES, QUERY_SYNTAX, parseQueryAPIExecuteResponse} from '../../utils/query';
|
13
15
|
import {parseQueryError} from '../../utils/error';
|
14
16
|
import '../../services/api';
|
15
17
|
|
@@ -87,8 +89,12 @@ const executeQuery: Reducer<ExecuteQueryState, ExecuteQueryAction> = (
|
|
87
89
|
}
|
88
90
|
|
89
91
|
case SAVE_QUERY_TO_HISTORY: {
|
90
|
-
const
|
91
|
-
|
92
|
+
const queryText = action.data.queryText;
|
93
|
+
|
94
|
+
// Do not save explicit yql syntax value for easier further support (use yql by default)
|
95
|
+
const syntax = action.data.mode === QUERY_MODES.pg ? QUERY_SYNTAX.pg : undefined;
|
96
|
+
|
97
|
+
const newQueries = [...state.history.queries, {queryText, syntax}].slice(
|
92
98
|
state.history.queries.length >= MAXIMUM_QUERIES_IN_HISTORY ? 1 : 0,
|
93
99
|
);
|
94
100
|
window.localStorage.setItem(QUERIES_HISTORY_KEY, JSON.stringify(newQueries));
|
@@ -151,7 +157,15 @@ interface SendQueryParams extends QueryRequestParams {
|
|
151
157
|
}
|
152
158
|
|
153
159
|
export const sendExecuteQuery = ({query, database, mode}: SendQueryParams) => {
|
154
|
-
|
160
|
+
let action: ExecuteActions = 'execute';
|
161
|
+
let syntax: QuerySyntax = QUERY_SYNTAX.yql;
|
162
|
+
|
163
|
+
if (mode === 'pg') {
|
164
|
+
action = 'execute-query';
|
165
|
+
syntax = QUERY_SYNTAX.pg;
|
166
|
+
} else if (mode) {
|
167
|
+
action = `execute-${mode}`;
|
168
|
+
}
|
155
169
|
|
156
170
|
return createApiRequest({
|
157
171
|
request: window.api.sendQuery({
|
@@ -159,6 +173,7 @@ export const sendExecuteQuery = ({query, database, mode}: SendQueryParams) => {
|
|
159
173
|
query,
|
160
174
|
database,
|
161
175
|
action,
|
176
|
+
syntax,
|
162
177
|
stats: 'profile',
|
163
178
|
}),
|
164
179
|
actions: SEND_QUERY,
|
@@ -166,10 +181,10 @@ export const sendExecuteQuery = ({query, database, mode}: SendQueryParams) => {
|
|
166
181
|
});
|
167
182
|
};
|
168
183
|
|
169
|
-
export const saveQueryToHistory = (
|
184
|
+
export const saveQueryToHistory = (queryText: string, mode: QueryMode) => {
|
170
185
|
return {
|
171
186
|
type: SAVE_QUERY_TO_HISTORY,
|
172
|
-
data:
|
187
|
+
data: {queryText, mode},
|
173
188
|
} as const;
|
174
189
|
};
|
175
190
|
|
@@ -206,4 +221,15 @@ export const setTenantPath = (value: string) => {
|
|
206
221
|
} as const;
|
207
222
|
};
|
208
223
|
|
224
|
+
export const selectQueriesHistory = (state: ExecuteQueryStateSlice): QueryInHistory[] => {
|
225
|
+
return state.executeQuery.history.queries.map((rawQuery) => {
|
226
|
+
if (typeof rawQuery === 'string') {
|
227
|
+
return {
|
228
|
+
queryText: rawQuery,
|
229
|
+
};
|
230
|
+
}
|
231
|
+
return rawQuery;
|
232
|
+
});
|
233
|
+
};
|
234
|
+
|
209
235
|
export default executeQuery;
|
@@ -9,10 +9,10 @@ import type {
|
|
9
9
|
ExplainQueryState,
|
10
10
|
PreparedExplainResponse,
|
11
11
|
} from '../../types/store/explainQuery';
|
12
|
-
import type {QueryRequestParams, QueryMode} from '../../types/store/query';
|
12
|
+
import type {QueryRequestParams, QueryMode, QuerySyntax} from '../../types/store/query';
|
13
13
|
|
14
14
|
import {preparePlan} from '../../utils/prepareQueryExplain';
|
15
|
-
import {parseQueryAPIExplainResponse, parseQueryExplainPlan} from '../../utils/query';
|
15
|
+
import {QUERY_SYNTAX, parseQueryAPIExplainResponse, parseQueryExplainPlan} from '../../utils/query';
|
16
16
|
import {parseQueryError} from '../../utils/error';
|
17
17
|
|
18
18
|
import {createRequestActionTypes, createApiRequest} from '../utils';
|
@@ -103,10 +103,18 @@ interface ExplainQueryParams extends QueryRequestParams {
|
|
103
103
|
}
|
104
104
|
|
105
105
|
export const getExplainQuery = ({query, database, mode}: ExplainQueryParams) => {
|
106
|
-
|
106
|
+
let action: ExplainActions = 'explain';
|
107
|
+
let syntax: QuerySyntax = QUERY_SYNTAX.yql;
|
108
|
+
|
109
|
+
if (mode === 'pg') {
|
110
|
+
action = 'explain-query';
|
111
|
+
syntax = QUERY_SYNTAX.pg;
|
112
|
+
} else if (mode) {
|
113
|
+
action = `explain-${mode}`;
|
114
|
+
}
|
107
115
|
|
108
116
|
return createApiRequest({
|
109
|
-
request: window.api.getExplainQuery(query, database, action),
|
117
|
+
request: window.api.getExplainQuery(query, database, action, syntax),
|
110
118
|
actions: GET_EXPLAIN_QUERY,
|
111
119
|
dataHandler: (response): PreparedExplainResponse => {
|
112
120
|
const {plan: rawPlan, ast} = parseQueryAPIExplainResponse(response);
|
@@ -1,17 +1,16 @@
|
|
1
1
|
import _flow from 'lodash/fp/flow';
|
2
2
|
import _sortBy from 'lodash/fp/sortBy';
|
3
3
|
import _uniqBy from 'lodash/fp/uniqBy';
|
4
|
-
import _omit from 'lodash/omit';
|
5
4
|
import {createSelector, Selector} from 'reselect';
|
6
5
|
import {Reducer} from 'redux';
|
7
6
|
|
8
|
-
import {
|
9
|
-
|
7
|
+
import type {
|
8
|
+
IHealthCheckInfoAction,
|
10
9
|
IHealthcheckInfoRootStateSlice,
|
10
|
+
IHealthcheckInfoState,
|
11
11
|
IIssuesTree,
|
12
|
-
IHealthCheckInfoAction,
|
13
12
|
} from '../../types/store/healthcheck';
|
14
|
-
import {IssueLog, StatusFlag} from '../../types/api/healthcheck';
|
13
|
+
import type {IssueLog, StatusFlag} from '../../types/api/healthcheck';
|
15
14
|
|
16
15
|
import '../../services/api';
|
17
16
|
import {createRequestActionTypes, createApiRequest} from '../utils';
|
@@ -49,6 +48,8 @@ const healthcheckInfo: Reducer<IHealthcheckInfoState, IHealthCheckInfoAction> =
|
|
49
48
|
...state,
|
50
49
|
error: action.error,
|
51
50
|
loading: false,
|
51
|
+
wasLoaded: true,
|
52
|
+
data: undefined,
|
52
53
|
};
|
53
54
|
}
|
54
55
|
|
@@ -110,6 +111,24 @@ const getInvertedConsequencesTree = ({
|
|
110
111
|
: [];
|
111
112
|
};
|
112
113
|
|
114
|
+
const getIssuesStatistics = (data: IssueLog[]): [StatusFlag, number][] => {
|
115
|
+
const issuesMap = {} as Record<StatusFlag, number>;
|
116
|
+
|
117
|
+
for (const issue of data) {
|
118
|
+
if (!issuesMap[issue.status]) {
|
119
|
+
issuesMap[issue.status] = 0;
|
120
|
+
}
|
121
|
+
issuesMap[issue.status]++;
|
122
|
+
}
|
123
|
+
|
124
|
+
return (Object.entries(issuesMap) as [StatusFlag, number][]).sort(([aStatus], [bStatus]) => {
|
125
|
+
const bPriority = mapStatusToPriority[bStatus] || 0;
|
126
|
+
const aPriority = mapStatusToPriority[aStatus] || 0;
|
127
|
+
|
128
|
+
return aPriority - bPriority;
|
129
|
+
});
|
130
|
+
};
|
131
|
+
|
113
132
|
const getIssuesLog = (state: IHealthcheckInfoRootStateSlice) =>
|
114
133
|
state.healthcheckInfo.data?.issue_log;
|
115
134
|
|
@@ -121,13 +140,10 @@ export const selectIssuesTrees: Selector<IHealthcheckInfoRootStateSlice, IIssues
|
|
121
140
|
return getInvertedConsequencesTree({data, roots});
|
122
141
|
});
|
123
142
|
|
124
|
-
export const
|
143
|
+
export const selectIssuesStatistics: Selector<
|
125
144
|
IHealthcheckInfoRootStateSlice,
|
126
|
-
|
127
|
-
|
128
|
-
> = createSelector([selectIssuesTrees, (_, id: string | undefined) => id], (issuesTrees = [], id) =>
|
129
|
-
issuesTrees.find((issuesTree) => issuesTree.id === id),
|
130
|
-
);
|
145
|
+
[StatusFlag, number][]
|
146
|
+
> = createSelector(getIssuesLog, (issues = []) => getIssuesStatistics(issues));
|
131
147
|
|
132
148
|
export function getHealthcheckInfo(database: string) {
|
133
149
|
return createApiRequest({
|
@@ -14,10 +14,12 @@ import {
|
|
14
14
|
CLUSTER_INFO_HIDDEN_KEY,
|
15
15
|
LAST_USED_QUERY_ACTION_KEY,
|
16
16
|
USE_BACKEND_PARAMS_FOR_TABLES_KEY,
|
17
|
+
LANGUAGE_KEY,
|
17
18
|
} from '../../../utils/constants';
|
18
19
|
import '../../../services/api';
|
19
|
-
import {
|
20
|
+
import {parseJson} from '../../../utils/utils';
|
20
21
|
import {QUERY_ACTIONS, QUERY_MODES} from '../../../utils/query';
|
22
|
+
import {readSavedSettingsValue, systemSettings, userSettings} from '../../../utils/settings';
|
21
23
|
|
22
24
|
import {TENANT_PAGES_IDS} from '../tenant/constants';
|
23
25
|
|
@@ -38,20 +40,12 @@ export const ProblemFilterValues = {
|
|
38
40
|
PROBLEMS: 'With problems',
|
39
41
|
} as const;
|
40
42
|
|
41
|
-
const userSettings = window.userSettings || {};
|
42
|
-
const systemSettings = window.systemSettings || {};
|
43
|
-
|
44
|
-
export function readSavedSettingsValue(key: string, defaultValue?: string) {
|
45
|
-
const savedValue = window.web_version ? userSettings[key] : getValueFromLS(key);
|
46
|
-
|
47
|
-
return savedValue ?? defaultValue;
|
48
|
-
}
|
49
|
-
|
50
43
|
export const initialState = {
|
51
44
|
problemFilter: ProblemFilterValues.ALL,
|
52
45
|
userSettings: {
|
53
46
|
...userSettings,
|
54
47
|
[THEME_KEY]: readSavedSettingsValue(THEME_KEY, 'system'),
|
48
|
+
[LANGUAGE_KEY]: readSavedSettingsValue(LANGUAGE_KEY),
|
55
49
|
[INVERTED_DISKS_KEY]: readSavedSettingsValue(INVERTED_DISKS_KEY, 'false'),
|
56
50
|
[USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY]: readSavedSettingsValue(
|
57
51
|
USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY,
|
@@ -20,6 +20,7 @@ const SET_QUERY_TAB = 'tenant/SET_QUERY_TAB';
|
|
20
20
|
const SET_DIAGNOSTICS_TAB = 'tenant/SET_DIAGNOSTICS_TAB';
|
21
21
|
const SET_SUMMARY_TAB = 'tenant/SET_SUMMARY_TAB';
|
22
22
|
const CLEAR_TENANT = 'tenant/CLEAR_TENANT';
|
23
|
+
const SET_DATA_WAS_NOT_LOADED = 'tenant/SET_DATA_WAS_NOT_LOADED';
|
23
24
|
|
24
25
|
const initialState = {loading: false, wasLoaded: false};
|
25
26
|
|
@@ -43,6 +44,10 @@ const tenantReducer: Reducer<TenantState, TenantAction> = (state = initialState,
|
|
43
44
|
}
|
44
45
|
|
45
46
|
case FETCH_TENANT.FAILURE: {
|
47
|
+
if (action.error?.isCancelled) {
|
48
|
+
return state;
|
49
|
+
}
|
50
|
+
|
46
51
|
return {
|
47
52
|
...state,
|
48
53
|
error: action.error,
|
@@ -84,6 +89,13 @@ const tenantReducer: Reducer<TenantState, TenantAction> = (state = initialState,
|
|
84
89
|
};
|
85
90
|
}
|
86
91
|
|
92
|
+
case SET_DATA_WAS_NOT_LOADED: {
|
93
|
+
return {
|
94
|
+
...state,
|
95
|
+
wasLoaded: false,
|
96
|
+
};
|
97
|
+
}
|
98
|
+
|
87
99
|
default:
|
88
100
|
return state;
|
89
101
|
}
|
@@ -91,7 +103,7 @@ const tenantReducer: Reducer<TenantState, TenantAction> = (state = initialState,
|
|
91
103
|
|
92
104
|
export const getTenantInfo = ({path}: {path: string}) => {
|
93
105
|
return createApiRequest({
|
94
|
-
request: window.api.getTenantInfo({path}),
|
106
|
+
request: window.api.getTenantInfo({path}, {concurrentId: 'getTenantInfo'}),
|
95
107
|
actions: FETCH_TENANT,
|
96
108
|
dataHandler: (tenantData): TTenant | undefined => {
|
97
109
|
return tenantData.TenantInfo?.[0];
|
@@ -131,4 +143,10 @@ export function setSummaryTab(tab: TenantSummaryTab) {
|
|
131
143
|
} as const;
|
132
144
|
}
|
133
145
|
|
146
|
+
export const setDataWasNotLoaded = () => {
|
147
|
+
return {
|
148
|
+
type: SET_DATA_WAS_NOT_LOADED,
|
149
|
+
} as const;
|
150
|
+
};
|
151
|
+
|
134
152
|
export default tenantReducer;
|
@@ -16,6 +16,7 @@ import {
|
|
16
16
|
setQueryTab,
|
17
17
|
setSummaryTab,
|
18
18
|
setTenantPage,
|
19
|
+
setDataWasNotLoaded,
|
19
20
|
} from './tenant';
|
20
21
|
|
21
22
|
export type TenantPage = ValueOf<typeof TENANT_PAGES_IDS>;
|
@@ -41,4 +42,5 @@ export type TenantAction =
|
|
41
42
|
| ReturnType<typeof setTenantPage>
|
42
43
|
| ReturnType<typeof setQueryTab>
|
43
44
|
| ReturnType<typeof setDiagnosticsTab>
|
44
|
-
| ReturnType<typeof setSummaryTab
|
45
|
+
| ReturnType<typeof setSummaryTab>
|
46
|
+
| ReturnType<typeof setDataWasNotLoaded>;
|
@@ -24,7 +24,7 @@ const filterTenantsByProblems = (tenants: PreparedTenant[], problemFilter: Probl
|
|
24
24
|
const filteredTenantsBySearch = (tenants: PreparedTenant[], searchQuery: string) => {
|
25
25
|
return tenants.filter((item) => {
|
26
26
|
const re = new RegExp(escapeRegExp(searchQuery), 'i');
|
27
|
-
return re.test(item.Name) || re.test(item.controlPlaneName);
|
27
|
+
return re.test(item.Name || '') || re.test(item.controlPlaneName);
|
28
28
|
});
|
29
29
|
};
|
30
30
|
|
@@ -2,8 +2,8 @@ import type {TTenant} from '../../../types/api/tenant';
|
|
2
2
|
import {isNumeric} from '../../../utils/utils';
|
3
3
|
|
4
4
|
const getControlPlaneValue = (tenant: TTenant) => {
|
5
|
-
const parts = tenant.Name
|
6
|
-
const defaultValue = parts
|
5
|
+
const parts = tenant.Name?.split('/');
|
6
|
+
const defaultValue = parts?.length ? parts[parts.length - 1] : '—';
|
7
7
|
const controlPlaneName = tenant.ControlPlane?.name;
|
8
8
|
|
9
9
|
return controlPlaneName ?? defaultValue;
|
@@ -2,6 +2,7 @@ import type {ReactNode} from 'react';
|
|
2
2
|
|
3
3
|
import type {InfoViewerItem} from '../components/InfoViewer';
|
4
4
|
import type {ETenantType} from './api/tenant';
|
5
|
+
import type {TSystemStateInfo} from './api/nodes';
|
5
6
|
import type {VersionToColorMap} from './versions';
|
6
7
|
|
7
8
|
export interface AdditionalVersionsProps {
|
@@ -20,5 +21,11 @@ export interface AdditionalClusterProps {
|
|
20
21
|
|
21
22
|
export interface AdditionalTenantsProps {
|
22
23
|
prepareTenantBackend?: (backend: string | undefined) => string | undefined;
|
23
|
-
getMonitoringLink?: (name
|
24
|
+
getMonitoringLink?: (name?: string, type?: ETenantType) => ReactNode;
|
25
|
+
}
|
26
|
+
|
27
|
+
export type NodeAddress = Pick<TSystemStateInfo, 'Host' | 'Endpoints'>;
|
28
|
+
|
29
|
+
export interface AdditionalNodesProps extends Record<string, unknown> {
|
30
|
+
getNodeRef?: (node?: NodeAddress) => string | null;
|
24
31
|
}
|
package/dist/types/api/tenant.ts
CHANGED
@@ -22,38 +22,38 @@ export interface TTenantInfo {
|
|
22
22
|
}
|
23
23
|
|
24
24
|
export interface TTenant {
|
25
|
-
Name
|
26
|
-
Id
|
27
|
-
Type
|
28
|
-
State
|
25
|
+
Name?: string;
|
26
|
+
Id?: string;
|
27
|
+
Type?: ETenantType;
|
28
|
+
State?: State;
|
29
29
|
StateStats?: THiveDomainStatsStateCount[];
|
30
|
-
Metrics
|
30
|
+
Metrics?: TMetrics;
|
31
31
|
NodeIds?: number[];
|
32
|
-
AliveNodes
|
33
|
-
Resources
|
32
|
+
AliveNodes?: number;
|
33
|
+
Resources?: TTenantResources;
|
34
34
|
/** uint64 */
|
35
|
-
CreateTime
|
36
|
-
Owner
|
35
|
+
CreateTime?: string;
|
36
|
+
Owner?: string;
|
37
37
|
Users?: string[];
|
38
38
|
PoolStats?: TPoolStats[];
|
39
|
-
UserAttributes
|
40
|
-
Overall
|
39
|
+
UserAttributes?: Record<string, string>;
|
40
|
+
Overall?: EFlag;
|
41
41
|
SystemTablets?: TTabletStateInfo[];
|
42
|
-
ResourceId
|
42
|
+
ResourceId?: string;
|
43
43
|
Tablets?: TTabletStateInfo[];
|
44
44
|
/** uint64 */
|
45
|
-
StorageAllocatedSize
|
45
|
+
StorageAllocatedSize?: string;
|
46
46
|
/** uint64 */
|
47
|
-
StorageMinAvailableSize
|
47
|
+
StorageMinAvailableSize?: string;
|
48
48
|
Nodes?: TSystemStateInfo[];
|
49
49
|
/** uint64 */
|
50
|
-
MemoryUsed
|
50
|
+
MemoryUsed?: string;
|
51
51
|
/** uint64 */
|
52
|
-
MemoryLimit
|
52
|
+
MemoryLimit?: string;
|
53
53
|
/** double */
|
54
|
-
CoresUsed
|
54
|
+
CoresUsed?: number;
|
55
55
|
/** uint64 */
|
56
|
-
StorageGroups
|
56
|
+
StorageGroups?: string;
|
57
57
|
|
58
58
|
MonitoringEndpoint?: string; // additional
|
59
59
|
ControlPlane?: ControlPlane; // additional
|
@@ -139,11 +139,10 @@ enum State {
|
|
139
139
|
'CONFIGURING' = 'CONFIGURING',
|
140
140
|
}
|
141
141
|
|
142
|
-
enum ETabletVolatileState {
|
142
|
+
export enum ETabletVolatileState {
|
143
143
|
'TABLET_VOLATILE_STATE_UNKNOWN' = 'TABLET_VOLATILE_STATE_UNKNOWN',
|
144
144
|
'TABLET_VOLATILE_STATE_STOPPED' = 'TABLET_VOLATILE_STATE_STOPPED',
|
145
145
|
'TABLET_VOLATILE_STATE_BOOTING' = 'TABLET_VOLATILE_STATE_BOOTING',
|
146
146
|
'TABLET_VOLATILE_STATE_STARTING' = 'TABLET_VOLATILE_STATE_STARTING',
|
147
147
|
'TABLET_VOLATILE_STATE_RUNNING' = 'TABLET_VOLATILE_STATE_RUNNING',
|
148
|
-
'_TABLET_VOLATILE_STATE_BLOCKED' = '_TABLET_VOLATILE_STATE_BLOCKED',
|
149
148
|
}
|
@@ -14,11 +14,17 @@ import type {IQueryResult, QueryError, QueryErrorResponse} from './query';
|
|
14
14
|
|
15
15
|
export type MonacoHotKeyAction = ValueOf<typeof MONACO_HOT_KEY_ACTIONS>;
|
16
16
|
|
17
|
+
export interface QueryInHistory {
|
18
|
+
queryText: string;
|
19
|
+
syntax?: string;
|
20
|
+
}
|
21
|
+
|
17
22
|
export interface ExecuteQueryState {
|
18
23
|
loading: boolean;
|
19
24
|
input: string;
|
20
25
|
history: {
|
21
|
-
|
26
|
+
// String type for backward compatibility
|
27
|
+
queries: (QueryInHistory | string)[];
|
22
28
|
currentIndex: number;
|
23
29
|
};
|
24
30
|
monacoHotKey: null | MonacoHotKeyAction;
|
@@ -38,3 +44,7 @@ export type ExecuteQueryAction =
|
|
38
44
|
| ReturnType<typeof saveQueryToHistory>
|
39
45
|
| ReturnType<typeof setMonacoHotKey>
|
40
46
|
| ReturnType<typeof setTenantPath>;
|
47
|
+
|
48
|
+
export interface ExecuteQueryStateSlice {
|
49
|
+
executeQuery: ExecuteQueryState;
|
50
|
+
}
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import {QUERY_ACTIONS, QUERY_MODES} from '../../utils/query';
|
1
|
+
import {QUERY_ACTIONS, QUERY_MODES, QUERY_SYNTAX} from '../../utils/query';
|
2
2
|
|
3
3
|
import type {IResponseError, NetworkError} from '../api/error';
|
4
4
|
import type {
|
@@ -29,6 +29,7 @@ export type QueryError = NetworkError | QueryErrorResponse;
|
|
29
29
|
|
30
30
|
export type QueryAction = ValueOf<typeof QUERY_ACTIONS>;
|
31
31
|
export type QueryMode = ValueOf<typeof QUERY_MODES>;
|
32
|
+
export type QuerySyntax = ValueOf<typeof QUERY_SYNTAX>;
|
32
33
|
|
33
34
|
export interface SavedQuery {
|
34
35
|
name: string;
|
@@ -1,4 +1,11 @@
|
|
1
1
|
export class AutoFetcher {
|
2
|
+
static DEFAULT_TIMEOUT = 30000;
|
3
|
+
static MIN_TIMEOUT = 30000;
|
4
|
+
timeout: number;
|
5
|
+
active: boolean;
|
6
|
+
timer: undefined | ReturnType<typeof setTimeout>;
|
7
|
+
launchCounter: number;
|
8
|
+
|
2
9
|
constructor() {
|
3
10
|
this.timeout = AutoFetcher.DEFAULT_TIMEOUT;
|
4
11
|
this.active = true;
|
@@ -52,11 +59,4 @@ export class AutoFetcher {
|
|
52
59
|
this.launchCounter++;
|
53
60
|
this.active = true;
|
54
61
|
}
|
55
|
-
|
56
|
-
static DEFAULT_TIMEOUT = 30000;
|
57
|
-
static MIN_TIMEOUT = 30000;
|
58
|
-
timeout: number;
|
59
|
-
active: boolean;
|
60
|
-
timer: undefined | ReturnType<typeof setTimeout>;
|
61
|
-
launchCounter: number;
|
62
62
|
}
|
package/dist/utils/constants.ts
CHANGED
@@ -25,7 +25,6 @@ export const TABLET_STATES = {
|
|
25
25
|
TABLET_VOLATILE_STATE_BOOTING: 'booting',
|
26
26
|
TABLET_VOLATILE_STATE_STARTING: 'starting',
|
27
27
|
TABLET_VOLATILE_STATE_RUNNING: 'running',
|
28
|
-
TABLET_VOLATILE_STATE_BLOCKED: 'blocked',
|
29
28
|
};
|
30
29
|
|
31
30
|
export const TABLET_COLORS = {
|
@@ -81,9 +80,11 @@ export const COLORS_PRIORITY = {
|
|
81
80
|
// ==== Titles ====
|
82
81
|
export const DEVELOPER_UI_TITLE = 'Developer UI';
|
83
82
|
export const CLUSTER_DEFAULT_TITLE = 'Cluster';
|
83
|
+
export const TENANT_DEFAULT_TITLE = 'Database';
|
84
84
|
|
85
85
|
// ==== Settings ====
|
86
86
|
export const THEME_KEY = 'theme';
|
87
|
+
export const LANGUAGE_KEY = 'language';
|
87
88
|
export const INVERTED_DISKS_KEY = 'invertedDisks';
|
88
89
|
export const USE_NODES_ENDPOINT_IN_DIAGNOSTICS_KEY = 'useNodesEndpointInDiagnostics';
|
89
90
|
export const ENABLE_ADDITIONAL_QUERY_MODES = 'enableAdditionalQueryModes';
|
@@ -1,3 +1,3 @@
|
|
1
1
|
{
|
2
|
-
"useQueryModes.queryModeCannotBeSet": "Query mode
|
2
|
+
"useQueryModes.queryModeCannotBeSet": "Query mode '{{mode}}' cannot be set. You need to turn in additional query modes in settings to enable it"
|
3
3
|
}
|
@@ -1,3 +1,3 @@
|
|
1
1
|
{
|
2
|
-
"useQueryModes.queryModeCannotBeSet": "Режим выполнения запроса
|
2
|
+
"useQueryModes.queryModeCannotBeSet": "Режим выполнения запроса '{{mode}}' недоступен. Вам необходимо включить дополнительные режимы выполнения запросов в настройках"
|
3
3
|
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import type {QueryMode} from '../../types/store/query';
|
2
2
|
import {ENABLE_ADDITIONAL_QUERY_MODES, QUERY_INITIAL_MODE_KEY} from '../constants';
|
3
|
-
import {isNewQueryMode} from '../query';
|
3
|
+
import {QUERY_MODES_TITLES, isNewQueryMode} from '../query';
|
4
4
|
import createToast from '../createToast';
|
5
5
|
import {useSetting} from './useSetting';
|
6
6
|
import i18n from './i18n';
|
@@ -18,7 +18,9 @@ export const useQueryModes = (): [QueryMode, SetQueryModeIfAvailable] => {
|
|
18
18
|
if (isNewQueryMode(value) && !enableAdditionalQueryModes) {
|
19
19
|
createToast({
|
20
20
|
name: 'QueryModeCannotBeSet',
|
21
|
-
title:
|
21
|
+
title:
|
22
|
+
errorMessage ??
|
23
|
+
i18n('useQueryModes.queryModeCannotBeSet', {mode: QUERY_MODES_TITLES[value]}),
|
22
24
|
type: 'error',
|
23
25
|
});
|
24
26
|
|
package/dist/utils/i18n/i18n.ts
CHANGED
@@ -2,15 +2,21 @@ import {I18N} from '@gravity-ui/i18n';
|
|
2
2
|
import {configure as configureUiKit} from '@gravity-ui/uikit';
|
3
3
|
import {configure as configureYdbUiComponents} from 'ydb-ui-components';
|
4
4
|
|
5
|
+
import {LANGUAGE_KEY} from '../constants';
|
6
|
+
import {readSavedSettingsValue} from '../settings';
|
7
|
+
|
5
8
|
enum Lang {
|
6
9
|
En = 'en',
|
7
10
|
Ru = 'ru',
|
8
11
|
}
|
9
12
|
|
13
|
+
const defaultLang = Lang.En;
|
14
|
+
const currentLang = readSavedSettingsValue(LANGUAGE_KEY, defaultLang);
|
15
|
+
|
10
16
|
const i18n = new I18N();
|
11
17
|
|
12
|
-
i18n.setLang(
|
13
|
-
configureYdbUiComponents({lang:
|
14
|
-
configureUiKit({lang:
|
18
|
+
i18n.setLang(currentLang);
|
19
|
+
configureYdbUiComponents({lang: currentLang});
|
20
|
+
configureUiKit({lang: currentLang});
|
15
21
|
|
16
|
-
export {i18n, Lang};
|
22
|
+
export {i18n, Lang, currentLang, defaultLang};
|
package/dist/utils/nodes.ts
CHANGED
@@ -18,12 +18,6 @@ export const NodesUptimeFilterTitles = {
|
|
18
18
|
export const isUnavailableNode = (node: NodesPreparedEntity | TSystemStateInfo) =>
|
19
19
|
!node.SystemState || node.SystemState === EFlag.Grey;
|
20
20
|
|
21
|
-
export type NodeAddress = Pick<TSystemStateInfo, 'Host' | 'Endpoints'>;
|
22
|
-
|
23
|
-
export interface AdditionalNodesInfo extends Record<string, unknown> {
|
24
|
-
getNodeRef?: (node?: NodeAddress) => string | null;
|
25
|
-
}
|
26
|
-
|
27
21
|
export const prepareNodesMap = (nodesList?: TNodeInfo[]) => {
|
28
22
|
return nodesList?.reduce<NodesMap>((nodesMap, node) => {
|
29
23
|
if (node.Id && node.Host) {
|