diff --git a/Gemfile b/Gemfile index 489d2bde51f4f..ee891ad7a6242 100644 --- a/Gemfile +++ b/Gemfile @@ -99,14 +99,14 @@ group :development, :test do # For UI testing. gem 'cucumber' - gem 'eyes_selenium' + gem 'eyes_selenium', '3.17.20' gem 'minitest', '~> 5.5' gem 'minitest-around' gem 'minitest-reporters', '~> 1.2.0.beta3' gem 'net-http-persistent' gem 'rinku' gem 'rspec' - gem 'selenium-webdriver' + gem 'selenium-webdriver', '3.141.0' gem 'spring' gem 'spring-commands-testunit' gem 'webdrivers', '~> 3.0' diff --git a/Gemfile.lock b/Gemfile.lock index 26688837e3dc6..d68cb99bdb24d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -366,7 +366,7 @@ GEM crack (0.4.3) safe_yaml (~> 1.0.0) crass (1.0.4) - css_parser (1.7.0) + css_parser (1.7.1) addressable cucumber (3.1.1) builder (>= 2.1.2) @@ -416,15 +416,20 @@ GEM eventmachine (1.2.5) execjs (2.7.0) exifr (1.2.5) - eyes_core (3.14.10) + eyes_core (3.17.20) chunky_png (= 1.3.6) faraday + faraday-cookie_jar + faraday_middleware oily_png (~> 1.2) oj - eyes_selenium (3.14.10) + eyes_selenium (3.17.20) + crass css_parser - eyes_core (= 3.14.10) + eyes_core (= 3.17.20) + nokogiri selenium-webdriver + state_machine factory_girl (4.7.0) activesupport (>= 3.0.0) factory_girl_rails (4.7.0) @@ -434,6 +439,11 @@ GEM redis (~> 3.2) faraday (0.15.4) multipart-post (>= 1.2, < 3) + faraday-cookie_jar (0.0.7) + faraday (>= 0.8.0) + http-cookie (~> 1.0.0) + faraday_middleware (0.14.0) + faraday (>= 0.7.4, < 1.0) ffi (1.10.0) firebase (0.2.6) httpclient @@ -520,7 +530,7 @@ GEM jsonapi-serializers (1.0.0) activesupport jumphash (0.1.0) - jwt (2.1.0) + jwt (2.2.2) kaminari (0.17.0) actionpack (>= 3.0.0) activesupport (>= 3.0.0) @@ -561,7 +571,7 @@ GEM multi_json (1.13.1) multi_test (0.1.2) multi_xml (0.5.5) - multipart-post (2.0.0) + multipart-post (2.1.1) mustermann (1.0.3) mysql2 (0.5.2) nakayoshi_fork (0.0.4) @@ -574,7 +584,7 @@ GEM net_http_ssl_fix (0.0.10) netrc (0.11.0) nio4r (2.3.1) - nokogiri (1.10.3) + nokogiri (1.10.10) mini_portile2 (~> 2.4.0) oauth (0.5.1) oauth2 (1.4.1) @@ -812,6 +822,7 @@ GEM sshkit (1.20.0) net-scp (>= 1.1.2) net-ssh (>= 2.8.0) + state_machine (1.2.0) stringex (2.5.2) swd (1.0.1) activesupport (>= 3) @@ -833,8 +844,8 @@ GEM tilt (2.0.10) timecop (0.8.1) ttfunk (1.4.0) - twilio-ruby (5.20.1) - faraday (~> 0.9) + twilio-ruby (5.40.1) + faraday (>= 0.9, < 2.0) jwt (>= 1.5, <= 2.5) nokogiri (>= 1.6, < 2.0) tzinfo (1.2.5) @@ -939,7 +950,7 @@ DEPENDENCIES devise_invitable (~> 1.6.0) dotiw execjs - eyes_selenium + eyes_selenium (= 3.17.20) factory_girl_rails fakeredis firebase @@ -1039,7 +1050,7 @@ DEPENDENCIES scss_lint sdoc seamless_database_pool! - selenium-webdriver + selenium-webdriver (= 3.141.0) sequel shotgun simplecov (~> 0.9) diff --git a/apps/src/blocklyAddons/cdoBlockSvg.js b/apps/src/blocklyAddons/cdoBlockSvg.js new file mode 100644 index 0000000000000..8caab445bcb65 --- /dev/null +++ b/apps/src/blocklyAddons/cdoBlockSvg.js @@ -0,0 +1,25 @@ +import GoogleBlockly from 'blockly/core'; + +export default class BlockSvg extends GoogleBlockly.BlockSvg { + getTitles() { + let fields = []; + this.inputList.forEach(input => { + input.fieldRow.forEach(field => { + fields.push(field); + }); + }); + return fields; + } + + getTitleValue(name) { + return super.getFieldValue(name); + } + + isUserVisible() { + return false; // TODO + } + + setHSV(h, s, v) { + return super.setColour(Blockly.utils.colour.hsvToHex(h, s, v * 255)); + } +} diff --git a/apps/src/blocklyAddons/cdoFieldDropdown.js b/apps/src/blocklyAddons/cdoFieldDropdown.js new file mode 100644 index 0000000000000..ee6a8468c4745 --- /dev/null +++ b/apps/src/blocklyAddons/cdoFieldDropdown.js @@ -0,0 +1,19 @@ +import GoogleBlockly from 'blockly/core'; + +export default class FieldDropdown extends GoogleBlockly.FieldDropdown { + constructor(menuGenerator, opt_changeHandler, opt_alwaysCallChangeHandler) { + let validator; + if (opt_changeHandler) { + validator = function(val) { + if ( + this.getSourceBlock() && + !this.getSourceBlock().isInsertionMarker_ && + this.value_ !== val + ) { + opt_changeHandler(val); + } + }; + } + super(menuGenerator, validator); + } +} diff --git a/apps/src/blocklyAddons/cdoInput.js b/apps/src/blocklyAddons/cdoInput.js new file mode 100644 index 0000000000000..c1a84cfd6fa63 --- /dev/null +++ b/apps/src/blocklyAddons/cdoInput.js @@ -0,0 +1,7 @@ +import GoogleBlockly from 'blockly/core'; + +export default class Input extends GoogleBlockly.Input { + appendTitle(a, b) { + return super.appendField(a, b); + } +} diff --git a/apps/src/blocklyAddons/cdoWorkspaceSvg.js b/apps/src/blocklyAddons/cdoWorkspaceSvg.js new file mode 100644 index 0000000000000..580a2af7870f6 --- /dev/null +++ b/apps/src/blocklyAddons/cdoWorkspaceSvg.js @@ -0,0 +1,22 @@ +import GoogleBlockly from 'blockly/core'; + +export default class WorkspaceSvg extends GoogleBlockly.WorkspaceSvg { + addUnusedBlocksHelpListener() {} // TODO + getAllUsedBlocks() { + return super.getAllBlocks(); + } + getToolboxWidth() { + return Blockly.mainBlockSpace.getMetrics().toolboxWidth; + } + isReadOnly() { + return false; // TODO + } + setEnableToolbox() {} // TODO +} + +WorkspaceSvg.prototype.blockSpaceEditor = { + blockLimits: { + blockLimitExceeded: () => false, // TODO + getLimit: () => {} // TODO + } +}; diff --git a/apps/src/lib/levelbuilder/TextareaWithMarkdownPreview.jsx b/apps/src/lib/levelbuilder/TextareaWithMarkdownPreview.jsx new file mode 100644 index 0000000000000..b6d12e238ddd3 --- /dev/null +++ b/apps/src/lib/levelbuilder/TextareaWithMarkdownPreview.jsx @@ -0,0 +1,71 @@ +import PropTypes from 'prop-types'; +import React from 'react'; +import SafeMarkdown from '@cdo/apps/templates/SafeMarkdown'; +import color from '@cdo/apps/util/color'; + +const styles = { + box: { + marginTop: 10, + marginBottom: 10, + border: '1px solid ' + color.light_gray, + padding: 10 + }, + input: { + width: '100%', + boxSizing: 'border-box', + padding: '4px 6px', + color: '#555', + border: '1px solid #ccc', + borderRadius: 4, + margin: 0 + } +}; + +/** + * Component for previewing Markdown for a edit field + */ +export default class TextareaWithMarkdownPreview extends React.Component { + static propTypes = { + markdown: PropTypes.string.isRequired, + label: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, + inputRows: PropTypes.number + }; + + constructor(props) { + super(props); + + this.state = { + markdown: this.props.markdown + }; + } + + handleMarkdownChange = event => { + this.setState({markdown: event.target.value}); + }; + + render() { + return ( +