From e90e0d2ce6d459f396126e3d5180a54f663f123a Mon Sep 17 00:00:00 2001 From: Hernan Rajchert Date: Tue, 9 May 2023 13:35:16 -0300 Subject: [PATCH] Fix blockly datetime picker --- .../src/Blockly/Blockly.ts | 23 ++ .../src/Blockly/DateTimeField.js | 213 ----------------- .../src/Blockly/DateTimeField.ts | 225 ++++++++++++++++++ .../src/Blockly/Events.purs | 4 +- .../src/Blockly/Internal.js | 4 +- .../src/Blockly/Internal.ts | 117 ++++----- marlowe-playground-client/tsconfig.json | 4 +- marlowe-playground-server/src/Gist.hs | 1 - 8 files changed, 315 insertions(+), 276 deletions(-) create mode 100644 marlowe-playground-client/src/Blockly/Blockly.ts delete mode 100644 marlowe-playground-client/src/Blockly/DateTimeField.js create mode 100644 marlowe-playground-client/src/Blockly/DateTimeField.ts diff --git a/marlowe-playground-client/src/Blockly/Blockly.ts b/marlowe-playground-client/src/Blockly/Blockly.ts new file mode 100644 index 0000000000..00eb846b74 --- /dev/null +++ b/marlowe-playground-client/src/Blockly/Blockly.ts @@ -0,0 +1,23 @@ +import { BlockBase, BlockCreate, BlockChange } from "blockly/core/events/events"; + +export function createBlocklyInstance_ () { + return import("blockly"); +}; + +export type Blockly = Awaited>; +export type Workspace = InstanceType +export type WorkspaceSvg = InstanceType +export type Block = InstanceType + +export type TZInfo = {tzOffset: number, offsetString: string} + +export function isBlockEvent (event: unknown): event is BlockBase { + return event.hasOwnProperty("blockId"); +} + +export function isBlockCreateEvent (event: unknown): event is BlockCreate { + return event.hasOwnProperty("type") && event["type"] == "create"; +} +export function isBlockChangeEvent (event: unknown): event is BlockChange { + return event.hasOwnProperty("type") && event["type"] == "change"; +} diff --git a/marlowe-playground-client/src/Blockly/DateTimeField.js b/marlowe-playground-client/src/Blockly/DateTimeField.js deleted file mode 100644 index 5ba08071f8..0000000000 --- a/marlowe-playground-client/src/Blockly/DateTimeField.js +++ /dev/null @@ -1,213 +0,0 @@ -// This function is analogue to Component.DateTimeLocalInput.State (parseInput) -// It parses the valueStr using the same Regexp and tries to create a Date -// object assuming that the date is in UTC. Functions utcToLocal/localToUtc -// should be used to adjust the offset. -function parseInput(valueStr) { - const timeRegex = /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?/; - const found = timeRegex.exec(valueStr); - if (found) { - const date = new Date(`${found[0]}Z`); - return { - matchStr: found[0], - unixTime: date.getTime(), // ms from epoch - }; - } - return null; -} - -function localToUtc(tzOffset, unixTimeLocal) { - return unixTimeLocal + tzOffset * 60 * 1000; -} - -function utcToLocal(tzOffset, unixTimeUtc) { - return localToUtc(-tzOffset, unixTimeUtc); -} - -function showNormalizedDateTime(unixTime, trimSeconds) { - const timeRegex = trimSeconds - ? /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/ - : /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?/; - const fullStr = new Date(unixTime).toISOString(); - const found = timeRegex.exec(fullStr); - if (found) return found[0]; - throw "showNormalizedDateTime can normalize a datetime string"; // This should not happen. -} - -// Register a custom DateTime Field to blockly: -// Used as base: -// * https://developers.google.com/blockly/guides/create-custom-blocks/fields/customizing-fields/creating -// * https://github.com/google/blockly-samples/blob/master/plugins/field-date/src/field_date.js -export function registerDateTimeField(Blockly) { - // If the field is already registered, return it. - const RegisteredFieldDateTime = Blockly.registry - ? Blockly.registry.getClass("field", "field_datetime") - : undefined; - - if (RegisteredFieldDateTime) return RegisteredFieldDateTime; - - const FieldDateTime = function ( - value = undefined, - validator = undefined, - tzInfo = undefined - ) { - if (typeof tzInfo === "undefined") { - tzInfo = { - tzOffset: 0, - offsetString: "", - }; - } - this.tzOffset = tzInfo.tzOffset; - this.offsetString = tzInfo.offsetString; - - // The default value for this field is the current date - value = this.doClassValidation_(value); - - FieldDateTime.prototype.DEFAULT_VALUE = this.doClassValidation_( - new Date().getTime() - ); - - FieldDateTime.superClass_.constructor.call(this, value, validator); - - this.onInputWrapper_ = null; - }; - Blockly.utils.object.inherits(FieldDateTime, Blockly.Field); - - FieldDateTime.fromJson = function (options) { - return new FieldDateTime(options["date"], undefined); - }; - - FieldDateTime.prototype.SERIALIZABLE = true; - - FieldDateTime.prototype.CURSOR = "text"; - - FieldDateTime.prototype.doClassValidation_ = function (newValue = undefined) { - if (typeof newValue == "number" || typeof newValue == "bigint") { - return newValue; - } else if (typeof newValue == "string") { - const parsedInt = parseInt(newValue, 10); - if (parsedInt + "" == newValue) { - return parsedInt; - } - } - - return null; - }; - - // The initView is a place in which we can modify how the element shows itself - FieldDateTime.prototype.initView = function () { - const constants = this.getConstants(); - // The picker element is a native HTML DOM input - // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local - this.picker_ = document.createElement("input"); - this.picker_.type = "datetime-local"; - - // We add these styles to avoid the picker element from growing - // when the screen resize - this.picker_.style.height = `${constants.FIELD_TEXT_HEIGHT}px`; - this.picker_.style.position = "absolute"; - this.picker_.style.fontSize = `${constants.FIELD_TEXT_FONTSIZE}px`; - this.picker_.style.boxSizing = "content-box"; - - // This hardcoded number was reached by experimentation, if not set - // the picker will occupy more space than needed. An alternative - // solution would be to create a canvas node with a 2D context, - // create a text element with the expected number of characters - // and calculating the size of that. This is easier. - this.picker_.style.width = "120px"; - - // We convert the UTC unix time to a local diff from epoch - // and convert that to the normalized representation that the - // datetime-local object needs (e.g: "2022-03-18T21:42") - this.picker_.value = showNormalizedDateTime( - utcToLocal(this.tzOffset, this.getValue()), - true - ); - - // In order to show an HTML element in Blockly we need to wrap - // it on an Svg foreignObject - const foreignObject = document.createElementNS( - "http://www.w3.org/2000/svg", - "foreignObject" - ); - foreignObject.appendChild(this.picker_); - this.foreignObject = foreignObject; - // We add the foreignObject to the fields `g` element. - this.fieldGroup_.appendChild(foreignObject); - - // This element is a textual representation of the local offset - // (e.g: "GMT+2") - this.offsetLabel = Blockly.utils.dom.createSvgElement( - Blockly.utils.Svg.TEXT, - { - class: "blocklyText", - }, - this.fieldGroup_ - ); - this.offsetLabel.textContent = this.offsetString; - this.offsetLabel.style.fill = "white"; - this.offsetLabel.style.fontSize = `${constants.FIELD_TEXT_FONTSIZE}pt`; - }; - - FieldDateTime.prototype.updateSize_ = function () { - const constants = this.getConstants(); - let totalWidth = 0; - const padding = 4; - const pickerW = this.picker_.offsetWidth; - const pickerH = constants.FIELD_TEXT_HEIGHT + padding; - - // In order for the input to be displayed, we need to set - // the foreignObject size to have its children dimensions - this.foreignObject.setAttribute("width", pickerW); - this.foreignObject.setAttribute("height", pickerH); - totalWidth += pickerW + padding; - this.offsetLabel.setAttribute("x", pickerW + padding); - - var halfHeight = pickerH / 2; - - this.offsetLabel.setAttribute( - "y", - halfHeight - - constants.FIELD_TEXT_HEIGHT / 2 + - constants.FIELD_TEXT_BASELINE - ); - const offsetLabelWidth = this.offsetLabel.getBBox().width; - - totalWidth += offsetLabelWidth + padding; - - this.size_.width = totalWidth; - this.size_.height = pickerH; - }; - - FieldDateTime.prototype.bindEvents_ = function () { - FieldDateTime.superClass_.bindEvents_.call(this); - const thisField = this; - - // Whenever the native input element changes it value, update - // the field model - this.onInputWrapper_ = Blockly.bindEventWithChecks_( - this.picker_, - "input", - this, - function () { - const parsedValue = parseInput(thisField.picker_.value); - if (parsedValue) { - thisField.setValue( - localToUtc(thisField.tzOffset, parsedValue.unixTime) - ); - } - } - ); - }; - - FieldDateTime.prototype.dispose = function () { - FieldDateTime.superClass_.dispose.call(this); - - if (this.onInputWrapper_) { - Blockly.unbindEvent_(this.onInputWrapper_); - } - }; - - Blockly.fieldRegistry.register("field_datetime", FieldDateTime); - - return FieldDateTime; -} diff --git a/marlowe-playground-client/src/Blockly/DateTimeField.ts b/marlowe-playground-client/src/Blockly/DateTimeField.ts new file mode 100644 index 0000000000..c08a1fdad5 --- /dev/null +++ b/marlowe-playground-client/src/Blockly/DateTimeField.ts @@ -0,0 +1,225 @@ +import { Blockly, TZInfo } from "./Blockly"; +// This function is analogue to Component.DateTimeLocalInput.State (parseInput) +// It parses the valueStr using the same Regexp and tries to create a Date +// object assuming that the date is in UTC. Functions utcToLocal/localToUtc +// should be used to adjust the offset. +function parseInput(valueStr: string) { + const timeRegex = /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?/; + const found = timeRegex.exec(valueStr); + if (found) { + const date = new Date(`${found[0]}Z`); + return { + matchStr: found[0], + unixTime: date.getTime(), // ms from epoch + }; + } + return null; +} + +function localToUtc(tzOffset: number, unixTimeLocal: number) { + return unixTimeLocal + tzOffset * 60 * 1000; +} + +function utcToLocal(tzOffset: number, unixTimeUtc: number) { + return localToUtc(-tzOffset, unixTimeUtc); +} + +function showNormalizedDateTime(unixTime: number, trimSeconds: boolean) { + const timeRegex = trimSeconds + ? /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/ + : /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})(:(\d{2}))?/; + const fullStr = new Date(unixTime).toISOString(); + const found = timeRegex.exec(fullStr); + if (found) return found[0]; + throw "showNormalizedDateTime can normalize a datetime string"; // This should not happen. +} + +function validateFieldDateTimeValue(newValue: number | bigint | string) { + if (typeof newValue == "number" || typeof newValue == "bigint") { + return newValue; + } else if (typeof newValue == "string") { + const parsedInt = parseInt(newValue, 10); + if (parsedInt + "" == newValue) { + return parsedInt; + } + } + + return null; +} + +// I've separated the creation of the class from the registering in Blockly to get the +// proper types. At some point we should try to modify how Blockly gets loaded so we can +// define this class as a top level construct. +function createDateTimeFieldClass(Blockly: Blockly) { + const Field = Blockly.Field; + + class FieldDateTime extends Field { + tzOffset: number; + offsetString: string; + // FIXME + onInputWrapper_: any; + + SERIALIZABLE = true; + CURSOR = "text"; + picker_: HTMLInputElement; + foreignObject: SVGForeignObjectElement; + offsetLabel: SVGTextElement; + + constructor(value: number | bigint | string, validator, tzInfo?: TZInfo) { + super(validateFieldDateTimeValue(value), validator); + if (typeof tzInfo === "undefined") { + tzInfo = { + tzOffset: 0, + offsetString: "", + }; + } + this.tzOffset = tzInfo.tzOffset; + this.offsetString = tzInfo.offsetString; + + // The default value for this field is the current date + FieldDateTime.prototype.DEFAULT_VALUE = validateFieldDateTimeValue( + new Date().getTime() + ); + + this.onInputWrapper_ = null; + } + + static fromJson(options) { + return new FieldDateTime(options["date"], undefined); + } + + initView() { + const constants = this.getConstants(); + // The picker element is a native HTML DOM input + // https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/datetime-local + this.picker_ = document.createElement("input"); + this.picker_.type = "datetime-local"; + + // We add these styles to avoid the picker element from growing + // when the screen resize + this.picker_.style.height = `${constants.FIELD_TEXT_HEIGHT}px`; + this.picker_.style.position = "absolute"; + this.picker_.style.fontSize = `${constants.FIELD_TEXT_FONTSIZE}px`; + this.picker_.style.boxSizing = "content-box"; + + // This hardcoded number was reached by experimentation, if not set + // the picker will occupy more space than needed. An alternative + // solution would be to create a canvas node with a 2D context, + // create a text element with the expected number of characters + // and calculating the size of that. This is easier. + this.picker_.style.width = "120px"; + + // We convert the UTC unix time to a local diff from epoch + // and convert that to the normalized representation that the + // datetime-local object needs (e.g: "2022-03-18T21:42") + this.picker_.value = showNormalizedDateTime( + utcToLocal(this.tzOffset, this.getValue()), + true + ); + + // In order to show an HTML element in Blockly we need to wrap + // it on an Svg foreignObject + const foreignObject = document.createElementNS( + "http://www.w3.org/2000/svg", + "foreignObject" + ); + foreignObject.appendChild(this.picker_); + this.foreignObject = foreignObject; + // We add the foreignObject to the fields `g` element. + this.fieldGroup_.appendChild(foreignObject); + + // This element is a textual representation of the local offset + // (e.g: "GMT+2") + this.offsetLabel = Blockly.utils.dom.createSvgElement( + Blockly.utils.Svg.TEXT, + { + class: "blocklyText", + }, + this.fieldGroup_ + ); + this.offsetLabel.textContent = this.offsetString; + this.offsetLabel.style.fill = "white"; + this.offsetLabel.style.fontSize = `${constants.FIELD_TEXT_FONTSIZE}pt`; + } + + updateSize_() { + const constants = this.getConstants(); + let totalWidth = 0; + const padding = 4; + const pickerW = this.picker_.offsetWidth; + const pickerH = constants.FIELD_TEXT_HEIGHT + padding; + + // In order for the input to be displayed, we need to set + // the foreignObject size to have its children dimensions + this.foreignObject.setAttribute("width", String(pickerW)); + this.foreignObject.setAttribute("height", String(pickerH)); + totalWidth += pickerW + padding; + this.offsetLabel.setAttribute("x", String(pickerW + padding)); + + var halfHeight = pickerH / 2; + + this.offsetLabel.setAttribute( + "y", + String( + halfHeight - + constants.FIELD_TEXT_HEIGHT / 2 + + constants.FIELD_TEXT_BASELINE + ) + ); + const offsetLabelWidth = this.offsetLabel.getBBox().width; + + totalWidth += offsetLabelWidth + padding; + + this.size_.width = totalWidth; + this.size_.height = pickerH; + } + + bindEvents_() { + super.bindEvents_(); + const thisField = this; + + // Whenever the native input element changes it value, update + // the field model + this.onInputWrapper_ = Blockly.bindEventWithChecks_( + this.picker_, + "input", + this, + function () { + const parsedValue = parseInput(thisField.picker_.value); + if (parsedValue) { + thisField.setValue( + localToUtc(thisField.tzOffset, parsedValue.unixTime) + ); + } + } + ); + } + + dispose() { + super.dispose(); + if (this.onInputWrapper_) { + Blockly.unbindEvent_(this.onInputWrapper_); + } + } + } + return FieldDateTime; +} + +type FieldDateTimeClass = ReturnType +// Register a custom DateTime Field to blockly: +// Used as base: +// * https://developers.google.com/blockly/guides/create-custom-blocks/fields/customizing-fields/creating +// * https://github.com/google/blockly-samples/blob/master/plugins/field-date/src/field_date.js +export function registerDateTimeField(Blockly: Blockly): FieldDateTimeClass { + // If the field is already registered, return it. + const RegisteredFieldDateTime = Blockly.registry + ? Blockly.registry.getClass("field", "field_datetime") + : undefined; + if (RegisteredFieldDateTime) return RegisteredFieldDateTime as FieldDateTimeClass; + + let FieldDateTime = createDateTimeFieldClass(Blockly); + + Blockly.fieldRegistry.register("field_datetime", FieldDateTime); + + return FieldDateTime; +} diff --git a/marlowe-playground-client/src/Blockly/Events.purs b/marlowe-playground-client/src/Blockly/Events.purs index 751522db07..5bf6cddb3c 100644 --- a/marlowe-playground-client/src/Blockly/Events.purs +++ b/marlowe-playground-client/src/Blockly/Events.purs @@ -37,7 +37,7 @@ foreign import data ChangeEvent :: Type instance hasEventChangeEvent :: HasEvent ChangeEvent where fromEvent :: Event -> Maybe ChangeEvent - fromEvent = readBlocklyEventType "change" + fromEvent = readBlocklyEventType "BlockChange" ------------------------------------------------------------ foreign import data UIEvent :: Type @@ -61,7 +61,7 @@ foreign import data MoveEvent :: Type instance hasEventMoveEvent :: HasEvent MoveEvent where fromEvent :: Event -> Maybe MoveEvent - fromEvent = readBlocklyEventType "move" + fromEvent = readBlocklyEventType "BlockMove" -- UUID of new parent block. Nothing if it is a top level block. newParentId :: MoveEvent -> Maybe String diff --git a/marlowe-playground-client/src/Blockly/Internal.js b/marlowe-playground-client/src/Blockly/Internal.js index 1b98cb1442..aaaa85ae3e 100644 --- a/marlowe-playground-client/src/Blockly/Internal.js +++ b/marlowe-playground-client/src/Blockly/Internal.js @@ -1,6 +1,6 @@ import * as internal from "src/Blockly/Internal.ts"; - -export const createBlocklyInstance_ = internal.createBlocklyInstance_; +import * as blockly from "src/Blockly/Blockly.ts"; +export const createBlocklyInstance_ = blockly.createBlocklyInstance_; export const addBlockType_ = internal.addBlockType_; export const addChangeListener = internal.addChangeListener; export const centerOnBlock = internal.centerOnBlock; diff --git a/marlowe-playground-client/src/Blockly/Internal.ts b/marlowe-playground-client/src/Blockly/Internal.ts index 5e857ea337..02a67507c2 100644 --- a/marlowe-playground-client/src/Blockly/Internal.ts +++ b/marlowe-playground-client/src/Blockly/Internal.ts @@ -1,19 +1,15 @@ import * as jsonBigInt from "json-bigint"; -// import { registerDateTimeField } from "src/Blockly/DateTimeField.js"; -import { registerDateTimeField } from "./DateTimeField.js"; -const JSONbig = jsonBigInt({ useNativeBigInt: true }); - -export function createBlocklyInstance_ () { - return import("blockly"); -}; - -type Blockly = Awaited>; -type Workspace = InstanceType -type WorkspaceSvg = InstanceType - -// w.constructor -// type Workspace2 = typeof (Blockly["Workspace"].constructor) +import { registerDateTimeField } from "./DateTimeField"; +import { + Blockly, + WorkspaceSvg, + TZInfo, + isBlockEvent, + isBlockChangeEvent, +} from "./Blockly"; +import { Block } from "blockly"; +const JSONbig = jsonBigInt({ useNativeBigInt: true }); export const debugBlockly = (name) => (state) => () => { if (typeof (window as any).blockly === "undefined") { @@ -22,10 +18,13 @@ export const debugBlockly = (name) => (state) => () => { (window as any).blockly[name] = state; }; -type TZInfo = {tzOffset: number, offsetString: string} +type DateTimeFieldValues = { time?: string; time_param: string }; export const createWorkspace = - (blockly: Blockly) => (workspaceDiv: string) => (config) => (tzInfo: TZInfo) => () => { - + (blockly: Blockly) => + (workspaceDiv: string) => + (config) => + (tzInfo: TZInfo) => + () => { /* Disable comments */ try { blockly.ContextMenuRegistry.registry.unregister("blockComment"); @@ -100,7 +99,8 @@ export const createWorkspace = // This extension takes care of changing the `timeout field` depending on the value of // `timeout_type`. When `timeout_type` is a constant, then we show a datetime picker // if it is a parameter we show a text field. - blockly.Extensions.register("dynamic_timeout_type", function () { + blockly.Extensions.register("dynamic_timeout_type", function (this: Block) { + // blockly.Extensions.register("dynamic_timeout_type", function () { const timeoutTypeField = this.getField("timeout_type"); // The timeoutField is mutable as we change it depending of the value of // the timeout type. @@ -116,15 +116,14 @@ export const createWorkspace = // We store in this mutable data the values of the timeout field indexed by the different // timeout types. We initialize this as undefined as there is no blockly event to get the initial // loaded data, so we mark this information to be gathered on a different way. - let fieldValues = undefined; // { time :: String | undefined, time_param :: String }; + let fieldValues: DateTimeFieldValues = undefined; // { time :: String | undefined, time_param :: String }; // The onChange function lets you know about Blockly events of the entire workspace, visual // changes, data changes, etc. const thisBlock = this; this.setOnChange(function (event) { // we only care about events for this block. - if (event.blockId != thisBlock.id) return; - + if (!isBlockEvent(event) || event.blockId != thisBlock.id) return; timeoutField = thisBlock.getField("timeout"); // This function sets the Timeout Field of the correct type @@ -146,18 +145,16 @@ export const createWorkspace = // event results in a bug where if you attach a new When block, // change to time_param and convert to marlowe, the old time value // is presented. - console.log('yea yea2') - debugger; - blockly.Events.CHANGE - blockly.Events.fire( - new blockly.Events.Change( - thisBlock, // block that changed - "field", // type of element that changed - "timeout", // name of the element that changed - fieldValues["time"], // old value - fieldValues["time_param"] // new value - ) - ); + + // blockly.Events.fire( + // new blockly.Events.Change( + // thisBlock, // block that changed + // "field", // type of element that changed + // "timeout", // name of the element that changed + // fieldValues["time"], // old value + // fieldValues["time_param"] // new value + // ) + // ); } }; @@ -179,13 +176,14 @@ export const createWorkspace = // Set the timeout field to the correct type updateTimeoutField(type); } - - if (event.element == "field" && event.name == "timeout") { - // If the timeout field changes, update the fieldValues "local store" - fieldValues[timeoutTypeField.getValue()] = event.newValue; - } else if (event.element == "field" && event.name == "timeout_type") { - // If the timeout_type field changes, then update the timeout field - updateTimeoutField(event.newValue); + if (isBlockChangeEvent(event)) { + if (event.element == "field" && event.name == "timeout") { + // If the timeout field changes, update the fieldValues "local store" + fieldValues[timeoutTypeField.getValue()] = event.newValue; + } else if (event.element == "field" && event.name == "timeout_type") { + // If the timeout_type field changes, then update the timeout field + updateTimeoutField(event.newValue); + } } }); }); @@ -218,20 +216,24 @@ function removeEmptyArrayFields(obj) { } } -export const addBlockType_ = (blockly: Blockly) => (name: string) => (block) => () => { - // we really don't want to be mutating the input object, it is not supposed to be state - var clone = JSONbig.parse(JSONbig.stringify(block)); - removeUndefinedFields(clone); - removeEmptyArrayFields(clone); - blockly.Blocks[name] = { - init: function () { - this.jsonInit(clone); - }, +export const addBlockType_ = + (blockly: Blockly) => (name: string) => (block) => () => { + // we really don't want to be mutating the input object, it is not supposed to be state + var clone = JSONbig.parse(JSONbig.stringify(block)); + removeUndefinedFields(clone); + removeEmptyArrayFields(clone); + blockly.Blocks[name] = { + init: function () { + this.jsonInit(clone); + }, + }; }; -}; export const initializeWorkspace_ = - (blockly: Blockly) => (workspace: WorkspaceSvg) => (workspaceBlocks) => () => { + (blockly: Blockly) => + (workspace: WorkspaceSvg) => + (workspaceBlocks) => + () => { blockly.Xml.domToWorkspace(workspaceBlocks, workspace); workspace.getAllBlocks(false)[0].setDeletable(false); }; @@ -251,7 +253,7 @@ export const getBlockById_ = }; // FIXME WorkspaceSvg -export const workspaceXML = (blockly: Blockly) => (workspace ) => () => { +export const workspaceXML = (blockly: Blockly) => (workspace) => () => { const isEmpty = workspace.getAllBlocks()[0].getChildren().length == 0; if (isEmpty) { return ""; @@ -261,11 +263,12 @@ export const workspaceXML = (blockly: Blockly) => (workspace ) => () => { } }; -export const loadWorkspace = (blockly: Blockly) => (workspace) => (xml) => () => { - var dom = blockly.utils.xml.textToDomDocument(xml) as any; // TODO FIXME - blockly.Xml.clearWorkspaceAndLoadFromXml(dom.childNodes[0], workspace); - workspace.getAllBlocks(false)[0].setDeletable(false); -}; +export const loadWorkspace = + (blockly: Blockly) => (workspace) => (xml) => () => { + var dom = blockly.utils.xml.textToDomDocument(xml) as any; // TODO FIXME + blockly.Xml.clearWorkspaceAndLoadFromXml(dom.childNodes[0], workspace); + workspace.getAllBlocks(false)[0].setDeletable(false); + }; export const addChangeListener = (workspace) => (listener) => () => { workspace.addChangeListener(listener); diff --git a/marlowe-playground-client/tsconfig.json b/marlowe-playground-client/tsconfig.json index 0e0646dcd1..a6c26c7655 100644 --- a/marlowe-playground-client/tsconfig.json +++ b/marlowe-playground-client/tsconfig.json @@ -1,6 +1,8 @@ { "compilerOptions": { - "lib": ["ES6", "DOM"] + "lib": ["ES6", "DOM"], + "target": "es6", + "module":"CommonJS" }, "include": ["src/**/*"], "exclude": ["node_modules"] diff --git a/marlowe-playground-server/src/Gist.hs b/marlowe-playground-server/src/Gist.hs index ae67b5af95..ff68615cdf 100644 --- a/marlowe-playground-server/src/Gist.hs +++ b/marlowe-playground-server/src/Gist.hs @@ -45,7 +45,6 @@ import qualified Servant.Extra import Text.Read (readEither) type API = Header "Authorization" (Token 'Github) :> "gists" :> GistAPI --- Puede que la solucion venga por aca, diciendole lo que tiene que devolver un 201 type GistAPI = Get '[ JSON] [Gist] :<|> ReqBody '[ JSON] NewGist :> PostCreated '[ JSON] Gist