flipper-ui 0.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (80) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.rspec +1 -0
  4. data/Gemfile +17 -0
  5. data/Guardfile +26 -0
  6. data/LICENSE +22 -0
  7. data/README.md +101 -0
  8. data/Rakefile +7 -0
  9. data/examples/basic.ru +44 -0
  10. data/examples/flipper.html +14 -0
  11. data/examples/flipper.png +0 -0
  12. data/flipper-ui.gemspec +21 -0
  13. data/lib/flipper-ui.rb +1 -0
  14. data/lib/flipper/ui.rb +23 -0
  15. data/lib/flipper/ui/action.rb +172 -0
  16. data/lib/flipper/ui/action_collection.rb +20 -0
  17. data/lib/flipper/ui/actions/features.rb +21 -0
  18. data/lib/flipper/ui/actions/file.rb +17 -0
  19. data/lib/flipper/ui/actions/gate.rb +143 -0
  20. data/lib/flipper/ui/actions/index.rb +17 -0
  21. data/lib/flipper/ui/assets/javascripts/application.coffee +305 -0
  22. data/lib/flipper/ui/assets/javascripts/spine/ajax.coffee +223 -0
  23. data/lib/flipper/ui/assets/javascripts/spine/list.coffee +43 -0
  24. data/lib/flipper/ui/assets/javascripts/spine/local.coffee +16 -0
  25. data/lib/flipper/ui/assets/javascripts/spine/manager.coffee +83 -0
  26. data/lib/flipper/ui/assets/javascripts/spine/relation.coffee +148 -0
  27. data/lib/flipper/ui/assets/javascripts/spine/route.coffee +146 -0
  28. data/lib/flipper/ui/assets/javascripts/spine/spine.coffee +542 -0
  29. data/lib/flipper/ui/assets/javascripts/spine/version +1 -0
  30. data/lib/flipper/ui/assets/stylesheets/application.scss +237 -0
  31. data/lib/flipper/ui/decorators/feature.rb +37 -0
  32. data/lib/flipper/ui/decorators/gate.rb +36 -0
  33. data/lib/flipper/ui/error.rb +10 -0
  34. data/lib/flipper/ui/eruby.rb +11 -0
  35. data/lib/flipper/ui/middleware.rb +66 -0
  36. data/lib/flipper/ui/public/css/application.css +183 -0
  37. data/lib/flipper/ui/public/css/images/animated-overlay.gif +0 -0
  38. data/lib/flipper/ui/public/css/images/ui-bg_diagonals-thick_18_b81900_40x40.png +0 -0
  39. data/lib/flipper/ui/public/css/images/ui-bg_diagonals-thick_20_666666_40x40.png +0 -0
  40. data/lib/flipper/ui/public/css/images/ui-bg_flat_10_000000_40x100.png +0 -0
  41. data/lib/flipper/ui/public/css/images/ui-bg_glass_100_f6f6f6_1x400.png +0 -0
  42. data/lib/flipper/ui/public/css/images/ui-bg_glass_100_fdf5ce_1x400.png +0 -0
  43. data/lib/flipper/ui/public/css/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
  44. data/lib/flipper/ui/public/css/images/ui-bg_gloss-wave_35_f6a828_500x100.png +0 -0
  45. data/lib/flipper/ui/public/css/images/ui-bg_highlight-soft_100_eeeeee_1x100.png +0 -0
  46. data/lib/flipper/ui/public/css/images/ui-bg_highlight-soft_75_ffe45c_1x100.png +0 -0
  47. data/lib/flipper/ui/public/css/images/ui-icons_222222_256x240.png +0 -0
  48. data/lib/flipper/ui/public/css/images/ui-icons_228ef1_256x240.png +0 -0
  49. data/lib/flipper/ui/public/css/images/ui-icons_ef8c08_256x240.png +0 -0
  50. data/lib/flipper/ui/public/css/images/ui-icons_ffd27a_256x240.png +0 -0
  51. data/lib/flipper/ui/public/css/images/ui-icons_ffffff_256x240.png +0 -0
  52. data/lib/flipper/ui/public/css/jquery-ui-1.10.3.slider.min.css +5 -0
  53. data/lib/flipper/ui/public/images/logo.png +0 -0
  54. data/lib/flipper/ui/public/images/remove.png +0 -0
  55. data/lib/flipper/ui/public/js/application.js +544 -0
  56. data/lib/flipper/ui/public/js/handlebars.js +1992 -0
  57. data/lib/flipper/ui/public/js/jquery-ui-1.10.3.slider.min.js +6 -0
  58. data/lib/flipper/ui/public/js/jquery.js +9555 -0
  59. data/lib/flipper/ui/public/js/jquery.min.js +4 -0
  60. data/lib/flipper/ui/public/js/jquery.min.map +1 -0
  61. data/lib/flipper/ui/public/js/spine/ajax.js +320 -0
  62. data/lib/flipper/ui/public/js/spine/list.js +72 -0
  63. data/lib/flipper/ui/public/js/spine/local.js +29 -0
  64. data/lib/flipper/ui/public/js/spine/manager.js +157 -0
  65. data/lib/flipper/ui/public/js/spine/relation.js +260 -0
  66. data/lib/flipper/ui/public/js/spine/route.js +223 -0
  67. data/lib/flipper/ui/public/js/spine/spine.js +927 -0
  68. data/lib/flipper/ui/util.rb +12 -0
  69. data/lib/flipper/ui/version.rb +5 -0
  70. data/lib/flipper/ui/views/index.erb +9 -0
  71. data/lib/flipper/ui/views/layout.erb +161 -0
  72. data/script/bootstrap +21 -0
  73. data/script/server +19 -0
  74. data/script/test +30 -0
  75. data/spec/flipper/ui/decorators/feature_spec.rb +59 -0
  76. data/spec/flipper/ui/decorators/gate_spec.rb +47 -0
  77. data/spec/flipper/ui/util_spec.rb +18 -0
  78. data/spec/flipper/ui_spec.rb +470 -0
  79. data/spec/helper.rb +35 -0
  80. metadata +168 -0
@@ -0,0 +1,5 @@
1
+ /*! jQuery UI - v1.10.3 - 2013-05-21
2
+ * http://jqueryui.com
3
+ * Includes: jquery.ui.core.css, jquery.ui.slider.css
4
+ * To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Trebuchet%20MS%2CTahoma%2CVerdana%2CArial%2Csans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=4px&bgColorHeader=f6a828&bgTextureHeader=gloss_wave&bgImgOpacityHeader=35&borderColorHeader=e78f08&fcHeader=ffffff&iconColorHeader=ffffff&bgColorContent=eeeeee&bgTextureContent=highlight_soft&bgImgOpacityContent=100&borderColorContent=dddddd&fcContent=333333&iconColorContent=222222&bgColorDefault=f6f6f6&bgTextureDefault=glass&bgImgOpacityDefault=100&borderColorDefault=cccccc&fcDefault=1c94c4&iconColorDefault=ef8c08&bgColorHover=fdf5ce&bgTextureHover=glass&bgImgOpacityHover=100&borderColorHover=fbcb09&fcHover=c77405&iconColorHover=ef8c08&bgColorActive=ffffff&bgTextureActive=glass&bgImgOpacityActive=65&borderColorActive=fbd850&fcActive=eb8f00&iconColorActive=ef8c08&bgColorHighlight=ffe45c&bgTextureHighlight=highlight_soft&bgImgOpacityHighlight=75&borderColorHighlight=fed22f&fcHighlight=363636&iconColorHighlight=228ef1&bgColorError=b81900&bgTextureError=diagonals_thick&bgImgOpacityError=18&borderColorError=cd0a0a&fcError=ffffff&iconColorError=ffd27a&bgColorOverlay=666666&bgTextureOverlay=diagonals_thick&bgImgOpacityOverlay=20&opacityOverlay=50&bgColorShadow=000000&bgTextureShadow=flat&bgImgOpacityShadow=10&opacityShadow=20&thicknessShadow=5px&offsetTopShadow=-5px&offsetLeftShadow=-5px&cornerRadiusShadow=5px
5
+ * Copyright 2013 jQuery Foundation and other contributors Licensed MIT */.ui-helper-hidden{display:none}.ui-helper-hidden-accessible{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.ui-helper-reset{margin:0;padding:0;border:0;outline:0;line-height:1.3;text-decoration:none;font-size:100%;list-style:none}.ui-helper-clearfix:before,.ui-helper-clearfix:after{content:"";display:table;border-collapse:collapse}.ui-helper-clearfix:after{clear:both}.ui-helper-clearfix{min-height:0}.ui-helper-zfix{width:100%;height:100%;top:0;left:0;position:absolute;opacity:0;filter:Alpha(Opacity=0)}.ui-front{z-index:100}.ui-state-disabled{cursor:default!important}.ui-icon{display:block;text-indent:-99999px;overflow:hidden;background-repeat:no-repeat}.ui-widget-overlay{position:fixed;top:0;left:0;width:100%;height:100%}.ui-slider{position:relative;text-align:left}.ui-slider .ui-slider-handle{position:absolute;z-index:2;width:1.2em;height:1.2em;cursor:default}.ui-slider .ui-slider-range{position:absolute;z-index:1;font-size:.7em;display:block;border:0;background-position:0 0}.ui-slider.ui-state-disabled .ui-slider-handle,.ui-slider.ui-state-disabled .ui-slider-range{filter:inherit}.ui-slider-horizontal{height:.8em}.ui-slider-horizontal .ui-slider-handle{top:-.3em;margin-left:-.6em}.ui-slider-horizontal .ui-slider-range{top:0;height:100%}.ui-slider-horizontal .ui-slider-range-min{left:0}.ui-slider-horizontal .ui-slider-range-max{right:0}.ui-slider-vertical{width:.8em;height:100px}.ui-slider-vertical .ui-slider-handle{left:-.3em;margin-left:0;margin-bottom:-.6em}.ui-slider-vertical .ui-slider-range{left:0;width:100%}.ui-slider-vertical .ui-slider-range-min{bottom:0}.ui-slider-vertical .ui-slider-range-max{top:0}.ui-widget{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1.1em}.ui-widget .ui-widget{font-size:1em}.ui-widget input,.ui-widget select,.ui-widget textarea,.ui-widget button{font-family:Trebuchet MS,Tahoma,Verdana,Arial,sans-serif;font-size:1em}.ui-widget-content{border:1px solid #ddd;background:#eee url(images/ui-bg_highlight-soft_100_eeeeee_1x100.png) 50% top repeat-x;color:#333}.ui-widget-content a{color:#333}.ui-widget-header{border:1px solid #396;background:#396;color:#fff;font-weight:bold}.ui-widget-header a{color:#fff}.ui-state-default,.ui-widget-content .ui-state-default,.ui-widget-header .ui-state-default{border:1px solid #ccc;background:#f6f6f6 url(images/ui-bg_glass_100_f6f6f6_1x400.png) 50% 50% repeat-x;font-weight:bold;color:#1c94c4}.ui-state-default a,.ui-state-default a:link,.ui-state-default a:visited{color:#1c94c4;text-decoration:none}.ui-state-hover,.ui-widget-content .ui-state-hover,.ui-widget-header .ui-state-hover,.ui-state-focus,.ui-widget-content .ui-state-focus,.ui-widget-header .ui-state-focus{border:1px solid #73d0a1;background:#9db;font-weight:bold;color:#c77405}.ui-state-hover a,.ui-state-hover a:hover,.ui-state-hover a:link,.ui-state-hover a:visited{color:#c77405;text-decoration:none}.ui-state-active,.ui-widget-content .ui-state-active,.ui-widget-header .ui-state-active{border:1px solid #b2e5cc;background:#ced;font-weight:bold;color:#eb8f00}.ui-state-active a,.ui-state-active a:link,.ui-state-active a:visited{color:#eb8f00;text-decoration:none}.ui-state-highlight,.ui-widget-content .ui-state-highlight,.ui-widget-header .ui-state-highlight{border:1px solid #fed22f;background:#ffe45c url(images/ui-bg_highlight-soft_75_ffe45c_1x100.png) 50% top repeat-x;color:#363636}.ui-state-highlight a,.ui-widget-content .ui-state-highlight a,.ui-widget-header .ui-state-highlight a{color:#363636}.ui-state-error,.ui-widget-content .ui-state-error,.ui-widget-header .ui-state-error{border:1px solid #cd0a0a;background:#b81900 url(images/ui-bg_diagonals-thick_18_b81900_40x40.png) 50% 50% repeat;color:#fff}.ui-state-error a,.ui-widget-content .ui-state-error a,.ui-widget-header .ui-state-error a{color:#fff}.ui-state-error-text,.ui-widget-content .ui-state-error-text,.ui-widget-header .ui-state-error-text{color:#fff}.ui-priority-primary,.ui-widget-content .ui-priority-primary,.ui-widget-header .ui-priority-primary{font-weight:bold}.ui-priority-secondary,.ui-widget-content .ui-priority-secondary,.ui-widget-header .ui-priority-secondary{opacity:.7;filter:Alpha(Opacity=70);font-weight:normal}.ui-state-disabled,.ui-widget-content .ui-state-disabled,.ui-widget-header .ui-state-disabled{opacity:.35;filter:Alpha(Opacity=35);background-image:none}.ui-state-disabled .ui-icon{filter:Alpha(Opacity=35)}.ui-icon{width:16px;height:16px}.ui-icon,.ui-widget-content .ui-icon{background-image:url(images/ui-icons_222222_256x240.png)}.ui-widget-header .ui-icon{background-image:url(images/ui-icons_ffffff_256x240.png)}.ui-state-default .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-hover .ui-icon,.ui-state-focus .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-active .ui-icon{background-image:url(images/ui-icons_ef8c08_256x240.png)}.ui-state-highlight .ui-icon{background-image:url(images/ui-icons_228ef1_256x240.png)}.ui-state-error .ui-icon,.ui-state-error-text .ui-icon{background-image:url(images/ui-icons_ffd27a_256x240.png)}.ui-icon-blank{background-position:16px 16px}.ui-icon-carat-1-n{background-position:0 0}.ui-icon-carat-1-ne{background-position:-16px 0}.ui-icon-carat-1-e{background-position:-32px 0}.ui-icon-carat-1-se{background-position:-48px 0}.ui-icon-carat-1-s{background-position:-64px 0}.ui-icon-carat-1-sw{background-position:-80px 0}.ui-icon-carat-1-w{background-position:-96px 0}.ui-icon-carat-1-nw{background-position:-112px 0}.ui-icon-carat-2-n-s{background-position:-128px 0}.ui-icon-carat-2-e-w{background-position:-144px 0}.ui-icon-triangle-1-n{background-position:0 -16px}.ui-icon-triangle-1-ne{background-position:-16px -16px}.ui-icon-triangle-1-e{background-position:-32px -16px}.ui-icon-triangle-1-se{background-position:-48px -16px}.ui-icon-triangle-1-s{background-position:-64px -16px}.ui-icon-triangle-1-sw{background-position:-80px -16px}.ui-icon-triangle-1-w{background-position:-96px -16px}.ui-icon-triangle-1-nw{background-position:-112px -16px}.ui-icon-triangle-2-n-s{background-position:-128px -16px}.ui-icon-triangle-2-e-w{background-position:-144px -16px}.ui-icon-arrow-1-n{background-position:0 -32px}.ui-icon-arrow-1-ne{background-position:-16px -32px}.ui-icon-arrow-1-e{background-position:-32px -32px}.ui-icon-arrow-1-se{background-position:-48px -32px}.ui-icon-arrow-1-s{background-position:-64px -32px}.ui-icon-arrow-1-sw{background-position:-80px -32px}.ui-icon-arrow-1-w{background-position:-96px -32px}.ui-icon-arrow-1-nw{background-position:-112px -32px}.ui-icon-arrow-2-n-s{background-position:-128px -32px}.ui-icon-arrow-2-ne-sw{background-position:-144px -32px}.ui-icon-arrow-2-e-w{background-position:-160px -32px}.ui-icon-arrow-2-se-nw{background-position:-176px -32px}.ui-icon-arrowstop-1-n{background-position:-192px -32px}.ui-icon-arrowstop-1-e{background-position:-208px -32px}.ui-icon-arrowstop-1-s{background-position:-224px -32px}.ui-icon-arrowstop-1-w{background-position:-240px -32px}.ui-icon-arrowthick-1-n{background-position:0 -48px}.ui-icon-arrowthick-1-ne{background-position:-16px -48px}.ui-icon-arrowthick-1-e{background-position:-32px -48px}.ui-icon-arrowthick-1-se{background-position:-48px -48px}.ui-icon-arrowthick-1-s{background-position:-64px -48px}.ui-icon-arrowthick-1-sw{background-position:-80px -48px}.ui-icon-arrowthick-1-w{background-position:-96px -48px}.ui-icon-arrowthick-1-nw{background-position:-112px -48px}.ui-icon-arrowthick-2-n-s{background-position:-128px -48px}.ui-icon-arrowthick-2-ne-sw{background-position:-144px -48px}.ui-icon-arrowthick-2-e-w{background-position:-160px -48px}.ui-icon-arrowthick-2-se-nw{background-position:-176px -48px}.ui-icon-arrowthickstop-1-n{background-position:-192px -48px}.ui-icon-arrowthickstop-1-e{background-position:-208px -48px}.ui-icon-arrowthickstop-1-s{background-position:-224px -48px}.ui-icon-arrowthickstop-1-w{background-position:-240px -48px}.ui-icon-arrowreturnthick-1-w{background-position:0 -64px}.ui-icon-arrowreturnthick-1-n{background-position:-16px -64px}.ui-icon-arrowreturnthick-1-e{background-position:-32px -64px}.ui-icon-arrowreturnthick-1-s{background-position:-48px -64px}.ui-icon-arrowreturn-1-w{background-position:-64px -64px}.ui-icon-arrowreturn-1-n{background-position:-80px -64px}.ui-icon-arrowreturn-1-e{background-position:-96px -64px}.ui-icon-arrowreturn-1-s{background-position:-112px -64px}.ui-icon-arrowrefresh-1-w{background-position:-128px -64px}.ui-icon-arrowrefresh-1-n{background-position:-144px -64px}.ui-icon-arrowrefresh-1-e{background-position:-160px -64px}.ui-icon-arrowrefresh-1-s{background-position:-176px -64px}.ui-icon-arrow-4{background-position:0 -80px}.ui-icon-arrow-4-diag{background-position:-16px -80px}.ui-icon-extlink{background-position:-32px -80px}.ui-icon-newwin{background-position:-48px -80px}.ui-icon-refresh{background-position:-64px -80px}.ui-icon-shuffle{background-position:-80px -80px}.ui-icon-transfer-e-w{background-position:-96px -80px}.ui-icon-transferthick-e-w{background-position:-112px -80px}.ui-icon-folder-collapsed{background-position:0 -96px}.ui-icon-folder-open{background-position:-16px -96px}.ui-icon-document{background-position:-32px -96px}.ui-icon-document-b{background-position:-48px -96px}.ui-icon-note{background-position:-64px -96px}.ui-icon-mail-closed{background-position:-80px -96px}.ui-icon-mail-open{background-position:-96px -96px}.ui-icon-suitcase{background-position:-112px -96px}.ui-icon-comment{background-position:-128px -96px}.ui-icon-person{background-position:-144px -96px}.ui-icon-print{background-position:-160px -96px}.ui-icon-trash{background-position:-176px -96px}.ui-icon-locked{background-position:-192px -96px}.ui-icon-unlocked{background-position:-208px -96px}.ui-icon-bookmark{background-position:-224px -96px}.ui-icon-tag{background-position:-240px -96px}.ui-icon-home{background-position:0 -112px}.ui-icon-flag{background-position:-16px -112px}.ui-icon-calendar{background-position:-32px -112px}.ui-icon-cart{background-position:-48px -112px}.ui-icon-pencil{background-position:-64px -112px}.ui-icon-clock{background-position:-80px -112px}.ui-icon-disk{background-position:-96px -112px}.ui-icon-calculator{background-position:-112px -112px}.ui-icon-zoomin{background-position:-128px -112px}.ui-icon-zoomout{background-position:-144px -112px}.ui-icon-search{background-position:-160px -112px}.ui-icon-wrench{background-position:-176px -112px}.ui-icon-gear{background-position:-192px -112px}.ui-icon-heart{background-position:-208px -112px}.ui-icon-star{background-position:-224px -112px}.ui-icon-link{background-position:-240px -112px}.ui-icon-cancel{background-position:0 -128px}.ui-icon-plus{background-position:-16px -128px}.ui-icon-plusthick{background-position:-32px -128px}.ui-icon-minus{background-position:-48px -128px}.ui-icon-minusthick{background-position:-64px -128px}.ui-icon-close{background-position:-80px -128px}.ui-icon-closethick{background-position:-96px -128px}.ui-icon-key{background-position:-112px -128px}.ui-icon-lightbulb{background-position:-128px -128px}.ui-icon-scissors{background-position:-144px -128px}.ui-icon-clipboard{background-position:-160px -128px}.ui-icon-copy{background-position:-176px -128px}.ui-icon-contact{background-position:-192px -128px}.ui-icon-image{background-position:-208px -128px}.ui-icon-video{background-position:-224px -128px}.ui-icon-script{background-position:-240px -128px}.ui-icon-alert{background-position:0 -144px}.ui-icon-info{background-position:-16px -144px}.ui-icon-notice{background-position:-32px -144px}.ui-icon-help{background-position:-48px -144px}.ui-icon-check{background-position:-64px -144px}.ui-icon-bullet{background-position:-80px -144px}.ui-icon-radio-on{background-position:-96px -144px}.ui-icon-radio-off{background-position:-112px -144px}.ui-icon-pin-w{background-position:-128px -144px}.ui-icon-pin-s{background-position:-144px -144px}.ui-icon-play{background-position:0 -160px}.ui-icon-pause{background-position:-16px -160px}.ui-icon-seek-next{background-position:-32px -160px}.ui-icon-seek-prev{background-position:-48px -160px}.ui-icon-seek-end{background-position:-64px -160px}.ui-icon-seek-start{background-position:-80px -160px}.ui-icon-seek-first{background-position:-80px -160px}.ui-icon-stop{background-position:-96px -160px}.ui-icon-eject{background-position:-112px -160px}.ui-icon-volume-off{background-position:-128px -160px}.ui-icon-volume-on{background-position:-144px -160px}.ui-icon-power{background-position:0 -176px}.ui-icon-signal-diag{background-position:-16px -176px}.ui-icon-signal{background-position:-32px -176px}.ui-icon-battery-0{background-position:-48px -176px}.ui-icon-battery-1{background-position:-64px -176px}.ui-icon-battery-2{background-position:-80px -176px}.ui-icon-battery-3{background-position:-96px -176px}.ui-icon-circle-plus{background-position:0 -192px}.ui-icon-circle-minus{background-position:-16px -192px}.ui-icon-circle-close{background-position:-32px -192px}.ui-icon-circle-triangle-e{background-position:-48px -192px}.ui-icon-circle-triangle-s{background-position:-64px -192px}.ui-icon-circle-triangle-w{background-position:-80px -192px}.ui-icon-circle-triangle-n{background-position:-96px -192px}.ui-icon-circle-arrow-e{background-position:-112px -192px}.ui-icon-circle-arrow-s{background-position:-128px -192px}.ui-icon-circle-arrow-w{background-position:-144px -192px}.ui-icon-circle-arrow-n{background-position:-160px -192px}.ui-icon-circle-zoomin{background-position:-176px -192px}.ui-icon-circle-zoomout{background-position:-192px -192px}.ui-icon-circle-check{background-position:-208px -192px}.ui-icon-circlesmall-plus{background-position:0 -208px}.ui-icon-circlesmall-minus{background-position:-16px -208px}.ui-icon-circlesmall-close{background-position:-32px -208px}.ui-icon-squaresmall-plus{background-position:-48px -208px}.ui-icon-squaresmall-minus{background-position:-64px -208px}.ui-icon-squaresmall-close{background-position:-80px -208px}.ui-icon-grip-dotted-vertical{background-position:0 -224px}.ui-icon-grip-dotted-horizontal{background-position:-16px -224px}.ui-icon-grip-solid-vertical{background-position:-32px -224px}.ui-icon-grip-solid-horizontal{background-position:-48px -224px}.ui-icon-gripsmall-diagonal-se{background-position:-64px -224px}.ui-icon-grip-diagonal-se{background-position:-80px -224px}.ui-corner-all,.ui-corner-top,.ui-corner-left,.ui-corner-tl{border-top-left-radius:4px}.ui-corner-all,.ui-corner-top,.ui-corner-right,.ui-corner-tr{border-top-right-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-left,.ui-corner-bl{border-bottom-left-radius:4px}.ui-corner-all,.ui-corner-bottom,.ui-corner-right,.ui-corner-br{border-bottom-right-radius:4px}.ui-widget-overlay{background:#666 url(images/ui-bg_diagonals-thick_20_666666_40x40.png) 50% 50% repeat;opacity:.5;filter:Alpha(Opacity=50)}.ui-widget-shadow{margin:-5px 0 0 -5px;padding:5px;background:#000 url(images/ui-bg_flat_10_000000_40x100.png) 50% 50% repeat-x;opacity:.2;filter:Alpha(Opacity=20);border-radius:5px}
@@ -0,0 +1,544 @@
1
+ (function() {
2
+ var App, Feature, Gate,
3
+ __hasProp = {}.hasOwnProperty,
4
+ __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
5
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
6
+
7
+ Feature = (function(_super) {
8
+
9
+ __extends(Feature, _super);
10
+
11
+ Feature.configure("Feature", "id", "name", "state", "description", "gates");
12
+
13
+ Feature.extend(Spine.Model.Ajax);
14
+
15
+ Feature.extend({
16
+ url: "" + Flipper.Config.url + "/features"
17
+ });
18
+
19
+ function Feature() {
20
+ var _this = this;
21
+ Feature.__super__.constructor.apply(this, arguments);
22
+ this.gates = this.gates.map(function(data) {
23
+ data.feature_id = _this.id;
24
+ return new Gate(data);
25
+ });
26
+ }
27
+
28
+ Feature.prototype.gate = function(name) {
29
+ var gates;
30
+ gates = this.gates.filter(function(gate) {
31
+ return gate.name === name;
32
+ });
33
+ return gates[0];
34
+ };
35
+
36
+ return Feature;
37
+
38
+ })(Spine.Model);
39
+
40
+ window.Feature = Feature;
41
+
42
+ Gate = (function(_super) {
43
+
44
+ __extends(Gate, _super);
45
+
46
+ Gate.configure("Gate", "feature_id", "key", "name", "value");
47
+
48
+ function Gate() {
49
+ Gate.__super__.constructor.apply(this, arguments);
50
+ }
51
+
52
+ Gate.prototype.url = function() {
53
+ return "" + Flipper.Config.url + "/features/" + (encodeURIComponent(this.feature_id)) + "/" + (encodeURIComponent(this.name));
54
+ };
55
+
56
+ Gate.prototype.disableSetMember = function(member, success_callback, error_callback) {
57
+ return this.setMember('disable', member, success_callback, error_callback);
58
+ };
59
+
60
+ Gate.prototype.enableSetMember = function(member, success_callback, error_callback) {
61
+ return this.setMember('enable', member, success_callback, error_callback);
62
+ };
63
+
64
+ Gate.prototype.setMember = function(operation, member, success_callback, error_callback) {
65
+ var options,
66
+ _this = this;
67
+ options = {
68
+ type: 'POST',
69
+ url: this.url(),
70
+ data: {
71
+ operation: operation,
72
+ value: member
73
+ },
74
+ success: function(data, status, xhr) {
75
+ Feature.trigger('reload');
76
+ _this.value = data.value;
77
+ if (success_callback) {
78
+ return success_callback(data, status, xhr);
79
+ }
80
+ },
81
+ error: function(data, status, error) {
82
+ var response;
83
+ response = data.responseText ? $.parseJSON(data.responseText) : {
84
+ message: "Something went wrong..."
85
+ };
86
+ alert("ERROR: " + response.message);
87
+ if (error_callback) {
88
+ return error_callback(data, status);
89
+ }
90
+ }
91
+ };
92
+ return $.ajax(options);
93
+ };
94
+
95
+ Gate.prototype.save = function(opts) {
96
+ var result;
97
+ result = Gate.__super__.save.apply(this, arguments);
98
+ this.ajaxSave(opts);
99
+ Feature.trigger('reload');
100
+ return result;
101
+ };
102
+
103
+ Gate.prototype.ajaxSave = function(opts) {
104
+ var options,
105
+ _this = this;
106
+ options = {
107
+ type: 'POST',
108
+ url: this.url(),
109
+ data: {
110
+ value: this.value
111
+ },
112
+ error: function(data, status, error) {
113
+ var response;
114
+ response = data.responseText ? $.parseJSON(data.responseText) : {
115
+ message: "Something went wrong..."
116
+ };
117
+ return alert("ERROR: " + response.message);
118
+ }
119
+ };
120
+ return $.ajax(options);
121
+ };
122
+
123
+ return Gate;
124
+
125
+ })(Spine.Model);
126
+
127
+ App = (function(_super) {
128
+
129
+ __extends(App, _super);
130
+
131
+ function App() {
132
+ App.__super__.constructor.apply(this, arguments);
133
+ this.feature_list = new App.FeatureList({
134
+ el: $('#features')
135
+ });
136
+ }
137
+
138
+ return App;
139
+
140
+ })(Spine.Controller);
141
+
142
+ App.FeatureList = (function(_super) {
143
+
144
+ __extends(FeatureList, _super);
145
+
146
+ function FeatureList() {
147
+ this.reload = __bind(this.reload, this);
148
+
149
+ this.addAll = __bind(this.addAll, this);
150
+
151
+ this.addOne = __bind(this.addOne, this);
152
+
153
+ var _this = this;
154
+ FeatureList.__super__.constructor.apply(this, arguments);
155
+ this.feature_controllers = {};
156
+ Feature.bind("refresh", this.addAll);
157
+ Feature.bind("reload", this.reload);
158
+ Feature.one('refresh', function() {
159
+ return Spine.Route.setup({
160
+ history: true
161
+ });
162
+ });
163
+ Feature.fetch();
164
+ Spine.Route.add(/features\/(.*)\/(.*)\/?/, function(matches) {
165
+ var controller, params;
166
+ params = {
167
+ id: matches.match[1],
168
+ gate: matches.match[2]
169
+ };
170
+ if (controller = _this.feature_controllers[params.id]) {
171
+ controller.edit();
172
+ return controller.activateGate(params);
173
+ }
174
+ });
175
+ Spine.Route.add(/features\/(.*)\/?/, function(matches) {
176
+ var controller, params;
177
+ params = {
178
+ id: matches.match[1]
179
+ };
180
+ if (controller = _this.feature_controllers[params.id]) {
181
+ controller.edit();
182
+ return controller.openDefaultGate();
183
+ }
184
+ });
185
+ }
186
+
187
+ FeatureList.prototype.addOne = function(feature) {
188
+ var controller;
189
+ controller = new App.Feature({
190
+ feature: feature
191
+ });
192
+ this.feature_controllers[feature.id] = controller;
193
+ return this.append(controller.render());
194
+ };
195
+
196
+ FeatureList.prototype.addAll = function() {
197
+ var all_features, feature, _i, _len, _results;
198
+ this.html('');
199
+ $('#no_features').hide();
200
+ all_features = Feature.all();
201
+ if (all_features.length > 0) {
202
+ _results = [];
203
+ for (_i = 0, _len = all_features.length; _i < _len; _i++) {
204
+ feature = all_features[_i];
205
+ _results.push(this.addOne(feature));
206
+ }
207
+ return _results;
208
+ } else {
209
+ return $('#no_features').show();
210
+ }
211
+ };
212
+
213
+ FeatureList.prototype.reload = function() {
214
+ Feature.fetch();
215
+ return this.addAll;
216
+ };
217
+
218
+ return FeatureList;
219
+
220
+ })(Spine.Controller);
221
+
222
+ App.Feature = (function(_super) {
223
+
224
+ __extends(Feature, _super);
225
+
226
+ Feature.prototype.elements = {
227
+ '.feature': 'dom_feature',
228
+ '.gates': 'dom_gates'
229
+ };
230
+
231
+ Feature.prototype.events = {
232
+ 'click .show-settings': 'openFeature',
233
+ 'click .hide-settings': 'hide',
234
+ 'click [data-tab]': 'clickTab'
235
+ };
236
+
237
+ function Feature() {
238
+ Feature.__super__.constructor.apply(this, arguments);
239
+ if (!(this.feature != null)) {
240
+ throw "@feature required";
241
+ }
242
+ }
243
+
244
+ Feature.prototype.render = function() {
245
+ this.html(this.template(this.feature));
246
+ this.gate_list = new App.GateList({
247
+ el: this.dom_gates
248
+ });
249
+ return this.el;
250
+ };
251
+
252
+ Feature.prototype.openFeature = function(event) {
253
+ if (event) {
254
+ event.preventDefault();
255
+ }
256
+ return this.navigate("" + Flipper.Config.url + "/features/" + this.feature.id);
257
+ };
258
+
259
+ Feature.prototype.openDefaultGate = function() {
260
+ return this.navigate("" + Flipper.Config.url + "/features/" + this.feature.id + "/boolean");
261
+ };
262
+
263
+ Feature.prototype.template = function(feature) {
264
+ var source, template;
265
+ source = $("#feature-template").html();
266
+ template = Handlebars.compile(source);
267
+ return template(feature);
268
+ };
269
+
270
+ Feature.prototype.clickTab = function(event) {
271
+ var name, tab;
272
+ event.preventDefault();
273
+ tab = $(event.currentTarget);
274
+ name = tab.attr('data-tab');
275
+ return this.navigate("" + Flipper.Config.url + "/features/" + this.feature.id + "/" + name);
276
+ };
277
+
278
+ Feature.prototype.activateGate = function(params) {
279
+ var name;
280
+ name = params.gate;
281
+ this.gate_list[name].active(params);
282
+ this.el.find('[data-tab]').removeClass('active');
283
+ return this.el.find("[data-tab=" + name + "]").addClass('active');
284
+ };
285
+
286
+ Feature.prototype.edit = function(event) {
287
+ if (event) {
288
+ event.preventDefault();
289
+ }
290
+ return this.dom_feature.addClass('settings');
291
+ };
292
+
293
+ Feature.prototype.hide = function(event) {
294
+ if (event) {
295
+ event.preventDefault();
296
+ }
297
+ this.dom_feature.removeClass('settings');
298
+ return this.navigate("" + Flipper.Config.url + "/");
299
+ };
300
+
301
+ return Feature;
302
+
303
+ })(Spine.Controller);
304
+
305
+ App.Gate = (function(_super) {
306
+
307
+ __extends(Gate, _super);
308
+
309
+ function Gate() {
310
+ Gate.__super__.constructor.apply(this, arguments);
311
+ this.active(this.renderForParams);
312
+ }
313
+
314
+ Gate.prototype.renderForParams = function(params) {
315
+ this.feature = Feature.find(params.id);
316
+ this.gate = this.feature.gate(params.gate);
317
+ return this.render();
318
+ };
319
+
320
+ Gate.prototype.render = function() {
321
+ var $slider, $slider_value;
322
+ this.html(this.template("#gate-" + (this.name.replace(/_/g, '-')) + "-template", this.gate));
323
+ $slider = $(".slider-range");
324
+ $slider_value = $slider.siblings("input[type='text']");
325
+ $slider.slider({
326
+ range: "min",
327
+ value: this.gate.value,
328
+ min: 0,
329
+ max: 100,
330
+ slide: function(event, ui) {
331
+ $slider_value.val(ui.value);
332
+ }
333
+ });
334
+ $slider_value.val($slider.slider("value"));
335
+ return $slider_value.change(function() {
336
+ $slider.slider("value", $(this).val());
337
+ });
338
+ };
339
+
340
+ Gate.prototype.template = function(html_id, context) {
341
+ var source, template;
342
+ source = $(html_id).html();
343
+ template = Handlebars.compile(source);
344
+ return template(context);
345
+ };
346
+
347
+ return Gate;
348
+
349
+ })(Spine.Controller);
350
+
351
+ App.Gate.Boolean = (function(_super) {
352
+
353
+ __extends(Boolean, _super);
354
+
355
+ Boolean.prototype.elements = {
356
+ 'input[value=true]': 'input'
357
+ };
358
+
359
+ Boolean.prototype.events = {
360
+ 'submit form': 'submit'
361
+ };
362
+
363
+ function Boolean() {
364
+ this.name = 'boolean';
365
+ Boolean.__super__.constructor.apply(this, arguments);
366
+ }
367
+
368
+ Boolean.prototype.submit = function(event) {
369
+ event.preventDefault();
370
+ this.gate.value = this.input.is(':checked');
371
+ this.gate.save();
372
+ return this.navigate("" + Flipper.Config.url + "/");
373
+ };
374
+
375
+ return Boolean;
376
+
377
+ })(App.Gate);
378
+
379
+ App.Gate.Set = (function(_super) {
380
+
381
+ __extends(Set, _super);
382
+
383
+ function Set() {
384
+ return Set.__super__.constructor.apply(this, arguments);
385
+ }
386
+
387
+ Set.prototype.elements = {
388
+ '.disable': 'dom_disable',
389
+ '.members': 'dom_members',
390
+ '[name=value]': 'dom_input'
391
+ };
392
+
393
+ Set.prototype.events = {
394
+ 'click .disable': 'disable',
395
+ 'submit form': 'submit'
396
+ };
397
+
398
+ Set.prototype.disable = function(event) {
399
+ var member, value;
400
+ event.preventDefault();
401
+ member = $(event.currentTarget).closest('.member');
402
+ value = member.attr('data-value');
403
+ return this.gate.disableSetMember(value, function(data, status, xhr) {
404
+ return member.remove();
405
+ });
406
+ };
407
+
408
+ Set.prototype.submit = function(event) {
409
+ var self, value;
410
+ event.preventDefault();
411
+ value = this.dom_input.val();
412
+ self = this;
413
+ return this.gate.enableSetMember(value, function(data, status, xhr) {
414
+ var html;
415
+ html = self.template("#gate-member-template", value);
416
+ self.dom_members.append(html);
417
+ return self.dom_input.val('');
418
+ });
419
+ };
420
+
421
+ return Set;
422
+
423
+ })(App.Gate);
424
+
425
+ App.Gate.Group = (function(_super) {
426
+
427
+ __extends(Group, _super);
428
+
429
+ function Group() {
430
+ this.name = 'group';
431
+ Group.__super__.constructor.apply(this, arguments);
432
+ }
433
+
434
+ return Group;
435
+
436
+ })(App.Gate.Set);
437
+
438
+ App.Gate.Actor = (function(_super) {
439
+
440
+ __extends(Actor, _super);
441
+
442
+ function Actor() {
443
+ this.name = 'actor';
444
+ Actor.__super__.constructor.apply(this, arguments);
445
+ }
446
+
447
+ return Actor;
448
+
449
+ })(App.Gate.Set);
450
+
451
+ App.Gate.Percentage = (function(_super) {
452
+
453
+ __extends(Percentage, _super);
454
+
455
+ function Percentage() {
456
+ return Percentage.__super__.constructor.apply(this, arguments);
457
+ }
458
+
459
+ Percentage.prototype.elements = {
460
+ 'input[type=text]': 'input'
461
+ };
462
+
463
+ Percentage.prototype.events = {
464
+ 'submit form': 'submit'
465
+ };
466
+
467
+ Percentage.prototype.validate = function() {
468
+ var float_value, valid;
469
+ float_value = parseFloat(this.gate.value);
470
+ valid = true;
471
+ if (isNaN(float_value) || float_value < 0 || float_value > 100) {
472
+ alert("The percentage value provided is not valid");
473
+ valid = false;
474
+ }
475
+ return valid;
476
+ };
477
+
478
+ Percentage.prototype.submit = function(event) {
479
+ event.preventDefault();
480
+ this.gate.value = this.input.val();
481
+ if (!this.validate()) {
482
+ return;
483
+ }
484
+ this.gate.save();
485
+ return this.navigate("" + Flipper.Config.url + "/");
486
+ };
487
+
488
+ return Percentage;
489
+
490
+ })(App.Gate);
491
+
492
+ App.Gate.PercentageOfActors = (function(_super) {
493
+
494
+ __extends(PercentageOfActors, _super);
495
+
496
+ function PercentageOfActors() {
497
+ this.name = 'percentage_of_actors';
498
+ PercentageOfActors.__super__.constructor.apply(this, arguments);
499
+ }
500
+
501
+ return PercentageOfActors;
502
+
503
+ })(App.Gate.Percentage);
504
+
505
+ App.Gate.PercentageOfRandom = (function(_super) {
506
+
507
+ __extends(PercentageOfRandom, _super);
508
+
509
+ function PercentageOfRandom() {
510
+ this.name = 'percentage_of_random';
511
+ PercentageOfRandom.__super__.constructor.apply(this, arguments);
512
+ }
513
+
514
+ return PercentageOfRandom;
515
+
516
+ })(App.Gate.Percentage);
517
+
518
+ App.GateList = (function(_super) {
519
+
520
+ __extends(GateList, _super);
521
+
522
+ function GateList() {
523
+ return GateList.__super__.constructor.apply(this, arguments);
524
+ }
525
+
526
+ GateList.prototype.controllers = {
527
+ boolean: App.Gate.Boolean,
528
+ group: App.Gate.Group,
529
+ actor: App.Gate.Actor,
530
+ percentage_of_actors: App.Gate.PercentageOfActors,
531
+ percentage_of_random: App.Gate.PercentageOfRandom
532
+ };
533
+
534
+ return GateList;
535
+
536
+ })(Spine.Stack);
537
+
538
+ jQuery(function() {
539
+ return new App({
540
+ el: $('#app')
541
+ });
542
+ });
543
+
544
+ }).call(this);