[#38: Enhance new repertory release available notification - partial] [Added FocusTrap to modals]
This commit is contained in:
@@ -1,4 +1,8 @@
|
||||
# Changelog
|
||||
## 1.1.5
|
||||
* \#38: Enhance new repertory release available notification
|
||||
* Added `FocusTrap` to modals
|
||||
|
||||
## 1.1.4
|
||||
* \#39: Cleanup old releases and UI upgrades
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
"devtron": "^1.4.0",
|
||||
"electron-debug": "^3.0.1",
|
||||
"electron-log": "^4.0.6",
|
||||
"focus-trap-react": "^6.0.0",
|
||||
"font-awesome": "^4.7.0",
|
||||
"node-schedule": "^1.3.2",
|
||||
"randomstring": "^1.1.5",
|
||||
|
||||
20
src/App.js
20
src/App.js
@@ -11,6 +11,7 @@ import InfoDetails from './components/InfoDetails/InfoDetails';
|
||||
import IPCContainer from './containers/IPCContainer/IPCContainer';
|
||||
import Loading from './components/UI/Loading/Loading';
|
||||
import MountItems from './containers/MountItems/MountItems';
|
||||
import NewReleases from './components/NewReleases/NewReleases';
|
||||
import {notifyError} from './redux/actions/error_actions';
|
||||
import Reboot from './components/Reboot/Reboot';
|
||||
import ReleaseVersionDisplay from './components/ReleaseVersionDisplay/ReleaseVersionDisplay';
|
||||
@@ -111,12 +112,26 @@ class App extends IPCContainer {
|
||||
!this.props.DismissDependencies &&
|
||||
this.props.AllowMount;
|
||||
|
||||
const showNewReleases = !showConfig &&
|
||||
!this.props.DisplayConfirmYesNo &&
|
||||
!showDependencies &&
|
||||
!this.props.DownloadActive &&
|
||||
!this.props.DisplayError &&
|
||||
!this.props.DisplayInfo &&
|
||||
!this.props.InstallActive &&
|
||||
!this.props.RebootRequired &&
|
||||
!this.props.DisplaySelectAppPlatform &&
|
||||
!showUpgrade &&
|
||||
!this.props.DismissNewReleasesAvailable &&
|
||||
(this.props.NewReleasesAvailable.length > 0);
|
||||
|
||||
const configDisplay = createModalConditionally(showConfig, <Configuration version={selectedVersion} remoteSupported={remoteSupported} />);
|
||||
const confirmDisplay = createModalConditionally(this.props.DisplayConfirmYesNo, <YesNo/>);
|
||||
const dependencyDisplay = createModalConditionally(showDependencies, <DependencyList/>);
|
||||
const downloadDisplay = createModalConditionally(this.props.DownloadActive, <DownloadProgress/>);
|
||||
const downloadDisplay = createModalConditionally(this.props.DownloadActive, <DownloadProgress />, false, true);
|
||||
const errorDisplay = createModalConditionally(this.props.DisplayError, <ErrorDetails/>, true);
|
||||
const infoDisplay = createModalConditionally(this.props.DisplayInfo, <InfoDetails/>, true);
|
||||
const newReleasesDisplay = createModalConditionally(showNewReleases, <NewReleases/>);
|
||||
const rebootDisplay = createModalConditionally(this.props.RebootRequired, <Reboot />);
|
||||
const selectAppPlatformDisplay = createModalConditionally(this.props.DisplaySelectAppPlatform, <SelectAppPlatform/>);
|
||||
const upgradeDisplay = createModalConditionally(showUpgrade, <UpgradeUI/>);
|
||||
@@ -175,6 +190,7 @@ class App extends IPCContainer {
|
||||
{mainContent}
|
||||
</div>
|
||||
</div>
|
||||
{newReleasesDisplay}
|
||||
{selectAppPlatformDisplay}
|
||||
{dependencyDisplay}
|
||||
{upgradeDisplay}
|
||||
@@ -201,12 +217,14 @@ const mapStateToProps = state => {
|
||||
DisplayError: state.error.DisplayError,
|
||||
DisplayInfo: state.error.DisplayInfo,
|
||||
DisplaySelectAppPlatform: state.common.DisplaySelectAppPlatform,
|
||||
DismissNewReleasesAvailable: state.relver.DismissNewReleasesAvailable,
|
||||
DownloadActive: state.download.DownloadActive,
|
||||
InstallActive: state.install.InstallActive,
|
||||
InstalledVersion: state.relver.InstalledVersion,
|
||||
LocationsLookup: state.relver.LocationsLookup,
|
||||
MissingDependencies: state.install.MissingDependencies,
|
||||
MountsBusy: state.mounts.MountsBusy,
|
||||
NewReleasesAvailable: state.relver.NewReleasesAvailable,
|
||||
Platform: state.common.Platform,
|
||||
ProviderState: state.mounts.ProviderState,
|
||||
RebootRequired: state.common.RebootRequired,
|
||||
|
||||
@@ -22,9 +22,9 @@ export default connect(mapStateToProps)(props => {
|
||||
</td>
|
||||
<td>
|
||||
{props.AllowDownload ?
|
||||
<a href={void(0)}
|
||||
className={'DependencyLink'}
|
||||
onClick={()=>{props.onDownload(); return false;}}><u>Install</u></a> :
|
||||
<a href={'#'}
|
||||
className={'DependencyLink'}
|
||||
onClick={()=>{props.onDownload(); return false;}}><u>Install</u></a> :
|
||||
'Installing...'}
|
||||
</td>
|
||||
</tr>
|
||||
@@ -32,4 +32,4 @@ export default connect(mapStateToProps)(props => {
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
28
src/components/NewReleases/NewRelease/NewRelease.js
Normal file
28
src/components/NewReleases/NewRelease/NewRelease.js
Normal file
@@ -0,0 +1,28 @@
|
||||
import React from 'react';
|
||||
import * as Constants from '../../../constants';
|
||||
import Button from '../../UI/Button/Button';
|
||||
|
||||
export default ({release}) => {
|
||||
return (
|
||||
<div>
|
||||
<h3>{'[' + Constants.RELEASE_TYPES[release.Release].toUpperCase() + '] ' + release.Display }</h3>
|
||||
<table cellSpacing={0} cellPadding={0} width="97%">
|
||||
<tbody>
|
||||
<tr style={{height: '4px'}}/>
|
||||
<tr>
|
||||
<td width="50%">
|
||||
<Button buttonStyles={{width: '100%'}}>Changes</Button>
|
||||
</td>
|
||||
<td>
|
||||
<div style={{width: 'var(--default_spacing)'}}/>
|
||||
</td>
|
||||
<td width="50%">
|
||||
<Button buttonStyles={{width: '100%'}}>Install</Button>
|
||||
</td>
|
||||
</tr>
|
||||
<tr style={{height: 'var(--default_spacing)'}}/>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
11
src/components/NewReleases/NewReleases.css
Normal file
11
src/components/NewReleases/NewReleases.css
Normal file
@@ -0,0 +1,11 @@
|
||||
.NewReleasesHeading {
|
||||
text-align: center;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.NewReleasesContent {
|
||||
max-height: 60vh;
|
||||
min-width: 50vw;
|
||||
overflow-y: auto;
|
||||
margin-bottom: var(--default_spacing);
|
||||
}
|
||||
35
src/components/NewReleases/NewReleases.js
Normal file
35
src/components/NewReleases/NewReleases.js
Normal file
@@ -0,0 +1,35 @@
|
||||
import React from 'react';
|
||||
import {connect} from 'react-redux';
|
||||
import Box from '../UI/Box/Box';
|
||||
import Button from '../UI/Button/Button';
|
||||
import NewRelease from './NewRelease/NewRelease';
|
||||
import './NewReleases.css';
|
||||
import {setDismissNewReleasesAvailable} from '../../redux/actions/release_version_actions';
|
||||
|
||||
const mapStateToProps = state => {
|
||||
return {
|
||||
NewReleasesAvailable: state.relver.NewReleasesAvailable,
|
||||
};
|
||||
};
|
||||
|
||||
const mapDispatchToProps = dispatch => {
|
||||
return {
|
||||
dismissNewReleasesAvailable: () => dispatch(setDismissNewReleasesAvailable(true)),
|
||||
};
|
||||
};
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||
const newReleases = props.NewReleasesAvailable.map(i => {
|
||||
return <NewRelease key={'new_release_' + i.Release + '_' + i.Version} release={i} />;
|
||||
});
|
||||
|
||||
return (
|
||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
||||
<h1 className={'NewReleasesHeading'}>New Repertory Versions Available</h1>
|
||||
<div className={'NewReleasesContent'}>
|
||||
{newReleases}
|
||||
</div>
|
||||
<Button clicked={props.dismissNewReleasesAvailable}>Dismiss</Button>
|
||||
</Box>
|
||||
);
|
||||
});
|
||||
@@ -4,6 +4,7 @@ import './Button.css';
|
||||
export default props => {
|
||||
return (
|
||||
<button disabled={props.disabled}
|
||||
autoFocus={props.autoFocus}
|
||||
className={'Button'}
|
||||
style={props.buttonStyles}
|
||||
onClick={props.clicked}>{props.children}</button>
|
||||
|
||||
@@ -6,6 +6,7 @@ export default props => {
|
||||
<div className={'CheckBoxOwner'}>
|
||||
<label className='CheckBoxLabel'>{props.label}
|
||||
<input checked={JSON.parse(props.checked)}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.disabled}
|
||||
onChange={props.changed}
|
||||
type='checkbox'/>
|
||||
@@ -13,4 +14,4 @@ export default props => {
|
||||
</label>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ export default props => {
|
||||
return (
|
||||
<div className={'DropDown'}>
|
||||
<select className={'DropDownSelect' + (props.auto ? ' Auto ' : '') + (props.alt ? ' Alt ' : '') }
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.disabled}
|
||||
onChange={props.changed}
|
||||
value={props.selected}>
|
||||
@@ -19,4 +20,4 @@ export default props => {
|
||||
</div>
|
||||
);
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import React from 'react';
|
||||
|
||||
import './Modal.css'
|
||||
import FocusTrap from 'focus-trap-react';
|
||||
|
||||
export default props => {
|
||||
let modalStyles = [];
|
||||
@@ -12,11 +14,14 @@ export default props => {
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
className={modalStyles.join(' ')}
|
||||
onClick={props.clicked}>
|
||||
<div className={contentStyles.join(' ')}>
|
||||
{props.children}
|
||||
<FocusTrap active={!props.disableFocusTrap}>
|
||||
<div
|
||||
className={modalStyles.join(' ')}
|
||||
onClick={props.clicked}>
|
||||
<div className={contentStyles.join(' ')}>
|
||||
{props.children}
|
||||
</div>
|
||||
</div>
|
||||
</div>);
|
||||
};
|
||||
</FocusTrap>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -163,6 +163,8 @@ class Configuration extends IPCContainer {
|
||||
ObjectLookup: objectLookup,
|
||||
OriginalItemList: itemListCopy,
|
||||
OriginalObjectLookup: objectLookupCopy,
|
||||
}, () => {
|
||||
|
||||
});
|
||||
} else {
|
||||
this.props.notifyError(arg.data.Error);
|
||||
@@ -262,20 +264,7 @@ class Configuration extends IPCContainer {
|
||||
);
|
||||
}
|
||||
|
||||
const configurationItems = this.state.ItemList
|
||||
.map((k, i) => {
|
||||
return (
|
||||
((!this.state.IsRemoteMount || !k.hide_remote) && (!k.advanced || (this.state.ShowAdvanced && k.advanced))) ?
|
||||
<ConfigurationItem advanced={k.advanced}
|
||||
changed={e=>this.handleItemChanged(e, i)}
|
||||
grouping={'Settings'}
|
||||
items={this.state.Template[k.label].items}
|
||||
key={i}
|
||||
label={k.label}
|
||||
template={this.state.Template[k.label]}
|
||||
value={k.value}/> :
|
||||
null)
|
||||
});
|
||||
let autoFocus = true;
|
||||
|
||||
let objectItems = [];
|
||||
for (const key of Object.keys(this.state.ObjectLookup)) {
|
||||
@@ -285,9 +274,12 @@ class Configuration extends IPCContainer {
|
||||
<div>
|
||||
{
|
||||
this.state.ObjectLookup[key].map((k, i) => {
|
||||
const shouldFocus = autoFocus;
|
||||
autoFocus = false;
|
||||
return (
|
||||
(!k.advanced || (this.state.ShowAdvanced && k.advanced && !k.remote) || this.showRemoteConfigItem(k, this.state.ObjectLookup[key])) ?
|
||||
<ConfigurationItem advanced={k.advanced}
|
||||
autoFocus={shouldFocus}
|
||||
changed={e=>this.handleObjectItemChanged(e, key, i)}
|
||||
grouping={key}
|
||||
items={this.state.Template[key].template[k.label].items}
|
||||
@@ -304,13 +296,33 @@ class Configuration extends IPCContainer {
|
||||
));
|
||||
}
|
||||
|
||||
const configurationItems = this.state.ItemList
|
||||
.map((k, i) => {
|
||||
const shouldFocus = autoFocus;
|
||||
autoFocus = false;
|
||||
return (
|
||||
((!this.state.IsRemoteMount || !k.hide_remote) && (!k.advanced || (this.state.ShowAdvanced && k.advanced))) ?
|
||||
<ConfigurationItem advanced={k.advanced}
|
||||
autoFocus={shouldFocus}
|
||||
changed={e=>this.handleItemChanged(e, i)}
|
||||
grouping={'Settings'}
|
||||
items={this.state.Template[k.label].items}
|
||||
key={i}
|
||||
label={k.label}
|
||||
template={this.state.Template[k.label]}
|
||||
value={k.value}/> :
|
||||
null
|
||||
);
|
||||
});
|
||||
|
||||
return (
|
||||
<div className={'Configuration'}>
|
||||
{confirmSave}
|
||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
||||
<div style={{float: 'right', margin: 0, padding: 0, marginTop: '-4px', boxSizing: 'border-box', display: 'block'}}>
|
||||
<b style={{cursor: 'pointer'}}
|
||||
onClick={this.checkSaveRequired}>X</b>
|
||||
<a href={'#'}
|
||||
onClick={this.checkSaveRequired}
|
||||
style={{cursor: 'pointer'}}>X</a>
|
||||
</div>
|
||||
<h1 style={{width: '100%', textAlign: 'center'}}>{(
|
||||
this.props.DisplayRemoteConfiguration ?
|
||||
|
||||
@@ -18,7 +18,7 @@ export default connect(null, mapDispatchToProps)(props => {
|
||||
const handleChanged = (e) => {
|
||||
const target = e.target;
|
||||
if (target.type === 'checkbox') {
|
||||
target.value = e.target.checked ? "true" : "false";
|
||||
target.value = e.target.checked ? 'true' : 'false';
|
||||
}
|
||||
props.changed(target);
|
||||
};
|
||||
@@ -30,49 +30,54 @@ export default connect(null, mapDispatchToProps)(props => {
|
||||
props.notifyInfo(props.label, description);
|
||||
};
|
||||
|
||||
infoDisplay = <a href={void(0)}
|
||||
className={'ConfigurationInfo'}
|
||||
onClick={()=>{displayInfo(); return false;}}><FontAwesomeIcon icon={faInfoCircle}/></a>;
|
||||
infoDisplay = <a href={'#'}
|
||||
className={'ConfigurationInfo'}
|
||||
onClick={()=>{displayInfo(); return false;}}><FontAwesomeIcon icon={faInfoCircle}/></a>;
|
||||
}
|
||||
|
||||
|
||||
let data;
|
||||
switch (props.template.type) {
|
||||
case "bool":
|
||||
case 'bool':
|
||||
data = <CheckBox changed={handleChanged}
|
||||
checked={props.value}
|
||||
disabled={props.readOnly}/>;
|
||||
disabled={props.readOnly}
|
||||
autoFocus={props.autoFocus}/>;
|
||||
break;
|
||||
|
||||
case "double":
|
||||
case 'double':
|
||||
data = <input min={0.0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={e=>handleChanged(e)}
|
||||
step={"0.01"}
|
||||
step={'0.01'}
|
||||
className={'ConfigurationItemInput'}
|
||||
type={'number'}
|
||||
value={parseFloat(props.value).toFixed(2)}/>;
|
||||
break;
|
||||
|
||||
case "list":
|
||||
case 'list':
|
||||
data = <DropDown alt
|
||||
auto
|
||||
autoFocus={props.autoFocus}
|
||||
changed={handleChanged}
|
||||
disabled={props.readOnly}
|
||||
items={props.items}
|
||||
selected={props.value} />;
|
||||
break;
|
||||
|
||||
case "string":
|
||||
case 'string':
|
||||
data = <input onChange={e=>handleChanged(e)}
|
||||
autoFocus={props.autoFocus}
|
||||
className={'ConfigurationItemInput'}
|
||||
disabled={props.readOnly}
|
||||
type={'text'}
|
||||
value={props.value}/>;
|
||||
break;
|
||||
|
||||
case "uint8":
|
||||
case 'uint8':
|
||||
data = <input max={255}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={e=>handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
@@ -80,9 +85,10 @@ export default connect(null, mapDispatchToProps)(props => {
|
||||
value={props.value}/>;
|
||||
break;
|
||||
|
||||
case "uint16":
|
||||
case 'uint16':
|
||||
data = <input max={65535}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={e=>handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
@@ -90,9 +96,10 @@ export default connect(null, mapDispatchToProps)(props => {
|
||||
value={props.value}/>;
|
||||
break;
|
||||
|
||||
case "uint32":
|
||||
case 'uint32':
|
||||
data = <input max={4294967295}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={e=>handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
@@ -100,9 +107,10 @@ export default connect(null, mapDispatchToProps)(props => {
|
||||
value={props.value}/>;
|
||||
break;
|
||||
|
||||
case "uint64":
|
||||
case 'uint64':
|
||||
data = <input max={18446744073709551615}
|
||||
min={0}
|
||||
autoFocus={props.autoFocus}
|
||||
disabled={props.readOnly}
|
||||
onChange={e=>handleChanged(e)}
|
||||
className={'ConfigurationItemInput'}
|
||||
@@ -129,4 +137,4 @@ export default connect(null, mapDispatchToProps)(props => {
|
||||
</table>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -152,8 +152,8 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
||||
}
|
||||
};
|
||||
removeControl = (
|
||||
<a col={dimensions=>dimensions.columns - 6}
|
||||
href={void(0)}
|
||||
<a href={'#'}
|
||||
col={dimensions=>dimensions.columns - 6}
|
||||
onClick={handleRemoveMount}
|
||||
row={secondRow + 3}
|
||||
style={removeStyle}>
|
||||
|
||||
@@ -30,6 +30,9 @@
|
||||
|
||||
a {
|
||||
outline: 0;
|
||||
color: var(--text_color);
|
||||
text-decoration: none;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
html, body {
|
||||
|
||||
@@ -13,7 +13,10 @@ import {
|
||||
setDismissDependencies
|
||||
} from './install_actions';
|
||||
import {unmountAll} from './mount_actions';
|
||||
import {getIPCRenderer} from '../../utils';
|
||||
import {
|
||||
getIPCRenderer,
|
||||
getNewReleases
|
||||
} from '../../utils';
|
||||
|
||||
export const CLEAR_UI_UPGRADE = 'relver/clearUIUpgrade';
|
||||
export const clearUIUpgrade = () => {
|
||||
@@ -123,11 +126,22 @@ export const loadReleases = () => {
|
||||
...response.data.Locations[appPlatform],
|
||||
};
|
||||
|
||||
const storedReleases = localStorage.getItem('releases');
|
||||
let newReleases = [];
|
||||
if (storedReleases && (storedReleases.length > 0)) {
|
||||
newReleases = getNewReleases(JSON.parse(storedReleases).VersionLookup, versionLookup);
|
||||
}
|
||||
|
||||
localStorage.setItem('releases', JSON.stringify({
|
||||
LocationsLookup: locationsLookup,
|
||||
VersionLookup: versionLookup
|
||||
}));
|
||||
dispatchActions(locationsLookup, versionLookup);
|
||||
|
||||
dispatch(setNewReleasesAvailable(newReleases));
|
||||
if (getState().relver.NewReleasesAvailable.length > 0) {
|
||||
dispatch(showWindow());
|
||||
}
|
||||
}).catch(error => {
|
||||
const releases = localStorage.getItem('releases');
|
||||
if (releases && (releases.length > 0)) {
|
||||
@@ -174,8 +188,10 @@ export const setActiveRelease = (release, version) => {
|
||||
};
|
||||
|
||||
export const setAllowDismissDependencies = createAction('relver/setAllowDismissDependencies');
|
||||
export const setDismissNewReleasesAvailable = createAction('relver/setDismissNewReleasesAvailable');
|
||||
export const setDismissUIUpgrade = createAction('relver/setDismissUIUpgrade');
|
||||
export const setInstalledVersion = createAction('relver/setInstalledVersion');
|
||||
export const setNewReleasesAvailable = createAction('relver/setNewReleasesAvailable');
|
||||
|
||||
export const SET_RELEASE_DATA = 'relver/setReleaseData';
|
||||
export const setReleaseData = (locationsLookup, versionLookup)=> {
|
||||
|
||||
@@ -15,8 +15,10 @@ const versionLookup = Constants.RELEASE_TYPES.map(k=> {
|
||||
|
||||
export const releaseVersionReducer = createReducer({
|
||||
AllowDismissDependencies: false,
|
||||
DismissNewReleasesAvailable: true,
|
||||
InstalledVersion: 'none',
|
||||
LocationsLookup: {},
|
||||
NewReleasesAvailable: [],
|
||||
Release: 0,
|
||||
ReleaseDefault: 0,
|
||||
ReleaseUpgradeAvailable: false,
|
||||
@@ -49,6 +51,12 @@ export const releaseVersionReducer = createReducer({
|
||||
AllowDismissDependencies: action.payload,
|
||||
};
|
||||
},
|
||||
[Actions.setDismissNewReleasesAvailable]: (state, action) => {
|
||||
return {
|
||||
...state,
|
||||
DismissNewReleasesAvailable: action.payload,
|
||||
};
|
||||
},
|
||||
[Actions.setDismissUIUpgrade]: (state, action) => {
|
||||
return {
|
||||
...state,
|
||||
@@ -61,6 +69,13 @@ export const releaseVersionReducer = createReducer({
|
||||
InstalledVersion: action.payload,
|
||||
}
|
||||
},
|
||||
[Actions.setNewReleasesAvailable]: (state, action) => {
|
||||
return {
|
||||
...state,
|
||||
DismissNewReleasesAvailable: false,
|
||||
NewReleasesAvailable: action.payload,
|
||||
};
|
||||
},
|
||||
[Actions.SET_RELEASE_DATA]: (state, action) => {
|
||||
return {
|
||||
...state,
|
||||
|
||||
35
src/utils.js
35
src/utils.js
@@ -6,8 +6,8 @@ const ipcRenderer = (!process.versions.hasOwnProperty('electron') && window && w
|
||||
window.require('electron').ipcRenderer :
|
||||
null;
|
||||
|
||||
export const createModalConditionally = (condition, jsx, critical) => {
|
||||
const modalProps = {critical: critical};
|
||||
export const createModalConditionally = (condition, jsx, critical, disableFocusTrap) => {
|
||||
const modalProps = {critical: critical, disableFocusTrap: disableFocusTrap};
|
||||
return condition ? (<Modal {...modalProps}>{jsx}</Modal>) : null;
|
||||
};
|
||||
|
||||
@@ -20,6 +20,37 @@ export const getIPCRenderer = () => {
|
||||
return ipcRenderer;
|
||||
};
|
||||
|
||||
export const getNewReleases = (existingReleases, newReleases) => {
|
||||
const ret = [];
|
||||
|
||||
existingReleases = Constants.RELEASE_TYPES.reduce((map, release) => {
|
||||
map[release] = [];
|
||||
return map;
|
||||
}, {});
|
||||
|
||||
if (existingReleases && newReleases) {
|
||||
Constants.RELEASE_TYPES.forEach(release => {
|
||||
newReleases[release]
|
||||
.filter(version => !existingReleases[release].includes(version) && (version !== 'unavailable'))
|
||||
.forEach(version => {
|
||||
ret.splice(0, 0, {
|
||||
Display: version,
|
||||
Release: Constants.RELEASE_TYPES.indexOf(release),
|
||||
Version: newReleases[release].indexOf(version),
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
ret.splice(0, 0, {
|
||||
Display: '1.1.1',
|
||||
Release: 0,
|
||||
Version: 2,
|
||||
});
|
||||
|
||||
return ret;
|
||||
};
|
||||
|
||||
export const getSelectedVersionFromState = state => {
|
||||
return (state.relver.Version === -1) ?
|
||||
'unavailable' :
|
||||
|
||||
Reference in New Issue
Block a user