Component refactoring

This commit is contained in:
Scott E. Graves
2018-10-03 14:54:05 -05:00
parent b4aa381023
commit b430465b7b
15 changed files with 390 additions and 128 deletions

View File

@@ -21,7 +21,7 @@ let mountedPIDs = [];
function createWindow() { function createWindow() {
// Create the browser window. // Create the browser window.
const height = process.env.ELECTRON_START_URL ? 340 : 320; const height = process.env.ELECTRON_START_URL ? 344 : 324;
mainWindow = new BrowserWindow({ mainWindow = new BrowserWindow({
width: 425, width: 425,
height: height, height: height,

View File

@@ -2,16 +2,17 @@ import React, {Component} from 'react';
import axios from 'axios'; import axios from 'axios';
import styles from './App.css'; import styles from './App.css';
import Box from './components/UI/Box/Box'; import Box from './components/UI/Box/Box';
import Button from './components/UI/Button/Button';
import Configuration from './containers/Configuration/Configuration'; import Configuration from './containers/Configuration/Configuration';
import CSSModules from 'react-css-modules'; import CSSModules from 'react-css-modules';
import DependencyList from './components/DependencyList/DependencyList'; import DependencyList from './components/DependencyList/DependencyList';
import DownloadProgress from './components/DownloadProgress/DownloadProgress'; import DownloadProgress from './components/DownloadProgress/DownloadProgress';
import DropDown from './components/UI/DropDown/DropDown';
import ErrorDetails from './components/ErrorDetails/ErrorDetails'; import ErrorDetails from './components/ErrorDetails/ErrorDetails';
import Grid from './components/UI/Grid/Grid';
import Loading from './components/UI/Loading/Loading'; import Loading from './components/UI/Loading/Loading';
import Modal from './components/UI/Modal/Modal'; import Modal from './components/UI/Modal/Modal';
import MountItems from './containers/MountItems/MountItems'; import MountItems from './containers/MountItems/MountItems';
import ReleaseVersionDisplay from './components/ReleaseVersionDisplay/ReleaseVersionDisplay';
import Text from './components/UI/Text/Text';
import UpgradeIcon from './components/UpgradeIcon/UpgradeIcon'; import UpgradeIcon from './components/UpgradeIcon/UpgradeIcon';
import UpgradeUI from './components/UpgradeUI/UpgradeUI'; import UpgradeUI from './components/UpgradeUI/UpgradeUI';
@@ -44,11 +45,11 @@ class App extends Component {
} }
state = { state = {
AllowOptions: false,
AllowDownload: false, AllowDownload: false,
AutoMountProcessed: false, AutoMountProcessed: false,
ConfigStorageType: null, ConfigStorageType: null,
DisplayError: false, DisplayError: false,
DisplayMainContent: false,
Error: null, Error: null,
ErrorAction: null, ErrorAction: null,
ErrorCritical: false, ErrorCritical: false,
@@ -74,7 +75,7 @@ class App extends Component {
'Beta', 'Beta',
'Alpha', 'Alpha',
], ],
RepertoryVersion: 'none', InstalledVersion: 'none',
Sia: { Sia: {
AutoMount: false, AutoMount: false,
MountLocation: '', MountLocation: '',
@@ -305,10 +306,10 @@ class App extends Component {
onCheckInstalledReply = (event, arg) => { onCheckInstalledReply = (event, arg) => {
const action = () => { const action = () => {
const repertoryVersion = arg.data.Success && arg.data.Exists ? arg.data.Version : 'none'; const installedVersion = arg.data.Success && arg.data.Exists ? arg.data.Version : 'none';
let versionAvailable = false; let versionAvailable = false;
if (repertoryVersion !== 'none') { if (installedVersion !== 'none') {
const latestVersion = this.state.VersionLookup[this.state.ReleaseTypes[this.state.Release]].length - 1; const latestVersion = this.state.VersionLookup[this.state.ReleaseTypes[this.state.Release]].length - 1;
let version = this.state.Version; let version = this.state.Version;
if (version === -1) { if (version === -1) {
@@ -321,7 +322,7 @@ class App extends Component {
AllowDownload: true, AllowDownload: true,
DownloadingDependency: false, DownloadingDependency: false,
MissingDependencies: arg.data.Dependencies, MissingDependencies: arg.data.Dependencies,
RepertoryVersion: repertoryVersion, InstalledVersion: installedVersion,
VersionAvailable: versionAvailable, VersionAvailable: versionAvailable,
}); });
}; };
@@ -430,7 +431,7 @@ class App extends Component {
} }
this.setState({ this.setState({
AllowOptions: true, DisplayMainContent: true,
LocationsLookup: locationsLookup, LocationsLookup: locationsLookup,
Version: version, Version: version,
VersionAvailable: version !== latestVersion, VersionAvailable: version !== latestVersion,
@@ -551,9 +552,9 @@ class App extends Component {
!this.state.MountsBusy && !this.state.MountsBusy &&
!this.state.DownloadActive && !this.state.DownloadActive &&
(selectedVersion !== 'unavailable') && (selectedVersion !== 'unavailable') &&
(selectedVersion !== this.state.RepertoryVersion); (selectedVersion !== this.state.InstalledVersion);
const allowMount = this.state.RepertoryVersion !== 'none'; const allowMount = this.state.InstalledVersion !== 'none';
const missingDependencies = (this.state.MissingDependencies.length > 0); const missingDependencies = (this.state.MissingDependencies.length > 0);
const allowConfig = this.state.LocationsLookup[selectedVersion] && const allowConfig = this.state.LocationsLookup[selectedVersion] &&
this.state.LocationsLookup[selectedVersion].config_support; this.state.LocationsLookup[selectedVersion].config_support;
@@ -596,23 +597,6 @@ class App extends Component {
); );
} }
let mountDisplay = null;
if (allowMount) {
mountDisplay = <MountItems allowConfig={allowConfig}
autoMountChanged={this.handleAutoMountChanged}
autoMountProcessed={this.notifyAutoMountProcessed}
changed={this.handleMountLocationChanged}
configClicked={this.handleConfigClicked}
directory={Constants.DATA_LOCATIONS[this.props.platform]}
errorHandler={this.setErrorState}
hyperspace={this.state.Hyperspace}
mountsBusy={this.notifyMountsBusy}
platform={this.props.platform}
processAutoMount={!this.state.AutoMountProcessed}
sia={this.state.Sia}
version={this.state.RepertoryVersion}/>;
}
let dependencyDisplay = null; let dependencyDisplay = null;
if (showDependencies) { if (showDependencies) {
dependencyDisplay = ( dependencyDisplay = (
@@ -634,14 +618,6 @@ class App extends Component {
</Modal>); </Modal>);
} }
let releaseDisplay = null;
if (this.state.ExtractActive) {
releaseDisplay = <h3 style={{textAlign: 'center'}}>{'Activating <' + selectedVersion + '>'}</h3>
} else {
releaseDisplay = <Button clicked={this.handleReleaseDownload}
disabled={!downloadEnabled}>Install</Button>;
}
let upgradeDisplay = null; let upgradeDisplay = null;
if (showUpgrade) { if (showUpgrade) {
upgradeDisplay = ( upgradeDisplay = (
@@ -652,53 +628,47 @@ class App extends Component {
); );
} }
let mainContent = null; let mainContent = [];
if (this.state.AllowOptions) { if (this.state.DisplayMainContent) {
mainContent = ( let key = 0;
<table width='100%' cellPadding='2'> mainContent.push((
<tbody> <div key={'rvd_' + key++}
<tr> style={{height: '40%'}}>
<td width='33.333%'> <ReleaseVersionDisplay disabled={this.state.DownloadActive || this.state.ExtractActive || this.state.MountsBusy}
<h2>Release</h2> downloadClicked={this.handleReleaseDownload}
</td> downloadDisabled={!downloadEnabled}
<td width='33.333%'> installedVersion={this.state.InstalledVersion}
<h2>Version<UpgradeIcon release={this.state.Release}
release releaseChanged={this.handleReleaseChanged}
available={this.state.VersionAvailable}/></h2> releaseExtracting={this.state.ExtractActive}
</td> releaseTypes={this.state.ReleaseTypes}
<td width='33.333%'> version={this.state.Version}
<h2>Installed</h2> versionAvailable={this.state.VersionAvailable}
</td> versionChanged={this.handleVersionChanged}
</tr> versions={this.state.VersionLookup[this.state.ReleaseTypes[this.state.Release]]}/>
<tr> </div>
<td> ));
<DropDown changed={this.handleReleaseChanged}
disabled={this.state.DownloadActive || this.state.ExtractActive || this.state.MountsBusy} if (allowMount) {
items={this.state.ReleaseTypes} mainContent.push((
selected={this.state.Release}/> <div key={'md_' + key++}
</td> style={{height: '60%'}}>
<td> <MountItems allowConfig={allowConfig}
<DropDown changed={this.handleVersionChanged} autoMountChanged={this.handleAutoMountChanged}
disabled={this.state.DownloadActive || this.state.ExtractActive || this.state.MountsBusy} autoMountProcessed={this.notifyAutoMountProcessed}
items={this.state.VersionLookup[this.state.ReleaseTypes[this.state.Release]]} changed={this.handleMountLocationChanged}
selected={this.state.Version}/> configClicked={this.handleConfigClicked}
</td> directory={Constants.DATA_LOCATIONS[this.props.platform]}
<td> errorHandler={this.setErrorState}
{this.state.RepertoryVersion} hyperspace={this.state.Hyperspace}
</td> mountsBusy={this.notifyMountsBusy}
</tr> platform={this.props.platform}
<tr> processAutoMount={!this.state.AutoMountProcessed}
<td colSpan={3}> sia={this.state.Sia}
{releaseDisplay} version={this.state.InstalledVersion}/>
</td> </div>
</tr> ));
<tr> }
<td colSpan={3}>
{mountDisplay}
</td>
</tr>
</tbody>
</table>);
} else { } else {
mainContent = <Loading/> mainContent = <Loading/>
} }
@@ -710,32 +680,25 @@ class App extends Component {
{upgradeDisplay} {upgradeDisplay}
{downloadDisplay} {downloadDisplay}
{configDisplay} {configDisplay}
<Box dxStyle={{height: '9.3%', padding: '2px'}}> <Box dxStyle={{height: '28px'}}>
<table cellPadding={0} <Grid>
cellSpacing={0} <Text col={0}
style={{margin: 0, padding: 0}} row={0}
width='100%'> colSpan={'remain'}
<tbody style={{margin: 0, padding: 0}}> rowSpan={'remain'}
<tr style={{margin: 0, padding: 0}}> text={'Repertory UI v' + this.props.version}
<td style={{margin: 0, padding: 0}} textAlign={'center'}
width='33.333%'/> type={'Heading1'}/>
<td style={{margin: 0, padding: 0}} <UpgradeIcon
width='33.333%'> available={!this.state.UpgradeAvailable}
<h1 style={{'textAlign': 'center'}}>{'Repertory UI v' + this.props.version}</h1> clicked={()=>this.setState({UpgradeDismissed: false})}
</td> col={dimensions => dimensions.columns - 7}
<td align='right' colSpan={6}
style={{margin: 0, padding: 0}} row={0}
valign='middle' rowSpan={'remain'}/>
width='33.333%'> </Grid>
<UpgradeIcon
available={this.state.UpgradeAvailable}
clicked={()=>this.setState({UpgradeDismissed: false})}/>
</td>
</tr>
</tbody>
</table>
</Box> </Box>
<Box dxStyle={{padding: '4px', marginTop: '10px', height: '90.7%'}}> <Box dxStyle={{padding: '8px', marginTop: '10px', height: '238px'}}>
{mainContent} {mainContent}
</Box> </Box>
</div> </div>

View File

@@ -0,0 +1,74 @@
import React from 'react';
import styles from './ReleaseVersionDisplay.css';
import CSSModules from 'react-css-modules';
import DropDown from '../UI/DropDown/DropDown';
import Grid from '../UI/Grid/Grid';
import Text from '../UI/Text/Text';
import Button from '../UI/Button/Button';
import UpgradeIcon from '../UpgradeIcon/UpgradeIcon';
export default CSSModules((props) => {
let optionsDisplay = null;
if (props.releaseExtracting) {
optionsDisplay = <Text align='center'
row={13}
rowSpan={7}
colSpan={'remain'}
text={'Activating <' + props.installedVersion + '>'}/>
} else {
optionsDisplay = <Button clicked={props.downloadClicked}
colSpan={20}
disabled={props.downloadDisabled}
row={13}
rowSpan={7}>Install</Button>;
}
return (
<Grid>
<Text colSpan={columns=>columns / 3}
rowSpan={4}
text={'Release'}
textAlign={'left'}
type={'Heading2'}/>
<DropDown changed={props.releaseChanged}
colSpan={remain=>remain / 3 - 1}
disabled={props.disabled}
items={props.releaseTypes}
row={5}
rowSpan={7}
selected={props.release}/>
<Text col={dimensions => dimensions.columns / 3}
colSpan={remain=>remain / 2}
rowSpan={4}
text={'Version'}
textAlign={'left'}
type={'Heading2'}/>
<UpgradeIcon available={props.versionAvailable}
col={dimensions => ((dimensions.columns / 3) * 2) - 6}
colSpan={4}
release
rowSpan={4}/>
<DropDown changed={props.versionChanged}
col={dimensions => dimensions.columns / 3}
colSpan={remain=>remain / 2 - 1}
disabled={props.disabled}
items={props.versions}
row={5}
rowSpan={7}
selected={props.version}/>
<Text col={dimensions => (dimensions.columns / 3) * 2}
colSpan={'remain'}
rowSpan={4}
text={'Installed'}
textAlign={'left'}
type={'Heading2'}/>
<Text col={dimensions => (dimensions.columns / 3) * 2}
colSpan={'remain'}
row={5}
rowSpan={7}
text={props.installedVersion}
textAlign={'left'}/>
{optionsDisplay}
</Grid>
);
}, styles, {allowMultiple: true});

View File

@@ -10,7 +10,8 @@
border: none; border: none;
text-decoration: none; text-decoration: none;
text-outline: none; text-outline: none;
width: 70px; height: 100%;
width: 100%;
} }
.Button:hover:enabled { .Button:hover:enabled {

View File

@@ -1,5 +1,7 @@
.DropDown { .DropDown {
display: block;
width: 100%; width: 100%;
height: 100%;
margin: 0; margin: 0;
padding: 0; padding: 0;
} }

View File

@@ -0,0 +1,18 @@
.Grid {
margin: 0;
padding: 0;
display: grid;
box-sizing: border-box;
height: 100%;
width: 100%;
overflow-y: auto;
overflow-x: auto;
}
.GridOwner {
padding: 0;
margin: 0;
width: 100%;
height: 100%;
box-sizing: border-box;
}

View File

@@ -0,0 +1,121 @@
import React, {Component} from 'react';
import CSSModules from 'react-css-modules';
import styles from './Grid.css';
import GridComponent from './GridComponent/GridComponent';
export default CSSModules(class extends Component {
constructor(props) {
super(props);
window.addEventListener("resize", this.updateSizeAsync);
}
state = {
calculated: false,
dimensions: {
columns: 0,
rows: 0
}
};
calculateDimensions = (size) => {
return {
columns: Math.floor(size.width / 4),
rows: Math.floor(size.height / 4)
};
};
getSize = () => {
const elem = this.refs.GridOwner;
return {
height: elem ? elem.clientHeight : 0,
width: elem ? elem.clientWidth : 0
};
};
updateSize = () => {
const state = {
...this.state
};
const size = this.getSize();
const dimensions = this.calculateDimensions(size);
if (state.dimensions !== dimensions) {
this.setState({
calculated: true,
dimensions: dimensions
})
}
};
updateSizeAsync = () => {
return new Promise((done) => {
this.updateSize();
done();
});
};
componentDidMount = () => {
this.updateSizeAsync();
};
componentWillUnmount = () => {
window.removeEventListener("resize", this.updateSizeAsync);
};
render() {
let children = null;
const dimensions = this.state.dimensions;
if (this.state.calculated) {
children = React.Children.map(this.props.children, (child, i) => {
let row = child.props.row || 0;
if (typeof(row) === 'function') {
row = row(dimensions);
}
let col = child.props.col || 0;
if (typeof(col) === 'function') {
col = col(dimensions);
}
let rowSpan = child.props.rowSpan;
if (typeof(rowSpan) === 'function') {
rowSpan = rowSpan(dimensions.rows - row, dimensions.rows);
}
let colSpan = child.props.colSpan;
if (typeof(colSpan) === 'function') {
colSpan = colSpan(dimensions.columns - col, dimensions.columns);
}
rowSpan = rowSpan ? (rowSpan === 'remain' ? (dimensions.rows - row) : rowSpan) : null;
colSpan = colSpan ? (colSpan === 'remain' ? dimensions.columns - col : colSpan) : null;
return <GridComponent
row={row}
col={col}
rowSpan={rowSpan}
colSpan={colSpan}
key={'gc_' + i}>{child}</GridComponent>;
});
}
const style = {
style: {
gridTemplateColumns: '4px '.repeat(dimensions.columns).trim(),
gridTemplateRows: '4px '.repeat(dimensions.rows).trim(),
gridAutoColumns: '4px',
gridAutoRows: '4px'
}
};
return (
<div
ref='GridOwner'
styleName='GridOwner'>
<div styleName='Grid' {...style}>
{children}
</div>
</div>
)
};
}, styles, {allowMultiple: true});

View File

@@ -0,0 +1,7 @@
.GridComponent {
padding: 0;
margin: 0;
display: flex;
justify-content: center;
align-items: center;
}

View File

@@ -0,0 +1,21 @@
import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './GridComponent.css';
export default CSSModules((props) => {
const style = {
style: {
gridRowStart: Math.floor(props.row + 1),
gridRowEnd: 'span ' + Math.floor(props.rowSpan || 1),
gridColumnStart: Math.floor(props.col + 1),
gridColumnEnd: 'span ' + Math.floor(props.colSpan || 1)
}
};
return (
<div styleName='GridComponent' {...style}>
{props.children}
</div>
);
}, styles, {allowMultiple: true});

View File

@@ -0,0 +1,39 @@
.TextOwner {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
display: flex;
justify-content: center;
align-content: center;
flex-direction: column;
}
.Text {
display: inline-block;
padding: 0;
margin: 0;
text-decoration: none;
text-align: center;
vertical-align: center;
color: var(--text_color);
}
.Heading1 {
font-weight: bold;
color: var(--heading_text_color);
}
.Heading2 {
font-weight: bold;
color: var(--heading_other_text_color);
}
.Heading3 {
font-weight: bold;
color: var(--heading_other_text_color);
}
.AltTextColor {
color: var(--heading_other_text_color);
}

View File

@@ -0,0 +1,28 @@
import React from 'react';
import CSSModules from 'react-css-modules';
import styles from './Text.css';
export default CSSModules((props) => {
const styleList = [];
styleList.push('Text');
if (props.type) {
styleList.push(props.type);
}
let style = {...props.style};
if (props.textAlign) {
style['textAlign'] = props.textAlign.toLowerCase();
}
const text = (
<div
styleName={styleList.join(' ')}
style={style}>{props.text}
</div>);
return props.noOwner ? text : (
<div styleName={'TextOwner'}>
{text}
</div>);
}, styles, {allowMultiple: true});

View File

@@ -1,26 +1,21 @@
.Owner { .Owner {
display: block;
margin-right: 2px;
padding: 0; padding: 0;
width: 20px; margin: 0;
height: 20px; width: 100%;
height: 100%;
border: 0; border: 0;
box-sizing: border-box; box-sizing: border-box;
cursor: pointer; cursor: pointer;
} }
.Owner p {
margin: 0;
padding: 0;
}
.UpgradeIcon { .UpgradeIcon {
display: block; display: block;
margin: 0; margin: 0;
padding: 0; padding: 0;
object-fit: contain;
border: 0; border: 0;
width: 20px; max-width: 100%;
height: 20px; max-height: 100%;
box-sizing: border-box; box-sizing: border-box;
opacity: 0.65; opacity: 0.65;
} }

View File

@@ -5,27 +5,21 @@ import availableImage from '../../assets/images/release_available.png';
import ReactTooltip from 'react-tooltip'; import ReactTooltip from 'react-tooltip';
export default CSSModules((props) => { export default CSSModules((props) => {
let style;
let style2;
let placement = 'left'; let placement = 'left';
let toolTipText = 'UI Upgrade Available'; let toolTipText = 'UI Upgrade Available';
if (props.release) { if (props.release) {
placement='bottom'; placement='bottom';
toolTipText = 'New Release Available'; toolTipText = 'New Release Available';
style = {float: 'right', marginRight: '5%', width: '15px', height: '15px', cursor: 'default'};
style2 = {width: '15px', height: '15px'};
} }
return props return props
.available ? .available ?
( (
<div style={style} <div styleName='Owner'>
styleName='Owner'>
<p data-tip='' data-for={placement}> <p data-tip='' data-for={placement}>
<img alt='' <img alt=''
onClick={props.clicked} onClick={props.clicked}
src={availableImage} src={availableImage}
style={style2}
styleName='UpgradeIcon'/> styleName='UpgradeIcon'/>
</p> </p>
<ReactTooltip id={placement} place={placement}>{toolTipText}</ReactTooltip> <ReactTooltip id={placement} place={placement}>{toolTipText}</ReactTooltip>

View File

@@ -1,5 +1,4 @@
.MountItems { .MountItems {
padding: 0; padding: 0;
margin-top: 8px;
width: 100%; width: 100%;
} }