voom-presenters 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (313) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +54 -0
  3. data/.ruby-version +1 -0
  4. data/Gemfile +11 -0
  5. data/Gemfile.lock +104 -0
  6. data/LICENSE +21 -0
  7. data/LICENSE.txt +21 -0
  8. data/README.md +45 -0
  9. data/ROADMAP.md +21 -0
  10. data/Rakefile +6 -0
  11. data/app/demo/component_status.pom +76 -0
  12. data/app/demo/components.pom +19 -0
  13. data/app/demo/components/badges.pom +25 -0
  14. data/app/demo/components/buttons.pom +51 -0
  15. data/app/demo/components/cards.pom +79 -0
  16. data/app/demo/components/chips.pom +91 -0
  17. data/app/demo/components/dialogs.pom +27 -0
  18. data/app/demo/components/drawers.pom +34 -0
  19. data/app/demo/components/expansion_panels.pom +21 -0
  20. data/app/demo/components/fabs-mini.pom +18 -0
  21. data/app/demo/components/fabs.pom +16 -0
  22. data/app/demo/components/footers.pom +36 -0
  23. data/app/demo/components/forms.pom +30 -0
  24. data/app/demo/components/headers.pom +37 -0
  25. data/app/demo/components/hidden_fields.pom +20 -0
  26. data/app/demo/components/icons.pom +94 -0
  27. data/app/demo/components/layouts.pom +44 -0
  28. data/app/demo/components/lists.pom +124 -0
  29. data/app/demo/components/menus.pom +43 -0
  30. data/app/demo/components/nav/drawer.pom +5 -0
  31. data/app/demo/components/nav/menu.pom +15 -0
  32. data/app/demo/components/selects.pom +30 -0
  33. data/app/demo/components/snackbar.pom +24 -0
  34. data/app/demo/components/snackbar_attached.pom +6 -0
  35. data/app/demo/components/tables.pom +39 -0
  36. data/app/demo/components/text_areas.pom +19 -0
  37. data/app/demo/components/text_fields.pom +57 -0
  38. data/app/demo/components/toggles.pom +29 -0
  39. data/app/demo/components/tooltips.pom +120 -0
  40. data/app/demo/event/actions.rb +86 -0
  41. data/app/demo/event/actions/dialog/show_dialog.pom +9 -0
  42. data/app/demo/event/actions/dialog/trigger.pom +86 -0
  43. data/app/demo/event/actions/nav/drawer.pom +5 -0
  44. data/app/demo/event/actions/nav/menu.pom +19 -0
  45. data/app/demo/event/autocomplete.pom +27 -0
  46. data/app/demo/event/field_level.pom +22 -0
  47. data/app/demo/event/form_level.pom +26 -0
  48. data/app/demo/event/nav/drawer.pom +5 -0
  49. data/app/demo/event/nav/menu.pom +14 -0
  50. data/app/demo/event/new_text.pom +6 -0
  51. data/app/demo/events.pom +98 -0
  52. data/app/demo/helpers/indented_grid.rb +14 -0
  53. data/app/demo/index.pom +19 -0
  54. data/app/demo/markdown.pom +73 -0
  55. data/app/demo/nav/top_nav.pom +42 -0
  56. data/app/demo/shared/code.pom +20 -0
  57. data/app/demo/shared/context_list.pom +29 -0
  58. data/app/demo/shared/debug.pom +17 -0
  59. data/app/demo/styles.pom +26 -0
  60. data/bin/console +22 -0
  61. data/bin/setup +8 -0
  62. data/component-status.yml +219 -0
  63. data/config.ru +21 -0
  64. data/lib/voom-presenters.rb +9 -0
  65. data/lib/voom/container_methods.rb +40 -0
  66. data/lib/voom/logger_methods.rb +11 -0
  67. data/lib/voom/parameters.rb +73 -0
  68. data/lib/voom/presenters-engine.rb +40 -0
  69. data/lib/voom/presenters.rb +13 -0
  70. data/lib/voom/presenters/api/app.rb +53 -0
  71. data/lib/voom/presenters/api/router.rb +94 -0
  72. data/lib/voom/presenters/app.rb +55 -0
  73. data/lib/voom/presenters/container_item.rb +16 -0
  74. data/lib/voom/presenters/demo/echo.rb +29 -0
  75. data/lib/voom/presenters/demo/search-terms.yml +50 -0
  76. data/lib/voom/presenters/demo/search.rb +29 -0
  77. data/lib/voom/presenters/dsl.rb +60 -0
  78. data/lib/voom/presenters/dsl/components/action.rb +35 -0
  79. data/lib/voom/presenters/dsl/components/avatar.rb +27 -0
  80. data/lib/voom/presenters/dsl/components/badge.rb +21 -0
  81. data/lib/voom/presenters/dsl/components/base.rb +78 -0
  82. data/lib/voom/presenters/dsl/components/button.rb +49 -0
  83. data/lib/voom/presenters/dsl/components/card.rb +119 -0
  84. data/lib/voom/presenters/dsl/components/checkbox.rb +16 -0
  85. data/lib/voom/presenters/dsl/components/chip.rb +48 -0
  86. data/lib/voom/presenters/dsl/components/content.rb +33 -0
  87. data/lib/voom/presenters/dsl/components/date_time.rb +17 -0
  88. data/lib/voom/presenters/dsl/components/dialog.rb +50 -0
  89. data/lib/voom/presenters/dsl/components/drawer.rb +40 -0
  90. data/lib/voom/presenters/dsl/components/event.rb +101 -0
  91. data/lib/voom/presenters/dsl/components/event_base.rb +20 -0
  92. data/lib/voom/presenters/dsl/components/expansion_panel.rb +46 -0
  93. data/lib/voom/presenters/dsl/components/footer.rb +25 -0
  94. data/lib/voom/presenters/dsl/components/form.rb +42 -0
  95. data/lib/voom/presenters/dsl/components/grid.rb +64 -0
  96. data/lib/voom/presenters/dsl/components/header.rb +33 -0
  97. data/lib/voom/presenters/dsl/components/hidden_field.rb +25 -0
  98. data/lib/voom/presenters/dsl/components/icon.rb +21 -0
  99. data/lib/voom/presenters/dsl/components/icon_base.rb +24 -0
  100. data/lib/voom/presenters/dsl/components/icon_toggle.rb +21 -0
  101. data/lib/voom/presenters/dsl/components/image.rb +36 -0
  102. data/lib/voom/presenters/dsl/components/input.rb +19 -0
  103. data/lib/voom/presenters/dsl/components/list.rb +39 -0
  104. data/lib/voom/presenters/dsl/components/lists/action.rb +72 -0
  105. data/lib/voom/presenters/dsl/components/lists/line.rb +83 -0
  106. data/lib/voom/presenters/dsl/components/lists/separator.rb +16 -0
  107. data/lib/voom/presenters/dsl/components/menu.rb +66 -0
  108. data/lib/voom/presenters/dsl/components/mixins/append.rb +20 -0
  109. data/lib/voom/presenters/dsl/components/mixins/attaches.rb +18 -0
  110. data/lib/voom/presenters/dsl/components/mixins/avatar.rb +18 -0
  111. data/lib/voom/presenters/dsl/components/mixins/buttons.rb +15 -0
  112. data/lib/voom/presenters/dsl/components/mixins/chips.rb +21 -0
  113. data/lib/voom/presenters/dsl/components/mixins/common.rb +50 -0
  114. data/lib/voom/presenters/dsl/components/mixins/content.rb +15 -0
  115. data/lib/voom/presenters/dsl/components/mixins/dialogs.rb +19 -0
  116. data/lib/voom/presenters/dsl/components/mixins/event.rb +19 -0
  117. data/lib/voom/presenters/dsl/components/mixins/expansion_panels.rb +15 -0
  118. data/lib/voom/presenters/dsl/components/mixins/grids.rb +15 -0
  119. data/lib/voom/presenters/dsl/components/mixins/helpers.rb +20 -0
  120. data/lib/voom/presenters/dsl/components/mixins/icons.rb +17 -0
  121. data/lib/voom/presenters/dsl/components/mixins/images.rb +15 -0
  122. data/lib/voom/presenters/dsl/components/mixins/menus.rb +15 -0
  123. data/lib/voom/presenters/dsl/components/mixins/selects.rb +17 -0
  124. data/lib/voom/presenters/dsl/components/mixins/snackbars.rb +18 -0
  125. data/lib/voom/presenters/dsl/components/mixins/text_fields.rb +35 -0
  126. data/lib/voom/presenters/dsl/components/mixins/toggles.rb +40 -0
  127. data/lib/voom/presenters/dsl/components/mixins/tooltips.rb +18 -0
  128. data/lib/voom/presenters/dsl/components/mixins/typography.rb +37 -0
  129. data/lib/voom/presenters/dsl/components/page.rb +29 -0
  130. data/lib/voom/presenters/dsl/components/radio_button.rb +14 -0
  131. data/lib/voom/presenters/dsl/components/select.rb +64 -0
  132. data/lib/voom/presenters/dsl/components/snackbar.rb +32 -0
  133. data/lib/voom/presenters/dsl/components/switch.rb +14 -0
  134. data/lib/voom/presenters/dsl/components/table.rb +102 -0
  135. data/lib/voom/presenters/dsl/components/text_area.rb +20 -0
  136. data/lib/voom/presenters/dsl/components/text_field.rb +74 -0
  137. data/lib/voom/presenters/dsl/components/toggle_base.rb +26 -0
  138. data/lib/voom/presenters/dsl/components/tooltip.rb +25 -0
  139. data/lib/voom/presenters/dsl/components/typography.rb +25 -0
  140. data/lib/voom/presenters/dsl/definer.rb +13 -0
  141. data/lib/voom/presenters/dsl/definition.rb +31 -0
  142. data/lib/voom/presenters/dsl/invalid_presenter.rb +8 -0
  143. data/lib/voom/presenters/dsl/lockable.rb +15 -0
  144. data/lib/voom/presenters/dsl/user_interface.rb +135 -0
  145. data/lib/voom/presenters/errors/parameter_validation.rb +10 -0
  146. data/lib/voom/presenters/errors/unprocessable.rb +8 -0
  147. data/lib/voom/presenters/helpers.rb +18 -0
  148. data/lib/voom/presenters/helpers/currency.rb +14 -0
  149. data/lib/voom/presenters/helpers/date.rb +22 -0
  150. data/lib/voom/presenters/helpers/errors.rb +11 -0
  151. data/lib/voom/presenters/helpers/inflector.rb +16 -0
  152. data/lib/voom/presenters/helpers/rails.rb +60 -0
  153. data/lib/voom/presenters/helpers/route.rb +11 -0
  154. data/lib/voom/presenters/helpers/time.rb +27 -0
  155. data/lib/voom/presenters/settings.rb +35 -0
  156. data/lib/voom/presenters/version.rb +5 -0
  157. data/lib/voom/presenters/web_client/app.rb +128 -0
  158. data/lib/voom/presenters/web_client/markdown_render.rb +16 -0
  159. data/lib/voom/presenters/web_client/router.rb +96 -0
  160. data/lib/voom/serializer.rb +43 -0
  161. data/lib/voom/symbol/to_str.rb +29 -0
  162. data/lib/voom/trace.rb +19 -0
  163. data/presenters.gemspec +37 -0
  164. data/public/.gitignore +2 -0
  165. data/public/bundle.css +11413 -0
  166. data/public/bundle.js +16456 -0
  167. data/public/dialog-polyfill.js +738 -0
  168. data/public/favicon.ico +0 -0
  169. data/public/img/demo/dog.png +0 -0
  170. data/public/img/demo/image_card.jpg +0 -0
  171. data/public/img/demo/rx.png +0 -0
  172. data/public/img/demo/welcome_card.jpg +0 -0
  173. data/public/img/settings/blue.png +0 -0
  174. data/public/img/settings/green.png +0 -0
  175. data/public/img/settings/orange.png +0 -0
  176. data/public/img/settings/purple.png +0 -0
  177. data/public/img/settings/red.png +0 -0
  178. data/public/img/settings/teal.png +0 -0
  179. data/public/img/settings/white.png +0 -0
  180. data/public/img/settings/yellow.png +0 -0
  181. data/public/scripts.js +289 -0
  182. data/public/style-bundle.js +73 -0
  183. data/public/styles.css +16 -0
  184. data/views/mdc/.gitignore +1 -0
  185. data/views/mdc/assets/js/app.js +10 -0
  186. data/views/mdc/assets/js/components/base-component.js +5 -0
  187. data/views/mdc/assets/js/components/button.js +15 -0
  188. data/views/mdc/assets/js/components/cards.js +3 -0
  189. data/views/mdc/assets/js/components/checkboxes.js +15 -0
  190. data/views/mdc/assets/js/components/chips.js +12 -0
  191. data/views/mdc/assets/js/components/date-time.js +6 -0
  192. data/views/mdc/assets/js/components/dialogs.js +32 -0
  193. data/views/mdc/assets/js/components/events.js +151 -0
  194. data/views/mdc/assets/js/components/events/autocomplete.js +96 -0
  195. data/views/mdc/assets/js/components/events/base.js +41 -0
  196. data/views/mdc/assets/js/components/events/dialog.js +25 -0
  197. data/views/mdc/assets/js/components/events/errors.js +142 -0
  198. data/views/mdc/assets/js/components/events/loads.js +22 -0
  199. data/views/mdc/assets/js/components/events/navigates.js +17 -0
  200. data/views/mdc/assets/js/components/events/posts.js +99 -0
  201. data/views/mdc/assets/js/components/events/replaces.js +82 -0
  202. data/views/mdc/assets/js/components/events/selects.js +28 -0
  203. data/views/mdc/assets/js/components/events/snackbar.js +23 -0
  204. data/views/mdc/assets/js/components/events/toggle_visiblity.js +19 -0
  205. data/views/mdc/assets/js/components/forms.js +57 -0
  206. data/views/mdc/assets/js/components/icon-toggles.js +21 -0
  207. data/views/mdc/assets/js/components/initialize.js +34 -0
  208. data/views/mdc/assets/js/components/lists.js +4 -0
  209. data/views/mdc/assets/js/components/menus.js +31 -0
  210. data/views/mdc/assets/js/components/mixins/event-handler.js +13 -0
  211. data/views/mdc/assets/js/components/selects.js +45 -0
  212. data/views/mdc/assets/js/components/snackbar.js +32 -0
  213. data/views/mdc/assets/js/components/text-fields.js +77 -0
  214. data/views/mdc/assets/js/dialog-polyfill.js +738 -0
  215. data/views/mdc/assets/js/material.js +3996 -0
  216. data/views/mdc/assets/js/utils/urls.js +54 -0
  217. data/views/mdc/assets/scss/app.scss +31 -0
  218. data/views/mdc/assets/scss/components/avatar.scss +41 -0
  219. data/views/mdc/assets/scss/components/button.scss +47 -0
  220. data/views/mdc/assets/scss/components/card.scss +54 -0
  221. data/views/mdc/assets/scss/components/checkbox.scss +5 -0
  222. data/views/mdc/assets/scss/components/chip.scss +30 -0
  223. data/views/mdc/assets/scss/components/datetime.scss +0 -0
  224. data/views/mdc/assets/scss/components/dialog.scss +3 -0
  225. data/views/mdc/assets/scss/components/expansion-panel.scss +153 -0
  226. data/views/mdc/assets/scss/components/fab.scss +8 -0
  227. data/views/mdc/assets/scss/components/grid.scss +10 -0
  228. data/views/mdc/assets/scss/components/icon-toggles.scss +9 -0
  229. data/views/mdc/assets/scss/components/icon.scss +34 -0
  230. data/views/mdc/assets/scss/components/image.scss +24 -0
  231. data/views/mdc/assets/scss/components/list.scss +9 -0
  232. data/views/mdc/assets/scss/components/menu.scss +17 -0
  233. data/views/mdc/assets/scss/components/select.scss +16 -0
  234. data/views/mdc/assets/scss/components/snackbar.scss +5 -0
  235. data/views/mdc/assets/scss/components/switch.scss +6 -0
  236. data/views/mdc/assets/scss/components/table-pagination.scss +65 -0
  237. data/views/mdc/assets/scss/components/textfield.scss +1 -0
  238. data/views/mdc/assets/scss/components/typography.scss +25 -0
  239. data/views/mdc/assets/scss/material.blue_grey-orange.min.css +8 -0
  240. data/views/mdc/assets/scss/styles.scss +11 -0
  241. data/views/mdc/assets/scss/theme.scss +5 -0
  242. data/views/mdc/body/drawer.erb +18 -0
  243. data/views/mdc/body/drawers/menu.erb +25 -0
  244. data/views/mdc/body/footer.erb +1 -0
  245. data/views/mdc/body/footers/large.erb +27 -0
  246. data/views/mdc/body/footers/menu_item.erb +6 -0
  247. data/views/mdc/body/footers/small.erb +14 -0
  248. data/views/mdc/body/header.erb +25 -0
  249. data/views/mdc/body/snackbar.erb +10 -0
  250. data/views/mdc/components/avatar.erb +24 -0
  251. data/views/mdc/components/badge.erb +2 -0
  252. data/views/mdc/components/body.erb +2 -0
  253. data/views/mdc/components/button.erb +17 -0
  254. data/views/mdc/components/buttons/button.erb +20 -0
  255. data/views/mdc/components/buttons/fab.erb +22 -0
  256. data/views/mdc/components/buttons/icon.erb +24 -0
  257. data/views/mdc/components/card.erb +49 -0
  258. data/views/mdc/components/checkbox.erb +22 -0
  259. data/views/mdc/components/chip.erb +31 -0
  260. data/views/mdc/components/content.erb +11 -0
  261. data/views/mdc/components/date_time.erb +30 -0
  262. data/views/mdc/components/dialog.erb +27 -0
  263. data/views/mdc/components/display.erb +2 -0
  264. data/views/mdc/components/event.erb +18 -0
  265. data/views/mdc/components/expansion_panel.erb +11 -0
  266. data/views/mdc/components/form.erb +15 -0
  267. data/views/mdc/components/grid.erb +24 -0
  268. data/views/mdc/components/headline.erb +2 -0
  269. data/views/mdc/components/hidden_field.erb +1 -0
  270. data/views/mdc/components/icon.erb +30 -0
  271. data/views/mdc/components/icon_toggle.erb +15 -0
  272. data/views/mdc/components/image.erb +7 -0
  273. data/views/mdc/components/link.erb +14 -0
  274. data/views/mdc/components/list.erb +14 -0
  275. data/views/mdc/components/list/actions.erb +6 -0
  276. data/views/mdc/components/list/actions/button.erb +1 -0
  277. data/views/mdc/components/list/actions/checkbox.erb +1 -0
  278. data/views/mdc/components/list/actions/icon.erb +1 -0
  279. data/views/mdc/components/list/actions/icon_toggle.erb +1 -0
  280. data/views/mdc/components/list/actions/radio_button.erb +1 -0
  281. data/views/mdc/components/list/actions/switch.erb +1 -0
  282. data/views/mdc/components/list/avatar.erb +5 -0
  283. data/views/mdc/components/list/checkbox.erb +5 -0
  284. data/views/mdc/components/list/icon.erb +5 -0
  285. data/views/mdc/components/list/info.erb +1 -0
  286. data/views/mdc/components/list/line.erb +34 -0
  287. data/views/mdc/components/list/menu.erb +23 -0
  288. data/views/mdc/components/list/separator.erb +1 -0
  289. data/views/mdc/components/menu.erb +29 -0
  290. data/views/mdc/components/modal.erb +15 -0
  291. data/views/mdc/components/radio_button.erb +11 -0
  292. data/views/mdc/components/render.erb +4 -0
  293. data/views/mdc/components/select.erb +22 -0
  294. data/views/mdc/components/snackbar.erb +17 -0
  295. data/views/mdc/components/static.erb +7 -0
  296. data/views/mdc/components/subheading.erb +2 -0
  297. data/views/mdc/components/switch.erb +13 -0
  298. data/views/mdc/components/table.erb +13 -0
  299. data/views/mdc/components/table/header.erb +7 -0
  300. data/views/mdc/components/table/pagination.erb +24 -0
  301. data/views/mdc/components/table/row.erb +14 -0
  302. data/views/mdc/components/text_area.erb +8 -0
  303. data/views/mdc/components/text_field.erb +27 -0
  304. data/views/mdc/components/title.erb +4 -0
  305. data/views/mdc/components/tooltip.erb +5 -0
  306. data/views/mdc/components/typography.erb +13 -0
  307. data/views/mdc/init-depends.sh +2 -0
  308. data/views/mdc/layout.erb +50 -0
  309. data/views/mdc/package-lock.json +11524 -0
  310. data/views/mdc/package.json +39 -0
  311. data/views/mdc/web.erb +1 -0
  312. data/views/mdc/webpack.config.js +47 -0
  313. metadata +539 -0
@@ -0,0 +1,3 @@
1
+ export function initCards() {
2
+ console.log('\tCards');
3
+ }
@@ -0,0 +1,15 @@
1
+ import {MDCCheckbox} from '@material/checkbox';
2
+
3
+ export function initCheckboxes() {
4
+ console.log('\tCheckboxes');
5
+
6
+ var components = document.querySelectorAll('.mdc-checkbox');
7
+ if (components) {
8
+ for (var i = 0; i < components.length; i++) {
9
+ var component = components[i];
10
+ if (!component.mdcComponent) {
11
+ component.mdcComponent = MDCCheckbox.attachTo(component);
12
+ }
13
+ }
14
+ }
15
+ }
@@ -0,0 +1,12 @@
1
+ import {MDCChip} from '@material/chips';
2
+
3
+ export function initChips() {
4
+ console.log('\tChips');
5
+ var components = document.querySelectorAll('.mdc-chip');
6
+ for (var i = 0; i < components.length; i++) {
7
+ var component = components[i];
8
+ if(!component.mdcComponent) {
9
+ component.mdcComponent = MDCChip.attachTo(component);
10
+ }
11
+ }
12
+ }
@@ -0,0 +1,6 @@
1
+ export function initDateTime() {
2
+ console.log('\tDateTime');
3
+ }
4
+
5
+
6
+
@@ -0,0 +1,32 @@
1
+ // This is used to get a proper binding of the actionData
2
+ // https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example
3
+ function createDialogHandler(dialog) {
4
+ return function () {
5
+ dialog.close();
6
+ };
7
+ }
8
+
9
+ export function initDialogs() {
10
+ console.log('\tDialogs');
11
+
12
+ var dialogs = document.querySelectorAll('.v-js-dialog');
13
+ if (dialogs) {
14
+ for (var i = 0; i < dialogs.length; i++) {
15
+ var dialog = dialogs[i];
16
+ var dialogButtons = dialog.querySelectorAll('button:not([disabled])');
17
+ for (var j = 0; j != dialogButtons.length; j++) {
18
+ var dialogButton = dialogButtons[j];
19
+ if (!dialogButton.dialog) {
20
+ dialogButton.dialog = dialog;
21
+ var buttonEvents = dialogButton.dataset.events;
22
+ // If the dialog button does not have any events tied to it,
23
+ // then close the dialog on click, otherwise let the events handlers
24
+ // take care of the close.
25
+ if (!buttonEvents) {
26
+ dialogButton.addEventListener('click', createDialogHandler(dialog));
27
+ }
28
+ }
29
+ }
30
+ }
31
+ }
32
+ }
@@ -0,0 +1,151 @@
1
+ import {VLoads} from './events/loads';
2
+ import {VPosts} from './events/posts';
3
+ import {VReplaces} from './events/replaces';
4
+ import {VDialog} from './events/dialog';
5
+ import {VErrors} from './events/errors';
6
+ import {VToggleVisiblity} from './events/toggle_visiblity';
7
+ import {VSnackbarEvent} from './events/snackbar';
8
+ import {VAutoComplete} from './events/autocomplete';
9
+ import {VSelects} from './events/selects';
10
+ import {VNavigates} from './events/navigates';
11
+
12
+
13
+ export class VEvents {
14
+ //[[type, url, target, params]]
15
+ constructor(actions, event) {
16
+ this.event = event;
17
+ this.actions = actions.map((action) => {
18
+ return this.constructor.action_class(action, event);
19
+ });
20
+ }
21
+
22
+ call() {
23
+ // Adapted from http://www.datchley.name/promise-patterns-anti-patterns/#executingpromisesinseries
24
+ var fnlist = this.actions.map((action) => {
25
+ return function (results) {
26
+ return Promise.resolve(action.call(results));
27
+ };
28
+ });
29
+
30
+ // Execute a list of Promise return functions in series
31
+ function pseries(list) {
32
+ var p = Promise.resolve([]);
33
+ return list.reduce(function (pacc, fn) {
34
+ return pacc = pacc.then(fn);
35
+ }, p);
36
+ }
37
+
38
+ var event = this.event;
39
+
40
+ pseries(fnlist)
41
+ .then(function (results) {
42
+ var result = results.pop();
43
+ var contentType = result.contentType;
44
+ var responseURL = result.responseURL;
45
+
46
+ if (event.target.dialog) {
47
+ event.target.dialog.close();
48
+ }
49
+ if (contentType && contentType.indexOf("text/html") !== -1 && typeof responseURL !== 'undefined') {
50
+ window.location = responseURL;
51
+ }
52
+
53
+ }).catch(function (results) {
54
+ var result = results.pop();
55
+ new VErrors(event).displayErrors(result);
56
+ });
57
+ }
58
+
59
+ static action_class(action, event) {
60
+ var action_type = action[0];
61
+ var url = action[1];
62
+ var options = action[2];
63
+ var params = action[3];
64
+
65
+ switch (action_type) {
66
+ case 'loads':
67
+ return new VLoads(options, url, params, event);
68
+ case 'replaces':
69
+ return new VReplaces(options, url, params, event);
70
+ case 'post':
71
+ return new VPosts(options, url, params, 'POST', event);
72
+ case 'update':
73
+ return new VPosts(options, url, params, 'PUT', event);
74
+ case 'delete':
75
+ return new VPosts(options, url, params, 'DELETE', event);
76
+ case 'dialog':
77
+ return new VDialog(options, params, event);
78
+ case 'toggle_visibility':
79
+ return new VToggleVisiblity(options, params, event);
80
+ case 'snackbar':
81
+ return new VSnackbarEvent(options, params, event);
82
+ case 'autocomplete':
83
+ return new VAutoComplete(options, url, params, event);
84
+ case 'selects':
85
+ return new VSelects(options, params, event);
86
+ case 'navigates':
87
+ return new VNavigates(options, params, event);
88
+ default:
89
+ throw action_type + ' is not supported.';
90
+ }
91
+ }
92
+
93
+ }
94
+
95
+ // This is used to get a proper binding of the actionData
96
+ // https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example
97
+ function createEventHandler(actionsData) {
98
+ return function (event) {
99
+ new VEvents(actionsData, event).call();
100
+ };
101
+ }
102
+
103
+ export function initEvents() {
104
+ console.log('\tEvents');
105
+
106
+ var events = document.querySelectorAll('[data-events]');
107
+ for (var i = 0; i < events.length; i++) {
108
+ var eventElem = events[i];
109
+ var eventsData = JSON.parse(eventElem.dataset.events);
110
+ for (var j = 0; j < eventsData.length; j++) {
111
+ var eventData = eventsData[j];
112
+ var eventName = eventData[0];
113
+ var eventOptions = eventData[2];
114
+ var actionsData = eventData[1];
115
+ var eventHandler = createEventHandler(actionsData);
116
+ // Delegate to the component if possible
117
+ if (eventElem.vComponent && eventElem.vComponent.initEventListener) {
118
+ eventElem.vComponent.initEventListener(eventName, eventHandler);
119
+ } else {
120
+ if (typeof eventElem.eventsHandler === 'undefined') {
121
+ eventElem.eventsHandler = {};
122
+ }
123
+ if (!eventElem.eventsHandler[eventName]) {
124
+ // Delegate to the component if possible
125
+ eventElem.eventsHandler[eventName] = eventHandler;
126
+ eventElem.addEventListener(eventName, eventHandler, eventOptions);
127
+ }
128
+ }
129
+ }
130
+ }
131
+ fireAfterLoad();
132
+ }
133
+
134
+ function fireAfterLoad() {
135
+ var events = document.querySelectorAll('[data-events]');
136
+ for (var i = 0; i < events.length; i++) {
137
+ var eventElem = events[i];
138
+ var eventsData = JSON.parse(eventElem.dataset.events);
139
+ for (var j = 0; j < eventsData.length; j++) {
140
+ var eventData = eventsData[j];
141
+ var eventName = eventData[0];
142
+ if(eventName==='after_init') {
143
+ var event = new Event('after_init');
144
+ // Dispatch the event.
145
+ eventElem.dispatchEvent(event);
146
+ }
147
+ }
148
+ }
149
+ }
150
+
151
+
@@ -0,0 +1,96 @@
1
+ import {VSnackbar} from '../snackbar';
2
+ import {VBase} from './base';
3
+ import {initialize} from '../initialize';
4
+
5
+ // Auto complete a datalist
6
+ // The elementId is a datalist
7
+ // The url is called as a GET expecting json back
8
+ export class VAutoComplete extends VBase {
9
+ constructor(options, url, params, event) {
10
+ super(options);
11
+ this.element_id = options.target;
12
+ this.url = url;
13
+ this.params = params;
14
+ this.event = event;
15
+ }
16
+
17
+ call(results) {
18
+ // Clear the timeout if it has already been set.
19
+ // This will prevent the previous task from executing
20
+ // if it has been less than <MILLISECONDS>
21
+ var parentElement = this.parentElement();
22
+ var updateElement = this.createUpdateElementHandler(this);
23
+ var promiseObj = new Promise(function (resolve) {
24
+ clearTimeout(parentElement.vTimeout);
25
+ // Make a new timeout
26
+ parentElement.vTimeout = setTimeout(updateElement, 500);
27
+ results.push({action:'autocomplete', statusCode: 200});
28
+ resolve(results);
29
+ });
30
+ return promiseObj;
31
+ }
32
+
33
+ // This is used to get a proper binding of the object
34
+ // https://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example
35
+ createUpdateElementHandler(_this_) {
36
+ return function () {
37
+ _this_.updateElement();
38
+ };
39
+ }
40
+
41
+ updateElement() {
42
+ this.clearErrors();
43
+ this.getData(this.populateOptions);
44
+ }
45
+
46
+ dataList() {
47
+ return document.getElementById(this.element_id);
48
+ }
49
+
50
+ getData(funcProcessData) {
51
+ var comp = this.component();
52
+ if(comp.value().length < 2){
53
+ return;
54
+ }
55
+ var httpRequest = new XMLHttpRequest();
56
+ if (!httpRequest) {
57
+ throw new Error('Cannot talk to server! Please upgrade your browser to one that supports XMLHttpRequest.');
58
+ // new VSnackbar('Cannot talk to server! Please upgrade your browser to one that supports XMLHttpRequest.').display();
59
+ }
60
+ var dataList = this.dataList();
61
+ var url = this.buildURL(this.url, this.params, this.inputValues());
62
+
63
+ httpRequest.onreadystatechange = function () {
64
+ if (httpRequest.readyState === XMLHttpRequest.DONE) {
65
+ console.log(httpRequest.status + ':' + this.getResponseHeader('content-type'));
66
+ if (httpRequest.status === 200) {
67
+ var response = JSON.parse(httpRequest.responseText);
68
+ funcProcessData(response, dataList);
69
+ } else {
70
+ console.error("Unable to autocomplete! ElementId: " + this.element_id);
71
+ }
72
+ }
73
+ };
74
+ console.log('GET:' + url);
75
+ httpRequest.open('GET', url, true);
76
+ httpRequest.send();
77
+ }
78
+
79
+ populateOptions(response, dataList) {
80
+ dataList.innerHTML = "";
81
+
82
+ response.forEach(function (item) {
83
+ var value = item;
84
+ var key = null;
85
+ if (Array.isArray(item)) {
86
+ value = item[0];
87
+ key = item[1];
88
+ }
89
+ // Create a new <option> element.
90
+ var option = document.createElement('option');
91
+ option.value = value;
92
+ option.dataset.key = key;
93
+ dataList.appendChild(option);
94
+ });
95
+ }
96
+ }
@@ -0,0 +1,41 @@
1
+ import {VErrors} from './errors';
2
+ import {VUrls} from '../../utils/urls';
3
+
4
+ export class VBase extends VUrls {
5
+ constructor(options) {
6
+ super();
7
+ this.options = options;
8
+ }
9
+
10
+ clearErrors() {
11
+ new VErrors().clearErrors();
12
+ }
13
+
14
+ parentElement() {
15
+ return document.getElementById(this.options.__parent_id__);
16
+ }
17
+
18
+ inputValues(form) {
19
+ var params = [];
20
+ // Let input component push parameters
21
+ var vComp = this.component();
22
+ if (vComp) {
23
+ vComp.prepareSubmit(form, params);
24
+ }
25
+ return params;
26
+ }
27
+
28
+ component() {
29
+ let parent = this.parentElement();
30
+ return parent ? this.parentElement().vComponent : null;
31
+ }
32
+
33
+ validate() {
34
+ var errors = [];
35
+ var comp = this.component();
36
+ if (comp) {
37
+ errors = comp.validate();
38
+ }
39
+ return errors;
40
+ }
41
+ }
@@ -0,0 +1,25 @@
1
+ export class VDialog {
2
+ constructor(options, params, event) {
3
+ this.dialogId = options.target;
4
+ this.params = params;
5
+ this.event = event;
6
+ }
7
+
8
+ call(results) {
9
+ var dialog = document.querySelector('#' + this.dialogId);
10
+ if(dialog) {
11
+ if (!dialog.showModal) {
12
+ dialogPolyfill.registerDialog(dialog);
13
+ }
14
+
15
+ dialog.showModal();
16
+ }else {
17
+ console.error("Unable to find dialog with id: "+this.dialogId+". Usually this means you forgot to attach it to the currently rendered page.");
18
+ }
19
+ var promiseObj = new Promise(function (resolve) {
20
+ results.push({action:'dialog', statusCode: 200});
21
+ resolve(results);
22
+ });
23
+ return promiseObj;
24
+ }
25
+ }
@@ -0,0 +1,142 @@
1
+ export class VErrors {
2
+ constructor(event) {
3
+ this.event = event;
4
+ }
5
+
6
+ clearErrors() {
7
+ var errorMessages = document.querySelectorAll('.v-error-message');
8
+
9
+ for (var i = 0; i < errorMessages.length; i++) {
10
+ errorMessages[i].remove();
11
+ }
12
+ }
13
+
14
+ // Rails errors
15
+ // {
16
+ // "name": [
17
+ // "Requires name"
18
+ // ]
19
+ // }
20
+
21
+ // Validation errors
22
+ // { :email => ["must be filled"] }
23
+
24
+ // Custom errors
25
+ // { :email => "must be filled" }
26
+
27
+ // Exceptions
28
+ // {exception: 'Something bad happened' }
29
+
30
+ stringsToArrays(value) {
31
+ if (Array.isArray(value) || value.constructor === Object) {
32
+ return value;
33
+ }
34
+ return new Array(value);
35
+ }
36
+
37
+ normalizeErrors(errors) {
38
+ if (errors && errors.constructor === Object) {
39
+ return Object.keys(errors).reduce((previous, key) => {
40
+ previous[key] = this.stringsToArrays(errors[key]);
41
+ return previous;
42
+ }, {});
43
+ }
44
+ return [];
45
+ }
46
+
47
+ // [http_status, content_type, resultText]
48
+ displayErrors(result) {
49
+ var httpStatus = result.statusCode;
50
+ var contentType = result.contentType;
51
+ var resultText = result.content;
52
+
53
+ var responseErrors = null;
54
+
55
+ if (contentType && contentType.indexOf("application/json") !== -1) {
56
+ responseErrors = JSON.parse(resultText);
57
+ } else if (contentType && contentType.indexOf("v/errors") !== -1) {
58
+ responseErrors = resultText;
59
+ }
60
+
61
+ if (responseErrors) {
62
+ if (!Array.isArray(responseErrors)) {
63
+ responseErrors = [responseErrors];
64
+ }
65
+ for (var response of responseErrors) {
66
+ var pageErrors = Object.values(this.normalizeErrors(response)).reduce(function (previous, value) {
67
+ if (Array.isArray(value)) {
68
+ previous.push(value.join('<br/>'));
69
+ }
70
+ return previous;
71
+ }, []);
72
+ var fieldErrors = this.normalizeErrors(response.errors);
73
+
74
+ for (var field in fieldErrors) {
75
+ if (!this.displayInputError(field, fieldErrors[field])) {
76
+ // Collect errors that can't be displayed at the field level
77
+ pageErrors.push(fieldErrors[field]);
78
+ }
79
+ }
80
+ this.prependErrors(pageErrors);
81
+ }
82
+ } else if (httpStatus === 0) {
83
+ this.prependErrors(["Unable to contact server. Please check that you are online and retry."]);
84
+ } else {
85
+ this.prependErrors(["The server returned an unexpected response! Status:" + httpStatus]);
86
+ }
87
+ }
88
+
89
+ // Sets the helper text on the field
90
+ // Returns true if it was able to set the error on the control
91
+ displayInputError(divId, messages) {
92
+ var currentEl = document.getElementById(divId);
93
+ if (currentEl && currentEl.mdcComponent) {
94
+ currentEl.mdcComponent.helperTextContent = messages.join(', ');
95
+ var helperText = document.getElementById(divId + '-input-helper-text');
96
+ helperText.classList.add('mdc-text-field--invalid',
97
+ 'mdc-text-field-helper-text--validation-msg',
98
+ 'mdc-text-field-helper-text--persistent');
99
+ currentEl.mdcComponent.valid = false;
100
+ return true;
101
+ }
102
+ return false;
103
+ }
104
+
105
+ // Creates a div before the element with the same id as the error
106
+ // Used to display an error message without their being an input field to attach the error to
107
+ prependErrors(messages) {
108
+ var errorsDiv = this.findNearestErrorDiv();
109
+ // create a new div element
110
+ var newDiv = document.createElement("div");
111
+ newDiv.className = 'v-error-message';
112
+ // and give it some content
113
+
114
+ for (var message of messages) {
115
+ var newContent = document.createTextNode(message);
116
+ newDiv.appendChild(newContent);
117
+ let br = document.createElement('br');
118
+ // add the text node to the newly created div
119
+ newDiv.appendChild(br);
120
+ }
121
+
122
+ // add the newly created element and its content into the DOM
123
+ if (errorsDiv) {
124
+ errorsDiv.parentElement.insertBefore(newDiv, errorsDiv);
125
+ return true;
126
+ } else {
127
+ console.error("Unable to display Errors! ", messages);
128
+ }
129
+ return false;
130
+ }
131
+
132
+ findNearestErrorDiv() {
133
+ let errorsDiv = null;
134
+ const currentDiv = this.event.target;
135
+ if(currentDiv) {
136
+ errorsDiv = currentDiv.closest('.v-errors')
137
+ }else{
138
+ errorsDiv = document.querySelector('.v-errors');
139
+ }
140
+ return errorsDiv;
141
+ }
142
+ }