[MM-21974] improve CSS for client certificate screens (#1164)
* [MM-21974]make certificate selection look better * fix console errors * wip * first css iteration * css fixes * use single quotes * suggested tweaks * some extra tweaks * remove console.log * Fix CR comments Co-authored-by: Dean Whillier <deanwhillier@users.noreply.github.com>
This commit is contained in:
@@ -7,9 +7,6 @@ import {Modal, Button, Table, Row, Col} from 'react-bootstrap';
|
||||
|
||||
import ShowCertificateModal from './showCertificateModal.jsx';
|
||||
|
||||
const CELL_SIZE = 23;
|
||||
const ELIPSIS_SIZE = 3;
|
||||
|
||||
export default class SelectCertificateModal extends React.Component {
|
||||
static propTypes = {
|
||||
onSelect: PropTypes.func.isRequired,
|
||||
@@ -28,14 +25,6 @@ export default class SelectCertificateModal extends React.Component {
|
||||
};
|
||||
}
|
||||
|
||||
maxSize = (item, max) => {
|
||||
if (!item || item.length <= max) {
|
||||
return item;
|
||||
}
|
||||
const sub = item.substring(0, max - ELIPSIS_SIZE);
|
||||
return `${sub}...`;
|
||||
}
|
||||
|
||||
selectfn = (index) => {
|
||||
return (() => {
|
||||
this.setState({selectedIndex: index});
|
||||
@@ -47,29 +36,21 @@ export default class SelectCertificateModal extends React.Component {
|
||||
const subject = (cert.subjectName || (cert.subject && cert.subject.commonName) || '');
|
||||
const serial = cert.serialNumber || '';
|
||||
|
||||
const issuerShort = this.maxSize(cert.issuer.commonName, CELL_SIZE);
|
||||
const subjectShort = this.maxSize(cert.subject.commonName, CELL_SIZE);
|
||||
const serialShort = this.maxSize(cert.serialNumber, CELL_SIZE);
|
||||
|
||||
const style = this.state.selectedIndex === index ? {background: '#457AB2', color: '#FFFFFF'} : {};
|
||||
return (
|
||||
<tr
|
||||
key={`cert-${index}`}
|
||||
onClick={this.selectfn(index)}
|
||||
style={style}
|
||||
className={this.state.selectedIndex === index ? 'selected' : ''}
|
||||
>
|
||||
<td
|
||||
style={style}
|
||||
title={issuer}
|
||||
>{issuerShort}</td>
|
||||
<td
|
||||
style={style}
|
||||
title={subject}
|
||||
>{subjectShort}</td>
|
||||
>{subject}</td>
|
||||
<td
|
||||
title={issuer}
|
||||
>{issuer}</td>
|
||||
<td
|
||||
style={style}
|
||||
title={serial}
|
||||
>{serialShort}</td>
|
||||
>{serial}</td>
|
||||
</tr>);
|
||||
};
|
||||
|
||||
@@ -119,19 +100,21 @@ export default class SelectCertificateModal extends React.Component {
|
||||
return (
|
||||
<Modal
|
||||
bsClass='modal'
|
||||
className='certificateModal'
|
||||
show={this.props.certificateRequests.length}
|
||||
className='certificate-modal'
|
||||
show={this.props.certificateRequests.length > 0}
|
||||
>
|
||||
<Modal.Header className={'noBorder'}>
|
||||
<Modal.Title className={'bottomBorder'}>{'Select a certificate'}</Modal.Title>
|
||||
<Modal.Header>
|
||||
<Modal.Title >{'Select a certificate'}</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<p className={'subtitle'}>{`Select a certificate to authenticate yourself to ${server}`}</p>
|
||||
<Table
|
||||
stripped={'true'}
|
||||
striped={true}
|
||||
hover={true}
|
||||
size={'sm'}
|
||||
className='certificateList'
|
||||
responsive={true}
|
||||
className='certificate-list'
|
||||
tabIndex={1}
|
||||
>
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -146,30 +129,32 @@ export default class SelectCertificateModal extends React.Component {
|
||||
</tbody>
|
||||
</Table>
|
||||
</Modal.Body>
|
||||
<Modal.Footer className={'noBorder'}>
|
||||
<Row className={'topBorder'}>
|
||||
<Col sm={4}>
|
||||
<Button
|
||||
variant={'info'}
|
||||
disabled={this.state.selectedIndex === null}
|
||||
onClick={this.handleCertificateInfo}
|
||||
className={'info'}
|
||||
>{'Certificate Information'}</Button>
|
||||
</Col>
|
||||
<Col sm={8}>
|
||||
<Button
|
||||
onClick={this.props.onCancel}
|
||||
variant={'secondary'}
|
||||
className={'secondary'}
|
||||
>{'Cancel'}</Button>
|
||||
<Button
|
||||
variant={'primary'}
|
||||
onClick={this.handleOk}
|
||||
disabled={this.state.selectedIndex === null}
|
||||
className={'primary'}
|
||||
>{'Ok'}</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
<Modal.Footer className={'no-border'}>
|
||||
<div className={'container-fluid'}>
|
||||
<Row>
|
||||
<Col sm={4}>
|
||||
<Button
|
||||
variant={'info'}
|
||||
disabled={this.state.selectedIndex === null}
|
||||
onClick={this.handleCertificateInfo}
|
||||
className={'info'}
|
||||
>{'Certificate Information'}</Button>
|
||||
</Col>
|
||||
<Col sm={8}>
|
||||
<Button
|
||||
onClick={this.props.onCancel}
|
||||
variant={'secondary'}
|
||||
className={'secondary'}
|
||||
>{'Cancel'}</Button>
|
||||
<Button
|
||||
variant={'primary'}
|
||||
onClick={this.handleOk}
|
||||
disabled={this.state.selectedIndex === null}
|
||||
className={'primary'}
|
||||
>{'OK'}</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
);
|
||||
|
@@ -3,7 +3,7 @@
|
||||
|
||||
import React, {Fragment} from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import {Modal, Button, Row} from 'react-bootstrap';
|
||||
import {Modal, Button, Row, Col} from 'react-bootstrap';
|
||||
|
||||
export default class ShowCertificateModal extends React.Component {
|
||||
static propTypes = {
|
||||
@@ -24,20 +24,30 @@ export default class ShowCertificateModal extends React.Component {
|
||||
}
|
||||
|
||||
render() {
|
||||
const certificateSection = (descriptor) => {
|
||||
return (
|
||||
<Fragment>
|
||||
<dt className={'certificate-key'}>{descriptor}</dt>
|
||||
<dd className={'certificate-section'}><span/></dd>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
const certificateItem = (descriptor, value) => {
|
||||
const ddclass = value ? '' : 'emtpyDescriptor';
|
||||
const val = value ? `${value}` : <span/>;
|
||||
return (
|
||||
<Fragment>
|
||||
<dt>{descriptor}</dt>
|
||||
<dd className={ddclass}>{val}</dd>
|
||||
<dt className={'certificate-key'}>{descriptor}</dt>
|
||||
<dd className={'certificate-value'}>{val}</dd>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
if (this.state.certificate === null) {
|
||||
return (
|
||||
<Modal>
|
||||
<Modal
|
||||
bsClass='modal'
|
||||
className='show-certificate'
|
||||
>
|
||||
<Modal.Body>
|
||||
{'No certificate Selected'}
|
||||
</Modal.Body>
|
||||
@@ -58,38 +68,45 @@ export default class ShowCertificateModal extends React.Component {
|
||||
return (
|
||||
<Modal
|
||||
bsClass='modal'
|
||||
className='certificateModal'
|
||||
className='show-certificate'
|
||||
show={this.state.certificate !== null}
|
||||
scrollable={true}
|
||||
scrollable={'true'}
|
||||
>
|
||||
<Modal.Header className={'noBorder'}>
|
||||
<Modal.Title className={'bottomBorder'}>{'Certificate Information'}</Modal.Title>
|
||||
<Modal.Header className={'no-border'}>
|
||||
<Modal.Title>{'Certificate information'}</Modal.Title>
|
||||
</Modal.Header>
|
||||
<Modal.Body>
|
||||
<h3 className={'certificateKey'}>{`${this.state.certificate.subject.commonName}`}</h3>
|
||||
<p className={'certInfo'}>{`Issued by: ${this.state.certificate.issuer.commonName}`}</p>
|
||||
<p className={'certInfo'}>{`Expires: ${expiration.toLocaleString(dateLocale, dateDisplayOptions)}`}</p>
|
||||
<p>{'Details'}</p>
|
||||
<p className='details'>{'Details'}</p>
|
||||
<dl>
|
||||
{certificateItem('Subject Name')}
|
||||
{certificateSection('Subject Name')}
|
||||
{certificateItem('Common Name', this.state.certificate.subject.commonName)}
|
||||
{certificateItem('Issuer Name')}
|
||||
</dl>
|
||||
<dl>
|
||||
{certificateSection('Issuer Name')}
|
||||
{certificateItem('Common Name', this.state.certificate.issuer.commonName)}
|
||||
</dl>
|
||||
<dl>
|
||||
{certificateItem('Serial Number', this.state.certificate.serialNumber)}
|
||||
{certificateItem('Not Valid Before', creation.toLocaleString(dateLocale, dateDisplayOptions))}
|
||||
{certificateItem('Not Valid After', expiration.toLocaleString(dateLocale, dateDisplayOptions))}
|
||||
{certificateItem('Public Key Info')}
|
||||
</dl>
|
||||
<dl>
|
||||
{certificateSection('Public Key Info')}
|
||||
{certificateItem('Algorithm', this.state.certificate.fingerprint.split('/')[0])}
|
||||
</dl>
|
||||
</Modal.Body>
|
||||
<Modal.Footer className={'noBorder'}>
|
||||
<Row className={'topBorder'}>
|
||||
<Button
|
||||
variant={'primary'}
|
||||
onClick={this.handleOk}
|
||||
className={'primary'}
|
||||
>{'Close'}</Button>
|
||||
</Row>
|
||||
<Modal.Footer className={'no-border'}>
|
||||
<div className='container-fluid'>
|
||||
<Row>
|
||||
<Col>
|
||||
<Button
|
||||
variant={'primary'}
|
||||
onClick={this.handleOk}
|
||||
className={'primary'}
|
||||
>{'Close'}</Button>
|
||||
</Col>
|
||||
</Row>
|
||||
</div>
|
||||
</Modal.Footer>
|
||||
</Modal>
|
||||
);
|
||||
|
@@ -1,121 +1,210 @@
|
||||
.certificateModal dialog {
|
||||
.certificate-modal .modal,
|
||||
.show-certificate .modal {
|
||||
background-color: aliceblue;
|
||||
margin-top: 40px;
|
||||
}
|
||||
|
||||
.certificateList thead {
|
||||
.show-certificate .modal-dialog {
|
||||
width: 800px;
|
||||
}
|
||||
.modal-header {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
.modal-header::after {
|
||||
border-bottom: solid 1px #E5E5E5;
|
||||
width: 100%;
|
||||
transform: translateY(15px);
|
||||
}
|
||||
.modal-footer::before {
|
||||
border-top: solid 1px #E5E5E5;
|
||||
width: 100%;
|
||||
transform: translateY(-15px);
|
||||
}
|
||||
.modal-body :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.certificate-modal .col-sm-4 {
|
||||
padding: 0px;
|
||||
text-align: left;
|
||||
}
|
||||
.certificate-modal .col-sm-8 {
|
||||
padding: 0px;
|
||||
}
|
||||
|
||||
.certificate-list thead {
|
||||
width: 557.89px;
|
||||
height: 22px;
|
||||
}
|
||||
.certificateList thead>tr>th {
|
||||
font-family: Helvetica Neue;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
padding: 2px;
|
||||
border-bottom: 1px solid #CCCCCC;
|
||||
color: #333333;
|
||||
|
||||
}
|
||||
|
||||
.certificateList tbody>tr>td {
|
||||
width: 227.17px;
|
||||
height: 47px;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 17px;
|
||||
|
||||
color: #555555;
|
||||
.certificate-list thead>tr {
|
||||
padding: 0px 5px;
|
||||
}
|
||||
|
||||
table.certificateList {
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #CCCCCC;
|
||||
box-sizing: border-box;
|
||||
box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.0008);
|
||||
border-radius: 4px;
|
||||
border-collapse: unset;
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
.certificateModal button {
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #CCCCCC;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
padding: 9px 12px;
|
||||
}
|
||||
|
||||
.certificateModal button:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.certificateModal button.primary {
|
||||
background: #457AB2;
|
||||
color: #FFFFFF;
|
||||
border: 1px solid #2E6DA4;
|
||||
}
|
||||
.certificateModal button.info {
|
||||
color: #457AB2;
|
||||
}
|
||||
|
||||
.certificateModal button.primary:hover {
|
||||
background: #659AD2;
|
||||
}
|
||||
|
||||
.certificateModal .subtitle {
|
||||
color: #737373;
|
||||
margin: 0px 15px 10px;
|
||||
}
|
||||
|
||||
.certificateModal .bottomBorder {
|
||||
padding-bottom: 10px;
|
||||
border-bottom: 1px solid #CCCCCC;
|
||||
}
|
||||
|
||||
.certificateModal .topBorder {
|
||||
border-top: 1px solid #CCCCCC;
|
||||
margin: 0 1px 0 1px;
|
||||
padding-top: 15px;
|
||||
}
|
||||
.certificateModal .noBorder {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.divider {
|
||||
border-right: 1px solid #CCCCCC;
|
||||
display: block;
|
||||
}
|
||||
|
||||
.certificateModal dt, dd {
|
||||
float: left;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.certificateModal dt { clear:both }
|
||||
|
||||
.certificateModal dl {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.certificateKey {
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 17px;
|
||||
|
||||
color: #737373;
|
||||
}
|
||||
|
||||
.certInfo {
|
||||
.certificate-list thead>tr>th {
|
||||
font-family: Helvetica Neue;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
line-height: 18px;
|
||||
padding: 3px 5px;
|
||||
border-bottom: 1px solid #CCCCCC;
|
||||
color: #333333;
|
||||
height: 22px;
|
||||
}
|
||||
|
||||
.certificate-list thead tr th:first-child span {
|
||||
padding-left: 5px;
|
||||
}
|
||||
.certificate-list thead tr th span {
|
||||
border-right: solid 1px #E5E5E5;
|
||||
display: block;
|
||||
}
|
||||
.certificate-list thead tr th:last-child span {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.certificate-list tbody tr {
|
||||
user-select: none;
|
||||
cursor: pointer;
|
||||
color: #555555;
|
||||
}
|
||||
|
||||
.certificate-list tbody>tr>td {
|
||||
max-width: 165px;
|
||||
height: 47px;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 14px;
|
||||
line-height: 17px;
|
||||
padding: 15px 10px;
|
||||
white-space: nowrap;
|
||||
overflow-x: hidden;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
|
||||
.certificate-list tbody tr td:first-child {
|
||||
padding-left: 15px;
|
||||
max-width: 227px;
|
||||
}
|
||||
|
||||
.certificate-list tbody tr.selected {
|
||||
background: #457AB2;
|
||||
color: #FFFFFF;
|
||||
}
|
||||
|
||||
table.certificate-list {
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #CCCCCC;
|
||||
border-radius: 4px;
|
||||
border-collapse: unset;
|
||||
box-shadow: inset 0px 1px 1px rgba(0, 0, 0, 0.0008);
|
||||
height: 150px;
|
||||
}
|
||||
|
||||
table.certificate-list:focus {
|
||||
border: 1px solid #66AFE9;
|
||||
box-sizing: border-box;
|
||||
box-shadow: 0px 0px 8px rgba(102, 175, 233, 0.6), inset 1px 1px 0px rgba(0, 0, 0, 0.00075);
|
||||
}
|
||||
|
||||
|
||||
.show-certificate button,
|
||||
.certificate-modal button {
|
||||
background: #FFFFFF;
|
||||
border: 1px solid #CCCCCC;
|
||||
box-sizing: border-box;
|
||||
border-radius: 4px;
|
||||
padding: 9px 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.show-certificate button:disabled,
|
||||
.certificate-modal button:disabled {
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.show-certificate button.primary,
|
||||
.certificate-modal button.primary {
|
||||
background: #457AB2;
|
||||
color: #FFFFFF;
|
||||
border: 1px solid #2E6DA4;
|
||||
}
|
||||
|
||||
|
||||
.show-certificate button.primary:hover,
|
||||
.certificate-modal button.primary:hover {
|
||||
background: #659AD2;
|
||||
}
|
||||
|
||||
.certificate-modal button.info {
|
||||
color: #457AB2;
|
||||
}
|
||||
|
||||
.certificate-modal button.info:disabled {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.show-certificate .subtitle,
|
||||
.certificate-modal .subtitle {
|
||||
color: #737373;
|
||||
margin: 0px 0px 15px 0px;
|
||||
}
|
||||
|
||||
.show-certificate .no-border,
|
||||
.certificate-modal .no-border {
|
||||
border: none;
|
||||
}
|
||||
|
||||
.show-certificate dl {
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.show-certificate dt, dd {
|
||||
float: left;
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.show-certificate dt {
|
||||
width: 150px;
|
||||
clear:both
|
||||
}
|
||||
|
||||
.show-certificate dd {
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.certificate-key {
|
||||
font-style: normal;
|
||||
font-weight: bold;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
color: #333333;
|
||||
text-align: right;
|
||||
}
|
||||
.certificate-value {
|
||||
padding-top: 1px;
|
||||
font-style: normal;
|
||||
font-weight: normal;
|
||||
font-size: 12px;
|
||||
line-height: 14px;
|
||||
text-align: left;
|
||||
color: #333333;
|
||||
}
|
||||
|
||||
.emtpyDescriptor {
|
||||
border-bottom: 1px solid #CCCCCC;
|
||||
.certificate-section {
|
||||
border-bottom: 1px solid #E5E5E5;
|
||||
width: 598px;
|
||||
height: 8px;
|
||||
}
|
||||
|
||||
.show-certificate .details {
|
||||
margin: 15px;
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
font-size: 12px;
|
||||
line-height: 15px;
|
||||
color: #333333;
|
||||
}
|
Reference in New Issue
Block a user