writefully 0.4.10 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/images/writefully/loading-bubbles.svg +14 -0
  3. data/app/assets/javascripts/writefully/writefully/initializers/manifest.coffee +5 -5
  4. data/app/assets/javascripts/writefully/writefully/initializers/setup.coffee +1 -1
  5. data/app/assets/javascripts/writefully/writefully/services/autosave.coffee +8 -0
  6. data/app/assets/stylesheets/writefully/base.sass +16 -1
  7. data/app/assets/stylesheets/writefully/profiles.sass +3 -0
  8. data/app/assets/stylesheets/writefully/sites.sass +0 -4
  9. data/app/assets/stylesheets/writefully/writefully.sass +2 -0
  10. data/app/controllers/writefully/profiles_controller.rb +12 -0
  11. data/app/models/writefully/authorship.rb +1 -1
  12. data/app/models/writefully/post.rb +1 -1
  13. data/app/views/writefully/application/_navigation.html.erb +2 -5
  14. data/app/views/writefully/application/_super_admin.html.erb +4 -0
  15. data/app/views/writefully/profiles/_form.html.erb +17 -0
  16. data/app/views/writefully/profiles/edit.html.erb +11 -0
  17. data/app/views/writefully/sites/new.html.erb +1 -1
  18. data/config/routes.rb +2 -1
  19. data/db/migrate/20140501094825_add_trashed_to_posts.rb +5 -0
  20. data/lib/writefully/cli.rb +1 -1
  21. data/lib/writefully/loader.rb +7 -2
  22. data/lib/writefully/postable.rb +22 -0
  23. data/lib/writefully/process.rb +9 -3
  24. data/lib/writefully/taxon.rb +52 -1
  25. data/lib/writefully/tools/dispatcher.rb +1 -1
  26. data/lib/writefully/tools/eraser.rb +16 -0
  27. data/lib/writefully/tools/pencil.rb +4 -34
  28. data/lib/writefully/tools/stationery.rb +42 -0
  29. data/lib/writefully/tools.rb +1 -0
  30. data/lib/writefully/version.rb +1 -1
  31. data/lib/writefully/workers/journalist.rb +2 -0
  32. data/spec/controllers/writefully/authorships_controller_spec.rb +7 -0
  33. data/spec/controllers/writefully/profiles_controller_spec.rb +7 -0
  34. data/spec/dummy/content/codemy-net/posts/1-hash-selector-pattern/meta.yml +0 -1
  35. data/spec/dummy/content/codemy-net/posts/2-rails-flash-partials/meta.yml +0 -1
  36. data/spec/dummy/db/schema.rb +2 -1
  37. data/spec/dummy/log/development.log +70 -0
  38. data/spec/dummy/log/test.log +2316 -0
  39. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_alerts.scssc +0 -0
  40. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_background-variant.scssc +0 -0
  41. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_border-radius.scssc +0 -0
  42. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_buttons.scssc +0 -0
  43. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_center-block.scssc +0 -0
  44. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_clearfix.scssc +0 -0
  45. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_forms.scssc +0 -0
  46. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_gradients.scssc +0 -0
  47. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_grid-framework.scssc +0 -0
  48. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_grid.scssc +0 -0
  49. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_hide-text.scssc +0 -0
  50. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_image.scssc +0 -0
  51. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_labels.scssc +0 -0
  52. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_list-group.scssc +0 -0
  53. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_nav-divider.scssc +0 -0
  54. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_nav-vertical-align.scssc +0 -0
  55. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_opacity.scssc +0 -0
  56. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_pagination.scssc +0 -0
  57. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_panels.scssc +0 -0
  58. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_progress-bar.scssc +0 -0
  59. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_reset-filter.scssc +0 -0
  60. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_resize.scssc +0 -0
  61. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_responsive-visibility.scssc +0 -0
  62. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_size.scssc +0 -0
  63. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_tab-focus.scssc +0 -0
  64. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_table-row.scssc +0 -0
  65. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_text-emphasis.scssc +0 -0
  66. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_text-overflow.scssc +0 -0
  67. data/spec/dummy/tmp/cache/assets/test/sass/2214915388977a1da0d5bf83510616733a1df75d/_vendor-prefixes.scssc +0 -0
  68. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_alerts.scssc +0 -0
  69. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_badges.scssc +0 -0
  70. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_breadcrumbs.scssc +0 -0
  71. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_button-groups.scssc +0 -0
  72. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_buttons.scssc +0 -0
  73. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_carousel.scssc +0 -0
  74. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_close.scssc +0 -0
  75. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_code.scssc +0 -0
  76. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_component-animations.scssc +0 -0
  77. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_dropdowns.scssc +0 -0
  78. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_forms.scssc +0 -0
  79. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_glyphicons.scssc +0 -0
  80. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_grid.scssc +0 -0
  81. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_input-groups.scssc +0 -0
  82. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_jumbotron.scssc +0 -0
  83. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_labels.scssc +0 -0
  84. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_list-group.scssc +0 -0
  85. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_media.scssc +0 -0
  86. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_mixins.scssc +0 -0
  87. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_modals.scssc +0 -0
  88. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_navbar.scssc +0 -0
  89. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_navs.scssc +0 -0
  90. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_normalize.scssc +0 -0
  91. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_pager.scssc +0 -0
  92. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_pagination.scssc +0 -0
  93. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_panels.scssc +0 -0
  94. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_popovers.scssc +0 -0
  95. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_print.scssc +0 -0
  96. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_progress-bars.scssc +0 -0
  97. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_responsive-embed.scssc +0 -0
  98. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_responsive-utilities.scssc +0 -0
  99. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_scaffolding.scssc +0 -0
  100. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_tables.scssc +0 -0
  101. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_thumbnails.scssc +0 -0
  102. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_tooltip.scssc +0 -0
  103. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_type.scssc +0 -0
  104. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_utilities.scssc +0 -0
  105. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_variables.scssc +0 -0
  106. data/spec/dummy/tmp/cache/assets/test/sass/4e0ec03be757f8083cd0b7f1d18721d9c08da7d6/_wells.scssc +0 -0
  107. data/spec/dummy/tmp/cache/assets/test/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/base.sassc +0 -0
  108. data/spec/dummy/tmp/cache/assets/test/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/profiles.sassc +0 -0
  109. data/spec/dummy/tmp/cache/assets/test/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/sessions.sassc +0 -0
  110. data/spec/dummy/tmp/cache/assets/test/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/sites.sassc +0 -0
  111. data/spec/dummy/tmp/cache/assets/test/sass/77bc3b7f842c905df4dddb7e3ac7b7cf15d9035b/writefully.sassc +0 -0
  112. data/spec/dummy/tmp/cache/assets/test/sass/af039d23726606ef9c96e50dbc4f6a7893b20f53/bootstrap.scssc +0 -0
  113. data/spec/dummy/tmp/cache/assets/test/sprockets/064b3076e29f54ea572ca43d6c5950cc +0 -0
  114. data/spec/dummy/tmp/cache/assets/test/sprockets/3063f229c5edc0e8a3d82d7bf78024de +0 -0
  115. data/spec/dummy/tmp/cache/assets/test/sprockets/31c84f37a0c92c38be6459f19997c981 +0 -0
  116. data/spec/dummy/tmp/cache/assets/test/sprockets/4684201e9a7b66017ea250f0d7fd06e2 +0 -0
  117. data/spec/dummy/tmp/cache/assets/test/sprockets/81e4a723953d063ec006596c9f2fb1ef +0 -0
  118. data/spec/dummy/tmp/cache/assets/test/sprockets/82b92bb7c88523dc617b3c0c877aeade +0 -0
  119. data/spec/dummy/tmp/cache/assets/test/sprockets/8d225befd9f2c5c3ef1ff73591bea154 +0 -0
  120. data/spec/dummy/tmp/cache/assets/test/sprockets/98223bde155ccb586e710444611aabb4 +0 -0
  121. data/spec/dummy/tmp/cache/assets/test/sprockets/9b9ee2a899dd8b3bfa592fba44ebf8d2 +0 -0
  122. data/spec/dummy/tmp/cache/assets/test/sprockets/a8b93e1f061f64547b92633c5bde6b13 +0 -0
  123. data/spec/dummy/tmp/cache/assets/test/sprockets/abf4fd7235880434a75a35635e4fb67a +0 -0
  124. data/spec/dummy/tmp/cache/assets/test/sprockets/adae8faa21b116471ec4285998d3f3cf +0 -0
  125. data/spec/dummy/tmp/cache/assets/test/sprockets/b83537e814e13cf03642ccc3d90fda13 +0 -0
  126. data/spec/dummy/tmp/cache/assets/test/sprockets/c1208bf8d0e9714161d8e6ae61781efc +0 -0
  127. data/spec/dummy/tmp/cache/assets/test/sprockets/d10e06dee94ddaa562f7df319407bf18 +0 -0
  128. data/spec/dummy/tmp/cache/assets/test/sprockets/d1238ae38ca7b9522d86d67ee367223e +0 -0
  129. data/spec/dummy/tmp/cache/assets/test/sprockets/d2c2fff5893ce8979ca48bab1c6f1c3a +0 -0
  130. data/spec/dummy/tmp/cache/assets/test/sprockets/d70cdda3055dc0a1d8b8e40baa559146 +0 -0
  131. data/spec/dummy/tmp/cache/assets/test/sprockets/d9930581c13e892e69359a33854d7af4 +0 -0
  132. data/spec/dummy/tmp/cache/assets/test/sprockets/e784991cbb1dab2f65db11cc0381b11d +0 -0
  133. data/spec/lib/writefully/content_spec.rb +0 -1
  134. data/spec/lib/writefully/tools/pencil_spec.rb +2 -2
  135. metadata +171 -3
  136. data/lib/writefully/workers_helpers.rb +0 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: ea727086bde7ed0d78dd3e7958a1fb03e97a81d2
4
- data.tar.gz: a918d1b2a13efcebd964644d9c7cd6026815d5f2
3
+ metadata.gz: f90afad3ac8a344ab63f1b9d301f27feaa0b4b4e
4
+ data.tar.gz: f4729685c69d37d11d244f8eafcaf96fbf67d8b7
5
5
  SHA512:
6
- metadata.gz: e320662c11c6f99e2daafd18095130c6bfc3979b5c0e4612b6a09d1b117bd70583c5c281b1b73d66eb3e132ee2598ff9703972ed33d07debf7cabe8924ac944d
7
- data.tar.gz: 96c3d3cac5e7eb62d7b28cee033ff1c53b9f12e217bead0f7e9fb18e9f08c10f90dfaf05ff48c5699b9bd4a6a029bef5affa5fd390a45fadbab2dd515999f4b8
6
+ metadata.gz: 9328f4d1e289b665ddc26ef2caaf29b43c555f0da2ee203aa1124de44923a5f27a28b9ae67d5f383453e6790b6785bf2827f63aa2a582a5b38bce5d59b8e08b1
7
+ data.tar.gz: 64c333720e0aba0799289765427724065676410bc607393cef7a209dab8a358bc33d9f0e3b2daf412eaf88e659f2cf94198d55aa5cea0f6ba8d99f77c6e837a4
@@ -0,0 +1,14 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32" width="32" height="32" fill="#ccc">
2
+ <circle transform="translate(8 0)" cx="0" cy="16" r="0">
3
+ <animate attributeName="r" values="0; 4; 0; 0" dur="1.2s" repeatCount="indefinite" begin="0"
4
+ keytimes="0;0.2;0.7;1" keySplines="0.2 0.2 0.4 0.8;0.2 0.6 0.4 0.8;0.2 0.6 0.4 0.8" calcMode="spline" />
5
+ </circle>
6
+ <circle transform="translate(16 0)" cx="0" cy="16" r="0">
7
+ <animate attributeName="r" values="0; 4; 0; 0" dur="1.2s" repeatCount="indefinite" begin="0.3"
8
+ keytimes="0;0.2;0.7;1" keySplines="0.2 0.2 0.4 0.8;0.2 0.6 0.4 0.8;0.2 0.6 0.4 0.8" calcMode="spline" />
9
+ </circle>
10
+ <circle transform="translate(24 0)" cx="0" cy="16" r="0">
11
+ <animate attributeName="r" values="0; 4; 0; 0" dur="1.2s" repeatCount="indefinite" begin="0.6"
12
+ keytimes="0;0.2;0.7;1" keySplines="0.2 0.2 0.4 0.8;0.2 0.6 0.4 0.8;0.2 0.6 0.4 0.8" calcMode="spline" />
13
+ </circle>
14
+ </svg>
@@ -1,4 +1,4 @@
1
- Application.services_manifest = ->
1
+ Writefully.services_manifest = ->
2
2
  # fill in your manifest here
3
3
  # example:
4
4
  # if you want to trigger a service on your entire app
@@ -21,8 +21,8 @@ Application.services_manifest = ->
21
21
  # body.photos.index').trigger 'application:services:service_name'
22
22
  #
23
23
 
24
- Application.run_ready = ->
25
- Application.services_manifest()
24
+ Writefully.run_ready = ->
25
+ Writefully.services_manifest()
26
26
 
27
- $(document).ready Application.run_ready
28
- $(document).on 'page:load', Application.run_ready
27
+ $(document).ready Writefully.run_ready
28
+ $(document).on 'page:load', Writefully.run_ready
@@ -1,4 +1,4 @@
1
- window.Application =
1
+ window.Writefully =
2
2
  Helpers: {}
3
3
  Services: {}
4
4
  Presenters: {}
@@ -0,0 +1,8 @@
1
+ class Writefully.Services.Notepad extends Transponder.Service
2
+ serviceName: 'autosave'
3
+ module: 'writefully'
4
+
5
+ init: ->
6
+
7
+ serve: ->
8
+ @init()
@@ -20,4 +20,19 @@ div.container
20
20
 
21
21
  .panel
22
22
  h1, h2, h3, h4, h5, h6
23
- margin: 0px !important
23
+ margin: 0px !important
24
+
25
+ form.form-horizontal
26
+ margin-top: 40px
27
+ p.form-info
28
+ padding: 10px
29
+
30
+ .form-control
31
+ border: none
32
+ @include box-shadow(none)
33
+ border-radius: 0px
34
+ background: #f8f8f8
35
+ border: 1px solid #e7e7e7
36
+
37
+ &:focus
38
+ @include box-shadow(0px 0px 5px #ddd)
@@ -0,0 +1,3 @@
1
+ body.writefully.profiles
2
+ h1
3
+ font-weight: 100
@@ -13,10 +13,6 @@ body.writefully.sites, body.writefully.posts.index
13
13
  ul.nav-tabs
14
14
  margin-bottom: 20px
15
15
 
16
- form#new_site
17
- margin-top: 40px
18
- p.form-info
19
- padding: 10px
20
16
 
21
17
 
22
18
  div.site.media
@@ -1,4 +1,6 @@
1
1
  @import "bootstrap"
2
+ @import "bootstrap/mixins"
2
3
  @import "base"
3
4
  @import "sites"
5
+ @import "profiles"
4
6
  @import "sessions"
@@ -0,0 +1,12 @@
1
+ require_dependency "writefully/application_controller"
2
+
3
+ module Writefully
4
+ class ProfilesController < ApplicationController
5
+ before_filter :authenticate_wf_authorship!
6
+
7
+
8
+ def edit
9
+ @authorship = current_wf_authorship
10
+ end
11
+ end
12
+ end
@@ -7,7 +7,7 @@ module Writefully
7
7
  has_many :posts
8
8
  has_many :owned_sites, class_name: "Writefully::Site", foreign_key: :owner_id
9
9
 
10
- store_accessor :data, :name, :email, :uid, :user_name, :auth_token
10
+ store_accessor :data, :name, :email, :uid, :user_name, :auth_token, :bio
11
11
 
12
12
  def to_s
13
13
  data["name"] || data["login"] || data["email"] || data["uid"]
@@ -8,7 +8,7 @@ module Writefully
8
8
  friendly_id :title, use: :slugged
9
9
 
10
10
  has_many :taggings, dependent: :destroy
11
- wf_taxonomize :tags, -> { where(type: nil) }, through: :taggings
11
+ wf_taxonomize :tags, through: :taggings
12
12
 
13
13
  belongs_to :authorship
14
14
  belongs_to :translation_source, class_name: "Writefully::Post"
@@ -10,12 +10,9 @@
10
10
  <%= link_to "Writefully", root_path, class: 'navbar-brand' %>
11
11
  </div>
12
12
  <div class="collapse navbar-collapse">
13
- <ul class='nav navbar-nav'>
14
- <%= activeable_link_to :li, "Dashboard", root_path, icon: 'home' %>
15
- <%= activeable_link_to :li, "New Site", new_site_path, icon: 'plus' %>
16
- </ul>
13
+ <%= render 'super_admin' if current_wf_authorship.role == 'super_admin' %>
17
14
  <ul class="nav navbar-nav navbar-right">
18
- <li><p class='navbar-text'><%= current_wf_authorship %></p></li>
15
+ <li><%= link_to current_wf_authorship, edit_profile_path %></li>
19
16
  <li><%= link_to "Sign Out", signout_path %></li>
20
17
  </ul>
21
18
  </div>
@@ -0,0 +1,4 @@
1
+ <ul class='nav navbar-nav'>
2
+ <%= activeable_link_to :li, "Dashboard", root_path, icon: 'home' %>
3
+ <%= activeable_link_to :li, "New Site", new_site_path, icon: 'plus' %>
4
+ </ul>
@@ -0,0 +1,17 @@
1
+ <%= form_for @authorship, html: { class: 'form-horizontal', role: 'form' } do |f| %>
2
+ <div class='form-group'>
3
+ <div class='col-sm-12'>
4
+ <%= f.text_field :name, class: 'form-control input-lg', placeholder: 'Name' %>
5
+ </div>
6
+ </div>
7
+ <div class='form-group'>
8
+ <div class='col-sm-12'>
9
+ <%= f.text_field :email, class: 'form-control input-lg', placeholder: 'Email' %>
10
+ </div>
11
+ </div>
12
+ <div class='form-group'>
13
+ <div class='col-sm-12'>
14
+ <%= f.text_area :bio, class: 'form-control input-lg', placeholder: 'A bit about yourself' %>
15
+ </div>
16
+ </div>
17
+ <% end %>
@@ -0,0 +1,11 @@
1
+ <%= content_for(:title, "Edit Author Profile") %>
2
+ <div class='row'>
3
+ <div class='col-md-4 col-md-offset-4'>
4
+ <h1 class='text-center'><%= current_wf_authorship %></h1>
5
+ <%= render 'form' %>
6
+ <p class='text-center loader hide'>
7
+ <%= image_tag 'writefully/loading-bubbles.svg', alt: 'loading icon', width: '128', height: '128' %>
8
+ </p>
9
+ </div>
10
+ </div>
11
+
@@ -1,4 +1,4 @@
1
- <%#= content_for(:title, "Site Setup") %>
1
+ <%= content_for(:title, "Site Setup") %>
2
2
  <div class='row'>
3
3
  <div class='col-md-4 col-md-offset-4'>
4
4
  <h1 class='text-center'>Site Setup</h1>
data/config/routes.rb CHANGED
@@ -5,7 +5,8 @@ Writefully::Engine.routes.draw do
5
5
  resources :posts, only: [:index, :show]
6
6
  end
7
7
 
8
- resources :authorships
8
+ resource :profile, only: [:edit]
9
+ resource :authorship, only: [:update]
9
10
  resource :hook, only: [:create]
10
11
 
11
12
  get '/signin', to: 'sessions#new'
@@ -0,0 +1,5 @@
1
+ class AddTrashedToPosts < ActiveRecord::Migration
2
+ def change
3
+ add_column :writefully_posts, :trashed, :boolean, default: false
4
+ end
5
+ end
@@ -45,7 +45,7 @@ module Writefully
45
45
 
46
46
  no_tasks do
47
47
  def listen(config)
48
- Writefully::Process.new(config).listen
48
+ Writefully::Process.instance.listen(config)
49
49
  end
50
50
 
51
51
  def setup_logger(logfile)
@@ -5,6 +5,10 @@ module Writefully
5
5
  SCOPES = %w(repo public_repo user write:repo_hook)
6
6
 
7
7
  class << self
8
+ QUEUE = {
9
+ top: -> (c, job) { c.lpush "jobs", job },
10
+ bottom: -> (c, job) { c.rpush "jobs", job }
11
+ }
8
12
 
9
13
  def options=(config)
10
14
  @_options = config
@@ -21,8 +25,9 @@ module Writefully
21
25
  end
22
26
  end
23
27
 
24
- def add_job worker, message
25
- Writefully.redis.with { |c| c.sadd "jobs", convert_job(worker, message) }
28
+ def add_job worker, message, position = nil
29
+ position_selector = position || :bottom
30
+ Writefully.redis.with { |c| QUEUE[position_selector].call(c, convert_job(worker, message)) }
26
31
  end
27
32
 
28
33
  def convert_job worker, message
@@ -9,6 +9,8 @@ module Writefully
9
9
  after_initialize :check_content_field_existence
10
10
  attr_accessor :publish
11
11
 
12
+ scope :with_taxonomies, -> (*types) { select(Taxon::EagerLoader.new(self).build(*types)) }
13
+
12
14
  before_save :publish_resource, if: -> { respond_to?(:published_at) }
13
15
  end
14
16
 
@@ -41,17 +43,37 @@ module Writefully
41
43
  class_eval do
42
44
  has_many :"#{type}", *args
43
45
 
46
+ define_method("all_#{type}") do
47
+ read_attribute(:"all_#{type}").map { |taxon| Hashie::Mash.new(taxon) }
48
+ end
49
+
44
50
  define_method("#{type}=") do |tokens|
45
51
  self.taxonomize_with(tokens, type)
46
52
  end
47
53
  end
48
54
  end
49
55
 
56
+ def filter_with(filters)
57
+ if filters.present?
58
+ filters.keys.inject(self) do |klass, type|
59
+ klass.where(id: by_taxonomies(filters[type].split(/,/), type))
60
+ end
61
+ else all end
62
+ end
63
+
64
+ def by_taxonomies(taxonomies, type)
65
+ joins(type.to_sym)
66
+ .where(writefully_tags: { slug: taxonomies,
67
+ type: (type == "tags" ? nil : type.classify) })
68
+ .uniq
69
+ end
70
+
50
71
  def wf_content(field_name)
51
72
  class_eval do
52
73
  alias_attribute :content, :"#{field_name}" unless field_name == :content
53
74
  end
54
75
  end
76
+
55
77
  end
56
78
  end
57
79
  end
@@ -14,15 +14,21 @@ require 'writefully/loader'
14
14
  require 'writefully/tools'
15
15
  require 'writefully/workers'
16
16
  require 'writefully/news_agency'
17
+ require 'singleton'
17
18
 
18
19
  %w(tag post site tagging authorship).each do |model|
19
20
  require File.dirname(__FILE__) + "/../../app/models/writefully/#{model}"
20
21
  end
21
22
 
22
23
  module Writefully
23
- Process = Struct.new(:config) do
24
+ class Process
25
+ include Singleton
26
+
27
+ attr_reader :config
28
+
29
+ def listen config
30
+ @config = config
24
31
 
25
- def listen
26
32
  set_title
27
33
  set_options
28
34
  log_start
@@ -88,7 +94,7 @@ module Writefully
88
94
 
89
95
  JOBS = {
90
96
  write: -> (index) { Writefully.add_job :journalists, index.merge({task: :publish}) },
91
- remove: -> (index) { Wrotefully.add_job :journalists, index.merge({task: :remove}) }
97
+ remove: -> (index) { Writefully.add_job :journalists, index.merge({task: :remove}), :top }
92
98
  }
93
99
 
94
100
  def queue_jobs indices, action
@@ -1,5 +1,13 @@
1
1
  module Writefully
2
- Taxon = Struct.new(:incoming, :existing, :type) do
2
+ class Taxon
3
+ attr_reader :incoming, :existing, :type
4
+
5
+ def initialize(incoming, existing, type)
6
+ @incoming = incoming
7
+ @existing = existing
8
+ @type = type
9
+ end
10
+
3
11
  def non_existing
4
12
  get_difference.map { |token| Tag.new(build_attributes(token)) }
5
13
  end
@@ -24,5 +32,48 @@ module Writefully
24
32
  def parameterized items
25
33
  items.map { |t| t.parameterize }
26
34
  end
35
+
36
+ class EagerLoader
37
+ attr_reader :tags, :taggings, :resource
38
+
39
+ def initialize(klass)
40
+ @tags = Tag.arel_table
41
+ @taggings = Tagging.arel_table
42
+ @resource = klass.arel_table
43
+ end
44
+
45
+ def build *types
46
+ [resource[Arel.star]] << types.map { |type| array_of_taxonomy_hstores_for(type) }
47
+ end
48
+
49
+ private
50
+
51
+ def array_of_taxonomy_hstores_for type
52
+ Arel::Nodes::NamedFunction.new('ARRAY', [hstore_for_taxon(type)]).as("all_#{type}")
53
+ end
54
+
55
+ def hstore_for_taxon type
56
+ tags.project(Arel.sql('hstore(taxon)')).from(taxons_for_resource(type))
57
+ end
58
+
59
+ def taxons_for_resource type
60
+ Tag.joins(:taggings).arel.where(tags_by_type(type))
61
+ .where(taggings_by_resource).as('taxon')
62
+ end
63
+
64
+ def tags_by_type type
65
+ tags[:type].eq(calculate_type(type))
66
+ end
67
+
68
+ def taggings_by_resource
69
+ # we use post_id for now but we should
70
+ # make it a polymorphic association later
71
+ taggings[:post_id].eq(resource[:id])
72
+ end
73
+
74
+ def calculate_type type
75
+ type == :tags ? nil : type.to_s.classify
76
+ end
77
+ end
27
78
  end
28
79
  end
@@ -12,7 +12,7 @@ module Writefully
12
12
  end
13
13
 
14
14
  def get_job_data
15
- Writefully.redis.with { |c| c.spop 'jobs' }
15
+ Writefully.redis.with { |c| c.lpop 'jobs' }
16
16
  end
17
17
 
18
18
  def heartbeat
@@ -0,0 +1,16 @@
1
+ module Writefully
2
+ module Tools
3
+ class Eraser < Stationery
4
+
5
+ def use
6
+ destroy
7
+ end
8
+
9
+ def destroy
10
+ compute_type.by_site(site_id)
11
+ .where(slug: content.slug)
12
+ .first.update_attributes(trashed: true)
13
+ end
14
+ end
15
+ end
16
+ end
@@ -1,21 +1,8 @@
1
1
  module Writefully
2
2
  module Tools
3
- class Pencil
4
- include Celluloid
3
+ class Pencil < Stationery
5
4
 
6
- attr_reader :resource, :content, :asset, :index, :site_id, :asset
7
-
8
- class ContentModelNotFound < StandardError; end
9
- class SomeAssetsNotUploaded < StandardError; end
10
-
11
- def initialize(index)
12
- @site_id = Site.where(slug: index[:site]).first.id
13
- @index = index
14
- @content = Content.new(index)
15
- @asset = Asset.new(index)
16
- end
17
-
18
- def perform
5
+ def use
19
6
  assets_uploaded = upload_assets.map(&:value).compact
20
7
  written_to_db = future.write if can_update_db?(assets_uploaded)
21
8
  terminate if written_to_db.value
@@ -24,7 +11,8 @@ module Writefully
24
11
  def computed_attributes
25
12
  content.meta.merge({
26
13
  "content" => asset.convert_for(content.body),
27
- "details" => asset.convert_for(content.details)
14
+ "details" => asset.convert_for(content.details),
15
+ "trashed" => false
28
16
  })
29
17
  end
30
18
 
@@ -32,8 +20,6 @@ module Writefully
32
20
  compute_type.by_site(site_id).where(slug: content.slug)
33
21
  .first_or_initialize
34
22
  .update_attributes(computed_attributes)
35
- ensure
36
- ::ActiveRecord::Base.clear_active_connections! if defined?(::ActiveRecord)
37
23
  end
38
24
 
39
25
  def upload_assets
@@ -49,22 +35,6 @@ module Writefully
49
35
  raise SomeAssetsNotUploaded, "Some assets was not uploaded"
50
36
  end
51
37
  end
52
-
53
- private
54
-
55
- def compute_type
56
- index[:resource].classify.constantize
57
- rescue NameError
58
- fallback_type
59
- end
60
-
61
- def fallback_type
62
- if index[:resource] == "posts"
63
- "Writefully::Post".constantize
64
- else
65
- raise ContentModelNotFound, "Model #{index[:resource].classify} was not found"
66
- end
67
- end
68
38
 
69
39
  end
70
40
  end
@@ -0,0 +1,42 @@
1
+ module Writefully
2
+ module Tools
3
+ class Stationery
4
+ include Celluloid
5
+
6
+ attr_reader :content, :asset, :index, :site_id
7
+
8
+ class ContentModelNotFound < StandardError; end
9
+ class SomeAssetsNotUploaded < StandardError; end
10
+
11
+ def initialize(index)
12
+ @site_id = Site.where(slug: index[:site]).first.id
13
+ @index = index
14
+ @content = Content.new(index)
15
+ @asset = Asset.new(index)
16
+ end
17
+
18
+ def perform
19
+ use
20
+ ensure
21
+ ::ActiveRecord::Base.clear_active_connections! if defined?(::ActiveRecord)
22
+ end
23
+
24
+ private
25
+
26
+ def compute_type
27
+ index[:resource].classify.constantize
28
+ rescue NameError
29
+ fallback_type
30
+ end
31
+
32
+ def fallback_type
33
+ if index[:resource] == "posts"
34
+ "Writefully::Post".constantize
35
+ else
36
+ raise ContentModelNotFound, "Model #{index[:resource].classify} was not found"
37
+ end
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -4,6 +4,7 @@ module Writefully
4
4
  end
5
5
  end
6
6
 
7
+ require 'writefully/tools/stationery'
7
8
  require 'writefully/tools/eraser'
8
9
  require 'writefully/tools/pencil'
9
10
  require 'writefully/tools/pigeon'
@@ -1,3 +1,3 @@
1
1
  module Writefully
2
- VERSION = "0.4.10"
2
+ VERSION = "0.5.0"
3
3
  end
@@ -9,6 +9,8 @@ module Writefully
9
9
 
10
10
  def remove
11
11
  Writefully.logger.info "Removing #{message[:resource]} #{message[:slug]}"
12
+ eraser = Tools::Eraser.new_link(message)
13
+ eraser.perform
12
14
  end
13
15
 
14
16
  def message_with_tries
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ module Writefully
4
+ describe AuthorshipsController do
5
+
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ require 'spec_helper'
2
+
3
+ module Writefully
4
+ describe ProfilesController do
5
+
6
+ end
7
+ end
@@ -1,5 +1,4 @@
1
1
  title: "Ruby Hash Selector Pattern"
2
- slug: "ruby-hash-selector-pattern"
3
2
  tags: ["Ruby"]
4
3
  playlists: ["A Shot of Ruby"]
5
4
  details:
@@ -1,5 +1,4 @@
1
1
  title: "Rails Flash Partials"
2
- slug: "rails-flash-partials"
3
2
  tags: ["Rails"]
4
3
  playlists: ["A Shot of Ruby"]
5
4
  details:
@@ -11,7 +11,7 @@
11
11
  #
12
12
  # It's strongly recommended that you check this file into your version control system.
13
13
 
14
- ActiveRecord::Schema.define(version: 20140403181629) do
14
+ ActiveRecord::Schema.define(version: 20140501094825) do
15
15
 
16
16
  # These are extensions that must be enabled in order to support this database
17
17
  enable_extension "plpgsql"
@@ -41,6 +41,7 @@ ActiveRecord::Schema.define(version: 20140403181629) do
41
41
  t.integer "authorship_id"
42
42
  t.datetime "created_at"
43
43
  t.datetime "updated_at"
44
+ t.boolean "trashed", default: false
44
45
  end
45
46
 
46
47
  add_index "writefully_posts", ["authorship_id"], name: "index_writefully_posts_on_authorship_id", using: :btree