Files
mattermostest/src/renderer/modals/certificate/certificateModal.tsx
Devin Binnie 59e4e7e516 [MM-14058] Add support for i18n (#2190)
* Add language files

* Add react-intl, mmjstool, setup for adding translations

* Translated main module

* Translations for renderer

* A few minor fixes

* More fixes

* Add CI, add missing menu translations, other cleanup

* Added setting to manually select the language of the app

* Force English for E2e

* Unit tests

* Fix mmjstool

* Move set language to before update menu

* PR feedback
2022-07-14 11:04:18 -04:00

244 lines
9.1 KiB
TypeScript

// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved.
// See LICENSE.txt for license information.
import {Certificate} from 'electron/renderer';
import React, {Fragment} from 'react';
import {Modal, Button, Table, Row, Col} from 'react-bootstrap';
import {FormattedMessage} from 'react-intl';
import {CertificateModalData} from 'types/certificate';
import {ModalMessage} from 'types/modals';
import {MODAL_INFO} from 'common/communication';
import IntlProvider from 'renderer/intl_provider';
import ShowCertificateModal from '../../components/showCertificateModal';
type Props = {
onSelect: (cert: Certificate) => void;
onCancel?: () => void;
getCertInfo: () => void;
}
type State = {
selectedIndex?: number;
showCertificate?: Certificate;
url?: string;
list?: Certificate[];
}
export default class SelectCertificateModal extends React.PureComponent<Props, State> {
constructor(props: Props) {
super(props);
this.state = {};
}
componentDidMount() {
window.addEventListener('message', this.handleCertInfoMessage);
this.props.getCertInfo();
}
componentWillUnmount() {
window.removeEventListener('message', this.handleCertInfoMessage);
}
handleCertInfoMessage = (event: {data: ModalMessage<CertificateModalData>}) => {
switch (event.data.type) {
case MODAL_INFO: {
const {url, list} = event.data.data;
this.setState({url, list});
break;
}
default:
break;
}
}
selectfn = (index: number) => {
return (() => {
this.setState({selectedIndex: index});
});
};
renderCert = (cert: Certificate, index: number) => {
const issuer = (cert.issuerName || (cert.issuer && cert.issuer.commonName) || '');
const subject = (cert.subjectName || (cert.subject && cert.subject.commonName) || '');
const serial = cert.serialNumber || '';
return (
<tr
key={`cert-${index}`}
onClick={this.selectfn(index)}
className={this.state.selectedIndex === index ? 'selected' : ''}
>
<td
title={subject}
>{subject}</td>
<td
title={issuer}
>{issuer}</td>
<td
title={serial}
>{serial}</td>
</tr>);
};
renderCerts = (certificateList: Certificate[]) => {
if (certificateList) {
const certs = certificateList.map(this.renderCert);
return (
<Fragment>
{certs}
</Fragment>
);
}
return (<Fragment><tr/><tr><td/><td>
<FormattedMessage
id='renderer.modals.certificate.certificateModal.noCertsAvailable'
defaultMessage='No certificates available'
/>
</td><td/></tr></Fragment>);
}
getSelectedCert = () => {
if (this.state.list && this.state.selectedIndex !== undefined) {
return this.state.list[this.state.selectedIndex];
}
return undefined;
};
handleOk = () => {
const cert = this.getSelectedCert();
if (cert) {
this.props.onSelect(cert);
}
}
handleCertificateInfo = () => {
const certificate = this.getSelectedCert();
this.setState({showCertificate: certificate});
}
certificateInfoClose = () => {
this.setState({showCertificate: undefined});
}
render() {
if (this.state.showCertificate) {
return (
<ShowCertificateModal
certificate={this.state.showCertificate}
onOk={this.certificateInfoClose}
/>
);
}
return (
<IntlProvider>
<Modal
bsClass='modal'
className='certificate-modal'
show={Boolean(this.state.list && this.state.url)}
onHide={() => {}}
>
<Modal.Header>
<Modal.Title>
<FormattedMessage
id='renderer.modals.certificate.certificateModal.title'
defaultMessage='Select a certificate'
/>
</Modal.Title>
</Modal.Header>
<Modal.Body>
<p className={'subtitle'}>
<FormattedMessage
id='renderer.modals.certificate.certificateModal.subtitle'
defaultMessage='Select a certificate to authenticate yourself to {url}'
values={{url: this.state.url}}
/>
</p>
<Table
striped={true}
hover={true}
responsive={true}
className='certificate-list'
tabIndex={1}
>
<thead>
<tr>
<th><span className={'divider'}>
<FormattedMessage
id='renderer.modals.certificate.certificateModal.subject'
defaultMessage='Subject'
/>
</span></th>
<th><span className={'divider'}>
<FormattedMessage
id='renderer.modals.certificate.certificateModal.issuer'
defaultMessage='Issuer'
/>
</span></th>
<th>
<FormattedMessage
id='renderer.modals.certificate.certificateModal.serial'
defaultMessage='Serial'
/>
</th>
</tr>
</thead>
<tbody>
{this.renderCerts(this.state.list!)}
<tr/* this is to correct table height without affecting real rows *//>
</tbody>
</Table>
</Modal.Body>
<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'}
>
<FormattedMessage
id='renderer.modals.certificate.certificateModal.certInfoButton'
defaultMessage='Certificate Information'
/>
</Button>
</Col>
<Col sm={8}>
<Button
variant='link'
onClick={this.props.onCancel}
className={'secondary'}
>
<FormattedMessage
id='label.cancel'
defaultMessage='Cancel'
/>
</Button>
<Button
variant='primary'
onClick={this.handleOk}
disabled={this.state.selectedIndex === null}
className={'primary'}
>
<FormattedMessage
id='label.ok'
defaultMessage='OK'
/>
</Button>
</Col>
</Row>
</div>
</Modal.Footer>
</Modal>
</IntlProvider>
);
}
}