From 519e15cc9ab2fd3d3c8c8f668834eaf9993c2312 Mon Sep 17 00:00:00 2001 From: ram Date: Fri, 13 Jan 2023 20:14:53 +0530 Subject: [PATCH 01/11] Changes for the 'Third party plugin file upgrade' notion task. --- .../assets/images/manual-plugin-upgrade.svg | 3 + web/src/config/icons/static.js | 1 + web/src/containers/Admin/Plugins/AddPlugin.js | 114 ++++++ web/src/containers/Admin/Plugins/MyPlugins.js | 227 ++---------- .../Admin/Plugins/PluginConfigure.js | 4 +- .../Admin/Plugins/PluginConfigureForm.js | 49 ++- web/src/containers/Admin/Plugins/index.css | 17 + web/src/containers/Admin/Plugins/index.js | 328 ++++++++++++++++-- 8 files changed, 499 insertions(+), 244 deletions(-) create mode 100644 web/public/assets/images/manual-plugin-upgrade.svg create mode 100644 web/src/containers/Admin/Plugins/AddPlugin.js diff --git a/web/public/assets/images/manual-plugin-upgrade.svg b/web/public/assets/images/manual-plugin-upgrade.svg new file mode 100644 index 0000000000..5ea1b6157c --- /dev/null +++ b/web/public/assets/images/manual-plugin-upgrade.svg @@ -0,0 +1,3 @@ + + + diff --git a/web/src/config/icons/static.js b/web/src/config/icons/static.js index 2429dee2a7..a2df321587 100644 --- a/web/src/config/icons/static.js +++ b/web/src/config/icons/static.js @@ -154,6 +154,7 @@ const icons = { DOLLAR_GEAR: '/assets/images/single-dollar-gear.svg', SWITCH_ASSET_FOR_FEES: '/assets/images/switch-asset-for-fees.svg', CLOCK: '/assets/images/clock.svg', + MANUAL_PLUGIN_UPGRADE: '/assets/images/manual-plugin-upgrade.svg', }; export default icons; diff --git a/web/src/containers/Admin/Plugins/AddPlugin.js b/web/src/containers/Admin/Plugins/AddPlugin.js new file mode 100644 index 0000000000..d537e117cc --- /dev/null +++ b/web/src/containers/Admin/Plugins/AddPlugin.js @@ -0,0 +1,114 @@ +import React from 'react'; +import { Button, Input, Radio } from 'antd'; +import { DownloadOutlined } from '@ant-design/icons'; + +const radioStyle = { + display: 'flex', + alignItems: 'center', + height: '30px', + lineHeight: '1.2', + padding: '24px 0', + margin: 0, + paddingLeft: '1px', + whiteSpace: 'normal', + letterSpacing: '-0.15px', +}; + +const AddThirdPartyPlugin = ({ + handleChange, + thirdPartyType, + handleFileChange, + handleURL, + thirdPartyError, + handleBack, + thirdParty, + getJSONFromURL, + updateState, + handleStep, + handleUpdatePlugin = () => {}, +}) => { + return ( +
+

+ Add third party plugin +

+
+ + + Upload a json file + + {thirdPartyType === 'upload_json' ? ( +
+
+
+ + +
+
+
+ ) : null} + + Input URL path + + {thirdPartyType === 'input_url' ? ( +
+ URL path + +
+ ) : null} +
+ {thirdPartyError ? ( +
{thirdPartyError}
+ ) : null} +
+
+ + +
+
+ ); +}; + +export default AddThirdPartyPlugin; diff --git a/web/src/containers/Admin/Plugins/MyPlugins.js b/web/src/containers/Admin/Plugins/MyPlugins.js index ae3523fb19..6da69b3d75 100644 --- a/web/src/containers/Admin/Plugins/MyPlugins.js +++ b/web/src/containers/Admin/Plugins/MyPlugins.js @@ -1,12 +1,11 @@ import React, { Component } from 'react'; -import { Button, Input, Spin, Modal, Radio, message } from 'antd'; import { Link } from 'react-router'; +import { Button, Input, Spin, Modal, message } from 'antd'; import _debounce from 'lodash/debounce'; -import { DownloadOutlined } from '@ant-design/icons'; -import axios from 'axios'; import { STATIC_ICONS } from 'config/icons'; import { addPlugin, updatePlugins } from './action'; +import AddThirdPartyPlugin from './AddPlugin'; class MyPlugins extends Component { constructor(props) { @@ -14,12 +13,8 @@ class MyPlugins extends Component { this.state = { isVisible: false, step: 1, - thirdPartyType: 'upload_json', isConfirm: true, pluginData: {}, - thirdParty: {}, - thirdPartyError: '', - jsonURL: '', buttonSubmitting: false, }; } @@ -47,23 +42,8 @@ class MyPlugins extends Component { this.setState({ isVisible: false, step: 1, - thirdParty: {}, - thirdPartyError: '', - jsonURL: '', }); - }; - - handleStep = (step) => { - this.setState({ step }); - }; - - handleChange = (e) => { - if (e.target.value === 'upload_json') { - this.setState({ thirdPartyType: 'upload_json' }); - } else { - this.setState({ thirdPartyType: 'input_url' }); - } - this.setState({ thirdPartyError: '', jsonURL: '' }); + this.props.handleCancel(); }; handleInput = (e) => { @@ -82,7 +62,7 @@ class MyPlugins extends Component { handleAddPlugin = async () => { const { restart, myPlugins } = this.props; const body = { - ...this.state.thirdParty, + ...this.props.thirdParty, enabled: true, }; this.setState({ buttonSubmitting: true }); @@ -136,195 +116,42 @@ class MyPlugins extends Component { } }; - handleURL = (e) => { - this.setState({ jsonURL: e.target.value }); - }; - - getJsonFromFile = async (file) => { - return await new Promise((resolve, reject) => { - const reader = new FileReader(); - reader.onload = (function () { - return function (e) { - try { - let json = JSON.parse(e.target.result); - resolve(json); - } catch (err) { - message.error(err.toString()); - reject('Invalid format'); - } - }; - })(file); - reader.readAsText(file); - }); - }; - - handleFileChange = async (event) => { - const file = event.target.files[0]; - if (file) { - try { - const res = await this.getJsonFromFile(file); - const check = this.checkJSON(res); - if (check) { - this.setState({ thirdParty: res, thirdPartyError: '' }); - } else { - this.setState({ - thirdPartyError: - 'The file format is not correct. Please make sure it follows JSON standard', - }); - } - } catch (err) { - this.setState({ - thirdPartyError: - 'The file format is not correct. Please make sure it follows JSON standard', - }); - } - } - }; - - checkJSON = (json) => { - if (json && json.name && json.version && json.author) { - return true; - } else { - return false; - } - }; - - getJSONFromURL = async () => { - try { - if (this.state.jsonURL) { - const res = await axios.get(this.state.jsonURL); - if (res.data) { - const check = this.checkJSON(res.data); - if (check) { - this.setState({ thirdParty: res.data, thirdPartyError: '' }); - this.handleStep(3); - } else { - this.setState({ - thirdPartyError: - 'The file format is not correct. Please make sure it follows JSON standard', - }); - } - } - } else { - this.setState({ thirdPartyError: 'Enter valid JSON file URL' }); - } - } catch (err) { - this.setState({ - thirdPartyError: - 'The file format is not correct. Please make sure it follows JSON standard', - }); - } + handleStep = (step) => { + this.setState({ step }); }; handleBack = () => { - this.setState({ thirdParty: {}, thirdPartyError: '' }); + this.props.handleSetBack(); this.handleStep(1); }; renderPopup = () => { - const radioStyle = { - display: 'flex', - alignItems: 'center', - height: '30px', - lineHeight: '1.2', - padding: '24px 0', - margin: 0, - paddingLeft: '1px', - whiteSpace: 'normal', - letterSpacing: '-0.15px', - }; + const { step, isConfirm, buttonSubmitting } = this.state; const { - step, + handleChange, + handleFileChange, + handleURL, thirdPartyType, - isConfirm, - thirdParty, thirdPartyError, - buttonSubmitting, - } = this.state; + getJSONFromURL, + updateState, + thirdParty, + } = this.props; switch (step) { case 2: return ( -
-

- Add third party plugin -

-
- - - Upload a json file - - {thirdPartyType === 'upload_json' ? ( -
-
-
- - -
-
-
- ) : null} - - Input URL path - - {thirdPartyType === 'input_url' ? ( -
- URL path - -
- ) : null} -
- {thirdPartyError ? ( -
{thirdPartyError}
- ) : null} -
-
- - -
-
+ ); case 3: return ( diff --git a/web/src/containers/Admin/Plugins/PluginConfigure.js b/web/src/containers/Admin/Plugins/PluginConfigure.js index 4227b96a76..cf410f6746 100644 --- a/web/src/containers/Admin/Plugins/PluginConfigure.js +++ b/web/src/containers/Admin/Plugins/PluginConfigure.js @@ -12,7 +12,8 @@ const PluginConfigure = ({ updatePluginList, removePlugin, restart, - handleRedirect + handleRedirect, + handleStep, }) => { const [pluginData, setPlugin] = useState({}); const [selectedNetworkPlugin, setNetworkData] = useState({}); @@ -60,6 +61,7 @@ const PluginConfigure = ({ selectedPlugin={pluginData} requestPlugin={requestPlugin} restart={restart} + handleStep={handleStep} /> ) : ( { } }; -const PluginConfigureForm = ({ selectedPlugin, requestPlugin, restart }) => { +const PluginConfigureForm = ({ + selectedPlugin, + requestPlugin, + restart, + handleStep = () => {}, +}) => { const [isLoading, setLoading] = useState(true); const [metaData, setMetaData] = useState({}); const getMetaData = useCallback(() => { @@ -173,22 +178,34 @@ const PluginConfigureForm = ({ selectedPlugin, requestPlugin, restart }) => { } return (
-
- plugin-icons -
-

{metaData.name}

-
- Version: {metaData.version} +
+
+ plugin-icons +
+

{metaData.name}

+
+ Version: {metaData.version} +
+
+ +
{renderContent(selectedPlugin, setMetaData, metaData, restart)}
diff --git a/web/src/containers/Admin/Plugins/index.css b/web/src/containers/Admin/Plugins/index.css index b7bd599e35..9cf6dc2677 100644 --- a/web/src/containers/Admin/Plugins/index.css +++ b/web/src/containers/Admin/Plugins/index.css @@ -462,3 +462,20 @@ .plugin-list-container .plugin-list .plugin-list-item .premium-plugin { color: #ff8000; } + +.w-85 { + width: 85%; +} + +.w-48 { + width: 48% !important; +} + +.Spinner-wrapper svg { + color: #ffffff; + font-size: 28px; +} + +.spinner-container { + padding-right: 1.25rem; +} diff --git a/web/src/containers/Admin/Plugins/index.js b/web/src/containers/Admin/Plugins/index.js index 187da49255..e94953f75e 100644 --- a/web/src/containers/Admin/Plugins/index.js +++ b/web/src/containers/Admin/Plugins/index.js @@ -1,14 +1,21 @@ import React, { Component } from 'react'; -import { Spin, Tabs, Breadcrumb, Modal, message } from 'antd'; import { connect } from 'react-redux'; -import { RightOutlined } from '@ant-design/icons'; +import { Spin, Tabs, Breadcrumb, Modal, message, Button } from 'antd'; +import { LoadingOutlined, RightOutlined } from '@ant-design/icons'; +import axios from 'axios'; import PluginList from './PluginList'; import PluginConfigure from './PluginConfigure'; import MyPlugins from './MyPlugins'; -import { removePlugin, requestPlugins, requestMyPlugins } from './action'; +import { + removePlugin, + requestPlugins, + requestMyPlugins, + updatePlugins, +} from './action'; import { STATIC_ICONS } from 'config/icons'; import Spinner from './Spinner'; +import AddThirdPartyPlugin from './AddPlugin'; import './index.css'; @@ -40,6 +47,11 @@ class Plugins extends Component { tabKey: plugin ? 'my_plugin' : 'explore', pluginCards: [], processing: false, + thirdPartyType: 'upload_json', + thirdPartyError: '', + thirdParty: {}, + step: 1, + jsonURL: '', }; this.removeTimeout = null; } @@ -227,7 +239,7 @@ class Plugins extends Component { }; onCancelModal = () => { - this.setState({ isVisible: false, selectedPlugin: {} }); + this.setState({ isVisible: false }); }; handlePluginList = (plugin) => { @@ -276,6 +288,274 @@ class Plugins extends Component { this.setState({ type: 'configure', isConfigure: true }); }; + handleUpdatePlugin = () => { + this.handleStep(3); + const body = { + ...this.state.thirdParty, + }; + updatePlugins({ name: body.name }, body) + .then((res) => { + if (res) { + message.success('Third party plugin updated successfully'); + this.onCancelModal(); + } + }) + .catch((err) => { + const _error = + err.data && err.data.message ? err.data.message : err.message; + message.error(_error); + this.onCancelModal(); + }); + }; + + updateState = (thirdPartyError) => { + this.setState({ thirdPartyError }); + }; + + handleCancel = () => { + this.setState({ + thirdParty: {}, + thirdPartyError: '', + jsonURL: '', + }); + }; + + handleStep = (step) => { + this.setState({ step, isVisible: true }); + }; + + handleURL = (e) => { + this.setState({ jsonURL: e.target.value }); + }; + + handleChange = (e) => { + if (e.target.value === 'upload_json') { + this.setState({ thirdPartyType: 'upload_json' }); + } else { + this.setState({ thirdPartyType: 'input_url' }); + } + this.setState({ thirdPartyError: '', jsonURL: '' }); + }; + + getJsonFromFile = async (file) => { + return await new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.onload = (function () { + return function (e) { + try { + let json = JSON.parse(e.target.result); + resolve(json); + } catch (err) { + message.error(err.toString()); + reject('Invalid format'); + } + }; + })(file); + reader.readAsText(file); + }); + }; + + checkJSON = (json) => { + if (json && json.name && json.version && json.author) { + return true; + } else { + return false; + } + }; + + handleFileChange = async (event) => { + const file = event.target.files[0]; + if (file) { + try { + const res = await this.getJsonFromFile(file); + const check = this.checkJSON(res); + if (check) { + this.setState({ thirdParty: res, thirdPartyError: '' }); + } else { + this.setState({ + thirdPartyError: + 'The file format is not correct. Please make sure it follows JSON standard', + }); + } + } catch (err) { + this.setState({ + thirdPartyError: + 'The file format is not correct. Please make sure it follows JSON standard', + }); + } + } + }; + + getJSONFromURL = async () => { + try { + if (this.state.jsonURL) { + const res = await axios.get(this.state.jsonURL); + if (res.data) { + const check = this.checkJSON(res.data); + if (check) { + this.setState({ thirdParty: res.data, thirdPartyError: '' }); + this.handleStep(3); + } else { + this.setState({ + thirdPartyError: + 'The file format is not correct. Please make sure it follows JSON standard', + }); + } + } + } else { + this.setState({ thirdPartyError: 'Enter valid JSON file URL' }); + } + } catch (err) { + this.setState({ + thirdPartyError: + 'The file format is not correct. Please make sure it follows JSON standard', + }); + } + }; + + handleBack = () => { + this.handleSetBack(); + this.handleStep(1); + }; + + handleSetBack = () => { + this.setState({ thirdParty: {}, thirdPartyError: '' }); + }; + + renderModalContent = () => { + const { + selectedPlugin, + thirdPartyType, + thirdPartyError, + step, + thirdParty, + } = this.state; + switch (step) { + case 1: + return ( +
+
+ manual-plugin-upgrade +
Upgrade third-party plugin
+
+
+
+ {selectedPlugin.icon ? ( + plugin-icon + ) : ( + plugin-icon + )} +
+
+
Name: {selectedPlugin.name}
+
Current version: 1
+
+
+
+ You can upgrade this plugin to a newer version manually by + uploading a .json file while maintaining the current plugin's + configuration values. +
+
+ Would you like to proceed with the upgrade? +
+
+ + +
+
+ ); + case 2: + return ( + + ); + case 3: + return ( +
+
+
+
+ + } + /> +
+
Upgrading plugin
+
+
+
Please wait while the upgrade is being applied...
+
+
+
+ ); + default: + return ( +
+
+
+ {selectedPlugin.icon ? ( + plugin-icon + ) : ( + plugin-icon + )} +
+
+

{selectedPlugin.name}

+
This plugin is coming soon!
+
+
+
+ ); + } + }; + render() { const { loading, @@ -291,6 +571,9 @@ class Plugins extends Component { removePluginName, pluginCards, processing, + thirdPartyType, + thirdPartyError, + thirdParty, } = this.state; if (loading || this.props.pluginsLoading) { return ( @@ -328,6 +611,7 @@ class Plugins extends Component { removePlugin={this.removePlugin} restart={this.handleRestart} handleRedirect={this.handleRedirect} + handleStep={this.handleStep} />
) : ( @@ -354,35 +638,25 @@ class Plugins extends Component { myPlugins={myPlugins} pluginData={pluginData} restart={this.handleRestart} + thirdPartyType={thirdPartyType} + thirdPartyError={thirdPartyError} + thirdParty={thirdParty} + handleStep={this.handleStep} + handleURL={this.handleURL} + handleChange={this.handleChange} + handleFileChange={this.handleFileChange} + handleBack={this.handleBack} + handleSetBack={this.handleSetBack} + handleCancel={this.handleCancel} + getJSONFromURL={this.getJSONFromURL} + updateState={this.updateState} />
)} -
-
-
- {selectedPlugin.icon ? ( - plugin-icon - ) : ( - plugin-icon - )} -
-
-

{selectedPlugin.name}

-
This plugin is coming soon!
-
-
-
+ {this.renderModalContent()}
Date: Mon, 16 Jan 2023 11:30:59 +0900 Subject: [PATCH 02/11] display admin total balance instead of available --- web/src/containers/Admin/AdminFinancials/Assets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/src/containers/Admin/AdminFinancials/Assets.js b/web/src/containers/Admin/AdminFinancials/Assets.js index 99013df91e..7e9dd2bdbd 100644 --- a/web/src/containers/Admin/AdminFinancials/Assets.js +++ b/web/src/containers/Admin/AdminFinancials/Assets.js @@ -168,7 +168,7 @@ const getColumns = ( className="coin-symbol-wrapper" onClick={() => handlePreview(selectedAsset)} > - {balance[`${symbol}_available`] || 0} + {balance[`${symbol}_balance`] || 0}
); }, From 586575c3ad01feaf890521408bc09f34dab927fa Mon Sep 17 00:00:00 2001 From: Ali Beikverdi Date: Mon, 16 Jan 2023 11:31:55 +0900 Subject: [PATCH 03/11] version update --- server/api/swagger/swagger.yaml | 2 +- server/package.json | 2 +- version | 2 +- web/package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/api/swagger/swagger.yaml b/server/api/swagger/swagger.yaml index ab324d76be..890512b56d 100644 --- a/server/api/swagger/swagger.yaml +++ b/server/api/swagger/swagger.yaml @@ -1,6 +1,6 @@ swagger: "2.0" info: - version: "2.4.6" + version: "2.4.7" title: HollaEx Kit host: api.hollaex.com basePath: /v2 diff --git a/server/package.json b/server/package.json index 56e996f2a0..1893586a5c 100644 --- a/server/package.json +++ b/server/package.json @@ -1,5 +1,5 @@ { - "version": "2.4.6", + "version": "2.4.7", "private": false, "description": "HollaEx Kit", "keywords": [ diff --git a/version b/version index 62e64205bf..48a6b508dc 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.4.6 \ No newline at end of file +2.4.7 \ No newline at end of file diff --git a/web/package.json b/web/package.json index 679a7758bf..a80d1d3d0f 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "hollaex-kit", - "version": "2.4.6", + "version": "2.4.7", "private": true, "dependencies": { "@ant-design/compatible": "1.0.5", From 1bfb7d404396c72d608a7694b05c7e78668ccc2f Mon Sep 17 00:00:00 2001 From: ram Date: Fri, 23 Dec 2022 11:15:47 +0530 Subject: [PATCH 04/11] implemented the retry withdraw via admin. --- .../Admin/Deposits/ValidateDismiss.js | 53 +++++++++++-------- web/src/containers/Admin/Deposits/index.js | 9 ++++ web/src/containers/Admin/Deposits/utils.js | 31 +++++++++++ 3 files changed, 72 insertions(+), 21 deletions(-) diff --git a/web/src/containers/Admin/Deposits/ValidateDismiss.js b/web/src/containers/Admin/Deposits/ValidateDismiss.js index ac0cfa438b..9e040deed9 100644 --- a/web/src/containers/Admin/Deposits/ValidateDismiss.js +++ b/web/src/containers/Admin/Deposits/ValidateDismiss.js @@ -46,7 +46,11 @@ const ValidateDismiss = ({ className="Validate-Dismiss-popup" >
- {statusType === 'validate' ? 'Validate' : 'Dismiss'} + {statusType === 'validate' + ? 'Validate' + : statusType === 'dismiss' + ? 'Dismiss' + : 'Retry'}
Please check and confirm the details below.
Check & Confirm @@ -61,29 +65,36 @@ const ValidateDismiss = ({ Amount: {validateData.amount} -
-
Transaction ID
- - - -
-
handleEdit('transaction_id')} - > - Edit + {statusType === 'validate' || statusType === 'dismiss' ? ( +
+
Transaction ID
+ + + +
+
handleEdit('transaction_id')} + > + Edit +
-
-
Description
- - - -
-
handleEdit('description')}> - Edit +
Description
+ + + +
+
handleEdit('description')} + > + Edit +
-
+ ) : ( + '' + )}