TextTractor 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +4 -0
  3. data/MIT-LICENSE +20 -0
  4. data/README.md +66 -0
  5. data/Rakefile +6 -0
  6. data/assets/images/blankpad.png +0 -0
  7. data/assets/images/stale.png +0 -0
  8. data/assets/images/translated.png +0 -0
  9. data/assets/images/untranslated.png +0 -0
  10. data/assets/js/application.js +38 -0
  11. data/assets/js/jquery.js +16 -0
  12. data/assets/js/jquery.pjax.js +188 -0
  13. data/config.ru +20 -0
  14. data/lib/text_tractor.rb +31 -0
  15. data/lib/text_tractor/api_server.rb +93 -0
  16. data/lib/text_tractor/base.rb +25 -0
  17. data/lib/text_tractor/config.rb +48 -0
  18. data/lib/text_tractor/phrase.rb +67 -0
  19. data/lib/text_tractor/projects.rb +202 -0
  20. data/lib/text_tractor/ui_server.rb +152 -0
  21. data/lib/text_tractor/users.rb +49 -0
  22. data/lib/text_tractor/users_spec.rb +10 -0
  23. data/lib/text_tractor/version.rb +3 -0
  24. data/spec/api_server_spec.rb +224 -0
  25. data/spec/config_spec.rb +56 -0
  26. data/spec/phrase_spec.rb +71 -0
  27. data/spec/project_spec.rb +292 -0
  28. data/spec/spec_helper.rb +51 -0
  29. data/spec/ui_server/authentication_spec.rb +60 -0
  30. data/spec/ui_server/project_management_spec.rb +103 -0
  31. data/spec/ui_server/project_viewing_spec.rb +137 -0
  32. data/spec/ui_server_spec.rb +6 -0
  33. data/spec/users_spec.rb +123 -0
  34. data/text_tractor.gemspec +33 -0
  35. data/views/blurbs/_blurb.haml +1 -0
  36. data/views/blurbs/edit.haml +5 -0
  37. data/views/blurbs/value.haml +9 -0
  38. data/views/index.haml +13 -0
  39. data/views/layout.haml +26 -0
  40. data/views/projects/getting_started.haml +16 -0
  41. data/views/projects/new.haml +18 -0
  42. data/views/projects/show.haml +23 -0
  43. data/views/styles.scss +218 -0
  44. data/views/users.haml +29 -0
  45. data/watchr.rb +8 -0
  46. metadata +225 -0
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "text_tractor/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "TextTractor"
7
+ s.version = TextTractor::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Jon Wood"]
10
+ s.email = ["jon@blankpad.net"]
11
+ s.homepage = "https://github.com/jellybob/text_tractor"
12
+ s.summary = %q{An implementation of the server side for a certain web service.}
13
+ s.description = %q{TextTractor provides a web interface so that your clients can edit their copy, while you get on with more interesting things.}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_dependency "haml"
21
+ s.add_dependency "sass"
22
+ s.add_dependency "sinatra"
23
+ s.add_dependency "json"
24
+ s.add_dependency "redis"
25
+ s.add_dependency "redis-namespace"
26
+
27
+ s.add_development_dependency "rake"
28
+ s.add_development_dependency "rspec"
29
+ s.add_development_dependency "rack-test"
30
+ s.add_development_dependency "capybara"
31
+
32
+ s.post_install_message = "If you're updating from 0.0.1 then you need to run TextTractor::Projects.update_datastore. See https://github.com/jellybob/text_tractor/wiki/Updating-Your-Datastore for details."
33
+ end
@@ -0,0 +1 @@
1
+ %dd{ "data-key" => @key }= @value
@@ -0,0 +1,5 @@
1
+ %dt{ class: "state-#{@phrase[@locale].state}" }= @path.split("/").collect { |part| part.gsub("_", " ").capitalize }.join(" / ")
2
+ %dd{ "data-key" => @path.gsub("/", ".") }
3
+ %form{ method: "post", action: "/projects/#{@api_key}/#{@locale}/#{@path}" }
4
+ %textarea{ name: "blurb" }= @phrase[@locale].to_s.strip
5
+ %input{ type: "submit", value: "Save" }
@@ -0,0 +1,9 @@
1
+ %dt{ class: "state-#{phrase.state}" }= key.split(".").collect { |part| part.gsub("_", " ").capitalize }.join(" / ")
2
+ %dd{ "data-key" => key }
3
+ - unless phrase.to_s.empty?
4
+ %p.translation= phrase.to_s
5
+ - else
6
+ %p.translation.empty Click to add a translation
7
+
8
+ - if show_original
9
+ %p.original= original
@@ -0,0 +1,13 @@
1
+ %h1 Projects
2
+
3
+ %section#projects
4
+ - if @projects.size > 0
5
+ %ul
6
+ - @projects.each do |project|
7
+ %li
8
+ %a{ href: "/projects/#{project["api_key"]}" }= project["name"]
9
+ - else
10
+ %p It doesn't look like you've got any projects yet.
11
+
12
+ - if current_user["superuser"]
13
+ %a#new_project{ href: "/projects/new" } Create a Project
@@ -0,0 +1,26 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %title TextTractor
5
+ %link{ rel: "stylesheet", href: "/styles.css"}
6
+ %script{ src: "/js/jquery.js" }
7
+ %script{ src: "/js/jquery.pjax.js" }
8
+ %script{ src: "/js/application.js" }
9
+
10
+ %body
11
+ %header
12
+ %ul#navigation
13
+ - if current_user["superuser"]
14
+ %li
15
+ %a{ href: "/users" } Users
16
+ %li
17
+ %a{ href: "/" } Projects
18
+
19
+ %h1 TextTractor
20
+
21
+ %section#content
22
+ =yield
23
+
24
+ %footer
25
+ %a{ href: "http://blankpad.net", target: "_top" }
26
+ %img{ src: "/images/blankpad.png", alt: "Blank Pad Development", title: "Developed by Blank Pad Development" }
@@ -0,0 +1,16 @@
1
+ %h1= "#{@project["name"]} (#{@project["default_locale"]})"
2
+ %p It doesn't look like you've set up your application to work with TextTractor yet. If you know what you're doing your API key is:
3
+ %p.api_key= @project["api_key"]
4
+
5
+ %p Otherwise, follow the instructions below to configure a Rails 3 application:
6
+
7
+ %p Add Copycopter client to your Gemfile
8
+ %code gem "copycopter_client"
9
+
10
+ %p Then create config/initializers/text_tractor.rb with the following content:
11
+ %code= @project.configuration_block
12
+
13
+ %p And finally, restart your application server. Your appliction will then upload translations and this page will disappear.
14
+ %p
15
+ As you open each page you'll see the translations defined on those pages appear here. Any changes you make from this web interface
16
+ will appear within your development and staging applications shortly afterwards.
@@ -0,0 +1,18 @@
1
+ %h1 New Project
2
+ %form{ action: "/projects", method: "post" }
3
+ %div.field
4
+ %label{ for: "name" } Project Name
5
+ %input{ type: "text", name: "project[name]", id: "name" }
6
+
7
+ %div.field
8
+ %label{ for: "default_locale" } Default Locale
9
+ %input{ type: "text", name: "project[default_locale]", id: "default_locale", value: "en" }
10
+
11
+ %h2 Users
12
+ %p Check the box next to each user who should be granted access to this project.
13
+ - @users.each do |user|
14
+ %div.field
15
+ %label{ for: "user_#{user["username"]}" }= user["name"]
16
+ %input{ type: "checkbox", name: "project[users][]", id: "user_#{user["username"]}" }
17
+
18
+ %input{ type: "submit", value: "Create Project" }
@@ -0,0 +1,23 @@
1
+ %h1= "#{@project["name"]} (#{@locale})"
2
+ %ul#locales
3
+ - @project.locales.each do |locale|
4
+ %li
5
+ - if locale == @locale
6
+ = locale
7
+ - else
8
+ %a{ href: "/projects/#{@project.api_key}/#{locale}" }= locale
9
+
10
+ %form#filter{ method: "get" }
11
+ %label{ for: "state" } Filter:
12
+ %select#state{ name: "state" }
13
+ - { "all" => "All", "needs_work" => "Requires work", "translated" => "Translated", "untranslated" => "Untranslated", "stale" => "Stale" }.each do |key, value|
14
+ - if key == params["state"]
15
+ %option{ selected: "selected", value: key }= value
16
+ - else
17
+ %option{ value: key }= value
18
+
19
+ %p Click on a phrase to edit it.
20
+
21
+ %dl
22
+ - @phrases.sort.each do |key, value|
23
+ = haml :"blurbs/value", :layout => false, :locals => { :phrase => value[@locale], :key => key, :locale => @locale, :original => value[@project.default_locale], :show_original => @project.default_locale != @locale }
@@ -0,0 +1,218 @@
1
+ /* Reset */
2
+ html, body, div, span, applet, object, iframe,
3
+ h1, h2, h3, h4, h5, h6, p, blockquote, pre,
4
+ a, abbr, acronym, address, big, cite, code,
5
+ del, dfn, em, img, ins, kbd, q, s, samp,
6
+ small, strike, strong, sub, sup, tt, var,
7
+ b, u, i, center,
8
+ dl, dt, dd, ol, ul, li,
9
+ fieldset, form, label, legend,
10
+ table, caption, tbody, tfoot, thead, tr, th, td,
11
+ article, aside, canvas, details, embed,
12
+ figure, figcaption, footer, header, hgroup,
13
+ menu, nav, output, ruby, section, summary,
14
+ time, mark, audio, video {
15
+ margin: 0;
16
+ padding: 0;
17
+ border: 0;
18
+ font-size: 100%;
19
+ font: inherit;
20
+ vertical-align: baseline;
21
+ }
22
+ /* HTML5 display-role reset for older browsers */
23
+ article, aside, details, figcaption, figure,
24
+ footer, header, hgroup, menu, nav, section {
25
+ display: block;
26
+ }
27
+ body {
28
+ line-height: 1;
29
+ }
30
+ ol, ul {
31
+ list-style: none;
32
+ }
33
+ blockquote, q {
34
+ quotes: none;
35
+ }
36
+ blockquote:before, blockquote:after,
37
+ q:before, q:after {
38
+ content: '';
39
+ content: none;
40
+ }
41
+ table {
42
+ border-collapse: collapse;
43
+ border-spacing: 0;
44
+ }
45
+
46
+ /* The real deal */
47
+ body {
48
+ background-color: #f5f5f5;
49
+ font-family: "Georgia", serif;
50
+ padding: 0;
51
+ margin: 0;
52
+
53
+ header {
54
+ margin: 0;
55
+ padding: 0.5em 1em;
56
+ background-color: darken(#f5f5f5, 50%);
57
+
58
+ h1 {
59
+ margin-top: 0;
60
+ margin-bottom: 0.2em;
61
+ font-size: 2em;
62
+ font-weight: bold;
63
+ }
64
+
65
+ ul#navigation {
66
+ li {
67
+ float: right;
68
+ font-weight: bold;
69
+ display: inline;
70
+ margin-top: 0.5em;
71
+ margin-left: 1em;
72
+
73
+ a {
74
+ color: black;
75
+ text-decoration: none;
76
+ }
77
+ }
78
+ }
79
+ }
80
+
81
+ section#content {
82
+ padding: 0.5em 1em;
83
+
84
+ h1 {
85
+ font-size: 1.5em;
86
+ margin-bottom: 0.5em;
87
+ }
88
+
89
+ h2 {
90
+ font-size: 1.3em;
91
+ margin-bottom: 0.5em;
92
+ margin-top: 1em;
93
+ }
94
+
95
+ p {
96
+ line-height: 1.4em;
97
+ margin: 0.5em 0;
98
+ }
99
+
100
+ ul {
101
+ margin-top: 1em;
102
+ margin-left: 1.2em;
103
+ list-style: disc;
104
+
105
+ li {
106
+ margin-bottom: 0.5em;
107
+ }
108
+ }
109
+
110
+ ul#locales {
111
+ margin-top: 0;
112
+ margin-bottom: 1em;
113
+ margin-left: 0;
114
+ padding-left: 0;
115
+ font-size: 1.1em;
116
+
117
+ &:before {
118
+ content: "Language:";
119
+ font-weight: bold;
120
+ }
121
+
122
+ li {
123
+ display: inline;
124
+ }
125
+ }
126
+
127
+ label {
128
+ font-weight: bold;
129
+ }
130
+
131
+ p.api_key {
132
+ text-align: center;
133
+ font-size: 1.5em;
134
+ font-weight: bold;
135
+ }
136
+
137
+ code {
138
+ background-color: #333;
139
+ border: 2px solid #999;
140
+ color: white;
141
+ display: block;
142
+ font-family: monospace;
143
+ white-space: pre;
144
+ padding: 0.5em;
145
+ margin-top: 0.5em;
146
+ margin-bottom: 0.5em;
147
+ }
148
+
149
+ form {
150
+ .field {
151
+ margin-bottom: 0.5em;
152
+
153
+ label {
154
+ width: 10em;
155
+ display: block;
156
+ float: left;
157
+ }
158
+
159
+ input[type="text"] {
160
+ min-width: 30em;
161
+ }
162
+
163
+ input[type="submit"] {
164
+ margin-left: 15em;
165
+ }
166
+ }
167
+ }
168
+
169
+ dl {
170
+ margin-bottom: 0.5em;
171
+
172
+ dt {
173
+ font-weight: bold;
174
+ background-position: top left;
175
+ background-repeat: no-repeat;
176
+ padding-left: 20px;
177
+
178
+ &.state-translated {
179
+ background-image: url("/images/translated.png");
180
+ }
181
+
182
+ &.state-untranslated {
183
+ background-image: url("/images/untranslated.png");
184
+ }
185
+
186
+ &.state-stale {
187
+ background-image: url("/images/stale.png");
188
+ }
189
+ }
190
+
191
+ dd {
192
+ margin-top: 0.2em;
193
+ margin-bottom: 0.5em;
194
+
195
+ textarea {
196
+ font-size: 1em;
197
+ font-family: "Georgia", serif;
198
+ padding: 0.3em;
199
+ width: 100%;
200
+ }
201
+
202
+ input[type="submit"] {
203
+ display: block;
204
+ font-size: 1em;
205
+ }
206
+
207
+ p.empty {
208
+ color: #999;
209
+ }
210
+ }
211
+ }
212
+ }
213
+
214
+ footer {
215
+ padding: 0.5em 1em;
216
+ text-align: right;
217
+ }
218
+ }
@@ -0,0 +1,29 @@
1
+ %h1 User Management
2
+ %p Listed below are the currently available users. You can only create users from here. To change their details, you'll have to get dirty in the console.
3
+
4
+ %ul
5
+ - @users.each do |user|
6
+ %li
7
+ = user["name"]
8
+ = "(Superuser)" if user["superuser"]
9
+
10
+ %h2 Create a User
11
+ %form{ method: "post" }
12
+ %div.field
13
+ %label{ for: "name" } Name
14
+ %input{ type: "text", id: "name", name: "user[name]" }
15
+
16
+ %div.field
17
+ %label{ for: "username" } Username
18
+ %input{ type: "text", id: "username", name: "user[username]" }
19
+
20
+ %div.field
21
+ %label{ for: "password" } Password
22
+ %input{ type: "text", id: "password", name: "user[password]" }
23
+
24
+ %div.field
25
+ %label{ for: "superuser" } Superuser
26
+ %input{ type: "checkbox", id: "superuser", name: "user[superuser]", value: "true" }
27
+
28
+ %div.field
29
+ %input{ type: "submit", value: "Create User" }
@@ -0,0 +1,8 @@
1
+ def restart_and_spec
2
+ system("powder restart")
3
+ system("bundle exec rspec spec")
4
+ end
5
+
6
+ watch( 'lib/.*\.rb' ) { |md| restart_and_spec }
7
+ watch( 'views/.*') { |md| restart_and_spec }
8
+ watch( 'spec/.*\.rb' ) { |md| system("bundle exec rspec spec") }
metadata ADDED
@@ -0,0 +1,225 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: TextTractor
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.1.0
6
+ platform: ruby
7
+ authors:
8
+ - Jon Wood
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2011-05-31 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: haml
18
+ requirement: &id001 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ type: :runtime
25
+ prerelease: false
26
+ version_requirements: *id001
27
+ - !ruby/object:Gem::Dependency
28
+ name: sass
29
+ requirement: &id002 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ">="
33
+ - !ruby/object:Gem::Version
34
+ version: "0"
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: *id002
38
+ - !ruby/object:Gem::Dependency
39
+ name: sinatra
40
+ requirement: &id003 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: "0"
46
+ type: :runtime
47
+ prerelease: false
48
+ version_requirements: *id003
49
+ - !ruby/object:Gem::Dependency
50
+ name: json
51
+ requirement: &id004 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ type: :runtime
58
+ prerelease: false
59
+ version_requirements: *id004
60
+ - !ruby/object:Gem::Dependency
61
+ name: redis
62
+ requirement: &id005 !ruby/object:Gem::Requirement
63
+ none: false
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: *id005
71
+ - !ruby/object:Gem::Dependency
72
+ name: redis-namespace
73
+ requirement: &id006 !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ">="
77
+ - !ruby/object:Gem::Version
78
+ version: "0"
79
+ type: :runtime
80
+ prerelease: false
81
+ version_requirements: *id006
82
+ - !ruby/object:Gem::Dependency
83
+ name: rake
84
+ requirement: &id007 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: "0"
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: *id007
93
+ - !ruby/object:Gem::Dependency
94
+ name: rspec
95
+ requirement: &id008 !ruby/object:Gem::Requirement
96
+ none: false
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ type: :development
102
+ prerelease: false
103
+ version_requirements: *id008
104
+ - !ruby/object:Gem::Dependency
105
+ name: rack-test
106
+ requirement: &id009 !ruby/object:Gem::Requirement
107
+ none: false
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ version: "0"
112
+ type: :development
113
+ prerelease: false
114
+ version_requirements: *id009
115
+ - !ruby/object:Gem::Dependency
116
+ name: capybara
117
+ requirement: &id010 !ruby/object:Gem::Requirement
118
+ none: false
119
+ requirements:
120
+ - - ">="
121
+ - !ruby/object:Gem::Version
122
+ version: "0"
123
+ type: :development
124
+ prerelease: false
125
+ version_requirements: *id010
126
+ description: TextTractor provides a web interface so that your clients can edit their copy, while you get on with more interesting things.
127
+ email:
128
+ - jon@blankpad.net
129
+ executables: []
130
+
131
+ extensions: []
132
+
133
+ extra_rdoc_files: []
134
+
135
+ files:
136
+ - .gitignore
137
+ - Gemfile
138
+ - MIT-LICENSE
139
+ - README.md
140
+ - Rakefile
141
+ - assets/images/blankpad.png
142
+ - assets/images/stale.png
143
+ - assets/images/translated.png
144
+ - assets/images/untranslated.png
145
+ - assets/js/application.js
146
+ - assets/js/jquery.js
147
+ - assets/js/jquery.pjax.js
148
+ - config.ru
149
+ - lib/text_tractor.rb
150
+ - lib/text_tractor/api_server.rb
151
+ - lib/text_tractor/base.rb
152
+ - lib/text_tractor/config.rb
153
+ - lib/text_tractor/phrase.rb
154
+ - lib/text_tractor/projects.rb
155
+ - lib/text_tractor/ui_server.rb
156
+ - lib/text_tractor/users.rb
157
+ - lib/text_tractor/users_spec.rb
158
+ - lib/text_tractor/version.rb
159
+ - spec/api_server_spec.rb
160
+ - spec/config_spec.rb
161
+ - spec/phrase_spec.rb
162
+ - spec/project_spec.rb
163
+ - spec/spec_helper.rb
164
+ - spec/ui_server/authentication_spec.rb
165
+ - spec/ui_server/project_management_spec.rb
166
+ - spec/ui_server/project_viewing_spec.rb
167
+ - spec/ui_server_spec.rb
168
+ - spec/users_spec.rb
169
+ - text_tractor.gemspec
170
+ - views/blurbs/_blurb.haml
171
+ - views/blurbs/edit.haml
172
+ - views/blurbs/value.haml
173
+ - views/index.haml
174
+ - views/layout.haml
175
+ - views/projects/getting_started.haml
176
+ - views/projects/new.haml
177
+ - views/projects/show.haml
178
+ - views/styles.scss
179
+ - views/users.haml
180
+ - watchr.rb
181
+ has_rdoc: true
182
+ homepage: https://github.com/jellybob/text_tractor
183
+ licenses: []
184
+
185
+ post_install_message: If you're updating from 0.0.1 then you need to run TextTractor::Projects.update_datastore. See https://github.com/jellybob/text_tractor/wiki/Updating-Your-Datastore for details.
186
+ rdoc_options: []
187
+
188
+ require_paths:
189
+ - lib
190
+ required_ruby_version: !ruby/object:Gem::Requirement
191
+ none: false
192
+ requirements:
193
+ - - ">="
194
+ - !ruby/object:Gem::Version
195
+ hash: 1027683455972089235
196
+ segments:
197
+ - 0
198
+ version: "0"
199
+ required_rubygems_version: !ruby/object:Gem::Requirement
200
+ none: false
201
+ requirements:
202
+ - - ">="
203
+ - !ruby/object:Gem::Version
204
+ hash: 1027683455972089235
205
+ segments:
206
+ - 0
207
+ version: "0"
208
+ requirements: []
209
+
210
+ rubyforge_project:
211
+ rubygems_version: 1.6.2
212
+ signing_key:
213
+ specification_version: 3
214
+ summary: An implementation of the server side for a certain web service.
215
+ test_files:
216
+ - spec/api_server_spec.rb
217
+ - spec/config_spec.rb
218
+ - spec/phrase_spec.rb
219
+ - spec/project_spec.rb
220
+ - spec/spec_helper.rb
221
+ - spec/ui_server/authentication_spec.rb
222
+ - spec/ui_server/project_management_spec.rb
223
+ - spec/ui_server/project_viewing_spec.rb
224
+ - spec/ui_server_spec.rb
225
+ - spec/users_spec.rb