ydb-embedded-ui 1.3.0 → 1.4.2

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 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
  ],