From fed35909cc01f05bb255386c7f592baf54760094 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torkel=20=C3=96degaard?= Date: Thu, 21 Sep 2017 13:32:57 +0200 Subject: [PATCH] tech: progress on react poc --- package.json | 2 + .../app/core/components/PasswordStrength.tsx | 39 ++++ public/app/core/components/collapse_box.ts | 58 ----- public/app/core/components/scroll/scroll.ts | 211 ------------------ public/app/core/components/wizard/wizard.html | 32 --- public/app/core/components/wizard/wizard.ts | 73 ------ public/app/core/core.ts | 9 +- .../app/core/directives/password_strength.js | 2 +- .../app/core/specs/PasswordStrength_specs.tsx | 14 ++ .../features/plugins/partials/ds_edit.html | 4 - public/app/partials/signup_step2.html | 2 +- public/sass/_grafana.scss | 1 - public/sass/components/_collapse_box.scss | 46 ---- public/test/test-main.js | 17 +- tasks/options/watch.js | 1 + yarn.lock | 18 ++ 16 files changed, 88 insertions(+), 441 deletions(-) create mode 100644 public/app/core/components/PasswordStrength.tsx delete mode 100644 public/app/core/components/collapse_box.ts delete mode 100644 public/app/core/components/scroll/scroll.ts delete mode 100644 public/app/core/components/wizard/wizard.html delete mode 100644 public/app/core/components/wizard/wizard.ts create mode 100644 public/app/core/specs/PasswordStrength_specs.tsx delete mode 100644 public/sass/components/_collapse_box.scss diff --git a/package.json b/package.json index 2e4f174dec0..82fcce2b20d 100644 --- a/package.json +++ b/package.json @@ -62,6 +62,7 @@ }, "license": "Apache-2.0", "dependencies": { + "@types/enzyme": "^2.8.8", "ace-builds": "^1.2.8", "eventemitter3": "^2.0.2", "gaze": "^1.1.2", @@ -75,6 +76,7 @@ "ngreact": "^0.4.1", "react": "^15.6.1", "react-dom": "^15.6.1", + "react-test-renderer": "^15.6.1", "remarkable": "^1.7.1", "sinon": "1.17.6", "systemjs-builder": "^0.15.34", diff --git a/public/app/core/components/PasswordStrength.tsx b/public/app/core/components/PasswordStrength.tsx new file mode 100644 index 00000000000..c376042ce75 --- /dev/null +++ b/public/app/core/components/PasswordStrength.tsx @@ -0,0 +1,39 @@ +import * as React from 'react'; +import * as ReactDOM from 'react-dom'; +import coreModule from '../core_module'; + +export interface IProps { + password: string; +} + +export class PasswordStrength extends React.Component { + + constructor(props) { + super(props); + } + + render() { + let strengthText = "strength: strong like a bull."; + let strengthClass = "password-strength-good"; + + if (this.props.password.length < 4) { + strengthText = "strength: weak sauce."; + strengthClass = "password-strength-bad"; + } + + if (this.props.password.length <= 8) { + strengthText = "strength: you can do better."; + strengthClass = "password-strength-ok"; + } + + return ( +
+ {strengthText} +
+ ); + } +} + +coreModule.directive('passwordStrength', function(reactDirective) { + return reactDirective(PasswordStrength, ['password']); +}); diff --git a/public/app/core/components/collapse_box.ts b/public/app/core/components/collapse_box.ts deleted file mode 100644 index 7fc234cb583..00000000000 --- a/public/app/core/components/collapse_box.ts +++ /dev/null @@ -1,58 +0,0 @@ -/// - -import coreModule from 'app/core/core_module'; - -const template = ` - -`; - -export class CollapseBoxCtrl { - isOpen: boolean; - stateChanged: () => void; - - /** @ngInject **/ - constructor(private $timeout) { - this.isOpen = false; - } - - toggle() { - this.isOpen = !this.isOpen; - this.$timeout(() => { - this.stateChanged(); - }); - } -} - -export function collapseBox() { - return { - restrict: 'E', - template: template, - controller: CollapseBoxCtrl, - bindToController: true, - controllerAs: 'ctrl', - scope: { - "title": "@", - "isOpen": "=?", - "stateChanged": "&" - }, - transclude: { - 'actions': '?collapseBoxActions', - 'body': 'collapseBoxBody', - }, - link: function(scope, elem, attrs) { - } - }; -} - -coreModule.directive('collapseBox', collapseBox); diff --git a/public/app/core/components/scroll/scroll.ts b/public/app/core/components/scroll/scroll.ts deleted file mode 100644 index 914f3ba2dd9..00000000000 --- a/public/app/core/components/scroll/scroll.ts +++ /dev/null @@ -1,211 +0,0 @@ -// /// -// -// import _ from 'lodash'; -// -// var objectAssign = require('object-assign'); -// var Emitter = require('tiny-emitter'); -// var Lethargy = require('lethargy').Lethargy; -// var support = require('./support'); -// var clone = require('./clone'); -// var bindAll = require('bindall-standalone'); -// var EVT_ID = 'virtualscroll'; -// -// var keyCodes = { -// LEFT: 37, -// UP: 38, -// RIGHT: 39, -// DOWN: 40 -// }; -// -// function VirtualScroll(this: any, options) { -// _.bindAll(this, '_onWheel', '_onMouseWheel', '_onTouchStart', '_onTouchMove', '_onKeyDown'); -// -// this.el = window; -// if (options && options.el) { -// this.el = options.el; -// delete options.el; -// } -// -// this.options = _.assign({ -// mouseMultiplier: 1, -// touchMultiplier: 2, -// firefoxMultiplier: 15, -// keyStep: 120, -// preventTouch: false, -// unpreventTouchClass: 'vs-touchmove-allowed', -// limitInertia: false -// }, options); -// -// if (this.options.limitInertia) this._lethargy = new Lethargy(); -// -// this._emitter = new Emitter(); -// this._event = { -// y: 0, -// x: 0, -// deltaX: 0, -// deltaY: 0 -// }; -// -// this.touchStartX = null; -// this.touchStartY = null; -// this.bodyTouchAction = null; -// } -// -// VirtualScroll.prototype._notify = function(e) { -// var evt = this._event; -// evt.x += evt.deltaX; -// evt.y += evt.deltaY; -// -// this._emitter.emit(EVT_ID, { -// x: evt.x, -// y: evt.y, -// deltaX: evt.deltaX, -// deltaY: evt.deltaY, -// originalEvent: e -// }); -// }; -// -// VirtualScroll.prototype._onWheel = function(e) { -// var options = this.options; -// if (this._lethargy && this._lethargy.check(e) === false) return; -// -// var evt = this._event; -// -// // In Chrome and in Firefox (at least the new one) -// evt.deltaX = e.wheelDeltaX || e.deltaX * -1; -// evt.deltaY = e.wheelDeltaY || e.deltaY * -1; -// -// // for our purpose deltamode = 1 means user is on a wheel mouse, not touch pad -// // real meaning: https://developer.mozilla.org/en-US/docs/Web/API/WheelEvent#Delta_modes -// if(support.isFirefox && e.deltaMode == 1) { -// evt.deltaX *= options.firefoxMultiplier; -// evt.deltaY *= options.firefoxMultiplier; -// } -// -// evt.deltaX *= options.mouseMultiplier; -// evt.deltaY *= options.mouseMultiplier; -// -// this._notify(e); -// }; -// -// VirtualScroll.prototype._onMouseWheel = function(e) { -// if (this.options.limitInertia && this._lethargy.check(e) === false) return; -// -// var evt = this._event; -// -// // In Safari, IE and in Chrome if 'wheel' isn't defined -// evt.deltaX = (e.wheelDeltaX) ? e.wheelDeltaX : 0; -// evt.deltaY = (e.wheelDeltaY) ? e.wheelDeltaY : e.wheelDelta; -// -// this._notify(e); -// }; -// -// VirtualScroll.prototype._onTouchStart = function(e) { -// var t = (e.targetTouches) ? e.targetTouches[0] : e; -// this.touchStartX = t.pageX; -// this.touchStartY = t.pageY; -// }; -// -// VirtualScroll.prototype._onTouchMove = function(e) { -// var options = this.options; -// if(options.preventTouch -// && !e.target.classList.contains(options.unpreventTouchClass)) { -// e.preventDefault(); -// } -// -// var evt = this._event; -// -// var t = (e.targetTouches) ? e.targetTouches[0] : e; -// -// evt.deltaX = (t.pageX - this.touchStartX) * options.touchMultiplier; -// evt.deltaY = (t.pageY - this.touchStartY) * options.touchMultiplier; -// -// this.touchStartX = t.pageX; -// this.touchStartY = t.pageY; -// -// this._notify(e); -// }; -// -// VirtualScroll.prototype._onKeyDown = function(e) { -// var evt = this._event; -// evt.deltaX = evt.deltaY = 0; -// -// switch(e.keyCode) { -// case keyCodes.LEFT: -// case keyCodes.UP: -// evt.deltaY = this.options.keyStep; -// break; -// -// case keyCodes.RIGHT: -// case keyCodes.DOWN: -// evt.deltaY = - this.options.keyStep; -// break; -// -// default: -// return; -// } -// -// this._notify(e); -// }; -// -// VirtualScroll.prototype._bind = function() { -// if(support.hasWheelEvent) this.el.addEventListener('wheel', this._onWheel); -// if(support.hasMouseWheelEvent) this.el.addEventListener('mousewheel', this._onMouseWheel); -// -// if(support.hasTouch) { -// this.el.addEventListener('touchstart', this._onTouchStart); -// this.el.addEventListener('touchmove', this._onTouchMove); -// } -// -// if(support.hasPointer && support.hasTouchWin) { -// this.bodyTouchAction = document.body.style.msTouchAction; -// document.body.style.msTouchAction = 'none'; -// this.el.addEventListener('MSPointerDown', this._onTouchStart, true); -// this.el.addEventListener('MSPointerMove', this._onTouchMove, true); -// } -// -// if(support.hasKeyDown) document.addEventListener('keydown', this._onKeyDown); -// }; -// -// VirtualScroll.prototype._unbind = function() { -// if(support.hasWheelEvent) this.el.removeEventListener('wheel', this._onWheel); -// if(support.hasMouseWheelEvent) this.el.removeEventListener('mousewheel', this._onMouseWheel); -// -// if(support.hasTouch) { -// this.el.removeEventListener('touchstart', this._onTouchStart); -// this.el.removeEventListener('touchmove', this._onTouchMove); -// } -// -// if(support.hasPointer && support.hasTouchWin) { -// document.body.style.msTouchAction = this.bodyTouchAction; -// this.el.removeEventListener('MSPointerDown', this._onTouchStart, true); -// this.el.removeEventListener('MSPointerMove', this._onTouchMove, true); -// } -// -// if(support.hasKeyDown) document.removeEventListener('keydown', this._onKeyDown); -// }; -// -// VirtualScroll.prototype.on = function(cb, ctx) { -// this._emitter.on(EVT_ID, cb, ctx); -// -// var events = this._emitter.e; -// if (events && events[EVT_ID] && events[EVT_ID].length === 1) this._bind(); -// }; -// -// VirtualScroll.prototype.off = function(cb, ctx) { -// this._emitter.off(EVT_ID, cb, ctx); -// -// var events = this._emitter.e; -// if (!events[EVT_ID] || events[EVT_ID].length <= 0) this._unbind(); -// }; -// -// VirtualScroll.prototype.reset = function() { -// var evt = this._event; -// evt.x = 0; -// evt.y = 0; -// }; -// -// VirtualScroll.prototype.destroy = function() { -// this._emitter.off(); -// this._unbind(); -// }; diff --git a/public/app/core/components/wizard/wizard.html b/public/app/core/components/wizard/wizard.html deleted file mode 100644 index 9d3f680649a..00000000000 --- a/public/app/core/components/wizard/wizard.html +++ /dev/null @@ -1,32 +0,0 @@ - - diff --git a/public/app/core/components/wizard/wizard.ts b/public/app/core/components/wizard/wizard.ts deleted file mode 100644 index 2ae38cf9e03..00000000000 --- a/public/app/core/components/wizard/wizard.ts +++ /dev/null @@ -1,73 +0,0 @@ -/// - -import config from 'app/core/config'; -import _ from 'lodash'; -import $ from 'jquery'; - -import coreModule from 'app/core/core_module'; -import appEvents from 'app/core/app_events'; - -export class WizardSrv { - /** @ngInject */ - constructor() { - } -} - -export interface WizardStep { - name: string; - type: string; - process: any; -} - -export class SelectOptionStep { - type: string; - name: string; - fulfill: any; - - constructor() { - this.type = 'select'; - } - - process() { - return new Promise((fulfill, reject) => { - - }); - } -} - -export class WizardFlow { - name: string; - steps: WizardStep[]; - - constructor(name) { - this.name = name; - this.steps = []; - } - - addStep(step) { - this.steps.push(step); - } - - next(index) { - var step = this.steps[0]; - - return step.process().then(() => { - if (this.steps.length === index+1) { - return; - } - - return this.next(index+1); - }); - } - - start() { - appEvents.emit('show-modal', { - src: 'public/app/core/components/wizard/wizard.html', - model: this - }); - - return this.next(0); - } -} - -coreModule.service('wizardSrv', WizardSrv); diff --git a/public/app/core/core.ts b/public/app/core/core.ts index 140c75fe863..d8be6c2a88d 100644 --- a/public/app/core/core.ts +++ b/public/app/core/core.ts @@ -35,7 +35,6 @@ import {layoutSelector} from './components/layout_selector/layout_selector'; import {switchDirective} from './components/switch'; import {dashboardSelector} from './components/dashboard_selector'; import {queryPartEditorDirective} from './components/query_part/query_part_editor'; -import {WizardFlow} from './components/wizard/wizard'; import {formDropdownDirective} from './components/form_dropdown/form_dropdown'; import 'app/core/controllers/all'; import 'app/core/services/all'; @@ -48,11 +47,9 @@ import {assignModelProperties} from './utils/model_utils'; import {contextSrv} from './services/context_srv'; import {KeybindingSrv} from './services/keybindingSrv'; import {helpModal} from './components/help/help'; -import {collapseBox} from './components/collapse_box'; +import {PasswordStrength} from './components/PasswordStrength'; import {JsonExplorer} from './components/json_explorer/json_explorer'; import {NavModelSrv, NavModel} from './nav_model_srv'; -import {CoolButton} from './components/CoolButton'; - export { arrayJoin, @@ -70,16 +67,14 @@ export { appEvents, dashboardSelector, queryPartEditorDirective, - WizardFlow, colors, formDropdownDirective, assignModelProperties, contextSrv, KeybindingSrv, helpModal, - collapseBox, JsonExplorer, NavModelSrv, NavModel, - CoolButton, + PasswordStrength, }; diff --git a/public/app/core/directives/password_strength.js b/public/app/core/directives/password_strength.js index fa3f8638ba1..089ff08c13b 100644 --- a/public/app/core/directives/password_strength.js +++ b/public/app/core/directives/password_strength.js @@ -4,7 +4,7 @@ define([ function (coreModule) { 'use strict'; - coreModule.default.directive('passwordStrength', function() { + coreModule.default.directive('passwordStrength2', function() { var template = '
' + '{{strengthText}}' + '
'; diff --git a/public/app/core/specs/PasswordStrength_specs.tsx b/public/app/core/specs/PasswordStrength_specs.tsx new file mode 100644 index 00000000000..0ba239b2637 --- /dev/null +++ b/public/app/core/specs/PasswordStrength_specs.tsx @@ -0,0 +1,14 @@ +// import React from 'react'; +// import {describe, beforeEach, it, sinon, expect} from 'test/lib/common'; +// import {shallow} from 'enzyme'; +// +// import {PasswordStrength} from '../components/PasswordStrength'; +// +// describe('PasswordStrength', () => { +// +// it.skip('should have class bad if length below 4', () => { +// const wrapper = shallow(); +// expect(wrapper.find(".password-strength-bad")).to.have.length(3); +// }); +// }); +// diff --git a/public/app/features/plugins/partials/ds_edit.html b/public/app/features/plugins/partials/ds_edit.html index fd978d8b704..f01ca47153b 100644 --- a/public/app/features/plugins/partials/ds_edit.html +++ b/public/app/features/plugins/partials/ds_edit.html @@ -1,10 +1,6 @@
- - - - -
+
diff --git a/public/sass/_grafana.scss b/public/sass/_grafana.scss index 77afde21e37..cbced4cbca1 100644 --- a/public/sass/_grafana.scss +++ b/public/sass/_grafana.scss @@ -76,7 +76,6 @@ @import "components/edit_sidemenu.scss"; @import "components/row.scss"; @import "components/json_explorer.scss"; -@import "components/collapse_box.scss"; @import "components/code_editor.scss"; // PAGES diff --git a/public/sass/components/_collapse_box.scss b/public/sass/components/_collapse_box.scss deleted file mode 100644 index 86658cfcfec..00000000000 --- a/public/sass/components/_collapse_box.scss +++ /dev/null @@ -1,46 +0,0 @@ -.collapse-box { - margin-bottom: $spacer; - - &--error { - .collapse-box__header { - border-color: $collapse-box-body-error-border; - } - .collapse-box__body { - border-color: $collapse-box-body-error-border; - } - } - -} - -.collapse-box__header { - display: flex; - flex-direction: row; - padding: $input-padding-y $input-padding-x; - margin-right: $gf-form-margin; - background-color: $input-label-bg; - font-size: $font-size-sm; - margin-right: $gf-form-margin; - border: $input-btn-border-width solid $collapse-box-body-border; - @include border-radius($label-border-radius-sm); -} - -.collapse-box__header-title { - flex-grow: 1; -} - -.collapse-box__body { - padding: $input-padding-y*2 $input-padding-x; - display: block; - margin-right: $gf-form-margin; - border: $input-btn-border-width solid $collapse-box-body-border; - border-top: none; - @include border-radius($label-border-radius-sm); -} - -.collapse-box__header-actions { - display: flex; - flex-direction: row; - a { - margin-left: $spacer; - } -} diff --git a/public/test/test-main.js b/public/test/test-main.js index 6df23f11106..ed20d19fd82 100644 --- a/public/test/test-main.js +++ b/public/test/test-main.js @@ -10,6 +10,9 @@ baseURL: '/base/', defaultJSExtensions: true, paths: { + 'react': 'vendor/npm/react/dist/react.js', + 'react-dom': 'vendor/npm/react-dom/dist/react-dom.js', + 'ngreact': 'vendor/npm/ngreact/ngReact.js', 'mousetrap': 'vendor/npm/mousetrap/mousetrap.js', 'eventemitter3': 'vendor/npm/eventemitter3/index.js', 'remarkable': 'vendor/npm/remarkable/dist/remarkable.js', @@ -83,7 +86,7 @@ function file2moduleName(filePath) { return filePath.replace(/\\/g, '/') - .replace(/^\/base\//, '') + .replace(/^\/base\//, '') .replace(/\.\w*$/, ''); } @@ -112,12 +115,12 @@ // load specs return Promise.all( Object.keys(window.__karma__.files) // All files served by Karma. - .filter(onlySpecFiles) - .map(file2moduleName) - .map(function(path) { - // console.log(path); - return System.import(path); - })); + .filter(onlySpecFiles) + .map(file2moduleName) + .map(function(path) { + // console.log(path); + return System.import(path); + })); }).then(function() { window.__karma__.start(); }, function(error) { diff --git a/tasks/options/watch.js b/tasks/options/watch.js index 54ecbd6672e..c421ec3e01e 100644 --- a/tasks/options/watch.js +++ b/tasks/options/watch.js @@ -23,6 +23,7 @@ module.exports = function(config, grunt) { gaze([ config.srcDir + '/app/**/*', + config.srcDir + '/test/**/*', config.srcDir + '/sass/**/*', ], function(err, watcher) { diff --git a/yarn.lock b/yarn.lock index 7b6472e84e6..9b626f54ac5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,17 @@ # yarn lockfile v1 +"@types/cheerio@*": + version "0.22.2" + resolved "https://registry.yarnpkg.com/@types/cheerio/-/cheerio-0.22.2.tgz#539625874bc856086ad491c2fdc9b10c05ae308e" + +"@types/enzyme@^2.8.8": + version "2.8.8" + resolved "https://registry.yarnpkg.com/@types/enzyme/-/enzyme-2.8.8.tgz#ddef76ac5435bb6d96c129b2b541d72c0ce75a41" + dependencies: + "@types/cheerio" "*" + "@types/react" "*" + "@types/react-dom@^15.5.4": version "15.5.4" resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-15.5.4.tgz#3f75ba86a2ce9a7d1d9e7d1ee3f186f3a9652d8f" @@ -3736,6 +3747,13 @@ react-dom@^15.6.1: object-assign "^4.1.0" prop-types "^15.5.10" +react-test-renderer@^15.6.1: + version "15.6.1" + resolved "https://registry.yarnpkg.com/react-test-renderer/-/react-test-renderer-15.6.1.tgz#026f4a5bb5552661fd2cc4bbcd0d4bc8a35ebf7e" + dependencies: + fbjs "^0.8.9" + object-assign "^4.1.0" + react@^15.6.1: version "15.6.1" resolved "https://registry.yarnpkg.com/react/-/react-15.6.1.tgz#baa8434ec6780bde997cdc380b79cd33b96393df"