ydb-embedded-ui 1.3.0 → 1.4.2

Sign up to get free protection for your applications and to get access to all the features.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,48 @@
1
1
  # Changelog
2
2
 
3
+ ### [1.4.2](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.4.1...v1.4.2) (2022-05-23)
4
+
5
+
6
+ ### UI Updates
7
+
8
+ * **QueryEditor:** replace warning for query losing with note about how query are saved ([89820ca](https://github.com/ydb-platform/ydb-embedded-ui/commit/89820ca7e2d02f880eb81d484b8947d599798d5f))
9
+
10
+
11
+ ### Bug Fixes
12
+
13
+ * **QueryEditor:** confirm query deletion with enter ([d3dadbd](https://github.com/ydb-platform/ydb-embedded-ui/commit/d3dadbd0244fead5f41bd98445669c4f5ce23c43))
14
+ * **QueryEditor:** field autofocus in query save dialog ([9225238](https://github.com/ydb-platform/ydb-embedded-ui/commit/92252384dc68c40191f7898fff9a2c1106b0b2f1))
15
+ * **QueryEditor:** save query with enter ([5f9c450](https://github.com/ydb-platform/ydb-embedded-ui/commit/5f9c450aedc90f0e162515294a74000c006f9be7))
16
+
17
+ ### [1.4.1](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.4.0...v1.4.1) (2022-05-17)
18
+
19
+
20
+ ### UI Updates
21
+
22
+ * **Tenant:** add tenant name wrapper ([8176d28](https://github.com/ydb-platform/ydb-embedded-ui/commit/8176d28a5769b2b95d667ed960ad34d7a0d9bb4c))
23
+
24
+
25
+ ### Bug Fixes
26
+
27
+ * **NodesTable:** align external link icon ([a379796](https://github.com/ydb-platform/ydb-embedded-ui/commit/a379796c6b8087f25f95ce3db4be33f18da71e04))
28
+
29
+ ## [1.4.0](https://github.com/ydb-platform/ydb-embedded-ui/compare/v1.3.0...v1.4.0) (2022-05-16)
30
+
31
+
32
+ ### Features
33
+
34
+ * **Tenant:** save initial tab preference ([7195d0f](https://github.com/ydb-platform/ydb-embedded-ui/commit/7195d0f7f5754c461555211515f80ea96464ca15))
35
+
36
+
37
+ ### UI Updtaes
38
+
39
+ * **NodesTable:** don't reserve space for icons next to node fqdn ([8fcf1b3](https://github.com/ydb-platform/ydb-embedded-ui/commit/8fcf1b3269dee7ada83d7c5abcf44ad004191851))
40
+
41
+
42
+ ### Bug Fixes
43
+
44
+ * **Tenant:** mapDispatchToProps types ([7dcaf56](https://github.com/ydb-platform/ydb-embedded-ui/commit/7dcaf561ec0c361d52d789b2ea3b1aba75339d83))
45
+
3
46
  ## [1.3.0](https://www.github.com/ydb-platform/ydb-embedded-ui/compare/v1.2.6...v1.3.0) (2022-05-12)
4
47
 
5
48
 
package/README.md CHANGED
@@ -8,7 +8,7 @@ Local viewer for YDB clusters
8
8
 
9
9
  1) Run on a machine with Docker installed:
10
10
  ```
11
- docker pull cr.yandex/yc/yandex-docker-local-ydb`
11
+ docker pull cr.yandex/yc/yandex-docker-local-ydb
12
12
  docker run --hostname localhost -e YDB_ALLOW_ORIGIN="http://localhost:3000" -dp 2135:2135 -dp 8765:8765 cr.yandex/yc/yandex-docker-local-ydb
13
13
  ```
14
14
  2) Run the frontend app in the development mode, via invoking `npm run dev`
@@ -9,8 +9,7 @@
9
9
  line-height: var(--yc-text-body2-line-height);
10
10
 
11
11
  &__clipboard-button {
12
- display: flex;
13
- visibility: hidden;
12
+ display: none;
14
13
  align-items: center;
15
14
 
16
15
  margin-left: 8px;
@@ -22,7 +21,7 @@
22
21
  }
23
22
 
24
23
  &_visible {
25
- visibility: visible;
24
+ display: flex;
26
25
  }
27
26
  }
28
27
 
@@ -144,7 +144,7 @@ body,
144
144
  }
145
145
 
146
146
  .data-table__row:hover .entity-status__clipboard-button {
147
- visibility: visible;
147
+ display: flex;
148
148
  }
149
149
 
150
150
  .no-problem {
@@ -1,25 +1,26 @@
1
1
  .kv-nodes {
2
+ &__host-name-wrapper {
3
+ display: flex;
4
+ }
5
+
2
6
  &__external-button {
3
- display: inline-flex;
4
- visibility: hidden;
7
+ display: none;
5
8
  align-items: center;
6
9
 
7
10
  margin-left: 4px;
8
11
 
9
- transform: translateY(-1px);
10
-
11
12
  .yc-button__text {
12
13
  margin: 0 4px;
13
14
  }
14
15
  }
15
16
 
16
17
  &__host-name {
17
- width: 90%;
18
+ overflow: hidden;
18
19
  }
19
20
  }
20
21
 
21
22
  .data-table__row:hover {
22
23
  .kv-nodes__external-button {
23
- visibility: visible;
24
+ display: inline-flex;
24
25
  }
25
26
  }
@@ -1,3 +1,4 @@
1
+ import {connect} from 'react-redux';
1
2
  import {Link} from 'react-router-dom';
2
3
  import cn from 'bem-cn-lite';
3
4
  import {useLocation} from 'react-router';
@@ -11,6 +12,8 @@ import Diagnostics from '../Diagnostics/Diagnostics';
11
12
 
12
13
  import {TenantGeneralTabsIds, TenantTabsGroups, TENANT_GENERAL_TABS} from '../TenantPages';
13
14
  import routes, {createHref} from '../../../routes';
15
+ import {setSettingValue} from '../../../store/reducers/settings';
16
+ import {TENANT_INITIAL_TAB_KEY} from '../../../utils/constants';
14
17
 
15
18
  import './ObjectGeneral.scss';
16
19
 
@@ -20,6 +23,7 @@ interface ObjectGeneralProps {
20
23
  type: string;
21
24
  additionalTenantInfo?: any;
22
25
  additionalNodesInfo?: any;
26
+ setSettingValue: (name: string, value: string) => void;
23
27
  }
24
28
 
25
29
  function ObjectGeneral(props: ObjectGeneralProps) {
@@ -63,6 +67,7 @@ function ObjectGeneral(props: ObjectGeneralProps) {
63
67
  );
64
68
  }}
65
69
  allowNotSelected
70
+ onSelectTab={(id) => props.setSettingValue(TENANT_INITIAL_TAB_KEY, id)}
66
71
  />
67
72
  </div>
68
73
  );
@@ -101,4 +106,8 @@ function ObjectGeneral(props: ObjectGeneralProps) {
101
106
  return renderContent();
102
107
  }
103
108
 
104
- export default ObjectGeneral;
109
+ const mapDispatchToProps = {
110
+ setSettingValue,
111
+ };
112
+
113
+ export default connect(null, mapDispatchToProps)(ObjectGeneral);
@@ -1,31 +1,24 @@
1
- import React, {useState, useRef} from 'react';
1
+ import React, {useState} from 'react';
2
2
  import _ from 'lodash';
3
3
  import cn from 'bem-cn-lite';
4
4
  import {useDispatch, useSelector} from 'react-redux';
5
- import {Dialog, DropdownMenu, Popup, TextInput, Button} from '@yandex-cloud/uikit';
5
+ import {Dialog, DropdownMenu, TextInput, Button} from '@yandex-cloud/uikit';
6
6
 
7
- import Icon from '../../../../components/Icon/Icon';
8
7
  import {setQueryNameToEdit} from '../../../../store/reducers/saveQuery';
9
8
 
10
9
  import './SaveQuery.scss';
11
10
 
12
11
  const b = cn('kv-save-query');
13
12
 
14
- const EMBEDDED_VERSION_WARNING =
15
- 'Please be aware: after cookies delete your saved queries will be lost.';
16
-
17
13
  function SaveQuery({savedQueries, onSaveQuery, saveButtonDisabled}) {
18
14
  const singleClusterMode = useSelector((state) => state.singleClusterMode);
19
15
  const [isDialogVisible, setIsDialogVisible] = useState(false);
20
- const [isEmbeddedWarningVisible, setIsEmbeddedWarningVisible] = useState(false);
21
16
  const [queryName, setQueryName] = useState('');
22
17
  const [validationError, setValidationError] = useState(null);
23
18
 
24
19
  const queryNameToEdit = useSelector((state) => state.saveQuery);
25
20
  const dispatch = useDispatch();
26
21
 
27
- const warningRef = useRef();
28
-
29
22
  const onSaveQueryClick = () => {
30
23
  setIsDialogVisible(true);
31
24
  dispatch(setQueryNameToEdit(null));
@@ -42,13 +35,6 @@ function SaveQuery({savedQueries, onSaveQuery, saveButtonDisabled}) {
42
35
  setValidationError(validateQueryName(value));
43
36
  };
44
37
 
45
- const onEmbeddedWarningOpen = () => {
46
- setIsEmbeddedWarningVisible(true);
47
- };
48
- const onEmbeddedWarningClose = () => {
49
- setIsEmbeddedWarningVisible(false);
50
- };
51
-
52
38
  const validateQueryName = (value) => {
53
39
  if (_.some(savedQueries, (q) => q.name.toLowerCase() === value.trim().toLowerCase())) {
54
40
  return 'This name already exists';
@@ -57,9 +43,11 @@ function SaveQuery({savedQueries, onSaveQuery, saveButtonDisabled}) {
57
43
  };
58
44
 
59
45
  const onSaveClick = () => {
60
- if (queryName && !validationError) {
61
- onSaveQuery(queryName);
46
+ if (!queryName || validationError) {
47
+ return;
62
48
  }
49
+
50
+ onSaveQuery(queryName);
63
51
  onCloseDialog();
64
52
  };
65
53
 
@@ -70,18 +58,38 @@ function SaveQuery({savedQueries, onSaveQuery, saveButtonDisabled}) {
70
58
 
71
59
  const renderDialog = () => {
72
60
  return (
73
- <Dialog open={isDialogVisible} hasCloseButton={false} size="s" onClose={onCloseDialog}>
61
+ <Dialog
62
+ open={isDialogVisible}
63
+ hasCloseButton={false}
64
+ size="s"
65
+ onClose={onCloseDialog}
66
+ onEnterKeyDown={onSaveClick}
67
+ >
74
68
  <Dialog.Header caption="Save query" />
75
69
  <Dialog.Body className={b('dialog-body')}>
76
- <span className={b('field-title', 'required')}>Query name</span>
77
- <div className={b('control-wrapper')}>
78
- <TextInput
79
- placeholder="Enter query name"
80
- text={queryName}
81
- onUpdate={onQueryNameChange}
82
- hasClear
83
- />
84
- <span className={b('error')}>{validationError}</span>
70
+ {singleClusterMode && (
71
+ <div className={b('dialog-row')}>
72
+ The query will be saved in your browser
73
+ </div>
74
+ )}
75
+ <div className={b('dialog-row')}>
76
+ <label
77
+ htmlFor="queryName"
78
+ className={b('field-title', 'required')}
79
+ >
80
+ Query name
81
+ </label>
82
+ <div className={b('control-wrapper')}>
83
+ <TextInput
84
+ id="queryName"
85
+ placeholder="Enter query name"
86
+ text={queryName}
87
+ onUpdate={onQueryNameChange}
88
+ hasClear
89
+ autoFocus
90
+ />
91
+ <span className={b('error')}>{validationError}</span>
92
+ </div>
85
93
  </div>
86
94
  </Dialog.Body>
87
95
  <Dialog.Footer
@@ -121,36 +129,10 @@ function SaveQuery({savedQueries, onSaveQuery, saveButtonDisabled}) {
121
129
  );
122
130
  };
123
131
 
124
- const renderEmbeddedVersionWarning = () => {
125
- return (
126
- <React.Fragment>
127
- <Popup
128
- className={b('embedded-popup')}
129
- anchorRef={warningRef}
130
- placement={['top']}
131
- open={isEmbeddedWarningVisible}
132
- hasArrow
133
- >
134
- {EMBEDDED_VERSION_WARNING}
135
- </Popup>
136
- <div
137
- className={b('embedded-tooltip')}
138
- ref={warningRef}
139
- onMouseEnter={onEmbeddedWarningOpen}
140
- onMouseLeave={onEmbeddedWarningClose}
141
- >
142
- <Icon name="question" height={18} width={18} viewBox="0 0 24 24" />
143
- </div>
144
- </React.Fragment>
145
- );
146
- };
147
-
148
132
  return (
149
133
  <React.Fragment>
150
134
  {queryNameToEdit ? renderSaveDropdownMenu() : renderSaveButton(onSaveQueryClick)}
151
135
  {isDialogVisible && renderDialog()}
152
-
153
- {singleClusterMode && renderEmbeddedVersionWarning()}
154
136
  </React.Fragment>
155
137
  );
156
138
  }
@@ -1,17 +1,19 @@
1
- @import '../../../../styles/mixins.scss';
2
-
3
1
  .kv-save-query {
4
- &__dialog-body {
2
+ &__dialog-row {
5
3
  display: flex;
6
4
  align-items: flex-start;
5
+
6
+ & + & {
7
+ margin-top: var(--yc-text-body-line-height);
8
+ }
7
9
  }
8
10
  &__field-title {
9
11
  margin-right: 12px;
10
12
 
11
13
  font-weight: 500;
12
- line-height: 32px;
14
+ line-height: 28px;
13
15
  white-space: nowrap;
14
- @include body2-typography();
16
+
15
17
  &.required {
16
18
  &::after {
17
19
  content: '*';
@@ -71,6 +71,7 @@ function SavedQueries({savedQueries, changeUserInput, onDeleteQuery}) {
71
71
  hasCloseButton={false}
72
72
  size="s"
73
73
  onClose={onClickCancelDelete}
74
+ onEnterKeyDown={onConfirmDeleteClick}
74
75
  >
75
76
  <Dialog.Header caption="Delete query" />
76
77
  <Dialog.Body className={b('dialog-body')}>
@@ -17,9 +17,9 @@ import routes, {CLUSTER_PAGES, createHref} from '../../routes';
17
17
  import {formatCPU, formatBytesToGigabyte} from '../../utils';
18
18
  import {hideTooltip, showTooltip} from '../../store/reducers/tooltip';
19
19
  import {withSearch} from '../../HOCS';
20
- import {ALL, DEFAULT_TABLE_SETTINGS} from '../../utils/constants';
20
+ import {ALL, DEFAULT_TABLE_SETTINGS, TENANT_INITIAL_TAB_KEY} from '../../utils/constants';
21
21
  import {getTenantsInfo} from '../../store/reducers/tenants';
22
- import {changeFilter} from '../../store/reducers/settings';
22
+ import {changeFilter, getSettingValue} from '../../store/reducers/settings';
23
23
  import {setHeader} from '../../store/reducers/header';
24
24
 
25
25
  import {clusterName} from '../../store';
@@ -119,6 +119,7 @@ class Tenants extends React.Component {
119
119
  filter,
120
120
  handleSearchQuery,
121
121
  additionalTenantsInfo = {},
122
+ savedTenantInitialTab,
122
123
  } = this.props;
123
124
 
124
125
  const filteredTenantsBySearch = tenants.filter(
@@ -129,6 +130,9 @@ class Tenants extends React.Component {
129
130
  );
130
131
  const filteredTenants = Tenants.filterTenants(filteredTenantsBySearch, filter);
131
132
 
133
+ const initialTenantGeneralTab = savedTenantInitialTab || TENANT_GENERAL_TABS[0].id;
134
+ const initialTenantInfoTab = TENANT_INFO_TABS[0].id;
135
+
132
136
  const columns = [
133
137
  {
134
138
  name: 'Name',
@@ -140,7 +144,7 @@ class Tenants extends React.Component {
140
144
  : undefined;
141
145
  const isExternalLink = Boolean(backend);
142
146
  return (
143
- <React.Fragment>
147
+ <div className={b('name-wrapper')}>
144
148
  <EntityStatus
145
149
  externalLink={isExternalLink}
146
150
  className={b('name')}
@@ -150,12 +154,12 @@ class Tenants extends React.Component {
150
154
  path={createHref(routes.tenant, undefined, {
151
155
  name: value,
152
156
  backend: tenantBackend,
153
- [TenantTabsGroups.info]: TENANT_INFO_TABS[0].id,
154
- [TenantTabsGroups.general]: TENANT_GENERAL_TABS[0].id,
157
+ [TenantTabsGroups.info]: initialTenantInfoTab,
158
+ [TenantTabsGroups.general]: initialTenantGeneralTab,
155
159
  })}
156
160
  />
157
161
  {additionalTenantsInfo.name && additionalTenantsInfo.name(value, row)}
158
- </React.Fragment>
162
+ </div>
159
163
  );
160
164
  },
161
165
  width: 440,
@@ -347,6 +351,7 @@ const mapStateToProps = (state) => {
347
351
  loading,
348
352
  error,
349
353
  filter: state.settings.problemFilter,
354
+ savedTenantInitialTab: getSettingValue(state, TENANT_INITIAL_TAB_KEY),
350
355
  };
351
356
  };
352
357
 
@@ -54,7 +54,13 @@
54
54
  .data-table__row:hover &__type-button {
55
55
  visibility: visible;
56
56
  }
57
+
58
+ &__name-wrapper {
59
+ display: flex;
60
+ align-items: center;
61
+ }
62
+
57
63
  &__name {
58
- max-width: 90%;
64
+ overflow: hidden;
59
65
  }
60
66
  }
@@ -1,4 +1,4 @@
1
- import {ALL, defaultUserSettings, SAVED_QUERIES_KEY, THEME_KEY} from '../../utils/constants';
1
+ import {ALL, defaultUserSettings, SAVED_QUERIES_KEY, THEME_KEY, TENANT_INITIAL_TAB_KEY} from '../../utils/constants';
2
2
  import '../../services/api';
3
3
  import {getValueFromLS} from '../../utils/utils';
4
4
 
@@ -13,6 +13,9 @@ const theme = window.web_version
13
13
  const savedQueries = window.web_version
14
14
  ? userSettings[SAVED_QUERIES_KEY]
15
15
  : getValueFromLS(SAVED_QUERIES_KEY, '[]');
16
+ const savedTenantGeneralTab = window.web_version
17
+ ? userSettings[TENANT_INITIAL_TAB_KEY]
18
+ : getValueFromLS(TENANT_INITIAL_TAB_KEY);
16
19
 
17
20
  export const initialState = {
18
21
  problemFilter: ALL,
@@ -21,6 +24,7 @@ export const initialState = {
21
24
  ...userSettings,
22
25
  theme,
23
26
  [SAVED_QUERIES_KEY]: savedQueries,
27
+ [TENANT_INITIAL_TAB_KEY]: savedTenantGeneralTab,
24
28
  },
25
29
  systemSettings,
26
30
  };
@@ -137,3 +137,5 @@ export const DEFAULT_TABLE_SETTINGS = {
137
137
  dynamicRender: true,
138
138
  highlightRows: true,
139
139
  };
140
+
141
+ export const TENANT_INITIAL_TAB_KEY = 'saved_tenant_initial_tab';
@@ -31,7 +31,7 @@ export function getNodesColumns({showTooltip, hideTooltip, tabletsPath, getNodeR
31
31
  return <span>—</span>;
32
32
  }
33
33
  return (
34
- <React.Fragment>
34
+ <div className={b('host-name-wrapper')}>
35
35
  <EntityStatus
36
36
  name={row.Host}
37
37
  status={row.Overall}
@@ -44,7 +44,7 @@ export function getNodesColumns({showTooltip, hideTooltip, tabletsPath, getNodeR
44
44
  <Icon name="external" />
45
45
  </Button>
46
46
  )}
47
- </React.Fragment>
47
+ </div>
48
48
  );
49
49
  },
50
50
  width: '350px',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ydb-embedded-ui",
3
- "version": "1.3.0",
3
+ "version": "1.4.2",
4
4
  "files": [
5
5
  "dist"
6
6
  ],