Merge branch 'view-in-try-michelson-ide' into 'dev'
Added view in try-michelson link See merge request ligolang/ligo!461
This commit is contained in:
commit
cd3e7cf32f
@ -7,6 +7,7 @@ import { AppState } from '../redux/app';
|
|||||||
import { CommandState } from '../redux/command';
|
import { CommandState } from '../redux/command';
|
||||||
import { DoneLoadingAction, LoadingState } from '../redux/loading';
|
import { DoneLoadingAction, LoadingState } from '../redux/loading';
|
||||||
import { ResultState } from '../redux/result';
|
import { ResultState } from '../redux/result';
|
||||||
|
import { Command } from '../redux/types';
|
||||||
import { OutputToolbarComponent } from './output-toolbar';
|
import { OutputToolbarComponent } from './output-toolbar';
|
||||||
|
|
||||||
const Container = styled.div<{ visible?: boolean }>`
|
const Container = styled.div<{ visible?: boolean }>`
|
||||||
@ -43,7 +44,7 @@ const CancelButton = styled.div`
|
|||||||
|
|
||||||
const Output = styled.div`
|
const Output = styled.div`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
padding: 0 0.5em 0.5em 0.5em;
|
padding: 0.5em;
|
||||||
display: flex;
|
display: flex;
|
||||||
overflow: scroll;
|
overflow: scroll;
|
||||||
/* This font size is used to calcuate spinner size */
|
/* This font size is used to calcuate spinner size */
|
||||||
@ -81,12 +82,11 @@ function copyOutput(el: HTMLElement | null) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function downloadOutput(el: HTMLElement | null) {
|
function downloadOutput(output: string) {
|
||||||
if (el) {
|
|
||||||
const anchor = document.createElement('a');
|
const anchor = document.createElement('a');
|
||||||
anchor.setAttribute(
|
anchor.setAttribute(
|
||||||
'href',
|
'href',
|
||||||
'data:text/plain;charset=utf-8,' + encodeURIComponent(el.innerHTML)
|
`data:text/plain;charset=utf-8,${encodeURIComponent(output)}`
|
||||||
);
|
);
|
||||||
anchor.setAttribute('download', 'output.txt');
|
anchor.setAttribute('download', 'output.txt');
|
||||||
|
|
||||||
@ -94,7 +94,6 @@ function downloadOutput(el: HTMLElement | null) {
|
|||||||
document.body.appendChild(anchor);
|
document.body.appendChild(anchor);
|
||||||
anchor.click();
|
anchor.click();
|
||||||
document.body.removeChild(anchor);
|
document.body.removeChild(anchor);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export const OutputTabComponent = (props: {
|
export const OutputTabComponent = (props: {
|
||||||
@ -107,6 +106,9 @@ export const OutputTabComponent = (props: {
|
|||||||
const contract = useSelector<AppState, ResultState['contract']>(
|
const contract = useSelector<AppState, ResultState['contract']>(
|
||||||
state => state.result.contract
|
state => state.result.contract
|
||||||
);
|
);
|
||||||
|
const command = useSelector<AppState, ResultState['command']>(
|
||||||
|
state => state.result.command
|
||||||
|
);
|
||||||
|
|
||||||
const loading = useSelector<AppState, LoadingState>(state => state.loading);
|
const loading = useSelector<AppState, LoadingState>(state => state.loading);
|
||||||
|
|
||||||
@ -132,10 +134,14 @@ export const OutputTabComponent = (props: {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<Container visible={props.selected}>
|
<Container visible={props.selected}>
|
||||||
{!(loading.loading || output.length === 0) && (
|
{!(
|
||||||
|
loading.loading ||
|
||||||
|
output.length === 0 ||
|
||||||
|
command !== Command.Compile
|
||||||
|
) && (
|
||||||
<OutputToolbarComponent
|
<OutputToolbarComponent
|
||||||
onCopy={() => copyOutput(preRef.current)}
|
onCopy={() => copyOutput(preRef.current)}
|
||||||
onDownload={() => downloadOutput(preRef.current)}
|
onDownload={() => downloadOutput(output)}
|
||||||
></OutputToolbarComponent>
|
></OutputToolbarComponent>
|
||||||
)}
|
)}
|
||||||
<Output id="output" ref={outputRef}>
|
<Output id="output" ref={outputRef}>
|
||||||
|
@ -1,78 +1,58 @@
|
|||||||
import { faCopy, faDownload } from '@fortawesome/free-solid-svg-icons';
|
import { faCopy, faDownload } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useSelector } from 'react-redux';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import { AppState } from '../redux/app';
|
||||||
|
import { ResultState } from '../redux/result';
|
||||||
|
import { Item, Toolbar } from './toolbar';
|
||||||
import { Tooltip } from './tooltip';
|
import { Tooltip } from './tooltip';
|
||||||
|
|
||||||
const Container = styled.div`
|
const Divider = styled.div`
|
||||||
display: flex;
|
display: block;
|
||||||
justify-content: flex-start;
|
background-color: rgba(0, 0, 0, 0.12);
|
||||||
padding: 0.2em 0.5em;
|
height: 20px;
|
||||||
z-index: 3;
|
width: 1px;
|
||||||
|
margin: 0 3px;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Action = styled.div`
|
const Link = styled.a`
|
||||||
z-index: 3;
|
font-size: 0.8em;
|
||||||
position: relative;
|
color: var(--blue);
|
||||||
margin: 4px 6px;
|
|
||||||
cursor: pointer;
|
|
||||||
|
|
||||||
opacity: 0.5;
|
|
||||||
color: #444;
|
|
||||||
|
|
||||||
::before {
|
|
||||||
content: '';
|
|
||||||
display: block;
|
|
||||||
position: absolute;
|
|
||||||
z-index: -1;
|
|
||||||
bottom: -4px;
|
|
||||||
left: -4px;
|
|
||||||
right: -4px;
|
|
||||||
top: -4px;
|
|
||||||
border-radius: 4px;
|
|
||||||
background: none;
|
|
||||||
box-sizing: border-box;
|
|
||||||
opacity: 0;
|
|
||||||
transform: scale(0);
|
|
||||||
transition-property: transform, opacity;
|
|
||||||
transition-duration: 0.15s;
|
|
||||||
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
:hover::before {
|
|
||||||
background-color: rgba(32, 33, 36, 0.059);
|
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
transform: scale(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
:hover {
|
|
||||||
opacity: 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:first-child {
|
|
||||||
margin-left: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:last-child {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const OutputToolbarComponent = (props: {
|
export const OutputToolbarComponent = (props: {
|
||||||
onCopy?: () => void;
|
onCopy?: () => void;
|
||||||
onDownload?: () => void;
|
onDownload?: () => void;
|
||||||
}) => {
|
}) => {
|
||||||
|
const output = useSelector<AppState, ResultState['output']>(
|
||||||
|
state => state.result.output
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Toolbar>
|
||||||
<Action onClick={() => props.onCopy && props.onCopy()}>
|
<Item onClick={() => props.onCopy && props.onCopy()}>
|
||||||
<FontAwesomeIcon icon={faCopy}></FontAwesomeIcon>
|
<FontAwesomeIcon icon={faCopy}></FontAwesomeIcon>
|
||||||
<Tooltip>Copy</Tooltip>
|
<Tooltip>Copy</Tooltip>
|
||||||
</Action>
|
</Item>
|
||||||
<Action onClick={() => props.onDownload && props.onDownload()}>
|
<Item onClick={() => props.onDownload && props.onDownload()}>
|
||||||
<FontAwesomeIcon icon={faDownload}></FontAwesomeIcon>
|
<FontAwesomeIcon icon={faDownload}></FontAwesomeIcon>
|
||||||
<Tooltip>Download</Tooltip>
|
<Tooltip>Download</Tooltip>
|
||||||
</Action>
|
</Item>
|
||||||
</Container>
|
<Divider></Divider>
|
||||||
|
<Item>
|
||||||
|
<Link
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
href={`https://try-michelson.tzalpha.net/?source=${encodeURIComponent(
|
||||||
|
output
|
||||||
|
)}`}
|
||||||
|
>
|
||||||
|
View in Try-Michelson IDE
|
||||||
|
</Link>
|
||||||
|
</Item>
|
||||||
|
</Toolbar>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
65
tools/webide/packages/client/src/components/toolbar.tsx
Normal file
65
tools/webide/packages/client/src/components/toolbar.tsx
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
padding: 0.2em 0.5em;
|
||||||
|
z-index: 3;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Group = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Item = styled.div`
|
||||||
|
z-index: 3;
|
||||||
|
position: relative;
|
||||||
|
margin: 4px 6px;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
opacity: 0.5;
|
||||||
|
color: #444;
|
||||||
|
|
||||||
|
::before {
|
||||||
|
content: '';
|
||||||
|
display: block;
|
||||||
|
position: absolute;
|
||||||
|
z-index: -1;
|
||||||
|
bottom: -4px;
|
||||||
|
left: -4px;
|
||||||
|
right: -4px;
|
||||||
|
top: -4px;
|
||||||
|
border-radius: 4px;
|
||||||
|
background: none;
|
||||||
|
box-sizing: border-box;
|
||||||
|
opacity: 0;
|
||||||
|
transform: scale(0);
|
||||||
|
transition-property: transform, opacity;
|
||||||
|
transition-duration: 0.15s;
|
||||||
|
transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
:hover::before {
|
||||||
|
background-color: rgba(32, 33, 36, 0.059);
|
||||||
|
opacity: 1;
|
||||||
|
transform: scale(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:first-child {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:last-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const Toolbar = (props: any) => {
|
||||||
|
return <Container>{props.children}</Container>;
|
||||||
|
};
|
@ -48,7 +48,7 @@
|
|||||||
--font_ghost_weight: 700;
|
--font_ghost_weight: 700;
|
||||||
--font_ghost_color: rgba(153, 153, 153, 0.5); /* or #CFCFCF */
|
--font_ghost_color: rgba(153, 153, 153, 0.5); /* or #CFCFCF */
|
||||||
|
|
||||||
--content_height: 85vh;
|
--content_height: 84vh;
|
||||||
|
|
||||||
--tooltip_foreground: white;
|
--tooltip_foreground: white;
|
||||||
--tooltip_background: rgba(0, 0, 0, 0.75) /*#404040*/;
|
--tooltip_background: rgba(0, 0, 0, 0.75) /*#404040*/;
|
||||||
|
@ -4,6 +4,7 @@ import { compileContract, getErrorMessage } from '../../services/api';
|
|||||||
import { AppState } from '../app';
|
import { AppState } from '../app';
|
||||||
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||||
import { ChangeOutputAction } from '../result';
|
import { ChangeOutputAction } from '../result';
|
||||||
|
import { Command } from '../types';
|
||||||
import { CancellableAction } from './cancellable';
|
import { CancellableAction } from './cancellable';
|
||||||
|
|
||||||
export class CompileAction extends CancellableAction {
|
export class CompileAction extends CancellableAction {
|
||||||
@ -24,13 +25,18 @@ export class CompileAction extends CancellableAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({ ...new ChangeOutputAction(michelsonCode.result) });
|
dispatch({
|
||||||
|
...new ChangeOutputAction(michelsonCode.result, Command.Compile)
|
||||||
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
...new ChangeOutputAction(`Error: ${getErrorMessage(ex)}`)
|
...new ChangeOutputAction(
|
||||||
|
`Error: ${getErrorMessage(ex)}`,
|
||||||
|
Command.Compile
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,6 +7,7 @@ import { AppState } from '../app';
|
|||||||
import { MichelsonFormat } from '../compile';
|
import { MichelsonFormat } from '../compile';
|
||||||
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||||
import { ChangeContractAction, ChangeOutputAction } from '../result';
|
import { ChangeContractAction, ChangeOutputAction } from '../result';
|
||||||
|
import { Command } from '../types';
|
||||||
import { CancellableAction } from './cancellable';
|
import { CancellableAction } from './cancellable';
|
||||||
|
|
||||||
Tezos.setProvider({
|
Tezos.setProvider({
|
||||||
@ -85,13 +86,18 @@ export class DeployAction extends CancellableAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({ ...new ChangeContractAction(contract.address) });
|
dispatch({
|
||||||
|
...new ChangeContractAction(contract.address, Command.Deploy)
|
||||||
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
...new ChangeOutputAction(`Error: ${getErrorMessage(ex)}`)
|
...new ChangeOutputAction(
|
||||||
|
`Error: ${getErrorMessage(ex)}`,
|
||||||
|
Command.Deploy
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { dryRun, getErrorMessage } from '../../services/api';
|
|||||||
import { AppState } from '../app';
|
import { AppState } from '../app';
|
||||||
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||||
import { ChangeOutputAction } from '../result';
|
import { ChangeOutputAction } from '../result';
|
||||||
|
import { Command } from '../types';
|
||||||
import { CancellableAction } from './cancellable';
|
import { CancellableAction } from './cancellable';
|
||||||
|
|
||||||
export class DryRunAction extends CancellableAction {
|
export class DryRunAction extends CancellableAction {
|
||||||
@ -25,13 +26,16 @@ export class DryRunAction extends CancellableAction {
|
|||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({ ...new ChangeOutputAction(result.output) });
|
dispatch({ ...new ChangeOutputAction(result.output, Command.DryRun) });
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
...new ChangeOutputAction(`Error: ${getErrorMessage(ex)}`)
|
...new ChangeOutputAction(
|
||||||
|
`Error: ${getErrorMessage(ex)}`,
|
||||||
|
Command.DryRun
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { getErrorMessage, runFunction } from '../../services/api';
|
|||||||
import { AppState } from '../app';
|
import { AppState } from '../app';
|
||||||
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||||
import { ChangeOutputAction } from '../result';
|
import { ChangeOutputAction } from '../result';
|
||||||
|
import { Command } from '../types';
|
||||||
import { CancellableAction } from './cancellable';
|
import { CancellableAction } from './cancellable';
|
||||||
|
|
||||||
export class EvaluateFunctionAction extends CancellableAction {
|
export class EvaluateFunctionAction extends CancellableAction {
|
||||||
@ -27,13 +28,18 @@ export class EvaluateFunctionAction extends CancellableAction {
|
|||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({ ...new ChangeOutputAction(result.output) });
|
dispatch({
|
||||||
|
...new ChangeOutputAction(result.output, Command.EvaluateFunction)
|
||||||
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
...new ChangeOutputAction(`Error: ${getErrorMessage(ex)}`)
|
...new ChangeOutputAction(
|
||||||
|
`Error: ${getErrorMessage(ex)}`,
|
||||||
|
Command.EvaluateFunction
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@ import { evaluateValue, getErrorMessage } from '../../services/api';
|
|||||||
import { AppState } from '../app';
|
import { AppState } from '../app';
|
||||||
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||||
import { ChangeOutputAction } from '../result';
|
import { ChangeOutputAction } from '../result';
|
||||||
|
import { Command } from '../types';
|
||||||
import { CancellableAction } from './cancellable';
|
import { CancellableAction } from './cancellable';
|
||||||
|
|
||||||
export class EvaluateValueAction extends CancellableAction {
|
export class EvaluateValueAction extends CancellableAction {
|
||||||
@ -28,13 +29,18 @@ export class EvaluateValueAction extends CancellableAction {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
dispatch({ ...new ChangeOutputAction(result.code) });
|
dispatch({
|
||||||
|
...new ChangeOutputAction(result.code, Command.EvaluateValue)
|
||||||
|
});
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
if (this.isCancelled()) {
|
if (this.isCancelled()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
dispatch({
|
dispatch({
|
||||||
...new ChangeOutputAction(`Error: ${getErrorMessage(ex)}`)
|
...new ChangeOutputAction(
|
||||||
|
`Error: ${getErrorMessage(ex)}`,
|
||||||
|
Command.EvaluateValue
|
||||||
|
)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,26 +1,36 @@
|
|||||||
|
import { Command } from './types';
|
||||||
|
|
||||||
export enum ActionType {
|
export enum ActionType {
|
||||||
ChangeOutput = 'result-change-output',
|
ChangeOutput = 'result-change-output',
|
||||||
ChangeContract = 'result-change-contract'
|
ChangeContract = 'result-change-contract'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ResultState {
|
export interface ResultState {
|
||||||
|
command: Command;
|
||||||
output: string;
|
output: string;
|
||||||
contract: string;
|
contract: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChangeOutputAction {
|
export class ChangeOutputAction {
|
||||||
public readonly type = ActionType.ChangeOutput;
|
public readonly type = ActionType.ChangeOutput;
|
||||||
constructor(public payload: ResultState['output']) {}
|
constructor(
|
||||||
|
public output: ResultState['output'],
|
||||||
|
public command: ResultState['command']
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChangeContractAction {
|
export class ChangeContractAction {
|
||||||
public readonly type = ActionType.ChangeContract;
|
public readonly type = ActionType.ChangeContract;
|
||||||
constructor(public payload: ResultState['contract']) {}
|
constructor(
|
||||||
|
public contract: ResultState['contract'],
|
||||||
|
public command: ResultState['command']
|
||||||
|
) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Action = ChangeOutputAction | ChangeContractAction;
|
type Action = ChangeOutputAction | ChangeContractAction;
|
||||||
|
|
||||||
const DEFAULT_STATE: ResultState = {
|
const DEFAULT_STATE: ResultState = {
|
||||||
|
command: Command.Compile,
|
||||||
output: '',
|
output: '',
|
||||||
contract: ''
|
contract: ''
|
||||||
};
|
};
|
||||||
@ -30,13 +40,15 @@ export default (state = DEFAULT_STATE, action: Action): ResultState => {
|
|||||||
case ActionType.ChangeOutput:
|
case ActionType.ChangeOutput:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
output: action.payload
|
output: action.output,
|
||||||
|
command: action.command
|
||||||
};
|
};
|
||||||
case ActionType.ChangeContract:
|
case ActionType.ChangeContract:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
output: DEFAULT_STATE.output,
|
output: DEFAULT_STATE.output,
|
||||||
contract: action.payload
|
contract: action.contract,
|
||||||
|
command: action.command
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return state;
|
return state;
|
||||||
|
Loading…
Reference in New Issue
Block a user