Merge branch 'improving-syntax-selection-ui' into 'dev'
Improving syntax selection UI See merge request ligolang/ligo!445
This commit is contained in:
commit
bbe7a29881
@ -1,5 +1,5 @@
|
|||||||
(*_*
|
(*_*
|
||||||
name: Cameligo Contract
|
name: CameLIGO Contract
|
||||||
language: cameligo
|
language: cameligo
|
||||||
compile:
|
compile:
|
||||||
entrypoint: main
|
entrypoint: main
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
(*_*
|
(*_*
|
||||||
name: Pascaligo Contract
|
name: PascaLIGO Contract
|
||||||
language: pascaligo
|
language: pascaligo
|
||||||
compile:
|
compile:
|
||||||
entrypoint: main
|
entrypoint: main
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
(*_*
|
(*_*
|
||||||
name: Reasonligo Contract
|
name: ReasonLIGO Contract
|
||||||
language: reasonligo
|
language: reasonligo
|
||||||
compile:
|
compile:
|
||||||
entrypoint: main
|
entrypoint: main
|
||||||
|
@ -1,84 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
|
||||||
<svg
|
|
||||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
|
||||||
xmlns:cc="http://creativecommons.org/ns#"
|
|
||||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
|
||||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
|
||||||
sodipodi:docname="ligo_run.svg"
|
|
||||||
id="svg4550"
|
|
||||||
version="1.1"
|
|
||||||
viewBox="0 0 193.35434 193.35434"
|
|
||||||
height="193.35434"
|
|
||||||
width="193.35434"
|
|
||||||
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"
|
|
||||||
style="fill:none">
|
|
||||||
<metadata
|
|
||||||
id="metadata4554">
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work
|
|
||||||
rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type
|
|
||||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
|
||||||
<dc:title></dc:title>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<sodipodi:namedview
|
|
||||||
pagecolor="#ffffff"
|
|
||||||
bordercolor="#666666"
|
|
||||||
borderopacity="1"
|
|
||||||
objecttolerance="10"
|
|
||||||
gridtolerance="10"
|
|
||||||
guidetolerance="10"
|
|
||||||
inkscape:pageopacity="0"
|
|
||||||
inkscape:pageshadow="2"
|
|
||||||
inkscape:window-width="2560"
|
|
||||||
inkscape:window-height="1400"
|
|
||||||
id="namedview4552"
|
|
||||||
showgrid="false"
|
|
||||||
inkscape:zoom="1.9624573"
|
|
||||||
inkscape:cx="24.54412"
|
|
||||||
inkscape:cy="104.17717"
|
|
||||||
inkscape:window-x="-12"
|
|
||||||
inkscape:window-y="-12"
|
|
||||||
inkscape:window-maximized="1"
|
|
||||||
inkscape:current-layer="svg4550"
|
|
||||||
fit-margin-top="0"
|
|
||||||
fit-margin-left="0"
|
|
||||||
fit-margin-right="0"
|
|
||||||
fit-margin-bottom="0" />
|
|
||||||
<circle
|
|
||||||
cx="96.67717"
|
|
||||||
cy="96.67717"
|
|
||||||
r="74"
|
|
||||||
id="circle4541"
|
|
||||||
style="stroke:url(#paint0_linear);stroke-width:45.35433197;stroke-miterlimit:4;stroke-dasharray:none" />
|
|
||||||
<defs
|
|
||||||
id="defs4548">
|
|
||||||
<linearGradient
|
|
||||||
id="paint0_linear"
|
|
||||||
x1="100"
|
|
||||||
y1="54"
|
|
||||||
x2="100"
|
|
||||||
y2="254"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
gradientTransform="translate(-3.322834,-57.322834)">
|
|
||||||
<stop
|
|
||||||
stop-color="#3AA0FF"
|
|
||||||
id="stop4543" />
|
|
||||||
<stop
|
|
||||||
offset="1"
|
|
||||||
stop-color="#0072DC"
|
|
||||||
id="stop4545" />
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<path
|
|
||||||
d="M 137.61977,80.627036 58.899178,68.296666 88.24752,141.00143 137.6208,80.624736 Z"
|
|
||||||
id="path4537"
|
|
||||||
inkscape:connector-curvature="0"
|
|
||||||
style="fill:#fc683a;stroke-width:2.53620434" />
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.4 KiB |
121
tools/webide/packages/client/src/components/editable-title.tsx
Normal file
121
tools/webide/packages/client/src/components/editable-title.tsx
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons';
|
||||||
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
||||||
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
|
import styled, { css } from 'styled-components';
|
||||||
|
|
||||||
|
import { Tooltip } from './tooltip';
|
||||||
|
|
||||||
|
const Container = styled.div`
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Input = styled.input<{ visible?: boolean }>`
|
||||||
|
position: absolute;
|
||||||
|
border-radius: var(--border_radius);
|
||||||
|
opacity: 0;
|
||||||
|
height: 2em;
|
||||||
|
width: 0;
|
||||||
|
border: none;
|
||||||
|
font-size: 1em;
|
||||||
|
|
||||||
|
outline: none;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
|
${props =>
|
||||||
|
props.visible &&
|
||||||
|
css`
|
||||||
|
padding-left: 0.5em;
|
||||||
|
opacity: 1;
|
||||||
|
width: 15em;
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const Label = styled.div<{ visible?: boolean }>`
|
||||||
|
color: var(--blue);
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
${props =>
|
||||||
|
props.visible &&
|
||||||
|
css`
|
||||||
|
opacity: 1;
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const PencilIcon = ({ ...props }) => (
|
||||||
|
<FontAwesomeIcon {...props} icon={faPencilAlt} size="sm"></FontAwesomeIcon>
|
||||||
|
);
|
||||||
|
|
||||||
|
const Pencil = styled(PencilIcon)<{ visible: boolean }>`
|
||||||
|
margin-left: 10px;
|
||||||
|
cursor: pointer;
|
||||||
|
color: var(--label_foreground);
|
||||||
|
opacity: 0;
|
||||||
|
|
||||||
|
:hover {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
${props =>
|
||||||
|
props.visible &&
|
||||||
|
css`
|
||||||
|
opacity: 0.5;
|
||||||
|
`}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const EditableTitleComponent = (props: {
|
||||||
|
id?: string;
|
||||||
|
title: string;
|
||||||
|
onChanged?: (value: string) => void;
|
||||||
|
className?: string;
|
||||||
|
}) => {
|
||||||
|
const [newTitle, setNewTitle] = useState(props.title);
|
||||||
|
const [showInput, setShowInput] = useState(false);
|
||||||
|
const inputEl = useRef<HTMLInputElement>(null);
|
||||||
|
|
||||||
|
const notifyChanged = () => {
|
||||||
|
if (props.onChanged && props.title !== newTitle) {
|
||||||
|
props.onChanged(newTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
setShowInput(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
setNewTitle(props.title);
|
||||||
|
}, [props.title]);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Container id={props.id} className={props.className}>
|
||||||
|
<Input
|
||||||
|
ref={inputEl}
|
||||||
|
visible={showInput}
|
||||||
|
value={newTitle}
|
||||||
|
onChange={event => setNewTitle(event.target.value)}
|
||||||
|
onBlur={_ => notifyChanged()}
|
||||||
|
onKeyDown={event => {
|
||||||
|
if (event.key === 'Enter') {
|
||||||
|
notifyChanged();
|
||||||
|
} else if (event.key === 'Escape') {
|
||||||
|
setNewTitle(props.title);
|
||||||
|
setShowInput(false);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
></Input>
|
||||||
|
<Label visible={!showInput}>{newTitle ? newTitle : 'Untitled'}</Label>
|
||||||
|
<div>
|
||||||
|
<Pencil
|
||||||
|
visible={!showInput}
|
||||||
|
onClick={() => {
|
||||||
|
if (inputEl.current) {
|
||||||
|
inputEl.current.select();
|
||||||
|
inputEl.current.setSelectionRange(0, 99999);
|
||||||
|
setShowInput(true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
></Pencil>
|
||||||
|
<Tooltip>Rename</Tooltip>
|
||||||
|
</div>
|
||||||
|
</Container>
|
||||||
|
);
|
||||||
|
};
|
@ -1,6 +1,10 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
|
import { useDispatch, useSelector } from 'react-redux';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
|
import { AppState } from '../redux/app';
|
||||||
|
import { ChangeTitleAction } from '../redux/editor';
|
||||||
|
import { EditableTitleComponent } from './editable-title';
|
||||||
import { MonacoComponent } from './monaco';
|
import { MonacoComponent } from './monaco';
|
||||||
import { ShareComponent } from './share';
|
import { ShareComponent } from './share';
|
||||||
import { SyntaxSelectComponent } from './syntax-select';
|
import { SyntaxSelectComponent } from './syntax-select';
|
||||||
@ -12,20 +16,44 @@ const Container = styled.div`
|
|||||||
const Header = styled.div`
|
const Header = styled.div`
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
min-height: 2.5em;
|
min-height: 2.5em;
|
||||||
border-bottom: 5px solid var(--blue_trans1);
|
border-bottom: 5px solid var(--blue_trans1);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const Subheader = styled.div`
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
background: var(--blue_trans1);
|
||||||
|
border: 5px solid rgba(0, 0, 0, 0);
|
||||||
|
border-top: none;
|
||||||
|
padding: 0 10px;
|
||||||
|
`;
|
||||||
|
|
||||||
export const EditorComponent = () => {
|
export const EditorComponent = () => {
|
||||||
|
const dispatch = useDispatch();
|
||||||
|
const title = useSelector<AppState, string>(state => state.editor.title);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Header>
|
<Header>
|
||||||
<SyntaxSelectComponent></SyntaxSelectComponent>
|
|
||||||
<ShareComponent></ShareComponent>
|
<ShareComponent></ShareComponent>
|
||||||
</Header>
|
</Header>
|
||||||
|
<Subheader>
|
||||||
|
<EditableTitleComponent
|
||||||
|
id="editor-title"
|
||||||
|
title={title}
|
||||||
|
onChanged={value => {
|
||||||
|
dispatch({ ...new ChangeTitleAction(value) });
|
||||||
|
}}
|
||||||
|
></EditableTitleComponent>
|
||||||
|
<SyntaxSelectComponent></SyntaxSelectComponent>
|
||||||
|
</Subheader>
|
||||||
<MonacoComponent></MonacoComponent>
|
<MonacoComponent></MonacoComponent>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
@ -3,12 +3,13 @@ import { useDispatch, useSelector } from 'react-redux';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import { AppState } from '../redux/app';
|
import { AppState } from '../redux/app';
|
||||||
|
import { ChangeDirtyAction, EditorState } from '../redux/editor';
|
||||||
import { ChangeSelectedAction, ExamplesState } from '../redux/examples';
|
import { ChangeSelectedAction, ExamplesState } from '../redux/examples';
|
||||||
import { getExample } from '../services/api';
|
import { getExample } from '../services/api';
|
||||||
|
|
||||||
const bgColor = 'transparent';
|
const bgColor = 'transparent';
|
||||||
const borderSize = '5px';
|
const borderSize = '5px';
|
||||||
const verticalPadding = '0.8em';
|
const verticalPadding = '0.6em';
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
flex: 0.5;
|
flex: 0.5;
|
||||||
@ -16,7 +17,7 @@ const Container = styled.div`
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const MenuItem = styled.div<{ selected: boolean }>`
|
const MenuItem = styled.div<{ selected?: boolean }>`
|
||||||
padding: ${verticalPadding} 0 ${verticalPadding} 1em;
|
padding: ${verticalPadding} 0 ${verticalPadding} 1em;
|
||||||
height: 1.5em;
|
height: 1.5em;
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -27,25 +28,12 @@ const MenuItem = styled.div<{ selected: boolean }>`
|
|||||||
border-left: ${`${borderSize} solid ${bgColor}`};
|
border-left: ${`${borderSize} solid ${bgColor}`};
|
||||||
border-left-color: ${props => (props.selected ? 'var(--blue)' : bgColor)};
|
border-left-color: ${props => (props.selected ? 'var(--blue)' : bgColor)};
|
||||||
|
|
||||||
:first-child {
|
|
||||||
margin-top: ${props => (props.selected ? '0' : `-${borderSize}`)};
|
|
||||||
}
|
|
||||||
|
|
||||||
:hover {
|
:hover {
|
||||||
background-color: ${props =>
|
background-color: ${props =>
|
||||||
props.selected ? 'var(--blue_trans1)' : 'var(--blue_trans2)'};
|
props.selected ? 'var(--blue_trans1)' : 'var(--blue_trans2)'};
|
||||||
border-left: ${`${borderSize} solid ${bgColor}`};
|
border-left: ${`${borderSize} solid ${bgColor}`};
|
||||||
border-left-color: ${props =>
|
border-left-color: ${props =>
|
||||||
props.selected ? 'var(--blue)' : 'transparent'};
|
props.selected ? 'var(--blue)' : 'transparent'};
|
||||||
:first-child {
|
|
||||||
margin-top: ${props => (props.selected ? '0' : `-${borderSize}`)};
|
|
||||||
padding-top: ${props =>
|
|
||||||
props.selected
|
|
||||||
? `${verticalPadding}`
|
|
||||||
: `calc(${verticalPadding} - ${borderSize})`};
|
|
||||||
border-top: ${props =>
|
|
||||||
props.selected ? '' : `${borderSize} solid var(--blue_opaque1)`};
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -57,44 +45,45 @@ const MenuContainer = styled.div`
|
|||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Header = styled.div<{ firstChildSelected: boolean }>`
|
const Header = styled.div`
|
||||||
border-bottom: ${props =>
|
|
||||||
props.firstChildSelected ? '' : '5px solid var(--blue_trans1)'};
|
|
||||||
min-height: 2.5em;
|
min-height: 2.5em;
|
||||||
padding: 0 10px;
|
padding: 0 10px;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
font-weight: 600;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Examples = () => {
|
export const Examples = () => {
|
||||||
const examples = useSelector<AppState, ExamplesState['list']>(
|
const examples = useSelector<AppState, ExamplesState['list']>(
|
||||||
(state: AppState) => state.examples.list
|
(state: AppState) => state.examples.list
|
||||||
);
|
);
|
||||||
const selectedExample = useSelector<AppState, ExamplesState['selected']>(
|
const editorDirty = useSelector<AppState, EditorState['dirty']>(
|
||||||
(state: AppState) => state.examples.selected
|
(state: AppState) => state.editor.dirty
|
||||||
);
|
);
|
||||||
|
|
||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Container>
|
<Container>
|
||||||
<Header
|
<Header>Examples</Header>
|
||||||
firstChildSelected={
|
|
||||||
!!selectedExample && examples[0].id === selectedExample.id
|
|
||||||
}
|
|
||||||
>
|
|
||||||
<span>Examples</span>
|
|
||||||
</Header>
|
|
||||||
<MenuContainer>
|
<MenuContainer>
|
||||||
{examples.map(example => {
|
{examples.map(example => {
|
||||||
return (
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
id={example.id}
|
id={example.id}
|
||||||
key={example.id}
|
key={example.id}
|
||||||
selected={!!selectedExample && example.id === selectedExample.id}
|
|
||||||
onClick={async () => {
|
onClick={async () => {
|
||||||
const response = await getExample(example.id);
|
const response = await getExample(example.id);
|
||||||
|
|
||||||
dispatch({ ...new ChangeSelectedAction(response) });
|
if (
|
||||||
|
!editorDirty ||
|
||||||
|
window.confirm(
|
||||||
|
'Are you sure you want to navigate away? Data you have entered will be lost.\n\nPress OK to continue or Cancel to stay on the current page.\n\n'
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
dispatch({ ...new ChangeSelectedAction(response) });
|
||||||
|
dispatch({ ...new ChangeDirtyAction(false) });
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{example.name}
|
{example.name}
|
||||||
|
@ -6,9 +6,9 @@ const Container = styled.div`
|
|||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
||||||
padding: 0.5em 1em;
|
padding: 0.2em 1em;
|
||||||
font-family: 'DM Sans', 'Open Sans', sans-serif;
|
font-family: 'DM Sans', 'Open Sans', sans-serif;
|
||||||
box-shadow: 0px 2px 3px 0px rgba(0, 0, 0, 0.3);
|
box-shadow: 0px 1px 1px 0px rgba(0, 0, 0, 0.3);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
const Group = styled.div`
|
const Group = styled.div`
|
||||||
|
@ -12,12 +12,12 @@ export const HGroup = styled.div`
|
|||||||
|
|
||||||
export const Label = styled.label`
|
export const Label = styled.label`
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
color: rgba(153, 153, 153, 1);
|
color: var(--label_foreground);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export const Input = styled.input`
|
export const Input = styled.input`
|
||||||
margin: 0.3em 0 0.7em 0;
|
margin: 0.3em 0 0.7em 0;
|
||||||
background-color: #eff7ff;
|
background-color: var(--input_background);
|
||||||
border-style: none;
|
border-style: none;
|
||||||
border-bottom: 5px solid #e1f1ff;
|
border-bottom: 5px solid #e1f1ff;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
@ -33,7 +33,7 @@ export const Input = styled.input`
|
|||||||
export const Textarea = styled.textarea`
|
export const Textarea = styled.textarea`
|
||||||
resize: vertical;
|
resize: vertical;
|
||||||
margin: 0.3em 0 0.7em 0;
|
margin: 0.3em 0 0.7em 0;
|
||||||
background-color: #eff7ff;
|
background-color: var(--input_background);
|
||||||
border-style: none;
|
border-style: none;
|
||||||
border-bottom: 5px solid #e1f1ff;
|
border-bottom: 5px solid #e1f1ff;
|
||||||
padding: 0.5em;
|
padding: 0.5em;
|
||||||
|
@ -4,7 +4,8 @@ import { useDispatch, useStore } from 'react-redux';
|
|||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
import { AppState } from '../redux/app';
|
import { AppState } from '../redux/app';
|
||||||
import { ChangeCodeAction } from '../redux/editor';
|
import { ChangeCodeAction, ChangeDirtyAction } from '../redux/editor';
|
||||||
|
import { ClearSelectedAction } from '../redux/examples';
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
height: var(--content_height);
|
height: var(--content_height);
|
||||||
@ -53,8 +54,14 @@ export const MonacoComponent = () => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let shouldDispatchCodeChangedAction = true;
|
||||||
|
|
||||||
const { dispose } = editor.onDidChangeModelContent(() => {
|
const { dispose } = editor.onDidChangeModelContent(() => {
|
||||||
dispatch({ ...new ChangeCodeAction(editor.getValue()) });
|
if (shouldDispatchCodeChangedAction) {
|
||||||
|
dispatch({ ...new ChangeCodeAction(editor.getValue()) });
|
||||||
|
dispatch({ ...new ChangeDirtyAction(true) });
|
||||||
|
dispatch({ ...new ClearSelectedAction() });
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
cleanupFunc.push(dispose);
|
cleanupFunc.push(dispose);
|
||||||
@ -64,11 +71,13 @@ export const MonacoComponent = () => {
|
|||||||
const { editor: editorState }: AppState = store.getState();
|
const { editor: editorState }: AppState = store.getState();
|
||||||
|
|
||||||
if (editorState.code !== editor.getValue()) {
|
if (editorState.code !== editor.getValue()) {
|
||||||
|
shouldDispatchCodeChangedAction = false;
|
||||||
editor.setValue(editorState.code);
|
editor.setValue(editorState.code);
|
||||||
|
shouldDispatchCodeChangedAction = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (editorState.language !== model.getModeId()) {
|
if (editorState.language !== model.getModeId()) {
|
||||||
if (editorState.language === 'reasonligo') {
|
if (editorState.language === 'reasonligo') {
|
||||||
monaco.editor.setModelLanguage(model, 'javascript');
|
monaco.editor.setModelLanguage(model, 'javascript');
|
||||||
} else {
|
} else {
|
||||||
monaco.editor.setModelLanguage(model, editorState.language);
|
monaco.editor.setModelLanguage(model, editorState.language);
|
||||||
|
@ -12,7 +12,7 @@ import { Tooltip } from './tooltip';
|
|||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: flex-end;
|
justify-content: flex-start;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
`;
|
`;
|
||||||
|
|
||||||
@ -81,9 +81,9 @@ const Input = styled.input<{ visible?: boolean }>`
|
|||||||
opacity: 0;
|
opacity: 0;
|
||||||
height: 2em;
|
height: 2em;
|
||||||
width: 2em;
|
width: 2em;
|
||||||
transform: translateX(-0.3em);
|
transform: translateX(0.3em);
|
||||||
border: none;
|
border: none;
|
||||||
padding: 0 1em;
|
padding-left: 2em;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
color: white;
|
color: white;
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ import styled, { css } from 'styled-components';
|
|||||||
import { AppState } from '../redux/app';
|
import { AppState } from '../redux/app';
|
||||||
import { ChangeLanguageAction, EditorState } from '../redux/editor';
|
import { ChangeLanguageAction, EditorState } from '../redux/editor';
|
||||||
import { Language } from '../redux/types';
|
import { Language } from '../redux/types';
|
||||||
|
import { Tooltip } from './tooltip';
|
||||||
|
|
||||||
const Container = styled.div`
|
const Container = styled.div`
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -22,14 +23,19 @@ const Header = styled.div`
|
|||||||
|
|
||||||
flex: 1;
|
flex: 1;
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
|
||||||
justify-content: space-between;
|
|
||||||
height: 2em;
|
height: 2em;
|
||||||
padding: 0 0.5em;
|
padding: 0 0.5em;
|
||||||
|
|
||||||
border: 1px solid var(--blue_trans1);
|
border: 1px solid var(--blue_trans1);
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
const Label = styled.div`
|
||||||
|
flex: 1;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
`;
|
||||||
|
|
||||||
const ArrowIcon = ({ rotate, ...props }: { rotate: boolean }) => (
|
const ArrowIcon = ({ rotate, ...props }: { rotate: boolean }) => (
|
||||||
<FontAwesomeIcon {...props} icon={faCaretDown} size="lg"></FontAwesomeIcon>
|
<FontAwesomeIcon {...props} icon={faCaretDown} size="lg"></FontAwesomeIcon>
|
||||||
);
|
);
|
||||||
@ -140,8 +146,11 @@ export const SyntaxSelectComponent = () => {
|
|||||||
</List>
|
</List>
|
||||||
</OutsideClickHandler>
|
</OutsideClickHandler>
|
||||||
<Header id="syntax-select" onClick={() => open(true)}>
|
<Header id="syntax-select" onClick={() => open(true)}>
|
||||||
<span>{OPTIONS[language]}</span>
|
<Label>
|
||||||
<Arrow rotate={opened}></Arrow>
|
{OPTIONS[language]}
|
||||||
|
<Arrow rotate={opened}></Arrow>
|
||||||
|
</Label>
|
||||||
|
<Tooltip>Select syntax</Tooltip>
|
||||||
</Header>
|
</Header>
|
||||||
</Container>
|
</Container>
|
||||||
);
|
);
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import React, { createElement, useEffect, useRef, useState } from 'react';
|
import React, { createElement, useCallback, useEffect, useRef, useState } from 'react';
|
||||||
import { render } from 'react-dom';
|
import { render } from 'react-dom';
|
||||||
import styled from 'styled-components';
|
import styled from 'styled-components';
|
||||||
|
|
||||||
@ -64,19 +64,22 @@ export const Tooltip = (props: { position?: Position; children: any }) => {
|
|||||||
const ref = useRef<HTMLDivElement>(null);
|
const ref = useRef<HTMLDivElement>(null);
|
||||||
const [isTooltipVisible, setTooltipVisible] = useState(false);
|
const [isTooltipVisible, setTooltipVisible] = useState(false);
|
||||||
|
|
||||||
const renderTooltip = (visible: boolean, triggerRect: ClientRect) => {
|
const renderTooltip = useCallback(
|
||||||
const tooltip = createElement(
|
(visible: boolean, triggerRect: ClientRect) => {
|
||||||
StyledTooltip,
|
const tooltip = createElement(
|
||||||
{
|
StyledTooltip,
|
||||||
visible,
|
{
|
||||||
x: calcX(triggerRect, props.position),
|
visible,
|
||||||
y: calcY(triggerRect, props.position)
|
x: calcX(triggerRect, props.position),
|
||||||
},
|
y: calcY(triggerRect, props.position)
|
||||||
props.children
|
},
|
||||||
);
|
props.children
|
||||||
|
);
|
||||||
|
|
||||||
render(tooltip, document.getElementById(TOOLTIP_CONTAINER_ID));
|
render(tooltip, document.getElementById(TOOLTIP_CONTAINER_ID));
|
||||||
};
|
},
|
||||||
|
[props.position, props.children]
|
||||||
|
);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (ref.current) {
|
if (ref.current) {
|
||||||
@ -98,7 +101,7 @@ export const Tooltip = (props: { position?: Position; children: any }) => {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
}, [isTooltipVisible, renderTooltip]);
|
||||||
|
|
||||||
return <div ref={ref}></div>;
|
return <div ref={ref}></div>;
|
||||||
};
|
};
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
--blue_opaque1: #dbeaff;
|
--blue_opaque1: #dbeaff;
|
||||||
--blue_trans2: rgba(14, 116, 255, 0.08); /* #eff7ff; */
|
--blue_trans2: rgba(14, 116, 255, 0.08); /* #eff7ff; */
|
||||||
|
|
||||||
|
--input_background: #eff7ff;
|
||||||
|
|
||||||
--grey: #888;
|
--grey: #888;
|
||||||
|
|
||||||
--box-shadow: 1px 3px 10px 0px rgba(153, 153, 153, 0.4); /* or #999999 */
|
--box-shadow: 1px 3px 10px 0px rgba(153, 153, 153, 0.4); /* or #999999 */
|
||||||
@ -46,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: 80vh;
|
||||||
|
|
||||||
--tooltip_foreground: white;
|
--tooltip_foreground: white;
|
||||||
--tooltip_background: rgba(0, 0, 0, 0.75) /*#404040*/;
|
--tooltip_background: rgba(0, 0, 0, 0.75) /*#404040*/;
|
||||||
|
@ -3,12 +3,16 @@ import { Language } from './types';
|
|||||||
|
|
||||||
export enum ActionType {
|
export enum ActionType {
|
||||||
ChangeLanguage = 'editor-change-language',
|
ChangeLanguage = 'editor-change-language',
|
||||||
ChangeCode = 'editor-change-code'
|
ChangeCode = 'editor-change-code',
|
||||||
|
ChangeDirty = 'editor-change-dirty',
|
||||||
|
ChangeTitle = 'editor-change-title'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface EditorState {
|
export interface EditorState {
|
||||||
language: Language;
|
language: Language;
|
||||||
code: string;
|
code: string;
|
||||||
|
title: string;
|
||||||
|
dirty: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class ChangeLanguageAction {
|
export class ChangeLanguageAction {
|
||||||
@ -21,14 +25,28 @@ export class ChangeCodeAction {
|
|||||||
constructor(public payload: EditorState['code']) {}
|
constructor(public payload: EditorState['code']) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class ChangeDirtyAction {
|
||||||
|
public readonly type = ActionType.ChangeDirty;
|
||||||
|
constructor(public payload: EditorState['dirty']) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
export class ChangeTitleAction {
|
||||||
|
public readonly type = ActionType.ChangeTitle;
|
||||||
|
constructor(public payload: EditorState['title']) {}
|
||||||
|
}
|
||||||
|
|
||||||
type Action =
|
type Action =
|
||||||
| ChangeCodeAction
|
| ChangeCodeAction
|
||||||
| ChangeLanguageAction
|
| ChangeLanguageAction
|
||||||
|
| ChangeDirtyAction
|
||||||
|
| ChangeTitleAction
|
||||||
| ChangeSelectedExampleAction;
|
| ChangeSelectedExampleAction;
|
||||||
|
|
||||||
const DEFAULT_STATE: EditorState = {
|
const DEFAULT_STATE: EditorState = {
|
||||||
language: Language.CameLigo,
|
language: Language.CameLigo,
|
||||||
code: ''
|
code: '',
|
||||||
|
title: '',
|
||||||
|
dirty: false
|
||||||
};
|
};
|
||||||
|
|
||||||
export default (state = DEFAULT_STATE, action: Action): EditorState => {
|
export default (state = DEFAULT_STATE, action: Action): EditorState => {
|
||||||
@ -36,7 +54,9 @@ export default (state = DEFAULT_STATE, action: Action): EditorState => {
|
|||||||
case ExamplesActionType.ChangeSelected:
|
case ExamplesActionType.ChangeSelected:
|
||||||
return {
|
return {
|
||||||
...state,
|
...state,
|
||||||
...(!action.payload ? DEFAULT_STATE : action.payload.editor)
|
...(!action.payload
|
||||||
|
? DEFAULT_STATE
|
||||||
|
: { ...action.payload.editor, title: action.payload.name })
|
||||||
};
|
};
|
||||||
case ActionType.ChangeLanguage:
|
case ActionType.ChangeLanguage:
|
||||||
return {
|
return {
|
||||||
@ -48,6 +68,17 @@ export default (state = DEFAULT_STATE, action: Action): EditorState => {
|
|||||||
...state,
|
...state,
|
||||||
code: action.payload
|
code: action.payload
|
||||||
};
|
};
|
||||||
|
case ActionType.ChangeDirty:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
dirty: action.payload
|
||||||
|
};
|
||||||
|
case ActionType.ChangeTitle:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
title: action.payload
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
return state;
|
|
||||||
};
|
};
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { ExampleState } from './example';
|
import { ExampleState } from './example';
|
||||||
|
|
||||||
export enum ActionType {
|
export enum ActionType {
|
||||||
ChangeSelected = 'examples-change-selected'
|
ChangeSelected = 'examples-change-selected',
|
||||||
|
ClearSelected = 'examples-clear-selected'
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ExampleItem {
|
export interface ExampleItem {
|
||||||
@ -19,13 +20,25 @@ export class ChangeSelectedAction {
|
|||||||
constructor(public payload: ExamplesState['selected']) {}
|
constructor(public payload: ExamplesState['selected']) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Action = ChangeSelectedAction;
|
export class ClearSelectedAction {
|
||||||
|
public readonly type = ActionType.ClearSelected;
|
||||||
|
}
|
||||||
|
|
||||||
|
type Action = ChangeSelectedAction | ClearSelectedAction;
|
||||||
|
|
||||||
export const DEFAULT_STATE: ExamplesState = {
|
export const DEFAULT_STATE: ExamplesState = {
|
||||||
selected: null,
|
selected: null,
|
||||||
list: []
|
list: []
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'development') {
|
||||||
|
DEFAULT_STATE.list = [
|
||||||
|
{ id: 'MzkMQ1oiVHJqbcfUuVFKTw', name: 'CameLIGO Contract' },
|
||||||
|
{ id: 'FEb62HL7onjg1424eUsGSg', name: 'PascaLIGO Contract' },
|
||||||
|
{ id: 'JPhSOehj_2MFwRIlml0ymQ', name: 'ReasonLIGO Contract' }
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
export default (state = DEFAULT_STATE, action: Action): ExamplesState => {
|
export default (state = DEFAULT_STATE, action: Action): ExamplesState => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
case ActionType.ChangeSelected:
|
case ActionType.ChangeSelected:
|
||||||
@ -33,6 +46,12 @@ export default (state = DEFAULT_STATE, action: Action): ExamplesState => {
|
|||||||
...state,
|
...state,
|
||||||
selected: action.payload
|
selected: action.payload
|
||||||
};
|
};
|
||||||
|
case ActionType.ClearSelected:
|
||||||
|
return {
|
||||||
|
...state,
|
||||||
|
selected: null
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
return state;
|
||||||
}
|
}
|
||||||
return state;
|
|
||||||
};
|
};
|
||||||
|
@ -15,7 +15,7 @@ import {
|
|||||||
ChangeParametersAction as ChangeDryRunParametersAction,
|
ChangeParametersAction as ChangeDryRunParametersAction,
|
||||||
ChangeStorageAction as ChangeDryRunStorageAction,
|
ChangeStorageAction as ChangeDryRunStorageAction,
|
||||||
} from './dry-run';
|
} from './dry-run';
|
||||||
import { ActionType as EditorActionType, ChangeCodeAction, ChangeLanguageAction } from './editor';
|
import { ActionType as EditorActionType, ChangeCodeAction, ChangeLanguageAction, ChangeTitleAction } from './editor';
|
||||||
import {
|
import {
|
||||||
ActionType as EvaluateFunctionActionType,
|
ActionType as EvaluateFunctionActionType,
|
||||||
ChangeEntrypointAction as ChangeEvaluateFunctionEntrypointAction,
|
ChangeEntrypointAction as ChangeEvaluateFunctionEntrypointAction,
|
||||||
@ -25,6 +25,7 @@ import {
|
|||||||
ActionType as EvaluateValueActionType,
|
ActionType as EvaluateValueActionType,
|
||||||
ChangeEntrypointAction as ChangeEvaluateValueEntrypointAction,
|
ChangeEntrypointAction as ChangeEvaluateValueEntrypointAction,
|
||||||
} from './evaluate-value';
|
} from './evaluate-value';
|
||||||
|
import { ActionType as ExamplesActionType, ChangeSelectedAction as ChangeSelectedExampleAction } from './examples';
|
||||||
|
|
||||||
export enum ActionType {
|
export enum ActionType {
|
||||||
ChangeShareLink = 'share-change-link'
|
ChangeShareLink = 'share-change-link'
|
||||||
@ -41,6 +42,7 @@ export class ChangeShareLinkAction {
|
|||||||
|
|
||||||
type Action =
|
type Action =
|
||||||
| ChangeShareLinkAction
|
| ChangeShareLinkAction
|
||||||
|
| ChangeTitleAction
|
||||||
| ChangeCodeAction
|
| ChangeCodeAction
|
||||||
| ChangeLanguageAction
|
| ChangeLanguageAction
|
||||||
| ChangeCompileEntrypointAction
|
| ChangeCompileEntrypointAction
|
||||||
@ -53,7 +55,8 @@ type Action =
|
|||||||
| ChangeDryRunStorageAction
|
| ChangeDryRunStorageAction
|
||||||
| ChangeEvaluateFunctionEntrypointAction
|
| ChangeEvaluateFunctionEntrypointAction
|
||||||
| ChangeEvaluateFunctionParametersAction
|
| ChangeEvaluateFunctionParametersAction
|
||||||
| ChangeEvaluateValueEntrypointAction;
|
| ChangeEvaluateValueEntrypointAction
|
||||||
|
| ChangeSelectedExampleAction;
|
||||||
|
|
||||||
const DEFAULT_STATE: ShareState = {
|
const DEFAULT_STATE: ShareState = {
|
||||||
link: ''
|
link: ''
|
||||||
@ -61,6 +64,8 @@ const DEFAULT_STATE: ShareState = {
|
|||||||
|
|
||||||
export default (state = DEFAULT_STATE, action: Action): ShareState => {
|
export default (state = DEFAULT_STATE, action: Action): ShareState => {
|
||||||
switch (action.type) {
|
switch (action.type) {
|
||||||
|
case EditorActionType.ChangeTitle:
|
||||||
|
case ExamplesActionType.ChangeSelected:
|
||||||
case EditorActionType.ChangeCode:
|
case EditorActionType.ChangeCode:
|
||||||
case EditorActionType.ChangeLanguage:
|
case EditorActionType.ChangeLanguage:
|
||||||
case CompileActionType.ChangeEntrypoint:
|
case CompileActionType.ChangeEntrypoint:
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
const proxy = require('http-proxy-middleware');
|
const proxy = require('http-proxy-middleware');
|
||||||
|
|
||||||
module.exports = function(app) {
|
module.exports = function (app) {
|
||||||
app.use(
|
app.use(
|
||||||
'/api',
|
'/api',
|
||||||
proxy({
|
proxy({
|
||||||
@ -8,4 +8,12 @@ module.exports = function(app) {
|
|||||||
changeOrigin: true
|
changeOrigin: true
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
|
app.use(
|
||||||
|
'/static/examples',
|
||||||
|
proxy({
|
||||||
|
target: 'http://localhost:8080',
|
||||||
|
changeOrigin: true
|
||||||
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
@ -24,7 +24,7 @@ describe('Share', () => {
|
|||||||
await responseCallback;
|
await responseCallback;
|
||||||
|
|
||||||
const actualShareLink = await page.evaluate(getInputValue, 'share-link');
|
const actualShareLink = await page.evaluate(getInputValue, 'share-link');
|
||||||
const expectedShareLink = `${API_HOST}/p/sIpy-2D9ExpCojwuBNw_-g`;
|
const expectedShareLink = `${API_HOST}/p/WxKPBq9-mkZ_kq4cMHXfCQ`;
|
||||||
|
|
||||||
expect(actualShareLink).toEqual(expectedShareLink);
|
expect(actualShareLink).toEqual(expectedShareLink);
|
||||||
done();
|
done();
|
||||||
|
@ -10,6 +10,8 @@ interface ShareBody {
|
|||||||
editor: {
|
editor: {
|
||||||
language: string;
|
language: string;
|
||||||
code: string;
|
code: string;
|
||||||
|
dirty: boolean;
|
||||||
|
title: string;
|
||||||
};
|
};
|
||||||
compile: {
|
compile: {
|
||||||
entrypoint: string;
|
entrypoint: string;
|
||||||
@ -39,7 +41,9 @@ const validateRequest = (body: any): { value: ShareBody; error: any } => {
|
|||||||
editor: joi
|
editor: joi
|
||||||
.object({
|
.object({
|
||||||
language: joi.string().required(),
|
language: joi.string().required(),
|
||||||
code: joi.string().required()
|
code: joi.string().required(),
|
||||||
|
dirty: joi.boolean().optional(),
|
||||||
|
title: joi.string().allow('')
|
||||||
})
|
})
|
||||||
.required(),
|
.required(),
|
||||||
compile: joi.object({
|
compile: joi.object({
|
||||||
|
@ -24,7 +24,9 @@ export async function loadDefaultState(appBundleDirectory: string) {
|
|||||||
deploy: {},
|
deploy: {},
|
||||||
evaluateValue: {},
|
evaluateValue: {},
|
||||||
evaluateFunction: {},
|
evaluateFunction: {},
|
||||||
editor: {},
|
editor: {
|
||||||
|
title: ''
|
||||||
|
},
|
||||||
examples: {
|
examples: {
|
||||||
selected: null,
|
selected: null,
|
||||||
list: examplesList
|
list: examplesList
|
||||||
@ -59,9 +61,9 @@ export async function loadDefaultState(appBundleDirectory: string) {
|
|||||||
};
|
};
|
||||||
defaultState.editor = {
|
defaultState.editor = {
|
||||||
...defaultState.editor,
|
...defaultState.editor,
|
||||||
...defaultExample.editor
|
...defaultExample.editor,
|
||||||
|
title: defaultExample.name
|
||||||
};
|
};
|
||||||
defaultState.examples.selected = defaultExample;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return defaultState;
|
return defaultState;
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
import { SchemaMigrationV1 } from './share-v1';
|
import { SchemaMigrationV2 } from './share-v2';
|
||||||
|
|
||||||
export default new SchemaMigrationV1();
|
export default new SchemaMigrationV2();
|
||||||
|
96
tools/webide/packages/server/src/schemas/share-v2.ts
Normal file
96
tools/webide/packages/server/src/schemas/share-v2.ts
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
import joi from '@hapi/joi';
|
||||||
|
|
||||||
|
import { Migration } from './migration';
|
||||||
|
import { SchemaMigrationV1, SchemaV1 } from './share-v1';
|
||||||
|
|
||||||
|
export type Version = 'v2';
|
||||||
|
|
||||||
|
export interface SchemaV2 {
|
||||||
|
version: Version;
|
||||||
|
state: {
|
||||||
|
editor: {
|
||||||
|
language: string;
|
||||||
|
code: string;
|
||||||
|
dirty: boolean;
|
||||||
|
title: string;
|
||||||
|
};
|
||||||
|
compile: {
|
||||||
|
entrypoint: string;
|
||||||
|
};
|
||||||
|
dryRun: {
|
||||||
|
entrypoint: string;
|
||||||
|
parameters: string;
|
||||||
|
storage: string;
|
||||||
|
};
|
||||||
|
deploy: {
|
||||||
|
entrypoint: string;
|
||||||
|
storage: string;
|
||||||
|
useTezBridge?: boolean;
|
||||||
|
};
|
||||||
|
evaluateValue: {
|
||||||
|
entrypoint: string;
|
||||||
|
};
|
||||||
|
evaluateFunction: {
|
||||||
|
entrypoint: string;
|
||||||
|
parameters: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SchemaMigrationV2 extends Migration {
|
||||||
|
readonly VERSION: Version = 'v2';
|
||||||
|
|
||||||
|
protected readonly schema = joi.object({
|
||||||
|
version: joi
|
||||||
|
.string()
|
||||||
|
.required()
|
||||||
|
.allow(this.VERSION),
|
||||||
|
state: joi.object({
|
||||||
|
editor: joi
|
||||||
|
.object({
|
||||||
|
language: joi.string().required(),
|
||||||
|
code: joi.string().required(),
|
||||||
|
dirty: joi.boolean().optional(),
|
||||||
|
title: joi.string().allow('')
|
||||||
|
})
|
||||||
|
.required(),
|
||||||
|
compile: joi.object({
|
||||||
|
entrypoint: joi.string().allow('')
|
||||||
|
}),
|
||||||
|
dryRun: joi.object({
|
||||||
|
entrypoint: joi.string().allow(''),
|
||||||
|
parameters: joi.any().allow(''),
|
||||||
|
storage: joi.any().allow('')
|
||||||
|
}),
|
||||||
|
deploy: joi.object({
|
||||||
|
entrypoint: joi.string().allow(''),
|
||||||
|
storage: joi.any().allow(''),
|
||||||
|
useTezBridge: joi.boolean().optional()
|
||||||
|
}),
|
||||||
|
evaluateValue: joi.object({
|
||||||
|
entrypoint: joi.string().allow('')
|
||||||
|
}),
|
||||||
|
evaluateFunction: joi.object({
|
||||||
|
entrypoint: joi.string().allow(''),
|
||||||
|
parameters: joi.any().allow('')
|
||||||
|
})
|
||||||
|
})
|
||||||
|
});
|
||||||
|
|
||||||
|
protected readonly previous = new SchemaMigrationV1();
|
||||||
|
|
||||||
|
protected migrate(data: SchemaV1): SchemaV2 {
|
||||||
|
return {
|
||||||
|
...data,
|
||||||
|
version: this.VERSION,
|
||||||
|
state: {
|
||||||
|
...data.state,
|
||||||
|
editor: {
|
||||||
|
...data.state.editor,
|
||||||
|
dirty: false,
|
||||||
|
title: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user