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 { DoneLoadingAction, LoadingState } from '../redux/loading';
|
||||
import { ResultState } from '../redux/result';
|
||||
import { Command } from '../redux/types';
|
||||
import { OutputToolbarComponent } from './output-toolbar';
|
||||
|
||||
const Container = styled.div<{ visible?: boolean }>`
|
||||
@ -43,7 +44,7 @@ const CancelButton = styled.div`
|
||||
|
||||
const Output = styled.div`
|
||||
flex: 1;
|
||||
padding: 0 0.5em 0.5em 0.5em;
|
||||
padding: 0.5em;
|
||||
display: flex;
|
||||
overflow: scroll;
|
||||
/* This font size is used to calcuate spinner size */
|
||||
@ -81,20 +82,18 @@ function copyOutput(el: HTMLElement | null) {
|
||||
}
|
||||
}
|
||||
|
||||
function downloadOutput(el: HTMLElement | null) {
|
||||
if (el) {
|
||||
const anchor = document.createElement('a');
|
||||
anchor.setAttribute(
|
||||
'href',
|
||||
'data:text/plain;charset=utf-8,' + encodeURIComponent(el.innerHTML)
|
||||
);
|
||||
anchor.setAttribute('download', 'output.txt');
|
||||
function downloadOutput(output: string) {
|
||||
const anchor = document.createElement('a');
|
||||
anchor.setAttribute(
|
||||
'href',
|
||||
`data:text/plain;charset=utf-8,${encodeURIComponent(output)}`
|
||||
);
|
||||
anchor.setAttribute('download', 'output.txt');
|
||||
|
||||
anchor.style.display = 'none';
|
||||
document.body.appendChild(anchor);
|
||||
anchor.click();
|
||||
document.body.removeChild(anchor);
|
||||
}
|
||||
anchor.style.display = 'none';
|
||||
document.body.appendChild(anchor);
|
||||
anchor.click();
|
||||
document.body.removeChild(anchor);
|
||||
}
|
||||
|
||||
export const OutputTabComponent = (props: {
|
||||
@ -107,6 +106,9 @@ export const OutputTabComponent = (props: {
|
||||
const contract = useSelector<AppState, ResultState['contract']>(
|
||||
state => state.result.contract
|
||||
);
|
||||
const command = useSelector<AppState, ResultState['command']>(
|
||||
state => state.result.command
|
||||
);
|
||||
|
||||
const loading = useSelector<AppState, LoadingState>(state => state.loading);
|
||||
|
||||
@ -132,10 +134,14 @@ export const OutputTabComponent = (props: {
|
||||
|
||||
return (
|
||||
<Container visible={props.selected}>
|
||||
{!(loading.loading || output.length === 0) && (
|
||||
{!(
|
||||
loading.loading ||
|
||||
output.length === 0 ||
|
||||
command !== Command.Compile
|
||||
) && (
|
||||
<OutputToolbarComponent
|
||||
onCopy={() => copyOutput(preRef.current)}
|
||||
onDownload={() => downloadOutput(preRef.current)}
|
||||
onDownload={() => downloadOutput(output)}
|
||||
></OutputToolbarComponent>
|
||||
)}
|
||||
<Output id="output" ref={outputRef}>
|
||||
|
@ -1,78 +1,58 @@
|
||||
import { faCopy, faDownload } from '@fortawesome/free-solid-svg-icons';
|
||||
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import styled from 'styled-components';
|
||||
|
||||
import { AppState } from '../redux/app';
|
||||
import { ResultState } from '../redux/result';
|
||||
import { Item, Toolbar } from './toolbar';
|
||||
import { Tooltip } from './tooltip';
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
justify-content: flex-start;
|
||||
padding: 0.2em 0.5em;
|
||||
z-index: 3;
|
||||
const Divider = styled.div`
|
||||
display: block;
|
||||
background-color: rgba(0, 0, 0, 0.12);
|
||||
height: 20px;
|
||||
width: 1px;
|
||||
margin: 0 3px;
|
||||
`;
|
||||
|
||||
const Action = 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;
|
||||
}
|
||||
const Link = styled.a`
|
||||
font-size: 0.8em;
|
||||
color: var(--blue);
|
||||
opacity: 1;
|
||||
`;
|
||||
|
||||
export const OutputToolbarComponent = (props: {
|
||||
onCopy?: () => void;
|
||||
onDownload?: () => void;
|
||||
}) => {
|
||||
const output = useSelector<AppState, ResultState['output']>(
|
||||
state => state.result.output
|
||||
);
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<Action onClick={() => props.onCopy && props.onCopy()}>
|
||||
<Toolbar>
|
||||
<Item onClick={() => props.onCopy && props.onCopy()}>
|
||||
<FontAwesomeIcon icon={faCopy}></FontAwesomeIcon>
|
||||
<Tooltip>Copy</Tooltip>
|
||||
</Action>
|
||||
<Action onClick={() => props.onDownload && props.onDownload()}>
|
||||
</Item>
|
||||
<Item onClick={() => props.onDownload && props.onDownload()}>
|
||||
<FontAwesomeIcon icon={faDownload}></FontAwesomeIcon>
|
||||
<Tooltip>Download</Tooltip>
|
||||
</Action>
|
||||
</Container>
|
||||
</Item>
|
||||
<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_color: rgba(153, 153, 153, 0.5); /* or #CFCFCF */
|
||||
|
||||
--content_height: 85vh;
|
||||
--content_height: 84vh;
|
||||
|
||||
--tooltip_foreground: white;
|
||||
--tooltip_background: rgba(0, 0, 0, 0.75) /*#404040*/;
|
||||
|
@ -4,6 +4,7 @@ import { compileContract, getErrorMessage } from '../../services/api';
|
||||
import { AppState } from '../app';
|
||||
import { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||
import { ChangeOutputAction } from '../result';
|
||||
import { Command } from '../types';
|
||||
import { CancellableAction } from './cancellable';
|
||||
|
||||
export class CompileAction extends CancellableAction {
|
||||
@ -24,13 +25,18 @@ export class CompileAction extends CancellableAction {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({ ...new ChangeOutputAction(michelsonCode.result) });
|
||||
dispatch({
|
||||
...new ChangeOutputAction(michelsonCode.result, Command.Compile)
|
||||
});
|
||||
} catch (ex) {
|
||||
if (this.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
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 { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||
import { ChangeContractAction, ChangeOutputAction } from '../result';
|
||||
import { Command } from '../types';
|
||||
import { CancellableAction } from './cancellable';
|
||||
|
||||
Tezos.setProvider({
|
||||
@ -85,13 +86,18 @@ export class DeployAction extends CancellableAction {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({ ...new ChangeContractAction(contract.address) });
|
||||
dispatch({
|
||||
...new ChangeContractAction(contract.address, Command.Deploy)
|
||||
});
|
||||
} catch (ex) {
|
||||
if (this.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
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 { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||
import { ChangeOutputAction } from '../result';
|
||||
import { Command } from '../types';
|
||||
import { CancellableAction } from './cancellable';
|
||||
|
||||
export class DryRunAction extends CancellableAction {
|
||||
@ -25,13 +26,16 @@ export class DryRunAction extends CancellableAction {
|
||||
if (this.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
dispatch({ ...new ChangeOutputAction(result.output) });
|
||||
dispatch({ ...new ChangeOutputAction(result.output, Command.DryRun) });
|
||||
} catch (ex) {
|
||||
if (this.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
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 { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||
import { ChangeOutputAction } from '../result';
|
||||
import { Command } from '../types';
|
||||
import { CancellableAction } from './cancellable';
|
||||
|
||||
export class EvaluateFunctionAction extends CancellableAction {
|
||||
@ -27,13 +28,18 @@ export class EvaluateFunctionAction extends CancellableAction {
|
||||
if (this.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
dispatch({ ...new ChangeOutputAction(result.output) });
|
||||
dispatch({
|
||||
...new ChangeOutputAction(result.output, Command.EvaluateFunction)
|
||||
});
|
||||
} catch (ex) {
|
||||
if (this.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
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 { DoneLoadingAction, UpdateLoadingAction } from '../loading';
|
||||
import { ChangeOutputAction } from '../result';
|
||||
import { Command } from '../types';
|
||||
import { CancellableAction } from './cancellable';
|
||||
|
||||
export class EvaluateValueAction extends CancellableAction {
|
||||
@ -28,13 +29,18 @@ export class EvaluateValueAction extends CancellableAction {
|
||||
return;
|
||||
}
|
||||
|
||||
dispatch({ ...new ChangeOutputAction(result.code) });
|
||||
dispatch({
|
||||
...new ChangeOutputAction(result.code, Command.EvaluateValue)
|
||||
});
|
||||
} catch (ex) {
|
||||
if (this.isCancelled()) {
|
||||
return;
|
||||
}
|
||||
dispatch({
|
||||
...new ChangeOutputAction(`Error: ${getErrorMessage(ex)}`)
|
||||
...new ChangeOutputAction(
|
||||
`Error: ${getErrorMessage(ex)}`,
|
||||
Command.EvaluateValue
|
||||
)
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -1,26 +1,36 @@
|
||||
import { Command } from './types';
|
||||
|
||||
export enum ActionType {
|
||||
ChangeOutput = 'result-change-output',
|
||||
ChangeContract = 'result-change-contract'
|
||||
}
|
||||
|
||||
export interface ResultState {
|
||||
command: Command;
|
||||
output: string;
|
||||
contract: string;
|
||||
}
|
||||
|
||||
export class ChangeOutputAction {
|
||||
public readonly type = ActionType.ChangeOutput;
|
||||
constructor(public payload: ResultState['output']) {}
|
||||
constructor(
|
||||
public output: ResultState['output'],
|
||||
public command: ResultState['command']
|
||||
) {}
|
||||
}
|
||||
|
||||
export class ChangeContractAction {
|
||||
public readonly type = ActionType.ChangeContract;
|
||||
constructor(public payload: ResultState['contract']) {}
|
||||
constructor(
|
||||
public contract: ResultState['contract'],
|
||||
public command: ResultState['command']
|
||||
) {}
|
||||
}
|
||||
|
||||
type Action = ChangeOutputAction | ChangeContractAction;
|
||||
|
||||
const DEFAULT_STATE: ResultState = {
|
||||
command: Command.Compile,
|
||||
output: '',
|
||||
contract: ''
|
||||
};
|
||||
@ -30,13 +40,15 @@ export default (state = DEFAULT_STATE, action: Action): ResultState => {
|
||||
case ActionType.ChangeOutput:
|
||||
return {
|
||||
...state,
|
||||
output: action.payload
|
||||
output: action.output,
|
||||
command: action.command
|
||||
};
|
||||
case ActionType.ChangeContract:
|
||||
return {
|
||||
...state,
|
||||
output: DEFAULT_STATE.output,
|
||||
contract: action.payload
|
||||
contract: action.contract,
|
||||
command: action.command
|
||||
};
|
||||
}
|
||||
return state;
|
||||
|
Loading…
Reference in New Issue
Block a user