mirror of
https://github.com/google/blockly.git
synced 2025-12-16 06:10:12 +01:00
refactor(blocks): Migrate blocks/variables.js and blocks/variables_dynamic.js to TypeScript (#7001)
* refactor: run js2ts on variables * refactor: clean up conversion of variables blocks to typescript * refactor: add types for custom context menu options * refactor: run js2ts on blocks/variables_dynamic.js * refactor: clean up types in variables_dynamic * chore: respond to PR comments * chore: format
This commit is contained in:
@@ -14,6 +14,7 @@ goog.declareModuleId('Blockly.libraryBlocks.loops');
|
||||
import type {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
|
||||
import type {Block} from '../core/block.js';
|
||||
import * as ContextMenu from '../core/contextmenu.js';
|
||||
import type {ContextMenuOption, LegacyContextMenuOption} from '../core/contextmenu_registry.js';
|
||||
import * as Events from '../core/events/events.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import * as Variables from '../core/variables.js';
|
||||
@@ -249,7 +250,8 @@ const CUSTOM_CONTEXT_MENU_CREATE_VARIABLES_GET_MIXIN = {
|
||||
* @param options List of menu options to add to.
|
||||
*/
|
||||
customContextMenu: function(
|
||||
this: CustomContextMenuBlock, options: Array<any>) {
|
||||
this: CustomContextMenuBlock,
|
||||
options: Array<ContextMenuOption|LegacyContextMenuOption>) {
|
||||
if (this.isInFlyout) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -8,33 +8,27 @@
|
||||
* @fileoverview Variable blocks for Blockly.
|
||||
* @suppress {checkTypes}
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.module('Blockly.libraryBlocks.variables');
|
||||
import * as goog from '../closure/goog/goog.js';
|
||||
goog.declareModuleId('Blockly.libraryBlocks.variables');
|
||||
|
||||
const ContextMenu = goog.require('Blockly.ContextMenu');
|
||||
const Extensions = goog.require('Blockly.Extensions');
|
||||
const Variables = goog.require('Blockly.Variables');
|
||||
const xmlUtils = goog.require('Blockly.utils.xml');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const {Block} = goog.requireType('Blockly.Block');
|
||||
// const {BlockDefinition} = goog.requireType('Blockly.blocks');
|
||||
// TODO (6248): Properly import the BlockDefinition type.
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const BlockDefinition = Object;
|
||||
const {Msg} = goog.require('Blockly.Msg');
|
||||
const {createBlockDefinitionsFromJsonArray, defineBlocks} = goog.require('Blockly.common');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.FieldLabel');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.FieldVariable');
|
||||
import * as ContextMenu from '../core/contextmenu.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import * as Variables from '../core/variables.js';
|
||||
import * as xmlUtils from '../core/utils/xml.js';
|
||||
import type {Block} from '../core/block.js';
|
||||
import type {ContextMenuOption, LegacyContextMenuOption} from '../core/contextmenu_registry.js';
|
||||
import {FieldVariable} from '../core/field_variable.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import type {WorkspaceSvg} from '../core/workspace_svg.js';
|
||||
import {createBlockDefinitionsFromJsonArray, defineBlocks} from '../core/common.js';
|
||||
import '../core/field_label.js';
|
||||
|
||||
|
||||
/**
|
||||
* A dictionary of the block definitions provided by this module.
|
||||
* @type {!Object<string, !BlockDefinition>}
|
||||
*/
|
||||
const blocks = createBlockDefinitionsFromJsonArray([
|
||||
export const blocks = createBlockDefinitionsFromJsonArray([
|
||||
// Block for variable getter.
|
||||
{
|
||||
'type': 'variables_get',
|
||||
@@ -75,25 +69,27 @@ const blocks = createBlockDefinitionsFromJsonArray([
|
||||
'extensions': ['contextMenu_variableSetterGetter'],
|
||||
},
|
||||
]);
|
||||
exports.blocks = blocks;
|
||||
|
||||
/** Type of a block that has CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN */
|
||||
type VariableBlock = Block&VariableMixin;
|
||||
interface VariableMixin extends VariableMixinType {}
|
||||
type VariableMixinType =
|
||||
typeof CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN;
|
||||
|
||||
/**
|
||||
* Mixin to add context menu items to create getter/setter blocks for this
|
||||
* setter/getter.
|
||||
* Used by blocks 'variables_set' and 'variables_get'.
|
||||
* @mixin
|
||||
* @augments Block
|
||||
* @package
|
||||
* @readonly
|
||||
*/
|
||||
const CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN = {
|
||||
/**
|
||||
* Add menu option to create getter/setter block for this setter/getter.
|
||||
* @param {!Array} options List of menu options to add to.
|
||||
* @this {Block}
|
||||
*
|
||||
* @param options List of menu options to add to.
|
||||
*/
|
||||
customContextMenu: function(options) {
|
||||
customContextMenu: function(
|
||||
this: VariableBlock,
|
||||
options: Array<ContextMenuOption|LegacyContextMenuOption>) {
|
||||
if (!this.isInFlyout) {
|
||||
let oppositeType;
|
||||
let contextMenuMsg;
|
||||
@@ -106,17 +102,19 @@ const CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN = {
|
||||
contextMenuMsg = Msg['VARIABLES_SET_CREATE_GET'];
|
||||
}
|
||||
|
||||
const option = {enabled: this.workspace.remainingCapacity() > 0};
|
||||
const name = this.getField('VAR').getText();
|
||||
option.text = contextMenuMsg.replace('%1', name);
|
||||
const name = this.getField('VAR')!.getText();
|
||||
const xmlField = xmlUtils.createElement('field');
|
||||
xmlField.setAttribute('name', 'VAR');
|
||||
xmlField.appendChild(xmlUtils.createTextNode(name));
|
||||
const xmlBlock = xmlUtils.createElement('block');
|
||||
xmlBlock.setAttribute('type', oppositeType);
|
||||
xmlBlock.appendChild(xmlField);
|
||||
option.callback = ContextMenu.callbackFactory(this, xmlBlock);
|
||||
options.push(option);
|
||||
|
||||
options.push({
|
||||
enabled: this.workspace.remainingCapacity() > 0,
|
||||
text: contextMenuMsg.replace('%1', name),
|
||||
callback: ContextMenu.callbackFactory(this, xmlBlock)
|
||||
});
|
||||
// Getter blocks have the option to rename or delete that variable.
|
||||
} else {
|
||||
if (this.type === 'variables_get' ||
|
||||
@@ -126,7 +124,7 @@ const CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN = {
|
||||
enabled: true,
|
||||
callback: renameOptionCallbackFactory(this),
|
||||
};
|
||||
const name = this.getField('VAR').getText();
|
||||
const name = this.getField('VAR')!.getText();
|
||||
const deleteOption = {
|
||||
text: Msg['DELETE_VARIABLE'].replace('%1', name),
|
||||
enabled: true,
|
||||
@@ -142,13 +140,15 @@ const CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN = {
|
||||
/**
|
||||
* Factory for callbacks for rename variable dropdown menu option
|
||||
* associated with a variable getter block.
|
||||
* @param {!Block} block The block with the variable to rename.
|
||||
* @return {!function()} A function that renames the variable.
|
||||
*
|
||||
* @param block The block with the variable to rename.
|
||||
* @returns A function that renames the variable.
|
||||
*/
|
||||
const renameOptionCallbackFactory = function(block) {
|
||||
const renameOptionCallbackFactory = function(block: VariableBlock): () => void {
|
||||
return function() {
|
||||
const workspace = block.workspace;
|
||||
const variable = block.getField('VAR').getVariable();
|
||||
const variableField = block.getField('VAR') as FieldVariable;
|
||||
const variable = variableField.getVariable()!;
|
||||
Variables.renameVariable(workspace, variable);
|
||||
};
|
||||
};
|
||||
@@ -156,15 +156,17 @@ const renameOptionCallbackFactory = function(block) {
|
||||
/**
|
||||
* Factory for callbacks for delete variable dropdown menu option
|
||||
* associated with a variable getter block.
|
||||
* @param {!Block} block The block with the variable to delete.
|
||||
* @return {!function()} A function that deletes the variable.
|
||||
*
|
||||
* @param block The block with the variable to delete.
|
||||
* @returns A function that deletes the variable.
|
||||
*/
|
||||
const deleteOptionCallbackFactory = function(block) {
|
||||
const deleteOptionCallbackFactory = function(block: VariableBlock): () => void {
|
||||
return function() {
|
||||
const workspace = block.workspace;
|
||||
const variable = block.getField('VAR').getVariable();
|
||||
const variableField = block.getField('VAR') as FieldVariable;
|
||||
const variable = variableField.getVariable()!;
|
||||
workspace.deleteVariableById(variable.getId());
|
||||
workspace.refreshToolboxSelection();
|
||||
(workspace as WorkspaceSvg).refreshToolboxSelection();
|
||||
};
|
||||
};
|
||||
|
||||
@@ -8,35 +8,28 @@
|
||||
* @fileoverview Variable blocks for Blockly.
|
||||
* @suppress {checkTypes}
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
goog.module('Blockly.libraryBlocks.variablesDynamic');
|
||||
import * as goog from '../closure/goog/goog.js';
|
||||
goog.declareModuleId('Blockly.libraryBlocks.variablesDynamic');
|
||||
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const AbstractEvent = goog.requireType('Blockly.Events.Abstract');
|
||||
const ContextMenu = goog.require('Blockly.ContextMenu');
|
||||
const Extensions = goog.require('Blockly.Extensions');
|
||||
const Variables = goog.require('Blockly.Variables');
|
||||
const xml = goog.require('Blockly.utils.xml');
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const {Block} = goog.requireType('Blockly.Block');
|
||||
// const {BlockDefinition} = goog.requireType('Blockly.blocks');
|
||||
// TODO (6248): Properly import the BlockDefinition type.
|
||||
/* eslint-disable-next-line no-unused-vars */
|
||||
const BlockDefinition = Object;
|
||||
const {Msg} = goog.require('Blockly.Msg');
|
||||
const {createBlockDefinitionsFromJsonArray, defineBlocks} = goog.require('Blockly.common');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.FieldLabel');
|
||||
/** @suppress {extraRequire} */
|
||||
goog.require('Blockly.FieldVariable');
|
||||
import * as ContextMenu from '../core/contextmenu.js';
|
||||
import * as Extensions from '../core/extensions.js';
|
||||
import * as Variables from '../core/variables.js';
|
||||
import * as xml from '../core/utils/xml.js';
|
||||
import {Abstract as AbstractEvent} from '../core/events/events_abstract.js';
|
||||
import type {Block} from '../core/block.js';
|
||||
import type {ContextMenuOption, LegacyContextMenuOption} from '../core/contextmenu_registry.js';
|
||||
import {FieldVariable} from '../core/field_variable.js';
|
||||
import {Msg} from '../core/msg.js';
|
||||
import type {WorkspaceSvg} from '../core/workspace_svg.js';
|
||||
import {createBlockDefinitionsFromJsonArray, defineBlocks} from '../core/common.js';
|
||||
import '../core/field_label.js';
|
||||
|
||||
|
||||
/**
|
||||
* A dictionary of the block definitions provided by this module.
|
||||
* @type {!Object<string, !BlockDefinition>}
|
||||
*/
|
||||
const blocks = createBlockDefinitionsFromJsonArray([
|
||||
export const blocks = createBlockDefinitionsFromJsonArray([
|
||||
// Block for variable getter.
|
||||
{
|
||||
'type': 'variables_get_dynamic',
|
||||
@@ -75,30 +68,34 @@ const blocks = createBlockDefinitionsFromJsonArray([
|
||||
'extensions': ['contextMenu_variableDynamicSetterGetter'],
|
||||
},
|
||||
]);
|
||||
exports.blocks = blocks;
|
||||
|
||||
/** Type of a block that has CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN */
|
||||
type VariableBlock = Block&VariableMixin;
|
||||
interface VariableMixin extends VariableMixinType {}
|
||||
type VariableMixinType =
|
||||
typeof CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN;
|
||||
|
||||
/**
|
||||
* Mixin to add context menu items to create getter/setter blocks for this
|
||||
* setter/getter.
|
||||
* Used by blocks 'variables_set_dynamic' and 'variables_get_dynamic'.
|
||||
* @mixin
|
||||
* @augments Block
|
||||
* @readonly
|
||||
*/
|
||||
const CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN = {
|
||||
/**
|
||||
* Add menu option to create getter/setter block for this setter/getter.
|
||||
* @param {!Array} options List of menu options to add to.
|
||||
* @this {Block}
|
||||
*
|
||||
* @param options List of menu options to add to.
|
||||
*/
|
||||
customContextMenu: function(options) {
|
||||
customContextMenu: function(
|
||||
this: VariableBlock,
|
||||
options: Array<ContextMenuOption|LegacyContextMenuOption>) {
|
||||
// Getter blocks have the option to create a setter block, and vice versa.
|
||||
if (!this.isInFlyout) {
|
||||
let oppositeType;
|
||||
let contextMenuMsg;
|
||||
const id = this.getFieldValue('VAR');
|
||||
const variableModel = this.workspace.getVariableById(id);
|
||||
const varType = variableModel.type;
|
||||
const varType = variableModel!.type;
|
||||
if (this.type === 'variables_get_dynamic') {
|
||||
oppositeType = 'variables_set_dynamic';
|
||||
contextMenuMsg = Msg['VARIABLES_GET_CREATE_SET'];
|
||||
@@ -107,9 +104,7 @@ const CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN = {
|
||||
contextMenuMsg = Msg['VARIABLES_SET_CREATE_GET'];
|
||||
}
|
||||
|
||||
const option = {enabled: this.workspace.remainingCapacity() > 0};
|
||||
const name = this.getField('VAR').getText();
|
||||
option.text = contextMenuMsg.replace('%1', name);
|
||||
const name = this.getField('VAR')!.getText();
|
||||
const xmlField = xml.createElement('field');
|
||||
xmlField.setAttribute('name', 'VAR');
|
||||
xmlField.setAttribute('variabletype', varType);
|
||||
@@ -117,8 +112,12 @@ const CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN = {
|
||||
const xmlBlock = xml.createElement('block');
|
||||
xmlBlock.setAttribute('type', oppositeType);
|
||||
xmlBlock.appendChild(xmlField);
|
||||
option.callback = ContextMenu.callbackFactory(this, xmlBlock);
|
||||
options.push(option);
|
||||
|
||||
options.push({
|
||||
enabled: this.workspace.remainingCapacity() > 0,
|
||||
text: contextMenuMsg.replace('%1', name),
|
||||
callback: ContextMenu.callbackFactory(this, xmlBlock)
|
||||
});
|
||||
} else {
|
||||
if (this.type === 'variables_get_dynamic' ||
|
||||
this.type === 'variables_get_reporter_dynamic') {
|
||||
@@ -127,7 +126,7 @@ const CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN = {
|
||||
enabled: true,
|
||||
callback: renameOptionCallbackFactory(this),
|
||||
};
|
||||
const name = this.getField('VAR').getText();
|
||||
const name = this.getField('VAR')!.getText();
|
||||
const deleteOption = {
|
||||
text: Msg['DELETE_VARIABLE'].replace('%1', name),
|
||||
enabled: true,
|
||||
@@ -141,16 +140,16 @@ const CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN = {
|
||||
/**
|
||||
* Called whenever anything on the workspace changes.
|
||||
* Set the connection type for this block.
|
||||
* @param {AbstractEvent} _e Change event.
|
||||
* @this {Block}
|
||||
*
|
||||
* @param _e Change event.
|
||||
*/
|
||||
onchange: function(_e) {
|
||||
onchange: function(this: VariableBlock, _e: AbstractEvent) {
|
||||
const id = this.getFieldValue('VAR');
|
||||
const variableModel = Variables.getVariable(this.workspace, id);
|
||||
const variableModel = Variables.getVariable(this.workspace, id)!;
|
||||
if (this.type === 'variables_get_dynamic') {
|
||||
this.outputConnection.setCheck(variableModel.type);
|
||||
this.outputConnection!.setCheck(variableModel.type);
|
||||
} else {
|
||||
this.getInput('VALUE').connection.setCheck(variableModel.type);
|
||||
this.getInput('VALUE')!.connection!.setCheck(variableModel.type);
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -158,13 +157,15 @@ const CUSTOM_CONTEXT_MENU_VARIABLE_GETTER_SETTER_MIXIN = {
|
||||
/**
|
||||
* Factory for callbacks for rename variable dropdown menu option
|
||||
* associated with a variable getter block.
|
||||
* @param {!Block} block The block with the variable to rename.
|
||||
* @return {!function()} A function that renames the variable.
|
||||
*
|
||||
* @param block The block with the variable to rename.
|
||||
* @returns A function that renames the variable.
|
||||
*/
|
||||
const renameOptionCallbackFactory = function(block) {
|
||||
const renameOptionCallbackFactory = function(block: VariableBlock) {
|
||||
return function() {
|
||||
const workspace = block.workspace;
|
||||
const variable = block.getField('VAR').getVariable();
|
||||
const variableField = block.getField('VAR') as FieldVariable;
|
||||
const variable = variableField.getVariable()!;
|
||||
Variables.renameVariable(workspace, variable);
|
||||
};
|
||||
};
|
||||
@@ -172,15 +173,17 @@ const renameOptionCallbackFactory = function(block) {
|
||||
/**
|
||||
* Factory for callbacks for delete variable dropdown menu option
|
||||
* associated with a variable getter block.
|
||||
* @param {!Block} block The block with the variable to delete.
|
||||
* @return {!function()} A function that deletes the variable.
|
||||
*
|
||||
* @param block The block with the variable to delete.
|
||||
* @returns A function that deletes the variable.
|
||||
*/
|
||||
const deleteOptionCallbackFactory = function(block) {
|
||||
const deleteOptionCallbackFactory = function(block: VariableBlock) {
|
||||
return function() {
|
||||
const workspace = block.workspace;
|
||||
const variable = block.getField('VAR').getVariable();
|
||||
const variableField = block.getField('VAR') as FieldVariable;
|
||||
const variable = variableField.getVariable()!;
|
||||
workspace.deleteVariableById(variable.getId());
|
||||
workspace.refreshToolboxSelection();
|
||||
(workspace as WorkspaceSvg).refreshToolboxSelection();
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user