Skip to content

Commit aced2a6

Browse files
authored
Merge pull request #1444 from merico-dev/jc-1386-configure-connection-ux-updates
`fix` `v0.9.2` data integrations - configure connection form ux updates
2 parents 93b1c6c + 4f47760 commit aced2a6

File tree

5 files changed

+153
-41
lines changed

5 files changed

+153
-41
lines changed
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import React from 'react'
2+
import {
3+
Colors,
4+
Icon,
5+
Popover,
6+
PopoverInteractionKind,
7+
Intent,
8+
Position
9+
} from '@blueprintjs/core'
10+
11+
const InputValidationError = (props) => {
12+
const { error, position = Position.TOP } = props
13+
return error
14+
? (
15+
<div className='inline-input-error' style={{ outline: 'none', cursor: 'pointer', margin: '5px 5px 3px 5px' }}>
16+
<Popover
17+
position={position}
18+
usePortal={true}
19+
openOnTargetFocus={true}
20+
intent={Intent.WARNING}
21+
interactionKind={PopoverInteractionKind.HOVER_TARGET_ONLY}
22+
>
23+
<Icon icon='warning-sign' size={12} color={Colors.RED5} style={{ outline: 'none' }} />
24+
<div style={{ outline: 'none', padding: '5px', borderTop: `2px solid ${Colors.RED5}` }}>{error}</div>
25+
</Popover>
26+
</div>
27+
)
28+
: null
29+
}
30+
31+
export default InputValidationError

config-ui/src/data/Providers.js

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -91,44 +91,44 @@ const ProviderFormLabels = {
9191

9292
const ProviderFormPlaceholders = {
9393
null: {
94-
name: 'Enter Instance Name',
95-
endpoint: 'Enter Endpoint URL eg. https://null-api.localhost',
96-
proxy: 'Enter Proxy URL eg. http://proxy.localhost:8080',
97-
token: 'Enter Auth Token eg. 3f5cda2a23ff410792e0',
94+
name: 'eg. Enter Instance Name',
95+
endpoint: 'eg. https://null-api.localhost',
96+
proxy: 'eg. http://proxy.localhost:8080',
97+
token: 'eg. 3f5cda2a23ff410792e0',
9898
username: 'Enter Username / E-mail',
9999
password: 'Enter Password'
100100
},
101101
gitlab: {
102-
name: 'Enter Instance Name',
103-
endpoint: 'Enter Endpoint URL eg. https://gitlab.com/api/v4',
104-
proxy: 'Enter Proxy URL eg. http://proxy.localhost:8080',
105-
token: 'Enter Auth Token eg. ff9d1ad0e5c04f1f98fa',
102+
name: 'eg. GitLab',
103+
endpoint: 'eg. https://gitlab.com/api/v4',
104+
proxy: 'eg. http://proxy.localhost:8080',
105+
token: 'eg. ff9d1ad0e5c04f1f98fa',
106106
username: 'Enter Username / E-mail',
107107
password: 'Enter Password'
108108
},
109109
jenkins: {
110-
name: 'Enter Instance Name',
111-
endpoint: 'Enter Endpoint URL eg. https://api.jenkins.io',
112-
proxy: 'Enter Proxy URL eg. http://proxy.localhost:8080',
113-
token: 'Enter Auth Token eg. 6b057ffe68464c93a057',
114-
username: 'Enter Username / E-mail',
115-
password: 'Enter Password'
110+
name: 'eg. Jenkins',
111+
endpoint: 'URL eg. https://api.jenkins.io',
112+
proxy: 'eg. http://proxy.localhost:8080',
113+
token: 'eg. 6b057ffe68464c93a057',
114+
username: 'eg. admin',
115+
password: 'eg. ************'
116116
},
117117
jira: {
118-
name: 'Enter Instance Name',
119-
endpoint: 'Enter Endpoint URL eg. https://your-domain.atlassian.net/rest/',
120-
proxy: 'Enter Proxy URL eg. http://proxy.localhost:8080',
121-
token: 'Enter Auth Token eg. 8c06a7cc50b746bfab30',
122-
username: 'Enter Username / E-mail',
123-
password: 'Enter Password'
118+
name: 'eg. JIRA',
119+
endpoint: 'eg. https://your-domain.atlassian.net/rest/',
120+
proxy: 'eg. http://proxy.localhost:8080',
121+
token: 'eg. 8c06a7cc50b746bfab30',
122+
username: 'eg. admin',
123+
password: 'eg. ************'
124124
},
125125
github: {
126-
name: 'Enter Instance Name',
127-
endpoint: 'Enter Endpoint URL eg. https://api.github.com',
128-
proxy: 'Enter Proxy URL eg. http://proxy.localhost:8080',
129-
token: 'Enter Auth Token(s) eg. 4c5cbdb62c165e2b3d18, 40008ebccff9837bb8d2',
130-
username: 'Enter Username / E-mail',
131-
password: 'Enter Password'
126+
name: 'eg. GitHub',
127+
endpoint: 'eg. https://api.github.com',
128+
proxy: 'eg. http://proxy.localhost:8080',
129+
token: 'eg. 4c5cbdb62c165e2b3d18, 40008ebccff9837bb8d2',
130+
username: 'eg. admin',
131+
password: 'eg. ************'
132132
}
133133
}
134134

config-ui/src/pages/configure/connections/ConfigureConnection.jsx

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import {
1010
Intent,
1111
Card,
1212
Elevation,
13+
Popover,
14+
Colors,
1315
} from '@blueprintjs/core'
1416
import Nav from '@/components/Nav'
1517
import Sidebar from '@/components/Sidebar'
@@ -218,7 +220,8 @@ export default function ConfigureConnection () {
218220
</div>
219221
{activeConnection && (
220222
<>
221-
<h2 style={{ margin: 0 }}>{activeConnection.name}</h2>
223+
{activeProvider.id === Providers.JIRA &&
224+
(<h2 style={{ margin: 0 }}>#{activeConnection.ID} {activeConnection.name}</h2>)}
222225
<p className='page-description'>Manage settings and options for this connection.</p>
223226
</>
224227
)}
@@ -246,6 +249,7 @@ export default function ConfigureConnection () {
246249
<div className='editConnection' style={{ display: 'flex' }}>
247250
<ConnectionForm
248251
isValid={isValidForm}
252+
validationErrors={validationErrors}
249253
activeProvider={activeProvider}
250254
name={name}
251255
endpointUrl={endpointUrl}
@@ -285,9 +289,9 @@ export default function ConfigureConnection () {
285289
</p>
286290
</>
287291
)}
288-
{validationErrors.length > 0 && (
292+
{/* {validationErrors.length > 0 && (
289293
<FormValidationErrors errors={validationErrors} />
290-
)}
294+
)} */}
291295
</Card>
292296
<div style={{ marginTop: '30px' }}>
293297
{renderProviderSettings(providerId, activeProvider)}

config-ui/src/pages/configure/connections/ConnectionForm.jsx

Lines changed: 64 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,15 @@ import {
77
Tag,
88
Elevation,
99
Popover,
10+
// PopoverInteractionKind,
1011
Position,
11-
Intent
12+
Intent,
13+
PopoverInteractionKind
1214
} from '@blueprintjs/core'
1315
import { Providers } from '@/data/Providers'
1416
import GenerateTokenForm from '@/pages/configure/connections/GenerateTokenForm'
17+
import FormValidationErrors from '@/components/messages/FormValidationErrors'
18+
import InputValidationError from '@/components/validation/InputValidationError'
1519

1620
import '@/styles/integration.scss'
1721
import '@/styles/connections.scss'
@@ -20,6 +24,7 @@ export default function ConnectionForm (props) {
2024
const {
2125
isLocked = false,
2226
isValid = true,
27+
validationErrors = [],
2328
activeProvider,
2429
name,
2530
endpointUrl,
@@ -83,6 +88,14 @@ export default function ConnectionForm (props) {
8388
setShowTokenCreator(isOpen)
8489
}
8590

91+
const fieldHasError = (fieldId) => {
92+
return validationErrors.some(e => e.includes(fieldId))
93+
}
94+
95+
const getFieldError = (fieldId) => {
96+
return validationErrors.find(e => e.includes(fieldId))
97+
}
98+
8699
useEffect(() => {
87100
if (!allowedAuthTypes.includes(authType)) {
88101
console.log('INVALID AUTH TYPE!')
@@ -158,10 +171,10 @@ export default function ConnectionForm (props) {
158171
label=''
159172
inline={true}
160173
labelFor='connection-name'
161-
className='formGroup'
174+
className='formGroup-inline'
162175
contentClassName='formGroupContent'
163176
>
164-
<Label style={{ display: 'inline' }}>
177+
<Label style={{ display: 'inline', marginRight: 0 }}>
165178
{labels
166179
? labels.name
167180
: (
@@ -176,9 +189,15 @@ export default function ConnectionForm (props) {
176189
placeholder={placeholders ? placeholders.name : 'Enter Instance Name'}
177190
value={name}
178191
onChange={(e) => onNameChange(e.target.value)}
179-
className='input connection-name-input'
192+
className={`input connection-name-input ${fieldHasError('Connection Source') ? 'invalid-field' : ''}`}
180193
leftIcon={[Providers.GITHUB, Providers.GITLAB, Providers.JENKINS].includes(activeProvider.id) ? 'lock' : null}
181-
fill
194+
inline={true}
195+
rightElement={(
196+
<InputValidationError
197+
error={getFieldError('Connection Source')}
198+
/>
199+
)}
200+
// fill
182201
/>
183202
</FormGroup>
184203
</div>
@@ -206,8 +225,13 @@ export default function ConnectionForm (props) {
206225
placeholder={placeholders ? placeholders.endpoint : 'Enter Endpoint URL'}
207226
value={endpointUrl}
208227
onChange={(e) => onEndpointChange(e.target.value)}
209-
className='input'
228+
className={`input endpoint-url-input ${fieldHasError('Endpoint') ? 'invalid-field' : ''}`}
210229
fill
230+
rightElement={(
231+
<InputValidationError
232+
error={getFieldError('Endpoint')}
233+
/>
234+
)}
211235
/>
212236
{/* <a href='#' style={{ margin: '5px 0 5px 5px' }}><Icon icon='info-sign' size='16' /></a> */}
213237
</FormGroup>
@@ -237,9 +261,14 @@ export default function ConnectionForm (props) {
237261
placeholder={placeholders ? placeholders.token : 'Enter Auth Token eg. EJrLG8DNeXADQcGOaaaX4B47'}
238262
value={token}
239263
onChange={(e) => onTokenChange(e.target.value)}
240-
className='input'
264+
className={`input auth-input ${fieldHasError('Auth') ? 'invalid-field' : ''}`}
241265
fill
242266
required
267+
rightElement={(
268+
<InputValidationError
269+
error={getFieldError('Auth')}
270+
/>
271+
)}
243272
/>
244273
{
245274
activeProvider.id === Providers.JIRA &&
@@ -305,8 +334,13 @@ export default function ConnectionForm (props) {
305334
placeholder='Enter Username'
306335
defaultValue={username}
307336
onChange={(e) => onUsernameChange(e.target.value)}
308-
className='input'
309-
style={{ maxWidth: '300px' }}
337+
className={`input username-input ${fieldHasError('Username') ? 'invalid-field' : ''}`}
338+
// style={{ maxWidth: '300px' }}
339+
rightElement={(
340+
<InputValidationError
341+
error={getFieldError('Username')}
342+
/>
343+
)}
310344
/>
311345
</FormGroup>
312346
</div>
@@ -334,8 +368,13 @@ export default function ConnectionForm (props) {
334368
placeholder='Enter Password'
335369
defaultValue={password}
336370
onChange={(e) => onPasswordChange(e.target.value)}
337-
className='input'
338-
style={{ maxWidth: '300px' }}
371+
className={`input password-input ${fieldHasError('Password') ? 'invalid-field' : ''}`}
372+
// style={{ maxWidth: '300px' }}
373+
rightElement={(
374+
<InputValidationError
375+
error={getFieldError('Password')}
376+
/>
377+
)}
339378
/>
340379
</FormGroup>
341380
</div>
@@ -363,7 +402,12 @@ export default function ConnectionForm (props) {
363402
defaultValue={proxy}
364403
onChange={(e) => onProxyChange(e.target.value)}
365404
disabled={isTesting || isSaving || isLocked}
366-
className='input'
405+
className={`input input-proxy ${fieldHasError('Proxy') ? 'invalid-field' : ''}`}
406+
rightElement={(
407+
<InputValidationError
408+
error={getFieldError('Proxy')}
409+
/>
410+
)}
367411
/>
368412
</FormGroup>
369413
</div>
@@ -383,6 +427,14 @@ export default function ConnectionForm (props) {
383427
/>
384428
</div>
385429
<div style={{ display: 'flex' }}>
430+
<div style={{ justifyContent: 'center', padding: '8px' }}>
431+
{validationErrors.length > 0 && (
432+
<Popover interactionKind={PopoverInteractionKind.HOVER_TARGET_ONLY}>
433+
<Icon icon='warning-sign' size={16} color={Colors.RED5} style={{ outline: 'none' }} />
434+
<div style={{ padding: '5px' }}><FormValidationErrors errors={validationErrors} /></div>
435+
</Popover>
436+
)}
437+
</div>
386438
<Button className='btn-cancel' icon='remove' text='Cancel' onClick={onCancel} disabled={isSaving || isTesting} />
387439
<Button
388440
className='btn-save'

config-ui/src/styles/integration.scss

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,4 +114,29 @@ table.connections-table {
114114
background-position: center center;
115115
background-repeat: no-repeat;
116116
background-size: 12px 12px;
117+
}
118+
119+
.configureConnection {
120+
min-width: 690px;
121+
max-width: 860px;
122+
margin-right: auto;
123+
124+
.bp3-input-group {
125+
&.connection-name-input, &.username-input, &.password-input {
126+
min-width: 320px;
127+
width: auto;
128+
max-width: 460px;
129+
}
130+
}
131+
}
132+
133+
.bp3-input-group {
134+
&.invalid-field {
135+
+ label { font-weight: bold }
136+
> input {
137+
box-shadow: rgb(232, 28, 28) 0px 0px 0px 1px, rgba(232, 71, 28, 0.3) 0px 0px 0px 3px, rgba(16, 22, 26, 0.2) 0px 1px 1px 0px inset;
138+
box-sizing: border-box;
139+
background-color: #ffeeee;
140+
}
141+
}
117142
}

0 commit comments

Comments
 (0)