Merged 1.3.x_branch into master
This commit is contained in:
30
.eslintrc.json
Normal file
30
.eslintrc.json
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
{
|
||||||
|
"root":true,
|
||||||
|
"env": {
|
||||||
|
"browser": true,
|
||||||
|
"es2021": true,
|
||||||
|
"node": true,
|
||||||
|
"jest/globals": true
|
||||||
|
},
|
||||||
|
"extends": [
|
||||||
|
"eslint:recommended",
|
||||||
|
"plugin:react/recommended",
|
||||||
|
"plugin:prettier/recommended"
|
||||||
|
],
|
||||||
|
"parser": "babel-eslint",
|
||||||
|
"parserOptions": {
|
||||||
|
"ecmaFeatures": {
|
||||||
|
"jsx": true
|
||||||
|
},
|
||||||
|
"ecmaVersion": 12,
|
||||||
|
"sourceType": "module"
|
||||||
|
},
|
||||||
|
"plugins": [
|
||||||
|
"prettier",
|
||||||
|
"react",
|
||||||
|
"jest"
|
||||||
|
],
|
||||||
|
"rules": {
|
||||||
|
"prettier/prettier": "warn"
|
||||||
|
}
|
||||||
|
}
|
||||||
8
.prettierrc.json
Normal file
8
.prettierrc.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"trailingComma": "es5",
|
||||||
|
"tabWidth": 2,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"jsxBracketSameLine": true,
|
||||||
|
"printWidth": 100
|
||||||
|
}
|
||||||
@@ -1,14 +1,36 @@
|
|||||||
{
|
{
|
||||||
"cSpell.words": [
|
"cSpell.words": [
|
||||||
|
"APPIMAGE",
|
||||||
|
"APPPLATFORM",
|
||||||
|
"Bodhi",
|
||||||
|
"Filebase",
|
||||||
|
"GUID's",
|
||||||
|
"HKCC",
|
||||||
|
"HKCR",
|
||||||
|
"HKCU",
|
||||||
"HKEY",
|
"HKEY",
|
||||||
"HKLM",
|
"HKLM",
|
||||||
|
"LOCALAPPDATA",
|
||||||
"Redistributable",
|
"Redistributable",
|
||||||
|
"Skylink's",
|
||||||
"Skylinks",
|
"Skylinks",
|
||||||
"Skynet",
|
"Skynet",
|
||||||
"Unmount",
|
"Unmount",
|
||||||
|
"WINFSP",
|
||||||
|
"blockstorage",
|
||||||
|
"centos",
|
||||||
|
"fontawesome",
|
||||||
|
"fortawesome",
|
||||||
"msiexec",
|
"msiexec",
|
||||||
|
"norestart",
|
||||||
|
"randomstring",
|
||||||
|
"reduxjs",
|
||||||
"relver",
|
"relver",
|
||||||
|
"scprime",
|
||||||
"siaprime",
|
"siaprime",
|
||||||
"skylink"
|
"skylink",
|
||||||
|
"undocked",
|
||||||
|
"valign",
|
||||||
|
"windir"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
2
.vimrc
2
.vimrc
@@ -1,6 +1,6 @@
|
|||||||
set autoread
|
set autoread
|
||||||
set path+=.,public/**,src/**,test/**
|
set path+=.,public/**,src/**,test/**
|
||||||
if has('win32')
|
if has('win32') || has('win64')
|
||||||
let &makeprg="create_dist.cmd"
|
let &makeprg="create_dist.cmd"
|
||||||
else
|
else
|
||||||
let &makeprg="./create_dist.sh"
|
let &makeprg="./create_dist.sh"
|
||||||
|
|||||||
242
CHANGELOG.md
242
CHANGELOG.md
@@ -1,150 +1,178 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## 1.3.4
|
||||||
|
- \#55: Enable 'Activate' release instead of 'Install' in notification pop-up
|
||||||
|
- \#58: Add authentication support for Skynet premium portals
|
||||||
|
- \#59: Add agent string / API key support for Skynet portals
|
||||||
|
- Ability to export Skylink's to json file
|
||||||
|
- Ability to import Skylink's from json file
|
||||||
|
|
||||||
## 1.3.3
|
## 1.3.3
|
||||||
* \#49: Download progress is not visible if dependencies are missing
|
|
||||||
* \#51: javascript error
|
- \#49: Download progress is not visible if dependencies are missing
|
||||||
* \#52: Mount location is not set error on new install
|
- \#51: javascript error
|
||||||
* \#53: Busy notification is still visible when 'Install' button is available
|
- \#52: Mount location is not set error on new install
|
||||||
* \#54: Unable to download UI update while dependencies are being checked
|
- \#53: Busy notification is still visible when 'Install' button is available
|
||||||
* Disabled 'Install' button in new release notification
|
- \#54: Unable to download UI update while dependencies are being checked
|
||||||
|
- Disabled 'Install' button in new release notification
|
||||||
|
|
||||||
## 1.3.2
|
## 1.3.2
|
||||||
* \#48: Support pinning files to cache
|
|
||||||
* Fixed Skynet export display
|
- \#48: Support pinning files to cache
|
||||||
* Properly detect existing remote
|
- Fixed Skynet export display
|
||||||
* Reduced number of Linux binaries to:
|
- Properly detect existing remote
|
||||||
* CentOS 7
|
- Reduced number of Linux binaries to:
|
||||||
* Solus
|
- CentOS 7
|
||||||
* S3 mount support [disabled]
|
- Solus
|
||||||
|
- S3 mount support [disabled]
|
||||||
|
|
||||||
## 1.3.1
|
## 1.3.1
|
||||||
* \#45: Skynet mount support
|
|
||||||
|
- \#45: Skynet mount support
|
||||||
|
|
||||||
## 1.3.0
|
## 1.3.0
|
||||||
* \#38: Enhance new repertory release available notification
|
|
||||||
* \#46: Fix Mount Manager unmount and mount detection
|
- \#38: Enhance new repertory release available notification
|
||||||
* Skynet support
|
- \#46: Fix Mount Manager unmount and mount detection
|
||||||
* Synchronize UI major/minor version with `repertory` major/minor version
|
- Skynet support
|
||||||
* Added `Password` component
|
- Synchronize UI major/minor version with `repertory` major/minor version
|
||||||
* Reduced number of Linux binaries to:
|
- Added `Password` component
|
||||||
* CentOS 7
|
- Reduced number of Linux binaries to:
|
||||||
* Debian 9
|
- CentOS 7
|
||||||
* Debian 10
|
- Debian 9
|
||||||
* Solus
|
- Debian 10
|
||||||
* Added `FocusTrap` to modals
|
- Solus
|
||||||
|
- Added `FocusTrap` to modals
|
||||||
|
|
||||||
## 1.1.4
|
## 1.1.4
|
||||||
* \#39: Cleanup old releases and UI upgrades
|
|
||||||
|
- \#39: Cleanup old releases and UI upgrades
|
||||||
|
|
||||||
## 1.1.3
|
## 1.1.3
|
||||||
* CentOS 8 support
|
|
||||||
* Support remote send and receive timeouts
|
- CentOS 8 support
|
||||||
* Support WinFSP mount manager
|
- Support remote send and receive timeouts
|
||||||
* Fix `spawn()` failure on Windows when paths contain spaces
|
- Support WinFSP mount manager
|
||||||
|
- Fix `spawn()` failure on Windows when paths contain spaces
|
||||||
|
|
||||||
## 1.1.2
|
## 1.1.2
|
||||||
* Style changes
|
|
||||||
|
- Style changes
|
||||||
|
|
||||||
## 1.1.1
|
## 1.1.1
|
||||||
* \#43: Support for remote UNIX mounts
|
|
||||||
* Improved mount state detection
|
- \#43: Support for remote UNIX mounts
|
||||||
|
- Improved mount state detection
|
||||||
|
|
||||||
## 1.1.0
|
## 1.1.0
|
||||||
* \#40: Support for remote Windows mounts
|
|
||||||
* \#42: Failing to unmount on OS X
|
- \#40: Support for remote Windows mounts
|
||||||
* Allow enabling dev tools (Ctrl-Shift-I or F12)
|
- \#42: Failing to unmount on OS X
|
||||||
* ScPrime re-brand
|
- Allow enabling dev tools (Ctrl-Shift-I or F12)
|
||||||
* Ubuntu 19.10 support
|
- ScPrime re-brand
|
||||||
* Linux Mint 19.2 support
|
- Ubuntu 19.10 support
|
||||||
* Fedora 31 support
|
- Linux Mint 19.2 support
|
||||||
|
- Fedora 31 support
|
||||||
|
|
||||||
## 1.0.11 (Linux only)
|
## 1.0.11 (Linux only)
|
||||||
* Fix Ubuntu 19.10 detection
|
|
||||||
|
- Fix Ubuntu 19.10 detection
|
||||||
|
|
||||||
## 1.0.10
|
## 1.0.10
|
||||||
* Fix VC runtime detection (detect additional GUID's)
|
|
||||||
|
- Fix VC runtime detection (detect additional GUID's)
|
||||||
|
|
||||||
## 1.0.9 (Alpha Testing Release)
|
## 1.0.9 (Alpha Testing Release)
|
||||||
* \#40: Support for remote Windows mounts
|
|
||||||
* ScPrime re-brand
|
- \#40: Support for remote Windows mounts
|
||||||
* Fix VC runtime detection (detect additional GUID's)
|
- ScPrime re-brand
|
||||||
|
- Fix VC runtime detection (detect additional GUID's)
|
||||||
|
|
||||||
## 1.0.8
|
## 1.0.8
|
||||||
* \#8: Add tooltips to settings
|
|
||||||
* \#36: Add ability to select Linux distribution type if OS is unsupported
|
- \#8: Add tooltips to settings
|
||||||
* \#37: Version check fails with incorrect message when VC runtime is missing
|
- \#36: Add ability to select Linux distribution type if OS is unsupported
|
||||||
* Added additional WinFsp uninstall strings
|
- \#37: Version check fails with incorrect message when VC runtime is missing
|
||||||
|
- Added additional WinFsp uninstall strings
|
||||||
|
|
||||||
## 1.0.7
|
## 1.0.7
|
||||||
* \#31: New installation displays 'Mount location is not set' on Windows
|
|
||||||
* \#33: Add 'Microsoft Visual C++ Redistributable' as dependency installation on Windows
|
- \#31: New installation displays 'Mount location is not set' on Windows
|
||||||
* \#32: Don't display network error message when check for UI updates fails
|
- \#33: Add 'Microsoft Visual C++ Redistributable' as dependency installation on Windows
|
||||||
* \#30: Add uninstall feature with reboot to handle WinFSP upgrades/downgrades
|
- \#32: Don't display network error message when check for UI updates fails
|
||||||
* \#34: Allow cancelling/closing dependency installation if version count > 1
|
- \#30: Add uninstall feature with reboot to handle WinFSP upgrades/downgrades
|
||||||
* Handle incorrect download sizes for dependencies and releases
|
- \#34: Allow cancelling/closing dependency installation if version count > 1
|
||||||
|
- Handle incorrect download sizes for dependencies and releases
|
||||||
|
|
||||||
## 1.0.6
|
## 1.0.6
|
||||||
* Additional Linux distribution support:
|
|
||||||
* Antergos
|
- Additional Linux distribution support:
|
||||||
* Manjaro
|
- Antergos
|
||||||
* Download latest `detect_linux.sh` if bundled script returns `unknown`
|
- Manjaro
|
||||||
* Display error message if OS is detected as `unknown`
|
- Download latest `detect_linux.sh` if bundled script returns `unknown`
|
||||||
|
- Display error message if OS is detected as `unknown`
|
||||||
|
|
||||||
## 1.0.5
|
## 1.0.5
|
||||||
* \#29: Mounts aren't being detected properly when switching releases
|
|
||||||
* Display window when dependencies are missing
|
- \#29: Mounts aren't being detected properly when switching releases
|
||||||
* Display window when UI upgrade is available
|
- Display window when dependencies are missing
|
||||||
* Display window and unmount all drives if release is no longer available
|
- Display window when UI upgrade is available
|
||||||
* Will primarily affect pre-release versions (Alpha, Beta, and RC)
|
- Display window and unmount all drives if release is no longer available
|
||||||
|
- Will primarily affect pre-release versions (Alpha, Beta, and RC)
|
||||||
|
|
||||||
## 1.0.4
|
## 1.0.4
|
||||||
* \#27: Implement Bitbucket backup download location
|
|
||||||
* \#28: Fix Linux upgrade
|
- \#27: Implement Bitbucket backup download location
|
||||||
* Additional Linux distribution support:
|
- \#28: Fix Linux upgrade
|
||||||
* Debian 10
|
- Additional Linux distribution support:
|
||||||
* OpenSUSE Leap 15.0
|
- Debian 10
|
||||||
* OpenSUSE Leap 15.1
|
- OpenSUSE Leap 15.0
|
||||||
* OpenSUSE Tumbleweed
|
- OpenSUSE Leap 15.1
|
||||||
|
- OpenSUSE Tumbleweed
|
||||||
|
|
||||||
## 1.0.3
|
## 1.0.3
|
||||||
* Linux distribution support
|
|
||||||
* Arch Linux
|
- Linux distribution support
|
||||||
* Bodhi 5.0.0
|
- Arch Linux
|
||||||
* CentOS 7
|
- Bodhi 5.0.0
|
||||||
* Debian 9
|
- CentOS 7
|
||||||
* Elementary OS 5.0
|
- Debian 9
|
||||||
* Fedora 28
|
- Elementary OS 5.0
|
||||||
* Fedora 29
|
- Fedora 28
|
||||||
* Fedora 30
|
- Fedora 29
|
||||||
* Linux Mint 19
|
- Fedora 30
|
||||||
* Linux Mint 19.1
|
- Linux Mint 19
|
||||||
* Solus
|
- Linux Mint 19.1
|
||||||
* Ubuntu 18.04
|
- Solus
|
||||||
* Ubuntu 18.10
|
- Ubuntu 18.04
|
||||||
* Ubuntu 19.04
|
- Ubuntu 18.10
|
||||||
* Removed `react-css-modules` dependency
|
- Ubuntu 19.04
|
||||||
* Removed Hyperspace (no active development/insufficient host network)
|
- Removed `react-css-modules` dependency
|
||||||
* Restore main window on error message
|
- Removed Hyperspace (no active development/insufficient host network)
|
||||||
|
- Restore main window on error message
|
||||||
|
|
||||||
## 1.0.2
|
## 1.0.2
|
||||||
* Option to launch application hidden (notification icon only)
|
|
||||||
* Close window to notification area
|
- Option to launch application hidden (notification icon only)
|
||||||
* Unmount on application exit
|
- Close window to notification area
|
||||||
* Ability to cancel mount retry on unexpected failure
|
- Unmount on application exit
|
||||||
* OS X support
|
- Ability to cancel mount retry on unexpected failure
|
||||||
* SiaPrime support
|
- OS X support
|
||||||
* Partial Linux support
|
- SiaPrime support
|
||||||
* Electron to v4
|
- Partial Linux support
|
||||||
* Prevent mount if dependencies are missing
|
- Electron to v4
|
||||||
|
- Prevent mount if dependencies are missing
|
||||||
|
|
||||||
## 1.0.1
|
## 1.0.1
|
||||||
* Added configuration settings for Repertory 1.0.0-alpha.2 and above
|
|
||||||
* Fixed memory leak on component unmount
|
- Added configuration settings for Repertory 1.0.0-alpha.2 and above
|
||||||
* Added error display
|
- Fixed memory leak on component unmount
|
||||||
* Lighter tray icon on Windows
|
- Added error display
|
||||||
* Tray icon indicates mount status on Windows
|
- Lighter tray icon on Windows
|
||||||
* Various fixes/layout changes
|
- Tray icon indicates mount status on Windows
|
||||||
|
- Various fixes/layout changes
|
||||||
|
|
||||||
## 1.0.0
|
## 1.0.0
|
||||||
* Initial release
|
|
||||||
* Windows support
|
- Initial release
|
||||||
|
- Windows support
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
# Repertory UI
|
# Repertory UI
|
||||||
* Lars Floe <lars@krankajen.se>
|
|
||||||
* Oleg Nypadymka <onypadymka@gmail.com>
|
- Lars Floe <lars@krankajen.se>
|
||||||
* Scott E. Graves <scott.e.graves@protonmail.com>
|
- Oleg Nypadymka <onypadymka@gmail.com>
|
||||||
|
- Scott E. Graves <scott.e.graves@protonmail.com>
|
||||||
|
|||||||
12
README.md
12
README.md
@@ -12,13 +12,13 @@ Skynet support is considered EXPERIMENTAL. Files added to Skynet should not be c
|
|||||||
* ScPrime >=1.4.1.2
|
* ScPrime >=1.4.1.2
|
||||||
|
|
||||||
## Downloads
|
## Downloads
|
||||||
* **Repertory UI v1.3.3 Linux
|
* **Repertory UI v1.3.4 Linux
|
||||||
64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.3_linux_x86_64.AppImage)
|
64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.4_linux_x86_64.AppImage)
|
||||||
* NOTE: Linux distributions require `fuse` and `libfuse` to be installed.
|
* NOTE: Linux distributions require `fuse` and `libfuse` to be installed.
|
||||||
* **Repertory UI v1.3.3 OS X
|
* **Repertory UI v1.3.4 OS X
|
||||||
64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.3_mac.dmg)
|
64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.4_mac.dmg)
|
||||||
* **Repertory UI v1.3.3 Windows
|
* **Repertory UI v1.3.4 Windows
|
||||||
64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.3_win.exe)
|
64-bit** [<Download\>](https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.4_win.exe)
|
||||||
|
|
||||||
## Supported Platforms
|
## Supported Platforms
|
||||||
* OS X 64-bit
|
* OS X 64-bit
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ if beginsWith darwin "$OSTYPE"; then
|
|||||||
JQ_EXEC=jq-osx-amd64
|
JQ_EXEC=jq-osx-amd64
|
||||||
SHA256_EXEC="shasum -a 256 -b"
|
SHA256_EXEC="shasum -a 256 -b"
|
||||||
else
|
else
|
||||||
DISTRO_LIST="centos7 debian9 debian10 solus"
|
DISTRO_LIST="centos7 solus"
|
||||||
OUT_FILE=repertory-ui_${APP_VER}_linux_x86_64.AppImage
|
OUT_FILE=repertory-ui_${APP_VER}_linux_x86_64.AppImage
|
||||||
BASE64_EXEC="base64 -w0"
|
BASE64_EXEC="base64 -w0"
|
||||||
JQ_EXEC=jq-linux64
|
JQ_EXEC=jq-linux64
|
||||||
|
|||||||
27
package.json
27
package.json
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "repertory-ui",
|
"name": "repertory-ui",
|
||||||
"version": "1.3.3",
|
"version": "1.3.4",
|
||||||
"private": true,
|
"private": true,
|
||||||
"author": "scott.e.graves@protonmail.com",
|
"author": "scott.e.graves@protonmail.com",
|
||||||
"description": "GUI for Repertory - Repertory allows you to mount Sia, Skynet, and/or ScPrime storage solutions via FUSE on Linux/OS X or via WinFSP on Windows.",
|
"description": "GUI for Repertory - Repertory allows you to mount Sia, Skynet, and/or ScPrime storage solutions via FUSE on Linux/OS X or via WinFSP on Windows.",
|
||||||
@@ -10,21 +10,22 @@
|
|||||||
"@fortawesome/react-fontawesome": "^0.1.13",
|
"@fortawesome/react-fontawesome": "^0.1.13",
|
||||||
"@reduxjs/toolkit": "^1.5.0",
|
"@reduxjs/toolkit": "^1.5.0",
|
||||||
"auto-launch": "^5.0.5",
|
"auto-launch": "^5.0.5",
|
||||||
"axios": "^0.21.0",
|
"axios": "^0.21.1",
|
||||||
"devtron": "^1.4.0",
|
"devtron": "^1.4.0",
|
||||||
"electron-debug": "^3.1.0",
|
"electron-debug": "^3.2.0",
|
||||||
"electron-log": "^4.3.0",
|
"electron-log": "^4.3.2",
|
||||||
"focus-trap-react": "^8.3.2",
|
"focus-trap-react": "^8.4.2",
|
||||||
"font-awesome": "^4.7.0",
|
"font-awesome": "^4.7.0",
|
||||||
"node-cron": "^1.2.1",
|
"node-cron": "1.2.1",
|
||||||
|
"prop-types": "^15.7.2",
|
||||||
"randomstring": "^1.1.5",
|
"randomstring": "^1.1.5",
|
||||||
"react": "^16.14.0",
|
"react": "16.14.0",
|
||||||
"react-checkbox-tree": "^1.6.0",
|
"react-checkbox-tree": "^1.6.0",
|
||||||
"react-dom": "^16.14.0",
|
"react-dom": "16.14.0",
|
||||||
"react-loader-spinner": "^3.1.14",
|
"react-loader-spinner": "^4.0.0",
|
||||||
"react-redux": "^7.2.2",
|
"react-redux": "^7.2.2",
|
||||||
"react-scripts": "4.0.3",
|
"react-scripts": "4.0.3",
|
||||||
"react-tooltip": "^4.2.11",
|
"react-tooltip": "^4.2.15",
|
||||||
"redux": "^4.0.5",
|
"redux": "^4.0.5",
|
||||||
"redux-thunk": "^2.3.0",
|
"redux-thunk": "^2.3.0",
|
||||||
"unzipper": "^0.10.11",
|
"unzipper": "^0.10.11",
|
||||||
@@ -36,6 +37,12 @@
|
|||||||
"electron": "5.0.13",
|
"electron": "5.0.13",
|
||||||
"electron-builder": "22.9.1",
|
"electron-builder": "22.9.1",
|
||||||
"electron-webpack": "^2.8.2",
|
"electron-webpack": "^2.8.2",
|
||||||
|
"eslint": "^7.22.0",
|
||||||
|
"eslint-config-prettier": "^8.3.0",
|
||||||
|
"eslint-plugin-jest": "^24.3.2",
|
||||||
|
"eslint-plugin-prettier": "^3.4.0",
|
||||||
|
"eslint-plugin-react": "^7.23.0",
|
||||||
|
"prettier": "2.2.1",
|
||||||
"webpack": "4.44.2",
|
"webpack": "4.44.2",
|
||||||
"webpack-dev-server": "3.11.1"
|
"webpack-dev-server": "3.11.1"
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,12 +1,4 @@
|
|||||||
const {
|
const { app, BrowserWindow, dialog, ipcMain, Menu, nativeImage, Tray } = require('electron');
|
||||||
app,
|
|
||||||
BrowserWindow,
|
|
||||||
dialog,
|
|
||||||
ipcMain,
|
|
||||||
Menu,
|
|
||||||
nativeImage,
|
|
||||||
Tray
|
|
||||||
} = require('electron');
|
|
||||||
const AutoLaunch = require('auto-launch');
|
const AutoLaunch = require('auto-launch');
|
||||||
const Constants = require('../src/constants');
|
const Constants = require('../src/constants');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
@@ -44,12 +36,12 @@ const UpgradeIPC = require('../src/renderer/ipc/UpgradeIPC');
|
|||||||
const platform = os.platform();
|
const platform = os.platform();
|
||||||
|
|
||||||
const dimensions = {
|
const dimensions = {
|
||||||
height: (platform === 'win32') ? 326 : (platform === 'darwin') ? 322 : 300,
|
height: platform === 'win32' || platform === 'darwin' ? 420 : 400,
|
||||||
width: (platform === 'win32') ? 468 : 628,
|
width: platform === 'win32' ? 468 : 628,
|
||||||
};
|
};
|
||||||
|
|
||||||
let isShutdown = false;
|
let isShutdown = false;
|
||||||
let isQuiting = false;
|
let isQuitting = false;
|
||||||
let isInstalling = false;
|
let isInstalling = false;
|
||||||
let launchHidden = false;
|
let launchHidden = false;
|
||||||
let cleanupReleases = false;
|
let cleanupReleases = false;
|
||||||
@@ -88,7 +80,7 @@ const createWindow = () => {
|
|||||||
if (platform === 'linux') {
|
if (platform === 'linux') {
|
||||||
extra = {
|
extra = {
|
||||||
icon: path.join(__dirname, '../build/', 'logo.png'),
|
icon: path.join(__dirname, '../build/', 'logo.png'),
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the browser window.
|
// Create the browser window.
|
||||||
@@ -102,27 +94,29 @@ const createWindow = () => {
|
|||||||
...extra,
|
...extra,
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
nodeIntegration: true,
|
nodeIntegration: true,
|
||||||
webSecurity: !process.env.ELECTRON_START_URL
|
webSecurity: !process.env.ELECTRON_START_URL,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
if (platform === 'linux') {
|
if (platform === 'linux') {
|
||||||
mainWindow.setMenuBarVisibility(false);
|
mainWindow.setMenuBarVisibility(false);
|
||||||
} else {
|
} else {
|
||||||
mainWindow.removeMenu();
|
mainWindow.removeMenu();
|
||||||
}
|
}
|
||||||
if ((platform === 'darwin') && launchHidden) {
|
if (platform === 'darwin' && launchHidden) {
|
||||||
app.dock.hide();
|
app.dock.hide();
|
||||||
}
|
}
|
||||||
|
|
||||||
// and load the index.html of the app.
|
// and load the index.html of the app.
|
||||||
const startUrl = process.env.ELECTRON_START_URL || url.format({
|
const startUrl =
|
||||||
pathname: path.join(__dirname, '../build/index.html'),
|
process.env.ELECTRON_START_URL ||
|
||||||
protocol: 'file:',
|
url.format({
|
||||||
slashes: true
|
pathname: path.join(__dirname, '../build/index.html'),
|
||||||
});
|
protocol: 'file:',
|
||||||
|
slashes: true,
|
||||||
|
});
|
||||||
|
|
||||||
mainWindow.on('close', function (event) {
|
mainWindow.on('close', function (event) {
|
||||||
if (!isQuiting) {
|
if (!isQuitting) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
if (mainWindow.isVisible()) {
|
if (mainWindow.isVisible()) {
|
||||||
setWindowVisibility(false);
|
setWindowVisibility(false);
|
||||||
@@ -140,9 +134,12 @@ const createWindow = () => {
|
|||||||
MountsIPC.unmountAllDrives();
|
MountsIPC.unmountAllDrives();
|
||||||
});
|
});
|
||||||
|
|
||||||
const appPath = (platform === 'win32') ? path.resolve(path.join(app.getAppPath(), '..\\..\\repertory-ui.exe')) :
|
const appPath =
|
||||||
(platform === 'darwin') ? path.resolve(path.join(path.dirname(app.getAppPath()), '../MacOS/repertory-ui')) :
|
platform === 'win32'
|
||||||
process.env.APPIMAGE;
|
? path.resolve(path.join(app.getAppPath(), '..\\..\\repertory-ui.exe'))
|
||||||
|
: platform === 'darwin'
|
||||||
|
? path.resolve(path.join(path.dirname(app.getAppPath()), '../MacOS/repertory-ui'))
|
||||||
|
: process.env.APPIMAGE;
|
||||||
|
|
||||||
const autoLauncher = new AutoLaunch({
|
const autoLauncher = new AutoLaunch({
|
||||||
name: 'Repertory UI',
|
name: 'Repertory UI',
|
||||||
@@ -151,51 +148,56 @@ const createWindow = () => {
|
|||||||
|
|
||||||
trayContextMenu = Menu.buildFromTemplate([
|
trayContextMenu = Menu.buildFromTemplate([
|
||||||
{
|
{
|
||||||
label: 'Visible', type: 'checkbox', click(item) {
|
label: 'Visible',
|
||||||
|
type: 'checkbox',
|
||||||
|
click(item) {
|
||||||
setWindowVisibility(item.checked);
|
setWindowVisibility(item.checked);
|
||||||
},
|
},
|
||||||
checked: !launchHidden,
|
checked: !launchHidden,
|
||||||
},
|
},
|
||||||
|
{ type: 'separator' },
|
||||||
{
|
{
|
||||||
type: 'separator'
|
label: 'Auto-start',
|
||||||
},
|
type: 'checkbox',
|
||||||
{
|
click(item) {
|
||||||
label: 'Auto-start', type: 'checkbox', click(item) {
|
|
||||||
if (item.checked) {
|
if (item.checked) {
|
||||||
autoLauncher.enable();
|
autoLauncher.enable();
|
||||||
} else {
|
} else {
|
||||||
autoLauncher.disable();
|
autoLauncher.disable();
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: 'Launch Hidden', type: 'checkbox', click(item) {
|
label: 'Launch Hidden',
|
||||||
|
type: 'checkbox',
|
||||||
|
click(item) {
|
||||||
launchHidden = !!item.checked;
|
launchHidden = !!item.checked;
|
||||||
saveUiSettings();
|
saveUiSettings();
|
||||||
},
|
},
|
||||||
checked: launchHidden,
|
checked: launchHidden,
|
||||||
},
|
},
|
||||||
|
{ type: 'separator' },
|
||||||
{
|
{
|
||||||
type: 'separator'
|
label: 'Delete Old Releases',
|
||||||
},
|
type: 'checkbox',
|
||||||
{
|
click(item) {
|
||||||
label: 'Delete Old Releases', type: 'checkbox', click(item) {
|
|
||||||
cleanupReleases = !!item.checked;
|
cleanupReleases = !!item.checked;
|
||||||
saveUiSettings();
|
saveUiSettings();
|
||||||
},
|
},
|
||||||
checked: cleanupReleases,
|
checked: cleanupReleases,
|
||||||
},
|
},
|
||||||
|
{ type: 'separator' },
|
||||||
{
|
{
|
||||||
type: 'separator'
|
label: 'Exit and Unmount',
|
||||||
},
|
click() {
|
||||||
{
|
|
||||||
label: 'Exit and Unmount', click() {
|
|
||||||
closeApplication();
|
closeApplication();
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
]);
|
]);
|
||||||
|
|
||||||
const image = nativeImage.createFromPath(path.join(__dirname, (platform === 'darwin') ? '../build/logo_mac.png' : '../build/logo.png'));
|
const image = nativeImage.createFromPath(
|
||||||
|
path.join(__dirname, platform === 'darwin' ? '../build/logo_mac.png' : '../build/logo.png')
|
||||||
|
);
|
||||||
mainWindowTray = new Tray(image);
|
mainWindowTray = new Tray(image);
|
||||||
|
|
||||||
autoLauncher
|
autoLauncher
|
||||||
@@ -203,7 +205,7 @@ const createWindow = () => {
|
|||||||
.then((enabled) => {
|
.then((enabled) => {
|
||||||
trayContextMenu.items[2].checked = enabled;
|
trayContextMenu.items[2].checked = enabled;
|
||||||
mainWindowTray.setToolTip('Repertory UI');
|
mainWindowTray.setToolTip('Repertory UI');
|
||||||
mainWindowTray.setContextMenu(trayContextMenu)
|
mainWindowTray.setContextMenu(trayContextMenu);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
closeApplication();
|
closeApplication();
|
||||||
@@ -225,37 +227,46 @@ const loadUiSettings = () => {
|
|||||||
cleanupReleases = !!settings.cleanup_releases;
|
cleanupReleases = !!settings.cleanup_releases;
|
||||||
PlatformIPC.setPlatformOverride(settings.platform_override);
|
PlatformIPC.setPlatformOverride(settings.platform_override);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const saveUiSettings = () => {
|
const saveUiSettings = () => {
|
||||||
const settingFile = path.join(helpers.getDataDirectory(), 'ui.json');
|
const settingFile = path.join(helpers.getDataDirectory(), 'ui.json');
|
||||||
try {
|
try {
|
||||||
fs.writeFileSync(settingFile, JSON.stringify({
|
fs.writeFileSync(
|
||||||
cleanup_releases: cleanupReleases,
|
settingFile,
|
||||||
launch_hidden: launchHidden,
|
JSON.stringify({
|
||||||
platform_override: PlatformIPC.getPlatformOverride(),
|
cleanup_releases: cleanupReleases,
|
||||||
}), 'utf-8');
|
launch_hidden: launchHidden,
|
||||||
} catch (e) {
|
platform_override: PlatformIPC.getPlatformOverride(),
|
||||||
}
|
}),
|
||||||
|
'utf-8'
|
||||||
|
);
|
||||||
|
} catch (e) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setIsInstalling = installing => {
|
const setIsInstalling = (installing) => {
|
||||||
isInstalling = installing;
|
isInstalling = installing;
|
||||||
};
|
};
|
||||||
|
|
||||||
const setTrayImage = driveInUse => {
|
const setTrayImage = (driveInUse) => {
|
||||||
let image;
|
let image;
|
||||||
if (driveInUse) {
|
if (driveInUse) {
|
||||||
image = nativeImage.createFromPath(path.join(__dirname, platform === 'darwin' ? '../build/logo_both_mac.png' : '../build/logo_both.png'));
|
image = nativeImage.createFromPath(
|
||||||
|
path.join(
|
||||||
|
__dirname,
|
||||||
|
platform === 'darwin' ? '../build/logo_both_mac.png' : '../build/logo_both.png'
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
image = nativeImage.createFromPath(path.join(__dirname, platform === 'darwin' ? '../build/logo_mac.png' : '../build/logo.png'));
|
image = nativeImage.createFromPath(
|
||||||
|
path.join(__dirname, platform === 'darwin' ? '../build/logo_mac.png' : '../build/logo.png')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
mainWindowTray.setImage(image);
|
mainWindowTray.setImage(image);
|
||||||
};
|
};
|
||||||
|
|
||||||
const setWindowVisibility = show => {
|
const setWindowVisibility = (show) => {
|
||||||
if (show) {
|
if (show) {
|
||||||
mainWindow.show();
|
mainWindow.show();
|
||||||
if (platform === 'darwin') {
|
if (platform === 'darwin') {
|
||||||
@@ -277,7 +288,7 @@ const setWindowVisibility = show => {
|
|||||||
|
|
||||||
if (trayContextMenu && mainWindowTray) {
|
if (trayContextMenu && mainWindowTray) {
|
||||||
trayContextMenu.items[0].checked = show;
|
trayContextMenu.items[0].checked = show;
|
||||||
mainWindowTray.setContextMenu(trayContextMenu)
|
mainWindowTray.setContextMenu(trayContextMenu);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -288,13 +299,13 @@ const standardIPCReply = (event, channel, data, error) => {
|
|||||||
...data,
|
...data,
|
||||||
Error: error instanceof Error ? error.toString() : error,
|
Error: error instanceof Error ? error.toString() : error,
|
||||||
Success: !error,
|
Success: !error,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
app.on('before-quit', function () {
|
app.on('before-quit', function () {
|
||||||
isQuiting = true;
|
isQuitting = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
let instanceLock = app.requestSingleInstanceLock();
|
let instanceLock = app.requestSingleInstanceLock();
|
||||||
|
|||||||
@@ -1,16 +1,22 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
|
<meta
|
||||||
<meta name="theme-color" content="#000000">
|
name="viewport"
|
||||||
|
content="width=device-width, initial-scale=1, shrink-to-fit=no"
|
||||||
|
/>
|
||||||
|
<meta name="theme-color" content="#000000" />
|
||||||
<!--
|
<!--
|
||||||
manifest.json provides metadata used when your web app is added to the
|
manifest.json provides metadata used when your web app is added to the
|
||||||
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
homescreen on Android. See https://developers.google.com/web/fundamentals/engage-and-retain/web-app-manifest/
|
||||||
-->
|
-->
|
||||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json">
|
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||||
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico">
|
<link rel="shortcut icon" href="%PUBLIC_URL%/favicon.ico" />
|
||||||
<link href="https://fonts.googleapis.com/css?family=Nunito:400,700" rel="stylesheet">
|
<link
|
||||||
|
href="https://fonts.googleapis.com/css?family=Nunito:400,700"
|
||||||
|
rel="stylesheet"
|
||||||
|
/>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Notice the use of %PUBLIC_URL% in the tags above.
|
Notice the use of %PUBLIC_URL% in the tags above.
|
||||||
@@ -24,9 +30,7 @@
|
|||||||
<title>Repertory UI</title>
|
<title>Repertory UI</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<noscript>
|
<noscript> You need to enable JavaScript to run this app.</noscript>
|
||||||
You need to enable JavaScript to run this app.
|
|
||||||
</noscript>
|
|
||||||
<div id="root"></div>
|
<div id="root"></div>
|
||||||
<!--
|
<!--
|
||||||
This HTML file is a template.
|
This HTML file is a template.
|
||||||
|
|||||||
@@ -1,60 +1,60 @@
|
|||||||
{
|
{
|
||||||
"Locations": {
|
"Locations": {
|
||||||
"centos7": {
|
"centos7": {
|
||||||
"1.3.3": {
|
"1.3.4": {
|
||||||
"sig": "BL1hmylvFtrY5GAJaZD4m2YAgOgf21N7aCRmQmVQqDpA5tLrLhaCxJaRwQaNTXrNFnwL3YHBXJQf5cJi43dVXI7o+rcltU5QDA2Q7DvzdlaMfL9saBzxLT0D94l017XvczaxhOlypEQIUzFVQYxGzdw3Kx6fKWFySeKgS4l+SB1FTXfeYhfp2ZApOdRB1Y9BzAIN0hATm/UBcBL12FlwCl4+YV6BEIz/07I8VypwxLx68dqGCE/ucTVCf/4D00oGcWEFfrIxBnGzSLFWSyvhvyJwJWvH4VIDIP2KwlhdEs/3p0ETzSl1YbV+bOeUbUGR6Nv2ljF62Y918WOXspiC6N2bDzvpBZkkpKs0xRih4AJQDHR6gs3/43XIqrnTrKMZbZVy2JnEkl3KNGmscLjzS8lus7Wmkn8l0qyOuGY30ef4q60q55VVUw4y+Ox66WbnMYpLpSCY56iNOjw0Kp+rpV7UreLFt5UffQuWWlOttrXs1XJKO9GYv8kbognKAf8gRr7iJWMbZWe8o4++P9ziwt4nd7JlcGzxKinntB4Jn/BHYJnJKGqHhA5j8EJ1QZlu3txruKdcOPV7RpXoFEvOJZ8rji7mUUrlPGM/UJ8JhLcr8P+goKza9dFcX3pFqVHOll4pNOmpPOE+ui+UPSk0I9oCBlEvHSMijywVnwjMh2Yb+VBbuC9Hw5qK2kMZgGXpysa40WrEO5dznJclRSDChIKWVJzdvqnQ2mkR7va+4YAi7Pi/7JnJkO1gcM7O0hGz2bHeG3j7xdUvf0pS8YCcEYojJ97xnBH5UWDYXPBnMsrBMy7mwu/TH8MEGtLiC+9k6THV4Xf9ooS2roHhVskkK5u3xhNFNLxeBVBnQvk7lHynjFbjVNa3URMsD5J5SzQ8O10UhAV8vnpTD70GO25htI1MZuMgV8KPZZ5pOlUMrxqgS14obph8TxMUrD3Wy6SZrwYj/0JTY0lkfhxaXuaecoKDVtCVmiTCcioFryvMymCuz0/0FV8ctlau5Ko3W2W0wmWCVmlDSU5xEybVDegSSnI6bWPQn1SgHUC6DpaWa5LOtCMBgA84AAEMRCMDIcc1EY/VAHz/NeU9UJFESdv/uniL2wcWRq72xPYVwD5fB5YEyFgHx3UXNxhtwMWeThEaOvmHp2snOksM6RSjXVcBLkzK7JQxb25AKEo0rpgHqcVZo+pRpl/6RyXmJWQb1Fl0N6/0fDzJUS3Ji1fAw4O9T2ftrrk1WUD/PsjdaXKRJfWDNl9iWN4gbv+KZAwx+BgF+oMD4b7bOU+cQnkISzT2WD8k/S7wKhrbyMGOWwPYHnebIj0TK0QR0+RWpcP5BggGe7/YpjizvVPGBySjYTcWcig=",
|
"sig": "CQZdxHimuD3li5JcHKJC3zdqNdw18RXFBQ9fgtxXe5FpgPq3bycXrMjmqaJaz25fLPl++e33PSlnzdaC2ede9vrWSfqfB3UG5Vdxxth/YnsqV4YzgGwOed6v9F7YcR2wgts8FpCzy+vokGWu2lI05pCx4ObNgqyvbyGcvGdzgTylhF+MlgSDtXdDV6B1Ba9d+Oj8lh3eA2d7v09ltxavEoiQmrX0ODK9dov9axT3JT/RZTNpAhTSfTT5YUgXmYWYQjZKdwCbFc4k23C1V0SKivB8lQ26Eaaxegwse+Kybar6CzisSkvAlTza9OCo/pxmJ/YedReldyj8pbq7+BweG82JWm8HVl4Y+ppXej69zFtAgcv1QWMYyXmBTfzoKMEUhrH3Brnj3b4ssAG6MKH2Y+lzwhzDYhpNXZ/+jfknFZPaGQ4UgUd1Nf46dPk0Pt+x3tzcweRO6XacfI8e+PNf5YIk+CKxyGjoVJfz1dEAKKg1RL1RXqHPK44MTSrHAIyUPgRNUq6zX23VkfdT4b/IftaIYEEO738wT0nutAtg7RLo2jx6w3hTjDSmh9Wz/szhtS/pP670PycryqH/JaE/5n4lgvSIZN7Inz9WWHbttX54H36usqcEiKr5yoSeOvdIsjWpHguKxasRNbib+Idnhug/Zs8XmshUfwAH3Y+6Wy5dM+IGfuyFpwkfQE2DQmfriyyn2gQf1EJZ6lxuFy1q5vQ9pf3QOaEU72yCu63EEYiXEnPQKgMPkBXxgo6Rp/Nskth0F2XXUYDUPD3lzOJLNMKn3G7ta5EkmZZhrk94pm8X5DpXdxzxFr/lvlWNic5trhWhVtJfci+yxZTI9IiXEfLTck0oYzkpaSxgTvOZ4DklW92xk682F41eNmdo64NwyqeHYS7uvLsJa4aRmRVmsfbY5RuOrDlAmr+yDX9OaISFfhGgByqPlv/5Sm27GFCHFfkvPrUGQWBOFnoRrnr1VZqKr2xRImDUhsP2FNaZJH2E0lBh7P6WmFu2/N1XwJ9w3TX1pwQXGJ/XERSCj7w972VZ8YMj+LHZ4anpZHuY4eL9PAkgwEEpTIqUJuJ2Oj1LGG3GGlT/HrR7tSofybi6+tNsD4egdFZ4HI3+nrPFGbYTQNQzzxXmPnukdP66h4lGGz8bBVT/wezKCK06RrgUKoi+GxcndMnF6JlAzzmiEDh2CXHJsFIr5eDx+pgxbr4Ibz4Mwu9qfeN6fNC+EAkewC1W3f3HoX3oozAT1AobitkT6CV7rHUD4xHWih/7uA+9uuAI2VgxfpfzyvR5H7kd51p63sB1DyvzpB9ssf/E7vxyzQJJhDEOWXUHi0ciMgeElFgJMUI49xzGvJUizV6YmwE=",
|
||||||
"sha256": "03c29d95cb5406f90b076d633fd6a3e2f4a42a5bcf75433099453c0767acc761",
|
"sha256": "ef29a5aad24f9f10cbac3e46b1be334a2f80b184efe0dcc09a5c1fa4526a68f4",
|
||||||
"urls": [
|
"urls": [
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.3_linux_x86_64.AppImage"
|
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.4_linux_x86_64.AppImage"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"darwin": {
|
"darwin": {
|
||||||
"1.3.3": {
|
"1.3.4": {
|
||||||
"sha256": "7fbcca92d5d3c728e3663a4cf4035c5d1c45f4cd3a43b5dab605969aa9f95d29",
|
"sig": "BGYvkHV/lP0/6sBdrsO2L3W94oFHduVd8J3DT/SJIXUKRbjLIUGLKwnF27H7gVr1rO1vHQWaNuVaBHQ8guTqh2GAxEFr9w+sFMm0dvnuRndpxcJ4AtVT6j7TiRojPMAPFk9Kd8rNda0jGH9CPG8358K0SNVU61/upi3+zHv4R/KYC47ZK/7R6BWxBUTA1l8/5Q70TE9Kco75j6c8fK8dV6nFfN8rp2mAmxZhmRtV2uFL4OguYhxM6Oba+wxVlq7ywiPjtck4gkYrI9wMvWetK0erI6lwki5YpwEN1tRqDqD2DeKBqsMj5H8kElHMCh+g9Y5DvVIKR1pZdpopgmIQNsfmo/CYgicUvN0ppvyMuLJ/p4PPVIg6ldu6VgjOBXykZIRkZF4TgKsVaDdOpQ6E2Wd4+tERrXwKeP76+3h1RYl4W2NSZ9Lc2wWe3FmK4HKU6jbJ1qy8FsjjxEHs0OJvvYmmEp9bIMtCPZnwf5wR4V2Ht3BScV93mAaWbaykBuWWpXtxiuxw01BZ9w8LAHKJ6BX48wEtz6CAQqF8nc5kDkexsMy2Al2fv3lj+xa5RPjHO/tY4jbUrAn1TCVc98tz+vHbD9TITVkdYcSPNUSMpUANGTvOTQ1CkjOO6pavpMlo96kdLKG+YqK0ERfCQ4YI3V7CjJhEdrkg9ZhLtv7vtyG4WicXBOARaW1OiQFYB48/np/6anKoS2uCDRQdj9vHLyE4C7PwfPKIg+cFCzCMGcvjHrBbGf7PnmSyYFY7PvGcEWylINoWeHquqAGq+N6wTNm+5K/IzmXh+II4dm4f0G15S4gSE/Ux4sIgYADAVXz1uaeARr+EfDOtUjqxAX1Aay1y+1WEFI3L66gszcdpiRsc46gwbYIJ585rVs+FOLNZI6Ak0RawzyZcifCcwaTWGG+kASLyC5XIgayw0hT3qPoZofSasB1RGM3PQ6trz8937RdDK2rQpry01zWsG/Kk+gxI5mZkU2kWgPtUxCPTG6+lLkEY7p9mg/Lo4/8Ze/qlb/xR/9i4+BBqtRRUHJzAsps0K0KicO7+MXB+Sc4hbvXkGFwpFd+JYy/Ry7TVRpiCp8Hdhk9PRtp//Ub1Fun4f7eadTCsbJs7duwKeBhUP0uGP2xo1pyWtFmZLm5ww2g40nEIHy8C5cvadPlN3NTKBZ8lqXqiN6fNtXel+T65vyoVic1FbVYihXSZOmFsJ+7mwDF6ayelAnx9kC0uI0gxpjaZWGPa1ygLWYNkSz4KIO2m5t9NZL6JyVXIRgPvie9rJKAFB2lgxBnkehpQMbU/FgpbzWb0a78OEkAxr4mD7U4WerlVU6jg8xx53tkCSpv35kNwsAOwW7YE+KN8VMW+6j0=",
|
||||||
"sig": "BPM/WKDq+vueZ7YcSI3S+GbisBPsv/OjZPnyxAfHvDQst+Fjrx/9jmTJTTFMtP0xZ1RtrnmSkAwjnyTJRgEPCfe4yWsV52augPp9tvEBVKJgb5KM10h1yN0+DlNB4PMPdE6Ix520mIbQXY72BedPt3qhkom5RN/rQ/ZTHO9qmKwHpvaukh4tUsfsMlGEzjm/Bzch2qdj1pi4CGuug0KxIp23NSgk2ic4EcnVR+aa1lhEpjgE6pGg5ikQ07GR/mFkvr6xAlrEQVXuJ7qGStkXjNuNywSAhT+kUwRr1Wd43s7FEikInLLbewhXStZLG/Q9fVYFxXBoPhk6g5deshGabmNCWt/4JcYYFEq5HWCoaT/86DKQJnLZ3ZMnO/cqlj/7jbi29TmTxvoqdDADp7yRMAcM89LsjDMiFnADlnlsBhUYrM8kjJsd4VGZESviMWmls3kPr3oaZ+OjBQdcYX/bpvrFULFtRxOHYPJHJ9W1IkOd2EGYf/BcxyjRxGqI18oj3a9VaVzyM3IWm3i2Bw0ijj2GQ+p/qeyy3lzTNM25LuUe/PJF9d0wuLisTpvFyW52tNOBLqhrT2wQK8oCo95MqSNKd22vfxJzTcD8PlZSG9ZXNTrmKFbYqJmi6JptUNLVlyn1L8uyJf4S+vL8HAJ1hSqr4iJ/AIF5nMBONzE/4PCP3tathkJ67Yfw0eQbOwl7d+fXSJjZtggFUADLGcwrCLHRclSiW7/9LpL6YJD+h0Ud9ZgLNjYjU/bHL6TCqeAtbSBYG6VNFWN+s73NaBkzC2kx6HnWaa2q4AHAxoix7/LUWhdWh85XGa1UUFWtyxy+hIM3cpacKrSd3u9VdKLHL3GtdfvQjvEE/5UyjH2VzedRVZntjVlBTnVDHq/J4prBAZyA/PSOGtK1x0LmlH2UdT3QEU1WNZaag7vLKWxfPPVvO8zoJG21l8xFWfoAZ/90HA5WRxEsSavSUXzvffmv9O5C/WnWj0tNRsWYqwOYS9l7IcrUDB68V2Rws/sDG56xfgqzdZM4CjM3BBQyarVWr9wyzxAfR0VFOf7GsjF7A1OpQXPiY8pVHg7QPTUSG0Ssse1/leZnU11CEpr/v8JwmHi7LRZ0KSbUowRwPjkzVdDrRjnIQh+2ssphL5mJHNfoxNUFAbvQidN5OjzdUoqEK7H6/OjjHek9mgvJuDDYSHV5cUwgmgPFTwONarrepFThj5YwKGQhYYsCqJLZ+ZunzsjXTJ3VlIF+B0qir370oEWq9dWvaLUYkC6QCHifJ+ZVaPp/pNln7S0zh/dTGO84aKwS0hF7S0uvTTiKRXHTBDmHnmSQuoG8Fku1iqbE9fkScIYPF2wO5N7UPgU86te8/to=",
|
"sha256": "5bb39cebbb0ccb3d010513d8f2aec11d370d78214a40515a4b484a3c65eb58ad",
|
||||||
"urls": [
|
"urls": [
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.3_mac.dmg"
|
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.4_mac.dmg"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"solus": {
|
"solus": {
|
||||||
"1.3.3": {
|
"1.3.4": {
|
||||||
"sig": "BL1hmylvFtrY5GAJaZD4m2YAgOgf21N7aCRmQmVQqDpA5tLrLhaCxJaRwQaNTXrNFnwL3YHBXJQf5cJi43dVXI7o+rcltU5QDA2Q7DvzdlaMfL9saBzxLT0D94l017XvczaxhOlypEQIUzFVQYxGzdw3Kx6fKWFySeKgS4l+SB1FTXfeYhfp2ZApOdRB1Y9BzAIN0hATm/UBcBL12FlwCl4+YV6BEIz/07I8VypwxLx68dqGCE/ucTVCf/4D00oGcWEFfrIxBnGzSLFWSyvhvyJwJWvH4VIDIP2KwlhdEs/3p0ETzSl1YbV+bOeUbUGR6Nv2ljF62Y918WOXspiC6N2bDzvpBZkkpKs0xRih4AJQDHR6gs3/43XIqrnTrKMZbZVy2JnEkl3KNGmscLjzS8lus7Wmkn8l0qyOuGY30ef4q60q55VVUw4y+Ox66WbnMYpLpSCY56iNOjw0Kp+rpV7UreLFt5UffQuWWlOttrXs1XJKO9GYv8kbognKAf8gRr7iJWMbZWe8o4++P9ziwt4nd7JlcGzxKinntB4Jn/BHYJnJKGqHhA5j8EJ1QZlu3txruKdcOPV7RpXoFEvOJZ8rji7mUUrlPGM/UJ8JhLcr8P+goKza9dFcX3pFqVHOll4pNOmpPOE+ui+UPSk0I9oCBlEvHSMijywVnwjMh2Yb+VBbuC9Hw5qK2kMZgGXpysa40WrEO5dznJclRSDChIKWVJzdvqnQ2mkR7va+4YAi7Pi/7JnJkO1gcM7O0hGz2bHeG3j7xdUvf0pS8YCcEYojJ97xnBH5UWDYXPBnMsrBMy7mwu/TH8MEGtLiC+9k6THV4Xf9ooS2roHhVskkK5u3xhNFNLxeBVBnQvk7lHynjFbjVNa3URMsD5J5SzQ8O10UhAV8vnpTD70GO25htI1MZuMgV8KPZZ5pOlUMrxqgS14obph8TxMUrD3Wy6SZrwYj/0JTY0lkfhxaXuaecoKDVtCVmiTCcioFryvMymCuz0/0FV8ctlau5Ko3W2W0wmWCVmlDSU5xEybVDegSSnI6bWPQn1SgHUC6DpaWa5LOtCMBgA84AAEMRCMDIcc1EY/VAHz/NeU9UJFESdv/uniL2wcWRq72xPYVwD5fB5YEyFgHx3UXNxhtwMWeThEaOvmHp2snOksM6RSjXVcBLkzK7JQxb25AKEo0rpgHqcVZo+pRpl/6RyXmJWQb1Fl0N6/0fDzJUS3Ji1fAw4O9T2ftrrk1WUD/PsjdaXKRJfWDNl9iWN4gbv+KZAwx+BgF+oMD4b7bOU+cQnkISzT2WD8k/S7wKhrbyMGOWwPYHnebIj0TK0QR0+RWpcP5BggGe7/YpjizvVPGBySjYTcWcig=",
|
"sig": "CQZdxHimuD3li5JcHKJC3zdqNdw18RXFBQ9fgtxXe5FpgPq3bycXrMjmqaJaz25fLPl++e33PSlnzdaC2ede9vrWSfqfB3UG5Vdxxth/YnsqV4YzgGwOed6v9F7YcR2wgts8FpCzy+vokGWu2lI05pCx4ObNgqyvbyGcvGdzgTylhF+MlgSDtXdDV6B1Ba9d+Oj8lh3eA2d7v09ltxavEoiQmrX0ODK9dov9axT3JT/RZTNpAhTSfTT5YUgXmYWYQjZKdwCbFc4k23C1V0SKivB8lQ26Eaaxegwse+Kybar6CzisSkvAlTza9OCo/pxmJ/YedReldyj8pbq7+BweG82JWm8HVl4Y+ppXej69zFtAgcv1QWMYyXmBTfzoKMEUhrH3Brnj3b4ssAG6MKH2Y+lzwhzDYhpNXZ/+jfknFZPaGQ4UgUd1Nf46dPk0Pt+x3tzcweRO6XacfI8e+PNf5YIk+CKxyGjoVJfz1dEAKKg1RL1RXqHPK44MTSrHAIyUPgRNUq6zX23VkfdT4b/IftaIYEEO738wT0nutAtg7RLo2jx6w3hTjDSmh9Wz/szhtS/pP670PycryqH/JaE/5n4lgvSIZN7Inz9WWHbttX54H36usqcEiKr5yoSeOvdIsjWpHguKxasRNbib+Idnhug/Zs8XmshUfwAH3Y+6Wy5dM+IGfuyFpwkfQE2DQmfriyyn2gQf1EJZ6lxuFy1q5vQ9pf3QOaEU72yCu63EEYiXEnPQKgMPkBXxgo6Rp/Nskth0F2XXUYDUPD3lzOJLNMKn3G7ta5EkmZZhrk94pm8X5DpXdxzxFr/lvlWNic5trhWhVtJfci+yxZTI9IiXEfLTck0oYzkpaSxgTvOZ4DklW92xk682F41eNmdo64NwyqeHYS7uvLsJa4aRmRVmsfbY5RuOrDlAmr+yDX9OaISFfhGgByqPlv/5Sm27GFCHFfkvPrUGQWBOFnoRrnr1VZqKr2xRImDUhsP2FNaZJH2E0lBh7P6WmFu2/N1XwJ9w3TX1pwQXGJ/XERSCj7w972VZ8YMj+LHZ4anpZHuY4eL9PAkgwEEpTIqUJuJ2Oj1LGG3GGlT/HrR7tSofybi6+tNsD4egdFZ4HI3+nrPFGbYTQNQzzxXmPnukdP66h4lGGz8bBVT/wezKCK06RrgUKoi+GxcndMnF6JlAzzmiEDh2CXHJsFIr5eDx+pgxbr4Ibz4Mwu9qfeN6fNC+EAkewC1W3f3HoX3oozAT1AobitkT6CV7rHUD4xHWih/7uA+9uuAI2VgxfpfzyvR5H7kd51p63sB1DyvzpB9ssf/E7vxyzQJJhDEOWXUHi0ciMgeElFgJMUI49xzGvJUizV6YmwE=",
|
||||||
"sha256": "03c29d95cb5406f90b076d633fd6a3e2f4a42a5bcf75433099453c0767acc761",
|
"sha256": "ef29a5aad24f9f10cbac3e46b1be334a2f80b184efe0dcc09a5c1fa4526a68f4",
|
||||||
"urls": [
|
"urls": [
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.3_linux_x86_64.AppImage"
|
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.4_linux_x86_64.AppImage"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"win32": {
|
"win32": {
|
||||||
"1.3.3": {
|
"1.3.4": {
|
||||||
"sha256": "a86091d453600506cccb25759b62a638c482ce8983d24a5b3ec1def9545ae1c3",
|
"sig": "BbUW6SbAl5pS+WF2kzmy0O8Zw6sdkP1TOP7GS78I+jNLgXzvFodQDsC2dqZclrtcqNvVLIdfHfZeRFYKsrJnEFmZc9Jib3+4rALdhsJY0kRzhgfZkhwydAIuRP/RTXJ4AKh8XgCuxoToPtytslSCgHN5LJmtDQL10naJrvk40n9Pkt0Kjep/8Bj1fc+7WMgtLaKJXiKjGlfax4/2UeMVyqTmkEbRPf9o8w3esfSfRvMwqAN1LnwW4ZbPDLVm1cRh9+BovCKEmVc28LvdtWY0pOios8K5NOI8GcfDmL+a3NsKow1GQPTqEMEa6/z+njdYehVVMeFpA8kI0UKljrQTf4n22BNE1ZzpBOoOCRxcrI4BeG5cy1VhzM7BUm+jaKxY/IuqdLNplXa7VSfRuI1sPVEegmQmDhZCJJXdugVC008UXO8HH731EHUCctMutQTCNLVHg1djyVTtuevQRalXEQMSY+VbAEP1ED3cwfJgwk92ZAVc323IjGNvjeDDlZW5sFUJUYBv94tfy8AWFDk2HnXG5r480fHwrI3ZoZh6cAssiV3OYaLjWUYlQkfWi7fIr43tEIquMxqcuMN+iRfxl+klvQt50xdeE+S/YWMRnixj0h+xSL79f0dryyYofwL924e8U8XSwxGvAPNiADc+VoyRNSqQnPtHn164VOfAPZCaIn8puex9LA5JYEhY9ayB7EW2YVd/Pfp7uI/KAzmngFuKyKG8KVvVE7qF7zSjX222SlweBRLm7f1QPthl0XzVgzzZJ8S1cHPJ//1unOsimQGmPhZDQrnhdFSrtkd2D1kX5dqmTKEx+wiL+Tm8cWFwPvg2nUfWlC9Zytpi9VjpbnczTQLW+JsPB7HOQ4ZYaWaxQATvb3kku3icWv9dY6gWa9Lc9N+gXbGkPV9R+Np0m92m9QA+TDf9HrZwzXLfBjUbfqrMvGhCdznJ9PFflbNQIsDLJeBFdoaHYX88IJIgom60Ef+EjUAhAsvW5A12g+4phENSIg2iv7Ifxc4l8KgtIyjLst9sBdhTDOH3J3Cscd+BxWVLeGjMWoMZ2mU6Bf6ohnO4Ofh9+oqmemHu2rrI3RxOSQF4w9sEv6AtD6C7TG3B+8qFdMic1XkRDxAsNHrwfKOxCytQ89fBH+fzNHRzGys7ADoTH0vm7FR7iADdy83Xt+i+7TK9KvUkR/W5cGgxRHDS1g4SdLetMf/FQ5olbyaW/OiGDtpzipS/Yv3QCMfn4XB3GahMPgLzu0uI9MNXFz9zjwwy0owgzP3Q6+ff3cn8QOIfa0RRLfJgyS71kbcEjHHRehYfuRHNi9/5NMF29irsbAxhWZwncCsoDRJvycwyz6dY+DZHkaDqUv0h8ew=",
|
||||||
"sig": "AeaJxYZ8LpeCAKJEeS0QmfwL894tHmJ2tHi4JRQPoPOzU2fxMSthgOIOLgeTIDuagVk4hbUeZ02Q/t53AQCcrgmyT9xxJy1/2gdkgBN4yLcD76dg9QsSIAT/D3W3oOwzvRu2GRHzKKjD+dzR2HDSbMz6YHsIJDBGqWEcd3PTJ0jREWpQm8slbNflnmMIgumRKzwws93fus4rxXqTTgl/wn01wgSbgrSjncuTRXQUtk63LofkH87g3ivLd3iHVUnCHYQlpKKUuyK1t5Prr7akcFno588k5VGmRYrXljcakobZVeG5ikCFl3+463Eq4Bf1AzMHS6jlSAyEigF10Ys0iD59DnoE2/q2GJekbW0Zjs7qWTQldJyvwa5lhsU5gOxgJYcydhmAu1jEw74jHu/XDFxIpsrfAZfowHTuItsv5kSjJAQleMtDmMnOPs+S+PDhgOTQjtksplnu3aSHdKKE88nkUdWhcddxTFqD1R6IKSBvPZGcRX17n64MnzWqq3yuSV0qAe0CgRWF7Cy48YMeaPk1V+yCkUSh2nvIkjfRc5rRv14Jh2sq03beMxnEC2n+PSV5WA85gWcmkl53iDJSfWATCq6M1rj+PzTwmnjagjnhgDDLolH/g/RWabUEA9ywG9xtJb2M0aCAY7sqeX8I5WEODkfmHTGvYi6E9L7xvpHwmYPxVr2Frs+PbKa8h5C4RLJZGQlia5Rw7i3g0byd9shpbRcrzoGEJmBbkzdMWgSwIVXPD+EqqfiTOdcmQy1JwsTF9zUx7auxXviAddr6HlXXFLt661b47WElRJGXgl1m9qi8eSYRIH0a5wF5XRU+LyCDllUTZhMNNGGP1U3azu3iYsOaYphobn/IVlZBJ4phoafr4D69PbOG+k9B4pTxwHeY7jmszUpiJMgonoftp9TLsLIzDcXBp0vEVoPE0fr1ljOAaQgdtsi0wr0Z2Nxtp5d04d/cYfvfOKx2M/uupdpmU/aBCnv79r9etnnEHhcQtpfCNAZ4567pYAiLiJ4zVEct715hZ6LN57Wx5YWfNT6aCUogWaLx0K5CaL9kv0HyllIoM5z1+7unKwmq4nSO5A1QAh67yCfPTISL2m1SIODmnYUqgBk95oX/AAEk+gaCil0b2A6JGxbI3OcUEyN4BZcWyJRL2QToEmUMNkUuK+aaQl5OTp2wNLFXO1wpqXQAVppDeY2nHqjUY9B2Wku2wFV61T1VZ9sYlGoFYjK7G6PQUsBCTmXAlpzLUjWadgWvKPyRehy4Bzdqwy+BuZ8BEC+txUDnh90jUqd9YCXGsMLEGa6EXijjCBRhqdfQTLZpd3n62YpMvXkfQ6lNnaI4ybqqXwuDpvB5Cvx3tk2VOwc=",
|
"sha256": "8b1e9bd73e11e4f8ef66f417c8735ea48715f41e822d7f77852bf392ac5970c6",
|
||||||
"urls": [
|
"urls": [
|
||||||
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.3_win.exe"
|
"https://bitbucket.org/blockstorage/repertory-ui/downloads/repertory-ui_1.3.4_win.exe"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"Versions": {
|
"Versions": {
|
||||||
"centos7": [
|
"centos7": [
|
||||||
"1.3.3"
|
"1.3.4"
|
||||||
],
|
],
|
||||||
"darwin": [
|
"darwin": [
|
||||||
"1.3.3"
|
"1.3.4"
|
||||||
],
|
],
|
||||||
"linux": [
|
"linux": [
|
||||||
"unavailable"
|
"unavailable"
|
||||||
],
|
],
|
||||||
"solus": [
|
"solus": [
|
||||||
"1.3.3"
|
"1.3.4"
|
||||||
],
|
],
|
||||||
"unknown": [
|
"unknown": [
|
||||||
"unavailable"
|
"unavailable"
|
||||||
],
|
],
|
||||||
"win32": [
|
"win32": [
|
||||||
"1.3.3"
|
"1.3.4"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/App.css
16
src/App.css
@@ -8,19 +8,3 @@
|
|||||||
background-size: cover;
|
background-size: cover;
|
||||||
}
|
}
|
||||||
|
|
||||||
.AppContainer {
|
|
||||||
width: 100%;
|
|
||||||
height: 100%;
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.AppHeader {
|
|
||||||
height: 28px;
|
|
||||||
margin-bottom: var(--default_spacing);
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.AppContent {
|
|
||||||
height: calc(100% - 36px);
|
|
||||||
box-sizing: border-box;
|
|
||||||
}
|
|
||||||
321
src/App.jsx
321
src/App.jsx
@@ -1,8 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './App.css';
|
import './App.css';
|
||||||
|
import AddEditHost from './containers/AddEditHost/AddEditHost';
|
||||||
import Box from './components/UI/Box/Box';
|
import Box from './components/UI/Box/Box';
|
||||||
import Configuration from './containers/Configuration/Configuration';
|
import Configuration from './containers/Configuration/Configuration';
|
||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
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 ErrorDetails from './components/ErrorDetails/ErrorDetails';
|
import ErrorDetails from './components/ErrorDetails/ErrorDetails';
|
||||||
@@ -11,28 +12,22 @@ import InfoDetails from './components/InfoDetails/InfoDetails';
|
|||||||
import IPCContainer from './containers/IPCContainer/IPCContainer';
|
import IPCContainer from './containers/IPCContainer/IPCContainer';
|
||||||
import Loading from './components/UI/Loading/Loading';
|
import Loading from './components/UI/Loading/Loading';
|
||||||
import MountItems from './containers/MountItems/MountItems';
|
import MountItems from './containers/MountItems/MountItems';
|
||||||
import NewReleases from './components/NewReleases/NewReleases';
|
import NewReleases from './components/NewReleases/NewReleases.jsx';
|
||||||
import {notifyError} from './redux/actions/error_actions';
|
import { notifyError } from './redux/actions/error_actions';
|
||||||
import Reboot from './components/Reboot/Reboot';
|
import Reboot from './components/Reboot/Reboot';
|
||||||
import {
|
import {
|
||||||
setDismissNewReleasesAvailable,
|
setDismissNewReleasesAvailable,
|
||||||
setNewReleasesAvailable
|
setNewReleasesAvailable,
|
||||||
} from './redux/actions/release_version_actions';
|
} from './redux/actions/release_version_actions';
|
||||||
import ReleaseVersionDisplay from './components/ReleaseVersionDisplay/ReleaseVersionDisplay';
|
import ReleaseVersionDisplay from './components/ReleaseVersionDisplay/ReleaseVersionDisplay';
|
||||||
import {
|
import { displaySelectAppPlatform, saveState } from './redux/actions/common_actions';
|
||||||
displaySelectAppPlatform,
|
|
||||||
saveState
|
|
||||||
} from './redux/actions/common_actions';
|
|
||||||
import SelectAppPlatform from './containers/SelectAppPlatform/SelectAppPlatform';
|
import SelectAppPlatform from './containers/SelectAppPlatform/SelectAppPlatform';
|
||||||
import Text from './components/UI/Text/Text';
|
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';
|
||||||
import {
|
import { loadReleases, setDismissUIUpgrade } from './redux/actions/release_version_actions';
|
||||||
loadReleases,
|
|
||||||
setDismissUIUpgrade
|
|
||||||
} from './redux/actions/release_version_actions';
|
|
||||||
import YesNo from './components/YesNo/YesNo';
|
import YesNo from './components/YesNo/YesNo';
|
||||||
import {createModalConditionally} from './utils';
|
import { createModalConditionally } from './utils.jsx';
|
||||||
import SkynetImport from './containers/SkynetImport/SkynetImport';
|
import SkynetImport from './containers/SkynetImport/SkynetImport';
|
||||||
import ApplicationBusy from './components/ApplicationBusy/ApplicationBusy';
|
import ApplicationBusy from './components/ApplicationBusy/ApplicationBusy';
|
||||||
import SkynetExport from './containers/SkynetExport/SkynetExport';
|
import SkynetExport from './containers/SkynetExport/SkynetExport';
|
||||||
@@ -59,13 +54,17 @@ class App extends IPCContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentDidUpdate(prevProps) {
|
componentDidUpdate(prevProps) {
|
||||||
if ((prevProps.Release !== this.props.Release) ||
|
if (
|
||||||
(prevProps.ReleaseVersion !== this.props.ReleaseVersion) ||
|
prevProps.Release !== this.props.Release ||
|
||||||
(prevProps.VersionLookup !== this.props.VersionLookup)) {
|
prevProps.ReleaseVersion !== this.props.ReleaseVersion ||
|
||||||
|
prevProps.VersionLookup !== this.props.VersionLookup
|
||||||
|
) {
|
||||||
this.props.saveState();
|
this.props.saveState();
|
||||||
} else if (Object.keys(this.props.ProviderState).filter(k => {
|
} else if (
|
||||||
return this.props.ProviderState[k] !== prevProps.ProviderState[k];
|
Object.keys(this.props.ProviderState).filter((k) => {
|
||||||
}).length > 0) {
|
return this.props.ProviderState[k] !== prevProps.ProviderState[k];
|
||||||
|
}).length > 0
|
||||||
|
) {
|
||||||
this.props.saveState();
|
this.props.saveState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -76,14 +75,16 @@ class App extends IPCContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
getSelectedVersion = () => {
|
getSelectedVersion = () => {
|
||||||
return (this.props.ReleaseVersion === -1) ?
|
return this.props.ReleaseVersion === -1
|
||||||
'unavailable' :
|
? 'unavailable'
|
||||||
this.props.VersionLookup[Constants.RELEASE_TYPES[this.props.Release]][this.props.ReleaseVersion];
|
: this.props.VersionLookup[Constants.RELEASE_TYPES[this.props.Release]][
|
||||||
|
this.props.ReleaseVersion
|
||||||
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
handleUpgradeIconClicked = () => {
|
handleUpgradeIconClicked = () => {
|
||||||
if (this.props.UpgradeAvailable) {
|
if (this.props.UpgradeAvailable) {
|
||||||
this.props.setDismissUIUpgrade(false)
|
this.props.setDismissUIUpgrade(false);
|
||||||
} else if (this.props.NewReleasesAvailable2.length > 0) {
|
} else if (this.props.NewReleasesAvailable2.length > 0) {
|
||||||
this.props.setNewReleasesAvailable(this.props.NewReleasesAvailable2);
|
this.props.setNewReleasesAvailable(this.props.NewReleasesAvailable2);
|
||||||
this.props.setDismissNewReleasesAvailable(false);
|
this.props.setDismissNewReleasesAvailable(false);
|
||||||
@@ -93,44 +94,51 @@ class App extends IPCContainer {
|
|||||||
render() {
|
render() {
|
||||||
const selectedVersion = this.getSelectedVersion();
|
const selectedVersion = this.getSelectedVersion();
|
||||||
|
|
||||||
const downloadEnabled = this.props.AllowDownload &&
|
const downloadEnabled =
|
||||||
|
this.props.AllowDownload &&
|
||||||
!this.props.MountsBusy &&
|
!this.props.MountsBusy &&
|
||||||
!this.props.DownloadActive &&
|
!this.props.DownloadActive &&
|
||||||
(selectedVersion !== 'unavailable') &&
|
selectedVersion !== 'unavailable' &&
|
||||||
(selectedVersion !== this.props.InstalledVersion);
|
selectedVersion !== this.props.InstalledVersion;
|
||||||
const missingDependencies = (this.props.MissingDependencies.length > 0) &&
|
const missingDependencies = this.props.MissingDependencies.length > 0 && this.props.AllowMount;
|
||||||
this.props.AllowMount;
|
|
||||||
|
|
||||||
const allowMount = this.props.AllowMount &&
|
const allowMount =
|
||||||
|
this.props.AllowMount &&
|
||||||
this.props.InstalledVersion !== 'none' &&
|
this.props.InstalledVersion !== 'none' &&
|
||||||
!missingDependencies &&
|
!missingDependencies &&
|
||||||
!this.props.InstallActive;
|
!this.props.InstallActive;
|
||||||
|
|
||||||
const remoteSupported = this.props.LocationsLookup[selectedVersion] &&
|
const remoteSupported =
|
||||||
|
this.props.LocationsLookup[selectedVersion] &&
|
||||||
this.props.LocationsLookup[selectedVersion].supports_remote;
|
this.props.LocationsLookup[selectedVersion].supports_remote;
|
||||||
|
|
||||||
const s3Supported = this.props.LocationsLookup[selectedVersion] &&
|
const s3Supported =
|
||||||
|
this.props.LocationsLookup[selectedVersion] &&
|
||||||
this.props.LocationsLookup[selectedVersion].s3_support;
|
this.props.LocationsLookup[selectedVersion].s3_support;
|
||||||
|
|
||||||
const skynetSupported = this.props.LocationsLookup[selectedVersion] &&
|
const skynetSupported =
|
||||||
|
this.props.LocationsLookup[selectedVersion] &&
|
||||||
this.props.LocationsLookup[selectedVersion].skynet_support;
|
this.props.LocationsLookup[selectedVersion].skynet_support;
|
||||||
|
|
||||||
const scPrimeSupported = this.props.LocationsLookup[selectedVersion] &&
|
const scPrimeSupported =
|
||||||
|
this.props.LocationsLookup[selectedVersion] &&
|
||||||
this.props.LocationsLookup[selectedVersion].siaprime_support;
|
this.props.LocationsLookup[selectedVersion].siaprime_support;
|
||||||
|
|
||||||
const siaSupported = this.props.LocationsLookup[selectedVersion] &&
|
const siaSupported =
|
||||||
|
this.props.LocationsLookup[selectedVersion] &&
|
||||||
this.props.LocationsLookup[selectedVersion].sia_support;
|
this.props.LocationsLookup[selectedVersion].sia_support;
|
||||||
|
|
||||||
const showConfig = !missingDependencies &&
|
const showConfig =
|
||||||
|
!missingDependencies &&
|
||||||
!this.props.DisplayPinnedManager &&
|
!this.props.DisplayPinnedManager &&
|
||||||
this.props.DisplayConfiguration &&
|
this.props.DisplayConfiguration &&
|
||||||
!this.props.RebootRequired;
|
!this.props.RebootRequired;
|
||||||
|
|
||||||
const showPinnedManager = !missingDependencies &&
|
const showPinnedManager =
|
||||||
!this.props.RebootRequired &&
|
!missingDependencies && !this.props.RebootRequired && this.props.DisplayPinnedManager;
|
||||||
this.props.DisplayPinnedManager;
|
|
||||||
|
|
||||||
const showUpgrade = this.props.UpgradeAvailable &&
|
const showUpgrade =
|
||||||
|
this.props.UpgradeAvailable &&
|
||||||
!this.props.DisplayError &&
|
!this.props.DisplayError &&
|
||||||
!showConfig &&
|
!showConfig &&
|
||||||
!this.props.DownloadActive &&
|
!this.props.DownloadActive &&
|
||||||
@@ -138,14 +146,16 @@ class App extends IPCContainer {
|
|||||||
!this.props.InstallActive &&
|
!this.props.InstallActive &&
|
||||||
!this.props.RebootRequired;
|
!this.props.RebootRequired;
|
||||||
|
|
||||||
const showDependencies = !showUpgrade &&
|
const showDependencies =
|
||||||
|
!showUpgrade &&
|
||||||
missingDependencies &&
|
missingDependencies &&
|
||||||
!this.props.DownloadActive &&
|
!this.props.DownloadActive &&
|
||||||
!this.props.RebootRequired &&
|
!this.props.RebootRequired &&
|
||||||
!this.props.DismissDependencies &&
|
!this.props.DismissDependencies &&
|
||||||
this.props.AllowMount;
|
this.props.AllowMount;
|
||||||
|
|
||||||
const showNewReleases = !showConfig &&
|
const showNewReleases =
|
||||||
|
!showConfig &&
|
||||||
!this.props.DisplayConfirmYesNo &&
|
!this.props.DisplayConfirmYesNo &&
|
||||||
!showDependencies &&
|
!showDependencies &&
|
||||||
!this.props.DownloadActive &&
|
!this.props.DownloadActive &&
|
||||||
@@ -156,9 +166,19 @@ class App extends IPCContainer {
|
|||||||
!this.props.DisplaySelectAppPlatform &&
|
!this.props.DisplaySelectAppPlatform &&
|
||||||
!showUpgrade &&
|
!showUpgrade &&
|
||||||
!this.props.DismissNewReleasesAvailable &&
|
!this.props.DismissNewReleasesAvailable &&
|
||||||
(this.props.NewReleasesAvailable.length > 0);
|
this.props.NewReleasesAvailable.length > 0;
|
||||||
|
|
||||||
const showSkynetImport = !showConfig &&
|
const showAddEditHost =
|
||||||
|
!showDependencies &&
|
||||||
|
!this.props.DownloadActive &&
|
||||||
|
!showNewReleases &&
|
||||||
|
!this.props.RebootRequired &&
|
||||||
|
!this.props.DisplaySelectAppPlatform &&
|
||||||
|
!showUpgrade &&
|
||||||
|
this.props.DisplayAddEditHost;
|
||||||
|
|
||||||
|
const showSkynetImport =
|
||||||
|
!showConfig &&
|
||||||
!showDependencies &&
|
!showDependencies &&
|
||||||
!this.props.DownloadActive &&
|
!this.props.DownloadActive &&
|
||||||
!showNewReleases &&
|
!showNewReleases &&
|
||||||
@@ -167,7 +187,8 @@ class App extends IPCContainer {
|
|||||||
!showUpgrade &&
|
!showUpgrade &&
|
||||||
this.props.DisplayImport;
|
this.props.DisplayImport;
|
||||||
|
|
||||||
const showSkynetExport = !showConfig &&
|
const showSkynetExport =
|
||||||
|
!showConfig &&
|
||||||
!showDependencies &&
|
!showDependencies &&
|
||||||
!this.props.DownloadActive &&
|
!this.props.DownloadActive &&
|
||||||
!showNewReleases &&
|
!showNewReleases &&
|
||||||
@@ -176,97 +197,143 @@ class App extends IPCContainer {
|
|||||||
!showUpgrade &&
|
!showUpgrade &&
|
||||||
this.props.DisplayExport;
|
this.props.DisplayExport;
|
||||||
|
|
||||||
const configDisplay = createModalConditionally(showConfig, <Configuration
|
const configDisplay = createModalConditionally(
|
||||||
version={selectedVersion}
|
showConfig,
|
||||||
s3Supported={s3Supported}
|
<Configuration
|
||||||
remoteSupported={remoteSupported}/>);
|
version={selectedVersion}
|
||||||
const pinnedManagerDisplay = createModalConditionally(showPinnedManager, <PinnedManager
|
s3Supported={s3Supported}
|
||||||
version={selectedVersion}/>)
|
remoteSupported={remoteSupported}
|
||||||
const confirmDisplay = createModalConditionally(this.props.DisplayConfirmYesNo, <YesNo/>);
|
/>
|
||||||
const dependencyDisplay = createModalConditionally(showDependencies,
|
);
|
||||||
<DependencyList/>, false, this.props.InstallActive);
|
const addEditHostDisplay = createModalConditionally(showAddEditHost, <AddEditHost />);
|
||||||
const downloadDisplay = createModalConditionally(this.props.DownloadActive,
|
const pinnedManagerDisplay = createModalConditionally(
|
||||||
<DownloadProgress/>, false, true);
|
showPinnedManager,
|
||||||
const errorDisplay = createModalConditionally(this.props.DisplayError, <ErrorDetails/>, true);
|
<PinnedManager version={selectedVersion} />
|
||||||
const infoDisplay = createModalConditionally(this.props.DisplayInfo, <InfoDetails/>, true);
|
);
|
||||||
const newReleasesDisplay = createModalConditionally(showNewReleases, <NewReleases/>);
|
const confirmDisplay = createModalConditionally(this.props.DisplayConfirmYesNo, <YesNo />);
|
||||||
const rebootDisplay = createModalConditionally(this.props.RebootRequired, <Reboot/>);
|
const dependencyDisplay = createModalConditionally(
|
||||||
const selectAppPlatformDisplay = createModalConditionally(this.props.DisplaySelectAppPlatform,
|
showDependencies,
|
||||||
<SelectAppPlatform/>);
|
<DependencyList />,
|
||||||
const upgradeDisplay = createModalConditionally(showUpgrade, <UpgradeUI/>);
|
false,
|
||||||
const importDisplay = createModalConditionally(showSkynetImport, <SkynetImport
|
this.props.InstallActive
|
||||||
version={selectedVersion}/>);
|
);
|
||||||
const exportDisplay = createModalConditionally(showSkynetExport, <SkynetExport
|
const downloadDisplay = createModalConditionally(
|
||||||
version={selectedVersion}/>)
|
this.props.DownloadActive,
|
||||||
const appBusyDisplay = createModalConditionally(this.props.AppBusy,
|
<DownloadProgress />,
|
||||||
<ApplicationBusy/>, false, true, this.props.AppBusyTransparent);
|
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 />);
|
||||||
|
const importDisplay = createModalConditionally(
|
||||||
|
showSkynetImport,
|
||||||
|
<SkynetImport version={selectedVersion} />
|
||||||
|
);
|
||||||
|
const exportDisplay = createModalConditionally(
|
||||||
|
showSkynetExport,
|
||||||
|
<SkynetExport version={selectedVersion} />
|
||||||
|
);
|
||||||
|
const appBusyDisplay = createModalConditionally(
|
||||||
|
this.props.AppBusy,
|
||||||
|
<ApplicationBusy />,
|
||||||
|
false,
|
||||||
|
true,
|
||||||
|
this.props.AppBusyTransparent
|
||||||
|
);
|
||||||
|
|
||||||
let mainContent = [];
|
let mainContent = [];
|
||||||
if (this.props.DisplaySelectAppPlatform || !this.props.AppReady) {
|
if (this.props.DisplaySelectAppPlatform || !this.props.AppReady) {
|
||||||
mainContent = (
|
mainContent = (
|
||||||
<Box dxStyle={{height: '100%'}}>
|
<Box col={0} colSpan={'remain'} row={10} rowSpan={'remain'}>
|
||||||
<Loading/>
|
<Loading />
|
||||||
</Box>);
|
</Box>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
let key = 0;
|
let key = 0;
|
||||||
mainContent.push((
|
mainContent.push(
|
||||||
<Box key={'md_' + key++}
|
<Box
|
||||||
dxStyle={{padding: 'var(--default_spacing)', height: 'auto'}}>
|
col={0}
|
||||||
<ReleaseVersionDisplay downloadDisabled={!downloadEnabled}
|
colSpan={'remain'}
|
||||||
version={selectedVersion}/>
|
row={10}
|
||||||
|
rowSpan={17}
|
||||||
|
key={'md_' + key++}
|
||||||
|
dxStyle={{ padding: 'var(--default_spacing)' }}>
|
||||||
|
<ReleaseVersionDisplay downloadDisabled={!downloadEnabled} version={selectedVersion} />
|
||||||
</Box>
|
</Box>
|
||||||
));
|
);
|
||||||
mainContent.push(<div key={'md_' + key++}
|
|
||||||
style={{paddingTop: 'var(--default_spacing)'}}/>);
|
|
||||||
if (allowMount) {
|
if (allowMount) {
|
||||||
mainContent.push((
|
mainContent.push(
|
||||||
<Box dxStyle={{padding: 'var(--default_spacing)', height: 'auto'}}
|
<Box
|
||||||
key={'md_' + key++}>
|
row={29}
|
||||||
<MountItems s3Supported={s3Supported}
|
rowSpan={'remain'}
|
||||||
remoteSupported={remoteSupported}
|
colSpan={'remain'}
|
||||||
scPrimeSupported={scPrimeSupported}
|
dxStyle={{ padding: 'var(--default_spacing)' }}
|
||||||
siaSupported={siaSupported}
|
key={'md_' + key++}>
|
||||||
skynetSupported={skynetSupported}/>
|
<MountItems
|
||||||
|
s3Supported={s3Supported}
|
||||||
|
remoteSupported={remoteSupported}
|
||||||
|
scPrimeSupported={scPrimeSupported}
|
||||||
|
siaSupported={siaSupported}
|
||||||
|
skynetSupported={skynetSupported}
|
||||||
|
/>
|
||||||
</Box>
|
</Box>
|
||||||
));
|
);
|
||||||
} else if (!downloadEnabled && (selectedVersion !== 'unavailable')) {
|
} else if (!downloadEnabled && selectedVersion !== 'unavailable') {
|
||||||
mainContent.push((
|
mainContent.push(
|
||||||
<Box dxStyle={{padding: 'var(--default_spacing)', height: '170px'}}
|
<Box
|
||||||
key={'md_' + key++}>
|
col={0}
|
||||||
<Loading/>
|
colSpan={'remain'}
|
||||||
|
row={29}
|
||||||
|
rowSpan={'remain'}
|
||||||
|
dxStyle={{ padding: 'var(--default_spacing)' }}
|
||||||
|
key={'md_' + key++}>
|
||||||
|
<Loading />
|
||||||
</Box>
|
</Box>
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'App'}>
|
<div className={'App'}>
|
||||||
<div className={'AppContainer'}>
|
<Grid>
|
||||||
<div className={'AppHeader'}>
|
<Box col={0} colSpan={'remain'} row={0} rowSpan={8}>
|
||||||
<Box>
|
<Grid noScroll>
|
||||||
<Grid>
|
<Text
|
||||||
<Text col={0}
|
col={0}
|
||||||
colSpan={'remain'}
|
colSpan={'remain'}
|
||||||
row={0}
|
row={0}
|
||||||
rowSpan={'remain'}
|
rowSpan={8}
|
||||||
text={'Repertory UI v' + this.props.Version}
|
text={'Repertory UI v' + this.props.Version}
|
||||||
textAlign={'center'}
|
textAlign={'center'}
|
||||||
type={'Heading1'}/>
|
type={'Heading1'}
|
||||||
<UpgradeIcon
|
/>
|
||||||
available={!missingDependencies && (this.props.UpgradeAvailable || (this.props.NewReleasesAvailable2.length > 0))}
|
<UpgradeIcon
|
||||||
newReleases={!missingDependencies && (!this.props.UpgradeAvailable && (this.props.NewReleasesAvailable2.length > 0))}
|
available={
|
||||||
clicked={this.handleUpgradeIconClicked}
|
!missingDependencies &&
|
||||||
col={dimensions => dimensions.columns - 6}
|
(this.props.UpgradeAvailable || this.props.NewReleasesAvailable2.length > 0)
|
||||||
colSpan={5}
|
}
|
||||||
row={1}
|
newReleases={
|
||||||
rowSpan={remain => remain - 1}/>
|
!missingDependencies &&
|
||||||
</Grid>
|
!this.props.UpgradeAvailable &&
|
||||||
</Box>
|
this.props.NewReleasesAvailable2.length > 0
|
||||||
</div>
|
}
|
||||||
<div className={'AppContent'}>
|
clicked={this.handleUpgradeIconClicked}
|
||||||
{mainContent}
|
col={(dimensions) => dimensions.columns - 6}
|
||||||
</div>
|
colSpan={1}
|
||||||
</div>
|
row={1}
|
||||||
|
rowSpan={(remain) => remain - 1}
|
||||||
|
/>
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
{mainContent}
|
||||||
|
</Grid>
|
||||||
{importDisplay}
|
{importDisplay}
|
||||||
{exportDisplay}
|
{exportDisplay}
|
||||||
{newReleasesDisplay}
|
{newReleasesDisplay}
|
||||||
@@ -275,6 +342,7 @@ class App extends IPCContainer {
|
|||||||
{upgradeDisplay}
|
{upgradeDisplay}
|
||||||
{pinnedManagerDisplay}
|
{pinnedManagerDisplay}
|
||||||
{configDisplay}
|
{configDisplay}
|
||||||
|
{addEditHostDisplay}
|
||||||
{infoDisplay}
|
{infoDisplay}
|
||||||
{confirmDisplay}
|
{confirmDisplay}
|
||||||
{downloadDisplay}
|
{downloadDisplay}
|
||||||
@@ -286,7 +354,7 @@ class App extends IPCContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = (state) => {
|
||||||
return {
|
return {
|
||||||
AllowDownload: state.download.AllowDownload,
|
AllowDownload: state.download.AllowDownload,
|
||||||
AllowMount: state.common.AllowMount,
|
AllowMount: state.common.AllowMount,
|
||||||
@@ -295,6 +363,7 @@ const mapStateToProps = state => {
|
|||||||
AppBusyTransparent: state.common.AppBusyTransparent,
|
AppBusyTransparent: state.common.AppBusyTransparent,
|
||||||
AppReady: state.common.AppReady,
|
AppReady: state.common.AppReady,
|
||||||
DismissDependencies: state.install.DismissDependencies,
|
DismissDependencies: state.install.DismissDependencies,
|
||||||
|
DisplayAddEditHost: state.host.DisplayAddEditHost,
|
||||||
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
||||||
DisplayConfirmYesNo: state.common.DisplayConfirmYesNo,
|
DisplayConfirmYesNo: state.common.DisplayConfirmYesNo,
|
||||||
DisplayError: state.error.DisplayError,
|
DisplayError: state.error.DisplayError,
|
||||||
@@ -324,15 +393,15 @@ const mapStateToProps = state => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
displaySelectAppPlatform: display => dispatch(displaySelectAppPlatform(display)),
|
displaySelectAppPlatform: (display) => dispatch(displaySelectAppPlatform(display)),
|
||||||
loadReleases: () => dispatch(loadReleases()),
|
loadReleases: () => dispatch(loadReleases()),
|
||||||
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
||||||
saveState: () => dispatch(saveState()),
|
saveState: () => dispatch(saveState()),
|
||||||
setDismissNewReleasesAvailable: dismiss => dispatch(setDismissNewReleasesAvailable(dismiss)),
|
setDismissNewReleasesAvailable: (dismiss) => dispatch(setDismissNewReleasesAvailable(dismiss)),
|
||||||
setNewReleasesAvailable: items => dispatch(setNewReleasesAvailable(items)),
|
setNewReleasesAvailable: (items) => dispatch(setNewReleasesAvailable(items)),
|
||||||
setDismissUIUpgrade: dismiss => dispatch(setDismissUIUpgrade(dismiss)),
|
setDismissUIUpgrade: (dismiss) => dispatch(setDismissUIUpgrade(dismiss)),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -2,22 +2,25 @@ import React from 'react';
|
|||||||
import Box from '../UI/Box/Box';
|
import Box from '../UI/Box/Box';
|
||||||
import Loader from 'react-loader-spinner';
|
import Loader from 'react-loader-spinner';
|
||||||
import Text from '../UI/Text/Text';
|
import Text from '../UI/Text/Text';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const ApplicationBusy = ({title}) => {
|
const ApplicationBusy = ({ title }) => {
|
||||||
return (
|
return (
|
||||||
<Box dxStyle={{padding: 'var(--default_spacing)'}}>
|
<Box dxDark dxStyle={{ padding: 'var(--default_spacing)' }}>
|
||||||
<Text
|
<Text text={title || 'Please Wait...'} textAlign={'center'} type={'Heading1'} />
|
||||||
text={title || 'Please Wait...'}
|
<div
|
||||||
textAlign={'center'}
|
style={{
|
||||||
type={'Heading1'}/>
|
paddingLeft: 'calc(50% - 16px)',
|
||||||
<div style={{paddingLeft: 'calc(50% - 16px)', paddingTop: 'var(--default_spacing)'}}>
|
paddingTop: 'var(--default_spacing)',
|
||||||
<Loader color={'var(--heading_text_color)'}
|
}}>
|
||||||
height={32}
|
<Loader color={'var(--heading_text_color)'} height={32} width={32} type="TailSpin" />
|
||||||
width={32}
|
|
||||||
type='TailSpin'/>
|
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ApplicationBusy.propTypes = {
|
||||||
|
title: PropTypes.string,
|
||||||
|
};
|
||||||
|
|
||||||
export default ApplicationBusy;
|
export default ApplicationBusy;
|
||||||
|
|||||||
@@ -1,17 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './Dependency.css';
|
import './Dependency.css';
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import * as Constants from '../../../constants';
|
import * as Constants from '../../../constants';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const Dependency = (props) => {
|
||||||
return {
|
|
||||||
AllowDownload: (state.download.DownloadType !== Constants.INSTALL_TYPES.Dependency) &&
|
|
||||||
!state.download.DownloadActive &&
|
|
||||||
!state.install.InstallActive,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps)(props => {
|
|
||||||
return (
|
return (
|
||||||
<div className={'Dependency'}>
|
<div className={'Dependency'}>
|
||||||
<table width="100%">
|
<table width="100%">
|
||||||
@@ -21,15 +14,40 @@ export default connect(mapStateToProps)(props => {
|
|||||||
<h3>{props.name}</h3>
|
<h3>{props.name}</h3>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
{props.AllowDownload ?
|
{props.AllowDownload ? (
|
||||||
<a href={'#'}
|
<a
|
||||||
className={'DependencyLink'}
|
href={'#'}
|
||||||
onClick={()=>{props.onDownload(); return false;}}><u>Install</u></a> :
|
className={'DependencyLink'}
|
||||||
'Installing...'}
|
onClick={() => {
|
||||||
|
props.onDownload();
|
||||||
|
return false;
|
||||||
|
}}>
|
||||||
|
<u>Install</u>
|
||||||
|
</a>
|
||||||
|
) : (
|
||||||
|
'Installing...'
|
||||||
|
)}
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
AllowDownload:
|
||||||
|
state.download.DownloadType !== Constants.INSTALL_TYPES.Dependency &&
|
||||||
|
!state.download.DownloadActive &&
|
||||||
|
!state.install.InstallActive,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Dependency.propTypes = {
|
||||||
|
AllowDownload: PropTypes.bool,
|
||||||
|
name: PropTypes.string.isRequired,
|
||||||
|
onDownload: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps)(Dependency);
|
||||||
|
|||||||
@@ -1,3 +1,2 @@
|
|||||||
.DependencyList {
|
.DependencyList {
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,61 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './DependencyList.css';
|
import './DependencyList.css';
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import * as Constants from '../../constants';
|
import * as Constants from '../../constants';
|
||||||
import Dependency from './Dependency/Dependency';
|
|
||||||
import Box from '../UI/Box/Box';
|
import Box from '../UI/Box/Box';
|
||||||
import {downloadItem} from '../../redux/actions/download_actions';
|
import Dependency from './Dependency/Dependency';
|
||||||
import {extractFileNameFromURL} from '../../utils';
|
import PropTypes from 'prop-types';
|
||||||
import {setDismissDependencies} from '../../redux/actions/install_actions';
|
import { connect } from 'react-redux';
|
||||||
|
import { createDismissDisplay } from '../../utils.jsx';
|
||||||
|
import { downloadItem } from '../../redux/actions/download_actions';
|
||||||
|
import { extractFileNameFromURL } from '../../utils.jsx';
|
||||||
|
import { setDismissDependencies } from '../../redux/actions/install_actions';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const DependencyList = (props) => {
|
||||||
|
const items = props.MissingDependencies.map((k, i) => {
|
||||||
|
return (
|
||||||
|
<Dependency
|
||||||
|
key={i}
|
||||||
|
name={k.display}
|
||||||
|
onDownload={() =>
|
||||||
|
props.downloadItem(
|
||||||
|
extractFileNameFromURL(k.download),
|
||||||
|
Constants.INSTALL_TYPES.Dependency,
|
||||||
|
k.download,
|
||||||
|
k.is_winfsp
|
||||||
|
)
|
||||||
|
}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box dxStyle={{ width: '300px', height: 'auto', padding: '5px' }}>
|
||||||
|
{createDismissDisplay(
|
||||||
|
() => props.setDismissDependencies(true),
|
||||||
|
!props.AllowDismissDependencies
|
||||||
|
)}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: 'auto',
|
||||||
|
paddingBottom: '5px',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
}}>
|
||||||
|
<h1
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
textAlign: 'center',
|
||||||
|
color: 'var(--text_color_error)',
|
||||||
|
}}>
|
||||||
|
Missing Dependencies
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
{items}
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
return {
|
return {
|
||||||
AllowDismissDependencies: state.relver.AllowDismissDependencies,
|
AllowDismissDependencies: state.relver.AllowDismissDependencies,
|
||||||
MissingDependencies: state.install.MissingDependencies,
|
MissingDependencies: state.install.MissingDependencies,
|
||||||
@@ -18,34 +65,15 @@ const mapStateToProps = state => {
|
|||||||
const mapDispatchToProps = (dispatch) => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
downloadItem: (name, type, url, isWinFSP) => dispatch(downloadItem(name, type, url, isWinFSP)),
|
downloadItem: (name, type, url, isWinFSP) => dispatch(downloadItem(name, type, url, isWinFSP)),
|
||||||
setDismissDependencies: dismiss => dispatch(setDismissDependencies(dismiss)),
|
setDismissDependencies: (dismiss) => dispatch(setDismissDependencies(dismiss)),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
DependencyList.propTypes = {
|
||||||
const items = props.MissingDependencies.map((k, i)=> {
|
AllowDismissDependencies: PropTypes.bool,
|
||||||
return (
|
MissingDependencies: PropTypes.array,
|
||||||
<Dependency key={i}
|
downloadItem: PropTypes.func.isRequired,
|
||||||
name={k.display}
|
setDismissDependencies: PropTypes.func.isRequired,
|
||||||
onDownload={()=>props.downloadItem(extractFileNameFromURL(k.download), Constants.INSTALL_TYPES.Dependency, k.download, k.is_winfsp)}/>
|
};
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
const dismissDisplay = (
|
export default connect(mapStateToProps, mapDispatchToProps)(DependencyList);
|
||||||
<div style={{float: 'right', margin: 0, paddingRight: '4px', boxSizing: 'border-box', display: 'block'}}>
|
|
||||||
<a href={'#'}
|
|
||||||
onClick={props.AllowDismissDependencies ? () => props.setDismissDependencies(true) : e => e.preventDefault()}
|
|
||||||
style={{cursor: props.AllowDismissDependencies ? 'pointer' : 'no-drop'}}>X</a>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Box dxStyle={{width: '300px', height: 'auto', padding: '5px'}}>
|
|
||||||
{dismissDisplay}
|
|
||||||
<div style={{width: '100%', height: 'auto', paddingBottom: '5px', boxSizing: 'border-box'}}>
|
|
||||||
<h1 style={{width: '100%', textAlign: 'center', color: 'var(--text_color_error)'}}>Missing Dependencies</h1>
|
|
||||||
</div>
|
|
||||||
{items}
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,9 +1,29 @@
|
|||||||
import Box from '../UI/Box/Box';
|
import Box from '../UI/Box/Box';
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import React from 'react';
|
|
||||||
import './DownloadProgress.css';
|
import './DownloadProgress.css';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const DownloadProgress = (props) => {
|
||||||
|
const width = props.Platform === 'linux' ? '480px' : '380px';
|
||||||
|
return (
|
||||||
|
<Box dxStyle={{ width: width, height: 'auto', padding: '5px' }}>
|
||||||
|
<div style={{ width: '100%', height: 'auto' }}>
|
||||||
|
<h1 style={{ width: '100%', textAlign: 'center' }}>
|
||||||
|
{'Downloading ' + props.DownloadName}
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<progress
|
||||||
|
max={100.0}
|
||||||
|
id={'download_progress'}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
value={props.DownloadProgress}
|
||||||
|
/>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
return {
|
return {
|
||||||
DownloadName: state.download.DownloadName,
|
DownloadName: state.download.DownloadName,
|
||||||
DownloadProgress: state.download.DownloadProgress,
|
DownloadProgress: state.download.DownloadProgress,
|
||||||
@@ -11,15 +31,10 @@ const mapStateToProps = state => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps)(props => {
|
DownloadProgress.propTypes = {
|
||||||
const width = props.Platform === 'linux' ? '480px' : '380px';
|
DownloadName: PropTypes.string.isRequired,
|
||||||
return (
|
DownloadProgress: PropTypes.number,
|
||||||
<Box dxStyle={{width: width, height: 'auto', padding: '5px'}}>
|
Platform: PropTypes.string.isRequired,
|
||||||
<div style={{width: '100%', height: 'auto'}}>
|
};
|
||||||
<h1 style={{width: '100%', textAlign: 'center'}}>{'Downloading ' + props.DownloadName}</h1>
|
|
||||||
</div>
|
export default connect(mapStateToProps)(DownloadProgress);
|
||||||
<progress max={100.0} id={'download_progress'}
|
|
||||||
style={{width: '100%'}}
|
|
||||||
value={props.DownloadProgress}/>
|
|
||||||
</Box>);
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,25 +1,14 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {dismissError} from '../../redux/actions/error_actions';
|
import './ErrorDetails.css';
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import Box from '../UI/Box/Box';
|
import Box from '../UI/Box/Box';
|
||||||
import Button from '../UI/Button/Button';
|
import Button from '../UI/Button/Button';
|
||||||
import './ErrorDetails.css';
|
import PropTypes from 'prop-types';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { dismissError } from '../../redux/actions/error_actions';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const ErrorDetails = (props) => {
|
||||||
return {
|
|
||||||
ErrorMessage: state.error.ErrorStack.length > 0 ? state.error.ErrorStack[0] : '',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
dismissError: () => dispatch(dismissError()),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|
||||||
return (
|
return (
|
||||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
<Box dxDark dxStyle={{ padding: 'var(--default_spacing)' }}>
|
||||||
<h1 className={'ErrorDetailsHeading'}>Application Error</h1>
|
<h1 className={'ErrorDetailsHeading'}>Application Error</h1>
|
||||||
<div className={'ErrorDetailsContent'}>
|
<div className={'ErrorDetailsContent'}>
|
||||||
<p>{props.ErrorMessage}</p>
|
<p>{props.ErrorMessage}</p>
|
||||||
@@ -27,4 +16,23 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
<Button clicked={props.dismissError}>Dismiss</Button>
|
<Button clicked={props.dismissError}>Dismiss</Button>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
ErrorMessage: state.error.ErrorStack.length > 0 ? state.error.ErrorStack[0] : '',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
dismissError: () => dispatch(dismissError()),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
ErrorDetails.propTypes = {
|
||||||
|
ErrorMessage: PropTypes.string.isRequired,
|
||||||
|
dismissError: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(ErrorDetails);
|
||||||
|
|||||||
@@ -17,3 +17,9 @@
|
|||||||
white-space: pre;
|
white-space: pre;
|
||||||
hyphens: none;
|
hyphens: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.InfoButtonOwner {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,23 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {dismissInfo} from '../../redux/actions/error_actions';
|
import './InfoDetails.css';
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import Box from '../UI/Box/Box';
|
import Box from '../UI/Box/Box';
|
||||||
import Button from '../UI/Button/Button';
|
import Button from '../UI/Button/Button';
|
||||||
import './InfoDetails.css';
|
import PropTypes from 'prop-types';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { dismissInfo, notifyError } from '../../redux/actions/error_actions';
|
||||||
|
import { promptLocationAndSaveFile } from '../../utils';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const InfoDetails = (props) => {
|
||||||
return {
|
|
||||||
InfoMessage: state.error.InfoStack.length > 0 ? state.error.InfoStack[0] : '',
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
dismissInfo: () => dispatch(dismissInfo()),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|
||||||
let msg = props.InfoMessage.message;
|
let msg = props.InfoMessage.message;
|
||||||
const classes = ['InfoDetailsContent'];
|
const classes = ['InfoDetailsContent'];
|
||||||
|
|
||||||
@@ -37,7 +27,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const scrollToTop = textArea => {
|
const scrollToTop = (textArea) => {
|
||||||
if (!textArea.firstClick) {
|
if (!textArea.firstClick) {
|
||||||
textArea.firstClick = true;
|
textArea.firstClick = true;
|
||||||
textArea.scrollTop = 0;
|
textArea.scrollTop = 0;
|
||||||
@@ -46,22 +36,65 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
<Box dxDark dxStyle={{ padding: 'var(--default_spacing)' }}>
|
||||||
<h1 className={'InfoDetailsHeading'}>{props.InfoMessage.title}</h1>
|
<h1 className={'InfoDetailsHeading'}>{props.InfoMessage.title}</h1>
|
||||||
<div className={classes.join(' ')}>
|
<div className={classes.join(' ')}>
|
||||||
{
|
{copyable ? (
|
||||||
copyable ? (
|
<textarea
|
||||||
<textarea autoFocus
|
autoFocus
|
||||||
rows={9}
|
rows={9}
|
||||||
value={msg}
|
onChange={() => {}}
|
||||||
className={'SkynetImportTextArea'}
|
value={msg}
|
||||||
onClick={e => scrollToTop(e.target)}/>
|
className={'SkynetImportTextArea'}
|
||||||
) : (
|
onClick={(e) => scrollToTop(e.target)}
|
||||||
<p style={{textAlign: 'left'}}>{msg}</p>
|
/>
|
||||||
)
|
) : (
|
||||||
}
|
<p style={{ textAlign: 'left' }}>{msg}</p>
|
||||||
|
)}
|
||||||
</div>
|
</div>
|
||||||
<Button clicked={props.dismissInfo}>Dismiss</Button>
|
{props.InfoMessage.saveToFile ? (
|
||||||
|
<div className={'InfoButtonOwner'}>
|
||||||
|
<Button clicked={props.dismissInfo}>Dismiss</Button>
|
||||||
|
<Button
|
||||||
|
buttonStyles={{ marginLeft: 'var(--default_spacing)' }}
|
||||||
|
clicked={() => {
|
||||||
|
if (
|
||||||
|
promptLocationAndSaveFile(
|
||||||
|
props.InfoMessage.fileName + '.' + props.InfoMessage.extension,
|
||||||
|
msg,
|
||||||
|
props.notifyError
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
props.dismissInfo();
|
||||||
|
}
|
||||||
|
}}>
|
||||||
|
Save...
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Button clicked={props.dismissInfo}>Dismiss</Button>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
InfoMessage: state.error.InfoStack.length > 0 ? state.error.InfoStack[0] : '',
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
notifyError: (msg) => dispatch(notifyError(msg)),
|
||||||
|
dismissInfo: () => dispatch(dismissInfo()),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
InfoDetails.propTypes = {
|
||||||
|
InfoMessage: PropTypes.object.isRequired,
|
||||||
|
dismissInfo: PropTypes.func.isRequired,
|
||||||
|
notifyError: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(InfoDetails);
|
||||||
|
|||||||
@@ -1,74 +0,0 @@
|
|||||||
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 mapStateToProps = state => {
|
|
||||||
return {
|
|
||||||
AllowInstall: state.install.MissingDependencies.length === 0,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
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(mapStateToProps, mapDispatchToProps)(({
|
|
||||||
AllowInstall,
|
|
||||||
dismiss,
|
|
||||||
release,
|
|
||||||
lastItem,
|
|
||||||
notifyError,
|
|
||||||
notifyInfo,
|
|
||||||
installReleaseByVersion
|
|
||||||
}) => {
|
|
||||||
const title = '[' + Constants.RELEASE_TYPES[release.Release] + '] ' + release.Display;
|
|
||||||
const displayChanges = async () => {
|
|
||||||
try {
|
|
||||||
const lines = await getChangesForRepertoryVersion(release.VersionString);
|
|
||||||
notifyInfo(title, formatLinesForDisplay(lines));
|
|
||||||
} catch (e) {
|
|
||||||
notifyError(e);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// TODO Switch to activate
|
|
||||||
/*const installReleaseVersion = () => {
|
|
||||||
dismiss();
|
|
||||||
installReleaseByVersion(release.Release, release.Version);
|
|
||||||
};
|
|
||||||
{AllowInstall ?
|
|
||||||
<Button buttonStyles={{width: '100%'}}
|
|
||||||
clicked={installReleaseVersion}>Install</Button> : null}*/
|
|
||||||
return (
|
|
||||||
<div>
|
|
||||||
<h2>{title}</h2>
|
|
||||||
<table cellSpacing={0} cellPadding={0} width="97%">
|
|
||||||
<tbody>
|
|
||||||
<tr style={{height: '4px'}}/>
|
|
||||||
<tr>
|
|
||||||
<td width="50%">
|
|
||||||
<Button buttonStyles={{width: '100%'}} clicked={displayChanges}>Changes</Button>
|
|
||||||
</td>
|
|
||||||
<td>
|
|
||||||
<div style={{width: 'var(--default_spacing)'}}/>
|
|
||||||
</td>
|
|
||||||
<td width="50%">
|
|
||||||
</td>
|
|
||||||
</tr>
|
|
||||||
{lastItem ? null : <tr style={{height: 'var(--default_spacing)'}}/>}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
98
src/components/NewReleases/NewRelease/NewRelease.jsx
Normal file
98
src/components/NewReleases/NewRelease/NewRelease.jsx
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import * as Constants from '../../../constants';
|
||||||
|
import Button from '../../UI/Button/Button';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { formatLinesForDisplay, getChangesForRepertoryVersion } from '../../../utils.jsx';
|
||||||
|
import { notifyError, notifyInfo } from '../../../redux/actions/error_actions';
|
||||||
|
import { setActiveRelease } from '../../../redux/actions/release_version_actions';
|
||||||
|
import { unmountAll } from '../../../redux/actions/mount_actions';
|
||||||
|
|
||||||
|
const NewRelease = ({
|
||||||
|
ActiveRelease,
|
||||||
|
ActiveVersion,
|
||||||
|
dismiss,
|
||||||
|
release,
|
||||||
|
lastItem,
|
||||||
|
notifyError,
|
||||||
|
notifyInfo,
|
||||||
|
setActiveRelease,
|
||||||
|
unmountAll,
|
||||||
|
}) => {
|
||||||
|
const title = '[' + Constants.RELEASE_TYPES[release.Release] + '] ' + release.Display;
|
||||||
|
const displayChanges = async () => {
|
||||||
|
try {
|
||||||
|
const lines = await getChangesForRepertoryVersion(release.VersionString);
|
||||||
|
notifyInfo(title, formatLinesForDisplay(lines));
|
||||||
|
} catch (e) {
|
||||||
|
notifyError(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const isActiveRelease = release.Release === ActiveRelease && release.Version === ActiveVersion;
|
||||||
|
const setReleaseAndVersion = () => {
|
||||||
|
dismiss();
|
||||||
|
unmountAll(() => {
|
||||||
|
setActiveRelease(release.Release, release.Version);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<h2>{title}</h2>
|
||||||
|
<table cellSpacing={0} cellPadding={0} width="97%">
|
||||||
|
<tbody>
|
||||||
|
<tr style={{ height: '4px' }} />
|
||||||
|
<tr>
|
||||||
|
<td width="50%">
|
||||||
|
<Button buttonStyles={{ width: '100%' }} clicked={displayChanges}>
|
||||||
|
Changes
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
</td>
|
||||||
|
<td width="50%">
|
||||||
|
{!isActiveRelease ? (
|
||||||
|
<Button buttonStyles={{ width: '100%' }} clicked={setReleaseAndVersion}>
|
||||||
|
Activate
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{lastItem ? null : <tr style={{ height: 'var(--default_spacing)' }} />}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
ActiveRelease: state.relver.Release,
|
||||||
|
ActiveVersion: state.relver.Version,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
setActiveRelease: (release, version) => dispatch(setActiveRelease(release, version)),
|
||||||
|
notifyError: (msg) => dispatch(notifyError(msg)),
|
||||||
|
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||||
|
unmountAll: (completedCallback) => dispatch(unmountAll(completedCallback)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
NewRelease.propTypes = {
|
||||||
|
ActiveRelease: PropTypes.number.isRequired,
|
||||||
|
ActiveVersion: PropTypes.number.isRequired,
|
||||||
|
dismiss: PropTypes.func.isRequired,
|
||||||
|
lastItem: PropTypes.bool.isRequired,
|
||||||
|
notifyError: PropTypes.func.isRequired,
|
||||||
|
notifyInfo: PropTypes.func.isRequired,
|
||||||
|
release: PropTypes.object.isRequired,
|
||||||
|
setActiveRelease: PropTypes.func.isRequired,
|
||||||
|
unmountAll: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(NewRelease);
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
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, idx) => {
|
|
||||||
return <NewRelease dismiss={props.dismissNewReleasesAvailable}
|
|
||||||
key={'new_release_' + i.Release + '_' + i.Version}
|
|
||||||
lastItem={idx === (props.NewReleasesAvailable.length - 1)}
|
|
||||||
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>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
48
src/components/NewReleases/NewReleases.jsx
Normal file
48
src/components/NewReleases/NewReleases.jsx
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import './NewReleases.css';
|
||||||
|
import Box from '../UI/Box/Box';
|
||||||
|
import Button from '../UI/Button/Button';
|
||||||
|
import NewRelease from './NewRelease/NewRelease.jsx';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { setDismissNewReleasesAvailable } from '../../redux/actions/release_version_actions';
|
||||||
|
|
||||||
|
const NewReleases = (props) => {
|
||||||
|
const newReleases = props.NewReleasesAvailable.map((i, idx) => {
|
||||||
|
return (
|
||||||
|
<NewRelease
|
||||||
|
dismiss={props.dismissNewReleasesAvailable}
|
||||||
|
key={'new_release_' + i.Release + '_' + i.Version}
|
||||||
|
lastItem={idx === props.NewReleasesAvailable.length - 1}
|
||||||
|
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>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
NewReleasesAvailable: state.relver.NewReleasesAvailable,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
dismissNewReleasesAvailable: () => dispatch(setDismissNewReleasesAvailable(true)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
NewReleases.propTypes = {
|
||||||
|
NewReleasesAvailable: PropTypes.array.isRequired,
|
||||||
|
dismissNewReleasesAvailable: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(NewReleases);
|
||||||
@@ -1,24 +1,31 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './Reboot.css';
|
import './Reboot.css';
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import Box from '../UI/Box/Box';
|
import Box from '../UI/Box/Box';
|
||||||
import Button from '../UI/Button/Button';
|
import Button from '../UI/Button/Button';
|
||||||
import {rebootSystem} from '../../redux/actions/common_actions';
|
import PropTypes from 'prop-types';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { rebootSystem } from '../../redux/actions/common_actions';
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const Reboot = (props) => {
|
||||||
|
return (
|
||||||
|
<Box dxDark dxStyle={{ padding: 'var(--default_spacing)' }}>
|
||||||
|
<h1 className={'RebootHeading'}>Reboot System</h1>
|
||||||
|
<div className={'RebootContent'}>
|
||||||
|
<p>Repertory requires a system reboot to continue.</p>
|
||||||
|
</div>
|
||||||
|
<Button clicked={() => props.rebootSystem()}>Reboot Now</Button>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
rebootSystem: () => dispatch(rebootSystem()),
|
rebootSystem: () => dispatch(rebootSystem()),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps)(props => {
|
Reboot.propTypes = {
|
||||||
return (
|
rebootSystem: PropTypes.func.isRequired,
|
||||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
};
|
||||||
<h1 className={'RebootHeading'}>Reboot System</h1>
|
|
||||||
<div className={'RebootContent'}>
|
export default connect(null, mapDispatchToProps)(Reboot);
|
||||||
<p>Repertory requires a system reboot to continue.</p>
|
|
||||||
</div>
|
|
||||||
<Button clicked={()=>props.rebootSystem()}>Reboot Now</Button>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,16 +1,165 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './ReleaseVersionDisplay.css';
|
import './ReleaseVersionDisplay.css';
|
||||||
import * as Constants from '../../constants';
|
import * as Constants from '../../constants';
|
||||||
import {connect} from 'react-redux';
|
import Button from '../UI/Button/Button';
|
||||||
import DropDown from '../UI/DropDown/DropDown';
|
import DropDown from '../UI/DropDown/DropDown';
|
||||||
import Grid from '../UI/Grid/Grid';
|
import Grid from '../UI/Grid/Grid';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import Text from '../UI/Text/Text';
|
import Text from '../UI/Text/Text';
|
||||||
import Button from '../UI/Button/Button';
|
|
||||||
import UpgradeIcon from '../UpgradeIcon/UpgradeIcon';
|
import UpgradeIcon from '../UpgradeIcon/UpgradeIcon';
|
||||||
import {setActiveRelease} from '../../redux/actions/release_version_actions';
|
import { connect } from 'react-redux';
|
||||||
import {downloadItem} from '../../redux/actions/download_actions';
|
import { downloadItem } from '../../redux/actions/download_actions';
|
||||||
|
import { setActiveRelease } from '../../redux/actions/release_version_actions';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const ReleaseVersionDisplay = (props) => {
|
||||||
|
const getSelectedVersion = () => {
|
||||||
|
return props.ReleaseVersion === -1
|
||||||
|
? 'unavailable'
|
||||||
|
: props.VersionLookup[Constants.RELEASE_TYPES[props.Release]][props.ReleaseVersion];
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDownloadRelease = () => {
|
||||||
|
const fileName = props.version + '.zip';
|
||||||
|
props.downloadItem(
|
||||||
|
fileName,
|
||||||
|
Constants.INSTALL_TYPES.Release,
|
||||||
|
props.LocationsLookup[props.version].urls
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleReleaseChanged = (e) => {
|
||||||
|
const release = Constants.RELEASE_TYPES.indexOf(e.target.value);
|
||||||
|
const releaseVersion = props.VersionLookup[Constants.RELEASE_TYPES[release]].length - 1;
|
||||||
|
props.setActiveRelease(release, releaseVersion);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleVersionChanged = (e) => {
|
||||||
|
const releaseVersion = props.VersionLookup[Constants.RELEASE_TYPES[props.Release]].indexOf(
|
||||||
|
e.target.value
|
||||||
|
);
|
||||||
|
props.setActiveRelease(props.Release, releaseVersion);
|
||||||
|
};
|
||||||
|
|
||||||
|
const text = props.InstalledVersion + ' [' + props.AppPlatform + ']';
|
||||||
|
const disabled =
|
||||||
|
props.DownloadActive ||
|
||||||
|
props.InstallActive ||
|
||||||
|
props.MountsBusy ||
|
||||||
|
(!props.AllowMount && getSelectedVersion() !== 'unavailable');
|
||||||
|
const releaseExtracting = props.InstallType === Constants.INSTALL_TYPES.Release;
|
||||||
|
|
||||||
|
let optionsDisplay = [];
|
||||||
|
let key = 0;
|
||||||
|
if (releaseExtracting) {
|
||||||
|
optionsDisplay.push(
|
||||||
|
<Text
|
||||||
|
col={(dimensions) => (dimensions.columns / 3) * 2}
|
||||||
|
colSpan={'remain'}
|
||||||
|
key={key++}
|
||||||
|
rowSpan={4}
|
||||||
|
text={'Activating'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
optionsDisplay.push(
|
||||||
|
<Text
|
||||||
|
col={(dimensions) => (dimensions.columns / 3) * 2}
|
||||||
|
colSpan={'remain'}
|
||||||
|
key={key++}
|
||||||
|
row={5}
|
||||||
|
rowSpan={7}
|
||||||
|
text={text}
|
||||||
|
textAlign={'left'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else if (props.downloadDisabled || props.DismissDependencies) {
|
||||||
|
optionsDisplay.push(
|
||||||
|
<Text
|
||||||
|
col={(dimensions) => (dimensions.columns / 3) * 2}
|
||||||
|
colSpan={'remain'}
|
||||||
|
key={key++}
|
||||||
|
rowSpan={4}
|
||||||
|
text={'Installed'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
|
||||||
|
optionsDisplay.push(
|
||||||
|
<Text
|
||||||
|
col={(dimensions) => (dimensions.columns / 3) * 2}
|
||||||
|
colSpan={'remain'}
|
||||||
|
key={key++}
|
||||||
|
row={5}
|
||||||
|
rowSpan={7}
|
||||||
|
text={text}
|
||||||
|
textAlign={'left'}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
optionsDisplay.push(
|
||||||
|
<Button
|
||||||
|
clicked={handleDownloadRelease}
|
||||||
|
col={(dimensions) => (dimensions.columns / 3) * 2}
|
||||||
|
colSpan={20}
|
||||||
|
key={key++}
|
||||||
|
row={5}
|
||||||
|
rowSpan={7}>
|
||||||
|
Install
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Grid noScroll>
|
||||||
|
<Text
|
||||||
|
colSpan={(columns) => columns / 3}
|
||||||
|
rowSpan={4}
|
||||||
|
text={'Release'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}
|
||||||
|
/>
|
||||||
|
<DropDown
|
||||||
|
changed={handleReleaseChanged}
|
||||||
|
colSpan={(remain) => remain / 3 - 1}
|
||||||
|
disabled={disabled}
|
||||||
|
items={Constants.RELEASE_TYPES}
|
||||||
|
row={5}
|
||||||
|
rowSpan={7}
|
||||||
|
selected={Constants.RELEASE_TYPES[props.Release]}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
col={(dimensions) => dimensions.columns / 3}
|
||||||
|
colSpan={(remain) => remain / 2}
|
||||||
|
rowSpan={4}
|
||||||
|
text={'Version'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}
|
||||||
|
/>
|
||||||
|
<UpgradeIcon
|
||||||
|
available={props.ReleaseUpgradeAvailable}
|
||||||
|
col={(dimensions) => (dimensions.columns / 3) * 2 - 6}
|
||||||
|
colSpan={4}
|
||||||
|
release
|
||||||
|
rowSpan={4}
|
||||||
|
/>
|
||||||
|
<DropDown
|
||||||
|
changed={handleVersionChanged}
|
||||||
|
col={(dimensions) => dimensions.columns / 3}
|
||||||
|
colSpan={(remain) => remain / 2 - 1}
|
||||||
|
disabled={disabled}
|
||||||
|
items={props.VersionLookup[Constants.RELEASE_TYPES[props.Release]]}
|
||||||
|
row={5}
|
||||||
|
rowSpan={7}
|
||||||
|
selected={props.VersionLookup[Constants.RELEASE_TYPES[props.Release]][props.ReleaseVersion]}
|
||||||
|
/>
|
||||||
|
{optionsDisplay}
|
||||||
|
</Grid>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
return {
|
return {
|
||||||
AllowMount: state.common.AllowMount,
|
AllowMount: state.common.AllowMount,
|
||||||
AppPlatform: state.common.AppPlatform,
|
AppPlatform: state.common.AppPlatform,
|
||||||
@@ -28,129 +177,31 @@ const mapStateToProps = state => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
downloadItem: (name, type, urls) => dispatch(downloadItem(name, type, urls)),
|
downloadItem: (name, type, urls) => dispatch(downloadItem(name, type, urls)),
|
||||||
setActiveRelease: (release, version) => dispatch(setActiveRelease(release, version)),
|
setActiveRelease: (release, version) => dispatch(setActiveRelease(release, version)),
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
ReleaseVersionDisplay.propTypes = {
|
||||||
const getSelectedVersion = () => {
|
AllowMount: PropTypes.bool,
|
||||||
return (props.ReleaseVersion === -1) ?
|
AppPlatform: PropTypes.string.isRequired,
|
||||||
'unavailable' :
|
DismissDependencies: PropTypes.bool.isRequired,
|
||||||
props.VersionLookup[Constants.RELEASE_TYPES[props.Release]][props.ReleaseVersion];
|
DownloadActive: PropTypes.bool,
|
||||||
};
|
InstallActive: PropTypes.bool,
|
||||||
|
InstallType: PropTypes.string,
|
||||||
|
InstalledVersion: PropTypes.string,
|
||||||
|
LocationsLookup: PropTypes.object.isRequired,
|
||||||
|
MountsBusy: PropTypes.bool,
|
||||||
|
Release: PropTypes.number.isRequired,
|
||||||
|
ReleaseUpgradeAvailable: PropTypes.bool,
|
||||||
|
ReleaseVersion: PropTypes.number.isRequired,
|
||||||
|
VersionLookup: PropTypes.object.isRequired,
|
||||||
|
downloadDisabled: PropTypes.bool,
|
||||||
|
downloadItem: PropTypes.func.isRequired,
|
||||||
|
setActiveRelease: PropTypes.func.isRequired,
|
||||||
|
version: PropTypes.string.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
const handleDownloadRelease = () => {
|
export default connect(mapStateToProps, mapDispatchToProps)(ReleaseVersionDisplay);
|
||||||
const fileName = props.version + '.zip';
|
|
||||||
props.downloadItem(fileName, Constants.INSTALL_TYPES.Release, props.LocationsLookup[props.version].urls);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleReleaseChanged = e => {
|
|
||||||
const release = Constants.RELEASE_TYPES.indexOf(e.target.value);
|
|
||||||
const releaseVersion = props.VersionLookup[Constants.RELEASE_TYPES[release]].length - 1;
|
|
||||||
props.setActiveRelease(release, releaseVersion);
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleVersionChanged = e => {
|
|
||||||
const releaseVersion = props.VersionLookup[Constants.RELEASE_TYPES[props.Release]].indexOf(e.target.value);
|
|
||||||
props.setActiveRelease(props.Release, releaseVersion);
|
|
||||||
};
|
|
||||||
|
|
||||||
const text = props.InstalledVersion + ' [' + props.AppPlatform + ']';
|
|
||||||
const disabled = props.DownloadActive ||
|
|
||||||
props.InstallActive ||
|
|
||||||
props.MountsBusy ||
|
|
||||||
(!props.AllowMount && (getSelectedVersion() !== 'unavailable')) ;
|
|
||||||
const releaseExtracting = (props.InstallType === Constants.INSTALL_TYPES.Release);
|
|
||||||
|
|
||||||
let optionsDisplay = [];
|
|
||||||
let key = 0;
|
|
||||||
if (releaseExtracting) {
|
|
||||||
optionsDisplay.push((
|
|
||||||
<Text col={dimensions => (dimensions.columns / 3) * 2}
|
|
||||||
colSpan={'remain'}
|
|
||||||
key={key++}
|
|
||||||
rowSpan={4}
|
|
||||||
text={'Activating'}
|
|
||||||
textAlign={'left'}
|
|
||||||
type={'Heading2'}/>
|
|
||||||
));
|
|
||||||
optionsDisplay.push((
|
|
||||||
<Text col={dimensions => (dimensions.columns / 3) * 2}
|
|
||||||
colSpan={'remain'}
|
|
||||||
key={key++}
|
|
||||||
row={5}
|
|
||||||
rowSpan={7}
|
|
||||||
text={text}
|
|
||||||
textAlign={'left'}/>
|
|
||||||
));
|
|
||||||
} else if (props.downloadDisabled || props.DismissDependencies) {
|
|
||||||
optionsDisplay.push((
|
|
||||||
<Text col={dimensions => (dimensions.columns / 3) * 2}
|
|
||||||
colSpan={'remain'}
|
|
||||||
key={key++}
|
|
||||||
rowSpan={4}
|
|
||||||
text={'Installed'}
|
|
||||||
textAlign={'left'}
|
|
||||||
type={'Heading2'}/>
|
|
||||||
));
|
|
||||||
|
|
||||||
optionsDisplay.push((
|
|
||||||
<Text col={dimensions => (dimensions.columns / 3) * 2}
|
|
||||||
colSpan={'remain'}
|
|
||||||
key={key++}
|
|
||||||
row={5}
|
|
||||||
rowSpan={7}
|
|
||||||
text={text}
|
|
||||||
textAlign={'left'}/>
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
optionsDisplay.push((
|
|
||||||
<Button clicked={handleDownloadRelease}
|
|
||||||
col={dimensions => (dimensions.columns / 3) * 2}
|
|
||||||
colSpan={20}
|
|
||||||
key={key++}
|
|
||||||
row={5}
|
|
||||||
rowSpan={7}>Install</Button>
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
return (
|
|
||||||
<Grid noScroll>
|
|
||||||
<Text colSpan={columns=>columns / 3}
|
|
||||||
rowSpan={4}
|
|
||||||
text={'Release'}
|
|
||||||
textAlign={'left'}
|
|
||||||
type={'Heading2'}/>
|
|
||||||
<DropDown changed={handleReleaseChanged}
|
|
||||||
colSpan={remain=>remain / 3 - 1}
|
|
||||||
disabled={disabled}
|
|
||||||
items={Constants.RELEASE_TYPES}
|
|
||||||
row={5}
|
|
||||||
rowSpan={7}
|
|
||||||
selected={Constants.RELEASE_TYPES[props.Release]}/>
|
|
||||||
<Text col={dimensions => dimensions.columns / 3}
|
|
||||||
colSpan={remain=>remain / 2}
|
|
||||||
rowSpan={4}
|
|
||||||
text={'Version'}
|
|
||||||
textAlign={'left'}
|
|
||||||
type={'Heading2'}/>
|
|
||||||
<UpgradeIcon available={props.ReleaseUpgradeAvailable}
|
|
||||||
col={dimensions => ((dimensions.columns / 3) * 2) - 6}
|
|
||||||
colSpan={4}
|
|
||||||
release
|
|
||||||
rowSpan={4}/>
|
|
||||||
<DropDown changed={handleVersionChanged}
|
|
||||||
col={dimensions => dimensions.columns / 3}
|
|
||||||
colSpan={remain=>remain / 2 - 1}
|
|
||||||
disabled={disabled}
|
|
||||||
items={props.VersionLookup[Constants.RELEASE_TYPES[props.Release]]}
|
|
||||||
row={5}
|
|
||||||
rowSpan={7}
|
|
||||||
selected={props.VersionLookup[Constants.RELEASE_TYPES[props.Release]][props.ReleaseVersion]}/>
|
|
||||||
{optionsDisplay}
|
|
||||||
</Grid>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './Box.css';
|
import './Box.css';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const Box = props => {
|
const Box = (props) => {
|
||||||
const styleList = [];
|
const styleList = [];
|
||||||
styleList.push('Box');
|
styleList.push('Box');
|
||||||
if (props.dxDark) {
|
if (props.dxDark) {
|
||||||
@@ -17,13 +18,20 @@ const Box = props => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div onClick={props.clicked} className={styleList.join(' ')} style={{ ...props.dxStyle }}>
|
||||||
onClick={props.clicked}
|
|
||||||
className={styleList.join(' ')}
|
|
||||||
style={{...props.dxStyle}}>
|
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Box.propTypes = {
|
||||||
|
children: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||||
|
clicked: PropTypes.func,
|
||||||
|
dxDark: PropTypes.bool,
|
||||||
|
dxFadeIn: PropTypes.bool,
|
||||||
|
dxSlideOut: PropTypes.bool,
|
||||||
|
dxSlideOutTop: PropTypes.bool,
|
||||||
|
dxStyle: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
export default Box;
|
export default Box;
|
||||||
|
|||||||
@@ -1,14 +1,26 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './Button.css';
|
import './Button.css';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const Button = props => {
|
const Button = (props) => {
|
||||||
return (
|
return (
|
||||||
<button disabled={props.disabled}
|
<button
|
||||||
autoFocus={props.autoFocus}
|
disabled={props.disabled}
|
||||||
className={'Button'}
|
autoFocus={props.autoFocus}
|
||||||
style={props.buttonStyles}
|
className={'Button'}
|
||||||
onClick={props.clicked}>{props.children}</button>
|
style={props.buttonStyles}
|
||||||
|
onClick={props.clicked}>
|
||||||
|
{props.children}
|
||||||
|
</button>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Button.propTypes = {
|
||||||
|
children: PropTypes.oneOfType([PropTypes.object, PropTypes.array, PropTypes.string]),
|
||||||
|
autoFocus: PropTypes.bool,
|
||||||
|
buttonStyles: PropTypes.object,
|
||||||
|
clicked: PropTypes.func,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
};
|
||||||
|
|
||||||
export default Button;
|
export default Button;
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ label.CheckBoxLabel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Hide the browser's default checkbox */
|
/* Hide the browser's default checkbox */
|
||||||
label.CheckBoxLabel input[type=checkbox] {
|
label.CheckBoxLabel input[type='checkbox'] {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@@ -41,7 +41,7 @@ label.CheckBoxLabel input[type=checkbox] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* On mouse-over, add a grey background color */
|
/* On mouse-over, add a grey background color */
|
||||||
label.CheckBoxLabel:hover input[type=checkbox] ~ .CheckBoxCheckMark {
|
label.CheckBoxLabel:hover input[type='checkbox'] ~ .CheckBoxCheckMark {
|
||||||
background-color: var(--control_background_hover);
|
background-color: var(--control_background_hover);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,7 +52,7 @@ label.CheckBoxLabel input:checked ~ .CheckBoxCheckMark {
|
|||||||
|
|
||||||
/* Create the CheckBoxCheckMark/indicator (hidden when not checked) */
|
/* Create the CheckBoxCheckMark/indicator (hidden when not checked) */
|
||||||
.CheckBoxCheckMark:after {
|
.CheckBoxCheckMark:after {
|
||||||
content: "";
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,31 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './CheckBox.css';
|
import './CheckBox.css';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const CheckBox = props => {
|
const CheckBox = (props) => {
|
||||||
return (
|
return (
|
||||||
<div className={'CheckBoxOwner'}>
|
<div className={'CheckBoxOwner'}>
|
||||||
<label className='CheckBoxLabel'>{props.label}
|
<label className="CheckBoxLabel">
|
||||||
<input checked={JSON.parse(props.checked)}
|
{props.label}
|
||||||
autoFocus={props.autoFocus}
|
<input
|
||||||
disabled={props.disabled}
|
checked={JSON.parse(props.checked)}
|
||||||
onChange={props.changed}
|
autoFocus={props.autoFocus}
|
||||||
type='checkbox'/>
|
disabled={props.disabled}
|
||||||
<span className='CheckBoxCheckMark'/>
|
onChange={props.changed}
|
||||||
|
type="checkbox"
|
||||||
|
/>
|
||||||
|
<span className="CheckBoxCheckMark" />
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CheckBox.propTypes = {
|
||||||
|
autoFocus: PropTypes.bool,
|
||||||
|
checked: PropTypes.oneOfType([PropTypes.string, PropTypes.bool]),
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
label: PropTypes.string,
|
||||||
|
changed: PropTypes.func,
|
||||||
|
};
|
||||||
|
|
||||||
export default CheckBox;
|
export default CheckBox;
|
||||||
|
|||||||
@@ -6,7 +6,8 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.DropDownSelect, .DropDownSelect.Alt {
|
.DropDownSelect,
|
||||||
|
.DropDownSelect.Alt {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
display: block;
|
display: block;
|
||||||
|
|||||||
@@ -1,10 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './DropDown.css';
|
import './DropDown.css';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const DropDown = props => {
|
const DropDown = (props) => {
|
||||||
const options = props.items.map((s, i) => {
|
const options = props.items.map((s, i) => {
|
||||||
return (
|
return (
|
||||||
<option className={'DropDownOption'} key={i} value={s}>{s}</option>
|
<option className={'DropDownOption'} key={i} value={s}>
|
||||||
|
{s}
|
||||||
|
</option>
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -20,7 +23,16 @@ const DropDown = props => {
|
|||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
DropDown.propTypes = {
|
||||||
|
alt: PropTypes.bool,
|
||||||
|
auto: PropTypes.bool,
|
||||||
|
autoFocus: PropTypes.bool,
|
||||||
|
changed: PropTypes.func,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
items: PropTypes.array,
|
||||||
|
selected: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default DropDown;
|
export default DropDown;
|
||||||
|
|||||||
@@ -1,23 +1,29 @@
|
|||||||
import React, {Component} from 'react';
|
import React, { Component } from 'react';
|
||||||
import './Grid.css';
|
import './Grid.css';
|
||||||
import GridComponent from './GridComponent/GridComponent';
|
import GridComponent from './GridComponent/GridComponent';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const DEFAULT_GRID_SIZE = 4;
|
const DEFAULT_GRID_SIZE = 4;
|
||||||
|
|
||||||
export default class Grid extends Component {
|
class Grid extends Component {
|
||||||
|
constructor(props) {
|
||||||
|
super(props);
|
||||||
|
this.sizeRef = React.createRef();
|
||||||
|
}
|
||||||
|
|
||||||
resizeTimeout;
|
resizeTimeout;
|
||||||
state = {
|
state = {
|
||||||
calculated: false,
|
calculated: false,
|
||||||
dimensions: {
|
dimensions: {
|
||||||
columns: 0,
|
columns: 0,
|
||||||
rows: 0
|
rows: 0,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
calculateDimensions = size => {
|
calculateDimensions = (size) => {
|
||||||
return {
|
return {
|
||||||
columns: Math.floor(size.width / this.getGridSize()),
|
columns: Math.floor(size.width / this.getGridSize()),
|
||||||
rows: Math.floor(size.height / this.getGridSize())
|
rows: Math.floor(size.height / this.getGridSize()),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -29,7 +35,7 @@ export default class Grid extends Component {
|
|||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
window.removeEventListener('resize', this.handleResize);
|
window.removeEventListener('resize', this.handleResize);
|
||||||
clearInterval(this.resizeTimeout);
|
clearInterval(this.resizeTimeout);
|
||||||
};
|
}
|
||||||
|
|
||||||
getGridSize = () => {
|
getGridSize = () => {
|
||||||
return this.props.gridSize || DEFAULT_GRID_SIZE;
|
return this.props.gridSize || DEFAULT_GRID_SIZE;
|
||||||
@@ -40,10 +46,10 @@ export default class Grid extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getSize = () => {
|
getSize = () => {
|
||||||
const elem = this.refs.GridOwner;
|
const elem = this.sizeRef.current;
|
||||||
return {
|
return {
|
||||||
height: elem ? elem.offsetHeight : 0,
|
height: elem ? elem.offsetHeight : 0,
|
||||||
width: elem ? elem.offsetWidth : 0
|
width: elem ? elem.offsetWidth : 0,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -54,15 +60,15 @@ export default class Grid extends Component {
|
|||||||
|
|
||||||
updateSize = () => {
|
updateSize = () => {
|
||||||
const state = {
|
const state = {
|
||||||
...this.state
|
...this.state,
|
||||||
};
|
};
|
||||||
const size = this.getSize();
|
const size = this.getSize();
|
||||||
const dimensions = this.calculateDimensions(size);
|
const dimensions = this.calculateDimensions(size);
|
||||||
if (state.dimensions !== dimensions) {
|
if (state.dimensions !== dimensions) {
|
||||||
this.setState({
|
this.setState({
|
||||||
calculated: true,
|
calculated: true,
|
||||||
dimensions: dimensions
|
dimensions: dimensions,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -79,34 +85,30 @@ export default class Grid extends Component {
|
|||||||
children = React.Children.map(this.props.children, (child, i) => {
|
children = React.Children.map(this.props.children, (child, i) => {
|
||||||
if (child) {
|
if (child) {
|
||||||
let row = child.props.row || 0;
|
let row = child.props.row || 0;
|
||||||
if (typeof(row) === 'function') {
|
if (typeof row === 'function') {
|
||||||
row = row(dimensions);
|
row = row(dimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
let col = child.props.col || 0;
|
let col = child.props.col || 0;
|
||||||
if (typeof(col) === 'function') {
|
if (typeof col === 'function') {
|
||||||
col = col(dimensions);
|
col = col(dimensions);
|
||||||
}
|
}
|
||||||
|
|
||||||
let rowSpan = child.props.rowSpan;
|
let rowSpan = child.props.rowSpan;
|
||||||
if (typeof(rowSpan) === 'function') {
|
if (typeof rowSpan === 'function') {
|
||||||
rowSpan = rowSpan(dimensions.rows - row, dimensions.rows);
|
rowSpan = rowSpan(dimensions.rows - row, dimensions.rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
let colSpan = child.props.colSpan;
|
let colSpan = child.props.colSpan;
|
||||||
if (typeof(colSpan) === 'function') {
|
if (typeof colSpan === 'function') {
|
||||||
colSpan = colSpan(dimensions.columns - col, dimensions.columns);
|
colSpan = colSpan(dimensions.columns - col, dimensions.columns);
|
||||||
}
|
}
|
||||||
|
|
||||||
rowSpan = rowSpan ? (rowSpan === 'remain' ? (dimensions.rows - row) : rowSpan) : null;
|
rowSpan = rowSpan ? (rowSpan === 'remain' ? dimensions.rows - row : rowSpan) : null;
|
||||||
colSpan = colSpan ? (colSpan === 'remain' ? dimensions.columns - col : colSpan) : null;
|
colSpan = colSpan ? (colSpan === 'remain' ? dimensions.columns - col : colSpan) : null;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<GridComponent row={row}
|
<GridComponent row={row} col={col} rowSpan={rowSpan} colSpan={colSpan} key={'gc_' + i}>
|
||||||
col={col}
|
|
||||||
rowSpan={rowSpan}
|
|
||||||
colSpan={colSpan}
|
|
||||||
key={'gc_' + i}>
|
|
||||||
{child}
|
{child}
|
||||||
</GridComponent>
|
</GridComponent>
|
||||||
);
|
);
|
||||||
@@ -123,7 +125,7 @@ export default class Grid extends Component {
|
|||||||
gridTemplateRows: gridSizePx.repeat(dimensions.rows),
|
gridTemplateRows: gridSizePx.repeat(dimensions.rows),
|
||||||
gridAutoColumns: gridSizePx,
|
gridAutoColumns: gridSizePx,
|
||||||
gridAutoRows: gridSizePx,
|
gridAutoRows: gridSizePx,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
if (this.props.noScroll) {
|
if (this.props.noScroll) {
|
||||||
@@ -132,13 +134,19 @@ export default class Grid extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div
|
<div ref={this.sizeRef} className={'GridOwner'}>
|
||||||
ref='GridOwner'
|
|
||||||
className={'GridOwner'}>
|
|
||||||
<div className={'Grid'} {...style}>
|
<div className={'Grid'} {...style}>
|
||||||
{children}
|
{children}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Grid.propTypes = {
|
||||||
|
children: PropTypes.oneOfType([PropTypes.object, PropTypes.array, PropTypes.string]),
|
||||||
|
gridSize: PropTypes.number,
|
||||||
|
noScroll: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default Grid;
|
||||||
|
|||||||
@@ -1,14 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './GridComponent.css';
|
import './GridComponent.css';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const GridComponent = props => {
|
const GridComponent = (props) => {
|
||||||
const style = {
|
const style = {
|
||||||
style: {
|
style: {
|
||||||
gridRowStart: Math.floor(props.row + 1),
|
gridRowStart: Math.floor(props.row + 1),
|
||||||
gridRowEnd: 'span ' + Math.floor(props.rowSpan || 1),
|
gridRowEnd: 'span ' + Math.floor(props.rowSpan || 1),
|
||||||
gridColumnStart: Math.floor(props.col + 1),
|
gridColumnStart: Math.floor(props.col + 1),
|
||||||
gridColumnEnd: 'span ' + Math.floor(props.colSpan || 1)
|
gridColumnEnd: 'span ' + Math.floor(props.colSpan || 1),
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -16,7 +17,14 @@ const GridComponent = props => {
|
|||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
GridComponent.propTypes = {
|
||||||
|
children: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||||
|
col: PropTypes.number.isRequired,
|
||||||
|
colSpan: PropTypes.number,
|
||||||
|
row: PropTypes.number.isRequired,
|
||||||
|
rowSpan: PropTypes.number,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default GridComponent;
|
export default GridComponent;
|
||||||
|
|||||||
@@ -10,8 +10,9 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
top: 50%; left: 50%;
|
top: 50%;
|
||||||
transform: translate(-50%,-50%);
|
left: 50%;
|
||||||
|
transform: translate(-50%, -50%);
|
||||||
width: 28px;
|
width: 28px;
|
||||||
height: 28px;
|
height: 28px;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|||||||
@@ -1,18 +1,15 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './Loading.css'
|
import './Loading.css';
|
||||||
import Loader from 'react-loader-spinner';
|
import Loader from 'react-loader-spinner';
|
||||||
|
|
||||||
const Loading = () => {
|
const Loading = () => {
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={'Loading'}>
|
||||||
className={'Loading'}>
|
|
||||||
<div className={'LoadingContent'}>
|
<div className={'LoadingContent'}>
|
||||||
<Loader color={'var(--heading_text_color)'}
|
<Loader color={'var(--heading_text_color)'} height={28} width={28} type="ThreeDots" />
|
||||||
height={28}
|
|
||||||
width={28}
|
|
||||||
type='ThreeDots'/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>);
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Loading;
|
export default Loading;
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import './Modal.css';
|
||||||
import './Modal.css'
|
|
||||||
import FocusTrap from 'focus-trap-react';
|
import FocusTrap from 'focus-trap-react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const Modal = props => {
|
const Modal = (props) => {
|
||||||
let modalStyles = [];
|
let modalStyles = [];
|
||||||
let contentStyles = [];
|
let contentStyles = [];
|
||||||
modalStyles.push('Modal');
|
modalStyles.push('Modal');
|
||||||
@@ -19,15 +19,19 @@ const Modal = props => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<FocusTrap active={!props.disableFocusTrap}>
|
<FocusTrap active={!props.disableFocusTrap}>
|
||||||
<div
|
<div className={modalStyles.join(' ')} onClick={props.clicked}>
|
||||||
className={modalStyles.join(' ')}
|
<div className={contentStyles.join(' ')}>{props.children}</div>
|
||||||
onClick={props.clicked}>
|
|
||||||
<div className={contentStyles.join(' ')}>
|
|
||||||
{props.children}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</FocusTrap>
|
</FocusTrap>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Modal.propTypes = {
|
||||||
|
children: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||||
|
clicked: PropTypes.func,
|
||||||
|
critical: PropTypes.bool,
|
||||||
|
disableFocusTrap: PropTypes.bool,
|
||||||
|
transparent: PropTypes.bool,
|
||||||
|
};
|
||||||
|
|
||||||
export default Modal;
|
export default Modal;
|
||||||
|
|||||||
@@ -1,11 +1,16 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const RootElem = props => {
|
const RootElem = (props) => {
|
||||||
return (
|
return (
|
||||||
<div style={{margin: 0, padding: 0}} {...props}>
|
<div style={{ margin: 0, padding: 0 }} {...props}>
|
||||||
{props.children}
|
{props.children}
|
||||||
</div>
|
</div>
|
||||||
)
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
RootElem.propTypes = {
|
||||||
|
children: PropTypes.oneOfType([PropTypes.object, PropTypes.array]),
|
||||||
};
|
};
|
||||||
|
|
||||||
export default RootElem;
|
export default RootElem;
|
||||||
|
|||||||
@@ -1,28 +1,34 @@
|
|||||||
import React from 'react';
|
|
||||||
import './Text.css';
|
import './Text.css';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
|
||||||
const Text = props => {
|
const Text = (props) => {
|
||||||
const styleList = [];
|
const styleList = [];
|
||||||
styleList.push('Text');
|
styleList.push('Text');
|
||||||
if (props.type) {
|
if (props.type) {
|
||||||
styleList.push('Text' + props.type);
|
styleList.push('Text' + props.type);
|
||||||
}
|
}
|
||||||
|
|
||||||
let style = {...props.style};
|
let style = { ...props.style };
|
||||||
if (props.textAlign) {
|
if (props.textAlign) {
|
||||||
style['textAlign'] = props.textAlign.toLowerCase();
|
style['textAlign'] = props.textAlign.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
const text = (
|
const text = (
|
||||||
<div
|
<div className={styleList.join(' ')} style={style}>
|
||||||
className={styleList.join(' ')}
|
{props.text}
|
||||||
style={style}>{props.text}
|
</div>
|
||||||
</div>);
|
);
|
||||||
|
|
||||||
return props.noOwner ? text : (
|
return props.noOwner ? text : <div className={'TextOwner'}>{text}</div>;
|
||||||
<div className={'TextOwner'}>
|
};
|
||||||
{text}
|
|
||||||
</div>);
|
Text.propTypes = {
|
||||||
|
noOwner: PropTypes.bool,
|
||||||
|
style: PropTypes.object,
|
||||||
|
text: PropTypes.string,
|
||||||
|
textAlign: PropTypes.string,
|
||||||
|
type: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Text;
|
export default Text;
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import React from 'react';
|
|
||||||
import './UpgradeIcon.css';
|
import './UpgradeIcon.css';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
import ReactTooltip from 'react-tooltip';
|
import ReactTooltip from 'react-tooltip';
|
||||||
import {faExclamationTriangle} from '@fortawesome/free-solid-svg-icons';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
const UpgradeIcon = props => {
|
const UpgradeIcon = (props) => {
|
||||||
const styles = ['UpgradeIcon'];
|
const styles = ['UpgradeIcon'];
|
||||||
let placement = 'left';
|
let placement = 'left';
|
||||||
let toolTipText = 'UI Upgrade Available';
|
let toolTipText = 'UI Upgrade Available';
|
||||||
@@ -17,21 +18,25 @@ const UpgradeIcon = props => {
|
|||||||
toolTipText = 'New Release Available';
|
toolTipText = 'New Release Available';
|
||||||
}
|
}
|
||||||
|
|
||||||
return props
|
return props.available ? (
|
||||||
.available ?
|
<div className={'UpgradeIconOwner'}>
|
||||||
(
|
<p data-tip="" data-for={placement}>
|
||||||
<div className={'UpgradeIconOwner'}>
|
<a href={'#'} className={styles.join(' ')} onClick={props.clicked}>
|
||||||
<p data-tip='' data-for={placement}>
|
<FontAwesomeIcon icon={faExclamationTriangle} />
|
||||||
<a href={'#'}
|
</a>
|
||||||
className={styles.join(' ')}
|
</p>
|
||||||
onClick={props.clicked}>
|
<ReactTooltip id={placement} place={placement}>
|
||||||
<FontAwesomeIcon icon={faExclamationTriangle}/>
|
{toolTipText}
|
||||||
</a>
|
</ReactTooltip>
|
||||||
</p>
|
</div>
|
||||||
<ReactTooltip id={placement} place={placement}>{toolTipText}</ReactTooltip>
|
) : null;
|
||||||
</div>
|
};
|
||||||
)
|
|
||||||
: null;
|
UpgradeIcon.propTypes = {
|
||||||
|
available: PropTypes.bool,
|
||||||
|
clicked: PropTypes.func,
|
||||||
|
newReleases: PropTypes.bool,
|
||||||
|
release: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default UpgradeIcon;
|
export default UpgradeIcon;
|
||||||
|
|||||||
@@ -1,55 +1,72 @@
|
|||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Button from '../UI/Button/Button';
|
|
||||||
import Box from '../UI/Box/Box';
|
|
||||||
import * as Constants from '../../constants';
|
|
||||||
import React from 'react';
|
|
||||||
import './UpgradeUI.css';
|
import './UpgradeUI.css';
|
||||||
import {setDismissUIUpgrade} from '../../redux/actions/release_version_actions';
|
import * as Constants from '../../constants';
|
||||||
import {downloadItem} from '../../redux/actions/download_actions';
|
import Box from '../UI/Box/Box';
|
||||||
|
import Button from '../UI/Button/Button';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import React from 'react';
|
||||||
|
import { downloadItem } from '../../redux/actions/download_actions';
|
||||||
|
import { setDismissUIUpgrade } from '../../redux/actions/release_version_actions';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const UpgradeUI = (props) => {
|
||||||
return {
|
|
||||||
Platform: state.common.Platform,
|
|
||||||
UpgradeData: state.relver.UpgradeData,
|
|
||||||
UpgradeVersion: state.relver.UpgradeVersion,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
downloadItem: (name, type, urls) => dispatch(downloadItem(name, type, urls)),
|
|
||||||
setDismissUIUpgrade: dismiss => dispatch(setDismissUIUpgrade(dismiss)),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|
||||||
const handleDownload = () => {
|
const handleDownload = () => {
|
||||||
const name = (props.Platform === 'win32') ?
|
const name =
|
||||||
'upgrade.exe' :
|
props.Platform === 'win32'
|
||||||
(props.Platform === 'darwin') ?
|
? 'upgrade.exe'
|
||||||
'upgrade.dmg' :
|
: props.Platform === 'darwin'
|
||||||
'repertory-ui_' + props.UpgradeVersion + '_linux_x86_64.AppImage';
|
? 'upgrade.dmg'
|
||||||
|
: 'repertory-ui_' + props.UpgradeVersion + '_linux_x86_64.AppImage';
|
||||||
props.downloadItem(name, Constants.INSTALL_TYPES.Upgrade, props.UpgradeData.urls);
|
props.downloadItem(name, Constants.INSTALL_TYPES.Upgrade, props.UpgradeData.urls);
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box dxStyle={{width: '180px', height: 'auto', padding: '5px'}}>
|
<Box dxStyle={{ width: '180px', height: 'auto', padding: '5px' }}>
|
||||||
<div style={{width: '100%', height: 'auto'}}>
|
<div style={{ width: '100%', height: 'auto' }}>
|
||||||
<h1 style={{width: '100%', textAlign: 'center'}}>UI Upgrade Available</h1>
|
<h1 style={{ width: '100%', textAlign: 'center' }}>UI Upgrade Available</h1>
|
||||||
</div>
|
</div>
|
||||||
<table cellSpacing={5} width="100%">
|
<table cellSpacing={5} width="100%">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="50%">
|
<td width="50%">
|
||||||
<Button buttonStyles={{width: '100%'}}
|
<Button buttonStyles={{ width: '100%' }} clicked={handleDownload}>
|
||||||
clicked={handleDownload}>Install</Button>
|
Install
|
||||||
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
<td width="50%">
|
<td width="50%">
|
||||||
<Button buttonStyles={{width: '100%'}}
|
<Button
|
||||||
clicked={() => props.setDismissUIUpgrade(true)}>Cancel</Button>
|
buttonStyles={{ width: '100%' }}
|
||||||
|
clicked={() => props.setDismissUIUpgrade(true)}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</Box>);
|
</Box>
|
||||||
});
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
Platform: state.common.Platform,
|
||||||
|
UpgradeData: state.relver.UpgradeData,
|
||||||
|
UpgradeVersion: state.relver.UpgradeVersion,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
downloadItem: (name, type, urls) => dispatch(downloadItem(name, type, urls)),
|
||||||
|
setDismissUIUpgrade: (dismiss) => dispatch(setDismissUIUpgrade(dismiss)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
UpgradeUI.propTypes = {
|
||||||
|
Platform: PropTypes.string.isRequired,
|
||||||
|
UpgradeData: PropTypes.object.isRequired,
|
||||||
|
UpgradeVersion: PropTypes.string.isRequired,
|
||||||
|
downloadItem: PropTypes.func.isRequired,
|
||||||
|
setDismissUIUpgrade: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(UpgradeUI);
|
||||||
|
|||||||
@@ -1,41 +1,57 @@
|
|||||||
import {connect} from 'react-redux';
|
|
||||||
import Button from '../UI/Button/Button';
|
|
||||||
import Box from '../UI/Box/Box';
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './YesNo.css';
|
import './YesNo.css';
|
||||||
import {hideConfirmYesNo} from '../../redux/actions/common_actions';
|
import Box from '../UI/Box/Box';
|
||||||
|
import Button from '../UI/Button/Button';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { confirmYesNoAction } from '../../redux/actions/common_actions';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const YesNo = (props) => {
|
||||||
return {
|
|
||||||
Title: state.common.ConfirmTitle,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
hideConfirmYesNo: confirmed => dispatch(hideConfirmYesNo(confirmed)),
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|
||||||
return (
|
return (
|
||||||
<Box dxStyle={{minWidth: '180px', height: 'auto', padding: 'var(--default_spacing)'}}>
|
<Box
|
||||||
<div style={{width: '100%', height: 'auto'}}>
|
dxStyle={{
|
||||||
<h1 style={{width: '100%', textAlign: 'center'}}>{props.Title}</h1>
|
minWidth: '180px',
|
||||||
|
height: 'auto',
|
||||||
|
padding: 'var(--default_spacing)',
|
||||||
|
}}>
|
||||||
|
<div style={{ width: '100%', height: 'auto' }}>
|
||||||
|
<h1 style={{ width: '100%', textAlign: 'center' }}>{props.Title}</h1>
|
||||||
</div>
|
</div>
|
||||||
<table cellSpacing={5} width="100%">
|
<table cellSpacing={5} width="100%">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td width="50%">
|
<td width="50%">
|
||||||
<Button buttonStyles={{width: '100%'}}
|
<Button buttonStyles={{ width: '100%' }} clicked={() => props.confirm(true)}>
|
||||||
clicked={() => props.hideConfirmYesNo(true)}>Yes</Button>
|
Yes
|
||||||
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
<td width="50%">
|
<td width="50%">
|
||||||
<Button buttonStyles={{width: '100%'}}
|
<Button buttonStyles={{ width: '100%' }} clicked={() => props.confirm(false)}>
|
||||||
clicked={() => props.hideConfirmYesNo(false)}>No</Button>
|
No
|
||||||
|
</Button>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</Box>);
|
</Box>
|
||||||
});
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
Title: state.common.ConfirmTitle,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
confirm: (confirmed) => dispatch(confirmYesNoAction.complete(confirmed)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
YesNo.propTypes = {
|
||||||
|
Title: PropTypes.string.isRequired,
|
||||||
|
confirm: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(YesNo);
|
||||||
|
|||||||
130
src/constants.js
130
src/constants.js
@@ -1,30 +1,30 @@
|
|||||||
Object.defineProperty(exports, '__esModule', {value : true});
|
Object.defineProperty(exports, '__esModule', { value: true });
|
||||||
exports.DEV_PUBLIC_KEY =
|
exports.DEV_PUBLIC_KEY =
|
||||||
'-----BEGIN PUBLIC KEY-----\n' +
|
'-----BEGIN PUBLIC KEY-----\n' +
|
||||||
'MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEKfZmq5mMAtD4kSt2Gc/5J\n' +
|
'MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEKfZmq5mMAtD4kSt2Gc/5J\n' +
|
||||||
'H+HHTYtUZE6YYvsvz8TNG/bNL67ZtNRyaoMyhLTfIN4rPBNLUfD+owNS+u5Yk+lS\n' +
|
'H+HHTYtUZE6YYvsvz8TNG/bNL67ZtNRyaoMyhLTfIN4rPBNLUfD+owNS+u5Yk+lS\n' +
|
||||||
'ZLYyOuhoCZIFefayYqKLr42G8EeuRbx0IMzXmJtN0a4rqxlWhkYufJubpdQ+V4DF\n' +
|
'ZLYyOuhoCZIFefayYqKLr42G8EeuRbx0IMzXmJtN0a4rqxlWhkYufJubpdQ+V4DF\n' +
|
||||||
'oeupcPdIATaadCKVeZC7A0G0uaSwoiAVMG5dZqjQW7F2LoQm3PhNkPvAybIJ6vBy\n' +
|
'oeupcPdIATaadCKVeZC7A0G0uaSwoiAVMG5dZqjQW7F2LoQm3PhNkPvAybIJ6vBy\n' +
|
||||||
'LqdBegS1JrDn43x/pvQHzLO+l+FIG23D1F7iF+yZm3DkzBdcmi/mOMYs/rXZpBym\n' +
|
'LqdBegS1JrDn43x/pvQHzLO+l+FIG23D1F7iF+yZm3DkzBdcmi/mOMYs/rXZpBym\n' +
|
||||||
'2/kTuSGh5buuJCeyOwR8N3WdvXw6+KHMU/wWU8qTCTT87mYbzH4YR8HgkjkLHxAO\n' +
|
'2/kTuSGh5buuJCeyOwR8N3WdvXw6+KHMU/wWU8qTCTT87mYbzH4YR8HgkjkLHxAO\n' +
|
||||||
'5waHK6vMu0TxugCdJmVV6BSbiarJsh66VRosn7+6hlq6AdgksxqCeNELZBS+LBki\n' +
|
'5waHK6vMu0TxugCdJmVV6BSbiarJsh66VRosn7+6hlq6AdgksxqCeNELZBS+LBki\n' +
|
||||||
'tb5hKyL+jNZnaHiR0U7USWtmnqZG6FVVRzlCnxP7tZo5O5Ex9AAFGz5JzOzsFNbv\n' +
|
'tb5hKyL+jNZnaHiR0U7USWtmnqZG6FVVRzlCnxP7tZo5O5Ex9AAFGz5JzOzsFNbv\n' +
|
||||||
'xwQ0zqaTQOze+MJbkda7JfRoC6TncD0+3hoXsiaF4mCn8PqUCn0DwhglcRucZlST\n' +
|
'xwQ0zqaTQOze+MJbkda7JfRoC6TncD0+3hoXsiaF4mCn8PqUCn0DwhglcRucZlST\n' +
|
||||||
'ZvDNDo1WAtxPJebb3aS6uymNhBIquQbVAWxVO4eTrOYEgutxwkHE3yO3is+ogp8d\n' +
|
'ZvDNDo1WAtxPJebb3aS6uymNhBIquQbVAWxVO4eTrOYEgutxwkHE3yO3is+ogp8d\n' +
|
||||||
'xot7f/+vzlbsbIDyuZBDe0fFkbTIMTU48QuUUVZpRKmKZTHQloz4EHqminbfX1sh\n' +
|
'xot7f/+vzlbsbIDyuZBDe0fFkbTIMTU48QuUUVZpRKmKZTHQloz4EHqminbfX1sh\n' +
|
||||||
'M7wvDkpJEtqbc0VnG/BukUzP6e7Skvgc7eF1sI3+8jH8du2rivZeZAl7Q2f+L9JA\n' +
|
'M7wvDkpJEtqbc0VnG/BukUzP6e7Skvgc7eF1sI3+8jH8du2rivZeZAl7Q2f+L9JA\n' +
|
||||||
'BY9pjaxttxsud7V5jeFi4tKuDHi21/XhSjlJK2c2C4AiUEK5/WhtGbQ5JjmcOjRq\n' +
|
'BY9pjaxttxsud7V5jeFi4tKuDHi21/XhSjlJK2c2C4AiUEK5/WhtGbQ5JjmcOjRq\n' +
|
||||||
'yXFRqLlerzOcop2kbtU3Ar230wOx3Dj23Wg8++lV3LU4U9vMR/t0qnSbCSGJys7m\n' +
|
'yXFRqLlerzOcop2kbtU3Ar230wOx3Dj23Wg8++lV3LU4U9vMR/t0qnSbCSGJys7m\n' +
|
||||||
'ax2JpFlTwj/0wYuTlVFoNQHZJ1cdfyRiRBY4Ou7XO0W5hcBBKiYsC+neEeMMHdCe\n' +
|
'ax2JpFlTwj/0wYuTlVFoNQHZJ1cdfyRiRBY4Ou7XO0W5hcBBKiYsC+neEeMMHdCe\n' +
|
||||||
'iTDIW/ojcVTdFovl+sq3n1u4SBknE90JC/3H+TPE1s2iB+fwORVg0KPosQSNDS0A\n' +
|
'iTDIW/ojcVTdFovl+sq3n1u4SBknE90JC/3H+TPE1s2iB+fwORVg0KPosQSNDS0A\n' +
|
||||||
'7iK6AZCDC3YooFo+OzHkYMt9uLkXiXMSLx70az+qlIwOzVHKxCo7W/QpeKCXUCRZ\n' +
|
'7iK6AZCDC3YooFo+OzHkYMt9uLkXiXMSLx70az+qlIwOzVHKxCo7W/QpeKCXUCRZ\n' +
|
||||||
'MMdlYEUs1PC8x2qIRUEVHuJ0XMTKNyOHmzVLuLK93wUWbToh+rdDxnbhX+emuESn\n' +
|
'MMdlYEUs1PC8x2qIRUEVHuJ0XMTKNyOHmzVLuLK93wUWbToh+rdDxnbhX+emuESn\n' +
|
||||||
'XH6aKiUwX4olEVKSylRUQw8nVckZGVWXzLDlgpzDrLHC8J8qHzFt7eCqOdiqsxhZ\n' +
|
'XH6aKiUwX4olEVKSylRUQw8nVckZGVWXzLDlgpzDrLHC8J8qHzFt7eCqOdiqsxhZ\n' +
|
||||||
'x1U5LtugxwSWncTZ7vlKl0DuC/AWB7SuDi7bGRMSVp2n+MnD1VLKlsCclHXjIciE\n' +
|
'x1U5LtugxwSWncTZ7vlKl0DuC/AWB7SuDi7bGRMSVp2n+MnD1VLKlsCclHXjIciE\n' +
|
||||||
'W29n3G3lJ/sOta2sxqLd0j1XBQddrFXl5b609sIY81ocHqu8P2hRu5CpqJ/sGZC5\n' +
|
'W29n3G3lJ/sOta2sxqLd0j1XBQddrFXl5b609sIY81ocHqu8P2hRu5CpqJ/sGZC5\n' +
|
||||||
'mMH3segHBkRj0xJcfOxceRLj1a+ULIIR3xL/3f8s5Id25TDo/nqBoCvu5PeCpo6L\n' +
|
'mMH3segHBkRj0xJcfOxceRLj1a+ULIIR3xL/3f8s5Id25TDo/nqBoCvu5PeCpo6L\n' +
|
||||||
'9wIDAQAB\n' +
|
'9wIDAQAB\n' +
|
||||||
'-----END PUBLIC KEY-----';
|
'-----END PUBLIC KEY-----';
|
||||||
|
|
||||||
const _REPERTORY_BRANCH = 'master';
|
const _REPERTORY_BRANCH = 'master';
|
||||||
const _REPERTORY_UI_BRANCH = 'master';
|
const _REPERTORY_UI_BRANCH = 'master';
|
||||||
@@ -32,19 +32,15 @@ const _REPERTORY_UI_BRANCH = 'master';
|
|||||||
exports.REPERTORY_BRANCH = _REPERTORY_BRANCH;
|
exports.REPERTORY_BRANCH = _REPERTORY_BRANCH;
|
||||||
exports.REPERTORY_UI_BRANCH = _REPERTORY_UI_BRANCH;
|
exports.REPERTORY_UI_BRANCH = _REPERTORY_UI_BRANCH;
|
||||||
|
|
||||||
exports.RELEASES_URL = 'https://bitbucket.org/blockstorage/repertory/raw/' +
|
exports.RELEASES_URL =
|
||||||
_REPERTORY_BRANCH + '/releases_1.3.json';
|
'https://bitbucket.org/blockstorage/repertory/raw/' + _REPERTORY_BRANCH + '/releases_1.3.json';
|
||||||
exports.UI_RELEASES_URL =
|
exports.UI_RELEASES_URL =
|
||||||
'https://bitbucket.org/blockstorage/repertory-ui/raw/' +
|
'https://bitbucket.org/blockstorage/repertory-ui/raw/' + _REPERTORY_UI_BRANCH + '/releases.json';
|
||||||
_REPERTORY_UI_BRANCH + '/releases.json';
|
|
||||||
|
|
||||||
exports.LINUX_DETECT_SCRIPT_URL =
|
exports.LINUX_DETECT_SCRIPT_URL =
|
||||||
'https://bitbucket.org/blockstorage/repertory/raw/' + _REPERTORY_BRANCH +
|
'https://bitbucket.org/blockstorage/repertory/raw/' + _REPERTORY_BRANCH + '/detect_linux2.sh';
|
||||||
'/detect_linux2.sh';
|
|
||||||
|
|
||||||
exports.LINUX_SELECTABLE_PLATFORMS = [
|
exports.LINUX_SELECTABLE_PLATFORMS = ['centos7'];
|
||||||
'centos7',
|
|
||||||
];
|
|
||||||
|
|
||||||
exports.WINFSP_VERSION_NAMES = [
|
exports.WINFSP_VERSION_NAMES = [
|
||||||
'WinFsp 2019',
|
'WinFsp 2019',
|
||||||
@@ -61,6 +57,7 @@ exports.WINFSP_VERSION_NAMES = [
|
|||||||
'WinFsp 2020.0',
|
'WinFsp 2020.0',
|
||||||
'WinFsp 2020.1',
|
'WinFsp 2020.1',
|
||||||
'WinFsp 2020.2',
|
'WinFsp 2020.2',
|
||||||
|
'WinFsp 2021',
|
||||||
'WinFsp 2021 B1',
|
'WinFsp 2021 B1',
|
||||||
'WinFsp 2021 B2',
|
'WinFsp 2021 B2',
|
||||||
'WinFsp 2021 Beta1',
|
'WinFsp 2021 Beta1',
|
||||||
@@ -68,58 +65,55 @@ exports.WINFSP_VERSION_NAMES = [
|
|||||||
];
|
];
|
||||||
|
|
||||||
exports.DATA_LOCATIONS = {
|
exports.DATA_LOCATIONS = {
|
||||||
linux : '~/.local/repertory/ui',
|
linux: '~/.local/repertory/ui',
|
||||||
darwin : '~/Library/Application Support/repertory/ui',
|
darwin: '~/Library/Application Support/repertory/ui',
|
||||||
win32 : '%LOCALAPPDATA%\\repertory\\ui'
|
win32: '%LOCALAPPDATA%\\repertory\\ui',
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.REPERTORY_LOCATIONS = {
|
exports.REPERTORY_LOCATIONS = {
|
||||||
linux : '~/.local/repertory',
|
linux: '~/.local/repertory',
|
||||||
darwin : '~/Library/Application Support/repertory',
|
darwin: '~/Library/Application Support/repertory',
|
||||||
win32 : '%LOCALAPPDATA%\\repertory'
|
win32: '%LOCALAPPDATA%\\repertory',
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.S3_PROVIDER_LIST = [
|
const _S3_CUSTOM_PROVIDER = 'Custom...';
|
||||||
'Filebase',
|
exports.S3_CUSTOM_PROVIDER = _S3_CUSTOM_PROVIDER;
|
||||||
];
|
exports.S3_PROVIDER_LIST = ['Filebase', _S3_CUSTOM_PROVIDER];
|
||||||
|
|
||||||
|
const _S3_CUSTOM_REGION = 'Custom...';
|
||||||
|
exports.S3_CUSTOM_REGION = _S3_CUSTOM_REGION;
|
||||||
exports.S3_REGION_PROVIDER_REGION = [
|
exports.S3_REGION_PROVIDER_REGION = [
|
||||||
'us-east-1',
|
['us-east-1', _S3_CUSTOM_REGION],
|
||||||
|
['any', _S3_CUSTOM_REGION],
|
||||||
];
|
];
|
||||||
|
|
||||||
exports.S3_PROVIDER_URL = {
|
exports.S3_PROVIDER_URL = {
|
||||||
'Filebase' : 'https://s3.filebase.com',
|
Filebase: 'https://s3.filebase.com',
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.PROVIDER_LIST = [
|
exports.PROVIDER_LIST = ['Sia', 'Skynet', 'ScPrime'];
|
||||||
'Sia',
|
|
||||||
'Skynet',
|
|
||||||
'ScPrime',
|
|
||||||
];
|
|
||||||
|
|
||||||
exports.PROVIDER_ARG = {
|
exports.PROVIDER_ARG = {
|
||||||
sia : '',
|
sia: '',
|
||||||
skynet : '-sk',
|
skynet: '-sk',
|
||||||
scprime : '-sp',
|
scprime: '-sp',
|
||||||
s3 : '-s3',
|
s3: '-s3',
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.DEFAULT_RELEASE = 0;
|
exports.DEFAULT_RELEASE = 0;
|
||||||
exports.RELEASE_TYPES = [
|
exports.RELEASE_TYPES = ['Release', 'RC', 'Beta', 'Alpha'];
|
||||||
'Release',
|
|
||||||
'RC',
|
|
||||||
'Beta',
|
|
||||||
'Alpha',
|
|
||||||
];
|
|
||||||
|
|
||||||
exports.INSTALL_TYPES = {
|
exports.INSTALL_TYPES = {
|
||||||
Dependency : 'dependency',
|
Dependency: 'dependency',
|
||||||
Release : 'release',
|
Release: 'release',
|
||||||
TestRelease : 'test_release',
|
TestRelease: 'test_release',
|
||||||
Upgrade : 'upgrade',
|
Upgrade: 'upgrade',
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.IPC_Browse_Directory = 'browse_directory';
|
exports.IPC_Browse_Directory = 'browse_directory';
|
||||||
|
exports.IPC_Browse_File = 'browse_file';
|
||||||
|
|
||||||
|
exports.IPC_Select_File = 'select_file';
|
||||||
|
|
||||||
exports.IPC_Check_Daemon_Version = 'check_daemon_version';
|
exports.IPC_Check_Daemon_Version = 'check_daemon_version';
|
||||||
exports.IPC_Check_Daemon_Version_Reply = 'check_daemon_version_reply';
|
exports.IPC_Check_Daemon_Version_Reply = 'check_daemon_version_reply';
|
||||||
@@ -185,11 +179,14 @@ exports.IPC_Install_Upgrade_Reply = 'install_upgrade_reply';
|
|||||||
exports.IPC_Mount_Drive = 'mount_drive';
|
exports.IPC_Mount_Drive = 'mount_drive';
|
||||||
exports.IPC_Mount_Drive_Reply = 'mount_drive_reply';
|
exports.IPC_Mount_Drive_Reply = 'mount_drive_reply';
|
||||||
|
|
||||||
|
exports.IPC_Read_File = 'read_file';
|
||||||
|
|
||||||
exports.IPC_Remove_Mount = 'remove_mount';
|
exports.IPC_Remove_Mount = 'remove_mount';
|
||||||
exports.IPC_Remove_Mount_Reply = 'remove_mount_reply';
|
exports.IPC_Remove_Mount_Reply = 'remove_mount_reply';
|
||||||
|
|
||||||
exports.IPC_Reboot_System = 'reboot_system';
|
exports.IPC_Reboot_System = 'reboot_system';
|
||||||
|
|
||||||
|
exports.IPC_Save_File = 'save_file';
|
||||||
exports.IPC_Save_State = 'save_state';
|
exports.IPC_Save_State = 'save_state';
|
||||||
|
|
||||||
exports.IPC_Set_Pinned = 'set_pinned';
|
exports.IPC_Set_Pinned = 'set_pinned';
|
||||||
@@ -203,6 +200,9 @@ exports.IPC_Set_Linux_AppPlatform = 'IPC_Set_Linux_AppPlatform';
|
|||||||
|
|
||||||
exports.IPC_Shutdown = 'shutdown';
|
exports.IPC_Shutdown = 'shutdown';
|
||||||
|
|
||||||
|
exports.IPC_Skynet_Test_Logon = 'skynet_test_logon';
|
||||||
|
exports.IPC_Skynet_Test_Logon_Reply = 'skynet_test_logon_reply';
|
||||||
|
|
||||||
exports.IPC_Test_Release = 'test_release';
|
exports.IPC_Test_Release = 'test_release';
|
||||||
exports.IPC_Test_Release_Reply = 'test_release_reply';
|
exports.IPC_Test_Release_Reply = 'test_release_reply';
|
||||||
|
|
||||||
|
|||||||
291
src/containers/AddEditHost/AddEditHost.js
Normal file
291
src/containers/AddEditHost/AddEditHost.js
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import Box from '../../components/UI/Box/Box';
|
||||||
|
import Button from '../../components/UI/Button/Button';
|
||||||
|
import DropDown from '../../components/UI/DropDown/DropDown';
|
||||||
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import Text from '../../components/UI/Text/Text';
|
||||||
|
import { addEditHostAction } from '../../redux/actions/host_actions';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { createDismissDisplay } from '../../utils.jsx';
|
||||||
|
import { notifyApplicationBusy } from '../../redux/actions/common_actions';
|
||||||
|
import { notifyError, notifyInfo } from '../../redux/actions/error_actions';
|
||||||
|
|
||||||
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
|
class AddEditHost extends IPCContainer {
|
||||||
|
state = {
|
||||||
|
AgentString: '',
|
||||||
|
ApiPassword: '',
|
||||||
|
ApiPort: 443,
|
||||||
|
AuthPassword: '',
|
||||||
|
AuthURL: '',
|
||||||
|
AuthUser: '',
|
||||||
|
HostNameOrIp: '',
|
||||||
|
Path: '',
|
||||||
|
Protocol: 'https',
|
||||||
|
TimeoutMs: 60000,
|
||||||
|
};
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setRequestHandler(Constants.IPC_Skynet_Test_Logon_Reply, this.onSkynetTestLogonReply);
|
||||||
|
|
||||||
|
if (this.props.HostData) {
|
||||||
|
this.setState({ ...this.state, ...this.props.HostData });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {
|
||||||
|
super.componentWillUnmount();
|
||||||
|
}
|
||||||
|
|
||||||
|
handleSave = () => {
|
||||||
|
if (this.state.HostNameOrIp.trim().length === 0) {
|
||||||
|
this.props.notifyError('Host / IP cannot be empty');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state.HostNameOrIp.trim().indexOf('/') >= 0) {
|
||||||
|
this.props.notifyError(`Host / IP cannot be contain '/'`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.state.HostNameOrIp.trim().indexOf(':') >= 0) {
|
||||||
|
this.props.notifyError(`Host / IP cannot be contain ':'`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
this.props.HostList.find(
|
||||||
|
(i) =>
|
||||||
|
(i.HostNameOrIp || '').trim() === this.state.HostNameOrIp &&
|
||||||
|
i.Protocol === this.state.Protocol &&
|
||||||
|
i.ApiPort == this.state.ApiPort
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
this.props.notifyError(`Portal already exists`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.props.completeAddEditHost(this.state);
|
||||||
|
};
|
||||||
|
|
||||||
|
handleTestLogon = () => {
|
||||||
|
try {
|
||||||
|
this.props.notifyApplicationBusy(true);
|
||||||
|
this.sendRequest(Constants.IPC_Skynet_Test_Logon, {
|
||||||
|
Version: this.props.InstalledVersion,
|
||||||
|
AuthURL: this.state.AuthURL,
|
||||||
|
AuthUser: this.state.AuthUser,
|
||||||
|
AuthPassword: this.state.AuthPassword,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
this.props.notifyApplicationBusy(false);
|
||||||
|
this.props.notifyError(e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onSkynetTestLogonReply = (_, arg) => {
|
||||||
|
this.props.notifyApplicationBusy(false);
|
||||||
|
if (arg.data.Success) {
|
||||||
|
this.props.notifyInfo('Logon was successful!');
|
||||||
|
} else {
|
||||||
|
this.props.notifyError(arg.data.Error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const allowTestLogon = this.state.AuthURL && this.state.AuthUser;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Box dxDark dxStyle={{ width: '430px', height: 'auto', padding: '5px' }}>
|
||||||
|
{createDismissDisplay(this.props.Close)}
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
height: 'auto',
|
||||||
|
paddingBottom: '5px',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
}}>
|
||||||
|
<h1
|
||||||
|
style={{
|
||||||
|
width: '100%',
|
||||||
|
textAlign: 'center',
|
||||||
|
color: 'var(--text_color_error)',
|
||||||
|
}}>
|
||||||
|
Portal Settings
|
||||||
|
</h1>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text text={'Host / IP'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ HostNameOrIp: e.target.value.trim() })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.HostNameOrIp}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text text={'Protocol'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
|
<Text text={'Port'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
|
<Text text={'Timeout (ms)'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<DropDown
|
||||||
|
changed={(e) => this.setState({ Protocol: e.target.value })}
|
||||||
|
items={['https', 'http']}
|
||||||
|
selected={this.state.Protocol}
|
||||||
|
/>
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ ApiPort: parseInt(e.target.value) })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
type={'number'}
|
||||||
|
min={1}
|
||||||
|
max={65535}
|
||||||
|
value={this.state.ApiPort}
|
||||||
|
/>
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ TimeoutMs: parseInt(e.target.value) })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
type={'number'}
|
||||||
|
min={1000}
|
||||||
|
step={1000}
|
||||||
|
value={this.state.TimeoutMs}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text text={'Agent String (optional)'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<Text text={'API Key (optional)'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ AgentString: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ flex: '1' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.AgentString}
|
||||||
|
/>
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ ApiPassword: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ flex: '1' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.ApiPassword}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text
|
||||||
|
noOwner
|
||||||
|
text={'Authentication URL (premium)'}
|
||||||
|
textAlign={'left'}
|
||||||
|
type={'Heading2'}
|
||||||
|
style={{ marginRight: 'auto' }}
|
||||||
|
/>
|
||||||
|
{allowTestLogon ? (
|
||||||
|
<a
|
||||||
|
href={'#'}
|
||||||
|
onClick={(e) => {
|
||||||
|
this.handleTestLogon();
|
||||||
|
e.preventDefault();
|
||||||
|
}}>
|
||||||
|
<u>test logon</u>
|
||||||
|
</a>
|
||||||
|
) : null}
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ AuthURL: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.AuthURL}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text text={'User Name (premium)'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<Text text={'Password (premium)'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ AuthUser: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ flex: '1' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.AuthUser}
|
||||||
|
/>
|
||||||
|
<div style={{ width: 'var(--default_spacing)' }} />
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ AuthPassword: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ flex: '1' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.AuthPassword}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
<p>
|
||||||
|
<b>
|
||||||
|
{'Portal URL: ' +
|
||||||
|
this.state.Protocol +
|
||||||
|
'://' +
|
||||||
|
this.state.HostNameOrIp +
|
||||||
|
((this.state.Protocol === 'http' && this.state.ApiPort != 80) ||
|
||||||
|
(this.state.Protocol === 'https' && this.state.ApiPort != 443)
|
||||||
|
? ':' + this.state.ApiPort.toString()
|
||||||
|
: '')}
|
||||||
|
</b>
|
||||||
|
</p>
|
||||||
|
<div style={{ height: 'var(--default_spacing)' }} />
|
||||||
|
</div>
|
||||||
|
<Button clicked={this.handleSave}>Save</Button>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
HostData: state.host.HostData,
|
||||||
|
HostList: state.host.HostList,
|
||||||
|
InstalledVersion: state.relver.InstalledVersion,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
Close: () => dispatch(addEditHostAction.complete(false)),
|
||||||
|
completeAddEditHost: (host_data) => dispatch(addEditHostAction.complete(true, { host_data })),
|
||||||
|
notifyApplicationBusy: (busy) => dispatch(notifyApplicationBusy(busy, true)),
|
||||||
|
notifyError: (msg) => dispatch(notifyError(msg)),
|
||||||
|
notifyInfo: (msg) => dispatch(notifyInfo(msg)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
AddEditHost.propTypes = {
|
||||||
|
Close: PropTypes.func.isRequired,
|
||||||
|
HostData: PropTypes.object,
|
||||||
|
HostList: PropTypes.array.isRequired,
|
||||||
|
InstalledVersion: PropTypes.string.isRequired,
|
||||||
|
completeAddEditHost: PropTypes.func.isRequired,
|
||||||
|
notifyApplicationBusy: PropTypes.func.isRequired,
|
||||||
|
notifyError: PropTypes.func.isRequired,
|
||||||
|
notifyInfo: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(AddEditHost);
|
||||||
@@ -1,31 +1,17 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import {Component} from 'react';
|
import PropTypes from 'prop-types';
|
||||||
|
import { Component } from 'react';
|
||||||
import './AddMount.css';
|
import './AddMount.css';
|
||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import Button from '../../components/UI/Button/Button';
|
import Button from '../../components/UI/Button/Button';
|
||||||
import Box from '../../components/UI/Box/Box';
|
import Box from '../../components/UI/Box/Box';
|
||||||
import Text from '../../components/UI/Text/Text';
|
import Text from '../../components/UI/Text/Text';
|
||||||
import {notifyError} from '../../redux/actions/error_actions';
|
import { notifyError } from '../../redux/actions/error_actions';
|
||||||
import {addRemoteMount, addS3Mount} from '../../redux/actions/mount_actions';
|
import { addRemoteMount, addS3Mount } from '../../redux/actions/mount_actions';
|
||||||
import {createModalConditionally} from '../../utils';
|
import { createModalConditionally } from '../../utils.jsx';
|
||||||
import DropDown from '../../components/UI/DropDown/DropDown';
|
import DropDown from '../../components/UI/DropDown/DropDown';
|
||||||
import * as Constants from '../../constants';
|
import * as Constants from '../../constants';
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
|
||||||
return {
|
|
||||||
RemoteMounts: state.mounts.RemoteMounts,
|
|
||||||
S3Mounts: state.mounts.S3Mounts,
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
addRemoteMount: (hostNameOrIp, port, token) => dispatch(addRemoteMount(hostNameOrIp, port, token)),
|
|
||||||
addS3Mount: (name, accessKey, secretKey, region, bucketName, url) => dispatch(addS3Mount(name, accessKey, secretKey, region, bucketName, url)),
|
|
||||||
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const default_state = {
|
const default_state = {
|
||||||
AccessKey: '',
|
AccessKey: '',
|
||||||
BucketName: '',
|
BucketName: '',
|
||||||
@@ -35,12 +21,14 @@ const default_state = {
|
|||||||
Name: '',
|
Name: '',
|
||||||
Port: 20000,
|
Port: 20000,
|
||||||
Provider: Constants.S3_PROVIDER_LIST[0],
|
Provider: Constants.S3_PROVIDER_LIST[0],
|
||||||
Region: Constants.S3_REGION_PROVIDER_REGION[0],
|
Region: Constants.S3_REGION_PROVIDER_REGION[0][0],
|
||||||
SecretKey: '',
|
SecretKey: '',
|
||||||
Token: '',
|
Token: '',
|
||||||
|
CustomURL: '',
|
||||||
|
CustomRegion: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(class extends Component {
|
class AddMount extends Component {
|
||||||
state = {
|
state = {
|
||||||
...default_state,
|
...default_state,
|
||||||
};
|
};
|
||||||
@@ -53,39 +41,59 @@ export default connect(mapStateToProps, mapDispatchToProps)(class extends Compon
|
|||||||
if (this.props.RemoteMounts.includes(provider)) {
|
if (this.props.RemoteMounts.includes(provider)) {
|
||||||
this.props.notifyError('Remote host already exists');
|
this.props.notifyError('Remote host already exists');
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState(
|
||||||
DisplayRemote: false
|
{
|
||||||
}, () => {
|
DisplayRemote: false,
|
||||||
this.props.addRemoteMount(this.state.HostNameOrIp, this.state.Port, this.state.Token);
|
},
|
||||||
this.setState({
|
() => {
|
||||||
...default_state,
|
this.props.addRemoteMount(this.state.HostNameOrIp, this.state.Port, this.state.Token);
|
||||||
});
|
this.setState({
|
||||||
});
|
...default_state,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
addS3Mount = () => {
|
addS3Mount = () => {
|
||||||
|
const isCustomProvider = this.state.Provider === Constants.S3_CUSTOM_PROVIDER;
|
||||||
|
const isCustomRegion = this.state.Region === Constants.S3_CUSTOM_REGION;
|
||||||
if (this.state.Name.length === 0) {
|
if (this.state.Name.length === 0) {
|
||||||
this.props.notifyError('Name cannot be empty.');
|
this.props.notifyError('Name cannot be empty.');
|
||||||
} else if (this.state.AccessKey.length === 0) {
|
} else if (this.state.AccessKey.length === 0) {
|
||||||
this.props.notifyError('AccessKey cannot be empty.');
|
this.props.notifyError('AccessKey cannot be empty.');
|
||||||
} else if (this.state.SecretKey.length === 0) {
|
} else if (this.state.SecretKey.length === 0) {
|
||||||
this.props.notifyError('SecretKey cannot be empty.')
|
this.props.notifyError('SecretKey cannot be empty.');
|
||||||
|
} else if (isCustomProvider && !this.state.CustomURL.trim()) {
|
||||||
|
this.props.notifyError('Custom URL cannot be empty.');
|
||||||
|
} else if (isCustomRegion && !this.state.CustomRegion.trim()) {
|
||||||
|
this.props.notifyError('Custom Region cannot be empty.');
|
||||||
} else {
|
} else {
|
||||||
const provider = 'S3' + this.state.Name;
|
const provider = 'S3' + this.state.Name;
|
||||||
if (this.props.S3Mounts.includes(provider)) {
|
if (this.props.S3Mounts.includes(provider)) {
|
||||||
this.props.notifyError('Remote host already exists');
|
this.props.notifyError('Remote host already exists');
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState(
|
||||||
DisplayS3: false
|
{
|
||||||
}, () => {
|
DisplayS3: false,
|
||||||
this.props.addS3Mount(this.state.Name, this.state.AccessKey, this.state.SecretKey,
|
},
|
||||||
this.state.Region, this.state.BucketName, Constants.S3_PROVIDER_URL[this.state.Provider]);
|
() => {
|
||||||
this.setState({
|
this.props.addS3Mount(
|
||||||
...default_state,
|
this.state.Name,
|
||||||
});
|
this.state.AccessKey,
|
||||||
});
|
this.state.SecretKey,
|
||||||
|
isCustomRegion ? this.state.CustomRegion : this.state.Region,
|
||||||
|
this.state.BucketName,
|
||||||
|
isCustomProvider
|
||||||
|
? this.state.CustomURL
|
||||||
|
: Constants.S3_PROVIDER_URL[this.state.Provider]
|
||||||
|
);
|
||||||
|
this.setState({
|
||||||
|
...default_state,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -105,142 +113,257 @@ export default connect(mapStateToProps, mapDispatchToProps)(class extends Compon
|
|||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const displayAddRemote = createModalConditionally(this.state.DisplayRemote, (
|
const displayAddRemote = createModalConditionally(
|
||||||
<Box dxDark
|
this.state.DisplayRemote,
|
||||||
dxStyle={{width: 'auto', height: 'auto', padding: 'var(--default_spacing)'}}>
|
<Box
|
||||||
<h1 style={{textAlign: 'center', paddingBottom: 'var(--default_spacing)'}}>Add Remote
|
dxDark
|
||||||
Mount</h1>
|
dxStyle={{
|
||||||
<Text text={'Hostname or IP'}
|
width: 'auto',
|
||||||
textAlign={'left'}
|
height: 'auto',
|
||||||
type={'Heading2'}/>
|
padding: 'var(--default_spacing)',
|
||||||
<input onChange={e => this.setState({HostNameOrIp: e.target.value.trim()})}
|
}}>
|
||||||
className={'ConfigurationItemInput'}
|
<h1
|
||||||
type={'text'}
|
style={{
|
||||||
value={this.state.HostNameOrIp}/>
|
textAlign: 'center',
|
||||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
paddingBottom: 'var(--default_spacing)',
|
||||||
<Text text={'Port'}
|
}}>
|
||||||
textAlign={'left'}
|
Add Remote Mount
|
||||||
type={'Heading2'}/>
|
</h1>
|
||||||
<input max={65535}
|
<Text text={'Hostname or IP'} textAlign={'left'} type={'Heading2'} />
|
||||||
min={1025}
|
<input
|
||||||
onChange={e => this.setState({Port: e.target.value})}
|
onChange={(e) => this.setState({ HostNameOrIp: e.target.value.trim() })}
|
||||||
className={'ConfigurationItemInput'}
|
className={'ConfigurationItemInput'}
|
||||||
type={'number'}
|
type={'text'}
|
||||||
value={this.state.Port}/>
|
value={this.state.HostNameOrIp}
|
||||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
/>
|
||||||
<Text text={'Remote Token'}
|
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||||
textAlign={'left'}
|
<Text text={'Port'} textAlign={'left'} type={'Heading2'} />
|
||||||
type={'Heading2'}/>
|
<input
|
||||||
<input onChange={e => this.setState({Token: e.target.value})}
|
max={65535}
|
||||||
className={'ConfigurationItemInput'}
|
min={1025}
|
||||||
type={'text'}
|
onChange={(e) => this.setState({ Port: e.target.value })}
|
||||||
value={this.state.Token}/>
|
className={'ConfigurationItemInput'}
|
||||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
type={'number'}
|
||||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
value={this.state.Port}
|
||||||
<Button buttonStyles={{width: '100%'}}
|
/>
|
||||||
clicked={() => this.addRemoteMount()}>OK</Button>
|
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
<Text text={'Remote Token'} textAlign={'left'} type={'Heading2'} />
|
||||||
<Button buttonStyles={{width: '100%'}}
|
<input
|
||||||
clicked={() => this.setState({DisplayRemote: false})}>Cancel</Button>
|
onChange={(e) => this.setState({ Token: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.Token}
|
||||||
|
/>
|
||||||
|
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Button buttonStyles={{ width: '100%' }} clicked={() => this.addRemoteMount()}>
|
||||||
|
OK
|
||||||
|
</Button>
|
||||||
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
|
<Button
|
||||||
|
buttonStyles={{ width: '100%' }}
|
||||||
|
clicked={() => this.setState({ DisplayRemote: false })}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
));
|
);
|
||||||
|
|
||||||
const displayAddS3 = createModalConditionally(this.state.DisplayS3, (
|
const displayAddS3 = createModalConditionally(
|
||||||
<Box dxDark
|
this.state.DisplayS3,
|
||||||
dxStyle={{width: 'auto', height: 'auto', padding: 'var(--default_spacing)'}}>
|
<Box
|
||||||
<h1 style={{textAlign: 'center', paddingBottom: 'var(--default_spacing)'}}>Add S3
|
dxDark
|
||||||
Mount</h1>
|
dxStyle={{
|
||||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
width: 'auto',
|
||||||
<Text text={'Name'}
|
height: 'auto',
|
||||||
textAlign={'left'}
|
padding: 'var(--default_spacing)',
|
||||||
type={'Heading2'}/>
|
}}>
|
||||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
<h1
|
||||||
<Text text={'Provider'}
|
style={{
|
||||||
textAlign={'left'}
|
textAlign: 'center',
|
||||||
type={'Heading2'}/>
|
paddingBottom: 'var(--default_spacing)',
|
||||||
|
}}>
|
||||||
|
Add S3 Mount
|
||||||
|
</h1>
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text text={'Name'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
|
<Text text={'Provider'} textAlign={'left'} type={'Heading2'} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
<input onChange={e => this.setState({Name: e.target.value.trim()})}
|
<input
|
||||||
className={'ConfigurationItemInput'}
|
onChange={(e) => this.setState({ Name: e.target.value.trim() })}
|
||||||
style={{width: '100%'}}
|
className={'ConfigurationItemInput'}
|
||||||
type={'text'}
|
style={{ width: '100%' }}
|
||||||
value={this.state.Name}/>
|
type={'text'}
|
||||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
value={this.state.Name}
|
||||||
<DropDown changed={e => this.setState({Provider: e.target.value})}
|
/>
|
||||||
items={Constants.S3_PROVIDER_LIST}
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
selected={this.state.Provider}/>
|
<DropDown
|
||||||
|
changed={(e) =>
|
||||||
|
this.setState({
|
||||||
|
Provider: e.target.value,
|
||||||
|
Region:
|
||||||
|
Constants.S3_REGION_PROVIDER_REGION[
|
||||||
|
Constants.S3_PROVIDER_LIST.indexOf(e.target.value)
|
||||||
|
][0],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
items={Constants.S3_PROVIDER_LIST}
|
||||||
|
selected={this.state.Provider}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
{this.state.Provider === Constants.S3_CUSTOM_PROVIDER ? (
|
||||||
<Text text={'Bucket Name (optional)'}
|
<div>
|
||||||
textAlign={'left'}
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
type={'Heading2'}/>
|
<Text text={'Custom URL'} textAlign={'left'} type={'Heading2'} />
|
||||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
</div>
|
||||||
<Text text={'Region'}
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
textAlign={'left'}
|
<input
|
||||||
type={'Heading2'}/>
|
onChange={(e) => this.setState({ CustomURL: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.CustomURL}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text text={'Bucket Name (optional)'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
|
<Text text={'Region'} textAlign={'left'} type={'Heading2'} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
<input onChange={e => this.setState({BucketName: e.target.value})}
|
<input
|
||||||
className={'ConfigurationItemInput'}
|
onChange={(e) => this.setState({ BucketName: e.target.value })}
|
||||||
style={{width: '100%'}}
|
className={'ConfigurationItemInput'}
|
||||||
type={'text'}
|
style={{ width: '100%' }}
|
||||||
value={this.state.BucketName}/>
|
type={'text'}
|
||||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
value={this.state.BucketName}
|
||||||
<input onChange={e => this.setState({Region: e.target.value})}
|
/>
|
||||||
className={'ConfigurationItemInput'}
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
type={'text'}
|
<DropDown
|
||||||
value={this.state.Region}/>
|
changed={(e) =>
|
||||||
|
this.setState({
|
||||||
|
Region: e.target.value,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
items={
|
||||||
|
Constants.S3_REGION_PROVIDER_REGION[
|
||||||
|
Constants.S3_PROVIDER_LIST.indexOf(this.state.Provider)
|
||||||
|
]
|
||||||
|
}
|
||||||
|
selected={this.state.Region}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
{this.state.Region === Constants.S3_CUSTOM_REGION ? (
|
||||||
<Text text={'Access Key'}
|
<div>
|
||||||
textAlign={'left'}
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
type={'Heading2'}/>
|
<div style={{ paddingLeft: 'var(--default_spacing)', width: '100%' }} />
|
||||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
<Text text={'Custom Region'} textAlign={'left'} type={'Heading2'} />
|
||||||
<Text text={'Secret Key'}
|
</div>
|
||||||
textAlign={'left'}
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
type={'Heading2'}/>
|
<div style={{ paddingLeft: 'var(--default_spacing)', width: '100%' }} />
|
||||||
|
<input
|
||||||
|
onChange={(e) => this.setState({ CustomRegion: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
style={{ width: '100%' }}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.CustomRegion}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<Text text={'Access Key'} textAlign={'left'} type={'Heading2'} />
|
||||||
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
|
<Text text={'Secret Key'} textAlign={'left'} type={'Heading2'} />
|
||||||
</div>
|
</div>
|
||||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
<input onChange={e => this.setState({AccessKey: e.target.value})}
|
<input
|
||||||
className={'ConfigurationItemInput'}
|
onChange={(e) => this.setState({ AccessKey: e.target.value })}
|
||||||
type={'text'}
|
className={'ConfigurationItemInput'}
|
||||||
value={this.state.AccessKey}/>
|
type={'text'}
|
||||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
value={this.state.AccessKey}
|
||||||
<input onChange={e => this.setState({SecretKey: e.target.value})}
|
/>
|
||||||
className={'ConfigurationItemInput'}
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
type={'text'}
|
<input
|
||||||
value={this.state.SecretKey}/>
|
onChange={(e) => this.setState({ SecretKey: e.target.value })}
|
||||||
|
className={'ConfigurationItemInput'}
|
||||||
|
type={'text'}
|
||||||
|
value={this.state.SecretKey}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div style={{paddingTop: 'calc(var(--default_spacing) * 2)'}}/>
|
<div style={{ paddingTop: 'calc(var(--default_spacing) * 2)' }} />
|
||||||
<div style={{display: 'flex', flexDirection: 'row'}}>
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
<div style={{width: '200%'}}/>
|
<div style={{ width: '200%' }} />
|
||||||
<Button buttonStyles={{width: '100%'}}
|
<Button buttonStyles={{ width: '100%' }} clicked={() => this.addS3Mount()}>
|
||||||
clicked={() => this.addS3Mount()}>OK</Button>
|
OK
|
||||||
<div style={{paddingLeft: 'var(--default_spacing)'}}/>
|
</Button>
|
||||||
<Button buttonStyles={{width: '100%'}}
|
<div style={{ paddingLeft: 'var(--default_spacing)' }} />
|
||||||
clicked={() => this.setState({DisplayS3: false})}>Cancel</Button>
|
<Button
|
||||||
|
buttonStyles={{ width: '100%' }}
|
||||||
|
clicked={() => this.setState({ DisplayS3: false })}>
|
||||||
|
Cancel
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
));
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'AddMount'}>
|
<div className={'AddMount'}>
|
||||||
{displayAddRemote}
|
{displayAddRemote}
|
||||||
{displayAddS3}
|
{displayAddS3}
|
||||||
<div className={'AddMountButtons'}>
|
<div className={'AddMountButtons'}>
|
||||||
{this.props.remoteSupported ?
|
{this.props.remoteSupported ? (
|
||||||
<Button className={'AddMountButton'}
|
<Button className={'AddMountButton'} clicked={this.handleAddRemoteMount}>
|
||||||
clicked={this.handleAddRemoteMount}>Add Remote Mount</Button> : null}
|
Add Remote Mount
|
||||||
{this.props.remoteSupported && this.props.s3Supported ?
|
</Button>
|
||||||
<div style={{paddingRight: 'var(--default_spacing)'}}/> : null}
|
) : null}
|
||||||
{this.props.s3Supported ?
|
{this.props.remoteSupported && this.props.s3Supported ? (
|
||||||
<Button className={'AddMountButton'}
|
<div style={{ paddingRight: 'var(--default_spacing)' }} />
|
||||||
clicked={this.handleAddS3Mount}>Add S3 Mount</Button> : null}
|
) : null}
|
||||||
|
{this.props.s3Supported ? (
|
||||||
|
<Button className={'AddMountButton'} clicked={this.handleAddS3Mount}>
|
||||||
|
Add S3 Mount
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
RemoteMounts: state.mounts.RemoteMounts,
|
||||||
|
S3Mounts: state.mounts.S3Mounts,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
addRemoteMount: (hostNameOrIp, port, token) =>
|
||||||
|
dispatch(addRemoteMount(hostNameOrIp, port, token)),
|
||||||
|
addS3Mount: (name, accessKey, secretKey, region, bucketName, url) =>
|
||||||
|
dispatch(addS3Mount(name, accessKey, secretKey, region, bucketName, url)),
|
||||||
|
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
AddMount.propTypes = {
|
||||||
|
RemoteMounts: PropTypes.array.isRequired,
|
||||||
|
S3Mounts: PropTypes.array.isRequired,
|
||||||
|
addRemoteMount: PropTypes.func.isRequired,
|
||||||
|
addS3Mount: PropTypes.func.isRequired,
|
||||||
|
notifyError: PropTypes.func.isRequired,
|
||||||
|
remoteSupported: PropTypes.bool,
|
||||||
|
s3Supported: PropTypes.bool,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(AddMount);
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './Configuration.css';
|
import './Configuration.css';
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import Box from '../../components/UI/Box/Box';
|
import Box from '../../components/UI/Box/Box';
|
||||||
import Button from '../../components/UI/Button/Button';
|
import Button from '../../components/UI/Button/Button';
|
||||||
import ConfigurationItem from './ConfigurationItem/ConfigurationItem';
|
import ConfigurationItem from './ConfigurationItem/ConfigurationItem';
|
||||||
import Modal from '../../components/UI/Modal/Modal';
|
|
||||||
import IPCContainer from '../IPCContainer/IPCContainer';
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||||
import {displayConfiguration} from '../../redux/actions/mount_actions';
|
import Modal from '../../components/UI/Modal/Modal';
|
||||||
import {notifyError} from '../../redux/actions/error_actions';
|
import PropTypes from 'prop-types';
|
||||||
import {displayPinnedManager} from '../../redux/actions/pinned_manager_actions';
|
import { connect } from 'react-redux';
|
||||||
|
import { createDismissDisplay } from '../../utils.jsx';
|
||||||
|
import { displayConfiguration } from '../../redux/actions/mount_actions';
|
||||||
|
import { displayPinnedManager } from '../../redux/actions/pinned_manager_actions';
|
||||||
|
import { notifyError } from '../../redux/actions/error_actions';
|
||||||
|
|
||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
@@ -25,7 +27,7 @@ class Configuration extends IPCContainer {
|
|||||||
ItemList: [],
|
ItemList: [],
|
||||||
Saving: false,
|
Saving: false,
|
||||||
ShowAdvanced: false,
|
ShowAdvanced: false,
|
||||||
Template: {}
|
Template: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
checkItemChanged = (itemA, itemB) => {
|
checkItemChanged = (itemA, itemB) => {
|
||||||
@@ -33,29 +35,44 @@ class Configuration extends IPCContainer {
|
|||||||
if (itemA.value.length !== itemB.value.length) {
|
if (itemA.value.length !== itemB.value.length) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return itemA.value.filter(i => !itemB.value.includes(i)).length !== 0;
|
return itemA.value.filter((i) => !itemB.value.includes(i)).length !== 0;
|
||||||
|
}
|
||||||
|
if (itemA.type === 'host_list') {
|
||||||
|
if (itemA.value.length !== itemB.value.length) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
itemA.value.filter((i) =>
|
||||||
|
itemB.value.find(
|
||||||
|
(j) =>
|
||||||
|
j.HostNameOrIp === i.HostNameOrIp &&
|
||||||
|
j.ApiPort === i.ApiPort &&
|
||||||
|
j.Protocol === i.Protocol &&
|
||||||
|
j.TimeoutMs === i.TimeoutMs &&
|
||||||
|
j.AgentString === i.AgentString &&
|
||||||
|
j.ApiPassword === i.ApiPassword &&
|
||||||
|
j.AuthURL === i.AuthURL &&
|
||||||
|
j.AuthUser === i.AuthUser &&
|
||||||
|
j.AuthPassword === i.AuthPassword
|
||||||
|
)
|
||||||
|
).length != itemA.value.length
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return itemA.value !== itemB.value;
|
return itemA.value !== itemB.value;
|
||||||
};
|
};
|
||||||
|
|
||||||
checkSaveRequired = () => {
|
checkSaveRequired = () => {
|
||||||
const changedItems = [];
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
for (const item of this.state.ItemList) {
|
const changedItems = this.state.ItemList.filter((item) => {
|
||||||
if (this.checkItemChanged(this.state.OriginalItemList[i++], item)) {
|
return this.checkItemChanged(this.state.OriginalItemList[i++], item);
|
||||||
changedItems.push(item);
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let changedObjectLookup = null;
|
let changedObjectLookup = null;
|
||||||
for (const key of Object.keys(this.state.ObjectLookup)) {
|
for (const key of Object.keys(this.state.ObjectLookup)) {
|
||||||
const changedObjectItems = [];
|
|
||||||
let j = 0;
|
let j = 0;
|
||||||
for (const item of this.state.ObjectLookup[key]) {
|
const changedObjectItems = this.state.ObjectLookup[key].filter((item) => {
|
||||||
if (this.checkItemChanged(this.state.OriginalObjectLookup[key][j++], item)) {
|
return this.checkItemChanged(this.state.OriginalObjectLookup[key][j++], item);
|
||||||
changedObjectItems.push(item);
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (changedObjectItems.length > 0) {
|
if (changedObjectItems.length > 0) {
|
||||||
if (changedObjectLookup === null) {
|
if (changedObjectLookup === null) {
|
||||||
@@ -65,7 +82,7 @@ class Configuration extends IPCContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((changedItems.length > 0) || changedObjectLookup) {
|
if (changedItems.length > 0 || changedObjectLookup) {
|
||||||
this.setState({
|
this.setState({
|
||||||
ChangedItems: changedItems,
|
ChangedItems: changedItems,
|
||||||
ChangedObjectLookup: changedObjectLookup,
|
ChangedObjectLookup: changedObjectLookup,
|
||||||
@@ -95,62 +112,69 @@ class Configuration extends IPCContainer {
|
|||||||
|
|
||||||
createItemList = (config, template) => {
|
createItemList = (config, template) => {
|
||||||
const objectList = [];
|
const objectList = [];
|
||||||
const itemList = Object
|
const itemList = Object.keys(config)
|
||||||
.keys(config)
|
.map((key) => {
|
||||||
.map(key => {
|
return {
|
||||||
return {
|
advanced: template[key] ? template[key].advanced : false,
|
||||||
advanced: template[key] ? template[key].advanced : false,
|
hide_remote: template[key] ? template[key].hide_remote : false,
|
||||||
hide_remote: template[key] ? template[key].hide_remote : false,
|
label: key,
|
||||||
label: key,
|
remote: template[key] ? template[key].remote : false,
|
||||||
remote: template[key] ? template[key].remote : false,
|
type: template[key] ? template[key].type : null,
|
||||||
type: template[key] ? template[key].type : null,
|
value:
|
||||||
value: (template[key] && (template[key].type === 'object')) ?
|
template[key] &&
|
||||||
config[key] :
|
(template[key].type === 'string_array' || template[key].type === 'object')
|
||||||
(template[key] && (template[key].type === 'string_array')) ?
|
? config[key]
|
||||||
config[key] :
|
: template[key] && template[key].type === 'host_list'
|
||||||
config[key].toString(),
|
? config[key]
|
||||||
};
|
: config[key].toString(),
|
||||||
})
|
};
|
||||||
.filter(i => {
|
})
|
||||||
let ret = template[i.label];
|
.filter((i) => {
|
||||||
if (ret && (template[i.label].type === 'object')) {
|
let ret = template[i.label];
|
||||||
objectList.push(i);
|
if (ret && template[i.label].type === 'object') {
|
||||||
ret = false;
|
objectList.push(i);
|
||||||
}
|
ret = false;
|
||||||
return ret;
|
}
|
||||||
});
|
return ret;
|
||||||
|
});
|
||||||
return {
|
return {
|
||||||
ObjectList: objectList,
|
ObjectList: objectList,
|
||||||
ItemList: itemList,
|
ItemList: itemList,
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
handleItemChanged = (target, idx) => {
|
handleItemChanged = (target, idx) => {
|
||||||
const itemList = [
|
const itemList = [...this.state.ItemList];
|
||||||
...this.state.ItemList
|
itemList[idx].value =
|
||||||
];
|
target.type === 'textarea'
|
||||||
itemList[idx].value = target.type === 'textarea' ? target.string_array : target.value.toString();
|
? target.string_array
|
||||||
|
: target.type === 'host_list'
|
||||||
|
? target.value
|
||||||
|
: target.value.toString();
|
||||||
this.setState({
|
this.setState({
|
||||||
ItemList: itemList
|
ItemList: itemList,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
handleObjectItemChanged = (target, name, idx) => {
|
handleObjectItemChanged = (target, name, idx) => {
|
||||||
const itemList = [
|
const itemList = [...this.state.ObjectLookup[name]];
|
||||||
...this.state.ObjectLookup[name]
|
|
||||||
];
|
|
||||||
const objectLookup = {
|
const objectLookup = {
|
||||||
...this.state.ObjectLookup,
|
...this.state.ObjectLookup,
|
||||||
};
|
};
|
||||||
|
|
||||||
itemList[idx].value = target.type === 'textarea' ? target.string_array : target.value.toString();
|
itemList[idx].value =
|
||||||
|
target.type === 'textarea'
|
||||||
|
? target.string_array
|
||||||
|
: target.type === 'host_list'
|
||||||
|
? target.value
|
||||||
|
: target.value.toString();
|
||||||
objectLookup[name] = itemList;
|
objectLookup[name] = itemList;
|
||||||
this.setState({
|
this.setState({
|
||||||
ObjectLookup: objectLookup,
|
ObjectLookup: objectLookup,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
onGetConfigReply = (event, arg) => {
|
onGetConfigReply = (_, arg) => {
|
||||||
if (arg.data.Success) {
|
if (arg.data.Success) {
|
||||||
const list = this.createItemList(arg.data.Config, this.state.Template);
|
const list = this.createItemList(arg.data.Config, this.state.Template);
|
||||||
const itemListCopy = JSON.parse(JSON.stringify(list.ItemList));
|
const itemListCopy = JSON.parse(JSON.stringify(list.ItemList));
|
||||||
@@ -161,8 +185,9 @@ class Configuration extends IPCContainer {
|
|||||||
objectLookup[obj.label] = list2.ItemList;
|
objectLookup[obj.label] = list2.ItemList;
|
||||||
}
|
}
|
||||||
|
|
||||||
const isRemoteMount = this.props.remoteSupported &&
|
const isRemoteMount =
|
||||||
JSON.parse(objectLookup['RemoteMount'].find(s => s.label === 'IsRemoteMount').value);
|
this.props.remoteSupported &&
|
||||||
|
JSON.parse(objectLookup['RemoteMount'].find((s) => s.label === 'IsRemoteMount').value);
|
||||||
if (isRemoteMount) {
|
if (isRemoteMount) {
|
||||||
for (const obj of list.ObjectList) {
|
for (const obj of list.ObjectList) {
|
||||||
if (obj.hide_remote) {
|
if (obj.hide_remote) {
|
||||||
@@ -172,32 +197,36 @@ class Configuration extends IPCContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const objectLookupCopy = JSON.parse(JSON.stringify(objectLookup));
|
const objectLookupCopy = JSON.parse(JSON.stringify(objectLookup));
|
||||||
this.setState({
|
this.setState(
|
||||||
IsRemoteMount: isRemoteMount,
|
{
|
||||||
ItemList: list.ItemList,
|
IsRemoteMount: isRemoteMount,
|
||||||
ObjectLookup: objectLookup,
|
ItemList: list.ItemList,
|
||||||
OriginalItemList: itemListCopy,
|
ObjectLookup: objectLookup,
|
||||||
OriginalObjectLookup: objectLookupCopy,
|
OriginalItemList: itemListCopy,
|
||||||
}, () => {
|
OriginalObjectLookup: objectLookupCopy,
|
||||||
|
},
|
||||||
});
|
() => {}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.props.notifyError(arg.data.Error);
|
this.props.notifyError(arg.data.Error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onGetConfigTemplateReply = (event, arg) => {
|
onGetConfigTemplateReply = (_, arg) => {
|
||||||
if (arg.data.Success) {
|
if (arg.data.Success) {
|
||||||
this.setState({
|
this.setState(
|
||||||
Template: arg.data.Template,
|
{
|
||||||
}, () => {
|
Template: arg.data.Template,
|
||||||
this.sendRequest(Constants.IPC_Get_Config, {
|
},
|
||||||
Provider: this.props.DisplayConfiguration,
|
() => {
|
||||||
Remote: this.props.DisplayRemoteConfiguration,
|
this.sendRequest(Constants.IPC_Get_Config, {
|
||||||
S3: this.props.DisplayS3Configuration,
|
Provider: this.props.DisplayConfiguration,
|
||||||
Version: this.props.version,
|
Remote: this.props.DisplayRemoteConfiguration,
|
||||||
});
|
S3: this.props.DisplayS3Configuration,
|
||||||
});
|
Version: this.props.version,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.props.notifyError(arg.data.Error, false, () => {
|
this.props.notifyError(arg.data.Error, false, () => {
|
||||||
if (this._isMounted) {
|
if (this._isMounted) {
|
||||||
@@ -212,77 +241,97 @@ class Configuration extends IPCContainer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
saveAndClose = () => {
|
saveAndClose = () => {
|
||||||
this.setState({
|
this.setState(
|
||||||
Saving: true,
|
{
|
||||||
}, () => {
|
Saving: true,
|
||||||
const changedItems = [];
|
},
|
||||||
for (const item of this.state.ChangedItems) {
|
() => {
|
||||||
changedItems.push({
|
let changedItems = this.state.ChangedItems.map((item) => {
|
||||||
Name: item.label,
|
return {
|
||||||
Value: item.type === 'string_array' ?
|
Name: item.label,
|
||||||
item.value.join(';') :
|
Value:
|
||||||
item.value,
|
item.type === 'string_array'
|
||||||
|
? item.value.join(';')
|
||||||
|
: item.type === 'host_list'
|
||||||
|
? JSON.stringify(item.value)
|
||||||
|
: item.value,
|
||||||
|
};
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if (this.state.ChangedObjectLookup) {
|
if (this.state.ChangedObjectLookup) {
|
||||||
for (const key of Object.keys(this.state.ChangedObjectLookup)) {
|
for (const key of Object.keys(this.state.ChangedObjectLookup)) {
|
||||||
for (const item of this.state.ChangedObjectLookup[key]) {
|
changedItems = changedItems.concat(
|
||||||
changedItems.push({
|
this.state.ChangedObjectLookup[key].map((item) => {
|
||||||
Name: key + '.' + item.label,
|
return {
|
||||||
Value: item.type === 'string_array' ?
|
Name: key + '.' + item.label,
|
||||||
item.value.join(';') :
|
Value:
|
||||||
item.value,
|
item.type === 'string_array'
|
||||||
});
|
? item.value.join(';')
|
||||||
|
: item.type === 'host_list'
|
||||||
|
? JSON.stringify(item.value)
|
||||||
|
: item.value,
|
||||||
|
};
|
||||||
|
})
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
this.sendRequest(Constants.IPC_Set_Config_Values, {
|
this.sendRequest(Constants.IPC_Set_Config_Values, {
|
||||||
Items: changedItems,
|
Items: changedItems,
|
||||||
Provider: this.props.DisplayConfiguration,
|
Provider: this.props.DisplayConfiguration,
|
||||||
Remote: this.props.DisplayRemoteConfiguration,
|
Remote: this.props.DisplayRemoteConfiguration,
|
||||||
S3: this.props.DisplayS3Configuration,
|
S3: this.props.DisplayS3Configuration,
|
||||||
Version: this.props.version,
|
Version: this.props.version,
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
showRemoteConfigItem = (item, itemList) => {
|
showRemoteConfigItem = (item, itemList) => {
|
||||||
if (item.advanced &&
|
if (
|
||||||
|
item.advanced &&
|
||||||
item.remote &&
|
item.remote &&
|
||||||
this.props.remoteSupported &&
|
this.props.remoteSupported &&
|
||||||
(item.label !== 'IsRemoteMount')) {
|
item.label !== 'IsRemoteMount'
|
||||||
const isRemoteMount = JSON.parse(itemList.find(s => s.label === 'IsRemoteMount').value);
|
) {
|
||||||
const enableRemoteMount = !isRemoteMount &&
|
const isRemoteMount = JSON.parse(itemList.find((s) => s.label === 'IsRemoteMount').value);
|
||||||
JSON.parse(itemList.find(s => s.label === 'EnableRemoteMount').value);
|
const enableRemoteMount =
|
||||||
return (item.label === 'RemoteHostNameOrIp') || (item.label === 'RemoteMaxConnections') ?
|
!isRemoteMount && JSON.parse(itemList.find((s) => s.label === 'EnableRemoteMount').value);
|
||||||
isRemoteMount :
|
return item.label === 'RemoteHostNameOrIp' || item.label === 'RemoteMaxConnections'
|
||||||
(item.label === 'RemoteReceiveTimeoutSeconds') || (item.label === 'RemoteSendTimeoutSeconds') || (item.label === 'RemotePort') || (item.label === 'RemoteToken') ?
|
? isRemoteMount
|
||||||
isRemoteMount || enableRemoteMount :
|
: item.label === 'RemoteReceiveTimeoutSeconds' ||
|
||||||
(item.label === 'EnableRemoteMount') ?
|
item.label === 'RemoteSendTimeoutSeconds' ||
|
||||||
!isRemoteMount :
|
item.label === 'RemotePort' ||
|
||||||
enableRemoteMount;
|
item.label === 'RemoteToken'
|
||||||
|
? isRemoteMount || enableRemoteMount
|
||||||
|
: item.label === 'EnableRemoteMount'
|
||||||
|
? !isRemoteMount
|
||||||
|
: enableRemoteMount;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let confirmSave = null;
|
let confirmSave = null;
|
||||||
if ((this.state.ChangedItems.length > 0) || this.state.ChangedObjectLookup) {
|
if (this.state.ChangedItems.length > 0 || this.state.ChangedObjectLookup) {
|
||||||
confirmSave = (
|
confirmSave = (
|
||||||
<Modal>
|
<Modal>
|
||||||
<Box dxStyle={{width: '40vw', padding: 'var(--default_spacing)'}}>
|
<Box dxStyle={{ width: '40vw', padding: 'var(--default_spacing)' }}>
|
||||||
<h1 style={{width: '100%', textAlign: 'center'}}>Save Changes?</h1>
|
<h1 style={{ width: '100%', textAlign: 'center' }}>Save Changes?</h1>
|
||||||
<table width='100%'>
|
<table width="100%">
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td align='center' width='50%'><Button clicked={this.saveAndClose}
|
<td align="center" width="50%">
|
||||||
disabled={this.state.Saving}>Yes</Button>
|
<Button clicked={this.saveAndClose} disabled={this.state.Saving}>
|
||||||
</td>
|
Yes
|
||||||
<td align='center' width='50%'><Button clicked={this.props.hideConfiguration}
|
</Button>
|
||||||
disabled={this.state.Saving}>No</Button></td>
|
</td>
|
||||||
</tr>
|
<td align="center" width="50%">
|
||||||
|
<Button clicked={this.props.hideConfiguration} disabled={this.state.Saving}>
|
||||||
|
No
|
||||||
|
</Button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -291,87 +340,98 @@ class Configuration extends IPCContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let autoFocus = true;
|
let autoFocus = true;
|
||||||
|
const getAutoFocus = () => {
|
||||||
|
return autoFocus;
|
||||||
|
};
|
||||||
|
const setAutoFocus = (value) => {
|
||||||
|
autoFocus = value;
|
||||||
|
};
|
||||||
|
|
||||||
let objectItems = [];
|
const objectItems = Object.keys(this.state.ObjectLookup).map((key) => {
|
||||||
for (const key of Object.keys(this.state.ObjectLookup)) {
|
return (
|
||||||
objectItems.push((
|
|
||||||
<div key={key}>
|
<div key={key}>
|
||||||
<h2>{key}</h2>
|
<h2>{key}</h2>
|
||||||
<div>
|
<div>
|
||||||
{
|
{this.state.ObjectLookup[key]
|
||||||
this.state.ObjectLookup[key].map((k, i) => {
|
.map((k, i) => {
|
||||||
const shouldFocus = autoFocus;
|
const shouldFocus = getAutoFocus();
|
||||||
autoFocus = false;
|
setAutoFocus(false);
|
||||||
return (
|
return !k.advanced ||
|
||||||
(!k.advanced || (this.state.ShowAdvanced && k.advanced && !k.remote) || this.showRemoteConfigItem(k, this.state.ObjectLookup[key])) ?
|
(this.state.ShowAdvanced && k.advanced && !k.remote) ||
|
||||||
<ConfigurationItem advanced={k.advanced}
|
this.showRemoteConfigItem(k, this.state.ObjectLookup[key]) ? (
|
||||||
autoFocus={shouldFocus}
|
<ConfigurationItem
|
||||||
changed={e => this.handleObjectItemChanged(e, key, i)}
|
advanced={k.advanced}
|
||||||
grouping={key}
|
autoFocus={shouldFocus}
|
||||||
items={this.state.Template[key].template[k.label].items}
|
changed={(e) => this.handleObjectItemChanged(e, key, i)}
|
||||||
key={i}
|
grouping={key}
|
||||||
label={k.label}
|
items={this.state.Template[key].template[k.label].items}
|
||||||
readOnly={this.state.IsRemoteMount && ((k.label === 'RemoteHostNameOrIp') || (k.label === 'RemotePort'))}
|
key={i}
|
||||||
template={this.state.Template[key].template[k.label]}
|
label={k.label}
|
||||||
value={k.value}/> :
|
readOnly={
|
||||||
null)
|
this.state.IsRemoteMount &&
|
||||||
|
(k.label === 'RemoteHostNameOrIp' || k.label === 'RemotePort')
|
||||||
|
}
|
||||||
|
template={this.state.Template[key].template[k.label]}
|
||||||
|
value={k.value}
|
||||||
|
/>
|
||||||
|
) : null;
|
||||||
})
|
})
|
||||||
}
|
.filter((i) => i !== null)}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
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
|
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
}).filter((i) => i !== null);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'Configuration'}>
|
<div className={'Configuration'}>
|
||||||
{confirmSave}
|
{confirmSave}
|
||||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
<Box dxDark dxStyle={{ padding: '5px' }}>
|
||||||
<div style={{
|
{createDismissDisplay(this.checkSaveRequired)}
|
||||||
float: 'right',
|
<h1 style={{ width: '100%', textAlign: 'center' }}>
|
||||||
margin: 0,
|
{(this.props.DisplayRemoteConfiguration
|
||||||
padding: 0,
|
? this.props.DisplayConfiguration.substr(6)
|
||||||
marginTop: '-4px',
|
: this.props.DisplayS3Configuration
|
||||||
boxSizing: 'border-box',
|
? this.props.DisplayConfiguration.substr(2)
|
||||||
display: 'block'
|
: this.props.DisplayConfiguration) + ' Configuration '}
|
||||||
}}>
|
|
||||||
<a href={'#'}
|
|
||||||
onClick={this.checkSaveRequired}
|
|
||||||
style={{cursor: 'pointer'}}>X</a>
|
|
||||||
</div>
|
|
||||||
<h1 style={{width: '100%', textAlign: 'center'}}>{(
|
|
||||||
this.props.DisplayRemoteConfiguration ?
|
|
||||||
this.props.DisplayConfiguration.substr(6) :
|
|
||||||
this.props.DisplayConfiguration) + ' Configuration '}
|
|
||||||
</h1>
|
</h1>
|
||||||
<div style={{overflowY: 'auto', height: '90%'}}>
|
<div style={{ overflowY: 'auto', height: '90%' }}>
|
||||||
{this.props.MState.Mounted && (configurationItems.length > 0) ? <Button
|
{this.props.MState.Mounted && configurationItems.length > 0 ? (
|
||||||
buttonStyles={{width: 'auto', height: 'auto', marginLeft: 'auto', marginRight: '4px'}}
|
<Button
|
||||||
clicked={() => {
|
buttonStyles={{
|
||||||
this.props.displayPinnedManager(true);
|
width: 'auto',
|
||||||
return false;
|
height: 'auto',
|
||||||
}}> Pinned File Manager... </Button> : null}
|
marginLeft: 'auto',
|
||||||
<div style={{marginBottom: '4px'}}/>
|
marginRight: '4px',
|
||||||
|
}}
|
||||||
|
clicked={() => {
|
||||||
|
this.props.displayPinnedManager(true);
|
||||||
|
return false;
|
||||||
|
}}>
|
||||||
|
Pinned File Manager...
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
<div style={{ marginBottom: '4px' }} />
|
||||||
{objectItems}
|
{objectItems}
|
||||||
{(configurationItems.length > 0) ? <h2>Settings</h2> : null}
|
{configurationItems.length > 0 ? <h2>Settings</h2> : null}
|
||||||
{configurationItems}
|
{configurationItems}
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
@@ -380,22 +440,33 @@ class Configuration extends IPCContainer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = (state) => {
|
||||||
return {
|
return {
|
||||||
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
||||||
DisplayRemoteConfiguration: state.mounts.DisplayRemoteConfiguration,
|
DisplayRemoteConfiguration: state.mounts.DisplayRemoteConfiguration,
|
||||||
DisplayS3Configuration: state.mounts.DisplayS3Configuration,
|
DisplayS3Configuration: state.mounts.DisplayS3Configuration,
|
||||||
MState: state.mounts.MountState[state.mounts.DisplayConfiguration],
|
MState: state.mounts.MountState[state.mounts.DisplayConfiguration],
|
||||||
Platform: state.common.Platform,
|
Platform: state.common.Platform,
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
displayPinnedManager: display => dispatch(displayPinnedManager(display)),
|
displayPinnedManager: (display) => dispatch(displayPinnedManager(display)),
|
||||||
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
||||||
hideConfiguration: () => dispatch(displayConfiguration(null, false)),
|
hideConfiguration: () => dispatch(displayConfiguration(null, false)),
|
||||||
}
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
Configuration.propTypes = {
|
||||||
|
displayPinnedManager: PropTypes.func.isRequired,
|
||||||
|
DisplayConfiguration: PropTypes.string.isRequired,
|
||||||
|
hideConfiguration: PropTypes.func.isRequired,
|
||||||
|
remoteSupported: PropTypes.bool.isRequired,
|
||||||
|
notifyError: PropTypes.func.isRequired,
|
||||||
|
MState: PropTypes.object.isRequired,
|
||||||
|
Platform: PropTypes.string.isRequired,
|
||||||
|
version: PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(Configuration);
|
export default connect(mapStateToProps, mapDispatchToProps)(Configuration);
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ textarea.ConfigurationItemInput {
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
resize: none;
|
resize: none;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
overflow:-moz-scrollbars-horizontal;
|
overflow: -moz-scrollbars-horizontal;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,31 +1,23 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './ConfigurationItem.css';
|
import './ConfigurationItem.css';
|
||||||
import CheckBox from '../../../components/UI/CheckBox/CheckBox';
|
import CheckBox from '../../../components/UI/CheckBox/CheckBox';
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import {faInfoCircle} from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
|
||||||
import {
|
|
||||||
notifyError,
|
|
||||||
notifyInfo
|
|
||||||
} from '../../../redux/actions/error_actions';
|
|
||||||
import settings from '../../../assets/settings';
|
|
||||||
import DropDown from '../../../components/UI/DropDown/DropDown';
|
import DropDown from '../../../components/UI/DropDown/DropDown';
|
||||||
|
import HostList from '../../HostList/HostList';
|
||||||
import Password from '../../../containers/UI/Password/Password';
|
import Password from '../../../containers/UI/Password/Password';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import settings from '../../../assets/settings';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { faInfoCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { notifyError, notifyInfo } from '../../../redux/actions/error_actions';
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const ConfigurationItem = (props) => {
|
||||||
return {
|
|
||||||
notifyError: msg => dispatch(notifyError(msg)),
|
|
||||||
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(null, mapDispatchToProps)(props => {
|
|
||||||
const handleChanged = (e) => {
|
const handleChanged = (e) => {
|
||||||
const target = e.target;
|
const target = e.target;
|
||||||
if (target.type === 'checkbox') {
|
if (target.type === 'checkbox') {
|
||||||
target.value = e.target.checked ? 'true' : 'false';
|
target.value = e.target.checked ? 'true' : 'false';
|
||||||
} else if (target.type === 'textarea') {
|
} else if (target.type === 'textarea') {
|
||||||
e.target.string_array = String(e.target.value).replace(/\r\n/g,'\n').split('\n');
|
e.target.string_array = String(e.target.value).replace(/\r\n/g, '\n').split('\n');
|
||||||
}
|
}
|
||||||
props.changed(target);
|
props.changed(target);
|
||||||
};
|
};
|
||||||
@@ -37,137 +29,204 @@ export default connect(null, mapDispatchToProps)(props => {
|
|||||||
props.notifyInfo(props.label, description);
|
props.notifyInfo(props.label, description);
|
||||||
};
|
};
|
||||||
|
|
||||||
infoDisplay = <a href={'#'}
|
infoDisplay = (
|
||||||
className={'ConfigurationInfo'}
|
<a
|
||||||
onClick={()=>{displayInfo(); return false;}}><FontAwesomeIcon icon={faInfoCircle}/></a>;
|
href={'#'}
|
||||||
|
className={'ConfigurationInfo'}
|
||||||
|
onClick={() => {
|
||||||
|
displayInfo();
|
||||||
|
return false;
|
||||||
|
}}>
|
||||||
|
<FontAwesomeIcon icon={faInfoCircle} />
|
||||||
|
</a>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let data;
|
let data;
|
||||||
switch (props.template.type) {
|
switch (props.template.type) {
|
||||||
case 'bool':
|
case 'bool':
|
||||||
data = <CheckBox changed={handleChanged}
|
data = (
|
||||||
checked={props.value}
|
<CheckBox
|
||||||
disabled={props.readOnly}
|
changed={handleChanged}
|
||||||
autoFocus={props.autoFocus}/>;
|
checked={props.value}
|
||||||
break;
|
disabled={props.readOnly}
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'double':
|
case 'double':
|
||||||
data = <input min={0.0}
|
data = (
|
||||||
autoFocus={props.autoFocus}
|
<input
|
||||||
disabled={props.readOnly}
|
min={0.0}
|
||||||
onChange={e=>handleChanged(e)}
|
autoFocus={props.autoFocus}
|
||||||
step={'0.01'}
|
disabled={props.readOnly}
|
||||||
className={'ConfigurationItemInput'}
|
onChange={(e) => handleChanged(e)}
|
||||||
type={'number'}
|
step={'0.01'}
|
||||||
value={parseFloat(props.value).toFixed(2)}/>;
|
className={'ConfigurationItemInput'}
|
||||||
break;
|
type={'number'}
|
||||||
|
value={parseFloat(props.value).toFixed(2)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'host_list':
|
||||||
|
data = (
|
||||||
|
<HostList
|
||||||
|
autoFocus={props.autoFocus}
|
||||||
|
disabled={props.readOnly}
|
||||||
|
onChange={(items) =>
|
||||||
|
handleChanged({
|
||||||
|
target: {
|
||||||
|
type: 'host_list',
|
||||||
|
value: items,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
type={props.template.subtype}
|
||||||
|
value={props.value}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'list':
|
case 'list':
|
||||||
data = <DropDown alt
|
data = (
|
||||||
auto
|
<DropDown
|
||||||
autoFocus={props.autoFocus}
|
alt
|
||||||
changed={handleChanged}
|
auto
|
||||||
disabled={props.readOnly}
|
autoFocus={props.autoFocus}
|
||||||
items={props.items}
|
changed={handleChanged}
|
||||||
selected={props.value} />;
|
disabled={props.readOnly}
|
||||||
break;
|
items={props.items}
|
||||||
|
selected={props.value}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'string':
|
case 'string':
|
||||||
if (props.template.subtype === 'password') {
|
if (props.template.subtype === 'password') {
|
||||||
data = (
|
data = (
|
||||||
<Password autoFocus={props.autoFocus}
|
<Password
|
||||||
changed={s => handleChanged({
|
autoFocus={props.autoFocus}
|
||||||
target: {
|
changed={(s) =>
|
||||||
type: 'password',
|
handleChanged({
|
||||||
value: s,
|
target: {
|
||||||
},
|
type: 'password',
|
||||||
})}
|
value: s,
|
||||||
disabled={props.readOnly}
|
},
|
||||||
mismatchHandler={() => props.notifyError('Passwords do not match')}
|
})
|
||||||
value={props.value} />
|
}
|
||||||
|
disabled={props.readOnly}
|
||||||
|
mismatchHandler={() => props.notifyError('Passwords do not match')}
|
||||||
|
value={props.value}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
data = (
|
data = (
|
||||||
<input onChange={e => handleChanged(e)}
|
<input
|
||||||
autoFocus={props.autoFocus}
|
onChange={(e) => handleChanged(e)}
|
||||||
className={'ConfigurationItemInput'}
|
autoFocus={props.autoFocus}
|
||||||
disabled={props.readOnly}
|
className={'ConfigurationItemInput'}
|
||||||
type={'text'}
|
disabled={props.readOnly}
|
||||||
value={props.value}/>
|
type={'text'}
|
||||||
|
value={props.value}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'uint8':
|
case 'uint8':
|
||||||
data = <input max={255}
|
data = (
|
||||||
min={0}
|
<input
|
||||||
autoFocus={props.autoFocus}
|
max={255}
|
||||||
disabled={props.readOnly}
|
min={0}
|
||||||
onChange={e=>handleChanged(e)}
|
autoFocus={props.autoFocus}
|
||||||
className={'ConfigurationItemInput'}
|
disabled={props.readOnly}
|
||||||
type={'number'}
|
onChange={(e) => handleChanged(e)}
|
||||||
value={props.value}/>;
|
className={'ConfigurationItemInput'}
|
||||||
break;
|
type={'number'}
|
||||||
|
value={props.value}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'uint16':
|
case 'uint16':
|
||||||
data = <input max={65535}
|
data = (
|
||||||
min={0}
|
<input
|
||||||
autoFocus={props.autoFocus}
|
max={65535}
|
||||||
disabled={props.readOnly}
|
min={0}
|
||||||
onChange={e=>handleChanged(e)}
|
autoFocus={props.autoFocus}
|
||||||
className={'ConfigurationItemInput'}
|
disabled={props.readOnly}
|
||||||
type={'number'}
|
onChange={(e) => handleChanged(e)}
|
||||||
value={props.value}/>;
|
className={'ConfigurationItemInput'}
|
||||||
break;
|
type={'number'}
|
||||||
|
value={props.value}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'uint32':
|
case 'uint32':
|
||||||
data = <input max={4294967295}
|
data = (
|
||||||
min={0}
|
<input
|
||||||
autoFocus={props.autoFocus}
|
max={4294967295}
|
||||||
disabled={props.readOnly}
|
min={0}
|
||||||
onChange={e=>handleChanged(e)}
|
autoFocus={props.autoFocus}
|
||||||
className={'ConfigurationItemInput'}
|
disabled={props.readOnly}
|
||||||
type={'number'}
|
onChange={(e) => handleChanged(e)}
|
||||||
value={props.value}/>;
|
className={'ConfigurationItemInput'}
|
||||||
break;
|
type={'number'}
|
||||||
|
value={props.value}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'uint64':
|
case 'uint64':
|
||||||
data = <input max={18446744073709551615}
|
data = (
|
||||||
min={0}
|
<input
|
||||||
autoFocus={props.autoFocus}
|
max={18446744073709551615}
|
||||||
disabled={props.readOnly}
|
min={0}
|
||||||
onChange={e=>handleChanged(e)}
|
autoFocus={props.autoFocus}
|
||||||
className={'ConfigurationItemInput'}
|
disabled={props.readOnly}
|
||||||
type={'number'}
|
onChange={(e) => handleChanged(e)}
|
||||||
value={props.value}/>;
|
className={'ConfigurationItemInput'}
|
||||||
break;
|
type={'number'}
|
||||||
|
value={props.value}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
|
||||||
case 'string_array':
|
case 'string_array':
|
||||||
data = (
|
data = (
|
||||||
<textarea autoFocus={props.autoFocus}
|
<textarea
|
||||||
disabled={props.readOnly}
|
autoFocus={props.autoFocus}
|
||||||
rows={4}
|
disabled={props.readOnly}
|
||||||
cols={36}
|
rows={4}
|
||||||
onChange={e=>handleChanged(e)}
|
cols={36}
|
||||||
className={'ConfigurationItemInput'}
|
onChange={(e) => handleChanged(e)}
|
||||||
value={props.value.join('\n')} />
|
className={'ConfigurationItemInput'}
|
||||||
|
value={props.value.join('\n')}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'password':
|
case 'password':
|
||||||
data = (
|
data = (
|
||||||
<Password autoFocus={props.autoFocus}
|
<Password
|
||||||
changed={s => handleChanged({
|
autoFocus={props.autoFocus}
|
||||||
target: {
|
changed={(s) =>
|
||||||
type: 'password',
|
handleChanged({
|
||||||
value: s,
|
target: {
|
||||||
},
|
type: 'password',
|
||||||
})}
|
value: s,
|
||||||
disabled={props.readOnly}
|
},
|
||||||
mismatchHandler={() => props.notifyError('Passwords do not match')}
|
})
|
||||||
value={props.value} />
|
}
|
||||||
|
disabled={props.readOnly}
|
||||||
|
mismatchHandler={() => props.notifyError('Passwords do not match')}
|
||||||
|
value={props.value}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
data = <div>{props.value}</div>;
|
data = <div>{props.value}</div>;
|
||||||
@@ -175,17 +234,44 @@ export default connect(null, mapDispatchToProps)(props => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={'ConfigurationItem'}>
|
<div className={'ConfigurationItem'}>
|
||||||
<table cellPadding='2'
|
<table cellPadding="2" width="100%">
|
||||||
width='100%'>
|
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
{infoDisplay ?
|
{infoDisplay ? (
|
||||||
<td width='100%' valign={'top'}>{infoDisplay} {props.label}</td> :
|
<td width="100%" valign={'top'}>
|
||||||
<td width='100%' valign={'top'}>{props.label}</td>}
|
{infoDisplay} {props.label}
|
||||||
|
</td>
|
||||||
|
) : (
|
||||||
|
<td width="100%" valign={'top'}>
|
||||||
|
{props.label}
|
||||||
|
</td>
|
||||||
|
)}
|
||||||
<td>{data}</td>
|
<td>{data}</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
notifyError: (msg) => dispatch(notifyError(msg)),
|
||||||
|
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
ConfigurationItem.propTypes = {
|
||||||
|
autoFocus: PropTypes.bool,
|
||||||
|
changed: PropTypes.func.isRequired,
|
||||||
|
grouping: PropTypes.string,
|
||||||
|
items: PropTypes.array,
|
||||||
|
label: PropTypes.string,
|
||||||
|
notifyError: PropTypes.func.isRequired,
|
||||||
|
notifyInfo: PropTypes.func.isRequired,
|
||||||
|
readOnly: PropTypes.bool,
|
||||||
|
template: PropTypes.object.isRequired,
|
||||||
|
value: PropTypes.oneOfType([PropTypes.array, PropTypes.string, PropTypes.number]),
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps)(ConfigurationItem);
|
||||||
|
|||||||
0
src/containers/HostList/Host/Host.css
Normal file
0
src/containers/HostList/Host/Host.css
Normal file
77
src/containers/HostList/Host/Host.js
Normal file
77
src/containers/HostList/Host/Host.js
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { addEditHostAction } from '../../../redux/actions/host_actions';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { faTrashAlt, faEdit } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
editHost: (host_list, host_data, cb) =>
|
||||||
|
dispatch(addEditHostAction.display(true, cb, { host_list, host_data })),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const Host = ({ allowDelete, editHost, host_list, host_data, onChange, onDelete }) => {
|
||||||
|
const handleEditHost = () => {
|
||||||
|
editHost(host_list, host_data, (changed, { host_data }) => {
|
||||||
|
if (changed) {
|
||||||
|
onChange(host_data);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const getHostDisplay = () => {
|
||||||
|
return (
|
||||||
|
host_data.HostNameOrIp +
|
||||||
|
((host_data.Protocol === 'http' && host_data.ApiPort === 80) ||
|
||||||
|
(host_data.Protocol === 'https' && host_data.ApiPort === 443)
|
||||||
|
? ''
|
||||||
|
: ':' + host_data.ApiPort)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const premium = host_data.AuthURL && host_data.AuthUser;
|
||||||
|
return (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'row' }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 0,
|
||||||
|
paddingRight: 'calc(var(--default_spacing) * 1.25)',
|
||||||
|
}}>
|
||||||
|
<a href={'#'} onClick={handleEditHost}>
|
||||||
|
<FontAwesomeIcon icon={faEdit} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
{allowDelete ? (
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
flex: 0,
|
||||||
|
paddingRight: 'calc(var(--default_spacing) * 1.25)',
|
||||||
|
}}>
|
||||||
|
<a href={'#'} onClick={onDelete}>
|
||||||
|
<FontAwesomeIcon icon={faTrashAlt} />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
) : null}
|
||||||
|
{premium ? (
|
||||||
|
<p>
|
||||||
|
<b>{'(premium) ' + getHostDisplay()}</b>
|
||||||
|
</p>
|
||||||
|
) : (
|
||||||
|
<p>{getHostDisplay()}</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
Host.propTypes = {
|
||||||
|
allowDelete: PropTypes.bool.isRequired,
|
||||||
|
editHost: PropTypes.func.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
onDelete: PropTypes.func.isRequired,
|
||||||
|
host_data: PropTypes.object.isRequired,
|
||||||
|
host_list: PropTypes.array.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps)(Host);
|
||||||
0
src/containers/HostList/HostList.css
Normal file
0
src/containers/HostList/HostList.css
Normal file
119
src/containers/HostList/HostList.js
Normal file
119
src/containers/HostList/HostList.js
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import './HostList.css';
|
||||||
|
import Host from './Host/Host';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
import { Component } from 'react';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { confirmYesNoAction } from '../../redux/actions/common_actions';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { addEditHostAction } from '../../redux/actions/host_actions';
|
||||||
|
import { faPlusCircle } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
|
class HostList extends Component {
|
||||||
|
state = {
|
||||||
|
items: [],
|
||||||
|
};
|
||||||
|
// autoFocus={props.autoFocus}
|
||||||
|
// disabled={props.readOnly}
|
||||||
|
// type={props.template.subtype}
|
||||||
|
|
||||||
|
componentDidMount() {
|
||||||
|
this.setState({ items: this.props.value });
|
||||||
|
}
|
||||||
|
|
||||||
|
componentWillUnmount() {}
|
||||||
|
|
||||||
|
handleAddHost = () => {
|
||||||
|
this.props.AddHost(this.state.items, (changed, { host_data }) => {
|
||||||
|
if (changed) {
|
||||||
|
const items = [...this.state.items, host_data];
|
||||||
|
this.updateItems(items);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
handleChanged = (host_data, index) => {
|
||||||
|
const items = [...this.state.items];
|
||||||
|
items[index] = host_data;
|
||||||
|
this.updateItems(items);
|
||||||
|
};
|
||||||
|
|
||||||
|
handleDeleted = (index) => {
|
||||||
|
this.props.ConfirmRemoveHost(
|
||||||
|
'Delete [' + this.state.items[index].HostNameOrIp + ']?',
|
||||||
|
(confirmed) => {
|
||||||
|
if (confirmed) {
|
||||||
|
const items = [...this.state.items];
|
||||||
|
items.splice(index, 1);
|
||||||
|
this.updateItems(items);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
updateItems = (items) => {
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
items,
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.props.onChange(this.state.items);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
let idx = 0;
|
||||||
|
return (
|
||||||
|
<div style={{ display: 'flex', flexDirection: 'column' }}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
maxHeight: '80px',
|
||||||
|
maxWidth: '260px',
|
||||||
|
minWidth: '260px',
|
||||||
|
backgroundColor: 'var(--control_background)',
|
||||||
|
padding: 'var(--default_spacing)',
|
||||||
|
overflowY: 'scroll',
|
||||||
|
}}>
|
||||||
|
{this.state.items.map((v, index) => {
|
||||||
|
return (
|
||||||
|
<Host
|
||||||
|
key={idx++}
|
||||||
|
onChange={(host_data) => this.handleChanged(host_data, index)}
|
||||||
|
onDelete={() => this.handleDeleted(index)}
|
||||||
|
allowDelete={this.state.items.length > 1}
|
||||||
|
host_data={v}
|
||||||
|
host_list={this.state.items.filter((i) => i !== v)}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</div>
|
||||||
|
<a
|
||||||
|
href={'#'}
|
||||||
|
onClick={this.handleAddHost}
|
||||||
|
style={{
|
||||||
|
marginTop: 'var(--default_spacing)',
|
||||||
|
}}>
|
||||||
|
<FontAwesomeIcon icon={faPlusCircle} />
|
||||||
|
<b>{' Add Portal '}</b>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
AddHost: (host_list, cb) => dispatch(addEditHostAction.display(true, cb, { host_list })),
|
||||||
|
ConfirmRemoveHost: (title, cb) => dispatch(confirmYesNoAction.display(true, cb, { title })),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
HostList.propTypes = {
|
||||||
|
AddHost: PropTypes.func.isRequired,
|
||||||
|
ConfirmRemoveHost: PropTypes.func.isRequired,
|
||||||
|
onChange: PropTypes.func.isRequired,
|
||||||
|
value: PropTypes.array.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(null, mapDispatchToProps)(HostList);
|
||||||
@@ -1,22 +1,22 @@
|
|||||||
import {Component} from 'react';
|
import { Component } from 'react';
|
||||||
import {getIPCRenderer} from '../../utils';
|
import { getIPCRenderer } from '../../utils.jsx';
|
||||||
|
|
||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
|
|
||||||
export default class IPCContainer extends Component {
|
class IPCContainer extends Component {
|
||||||
handlerList = {};
|
handlerList = {};
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
for (let name in this.handlerList) {
|
for (let name in this.handlerList) {
|
||||||
if (this.handlerList.hasOwnProperty(name)) {
|
if (Object.prototype.hasOwnProperty.call(this.handlerList, name)) {
|
||||||
ipcRenderer.removeListener(name, this.handlerList[name]);
|
ipcRenderer.removeListener(name, this.handlerList[name]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this.handlerList = {};
|
this.handlerList = {};
|
||||||
};
|
}
|
||||||
|
|
||||||
sendRequest = (name, data) => {
|
sendRequest = (name, data) => {
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
@@ -41,5 +41,6 @@ export default class IPCContainer extends Component {
|
|||||||
ipcRenderer.on(name, callback);
|
ipcRenderer.on(name, callback);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
}
|
||||||
|
|
||||||
};
|
export default IPCContainer;
|
||||||
|
|||||||
@@ -1,46 +1,26 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './MountItem.css';
|
import './MountItem.css';
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import DropDown from '../../../components/UI/DropDown/DropDown';
|
|
||||||
import Button from '../../../components/UI/Button/Button';
|
import Button from '../../../components/UI/Button/Button';
|
||||||
import Loader from 'react-loader-spinner';
|
import CheckBox from '../../../components/UI/CheckBox/CheckBox';
|
||||||
import Text from '../../../components/UI/Text/Text';
|
import DropDown from '../../../components/UI/DropDown/DropDown';
|
||||||
import Grid from '../../../components/UI/Grid/Grid';
|
import Grid from '../../../components/UI/Grid/Grid';
|
||||||
import configureImage from '../../../assets/images/configure.png';
|
import Loader from 'react-loader-spinner';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import RootElem from '../../../components/UI/RootElem/RootElem';
|
import RootElem from '../../../components/UI/RootElem/RootElem';
|
||||||
|
import Text from '../../../components/UI/Text/Text';
|
||||||
|
import configureImage from '../../../assets/images/configure.png';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
import {
|
import {
|
||||||
displayConfiguration,
|
displayConfiguration,
|
||||||
removeMount,
|
removeMount,
|
||||||
setProviderState
|
setProviderState,
|
||||||
} from '../../../redux/actions/mount_actions';
|
} from '../../../redux/actions/mount_actions';
|
||||||
import {
|
import { displaySkynetExport, displaySkynetImport } from '../../../redux/actions/skynet_actions';
|
||||||
displaySkynetExport,
|
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
displaySkynetImport,
|
|
||||||
} from '../../../redux/actions/skynet_actions'
|
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
|
||||||
import { faTrashAlt} from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import CheckBox from '../../../components/UI/CheckBox/CheckBox';
|
|
||||||
|
|
||||||
const mapStateToProps = (state, ownProps) => {
|
const MountItem = (props) => {
|
||||||
return {
|
const handleAutoMountChanged = (e) => {
|
||||||
MState: state.mounts.MountState[ownProps.provider],
|
|
||||||
Platform: state.common.Platform,
|
|
||||||
PState: state.mounts.ProviderState[ownProps.provider]
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
displayConfiguration: (provider, remote, s3) => dispatch(displayConfiguration(provider, remote, s3)),
|
|
||||||
displaySkynetExport: display => dispatch(displaySkynetExport(display)),
|
|
||||||
displaySkynetImport: display => dispatch(displaySkynetImport(display)),
|
|
||||||
removeMount: provider => dispatch(removeMount(provider)),
|
|
||||||
setProviderState: (provider, state) => dispatch(setProviderState(provider, state)),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|
||||||
const handleAutoMountChanged = e => {
|
|
||||||
const state = {
|
const state = {
|
||||||
...props.PState,
|
...props.PState,
|
||||||
AutoMount: e.target.checked,
|
AutoMount: e.target.checked,
|
||||||
@@ -48,7 +28,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
props.setProviderState(props.provider, state);
|
props.setProviderState(props.provider, state);
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleAutoRestartChanged = e => {
|
const handleAutoRestartChanged = (e) => {
|
||||||
const state = {
|
const state = {
|
||||||
...props.PState,
|
...props.PState,
|
||||||
AutoRestart: e.target.checked,
|
AutoRestart: e.target.checked,
|
||||||
@@ -57,18 +37,23 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let secondRow = 6;
|
let secondRow = 6;
|
||||||
const pointer = {cursor: props.MState.AllowMount ? 'pointer' : 'no-drop'};
|
const pointer = { cursor: props.MState.AllowMount ? 'pointer' : 'no-drop' };
|
||||||
const configButton = (
|
const configButton = (
|
||||||
<RootElem colSpan={4}
|
<RootElem colSpan={4} rowSpan={6}>
|
||||||
rowSpan={6}>
|
<img
|
||||||
<img alt=''
|
alt=""
|
||||||
height={'16px'}
|
height={'16px'}
|
||||||
onClick={props.MState.AllowMount ? () => props.displayConfiguration(props.provider, props.remote, props.s3) : e => {
|
onClick={
|
||||||
e.preventDefault();
|
props.MState.AllowMount
|
||||||
}}
|
? () => props.displayConfiguration(props.provider, props.remote, props.s3)
|
||||||
src={configureImage}
|
: (e) => {
|
||||||
style={{padding: 0, border: 0, margin: 0, ...pointer}}
|
e.preventDefault();
|
||||||
width={'16px'}/>
|
}
|
||||||
|
}
|
||||||
|
src={configureImage}
|
||||||
|
style={{ padding: 0, border: 0, margin: 0, ...pointer }}
|
||||||
|
width={'16px'}
|
||||||
|
/>
|
||||||
</RootElem>
|
</RootElem>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -77,80 +62,95 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
if (props.Platform === 'win32') {
|
if (props.Platform === 'win32') {
|
||||||
inputColumnSpan = 20;
|
inputColumnSpan = 20;
|
||||||
const index = props.MState.DriveLetters.indexOf(props.PState.MountLocation);
|
const index = props.MState.DriveLetters.indexOf(props.PState.MountLocation);
|
||||||
inputControls = <DropDown changed={props.changed}
|
inputControls = (
|
||||||
colSpan={inputColumnSpan}
|
<DropDown
|
||||||
disabled={!props.MState.AllowMount || props.MState.Mounted}
|
changed={props.changed}
|
||||||
items={props.MState.DriveLetters}
|
colSpan={inputColumnSpan}
|
||||||
row={secondRow}
|
disabled={!props.MState.AllowMount || props.MState.Mounted}
|
||||||
rowSpan={7}
|
items={props.MState.DriveLetters}
|
||||||
selected={index >= 0 ? props.PState.MountLocation : ''}/>;
|
row={secondRow}
|
||||||
|
rowSpan={7}
|
||||||
|
selected={index >= 0 ? props.PState.MountLocation : ''}
|
||||||
|
/>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
inputColumnSpan = 64;
|
inputColumnSpan = 64;
|
||||||
inputControls = [];
|
inputControls = [];
|
||||||
let key = 0;
|
let key = 0;
|
||||||
inputControls.push((
|
inputControls.push(
|
||||||
<RootElem colSpan={inputColumnSpan - 8}
|
<RootElem colSpan={inputColumnSpan - 8} key={'i' + key++} row={secondRow} rowSpan={7}>
|
||||||
key={'i' + key++}
|
<input
|
||||||
row={secondRow}
|
disabled={!props.MState.AllowMount || props.MState.Mounted}
|
||||||
rowSpan={7}>
|
maxLength={4096}
|
||||||
<input disabled={!props.MState.AllowMount || props.MState.Mounted}
|
onChange={props.changed}
|
||||||
maxLength={4096}
|
size={4096}
|
||||||
onChange={props.changed}
|
className={'MountItemInput'}
|
||||||
size={4096}
|
type={'text'}
|
||||||
className={'MountItemInput'}
|
value={props.PState.MountLocation}
|
||||||
type={'text'}
|
/>
|
||||||
value={props.PState.MountLocation}/>
|
|
||||||
</RootElem>
|
</RootElem>
|
||||||
));
|
);
|
||||||
inputControls.push((
|
inputControls.push(
|
||||||
<Button clicked={()=>props.browseClicked(props.provider, props.PState.MountLocation)}
|
<Button
|
||||||
col={inputColumnSpan - 7}
|
clicked={() => props.browseClicked(props.provider, props.PState.MountLocation)}
|
||||||
colSpan={7}
|
col={inputColumnSpan - 7}
|
||||||
disabled={props.MState.Mounted || !props.MState.AllowMount}
|
colSpan={7}
|
||||||
key={'b' + key++}
|
disabled={props.MState.Mounted || !props.MState.AllowMount}
|
||||||
row={secondRow}
|
key={'b' + key++}
|
||||||
rowSpan={7}>...</Button>
|
row={secondRow}
|
||||||
));
|
rowSpan={7}>
|
||||||
|
...
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const buttonDisplay = props.MState.AllowMount ?
|
const buttonDisplay = props.MState.AllowMount ? (
|
||||||
(props.MState.Mounted ? 'Unmount' : 'Mount') :
|
props.MState.Mounted ? (
|
||||||
<Loader color={'var(--heading_text_color)'}
|
'Unmount'
|
||||||
height={19}
|
) : (
|
||||||
type='Circles'
|
'Mount'
|
||||||
width={19}/>;
|
)
|
||||||
|
) : (
|
||||||
|
<Loader color={'var(--heading_text_color)'} height={19} type="Circles" width={19} />
|
||||||
|
);
|
||||||
|
|
||||||
const actionsDisplay = (
|
const actionsDisplay = (
|
||||||
<Button
|
<Button
|
||||||
clicked={() => props.clicked(props.provider, props.remote, props.s3, !props.MState.Mounted, props.PState.MountLocation)}
|
clicked={() =>
|
||||||
|
props.clicked(
|
||||||
|
props.provider,
|
||||||
|
props.remote,
|
||||||
|
props.s3,
|
||||||
|
!props.MState.Mounted,
|
||||||
|
props.PState.MountLocation
|
||||||
|
)
|
||||||
|
}
|
||||||
col={inputColumnSpan + 2}
|
col={inputColumnSpan + 2}
|
||||||
colSpan={21}
|
colSpan={21}
|
||||||
disabled={!props.MState.AllowMount}
|
disabled={!props.MState.AllowMount}
|
||||||
row={secondRow}
|
row={secondRow}
|
||||||
rowSpan={7}>
|
rowSpan={7}>
|
||||||
{buttonDisplay}
|
{buttonDisplay}
|
||||||
</Button>);
|
</Button>
|
||||||
|
);
|
||||||
|
|
||||||
const autoMountControl = (
|
const autoMountControl = (
|
||||||
<RootElem col={inputColumnSpan + 24}
|
<RootElem col={inputColumnSpan + 24} colSpan={28} row={secondRow} rowSpan={7}>
|
||||||
colSpan={28}
|
<CheckBox
|
||||||
row={secondRow}
|
changed={handleAutoMountChanged}
|
||||||
rowSpan={7}>
|
checked={props.PState.AutoMount}
|
||||||
<CheckBox changed={handleAutoMountChanged}
|
label={'Auto-mount'}
|
||||||
checked={props.PState.AutoMount}
|
/>
|
||||||
label={'Auto-mount'}/>
|
|
||||||
</RootElem>
|
</RootElem>
|
||||||
);
|
);
|
||||||
|
|
||||||
const autoRestartControl = (
|
const autoRestartControl = (
|
||||||
<RootElem col={inputColumnSpan + 24 + 28}
|
<RootElem col={inputColumnSpan + 24 + 28} colSpan={24} row={secondRow} rowSpan={7}>
|
||||||
colSpan={24}
|
<CheckBox
|
||||||
row={secondRow}
|
changed={handleAutoRestartChanged}
|
||||||
rowSpan={7}>
|
checked={props.PState.AutoRestart}
|
||||||
<CheckBox changed={handleAutoRestartChanged}
|
label={'Restart'}
|
||||||
checked={props.PState.AutoRestart}
|
/>
|
||||||
label={'Restart'}/>
|
|
||||||
</RootElem>
|
</RootElem>
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -158,7 +158,7 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
if (props.allowRemove) {
|
if (props.allowRemove) {
|
||||||
const removeDisabled = !props.MState.AllowMount || props.MState.Mounted;
|
const removeDisabled = !props.MState.AllowMount || props.MState.Mounted;
|
||||||
const removeStyle = {
|
const removeStyle = {
|
||||||
cursor: removeDisabled ? 'no-drop' : 'pointer'
|
cursor: removeDisabled ? 'no-drop' : 'pointer',
|
||||||
};
|
};
|
||||||
const handleRemoveMount = () => {
|
const handleRemoveMount = () => {
|
||||||
if (!removeDisabled) {
|
if (!removeDisabled) {
|
||||||
@@ -166,17 +166,15 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
removeControl = (
|
removeControl = (
|
||||||
<RootElem col={dimensions=>dimensions.columns - 6}
|
<RootElem col={(dimensions) => dimensions.columns - 6} row={secondRow + 3}>
|
||||||
row={secondRow + 3}>
|
<a href={'#'} onClick={handleRemoveMount} style={removeStyle}>
|
||||||
<a href={'#'}
|
<FontAwesomeIcon icon={faTrashAlt} />
|
||||||
onClick={handleRemoveMount}
|
|
||||||
style={removeStyle}>
|
|
||||||
<FontAwesomeIcon icon={faTrashAlt}/>
|
|
||||||
</a>
|
</a>
|
||||||
</RootElem>);
|
</RootElem>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const isSkynet = (props.provider === 'Skynet');
|
const isSkynet = props.provider === 'Skynet';
|
||||||
return (
|
return (
|
||||||
<div className={'MountItem'}>
|
<div className={'MountItem'}>
|
||||||
<Grid noScroll>
|
<Grid noScroll>
|
||||||
@@ -185,28 +183,47 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
col={configButton ? 6 : 0}
|
col={configButton ? 6 : 0}
|
||||||
rowSpan={5}
|
rowSpan={5}
|
||||||
colSpan={90}
|
colSpan={90}
|
||||||
text={props.remote ? props.provider.substr(6) : props.s3 ? props.provider.substr(2) : isSkynet ? props.provider + ' [EXPERIMENTAL]' : props.provider}
|
text={
|
||||||
|
props.remote
|
||||||
|
? props.provider.substr(6)
|
||||||
|
: props.s3
|
||||||
|
? props.provider.substr(2)
|
||||||
|
: isSkynet
|
||||||
|
? props.provider + ' [EXPERIMENTAL]'
|
||||||
|
: props.provider
|
||||||
|
}
|
||||||
textAlign={'Left'}
|
textAlign={'Left'}
|
||||||
type={'Heading2'}/>
|
type={'Heading2'}
|
||||||
{(isSkynet && (props.MState.Mounted)) ? (
|
/>
|
||||||
<a href={'#'}
|
{isSkynet && props.MState.Mounted ? (
|
||||||
col={(configButton ? 24 : 18) + 34}
|
<a
|
||||||
onClick={props.MState.AllowMount ? () => props.displaySkynetExport(true) : e => {
|
href={'#'}
|
||||||
e.preventDefault();
|
col={(configButton ? 24 : 18) + 34}
|
||||||
}}
|
onClick={
|
||||||
rowSpan={5}
|
props.MState.AllowMount
|
||||||
style={{...pointer, fontWeight: 'normal'}}>
|
? () => props.displaySkynetExport(true)
|
||||||
|
: (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rowSpan={5}
|
||||||
|
style={{ ...pointer, fontWeight: 'normal' }}>
|
||||||
<u>Export</u>
|
<u>Export</u>
|
||||||
</a>
|
</a>
|
||||||
) : null}
|
) : null}
|
||||||
{(isSkynet && (props.MState.Mounted)) ? (
|
{isSkynet && props.MState.Mounted ? (
|
||||||
<a href={'#'}
|
<a
|
||||||
col={(configButton ? 24 + 13 : 18 + 13) + 34}
|
href={'#'}
|
||||||
onClick={props.MState.AllowMount ? () => props.displaySkynetImport(true) : e => {
|
col={(configButton ? 24 + 13 : 18 + 13) + 34}
|
||||||
e.preventDefault();
|
onClick={
|
||||||
}}
|
props.MState.AllowMount
|
||||||
rowSpan={5}
|
? () => props.displaySkynetImport(true)
|
||||||
style={{...pointer, fontWeight: 'normal'}}>
|
: (e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
rowSpan={5}
|
||||||
|
style={{ ...pointer, fontWeight: 'normal' }}>
|
||||||
<u>Import</u>
|
<u>Import</u>
|
||||||
</a>
|
</a>
|
||||||
) : null}
|
) : null}
|
||||||
@@ -218,4 +235,43 @@ export default connect(mapStateToProps, mapDispatchToProps)(props => {
|
|||||||
</Grid>
|
</Grid>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
});
|
};
|
||||||
|
|
||||||
|
const mapStateToProps = (state, ownProps) => {
|
||||||
|
return {
|
||||||
|
MState: state.mounts.MountState[ownProps.provider],
|
||||||
|
Platform: state.common.Platform,
|
||||||
|
PState: state.mounts.ProviderState[ownProps.provider],
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
displayConfiguration: (provider, remote, s3) =>
|
||||||
|
dispatch(displayConfiguration(provider, remote, s3)),
|
||||||
|
displaySkynetExport: (display) => dispatch(displaySkynetExport(display)),
|
||||||
|
displaySkynetImport: (display) => dispatch(displaySkynetImport(display)),
|
||||||
|
removeMount: (provider) => dispatch(removeMount(provider)),
|
||||||
|
setProviderState: (provider, state) => dispatch(setProviderState(provider, state)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
MountItem.propTypes = {
|
||||||
|
MState: PropTypes.object.isRequired,
|
||||||
|
PState: PropTypes.object.isRequired,
|
||||||
|
Platform: PropTypes.string.isRequired,
|
||||||
|
allowRemove: PropTypes.bool,
|
||||||
|
browseClicked: PropTypes.func.isRequired,
|
||||||
|
changed: PropTypes.func.isRequired,
|
||||||
|
clicked: PropTypes.func.isRequired,
|
||||||
|
displayConfiguration: PropTypes.func.isRequired,
|
||||||
|
displaySkynetExport: PropTypes.func.isRequired,
|
||||||
|
displaySkynetImport: PropTypes.func.isRequired,
|
||||||
|
provider: PropTypes.string.isRequired,
|
||||||
|
remote: PropTypes.bool,
|
||||||
|
removeMount: PropTypes.func.isRequired,
|
||||||
|
s3: PropTypes.bool,
|
||||||
|
setProviderState: PropTypes.func.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(MountItem);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
.MountItems {
|
.MountItems {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 121px;
|
height: 212px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
.MountItemsRemote {
|
.MountItemsRemote {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 121px;
|
height: 212px;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import './MountItems.css';
|
||||||
import AddMount from '../AddMount/AddMount';
|
import AddMount from '../AddMount/AddMount';
|
||||||
import Box from '../../components/UI/Box/Box';
|
import Box from '../../components/UI/Box/Box';
|
||||||
import Button from '../../components/UI/Button/Button';
|
import Button from '../../components/UI/Button/Button';
|
||||||
import {connect} from 'react-redux';
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||||
import './MountItems.css';
|
|
||||||
import Modal from '../../components/UI/Modal/Modal';
|
import Modal from '../../components/UI/Modal/Modal';
|
||||||
import MountItem from './MountItem/MountItem';
|
import MountItem from './MountItem/MountItem';
|
||||||
import IPCContainer from '../IPCContainer/IPCContainer';
|
import { connect } from 'react-redux';
|
||||||
|
import { notifyError } from '../../redux/actions/error_actions';
|
||||||
import {
|
import {
|
||||||
resetMountsState,
|
resetMountsState,
|
||||||
setAllowMount,
|
setAllowMount,
|
||||||
@@ -14,9 +15,8 @@ import {
|
|||||||
setBusy,
|
setBusy,
|
||||||
setMounted,
|
setMounted,
|
||||||
setMountState,
|
setMountState,
|
||||||
setProviderState
|
setProviderState,
|
||||||
} from '../../redux/actions/mount_actions';
|
} from '../../redux/actions/mount_actions';
|
||||||
import {notifyError} from '../../redux/actions/error_actions';
|
|
||||||
|
|
||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
@@ -29,7 +29,7 @@ class MountItems extends IPCContainer {
|
|||||||
RetryItems: {},
|
RetryItems: {},
|
||||||
};
|
};
|
||||||
|
|
||||||
addMountsBusy = provider => {
|
addMountsBusy = (provider) => {
|
||||||
this.props.setMountsBusy(true);
|
this.props.setMountsBusy(true);
|
||||||
this.activeDetections.push(provider);
|
this.activeDetections.push(provider);
|
||||||
};
|
};
|
||||||
@@ -43,15 +43,18 @@ class MountItems extends IPCContainer {
|
|||||||
...this.state.RetryItems,
|
...this.state.RetryItems,
|
||||||
};
|
};
|
||||||
delete retryItems[provider];
|
delete retryItems[provider];
|
||||||
this.setState({
|
this.setState(
|
||||||
DisplayRetry: Object.keys(retryItems).length > 0,
|
{
|
||||||
RetryItems: retryItems,
|
DisplayRetry: Object.keys(retryItems).length > 0,
|
||||||
}, () => {
|
RetryItems: retryItems,
|
||||||
if (this.state.DisplayRetry) {
|
},
|
||||||
this.sendRequest(Constants.IPC_Show_Window);
|
() => {
|
||||||
|
if (this.state.DisplayRetry) {
|
||||||
|
this.sendRequest(Constants.IPC_Show_Window);
|
||||||
|
}
|
||||||
|
stateCallback();
|
||||||
}
|
}
|
||||||
stateCallback();
|
);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -64,18 +67,16 @@ class MountItems extends IPCContainer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
for (const provider in this.state.RetryItems) {
|
Object.keys(this.state.RetryItems).forEach((provider) => {
|
||||||
if (this.state.RetryItems.hasOwnProperty(provider)) {
|
this.cancelRetryMount(provider);
|
||||||
this.cancelRetryMount(provider);
|
});
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this.props.resetMountsState();
|
this.props.resetMountsState();
|
||||||
this.activeDetections = [];
|
this.activeDetections = [];
|
||||||
super.componentWillUnmount();
|
super.componentWillUnmount();
|
||||||
};
|
}
|
||||||
|
|
||||||
detectMount = provider => {
|
detectMount = (provider) => {
|
||||||
this.addMountsBusy(provider);
|
this.addMountsBusy(provider);
|
||||||
|
|
||||||
this.sendRequest(Constants.IPC_Detect_Mount, {
|
this.sendRequest(Constants.IPC_Detect_Mount, {
|
||||||
@@ -86,10 +87,9 @@ class MountItems extends IPCContainer {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
detectMounts = ()=> {
|
detectMounts = () => {
|
||||||
if (!this.state.DisplayRetry) {
|
if (!this.state.DisplayRetry) {
|
||||||
const providerList = this.getProviderList();
|
this.getProviderList().forEach((provider) => {
|
||||||
providerList.forEach(provider => {
|
|
||||||
this.detectMount(provider);
|
this.detectMount(provider);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ class MountItems extends IPCContainer {
|
|||||||
displayRetryMount = (provider, remote, s3, mountLocation, msg) => {
|
displayRetryMount = (provider, remote, s3, mountLocation, msg) => {
|
||||||
if (!this.state.RetryItems[provider]) {
|
if (!this.state.RetryItems[provider]) {
|
||||||
let retryItems = {
|
let retryItems = {
|
||||||
...this.state.RetryItems
|
...this.state.RetryItems,
|
||||||
};
|
};
|
||||||
retryItems[provider] = {
|
retryItems[provider] = {
|
||||||
RetrySeconds: 10,
|
RetrySeconds: 10,
|
||||||
@@ -110,28 +110,31 @@ class MountItems extends IPCContainer {
|
|||||||
};
|
};
|
||||||
this.props.setMountState(provider, mountState);
|
this.props.setMountState(provider, mountState);
|
||||||
|
|
||||||
this.setState({
|
this.setState(
|
||||||
DisplayRetry: true,
|
{
|
||||||
RetryItems: retryItems,
|
DisplayRetry: true,
|
||||||
}, () => {
|
RetryItems: retryItems,
|
||||||
this.sendRequest(Constants.IPC_Show_Window);
|
},
|
||||||
this.retryIntervals[provider] = setInterval(() => {
|
() => {
|
||||||
let retryItems = {
|
this.sendRequest(Constants.IPC_Show_Window);
|
||||||
...this.state.RetryItems,
|
this.retryIntervals[provider] = setInterval(() => {
|
||||||
};
|
const retryItems = {
|
||||||
const retrySeconds = retryItems[provider].RetrySeconds - 1;
|
...this.state.RetryItems,
|
||||||
if (retrySeconds === 0) {
|
};
|
||||||
this.cancelRetryMount(provider, () => {
|
const retrySeconds = retryItems[provider].RetrySeconds - 1;
|
||||||
this.handleMountUnMount(provider, remote, s3, true, mountLocation);
|
if (retrySeconds === 0) {
|
||||||
});
|
this.cancelRetryMount(provider, () => {
|
||||||
} else {
|
this.handleMountUnMount(provider, remote, s3, true, mountLocation);
|
||||||
retryItems[provider].RetrySeconds = retrySeconds;
|
});
|
||||||
this.setState({
|
} else {
|
||||||
RetryItems: retryItems,
|
retryItems[provider].RetrySeconds = retrySeconds;
|
||||||
});
|
this.setState({
|
||||||
}
|
RetryItems: retryItems,
|
||||||
}, 1000);
|
});
|
||||||
});
|
}
|
||||||
|
}, 1000);
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -140,7 +143,7 @@ class MountItems extends IPCContainer {
|
|||||||
Title: provider + ' Mount Location',
|
Title: provider + ' Mount Location',
|
||||||
Location: location,
|
Location: location,
|
||||||
});
|
});
|
||||||
if (location && (location.length > 0)) {
|
if (location && location.length > 0) {
|
||||||
this.handleMountLocationChanged(provider, location);
|
this.handleMountLocationChanged(provider, location);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -154,19 +157,23 @@ class MountItems extends IPCContainer {
|
|||||||
};
|
};
|
||||||
|
|
||||||
handleMountUnMount = (provider, remote, s3, mount, location) => {
|
handleMountUnMount = (provider, remote, s3, mount, location) => {
|
||||||
if (!location || (location.trim().length === 0)) {
|
if (!location || location.trim().length === 0) {
|
||||||
this.props.notifyError('Mount location is not set');
|
this.props.notifyError('Mount location is not set');
|
||||||
} else {
|
} else {
|
||||||
let allowAction = true;
|
let allowAction = true;
|
||||||
if (mount) {
|
if (mount) {
|
||||||
let result = remote || s3 || provider === 'Skynet' ?
|
let result =
|
||||||
{Valid: true, Success: true} :
|
remote || s3 || provider === 'Skynet'
|
||||||
this.sendSyncRequest(Constants.IPC_Check_Daemon_Version, {
|
? { Valid: true, Success: true }
|
||||||
Provider: provider,
|
: this.sendSyncRequest(Constants.IPC_Check_Daemon_Version, {
|
||||||
Remote: remote,
|
Provider: provider,
|
||||||
S3: s3,
|
Remote: remote,
|
||||||
Version: this.props.InstalledVersion
|
S3: s3,
|
||||||
}).data;
|
Version: this.props.InstalledVersion,
|
||||||
|
}).data;
|
||||||
|
const displayRetry = (msg) => {
|
||||||
|
this.displayRetryMount(provider, remote, s3, location, msg);
|
||||||
|
};
|
||||||
if (result.Success) {
|
if (result.Success) {
|
||||||
if (result.Valid) {
|
if (result.Valid) {
|
||||||
if (this.props.Platform !== 'win32') {
|
if (this.props.Platform !== 'win32') {
|
||||||
@@ -180,20 +187,30 @@ class MountItems extends IPCContainer {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
allowAction = false;
|
allowAction = false;
|
||||||
if ((result.Code === new Uint32Array([-1])[0]) || (result.Code === new Uint8Array([-1])[0])) {
|
if (
|
||||||
this.displayRetryMount(provider, remote, s3, location, 'Failed to connect to ' + provider + ' daemon');
|
result.Code === new Uint32Array([-1])[0] ||
|
||||||
} else if ((result.Code === new Uint32Array([-3])[0]) || (result.Code === new Uint8Array([-3])[0])) {
|
result.Code === new Uint8Array([-1])[0]
|
||||||
this.displayRetryMount(provider, remote, s3, location, 'Incompatible ' + provider + ' daemon. Please upgrade ' + provider + '.');
|
) {
|
||||||
|
displayRetry('Failed to connect to ' + provider + ' daemon');
|
||||||
|
} else if (
|
||||||
|
result.Code === new Uint32Array([-3])[0] ||
|
||||||
|
result.Code === new Uint8Array([-3])[0]
|
||||||
|
) {
|
||||||
|
displayRetry(
|
||||||
|
'Incompatible ' + provider + ' daemon. Please upgrade ' + provider + '.'
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.displayRetryMount(provider, remote, s3, location, 'Version check failed: ' + result.Error);
|
displayRetry('Version check failed: ' + result.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
allowAction = false;
|
allowAction = false;
|
||||||
if (this.props.Platform === 'win32') {
|
if (this.props.Platform === 'win32') {
|
||||||
this.props.notifyError('Failed to launch repertory. Please install Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019.');
|
this.props.notifyError(
|
||||||
|
'Failed to launch repertory. Please install Microsoft Visual C++ Redistributable for Visual Studio 2015, 2017 and 2019.'
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
this.displayRetryMount(provider, remote, s3, location, 'Version check failed: ' + result.Error);
|
displayRetry('Version check failed: ' + result.Error);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -202,32 +219,24 @@ class MountItems extends IPCContainer {
|
|||||||
this.addMountsBusy(provider);
|
this.addMountsBusy(provider);
|
||||||
this.props.setAllowMount(provider, false);
|
this.props.setAllowMount(provider, false);
|
||||||
|
|
||||||
if (mount) {
|
this.sendRequest(mount ? Constants.IPC_Mount_Drive : Constants.IPC_Unmount_Drive, {
|
||||||
this.sendRequest(Constants.IPC_Mount_Drive, {
|
Location: location,
|
||||||
Location: location,
|
Provider: provider,
|
||||||
Provider: provider,
|
Remote: remote,
|
||||||
Remote: remote,
|
S3: s3,
|
||||||
S3: s3,
|
Version: this.props.InstalledVersion,
|
||||||
Version: this.props.InstalledVersion,
|
});
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.sendRequest(Constants.IPC_Unmount_Drive, {
|
|
||||||
Location: location,
|
|
||||||
Provider: provider,
|
|
||||||
Remote: remote,
|
|
||||||
S3: s3,
|
|
||||||
Version: this.props.InstalledVersion,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
getProviderList = providersOnly => {
|
getProviderList = (providersOnly) => {
|
||||||
const providerList = Constants.PROVIDER_LIST.filter(i => {
|
const providerList = Constants.PROVIDER_LIST.filter((i) => {
|
||||||
return ((i === 'Skynet') && this.props.skynetSupported) ||
|
return (
|
||||||
((i === 'ScPrime') && this.props.scPrimeSupported) ||
|
(i === 'Skynet' && this.props.skynetSupported) ||
|
||||||
((i === 'Sia') && this.props.siaSupported);
|
(i === 'ScPrime' && this.props.scPrimeSupported) ||
|
||||||
|
(i === 'Sia' && this.props.siaSupported)
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
let remoteList = [];
|
let remoteList = [];
|
||||||
@@ -240,26 +249,22 @@ class MountItems extends IPCContainer {
|
|||||||
s3List = [...this.props.S3Mounts];
|
s3List = [...this.props.S3Mounts];
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return [...providerList, ...remoteList, ...s3List];
|
||||||
...providerList,
|
|
||||||
...remoteList,
|
|
||||||
...s3List,
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
hasActiveMount = () => {
|
hasActiveMount = () => {
|
||||||
for (const provider of Object.keys(this.props.MountState)) {
|
return !!Object.keys(this.props.MountState).find((provider) => {
|
||||||
if (this.props.MountState[provider].Mounted)
|
return this.props.MountState[provider].Mounted;
|
||||||
return true;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
onDetectMountReply = (event, arg) => {
|
onDetectMountReply = (_, arg) => {
|
||||||
const provider = arg.data.Provider;
|
const provider = arg.data.Provider;
|
||||||
if (!this.state.RetryItems[provider]) {
|
if (!this.state.RetryItems[provider]) {
|
||||||
if (arg.data.Success && (!arg.data.Active || (arg.data.Location && (arg.data.Location.length > 0)))) {
|
if (
|
||||||
|
arg.data.Success &&
|
||||||
|
(!arg.data.Active || (arg.data.Location && arg.data.Location.length > 0))
|
||||||
|
) {
|
||||||
const mountState = {
|
const mountState = {
|
||||||
AllowMount: true,
|
AllowMount: true,
|
||||||
DriveLetters: arg.data.DriveLetters,
|
DriveLetters: arg.data.DriveLetters,
|
||||||
@@ -267,7 +272,12 @@ class MountItems extends IPCContainer {
|
|||||||
};
|
};
|
||||||
this.props.setMountState(provider, mountState);
|
this.props.setMountState(provider, mountState);
|
||||||
|
|
||||||
this.updateMountLocation(provider, arg.data.Location, mountState.Mounted, arg.data.DriveLetters);
|
this.updateMountLocation(
|
||||||
|
provider,
|
||||||
|
arg.data.Location,
|
||||||
|
mountState.Mounted,
|
||||||
|
arg.data.DriveLetters
|
||||||
|
);
|
||||||
this.props.setAutoMountProcessed(provider, true);
|
this.props.setAutoMountProcessed(provider, true);
|
||||||
this.removeMountsBusy(provider);
|
this.removeMountsBusy(provider);
|
||||||
} else {
|
} else {
|
||||||
@@ -277,14 +287,20 @@ class MountItems extends IPCContainer {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
onMountDriveReply = (event, arg) => {
|
onMountDriveReply = (_, arg) => {
|
||||||
this.props.setMounted(arg.data.Provider, arg.data.Success);
|
this.props.setMounted(arg.data.Provider, arg.data.Success);
|
||||||
this.detectMount(arg.data.Provider);
|
this.detectMount(arg.data.Provider);
|
||||||
this.removeMountsBusy(arg.data.Provider);
|
this.removeMountsBusy(arg.data.Provider);
|
||||||
};
|
};
|
||||||
|
|
||||||
onUnmountDriveReply = (event, arg) => {
|
onUnmountDriveReply = (_, arg) => {
|
||||||
if (arg && arg.data && !arg.data.Expected && arg.data.Location && this.props.ProviderState[arg.data.Provider].AutoRestart) {
|
if (
|
||||||
|
arg &&
|
||||||
|
arg.data &&
|
||||||
|
!arg.data.Expected &&
|
||||||
|
arg.data.Location &&
|
||||||
|
this.props.ProviderState[arg.data.Provider].AutoRestart
|
||||||
|
) {
|
||||||
this.displayRetryMount(arg.data.Provider, arg.data.Remote, arg.data.Location);
|
this.displayRetryMount(arg.data.Provider, arg.data.Remote, arg.data.Location);
|
||||||
} else {
|
} else {
|
||||||
this.detectMount(arg.data.Provider);
|
this.detectMount(arg.data.Provider);
|
||||||
@@ -292,140 +308,152 @@ class MountItems extends IPCContainer {
|
|||||||
this.removeMountsBusy(arg.data.Provider);
|
this.removeMountsBusy(arg.data.Provider);
|
||||||
};
|
};
|
||||||
|
|
||||||
removeMountsBusy = provider => {
|
removeMountsBusy = (provider) => {
|
||||||
const idx = this.activeDetections.indexOf(provider);
|
const idx = this.activeDetections.indexOf(provider);
|
||||||
if (idx > -1) {
|
if (idx > -1) {
|
||||||
this.activeDetections.splice(idx, 1);
|
this.activeDetections.splice(idx, 1);
|
||||||
}
|
}
|
||||||
this.props.setMountsBusy((this.activeDetections.length > 0) || this.hasActiveMount());
|
this.props.setMountsBusy(this.activeDetections.length > 0 || this.hasActiveMount());
|
||||||
};
|
};
|
||||||
|
|
||||||
updateMountLocation = (provider, location, mounted, driveLetters) => {
|
updateMountLocation = (provider, location, mounted, driveLetters) => {
|
||||||
const providerState = this.props.ProviderState[provider];
|
const providerState = this.props.ProviderState[provider];
|
||||||
if (location.length === 0) {
|
if (location.length === 0) {
|
||||||
location = (this.props.Platform === 'win32') ?
|
location =
|
||||||
!providerState.MountLocation || providerState.MountLocation.trim().length === 0 ? driveLetters[0] : providerState.MountLocation :
|
this.props.Platform === 'win32'
|
||||||
providerState.MountLocation;
|
? !providerState.MountLocation || providerState.MountLocation.trim().length === 0
|
||||||
|
? driveLetters[0]
|
||||||
|
: providerState.MountLocation
|
||||||
|
: providerState.MountLocation;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (location !== providerState.MountLocation) {
|
if (location !== providerState.MountLocation) {
|
||||||
this.handleMountLocationChanged(provider, location);
|
this.handleMountLocationChanged(provider, location);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.props.AutoMountProcessed[provider] &&
|
if (
|
||||||
|
!this.props.AutoMountProcessed[provider] &&
|
||||||
this.props.ProviderState[provider].AutoMount &&
|
this.props.ProviderState[provider].AutoMount &&
|
||||||
!mounted &&
|
!mounted &&
|
||||||
(location.length > 0)) {
|
location.length > 0
|
||||||
this.handleMountUnMount(provider, this.props.RemoteMounts.includes(provider), this.props.S3Mounts.includes(provider), true, location);
|
) {
|
||||||
|
this.handleMountUnMount(
|
||||||
|
provider,
|
||||||
|
this.props.RemoteMounts.includes(provider),
|
||||||
|
this.props.S3Mounts.includes(provider),
|
||||||
|
true,
|
||||||
|
location
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let retryDisplay;
|
let retryDisplay;
|
||||||
if (this.state.DisplayRetry) {
|
if (this.state.DisplayRetry) {
|
||||||
let retryList = [];
|
const retryList = [];
|
||||||
let retryCount = 0;
|
let retryCount = 0;
|
||||||
for (const provider in this.state.RetryItems) {
|
Object.keys(this.state.RetryItems).forEach((provider) => {
|
||||||
if (this.state.RetryItems.hasOwnProperty(provider)) {
|
if (this.state.RetryItems[provider].RetryMessage) {
|
||||||
if (this.state.RetryItems[provider].RetryMessage) {
|
retryList.push(
|
||||||
retryList.push(<p key={'rl_' + retryList.length}>{this.state.RetryItems[provider].RetryMessage}</p>);
|
<p key={'rl_' + retryList.length}>{this.state.RetryItems[provider].RetryMessage}</p>
|
||||||
}
|
);
|
||||||
retryList.push(<Button clicked={() => this.cancelRetryMount(provider, () => this.detectMounts())}
|
|
||||||
key={'rl_' + retryList.length}>Cancel {provider} Remount
|
|
||||||
({this.state.RetryItems[provider].RetrySeconds}s)</Button>);
|
|
||||||
if (++retryCount < Object.keys(this.state.RetryItems).length) {
|
|
||||||
retryList.push(<div style={{paddingTop: 'var(--default_spacing)'}}
|
|
||||||
key={'rl_' + retryList.length}/>);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
retryList.push(
|
||||||
|
<Button
|
||||||
|
clicked={() => this.cancelRetryMount(provider, () => this.detectMounts())}
|
||||||
|
key={'rl_' + retryList.length}>
|
||||||
|
Cancel {provider} Remount ({this.state.RetryItems[provider].RetrySeconds}s)
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
if (++retryCount < Object.keys(this.state.RetryItems).length) {
|
||||||
|
retryList.push(
|
||||||
|
<div style={{ paddingTop: 'var(--default_spacing)' }} key={'rl_' + retryList.length} />
|
||||||
|
);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
retryDisplay = (
|
retryDisplay = (
|
||||||
<Modal>
|
<Modal>
|
||||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)', minWidth: '70vw'}}>
|
<Box dxDark dxStyle={{ padding: 'var(--default_spacing)', minWidth: '70vw' }}>
|
||||||
<h1 style={{
|
<h1
|
||||||
textAlign: 'center',
|
style={{
|
||||||
paddingBottom: 'var(--default_spacing)',
|
textAlign: 'center',
|
||||||
color: 'var(--text_color_error)'
|
paddingBottom: 'var(--default_spacing)',
|
||||||
}}>Mount Failed</h1>
|
color: 'var(--text_color_error)',
|
||||||
|
}}>
|
||||||
|
Mount Failed
|
||||||
|
</h1>
|
||||||
{retryList}
|
{retryList}
|
||||||
</Box>
|
</Box>
|
||||||
</Modal>
|
</Modal>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
let footerItems = [];
|
const footerItems = [];
|
||||||
if (this.props.remoteSupported || this.props.s3Supported) {
|
if (this.props.remoteSupported || this.props.s3Supported) {
|
||||||
footerItems.push(<AddMount remoteSupported={this.props.remoteSupported}
|
footerItems.push(
|
||||||
s3Supported={this.props.s3Supported}
|
<AddMount
|
||||||
key={'hi_' + footerItems.length}/>);
|
remoteSupported={this.props.remoteSupported}
|
||||||
|
s3Supported={this.props.s3Supported}
|
||||||
|
key={'hi_' + footerItems.length}
|
||||||
|
/>
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
footerItems.push(<div key={'hi_' + footerItems.length}
|
footerItems.push(<div key={'hi_' + footerItems.length} style={{ height: '27px' }} />);
|
||||||
style={{height: '27px'}}/>);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let items = [];
|
const mountItems = [];
|
||||||
for (const provider of this.getProviderList(true)) {
|
const addMountItem = (provider, remote, s3) => {
|
||||||
items.push((
|
if (mountItems.length > 0) {
|
||||||
<MountItem allowRemove={false}
|
mountItems.push(
|
||||||
browseClicked={this.handleBrowseLocation}
|
<div
|
||||||
changed={e => this.handleMountLocationChanged(provider, e.target.value)}
|
key={'it_' + mountItems.length}
|
||||||
clicked={this.handleMountUnMount}
|
style={{ paddingTop: 'calc(var(--default_spacing) * 2.5)' }}
|
||||||
key={'it_' + items.length}
|
/>
|
||||||
provider={provider}/>
|
);
|
||||||
));
|
}
|
||||||
items.push(<div key={'it_' + items.length}
|
|
||||||
style={{paddingTop: 'var(--default_spacing)'}} />)
|
mountItems.push(
|
||||||
}
|
<MountItem
|
||||||
|
allowRemove={remote || s3}
|
||||||
|
browseClicked={this.handleBrowseLocation}
|
||||||
|
changed={(e) => this.handleMountLocationChanged(provider, e.target.value)}
|
||||||
|
clicked={this.handleMountUnMount}
|
||||||
|
key={'it_' + mountItems.length}
|
||||||
|
provider={provider}
|
||||||
|
remote={remote}
|
||||||
|
s3={s3}
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getProviderList(true).forEach((provider) => addMountItem(provider));
|
||||||
|
|
||||||
if (this.props.remoteSupported) {
|
if (this.props.remoteSupported) {
|
||||||
for (const provider of this.props.RemoteMounts) {
|
this.props.RemoteMounts.forEach((provider) => addMountItem(provider, true));
|
||||||
items.push((
|
|
||||||
<MountItem allowRemove={true}
|
|
||||||
browseClicked={this.handleBrowseLocation}
|
|
||||||
changed={e => this.handleMountLocationChanged(provider, e.target.value)}
|
|
||||||
clicked={this.handleMountUnMount}
|
|
||||||
key={'it_' + items.length}
|
|
||||||
provider={provider}
|
|
||||||
remote/>
|
|
||||||
));
|
|
||||||
items.push(<div key={'it_' + items.length}
|
|
||||||
style={{paddingTop: 'var(--default_spacing)'}}/>)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.props.s3Supported) {
|
if (this.props.s3Supported) {
|
||||||
for (const provider of this.props.S3Mounts) {
|
this.props.S3Mounts.forEach((provider) => addMountItem(provider, false, true));
|
||||||
items.push((
|
|
||||||
<MountItem allowRemove={true}
|
|
||||||
browseClicked={this.handleBrowseLocation}
|
|
||||||
changed={e => this.handleMountLocationChanged(provider, e.target.value)}
|
|
||||||
clicked={this.handleMountUnMount}
|
|
||||||
key={'it_' + items.length}
|
|
||||||
provider={provider}
|
|
||||||
s3/>
|
|
||||||
));
|
|
||||||
items.push(<div key={'it_' + items.length}
|
|
||||||
style={{paddingTop: 'var(--default_spacing)'}}/>)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
items.splice(items.length - 1, 1);
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{margin: 0, padding: 0}}>
|
<div style={{ margin: 0, padding: 0 }}>
|
||||||
{retryDisplay}
|
{retryDisplay}
|
||||||
<div
|
<div
|
||||||
className={this.props.remoteSupported || this.props.s3Supported ? 'MountItemsRemote' : 'MountItems'}>
|
className={
|
||||||
{items}
|
this.props.remoteSupported || this.props.s3Supported ? 'MountItemsRemote' : 'MountItems'
|
||||||
|
}>
|
||||||
|
{mountItems}
|
||||||
</div>
|
</div>
|
||||||
<div style={{paddingTop: 'var(--default_spacing)'}}/>
|
<div style={{ paddingTop: 'var(--default_spacing)' }} />
|
||||||
{footerItems}
|
{footerItems}
|
||||||
</div>);
|
</div>
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = (state) => {
|
||||||
return {
|
return {
|
||||||
AutoMountProcessed: state.mounts.AutoMountProcessed,
|
AutoMountProcessed: state.mounts.AutoMountProcessed,
|
||||||
InstalledVersion: state.relver.InstalledVersion,
|
InstalledVersion: state.relver.InstalledVersion,
|
||||||
@@ -435,20 +463,21 @@ const mapStateToProps = state => {
|
|||||||
ProviderState: state.mounts.ProviderState,
|
ProviderState: state.mounts.ProviderState,
|
||||||
RemoteMounts: state.mounts.RemoteMounts,
|
RemoteMounts: state.mounts.RemoteMounts,
|
||||||
S3Mounts: state.mounts.S3Mounts,
|
S3Mounts: state.mounts.S3Mounts,
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
notifyError: (msg, critical, callback) => dispatch(notifyError(msg, critical, callback)),
|
||||||
resetMountsState: () => dispatch(resetMountsState()),
|
resetMountsState: () => dispatch(resetMountsState()),
|
||||||
setAllowMount: (provider, allow) => dispatch(setAllowMount(provider, allow)),
|
setAllowMount: (provider, allow) => dispatch(setAllowMount(provider, allow)),
|
||||||
setAutoMountProcessed: (provider, processed) => dispatch(setAutoMountProcessed(provider, processed)),
|
setAutoMountProcessed: (provider, processed) =>
|
||||||
|
dispatch(setAutoMountProcessed(provider, processed)),
|
||||||
setMounted: (provider, mounted) => dispatch(setMounted(provider, mounted)),
|
setMounted: (provider, mounted) => dispatch(setMounted(provider, mounted)),
|
||||||
setMountsBusy: busy => dispatch(setBusy(busy)),
|
setMountsBusy: (busy) => dispatch(setBusy(busy)),
|
||||||
setMountState: (provider, state) => dispatch(setMountState(provider, state)),
|
setMountState: (provider, state) => dispatch(setMountState(provider, state)),
|
||||||
setProviderState: (provider, state) => dispatch(setProviderState(provider, state)),
|
setProviderState: (provider, state) => dispatch(setProviderState(provider, state)),
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(MountItems);
|
export default connect(mapStateToProps, mapDispatchToProps)(MountItems);
|
||||||
|
|||||||
@@ -1,41 +1,24 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './PinnedManager.css';
|
import './PinnedManager.css';
|
||||||
import {connect} from 'react-redux';
|
|
||||||
import IPCContainer from '../IPCContainer/IPCContainer';
|
|
||||||
import {notifyApplicationBusy} from '../../redux/actions/common_actions';
|
|
||||||
import {notifyError, notifyInfo} from '../../redux/actions/error_actions';
|
|
||||||
import Box from '../../components/UI/Box/Box';
|
import Box from '../../components/UI/Box/Box';
|
||||||
import {displayPinnedManager} from '../../redux/actions/pinned_manager_actions';
|
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
|
||||||
import {faFolder} from '@fortawesome/free-solid-svg-icons';
|
|
||||||
import Button from '../../components/UI/Button/Button';
|
import Button from '../../components/UI/Button/Button';
|
||||||
import CheckBox from '../../components/UI/CheckBox/CheckBox';
|
import CheckBox from '../../components/UI/CheckBox/CheckBox';
|
||||||
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { connect } from 'react-redux';
|
||||||
|
import { displayPinnedManager } from '../../redux/actions/pinned_manager_actions';
|
||||||
|
import { faFolder } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { notifyApplicationBusy } from '../../redux/actions/common_actions';
|
||||||
|
import { notifyError, notifyInfo } from '../../redux/actions/error_actions';
|
||||||
|
|
||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
class PinnedManager extends IPCContainer {
|
||||||
return {
|
|
||||||
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
|
||||||
DisplayRemoteConfiguration: state.mounts.DisplayRemoteConfiguration,
|
|
||||||
DisplayS3Configuration: state.mounts.DisplayS3Configuration,
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
|
||||||
return {
|
|
||||||
displayPinnedManager: display => dispatch(displayPinnedManager(display)),
|
|
||||||
notifyApplicationBusy: busy => dispatch(notifyApplicationBusy(busy, true)),
|
|
||||||
notifyError: (msg, cb) => dispatch(notifyError(msg, false, cb)),
|
|
||||||
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCContainer {
|
|
||||||
state = {
|
state = {
|
||||||
active_directory: '/',
|
active_directory: '/',
|
||||||
items: [],
|
items: [],
|
||||||
previous: [],
|
previous: [],
|
||||||
}
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.setRequestHandler(Constants.IPC_Get_Directory_Items_Reply, this.onGetDirectoryItemsReply);
|
this.setRequestHandler(Constants.IPC_Get_Directory_Items_Reply, this.onGetDirectoryItemsReply);
|
||||||
@@ -54,21 +37,22 @@ export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCCon
|
|||||||
Version: this.props.version,
|
Version: this.props.version,
|
||||||
Path: this.state.active_directory,
|
Path: this.state.active_directory,
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
onGetDirectoryItemsReply = (_, {data}) => {
|
onGetDirectoryItemsReply = (_, { data }) => {
|
||||||
if (data.Success) {
|
if (data.Success) {
|
||||||
const items = data.Items
|
const items = data.Items.filter(
|
||||||
.filter(i => i.path !== '.' && (this.state.active_directory !== '/' || (i.path.substr(0, 1) !== '.')))
|
(i) =>
|
||||||
.map(i => {
|
i.path !== '.' && (this.state.active_directory !== '/' || i.path.substr(0, 1) !== '.')
|
||||||
|
).map((i) => {
|
||||||
return {
|
return {
|
||||||
...i,
|
...i,
|
||||||
name: i.path === '..' ? i.path : i.path.substr(i.path.lastIndexOf('/') + 1),
|
name: i.path === '..' ? i.path : i.path.substr(i.path.lastIndexOf('/') + 1),
|
||||||
meta: {
|
meta: {
|
||||||
...i.meta,
|
...i.meta,
|
||||||
pinned: i.meta.pinned === '1',
|
pinned: i.meta.pinned === '1',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
});
|
});
|
||||||
this.setState({
|
this.setState({
|
||||||
items,
|
items,
|
||||||
@@ -78,103 +62,143 @@ export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCCon
|
|||||||
this.props.displayPinnedManager(false);
|
this.props.displayPinnedManager(false);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
createDirectory = (name, path, idx, total, item_idx) => {
|
createDirectory = (name, path, idx, total, item_idx) => {
|
||||||
const style = {}
|
const style = {};
|
||||||
if (item_idx + 1 !== total) {
|
if (item_idx + 1 !== total) {
|
||||||
style.marginBottom = '4px';
|
style.marginBottom = '4px';
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div key={'dir_' + idx} style={{...style}}>
|
<div key={'dir_' + idx} style={{ ...style }}>
|
||||||
<Button buttonStyles={{textAlign: 'left'}}
|
<Button
|
||||||
clicked={() => {
|
buttonStyles={{ textAlign: 'left' }}
|
||||||
const previous = [...this.state.previous];
|
clicked={() => {
|
||||||
if (path === '..') {
|
const previous = [...this.state.previous];
|
||||||
path = previous.pop();
|
if (path === '..') {
|
||||||
} else {
|
path = previous.pop();
|
||||||
previous.push(this.state.active_directory);
|
} else {
|
||||||
}
|
previous.push(this.state.active_directory);
|
||||||
this.setState({
|
}
|
||||||
items: [],
|
this.setState(
|
||||||
active_directory: path,
|
{
|
||||||
previous,
|
items: [],
|
||||||
}, () => {
|
active_directory: path,
|
||||||
this.grabDirectoryItems();
|
previous,
|
||||||
});
|
},
|
||||||
}}>
|
() => {
|
||||||
<FontAwesomeIcon icon={faFolder}
|
this.grabDirectoryItems();
|
||||||
fixedWidth
|
}
|
||||||
color={'var(--heading_text_color)'}
|
);
|
||||||
style={{padding: 0, margin: 0}}/>
|
}}>
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon={faFolder}
|
||||||
|
fixedWidth
|
||||||
|
color={'var(--heading_text_color)'}
|
||||||
|
style={{ padding: 0, margin: 0 }}
|
||||||
|
/>
|
||||||
{name}
|
{name}
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
createFile = (name, path, pinned, idx, total, item_idx) => {
|
createFile = (name, path, pinned, idx, total, item_idx) => {
|
||||||
const style = {textAlign: 'left'}
|
const style = { textAlign: 'left' };
|
||||||
if (item_idx + 1 !== total) {
|
if (item_idx + 1 !== total) {
|
||||||
style.marginBottom = '2px';
|
style.marginBottom = '2px';
|
||||||
}
|
}
|
||||||
return (
|
return (
|
||||||
<div key={'file_' + idx} style={{...style}}>
|
<div key={'file_' + idx} style={{ ...style }}>
|
||||||
<CheckBox checked={pinned}
|
<CheckBox
|
||||||
changed={() => {
|
checked={pinned}
|
||||||
const items = JSON.parse(JSON.stringify(this.state.items));
|
changed={() => {
|
||||||
const pinned = items[item_idx].meta.pinned = !items[item_idx].meta.pinned;
|
const items = JSON.parse(JSON.stringify(this.state.items));
|
||||||
this.setState({
|
const pinned = (items[item_idx].meta.pinned = !items[item_idx].meta.pinned);
|
||||||
items
|
this.setState(
|
||||||
}, () => {
|
{
|
||||||
this.sendSyncRequest(Constants.IPC_Set_Pinned, {
|
items,
|
||||||
Provider: this.props.DisplayConfiguration,
|
},
|
||||||
Remote: this.props.DisplayRemoteConfiguration,
|
() => {
|
||||||
S3: this.props.DisplayS3Configuration,
|
this.sendSyncRequest(Constants.IPC_Set_Pinned, {
|
||||||
Version: this.props.version,
|
Provider: this.props.DisplayConfiguration,
|
||||||
Path: path,
|
Remote: this.props.DisplayRemoteConfiguration,
|
||||||
Pinned: pinned,
|
S3: this.props.DisplayS3Configuration,
|
||||||
});
|
Version: this.props.version,
|
||||||
});
|
Path: path,
|
||||||
}}
|
Pinned: pinned,
|
||||||
label={name}/>
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}}
|
||||||
|
label={name}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
let idx = 0;
|
let idx = 0;
|
||||||
return (
|
return (
|
||||||
<Box dxDark dxStyle={{
|
<Box
|
||||||
height: 'calc(100vh - (var(--default_spacing) * 4)',
|
dxDark
|
||||||
padding: 'var(--default_spacing)',
|
dxStyle={{
|
||||||
width: 'calc(100vw - (var(--default_spacing) * 4)'
|
height: 'calc(100vh - (var(--default_spacing) * 4)',
|
||||||
}}>
|
padding: 'var(--default_spacing)',
|
||||||
|
width: 'calc(100vw - (var(--default_spacing) * 4)',
|
||||||
|
}}>
|
||||||
<div className={'PinnedManager'}>
|
<div className={'PinnedManager'}>
|
||||||
<div className={'PinnedManagerHeading'}>
|
<div className={'PinnedManagerHeading'}>
|
||||||
<div className={'PinnedManagerClose'}>
|
<div className={'PinnedManagerClose'}>
|
||||||
<a href={'#'}
|
<a
|
||||||
onClick={() => this.props.displayPinnedManager(false)}
|
href={'#'}
|
||||||
style={{cursor: 'pointer', flex: '0'}}>X</a>
|
onClick={() => this.props.displayPinnedManager(false)}
|
||||||
|
style={{ cursor: 'pointer', flex: '0' }}>
|
||||||
|
X
|
||||||
|
</a>
|
||||||
</div>
|
</div>
|
||||||
<h1 style={{width: '100%', textAlign: 'center'}}>{'Pinned File Manager'}</h1>
|
<h1 style={{ width: '100%', textAlign: 'center' }}>{'Pinned File Manager'}</h1>
|
||||||
<div className={'PinnedManagerActiveDirectory'}>
|
<div className={'PinnedManagerActiveDirectory'}>
|
||||||
<b> {this.state.active_directory}</b>
|
<b> {this.state.active_directory}</b>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className={'PinnedManagerItemsOwner'}>
|
<div className={'PinnedManagerItemsOwner'}>
|
||||||
<div className={'PinnedManagerItems'}>
|
<div className={'PinnedManagerItems'}>
|
||||||
{
|
{this.state.items.map((i, k) => {
|
||||||
this.state.items.map((i, k) => {
|
return i.directory
|
||||||
return i.directory ?
|
? this.createDirectory(i.name, i.path, idx++, this.state.items.length, k)
|
||||||
this.createDirectory(i.name, i.path, idx++, this.state.items.length, k) :
|
: this.createFile(
|
||||||
this.createFile(i.name, i.path, i.meta.pinned, idx++, this.state.items.length, k);
|
i.name,
|
||||||
})
|
i.path,
|
||||||
}
|
i.meta.pinned,
|
||||||
|
idx++,
|
||||||
|
this.state.items.length,
|
||||||
|
k
|
||||||
|
);
|
||||||
|
})}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
)
|
);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
|
||||||
|
const mapStateToProps = (state) => {
|
||||||
|
return {
|
||||||
|
DisplayConfiguration: state.mounts.DisplayConfiguration,
|
||||||
|
DisplayRemoteConfiguration: state.mounts.DisplayRemoteConfiguration,
|
||||||
|
DisplayS3Configuration: state.mounts.DisplayS3Configuration,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => {
|
||||||
|
return {
|
||||||
|
displayPinnedManager: (display) => dispatch(displayPinnedManager(display)),
|
||||||
|
notifyApplicationBusy: (busy) => dispatch(notifyApplicationBusy(busy, true)),
|
||||||
|
notifyError: (msg, cb) => dispatch(notifyError(msg, false, cb)),
|
||||||
|
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default connect(mapStateToProps, mapDispatchToProps)(PinnedManager);
|
||||||
|
|||||||
@@ -1,43 +1,47 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './SelectAppPlatform.css';
|
import './SelectAppPlatform.css';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import * as Constants from '../../constants';
|
import * as Constants from '../../constants';
|
||||||
import Box from '../../components/UI/Box/Box';
|
import Box from '../../components/UI/Box/Box';
|
||||||
import Button from '../../components/UI/Button/Button';
|
import Button from '../../components/UI/Button/Button';
|
||||||
import {
|
import { downloadItem, setAllowDownload } from '../../redux/actions/download_actions';
|
||||||
downloadItem,
|
|
||||||
setAllowDownload
|
|
||||||
} from '../../redux/actions/download_actions';
|
|
||||||
import DropDown from '../../components/UI/DropDown/DropDown';
|
import DropDown from '../../components/UI/DropDown/DropDown';
|
||||||
import IPCContainer from '../IPCContainer/IPCContainer';
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||||
import {notifyError} from '../../redux/actions/error_actions';
|
import { notifyError } from '../../redux/actions/error_actions';
|
||||||
import {setInstallTestActive} from '../../redux/actions/install_actions';
|
import { setInstallTestActive } from '../../redux/actions/install_actions';
|
||||||
|
|
||||||
class SelectAppPlatform extends IPCContainer {
|
class SelectAppPlatform extends IPCContainer {
|
||||||
state = {
|
state = {
|
||||||
Selected: 0,
|
Selected: 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
grabLatestRelease = appPlatform => {
|
grabLatestRelease = (appPlatform) => {
|
||||||
const errorHandler = error => {
|
const errorHandler = (error) => {
|
||||||
this.props.notifyError(error);
|
this.props.notifyError(error);
|
||||||
this.props.setInstallTestActive(false);
|
this.props.setInstallTestActive(false);
|
||||||
this.props.setAllowDownload(false);
|
this.props.setAllowDownload(false);
|
||||||
};
|
};
|
||||||
axios
|
axios
|
||||||
.get(Constants.RELEASES_URL)
|
.get(Constants.RELEASES_URL)
|
||||||
.then(response => {
|
.then((response) => {
|
||||||
try {
|
try {
|
||||||
const releases = response.data.Versions.Release[appPlatform];
|
const releases = response.data.Versions.Release[appPlatform];
|
||||||
const latestVersion = releases[releases.length - 1];
|
const latestVersion = releases[releases.length - 1];
|
||||||
const release = response.data.Locations[appPlatform][latestVersion];
|
const release = response.data.Locations[appPlatform][latestVersion];
|
||||||
this.props.downloadItem(latestVersion + '.zip', Constants.INSTALL_TYPES.TestRelease, release.urls, false, latestVersion, appPlatform);
|
this.props.downloadItem(
|
||||||
|
latestVersion + '.zip',
|
||||||
|
Constants.INSTALL_TYPES.TestRelease,
|
||||||
|
release.urls,
|
||||||
|
false,
|
||||||
|
latestVersion,
|
||||||
|
appPlatform
|
||||||
|
);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
errorHandler(error);
|
errorHandler(error);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
errorHandler(error);
|
errorHandler(error);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -45,10 +49,10 @@ class SelectAppPlatform extends IPCContainer {
|
|||||||
handleTestClicked = () => {
|
handleTestClicked = () => {
|
||||||
this.props.setInstallTestActive(true);
|
this.props.setInstallTestActive(true);
|
||||||
this.props.setAllowDownload(true);
|
this.props.setAllowDownload(true);
|
||||||
this.grabLatestRelease(Constants.LINUX_SELECTABLE_PLATFORMS[this.state.Selected])
|
this.grabLatestRelease(Constants.LINUX_SELECTABLE_PLATFORMS[this.state.Selected]);
|
||||||
};
|
};
|
||||||
|
|
||||||
handleChanged = e => {
|
handleChanged = (e) => {
|
||||||
this.setState({
|
this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
Selected: Constants.LINUX_SELECTABLE_PLATFORMS.indexOf(e.target.value),
|
Selected: Constants.LINUX_SELECTABLE_PLATFORMS.indexOf(e.target.value),
|
||||||
@@ -57,36 +61,43 @@ class SelectAppPlatform extends IPCContainer {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<Box dxDark dxStyle={{padding: 'var(--default_spacing)'}}>
|
<Box dxDark dxStyle={{ padding: 'var(--default_spacing)' }}>
|
||||||
<h1 className={'SAPHeading'}>Select Linux Platform</h1>
|
<h1 className={'SAPHeading'}>Select Linux Platform</h1>
|
||||||
<div className={'SAPContent'}>
|
<div className={'SAPContent'}>
|
||||||
<p>Repertory was unable to detect your Linux distribution. Please select one of the following and click <b>Test</b> to continue:</p>
|
<p>
|
||||||
|
Repertory was unable to detect your Linux distribution. Please select one of the
|
||||||
|
following and click <b>Test</b> to continue:
|
||||||
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div className={'SAPActions'}>
|
<div className={'SAPActions'}>
|
||||||
<DropDown changed={this.handleChanged}
|
<DropDown
|
||||||
disabled={this.props.InstallTestActive}
|
changed={this.handleChanged}
|
||||||
items={Constants.LINUX_SELECTABLE_PLATFORMS}
|
disabled={this.props.InstallTestActive}
|
||||||
selected={Constants.LINUX_SELECTABLE_PLATFORMS[this.state.Selected]}/>
|
items={Constants.LINUX_SELECTABLE_PLATFORMS}
|
||||||
<Button clicked={this.handleTestClicked}
|
selected={Constants.LINUX_SELECTABLE_PLATFORMS[this.state.Selected]}
|
||||||
disabled={this.props.InstallTestActive}>Test</Button>
|
/>
|
||||||
|
<Button clicked={this.handleTestClicked} disabled={this.props.InstallTestActive}>
|
||||||
|
Test
|
||||||
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = (state) => {
|
||||||
return {
|
return {
|
||||||
InstallTestActive: state.install.InstallTestActive,
|
InstallTestActive: state.install.InstallTestActive,
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
downloadItem: (name, type, urls, isWinFSP, testVersion, appPlatform) => dispatch(downloadItem(name, type, urls, isWinFSP, testVersion, appPlatform)),
|
downloadItem: (name, type, urls, isWinFSP, testVersion, appPlatform) =>
|
||||||
notifyError: msg => dispatch(notifyError(msg)),
|
dispatch(downloadItem(name, type, urls, isWinFSP, testVersion, appPlatform)),
|
||||||
setAllowDownload: allow => dispatch(setAllowDownload(allow)),
|
notifyError: (msg) => dispatch(notifyError(msg)),
|
||||||
setInstallTestActive: active => dispatch(setInstallTestActive(active)),
|
setAllowDownload: (allow) => dispatch(setAllowDownload(allow)),
|
||||||
|
setInstallTestActive: (active) => dispatch(setInstallTestActive(active)),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,59 +1,71 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import './SkynetExport.css';
|
import './SkynetExport.css';
|
||||||
import CheckboxTree from 'react-checkbox-tree';
|
import CheckboxTree from 'react-checkbox-tree';
|
||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import IPCContainer from '../IPCContainer/IPCContainer';
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||||
import {notifyApplicationBusy} from '../../redux/actions/common_actions';
|
import { notifyApplicationBusy } from '../../redux/actions/common_actions';
|
||||||
import {notifyError, notifyInfo} from '../../redux/actions/error_actions';
|
import { notifyError, notifyInfo } from '../../redux/actions/error_actions';
|
||||||
import Box from '../../components/UI/Box/Box';
|
import Box from '../../components/UI/Box/Box';
|
||||||
import {displaySkynetExport} from '../../redux/actions/skynet_actions';
|
import { displaySkynetExport } from '../../redux/actions/skynet_actions';
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import {
|
import {
|
||||||
faCheckSquare, faChevronDown,
|
faCheckSquare,
|
||||||
faChevronRight, faFile, faFolder, faFolderOpen,
|
faChevronDown,
|
||||||
faHSquare, faMinusSquare, faPlusSquare,
|
faChevronRight,
|
||||||
faSquare
|
faFile,
|
||||||
|
faFolder,
|
||||||
|
faFolderOpen,
|
||||||
|
faHSquare,
|
||||||
|
faMinusSquare,
|
||||||
|
faPlusSquare,
|
||||||
|
faSquare,
|
||||||
} from '@fortawesome/free-solid-svg-icons';
|
} from '@fortawesome/free-solid-svg-icons';
|
||||||
import Button from '../../components/UI/Button/Button';
|
import Button from '../../components/UI/Button/Button';
|
||||||
|
|
||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = (state) => {
|
||||||
return {
|
return {
|
||||||
AppBusy: state.common.AppBusy,
|
AppBusy: state.common.AppBusy,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
displaySkynetExport: display => dispatch(displaySkynetExport(display)),
|
displaySkynetExport: (display) => dispatch(displaySkynetExport(display)),
|
||||||
notifyApplicationBusy: busy => dispatch(notifyApplicationBusy(busy, true)),
|
notifyApplicationBusy: (busy) => dispatch(notifyApplicationBusy(busy, true)),
|
||||||
notifyError: msg => dispatch(notifyError(msg)),
|
notifyError: (msg) => dispatch(notifyError(msg)),
|
||||||
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg, true, 'skynet_export', 'json')),
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCContainer {
|
export default connect(
|
||||||
state = {
|
mapStateToProps,
|
||||||
checked: [],
|
mapDispatchToProps
|
||||||
clicked: {},
|
)(
|
||||||
expanded: [],
|
class extends IPCContainer {
|
||||||
nodes: [],
|
state = {
|
||||||
second_stage: false,
|
checked: [],
|
||||||
}
|
clicked: {},
|
||||||
|
expanded: [],
|
||||||
|
nodes: [],
|
||||||
|
second_stage: false,
|
||||||
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
this.setRequestHandler(Constants.IPC_Grab_Skynet_Tree_Reply, this.onGrabSkynetTreeReply);
|
this.setRequestHandler(Constants.IPC_Grab_Skynet_Tree_Reply, this.onGrabSkynetTreeReply);
|
||||||
this.setRequestHandler(Constants.IPC_Export_Skylinks_Reply, this.onExportSkylinksReply);
|
this.setRequestHandler(Constants.IPC_Export_Skylinks_Reply, this.onExportSkylinksReply);
|
||||||
this.sendRequest(Constants.IPC_Grab_Skynet_Tree, {Version: this.props.version});
|
this.sendRequest(Constants.IPC_Grab_Skynet_Tree, {
|
||||||
}
|
Version: this.props.version,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
componentWillUnmount() {
|
||||||
super.componentWillUnmount();
|
super.componentWillUnmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
createNodes = items => {
|
createNodes = (items) => {
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
name: '',
|
name: '',
|
||||||
path: '',
|
path: '',
|
||||||
@@ -61,175 +73,250 @@ export default connect(mapStateToProps, mapDispatchToProps)(class extends IPCCon
|
|||||||
children: [],
|
children: [],
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
const ret = [];
|
const ret = [];
|
||||||
for (const item of items) {
|
for (const item of items) {
|
||||||
const treeItem = {
|
const treeItem = {
|
||||||
label: item.name,
|
label: item.name,
|
||||||
path: item.path,
|
path: item.path,
|
||||||
value: item.name === '/' ? 0 : item.path ? item.path : JSON.stringify(item),
|
value: item.name === '/' ? 0 : item.path ? item.path : JSON.stringify(item),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (item.directory) {
|
if (item.directory) {
|
||||||
treeItem.children = this.createNodes(item.children);
|
treeItem.children = this.createNodes(item.children);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.push(treeItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
ret.push(treeItem);
|
return ret;
|
||||||
}
|
};
|
||||||
|
|
||||||
return ret;
|
handleNavigation = () => {
|
||||||
}
|
if (this.state.second_stage) {
|
||||||
|
this.props.notifyApplicationBusy(true);
|
||||||
handleNavigation = () => {
|
this.sendRequest(Constants.IPC_Export_Skylinks, {
|
||||||
if (this.state.second_stage) {
|
Version: this.props.version,
|
||||||
this.props.notifyApplicationBusy(true);
|
Paths: this.state.checked,
|
||||||
this.sendRequest(Constants.IPC_Export_Skylinks, {
|
|
||||||
Version: this.props.version,
|
|
||||||
Paths: this.state.checked,
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
if (this.state.checked.length === 0) {
|
|
||||||
this.props.notifyError('No files have been checked');
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
second_stage: true,
|
|
||||||
});
|
});
|
||||||
|
} else {
|
||||||
|
if (this.state.checked.length === 0) {
|
||||||
|
this.props.notifyError('No files have been checked');
|
||||||
|
} else {
|
||||||
|
this.setState({
|
||||||
|
second_stage: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
onExportSkylinksReply = (_, arg) => {
|
onExportSkylinksReply = (_, arg) => {
|
||||||
this.props.notifyApplicationBusy(false);
|
this.props.notifyApplicationBusy(false);
|
||||||
if (arg.data.Success) {
|
if (arg.data.Success) {
|
||||||
this.setState({
|
this.setState(
|
||||||
checked: [],
|
|
||||||
clicked: {},
|
|
||||||
expanded: [],
|
|
||||||
nodes: [],
|
|
||||||
second_stage: false,
|
|
||||||
}, () => {
|
|
||||||
this.props.notifyInfo('Skylink Exports', '!alternate!!copyable!' + JSON.stringify(arg.data.Result.success, null, 2));
|
|
||||||
this.sendRequest(Constants.IPC_Grab_Skynet_Tree, {Version: this.props.version});
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.props.notifyError(arg.data.Error);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
onGrabSkynetTreeReply = (_, arg) => {
|
|
||||||
if (arg.data.Success) {
|
|
||||||
this.setState({
|
|
||||||
checked: [],
|
|
||||||
expanded: [0],
|
|
||||||
nodes: this.createNodes(arg.data.Result),
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
this.setState({
|
|
||||||
checked: [],
|
|
||||||
expanded: [],
|
|
||||||
nodes: [],
|
|
||||||
}, () => {
|
|
||||||
this.props.notifyError(arg.data.Error);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
render() {
|
|
||||||
return this.props.AppBusy ? (<div/>) : (
|
|
||||||
<Box dxDark dxStyle={{
|
|
||||||
height: '90vh',
|
|
||||||
padding: 'var(--default_spacing)',
|
|
||||||
width: 'calc(100vw - (var(--default_spacing) * 4)'
|
|
||||||
}}>
|
|
||||||
<div
|
|
||||||
style={{
|
|
||||||
float: 'right',
|
|
||||||
margin: 0,
|
|
||||||
padding: 0,
|
|
||||||
marginTop: '-4px',
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
display: 'block'
|
|
||||||
}}>
|
|
||||||
<a href={'#'}
|
|
||||||
onClick={() => this.props.displaySkynetExport(false)}
|
|
||||||
style={{cursor: 'pointer'}}>X</a>
|
|
||||||
</div>
|
|
||||||
<h1
|
|
||||||
className={'SkynetExportHeading'}>{this.state.second_stage ? 'Verify Exports' : 'Export Files'}</h1>
|
|
||||||
<div className={this.state.second_stage ? 'SkynetExportList' : 'SkynetExportTree'}>
|
|
||||||
{
|
{
|
||||||
this.state.second_stage ?
|
checked: [],
|
||||||
this.state.checked.map(path => {
|
clicked: {},
|
||||||
|
expanded: [],
|
||||||
|
nodes: [],
|
||||||
|
second_stage: false,
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.props.notifyInfo(
|
||||||
|
'Skylink Exports',
|
||||||
|
'!alternate!!copyable!' + JSON.stringify(arg.data.Result.success, null, 2)
|
||||||
|
);
|
||||||
|
this.sendRequest(Constants.IPC_Grab_Skynet_Tree, {
|
||||||
|
Version: this.props.version,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
this.props.notifyError(arg.data.Error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
onGrabSkynetTreeReply = (_, arg) => {
|
||||||
|
if (arg.data.Success) {
|
||||||
|
this.setState({
|
||||||
|
checked: [],
|
||||||
|
expanded: [0],
|
||||||
|
nodes: this.createNodes(arg.data.Result),
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
this.setState(
|
||||||
|
{
|
||||||
|
checked: [],
|
||||||
|
expanded: [],
|
||||||
|
nodes: [],
|
||||||
|
},
|
||||||
|
() => {
|
||||||
|
this.props.notifyError(arg.data.Error);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
render() {
|
||||||
|
return this.props.AppBusy ? (
|
||||||
|
<div />
|
||||||
|
) : (
|
||||||
|
<Box
|
||||||
|
dxDark
|
||||||
|
dxStyle={{
|
||||||
|
height: '90vh',
|
||||||
|
padding: 'var(--default_spacing)',
|
||||||
|
width: 'calc(100vw - (var(--default_spacing) * 4)',
|
||||||
|
}}>
|
||||||
|
<div
|
||||||
|
style={{
|
||||||
|
float: 'right',
|
||||||
|
margin: 0,
|
||||||
|
padding: 0,
|
||||||
|
marginTop: '-4px',
|
||||||
|
boxSizing: 'border-box',
|
||||||
|
display: 'block',
|
||||||
|
}}>
|
||||||
|
<a
|
||||||
|
href={'#'}
|
||||||
|
onClick={() => this.props.displaySkynetExport(false)}
|
||||||
|
style={{ cursor: 'pointer' }}>
|
||||||
|
X
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<h1 className={'SkynetExportHeading'}>
|
||||||
|
{this.state.second_stage ? 'Verify Exports' : 'Export Files'}
|
||||||
|
</h1>
|
||||||
|
<div className={this.state.second_stage ? 'SkynetExportList' : 'SkynetExportTree'}>
|
||||||
|
{this.state.second_stage ? (
|
||||||
|
this.state.checked.map((path) => {
|
||||||
return (
|
return (
|
||||||
<input readOnly
|
<input
|
||||||
className={'ConfigurationItemInput'}
|
readOnly
|
||||||
key={path}
|
className={'ConfigurationItemInput'}
|
||||||
style={{width: '100%', marginBottom: 'var(--default_spacing)'}}
|
key={path}
|
||||||
type={'text'}
|
style={{
|
||||||
value={path}/>
|
width: '100%',
|
||||||
|
marginBottom: 'var(--default_spacing)',
|
||||||
|
}}
|
||||||
|
type={'text'}
|
||||||
|
value={path}
|
||||||
|
/>
|
||||||
);
|
);
|
||||||
})
|
})
|
||||||
: (
|
) : (
|
||||||
<CheckboxTree checked={this.state.checked}
|
<CheckboxTree
|
||||||
expanded={this.state.expanded}
|
checked={this.state.checked}
|
||||||
expandOnClick
|
expanded={this.state.expanded}
|
||||||
showExpandAll
|
expandOnClick
|
||||||
icons={{
|
showExpandAll
|
||||||
check: <FontAwesomeIcon icon={faCheckSquare} fixedWidth
|
icons={{
|
||||||
style={{padding: 0, margin: 0}}/>,
|
check: (
|
||||||
uncheck: <FontAwesomeIcon icon={faSquare} fixedWidth
|
<FontAwesomeIcon
|
||||||
style={{padding: 0, margin: 0}}/>,
|
icon={faCheckSquare}
|
||||||
halfCheck: <FontAwesomeIcon icon={faHSquare} fixedWidth
|
fixedWidth
|
||||||
style={{padding: 0, margin: 0}}/>,
|
style={{ padding: 0, margin: 0 }}
|
||||||
expandClose: <FontAwesomeIcon icon={faChevronRight} fixedWidth
|
/>
|
||||||
style={{padding: 0, margin: 0}}/>,
|
),
|
||||||
expandOpen: <FontAwesomeIcon icon={faChevronDown} fixedWidth
|
uncheck: (
|
||||||
style={{padding: 0, margin: 0}}/>,
|
<FontAwesomeIcon icon={faSquare} fixedWidth style={{ padding: 0, margin: 0 }} />
|
||||||
expandAll: <FontAwesomeIcon icon={faPlusSquare} fixedWidth
|
),
|
||||||
style={{padding: 0, margin: 0}}/>,
|
halfCheck: (
|
||||||
collapseAll: <FontAwesomeIcon icon={faMinusSquare} fixedWidth
|
<FontAwesomeIcon
|
||||||
style={{padding: 0, margin: 0}}/>,
|
icon={faHSquare}
|
||||||
parentClose: <FontAwesomeIcon icon={faFolder}
|
fixedWidth
|
||||||
fixedWidth
|
style={{ padding: 0, margin: 0 }}
|
||||||
color={'var(--heading_text_color)'}
|
/>
|
||||||
style={{padding: 0, margin: 0}}/>,
|
),
|
||||||
parentOpen: <FontAwesomeIcon icon={faFolderOpen}
|
expandClose: (
|
||||||
fixedWidth
|
<FontAwesomeIcon
|
||||||
color={'var(--heading_text_color)'}
|
icon={faChevronRight}
|
||||||
style={{padding: 0, margin: 0}}/>,
|
fixedWidth
|
||||||
leaf: <FontAwesomeIcon icon={faFile}
|
style={{ padding: 0, margin: 0 }}
|
||||||
fixedWidth
|
/>
|
||||||
color={'var(--text_color)'}
|
),
|
||||||
style={{padding: 0, margin: 0}}/>
|
expandOpen: (
|
||||||
}}
|
<FontAwesomeIcon
|
||||||
nodes={this.state.nodes}
|
icon={faChevronDown}
|
||||||
onClick={clicked => this.setState({clicked})}
|
fixedWidth
|
||||||
onCheck={checked => this.setState({checked})}
|
style={{ padding: 0, margin: 0 }}
|
||||||
onExpand={expanded => this.setState({expanded})}/>
|
/>
|
||||||
)
|
),
|
||||||
}
|
expandAll: (
|
||||||
</div>
|
<FontAwesomeIcon
|
||||||
<div style={{display: 'flex', justifyContent: 'flex-end'}}>
|
icon={faPlusSquare}
|
||||||
{
|
fixedWidth
|
||||||
this.state.second_stage ?
|
style={{ padding: 0, margin: 0 }}
|
||||||
<Button buttonStyles={{
|
/>
|
||||||
|
),
|
||||||
|
collapseAll: (
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon={faMinusSquare}
|
||||||
|
fixedWidth
|
||||||
|
style={{ padding: 0, margin: 0 }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
parentClose: (
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon={faFolder}
|
||||||
|
fixedWidth
|
||||||
|
color={'var(--heading_text_color)'}
|
||||||
|
style={{ padding: 0, margin: 0 }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
parentOpen: (
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon={faFolderOpen}
|
||||||
|
fixedWidth
|
||||||
|
color={'var(--heading_text_color)'}
|
||||||
|
style={{ padding: 0, margin: 0 }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
leaf: (
|
||||||
|
<FontAwesomeIcon
|
||||||
|
icon={faFile}
|
||||||
|
fixedWidth
|
||||||
|
color={'var(--text_color)'}
|
||||||
|
style={{ padding: 0, margin: 0 }}
|
||||||
|
/>
|
||||||
|
),
|
||||||
|
}}
|
||||||
|
nodes={this.state.nodes}
|
||||||
|
onClick={(clicked) => this.setState({ clicked })}
|
||||||
|
onCheck={(checked) => this.setState({ checked })}
|
||||||
|
onExpand={(expanded) => this.setState({ expanded })}
|
||||||
|
/>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
<div style={{ display: 'flex', justifyContent: 'flex-end' }}>
|
||||||
|
{this.state.second_stage ? (
|
||||||
|
<Button
|
||||||
|
buttonStyles={{
|
||||||
|
height: 'auto',
|
||||||
|
marginLeft: 'var(--default_spacing)',
|
||||||
|
marginTop: 'var(--default_spacing)',
|
||||||
|
width: 'auto',
|
||||||
|
}}
|
||||||
|
clicked={() =>
|
||||||
|
this.setState({
|
||||||
|
second_stage: false,
|
||||||
|
})
|
||||||
|
}>
|
||||||
|
{'Back'}
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
<Button
|
||||||
|
buttonStyles={{
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
marginLeft: 'var(--default_spacing)',
|
marginLeft: 'var(--default_spacing)',
|
||||||
marginTop: 'var(--default_spacing)',
|
marginTop: 'var(--default_spacing)',
|
||||||
width: 'auto'
|
width: 'auto',
|
||||||
}} clicked={() => this.setState({
|
}}
|
||||||
second_stage: false,
|
clicked={this.handleNavigation}>
|
||||||
})}>{'Back'}</Button> :
|
{this.state.second_stage ? 'Export' : 'Next'}
|
||||||
null
|
</Button>
|
||||||
}
|
</div>
|
||||||
<Button buttonStyles={{
|
</Box>
|
||||||
height: 'auto',
|
);
|
||||||
marginLeft: 'var(--default_spacing)',
|
}
|
||||||
marginTop: 'var(--default_spacing)',
|
|
||||||
width: 'auto'
|
|
||||||
}}
|
|
||||||
clicked={this.handleNavigation}>{this.state.second_stage ? 'Export' : 'Next'}</Button>
|
|
||||||
</div>
|
|
||||||
</Box>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|||||||
@@ -1,32 +1,43 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import './Import.css'
|
import './Import.css';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
|
|
||||||
const Import = ({data}) => {
|
const Import = ({ data }) => {
|
||||||
return (
|
return (
|
||||||
<div className={'ImportOwner'}>
|
<div className={'ImportOwner'}>
|
||||||
<input readOnly
|
<input
|
||||||
className={'ConfigurationItemInput'}
|
readOnly
|
||||||
style={{
|
className={'ConfigurationItemInput'}
|
||||||
maxWidth: 'calc(33.33% - var(--default_spacing)',
|
style={{
|
||||||
marginRight: 'var(--default_spacing)'
|
maxWidth: 'calc(33.33% - var(--default_spacing)',
|
||||||
}}
|
marginRight: 'var(--default_spacing)',
|
||||||
type={'text'}
|
}}
|
||||||
value={data.directory}/>
|
type={'text'}
|
||||||
<input readOnly
|
value={data.directory}
|
||||||
className={'ConfigurationItemInput'}
|
/>
|
||||||
style={{maxWidth: 'calc(33.33% - calc(var(--default_spacing) / 2))'}}
|
<input
|
||||||
type={'text'}
|
readOnly
|
||||||
value={data.skylink}/>
|
className={'ConfigurationItemInput'}
|
||||||
<input readOnly
|
style={{ maxWidth: 'calc(33.33% - calc(var(--default_spacing) / 2))' }}
|
||||||
className={'ConfigurationItemInput'}
|
type={'text'}
|
||||||
style={{
|
value={data.skylink}
|
||||||
maxWidth: 'calc(33.33% - calc(var(--default_spacing) / 2))',
|
/>
|
||||||
marginLeft: 'var(--default_spacing)'
|
<input
|
||||||
}}
|
readOnly
|
||||||
type={'text'}
|
className={'ConfigurationItemInput'}
|
||||||
value={data.token}/>
|
style={{
|
||||||
|
maxWidth: 'calc(33.33% - calc(var(--default_spacing) / 2))',
|
||||||
|
marginLeft: 'var(--default_spacing)',
|
||||||
|
}}
|
||||||
|
type={'text'}
|
||||||
|
value={data.token}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
Import.propTypes = {
|
||||||
|
data: PropTypes.object,
|
||||||
|
};
|
||||||
|
|
||||||
export default Import;
|
export default Import;
|
||||||
|
|||||||
@@ -1,32 +1,42 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import './ImportList.css'
|
import './ImportList.css';
|
||||||
import Import from './Import/Import'
|
import Import from './Import/Import';
|
||||||
|
import PropTypes from 'prop-types';
|
||||||
import Text from '../../../components/UI/Text/Text';
|
import Text from '../../../components/UI/Text/Text';
|
||||||
|
|
||||||
const ImportList = ({imports_array}) => {
|
const ImportList = ({ imports_array }) => {
|
||||||
let key = 0;
|
let key = 0;
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<div className={'ImportListHeader'}>
|
<div className={'ImportListHeader'}>
|
||||||
<Text type={'Heading1'} text={'Directory'}
|
<Text
|
||||||
style={{minWidth: '33.33%', maxWidth: '33.33%'}}/>
|
type={'Heading1'}
|
||||||
<Text type={'Heading1'} text={'Skylink'} style={{minWidth: '33.33%', maxWidth: '33.33%'}}/>
|
text={'Directory'}
|
||||||
<Text type={'Heading1'} text={'Token'} style={{minWidth: '33.33%', maxWidth: '33.33%'}}/>
|
style={{ minWidth: '33.33%', maxWidth: '33.33%' }}
|
||||||
|
/>
|
||||||
|
<Text
|
||||||
|
type={'Heading1'}
|
||||||
|
text={'Skylink'}
|
||||||
|
style={{ minWidth: '33.33%', maxWidth: '33.33%' }}
|
||||||
|
/>
|
||||||
|
<Text type={'Heading1'} text={'Token'} style={{ minWidth: '33.33%', maxWidth: '33.33%' }} />
|
||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr />
|
||||||
<div className={'ImportListOwner'}>
|
<div className={'ImportListOwner'}>
|
||||||
{
|
{imports_array.map((data) => {
|
||||||
imports_array.map(data => {
|
return (
|
||||||
return (
|
<div key={'import_' + key++}>
|
||||||
<div key={'import_' + key++}>
|
<Import data={data} />
|
||||||
<Import data={data}/>
|
</div>
|
||||||
</div>
|
);
|
||||||
);
|
})}
|
||||||
})
|
|
||||||
}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ImportList.propTypes = {
|
||||||
|
imports_array: PropTypes.array.isRequired,
|
||||||
|
};
|
||||||
|
|
||||||
export default ImportList;
|
export default ImportList;
|
||||||
|
|||||||
@@ -1,228 +1,277 @@
|
|||||||
import React from 'react'
|
import React from 'react';
|
||||||
import {connect} from 'react-redux';
|
import { connect } from 'react-redux';
|
||||||
import './SkynetImport.css'
|
import './SkynetImport.css';
|
||||||
import Box from '../../components/UI/Box/Box';
|
import Box from '../../components/UI/Box/Box';
|
||||||
import Button from '../../components/UI/Button/Button';
|
import Button from '../../components/UI/Button/Button';
|
||||||
import {displaySkynetImport} from '../../redux/actions/skynet_actions';
|
import { displaySkynetImport } from '../../redux/actions/skynet_actions';
|
||||||
import ImportList from './ImportList/ImportList'
|
import ImportList from './ImportList/ImportList';
|
||||||
import IPCContainer from '../IPCContainer/IPCContainer';
|
import IPCContainer from '../IPCContainer/IPCContainer';
|
||||||
import {notifyApplicationBusy} from '../../redux/actions/common_actions';
|
import { notifyApplicationBusy } from '../../redux/actions/common_actions';
|
||||||
import {
|
import { notifyError, notifyInfo } from '../../redux/actions/error_actions';
|
||||||
notifyError,
|
import { promptLocationAndReadFile } from '../../utils';
|
||||||
notifyInfo
|
|
||||||
} from '../../redux/actions/error_actions';
|
|
||||||
|
|
||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
const mapStateToProps = state => {
|
const mapStateToProps = (state) => {
|
||||||
return {
|
return {
|
||||||
AppBusy: state.common.AppBusy,
|
AppBusy: state.common.AppBusy,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const mapDispatchToProps = dispatch => {
|
const mapDispatchToProps = (dispatch) => {
|
||||||
return {
|
return {
|
||||||
displaySkynetImport: display => dispatch(displaySkynetImport(display)),
|
displaySkynetImport: (display) => dispatch(displaySkynetImport(display)),
|
||||||
notifyApplicationBusy: busy => dispatch(notifyApplicationBusy(busy, true)),
|
notifyApplicationBusy: (busy) => dispatch(notifyApplicationBusy(busy, true)),
|
||||||
notifyError: msg => dispatch(notifyError(msg)),
|
notifyError: (msg) => dispatch(notifyError(msg)),
|
||||||
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
notifyInfo: (title, msg) => dispatch(notifyInfo(title, msg)),
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export default connect(mapStateToProps, mapDispatchToProps)(class SkynetImport extends IPCContainer {
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(
|
||||||
|
class SkynetImport extends IPCContainer {
|
||||||
|
state = {
|
||||||
|
import_text: '',
|
||||||
|
imports_array: [],
|
||||||
|
second_stage: false,
|
||||||
|
};
|
||||||
|
|
||||||
state = {
|
componentDidMount() {
|
||||||
import_text: '',
|
this.setRequestHandler(Constants.IPC_Import_Skylinks_Reply, this.onImportSkylinksReply);
|
||||||
imports_array: [],
|
}
|
||||||
second_stage: false,
|
|
||||||
};
|
|
||||||
|
|
||||||
componentDidMount() {
|
componentWillUnmount() {
|
||||||
this.setRequestHandler(Constants.IPC_Import_Skylinks_Reply, this.onImportSkylinksReply);
|
super.componentWillUnmount();
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount() {
|
displaySyntax = () => {
|
||||||
super.componentWillUnmount();
|
const msg =
|
||||||
}
|
'!alternate!To import Skylinks into the root directory, list each Skylink on a new line:\n' +
|
||||||
|
' AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA\n' +
|
||||||
|
' AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg\n' +
|
||||||
|
'\n' +
|
||||||
|
'To import Skylinks into new or existing directories, use the following syntax:\n' +
|
||||||
|
' directory="/my/sub/dir",skylink="AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA"\n' +
|
||||||
|
' directory="/my/sub/dir2",skylink="AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg"\n' +
|
||||||
|
'\n' +
|
||||||
|
'You can also specify a password if this in an encrypted Repertory Skylink:\n' +
|
||||||
|
' directory="/my/sub/dir",skylink="AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",token="My Password"\n' +
|
||||||
|
' directory="/my/sub/dir",skylink="AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg",token="My Password"\n' +
|
||||||
|
'\n' +
|
||||||
|
'To import Skylinks using JSON syntax:\n' +
|
||||||
|
' [\n' +
|
||||||
|
' {\n' +
|
||||||
|
' "directory": "/",\n' +
|
||||||
|
' "skylink": "AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",\n' +
|
||||||
|
' "token": "My Password"\n' +
|
||||||
|
' },\n' +
|
||||||
|
' {\n' +
|
||||||
|
' "directory": "/my/sub/dir",\n' +
|
||||||
|
' "skylink": "AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg",\n' +
|
||||||
|
' "token": "My Password"\n' +
|
||||||
|
' }\n' +
|
||||||
|
' ]';
|
||||||
|
this.props.notifyInfo('Import Syntax', msg);
|
||||||
|
};
|
||||||
|
|
||||||
displaySyntax = () => {
|
handleLoadFile = () => {
|
||||||
const msg = '!alternate!To import Skylinks into the root directory, list each Skylink on a new line:\n' +
|
const data = promptLocationAndReadFile(this.props.notifyError);
|
||||||
' AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA\n' +
|
if (data) {
|
||||||
' AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg\n' +
|
this.setState({ import_text: data });
|
||||||
'\n' +
|
|
||||||
'To import Skylinks into new or existing directories, use the following syntax:\n' +
|
|
||||||
' directory="/my/sub/dir",skylink="AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA"\n' +
|
|
||||||
' directory="/my/sub/dir2",skylink="AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg"\n' +
|
|
||||||
'\n' +
|
|
||||||
'You can also specify a password if this in an encrypted Repertory Skylink:\n' +
|
|
||||||
' directory="/my/sub/dir",skylink="AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",token="My Password"\n' +
|
|
||||||
' directory="/my/sub/dir",skylink="AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg",token="My Password"\n' +
|
|
||||||
'\n' +
|
|
||||||
'To import Skylinks using JSON syntax:\n' +
|
|
||||||
' [\n' +
|
|
||||||
' {\n' +
|
|
||||||
' "directory": "/",\n' +
|
|
||||||
' "skylink": "AACeCiD6WQG6DzDcCdIu3cFPSxMUMoQPx46NYSyijNMKUA",\n' +
|
|
||||||
' "token": "My Password"\n' +
|
|
||||||
' },\n' +
|
|
||||||
' {\n' +
|
|
||||||
' "directory": "/my/sub/dir",\n' +
|
|
||||||
' "skylink": "AACyjmDGoHqY7mTaxi-rkpnKUJGZK1B4UhrF74Nv6tY6Cg",\n' +
|
|
||||||
' "token": "My Password"\n' +
|
|
||||||
' }\n' +
|
|
||||||
' ]';
|
|
||||||
this.props.notifyInfo('Import Syntax', msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
handleNavigation = () => {
|
|
||||||
if (this.state.second_stage) {
|
|
||||||
try {
|
|
||||||
this.props.notifyApplicationBusy(true);
|
|
||||||
this.sendRequest(Constants.IPC_Import_Skylinks, {
|
|
||||||
Version: this.props.version,
|
|
||||||
JsonArray: this.state.imports_array,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.props.notifyApplicationBusy(false);
|
|
||||||
this.props.notifyError(e);
|
|
||||||
}
|
}
|
||||||
} else {
|
};
|
||||||
const items = this.state.import_text.split('\n');
|
|
||||||
let importsArray = [];
|
handleNavigation = () => {
|
||||||
try {
|
if (this.state.second_stage) {
|
||||||
for (let item of items) {
|
try {
|
||||||
item = item.trim();
|
this.props.notifyApplicationBusy(true);
|
||||||
if (item.startsWith('[')) {
|
this.sendRequest(Constants.IPC_Import_Skylinks, {
|
||||||
importsArray = JSON.parse(this.state.import_text.trim());
|
Version: this.props.version,
|
||||||
break;
|
JsonArray: this.state.imports_array,
|
||||||
} else if (item.indexOf('=') >= 0) {
|
});
|
||||||
const parts = item.split(',')
|
} catch (e) {
|
||||||
let importItem = {
|
this.props.notifyApplicationBusy(false);
|
||||||
directory: '/',
|
this.props.notifyError(e);
|
||||||
skylink: '',
|
}
|
||||||
token: '',
|
} else {
|
||||||
};
|
const items = this.state.import_text.split('\n');
|
||||||
for (let part of parts) {
|
let importsArray = [];
|
||||||
part = part.trim();
|
try {
|
||||||
const pair = part.split('=');
|
for (let item of items) {
|
||||||
if (pair.length !== 2) {
|
item = item.trim();
|
||||||
|
if (item.startsWith('[')) {
|
||||||
|
importsArray = JSON.parse(this.state.import_text.trim());
|
||||||
|
break;
|
||||||
|
} else if (item.indexOf('=') >= 0) {
|
||||||
|
const parts = item.split(',');
|
||||||
|
let importItem = {
|
||||||
|
directory: '/',
|
||||||
|
skylink: '',
|
||||||
|
token: '',
|
||||||
|
};
|
||||||
|
for (let part of parts) {
|
||||||
|
part = part.trim();
|
||||||
|
const pair = part.split('=');
|
||||||
|
if (pair.length !== 2) {
|
||||||
|
throw new Error('Invalid syntax for import: directory="",skylink="",token=""');
|
||||||
|
}
|
||||||
|
importItem = {
|
||||||
|
...importItem,
|
||||||
|
[pair[0].trim()]: pair[1].trim().replace(/"/g, ''),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (!importItem.skylink) {
|
||||||
throw new Error('Invalid syntax for import: directory="",skylink="",token=""');
|
throw new Error('Invalid syntax for import: directory="",skylink="",token=""');
|
||||||
}
|
}
|
||||||
importItem = {
|
importsArray.push(importItem);
|
||||||
...importItem,
|
} else if (item.length > 0) {
|
||||||
[pair[0].trim()]: pair[1].trim().replace(/"/g, ''),
|
importsArray.push({
|
||||||
};
|
directory: '/',
|
||||||
|
skylink: item,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
if (!importItem.skylink) {
|
|
||||||
throw new Error('Invalid syntax for import: directory="",skylink="",token=""');
|
|
||||||
}
|
|
||||||
importsArray.push(importItem);
|
|
||||||
} else if (item.length > 0) {
|
|
||||||
importsArray.push({
|
|
||||||
directory: '/',
|
|
||||||
skylink: item,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (importsArray.length === 0) {
|
if (importsArray.length === 0) {
|
||||||
throw new Error('Nothing to import');
|
throw new Error('Nothing to import');
|
||||||
|
}
|
||||||
|
this.setState({
|
||||||
|
imports_array: importsArray,
|
||||||
|
second_stage: true,
|
||||||
|
});
|
||||||
|
} catch (e) {
|
||||||
|
this.props.notifyError(e);
|
||||||
}
|
}
|
||||||
this.setState({
|
|
||||||
imports_array: importsArray,
|
|
||||||
second_stage: true,
|
|
||||||
});
|
|
||||||
} catch (e) {
|
|
||||||
this.props.notifyError(e);
|
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
|
||||||
|
|
||||||
onImportSkylinksReply = (_, arg) => {
|
onImportSkylinksReply = (_, arg) => {
|
||||||
this.props.notifyApplicationBusy(false);
|
this.props.notifyApplicationBusy(false);
|
||||||
if (arg.data.Success) {
|
if (arg.data.Success) {
|
||||||
const failedImportsArray = this.state.imports_array.filter(i => {
|
const failedImportsArray = this.state.imports_array.filter((i) => {
|
||||||
return arg.data.Result.failed.includes(i.skylink);
|
return arg.data.Result.failed.includes(i.skylink);
|
||||||
});
|
});
|
||||||
const count = this.state.imports_array.length;
|
const count = this.state.imports_array.length;
|
||||||
this.setState({
|
this.setState(
|
||||||
import_text: failedImportsArray.length > 0 ? JSON.stringify(failedImportsArray, null, 2) : '',
|
{
|
||||||
imports_array: [],
|
import_text:
|
||||||
second_stage: false,
|
failedImportsArray.length > 0 ? JSON.stringify(failedImportsArray, null, 2) : '',
|
||||||
}, () => {
|
imports_array: [],
|
||||||
if (failedImportsArray.length > 0) {
|
second_stage: false,
|
||||||
this.props.notifyError(`Failed to import ${failedImportsArray.length} item(s)`);
|
},
|
||||||
} else {
|
() => {
|
||||||
this.props.notifyInfo('Import Result', `Successfully imported ${count} item(s)`);
|
if (failedImportsArray.length > 0) {
|
||||||
}
|
this.props.notifyError(`Failed to import ${failedImportsArray.length} item(s)`);
|
||||||
});
|
} else {
|
||||||
} else {
|
this.props.notifyInfo('Import Result', `Successfully imported ${count} item(s)`);
|
||||||
this.props.notifyError(arg.data.Error);
|
}
|
||||||
}
|
}
|
||||||
};
|
);
|
||||||
|
} else {
|
||||||
|
this.props.notifyError(arg.data.Error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return this.props.AppBusy ? (<div/>) : (
|
return this.props.AppBusy ? (
|
||||||
<Box dxDark dxStyle={{
|
<div />
|
||||||
height: 'auto',
|
) : (
|
||||||
padding: 'var(--default_spacing)',
|
<Box
|
||||||
width: 'calc(100vw - (var(--default_spacing) * 4)'
|
dxDark
|
||||||
}}>
|
dxStyle={{
|
||||||
<div
|
height: 'auto',
|
||||||
style={{
|
padding: 'var(--default_spacing)',
|
||||||
float: 'right',
|
width: 'calc(100vw - (var(--default_spacing) * 4)',
|
||||||
margin: 0,
|
|
||||||
padding: 0,
|
|
||||||
marginTop: '-4px',
|
|
||||||
boxSizing: 'border-box',
|
|
||||||
display: 'block'
|
|
||||||
}}>
|
}}>
|
||||||
<a href={'#'}
|
<div
|
||||||
onClick={() => this.props.displaySkynetImport(false)}
|
style={{
|
||||||
style={{cursor: 'pointer'}}>X</a>
|
float: 'right',
|
||||||
</div>
|
margin: 0,
|
||||||
<h1
|
padding: 0,
|
||||||
className={'SkynetImportHeading'}>{this.state.second_stage ? 'Verify Imports' : 'Import List'}</h1>
|
marginTop: '-4px',
|
||||||
{
|
boxSizing: 'border-box',
|
||||||
this.state.second_stage ? (
|
display: 'block',
|
||||||
<ImportList imports_array={this.state.imports_array}/>
|
}}>
|
||||||
|
<a
|
||||||
|
href={'#'}
|
||||||
|
onClick={() => this.props.displaySkynetImport(false)}
|
||||||
|
style={{ cursor: 'pointer' }}>
|
||||||
|
X
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<h1 className={'SkynetImportHeading'}>
|
||||||
|
{this.state.second_stage ? 'Verify Imports' : 'Import List'}
|
||||||
|
</h1>
|
||||||
|
{this.state.second_stage ? (
|
||||||
|
<ImportList imports_array={this.state.imports_array} />
|
||||||
) : (
|
) : (
|
||||||
<textarea autoFocus={true}
|
<textarea
|
||||||
className={'SkynetImportTextArea'}
|
autoFocus={true}
|
||||||
onChange={e => this.setState({
|
className={'SkynetImportTextArea'}
|
||||||
import_text: e.target.value,
|
onChange={(e) =>
|
||||||
})}
|
this.setState({
|
||||||
value={this.state.import_text}
|
import_text: e.target.value,
|
||||||
rows={10}/>
|
})
|
||||||
)
|
}
|
||||||
}
|
value={this.state.import_text}
|
||||||
<div className={'SkynetImportButtons'}>
|
rows={10}
|
||||||
<Button
|
/>
|
||||||
buttonStyles={{height: 'auto', marginTop: 'var(--default_spacing)', width: 'auto'}}
|
)}
|
||||||
clicked={this.displaySyntax}>Import Syntax...</Button>
|
<div className={'SkynetImportButtons'}>
|
||||||
<div className={'SkynetActionButtons'}>
|
<Button
|
||||||
{
|
buttonStyles={{
|
||||||
this.state.second_stage ?
|
height: 'auto',
|
||||||
<Button buttonStyles={{
|
marginTop: 'var(--default_spacing)',
|
||||||
|
width: 'auto',
|
||||||
|
}}
|
||||||
|
clicked={this.displaySyntax}>
|
||||||
|
Import Syntax...
|
||||||
|
</Button>
|
||||||
|
<div className={'SkynetActionButtons'}>
|
||||||
|
{this.state.second_stage ? (
|
||||||
|
<Button
|
||||||
|
buttonStyles={{
|
||||||
|
height: 'auto',
|
||||||
|
marginLeft: 'var(--default_spacing)',
|
||||||
|
marginTop: 'var(--default_spacing)',
|
||||||
|
width: 'auto',
|
||||||
|
}}
|
||||||
|
clicked={() =>
|
||||||
|
this.setState({
|
||||||
|
second_stage: false,
|
||||||
|
})
|
||||||
|
}>
|
||||||
|
{'Back'}
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
{!this.state.second_stage ? (
|
||||||
|
<Button
|
||||||
|
buttonStyles={{
|
||||||
|
height: 'auto',
|
||||||
|
marginLeft: 'var(--default_spacing)',
|
||||||
|
marginTop: 'var(--default_spacing)',
|
||||||
|
width: 'auto',
|
||||||
|
}}
|
||||||
|
clicked={this.handleLoadFile}>
|
||||||
|
{'Import File...'}
|
||||||
|
</Button>
|
||||||
|
) : null}
|
||||||
|
<Button
|
||||||
|
buttonStyles={{
|
||||||
height: 'auto',
|
height: 'auto',
|
||||||
marginLeft: 'var(--default_spacing)',
|
marginLeft: 'var(--default_spacing)',
|
||||||
marginTop: 'var(--default_spacing)',
|
marginTop: 'var(--default_spacing)',
|
||||||
width: 'auto'
|
width: 'auto',
|
||||||
}} clicked={() => this.setState({
|
}}
|
||||||
second_stage: false,
|
clicked={this.handleNavigation}>
|
||||||
})}>{'Back'}</Button> :
|
{this.state.second_stage ? 'Import' : 'Next'}
|
||||||
null
|
</Button>
|
||||||
}
|
</div>
|
||||||
<Button buttonStyles={{
|
|
||||||
height: 'auto',
|
|
||||||
marginLeft: 'var(--default_spacing)',
|
|
||||||
marginTop: 'var(--default_spacing)',
|
|
||||||
width: 'auto'
|
|
||||||
}}
|
|
||||||
clicked={this.handleNavigation}>{this.state.second_stage ? 'Import' : 'Next'}</Button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</Box>
|
||||||
</Box>
|
);
|
||||||
);
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import React, {Component} from 'react';
|
import React, { Component } from 'react';
|
||||||
import './Password.css';
|
import './Password.css';
|
||||||
import {faEye, faEyeSlash} from '@fortawesome/free-solid-svg-icons';
|
import PropTypes from 'prop-types';
|
||||||
import {FontAwesomeIcon} from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import { faEye, faEyeSlash } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
|
||||||
export default class Password extends Component {
|
class Password extends Component {
|
||||||
state = {
|
state = {
|
||||||
button_text: 'clear',
|
button_text: 'clear',
|
||||||
password: '',
|
password: '',
|
||||||
@@ -12,14 +13,14 @@ export default class Password extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
componentDidMount() {
|
||||||
if (!this.props.value || (this.props.value.length === 0)) {
|
if (!this.props.value || this.props.value.length === 0) {
|
||||||
this.setState({
|
this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
button_text: 'set',
|
button_text: 'set',
|
||||||
password: '',
|
password: '',
|
||||||
password2: '',
|
password2: '',
|
||||||
show_password: false,
|
show_password: false,
|
||||||
})
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
@@ -27,7 +28,7 @@ export default class Password extends Component {
|
|||||||
password: this.props.value,
|
password: this.props.value,
|
||||||
password2: '',
|
password2: '',
|
||||||
show_password: false,
|
show_password: false,
|
||||||
})
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,16 +53,19 @@ export default class Password extends Component {
|
|||||||
password2: '',
|
password2: '',
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
this.setState({
|
this.setState(
|
||||||
...this.state,
|
{
|
||||||
button_text: 'set',
|
...this.state,
|
||||||
password: '',
|
button_text: 'set',
|
||||||
password2: '',
|
password: '',
|
||||||
}, () => {
|
password2: '',
|
||||||
if (this.props.mismatchHandler) {
|
},
|
||||||
this.props.mismatchHandler();
|
() => {
|
||||||
|
if (this.props.mismatchHandler) {
|
||||||
|
this.props.mismatchHandler();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -79,7 +83,7 @@ export default class Password extends Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handlePasswordChanged = e => {
|
handlePasswordChanged = (e) => {
|
||||||
if (this.state.button_text === 'set') {
|
if (this.state.button_text === 'set') {
|
||||||
this.setState({
|
this.setState({
|
||||||
...this.state,
|
...this.state,
|
||||||
@@ -93,8 +97,11 @@ export default class Password extends Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
handlePasswordKeyUp = e => {
|
handlePasswordKeyUp = (e) => {
|
||||||
if ((e.keyCode === 13) && ((this.state.button_text === 'confirm') || (this.state.button_text === 'set'))) {
|
if (
|
||||||
|
e.keyCode === 13 &&
|
||||||
|
(this.state.button_text === 'confirm' || this.state.button_text === 'set')
|
||||||
|
) {
|
||||||
this.handleActionClick();
|
this.handleActionClick();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -108,28 +115,38 @@ export default class Password extends Component {
|
|||||||
|
|
||||||
render() {
|
render() {
|
||||||
return (
|
return (
|
||||||
<div className={'PasswordOwner'} style={{...this.props.style}}>
|
<div className={'PasswordOwner'} style={{ ...this.props.style }}>
|
||||||
{
|
{this.props.readOnly ? null : (
|
||||||
this.props.readOnly ? null : <a href={'#'}
|
<a href={'#'} className={'PasswordLink'} onClick={this.handleActionClick}>
|
||||||
className={'PasswordLink'}
|
|
||||||
onClick={this.handleActionClick}>
|
|
||||||
<u>{this.state.button_text}</u>
|
<u>{this.state.button_text}</u>
|
||||||
</a>
|
</a>
|
||||||
}
|
)}
|
||||||
<input autoFocus={this.props.autoFocus}
|
<input
|
||||||
readOnly={this.props.readOnly}
|
autoFocus={this.props.autoFocus}
|
||||||
className={'PasswordInput'}
|
readOnly={this.props.readOnly}
|
||||||
disabled={this.props.readOnly || (this.state.button_text === 'clear')}
|
className={'PasswordInput'}
|
||||||
onChange={this.handlePasswordChanged}
|
disabled={this.props.readOnly || this.state.button_text === 'clear'}
|
||||||
onKeyUp={this.handlePasswordKeyUp}
|
onChange={this.handlePasswordChanged}
|
||||||
type={this.state.show_password ? 'text' : 'password'}
|
onKeyUp={this.handlePasswordKeyUp}
|
||||||
value={(this.state.button_text === 'confirm') ? this.state.password2 : this.state.password}/>
|
type={this.state.show_password ? 'text' : 'password'}
|
||||||
<a href={'#'}
|
value={this.state.button_text === 'confirm' ? this.state.password2 : this.state.password}
|
||||||
className={'PasswordShowHide'}
|
/>
|
||||||
onClick={this.handleShowHideClick}>
|
<a href={'#'} className={'PasswordShowHide'} onClick={this.handleShowHideClick}>
|
||||||
<FontAwesomeIcon icon={this.state.show_password ? faEye : faEyeSlash} fixedWidth/>
|
<FontAwesomeIcon icon={this.state.show_password ? faEye : faEyeSlash} fixedWidth />
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Password.propTypes = {
|
||||||
|
autoFocus: PropTypes.bool,
|
||||||
|
changed: PropTypes.func,
|
||||||
|
disabled: PropTypes.bool,
|
||||||
|
mismatchHandler: PropTypes.func,
|
||||||
|
readOnly: PropTypes.bool,
|
||||||
|
style: PropTypes.object,
|
||||||
|
value: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export default Password;
|
||||||
|
|||||||
1057
src/helpers.js
1057
src/helpers.js
File diff suppressed because it is too large
Load Diff
@@ -8,28 +8,30 @@ test('verify signature success', () => {
|
|||||||
.verifySignature(
|
.verifySignature(
|
||||||
path.resolve('test/test_verify_signature.dat'),
|
path.resolve('test/test_verify_signature.dat'),
|
||||||
path.resolve('test/test_verify_signature.dat.sig'),
|
path.resolve('test/test_verify_signature.dat.sig'),
|
||||||
path.resolve('blockstorage_dev_public.pem'))
|
path.resolve('blockstorage_dev_public.pem')
|
||||||
.then(stdout => {
|
)
|
||||||
|
.then((stdout) => {
|
||||||
expect(stdout).toBeDefined();
|
expect(stdout).toBeDefined();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('verify signature fail', () => {
|
test('verify signature fail', () => {
|
||||||
return expect(helpers
|
return expect(
|
||||||
.verifySignature(
|
helpers.verifySignature(
|
||||||
path.resolve('test/test_verify_signature_fail.dat'),
|
path.resolve('test/test_verify_signature_fail.dat'),
|
||||||
path.resolve('test/test_verify_signature.dat.sig'),
|
path.resolve('test/test_verify_signature.dat.sig'),
|
||||||
path.resolve('blockstorage_dev_public.pem')))
|
path.resolve('blockstorage_dev_public.pem')
|
||||||
.rejects
|
)
|
||||||
.toThrow()
|
).rejects.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('create temp signature files', () => {
|
test('create temp signature files', () => {
|
||||||
const b64signature = fs.readFileSync(path.resolve('test/test_create_signature.sig.b64'), {encoding: 'utf8'}).replace(/(\r\n|\n|\r)/gm,"");
|
const b64signature = fs
|
||||||
const data = helpers
|
.readFileSync(path.resolve('test/test_create_signature.sig.b64'), {
|
||||||
.createSignatureFiles(
|
encoding: 'utf8',
|
||||||
b64signature,
|
})
|
||||||
Constants.DEV_PUBLIC_KEY);
|
.replace(/(\r\n|\n|\r)/gm, '');
|
||||||
|
const data = helpers.createSignatureFiles(b64signature, Constants.DEV_PUBLIC_KEY);
|
||||||
expect(data).toBeDefined();
|
expect(data).toBeDefined();
|
||||||
expect(data.PublicKeyFile).toBeDefined();
|
expect(data.PublicKeyFile).toBeDefined();
|
||||||
expect(data.SignatureFile).toBeDefined();
|
expect(data.SignatureFile).toBeDefined();
|
||||||
@@ -37,22 +39,33 @@ test('create temp signature files', () => {
|
|||||||
expect(fs.statSync(data.SignatureFile).isFile()).toBe(true);
|
expect(fs.statSync(data.SignatureFile).isFile()).toBe(true);
|
||||||
expect(fs.statSync(data.PublicKeyFile).isFile()).toBe(true);
|
expect(fs.statSync(data.PublicKeyFile).isFile()).toBe(true);
|
||||||
|
|
||||||
const b64signature2 = fs.readFileSync(data.SignatureFile).toString('base64').replace(/(\r\n|\n|\r)/gm,"");
|
const b64signature2 = fs
|
||||||
|
.readFileSync(data.SignatureFile)
|
||||||
|
.toString('base64')
|
||||||
|
.replace(/(\r\n|\n|\r)/gm, '');
|
||||||
expect(b64signature2).toEqual(b64signature);
|
expect(b64signature2).toEqual(b64signature);
|
||||||
|
|
||||||
expect(fs.readFileSync(data.PublicKeyFile, {encoding: 'utf8'})).toEqual(Constants.DEV_PUBLIC_KEY);
|
expect(fs.readFileSync(data.PublicKeyFile, { encoding: 'utf8' })).toEqual(
|
||||||
|
Constants.DEV_PUBLIC_KEY
|
||||||
|
);
|
||||||
fs.unlinkSync(data.PublicKeyFile);
|
fs.unlinkSync(data.PublicKeyFile);
|
||||||
fs.unlinkSync(data.SignatureFile);
|
fs.unlinkSync(data.SignatureFile);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('verify sha56 success', ()=> {
|
test('verify sha56 success', () => {
|
||||||
const hash = fs.readFileSync('test/test_verify_sha256.dat.sha256', {encoding: 'utf8'});
|
const hash = fs.readFileSync('test/test_verify_sha256.dat.sha256', {
|
||||||
return expect(helpers.verifyHash(path.resolve('test/test_verify_sha256.dat'), hash))
|
encoding: 'utf8',
|
||||||
.resolves.toBe(hash)
|
});
|
||||||
|
return expect(
|
||||||
|
helpers.verifyHash(path.resolve('test/test_verify_sha256.dat'), hash)
|
||||||
|
).resolves.toBe(hash);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('verify sha56 fail', ()=> {
|
test('verify sha56 fail', () => {
|
||||||
const hash = fs.readFileSync('test/test_verify_sha256.dat.sha256', {encoding: 'utf8'});
|
const hash = fs.readFileSync('test/test_verify_sha256.dat.sha256', {
|
||||||
return expect(helpers.verifyHash(path.resolve('test/test_verify_sha256_fail.dat'), hash))
|
encoding: 'utf8',
|
||||||
.rejects.toThrow();
|
});
|
||||||
|
return expect(
|
||||||
|
helpers.verifyHash(path.resolve('test/test_verify_sha256_fail.dat'), hash)
|
||||||
|
).rejects.toThrow();
|
||||||
});
|
});
|
||||||
@@ -6,7 +6,7 @@
|
|||||||
--control_border: 1px solid rgba(80, 80, 90, 0.9);
|
--control_border: 1px solid rgba(80, 80, 90, 0.9);
|
||||||
--control_box_shadow: 2px 2px 2px black;
|
--control_box_shadow: 2px 2px 2px black;
|
||||||
--control_transparent_background: rgba(10, 10, 16, 0.5);
|
--control_transparent_background: rgba(10, 10, 16, 0.5);
|
||||||
--control_dark_transparent_background: rgba(10, 10, 16, 0.7);
|
--control_dark_transparent_background: rgba(10, 10, 16, 0.75);
|
||||||
|
|
||||||
--text_color: rgba(200, 200, 240, 0.65);
|
--text_color: rgba(200, 200, 240, 0.65);
|
||||||
--text_color_hover: rgba(200, 200, 225, 0.65);
|
--text_color_hover: rgba(200, 200, 225, 0.65);
|
||||||
@@ -35,7 +35,8 @@ a {
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
html, body {
|
html,
|
||||||
|
body {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@@ -52,7 +53,9 @@ p {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
h1, h2, h3 {
|
h1,
|
||||||
|
h2,
|
||||||
|
h3 {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
@@ -65,7 +68,8 @@ h1 {
|
|||||||
color: var(--heading_text_color);
|
color: var(--heading_text_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
h2, h3 {
|
h2,
|
||||||
|
h3 {
|
||||||
color: var(--heading_other_text_color);
|
color: var(--heading_other_text_color);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,19 +85,23 @@ p {
|
|||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollable-content, ::-webkit-scrollbar {
|
.scrollable-content,
|
||||||
|
::-webkit-scrollbar {
|
||||||
width: 8px;
|
width: 8px;
|
||||||
height: 8px;
|
height: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollable-content, ::-webkit-scrollbar * {
|
.scrollable-content,
|
||||||
|
::-webkit-scrollbar * {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollable-content, ::-webkit-scrollbar-thumb {
|
.scrollable-content,
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
background: var(--control_background_hover) !important;
|
background: var(--control_background_hover) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.scrollbar-corner, ::-webkit-scrollbar-corner {
|
.scrollbar-corner,
|
||||||
|
::-webkit-scrollbar-corner {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
}
|
}
|
||||||
|
|||||||
20
src/index.js
20
src/index.js
@@ -3,16 +3,16 @@ import 'react-checkbox-tree/lib/react-checkbox-tree.css';
|
|||||||
|
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
import ReactDOM from 'react-dom';
|
import ReactDOM from 'react-dom';
|
||||||
import {Provider} from 'react-redux';
|
import { Provider } from 'react-redux';
|
||||||
|
|
||||||
import packageJson from '../package.json';
|
import packageJson from '../package.json';
|
||||||
|
|
||||||
import App from './App.jsx';
|
import App from './App.jsx';
|
||||||
import {setProviderState} from './redux/actions/mount_actions';
|
import { setProviderState } from './redux/actions/mount_actions';
|
||||||
import {setActiveRelease} from './redux/actions/release_version_actions';
|
import { setActiveRelease } from './redux/actions/release_version_actions';
|
||||||
import createAppStore from './redux/store/createAppStore';
|
import createAppStore from './redux/store/createAppStore';
|
||||||
import * as serviceWorker from './serviceWorker';
|
import * as serviceWorker from './serviceWorker';
|
||||||
import {getIPCRenderer} from './utils';
|
import { getIPCRenderer } from './utils.jsx';
|
||||||
|
|
||||||
const Constants = require('./constants');
|
const Constants = require('./constants');
|
||||||
|
|
||||||
@@ -44,17 +44,17 @@ if (ipcRenderer) {
|
|||||||
}
|
}
|
||||||
store.dispatch(setProviderState(provider, state));
|
store.dispatch(setProviderState(provider, state));
|
||||||
}
|
}
|
||||||
store.dispatch(
|
store.dispatch(setActiveRelease(result.data.Release, result.data.Version));
|
||||||
setActiveRelease(result.data.Release, result.data.Version));
|
|
||||||
} else {
|
} else {
|
||||||
store = createAppStore(platformInfo, packageJson.version, {});
|
store = createAppStore(platformInfo, packageJson.version, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
ReactDOM.render((
|
ReactDOM.render(
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<App/>
|
<App />
|
||||||
</Provider>
|
</Provider>,
|
||||||
), document.getElementById('root'));
|
document.getElementById('root')
|
||||||
|
);
|
||||||
serviceWorker.unregister();
|
serviceWorker.unregister();
|
||||||
});
|
});
|
||||||
ipcRenderer.send(Constants.IPC_Get_State);
|
ipcRenderer.send(Constants.IPC_Get_State);
|
||||||
|
|||||||
@@ -1,31 +1,15 @@
|
|||||||
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
|
import { createResponseDialogAction } from '../utils';
|
||||||
|
|
||||||
|
export const confirmYesNoAction = createResponseDialogAction('common', 'confirmYesNo');
|
||||||
|
|
||||||
import * as Constants from '../../constants';
|
import * as Constants from '../../constants';
|
||||||
import {createAction} from '@reduxjs/toolkit';
|
import { getIPCRenderer } from '../../utils.jsx';
|
||||||
import {getIPCRenderer} from '../../utils';
|
|
||||||
|
|
||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
let yesNoResolvers = [];
|
|
||||||
|
|
||||||
export const confirmYesNo = title => {
|
export const displaySelectAppPlatform = (display) => {
|
||||||
return dispatch => {
|
return (dispatch) => {
|
||||||
return new Promise(resolve => {
|
|
||||||
dispatch(handleConfirmYesNo(true, title, resolve));
|
|
||||||
});
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const DISPLAY_CONFIRM_YES_NO = 'common/displayConfirmYesNo';
|
|
||||||
const displayConfirmYesNo = (show, title) => {
|
|
||||||
return {
|
|
||||||
type: DISPLAY_CONFIRM_YES_NO,
|
|
||||||
payload: {
|
|
||||||
show,
|
|
||||||
title
|
|
||||||
},
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const displaySelectAppPlatform = display => {
|
|
||||||
return dispatch => {
|
|
||||||
if (display) {
|
if (display) {
|
||||||
dispatch(showWindow());
|
dispatch(showWindow());
|
||||||
}
|
}
|
||||||
@@ -34,69 +18,47 @@ export const displaySelectAppPlatform = display => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const hideConfirmYesNo = confirmed => {
|
|
||||||
return dispatch => {
|
|
||||||
dispatch(handleConfirmYesNo(false, confirmed));
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleConfirmYesNo = (show, titleOrConfirmed, resolve) => {
|
|
||||||
return dispatch => {
|
|
||||||
if (show) {
|
|
||||||
yesNoResolvers.push(resolve);
|
|
||||||
dispatch(displayConfirmYesNo(show, titleOrConfirmed));
|
|
||||||
} else {
|
|
||||||
yesNoResolvers[0](titleOrConfirmed);
|
|
||||||
yesNoResolvers.splice(0, 1);
|
|
||||||
dispatch(displayConfirmYesNo(false));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const NOTIFY_APPLICATION_BUSY = 'common/notifyApplicationBusy';
|
export const NOTIFY_APPLICATION_BUSY = 'common/notifyApplicationBusy';
|
||||||
export const notifyApplicationBusy = (busy, transparent) => {
|
export const notifyApplicationBusy = (busy, transparent) => {
|
||||||
return {
|
return {
|
||||||
type: NOTIFY_APPLICATION_BUSY,
|
type: NOTIFY_APPLICATION_BUSY,
|
||||||
payload: {
|
payload: { busy, transparent },
|
||||||
busy,
|
|
||||||
transparent
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const notifyRebootRequired = createAction('common/notifyRebootRequired');
|
export const notifyRebootRequired = createAction('common/notifyRebootRequired');
|
||||||
|
|
||||||
export const rebootSystem = () => {
|
export const rebootSystem = () => {
|
||||||
return dispatch => {
|
return (dispatch) => {
|
||||||
dispatch(setApplicationReady(false));
|
dispatch(setApplicationReady(false));
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
ipcRenderer.send(Constants.IPC_Reboot_System);
|
ipcRenderer.send(Constants.IPC_Reboot_System);
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const saveState = () => {
|
export const saveState = () => {
|
||||||
return (dispatch, getState) => {
|
return (_, getState) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
if (state.common.AppReady) {
|
if (state.common.AppReady) {
|
||||||
let currentState = {
|
let currentState = {
|
||||||
Release: state.relver.Release,
|
Release: state.relver.Release,
|
||||||
RemoteMounts: state.mounts.RemoteMounts,
|
RemoteMounts: state.mounts.RemoteMounts,
|
||||||
|
S3Mounts: state.mounts.S3Mounts,
|
||||||
Version: state.relver.Version,
|
Version: state.relver.Version,
|
||||||
};
|
};
|
||||||
|
|
||||||
const providerList = [
|
const providerList = [
|
||||||
...Constants.PROVIDER_LIST,
|
...Constants.PROVIDER_LIST,
|
||||||
...state.mounts.RemoteMounts,
|
...state.mounts.RemoteMounts,
|
||||||
|
...state.mounts.S3Mounts,
|
||||||
];
|
];
|
||||||
for (const provider of providerList) {
|
for (const provider of providerList) {
|
||||||
currentState[provider] = state.mounts.ProviderState[provider];
|
currentState[provider] = state.mounts.ProviderState[provider];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
ipcRenderer.send(Constants.IPC_Save_State, {
|
ipcRenderer.send(Constants.IPC_Save_State, { State: currentState });
|
||||||
State: currentState
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -106,7 +68,7 @@ export const setAllowMount = createAction('common/setAllowMount');
|
|||||||
export const setApplicationReady = createAction('common/setApplicationReady');
|
export const setApplicationReady = createAction('common/setApplicationReady');
|
||||||
|
|
||||||
export const SET_DISPLAY_SELECT_APPPLATFORM = 'common/displaySelectAppPlatform';
|
export const SET_DISPLAY_SELECT_APPPLATFORM = 'common/displaySelectAppPlatform';
|
||||||
export const setDisplaySelectAppPlatform = display => {
|
export const setDisplaySelectAppPlatform = (display) => {
|
||||||
return {
|
return {
|
||||||
type: SET_DISPLAY_SELECT_APPPLATFORM,
|
type: SET_DISPLAY_SELECT_APPPLATFORM,
|
||||||
payload: display,
|
payload: display,
|
||||||
@@ -116,14 +78,14 @@ export const setDisplaySelectAppPlatform = display => {
|
|||||||
export const setLinuxAppPlatform = createAction('common/setLinuxAppPlatform');
|
export const setLinuxAppPlatform = createAction('common/setLinuxAppPlatform');
|
||||||
|
|
||||||
export const setRebootRequired = () => {
|
export const setRebootRequired = () => {
|
||||||
return dispatch => {
|
return (dispatch) => {
|
||||||
dispatch(showWindow());
|
dispatch(showWindow());
|
||||||
dispatch(notifyRebootRequired(true));
|
dispatch(notifyRebootRequired(true));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const showWindow = () => {
|
export const showWindow = () => {
|
||||||
return dispatch => {
|
return () => {
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
ipcRenderer.send(Constants.IPC_Show_Window);
|
ipcRenderer.send(Constants.IPC_Show_Window);
|
||||||
}
|
}
|
||||||
@@ -131,7 +93,7 @@ export const showWindow = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const shutdownApplication = () => {
|
export const shutdownApplication = () => {
|
||||||
return dispatch => {
|
return (dispatch) => {
|
||||||
dispatch(setApplicationReady(false));
|
dispatch(setApplicationReady(false));
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
ipcRenderer.send(Constants.IPC_Shutdown);
|
ipcRenderer.send(Constants.IPC_Shutdown);
|
||||||
|
|||||||
@@ -1,26 +1,21 @@
|
|||||||
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import * as Constants from '../../constants';
|
import * as Constants from '../../constants';
|
||||||
import {createAction} from '@reduxjs/toolkit';
|
import { getIPCRenderer } from '../../utils.jsx';
|
||||||
import {getIPCRenderer} from '../../utils';
|
|
||||||
import {notifyError} from './error_actions';
|
import { notifyError } from './error_actions';
|
||||||
import {
|
import {
|
||||||
installAndTestRelease,
|
installAndTestRelease,
|
||||||
installDependency,
|
installDependency,
|
||||||
installRelease,
|
installRelease,
|
||||||
installUpgrade
|
installUpgrade,
|
||||||
} from './install_actions';
|
} from './install_actions';
|
||||||
|
|
||||||
export const setAllowDownload = createAction('download/setAllowDownload');
|
export const setAllowDownload = createAction('download/setAllowDownload');
|
||||||
|
|
||||||
export const SET_DOWNLOAD_BEGIN = 'download/setDownloadBegin';
|
export const SET_DOWNLOAD_BEGIN = 'download/setDownloadBegin';
|
||||||
export const setDownloadBegin = (name, type, url) => {
|
export const setDownloadBegin = (name, type, url) => {
|
||||||
return {
|
return { type: SET_DOWNLOAD_BEGIN, payload: { name, type, url } };
|
||||||
type: SET_DOWNLOAD_BEGIN,
|
|
||||||
payload: {
|
|
||||||
name,
|
|
||||||
type,
|
|
||||||
url
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setDownloadEnd = createAction('download/setDownloadEnd');
|
export const setDownloadEnd = createAction('download/setDownloadEnd');
|
||||||
@@ -32,27 +27,28 @@ export const downloadItem = (name, type, urls, isWinFSP, testVersion, appPlatfor
|
|||||||
urls = [urls];
|
urls = [urls];
|
||||||
}
|
}
|
||||||
|
|
||||||
const downloadComplete = result => {
|
const downloadComplete = (result) => {
|
||||||
if (result.Success) {
|
if (result.Success) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case Constants.INSTALL_TYPES.Dependency:
|
case Constants.INSTALL_TYPES.Dependency:
|
||||||
dispatch(installDependency(result.Destination, result.URL, isWinFSP));
|
dispatch(installDependency(result.Destination, result.URL, isWinFSP));
|
||||||
break;
|
break;
|
||||||
case Constants.INSTALL_TYPES.Release:
|
case Constants.INSTALL_TYPES.Release:
|
||||||
dispatch(installRelease(result.Destination));
|
dispatch(installRelease(result.Destination));
|
||||||
break;
|
break;
|
||||||
case Constants.INSTALL_TYPES.TestRelease:
|
case Constants.INSTALL_TYPES.TestRelease:
|
||||||
dispatch(installAndTestRelease(result.Destination, testVersion, appPlatform));
|
dispatch(installAndTestRelease(result.Destination, testVersion, appPlatform));
|
||||||
break;
|
break;
|
||||||
case Constants.INSTALL_TYPES.Upgrade:
|
case Constants.INSTALL_TYPES.Upgrade:
|
||||||
//const info = this.props.LocationsLookup[this.props.AppPlatform][this.props.VersionLookup[this.props.AppPlatform][0]];
|
// const info =
|
||||||
const sha256 = null;//info.sha256;
|
// this.props.LocationsLookup[this.props.AppPlatform][this.props.VersionLookup[this.props.AppPlatform][0]];
|
||||||
const signature = null;//info.sig;
|
//const sha256 = null; // info.sha256;
|
||||||
dispatch(installUpgrade(result.Destination, sha256, signature, !!result.SkipVerification));
|
//const signature = null; // info.sig;
|
||||||
break;
|
dispatch(installUpgrade(result.Destination, null, null, !!result.SkipVerification));
|
||||||
default:
|
break;
|
||||||
dispatch(notifyError('Unknown download type: ' + type));
|
default:
|
||||||
break;
|
dispatch(notifyError('Unknown download type: ' + type));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (type === Constants.INSTALL_TYPES.TestRelease) {
|
if (type === Constants.INSTALL_TYPES.TestRelease) {
|
||||||
@@ -62,10 +58,10 @@ export const downloadItem = (name, type, urls, isWinFSP, testVersion, appPlatfor
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const downloadAtIndex = index => {
|
const downloadAtIndex = (index) => {
|
||||||
const url = urls[index];
|
const url = urls[index];
|
||||||
const state = getState();
|
const state = getState();
|
||||||
if ((index > 0) || (!state.download.DownloadActive && state.download.AllowDownload)) {
|
if (index > 0 || (!state.download.DownloadActive && state.download.AllowDownload)) {
|
||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
dispatch(setDownloadBegin(name, type, url));
|
dispatch(setDownloadBegin(name, type, url));
|
||||||
@@ -76,7 +72,7 @@ export const downloadItem = (name, type, urls, isWinFSP, testVersion, appPlatfor
|
|||||||
|
|
||||||
const downloadFileComplete = (_, arg) => {
|
const downloadFileComplete = (_, arg) => {
|
||||||
ipcRenderer.removeListener(Constants.IPC_Download_File_Progress, downloadFileProgress);
|
ipcRenderer.removeListener(Constants.IPC_Download_File_Progress, downloadFileProgress);
|
||||||
if (!arg.data.Success && (++index < urls.length)) {
|
if (!arg.data.Success && ++index < urls.length) {
|
||||||
downloadAtIndex(index);
|
downloadAtIndex(index);
|
||||||
} else {
|
} else {
|
||||||
downloadComplete(arg.data);
|
downloadComplete(arg.data);
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
import {
|
import { showWindow, shutdownApplication } from './common_actions';
|
||||||
showWindow,
|
|
||||||
shutdownApplication
|
|
||||||
} from './common_actions';
|
|
||||||
|
|
||||||
let ErrorActions = [];
|
let ErrorActions = [];
|
||||||
|
|
||||||
@@ -36,13 +33,13 @@ export const dismissError = () => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const dismissInfo = () => {
|
export const dismissInfo = () => {
|
||||||
return dispatch => {
|
return (dispatch) => {
|
||||||
dispatch(clearInfo());
|
dispatch(clearInfo());
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const notifyError = (msg, critical, callback) => {
|
export const notifyError = (msg, critical, callback) => {
|
||||||
return dispatch => {
|
return (dispatch) => {
|
||||||
ErrorActions = [callback, ...ErrorActions];
|
ErrorActions = [callback, ...ErrorActions];
|
||||||
msg = msg ? msg.toString() : 'Unknown Error';
|
msg = msg ? msg.toString() : 'Unknown Error';
|
||||||
dispatch(setErrorInfo(msg, critical));
|
dispatch(setErrorInfo(msg, critical));
|
||||||
@@ -50,33 +47,23 @@ export const notifyError = (msg, critical, callback) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const notifyInfo = (title, msg) => {
|
export const notifyInfo = (title, msg, saveToFile, fileName, extension) => {
|
||||||
return dispatch => {
|
return (dispatch) => {
|
||||||
title = title ? title.toString() : 'Information';
|
title = title ? title.toString() : 'Information';
|
||||||
msg = msg ? msg.toString() : '';
|
msg = msg ? msg.toString() : '';
|
||||||
dispatch(setInfo(title, msg));
|
dispatch(setInfo(title, msg, saveToFile, fileName, extension));
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SET_ERROR_INFO = 'error/setErrorInfo';
|
export const SET_ERROR_INFO = 'error/setErrorInfo';
|
||||||
export const setErrorInfo = (msg, critical) => {
|
export const setErrorInfo = (msg, critical) => {
|
||||||
return {
|
return { type: SET_ERROR_INFO, payload: { msg, critical } };
|
||||||
type: SET_ERROR_INFO,
|
|
||||||
payload: {
|
|
||||||
msg,
|
|
||||||
critical
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
export const SET_INFO = 'error/setInfo';
|
export const SET_INFO = 'error/setInfo';
|
||||||
export const setInfo = (title, msg) => {
|
export const setInfo = (title, msg, saveToFile, fileName, extension) => {
|
||||||
return {
|
return {
|
||||||
type: SET_INFO,
|
type: SET_INFO,
|
||||||
payload: {
|
payload: { title, msg, saveToFile, fileName, extension },
|
||||||
title,
|
};
|
||||||
msg
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
3
src/redux/actions/host_actions.js
Normal file
3
src/redux/actions/host_actions.js
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
import { createResponseDialogAction } from '../utils';
|
||||||
|
|
||||||
|
export const addEditHostAction = createResponseDialogAction('host', 'displayAddEditHost');
|
||||||
@@ -1,35 +1,34 @@
|
|||||||
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import * as Constants from '../../constants';
|
import * as Constants from '../../constants';
|
||||||
import {createAction} from '@reduxjs/toolkit';
|
import { getIPCRenderer, getSelectedVersionFromState } from '../../utils.jsx';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getIPCRenderer,
|
confirmYesNoAction,
|
||||||
getSelectedVersionFromState
|
|
||||||
} from '../../utils';
|
|
||||||
import {notifyError} from './error_actions';
|
|
||||||
import {downloadItem, setAllowDownload} from './download_actions';
|
|
||||||
import {
|
|
||||||
loadReleases,
|
|
||||||
setActiveRelease,
|
|
||||||
setInstalledVersion,
|
|
||||||
setReleaseUpgradeAvailable,
|
|
||||||
setNewReleasesAvailable2,
|
|
||||||
} from './release_version_actions';
|
|
||||||
import {
|
|
||||||
confirmYesNo,
|
|
||||||
displaySelectAppPlatform,
|
displaySelectAppPlatform,
|
||||||
setAllowMount,
|
setAllowMount,
|
||||||
setApplicationReady,
|
setApplicationReady,
|
||||||
setLinuxAppPlatform,
|
setLinuxAppPlatform,
|
||||||
setRebootRequired,
|
setRebootRequired,
|
||||||
showWindow,
|
showWindow,
|
||||||
shutdownApplication
|
shutdownApplication,
|
||||||
} from './common_actions';
|
} from './common_actions';
|
||||||
import {unmountAll} from './mount_actions';
|
import { downloadItem, setAllowDownload } from './download_actions';
|
||||||
|
import { notifyError } from './error_actions';
|
||||||
|
import { unmountAll } from './mount_actions';
|
||||||
|
import {
|
||||||
|
loadReleases,
|
||||||
|
setActiveRelease,
|
||||||
|
setInstalledVersion,
|
||||||
|
setNewReleasesAvailable2,
|
||||||
|
setReleaseUpgradeAvailable,
|
||||||
|
} from './release_version_actions';
|
||||||
|
|
||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
|
|
||||||
export const checkInstalled = (dependencies, version) => {
|
export const checkInstalled = (dependencies, version) => {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const checkInstalledComplete = (event, arg) => {
|
const checkInstalledComplete = (_, arg) => {
|
||||||
const result = arg.data;
|
const result = arg.data;
|
||||||
const updateState = () => {
|
const updateState = () => {
|
||||||
const installedVersion = result.Success && result.Exists ? result.Version : 'none';
|
const installedVersion = result.Success && result.Exists ? result.Version : 'none';
|
||||||
@@ -40,7 +39,8 @@ export const checkInstalled = (dependencies, version) => {
|
|||||||
|
|
||||||
let upgradeAvailable = false;
|
let upgradeAvailable = false;
|
||||||
if (installedVersion !== 'none') {
|
if (installedVersion !== 'none') {
|
||||||
const latestVersion = state.relver.VersionLookup[Constants.RELEASE_TYPES[release]].length - 1;
|
const latestVersion =
|
||||||
|
state.relver.VersionLookup[Constants.RELEASE_TYPES[release]].length - 1;
|
||||||
if (version === -1) {
|
if (version === -1) {
|
||||||
version = latestVersion;
|
version = latestVersion;
|
||||||
dispatch(setActiveRelease(release, version));
|
dispatch(setActiveRelease(release, version));
|
||||||
@@ -57,11 +57,13 @@ export const checkInstalled = (dependencies, version) => {
|
|||||||
const autoInstallRelease = getState().install.AutoInstallRelease;
|
const autoInstallRelease = getState().install.AutoInstallRelease;
|
||||||
dispatch(setAutoInstallRelease(false));
|
dispatch(setAutoInstallRelease(false));
|
||||||
|
|
||||||
if (result.Dependencies && (result.Dependencies.length > 0)) {
|
if (result.Dependencies && result.Dependencies.length > 0) {
|
||||||
dispatch(showWindow());
|
dispatch(showWindow());
|
||||||
} else if ((installedVersion === 'none') && autoInstallRelease) {
|
} else if (installedVersion === 'none' && autoInstallRelease) {
|
||||||
dispatch(setAllowMount(false));
|
dispatch(setAllowMount(false));
|
||||||
const versionString = getState().relver.VersionLookup[Constants.RELEASE_TYPES[release]][version];
|
const versionString = getState().relver.VersionLookup[Constants.RELEASE_TYPES[release]][
|
||||||
|
version
|
||||||
|
];
|
||||||
const urls = getState().relver.LocationsLookup[versionString].urls;
|
const urls = getState().relver.LocationsLookup[versionString].urls;
|
||||||
const fileName = versionString + '.zip';
|
const fileName = versionString + '.zip';
|
||||||
dispatch(downloadItem(fileName, Constants.INSTALL_TYPES.Release, urls));
|
dispatch(downloadItem(fileName, Constants.INSTALL_TYPES.Release, urls));
|
||||||
@@ -89,9 +91,12 @@ export const checkVersionInstalled = () => {
|
|||||||
|
|
||||||
dispatch(setAllowDownload(false));
|
dispatch(setAllowDownload(false));
|
||||||
const selectedVersion = getSelectedVersionFromState(state);
|
const selectedVersion = getSelectedVersionFromState(state);
|
||||||
if (selectedVersion && (selectedVersion !== 'unavailable')) {
|
if (selectedVersion && selectedVersion !== 'unavailable') {
|
||||||
let dependencies = [];
|
let dependencies = [];
|
||||||
if (state.relver.LocationsLookup[selectedVersion] && state.relver.LocationsLookup[selectedVersion].dependencies) {
|
if (
|
||||||
|
state.relver.LocationsLookup[selectedVersion] &&
|
||||||
|
state.relver.LocationsLookup[selectedVersion].dependencies
|
||||||
|
) {
|
||||||
dependencies = state.relver.LocationsLookup[selectedVersion].dependencies;
|
dependencies = state.relver.LocationsLookup[selectedVersion].dependencies;
|
||||||
}
|
}
|
||||||
dispatch(checkInstalled(dependencies, selectedVersion));
|
dispatch(checkInstalled(dependencies, selectedVersion));
|
||||||
@@ -107,9 +112,9 @@ export const installDependency = (source, url, isWinFSP) => {
|
|||||||
if (ipcRenderer && !getState().install.InstallActive) {
|
if (ipcRenderer && !getState().install.InstallActive) {
|
||||||
dispatch(setInstallActive(Constants.INSTALL_TYPES.Dependency));
|
dispatch(setInstallActive(Constants.INSTALL_TYPES.Dependency));
|
||||||
|
|
||||||
const installDependencyComplete = (event, arg) => {
|
const installDependencyComplete = (_, arg) => {
|
||||||
const result = arg.data;
|
const result = arg.data;
|
||||||
const handleCompleted = ()=> {
|
const handleCompleted = () => {
|
||||||
if (result.RebootRequired) {
|
if (result.RebootRequired) {
|
||||||
dispatch(setRebootRequired());
|
dispatch(setRebootRequired());
|
||||||
} else {
|
} else {
|
||||||
@@ -122,10 +127,10 @@ export const installDependency = (source, url, isWinFSP) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (result.Success && source.toLowerCase().endsWith('.dmg')) {
|
if (result.Success && source.toLowerCase().endsWith('.dmg')) {
|
||||||
const dep = getState().install.MissingDependencies.find(d => {
|
const dep = getState().install.MissingDependencies.find((d) => {
|
||||||
return d.download === url;
|
return d.download === url;
|
||||||
});
|
});
|
||||||
const i = setInterval(()=> {
|
const i = setInterval(() => {
|
||||||
const ret = ipcRenderer.sendSync(Constants.IPC_Check_Dependency_Installed + '_sync', {
|
const ret = ipcRenderer.sendSync(Constants.IPC_Check_Dependency_Installed + '_sync', {
|
||||||
File: dep.file,
|
File: dep.file,
|
||||||
});
|
});
|
||||||
@@ -160,7 +165,7 @@ export const installAndTestRelease = (source, version, appPlatform) => {
|
|||||||
FilePath: source,
|
FilePath: source,
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.once(Constants.IPC_Test_Release_Reply, (event, arg) => {
|
ipcRenderer.once(Constants.IPC_Test_Release_Reply, (_, arg) => {
|
||||||
if (arg.data.Success) {
|
if (arg.data.Success) {
|
||||||
ipcRenderer.sendSync(Constants.IPC_Set_Linux_AppPlatform, {
|
ipcRenderer.sendSync(Constants.IPC_Set_Linux_AppPlatform, {
|
||||||
AppPlatform: appPlatform,
|
AppPlatform: appPlatform,
|
||||||
@@ -177,7 +182,7 @@ export const installAndTestRelease = (source, version, appPlatform) => {
|
|||||||
});
|
});
|
||||||
ipcRenderer.send(Constants.IPC_Test_Release, {
|
ipcRenderer.send(Constants.IPC_Test_Release, {
|
||||||
Version: version,
|
Version: version,
|
||||||
})
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
ipcRenderer.once(Constants.IPC_Extract_Release_Complete, extractReleaseComplete);
|
ipcRenderer.once(Constants.IPC_Extract_Release_Complete, extractReleaseComplete);
|
||||||
@@ -201,26 +206,26 @@ export const installReleaseByVersion = (release, version) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (getState().mounts.MountsBusy) {
|
if (getState().mounts.MountsBusy) {
|
||||||
dispatch(confirmYesNo('Unmount all drives?'))
|
dispatch(confirmYesNoAction.display(true, null, { title: 'Unmount all drives?' }))
|
||||||
.then(confirmed => {
|
.then(({ changed }) => {
|
||||||
if (confirmed) {
|
if (changed) {
|
||||||
dispatch(unmountAll(install));
|
dispatch(unmountAll(install));
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => notifyError(error));
|
.catch((error) => notifyError(error));
|
||||||
} else {
|
} else {
|
||||||
install();
|
install();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const installRelease = source => {
|
export const installRelease = (source) => {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
if (ipcRenderer && !getState().install.InstallActive) {
|
if (ipcRenderer && !getState().install.InstallActive) {
|
||||||
dispatch(setInstallActive(Constants.INSTALL_TYPES.Release));
|
dispatch(setInstallActive(Constants.INSTALL_TYPES.Release));
|
||||||
|
|
||||||
const version = getSelectedVersionFromState(getState());
|
const version = getSelectedVersionFromState(getState());
|
||||||
const extractReleaseComplete = (event, arg) => {
|
const extractReleaseComplete = (_, arg) => {
|
||||||
ipcRenderer.send(Constants.IPC_Delete_File, {
|
ipcRenderer.send(Constants.IPC_Delete_File, {
|
||||||
FilePath: source,
|
FilePath: source,
|
||||||
});
|
});
|
||||||
@@ -249,19 +254,26 @@ export const installUpgrade = (source, sha256, signature, skipVerification) => {
|
|||||||
dispatch(setInstallActive(Constants.INSTALL_TYPES.Upgrade));
|
dispatch(setInstallActive(Constants.INSTALL_TYPES.Upgrade));
|
||||||
dispatch(setApplicationReady(false));
|
dispatch(setApplicationReady(false));
|
||||||
|
|
||||||
const installUpgradeComplete = (event, arg) => {
|
const installUpgradeComplete = (_, arg) => {
|
||||||
const result = arg.data;
|
const result = arg.data;
|
||||||
if (result.Success) {
|
if (result.Success) {
|
||||||
dispatch(shutdownApplication());
|
dispatch(shutdownApplication());
|
||||||
} else {
|
} else {
|
||||||
dispatch(setApplicationReady(true));
|
dispatch(setApplicationReady(true));
|
||||||
dispatch(setInstallComplete(result));
|
dispatch(setInstallComplete(result));
|
||||||
dispatch(notifyError(result.Error, false, () => {
|
dispatch(
|
||||||
// TODO Prompt to verify
|
notifyError(
|
||||||
if (result.AllowSkipVerification) {
|
result.Error,
|
||||||
dispatch(installUpgrade(source, sha256, signature, true));
|
false,
|
||||||
}
|
() => {
|
||||||
}, false));
|
// TODO Prompt to verify
|
||||||
|
if (result.AllowSkipVerification) {
|
||||||
|
dispatch(installUpgrade(source, sha256, signature, true));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false
|
||||||
|
)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import {createAction} from '@reduxjs/toolkit';
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import * as Constants from '../../constants';
|
import * as Constants from '../../constants';
|
||||||
import {getIPCRenderer} from '../../utils';
|
import { getIPCRenderer } from '../../utils.jsx';
|
||||||
|
|
||||||
import {confirmYesNo, saveState} from './common_actions';
|
import { confirmYesNoAction, saveState } from './common_actions';
|
||||||
import {notifyError} from './error_actions';
|
import { notifyError } from './error_actions';
|
||||||
|
|
||||||
export const addRemoteMount = (hostNameOrIp, port, token) => {
|
export const addRemoteMount = (hostNameOrIp, port, token) => {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
@@ -23,18 +23,17 @@ export const addRemoteMount = (hostNameOrIp, port, token) => {
|
|||||||
Version: getState().relver.InstalledVersion,
|
Version: getState().relver.InstalledVersion,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
dispatch(
|
dispatch(notifyError('Failed to create remote mount: ' + arg.data.Error));
|
||||||
notifyError('Failed to set \'RemoteToken\': ' + arg.data.Error));
|
|
||||||
dispatch(setBusy(false));
|
dispatch(setBusy(false));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.send(Constants.IPC_Set_Config_Values, {
|
ipcRenderer.send(Constants.IPC_Set_Config_Values, {
|
||||||
Items: [
|
Items: [
|
||||||
{Name: 'RemoteMount.RemoteHostNameOrIp', Value: hostNameOrIp},
|
{ Name: 'RemoteMount.RemoteHostNameOrIp', Value: hostNameOrIp },
|
||||||
{Name: 'RemoteMount.RemoteToken', Value: token},
|
{ Name: 'RemoteMount.RemoteToken', Value: token },
|
||||||
{Name: 'RemoteMount.RemotePort', Value: port},
|
{ Name: 'RemoteMount.RemotePort', Value: port.toString() },
|
||||||
{Name: 'RemoteMount.IsRemoteMount', Value: 'true'},
|
{ Name: 'RemoteMount.IsRemoteMount', Value: 'true' },
|
||||||
],
|
],
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
Remote: true,
|
Remote: true,
|
||||||
@@ -59,19 +58,18 @@ export const addS3Mount = (name, accessKey, secretKey, region, bucketName, url)
|
|||||||
Version: getState().relver.InstalledVersion,
|
Version: getState().relver.InstalledVersion,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
dispatch(
|
dispatch(notifyError('Failed to create S3 instance: ' + arg.data.Error));
|
||||||
notifyError('Failed to create S3 instance: ' + arg.data.Error));
|
|
||||||
dispatch(setBusy(false));
|
dispatch(setBusy(false));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcRenderer.send(Constants.IPC_Set_Config_Values, {
|
ipcRenderer.send(Constants.IPC_Set_Config_Values, {
|
||||||
Items: [
|
Items: [
|
||||||
{Name: 'S3Config.AccessKey', Value: accessKey},
|
{ Name: 'S3Config.AccessKey', Value: accessKey },
|
||||||
{Name: 'S3Config.SecretKey', Value: secretKey},
|
{ Name: 'S3Config.SecretKey', Value: secretKey },
|
||||||
{Name: 'S3Config.Region', Value: region},
|
{ Name: 'S3Config.Region', Value: region },
|
||||||
{Name: 'S3Config.BucketName', Value: bucketName},
|
{ Name: 'S3Config.BucketName', Value: bucketName },
|
||||||
{Name: 'S3Config.URL', Value: url},
|
{ Name: 'S3Config.URL', Value: url },
|
||||||
],
|
],
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
S3: true,
|
S3: true,
|
||||||
@@ -95,20 +93,23 @@ export const displayConfiguration = (provider, remote, s3) => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const removeMount = provider => {
|
export const removeMount = (provider) => {
|
||||||
return dispatch => {
|
return (dispatch) => {
|
||||||
const isRemote = provider.startsWith('Remote');
|
const isRemote = provider.startsWith('Remote');
|
||||||
dispatch(confirmYesNo('Delete [' + provider.substr(isRemote ? 6 : 2) + ']?'))
|
dispatch(
|
||||||
.then(confirmed => {
|
confirmYesNoAction.display(true, null, {
|
||||||
if (confirmed) {
|
title: 'Delete [' + provider.substr(isRemote ? 6 : 2) + ']?',
|
||||||
|
})
|
||||||
|
).then(({ changed }) => {
|
||||||
|
if (changed) {
|
||||||
dispatch(removeMount2(provider));
|
dispatch(removeMount2(provider));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const removeMount2 = provider => {
|
const removeMount2 = (provider) => {
|
||||||
return dispatch => {
|
return (dispatch) => {
|
||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
ipcRenderer.once(Constants.IPC_Remove_Mount_Reply, (_, arg) => {
|
ipcRenderer.once(Constants.IPC_Remove_Mount_Reply, (_, arg) => {
|
||||||
if (arg.data.Success) {
|
if (arg.data.Success) {
|
||||||
@@ -119,7 +120,7 @@ const removeMount2 = provider => {
|
|||||||
const isRemote = provider.startsWith('Remote');
|
const isRemote = provider.startsWith('Remote');
|
||||||
ipcRenderer.send(Constants.IPC_Remove_Mount, {
|
ipcRenderer.send(Constants.IPC_Remove_Mount, {
|
||||||
Remote: isRemote,
|
Remote: isRemote,
|
||||||
Name: provider.substr(isRemote ? 6 : 2)
|
Name: provider.substr(isRemote ? 6 : 2),
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -128,44 +129,38 @@ export const removeMount3 = createAction('mounts/removeMount3');
|
|||||||
|
|
||||||
export const RESET_MOUNTS_STATE = 'mounts/resetMountsState';
|
export const RESET_MOUNTS_STATE = 'mounts/resetMountsState';
|
||||||
export const resetMountsState = () => {
|
export const resetMountsState = () => {
|
||||||
return {type: RESET_MOUNTS_STATE, payload: null,}
|
return { type: RESET_MOUNTS_STATE, payload: null };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const SET_ALLOW_MOUNT = 'mounts/setAllowMount';
|
export const SET_ALLOW_MOUNT = 'mounts/setAllowMount';
|
||||||
export const setAllowMount =
|
export const setAllowMount = (provider, allow) => {
|
||||||
(provider,
|
return { type: SET_ALLOW_MOUNT, payload: { provider, allow } };
|
||||||
allow) => {
|
};
|
||||||
return {type: SET_ALLOW_MOUNT, payload: {provider, allow}};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SET_AUTO_MOUNT_PROCESSED = 'mounts/setAutoMountProcessed';
|
export const SET_AUTO_MOUNT_PROCESSED = 'mounts/setAutoMountProcessed';
|
||||||
export const setAutoMountProcessed = (provider, processed) => {
|
export const setAutoMountProcessed = (provider, processed) => {
|
||||||
return {type: SET_AUTO_MOUNT_PROCESSED, payload: {provider, processed}};
|
return { type: SET_AUTO_MOUNT_PROCESSED, payload: { provider, processed } };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setBusy = createAction('mounts/setBusy');
|
export const setBusy = createAction('mounts/setBusy');
|
||||||
|
|
||||||
export const SET_MOUNT_STATE = 'mounts/setMountState';
|
export const SET_MOUNT_STATE = 'mounts/setMountState';
|
||||||
export const setMountState =
|
export const setMountState = (provider, state) => {
|
||||||
(provider,
|
return { type: SET_MOUNT_STATE, payload: { provider, state } };
|
||||||
state) => {
|
};
|
||||||
return {type: SET_MOUNT_STATE, payload: {provider, state}};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SET_MOUNTED = 'mounts/setMounted';
|
export const SET_MOUNTED = 'mounts/setMounted';
|
||||||
export const setMounted =
|
export const setMounted = (provider, mounted) => {
|
||||||
(provider,
|
return { type: SET_MOUNTED, payload: { provider, mounted } };
|
||||||
mounted) => {
|
};
|
||||||
return {type: SET_MOUNTED, payload: {provider, mounted}};
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SET_PROVIDER_STATE = 'mounts/setProviderState';
|
export const SET_PROVIDER_STATE = 'mounts/setProviderState';
|
||||||
export const setProviderState = (provider, state) => {
|
export const setProviderState = (provider, state) => {
|
||||||
return {type: SET_PROVIDER_STATE, payload: {provider, state}}
|
return { type: SET_PROVIDER_STATE, payload: { provider, state } };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const unmountAll = completedCallback => {
|
export const unmountAll = (completedCallback) => {
|
||||||
return dispatch => {
|
return (dispatch) => {
|
||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
const unmountedCallback = () => {
|
const unmountedCallback = () => {
|
||||||
dispatch(resetMountsState());
|
dispatch(resetMountsState());
|
||||||
@@ -173,5 +168,5 @@ export const unmountAll = completedCallback => {
|
|||||||
};
|
};
|
||||||
ipcRenderer.once(Constants.IPC_Unmount_All_Drives_Reply, unmountedCallback);
|
ipcRenderer.once(Constants.IPC_Unmount_All_Drives_Reply, unmountedCallback);
|
||||||
ipcRenderer.send(Constants.IPC_Unmount_All_Drives);
|
ipcRenderer.send(Constants.IPC_Unmount_All_Drives);
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import {createAction} from '@reduxjs/toolkit';
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
export const displayPinnedManager = createAction('pinned/displayPinnedManager');
|
export const displayPinnedManager = createAction('pinned/displayPinnedManager');
|
||||||
|
|
||||||
|
|||||||
@@ -1,23 +1,18 @@
|
|||||||
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
import * as Constants from '../../constants';
|
import * as Constants from '../../constants';
|
||||||
import {createAction} from '@reduxjs/toolkit';
|
|
||||||
import {notifyError} from './error_actions';
|
|
||||||
import {
|
|
||||||
saveState,
|
|
||||||
setAllowMount,
|
|
||||||
setApplicationReady,
|
|
||||||
showWindow
|
|
||||||
} from './common_actions';
|
|
||||||
import {
|
|
||||||
checkVersionInstalled,
|
|
||||||
setDismissDependencies
|
|
||||||
} from './install_actions';
|
|
||||||
import {unmountAll} from './mount_actions';
|
|
||||||
import {
|
import {
|
||||||
checkNewReleases,
|
checkNewReleases,
|
||||||
getIPCRenderer,
|
getIPCRenderer,
|
||||||
getNewReleases, getSelectedVersionFromState
|
getNewReleases,
|
||||||
} from '../../utils';
|
getSelectedVersionFromState,
|
||||||
|
} from '../../utils.jsx';
|
||||||
|
|
||||||
|
import { saveState, setAllowMount, setApplicationReady, showWindow } from './common_actions';
|
||||||
|
import { notifyError } from './error_actions';
|
||||||
|
import { checkVersionInstalled, setDismissDependencies } from './install_actions';
|
||||||
|
import { unmountAll } from './mount_actions';
|
||||||
|
|
||||||
export const CLEAR_UI_UPGRADE = 'relver/clearUIUpgrade';
|
export const CLEAR_UI_UPGRADE = 'relver/clearUIUpgrade';
|
||||||
export const clearUIUpgrade = () => {
|
export const clearUIUpgrade = () => {
|
||||||
@@ -27,12 +22,12 @@ export const clearUIUpgrade = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const cleanupOldReleases = versionList => {
|
const cleanupOldReleases = (versionList) => {
|
||||||
return dispatch => {
|
return () => {
|
||||||
const ipcRenderer = getIPCRenderer();
|
const ipcRenderer = getIPCRenderer();
|
||||||
if (ipcRenderer) {
|
if (ipcRenderer) {
|
||||||
ipcRenderer.sendSync(Constants.IPC_Cleanup_Releases + '_sync', {
|
ipcRenderer.sendSync(Constants.IPC_Cleanup_Releases + '_sync', {
|
||||||
version_list: versionList
|
version_list: versionList,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -42,32 +37,40 @@ export const detectUIUpgrade = () => {
|
|||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
axios
|
axios
|
||||||
.get(Constants.UI_RELEASES_URL)
|
.get(Constants.UI_RELEASES_URL)
|
||||||
.then(response => {
|
.then((response) => {
|
||||||
const state = getState();
|
const state = getState();
|
||||||
const appPlatform = state.common.AppPlatform;
|
const appPlatform = state.common.AppPlatform;
|
||||||
const version = state.common.Version;
|
const version = state.common.Version;
|
||||||
const data = response.data;
|
const data = response.data;
|
||||||
|
|
||||||
if (data.Versions &&
|
if (
|
||||||
|
data.Versions &&
|
||||||
data.Versions[appPlatform] &&
|
data.Versions[appPlatform] &&
|
||||||
(data.Versions[appPlatform].length > 0) &&
|
data.Versions[appPlatform].length > 0 &&
|
||||||
(data.Versions[appPlatform][0] !== version)) {
|
data.Versions[appPlatform][0] !== version
|
||||||
dispatch(setUIUpgradeData(data.Locations[appPlatform][data.Versions[appPlatform][0]], data.Versions[appPlatform][0]));
|
) {
|
||||||
|
dispatch(
|
||||||
|
setUIUpgradeData(
|
||||||
|
data.Locations[appPlatform][data.Versions[appPlatform][0]],
|
||||||
|
data.Versions[appPlatform][0]
|
||||||
|
)
|
||||||
|
);
|
||||||
if (!state.relver.UpgradeDismissed) {
|
if (!state.relver.UpgradeDismissed) {
|
||||||
dispatch(showWindow());
|
dispatch(showWindow());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
dispatch(clearUIUpgrade());
|
dispatch(clearUIUpgrade());
|
||||||
}
|
}
|
||||||
}).catch(() => {
|
})
|
||||||
|
.catch(() => {
|
||||||
dispatch(clearUIUpgrade());
|
dispatch(clearUIUpgrade());
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const loadReleases = () => {
|
export const loadReleases = () => {
|
||||||
return (dispatch, getState) => {
|
return (dispatch, getState) => {
|
||||||
const dispatchActions = (locationsLookup, versionLookup)=> {
|
const dispatchActions = (locationsLookup, versionLookup) => {
|
||||||
const state = getState().relver;
|
const state = getState().relver;
|
||||||
let release = state.Release;
|
let release = state.Release;
|
||||||
if (release >= Constants.RELEASE_TYPES.length) {
|
if (release >= Constants.RELEASE_TYPES.length) {
|
||||||
@@ -78,19 +81,21 @@ export const loadReleases = () => {
|
|||||||
let version = state.Version;
|
let version = state.Version;
|
||||||
if (versionLookup[Constants.RELEASE_TYPES[release]][0] === 'unavailable') {
|
if (versionLookup[Constants.RELEASE_TYPES[release]][0] === 'unavailable') {
|
||||||
release = Constants.DEFAULT_RELEASE;
|
release = Constants.DEFAULT_RELEASE;
|
||||||
version = latestVersion = versionLookup[Constants.RELEASE_TYPES[release]].length - 1
|
version = latestVersion = versionLookup[Constants.RELEASE_TYPES[release]].length - 1;
|
||||||
} else if ((version === -1) || !versionLookup[Constants.RELEASE_TYPES[release]][version]) {
|
} else if (version === -1 || !versionLookup[Constants.RELEASE_TYPES[release]][version]) {
|
||||||
version = latestVersion;
|
version = latestVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch(setReleaseData(locationsLookup, versionLookup));
|
dispatch(setReleaseData(locationsLookup, versionLookup));
|
||||||
|
|
||||||
const dispatchActions = (processAllowDismiss = true) => {
|
const dispatchActions = (processAllowDismiss = true) => {
|
||||||
dispatch(setReleaseUpgradeAvailable((version !== latestVersion)));
|
dispatch(setReleaseUpgradeAvailable(version !== latestVersion));
|
||||||
dispatch(setApplicationReady(true));
|
dispatch(setApplicationReady(true));
|
||||||
dispatch(detectUIUpgrade());
|
dispatch(detectUIUpgrade());
|
||||||
if (processAllowDismiss) {
|
if (processAllowDismiss) {
|
||||||
dispatch(setAllowDismissDependencies(versionLookup[Constants.RELEASE_TYPES[release]].length > 1));
|
dispatch(
|
||||||
|
setAllowDismissDependencies(versionLookup[Constants.RELEASE_TYPES[release]].length > 1)
|
||||||
|
);
|
||||||
}
|
}
|
||||||
dispatch(checkVersionInstalled());
|
dispatch(checkVersionInstalled());
|
||||||
|
|
||||||
@@ -98,16 +103,18 @@ export const loadReleases = () => {
|
|||||||
for (const key of Object.keys(locationsLookup)) {
|
for (const key of Object.keys(locationsLookup)) {
|
||||||
versionList.push(key);
|
versionList.push(key);
|
||||||
}
|
}
|
||||||
dispatch(cleanupOldReleases(versionList))
|
dispatch(cleanupOldReleases(versionList));
|
||||||
};
|
};
|
||||||
|
|
||||||
if ((version !== state.Version) || (release !== state.Release)) {
|
if (version !== state.Version || release !== state.Release) {
|
||||||
dispatch(unmountAll(() => {
|
dispatch(
|
||||||
dispatch(setActiveRelease(release, version));
|
unmountAll(() => {
|
||||||
dispatchActions(false);
|
dispatch(setActiveRelease(release, version));
|
||||||
dispatch(showWindow());
|
dispatchActions(false);
|
||||||
dispatch(saveState());
|
dispatch(showWindow());
|
||||||
}));
|
dispatch(saveState());
|
||||||
|
})
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
dispatchActions();
|
dispatchActions();
|
||||||
}
|
}
|
||||||
@@ -115,7 +122,7 @@ export const loadReleases = () => {
|
|||||||
|
|
||||||
axios
|
axios
|
||||||
.get(Constants.RELEASES_URL)
|
.get(Constants.RELEASES_URL)
|
||||||
.then(response => {
|
.then((response) => {
|
||||||
const appPlatform = getState().common.AppPlatform;
|
const appPlatform = getState().common.AppPlatform;
|
||||||
const versionLookup = {
|
const versionLookup = {
|
||||||
Release: response.data.Versions.Release[appPlatform],
|
Release: response.data.Versions.Release[appPlatform],
|
||||||
@@ -129,14 +136,21 @@ export const loadReleases = () => {
|
|||||||
|
|
||||||
const storedReleases = localStorage.getItem('releases');
|
const storedReleases = localStorage.getItem('releases');
|
||||||
let newReleases = [];
|
let newReleases = [];
|
||||||
if (storedReleases && (storedReleases.length > 0)) {
|
if (storedReleases && storedReleases.length > 0) {
|
||||||
newReleases = getNewReleases(JSON.parse(storedReleases).VersionLookup, versionLookup, getSelectedVersionFromState(getState()));
|
newReleases = getNewReleases(
|
||||||
|
JSON.parse(storedReleases).VersionLookup,
|
||||||
|
versionLookup,
|
||||||
|
getSelectedVersionFromState(getState())
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
localStorage.setItem('releases', JSON.stringify({
|
localStorage.setItem(
|
||||||
LocationsLookup: locationsLookup,
|
'releases',
|
||||||
VersionLookup: versionLookup
|
JSON.stringify({
|
||||||
}));
|
LocationsLookup: locationsLookup,
|
||||||
|
VersionLookup: versionLookup,
|
||||||
|
})
|
||||||
|
);
|
||||||
dispatchActions(locationsLookup, versionLookup);
|
dispatchActions(locationsLookup, versionLookup);
|
||||||
|
|
||||||
dispatch(setNewReleasesAvailable(newReleases));
|
dispatch(setNewReleasesAvailable(newReleases));
|
||||||
@@ -144,12 +158,15 @@ export const loadReleases = () => {
|
|||||||
dispatch(setNewReleasesAvailable2(newReleases));
|
dispatch(setNewReleasesAvailable2(newReleases));
|
||||||
localStorage.setItem('previous_releases', storedReleases);
|
localStorage.setItem('previous_releases', storedReleases);
|
||||||
dispatch(showWindow());
|
dispatch(showWindow());
|
||||||
} else if ((newReleases = checkNewReleases(getSelectedVersionFromState(getState()))).length > 0) {
|
} else if (
|
||||||
|
(newReleases = checkNewReleases(getSelectedVersionFromState(getState()))).length > 0
|
||||||
|
) {
|
||||||
dispatch(setNewReleasesAvailable2(newReleases));
|
dispatch(setNewReleasesAvailable2(newReleases));
|
||||||
}
|
}
|
||||||
}).catch(error => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
const releases = localStorage.getItem('releases');
|
const releases = localStorage.getItem('releases');
|
||||||
if (releases && (releases.length > 0)) {
|
if (releases && releases.length > 0) {
|
||||||
const obj = JSON.parse(releases);
|
const obj = JSON.parse(releases);
|
||||||
const locationsLookup = obj.LocationsLookup;
|
const locationsLookup = obj.LocationsLookup;
|
||||||
const versionLookup = obj.VersionLookup;
|
const versionLookup = obj.VersionLookup;
|
||||||
@@ -166,10 +183,7 @@ export const NOTIFY_ACTIVE_RELEASE = 'relver/notifyActiveRelease';
|
|||||||
export const notifyActiveRelease = (release, version) => {
|
export const notifyActiveRelease = (release, version) => {
|
||||||
return {
|
return {
|
||||||
type: NOTIFY_ACTIVE_RELEASE,
|
type: NOTIFY_ACTIVE_RELEASE,
|
||||||
payload: {
|
payload: { release: release, version: version },
|
||||||
release: release,
|
|
||||||
version: version
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -183,7 +197,7 @@ export const setActiveRelease = (release, version) => {
|
|||||||
version = -1;
|
version = -1;
|
||||||
}
|
}
|
||||||
const versions = relver.VersionLookup[Constants.RELEASE_TYPES[release]];
|
const versions = relver.VersionLookup[Constants.RELEASE_TYPES[release]];
|
||||||
dispatch(setAllowDismissDependencies(versions && (versions.length > 1)));
|
dispatch(setAllowDismissDependencies(versions && versions.length > 1));
|
||||||
dispatch(setDismissDependencies(false));
|
dispatch(setDismissDependencies(false));
|
||||||
dispatch(notifyActiveRelease(release, version));
|
dispatch(notifyActiveRelease(release, version));
|
||||||
if (common.AppReady) {
|
if (common.AppReady) {
|
||||||
@@ -200,14 +214,14 @@ export const setNewReleasesAvailable = createAction('relver/setNewReleasesAvaila
|
|||||||
export const setNewReleasesAvailable2 = createAction('relver/setNewReleasesAvailable2');
|
export const setNewReleasesAvailable2 = createAction('relver/setNewReleasesAvailable2');
|
||||||
|
|
||||||
export const SET_RELEASE_DATA = 'relver/setReleaseData';
|
export const SET_RELEASE_DATA = 'relver/setReleaseData';
|
||||||
export const setReleaseData = (locationsLookup, versionLookup)=> {
|
export const setReleaseData = (locationsLookup, versionLookup) => {
|
||||||
return {
|
return {
|
||||||
type: SET_RELEASE_DATA,
|
type: SET_RELEASE_DATA,
|
||||||
payload: {
|
payload: {
|
||||||
locations: locationsLookup,
|
locations: locationsLookup,
|
||||||
versions: versionLookup,
|
versions: versionLookup,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export const setReleaseUpgradeAvailable = createAction('relver/setReleaseUpgradeAvailable');
|
export const setReleaseUpgradeAvailable = createAction('relver/setReleaseUpgradeAvailable');
|
||||||
@@ -219,6 +233,6 @@ export const setUIUpgradeData = (upgradeData, version) => {
|
|||||||
payload: {
|
payload: {
|
||||||
upgrade_data: upgradeData,
|
upgrade_data: upgradeData,
|
||||||
version: version,
|
version: version,
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {createAction} from '@reduxjs/toolkit';
|
import { createAction } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
export const displaySkynetExport = createAction('skynet/displaySkynetExport');
|
export const displaySkynetExport = createAction('skynet/displaySkynetExport');
|
||||||
export const displaySkynetImport = createAction('skynet/displaySkynetImport');
|
export const displaySkynetImport = createAction('skynet/displaySkynetImport');
|
||||||
|
|||||||
@@ -1,71 +1,66 @@
|
|||||||
import {createReducer} from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import {
|
import {
|
||||||
DISPLAY_CONFIRM_YES_NO,
|
confirmYesNoAction,
|
||||||
NOTIFY_APPLICATION_BUSY,
|
NOTIFY_APPLICATION_BUSY,
|
||||||
notifyRebootRequired,
|
notifyRebootRequired,
|
||||||
|
SET_DISPLAY_SELECT_APPPLATFORM,
|
||||||
setAllowMount,
|
setAllowMount,
|
||||||
setApplicationReady,
|
setApplicationReady,
|
||||||
setLinuxAppPlatform,
|
setLinuxAppPlatform,
|
||||||
SET_DISPLAY_SELECT_APPPLATFORM
|
|
||||||
} from '../actions/common_actions';
|
} from '../actions/common_actions';
|
||||||
|
|
||||||
export const createCommonReducer = (platformInfo, version) => {
|
export const createCommonReducer = (platformInfo, version) => {
|
||||||
return createReducer({
|
return createReducer(
|
||||||
AllowMount: false,
|
{
|
||||||
AppBusy: false,
|
AllowMount: false,
|
||||||
AppBusyTransparent: false,
|
AppBusy: false,
|
||||||
AppPlatform: platformInfo.AppPlatform,
|
AppBusyTransparent: false,
|
||||||
AppReady: false,
|
AppPlatform: platformInfo.AppPlatform,
|
||||||
DisplayConfirmYesNo: false,
|
AppReady: false,
|
||||||
ConfirmTitle: null,
|
DisplayConfirmYesNo: false,
|
||||||
DisplaySelectAppPlatform: false,
|
ConfirmTitle: null,
|
||||||
Platform: platformInfo.Platform,
|
DisplaySelectAppPlatform: false,
|
||||||
RebootRequired: false,
|
Platform: platformInfo.Platform,
|
||||||
Version: version,
|
RebootRequired: false,
|
||||||
}, {
|
Version: version,
|
||||||
[DISPLAY_CONFIRM_YES_NO]: (state, action) => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
DisplayConfirmYesNo: action.payload.show,
|
|
||||||
ConfirmTitle: action.payload.show ? action.payload.title : null,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[SET_DISPLAY_SELECT_APPPLATFORM]: (state, action) => {
|
{
|
||||||
return {
|
[confirmYesNoAction.action_type]: (state, action) => {
|
||||||
...state,
|
return {
|
||||||
DisplaySelectAppPlatform: action.payload,
|
...state,
|
||||||
}
|
DisplayConfirmYesNo: action.payload.display,
|
||||||
},
|
ConfirmTitle:
|
||||||
[setAllowMount]: (state, action) => {
|
action.payload.display && action.payload.data ? action.payload.data.title : null,
|
||||||
return {
|
};
|
||||||
...state,
|
},
|
||||||
AllowMount: action.payload,
|
[SET_DISPLAY_SELECT_APPPLATFORM]: (state, action) => {
|
||||||
}
|
return { ...state, DisplaySelectAppPlatform: action.payload };
|
||||||
},
|
},
|
||||||
[setApplicationReady]: (state, action) => {
|
[setAllowMount]: (state, action) => {
|
||||||
return {
|
return { ...state, AllowMount: action.payload };
|
||||||
...state,
|
},
|
||||||
AppReady: action.payload,
|
[setApplicationReady]: (state, action) => {
|
||||||
};
|
return {
|
||||||
},
|
...state,
|
||||||
[setLinuxAppPlatform]: (state, action) => {
|
AppReady: action.payload,
|
||||||
return {
|
};
|
||||||
...state,
|
},
|
||||||
AppPlatform: action.payload,
|
[setLinuxAppPlatform]: (state, action) => {
|
||||||
}
|
return { ...state, AppPlatform: action.payload };
|
||||||
},
|
},
|
||||||
[NOTIFY_APPLICATION_BUSY]: (state, action) => {
|
[NOTIFY_APPLICATION_BUSY]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
AppBusy: action.payload.busy,
|
AppBusy: action.payload.busy,
|
||||||
AppBusyTransparent: action.payload.busy && action.payload.transparent,
|
AppBusyTransparent: action.payload.busy && action.payload.transparent,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[notifyRebootRequired]: (state, action) => {
|
[notifyRebootRequired]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
RebootRequired: action.payload,
|
RebootRequired: action.payload,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
});
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,9 +1,10 @@
|
|||||||
import {createReducer} from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
setAllowDownload,
|
|
||||||
SET_DOWNLOAD_BEGIN,
|
SET_DOWNLOAD_BEGIN,
|
||||||
|
setAllowDownload,
|
||||||
setDownloadEnd,
|
setDownloadEnd,
|
||||||
setDownloadProgress
|
setDownloadProgress,
|
||||||
} from '../actions/download_actions';
|
} from '../actions/download_actions';
|
||||||
|
|
||||||
const defaultDownloadState = {
|
const defaultDownloadState = {
|
||||||
@@ -17,37 +18,37 @@ const defaultDownloadState = {
|
|||||||
DownloadType: null,
|
DownloadType: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
export const downloadReducer = createReducer({
|
export const downloadReducer = createReducer(
|
||||||
...defaultDownloadState,
|
{
|
||||||
AllowDownload: false,
|
...defaultDownloadState,
|
||||||
}, {
|
AllowDownload: false,
|
||||||
[setAllowDownload]: (state, action) => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
AllowDownload: action.payload,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
[SET_DOWNLOAD_BEGIN]: (state, action) => {
|
{
|
||||||
return {
|
[setAllowDownload]: (state, action) => {
|
||||||
...state,
|
return {
|
||||||
...defaultDownloadState,
|
...state,
|
||||||
DownloadActive: true,
|
AllowDownload: action.payload,
|
||||||
DownloadName: action.payload.name,
|
};
|
||||||
DownloadType: action.payload.type,
|
},
|
||||||
DownloadURL: action.payload.url,
|
[SET_DOWNLOAD_BEGIN]: (state, action) => {
|
||||||
}
|
return {
|
||||||
},
|
...state,
|
||||||
[setDownloadEnd]: (state, action) => {
|
...defaultDownloadState,
|
||||||
return {
|
DownloadActive: true,
|
||||||
...state,
|
DownloadName: action.payload.name,
|
||||||
...defaultDownloadState,
|
DownloadType: action.payload.type,
|
||||||
DownloadResult: action.payload,
|
DownloadURL: action.payload.url,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[setDownloadProgress]: (state, action) => {
|
[setDownloadEnd]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
DownloadProgress: action.payload,
|
...defaultDownloadState,
|
||||||
}
|
DownloadResult: action.payload,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
[setDownloadProgress]: (state, action) => {
|
||||||
|
return { ...state, DownloadProgress: action.payload };
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
import {createReducer} from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import {
|
import { CLEAR_ERROR, CLEAR_INFO, SET_ERROR_INFO, SET_INFO } from '../actions/error_actions';
|
||||||
CLEAR_ERROR,
|
|
||||||
CLEAR_INFO,
|
|
||||||
SET_ERROR_INFO,
|
|
||||||
SET_INFO
|
|
||||||
} from '../actions/error_actions';
|
|
||||||
|
|
||||||
export const errorReducer = createReducer({
|
export const errorReducer = createReducer(
|
||||||
DisplayError: false,
|
{
|
||||||
DisplayInfo: false,
|
DisplayError: false,
|
||||||
ErrorCritical: false,
|
DisplayInfo: false,
|
||||||
ErrorStack: [],
|
ErrorCritical: false,
|
||||||
InfoStack: [],
|
ErrorStack: [],
|
||||||
}, {
|
InfoStack: [],
|
||||||
[CLEAR_ERROR]: state => {
|
|
||||||
const errorStack = (state.ErrorStack.length > 0) ? state.ErrorStack.slice(1) : [];
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
DisplayError: (errorStack.length > 0),
|
|
||||||
ErrorStack: errorStack,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[CLEAR_INFO]: state => {
|
{
|
||||||
const infoStack = (state.InfoStack.length > 0) ? state.InfoStack.slice(1) : [];
|
[CLEAR_ERROR]: (state) => {
|
||||||
return {
|
const errorStack = state.ErrorStack.length > 0 ? state.ErrorStack.slice(1) : [];
|
||||||
...state,
|
return {
|
||||||
DisplayInfo: (infoStack.length > 0),
|
...state,
|
||||||
InfoStack: infoStack,
|
DisplayError: errorStack.length > 0,
|
||||||
}
|
ErrorStack: errorStack,
|
||||||
},
|
};
|
||||||
[SET_ERROR_INFO]: (state, action) => {
|
},
|
||||||
const errorStack = [action.payload.msg, ...state.ErrorStack];
|
[CLEAR_INFO]: (state) => {
|
||||||
return {
|
const infoStack = state.InfoStack.length > 0 ? state.InfoStack.slice(1) : [];
|
||||||
...state,
|
return {
|
||||||
DisplayError: true,
|
...state,
|
||||||
ErrorCritical: state.ErrorCritical || action.payload.critical,
|
DisplayInfo: infoStack.length > 0,
|
||||||
ErrorStack: errorStack,
|
InfoStack: infoStack,
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
[SET_INFO]: (state, action) => {
|
[SET_ERROR_INFO]: (state, action) => {
|
||||||
const infoStack = [{
|
const errorStack = [action.payload.msg, ...state.ErrorStack];
|
||||||
title: action.payload.title,
|
return {
|
||||||
message: action.payload.msg
|
...state,
|
||||||
}, ...state.InfoStack];
|
DisplayError: true,
|
||||||
return {
|
ErrorCritical: state.ErrorCritical || action.payload.critical,
|
||||||
...state,
|
ErrorStack: errorStack,
|
||||||
DisplayInfo: true,
|
};
|
||||||
InfoStack: infoStack,
|
},
|
||||||
}
|
[SET_INFO]: (state, action) => {
|
||||||
|
const infoStack = [
|
||||||
|
{
|
||||||
|
title: action.payload.title,
|
||||||
|
message: action.payload.msg,
|
||||||
|
saveToFile: action.payload.saveToFile,
|
||||||
|
fileName: action.payload.fileName,
|
||||||
|
extension: action.payload.extension,
|
||||||
|
},
|
||||||
|
...state.InfoStack,
|
||||||
|
];
|
||||||
|
return { ...state, DisplayInfo: true, InfoStack: infoStack };
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|||||||
20
src/redux/reducers/host_reducer.js
Normal file
20
src/redux/reducers/host_reducer.js
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
|
import { addEditHostAction } from '../actions/host_actions';
|
||||||
|
|
||||||
|
export const hostReducer = createReducer(
|
||||||
|
{
|
||||||
|
DisplayAddEditHost: false,
|
||||||
|
HostData: {},
|
||||||
|
HostList: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
[addEditHostAction.action_type]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
DisplayAddEditHost: action.payload.display,
|
||||||
|
HostData: action.payload.data ? action.payload.data.host_data || {} : {},
|
||||||
|
HostList: action.payload.data ? action.payload.data.host_list || [] : [],
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
@@ -1,60 +1,51 @@
|
|||||||
import {createReducer} from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import {
|
import {
|
||||||
setAutoInstallRelease,
|
setAutoInstallRelease,
|
||||||
setDismissDependencies,
|
setDismissDependencies,
|
||||||
setInstallActive,
|
setInstallActive,
|
||||||
setInstallComplete,
|
setInstallComplete,
|
||||||
setInstallTestActive,
|
setInstallTestActive,
|
||||||
setMissingDependencies
|
setMissingDependencies,
|
||||||
} from '../actions/install_actions';
|
} from '../actions/install_actions';
|
||||||
|
|
||||||
export const installReducer = createReducer({
|
export const installReducer = createReducer(
|
||||||
AutoInstallRelease: false,
|
{
|
||||||
DismissDependencies: false,
|
AutoInstallRelease: false,
|
||||||
InstallActive: false,
|
DismissDependencies: false,
|
||||||
InstallResult: null,
|
InstallActive: false,
|
||||||
InstallTestActive: false,
|
InstallResult: null,
|
||||||
InstallType: null,
|
InstallTestActive: false,
|
||||||
MissingDependencies: [],
|
InstallType: null,
|
||||||
}, {
|
MissingDependencies: [],
|
||||||
[setAutoInstallRelease]: (state, action) => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
AutoInstallRelease: action.payload,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[setDismissDependencies]: (state, action) => {
|
{
|
||||||
return {
|
[setAutoInstallRelease]: (state, action) => {
|
||||||
...state,
|
return { ...state, AutoInstallRelease: action.payload };
|
||||||
DismissDependencies: action.payload,
|
},
|
||||||
}
|
[setDismissDependencies]: (state, action) => {
|
||||||
},
|
return { ...state, DismissDependencies: action.payload };
|
||||||
[setInstallActive]: (state, action) => {
|
},
|
||||||
return {
|
[setInstallActive]: (state, action) => {
|
||||||
...state,
|
return {
|
||||||
InstallActive: true,
|
...state,
|
||||||
InstallResult: null,
|
InstallActive: true,
|
||||||
InstallType: action.payload,
|
InstallResult: null,
|
||||||
};
|
InstallType: action.payload,
|
||||||
},
|
};
|
||||||
[setInstallComplete]: (state, action) => {
|
},
|
||||||
return {
|
[setInstallComplete]: (state, action) => {
|
||||||
...state,
|
return {
|
||||||
InstallActive: false,
|
...state,
|
||||||
InstallResult: action.payload,
|
InstallActive: false,
|
||||||
InstallType: null,
|
InstallResult: action.payload,
|
||||||
}
|
InstallType: null,
|
||||||
},
|
};
|
||||||
[setInstallTestActive]: (state, action) => {
|
},
|
||||||
return {
|
[setInstallTestActive]: (state, action) => {
|
||||||
...state,
|
return { ...state, InstallTestActive: action.payload };
|
||||||
InstallTestActive: action.payload,
|
},
|
||||||
}
|
[setMissingDependencies]: (state, action) => {
|
||||||
},
|
return { ...state, MissingDependencies: action.payload };
|
||||||
[setMissingDependencies]: (state, action) => {
|
},
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
MissingDependencies: action.payload,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import {createReducer} from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
|
|
||||||
import * as Constants from '../../constants';
|
import * as Constants from '../../constants';
|
||||||
import {
|
import {
|
||||||
@@ -12,49 +12,49 @@ import {
|
|||||||
SET_MOUNT_STATE,
|
SET_MOUNT_STATE,
|
||||||
SET_MOUNTED,
|
SET_MOUNTED,
|
||||||
SET_PROVIDER_STATE,
|
SET_PROVIDER_STATE,
|
||||||
setBusy
|
setBusy,
|
||||||
} from '../actions/mount_actions';
|
} from '../actions/mount_actions';
|
||||||
|
|
||||||
export const createMountReducer = state => {
|
export const createMountReducer = (state) => {
|
||||||
let providerList = [
|
let providerList = [
|
||||||
...Constants.PROVIDER_LIST,
|
...Constants.PROVIDER_LIST,
|
||||||
...(state.RemoteMounts || []),
|
...(state.RemoteMounts || []),
|
||||||
...(state.S3Mounts || []),
|
...(state.S3Mounts || []),
|
||||||
];
|
];
|
||||||
const providerState = providerList
|
const providerState = providerList
|
||||||
.map(provider => {
|
.map((provider) => {
|
||||||
return {
|
return {
|
||||||
[provider]: {
|
[provider]: {
|
||||||
AutoMount: false,
|
AutoMount: false,
|
||||||
AutoRestart: false,
|
AutoRestart: false,
|
||||||
MountLocation: '',
|
MountLocation: '',
|
||||||
}
|
},
|
||||||
}
|
};
|
||||||
})
|
|
||||||
.reduce((map, obj) => {
|
|
||||||
return {...map, ...obj}
|
|
||||||
});
|
|
||||||
|
|
||||||
const mountState = providerList
|
|
||||||
.map(provider => {
|
|
||||||
return {
|
|
||||||
[provider]: {
|
|
||||||
AllowMount: false,
|
|
||||||
DriveLetters: [],
|
|
||||||
Mounted: false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.reduce((map, obj) => {
|
|
||||||
return {...map, ...obj}
|
|
||||||
});
|
|
||||||
|
|
||||||
const autoMountProcessed =
|
|
||||||
providerList.map(provider => {
|
|
||||||
return {[provider]: false,}
|
|
||||||
})
|
})
|
||||||
.reduce((map, obj) => {
|
.reduce((map, obj) => {
|
||||||
return {...map, ...obj}
|
return { ...map, ...obj };
|
||||||
|
});
|
||||||
|
|
||||||
|
const mountState = providerList
|
||||||
|
.map((provider) => {
|
||||||
|
return {
|
||||||
|
[provider]: {
|
||||||
|
AllowMount: false,
|
||||||
|
DriveLetters: [],
|
||||||
|
Mounted: false,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.reduce((map, obj) => {
|
||||||
|
return { ...map, ...obj };
|
||||||
|
});
|
||||||
|
|
||||||
|
const autoMountProcessed = providerList
|
||||||
|
.map((provider) => {
|
||||||
|
return { [provider]: false };
|
||||||
|
})
|
||||||
|
.reduce((map, obj) => {
|
||||||
|
return { ...map, ...obj };
|
||||||
});
|
});
|
||||||
|
|
||||||
return createReducer(
|
return createReducer(
|
||||||
@@ -71,52 +71,56 @@ export const createMountReducer = state => {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
[addRemoteMount2]: (state, action) => {
|
[addRemoteMount2]: (state, action) => {
|
||||||
let mountState = {...state.MountState};
|
let mountState = { ...state.MountState };
|
||||||
mountState[action.payload] = {
|
mountState[action.payload] = {
|
||||||
AllowMount: false,
|
AllowMount: false,
|
||||||
DriveLetters: [],
|
DriveLetters: [],
|
||||||
Mounted: false,
|
Mounted: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let providerState = {...state.ProviderState};
|
let providerState = { ...state.ProviderState };
|
||||||
providerState[action.payload] = {
|
providerState[action.payload] = {
|
||||||
AutoMount: false,
|
AutoMount: false,
|
||||||
AutoRestart: false,
|
AutoRestart: false,
|
||||||
MountLocation: '',
|
MountLocation: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
let autoMountProcessed = {...state.AutoMountProcessed};
|
let autoMountProcessed = { ...state.AutoMountProcessed };
|
||||||
autoMountProcessed[action.payload] = true;
|
autoMountProcessed[action.payload] = true;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state, AutoMountProcessed: autoMountProcessed,
|
...state,
|
||||||
MountState: mountState, ProviderState: providerState,
|
AutoMountProcessed: autoMountProcessed,
|
||||||
|
MountState: mountState,
|
||||||
|
ProviderState: providerState,
|
||||||
RemoteMounts: [...state.RemoteMounts, action.payload],
|
RemoteMounts: [...state.RemoteMounts, action.payload],
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
[addS3Mount2]: (state, action) => {
|
[addS3Mount2]: (state, action) => {
|
||||||
let mountState = {...state.MountState};
|
let mountState = { ...state.MountState };
|
||||||
mountState[action.payload] = {
|
mountState[action.payload] = {
|
||||||
AllowMount: false,
|
AllowMount: false,
|
||||||
DriveLetters: [],
|
DriveLetters: [],
|
||||||
Mounted: false,
|
Mounted: false,
|
||||||
};
|
};
|
||||||
|
|
||||||
let providerState = {...state.ProviderState};
|
let providerState = { ...state.ProviderState };
|
||||||
providerState[action.payload] = {
|
providerState[action.payload] = {
|
||||||
AutoMount: false,
|
AutoMount: false,
|
||||||
AutoRestart: false,
|
AutoRestart: false,
|
||||||
MountLocation: '',
|
MountLocation: '',
|
||||||
};
|
};
|
||||||
|
|
||||||
let autoMountProcessed = {...state.AutoMountProcessed};
|
let autoMountProcessed = { ...state.AutoMountProcessed };
|
||||||
autoMountProcessed[action.payload] = true;
|
autoMountProcessed[action.payload] = true;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...state, AutoMountProcessed: autoMountProcessed,
|
...state,
|
||||||
MountState: mountState, ProviderState: providerState,
|
AutoMountProcessed: autoMountProcessed,
|
||||||
|
MountState: mountState,
|
||||||
|
ProviderState: providerState,
|
||||||
S3Mounts: [...state.S3Mounts, action.payload],
|
S3Mounts: [...state.S3Mounts, action.payload],
|
||||||
}
|
};
|
||||||
},
|
},
|
||||||
[DISPLAY_CONFIGURATION]: (state, action) => {
|
[DISPLAY_CONFIGURATION]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
@@ -127,19 +131,17 @@ export const createMountReducer = state => {
|
|||||||
};
|
};
|
||||||
},
|
},
|
||||||
[removeMount3]: (state, action) => {
|
[removeMount3]: (state, action) => {
|
||||||
let mountState = {...state.MountState};
|
let mountState = { ...state.MountState };
|
||||||
delete mountState[action.payload];
|
delete mountState[action.payload];
|
||||||
|
|
||||||
let providerState = {...state.ProviderState};
|
let providerState = { ...state.ProviderState };
|
||||||
delete providerState[action.payload];
|
delete providerState[action.payload];
|
||||||
|
|
||||||
let autoMountProcessed = {...state.AutoMountProcessed};
|
let autoMountProcessed = { ...state.AutoMountProcessed };
|
||||||
delete autoMountProcessed[action.payload];
|
delete autoMountProcessed[action.payload];
|
||||||
|
|
||||||
const remoteMounts =
|
const remoteMounts = state.RemoteMounts.filter((i) => i !== action.payload);
|
||||||
state.RemoteMounts.filter(i => i !== action.payload);
|
const s3Mounts = state.S3Mounts.filter((i) => i !== action.payload);
|
||||||
const s3Mounts =
|
|
||||||
state.S3Mounts.filter(i => i !== action.payload);
|
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
AutoMountProcessed: autoMountProcessed,
|
AutoMountProcessed: autoMountProcessed,
|
||||||
@@ -149,8 +151,8 @@ export const createMountReducer = state => {
|
|||||||
S3Mounts: s3Mounts,
|
S3Mounts: s3Mounts,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[RESET_MOUNTS_STATE]: (state, action) => {
|
[RESET_MOUNTS_STATE]: (state) => {
|
||||||
return {...state, MountsBusy: false, MountState: mountState,}
|
return { ...state, MountsBusy: false, MountState: mountState };
|
||||||
},
|
},
|
||||||
[SET_AUTO_MOUNT_PROCESSED]: (state, action) => {
|
[SET_AUTO_MOUNT_PROCESSED]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
@@ -158,7 +160,7 @@ export const createMountReducer = state => {
|
|||||||
AutoMountProcessed: {
|
AutoMountProcessed: {
|
||||||
...state.AutoMountProcessed,
|
...state.AutoMountProcessed,
|
||||||
[action.payload.provider]: action.payload.processed,
|
[action.payload.provider]: action.payload.processed,
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[SET_ALLOW_MOUNT]: (state, action) => {
|
[SET_ALLOW_MOUNT]: (state, action) => {
|
||||||
@@ -169,15 +171,13 @@ export const createMountReducer = state => {
|
|||||||
[action.payload.provider]: {
|
[action.payload.provider]: {
|
||||||
...state.MountState[action.payload.provider],
|
...state.MountState[action.payload.provider],
|
||||||
AllowMount: action.payload.allow,
|
AllowMount: action.payload.allow,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[setBusy]:
|
[setBusy]: (state, action) => {
|
||||||
(state,
|
return { ...state, MountsBusy: action.payload };
|
||||||
action) => {
|
},
|
||||||
return {...state, MountsBusy: action.payload};
|
|
||||||
},
|
|
||||||
[SET_MOUNT_STATE]: (state, action) => {
|
[SET_MOUNT_STATE]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
@@ -185,9 +185,9 @@ export const createMountReducer = state => {
|
|||||||
...state.MountState,
|
...state.MountState,
|
||||||
[action.payload.provider]: {
|
[action.payload.provider]: {
|
||||||
...state.MountState[action.payload.provider],
|
...state.MountState[action.payload.provider],
|
||||||
...action.payload.state
|
...action.payload.state,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[SET_MOUNTED]: (state, action) => {
|
[SET_MOUNTED]: (state, action) => {
|
||||||
@@ -198,8 +198,8 @@ export const createMountReducer = state => {
|
|||||||
[action.payload.provider]: {
|
[action.payload.provider]: {
|
||||||
...state.MountState[action.payload.provider],
|
...state.MountState[action.payload.provider],
|
||||||
Mounted: action.payload.mounted,
|
Mounted: action.payload.mounted,
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[SET_PROVIDER_STATE]: (state, action) => {
|
[SET_PROVIDER_STATE]: (state, action) => {
|
||||||
@@ -209,10 +209,11 @@ export const createMountReducer = state => {
|
|||||||
...state.ProviderState,
|
...state.ProviderState,
|
||||||
[action.payload.provider]: {
|
[action.payload.provider]: {
|
||||||
...state.ProviderState[action.payload.provider],
|
...state.ProviderState[action.payload.provider],
|
||||||
...action.payload.state
|
...action.payload.state,
|
||||||
},
|
},
|
||||||
}
|
},
|
||||||
};
|
};
|
||||||
}
|
},
|
||||||
});
|
}
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,13 +1,16 @@
|
|||||||
import {createReducer} from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import {displayPinnedManager} from '../actions/pinned_manager_actions';
|
import { displayPinnedManager } from '../actions/pinned_manager_actions';
|
||||||
|
|
||||||
export const pinnedManagerReducer = createReducer({
|
export const pinnedManagerReducer = createReducer(
|
||||||
DisplayPinnedManager: false,
|
{
|
||||||
}, {
|
DisplayPinnedManager: false,
|
||||||
[displayPinnedManager]: (state, action) => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
DisplayPinnedManager: action.payload,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
});
|
{
|
||||||
|
[displayPinnedManager]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
DisplayPinnedManager: action.payload,
|
||||||
|
};
|
||||||
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
import {createReducer} from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import * as Actions from '../actions/release_version_actions';
|
|
||||||
import * as Constants from '../../constants';
|
|
||||||
|
|
||||||
const versionLookup = Constants.RELEASE_TYPES.map(k=> {
|
import * as Constants from '../../constants';
|
||||||
return {
|
import * as Actions from '../actions/release_version_actions';
|
||||||
[k]: ['unavailable']
|
|
||||||
};
|
const versionLookup = Constants.RELEASE_TYPES.map((k) => {
|
||||||
|
return { [k]: ['unavailable'] };
|
||||||
}).reduce((map, obj) => {
|
}).reduce((map, obj) => {
|
||||||
return {
|
return {
|
||||||
...map,
|
...map,
|
||||||
@@ -13,95 +12,95 @@ const versionLookup = Constants.RELEASE_TYPES.map(k=> {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
export const releaseVersionReducer = createReducer({
|
export const releaseVersionReducer = createReducer(
|
||||||
AllowDismissDependencies: false,
|
{
|
||||||
DismissNewReleasesAvailable: true,
|
AllowDismissDependencies: false,
|
||||||
InstalledVersion: 'none',
|
DismissNewReleasesAvailable: true,
|
||||||
LocationsLookup: {},
|
InstalledVersion: 'none',
|
||||||
NewReleasesAvailable: [],
|
LocationsLookup: {},
|
||||||
NewReleasesAvailable2: [],
|
NewReleasesAvailable: [],
|
||||||
Release: Constants.DEFAULT_RELEASE,
|
NewReleasesAvailable2: [],
|
||||||
ReleaseUpgradeAvailable: false,
|
Release: Constants.DEFAULT_RELEASE,
|
||||||
UpgradeAvailable: false,
|
ReleaseUpgradeAvailable: false,
|
||||||
UpgradeData: null,
|
UpgradeAvailable: false,
|
||||||
UpgradeVersion: null,
|
UpgradeData: null,
|
||||||
UpgradeDismissed: false,
|
UpgradeVersion: null,
|
||||||
Version: -1,
|
UpgradeDismissed: false,
|
||||||
VersionLookup: versionLookup,
|
Version: -1,
|
||||||
}, {
|
VersionLookup: versionLookup,
|
||||||
[Actions.CLEAR_UI_UPGRADE]: state => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
UpgradeAvailable: false,
|
|
||||||
UpgradeDismissed: false,
|
|
||||||
UpgradeData: null,
|
|
||||||
UpgradeVersion: null,
|
|
||||||
};
|
|
||||||
},
|
},
|
||||||
[Actions.NOTIFY_ACTIVE_RELEASE]: (state, action) => {
|
{
|
||||||
return {
|
[Actions.CLEAR_UI_UPGRADE]: (state) => {
|
||||||
...state,
|
return {
|
||||||
Release: action.payload.release,
|
...state,
|
||||||
Version: action.payload.version
|
UpgradeAvailable: false,
|
||||||
};
|
UpgradeDismissed: false,
|
||||||
},
|
UpgradeData: null,
|
||||||
[Actions.setAllowDismissDependencies]: (state, action) => {
|
UpgradeVersion: null,
|
||||||
return {
|
};
|
||||||
...state,
|
},
|
||||||
AllowDismissDependencies: action.payload,
|
[Actions.NOTIFY_ACTIVE_RELEASE]: (state, action) => {
|
||||||
};
|
return {
|
||||||
},
|
...state,
|
||||||
[Actions.setDismissNewReleasesAvailable]: (state, action) => {
|
Release: action.payload.release,
|
||||||
return {
|
Version: action.payload.version,
|
||||||
...state,
|
};
|
||||||
DismissNewReleasesAvailable: action.payload,
|
},
|
||||||
};
|
[Actions.setAllowDismissDependencies]: (state, action) => {
|
||||||
},
|
return {
|
||||||
[Actions.setDismissUIUpgrade]: (state, action) => {
|
...state,
|
||||||
return {
|
AllowDismissDependencies: action.payload,
|
||||||
...state,
|
};
|
||||||
UpgradeDismissed: action.payload,
|
},
|
||||||
};
|
[Actions.setDismissNewReleasesAvailable]: (state, action) => {
|
||||||
},
|
return {
|
||||||
[Actions.setInstalledVersion]: (state, action) => {
|
...state,
|
||||||
return {
|
DismissNewReleasesAvailable: action.payload,
|
||||||
...state,
|
};
|
||||||
InstalledVersion: action.payload,
|
},
|
||||||
}
|
[Actions.setDismissUIUpgrade]: (state, action) => {
|
||||||
},
|
return {
|
||||||
[Actions.setNewReleasesAvailable]: (state, action) => {
|
...state,
|
||||||
return {
|
UpgradeDismissed: action.payload,
|
||||||
...state,
|
};
|
||||||
DismissNewReleasesAvailable: false,
|
},
|
||||||
NewReleasesAvailable: action.payload,
|
[Actions.setInstalledVersion]: (state, action) => {
|
||||||
};
|
return { ...state, InstalledVersion: action.payload };
|
||||||
},
|
},
|
||||||
[Actions.setNewReleasesAvailable2]: (state, action) => {
|
[Actions.setNewReleasesAvailable]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
NewReleasesAvailable2: action.payload,
|
DismissNewReleasesAvailable: false,
|
||||||
};
|
NewReleasesAvailable: action.payload,
|
||||||
},
|
};
|
||||||
[Actions.SET_RELEASE_DATA]: (state, action) => {
|
},
|
||||||
return {
|
[Actions.setNewReleasesAvailable2]: (state, action) => {
|
||||||
...state,
|
return {
|
||||||
LocationsLookup: action.payload.locations,
|
...state,
|
||||||
VersionLookup: action.payload.versions,
|
NewReleasesAvailable2: action.payload,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
[Actions.setReleaseUpgradeAvailable]: (state, action) => {
|
[Actions.SET_RELEASE_DATA]: (state, action) => {
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
ReleaseUpgradeAvailable: action.payload,
|
LocationsLookup: action.payload.locations,
|
||||||
};
|
VersionLookup: action.payload.versions,
|
||||||
},
|
};
|
||||||
[Actions.SET_UI_UPGRADE_DATA]: (state, action) => {
|
},
|
||||||
return {
|
[Actions.setReleaseUpgradeAvailable]: (state, action) => {
|
||||||
...state,
|
return {
|
||||||
UpgradeAvailable: true,
|
...state,
|
||||||
UpgradeData: action.payload.upgrade_data,
|
ReleaseUpgradeAvailable: action.payload,
|
||||||
UpgradeVersion: action.payload.version,
|
};
|
||||||
UpgradeDismissed: false,
|
},
|
||||||
};
|
[Actions.SET_UI_UPGRADE_DATA]: (state, action) => {
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
UpgradeAvailable: true,
|
||||||
|
UpgradeData: action.payload.upgrade_data,
|
||||||
|
UpgradeVersion: action.payload.version,
|
||||||
|
UpgradeDismissed: false,
|
||||||
|
};
|
||||||
|
},
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
|
|||||||
@@ -1,20 +1,17 @@
|
|||||||
import {createReducer} from '@reduxjs/toolkit';
|
import { createReducer } from '@reduxjs/toolkit';
|
||||||
import * as Actions from '../actions/skynet_actions';
|
import * as Actions from '../actions/skynet_actions';
|
||||||
|
|
||||||
export const skynetReducer = createReducer({
|
export const skynetReducer = createReducer(
|
||||||
DisplayExport: false,
|
{
|
||||||
DisplayImport: false,
|
DisplayExport: false,
|
||||||
}, {
|
DisplayImport: false,
|
||||||
[Actions.displaySkynetExport]: (state, action) => {
|
|
||||||
return {
|
|
||||||
...state,
|
|
||||||
DisplayExport: action.payload,
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
[Actions.displaySkynetImport]: (state, action) => {
|
{
|
||||||
return {
|
[Actions.displaySkynetExport]: (state, action) => {
|
||||||
...state,
|
return { ...state, DisplayExport: action.payload };
|
||||||
DisplayImport: action.payload,
|
},
|
||||||
}
|
[Actions.displaySkynetImport]: (state, action) => {
|
||||||
},
|
return { ...state, DisplayImport: action.payload };
|
||||||
});
|
},
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|||||||
@@ -1,18 +1,21 @@
|
|||||||
import {configureStore, getDefaultMiddleware} from '@reduxjs/toolkit';
|
import { configureStore, getDefaultMiddleware } from '@reduxjs/toolkit';
|
||||||
import {createCommonReducer} from '../reducers/common_reducer';
|
|
||||||
import {downloadReducer} from '../reducers/download_reducer';
|
import { createCommonReducer } from '../reducers/common_reducer';
|
||||||
import {errorReducer} from '../reducers/error_reducer';
|
import { downloadReducer } from '../reducers/download_reducer';
|
||||||
import {installReducer} from '../reducers/install_reducer';
|
import { errorReducer } from '../reducers/error_reducer';
|
||||||
import {createMountReducer} from '../reducers/mount_reducer';
|
import { installReducer } from '../reducers/install_reducer';
|
||||||
import {releaseVersionReducer} from '../reducers/release_version_reducer';
|
import { createMountReducer } from '../reducers/mount_reducer';
|
||||||
import {skynetReducer} from '../reducers/skynet_reducer';
|
import { pinnedManagerReducer } from '../reducers/pinned_manager_reducer';
|
||||||
import {pinnedManagerReducer} from '../reducers/pinned_manager_reducer'
|
import { releaseVersionReducer } from '../reducers/release_version_reducer';
|
||||||
|
import { skynetReducer } from '../reducers/skynet_reducer';
|
||||||
|
import { hostReducer } from '../reducers/host_reducer';
|
||||||
|
|
||||||
export default function createAppStore(platformInfo, version, state) {
|
export default function createAppStore(platformInfo, version, state) {
|
||||||
const reducer = {
|
const reducer = {
|
||||||
common: createCommonReducer(platformInfo, version),
|
common: createCommonReducer(platformInfo, version),
|
||||||
download: downloadReducer,
|
download: downloadReducer,
|
||||||
error: errorReducer,
|
error: errorReducer,
|
||||||
|
host: hostReducer,
|
||||||
install: installReducer,
|
install: installReducer,
|
||||||
mounts: createMountReducer(state),
|
mounts: createMountReducer(state),
|
||||||
relver: releaseVersionReducer,
|
relver: releaseVersionReducer,
|
||||||
@@ -25,6 +28,6 @@ export default function createAppStore(platformInfo, version, state) {
|
|||||||
return configureStore({
|
return configureStore({
|
||||||
reducer,
|
reducer,
|
||||||
middleware,
|
middleware,
|
||||||
devTools: process.env.NODE_ENV !== 'production'
|
devTools: process.env.NODE_ENV !== 'production',
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
47
src/redux/utils.js
Normal file
47
src/redux/utils.js
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
export const createResponseDialogAction = (type, name) => {
|
||||||
|
let resolverList = [];
|
||||||
|
|
||||||
|
const display = (show, cb, data) => {
|
||||||
|
return (dispatch) => {
|
||||||
|
if (cb) {
|
||||||
|
dispatch(display(show, null, data)).then(({ changed, data }) => cb(changed, data));
|
||||||
|
} else {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
dispatch(handleDisplay(show, data, resolve));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleDisplay = (show, data, resolve) => {
|
||||||
|
return (dispatch) => {
|
||||||
|
if (show) {
|
||||||
|
resolverList.push(resolve);
|
||||||
|
dispatch(displayAction(show, data));
|
||||||
|
} else {
|
||||||
|
dispatch(complete(false));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const complete = (changed, data) => {
|
||||||
|
return (dispatch) => {
|
||||||
|
if (changed) {
|
||||||
|
resolverList[0]({ changed, data });
|
||||||
|
}
|
||||||
|
resolverList.splice(0, 1);
|
||||||
|
dispatch(displayAction(false));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const DISPLAY_ACTION = type + '/' + name;
|
||||||
|
const displayAction = (display, data) => {
|
||||||
|
return { type: DISPLAY_ACTION, payload: { display, data } };
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
action_type: DISPLAY_ACTION,
|
||||||
|
complete,
|
||||||
|
display,
|
||||||
|
};
|
||||||
|
};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
|
|
||||||
const addListeners = (ipcMain, {closeApplication, setWindowVisibility}) => {
|
const addListeners = (ipcMain, { closeApplication, setWindowVisibility }) => {
|
||||||
ipcMain.on(Constants.IPC_Shutdown, () => {
|
ipcMain.on(Constants.IPC_Shutdown, () => {
|
||||||
closeApplication();
|
closeApplication();
|
||||||
});
|
});
|
||||||
@@ -9,12 +9,10 @@ const addListeners = (ipcMain, {closeApplication, setWindowVisibility}) => {
|
|||||||
setWindowVisibility(true);
|
setWindowVisibility(true);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Show_Window + '_sync', event => {
|
ipcMain.on(Constants.IPC_Show_Window + '_sync', (event) => {
|
||||||
setWindowVisibility(true);
|
setWindowVisibility(true);
|
||||||
event.returnValue = true;
|
event.returnValue = true;
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = { addListeners };
|
||||||
addListeners
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,48 +1,55 @@
|
|||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
|
|
||||||
const addListeners = (ipcMain, {standardIPCReply}) => {
|
const addListeners = (ipcMain, { standardIPCReply }) => {
|
||||||
ipcMain.on(Constants.IPC_Get_Config, (event, data) => {
|
ipcMain.on(Constants.IPC_Get_Config, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.getConfig(data.Version, data.Provider, data.Remote, data.S3)
|
.getConfig(data.Version, data.Provider, data.Remote, data.S3)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
if (data.Code === 0) {
|
if (data.Code === 0) {
|
||||||
standardIPCReply(event, Constants.IPC_Get_Config_Reply, {
|
standardIPCReply(event, Constants.IPC_Get_Config_Reply, {
|
||||||
Config: data.Data,
|
Config: data.Data,
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, data.Code);
|
standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, data.Code);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, error);
|
standardIPCReply(event, Constants.IPC_Get_Config_Reply, {}, error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Get_Config_Template, (event, data) => {
|
ipcMain.on(Constants.IPC_Get_Config_Template, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.getConfigTemplate(data.Version, data.Provider, data.Remote, data.S3)
|
.getConfigTemplate(data.Version, data.Provider, data.Remote, data.S3)
|
||||||
.then((data) => {
|
.then((data) => {
|
||||||
standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, {
|
standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, {
|
||||||
Template: data,
|
Template: data,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, {}, error);
|
||||||
});
|
});
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
standardIPCReply(event, Constants.IPC_Get_Config_Template_Reply, {}, error);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Set_Config_Values, (event, data) => {
|
ipcMain.on(Constants.IPC_Set_Config_Values, (event, data) => {
|
||||||
const setConfigValue = (i) => {
|
const setConfigValue = (i) => {
|
||||||
if (i < data.Items.length) {
|
if (i < data.Items.length) {
|
||||||
helpers
|
helpers
|
||||||
.setConfigValue(data.Items[i].Name, data.Items[i].Value, data.Provider, data.Remote, data.S3, data.Version)
|
.setConfigValue(
|
||||||
.then(() => {
|
data.Items[i].Name,
|
||||||
setConfigValue(++i);
|
data.Items[i].Value,
|
||||||
})
|
data.Provider,
|
||||||
.catch(error => {
|
data.Remote,
|
||||||
standardIPCReply(event, Constants.IPC_Set_Config_Values_Reply, {}, error);
|
data.S3,
|
||||||
});
|
data.Version
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
setConfigValue(++i);
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Set_Config_Values_Reply, {}, error);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
standardIPCReply(event, Constants.IPC_Set_Config_Values_Reply, {});
|
standardIPCReply(event, Constants.IPC_Set_Config_Values_Reply, {});
|
||||||
}
|
}
|
||||||
@@ -51,6 +58,4 @@ const addListeners = (ipcMain, {standardIPCReply}) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = { addListeners };
|
||||||
addListeners
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,47 +1,46 @@
|
|||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
|
|
||||||
const addListeners = (ipcMain, {standardIPCReply}) => {
|
const addListeners = (ipcMain, { standardIPCReply }) => {
|
||||||
ipcMain.on(Constants.IPC_Check_Daemon_Version, (event, data) => {
|
ipcMain.on(Constants.IPC_Check_Daemon_Version, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.checkDaemonVersion(data.Version, data.Provider)
|
.checkDaemonVersion(data.Version, data.Provider)
|
||||||
.then(code => {
|
.then((code) => {
|
||||||
standardIPCReply(event, Constants.IPC_Check_Daemon_Version_Reply, {
|
standardIPCReply(event, Constants.IPC_Check_Daemon_Version_Reply, {
|
||||||
Valid: (code === 0),
|
Valid: code === 0,
|
||||||
Code: code,
|
Code: code,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
standardIPCReply(
|
||||||
|
event,
|
||||||
|
Constants.IPC_Check_Daemon_Version_Reply,
|
||||||
|
{
|
||||||
|
Valid: false,
|
||||||
|
},
|
||||||
|
e
|
||||||
|
);
|
||||||
});
|
});
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
standardIPCReply(event, Constants.IPC_Check_Daemon_Version_Reply, {
|
|
||||||
Valid: false,
|
|
||||||
}, e);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Check_Daemon_Version + '_sync', (event, data) => {
|
ipcMain.on(Constants.IPC_Check_Daemon_Version + '_sync', (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.checkDaemonVersion(data.Version, data.Provider)
|
.checkDaemonVersion(data.Version, data.Provider)
|
||||||
.then(code => {
|
.then((code) => {
|
||||||
event.returnValue = {
|
event.returnValue = {
|
||||||
data: {
|
data: {
|
||||||
Success: true,
|
Success: true,
|
||||||
Valid: (code === 0),
|
Valid: code === 0,
|
||||||
Code: code,
|
Code: code,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch((e) => {
|
||||||
event.returnValue = {
|
event.returnValue = {
|
||||||
data: {
|
data: { Error: e.toString(), Success: false, Valid: false },
|
||||||
Error: e.toString(),
|
};
|
||||||
Success: false,
|
});
|
||||||
Valid: false
|
|
||||||
},
|
|
||||||
};
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = { addListeners };
|
||||||
addListeners
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ const Constants = require('../../constants');
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
|
|
||||||
const addListeners = (ipcMain, {standardIPCReply}) => {
|
const addListeners = (ipcMain, { standardIPCReply }) => {
|
||||||
ipcMain.on(Constants.IPC_Check_Dependency_Installed, (event, data) => {
|
ipcMain.on(Constants.IPC_Check_Dependency_Installed, (event, data) => {
|
||||||
try {
|
try {
|
||||||
const exists = fs.lstatSync(data.File).isFile();
|
const exists = fs.lstatSync(data.File).isFile();
|
||||||
@@ -13,7 +13,7 @@ const addListeners = (ipcMain, {standardIPCReply}) => {
|
|||||||
});
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
standardIPCReply(event, Constants.IPC_Check_Dependency_Installed_Reply, {
|
standardIPCReply(event, Constants.IPC_Check_Dependency_Installed_Reply, {
|
||||||
data : {
|
data: {
|
||||||
Exists: false,
|
Exists: false,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@@ -30,9 +30,7 @@ const addListeners = (ipcMain, {standardIPCReply}) => {
|
|||||||
};
|
};
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
event.returnValue = {
|
event.returnValue = {
|
||||||
data: {
|
data: { Exists: false },
|
||||||
Exists: false
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -40,56 +38,71 @@ const addListeners = (ipcMain, {standardIPCReply}) => {
|
|||||||
ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => {
|
ipcMain.on(Constants.IPC_Install_Dependency, (event, data) => {
|
||||||
if (data.Source.toLowerCase().endsWith('.dmg')) {
|
if (data.Source.toLowerCase().endsWith('.dmg')) {
|
||||||
helpers
|
helpers
|
||||||
.executeAsync('open', ['-a', 'Finder', '-W', data.Source])
|
.executeAsync('open', ['-a', 'Finder', '-W', data.Source])
|
||||||
.then(() => {
|
|
||||||
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
|
||||||
Source: data.Source,
|
|
||||||
URL: data.URL,
|
|
||||||
});
|
|
||||||
})
|
|
||||||
.catch(error=> {
|
|
||||||
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
|
||||||
Source: data.Source,
|
|
||||||
URL: data.URL,
|
|
||||||
}, error);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
const execInstall = () => {
|
|
||||||
helpers
|
|
||||||
.executeAndWait(data.Source)
|
|
||||||
.then(() => {
|
.then(() => {
|
||||||
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
||||||
Source: data.Source,
|
Source: data.Source,
|
||||||
URL: data.URL,
|
URL: data.URL,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
standardIPCReply(
|
||||||
Source: data.Source,
|
event,
|
||||||
URL: data.URL,
|
Constants.IPC_Install_Dependency_Reply,
|
||||||
}, error);
|
{
|
||||||
|
Source: data.Source,
|
||||||
|
URL: data.URL,
|
||||||
|
},
|
||||||
|
error
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
} else {
|
||||||
if (data.IsWinFSP) {
|
const execInstall = () => {
|
||||||
helpers
|
helpers
|
||||||
.performWindowsUninstall(Constants.WINFSP_VERSION_NAMES)
|
.executeAndWait(data.Source)
|
||||||
.then(uninstalled => {
|
.then(() => {
|
||||||
if (uninstalled) {
|
|
||||||
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
||||||
RebootRequired: true,
|
|
||||||
Source: data.Source,
|
Source: data.Source,
|
||||||
URL: data.URL,
|
URL: data.URL,
|
||||||
});
|
});
|
||||||
} else {
|
})
|
||||||
execInstall();
|
.catch((error) => {
|
||||||
}
|
standardIPCReply(
|
||||||
})
|
event,
|
||||||
.catch(error => {
|
Constants.IPC_Install_Dependency_Reply,
|
||||||
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
{
|
||||||
Source: data.Source,
|
Source: data.Source,
|
||||||
URL: data.URL,
|
URL: data.URL,
|
||||||
}, error);
|
},
|
||||||
});
|
error
|
||||||
|
);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
if (data.IsWinFSP) {
|
||||||
|
helpers
|
||||||
|
.performWindowsUninstall(Constants.WINFSP_VERSION_NAMES)
|
||||||
|
.then((uninstalled) => {
|
||||||
|
if (uninstalled) {
|
||||||
|
standardIPCReply(event, Constants.IPC_Install_Dependency_Reply, {
|
||||||
|
RebootRequired: true,
|
||||||
|
Source: data.Source,
|
||||||
|
URL: data.URL,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
execInstall();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
standardIPCReply(
|
||||||
|
event,
|
||||||
|
Constants.IPC_Install_Dependency_Reply,
|
||||||
|
{
|
||||||
|
Source: data.Source,
|
||||||
|
URL: data.URL,
|
||||||
|
},
|
||||||
|
error
|
||||||
|
);
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
execInstall();
|
execInstall();
|
||||||
}
|
}
|
||||||
@@ -97,6 +110,4 @@ const addListeners = (ipcMain, {standardIPCReply}) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = { addListeners };
|
||||||
addListeners
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -2,24 +2,32 @@ const Constants = require('../../constants');
|
|||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
const path = require('path');
|
const path = require('path');
|
||||||
|
|
||||||
const addListeners = (ipcMain, {standardIPCReply}) => {
|
const addListeners = (ipcMain, { standardIPCReply }) => {
|
||||||
ipcMain.on(Constants.IPC_Download_File, (event, data) => {
|
ipcMain.on(Constants.IPC_Download_File, (event, data) => {
|
||||||
const destination = path.join(helpers.getDataDirectory(), data.Filename);
|
const destination = path.join(helpers.getDataDirectory(), data.Filename);
|
||||||
helpers.downloadFile(data.URL, destination, (progress) => {
|
helpers.downloadFile(
|
||||||
standardIPCReply(event, Constants.IPC_Download_File_Progress, {
|
data.URL,
|
||||||
Destination: destination,
|
destination,
|
||||||
Progress: progress,
|
(progress) => {
|
||||||
URL: data.URL,
|
standardIPCReply(event, Constants.IPC_Download_File_Progress, {
|
||||||
});
|
Destination: destination,
|
||||||
}, error => {
|
Progress: progress,
|
||||||
standardIPCReply(event, Constants.IPC_Download_File_Complete, {
|
URL: data.URL,
|
||||||
Destination: destination,
|
});
|
||||||
URL: data.URL,
|
},
|
||||||
}, error);
|
(error) => {
|
||||||
});
|
standardIPCReply(
|
||||||
|
event,
|
||||||
|
Constants.IPC_Download_File_Complete,
|
||||||
|
{
|
||||||
|
Destination: destination,
|
||||||
|
URL: data.URL,
|
||||||
|
},
|
||||||
|
error
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = { addListeners };
|
||||||
addListeners
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,31 +1,86 @@
|
|||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
|
|
||||||
const addListeners = (ipcMain, {getMainWindow, dialog}) => {
|
const addListeners = (ipcMain, { getMainWindow, dialog }) => {
|
||||||
ipcMain.on(Constants.IPC_Browse_Directory + '_sync', (event, data) => {
|
ipcMain.on(Constants.IPC_Browse_Directory + '_sync', (event, data) => {
|
||||||
dialog.showOpenDialog(getMainWindow(), {
|
dialog.showOpenDialog(
|
||||||
defaultPath: data.Location,
|
getMainWindow(),
|
||||||
properties: ['openDirectory'],
|
{
|
||||||
title: data.Title,
|
defaultPath: data.Location,
|
||||||
}, (filePaths) => {
|
properties: ['openDirectory'],
|
||||||
if (filePaths && (filePaths.length > 0)) {
|
title: data.Title,
|
||||||
event.returnValue = filePaths[0];
|
},
|
||||||
} else {
|
(filePaths) => {
|
||||||
event.returnValue = '';
|
if (filePaths && filePaths.length > 0) {
|
||||||
|
event.returnValue = filePaths[0];
|
||||||
|
} else {
|
||||||
|
event.returnValue = '';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Delete_File, (event, data) => {
|
ipcMain.on(Constants.IPC_Browse_File + '_sync', (event, data) => {
|
||||||
|
dialog.showOpenDialog(
|
||||||
|
getMainWindow(),
|
||||||
|
{
|
||||||
|
defaultPath: data.Location,
|
||||||
|
properties: ['openFile'],
|
||||||
|
title: data.Title,
|
||||||
|
},
|
||||||
|
(filePaths) => {
|
||||||
|
if (filePaths && filePaths.length > 0) {
|
||||||
|
event.returnValue = filePaths[0];
|
||||||
|
} else {
|
||||||
|
event.returnValue = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(Constants.IPC_Delete_File, (_, data) => {
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync(data.FilePath)) {
|
if (fs.existsSync(data.FilePath)) {
|
||||||
fs.unlinkSync(data.FilePath);
|
fs.unlinkSync(data.FilePath);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(Constants.IPC_Select_File + '_sync', (event, data) => {
|
||||||
|
dialog.showSaveDialog(
|
||||||
|
getMainWindow(),
|
||||||
|
{
|
||||||
|
defaultPath: data.Location,
|
||||||
|
properties: ['createDirectory', 'showOverwriteConfirmation'],
|
||||||
|
title: data.Title,
|
||||||
|
},
|
||||||
|
(filePath) => {
|
||||||
|
if (filePath && filePath.length > 0) {
|
||||||
|
event.returnValue = filePath;
|
||||||
|
} else {
|
||||||
|
event.returnValue = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(Constants.IPC_Read_File + '_sync', (event, data) => {
|
||||||
|
try {
|
||||||
|
const contents = fs.readFileSync(data.Location, 'utf8').toString();
|
||||||
|
event.returnValue = { success: true, contents };
|
||||||
|
} catch (err) {
|
||||||
|
event.returnValue = { success: false, error: err.toString() };
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
ipcMain.on(Constants.IPC_Save_File + '_sync', (event, data) => {
|
||||||
|
try {
|
||||||
|
fs.writeFileSync(data.Location, data.Data, 'utf8');
|
||||||
|
event.returnValue = { success: true };
|
||||||
|
} catch (err) {
|
||||||
|
event.returnValue = { success: false, error: err.toString() };
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = { addListeners };
|
||||||
addListeners
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ let manualMountDetection = {};
|
|||||||
let mountedData = {};
|
let mountedData = {};
|
||||||
let mountedLocations = [];
|
let mountedLocations = [];
|
||||||
|
|
||||||
const clearManualMountDetection = provider => {
|
const clearManualMountDetection = (provider) => {
|
||||||
if (manualMountDetection[provider]) {
|
if (manualMountDetection[provider]) {
|
||||||
clearInterval(manualMountDetection[provider]);
|
clearInterval(manualMountDetection[provider]);
|
||||||
delete manualMountDetection[provider];
|
delete manualMountDetection[provider];
|
||||||
@@ -20,28 +20,28 @@ const clearManualMountDetection = provider => {
|
|||||||
const monitorMount = (sender, provider, providerList, version, pid, location) => {
|
const monitorMount = (sender, provider, providerList, version, pid, location) => {
|
||||||
manualMountDetection[provider] = setInterval(() => {
|
manualMountDetection[provider] = setInterval(() => {
|
||||||
helpers
|
helpers
|
||||||
.detectRepertoryMounts(version, providerList)
|
.detectRepertoryMounts(version, providerList)
|
||||||
.then(result => {
|
.then((result) => {
|
||||||
if (result[provider].PID !== pid) {
|
if (result[provider].PID !== pid) {
|
||||||
if (result[provider].PID === -1) {
|
if (result[provider].PID === -1) {
|
||||||
clearManualMountDetection(provider);
|
clearManualMountDetection(provider);
|
||||||
sender.send(Constants.IPC_Unmount_Drive_Reply, {
|
sender.send(Constants.IPC_Unmount_Drive_Reply, {
|
||||||
data: {
|
data: {
|
||||||
Expected: expectedUnmount[provider],
|
Expected: expectedUnmount[provider],
|
||||||
Location: location,
|
Location: location,
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
Error: Error(provider + ' Unmounted').toString(),
|
Error: Error(provider + ' Unmounted').toString(),
|
||||||
Success: false,
|
Success: false,
|
||||||
}
|
},
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
pid = result[provider].PID;
|
pid = result[provider].PID;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
})
|
.catch((e) => {
|
||||||
.catch(e => {
|
console.log(e);
|
||||||
console.log(e);
|
});
|
||||||
});
|
|
||||||
}, 6000);
|
}, 6000);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -62,12 +62,9 @@ const unmountAllDrives = () => {
|
|||||||
mountedData = {};
|
mountedData = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => {
|
const addListeners = (ipcMain, { setTrayImage, standardIPCReply }) => {
|
||||||
ipcMain.on(Constants.IPC_Check_Mount_Location + '_sync', (event, data) => {
|
ipcMain.on(Constants.IPC_Check_Mount_Location + '_sync', (event, data) => {
|
||||||
let response = {
|
let response = { Success: true, Error: '' };
|
||||||
Success: true,
|
|
||||||
Error: ''
|
|
||||||
};
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (fs.existsSync(data.Location) && fs.statSync(data.Location).isDirectory()) {
|
if (fs.existsSync(data.Location) && fs.statSync(data.Location).isDirectory()) {
|
||||||
@@ -90,11 +87,7 @@ const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => {
|
|||||||
const provider = data.Provider;
|
const provider = data.Provider;
|
||||||
|
|
||||||
let driveLetters = {};
|
let driveLetters = {};
|
||||||
const providerList = [
|
const providerList = [...Constants.PROVIDER_LIST, ...data.RemoteMounts, ...data.S3Mounts];
|
||||||
...Constants.PROVIDER_LIST,
|
|
||||||
...data.RemoteMounts,
|
|
||||||
...data.S3Mounts,
|
|
||||||
];
|
|
||||||
for (const provider of providerList) {
|
for (const provider of providerList) {
|
||||||
driveLetters[provider] = [];
|
driveLetters[provider] = [];
|
||||||
}
|
}
|
||||||
@@ -106,8 +99,7 @@ const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => {
|
|||||||
if (Object.keys(locations).length > 0) {
|
if (Object.keys(locations).length > 0) {
|
||||||
for (const provider of providerList) {
|
for (const provider of providerList) {
|
||||||
driveInUse = locations[provider].startsWith(drive);
|
driveInUse = locations[provider].startsWith(drive);
|
||||||
if (driveInUse)
|
if (driveInUse) break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!driveInUse) {
|
if (!driveInUse) {
|
||||||
@@ -117,17 +109,18 @@ const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => {
|
|||||||
driveLetters[provider].push(drive);
|
driveLetters[provider].push(drive);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Object.keys(locations).length > 0) {
|
if (Object.keys(locations).length > 0) {
|
||||||
for (const provider of providerList) {
|
for (const provider of providerList) {
|
||||||
if (locations[provider].length > 0) {
|
if (locations[provider].length > 0) {
|
||||||
if (!driveLetters[provider].find((driveLetter) => {
|
if (
|
||||||
return driveLetter === locations[provider];
|
!driveLetters[provider].find((driveLetter) => {
|
||||||
})) {
|
return driveLetter === locations[provider];
|
||||||
|
})
|
||||||
|
) {
|
||||||
driveLetters[provider].push(locations[provider]);
|
driveLetters[provider].push(locations[provider]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -135,66 +128,79 @@ const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const setImage = locations => {
|
const setImage = (locations) => {
|
||||||
let driveInUse;
|
let driveInUse;
|
||||||
if (Object.keys(locations).length > 0) {
|
if (Object.keys(locations).length > 0) {
|
||||||
for (const provider of providerList) {
|
for (const provider of providerList) {
|
||||||
driveInUse = locations[provider] && locations[provider].length > 0;
|
driveInUse = locations[provider] && locations[provider].length > 0;
|
||||||
if (driveInUse)
|
if (driveInUse) break;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setTrayImage(driveInUse)
|
setTrayImage(driveInUse);
|
||||||
};
|
};
|
||||||
|
|
||||||
helpers
|
helpers
|
||||||
.detectRepertoryMounts(data.Version, providerList)
|
.detectRepertoryMounts(data.Version, providerList)
|
||||||
.then((results) => {
|
.then((results) => {
|
||||||
let storageData = {};
|
let storageData = {};
|
||||||
let locations = {};
|
let locations = {};
|
||||||
for (const provider of providerList) {
|
for (const provider of providerList) {
|
||||||
storageData[provider] = results[provider] ? results[provider] : {
|
storageData[provider] = results[provider]
|
||||||
Active: false,
|
? results[provider]
|
||||||
Location: '',
|
: {
|
||||||
PID: -1,
|
Active: false,
|
||||||
};
|
Location: '',
|
||||||
locations[provider] = storageData[provider].Location;
|
PID: -1,
|
||||||
|
};
|
||||||
|
locations[provider] = storageData[provider].Location;
|
||||||
|
|
||||||
if (storageData[provider].PID !== -1) {
|
if (storageData[provider].PID !== -1) {
|
||||||
expectedUnmount[provider] = false;
|
expectedUnmount[provider] = false;
|
||||||
if (firstMountCheck) {
|
if (firstMountCheck) {
|
||||||
monitorMount(event.sender, provider, providerList, data.Version, storageData[provider].PID, storageData[provider].Location);
|
monitorMount(
|
||||||
|
event.sender,
|
||||||
|
provider,
|
||||||
|
providerList,
|
||||||
|
data.Version,
|
||||||
|
storageData[provider].PID,
|
||||||
|
storageData[provider].Location
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (os.platform() === 'win32') {
|
if (os.platform() === 'win32') {
|
||||||
grabDriveLetters(locations);
|
grabDriveLetters(locations);
|
||||||
}
|
}
|
||||||
|
|
||||||
setImage(locations);
|
setImage(locations);
|
||||||
if (firstMountCheck) {
|
if (firstMountCheck) {
|
||||||
firstMountCheck = false;
|
firstMountCheck = false;
|
||||||
}
|
}
|
||||||
standardIPCReply(event, Constants.IPC_Detect_Mount_Reply, {
|
standardIPCReply(event, Constants.IPC_Detect_Mount_Reply, {
|
||||||
Active: storageData[provider].Active,
|
Active: storageData[provider].Active,
|
||||||
DriveLetters: driveLetters[provider],
|
DriveLetters: driveLetters[provider],
|
||||||
Location: locations[provider],
|
Location: locations[provider],
|
||||||
PID: storageData[provider].PID,
|
PID: storageData[provider].PID,
|
||||||
Provider: provider,
|
Provider: provider,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
if (os.platform() === 'win32') {
|
||||||
|
grabDriveLetters({});
|
||||||
|
}
|
||||||
|
setImage({});
|
||||||
|
standardIPCReply(
|
||||||
|
event,
|
||||||
|
Constants.IPC_Detect_Mount_Reply,
|
||||||
|
{
|
||||||
|
DriveLetters: driveLetters[provider],
|
||||||
|
Provider: provider,
|
||||||
|
},
|
||||||
|
error
|
||||||
|
);
|
||||||
});
|
});
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
if (os.platform() === 'win32') {
|
|
||||||
grabDriveLetters({});
|
|
||||||
}
|
|
||||||
setImage({});
|
|
||||||
standardIPCReply(event, Constants.IPC_Detect_Mount_Reply, {
|
|
||||||
DriveLetters: driveLetters[provider],
|
|
||||||
Provider: provider,
|
|
||||||
}, error);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Mount_Drive, (event, data) => {
|
ipcMain.on(Constants.IPC_Mount_Drive, (event, data) => {
|
||||||
@@ -216,28 +222,40 @@ const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => {
|
|||||||
delete mountedData[data.Location];
|
delete mountedData[data.Location];
|
||||||
}
|
}
|
||||||
|
|
||||||
standardIPCReply(event, Constants.IPC_Unmount_Drive_Reply, {
|
standardIPCReply(
|
||||||
Expected: expectedUnmount[data.Provider],
|
event,
|
||||||
Location: data.Location,
|
Constants.IPC_Unmount_Drive_Reply,
|
||||||
Provider: data.Provider,
|
{
|
||||||
Remote: data.Remote,
|
Expected: expectedUnmount[data.Provider],
|
||||||
S3: data.S3,
|
Location: data.Location,
|
||||||
}, error || Error(data.Provider + ' Unmounted'));
|
Provider: data.Provider,
|
||||||
|
Remote: data.Remote,
|
||||||
|
S3: data.S3,
|
||||||
|
},
|
||||||
|
error || Error(data.Provider + ' Unmounted')
|
||||||
|
);
|
||||||
};
|
};
|
||||||
helpers
|
helpers
|
||||||
.executeMount(data.Version, data.Provider, data.Remote, data.S3, data.Location, (error, pid) => {
|
.executeMount(
|
||||||
errorHandler(pid, error);
|
data.Version,
|
||||||
})
|
data.Provider,
|
||||||
.then(() => {
|
data.Remote,
|
||||||
standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, {
|
data.S3,
|
||||||
Provider: data.Provider,
|
data.Location,
|
||||||
Remote: data.Remote,
|
(error, pid) => {
|
||||||
S3: data.S3,
|
errorHandler(pid, error);
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then(() => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Mount_Drive_Reply, {
|
||||||
|
Provider: data.Provider,
|
||||||
|
Remote: data.Remote,
|
||||||
|
S3: data.S3,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
errorHandler(-1, error);
|
||||||
});
|
});
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
errorHandler(-1, error);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -245,17 +263,26 @@ const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => {
|
|||||||
if (data.Remote) {
|
if (data.Remote) {
|
||||||
data.Name = data.Name.replace(':', '_');
|
data.Name = data.Name.replace(':', '_');
|
||||||
}
|
}
|
||||||
const dataDirectory = path.resolve(path.join(helpers.getDataDirectory(), '..', data.Remote ? 'remote' : 's3', data.Name));
|
const dataDirectory = path.resolve(
|
||||||
|
path.join(helpers.getDataDirectory(), '..', data.Remote ? 'remote' : 's3', data.Name)
|
||||||
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
helpers.removeDirectoryRecursively(dataDirectory);
|
helpers.removeDirectoryRecursively(dataDirectory);
|
||||||
standardIPCReply(event, Constants.IPC_Remove_Mount_Reply, {DataDirectory: dataDirectory});
|
standardIPCReply(event, Constants.IPC_Remove_Mount_Reply, {
|
||||||
|
DataDirectory: dataDirectory,
|
||||||
|
});
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
standardIPCReply(event, Constants.IPC_Remove_Mount_Reply, {DataDirectory: dataDirectory}, e);
|
standardIPCReply(
|
||||||
|
event,
|
||||||
|
Constants.IPC_Remove_Mount_Reply,
|
||||||
|
{ DataDirectory: dataDirectory },
|
||||||
|
e
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Unmount_All_Drives, event => {
|
ipcMain.on(Constants.IPC_Unmount_All_Drives, (event) => {
|
||||||
unmountAllDrives();
|
unmountAllDrives();
|
||||||
standardIPCReply(event, Constants.IPC_Unmount_All_Drives_Reply);
|
standardIPCReply(event, Constants.IPC_Unmount_All_Drives_Reply);
|
||||||
});
|
});
|
||||||
@@ -265,17 +292,17 @@ const addListeners = (ipcMain, {setTrayImage, standardIPCReply}) => {
|
|||||||
|
|
||||||
expectedUnmount[data.Provider] = true;
|
expectedUnmount[data.Provider] = true;
|
||||||
helpers
|
helpers
|
||||||
.stopMountProcess(data.Version, data.Provider, data.Remote, data.S3)
|
.stopMountProcess(data.Version, data.Provider, data.Remote, data.S3)
|
||||||
.then(result => {
|
.then((result) => {
|
||||||
console.log(result);
|
console.log(result);
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch((e) => {
|
||||||
console.log(e);
|
console.log(e);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
addListeners,
|
addListeners,
|
||||||
unmountAllDrives
|
unmountAllDrives,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,49 +1,45 @@
|
|||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
|
|
||||||
const addListeners = (ipcMain, {standardIPCReply}) => {
|
const addListeners = (ipcMain, { standardIPCReply }) => {
|
||||||
ipcMain.on(Constants.IPC_Get_Directory_Items, (event, data) => {
|
ipcMain.on(Constants.IPC_Get_Directory_Items, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.grabDirectoryItems(data.Path, data.Version, data.Provider, data.Remote, data.S3)
|
.grabDirectoryItems(data.Path, data.Version, data.Provider, data.Remote, data.S3)
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {
|
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {
|
||||||
Items: data.items,
|
Items: data.items,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {}, e);
|
||||||
});
|
});
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {}, e);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Get_Pinned_Files, (event, data) => {
|
ipcMain.on(Constants.IPC_Get_Pinned_Files, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.grabDirectoryItems(data.Path, data.Version, data.Provider, data.Remote, data.S3)
|
.grabDirectoryItems(data.Path, data.Version, data.Provider, data.Remote, data.S3)
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {
|
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {
|
||||||
Items: data.items,
|
Items: data.items,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((e) => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {}, e);
|
||||||
});
|
});
|
||||||
})
|
|
||||||
.catch(e => {
|
|
||||||
standardIPCReply(event, Constants.IPC_Get_Directory_Items_Reply, {}, e);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Get_Pinned_Files_Status, (event, data) => {
|
ipcMain.on(Constants.IPC_Get_Pinned_Files_Status, (event, data) => {});
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Set_Pinned + '_sync', (event, data) => {
|
ipcMain.on(Constants.IPC_Set_Pinned + '_sync', (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.setPinned(data.Path, data.Pinned, data.Version, data.Provider, data.Remote, data.S3)
|
.setPinned(data.Path, data.Pinned, data.Version, data.Provider, data.Remote, data.S3)
|
||||||
.then(success => {
|
.then((success) => {
|
||||||
event.returnValue = success;
|
event.returnValue = success;
|
||||||
})
|
})
|
||||||
.catch(e => {
|
.catch((e) => {
|
||||||
event.returnValue = false;
|
event.returnValue = false;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = { addListeners };
|
||||||
addListeners
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -10,11 +10,11 @@ const getPlatformOverride = () => {
|
|||||||
return _platformOverride;
|
return _platformOverride;
|
||||||
};
|
};
|
||||||
|
|
||||||
const setPlatformOverride = platformOverride => {
|
const setPlatformOverride = (platformOverride) => {
|
||||||
_platformOverride = platformOverride;
|
_platformOverride = platformOverride;
|
||||||
};
|
};
|
||||||
|
|
||||||
const addListeners = (ipcMain, {detectScript, saveUiSettings}) => {
|
const addListeners = (ipcMain, { detectScript, saveUiSettings }) => {
|
||||||
ipcMain.on(Constants.IPC_Get_Platform, (event) => {
|
ipcMain.on(Constants.IPC_Get_Platform, (event) => {
|
||||||
const sendResponse = (appPlatform, platform) => {
|
const sendResponse = (appPlatform, platform) => {
|
||||||
event.sender.send(Constants.IPC_Get_Platform_Reply, {
|
event.sender.send(Constants.IPC_Get_Platform_Reply, {
|
||||||
@@ -25,40 +25,39 @@ const addListeners = (ipcMain, {detectScript, saveUiSettings}) => {
|
|||||||
|
|
||||||
const platform = os.platform();
|
const platform = os.platform();
|
||||||
if (platform === 'linux') {
|
if (platform === 'linux') {
|
||||||
if (_platformOverride && (_platformOverride.length > 0)) {
|
if (_platformOverride && _platformOverride.length > 0) {
|
||||||
sendResponse(_platformOverride, 'linux');
|
sendResponse(_platformOverride, 'linux');
|
||||||
} else {
|
} else {
|
||||||
const scriptFile = path.join(os.tmpdir(), 'repertory_detect_linux.sh');
|
const scriptFile = path.join(os.tmpdir(), 'repertory_detect_linux.sh');
|
||||||
fs.writeFileSync(scriptFile, detectScript);
|
fs.writeFileSync(scriptFile, detectScript);
|
||||||
|
|
||||||
helpers
|
helpers
|
||||||
.executeScript(scriptFile)
|
.executeScript(scriptFile)
|
||||||
.then(data => {
|
.then((data) => {
|
||||||
let appPlatform = data.replace(/(\r\n|\n|\r)/gm, "");
|
let appPlatform = data.replace(/(\r\n|\n|\r)/gm, '');
|
||||||
if (appPlatform === 'unknown') {
|
if (appPlatform === 'unknown') {
|
||||||
helpers
|
helpers.downloadFile(Constants.LINUX_DETECT_SCRIPT_URL, scriptFile, null, (err) => {
|
||||||
.downloadFile(Constants.LINUX_DETECT_SCRIPT_URL, scriptFile, null, err => {
|
if (err) {
|
||||||
if (err) {
|
|
||||||
sendResponse(appPlatform, platform);
|
|
||||||
} else {
|
|
||||||
helpers
|
|
||||||
.executeScript(scriptFile)
|
|
||||||
.then(data => {
|
|
||||||
appPlatform = data.replace(/(\r\n|\n|\r)/gm, "");
|
|
||||||
sendResponse(appPlatform, platform);
|
sendResponse(appPlatform, platform);
|
||||||
})
|
} else {
|
||||||
.catch(() => {
|
helpers
|
||||||
sendResponse(appPlatform, platform);
|
.executeScript(scriptFile)
|
||||||
});
|
.then((data) => {
|
||||||
}
|
appPlatform = data.replace(/(\r\n|\n|\r)/gm, '');
|
||||||
});
|
sendResponse(appPlatform, platform);
|
||||||
} else {
|
})
|
||||||
sendResponse(appPlatform, platform);
|
.catch(() => {
|
||||||
}
|
sendResponse(appPlatform, platform);
|
||||||
})
|
});
|
||||||
.catch(() => {
|
}
|
||||||
sendResponse(platform, platform);
|
});
|
||||||
});
|
} else {
|
||||||
|
sendResponse(appPlatform, platform);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
sendResponse(platform, platform);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sendResponse(platform, platform);
|
sendResponse(platform, platform);
|
||||||
@@ -75,5 +74,5 @@ const addListeners = (ipcMain, {detectScript, saveUiSettings}) => {
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
getPlatformOverride,
|
getPlatformOverride,
|
||||||
setPlatformOverride,
|
setPlatformOverride,
|
||||||
addListeners
|
addListeners,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -5,28 +5,33 @@ const os = require('os');
|
|||||||
const path = require('path');
|
const path = require('path');
|
||||||
const unzip = require('unzipper');
|
const unzip = require('unzipper');
|
||||||
|
|
||||||
const addListeners = (ipcMain, {getCleanupReleases, standardIPCReply}) => {
|
const addListeners = (ipcMain, { getCleanupReleases, standardIPCReply }) => {
|
||||||
ipcMain.on(Constants.IPC_Check_Installed, (event, data) => {
|
ipcMain.on(Constants.IPC_Check_Installed, (event, data) => {
|
||||||
const destination = path.join(helpers.getDataDirectory(), data.Version);
|
const destination = path.join(helpers.getDataDirectory(), data.Version);
|
||||||
helpers
|
helpers
|
||||||
.getMissingDependencies(data.Dependencies)
|
.getMissingDependencies(data.Dependencies)
|
||||||
.then((dependencies) => {
|
.then((dependencies) => {
|
||||||
let exists = false;
|
let exists = false;
|
||||||
try {
|
try {
|
||||||
exists = fs.existsSync(destination) && fs.lstatSync(destination).isDirectory();
|
exists = fs.existsSync(destination) && fs.lstatSync(destination).isDirectory();
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
standardIPCReply(event, Constants.IPC_Check_Installed_Reply, {
|
||||||
standardIPCReply(event, Constants.IPC_Check_Installed_Reply, {
|
Dependencies: dependencies,
|
||||||
Dependencies: dependencies,
|
Exists: exists,
|
||||||
Exists: exists,
|
Version: data.Version,
|
||||||
Version: data.Version,
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
standardIPCReply(
|
||||||
|
event,
|
||||||
|
Constants.IPC_Check_Installed_Reply,
|
||||||
|
{
|
||||||
|
Dependencies: [],
|
||||||
|
Version: data.Version,
|
||||||
|
},
|
||||||
|
error
|
||||||
|
);
|
||||||
});
|
});
|
||||||
}).catch(error => {
|
|
||||||
standardIPCReply(event, Constants.IPC_Check_Installed_Reply, {
|
|
||||||
Dependencies: [],
|
|
||||||
Version: data.Version,
|
|
||||||
}, error);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Cleanup_Releases + '_sync', (event, data) => {
|
ipcMain.on(Constants.IPC_Cleanup_Releases + '_sync', (event, data) => {
|
||||||
@@ -44,52 +49,59 @@ const addListeners = (ipcMain, {getCleanupReleases, standardIPCReply}) => {
|
|||||||
|
|
||||||
const stream = fs.createReadStream(data.Source);
|
const stream = fs.createReadStream(data.Source);
|
||||||
stream
|
stream
|
||||||
.pipe(unzip.Extract({ path: destination }))
|
.pipe(unzip.Extract({ path: destination }))
|
||||||
.on('error', error => {
|
.on('error', (error) => {
|
||||||
try {
|
try {
|
||||||
helpers.removeDirectoryRecursively(destination);
|
helpers.removeDirectoryRecursively(destination);
|
||||||
} catch (e) {
|
} catch (e) {}
|
||||||
}
|
stream.close();
|
||||||
stream.close();
|
standardIPCReply(
|
||||||
standardIPCReply(event, Constants.IPC_Extract_Release_Complete, {
|
event,
|
||||||
Source: data.Source,
|
Constants.IPC_Extract_Release_Complete,
|
||||||
}, error);
|
{
|
||||||
})
|
Source: data.Source,
|
||||||
.on('finish', () => {
|
},
|
||||||
stream.close();
|
error
|
||||||
if (os.platform() !== 'win32') {
|
);
|
||||||
helpers
|
})
|
||||||
.executeAndWait("chmod +x \"" + path.join(destination, 'repertory') + "\"")
|
.on('finish', () => {
|
||||||
.then(() => {
|
stream.close();
|
||||||
|
if (os.platform() !== 'win32') {
|
||||||
|
helpers
|
||||||
|
.executeAndWait('chmod +x "' + path.join(destination, 'repertory') + '"')
|
||||||
|
.then(() => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Extract_Release_Complete, {
|
||||||
|
Source: data.Source,
|
||||||
|
});
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
standardIPCReply(
|
||||||
|
event,
|
||||||
|
Constants.IPC_Extract_Release_Complete,
|
||||||
|
{
|
||||||
|
Source: data.Source,
|
||||||
|
},
|
||||||
|
error
|
||||||
|
);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
standardIPCReply(event, Constants.IPC_Extract_Release_Complete, {
|
standardIPCReply(event, Constants.IPC_Extract_Release_Complete, {
|
||||||
Source: data.Source,
|
Source: data.Source,
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
.catch(error => {
|
});
|
||||||
standardIPCReply(event, Constants.IPC_Extract_Release_Complete, {
|
|
||||||
Source: data.Source,
|
|
||||||
}, error);
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
standardIPCReply(event, Constants.IPC_Extract_Release_Complete, {
|
|
||||||
Source: data.Source,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|
||||||
ipcMain.on(Constants.IPC_Test_Release, (event, data) => {
|
ipcMain.on(Constants.IPC_Test_Release, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.testRepertoryBinary(data.Version)
|
.testRepertoryBinary(data.Version)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
standardIPCReply(event, Constants.IPC_Test_Release_Reply, {});
|
standardIPCReply(event, Constants.IPC_Test_Release_Reply, {});
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
standardIPCReply(event, Constants.IPC_Test_Release_Reply, {}, error);
|
standardIPCReply(event, Constants.IPC_Test_Release_Reply, {}, error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = { addListeners };
|
||||||
addListeners
|
|
||||||
};
|
|
||||||
|
|||||||
@@ -1,16 +1,16 @@
|
|||||||
const Constants = require('../../constants');
|
const Constants = require('../../constants');
|
||||||
const helpers = require('../../helpers');
|
const helpers = require('../../helpers');
|
||||||
|
|
||||||
const addListeners = (ipcMain, {standardIPCReply}) => {
|
const addListeners = (ipcMain, { standardIPCReply }) => {
|
||||||
ipcMain.on(Constants.IPC_Export_Skylinks, (event, data) => {
|
ipcMain.on(Constants.IPC_Export_Skylinks, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.exportSkylinks(data.Version, data.Paths)
|
.exportSkylinks(data.Version, data.Paths)
|
||||||
.then(result => {
|
.then((result) => {
|
||||||
standardIPCReply(event, Constants.IPC_Export_Skylinks_Reply, {
|
standardIPCReply(event, Constants.IPC_Export_Skylinks_Reply, {
|
||||||
Result: result,
|
Result: result,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
standardIPCReply(event, Constants.IPC_Export_Skylinks_Reply, {}, error);
|
standardIPCReply(event, Constants.IPC_Export_Skylinks_Reply, {}, error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -18,12 +18,12 @@ const addListeners = (ipcMain, {standardIPCReply}) => {
|
|||||||
ipcMain.on(Constants.IPC_Grab_Skynet_Tree, (event, data) => {
|
ipcMain.on(Constants.IPC_Grab_Skynet_Tree, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.grabSkynetFileTree(data.Version)
|
.grabSkynetFileTree(data.Version)
|
||||||
.then(result => {
|
.then((result) => {
|
||||||
standardIPCReply(event, Constants.IPC_Grab_Skynet_Tree_Reply, {
|
standardIPCReply(event, Constants.IPC_Grab_Skynet_Tree_Reply, {
|
||||||
Result: result,
|
Result: result,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
standardIPCReply(event, Constants.IPC_Grab_Skynet_Tree_Reply, {}, error);
|
standardIPCReply(event, Constants.IPC_Grab_Skynet_Tree_Reply, {}, error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -31,17 +31,30 @@ const addListeners = (ipcMain, {standardIPCReply}) => {
|
|||||||
ipcMain.on(Constants.IPC_Import_Skylinks, (event, data) => {
|
ipcMain.on(Constants.IPC_Import_Skylinks, (event, data) => {
|
||||||
helpers
|
helpers
|
||||||
.importSkylinks(data.Version, data.JsonArray)
|
.importSkylinks(data.Version, data.JsonArray)
|
||||||
.then(result => {
|
.then((result) => {
|
||||||
standardIPCReply(event, Constants.IPC_Import_Skylinks_Reply, {
|
standardIPCReply(event, Constants.IPC_Import_Skylinks_Reply, {
|
||||||
Result: result,
|
Result: result,
|
||||||
});
|
});
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch((error) => {
|
||||||
standardIPCReply(event, Constants.IPC_Import_Skylinks_Reply, {}, error);
|
standardIPCReply(event, Constants.IPC_Import_Skylinks_Reply, {}, error);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
ipcMain.on(Constants.IPC_Skynet_Test_Logon, (event, data) => {
|
||||||
|
helpers
|
||||||
|
.testSkynetLogon(data.Version, data.AuthURL, data.AuthUser, data.AuthPassword)
|
||||||
|
.then((success) => {
|
||||||
|
if (success) {
|
||||||
|
standardIPCReply(event, Constants.IPC_Skynet_Test_Logon_Reply, {});
|
||||||
|
} else {
|
||||||
|
standardIPCReply(event, Constants.IPC_Skynet_Test_Logon_Reply, {}, 'Logon failed. Please check credentials');
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((error) => {
|
||||||
|
standardIPCReply(event, Constants.IPC_Skynet_Test_Logon_Reply, {}, error);
|
||||||
|
});
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = { addListeners };
|
||||||
addListeners
|
|
||||||
};
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user