commit
a76fcb68c3
@ -0,0 +1,353 @@ |
||||
'use strict' |
||||
import { NightwatchBrowser } from 'nightwatch' |
||||
import init from '../helpers/init' |
||||
|
||||
let firstProxyAddress: string |
||||
let lastProxyAddress: string |
||||
let shortenedFirstAddress: string |
||||
let shortenedLastAddress: string |
||||
module.exports = { |
||||
'@disabled': true, |
||||
before: function (browser: NightwatchBrowser, done: VoidFunction) { |
||||
init(browser, done) |
||||
}, |
||||
|
||||
'@sources': function () { |
||||
return sources |
||||
}, |
||||
|
||||
|
||||
'Should show deploy proxy option for UUPS upgradeable contract #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.clickLaunchIcon('udapp') |
||||
.switchEnvironment('vm-merge') // this runtime doesn't have the PUSH0 opcode.
|
||||
.clickLaunchIcon('solidity') |
||||
.click('.remixui_compilerConfigSection') |
||||
.setValue('#evmVersionSelector', 'paris') // set an evm version which doesn't have PUSH0 opcode.
|
||||
.clickLaunchIcon('filePanel') |
||||
.addFile('myTokenV1.sol', sources[0]['myTokenV1.sol']) |
||||
.clickLaunchIcon('solidity') |
||||
.pause(2000) |
||||
// because the compilatiom imports are slow and sometimes stop loading (not sure why, it's bug) we need to recompile and check to see if the files are really in de FS
|
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.clickLaunchIcon('filePanel') |
||||
.isVisible({ |
||||
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"]', |
||||
timeout: 120000, |
||||
suppressNotFoundErrors: true |
||||
}) |
||||
.clickLaunchIcon('solidity') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.clickLaunchIcon('filePanel') |
||||
.isVisible({ |
||||
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"]', |
||||
timeout: 120000, |
||||
suppressNotFoundErrors: true |
||||
}) |
||||
.clickLaunchIcon('solidity') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.clickLaunchIcon('filePanel') |
||||
.waitForElementVisible({ |
||||
selector: '*[data-id="treeViewDivtreeViewItem.deps/npm/@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol"]', |
||||
timeout: 120000, |
||||
}) |
||||
.clickLaunchIcon('solidity') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyToken]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyToken]') |
||||
.waitForElementPresent('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]') |
||||
}, |
||||
|
||||
'Should show upgrade proxy option for child contract inheriting UUPS parent contract #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.addFile('myTokenV2.sol', sources[1]['myTokenV2.sol']) |
||||
.clickLaunchIcon('solidity') |
||||
.assert.visible('[data-id="compilerContainerCompileBtn"]') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyTokenV2]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyTokenV2]') |
||||
.waitForElementPresent('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]') |
||||
}, |
||||
|
||||
'Should deploy proxy without initialize parameters #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.openFile('myTokenV1.sol') |
||||
.clickLaunchIcon('solidity') |
||||
.assert.visible('[data-id="compilerContainerCompileBtn"]') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyToken]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyToken]') |
||||
.verify.visible('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.waitForElementPresent('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.click('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.setValue('[data-id="initializeInputs-initialOwner"]', '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4') |
||||
.createContract('') |
||||
.waitForElementContainsText('[data-id="udappNotifyModalDialogModalTitle-react"]', 'Deploy Implementation & Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.click('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.waitForElementContainsText('[data-id="confirmProxyDeploymentModalDialogModalTitle-react"]', 'Confirm Deploy Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.click('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander0"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') |
||||
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Deploying ERC1967 >= 5.0.0 as proxy...') |
||||
}, |
||||
|
||||
'Should interact with deployed contract via ERC1967 (proxy) #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.getAddressAtPosition(1, (address) => { |
||||
firstProxyAddress = address |
||||
shortenedFirstAddress = address.slice(0, 5) + '...' + address.slice(address.length - 5, address.length) |
||||
}) |
||||
.clickInstance(1) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(firstProxyAddress, 'name - call', null, '0:\nstring: MyToken').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(firstProxyAddress, 'symbol - call', null, '0:\nstring: MTK').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
}, |
||||
|
||||
'Should deploy proxy with initialize parameters #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.waitForElementPresent('[data-id="deployAndRunClearInstances"]') |
||||
.click('[data-id="deployAndRunClearInstances"]') |
||||
.addFile('initializeProxy.sol', sources[2]['initializeProxy.sol']) |
||||
.clickLaunchIcon('solidity') |
||||
.assert.visible('[data-id="compilerContainerCompileBtn"]') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyInitializedToken]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyInitializedToken]') |
||||
.waitForElementPresent('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.click('[data-id="contractGUIDeployWithProxyLabel"]') |
||||
.useXpath() |
||||
.waitForElementPresent('//*[@id="runTabView"]/div/div[2]/div[3]/div[1]/div/div[1]/div[4]/div/div[1]/input') |
||||
.waitForElementPresent('//*[@id="runTabView"]/div/div[2]/div[3]/div[1]/div/div[1]/div[4]/div/div[2]/input') |
||||
.setValue('//*[@id="runTabView"]/div/div[2]/div[3]/div[1]/div/div[1]/div[4]/div/div[1]/input', 'Remix') |
||||
.setValue('//*[@id="runTabView"]/div/div[2]/div[3]/div[1]/div/div[1]/div[4]/div/div[2]/input', "R") |
||||
.useCss() |
||||
.setValue('[data-id="initializeInputs-initialOwner"]', '0x5B38Da6a701c568545dCfcB03FcB875f56beddC4') |
||||
.createContract('') |
||||
.waitForElementContainsText('[data-id="udappNotifyModalDialogModalTitle-react"]', 'Deploy Implementation & Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.click('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.waitForElementContainsText('[data-id="confirmProxyDeploymentModalDialogModalTitle-react"]', 'Confirm Deploy Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.click('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander0"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') |
||||
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Deploying ERC1967 >= 5.0.0 as proxy...') |
||||
}, |
||||
|
||||
'Should interact with initialized contract to verify parameters #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.getAddressAtPosition(1, (address) => { |
||||
lastProxyAddress = address |
||||
shortenedLastAddress = address.slice(0, 5) + '...' + address.slice(address.length - 5, address.length) |
||||
}) |
||||
.clickInstance(1) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(lastProxyAddress, 'name - call', null, '0:\nstring: Remix').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(lastProxyAddress, 'symbol - call', null, '0:\nstring: R').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
}, |
||||
|
||||
'Should upgrade contract by selecting a previously deployed proxy address from dropdown (MyTokenV1 to MyTokenV2) #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.click('*[data-id="terminalClearConsole"]')
|
||||
.waitForElementPresent('[data-id="deployAndRunClearInstances"]') |
||||
.click('[data-id="deployAndRunClearInstances"]') |
||||
.openFile('myTokenV2.sol') |
||||
.clickLaunchIcon('solidity') |
||||
.assert.visible('[data-id="compilerContainerCompileBtn"]') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyTokenV2]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyTokenV2]') |
||||
.waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]') |
||||
.click('[data-id="contractGUIUpgradeImplementationLabel"]') |
||||
.waitForElementPresent('[data-id="toggleProxyAddressDropdown"]') |
||||
.click('[data-id="toggleProxyAddressDropdown"]') |
||||
.waitForElementVisible('[data-id="proxy-dropdown-items"]') |
||||
.assert.textContains('[data-id="proxy-dropdown-items"]', shortenedFirstAddress) |
||||
.assert.textContains('[data-id="proxy-dropdown-items"]', shortenedLastAddress) |
||||
|
||||
.click('[data-id="proxyAddress1"]') |
||||
.createContract('') |
||||
.waitForElementContainsText('[data-id="udappNotifyModalDialogModalTitle-react"]', 'Deploy Implementation & Update Proxy') |
||||
.waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.click('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.waitForElementContainsText('[data-id="confirmProxyDeploymentModalDialogModalTitle-react"]', 'Confirm Update Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.click( |
||||
{ |
||||
selector: '[data-id="confirmProxyDeployment-modal-footer-ok-react"]', |
||||
}) |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander0"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') |
||||
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Using ERC1967 >= 5.0.0 for the proxy upgrade...') |
||||
}, |
||||
|
||||
'Should interact with upgraded function in contract MyTokenV2 #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.clickInstance(1) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(lastProxyAddress, 'version - call', null, '0:\nstring: MyTokenV2!').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
}, |
||||
|
||||
'Should upgrade contract by providing proxy address in input field (MyTokenV1 to MyTokenV2) #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.click('*[data-id="terminalClearConsole"]')
|
||||
.waitForElementPresent('[data-id="deployAndRunClearInstances"]') |
||||
.click('[data-id="deployAndRunClearInstances"]') |
||||
.openFile('myTokenV2.sol') |
||||
.clickLaunchIcon('solidity') |
||||
.assert.visible('[data-id="compilerContainerCompileBtn"]') |
||||
.click('[data-id="compilerContainerCompileBtn"]') |
||||
.waitForElementPresent('select[id="compiledContracts"] option[value=MyTokenV2]', 60000) |
||||
.clickLaunchIcon('udapp') |
||||
.click('select.udapp_contractNames') |
||||
.click('select.udapp_contractNames option[value=MyTokenV2]') |
||||
.waitForElementPresent('[data-id="contractGUIUpgradeImplementationLabel"]') |
||||
.waitForElementPresent('[data-id="toggleProxyAddressDropdown"]') |
||||
.clearValue('[data-id="ERC1967AddressInput"]') |
||||
.setValue('[data-id="ERC1967AddressInput"]', firstProxyAddress) |
||||
.createContract('') |
||||
.waitForElementContainsText('[data-id="udappNotifyModalDialogModalTitle-react"]', 'Deploy Implementation & Update Proxy') |
||||
.waitForElementVisible('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.click('[data-id="udappNotify-modal-footer-ok-react"]') |
||||
.waitForElementContainsText('[data-id="confirmProxyDeploymentModalDialogModalTitle-react"]', 'Confirm Update Proxy (ERC1967)') |
||||
.waitForElementVisible('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.click('[data-id="confirmProxyDeployment-modal-footer-ok-react"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander0"]') |
||||
.waitForElementPresent('[data-id="universalDappUiTitleExpander1"]') |
||||
.waitForElementContainsText('*[data-id="terminalJournal"]', 'Using ERC1967 >= 5.0.0 for the proxy upgrade...') |
||||
}, |
||||
|
||||
'Should interact with upgraded contract through provided proxy address #group1': function (browser: NightwatchBrowser) { |
||||
browser |
||||
.clearConsole() |
||||
.clickInstance(1) |
||||
.perform((done) => { |
||||
browser.testConstantFunction(firstProxyAddress, 'version - call', null, '0:\nstring: MyTokenV2!').perform(() => { |
||||
done() |
||||
}) |
||||
}) |
||||
}, |
||||
'Should debug the call': function(browser: NightwatchBrowser) { |
||||
browser |
||||
.debugTransaction(0) |
||||
.waitForElementVisible({ |
||||
locateStrategy: 'xpath', |
||||
selector: '//*[@data-id="treeViewLivm trace step" and contains(.,"7")]', |
||||
timeout: 60000 |
||||
}) |
||||
.goToVMTraceStep(129) |
||||
.waitForElementContainsText('*[data-id="functionPanel"]', 'version()', 60000) |
||||
.end() |
||||
} |
||||
} |
||||
|
||||
|
||||
const sources = [ |
||||
{ |
||||
'myTokenV1.sol': { |
||||
content: ` |
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20; |
||||
|
||||
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; |
||||
|
||||
contract MyToken is Initializable, ERC721Upgradeable, OwnableUpgradeable, UUPSUpgradeable { |
||||
/// @custom:oz-upgrades-unsafe-allow constructor
|
||||
constructor() { |
||||
_disableInitializers(); |
||||
} |
||||
|
||||
function initialize(address initialOwner) initializer public { |
||||
__ERC721_init("MyToken", "MTK"); |
||||
__Ownable_init(initialOwner); |
||||
__UUPSUpgradeable_init(); |
||||
} |
||||
|
||||
function _authorizeUpgrade(address newImplementation) |
||||
internal |
||||
onlyOwner |
||||
override |
||||
{} |
||||
} |
||||
` |
||||
} |
||||
}, { |
||||
'myTokenV2.sol': { |
||||
content: ` |
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20; |
||||
import "./myTokenV1.sol"; |
||||
|
||||
contract MyTokenV2 is MyToken { |
||||
function version () public view returns (string memory) { |
||||
return "MyTokenV2!"; |
||||
} |
||||
} |
||||
` |
||||
} |
||||
}, { |
||||
'initializeProxy.sol': { |
||||
content: ` |
||||
// SPDX-License-Identifier: MIT
|
||||
pragma solidity ^0.8.20; |
||||
|
||||
import "@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; |
||||
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; |
||||
|
||||
contract MyInitializedToken is Initializable, ERC721Upgradeable, OwnableUpgradeable, UUPSUpgradeable { |
||||
/// @custom:oz-upgrades-unsafe-allow constructor
|
||||
constructor() { |
||||
_disableInitializers(); |
||||
} |
||||
|
||||
function initialize(string memory tokenName, string memory tokenSymbol, address initialOwner) initializer public { |
||||
__ERC721_init(tokenName, tokenSymbol); |
||||
__Ownable_init(initialOwner); |
||||
__UUPSUpgradeable_init(); |
||||
} |
||||
|
||||
function _authorizeUpgrade(address newImplementation) |
||||
internal |
||||
onlyOwner |
||||
override |
||||
{} |
||||
} |
||||
` |
||||
} |
||||
} |
||||
] |
After Width: | Height: | Size: 2.5 KiB |
@ -0,0 +1,26 @@ |
||||
import React, { useState } from 'react' |
||||
import { useAccordionToggle } from 'react-bootstrap/AccordionToggle' |
||||
|
||||
export type CustomAccordionToggleProps = { |
||||
children: React.ReactNode |
||||
eventKey: string |
||||
callback?: any |
||||
} |
||||
|
||||
export default function CustomAccordionToggle({ children, eventKey }: CustomAccordionToggleProps) { |
||||
const [toggleAccordion, setToggleAccordion] = useState(false) |
||||
|
||||
const decoratedOnClick = useAccordionToggle(eventKey, () => |
||||
setToggleAccordion(!toggleAccordion) |
||||
) |
||||
|
||||
return ( |
||||
<div |
||||
onClick={decoratedOnClick} |
||||
className="d-flex flex-row justify-content-between align-items-center mx-3" |
||||
> |
||||
{children} |
||||
<i className={toggleAccordion ? 'far fa-angle-down' : 'far fa-angle-right'}></i> |
||||
</div> |
||||
) |
||||
} |
File diff suppressed because one or more lines are too long
@ -0,0 +1,66 @@ |
||||
export const fetchContractFromBlockscout = async (plugin, endpoint, contractAddress, targetPath, shouldSetFile = true) => { |
||||
let data |
||||
const compilationTargets = {} |
||||
|
||||
try { |
||||
data = await fetch('https://' + endpoint + '/api?module=contract&action=getsourcecode&address=' + contractAddress) |
||||
data = await data.json() |
||||
// blockscout api doc https://blockscout.com/poa/core/api-docs
|
||||
if (data.message === 'OK' && data.status === "1") { |
||||
if (data.result.length) { |
||||
if (!data.result[0].SourceCode || data.result[0].SourceCode === '') { |
||||
throw new Error(`contract not verified on Blockscout ${endpoint} network`) |
||||
} |
||||
} |
||||
} else throw new Error('unable to retrieve contract data ' + data.message) |
||||
} catch (e) { |
||||
throw new Error('unable to retrieve contract data: ' + e.message) |
||||
} |
||||
|
||||
if (!data || !data.result) { |
||||
return null |
||||
} |
||||
|
||||
if (data.result[0].FileName === '') { |
||||
const fileName = `${targetPath}/${data.result[0].ContractName}.sol` |
||||
if (shouldSetFile) await plugin.call('fileManager', 'setFile', fileName, data.result[0].SourceCode) |
||||
compilationTargets[fileName] = { content: data.result[0].SourceCode } |
||||
} else { |
||||
const sources = {} |
||||
sources[data.result[0].FileName] = data.result[0].SourceCode |
||||
if (data.result[0].AdditionalSources && Array.isArray(data.result[0].AdditionalSources)) { |
||||
for (const object of data.result[0].AdditionalSources) { |
||||
sources[object.Filename] = object.SourceCode |
||||
} |
||||
} |
||||
|
||||
for (let [file, source] of Object.entries(sources)) { // eslint-disable-line
|
||||
file = file.replace('browser/', '') // should be fixed in the remix IDE end.
|
||||
file = file.replace(/^\//g, '') // remove first slash.
|
||||
if (await plugin.call('contentImport', 'isExternalUrl', file)) { |
||||
// nothing to do, the compiler callback will handle those
|
||||
} else { |
||||
const path = `${targetPath}/${file}` |
||||
const content = source |
||||
if (shouldSetFile) await plugin.call('fileManager', 'setFile', path, content) |
||||
compilationTargets[path] = { content } |
||||
} |
||||
} |
||||
} |
||||
|
||||
let runs = 0 |
||||
try { |
||||
runs = parseInt(data.result[0].OptimizationRuns) |
||||
} catch (e) { } |
||||
const settings = { |
||||
version: data.result[0].CompilerVersion.replace(/^v/, ''), |
||||
language: 'Solidity', |
||||
evmVersion: data.result[0].EVMVersion.toLowerCase(), |
||||
optimize: data.result[0].OptimizationUsed === 'true', |
||||
runs |
||||
} |
||||
return { |
||||
settings, |
||||
compilationTargets |
||||
} |
||||
} |
@ -0,0 +1,77 @@ |
||||
import {CopyToClipboard} from '@remix-ui/clipboard' |
||||
import {CustomTooltip} from '@remix-ui/helper' |
||||
import React, {useEffect, useState} from 'react' |
||||
import {FormattedMessage, useIntl} from 'react-intl' |
||||
import {SindriSettingsProps} from '../types' |
||||
import {sindriAccessTokenLink} from './constants' |
||||
|
||||
export function SindriSettings(props: SindriSettingsProps) { |
||||
const [sindriToken, setSindriToken] = useState<string>('') |
||||
const intl = useIntl() |
||||
|
||||
useEffect(() => { |
||||
if (props.config) { |
||||
const sindriToken = props.config.get('settings/sindri-access-token') || '' |
||||
setSindriToken(sindriToken) |
||||
} |
||||
}, [props.config]) |
||||
|
||||
const handleChangeTokenState = (event) => { |
||||
const token = event.target.value ? event.target.value.trim() : event.target.value |
||||
setSindriToken(token) |
||||
} |
||||
|
||||
// api key settings
|
||||
const saveSindriToken = () => { |
||||
props.saveToken(sindriToken) |
||||
} |
||||
|
||||
const removeToken = () => { |
||||
setSindriToken('') |
||||
props.removeToken() |
||||
} |
||||
|
||||
return ( |
||||
<div className="border-top"> |
||||
<div className="card-body pt-3 pb-2"> |
||||
<h6 className="card-title"> |
||||
<FormattedMessage id="settings.sindriAccessTokenTitle" /> |
||||
</h6> |
||||
<p className="mb-1"> |
||||
<FormattedMessage id="settings.sindriAccessTokenText" /> |
||||
</p> |
||||
<p className=""> |
||||
<FormattedMessage id="settings.sindriAccessTokenText2" /> |
||||
</p> |
||||
<p className="mb-1"> |
||||
<a className="text-primary" target="_blank" href={sindriAccessTokenLink}> |
||||
{sindriAccessTokenLink} |
||||
</a> |
||||
</p> |
||||
<div> |
||||
<label className="mb-0 pb-0"> |
||||
<FormattedMessage id="settings.token" />: |
||||
</label> |
||||
<div className="input-group text-secondary mb-0 h6"> |
||||
<input id="sindriaccesstoken" data-id="settingsTabSindriAccessToken" type="password" className="form-control" onChange={(e) => handleChangeTokenState(e)} value={sindriToken} /> |
||||
<div className="input-group-append"> |
||||
<CopyToClipboard tip={intl.formatMessage({id: 'settings.copy'})} content={sindriToken} data-id="copyToClipboardCopyIcon" className="far fa-copy ml-1 p-2 mt-1" direction={'top'} /> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
<div> |
||||
<div className="text-secondary mb-0 h6"> |
||||
<div className="d-flex justify-content-end pt-2"> |
||||
<input className="btn btn-sm btn-primary ml-2" id="savesindritoken" data-id="settingsTabSaveSindriToken" onClick={saveSindriToken} value={intl.formatMessage({id: 'settings.save'})} type="button"></input> |
||||
<CustomTooltip tooltipText={<FormattedMessage id="settings.deleteSindriCredentials" />} tooltipClasses="text-nowrap" tooltipId="removesindritokenTooltip" placement="top-start"> |
||||
<button className="btn btn-sm btn-secondary ml-2" id="removesindritoken" data-id="settingsTabRemoveSindriToken" onClick={removeToken}> |
||||
<FormattedMessage id="settings.remove" /> |
||||
</button> |
||||
</CustomTooltip> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
) |
||||
} |
@ -1 +1,3 @@ |
||||
export * from './lib/remix-ui-terminal' |
||||
export * from './lib/remix-ui-terminal-wrapper' |
||||
export * from './lib/context' |
@ -0,0 +1,41 @@ |
||||
import { appPlatformTypes, platformContext } from '@remix-ui/app' |
||||
import { CustomTooltip } from '@remix-ui/helper' |
||||
import React, { useState, useEffect, useRef, useContext } from 'react' // eslint-disable-line
|
||||
import { FormattedMessage, useIntl } from 'react-intl' |
||||
import { listenOnNetworkAction } from '../actions/terminalAction' |
||||
import { TerminalContext } from '../context' |
||||
import { RemixUiTerminalProps } from '../types/terminalTypes' |
||||
import { RemixUITerminalMenu } from './remix-ui-terminal-menu' |
||||
import { RemixUITerminalMenuToggle } from './remix-ui-terminal-menu-toggle' |
||||
import { RemixUIXtermMenu } from '../../../../xterm/src/lib/components/remix-ui-terminal-menu-xterm' |
||||
import { RemixUITerminalMenuButtons } from './remix-ui-terminal-menu-buttons' |
||||
|
||||
export const RemixUITerminalBar = (props: RemixUiTerminalProps) => { |
||||
const { terminalState, xtermState } = useContext(TerminalContext) |
||||
const platform = useContext(platformContext) |
||||
const intl = useIntl() |
||||
const terminalMenu = useRef(null) |
||||
|
||||
useEffect(() => { |
||||
props.plugin.call('layout', 'minimize', props.plugin.profile.name, !terminalState.isOpen) |
||||
}, [terminalState.isOpen]) |
||||
|
||||
return (<> |
||||
<div className="remix_ui_terminal_bar d-flex"> |
||||
<div |
||||
className="remix_ui_terminal_menu justify-content-between d-flex w-100 align-items-center position-relative border-top border-dark bg-light" |
||||
ref={terminalMenu} |
||||
data-id="terminalToggleMenu" |
||||
> |
||||
<RemixUITerminalMenuToggle {...props} /> |
||||
{platform === appPlatformTypes.desktop ? |
||||
<div className='d-flex flex-row w-100 justify-content-between '> |
||||
<RemixUITerminalMenuButtons {...props} /> |
||||
{xtermState.showOutput? <RemixUITerminalMenu {...props} />: <RemixUIXtermMenu {...props} />} |
||||
</div> : |
||||
<RemixUITerminalMenu {...props} /> |
||||
} |
||||
</div> |
||||
</div></> |
||||
) |
||||
} |
@ -0,0 +1,3 @@ |
||||
.xtermButton { |
||||
width: 4rem;; |
||||
} |
@ -0,0 +1,31 @@ |
||||
import React, { useContext, useEffect } from 'react' // eslint-disable-line
|
||||
import { TerminalContext } from '../context' |
||||
import { RemixUiTerminalProps, SET_OPEN } from '../types/terminalTypes' |
||||
import './remix-ui-terminal-menu-buttons.css' |
||||
|
||||
export const RemixUITerminalMenuButtons = (props: RemixUiTerminalProps) => { |
||||
const { xtermState, dispatchXterm, terminalState, dispatch } = useContext(TerminalContext) |
||||
|
||||
function selectOutput(event: any): void { |
||||
props.plugin.call('layout', 'minimize', props.plugin.profile.name, false) |
||||
dispatchXterm({ type: 'SHOW_OUTPUT', payload: true }) |
||||
dispatch({ type: SET_OPEN, payload: true }) |
||||
} |
||||
|
||||
function showTerminal(event: any): void { |
||||
props.plugin.call('layout', 'minimize', props.plugin.profile.name, false) |
||||
dispatchXterm({ type: 'SHOW_OUTPUT', payload: false }) |
||||
dispatch({ type: SET_OPEN, payload: true }) |
||||
} |
||||
|
||||
return ( |
||||
<div className='d-flex flex-row align-items-center'> |
||||
<button id="tabOutput" className={`xtermButton btn btn-sm border-secondary mr-2 border ${!xtermState.showOutput ? '' : 'd-flex btn-secondary'}`} onClick={selectOutput}> |
||||
Output |
||||
</button> |
||||
<button id="tabXTerm" className={`xtermButton btn btn-sm border-secondary ${xtermState.terminalsEnabled ? 'd-block' : 'd-none'} ${xtermState.showOutput ? 'd-none' : 'btn-secondary'}`} onClick={showTerminal}> |
||||
<span className="far fa-terminal border-0 ml-1"></span> |
||||
</button> |
||||
</div> |
||||
) |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue