lesli 5.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (398) hide show
  1. checksums.yaml +7 -0
  2. data/Rakefile +3 -0
  3. data/app/assets/config/lesli_manifest.js +53 -0
  4. data/app/assets/fonts/lesli/Domine/Domine-Bold.ttf +0 -0
  5. data/app/assets/fonts/lesli/Domine/Domine-Regular.ttf +0 -0
  6. data/app/assets/fonts/lesli/Domine/OFL.txt +95 -0
  7. data/app/assets/fonts/lesli/MaterialDesign/icons.woff2 +0 -0
  8. data/app/assets/fonts/lesli/Montserrat/Montserrat-Variable.ttf +0 -0
  9. data/app/assets/fonts/lesli/OpenSans/OpenSans-Variable.ttf +0 -0
  10. data/app/assets/fonts/lesli/Remix/remixicon.eot +0 -0
  11. data/app/assets/fonts/lesli/Remix/remixicon.glyph.json +1 -0
  12. data/app/assets/fonts/lesli/Remix/remixicon.svg +7633 -0
  13. data/app/assets/fonts/lesli/Remix/remixicon.symbol.svg +11 -0
  14. data/app/assets/fonts/lesli/Remix/remixicon.ttf +0 -0
  15. data/app/assets/fonts/lesli/Remix/remixicon.woff +0 -0
  16. data/app/assets/fonts/lesli/Remix/remixicon.woff2 +0 -0
  17. data/app/assets/fonts/lesli/Roboto/LICENSE.txt +202 -0
  18. data/app/assets/fonts/lesli/Roboto/Roboto-Black.ttf +0 -0
  19. data/app/assets/fonts/lesli/Roboto/Roboto-BlackItalic.ttf +0 -0
  20. data/app/assets/fonts/lesli/Roboto/Roboto-Bold.ttf +0 -0
  21. data/app/assets/fonts/lesli/Roboto/Roboto-BoldItalic.ttf +0 -0
  22. data/app/assets/fonts/lesli/Roboto/Roboto-Italic.ttf +0 -0
  23. data/app/assets/fonts/lesli/Roboto/Roboto-Light.ttf +0 -0
  24. data/app/assets/fonts/lesli/Roboto/Roboto-LightItalic.ttf +0 -0
  25. data/app/assets/fonts/lesli/Roboto/Roboto-Medium.ttf +0 -0
  26. data/app/assets/fonts/lesli/Roboto/Roboto-MediumItalic.ttf +0 -0
  27. data/app/assets/fonts/lesli/Roboto/Roboto-Regular.ttf +0 -0
  28. data/app/assets/fonts/lesli/Roboto/Roboto-Thin.ttf +0 -0
  29. data/app/assets/fonts/lesli/Roboto/Roboto-ThinItalic.ttf +0 -0
  30. data/app/assets/icons/lesli/cloud-admin.svg +1 -0
  31. data/app/assets/icons/lesli/cloud-audit.svg +1 -0
  32. data/app/assets/icons/lesli/cloud-babel.svg +1 -0
  33. data/app/assets/icons/lesli/cloud-bell.svg +1 -0
  34. data/app/assets/icons/lesli/cloud-books.svg +1 -0
  35. data/app/assets/icons/lesli/cloud-development.svg +1 -0
  36. data/app/assets/icons/lesli/cloud-dispatcher.svg +1 -0
  37. data/app/assets/icons/lesli/cloud-driver.svg +1 -0
  38. data/app/assets/icons/lesli/cloud-focus.svg +1 -0
  39. data/app/assets/icons/lesli/cloud-help.svg +1 -0
  40. data/app/assets/icons/lesli/cloud-kb.svg +1 -0
  41. data/app/assets/icons/lesli/cloud-leaf.svg +1 -0
  42. data/app/assets/icons/lesli/cloud-lesli.svg +1 -0
  43. data/app/assets/icons/lesli/cloud-mailer.svg +1 -0
  44. data/app/assets/icons/lesli/cloud-one.svg +1 -0
  45. data/app/assets/icons/lesli/cloud-profile.svg +1 -0
  46. data/app/assets/icons/lesli/cloud-proposal.svg +1 -0
  47. data/app/assets/icons/lesli/cloud-scraper.svg +1 -0
  48. data/app/assets/icons/lesli/cloud-shared.svg +1 -0
  49. data/app/assets/icons/lesli/cloud-storage.svg +1 -0
  50. data/app/assets/icons/lesli/cloud-talk.svg +1 -0
  51. data/app/assets/icons/lesli/cloud-team.svg +1 -0
  52. data/app/assets/icons/lesli/cloud-time.svg +1 -0
  53. data/app/assets/icons/lesli/cloud-vault.svg +1 -0
  54. data/app/assets/icons/lesli/cloud-word.svg +1 -0
  55. data/app/assets/icons/lesli/icon-module.svg +1 -0
  56. data/app/assets/icons/lesli/logo-android.svg +1 -0
  57. data/app/assets/icons/lesli/logo-bulma.svg +1 -0
  58. data/app/assets/icons/lesli/logo-ios.svg +1 -0
  59. data/app/assets/icons/lesli/logo-linux.svg +1 -0
  60. data/app/assets/icons/lesli/logo-mac.svg +1 -0
  61. data/app/assets/icons/lesli/logo-module.svg +1 -0
  62. data/app/assets/icons/lesli/logo-postgresql.svg +1 -0
  63. data/app/assets/icons/lesli/logo-rails.svg +1 -0
  64. data/app/assets/icons/lesli/logo-ruby.svg +1 -0
  65. data/app/assets/icons/lesli/logo-sass.svg +1 -0
  66. data/app/assets/icons/lesli/logo-vue.svg +1 -0
  67. data/app/assets/icons/lesli/logo-web.svg +1 -0
  68. data/app/assets/icons/lesli/logo-windows.svg +1 -0
  69. data/app/assets/icons/readme.md +10 -0
  70. data/app/assets/images/lesli/brand/app-auth.svg +9 -0
  71. data/app/assets/images/lesli/brand/app-icon.svg +42 -0
  72. data/app/assets/images/lesli/brand/app-logo.svg +4 -0
  73. data/app/assets/images/lesli/brand/favicon.png +0 -0
  74. data/app/assets/images/lesli/brand/favicon.svg +61 -0
  75. data/app/assets/images/lesli/brand/login-background.jpg +0 -0
  76. data/app/assets/javascripts/lesli/users/sessions.js +786 -0
  77. data/app/assets/stylesheets/lesli/users/confirmations.scss +34 -0
  78. data/app/assets/stylesheets/lesli/users/devise.scss +32 -0
  79. data/app/assets/stylesheets/lesli/users/oauth.scss +34 -0
  80. data/app/assets/stylesheets/lesli/users/passwords.scss +34 -0
  81. data/app/assets/stylesheets/lesli/users/registrations.scss +34 -0
  82. data/app/assets/stylesheets/lesli/users/sessions.scss +38 -0
  83. data/app/controllers/lesli/application_controller.rb +108 -0
  84. data/app/controllers/lesli/application_devise_controller.rb +54 -0
  85. data/app/controllers/lesli/application_lesli_controller.rb +61 -0
  86. data/app/controllers/lesli/interfaces/application/authorization.rb +107 -0
  87. data/app/controllers/lesli/interfaces/application/customization.rb +46 -0
  88. data/app/controllers/lesli/interfaces/application/logger.rb +133 -0
  89. data/app/controllers/lesli/interfaces/application/requester.rb +84 -0
  90. data/app/controllers/lesli/interfaces/application/responder.rb +132 -0
  91. data/app/controllers/lesli/profiles_controller.rb +60 -0
  92. data/app/controllers/users/confirmations_controller.rb +30 -0
  93. data/app/controllers/users/omniauth_callbacks_controller.rb +30 -0
  94. data/app/controllers/users/passwords_controller.rb +34 -0
  95. data/app/controllers/users/registrations_controller.rb +62 -0
  96. data/app/controllers/users/sessions_controller.rb +142 -0
  97. data/app/controllers/users/unlocks_controller.rb +30 -0
  98. data/app/helpers/lesli/assets_helper.rb +92 -0
  99. data/app/helpers/lesli/customization_helper.rb +84 -0
  100. data/app/helpers/lesli/general_helper.rb +83 -0
  101. data/app/helpers/lesli/navigation_helper.rb +349 -0
  102. data/app/helpers/lesli/profiles_helper.rb +4 -0
  103. data/app/helpers/lesli/system_helper.rb +57 -0
  104. data/app/lib/date2.rb +192 -0
  105. data/app/lib/lesli/system.rb +80 -0
  106. data/app/models/concerns/account_engines.rb +249 -0
  107. data/app/models/concerns/user_activities.rb +163 -0
  108. data/app/models/concerns/user_extensions.rb +129 -0
  109. data/app/models/concerns/user_guard.rb +278 -0
  110. data/app/models/concerns/user_polyfill.rb +134 -0
  111. data/app/models/lesli/account/log.rb +57 -0
  112. data/app/models/lesli/account.rb +76 -0
  113. data/app/models/lesli/application_lesli_record.rb +37 -0
  114. data/app/models/lesli/profile.rb +4 -0
  115. data/app/models/lesli/system_controller/action.rb +37 -0
  116. data/app/models/lesli/system_controller.rb +37 -0
  117. data/app/models/lesli/user/agent.rb +37 -0
  118. data/app/models/lesli/user/log.rb +38 -0
  119. data/app/models/lesli/user/request.rb +37 -0
  120. data/app/models/lesli/user/session.rb +105 -0
  121. data/app/models/lesli/user.rb +162 -0
  122. data/app/services/lesli/application_lesli_service.rb +168 -0
  123. data/app/services/lesli/user/session_service.rb +62 -0
  124. data/app/validators/lesli/application_lesli_validator.rb +67 -0
  125. data/app/validators/lesli/users_validator.rb +217 -0
  126. data/app/views/devise/confirmations/new.html.erb +16 -0
  127. data/app/views/devise/mailer/confirmation_instructions.html.erb +5 -0
  128. data/app/views/devise/mailer/email_changed.html.erb +7 -0
  129. data/app/views/devise/mailer/password_change.html.erb +3 -0
  130. data/app/views/devise/mailer/reset_password_instructions.html.erb +8 -0
  131. data/app/views/devise/mailer/unlock_instructions.html.erb +7 -0
  132. data/app/views/devise/passwords/edit.html.erb +25 -0
  133. data/app/views/devise/passwords/new.html.erb +16 -0
  134. data/app/views/devise/registrations/edit.html.erb +43 -0
  135. data/app/views/devise/registrations/new.html.erb +29 -0
  136. data/app/views/devise/sessions/new.html.erb +178 -0
  137. data/app/views/devise/shared/_error_messages.html.erb +15 -0
  138. data/app/views/devise/shared/_links.html.erb +25 -0
  139. data/app/views/devise/unlocks/new.html.erb +16 -0
  140. data/app/views/lesli/devise/sessions/_form.html.erb +17 -0
  141. data/app/views/lesli/devise/sessions/_session.html.erb +2 -0
  142. data/app/views/lesli/devise/sessions/edit.html.erb +10 -0
  143. data/app/views/lesli/devise/sessions/index.html.erb +14 -0
  144. data/app/views/lesli/devise/sessions/new.html.erb +9 -0
  145. data/app/views/lesli/devise/sessions/show.html.erb +10 -0
  146. data/app/views/lesli/layouts/application-devise.html.erb +58 -0
  147. data/app/views/lesli/layouts/application-lesli.html.erb +57 -0
  148. data/app/views/lesli/layouts/application-public.html.erb +59 -0
  149. data/app/views/lesli/partials/_application-analytics.html.erb +71 -0
  150. data/app/views/lesli/partials/_application-data.html.erb +102 -0
  151. data/app/views/lesli/partials/_application-head.html.erb +56 -0
  152. data/app/views/lesli/partials/_application-lesli-chatbox.html.erb +35 -0
  153. data/app/views/lesli/partials/_application-lesli-content.html.erb +35 -0
  154. data/app/views/lesli/partials/_application-lesli-engines.html.erb +83 -0
  155. data/app/views/lesli/partials/_application-lesli-footer.html.erb +82 -0
  156. data/app/views/lesli/partials/_application-lesli-header.html.erb +79 -0
  157. data/app/views/lesli/partials/_application-lesli-icons.html.erb +1 -0
  158. data/app/views/lesli/partials/_application-lesli-javascript.html.erb +57 -0
  159. data/app/views/lesli/partials/_application-lesli-navigation.html.erb +52 -0
  160. data/app/views/lesli/partials/_application-lesli-notices.html.erb +43 -0
  161. data/app/views/lesli/partials/_application-lesli-panels.html.erb +58 -0
  162. data/app/views/lesli/partials/_application-lesli-scss.html.erb +60 -0
  163. data/app/views/lesli/partials/_application-lesli-sidebar.html.erb +50 -0
  164. data/app/views/lesli/partials/_application-public-footer.html.erb +51 -0
  165. data/app/views/lesli/partials/_application-public-javascript.html.erb +51 -0
  166. data/app/views/lesli/partials/_application-public-scss.html.erb +35 -0
  167. data/app/views/lesli/profiles/_form.html.erb +17 -0
  168. data/app/views/lesli/profiles/_profile.html.erb +2 -0
  169. data/app/views/lesli/profiles/edit.html.erb +10 -0
  170. data/app/views/lesli/profiles/index.html.erb +14 -0
  171. data/app/views/lesli/profiles/new.html.erb +9 -0
  172. data/app/views/lesli/profiles/show.html.erb +10 -0
  173. data/app/views/lesli/wrappers/_application-auth.html.erb +65 -0
  174. data/config/initializers/devise.rb +334 -0
  175. data/config/initializers/lesli_defaults.rb +100 -0
  176. data/config/locales/devise.en.yml +65 -0
  177. data/config/routes.rb +52 -0
  178. data/db/migrate/v1.0/0010000110_create_lesli_accounts.rb +70 -0
  179. data/db/migrate/v1.0/0010000210_create_lesli_roles.rb +59 -0
  180. data/db/migrate/v1.0/0010000310_create_lesli_users.rb +97 -0
  181. data/db/migrate/v1.0/0010000610_create_lesli_system_controllers.rb +44 -0
  182. data/db/migrate/v1.0/0010000710_create_lesli_system_controller_actions.rb +43 -0
  183. data/db/migrate/v1.0/0010001210_create_lesli_account_activities.rb +50 -0
  184. data/db/migrate/v1.0/0010001310_create_lesli_account_logs.rb +45 -0
  185. data/db/migrate/v1.0/0010003210_create_lesli_user_sessions.rb +51 -0
  186. data/db/migrate/v1.0/0010003310_create_lesli_user_requests.rb +48 -0
  187. data/db/migrate/v1.0/0010003610_create_lesli_user_logs.rb +45 -0
  188. data/db/migrate/v1.0/0010004010_create_lesli_user_agents.rb +46 -0
  189. data/db/seed/development/accounts.rb +47 -0
  190. data/db/seed/development/users.rb +53 -0
  191. data/db/seed/development.rb +35 -0
  192. data/db/seed/production.rb +35 -0
  193. data/db/seed/test.rb +35 -0
  194. data/db/seed/tools.rb +60 -0
  195. data/db/seeds.rb +64 -0
  196. data/db/structure/00000000_locations.json +32 -0
  197. data/db/structure/00000000_people.json +34 -0
  198. data/db/structure/00000003_actions.json +14 -0
  199. data/db/structure/00000004_activities.json +20 -0
  200. data/db/structure/00000005_discussions.json +8 -0
  201. data/db/structure/00000006_files.json +32 -0
  202. data/db/structure/00000007_subscribers.json +11 -0
  203. data/db/structure/00000008_custom_fields.json +8 -0
  204. data/db/structure/00000201_workflows.json +17 -0
  205. data/db/structure/00000202_workflow_statuses.json +24 -0
  206. data/db/structure/00000203_workflow_associations.json +14 -0
  207. data/db/structure/00000204_workflow_actions.json +39 -0
  208. data/db/structure/00000205_workflow_checks.json +27 -0
  209. data/db/structure/00000301_custom_fields.json +38 -0
  210. data/db/structure/00000401_custom_validations.json +14 -0
  211. data/db/structure/00000402_custom_validation_rules.json +23 -0
  212. data/db/structure/00000403_custom_validation_fields.json +14 -0
  213. data/db/structure/00000501_dashboards.json +14 -0
  214. data/db/structure/00000502_dashboard_components.json +23 -0
  215. data/db/tables/0010001010_create_account_settings.rb +42 -0
  216. data/db/tables/0010001110_create_account_locations.rb +64 -0
  217. data/db/tables/0010001410_create_account_files.rb +52 -0
  218. data/db/tables/0010001510_create_account_currencies.rb +48 -0
  219. data/db/tables/0010001610_create_account_currency_exchange_rates.rb +54 -0
  220. data/db/tables/0010003010_create_user_details.rb +49 -0
  221. data/db/tables/0010003110_create_user_settings.rb +44 -0
  222. data/db/tables/0010003410_create_user_activities.rb +51 -0
  223. data/db/tables/0010003510_create_user_roles.rb +43 -0
  224. data/db/tables/0010003710_create_user_codes.rb +43 -0
  225. data/db/tables/0010003810_create_user_shortcuts.rb +46 -0
  226. data/db/tables/0010004110_create_user_tokens.rb +45 -0
  227. data/db/tables/0010005010_create_descriptors.rb +45 -0
  228. data/db/tables/0010005110_create_descriptor_privileges.rb +44 -0
  229. data/db/tables/0010005210_create_descriptor_activities.rb +51 -0
  230. data/db/tables/0010005510_create_role_descriptors.rb +44 -0
  231. data/db/tables/0010005610_create_role_activities.rb +50 -0
  232. data/db/tables/0010005710_create_role_privileges.rb +45 -0
  233. data/db/tables/0010009010_create_feedbacks.rb +56 -0
  234. data/lib/assets/javascripts/lesli/i18n.js +1095 -0
  235. data/lib/assets/javascripts/lesli/translations.js +15 -0
  236. data/lib/lesli/configuration.rb +45 -0
  237. data/lib/lesli/engine.rb +62 -0
  238. data/lib/lesli/version.rb +34 -0
  239. data/lib/lesli.rb +6 -0
  240. data/lib/sass/lesli/bulma/loader.scss +84 -0
  241. data/lib/sass/lesli/cloud-objects/discussion.scss +77 -0
  242. data/lib/sass/lesli/cloud-objects/file.scss +138 -0
  243. data/lib/sass/lesli/components/editor-richtext.scss +78 -0
  244. data/lib/sass/lesli/components/keypad.scss +109 -0
  245. data/lib/sass/lesli/devise/confirmations.scss.erb +75 -0
  246. data/lib/sass/lesli/devise/passwords.scss.erb +86 -0
  247. data/lib/sass/lesli/devise/registrations.scss.erb +50 -0
  248. data/lib/sass/lesli/devise/sessions.scss +36 -0
  249. data/lib/sass/lesli/elements/autocomplete.scss +72 -0
  250. data/lib/sass/lesli/elements/avatar.scss +48 -0
  251. data/lib/sass/lesli/elements/calendar.scss +47 -0
  252. data/lib/sass/lesli/elements/card.scss +37 -0
  253. data/lib/sass/lesli/elements/content.scss +37 -0
  254. data/lib/sass/lesli/elements/empty.scss +43 -0
  255. data/lib/sass/lesli/elements/file-uploader.scss +74 -0
  256. data/lib/sass/lesli/elements/form.scss +43 -0
  257. data/lib/sass/lesli/elements/gallery.scss +98 -0
  258. data/lib/sass/lesli/elements/header.scss +44 -0
  259. data/lib/sass/lesli/elements/input-tag.scss +73 -0
  260. data/lib/sass/lesli/elements/loading.scss +63 -0
  261. data/lib/sass/lesli/elements/map.scss +107 -0
  262. data/lib/sass/lesli/elements/msg.scss +77 -0
  263. data/lib/sass/lesli/elements/navbar.scss +115 -0
  264. data/lib/sass/lesli/elements/panel.scss +65 -0
  265. data/lib/sass/lesli/elements/tab.scss +48 -0
  266. data/lib/sass/lesli/elements/table.scss +118 -0
  267. data/lib/sass/lesli/elements/toggle.scss +102 -0
  268. data/lib/sass/lesli/elements/toolbar.scss +66 -0
  269. data/lib/sass/lesli/fonts/families.scss +47 -0
  270. data/lib/sass/lesli/fonts/mdicons.scss +84 -0
  271. data/lib/sass/lesli/fonts/remixicons.scss +2602 -0
  272. data/lib/sass/lesli/helpers/display.scss +44 -0
  273. data/lib/sass/lesli/helpers/tooltip.scss +91 -0
  274. data/lib/sass/lesli/layouts/application-announcements.scss +40 -0
  275. data/lib/sass/lesli/layouts/application-component.scss +50 -0
  276. data/lib/sass/lesli/layouts/application-engines.scss +155 -0
  277. data/lib/sass/lesli/layouts/application-footer.scss +102 -0
  278. data/lib/sass/lesli/layouts/application-header.scss +152 -0
  279. data/lib/sass/lesli/layouts/application-navbar.scss +61 -0
  280. data/lib/sass/lesli/layouts/application-search.scss +71 -0
  281. data/lib/sass/lesli/layouts/application-sidebar.scss +219 -0
  282. data/lib/sass/lesli/overrides/sweetalert.scss +106 -0
  283. data/lib/sass/lesli/pages/dashboards.scss +57 -0
  284. data/lib/sass/lesli/pages/invites.scss +81 -0
  285. data/lib/sass/lesli/pages/mfas.scss +36 -0
  286. data/lib/sass/lesli/pages/otps.scss +36 -0
  287. data/lib/sass/lesli/pages/passes.scss +35 -0
  288. data/lib/sass/lesli/panels/panel-announcements.scss +56 -0
  289. data/lib/sass/lesli/panels/panel-notification.scss +67 -0
  290. data/lib/sass/lesli/panels/panel-profile.scss +62 -0
  291. data/lib/sass/lesli/panels/panel-tasks.scss +41 -0
  292. data/lib/sass/lesli/panels/panel-ticket.scss +57 -0
  293. data/lib/sass/lesli/settings/variables.scss +148 -0
  294. data/lib/sass/lesli/shared/workflow-status-progress.scss +135 -0
  295. data/lib/sass/lesli/templates/application.scss +141 -0
  296. data/lib/sass/lesli/templates/dashboards.scss +32 -0
  297. data/lib/sass/lesli/templates/devise.scss +185 -0
  298. data/lib/sass/lesli/templates/empty.scss +42 -0
  299. data/lib/sass/lesli/templates/pdf.scss +45 -0
  300. data/lib/sass/lesli/templates/public.scss +71 -0
  301. data/lib/tasks/db.rb +75 -0
  302. data/lib/tasks/lesli/controllers.rake +103 -0
  303. data/lib/tasks/lesli_tasks.rake +23 -0
  304. data/lib/vue/application.js +269 -0
  305. data/lib/vue/apps/cloudobjects/action.vue +193 -0
  306. data/lib/vue/apps/cloudobjects/discussion/content.vue +60 -0
  307. data/lib/vue/apps/cloudobjects/discussion/element.vue +132 -0
  308. data/lib/vue/apps/cloudobjects/discussion/filters.vue +108 -0
  309. data/lib/vue/apps/cloudobjects/discussion/new.vue +130 -0
  310. data/lib/vue/apps/cloudobjects/discussion.vue +98 -0
  311. data/lib/vue/apps/cloudobjects/file/grid.vue +215 -0
  312. data/lib/vue/apps/cloudobjects/file/list.vue +106 -0
  313. data/lib/vue/apps/cloudobjects/file.vue +145 -0
  314. data/lib/vue/apps/dashboards/apps/edit.vue +105 -0
  315. data/lib/vue/apps/dashboards/apps/index.vue +114 -0
  316. data/lib/vue/apps/dashboards/apps/new.vue +89 -0
  317. data/lib/vue/apps/dashboards/apps/show.vue +76 -0
  318. data/lib/vue/apps/dashboards/components/form.vue +267 -0
  319. data/lib/vue/apps/dashboards/components/preview.vue +172 -0
  320. data/lib/vue/apps/workflows2/apps/actions/form.vue +232 -0
  321. data/lib/vue/apps/workflows2/apps/actions/forms/chatroom-form.vue +103 -0
  322. data/lib/vue/apps/workflows2/apps/actions/forms/cloud-object-clone-form.vue +125 -0
  323. data/lib/vue/apps/workflows2/apps/actions/forms/cloud-object-file-form.vue +102 -0
  324. data/lib/vue/apps/workflows2/apps/actions/forms/email-form.vue +190 -0
  325. data/lib/vue/apps/workflows2/apps/actions/forms/notification-form.vue +124 -0
  326. data/lib/vue/apps/workflows2/apps/actions/forms/send-cloud-object-file.vue +170 -0
  327. data/lib/vue/apps/workflows2/apps/actions/forms/task-form.vue +258 -0
  328. data/lib/vue/apps/workflows2/apps/actions/index.vue +146 -0
  329. data/lib/vue/apps/workflows2/apps/checks/form.vue +200 -0
  330. data/lib/vue/apps/workflows2/apps/checks/index.vue +160 -0
  331. data/lib/vue/apps/workflows2/apps/index.vue +177 -0
  332. data/lib/vue/apps/workflows2/apps/new.vue +97 -0
  333. data/lib/vue/apps/workflows2/apps/show.vue +146 -0
  334. data/lib/vue/apps/workflows2/components/associations.vue +215 -0
  335. data/lib/vue/apps/workflows2/components/chart.vue +91 -0
  336. data/lib/vue/apps/workflows2/components/workflow-form.vue +466 -0
  337. data/lib/vue/apps/workflows2/components/workflow-status-dropdown.vue +129 -0
  338. data/lib/vue/devise/confirmations.js +33 -0
  339. data/lib/vue/devise/passwords.js +137 -0
  340. data/lib/vue/devise/registrations.js +162 -0
  341. data/lib/vue/devise/sessions.js +143 -0
  342. data/lib/vue/layouts/application-announcements.vue +78 -0
  343. data/lib/vue/layouts/application-engines.vue +66 -0
  344. data/lib/vue/layouts/application-footer.vue +123 -0
  345. data/lib/vue/layouts/application-header.vue +213 -0
  346. data/lib/vue/layouts/application-navbar.vue +110 -0
  347. data/lib/vue/layouts/application-search.vue +86 -0
  348. data/lib/vue/layouts/application-sidebar.vue +63 -0
  349. data/lib/vue/layouts/dashboard-component.vue +62 -0
  350. data/lib/vue/pages/errors/app.js +32 -0
  351. data/lib/vue/pages/invites/app.js +76 -0
  352. data/lib/vue/pages/mfas/application.js +77 -0
  353. data/lib/vue/pages/onboarding/application.js +45 -0
  354. data/lib/vue/pages/onboarding/components/address.vue +120 -0
  355. data/lib/vue/pages/onboarding/components/buttons.vue +67 -0
  356. data/lib/vue/pages/onboarding/components/contact.vue +148 -0
  357. data/lib/vue/pages/onboarding/components/date-time.vue +265 -0
  358. data/lib/vue/pages/onboarding/components/finish.vue +62 -0
  359. data/lib/vue/pages/onboarding/components/general-info.vue +93 -0
  360. data/lib/vue/pages/onboarding/components/indicators.vue +78 -0
  361. data/lib/vue/pages/onboarding/components/welcome.vue +66 -0
  362. data/lib/vue/pages/onboarding/show.vue +67 -0
  363. data/lib/vue/pages/onboarding/store.js +165 -0
  364. data/lib/vue/pages/otps/application.js +90 -0
  365. data/lib/vue/pages/passes/application.js +80 -0
  366. data/lib/vue/pages/websites/application.js +34 -0
  367. data/lib/vue/panels/panel-announcements.vue +248 -0
  368. data/lib/vue/panels/panel-files.vue +281 -0
  369. data/lib/vue/panels/panel-notifications.vue +106 -0
  370. data/lib/vue/panels/panel-profile.vue +76 -0
  371. data/lib/vue/panels/panel-tasks.vue +124 -0
  372. data/lib/vue/panels/panel-tickets.vue +181 -0
  373. data/lib/vue/public.js +85 -0
  374. data/lib/vue/stores/announcements.js +75 -0
  375. data/lib/vue/stores/cloud-bell/notification.js +114 -0
  376. data/lib/vue/stores/cloudobjects/action.js +181 -0
  377. data/lib/vue/stores/cloudobjects/discussion.js +221 -0
  378. data/lib/vue/stores/cloudobjects/file.js +205 -0
  379. data/lib/vue/stores/dashboard.js +251 -0
  380. data/lib/vue/stores/firebase.js +163 -0
  381. data/lib/vue/stores/layout.js +60 -0
  382. data/lib/vue/stores/panels/announcements.js +153 -0
  383. data/lib/vue/stores/panels/task.js +66 -0
  384. data/lib/vue/stores/panels/tickets.js +129 -0
  385. data/lib/vue/stores/profile.js +90 -0
  386. data/lib/vue/stores/search.js +154 -0
  387. data/lib/vue/stores/services/translator.js +87 -0
  388. data/lib/vue/stores/workflow.js +185 -0
  389. data/lib/vue/stores/workflow2.js +345 -0
  390. data/lib/vue/stores/workflows/actions.js +327 -0
  391. data/lib/vue/stores/workflows/associations.js +130 -0
  392. data/lib/vue/stores/workflows/checks.js +210 -0
  393. data/lib/webpack/base.js +182 -0
  394. data/lib/webpack/core.js +80 -0
  395. data/lib/webpack/engines.js +162 -0
  396. data/license +674 -0
  397. data/readme.md +120 -0
  398. metadata +554 -0
@@ -0,0 +1,1095 @@
1
+ // I18n.js
2
+ // =======
3
+ //
4
+ // This small library provides the Rails I18n API on the Javascript.
5
+ // You don't actually have to use Rails (or even Ruby) to use I18n.js.
6
+ // Just make sure you export all translations in an object like this:
7
+ //
8
+ // I18n.translations.en = {
9
+ // hello: "Hello World"
10
+ // };
11
+ //
12
+ // See tests for specific formatting like numbers and dates.
13
+ //
14
+
15
+ // Using UMD pattern from
16
+ // https://github.com/umdjs/umd#regular-module
17
+ // `returnExports.js` version
18
+ ;(function (root, factory) {
19
+ if (typeof define === 'function' && define.amd) {
20
+ // AMD. Register as an anonymous module.
21
+ define("i18n", function(){ return factory(root);});
22
+ } else if (typeof module === 'object' && module.exports) {
23
+ // Node. Does not work with strict CommonJS, but
24
+ // only CommonJS-like environments that support module.exports,
25
+ // like Node.
26
+ module.exports = factory(root);
27
+ } else {
28
+ // Browser globals (root is window)
29
+ root.I18n = factory(root);
30
+ }
31
+ }(this, function(global) {
32
+ "use strict";
33
+
34
+ // Use previously defined object if exists in current scope
35
+ var I18n = global && global.I18n || {};
36
+
37
+ // Just cache the Array#slice function.
38
+ var slice = Array.prototype.slice;
39
+
40
+ // Apply number padding.
41
+ var padding = function(number) {
42
+ return ("0" + number.toString()).substr(-2);
43
+ };
44
+
45
+ // Improved toFixed number rounding function with support for unprecise floating points
46
+ // JavaScript's standard toFixed function does not round certain numbers correctly (for example 0.105 with precision 2).
47
+ var toFixed = function(number, precision) {
48
+ return decimalAdjust('round', number, -precision).toFixed(precision);
49
+ };
50
+
51
+ // Is a given variable an object?
52
+ // Borrowed from Underscore.js
53
+ var isObject = function(obj) {
54
+ var type = typeof obj;
55
+ return type === 'function' || type === 'object'
56
+ };
57
+
58
+ var isFunction = function(func) {
59
+ var type = typeof func;
60
+ return type === 'function'
61
+ };
62
+
63
+ // Check if value is different than undefined and null;
64
+ var isSet = function(value) {
65
+ return typeof(value) !== 'undefined' && value !== null;
66
+ };
67
+
68
+ // Is a given value an array?
69
+ // Borrowed from Underscore.js
70
+ var isArray = function(val) {
71
+ if (Array.isArray) {
72
+ return Array.isArray(val);
73
+ }
74
+ return Object.prototype.toString.call(val) === '[object Array]';
75
+ };
76
+
77
+ var isString = function(val) {
78
+ return typeof val === 'string' || Object.prototype.toString.call(val) === '[object String]';
79
+ };
80
+
81
+ var isNumber = function(val) {
82
+ return typeof val === 'number' || Object.prototype.toString.call(val) === '[object Number]';
83
+ };
84
+
85
+ var isBoolean = function(val) {
86
+ return val === true || val === false;
87
+ };
88
+
89
+ var isNull = function(val) {
90
+ return val === null;
91
+ };
92
+
93
+ var decimalAdjust = function(type, value, exp) {
94
+ // If the exp is undefined or zero...
95
+ if (typeof exp === 'undefined' || +exp === 0) {
96
+ return Math[type](value);
97
+ }
98
+ value = +value;
99
+ exp = +exp;
100
+ // If the value is not a number or the exp is not an integer...
101
+ if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
102
+ return NaN;
103
+ }
104
+ // Shift
105
+ value = value.toString().split('e');
106
+ value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
107
+ // Shift back
108
+ value = value.toString().split('e');
109
+ return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
110
+ };
111
+
112
+ var lazyEvaluate = function(message, scope) {
113
+ if (isFunction(message)) {
114
+ return message(scope);
115
+ } else {
116
+ return message;
117
+ }
118
+ };
119
+
120
+ var merge = function (dest, obj) {
121
+ var key, value;
122
+ for (key in obj) if (obj.hasOwnProperty(key)) {
123
+ value = obj[key];
124
+ if (isString(value) || isNumber(value) || isBoolean(value) || isArray(value) || isNull(value)) {
125
+ dest[key] = value;
126
+ } else {
127
+ if (dest[key] == null) dest[key] = {};
128
+ merge(dest[key], value);
129
+ }
130
+ }
131
+ return dest;
132
+ };
133
+
134
+ // Set default days/months translations.
135
+ var DATE = {
136
+ day_names: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]
137
+ , abbr_day_names: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
138
+ , month_names: [null, "January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]
139
+ , abbr_month_names: [null, "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]
140
+ , meridian: ["AM", "PM"]
141
+ };
142
+
143
+ // Set default number format.
144
+ var NUMBER_FORMAT = {
145
+ precision: 3
146
+ , separator: "."
147
+ , delimiter: ","
148
+ , strip_insignificant_zeros: false
149
+ };
150
+
151
+ // Set default currency format.
152
+ var CURRENCY_FORMAT = {
153
+ unit: "$"
154
+ , precision: 2
155
+ , format: "%u%n"
156
+ , sign_first: true
157
+ , delimiter: ","
158
+ , separator: "."
159
+ };
160
+
161
+ // Set default percentage format.
162
+ var PERCENTAGE_FORMAT = {
163
+ unit: "%"
164
+ , precision: 3
165
+ , format: "%n%u"
166
+ , separator: "."
167
+ , delimiter: ""
168
+ };
169
+
170
+ // Set default size units.
171
+ var SIZE_UNITS = [null, "kb", "mb", "gb", "tb"];
172
+
173
+ // Other default options
174
+ var DEFAULT_OPTIONS = {
175
+ // Set default locale. This locale will be used when fallback is enabled and
176
+ // the translation doesn't exist in a particular locale.
177
+ defaultLocale: "en"
178
+ // Set the current locale to `en`.
179
+ , locale: "en"
180
+ // Set the translation key separator.
181
+ , defaultSeparator: "."
182
+ // Set the placeholder format. Accepts `{{placeholder}}` and `%{placeholder}`.
183
+ , placeholder: /(?:\{\{|%\{)(.*?)(?:\}\}?)/gm
184
+ // Set if engine should fallback to the default locale when a translation
185
+ // is missing.
186
+ , fallbacks: false
187
+ // Set the default translation object.
188
+ , translations: {}
189
+ // Set missing translation behavior. 'message' will display a message
190
+ // that the translation is missing, 'guess' will try to guess the string
191
+ , missingBehaviour: 'message'
192
+ // if you use missingBehaviour with 'message', but want to know that the
193
+ // string is actually missing for testing purposes, you can prefix the
194
+ // guessed string by setting the value here. By default, no prefix!
195
+ , missingTranslationPrefix: ''
196
+ };
197
+
198
+ // Set default locale. This locale will be used when fallback is enabled and
199
+ // the translation doesn't exist in a particular locale.
200
+ I18n.reset = function() {
201
+ var key;
202
+ for (key in DEFAULT_OPTIONS) {
203
+ this[key] = DEFAULT_OPTIONS[key];
204
+ }
205
+ };
206
+
207
+ // Much like `reset`, but only assign options if not already assigned
208
+ I18n.initializeOptions = function() {
209
+ var key;
210
+ for (key in DEFAULT_OPTIONS) if (!isSet(this[key])) {
211
+ this[key] = DEFAULT_OPTIONS[key];
212
+ }
213
+ };
214
+ I18n.initializeOptions();
215
+
216
+ // Return a list of all locales that must be tried before returning the
217
+ // missing translation message. By default, this will consider the inline option,
218
+ // current locale and fallback locale.
219
+ //
220
+ // I18n.locales.get("de-DE");
221
+ // // ["de-DE", "de", "en"]
222
+ //
223
+ // You can define custom rules for any locale. Just make sure you return a array
224
+ // containing all locales.
225
+ //
226
+ // // Default the Wookie locale to English.
227
+ // I18n.locales["wk"] = function(locale) {
228
+ // return ["en"];
229
+ // };
230
+ //
231
+ I18n.locales = {};
232
+
233
+ // Retrieve locales based on inline locale, current locale or default to
234
+ // I18n's detection.
235
+ I18n.locales.get = function(locale) {
236
+ var result = this[locale] || this[I18n.locale] || this["default"];
237
+
238
+ if (isFunction(result)) {
239
+ result = result(locale);
240
+ }
241
+
242
+ if (isArray(result) === false) {
243
+ result = [result];
244
+ }
245
+
246
+ return result;
247
+ };
248
+
249
+ // The default locale list.
250
+ I18n.locales["default"] = function(locale) {
251
+ var locales = []
252
+ , list = []
253
+ ;
254
+
255
+ // Handle the inline locale option that can be provided to
256
+ // the `I18n.t` options.
257
+ if (locale) {
258
+ locales.push(locale);
259
+ }
260
+
261
+ // Add the current locale to the list.
262
+ if (!locale && I18n.locale) {
263
+ locales.push(I18n.locale);
264
+ }
265
+
266
+ // Add the default locale if fallback strategy is enabled.
267
+ if (I18n.fallbacks && I18n.defaultLocale) {
268
+ locales.push(I18n.defaultLocale);
269
+ }
270
+
271
+ // Locale code format 1:
272
+ // According to RFC4646 (https://www.ietf.org/rfc/rfc4646.txt)
273
+ // language codes for Traditional Chinese should be `zh-Hant`
274
+ //
275
+ // But due to backward compatibility
276
+ // We use older version of IETF language tag
277
+ // @see https://www.w3.org/TR/html401/struct/dirlang.html
278
+ // @see https://en.wikipedia.org/wiki/IETF_language_tag
279
+ //
280
+ // Format: `language-code = primary-code ( "-" subcode )*`
281
+ //
282
+ // primary-code uses ISO639-1
283
+ // @see https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
284
+ // @see https://www.iso.org/iso/home/standards/language_codes.htm
285
+ //
286
+ // subcode uses ISO 3166-1 alpha-2
287
+ // @see https://en.wikipedia.org/wiki/ISO_3166
288
+ // @see https://www.iso.org/iso/country_codes.htm
289
+ //
290
+ // @note
291
+ // subcode can be in upper case or lower case
292
+ // defining it in upper case is a convention only
293
+
294
+
295
+ // Locale code format 2:
296
+ // Format: `code = primary-code ( "-" region-code )*`
297
+ // primary-code uses ISO 639-1
298
+ // script-code uses ISO 15924
299
+ // region-code uses ISO 3166-1 alpha-2
300
+ // Example: zh-Hant-TW, en-HK, zh-Hant-CN
301
+ //
302
+ // It is similar to RFC4646 (or actually the same),
303
+ // but seems to be limited to language, script, region
304
+
305
+ // Compute each locale with its country code.
306
+ // So this will return an array containing
307
+ // `de-DE` and `de`
308
+ // or
309
+ // `zh-hans-tw`, `zh-hans`, `zh`
310
+ // locales.
311
+ locales.forEach(function(locale) {
312
+ var localeParts = locale.split("-");
313
+ var firstFallback = null;
314
+ var secondFallback = null;
315
+ if (localeParts.length === 3) {
316
+ firstFallback = [
317
+ localeParts[0],
318
+ localeParts[1]
319
+ ].join("-");
320
+ secondFallback = localeParts[0];
321
+ }
322
+ else if (localeParts.length === 2) {
323
+ firstFallback = localeParts[0];
324
+ }
325
+
326
+ if (list.indexOf(locale) === -1) {
327
+ list.push(locale);
328
+ }
329
+
330
+ if (! I18n.fallbacks) {
331
+ return;
332
+ }
333
+
334
+ [
335
+ firstFallback,
336
+ secondFallback
337
+ ].forEach(function(nullableFallbackLocale) {
338
+ // We don't want null values
339
+ if (typeof nullableFallbackLocale === "undefined") { return; }
340
+ if (nullableFallbackLocale === null) { return; }
341
+ // We don't want duplicate values
342
+ //
343
+ // Comparing with `locale` first is faster than
344
+ // checking whether value's presence in the list
345
+ if (nullableFallbackLocale === locale) { return; }
346
+ if (list.indexOf(nullableFallbackLocale) !== -1) { return; }
347
+
348
+ list.push(nullableFallbackLocale);
349
+ });
350
+ });
351
+
352
+ // No locales set? English it is.
353
+ if (!locales.length) {
354
+ locales.push("en");
355
+ }
356
+
357
+ return list;
358
+ };
359
+
360
+ // Hold pluralization rules.
361
+ I18n.pluralization = {};
362
+
363
+ // Return the pluralizer for a specific locale.
364
+ // If no specify locale is found, then I18n's default will be used.
365
+ I18n.pluralization.get = function(locale) {
366
+ return this[locale] || this[I18n.locale] || this["default"];
367
+ };
368
+
369
+ // The default pluralizer rule.
370
+ // It detects the `zero`, `one`, and `other` scopes.
371
+ I18n.pluralization["default"] = function(count) {
372
+ switch (count) {
373
+ case 0: return ["zero", "other"];
374
+ case 1: return ["one"];
375
+ default: return ["other"];
376
+ }
377
+ };
378
+
379
+ // Return current locale. If no locale has been set, then
380
+ // the current locale will be the default locale.
381
+ I18n.currentLocale = function() {
382
+ return this.locale || this.defaultLocale;
383
+ };
384
+
385
+ // Check if value is different than undefined and null;
386
+ I18n.isSet = isSet;
387
+
388
+ // Find and process the translation using the provided scope and options.
389
+ // This is used internally by some functions and should not be used as an
390
+ // public API.
391
+ I18n.lookup = function(scope, options) {
392
+ options = options || {};
393
+
394
+ var locales = this.locales.get(options.locale).slice()
395
+ , locale
396
+ , scopes
397
+ , fullScope
398
+ , translations
399
+ ;
400
+
401
+ fullScope = this.getFullScope(scope, options);
402
+
403
+ while (locales.length) {
404
+ locale = locales.shift();
405
+ scopes = fullScope.split(options.separator || this.defaultSeparator);
406
+ translations = this.translations[locale];
407
+
408
+ if (!translations) {
409
+ continue;
410
+ }
411
+ while (scopes.length) {
412
+ translations = translations[scopes.shift()];
413
+
414
+ if (translations === undefined || translations === null) {
415
+ break;
416
+ }
417
+ }
418
+
419
+ if (translations !== undefined && translations !== null) {
420
+ return translations;
421
+ }
422
+ }
423
+
424
+ if (isSet(options.defaultValue)) {
425
+ return lazyEvaluate(options.defaultValue, scope);
426
+ }
427
+ };
428
+
429
+ // lookup pluralization rule key into translations
430
+ I18n.pluralizationLookupWithoutFallback = function(count, locale, translations) {
431
+ var pluralizer = this.pluralization.get(locale)
432
+ , pluralizerKeys = pluralizer(count)
433
+ , pluralizerKey
434
+ , message;
435
+
436
+ if (translations && isObject(translations)) {
437
+ while (pluralizerKeys.length) {
438
+ pluralizerKey = pluralizerKeys.shift();
439
+ if (isSet(translations[pluralizerKey])) {
440
+ message = translations[pluralizerKey];
441
+ break;
442
+ }
443
+ }
444
+ }
445
+
446
+ return message;
447
+ };
448
+
449
+ // Lookup dedicated to pluralization
450
+ I18n.pluralizationLookup = function(count, scope, options) {
451
+ options = options || {};
452
+ var locales = this.locales.get(options.locale).slice()
453
+ , locale
454
+ , scopes
455
+ , translations
456
+ , message
457
+ ;
458
+ scope = this.getFullScope(scope, options);
459
+
460
+ while (locales.length) {
461
+ locale = locales.shift();
462
+ scopes = scope.split(options.separator || this.defaultSeparator);
463
+ translations = this.translations[locale];
464
+
465
+ if (!translations) {
466
+ continue;
467
+ }
468
+
469
+ while (scopes.length) {
470
+ translations = translations[scopes.shift()];
471
+ if (!isObject(translations)) {
472
+ break;
473
+ }
474
+ if (scopes.length === 0) {
475
+ message = this.pluralizationLookupWithoutFallback(count, locale, translations);
476
+ }
477
+ }
478
+ if (typeof message !== "undefined" && message !== null) {
479
+ break;
480
+ }
481
+ }
482
+
483
+ if (typeof message === "undefined" || message === null) {
484
+ if (isSet(options.defaultValue)) {
485
+ if (isObject(options.defaultValue)) {
486
+ message = this.pluralizationLookupWithoutFallback(count, options.locale, options.defaultValue);
487
+ } else {
488
+ message = options.defaultValue;
489
+ }
490
+ translations = options.defaultValue;
491
+ }
492
+ }
493
+
494
+ return { message: message, translations: translations };
495
+ };
496
+
497
+ // Rails changed the way the meridian is stored.
498
+ // It started with `date.meridian` returning an array,
499
+ // then it switched to `time.am` and `time.pm`.
500
+ // This function abstracts this difference and returns
501
+ // the correct meridian or the default value when none is provided.
502
+ I18n.meridian = function() {
503
+ var time = this.lookup("time");
504
+ var date = this.lookup("date");
505
+
506
+ if (time && time.am && time.pm) {
507
+ return [time.am, time.pm];
508
+ } else if (date && date.meridian) {
509
+ return date.meridian;
510
+ } else {
511
+ return DATE.meridian;
512
+ }
513
+ };
514
+
515
+ // Merge serveral hash options, checking if value is set before
516
+ // overwriting any value. The precedence is from left to right.
517
+ //
518
+ // I18n.prepareOptions({name: "John Doe"}, {name: "Mary Doe", role: "user"});
519
+ // #=> {name: "John Doe", role: "user"}
520
+ //
521
+ I18n.prepareOptions = function() {
522
+ var args = slice.call(arguments)
523
+ , options = {}
524
+ , subject
525
+ ;
526
+
527
+ while (args.length) {
528
+ subject = args.shift();
529
+
530
+ if (typeof(subject) != "object") {
531
+ continue;
532
+ }
533
+
534
+ for (var attr in subject) {
535
+ if (!subject.hasOwnProperty(attr)) {
536
+ continue;
537
+ }
538
+
539
+ if (isSet(options[attr])) {
540
+ continue;
541
+ }
542
+
543
+ options[attr] = subject[attr];
544
+ }
545
+ }
546
+
547
+ return options;
548
+ };
549
+
550
+ // Generate a list of translation options for default fallbacks.
551
+ // `defaultValue` is also deleted from options as it is returned as part of
552
+ // the translationOptions array.
553
+ I18n.createTranslationOptions = function(scope, options) {
554
+ var translationOptions = [{scope: scope}];
555
+
556
+ // Defaults should be an array of hashes containing either
557
+ // fallback scopes or messages
558
+ if (isSet(options.defaults)) {
559
+ translationOptions = translationOptions.concat(options.defaults);
560
+ }
561
+
562
+ // Maintain support for defaultValue. Since it is always a message
563
+ // insert it in to the translation options as such.
564
+ if (isSet(options.defaultValue)) {
565
+ translationOptions.push({ message: options.defaultValue });
566
+ }
567
+
568
+ return translationOptions;
569
+ };
570
+
571
+ // Translate the given scope with the provided options.
572
+ I18n.translate = function(scope, options) {
573
+ options = options || {};
574
+
575
+ var translationOptions = this.createTranslationOptions(scope, options);
576
+
577
+ var translation;
578
+ var usedScope = scope;
579
+
580
+ var optionsWithoutDefault = this.prepareOptions(options)
581
+ delete optionsWithoutDefault.defaultValue
582
+
583
+ // Iterate through the translation options until a translation
584
+ // or message is found.
585
+ var translationFound =
586
+ translationOptions.some(function(translationOption) {
587
+ if (isSet(translationOption.scope)) {
588
+ usedScope = translationOption.scope;
589
+ translation = this.lookup(usedScope, optionsWithoutDefault);
590
+ } else if (isSet(translationOption.message)) {
591
+ translation = lazyEvaluate(translationOption.message, scope);
592
+ }
593
+
594
+ if (translation !== undefined && translation !== null) {
595
+ return true;
596
+ }
597
+ }, this);
598
+
599
+ if (!translationFound) {
600
+ return this.missingTranslation(scope, options);
601
+ }
602
+
603
+ if (typeof(translation) === "string") {
604
+ translation = this.interpolate(translation, options);
605
+ } else if (isArray(translation)) {
606
+ translation = translation.map(function(t) {
607
+ return (typeof(t) === "string" ? this.interpolate(t, options) : t);
608
+ }, this);
609
+ } else if (isObject(translation) && isSet(options.count)) {
610
+ translation = this.pluralize(options.count, usedScope, options);
611
+ }
612
+
613
+ return translation;
614
+ };
615
+
616
+ // This function interpolates the all variables in the given message.
617
+ I18n.interpolate = function(message, options) {
618
+ if (message == null) {
619
+ return message;
620
+ }
621
+
622
+ options = options || {};
623
+ var matches = message.match(this.placeholder)
624
+ , placeholder
625
+ , value
626
+ , name
627
+ , regex
628
+ ;
629
+
630
+ if (!matches) {
631
+ return message;
632
+ }
633
+
634
+ while (matches.length) {
635
+ placeholder = matches.shift();
636
+ name = placeholder.replace(this.placeholder, "$1");
637
+
638
+ if (isSet(options[name])) {
639
+ value = options[name].toString().replace(/\$/gm, "_#$#_");
640
+ } else if (name in options) {
641
+ value = this.nullPlaceholder(placeholder, message, options);
642
+ } else {
643
+ value = this.missingPlaceholder(placeholder, message, options);
644
+ }
645
+
646
+ regex = new RegExp(placeholder.replace(/{/gm, "\\{").replace(/}/gm, "\\}"));
647
+ message = message.replace(regex, value);
648
+ }
649
+
650
+ return message.replace(/_#\$#_/g, "$");
651
+ };
652
+
653
+ // Pluralize the given scope using the `count` value.
654
+ // The pluralized translation may have other placeholders,
655
+ // which will be retrieved from `options`.
656
+ I18n.pluralize = function(count, scope, options) {
657
+ options = this.prepareOptions({count: String(count)}, options)
658
+ var pluralizer, result;
659
+
660
+ result = this.pluralizationLookup(count, scope, options);
661
+ if (typeof result.translations === "undefined" || result.translations == null) {
662
+ return this.missingTranslation(scope, options);
663
+ }
664
+
665
+ if (typeof result.message !== "undefined" && result.message != null) {
666
+ return this.interpolate(result.message, options);
667
+ }
668
+ else {
669
+ pluralizer = this.pluralization.get(options.locale);
670
+ return this.missingTranslation(scope + '.' + pluralizer(count)[0], options);
671
+ }
672
+ };
673
+
674
+ // Return a missing translation message for the given parameters.
675
+ I18n.missingTranslation = function(scope, options) {
676
+ //guess intended string
677
+ if(this.missingBehaviour === 'guess'){
678
+ //get only the last portion of the scope
679
+ var s = scope.split('.').slice(-1)[0];
680
+ //replace underscore with space && camelcase with space and lowercase letter
681
+ return (this.missingTranslationPrefix.length > 0 ? this.missingTranslationPrefix : '') +
682
+ s.replace(/_/g,' ').replace(/([a-z])([A-Z])/g,
683
+ function(match, p1, p2) {return p1 + ' ' + p2.toLowerCase()} );
684
+ }
685
+
686
+ var localeForTranslation = (options != null && options.locale != null) ? options.locale : this.currentLocale();
687
+ var fullScope = this.getFullScope(scope, options);
688
+ var fullScopeWithLocale = [localeForTranslation, fullScope].join(options.separator || this.defaultSeparator);
689
+
690
+ return '[missing "' + fullScopeWithLocale + '" translation]';
691
+ };
692
+
693
+ // Return a missing placeholder message for given parameters
694
+ I18n.missingPlaceholder = function(placeholder, message, options) {
695
+ return "[missing " + placeholder + " value]";
696
+ };
697
+
698
+ I18n.nullPlaceholder = function() {
699
+ return I18n.missingPlaceholder.apply(I18n, arguments);
700
+ };
701
+
702
+ // Format number using localization rules.
703
+ // The options will be retrieved from the `number.format` scope.
704
+ // If this isn't present, then the following options will be used:
705
+ //
706
+ // - `precision`: `3`
707
+ // - `separator`: `"."`
708
+ // - `delimiter`: `","`
709
+ // - `strip_insignificant_zeros`: `false`
710
+ //
711
+ // You can also override these options by providing the `options` argument.
712
+ //
713
+ I18n.toNumber = function(number, options) {
714
+ options = this.prepareOptions(
715
+ options
716
+ , this.lookup("number.format")
717
+ , NUMBER_FORMAT
718
+ );
719
+
720
+ var negative = number < 0
721
+ , string = toFixed(Math.abs(number), options.precision).toString()
722
+ , parts = string.split(".")
723
+ , precision
724
+ , buffer = []
725
+ , formattedNumber
726
+ , format = options.format || "%n"
727
+ , sign = negative ? "-" : ""
728
+ ;
729
+
730
+ number = parts[0];
731
+ precision = parts[1];
732
+
733
+ while (number.length > 0) {
734
+ buffer.unshift(number.substr(Math.max(0, number.length - 3), 3));
735
+ number = number.substr(0, number.length -3);
736
+ }
737
+
738
+ formattedNumber = buffer.join(options.delimiter);
739
+
740
+ if (options.strip_insignificant_zeros && precision) {
741
+ precision = precision.replace(/0+$/, "");
742
+ }
743
+
744
+ if (options.precision > 0 && precision) {
745
+ formattedNumber += options.separator + precision;
746
+ }
747
+
748
+ if (options.sign_first) {
749
+ format = "%s" + format;
750
+ }
751
+ else {
752
+ format = format.replace("%n", "%s%n");
753
+ }
754
+
755
+ formattedNumber = format
756
+ .replace("%u", options.unit)
757
+ .replace("%n", formattedNumber)
758
+ .replace("%s", sign)
759
+ ;
760
+
761
+ return formattedNumber;
762
+ };
763
+
764
+ // Format currency with localization rules.
765
+ // The options will be retrieved from the `number.currency.format` and
766
+ // `number.format` scopes, in that order.
767
+ //
768
+ // Any missing option will be retrieved from the `I18n.toNumber` defaults and
769
+ // the following options:
770
+ //
771
+ // - `unit`: `"$"`
772
+ // - `precision`: `2`
773
+ // - `format`: `"%u%n"`
774
+ // - `delimiter`: `","`
775
+ // - `separator`: `"."`
776
+ //
777
+ // You can also override these options by providing the `options` argument.
778
+ //
779
+ I18n.toCurrency = function(number, options) {
780
+ options = this.prepareOptions(
781
+ options
782
+ , this.lookup("number.currency.format", options)
783
+ , this.lookup("number.format", options)
784
+ , CURRENCY_FORMAT
785
+ );
786
+
787
+ return this.toNumber(number, options);
788
+ };
789
+
790
+ // Localize several values.
791
+ // You can provide the following scopes: `currency`, `number`, or `percentage`.
792
+ // If you provide a scope that matches the `/^(date|time)/` regular expression
793
+ // then the `value` will be converted by using the `I18n.toTime` function.
794
+ //
795
+ // It will default to the value's `toString` function.
796
+ //
797
+ I18n.localize = function(scope, value, options) {
798
+ options || (options = {});
799
+
800
+ switch (scope) {
801
+ case "currency":
802
+ return this.toCurrency(value, options);
803
+ case "number":
804
+ scope = this.lookup("number.format", options);
805
+ return this.toNumber(value, scope);
806
+ case "percentage":
807
+ return this.toPercentage(value, options);
808
+ default:
809
+ var localizedValue;
810
+
811
+ if (scope.match(/^(date|time)/)) {
812
+ localizedValue = this.toTime(scope, value, options);
813
+ } else {
814
+ localizedValue = value.toString();
815
+ }
816
+
817
+ return this.interpolate(localizedValue, options);
818
+ }
819
+ };
820
+
821
+ // Parse a given `date` string into a JavaScript Date object.
822
+ // This function is time zone aware.
823
+ //
824
+ // The following string formats are recognized:
825
+ //
826
+ // yyyy-mm-dd
827
+ // yyyy-mm-dd[ T]hh:mm::ss
828
+ // yyyy-mm-dd[ T]hh:mm::ss
829
+ // yyyy-mm-dd[ T]hh:mm::ssZ
830
+ // yyyy-mm-dd[ T]hh:mm::ss+0000
831
+ // yyyy-mm-dd[ T]hh:mm::ss+00:00
832
+ // yyyy-mm-dd[ T]hh:mm::ss.123Z
833
+ //
834
+ I18n.parseDate = function(date) {
835
+ var matches, convertedDate, fraction;
836
+ // A date input of `null` or `undefined` will be returned as-is
837
+ if (date == null) {
838
+ return date;
839
+ }
840
+ // we have a date, so just return it.
841
+ if (typeof(date) === "object") {
842
+ return date;
843
+ }
844
+
845
+ matches = date.toString().match(/(\d{4})-(\d{2})-(\d{2})(?:[ T](\d{2}):(\d{2}):(\d{2})([\.,]\d{1,3})?)?(Z|\+00:?00)?/);
846
+
847
+ if (matches) {
848
+ for (var i = 1; i <= 6; i++) {
849
+ matches[i] = parseInt(matches[i], 10) || 0;
850
+ }
851
+
852
+ // month starts on 0
853
+ matches[2] -= 1;
854
+
855
+ fraction = matches[7] ? 1000 * ("0" + matches[7]) : null;
856
+
857
+ if (matches[8]) {
858
+ convertedDate = new Date(Date.UTC(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6], fraction));
859
+ } else {
860
+ convertedDate = new Date(matches[1], matches[2], matches[3], matches[4], matches[5], matches[6], fraction);
861
+ }
862
+ } else if (typeof(date) == "number") {
863
+ // UNIX timestamp
864
+ convertedDate = new Date();
865
+ convertedDate.setTime(date);
866
+ } else if (date.match(/([A-Z][a-z]{2}) ([A-Z][a-z]{2}) (\d+) (\d+:\d+:\d+) ([+-]\d+) (\d+)/)) {
867
+ // This format `Wed Jul 20 13:03:39 +0000 2011` is parsed by
868
+ // webkit/firefox, but not by IE, so we must parse it manually.
869
+ convertedDate = new Date();
870
+ convertedDate.setTime(Date.parse([
871
+ RegExp.$1, RegExp.$2, RegExp.$3, RegExp.$6, RegExp.$4, RegExp.$5
872
+ ].join(" ")));
873
+ } else if (date.match(/\d+ \d+:\d+:\d+ [+-]\d+ \d+/)) {
874
+ // a valid javascript format with timezone info
875
+ convertedDate = new Date();
876
+ convertedDate.setTime(Date.parse(date));
877
+ } else {
878
+ // an arbitrary javascript string
879
+ convertedDate = new Date();
880
+ convertedDate.setTime(Date.parse(date));
881
+ }
882
+
883
+ return convertedDate;
884
+ };
885
+
886
+ // Formats time according to the directives in the given format string.
887
+ // The directives begins with a percent (%) character. Any text not listed as a
888
+ // directive will be passed through to the output string.
889
+ //
890
+ // The accepted formats are:
891
+ //
892
+ // %a - The abbreviated weekday name (Sun)
893
+ // %A - The full weekday name (Sunday)
894
+ // %b - The abbreviated month name (Jan)
895
+ // %B - The full month name (January)
896
+ // %c - The preferred local date and time representation
897
+ // %d - Day of the month (01..31)
898
+ // %-d - Day of the month (1..31)
899
+ // %H - Hour of the day, 24-hour clock (00..23)
900
+ // %-H/%k - Hour of the day, 24-hour clock (0..23)
901
+ // %I - Hour of the day, 12-hour clock (01..12)
902
+ // %-I/%l - Hour of the day, 12-hour clock (1..12)
903
+ // %m - Month of the year (01..12)
904
+ // %-m - Month of the year (1..12)
905
+ // %M - Minute of the hour (00..59)
906
+ // %-M - Minute of the hour (0..59)
907
+ // %p - Meridian indicator (AM or PM)
908
+ // %P - Meridian indicator (am or pm)
909
+ // %S - Second of the minute (00..60)
910
+ // %-S - Second of the minute (0..60)
911
+ // %w - Day of the week (Sunday is 0, 0..6)
912
+ // %y - Year without a century (00..99)
913
+ // %-y - Year without a century (0..99)
914
+ // %Y - Year with century
915
+ // %z/%Z - Timezone offset (+0545)
916
+ //
917
+ I18n.strftime = function(date, format, options) {
918
+ var options = this.lookup("date", options)
919
+ , meridianOptions = I18n.meridian()
920
+ ;
921
+
922
+ if (!options) {
923
+ options = {};
924
+ }
925
+
926
+ options = this.prepareOptions(options, DATE);
927
+
928
+ if (isNaN(date.getTime())) {
929
+ throw new Error('I18n.strftime() requires a valid date object, but received an invalid date.');
930
+ }
931
+
932
+ var weekDay = date.getDay()
933
+ , day = date.getDate()
934
+ , year = date.getFullYear()
935
+ , month = date.getMonth() + 1
936
+ , hour = date.getHours()
937
+ , hour12 = hour
938
+ , meridian = hour > 11 ? 1 : 0
939
+ , secs = date.getSeconds()
940
+ , mins = date.getMinutes()
941
+ , offset = date.getTimezoneOffset()
942
+ , absOffsetHours = Math.floor(Math.abs(offset / 60))
943
+ , absOffsetMinutes = Math.abs(offset) - (absOffsetHours * 60)
944
+ , timezoneoffset = (offset > 0 ? "-" : "+") +
945
+ (absOffsetHours.toString().length < 2 ? "0" + absOffsetHours : absOffsetHours) +
946
+ (absOffsetMinutes.toString().length < 2 ? "0" + absOffsetMinutes : absOffsetMinutes)
947
+ ;
948
+
949
+ if (hour12 > 12) {
950
+ hour12 = hour12 - 12;
951
+ } else if (hour12 === 0) {
952
+ hour12 = 12;
953
+ }
954
+
955
+ format = format.replace("%a", options.abbr_day_names[weekDay]);
956
+ format = format.replace("%A", options.day_names[weekDay]);
957
+ format = format.replace("%b", options.abbr_month_names[month]);
958
+ format = format.replace("%B", options.month_names[month]);
959
+ format = format.replace("%d", padding(day));
960
+ format = format.replace("%e", day);
961
+ format = format.replace("%-d", day);
962
+ format = format.replace("%H", padding(hour));
963
+ format = format.replace("%-H", hour);
964
+ format = format.replace("%k", hour);
965
+ format = format.replace("%I", padding(hour12));
966
+ format = format.replace("%-I", hour12);
967
+ format = format.replace("%l", hour12);
968
+ format = format.replace("%m", padding(month));
969
+ format = format.replace("%-m", month);
970
+ format = format.replace("%M", padding(mins));
971
+ format = format.replace("%-M", mins);
972
+ format = format.replace("%p", meridianOptions[meridian]);
973
+ format = format.replace("%P", meridianOptions[meridian].toLowerCase());
974
+ format = format.replace("%S", padding(secs));
975
+ format = format.replace("%-S", secs);
976
+ format = format.replace("%w", weekDay);
977
+ format = format.replace("%y", padding(year));
978
+ format = format.replace("%-y", padding(year).replace(/^0+/, ""));
979
+ format = format.replace("%Y", year);
980
+ format = format.replace("%z", timezoneoffset);
981
+ format = format.replace("%Z", timezoneoffset);
982
+
983
+ return format;
984
+ };
985
+
986
+ // Convert the given dateString into a formatted date.
987
+ I18n.toTime = function(scope, dateString, options) {
988
+ var date = this.parseDate(dateString)
989
+ , format = this.lookup(scope, options)
990
+ ;
991
+
992
+ // A date input of `null` or `undefined` will be returned as-is
993
+ if (date == null) {
994
+ return date;
995
+ }
996
+
997
+ var date_string = date.toString()
998
+ if (date_string.match(/invalid/i)) {
999
+ return date_string;
1000
+ }
1001
+
1002
+ if (!format) {
1003
+ return date_string;
1004
+ }
1005
+
1006
+ return this.strftime(date, format, options);
1007
+ };
1008
+
1009
+ // Convert a number into a formatted percentage value.
1010
+ I18n.toPercentage = function(number, options) {
1011
+ options = this.prepareOptions(
1012
+ options
1013
+ , this.lookup("number.percentage.format", options)
1014
+ , this.lookup("number.format", options)
1015
+ , PERCENTAGE_FORMAT
1016
+ );
1017
+
1018
+ return this.toNumber(number, options);
1019
+ };
1020
+
1021
+ // Convert a number into a readable size representation.
1022
+ I18n.toHumanSize = function(number, options) {
1023
+ var kb = 1024
1024
+ , size = number
1025
+ , iterations = 0
1026
+ , unit
1027
+ , precision
1028
+ , fullScope
1029
+ ;
1030
+
1031
+ while (size >= kb && iterations < 4) {
1032
+ size = size / kb;
1033
+ iterations += 1;
1034
+ }
1035
+
1036
+ if (iterations === 0) {
1037
+ fullScope = this.getFullScope("number.human.storage_units.units.byte", options);
1038
+ unit = this.t(fullScope, {count: size});
1039
+ precision = 0;
1040
+ } else {
1041
+ fullScope = this.getFullScope("number.human.storage_units.units." + SIZE_UNITS[iterations], options);
1042
+ unit = this.t(fullScope);
1043
+ precision = (size - Math.floor(size) === 0) ? 0 : 1;
1044
+ }
1045
+
1046
+ options = this.prepareOptions(
1047
+ options
1048
+ , {unit: unit, precision: precision, format: "%n%u", delimiter: ""}
1049
+ );
1050
+
1051
+ return this.toNumber(size, options);
1052
+ };
1053
+
1054
+ I18n.getFullScope = function(scope, options) {
1055
+ options = options || {};
1056
+
1057
+ // Deal with the scope as an array.
1058
+ if (isArray(scope)) {
1059
+ scope = scope.join(options.separator || this.defaultSeparator);
1060
+ }
1061
+
1062
+ // Deal with the scope option provided through the second argument.
1063
+ //
1064
+ // I18n.t('hello', {scope: 'greetings'});
1065
+ //
1066
+ if (options.scope) {
1067
+ scope = [options.scope, scope].join(options.separator || this.defaultSeparator);
1068
+ }
1069
+
1070
+ return scope;
1071
+ };
1072
+ /**
1073
+ * Merge obj1 with obj2 (shallow merge), without modifying inputs
1074
+ * @param {Object} obj1
1075
+ * @param {Object} obj2
1076
+ * @returns {Object} Merged values of obj1 and obj2
1077
+ *
1078
+ * In order to support ES3, `Object.prototype.hasOwnProperty.call` is used
1079
+ * Idea is from:
1080
+ * https://stackoverflow.com/questions/8157700/object-has-no-hasownproperty-method-i-e-its-undefined-ie8
1081
+ */
1082
+ I18n.extend = function ( obj1, obj2 ) {
1083
+ if (typeof(obj1) === "undefined" && typeof(obj2) === "undefined") {
1084
+ return {};
1085
+ }
1086
+ return merge(obj1, obj2);
1087
+ };
1088
+
1089
+ // Set aliases, so we can save some typing.
1090
+ I18n.t = I18n.translate.bind(I18n);
1091
+ I18n.l = I18n.localize.bind(I18n);
1092
+ I18n.p = I18n.pluralize.bind(I18n);
1093
+
1094
+ return I18n;
1095
+ }));