@@ -2,10 +2,10 @@ import { getApiKeys } from "redux/selectors/usersSelectors";
2
2
import Card from "antd/es/card" ;
3
3
import Flex from "antd/es/flex" ;
4
4
import Title from "antd/es/typography/Title" ;
5
- import Table from "antd/es/table" ;
5
+ import Table , { ColumnsType } from "antd/es/table" ;
6
6
import Tooltip from "antd/es/tooltip" ;
7
7
import { useDispatch , useSelector } from "react-redux" ;
8
- import { useState } from "react" ;
8
+ import { useState , useCallback , useMemo } from "react" ;
9
9
import { styled } from "styled-components" ;
10
10
import { AddIcon , CustomModal , EditPopover , TacoButton , messageInstance } from "lowcoder-design" ;
11
11
import { trans } from "i18n" ;
@@ -21,7 +21,7 @@ const TableStyled = styled(Table)`
21
21
.ant-table-tbody > tr > td {
22
22
padding: 11px 12px;
23
23
}
24
- ` ;
24
+ ` as typeof Table ;
25
25
26
26
const OperationWrapper = styled . div `
27
27
display: flex;
@@ -42,6 +42,8 @@ const CreateButton = styled(TacoButton)`
42
42
export type ApiKeyType = {
43
43
id : string ;
44
44
token : string ;
45
+ name : string ;
46
+ description ?: string ;
45
47
}
46
48
47
49
export default function UserApiKeysCard ( ) {
@@ -50,116 +52,140 @@ export default function UserApiKeysCard() {
50
52
const [ modalVisible , setModalVisible ] = useState ( false ) ;
51
53
const [ newApiKey , setNewApiKey ] = useState < ApiKeyType > ( ) ;
52
54
53
- const handleCopy = ( value : string ) => {
54
- navigator . clipboard . writeText ( value ) . then ( ( ) => {
55
- messageInstance . success ( 'Copied to clipboard!' ) ;
56
- } ) . catch ( err => {
57
- messageInstance . error ( 'Failed to copy!' ) ;
55
+ const handleCopy = useCallback ( ( value : string ) => {
56
+ navigator . clipboard . writeText ( value )
57
+ . then ( ( ) => messageInstance . success ( 'Copied to clipboard!' ) )
58
+ . catch ( ( ) => messageInstance . error ( 'Failed to copy!' ) ) ;
59
+ } , [ ] ) ;
60
+
61
+ const handleDeleteApiKey = useCallback ( ( apiKeyId : string ) => {
62
+ CustomModal . confirm ( {
63
+ title : trans ( "profile.deleteApiKey" ) ,
64
+ content : trans ( "profile.deleteApiKeyContent" ) ,
65
+ onConfirm : ( ) => {
66
+ UserApi . deleteApiKey ( apiKeyId )
67
+ . then ( resp => {
68
+ if ( validateResponse ( resp ) ) {
69
+ dispatch ( fetchApiKeysAction ( ) ) ;
70
+ }
71
+ } )
72
+ . catch ( ( ) => {
73
+ messageInstance . error ( trans ( "profile.deleteApiKeyError" ) ) ;
74
+ } ) ;
75
+ } ,
76
+ confirmBtnType : "delete" ,
77
+ okText : trans ( "delete" ) ,
58
78
} ) ;
59
- } ;
79
+ } , [ dispatch ] ) ;
80
+
81
+ const handleModalClose = useCallback ( ( ) => {
82
+ setModalVisible ( false ) ;
83
+ } , [ ] ) ;
84
+
85
+ const handleConfigCreate = useCallback ( ( apiKey ?: ApiKeyType ) => {
86
+ setModalVisible ( false ) ;
87
+ setNewApiKey ( apiKey ) ;
88
+ dispatch ( fetchApiKeysAction ( ) ) ;
89
+ } , [ dispatch ] ) ;
90
+
91
+ const columns : ColumnsType < ApiKeyType > = useMemo ( ( ) => [
92
+ {
93
+ title : trans ( "profile.apiKeyName" ) ,
94
+ dataIndex : "name" ,
95
+ ellipsis : true ,
96
+ } ,
97
+ {
98
+ title : trans ( "profile.apiKeyDescription" ) ,
99
+ dataIndex : "description" ,
100
+ width : 400 ,
101
+ render : ( value : string ) => value || '-' ,
102
+ } ,
103
+ {
104
+ title : trans ( "profile.apiKey" ) ,
105
+ dataIndex : "token" ,
106
+ width : 500 ,
107
+ render : ( value : string , record : ApiKeyType ) => {
108
+ if ( newApiKey ?. id === record . id ) {
109
+ return (
110
+ < Tooltip placement = "topLeft" title = { trans ( "profile.apiKeyCopy" ) } >
111
+ < div
112
+ onClick = { ( ) => handleCopy ( newApiKey . token ) }
113
+ style = { { cursor : 'pointer' , width : '500px' } }
114
+ >
115
+ { newApiKey . token }
116
+
117
+ < CopyOutlined />
118
+ </ div >
119
+ </ Tooltip >
120
+ ) ;
121
+ }
122
+ return < div > { value } </ div > ;
123
+ }
124
+ } ,
125
+ {
126
+ title : " " ,
127
+ dataIndex : "operation" ,
128
+ width : "208px" ,
129
+ render : ( _ : unknown , record : ApiKeyType ) => (
130
+ < OperationWrapper >
131
+ < EditPopover
132
+ del = { ( ) => handleDeleteApiKey ( record . id ) }
133
+ >
134
+ < PopoverIcon tabIndex = { - 1 } />
135
+ </ EditPopover >
136
+ </ OperationWrapper >
137
+ ) ,
138
+ } ,
139
+ ] , [ newApiKey , handleCopy , handleDeleteApiKey ] ) ;
140
+
141
+ const dataSource = useMemo ( ( ) =>
142
+ apiKeys . map ( ( apiKey , i ) => ( {
143
+ ...apiKey ,
144
+ key : i ,
145
+ } ) )
146
+ , [ apiKeys ] ) ;
60
147
61
148
return (
62
149
< >
63
150
< Card style = { { marginBottom : "20px" } } >
64
151
< Flex justify = "space-between" align = "center" style = { { marginBottom : '8px' } } >
65
152
< Title level = { 4 } > { trans ( "profile.apiKeys" ) } </ Title >
66
- < h4 > < a href = { trans ( "docUrls.apiDocHome" ) } target = "_blank" > { trans ( "home.howToUseAPI" ) } </ a > </ h4 >
153
+ < h4 >
154
+ < a href = { trans ( "docUrls.apiDocHome" ) } target = "_blank" rel = "noopener noreferrer" >
155
+ { trans ( "home.howToUseAPI" ) }
156
+ </ a >
157
+ </ h4 >
67
158
< CreateButton
68
- buttonType = { "primary" }
159
+ buttonType = "primary"
69
160
icon = { < AddIcon /> }
70
- onClick = { ( ) =>
71
- setModalVisible ( true )
72
- }
161
+ onClick = { ( ) => setModalVisible ( true ) }
73
162
>
74
163
{ trans ( "profile.createApiKey" ) }
75
164
</ CreateButton >
76
165
</ Flex >
77
- { Boolean ( newApiKey ) && < Alert message = { trans ( "profile.apiKeyInfo" ) } type = "info" style = { { marginBottom : '16px' } } /> }
166
+
167
+ { Boolean ( newApiKey ) && (
168
+ < Alert
169
+ message = { trans ( "profile.apiKeyInfo" ) }
170
+ type = "info"
171
+ style = { { marginBottom : '16px' } }
172
+ />
173
+ ) }
174
+
78
175
< TableStyled
79
- tableLayout = { "auto" }
176
+ tableLayout = "auto"
80
177
scroll = { { x : "100%" } }
81
178
pagination = { false }
82
- columns = { [
83
- {
84
- title : trans ( "profile.apiKeyName" ) ,
85
- dataIndex : "name" ,
86
- ellipsis : true ,
87
- } ,
88
- {
89
- title : trans ( "profile.apiKeyDescription" ) ,
90
- dataIndex : "description" ,
91
- ellipsis : true ,
92
- render : ( value : string ) => {
93
- return (
94
- < >
95
- { value || '-' }
96
- </ >
97
- )
98
- }
99
- } ,
100
- {
101
- title : trans ( "profile.apiKey" ) ,
102
- dataIndex : "token" ,
103
- ellipsis : true ,
104
- render : ( value : string , record : any ) => {
105
- if ( newApiKey ?. id === record . id ) {
106
- return (
107
- < Tooltip placement = "topLeft" title = { trans ( "profile.apiKeyCopy" ) } >
108
- < div onClick = { ( ) => handleCopy ( newApiKey ?. token ! ) } style = { { cursor : 'pointer' } } >
109
- { value }
110
-
111
- < CopyOutlined />
112
- </ div >
113
- </ Tooltip >
114
- )
115
- }
116
- return < div > { value } </ div >
117
- }
118
- } ,
119
- { title : " " , dataIndex : "operation" , width : "208px" } ,
120
- ] }
121
- dataSource = { apiKeys . map ( ( apiKey , i ) => ( {
122
- ...apiKey ,
123
- key : i ,
124
- operation : (
125
- < OperationWrapper >
126
- < EditPopover
127
- del = { ( ) => {
128
- CustomModal . confirm ( {
129
- title : trans ( "profile.deleteApiKey" ) ,
130
- content : trans ( "profile.deleteApiKeyContent" ) ,
131
- onConfirm : ( ) => {
132
- UserApi . deleteApiKey ( apiKey . id ) . then ( resp => {
133
- if ( validateResponse ( resp ) ) {
134
- dispatch ( fetchApiKeysAction ( ) ) ;
135
- }
136
- } )
137
- . catch ( ( e ) => {
138
- messageInstance . error ( trans ( "profile.deleteApiKeyError" ) ) ;
139
- } )
140
- } ,
141
- confirmBtnType : "delete" ,
142
- okText : trans ( "delete" ) ,
143
- } )
144
- } }
145
- >
146
- < PopoverIcon tabIndex = { - 1 } />
147
- </ EditPopover >
148
- </ OperationWrapper >
149
- ) ,
150
- } ) ) }
179
+ columns = { columns }
180
+ dataSource = { dataSource }
151
181
/>
152
182
</ Card >
153
183
154
184
< CreateApiKeyModal
155
185
modalVisible = { modalVisible }
156
- closeModal = { ( ) => setModalVisible ( false ) }
157
- onConfigCreate = { ( apiKey ?: ApiKeyType ) => {
158
- setModalVisible ( false ) ;
159
- setNewApiKey ( apiKey ) ;
160
- dispatch ( fetchApiKeysAction ( ) ) ;
161
- } }
186
+ closeModal = { handleModalClose }
187
+ onConfigCreate = { handleConfigCreate }
162
188
/>
163
189
</ >
164
- )
190
+ ) ;
165
191
}
0 commit comments