cabana/src/components/SaveDbcModal.js

253 lines
6.6 KiB
JavaScript

import React, { Component } from 'react';
import cx from 'classnames';
import PropTypes from 'prop-types';
import FileSaver from 'file-saver';
import OpenDbc from '../api/OpenDbc';
import DBC from '../models/can/dbc';
import Modal from './Modals/baseModal';
// import TabStyles from '../styles/modal-tabs';
export default class SaveDbcModal extends Component {
static propTypes = {
dbc: PropTypes.instanceOf(DBC).isRequired,
sourceDbcFilename: PropTypes.string.isRequired,
handleClose: PropTypes.func.isRequired,
onDbcSaved: PropTypes.func.isRequired,
openDbcClient: PropTypes.instanceOf(OpenDbc).isRequired,
hasGithubAuth: PropTypes.bool.isRequired,
loginWithGithub: PropTypes.element.isRequired
};
constructor(props) {
super(props);
this.state = {
tab: 'GitHub',
openDbcFork: null,
dbcFilename: this.props.sourceDbcFilename,
tabs: ['GitHub', 'Download'],
commitMessage: 'OpenDBC updates'
};
this.commitToGitHub = this.commitToGitHub.bind(this);
this.downloadDbcFile = this.downloadDbcFile.bind(this);
this.forkOpenDbcAndWait = this.forkOpenDbcAndWait.bind(this);
this.renderForkButton = this.renderForkButton.bind(this);
this.renderTabNavigation = this.renderTabNavigation.bind(this);
this.renderActions = this.renderActions.bind(this);
}
async componentWillMount() {
const openDbcFork = await this.props.openDbcClient.getUserOpenDbcFork();
this.setState({ openDbcFork });
}
async commitToGitHub() {
const { openDbcFork, dbcFilename } = this.state;
const filename = `${dbcFilename.replace(/\.dbc/g, '')}.dbc`;
const success = await this.props.openDbcClient.commitFile(
openDbcFork,
filename,
this.props.dbc.text(),
this.state.commitMessage
);
if (success) {
this.props.onDbcSaved(filename);
}
}
async downloadDbcFile() {
const blob = new Blob([this.props.dbc.text()], {
type: 'text/plain;charset=utf-8'
});
const filename = `${this.state.dbcFilename.replace(/\.dbc/g, '')}.dbc`;
FileSaver.saveAs(blob, filename, true);
}
async forkOpenDbcAndWait() {
const forkResponseSuccess = await this.props.openDbcClient.fork();
if (forkResponseSuccess) {
let isTimedOut = false;
const timeout = window.setTimeout(() => {
isTimedOut = true;
}, 30000);
const interval = window.setInterval(() => {
if (!isTimedOut) {
this.props.openDbcClient.getUserOpenDbcFork().then((openDbcFork) => {
if (openDbcFork !== null) {
this.setState({ openDbcFork });
window.clearInterval(interval);
window.clearTimeout(timeout);
}
});
} else {
window.clearInterval(interval);
}
}, 3000);
} else {
// fork failed
}
}
primaryActionDisabled() {
const { tab } = this.state;
if (tab === 'GitHub') {
return (
this.state.openDbcFork != null && this.state.dbcFilename.length > 0
);
}
if (tab === 'Download') {
return true;
}
}
renderForkButton() {
return (
<button onClick={this.forkOpenDbcAndWait}>
<i className="fa fa-code-fork" />
<span> Fork OpenDBC</span>
</button>
);
}
renderForkStep() {
const { openDbcFork } = this.state;
let content;
if (openDbcFork !== null) {
content = (
<button disabled>
<i className="fa fa-code-fork" />
<span>
{' '}
Forked:
{openDbcFork}
</span>
</button>
);
} else if (this.props.hasGithubAuth) {
content = this.renderForkButton();
} else {
content = this.props.loginWithGithub;
}
return (
<div>
{openDbcFork !== null ? this.renderForkButton() : null}
{content}
<hr />
</div>
);
}
renderFilenameField() {
return (
<div className="form-field" data-extension=".dbc">
<label htmlFor="filename">
<span>Choose a filename:</span>
<sup>Pick a unique name for your car DBC file</sup>
</label>
<input
type="text"
id="filename"
value={this.state.dbcFilename.replace(/\.dbc/g, '')}
size={this.state.dbcFilename.length + 2}
onChange={(e) => this.setState({ dbcFilename: e.target.value })}
/>
</div>
);
}
renderTabNavigation() {
return (
<div className="cabana-tabs-navigation">
{this.state.tabs.map((tab) => (
<button
className={cx({ 'is-active': this.state.tab === tab })}
onClick={() => {
this.setState({ tab });
}}
key={tab}
>
<span>{tab}</span>
</button>
))}
</div>
);
}
renderCommitMessage() {
return (
<div className="form-field">
<label htmlFor="commit-message">
<span>Commit Message:</span>
<sup>Message appears in git logs</sup>
</label>
<input
type="text"
id="commit-message"
value={this.state.commitMessage}
onChange={(e) => this.setState({ commitMessage: e.target.value })}
/>
</div>
);
}
renderTabContent() {
const { tab } = this.state;
if (tab === 'GitHub') {
return (
<div>
{this.renderForkStep()}
{this.renderFilenameField()}
{this.renderCommitMessage()}
</div>
);
}
if (tab === 'Download') {
return <div>{this.renderFilenameField()}</div>;
}
}
renderActions() {
const { tab } = this.state;
if (tab === 'GitHub') {
return (
<div>
<button className="button--inverted" onClick={this.props.handleClose}>
<span>Cancel</span>
</button>
<button className="button--primary" onClick={this.commitToGitHub}>
<span>Commit to GitHub</span>
</button>
</div>
);
}
if (tab === 'Download') {
return (
<div>
<button className="button--inverted" onClick={this.props.handleClose}>
<span>Cancel</span>
</button>
<button className="button--primary" onClick={this.downloadDbcFile}>
<span>Download</span>
</button>
</div>
);
}
}
render() {
return (
<Modal
title="Save DBC File"
subtitle="Save your progress and output to a DBC file"
handleClose={this.props.handleClose}
navigation={this.renderTabNavigation()}
actions={this.renderActions()}
>
{this.renderTabContent()}
</Modal>
);
}
}