diff --git a/src/components/NewReleases/NewRelease/NewRelease.js b/src/components/NewReleases/NewRelease/NewRelease.js index a8b5de3..0ad4fec 100644 --- a/src/components/NewReleases/NewRelease/NewRelease.js +++ b/src/components/NewReleases/NewRelease/NewRelease.js @@ -1,23 +1,52 @@ import React from 'react'; +import {connect} from 'react-redux'; import * as Constants from '../../../constants'; import Button from '../../UI/Button/Button'; +import {formatLinesForDisplay, getChangesForRepertoryVersion} from '../../../utils'; +import { + notifyError, + notifyInfo +} from '../../../redux/actions/error_actions'; +import {installReleaseByVersion} from '../../../redux/actions/install_actions'; + +const mapDispatchToProps = dispatch => { + return { + installReleaseByVersion: (release, version) => dispatch(installReleaseByVersion(release, version)), + notifyError: msg => dispatch(notifyError(msg)), + notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)), + }; +}; + +export default connect(null, mapDispatchToProps)(({dismiss, release, lastItem, notifyError, notifyInfo, installReleaseByVersion}) => { + const title = '[' + Constants.RELEASE_TYPES[release.Release] + '] ' + release.Display; + const installReleaseVersion = () => { + dismiss(); + installReleaseByVersion(release.Release, release.Version); + }; + const displayChanges = async () => { + try { + const lines = await getChangesForRepertoryVersion(release.VersionString); + notifyInfo(title, formatLinesForDisplay(lines)); + } catch (e) { + notifyError(e); + } + }; -export default ({release, lastItem}) => { return (
-

{'[' + Constants.RELEASE_TYPES[release.Release] + '] ' + release.Display }

+

{title}

{lastItem ? null : } @@ -25,4 +54,4 @@ export default ({release, lastItem}) => {
- +
- +
); -}; +}); diff --git a/src/components/NewReleases/NewReleases.js b/src/components/NewReleases/NewReleases.js index 5c4638c..4c4656e 100644 --- a/src/components/NewReleases/NewReleases.js +++ b/src/components/NewReleases/NewReleases.js @@ -20,7 +20,8 @@ const mapDispatchToProps = dispatch => { export default connect(mapStateToProps, mapDispatchToProps)(props => { const newReleases = props.NewReleasesAvailable.map((i, idx) => { - return ; }); diff --git a/src/redux/actions/install_actions.js b/src/redux/actions/install_actions.js index b8eaf77..5b28fff 100644 --- a/src/redux/actions/install_actions.js +++ b/src/redux/actions/install_actions.js @@ -5,7 +5,7 @@ import { getSelectedVersionFromState } from '../../utils'; import {notifyError} from './error_actions'; -import {setAllowDownload} from './download_actions'; +import {downloadItem, setAllowDownload} from './download_actions'; import { loadReleases, setActiveRelease, @@ -32,13 +32,15 @@ export const checkInstalled = (dependencies, version) => { const installedVersion = result.Success && result.Exists ? result.Version : 'none'; const state = getState(); + const release = state.relver.Release; + let version = state.relver.Version; + let upgradeAvailable = false; if (installedVersion !== 'none') { - const latestVersion = state.relver.VersionLookup[Constants.RELEASE_TYPES[state.relver.Release]].length - 1; - let version = state.relver.Version; + const latestVersion = state.relver.VersionLookup[Constants.RELEASE_TYPES[release]].length - 1; if (version === -1) { version = latestVersion; - dispatch(setActiveRelease(state.relver.Release, version)); + dispatch(setActiveRelease(release, version)); } else { upgradeAvailable = version !== latestVersion; } @@ -48,8 +50,18 @@ export const checkInstalled = (dependencies, version) => { dispatch(setMissingDependencies(result.Dependencies)); dispatch(setAllowDownload(true)); dispatch(setAllowMount(true)); + + const autoInstallRelease = getState().install.AutoInstallRelease; + dispatch(setAutoInstallRelease(false)); + if (result.Dependencies && (result.Dependencies.length > 0)) { dispatch(showWindow()); + } else if ((installedVersion === 'none') && autoInstallRelease) { + dispatch(setAllowMount(false)); + const versionString = getState().relver.VersionLookup[Constants.RELEASE_TYPES[release]][version]; + const urls = getState().relver.LocationsLookup[versionString].urls; + const fileName = versionString + '.zip'; + dispatch(downloadItem(fileName, Constants.INSTALL_TYPES.Release, urls)); } }; @@ -174,6 +186,24 @@ export const installAndTestRelease = (source, version, appPlatform) => { }; }; +export const installReleaseByVersion = (release, version) => { + return (dispatch, getState) => { + let allowInstall = !getState().mounts.MountsBusy; + if (!allowInstall) { + // TODO: prompt to unmount + } + + if (allowInstall) { + if (getState().download.AllowDownload && !getState().download.DownloadActive) { + dispatch(setAutoInstallRelease(true)); + dispatch(setActiveRelease(release, version)); + } else { + notifyError('Download is active. Unable to install release.'); + } + } + }; +}; + export const installRelease = source => { return (dispatch, getState) => { if (ipcRenderer && !getState().install.InstallActive) { @@ -231,6 +261,7 @@ export const installUpgrade = (source, sha256, signature, skipVerification) => { }; }; +export const setAutoInstallRelease = createAction('install/setAutoInstallRelease'); export const setDismissDependencies = createAction('install/setDismissDependencies'); export const setInstallActive = createAction('install/setInstallActive'); export const setInstallTestActive = createAction('install/setInstallTestActive'); diff --git a/src/redux/reducers/install_reducer.js b/src/redux/reducers/install_reducer.js index cdcca1a..8ec65f7 100644 --- a/src/redux/reducers/install_reducer.js +++ b/src/redux/reducers/install_reducer.js @@ -1,5 +1,6 @@ import {createReducer} from '@reduxjs/toolkit'; import { + setAutoInstallRelease, setDismissDependencies, setInstallActive, setInstallComplete, @@ -8,6 +9,7 @@ import { } from '../actions/install_actions'; export const installReducer = createReducer({ + AutoInstallRelease: false, DismissDependencies: false, InstallActive: false, InstallResult: null, @@ -15,6 +17,12 @@ export const installReducer = createReducer({ InstallType: null, MissingDependencies: [], }, { + [setAutoInstallRelease]: (state, action) => { + return { + ...state, + AutoInstallRelease: action.payload, + } + }, [setDismissDependencies]: (state, action) => { return { ...state, diff --git a/src/utils.js b/src/utils.js index 47d29de..2448039 100644 --- a/src/utils.js +++ b/src/utils.js @@ -1,6 +1,7 @@ import React from 'react'; import * as Constants from './constants'; import Modal from './components/UI/Modal/Modal'; +import axios from 'axios'; const ipcRenderer = (!process.versions.hasOwnProperty('electron') && window && window.require) ? window.require('electron').ipcRenderer : @@ -16,6 +17,47 @@ export const extractFileNameFromURL = url => { return parts[parts.length - 1]; }; +export const formatLinesForDisplay = lines => { + let msg = ''; + for (let i = 1; i < lines.length; i++) { + if (i > 1) { + msg += '\n'; + } + msg += (lines[i].replace(/(\\#)/gm, '#') + '\n'); + } + return msg; +}; + +export const getChangesForRepertoryVersion = version => { + return new Promise((resolve, reject) => { + const url = `https://bitbucket.org/blockstorage/repertory/raw/${version}/CHANGELOG.md`; + axios + .get(url, { + responseType: 'text', + }) + .then(response => { + try { + let found = false; + let ended = false; + let lines = response.data + .replace(/(\r\n)/gm, '\n') + .split('\n') + .filter(l => { + return !ended && (l.length > 0) && (found + ? !(ended = l.startsWith('## ')) + : (found = l.startsWith(`## ${version}`))); + }); + resolve(lines); + } catch (e) { + reject(e); + } + }) + .catch(error => { + reject(error); + }); + }); +}; + export const getIPCRenderer = () => { return ipcRenderer; }; @@ -37,16 +79,18 @@ export const getNewReleases = (existingReleases, newReleases) => { Display: version, Release: Constants.RELEASE_TYPES.indexOf(release), Version: newReleases[release].indexOf(version), + VersionString: version, }); }); }); } - ret.push({ - Display: '1.1.1', - Release: 1, - Version: 2, - }); + /*ret.push({ + Display: '1.2.2-release', + Release: 0, + Version: 3, + VersionString: '1.2.2-release', + });*/ return ret; };