|
1 | | -import {ArrowsRotateRight} from '@gravity-ui/icons'; |
2 | | -import type {Column as DataTableColumn} from '@gravity-ui/react-data-table'; |
3 | | -import {Icon, Text} from '@gravity-ui/uikit'; |
4 | 1 | import {skipToken} from '@reduxjs/toolkit/query'; |
5 | 2 |
|
6 | | -import {ButtonWithConfirmDialog} from '../../components/ButtonWithConfirmDialog/ButtonWithConfirmDialog'; |
7 | | -import {DeveloperUILinkButton} from '../../components/DeveloperUILinkButton/DeveloperUILinkButton'; |
8 | | -import {EntityStatus} from '../../components/EntityStatus/EntityStatus'; |
9 | 3 | import {ResponseError} from '../../components/Errors/ResponseError'; |
10 | | -import {InternalLink} from '../../components/InternalLink'; |
11 | | -import {ResizeableDataTable} from '../../components/ResizeableDataTable/ResizeableDataTable'; |
12 | 4 | import {TableSkeleton} from '../../components/TableSkeleton/TableSkeleton'; |
13 | | -import {TabletState} from '../../components/TabletState/TabletState'; |
14 | | -import {getTabletPagePath} from '../../routes'; |
15 | | -import {selectIsUserAllowedToMakeChanges} from '../../store/reducers/authentication/authentication'; |
16 | | -import {tabletApi} from '../../store/reducers/tablet'; |
17 | 5 | import {selectTabletsWithFqdn, tabletsApi} from '../../store/reducers/tablets'; |
18 | | -import {ETabletState} from '../../types/api/tablet'; |
19 | | -import type {TTabletStateInfo} from '../../types/api/tablet'; |
20 | 6 | import type {TabletsApiRequestParams} from '../../types/store/tablets'; |
21 | 7 | import {cn} from '../../utils/cn'; |
22 | | -import {DEFAULT_TABLE_SETTINGS, EMPTY_DATA_PLACEHOLDER} from '../../utils/constants'; |
23 | | -import {calcUptime} from '../../utils/dataFormatters/dataFormatters'; |
24 | | -import {createTabletDeveloperUIHref} from '../../utils/developerUI/developerUI'; |
25 | 8 | import {useAutoRefreshInterval, useTypedSelector} from '../../utils/hooks'; |
26 | | -import {getDefaultNodePath} from '../Node/NodePages'; |
27 | 9 |
|
28 | | -import i18n from './i18n'; |
| 10 | +import {TabletsTable} from './TabletsTable'; |
29 | 11 |
|
30 | 12 | const b = cn('tablets'); |
31 | 13 |
|
32 | | -function getColumns({database}: {database?: string}) { |
33 | | - const columns: DataTableColumn<TTabletStateInfo & {fqdn?: string}>[] = [ |
34 | | - { |
35 | | - name: 'Type', |
36 | | - get header() { |
37 | | - return i18n('Type'); |
38 | | - }, |
39 | | - render: ({row}) => { |
40 | | - const isFollower = row.Leader === false; |
41 | | - return ( |
42 | | - <span> |
43 | | - {row.Type} {isFollower ? <Text color="secondary">follower</Text> : ''} |
44 | | - </span> |
45 | | - ); |
46 | | - }, |
47 | | - }, |
48 | | - { |
49 | | - name: 'TabletId', |
50 | | - width: 220, |
51 | | - get header() { |
52 | | - return i18n('Tablet'); |
53 | | - }, |
54 | | - render: ({row}) => { |
55 | | - if (!row.TabletId) { |
56 | | - return EMPTY_DATA_PLACEHOLDER; |
57 | | - } |
58 | | - |
59 | | - const tabletPath = getTabletPagePath(row.TabletId, { |
60 | | - nodeId: row.NodeId, |
61 | | - type: row.Type, |
62 | | - tenantName: database, |
63 | | - }); |
64 | | - |
65 | | - return ( |
66 | | - <EntityStatus |
67 | | - name={row.TabletId?.toString()} |
68 | | - path={tabletPath} |
69 | | - hasClipboardButton |
70 | | - showStatus={false} |
71 | | - additionalControls={ |
72 | | - <DeveloperUILinkButton |
73 | | - href={createTabletDeveloperUIHref(row.TabletId)} |
74 | | - /> |
75 | | - } |
76 | | - /> |
77 | | - ); |
78 | | - }, |
79 | | - }, |
80 | | - { |
81 | | - name: 'State', |
82 | | - get header() { |
83 | | - return i18n('State'); |
84 | | - }, |
85 | | - render: ({row}) => { |
86 | | - return <TabletState state={row.State} />; |
87 | | - }, |
88 | | - }, |
89 | | - { |
90 | | - name: 'NodeId', |
91 | | - get header() { |
92 | | - return i18n('Node ID'); |
93 | | - }, |
94 | | - render: ({row}) => { |
95 | | - const nodePath = |
96 | | - row.NodeId === undefined ? undefined : getDefaultNodePath(row.NodeId); |
97 | | - return <InternalLink to={nodePath}>{row.NodeId}</InternalLink>; |
98 | | - }, |
99 | | - align: 'right', |
100 | | - }, |
101 | | - { |
102 | | - name: 'fqdn', |
103 | | - get header() { |
104 | | - return i18n('Node FQDN'); |
105 | | - }, |
106 | | - render: ({row}) => { |
107 | | - if (!row.fqdn) { |
108 | | - return <span>—</span>; |
109 | | - } |
110 | | - return <EntityStatus name={row.fqdn} showStatus={false} hasClipboardButton />; |
111 | | - }, |
112 | | - }, |
113 | | - { |
114 | | - name: 'Generation', |
115 | | - get header() { |
116 | | - return i18n('Generation'); |
117 | | - }, |
118 | | - align: 'right', |
119 | | - }, |
120 | | - { |
121 | | - name: 'Uptime', |
122 | | - get header() { |
123 | | - return i18n('Uptime'); |
124 | | - }, |
125 | | - render: ({row}) => { |
126 | | - return calcUptime(row.ChangeTime); |
127 | | - }, |
128 | | - sortAccessor: (row) => -Number(row.ChangeTime), |
129 | | - align: 'right', |
130 | | - }, |
131 | | - { |
132 | | - name: 'Actions', |
133 | | - sortable: false, |
134 | | - resizeable: false, |
135 | | - header: '', |
136 | | - render: ({row}) => { |
137 | | - return <TabletActions {...row} />; |
138 | | - }, |
139 | | - }, |
140 | | - ]; |
141 | | - return columns; |
142 | | -} |
143 | | - |
144 | | -function TabletActions(tablet: TTabletStateInfo) { |
145 | | - const isDisabledRestart = tablet.State === ETabletState.Stopped; |
146 | | - const isUserAllowedToMakeChanges = useTypedSelector(selectIsUserAllowedToMakeChanges); |
147 | | - const [killTablet] = tabletApi.useKillTabletMutation(); |
148 | | - |
149 | | - const id = tablet.TabletId; |
150 | | - if (!id) { |
151 | | - return null; |
152 | | - } |
153 | | - |
154 | | - return ( |
155 | | - <ButtonWithConfirmDialog |
156 | | - buttonView="outlined" |
157 | | - dialogHeader={i18n('dialog.kill-header')} |
158 | | - dialogText={i18n('dialog.kill-text')} |
159 | | - onConfirmAction={() => { |
160 | | - return killTablet({id}).unwrap(); |
161 | | - }} |
162 | | - buttonDisabled={isDisabledRestart || !isUserAllowedToMakeChanges} |
163 | | - withPopover |
164 | | - popoverContent={i18n('controls.kill-not-allowed')} |
165 | | - popoverDisabled={isUserAllowedToMakeChanges} |
166 | | - > |
167 | | - <Icon data={ArrowsRotateRight} /> |
168 | | - </ButtonWithConfirmDialog> |
169 | | - ); |
170 | | -} |
171 | | - |
172 | 14 | interface TabletsProps { |
173 | 15 | path?: string; |
174 | 16 | database?: string; |
@@ -203,14 +45,7 @@ export function Tablets({nodeId, path, database, className}: TabletsProps) { |
203 | 45 | return ( |
204 | 46 | <div className={b(null, className)}> |
205 | 47 | {error ? <ResponseError error={error} /> : null} |
206 | | - {currentData ? ( |
207 | | - <ResizeableDataTable |
208 | | - columns={getColumns({database})} |
209 | | - data={tablets} |
210 | | - settings={DEFAULT_TABLE_SETTINGS} |
211 | | - emptyDataMessage={i18n('noTabletsData')} |
212 | | - /> |
213 | | - ) : null} |
| 48 | + {currentData ? <TabletsTable tablets={tablets} database={database} /> : null} |
214 | 49 | </div> |
215 | 50 | ); |
216 | 51 | } |
0 commit comments