elabs 2.0.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (404) hide show
  1. checksums.yaml +7 -0
  2. data/.eslintrc.yml +26 -0
  3. data/.gitignore +49 -0
  4. data/.gitlab-ci.yml +93 -0
  5. data/.haml-lint.yml +4 -0
  6. data/.node-version +1 -0
  7. data/.rspec +1 -0
  8. data/.rubocop.yml +59 -0
  9. data/.ruby-version +1 -0
  10. data/.simplecov +5 -0
  11. data/.stylelintrc.yml +218 -0
  12. data/CHANGELOG.md +273 -0
  13. data/CODE_OF_CONDUCT.md +78 -0
  14. data/Gemfile +75 -0
  15. data/Gemfile.lock +376 -0
  16. data/LICENSE +21 -0
  17. data/LICENSES.md +6 -0
  18. data/README.md +41 -0
  19. data/ROADMAP.md +61 -0
  20. data/Rakefile +32 -0
  21. data/app/assets/config/elabs_manifest.js +3 -0
  22. data/app/assets/images/elabs/preview_placeholder.png +0 -0
  23. data/app/assets/images/elabs/preview_placeholder_nsfw.png +0 -0
  24. data/app/assets/javascripts/elabs/application.js +27 -0
  25. data/app/assets/javascripts/elabs/helpers-codemirror.js +29 -0
  26. data/app/assets/javascripts/elabs/helpers-markdown.js +42 -0
  27. data/app/assets/javascripts/elabs/helpers.js +17 -0
  28. data/app/assets/javascripts/elabs/modals.js +19 -0
  29. data/app/assets/javascripts/elabs/tabs.js +32 -0
  30. data/app/assets/stylesheets/elabs/_colors.scss +345 -0
  31. data/app/assets/stylesheets/elabs/_icons.scss +9 -0
  32. data/app/assets/stylesheets/elabs/_variables.scss +13 -0
  33. data/app/assets/stylesheets/elabs/app/_acts.scss +58 -0
  34. data/app/assets/stylesheets/elabs/app/_alerts.scss +3 -0
  35. data/app/assets/stylesheets/elabs/app/_buttons.scss +21 -0
  36. data/app/assets/stylesheets/elabs/app/_comments.scss +1 -0
  37. data/app/assets/stylesheets/elabs/app/_content.scss +10 -0
  38. data/app/assets/stylesheets/elabs/app/_content_uploads.scss +39 -0
  39. data/app/assets/stylesheets/elabs/app/_empty.scss +19 -0
  40. data/app/assets/stylesheets/elabs/app/_errors.scss +9 -0
  41. data/app/assets/stylesheets/elabs/app/_filter_links.scss +27 -0
  42. data/app/assets/stylesheets/elabs/app/_forms.scss +69 -0
  43. data/app/assets/stylesheets/elabs/app/_helpers.scss +3 -0
  44. data/app/assets/stylesheets/elabs/app/_languages.scss +6 -0
  45. data/app/assets/stylesheets/elabs/app/_layout.scss +194 -0
  46. data/app/assets/stylesheets/elabs/app/_licenses.scss +6 -0
  47. data/app/assets/stylesheets/elabs/app/_link-to-top.scss +8 -0
  48. data/app/assets/stylesheets/elabs/app/_medias.scss +12 -0
  49. data/app/assets/stylesheets/elabs/app/_modals.scss +53 -0
  50. data/app/assets/stylesheets/elabs/app/_nsfw.scss +5 -0
  51. data/app/assets/stylesheets/elabs/app/_pagination.scss +16 -0
  52. data/app/assets/stylesheets/elabs/app/_tabs.scss +54 -0
  53. data/app/assets/stylesheets/elabs/app/_tags.scss +6 -0
  54. data/app/assets/stylesheets/elabs/app/_toolbars.scss +3 -0
  55. data/app/assets/stylesheets/elabs/app/_users.scss +6 -0
  56. data/app/assets/stylesheets/elabs/app/admin-members/_forms.scss +6 -0
  57. data/app/assets/stylesheets/elabs/app/admin-members/_indexes.scss +70 -0
  58. data/app/assets/stylesheets/elabs/app/admin-members/_layout.scss +17 -0
  59. data/app/assets/stylesheets/elabs/app/areas/_devise.scss +31 -0
  60. data/app/assets/stylesheets/elabs/app/components/_cards.scss +16 -0
  61. data/app/assets/stylesheets/elabs/app/components/_container.scss +4 -0
  62. data/app/assets/stylesheets/elabs/app/mixins/_classifier-card.scss +16 -0
  63. data/app/assets/stylesheets/elabs/app/mixins/_content-card.scss +58 -0
  64. data/app/assets/stylesheets/elabs/app/mixins/_content-full.scss +39 -0
  65. data/app/assets/stylesheets/elabs/app/mixins/_icon.scss +9 -0
  66. data/app/assets/stylesheets/elabs/application.css +14 -0
  67. data/app/assets/stylesheets/elabs/lib/_codemirror.scss +26 -0
  68. data/app/assets/stylesheets/elabs/lib/fontawesome/_fontawesome.scss +38 -0
  69. data/app/assets/stylesheets/elabs/lib/fontawesome/_fonts.scss +42 -0
  70. data/app/assets/stylesheets/elabs/lib/fontawesome/_icons.scss +1118 -0
  71. data/app/assets/stylesheets/elabs/lib/knacss/_knacss-variables.scss +230 -0
  72. data/app/assets/stylesheets/elabs/lib/knacss/_knacss.scss +59 -0
  73. data/app/assets/stylesheets/elabs/style.scss +72 -0
  74. data/app/controllers/elabs/acts_controller.rb +12 -0
  75. data/app/controllers/elabs/admin/admin_application_controller.rb +19 -0
  76. data/app/controllers/elabs/admin/admin_content_application_controller.rb +66 -0
  77. data/app/controllers/elabs/admin/albums_controller.rb +10 -0
  78. data/app/controllers/elabs/admin/articles_controller.rb +10 -0
  79. data/app/controllers/elabs/admin/languages_controller.rb +77 -0
  80. data/app/controllers/elabs/admin/licenses_controller.rb +77 -0
  81. data/app/controllers/elabs/admin/notes_controller.rb +10 -0
  82. data/app/controllers/elabs/admin/projects_controller.rb +10 -0
  83. data/app/controllers/elabs/admin/reports_controller.rb +34 -0
  84. data/app/controllers/elabs/admin/tags_controller.rb +56 -0
  85. data/app/controllers/elabs/admin/uploads_controller.rb +10 -0
  86. data/app/controllers/elabs/admin/users_controller.rb +43 -0
  87. data/app/controllers/elabs/albums_controller.rb +26 -0
  88. data/app/controllers/elabs/articles_controller.rb +25 -0
  89. data/app/controllers/elabs/auth/callbacks_controller.rb +38 -0
  90. data/app/controllers/elabs/auth/confirmations_controller.rb +43 -0
  91. data/app/controllers/elabs/auth/passwords_controller.rb +47 -0
  92. data/app/controllers/elabs/auth/registrations_controller.rb +70 -0
  93. data/app/controllers/elabs/auth/sessions_controller.rb +36 -0
  94. data/app/controllers/elabs/auth/unlocks_controller.rb +38 -0
  95. data/app/controllers/elabs/concerns/elabs_controller.rb +18 -0
  96. data/app/controllers/elabs/concerns/localizable.rb +11 -0
  97. data/app/controllers/elabs/concerns/reportable.rb +17 -0
  98. data/app/controllers/elabs/content_application_controller.rb +45 -0
  99. data/app/controllers/elabs/elabs_application_controller.rb +95 -0
  100. data/app/controllers/elabs/languages_controller.rb +36 -0
  101. data/app/controllers/elabs/licenses_controller.rb +31 -0
  102. data/app/controllers/elabs/member/albums_controller.rb +11 -0
  103. data/app/controllers/elabs/member/articles_controller.rb +11 -0
  104. data/app/controllers/elabs/member/member_application_controller.rb +12 -0
  105. data/app/controllers/elabs/member/member_content_application_controller.rb +128 -0
  106. data/app/controllers/elabs/member/notes_controller.rb +11 -0
  107. data/app/controllers/elabs/member/preferences_controller.rb +36 -0
  108. data/app/controllers/elabs/member/projects_controller.rb +11 -0
  109. data/app/controllers/elabs/member/uploads_controller.rb +11 -0
  110. data/app/controllers/elabs/member/users_controller.rb +28 -0
  111. data/app/controllers/elabs/notes_controller.rb +25 -0
  112. data/app/controllers/elabs/projects_controller.rb +30 -0
  113. data/app/controllers/elabs/reports_controller.rb +36 -0
  114. data/app/controllers/elabs/tags_controller.rb +36 -0
  115. data/app/controllers/elabs/uploads_controller.rb +24 -0
  116. data/app/controllers/elabs/users_controller.rb +36 -0
  117. data/app/helpers/elabs/acts_helper.rb +22 -0
  118. data/app/helpers/elabs/admin_content_helper.rb +54 -0
  119. data/app/helpers/elabs/application_helper.rb +54 -0
  120. data/app/helpers/elabs/content_filters_helper.rb +97 -0
  121. data/app/helpers/elabs/content_renderer_helper.rb +13 -0
  122. data/app/helpers/elabs/member_content_helper.rb +47 -0
  123. data/app/helpers/elabs/thumbnails_helper.rb +28 -0
  124. data/app/helpers/elabs/time_helper.rb +19 -0
  125. data/app/helpers/elabs/uploads_helper.rb +19 -0
  126. data/app/jobs/elabs/application_job.rb +4 -0
  127. data/app/mailers/elabs/application_mailer.rb +6 -0
  128. data/app/models/elabs/act.rb +7 -0
  129. data/app/models/elabs/album.rb +24 -0
  130. data/app/models/elabs/albums_tag.rb +21 -0
  131. data/app/models/elabs/albums_upload.rb +21 -0
  132. data/app/models/elabs/application_content_record.rb +10 -0
  133. data/app/models/elabs/application_record.rb +5 -0
  134. data/app/models/elabs/article.rb +23 -0
  135. data/app/models/elabs/articles_tag.rb +21 -0
  136. data/app/models/elabs/comment.rb +12 -0
  137. data/app/models/elabs/concerns/actable_entity.rb +52 -0
  138. data/app/models/elabs/concerns/content_entity.rb +70 -0
  139. data/app/models/elabs/concerns/countable_entity.rb +81 -0
  140. data/app/models/elabs/concerns/taggable.rb +33 -0
  141. data/app/models/elabs/language.rb +17 -0
  142. data/app/models/elabs/license.rb +15 -0
  143. data/app/models/elabs/note.rb +21 -0
  144. data/app/models/elabs/notes_tag.rb +21 -0
  145. data/app/models/elabs/preference.rb +9 -0
  146. data/app/models/elabs/project.rb +25 -0
  147. data/app/models/elabs/projects_album.rb +21 -0
  148. data/app/models/elabs/projects_article.rb +21 -0
  149. data/app/models/elabs/projects_note.rb +21 -0
  150. data/app/models/elabs/projects_tag.rb +21 -0
  151. data/app/models/elabs/projects_upload.rb +21 -0
  152. data/app/models/elabs/report.rb +11 -0
  153. data/app/models/elabs/tag.rb +18 -0
  154. data/app/models/elabs/upload.rb +28 -0
  155. data/app/models/elabs/uploads_tag.rb +21 -0
  156. data/app/models/elabs/user.rb +30 -0
  157. data/app/validators/elabs/associated_author_validator.rb +11 -0
  158. data/app/views/elabs/acts/_act.json.jbuilder +2 -0
  159. data/app/views/elabs/acts/_filters.html.haml +3 -0
  160. data/app/views/elabs/acts/index.html.haml +27 -0
  161. data/app/views/elabs/acts/index.json.jbuilder +1 -0
  162. data/app/views/elabs/admin/albums/_album.json.jbuilder +2 -0
  163. data/app/views/elabs/admin/albums/index.html.haml +43 -0
  164. data/app/views/elabs/admin/albums/index.json.jbuilder +1 -0
  165. data/app/views/elabs/admin/articles/_article.json.jbuilder +2 -0
  166. data/app/views/elabs/admin/articles/index.html.haml +41 -0
  167. data/app/views/elabs/admin/articles/index.json.jbuilder +1 -0
  168. data/app/views/elabs/admin/languages/_form.html.haml +18 -0
  169. data/app/views/elabs/admin/languages/_language.json.jbuilder +2 -0
  170. data/app/views/elabs/admin/languages/edit.html.haml +6 -0
  171. data/app/views/elabs/admin/languages/index.html.haml +34 -0
  172. data/app/views/elabs/admin/languages/index.json.jbuilder +1 -0
  173. data/app/views/elabs/admin/languages/new.html.haml +3 -0
  174. data/app/views/elabs/admin/licenses/_form.html.haml +25 -0
  175. data/app/views/elabs/admin/licenses/_license.json.jbuilder +2 -0
  176. data/app/views/elabs/admin/licenses/edit.html.haml +6 -0
  177. data/app/views/elabs/admin/licenses/index.html.haml +42 -0
  178. data/app/views/elabs/admin/licenses/index.json.jbuilder +1 -0
  179. data/app/views/elabs/admin/licenses/new.html.haml +3 -0
  180. data/app/views/elabs/admin/notes/_note.json.jbuilder +2 -0
  181. data/app/views/elabs/admin/notes/index.html.haml +40 -0
  182. data/app/views/elabs/admin/notes/index.json.jbuilder +1 -0
  183. data/app/views/elabs/admin/projects/_project.json.jbuilder +2 -0
  184. data/app/views/elabs/admin/projects/index.html.haml +45 -0
  185. data/app/views/elabs/admin/projects/index.json.jbuilder +1 -0
  186. data/app/views/elabs/admin/reports/index.html.haml +27 -0
  187. data/app/views/elabs/admin/reports/index.json.jbuilder +1 -0
  188. data/app/views/elabs/admin/tags/_form.html.haml +17 -0
  189. data/app/views/elabs/admin/tags/_tag.json.jbuilder +2 -0
  190. data/app/views/elabs/admin/tags/edit.html.haml +6 -0
  191. data/app/views/elabs/admin/tags/index.html.haml +27 -0
  192. data/app/views/elabs/admin/tags/index.json.jbuilder +1 -0
  193. data/app/views/elabs/admin/uploads/_upload.json.jbuilder +2 -0
  194. data/app/views/elabs/admin/uploads/index.html.haml +45 -0
  195. data/app/views/elabs/admin/uploads/index.json.jbuilder +1 -0
  196. data/app/views/elabs/admin/users/_admin_user.json.jbuilder +2 -0
  197. data/app/views/elabs/admin/users/index.html.haml +33 -0
  198. data/app/views/elabs/admin/users/index.json.jbuilder +1 -0
  199. data/app/views/elabs/admin/users/show.html.haml +26 -0
  200. data/app/views/elabs/admin/users/show.json.jbuilder +1 -0
  201. data/app/views/elabs/albums/_album.html.haml +38 -0
  202. data/app/views/elabs/albums/_album.json.jbuilder +2 -0
  203. data/app/views/elabs/albums/_filters.html.haml +8 -0
  204. data/app/views/elabs/albums/index.html.haml +9 -0
  205. data/app/views/elabs/albums/index.json.jbuilder +1 -0
  206. data/app/views/elabs/albums/show.html.haml +60 -0
  207. data/app/views/elabs/albums/show.json.jbuilder +1 -0
  208. data/app/views/elabs/articles/_article.html.haml +30 -0
  209. data/app/views/elabs/articles/_article.json.jbuilder +2 -0
  210. data/app/views/elabs/articles/_filters.html.haml +8 -0
  211. data/app/views/elabs/articles/index.html.haml +9 -0
  212. data/app/views/elabs/articles/index.json.jbuilder +1 -0
  213. data/app/views/elabs/articles/show.html.haml +45 -0
  214. data/app/views/elabs/articles/show.json.jbuilder +1 -0
  215. data/app/views/elabs/auth/confirmations/new.html.haml +26 -0
  216. data/app/views/elabs/auth/passwords/edit.html.haml +31 -0
  217. data/app/views/elabs/auth/passwords/new.html.haml +23 -0
  218. data/app/views/elabs/auth/registrations/edit.html.haml +48 -0
  219. data/app/views/elabs/auth/registrations/new.html.haml +34 -0
  220. data/app/views/elabs/auth/sessions/_new.html.haml +15 -0
  221. data/app/views/elabs/auth/sessions/new.html.haml +8 -0
  222. data/app/views/elabs/auth/shared/_links.html.haml +16 -0
  223. data/app/views/elabs/auth/unlocks/new.html.haml +23 -0
  224. data/app/views/elabs/comments/_comment.json.jbuilder +2 -0
  225. data/app/views/elabs/comments/_comments.html.haml +21 -0
  226. data/app/views/elabs/comments/_form.html.haml +31 -0
  227. data/app/views/elabs/languages/_associations.html.haml +51 -0
  228. data/app/views/elabs/languages/_filters.html.haml +6 -0
  229. data/app/views/elabs/languages/_language.json.jbuilder +2 -0
  230. data/app/views/elabs/languages/index.html.haml +33 -0
  231. data/app/views/elabs/languages/index.json.jbuilder +1 -0
  232. data/app/views/elabs/languages/show.html.haml +38 -0
  233. data/app/views/elabs/languages/show.json.jbuilder +1 -0
  234. data/app/views/elabs/layouts/_empty.html.haml +3 -0
  235. data/app/views/elabs/layouts/_footer.html.haml +6 -0
  236. data/app/views/elabs/layouts/_hidden_entry.html.haml +6 -0
  237. data/app/views/elabs/layouts/_hidden_entry_full.html.haml +6 -0
  238. data/app/views/elabs/layouts/_language_menu.html.haml +2 -0
  239. data/app/views/elabs/layouts/_menu.html.haml +72 -0
  240. data/app/views/elabs/layouts/admin_application.html.haml +21 -0
  241. data/app/views/elabs/layouts/application.html.haml +37 -0
  242. data/app/views/elabs/layouts/lists/_albums.html.haml +10 -0
  243. data/app/views/elabs/layouts/lists/_projects.html.haml +10 -0
  244. data/app/views/elabs/layouts/lists/_tags.html.haml +9 -0
  245. data/app/views/elabs/layouts/mailer.html.haml +8 -0
  246. data/app/views/elabs/layouts/mailer.text.haml +1 -0
  247. data/app/views/elabs/layouts/member_application.html.haml +21 -0
  248. data/app/views/elabs/licenses/_associations.html.haml +51 -0
  249. data/app/views/elabs/licenses/_filters.html.haml +3 -0
  250. data/app/views/elabs/licenses/_license.json.jbuilder +2 -0
  251. data/app/views/elabs/licenses/index.html.haml +27 -0
  252. data/app/views/elabs/licenses/index.json.jbuilder +1 -0
  253. data/app/views/elabs/licenses/show.html.haml +44 -0
  254. data/app/views/elabs/licenses/show.json.jbuilder +1 -0
  255. data/app/views/elabs/member/albums/_album.json.jbuilder +2 -0
  256. data/app/views/elabs/member/albums/_form.html.haml +64 -0
  257. data/app/views/elabs/member/albums/edit.html.haml +6 -0
  258. data/app/views/elabs/member/albums/index.html.haml +49 -0
  259. data/app/views/elabs/member/albums/index.json.jbuilder +1 -0
  260. data/app/views/elabs/member/albums/new.html.haml +3 -0
  261. data/app/views/elabs/member/articles/_article.json.jbuilder +2 -0
  262. data/app/views/elabs/member/articles/_form.html.haml +70 -0
  263. data/app/views/elabs/member/articles/edit.html.haml +6 -0
  264. data/app/views/elabs/member/articles/index.html.haml +47 -0
  265. data/app/views/elabs/member/articles/index.json.jbuilder +1 -0
  266. data/app/views/elabs/member/articles/new.html.haml +3 -0
  267. data/app/views/elabs/member/layouts/_empty.html.haml +4 -0
  268. data/app/views/elabs/member/layouts/_markdown-preview.html.haml +8 -0
  269. data/app/views/elabs/member/notes/_form.html.haml +54 -0
  270. data/app/views/elabs/member/notes/_note.json.jbuilder +2 -0
  271. data/app/views/elabs/member/notes/edit.html.haml +6 -0
  272. data/app/views/elabs/member/notes/index.html.haml +47 -0
  273. data/app/views/elabs/member/notes/index.json.jbuilder +1 -0
  274. data/app/views/elabs/member/notes/new.html.haml +3 -0
  275. data/app/views/elabs/member/preferences/_form.html.haml +20 -0
  276. data/app/views/elabs/member/preferences/edit.html.haml +3 -0
  277. data/app/views/elabs/member/projects/_form.html.haml +71 -0
  278. data/app/views/elabs/member/projects/_project.json.jbuilder +2 -0
  279. data/app/views/elabs/member/projects/edit.html.haml +6 -0
  280. data/app/views/elabs/member/projects/index.html.haml +53 -0
  281. data/app/views/elabs/member/projects/index.json.jbuilder +1 -0
  282. data/app/views/elabs/member/projects/new.html.haml +3 -0
  283. data/app/views/elabs/member/uploads/_form.html.haml +67 -0
  284. data/app/views/elabs/member/uploads/_upload.json.jbuilder +2 -0
  285. data/app/views/elabs/member/uploads/edit.html.haml +6 -0
  286. data/app/views/elabs/member/uploads/index.html.haml +61 -0
  287. data/app/views/elabs/member/uploads/index.json.jbuilder +1 -0
  288. data/app/views/elabs/member/uploads/new.html.haml +3 -0
  289. data/app/views/elabs/member/users/_form.html.haml +38 -0
  290. data/app/views/elabs/notes/_filters.html.haml +7 -0
  291. data/app/views/elabs/notes/_note.html.haml +31 -0
  292. data/app/views/elabs/notes/_note.json.jbuilder +2 -0
  293. data/app/views/elabs/notes/index.html.haml +9 -0
  294. data/app/views/elabs/notes/index.json.jbuilder +1 -0
  295. data/app/views/elabs/notes/show.html.haml +44 -0
  296. data/app/views/elabs/notes/show.json.jbuilder +1 -0
  297. data/app/views/elabs/projects/_associations.html.haml +46 -0
  298. data/app/views/elabs/projects/_filters.html.haml +8 -0
  299. data/app/views/elabs/projects/_project.html.haml +29 -0
  300. data/app/views/elabs/projects/index.html.haml +9 -0
  301. data/app/views/elabs/projects/index.json.jbuilder +1 -0
  302. data/app/views/elabs/projects/show.html.haml +71 -0
  303. data/app/views/elabs/projects/show.json.jbuilder +1 -0
  304. data/app/views/elabs/reports/_form.html.haml +29 -0
  305. data/app/views/elabs/tags/_associations.html.haml +51 -0
  306. data/app/views/elabs/tags/_filters.html.haml +3 -0
  307. data/app/views/elabs/tags/_tag.json.jbuilder +2 -0
  308. data/app/views/elabs/tags/index.html.haml +26 -0
  309. data/app/views/elabs/tags/index.json.jbuilder +1 -0
  310. data/app/views/elabs/tags/show.html.haml +34 -0
  311. data/app/views/elabs/tags/show.json.jbuilder +1 -0
  312. data/app/views/elabs/uploads/_filters.html.haml +7 -0
  313. data/app/views/elabs/uploads/_player.html.haml +10 -0
  314. data/app/views/elabs/uploads/_preview.html.haml +17 -0
  315. data/app/views/elabs/uploads/_upload.html.haml +41 -0
  316. data/app/views/elabs/uploads/_upload.json.jbuilder +2 -0
  317. data/app/views/elabs/uploads/index.html.haml +9 -0
  318. data/app/views/elabs/uploads/index.json.jbuilder +1 -0
  319. data/app/views/elabs/uploads/show.html.haml +58 -0
  320. data/app/views/elabs/uploads/show.json.jbuilder +1 -0
  321. data/app/views/elabs/users/_associations.html.haml +51 -0
  322. data/app/views/elabs/users/_filters.html.haml +4 -0
  323. data/app/views/elabs/users/_user.html.haml +31 -0
  324. data/app/views/elabs/users/_user.json.jbuilder +2 -0
  325. data/app/views/elabs/users/index.html.haml +7 -0
  326. data/app/views/elabs/users/index.json.jbuilder +1 -0
  327. data/app/views/elabs/users/show.html.haml +48 -0
  328. data/app/views/elabs/users/show.json.jbuilder +1 -0
  329. data/bin/rails +14 -0
  330. data/config.ru +5 -0
  331. data/config/brakeman.ignore +124 -0
  332. data/config/brakeman.yml +3 -0
  333. data/config/cucumber.yml +9 -0
  334. data/config/routes.rb +116 -0
  335. data/db/migrate/20180813000000_devise_update_users.rb +15 -0
  336. data/db/migrate/20180813000001_create_languages.rb +16 -0
  337. data/db/migrate/20180813000002_create_tags.rb +14 -0
  338. data/db/migrate/20180813000004_create_licenses.rb +17 -0
  339. data/db/migrate/20180813000005_create_reports.rb +15 -0
  340. data/db/migrate/20180813000006_create_comments.rb +15 -0
  341. data/db/migrate/20180813000007_create_acts.rb +10 -0
  342. data/db/migrate/20180813000008_create_preferences.rb +13 -0
  343. data/db/migrate/20180813000009_create_active_storage_tables.active_storage.rb +26 -0
  344. data/db/migrate/20180813000010_create_albums.rb +23 -0
  345. data/db/migrate/20180813000011_create_articles.rb +23 -0
  346. data/db/migrate/20180813000012_create_notes.rb +21 -0
  347. data/db/migrate/20180813000013_create_uploads.rb +26 -0
  348. data/db/migrate/20180813000014_create_projects.rb +44 -0
  349. data/db/seeds.rb +10 -0
  350. data/db/seeds_development.rb +21 -0
  351. data/db/seeds_production.rb +0 -0
  352. data/docs/contributing.md +52 -0
  353. data/docs/cucumber_terms.md +9 -0
  354. data/docs/migrating.md +4 -0
  355. data/docs/overriding.md +20 -0
  356. data/docs/setup.md +136 -0
  357. data/docs/tips.md +13 -0
  358. data/elabs.gemspec +25 -0
  359. data/lib/assets/javascripts/README-highlight.js.md +39 -0
  360. data/lib/assets/javascripts/codemirror-5.39.2/addon/mode/overlay.js +90 -0
  361. data/lib/assets/javascripts/codemirror-5.39.2/lib/codemirror.js +9684 -0
  362. data/lib/assets/javascripts/codemirror-5.39.2/mode/clike/clike.js +834 -0
  363. data/lib/assets/javascripts/codemirror-5.39.2/mode/css/css.js +832 -0
  364. data/lib/assets/javascripts/codemirror-5.39.2/mode/gfm/gfm.js +129 -0
  365. data/lib/assets/javascripts/codemirror-5.39.2/mode/htmlmixed/htmlmixed.js +152 -0
  366. data/lib/assets/javascripts/codemirror-5.39.2/mode/javascript/javascript.js +896 -0
  367. data/lib/assets/javascripts/codemirror-5.39.2/mode/markdown/markdown.js +882 -0
  368. data/lib/assets/javascripts/codemirror-5.39.2/mode/meta.js +217 -0
  369. data/lib/assets/javascripts/codemirror-5.39.2/mode/xml/xml.js +402 -0
  370. data/lib/assets/javascripts/highlight.js-9.12.0/highlight.pack.js +2 -0
  371. data/lib/assets/javascripts/markdown-it-8.4.2.min.js +1 -0
  372. data/lib/assets/stylesheets/codemirror-5.39.2/lib/codemirror.css +346 -0
  373. data/lib/assets/stylesheets/codemirror-5.39.2/theme/base16-dark.css +38 -0
  374. data/lib/assets/stylesheets/codemirror-5.39.2/theme/base16-light.css +38 -0
  375. data/lib/assets/stylesheets/highlight.js-9.12.0/styles/atelier-sulphurpool-light.css +69 -0
  376. data/lib/elabs.rb +41 -0
  377. data/lib/elabs/engine.rb +5 -0
  378. data/lib/elabs/version.rb +3 -0
  379. data/lib/generators/elabs/assets_generator.rb +36 -0
  380. data/lib/generators/elabs/devise_views_generator.rb +24 -0
  381. data/lib/generators/elabs/install_generator.rb +26 -0
  382. data/lib/generators/elabs/required_assets_generator.rb +26 -0
  383. data/lib/generators/elabs/views_generator.rb +25 -0
  384. data/lib/generators/templates/elabs.rb +25 -0
  385. data/lib/generators/templates/fast_gettext.rb +3 -0
  386. data/lib/tasks/.keep +0 -0
  387. data/lib/tasks/cucumber.rake +75 -0
  388. data/lib/tasks/elabs_tasks.rake +4 -0
  389. data/lib/tasks/factory_bot.rake +14 -0
  390. data/lib/tasks/wipe.rake +31 -0
  391. data/locale/app.pot +1124 -0
  392. data/locale/devise_strings.rb +88 -0
  393. data/locale/en/app.edit.po +1123 -0
  394. data/locale/en/app.po +1123 -0
  395. data/locale/en/app.po.time_stamp +0 -0
  396. data/locale/fr/app.edit.po +1126 -0
  397. data/locale/fr/app.po +1125 -0
  398. data/locale/fr/app.po.time_stamp +0 -0
  399. data/locale/model_attributes.rb +85 -0
  400. data/package.json +22 -0
  401. data/script/cucumber +10 -0
  402. data/tmp/pids/.keep +0 -0
  403. data/yarn.lock +2759 -0
  404. metadata +463 -0
@@ -0,0 +1 @@
1
+ json.partial! 'uploads/upload', upload: @upload
@@ -0,0 +1,51 @@
1
+ %aside.tabs
2
+ %ul.tabs__tabs-list
3
+ %li.tabs__tabs-list__tab#tab-albums
4
+ %a{ href: '#tab-content-albums', onclick: 'selectTab(event, "albums")' }= _('Albums')
5
+ %li.tabs__tabs-list__tab#tab-articles
6
+ %a{ href: '#tab-content-articles', onclick: 'selectTab(event, "articles")' }= _('Articles')
7
+ %li.tabs__tabs-list__tab#tab-notes
8
+ %a{ href: '#tab-content-notes', onclick: 'selectTab(event, "notes")' }= _('Notes')
9
+ %li.tabs__tabs-list__tab#tab-projects
10
+ %a{ href: '#tab-content-projects', onclick: 'selectTab(event, "projects")' }= _('Projects')
11
+ %li.tabs__tabs-list__tab#tab-uploads
12
+ %a{ href: '#tab-content-uploads', onclick: 'selectTab(event, "uploads")' }= _('Uploads')
13
+
14
+ %section.tabs__tab-content.albums-list#tab-content-albums
15
+ .tabs__tab-content__title
16
+ %h2= format _('Last %<amount>i albums:'), amount: Elabs.max_related_items
17
+ .actions= link_to _('Show all'), user_albums_url(user)
18
+ - user_albums.each do |a|
19
+ = render 'elabs/albums/album', album: a
20
+
21
+ %section.tabs__tab-content.articles-list#tab-content-articles
22
+ .tabs__tab-content__title
23
+ %h2= format _('Last %<amount>i articles:'), amount: Elabs.max_related_items
24
+ .actions= link_to _('Show all'), user_articles_url(user)
25
+ - user_articles.each do |a|
26
+ = render 'elabs/articles/article', article: a
27
+
28
+ %section.tabs__tab-content.notes-list#tab-content-notes
29
+ .tabs__tab-content__title
30
+ %h2= format _('Last %<amount>i notes:'), amount: Elabs.max_related_items
31
+ .actions= link_to _('Show all'), user_notes_url(user)
32
+ - user_notes.each do |n|
33
+ = render 'elabs/notes/note', note: n
34
+
35
+ %section.tabs__tab-content.projects-list#tab-content-projects
36
+ .tabs__tab-content__title
37
+ %h2= format _('Last %<amount>i projects:'), amount: Elabs.max_related_items
38
+ .actions= link_to _('Show all'), user_projects_url(user)
39
+ - user_projects.each do |p|
40
+ = render 'elabs/projects/project', project: p
41
+
42
+ %section.tabs__tab-content.uploads-list#tab-content-uploads
43
+ .tabs__tab-content__title
44
+ %h2= format _('Last %<amount>i uploads:'), amount: Elabs.max_related_items
45
+ .actions= link_to _('Show all'), user_uploads_url(user)
46
+ - user_uploads.each do |u|
47
+ = render 'elabs/uploads/upload', upload: u
48
+
49
+ :javascript
50
+ initializeTabs ()
51
+ selectTab('albums')
@@ -0,0 +1,4 @@
1
+ .filter-links
2
+ .filter-links__group
3
+ = order_link _('Username'), 'username'
4
+ = order_link _('Insc. date'), 'created_at'
@@ -0,0 +1,31 @@
1
+ .user.user-card
2
+ %header
3
+ .icon= icon 'user', %w[3x fw]
4
+ .headers
5
+ %h3= link_to user.username, user, class: 'title'
6
+
7
+ %ul.informations
8
+ %li
9
+ %b= _('Role:')
10
+ = user.role
11
+
12
+ %li
13
+ %b= _('Since:')
14
+ = user.created_at
15
+
16
+ .content
17
+ = link_to user_projects_path(user), class: 'btn btn--block' do
18
+ = icon 'cog'
19
+ = format(n_('%<nb>i project', '%<nb>i projects', user.projects_count), nb: user.projects_count)
20
+ = link_to user_articles_path(user), class: 'btn btn--block' do
21
+ = icon 'font'
22
+ = format(n_('%<nb>i article', '%<nb>i articles', user.articles_count), nb: user.articles_count)
23
+ = link_to user_notes_path(user), class: 'btn btn--block' do
24
+ = icon 'sticky-note'
25
+ = format(n_('%<nb>i note', '%<nb>i notes', user.notes_count), nb: user.notes_count)
26
+ = link_to user_uploads_path(user), class: 'btn btn--block' do
27
+ = icon 'image'
28
+ = format(n_('%<nb>i upload', '%<nb>i uploads', user.uploads_count), nb: user.uploads_count)
29
+ = link_to user_albums_path(user), class: 'btn btn--block' do
30
+ = icon 'book'
31
+ = format(n_('%<nb>i album', '%<nb>i albums', user.albums_count), nb: user.albums_count)
@@ -0,0 +1,2 @@
1
+ json.extract! user, :id, :created_at, :updated_at
2
+ json.url user_url(user, format: :json)
@@ -0,0 +1,7 @@
1
+ - @page_title = _('Users')
2
+
3
+ .users-list
4
+ - @users.each do |user|
5
+ = render 'user', user: user
6
+
7
+ = paginate @users
@@ -0,0 +1 @@
1
+ json.array! @users, partial: 'users/user', as: :user
@@ -0,0 +1,48 @@
1
+ - @page_title = @user.real_name || @user.username
2
+ .user.user--full
3
+ %aside
4
+ %ul
5
+ %li
6
+ = icon('user', ['fw'])
7
+ %strong= _('Username')
8
+ = @user.username
9
+ %li
10
+ = icon('user', ['fw'])
11
+ %strong= _('Real name')
12
+ = @user.real_name
13
+ %li
14
+ = icon('calendar-check', ['fw'])
15
+ %strong= _('Subscription date')
16
+ = @user.created_at
17
+ %li
18
+ = icon('amount', ['fw'])
19
+ %strong= _('Albums:')
20
+ = @user.albums_count
21
+ %li
22
+ = icon('amount', ['fw'])
23
+ %strong= _('Articles:')
24
+ = @user.articles_count
25
+ %li
26
+ = icon('amount', ['fw'])
27
+ %strong= _('Notes:')
28
+ = @user.notes_count
29
+ %li
30
+ = icon('amount', ['fw'])
31
+ %strong= _('Projects:')
32
+ = @user.projects_count
33
+ %li
34
+ = icon('amount', ['fw'])
35
+ %strong= _('Uploads:')
36
+ = @user.uploads_count
37
+ .content
38
+ - unless @user.biography.nil?
39
+ %article
40
+ = markdown @user.biography
41
+
42
+ = render 'associations',
43
+ user: @user,
44
+ user_albums: @user_albums,
45
+ user_articles: @user_articles,
46
+ user_notes: @user_notes,
47
+ user_projects: @user_projects,
48
+ user_uploads: @user_uploads
@@ -0,0 +1 @@
1
+ json.partial! 'users/user', user: @user
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+ # This command will automatically be run when you run "rails" with Rails gems
3
+ # installed from the root of your application.
4
+
5
+ ENGINE_ROOT = File.expand_path('..', __dir__)
6
+ ENGINE_PATH = File.expand_path('../lib/elabs/engine', __dir__)
7
+ APP_PATH = File.expand_path('../spec/dummy/config/application', __dir__)
8
+
9
+ # Set up gems listed in the Gemfile.
10
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
11
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
12
+
13
+ require 'rails/all'
14
+ require 'rails/engine/commands'
@@ -0,0 +1,5 @@
1
+ # This file is used by Rack-based servers to start the application.
2
+
3
+ require_relative 'config/environment'
4
+
5
+ run Rails.application
@@ -0,0 +1,124 @@
1
+ {
2
+ "ignored_warnings": [
3
+ {
4
+ "warning_type": "Unscoped Find",
5
+ "warning_code": 82,
6
+ "fingerprint": "14eb16e2efd5474628f981fdff434cb13c73df4d17b93ceea6b82a8f99a09552",
7
+ "check_name": "UnscopedFind",
8
+ "message": "Unscoped call to Album#find",
9
+ "file": "app/controllers/albums_controller.rb",
10
+ "line": 18,
11
+ "link": "https://brakemanscanner.org/docs/warning_types/unscoped_find/",
12
+ "code": "Album.find(params[:id])",
13
+ "render_path": null,
14
+ "location": {
15
+ "type": "method",
16
+ "class": "AlbumsController",
17
+ "method": "set_album"
18
+ },
19
+ "user_input": "params[:id]",
20
+ "confidence": "Weak",
21
+ "note": ""
22
+ },
23
+ {
24
+ "warning_type": "Cross-Site Scripting",
25
+ "warning_code": 4,
26
+ "fingerprint": "74d83c9e5d3fb98de33d9c690a9380c40f0e35f3b85f390e871858bb8d34c1fe",
27
+ "check_name": "LinkToHref",
28
+ "message": "Potentially unsafe model attribute in link_to href",
29
+ "file": "app/views/licenses/show.html.haml",
30
+ "line": 15,
31
+ "link": "https://brakemanscanner.org/docs/warning_types/link_to_href",
32
+ "code": "link_to(_(\"TL; DR\"), License.find(params[:id]).tldr_url, :target => \"_blank\")",
33
+ "render_path": [{"type":"controller","class":"LicensesController","method":"show","line":18,"file":"app/controllers/licenses_controller.rb"}],
34
+ "location": {
35
+ "type": "template",
36
+ "template": "licenses/show"
37
+ },
38
+ "user_input": "License.find(params[:id]).tldr_url",
39
+ "confidence": "Weak",
40
+ "note": "URLS are set by admins only"
41
+ },
42
+ {
43
+ "warning_type": "Unscoped Find",
44
+ "warning_code": 82,
45
+ "fingerprint": "96f2f0238c7611c20a731155fa4ab107874326d762a84e9b1858c0801c10d741",
46
+ "check_name": "UnscopedFind",
47
+ "message": "Unscoped call to Note#find",
48
+ "file": "app/controllers/notes_controller.rb",
49
+ "line": 18,
50
+ "link": "https://brakemanscanner.org/docs/warning_types/unscoped_find/",
51
+ "code": "Note.find(params[:id])",
52
+ "render_path": null,
53
+ "location": {
54
+ "type": "method",
55
+ "class": "NotesController",
56
+ "method": "set_note"
57
+ },
58
+ "user_input": "params[:id]",
59
+ "confidence": "Weak",
60
+ "note": ""
61
+ },
62
+ {
63
+ "warning_type": "Unscoped Find",
64
+ "warning_code": 82,
65
+ "fingerprint": "b65152f1b2c4e9e18bcc4a3fd637b7bd5dd4b79421460a2c764bc3ead2ad1aa0",
66
+ "check_name": "UnscopedFind",
67
+ "message": "Unscoped call to Project#find",
68
+ "file": "app/controllers/projects_controller.rb",
69
+ "line": 23,
70
+ "link": "https://brakemanscanner.org/docs/warning_types/unscoped_find/",
71
+ "code": "Project.find(params[:id])",
72
+ "render_path": null,
73
+ "location": {
74
+ "type": "method",
75
+ "class": "ProjectsController",
76
+ "method": "set_project"
77
+ },
78
+ "user_input": "params[:id]",
79
+ "confidence": "Weak",
80
+ "note": ""
81
+ },
82
+ {
83
+ "warning_type": "Unscoped Find",
84
+ "warning_code": 82,
85
+ "fingerprint": "c03df681f497ea4ef182b6236295be2dd61879612b212e7a6ea3a1b2e6faf7d0",
86
+ "check_name": "UnscopedFind",
87
+ "message": "Unscoped call to Upload#find",
88
+ "file": "app/controllers/uploads_controller.rb",
89
+ "line": 17,
90
+ "link": "https://brakemanscanner.org/docs/warning_types/unscoped_find/",
91
+ "code": "Upload.find(params[:id])",
92
+ "render_path": null,
93
+ "location": {
94
+ "type": "method",
95
+ "class": "UploadsController",
96
+ "method": "set_upload"
97
+ },
98
+ "user_input": "params[:id]",
99
+ "confidence": "Weak",
100
+ "note": ""
101
+ },
102
+ {
103
+ "warning_type": "Cross-Site Scripting",
104
+ "warning_code": 4,
105
+ "fingerprint": "c125f39a448be85c1445467afabaf1a1992e9e1bf59af040b0277b33fa708901",
106
+ "check_name": "LinkToHref",
107
+ "message": "Potentially unsafe model attribute in link_to href",
108
+ "file": "app/views/licenses/show.html.haml",
109
+ "line": 12,
110
+ "link": "https://brakemanscanner.org/docs/warning_types/link_to_href",
111
+ "code": "link_to(_(\"Home page\"), License.find(params[:id]).url, :target => \"_blank\")",
112
+ "render_path": [{"type":"controller","class":"LicensesController","method":"show","line":18,"file":"app/controllers/licenses_controller.rb"}],
113
+ "location": {
114
+ "type": "template",
115
+ "template": "licenses/show"
116
+ },
117
+ "user_input": "License.find(params[:id]).url",
118
+ "confidence": "Weak",
119
+ "note": "URLS are set by admins only"
120
+ }
121
+ ],
122
+ "updated": "2018-08-01 07:04:08 +0200",
123
+ "brakeman_version": "4.3.1"
124
+ }
@@ -0,0 +1,3 @@
1
+ ---
2
+ :run_all_checks: true
3
+ :assume_all_routes: false
@@ -0,0 +1,9 @@
1
+ <%
2
+ rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
3
+ rerun = rerun.strip.gsub /\s/, ' '
4
+ rerun_opts = rerun.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
5
+ std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} --strict --tags 'not @wip'"
6
+ %>
7
+ default: <%= std_opts %> features
8
+ wip: --tags @wip:3 --wip features
9
+ rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags 'not @wip'
@@ -0,0 +1,116 @@
1
+ Elabs::Engine.routes.draw do
2
+ # Devise routes: use Elabs custom controllers (adds support for username and preferences)
3
+ devise_for :users, path: 'auth', controllers: {
4
+ confirmations: 'elabs/auth/confirmations',
5
+ passwords: 'elabs/auth/passwords',
6
+ registrations: 'elabs/auth/registrations',
7
+ sessions: 'elabs/auth/sessions',
8
+ unlocks: 'elabs/auth/unlocks'
9
+ }
10
+ # Resources
11
+ resources :albums, only: %i[index show] do
12
+ resources :uploads, only: %i[index]
13
+ post 'comment', to: 'albums#create_comment', as: 'create_comment'
14
+ end
15
+ resources :articles, only: %i[index show] do
16
+ post 'comment', to: 'articles#create_comment', as: 'create_comment'
17
+ end
18
+ resources :languages, only: %i[index show] do
19
+ resources :albums, only: %i[index]
20
+ resources :articles, only: %i[index]
21
+ resources :notes, only: %i[index]
22
+ resources :projects, only: %i[index]
23
+ resources :uploads, only: %i[index]
24
+ end
25
+ resources :licenses, only: %i[index show] do
26
+ resources :albums, only: %i[index]
27
+ resources :articles, only: %i[index]
28
+ resources :notes, only: %i[index]
29
+ resources :projects, only: %i[index]
30
+ resources :uploads, only: %i[index]
31
+ end
32
+ resources :notes, only: %i[index show] do
33
+ post 'comment', to: 'notes#create_comment', as: 'create_comment'
34
+ end
35
+ resources :projects, only: %i[index show] do
36
+ resources :articles, only: %i[index]
37
+ resources :albums, only: %i[index]
38
+ resources :notes, only: %i[index]
39
+ resources :uploads, only: %i[index]
40
+ post 'comment', to: 'projects#create_comment', as: 'create_comment'
41
+ end
42
+
43
+ # Classifiers
44
+ resources :tags, only: %i[index show] do
45
+ resources :albums, only: %i[index]
46
+ resources :articles, only: %i[index]
47
+ resources :notes, only: %i[index]
48
+ resources :projects, only: %i[index]
49
+ resources :uploads, only: %i[index]
50
+ end
51
+ resources :uploads, only: %i[index show] do
52
+ post 'comment', to: 'uploads#create_comment', as: 'create_comment'
53
+ end
54
+ resources :users, only: %i[index show] do
55
+ resources :albums, only: %i[index]
56
+ resources :articles, only: %i[index]
57
+ resources :notes, only: %i[index]
58
+ resources :projects, only: %i[index]
59
+ resources :uploads, only: %i[index]
60
+ end
61
+
62
+ # Reports
63
+ post '/reports', to: 'reports#create', as: :create_report
64
+
65
+ # Activity
66
+ get '/activity', to: 'acts#index', as: :activities
67
+
68
+ # Member
69
+ namespace :member do
70
+ resources :albums, except: %i[show] do
71
+ put 'toggle_publication', to: 'albums#toggle_publication', as: :toggle_publication
72
+ end
73
+ resources :articles, except: %i[show] do
74
+ put 'toggle_publication', to: 'articles#toggle_publication', as: :toggle_publication
75
+ end
76
+ resources :notes, except: %i[show] do
77
+ put 'toggle_publication', to: 'notes#toggle_publication', as: :toggle_publication
78
+ end
79
+ resources :projects, except: %i[show] do
80
+ put 'toggle_publication', to: 'projects#toggle_publication', as: :toggle_publication
81
+ end
82
+ resources :uploads, except: %i[show] do
83
+ put 'toggle_publication', to: 'uploads#toggle_publication', as: :toggle_publication
84
+ end
85
+
86
+ get '/preferences', to: 'preferences#edit', as: :edit_preferences
87
+ patch '/preferences', to: 'preferences#update', as: :update_preferences
88
+ patch '/account', to: 'users#update', as: :update_user
89
+ end
90
+
91
+ # Admin
92
+ namespace :admin do
93
+ # Content resources
94
+ resources :albums, only: %i[index destroy] do
95
+ put 'toggle_lock', to: 'albums#toggle_lock', as: :toggle_lock
96
+ end
97
+ resources :articles, only: %i[index destroy] do
98
+ put 'toggle_lock', to: 'articles#toggle_lock', as: :toggle_lock
99
+ end
100
+ resources :notes, only: %i[index destroy] do
101
+ put 'toggle_lock', to: 'notes#toggle_lock', as: :toggle_lock
102
+ end
103
+ resources :projects, only: %i[index destroy] do
104
+ put 'toggle_lock', to: 'projects#toggle_lock', as: :toggle_lock
105
+ end
106
+ resources :uploads, only: %i[index destroy] do
107
+ put 'toggle_lock', to: 'uploads#toggle_lock', as: :toggle_lock
108
+ end
109
+ # Basic resources
110
+ resources :languages, except: %i[show]
111
+ resources :licenses, except: %i[show]
112
+ resources :reports, only: %i[index destroy]
113
+ resources :tags, except: %i[create show]
114
+ resources :users, only: %i[index show destroy]
115
+ end
116
+ end
@@ -0,0 +1,15 @@
1
+ class DeviseUpdateUsers < ActiveRecord::Migration[5.2]
2
+ def change
3
+ add_column :users, :username, :string, null: false
4
+ add_column :users, :real_name, :string
5
+ add_column :users, :biography, :text
6
+ add_column :users, :role, :string, null: false, default: 'user'
7
+ add_column :users, :albums_count, :integer, default: 0, null: false
8
+ add_column :users, :articles_count, :integer, default: 0, null: false
9
+ add_column :users, :notes_count, :integer, default: 0, null: false
10
+ add_column :users, :projects_count, :integer, default: 0, null: false
11
+ add_column :users, :uploads_count, :integer, default: 0, null: false
12
+
13
+ add_index :users, :username, unique: true
14
+ end
15
+ end