phrasing 4.0.0rc3 → 4.0.0rc4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: aa17e70cddb3a13fbaefc3f473d185c93ddad028
4
- data.tar.gz: 4947a95d4f5c5f1dda178056a589b2f2548fedf9
3
+ metadata.gz: 6ec5cf82a1f8789b4f8c7f25f1fd93ec9c370ded
4
+ data.tar.gz: 9d92db89baa70f2adf1fd122ced6cb949ee4e44e
5
5
  SHA512:
6
- metadata.gz: 645b4738ea92b854116bac7cdaef56a797c4121629788a5d7b7b956a11d0869152ccb694a319552ff87ec9938ebc537c64716f419931e60fc6503a9772ac5014
7
- data.tar.gz: 01aff8859f2081498e5f274a5239f329b6f5ce0faf16b14b85170dd843edfaaaed5ab9a411874552e60708b662be0d945f60857b9a46eb47efe9fb6a76fbc91a
6
+ metadata.gz: 1ab0220b8ad7cf33ec522ba8155d2aeb65ffed693bb2c4eed8a8ce736efc0ae8b96d859618829092b6c3a6984dd4a13affe8cc9935fafc199f08ea3f9afd717b
7
+ data.tar.gz: 61f3907edde2443d5b50f050f01edfec95f258614601aebc3d77e02db8795868a6067b4e17e7ab6318cf7ce9436dd666271e80edcf7812b9bf470261d40b9197
@@ -1,9 +1,12 @@
1
1
  language: ruby
2
- rvm:
3
- - 1.9.3
4
- - 2.0.0
5
- - 2.1.2
6
- env:
7
- - "RAILS_VERSION=3.2.0"
8
- - "RAILS_VERSION=4.0.0"
9
- - "RAILS_VERSION=4.1.0"
2
+
3
+ matrix:
4
+ include:
5
+ - rvm: 1.9.3
6
+ env: "RAILS_VERSION=3.2.0"
7
+ - rvm: 2.0.0
8
+ env: "RAILS_VERSION=4.0.0"
9
+ - rvm: 2.1.2
10
+ env: "RAILS_VERSION=4.1.0"
11
+ - rvm: 2.2.0
12
+ env: "RAILS_VERSION=4.2.0"
@@ -1,5 +1,13 @@
1
1
  # Phrasing Change Log
2
2
 
3
+ ## 3.2.9 (January 7th, 2015)
4
+
5
+ Require only haml, not haml-rails.
6
+
7
+ ## 3.2.8 (January 6th, 2015)
8
+
9
+ Fix confirm dialogs when deleting phrases and phrase versions.
10
+
3
11
  ## 3.2.7 (October 3rd, 2014)
4
12
 
5
13
  Add a config option to set a parent controller to Phrasing Engine Controllers.
data/Gemfile CHANGED
@@ -8,10 +8,9 @@ rails_version = ENV["RAILS_VERSION"] || "4.1.4"
8
8
  gem "rails", "~> #{rails_version}"
9
9
 
10
10
  gem 'factory_girl_rails'
11
- gem 'haml-rails'
12
11
  gem 'sqlite3'
13
12
  gem 'rspec-rails'
14
13
  gem 'capybara', '~> 2.3.0'
15
14
  gem 'jasmine-rails'
16
15
  gem 'pry-rails'
17
- gem 'sass', '3.4.0'
16
+ gem 'sass', '3.4.0'
@@ -0,0 +1,153 @@
1
+ //= require editor
2
+
3
+ var Phrasing = {
4
+ Bus : $({}),
5
+ EDIT_MODE_KEY : 'editing-mode'
6
+ };
7
+
8
+ function StatusBubbleWidget(options){
9
+ this.$statusText = options.$statusText;
10
+ this.$statusIndicator = options.$statusIndicator;
11
+ this.$editModeChechbox = options.$editModeChechbox;
12
+ this._init();
13
+ }
14
+
15
+ StatusBubbleWidget.prototype = {
16
+ _init : function(){
17
+ this.$editModeChechbox.on('change', function(){
18
+ if(this.checked){
19
+ Phrasing.Bus.trigger('phrasing:edit-mode:on');
20
+ }else{
21
+ Phrasing.Bus.trigger('phrasing:edit-mode:off');
22
+ }
23
+ });
24
+ },
25
+
26
+ _alterStatus : function(text, color){
27
+ this.$statusText.text(text);
28
+ this.$statusIndicator.css('background-color', color);
29
+ },
30
+
31
+ saving : function(){
32
+ this._alterStatus('Saving', 'orange');
33
+ },
34
+
35
+ saved : function(){
36
+ this._alterStatus('Saved', '#56AE45');
37
+ },
38
+
39
+ error : function(){
40
+ this._alterStatus('Error', 'red');
41
+ }
42
+ };
43
+
44
+ var phrasing_setup = function(){
45
+ var statusBubbleWidget = new StatusBubbleWidget({
46
+ $statusText : $('#phrasing-edit-mode-bubble #phrasing-saved-status-headline p'),
47
+ $statusIndicator : $('#phrasing-saved-status-indicator-circle'),
48
+ $editModeChechbox : $('#edit-mode-onoffswitch')
49
+ });
50
+
51
+ Phrasing.Bus.on('phrasing:edit-mode:on', function(){
52
+ $('.phrasable').addClass("phrasable-on").attr("contenteditable", 'true');
53
+ localStorage.setItem(Phrasing.EDIT_MODE_KEY, 'true');
54
+ });
55
+
56
+ Phrasing.Bus.on('phrasing:edit-mode:off', function(){
57
+ $('.phrasable').removeClass("phrasable-on").attr("contenteditable", "false");
58
+ localStorage.setItem(Phrasing.EDIT_MODE_KEY, "false");
59
+ });
60
+
61
+ // Initialize the editing bubble
62
+ editor.init();
63
+
64
+ // Making sure to send csrf token from layout file.
65
+ $(document).ajaxSend(function(e, xhr, options) {
66
+ var token = $("meta[name='csrf-token']").attr("content");
67
+ xhr.setRequestHeader("X-CSRF-Token", token);
68
+ });
69
+
70
+ // Hash size function
71
+ Object.size = function(obj){
72
+ var size = 0, key;
73
+ for (key in obj) { if (obj.hasOwnProperty(key)) size++; }
74
+ return size;
75
+ };
76
+
77
+ // Trigger AJAX on textchange
78
+ var userTriggeredPhrasingDOMChange = true;
79
+ var timer = {};
80
+ var timer_status = {};
81
+
82
+ $('.phrasable').on('DOMNodeInserted DOMNodeRemoved DOMCharacterDataModified', function(e){
83
+ if (userTriggeredPhrasingDOMChange === false){
84
+ return;
85
+ }
86
+
87
+ statusBubbleWidget.saving();
88
+
89
+ var record = this;
90
+
91
+ clearTimeout(timer[$(record).data("url")]);
92
+ timer_status[$(record).data("url")] = 0;
93
+
94
+ timer[$(record).data("url")] = setTimeout(function(){
95
+ savePhraseViaAjax(record);
96
+ delete timer_status[$(record).data("url")];
97
+ },2500);
98
+
99
+ timer_status[$(record).data("url")] = 1;
100
+ });
101
+
102
+ // AJAX Request
103
+ function savePhraseViaAjax(record){
104
+
105
+ var url = $(record).data("url");
106
+
107
+ var content = record.innerHTML;
108
+
109
+ if(content.length === 0){
110
+ content = "Empty";
111
+ }
112
+
113
+ $.ajax({
114
+ type: "PUT",
115
+ url: url,
116
+ data: { new_value: content },
117
+ success: function(e){
118
+ userTriggeredPhrasingDOMChange = false;
119
+ if(content === "Empty"){
120
+ $('span.phrasable[data-url="'+ url +'"]').html(content);
121
+ }else{
122
+ // Not to lose the cursor on the current contenteditable element
123
+ $('span.phrasable[data-url="'+ url +'"]').not(record).html(content);
124
+ }
125
+ userTriggeredPhrasingDOMChange = true;
126
+
127
+ if (Object.size(timer_status) === 0){
128
+ statusBubbleWidget.saved();
129
+ }
130
+ },
131
+ error: function(e){
132
+ statusBubbleWidget.error();
133
+ }
134
+ });
135
+ }
136
+
137
+ if(localStorage.getItem(Phrasing.EDIT_MODE_KEY) === undefined){
138
+ localStorage.setItem(Phrasing.EDIT_MODE_KEY, 'true');
139
+ }
140
+
141
+ if(localStorage.getItem(Phrasing.EDIT_MODE_KEY) == 'true'){
142
+ $('#edit-mode-onoffswitch').prop('checked', true).change();
143
+ }else{
144
+ $('#edit-mode-onoffswitch').prop('checked', false).change();
145
+ }
146
+
147
+ };
148
+
149
+ $(document).ready(phrasing_setup);
150
+
151
+ $(document).on('page:before-change', function() {
152
+ Phrasing.Bus.off();
153
+ });
@@ -8,14 +8,14 @@
8
8
  overflow: hidden;
9
9
  }*/
10
10
 
11
- .phrasable_on{
11
+ .phrasable.phrasable-on{
12
12
  border-bottom: 1px dashed black;
13
-
13
+
14
14
  a{
15
15
  pointer-events: none;
16
16
  cursor: default;
17
17
  }
18
-
18
+
19
19
  &:focus{
20
20
  outline: none;
21
21
  }
@@ -172,7 +172,7 @@ span.no-overflow {
172
172
  margin-right: 0px;
173
173
  opacity: 0;
174
174
  }
175
-
175
+
176
176
  input{
177
177
  border-left: 2px solid transparent;
178
178
  padding-right: 5px;
@@ -248,4 +248,4 @@ span.no-overflow {
248
248
 
249
249
  .url {
250
250
  -webkit-font-smoothing: antialiased;
251
- }
251
+ }
@@ -8,8 +8,11 @@ class PhrasingPhrasesController < Phrasing.parent_controller.constantize
8
8
 
9
9
  before_filter :authorize_editor
10
10
 
11
- def import_export; end
12
- def help; end
11
+ def import_export
12
+ end
13
+
14
+ def help
15
+ end
13
16
 
14
17
  def index
15
18
  params[:locale] ||= I18n.default_locale
@@ -22,33 +25,29 @@ class PhrasingPhrasesController < Phrasing.parent_controller.constantize
22
25
  end
23
26
 
24
27
  def update
25
- if request.xhr?
26
- xhr_phrase_update
27
- else
28
- phrase_update
29
- end
28
+ request.xhr? ? xhr_phrase_update : phrase_update
30
29
  end
31
30
 
32
31
  def download
33
32
  app_name = Rails.application.class.to_s.split("::").first
34
33
  app_env = Rails.env
35
- filename = "phrasing_phrases_#{app_name}_#{app_env}_#{Time.now.strftime("%Y_%m_%d_%H_%M_%S")}.yml"
34
+ time = Time.now.strftime('%Y_%m_%d_%H_%M_%S')
35
+ filename = "phrasing_phrases_#{app_name}_#{app_env}_#{time}.yml"
36
36
  send_data Phrasing::Serializer.export_yaml, filename: filename
37
37
  end
38
38
 
39
39
  def upload
40
- number_of_changes = Phrasing::Serializer.import_yaml(params["file"].tempfile)
41
- redirect_to phrasing_phrases_path, notice: "YAML file uploaded successfully! Number of phrases changed: #{number_of_changes}."
42
- rescue => e
43
- logger.info "\n#{e.class}\n#{e.message}"
44
- message = if params[:file].nil?
45
- "Please choose a file."
46
- else
47
- "Please upload a valid YAML file."
48
- end
49
-
50
- flash[:alert] = "There was an error processing your upload! #{message}"
51
- render action: 'import_export', status: 400
40
+ number_of_changes = Phrasing::Serializer.import_yaml(params["file"].tempfile)
41
+ redirect_to phrasing_phrases_path, notice: "YAML file uploaded successfully! Number of phrases changed: #{number_of_changes}."
42
+ rescue => e
43
+ message = if params[:file].nil?
44
+ 'Please choose a file.'
45
+ else
46
+ 'Please upload a valid YAML file.'
47
+ end
48
+
49
+ flash[:alert] = "There was an error processing your upload! #{message}"
50
+ render action: 'import_export', status: 400
52
51
  end
53
52
 
54
53
  def destroy
@@ -59,33 +58,30 @@ class PhrasingPhrasesController < Phrasing.parent_controller.constantize
59
58
 
60
59
  private
61
60
 
62
- def authorize_editor
63
- redirect_to root_path unless can_edit_phrases?
64
- end
61
+ def authorize_editor
62
+ redirect_to root_path unless can_edit_phrases?
63
+ end
65
64
 
66
- def xhr_phrase_update
67
- klass, attribute = params[:klass], params[:attribute]
68
-
69
- if Phrasing.is_whitelisted?(klass, attribute)
70
- class_object = klass.classify.constantize
71
- @object = class_object.where(id: params[:id]).first
72
- @object.send("#{attribute}=",params[:new_value])
73
- @object.save!
74
- render json: @object
75
- else
76
- render status: 403, text: "Attribute not whitelisted!"
77
- end
78
-
79
- rescue ActiveRecord::RecordInvalid => e
80
- render status: 403, text: e
81
- end
65
+ def xhr_phrase_update
66
+ klass, attribute = params[:klass], params[:attribute]
67
+
68
+ return render status: 403, text: 'Phrase not whitelisted' unless Phrasing.whitelisted?(klass, attribute)
82
69
 
83
- def phrase_update
84
- phrase = PhrasingPhrase.find(params[:id])
85
- phrase.value = params[:phrasing_phrase][:value]
86
- phrase.save!
70
+ record = klass.classify.constantize.find(params[:id])
87
71
 
88
- redirect_to phrasing_phrases_path, notice: "#{phrase.key} updated!"
72
+ if record.update(attribute => params[:new_value])
73
+ render json: record
74
+ else
75
+ render status: 403, json: record.error.full_messages
89
76
  end
77
+ end
78
+
79
+ def phrase_update
80
+ phrase = PhrasingPhrase.find(params[:id])
81
+ phrase.value = params[:phrasing_phrase][:value]
82
+ phrase.save!
83
+
84
+ redirect_to phrasing_phrases_path, notice: "#{phrase.key} updated!"
85
+ end
90
86
 
91
87
  end
@@ -1,14 +1,13 @@
1
1
  module InlineHelper
2
- # Normal phrase
3
- # phrase("headline", url: www.infinum.co/yabadaba, inverse: true, scope: "models.errors")
4
-
5
- # Data model phrase
6
- # phrase(record, :title, inverse: true, class: phrase-record-title)
7
2
 
3
+ # Normal phrase
4
+ # phrase("headline", url: www.infinum.co/yabadaba, inverse: true, scope: "models.errors")
5
+ # Data model phrase
6
+ # phrase(record, :title, inverse: true, class: phrase-record-title)
8
7
  def phrase(*args)
9
- if args[0].class == String or args[0].class == Symbol
10
- key, options = args[0].to_s, args[1]
11
- phrasing_phrase(key,options || {})
8
+ if args[0].class.in? [String, Symbol]
9
+ key, options = args[0].to_s, (args[1] || {})
10
+ inline(extract_record(key, options), :value, options)
12
11
  else
13
12
  record, attribute, options = args[0], args[1], args[2]
14
13
  inline(record, attribute, options || {})
@@ -17,33 +16,31 @@ module InlineHelper
17
16
 
18
17
  private
19
18
 
20
- def inline(record, attribute, options={})
21
- return uneditable_phrase(record, attribute) unless can_edit_phrases?
19
+ def inline(record, attribute, options = {})
20
+ return uneditable_phrase(record, attribute) unless can_edit_phrases?
22
21
 
23
- klass = 'phrasable phrasable_on'
24
- klass += ' inverse' if options[:inverse]
25
- klass += options[:class] if options[:class]
22
+ klass = 'phrasable'
23
+ klass += ' inverse' if options[:inverse]
24
+ klass += options[:class] if options[:class]
26
25
 
27
- url = phrasing_polymorphic_url(record, attribute)
26
+ url = phrasing_polymorphic_url(record, attribute)
28
27
 
29
- content_tag(:span, { class: klass, contenteditable: true, spellcheck: false, "data-url" => url }) do
30
- (record.send(attribute) || record.try(:key)).to_s.html_safe
31
- end
28
+ content_tag(:span, class: klass, contenteditable: true, spellcheck: false, 'data-url' => url) do
29
+ (record.send(attribute) || record.try(:key)).to_s.html_safe
32
30
  end
31
+ end
33
32
 
34
- def phrasing_phrase(key, options = {})
35
- key = options[:scope] ? "#{options[:scope]}.#{key}" : key
36
- record = PhrasingPhrase.find_phrase(key)
37
- inline(record, :value, options)
38
- end
33
+ def extract_record(key, options = {})
34
+ key = options[:scope] ? "#{options[:scope]}.#{key}" : key
35
+ PhrasingPhrase.find_phrase(key)
36
+ end
39
37
 
40
- def uneditable_phrase(record, attribute)
41
- record_value = record.send(attribute)
42
- record_value.to_s.html_safe
43
- end
38
+ def uneditable_phrase(record, attribute)
39
+ record.public_send(attribute).to_s.html_safe
40
+ end
44
41
 
45
- def phrasing_polymorphic_url(record, attribute)
46
- phrasing_phrase_path(klass: record.class.to_s, id: record.id, attribute: attribute)
47
- end
42
+ def phrasing_polymorphic_url(record, attribute)
43
+ phrasing_phrase_path(klass: record.class.to_s, id: record.id, attribute: attribute)
44
+ end
48
45
 
49
- end
46
+ end
@@ -1,6 +1,6 @@
1
1
  .edit
2
2
  %h2= @phrasing_phrase.key
3
- = link_to "Delete Phrase", phrasing_phrase_path(@phrasing_phrase), class: "btn btn-danger delete-phrase", method: :delete, onclick: "return confirm('Are you sure?');"
3
+ = link_to "Delete Phrase", phrasing_phrase_path(@phrasing_phrase), class: "btn btn-danger delete-phrase", method: :delete, data: { confirm: 'Are you sure?' }
4
4
  = form_for @phrasing_phrase, url: { action: "update" } do |f|
5
5
  = f.text_area :value, rows: 12
6
6
  = f.submit "Update", class: "btn btn-success submit-edit-phrase"
@@ -20,4 +20,4 @@
20
20
  %td.phrasing-version-value= version.value.html_safe
21
21
  %td.phrasing-version-created_at= version.created_at.strftime("%d-%m-%Y %H:%M:%S")
22
22
  %td= link_to "Revert", phrasing_phrase_path(@phrasing_phrase.id, phrasing_phrase: {value: version.value}), class: "btn btn-success", method: :put
23
- %td= link_to "Delete", phrasing_phrase_version_path(version.id), class: "btn btn-danger", method: :delete, onclick: "return confirm('Are you sure?');"
23
+ %td= link_to "Delete", phrasing_phrase_version_path(version.id), class: "btn btn-danger", method: :delete, data: { confirm: 'Are you sure?' }
@@ -3,7 +3,7 @@ require 'phrasing/serializer'
3
3
  require 'phrasing/rails/engine'
4
4
  require 'jquery-rails'
5
5
  require 'jquery-cookie-rails'
6
- require 'haml-rails'
6
+ require 'haml'
7
7
 
8
8
  module Phrasing
9
9
  mattr_accessor :allow_update_on_all_models_and_attributes
@@ -33,7 +33,7 @@ module Phrasing
33
33
  @@whitelist = whitelist
34
34
  end
35
35
 
36
- def self.is_whitelisted?(klass,attribute)
37
- allow_update_on_all_models_and_attributes == true or whitelist.include? "#{klass}.#{attribute}"
36
+ def self.whitelisted?(klass, attribute)
37
+ allow_update_on_all_models_and_attributes == true || whitelist.include?("#{klass}.#{attribute}")
38
38
  end
39
- end
39
+ end
@@ -1,3 +1,3 @@
1
1
  module Phrasing
2
- VERSION = "4.0.0rc3"
3
- end
2
+ VERSION = "4.0.0rc4"
3
+ end
@@ -18,7 +18,7 @@ Gem::Specification.new do |s|
18
18
 
19
19
  s.add_dependency "rails", ">= 3.2.0"
20
20
  s.add_dependency "railties", ">= 3.2"
21
- s.add_dependency "haml-rails"
21
+ s.add_dependency "haml"
22
22
  s.add_dependency "jquery-rails"
23
23
  s.add_dependency "jquery-cookie-rails"
24
24
  s.add_dependency "sass"
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe PhrasingPhrasesController do
4
+ describe 'GET #new' do
5
+ it 'renders index template' do
6
+ get :index
7
+ expect(response).to render_template(:index)
8
+ end
9
+
10
+ let(:phrase) { FactoryGirl.create(:phrasing_phrase, value: 'old_value') }
11
+
12
+ it 'updates phrase' do
13
+ expect do
14
+ xhr(:put, :update, klass: 'PhrasingPhrase',
15
+ attribute: 'value',
16
+ id: phrase.id,
17
+ new_value: 'new_value')
18
+ end.to change { phrase.reload.value }.from('old_value').to('new_value')
19
+
20
+ expect(response.code).to eq('200')
21
+ end
22
+
23
+ it 'updates phrase' do
24
+ expect do
25
+ xhr(:put, :update, klass: 'PhrasingPhrase',
26
+ attribute: 'locale',
27
+ id: phrase.id,
28
+ new_value: 'de')
29
+ end.to_not change { phrase.reload.locale }
30
+
31
+ expect(response.code).to eq('403')
32
+ end
33
+ end
34
+ end
@@ -6,6 +6,8 @@
6
6
 
7
7
  <div><%= phrase('test', scope: 'models.errors') %></div>
8
8
 
9
+ <div><%= phrase('test', scope: 'models.errors') %></div>
10
+
9
11
  <div><%= phrase 'test', scope: :site %></div>
10
12
 
11
- <div><%= distance_of_time_in_words(Time.now, Time.now) %></div>
13
+ <div><%= distance_of_time_in_words(Time.now, Time.now) %></div>
@@ -2,7 +2,6 @@
2
2
  require 'spec_helper'
3
3
 
4
4
  describe Phrasing::Serializer do
5
-
6
5
  let(:english_phrases) do
7
6
  PhrasingPhrase.where(locale: :en)
8
7
  end
@@ -12,15 +11,14 @@ describe Phrasing::Serializer do
12
11
  end
13
12
 
14
13
  describe 'flatten_the_hash' do
15
-
16
14
  it 'with simple data' do
17
- hash = { "site.intro" => "Hello", "site.outro" => "KthnxBye", "site.overture" => "The Butler"}
15
+ hash = { "site.intro" => "Hello", "site.outro" => "KthnxBye", "site.overture" => "The Butler" }
18
16
  new_hash = Phrasing::Serializer.flatten_the_hash(hash)
19
17
  expect(new_hash).to eq(hash)
20
18
  end
21
19
 
22
20
  it 'with nested data' do
23
- hash = { "site.text" => {"intro" => "Hello", "outro" => "KthnxBye"}}
21
+ hash = { "site.text" => { "intro" => "Hello", "outro" => "KthnxBye" } }
24
22
  new_hash = Phrasing::Serializer.flatten_the_hash(hash)
25
23
 
26
24
  predicted_new_hash = { "site.text.intro" => "Hello", "site.text.outro" => "KthnxBye" }
@@ -28,17 +26,24 @@ describe Phrasing::Serializer do
28
26
  end
29
27
 
30
28
  it 'with deeply nested data' do
31
- hash = { "site" => {"text" => {"intro" => "Hello", "outro" => "KthnxBye", "overture" => {"intro" => "Overture intro", "outro" => "Overture outro"}}}}
29
+ hash = { "site" => { "text" => { "intro" => "Hello",
30
+ "outro" => "KthnxBye",
31
+ "overture" => { "intro" => "Overture intro",
32
+ "outro" => "Overture outro" }
33
+ }
34
+ }
35
+ }
32
36
  new_hash = Phrasing::Serializer.flatten_the_hash(hash)
33
37
 
34
- predicted_new_hash = { "site.text.intro" => "Hello", "site.text.outro" => "KthnxBye", "site.text.overture.intro" => "Overture intro", "site.text.overture.outro" => "Overture outro"}
38
+ predicted_new_hash = { "site.text.intro" => "Hello",
39
+ "site.text.outro" => "KthnxBye",
40
+ "site.text.overture.intro" => "Overture intro",
41
+ "site.text.overture.outro" => "Overture outro" }
35
42
  expect(new_hash).to eq(predicted_new_hash)
36
43
  end
37
-
38
44
  end
39
45
 
40
46
  context 'import_yaml' do
41
-
42
47
  it 'simply formatted phrases' do
43
48
  yaml = <<-YAML
44
49
  en:
@@ -84,7 +89,6 @@ describe Phrasing::Serializer do
84
89
  expect(english_phrases.where(key: "site.text.overture.outro").first.value).to eq("Overture outro")
85
90
  end
86
91
 
87
-
88
92
  it 'overrides old values' do
89
93
  FactoryGirl.create(:phrasing_phrase, key: "site.intro", value: "Go Home")
90
94
  FactoryGirl.create(:phrasing_phrase, key: "site.outro", value: "Kthnx Bye")
@@ -104,10 +108,8 @@ describe Phrasing::Serializer do
104
108
 
105
109
  expect(number_of_changes).to eq(1)
106
110
  end
107
-
108
111
  end
109
112
 
110
-
111
113
  context 'imports and exports' do
112
114
  it 'without changing, should return 0 number of changes' do
113
115
  FactoryGirl.create(:phrasing_phrase, key: "site.intro", value: "Go Home")
@@ -126,7 +128,6 @@ describe Phrasing::Serializer do
126
128
  end
127
129
  end
128
130
 
129
-
130
131
  context 'export_yaml' do
131
132
  it 'flattened phrases' do
132
133
  FactoryGirl.create(:phrasing_phrase, key: "site.intro", value: "Go Home")
@@ -153,13 +154,5 @@ describe Phrasing::Serializer do
153
154
  expect(yaml).to match(/en:\s*\n\s*site.intro:\sHello/)
154
155
  expect(yaml).to match(/fr:\s*\n\s*site.intro:\sBonjour/)
155
156
  end
156
-
157
157
  end
158
-
159
-
160
-
161
158
  end
162
-
163
-
164
-
165
-
@@ -10,4 +10,5 @@ Dir["#{File.dirname(__FILE__)}/factories/**/*.rb"].each { |f| require f }
10
10
  RSpec.configure do |config|
11
11
  config.mock_with :rspec
12
12
  config.use_transactional_fixtures = true
13
+ config.infer_spec_type_from_file_location!
13
14
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: phrasing
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.0.0rc3
4
+ version: 4.0.0rc4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tomislav Car
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-10-17 00:00:00.000000000 Z
12
+ date: 2015-05-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rails
@@ -40,7 +40,7 @@ dependencies:
40
40
  - !ruby/object:Gem::Version
41
41
  version: '3.2'
42
42
  - !ruby/object:Gem::Dependency
43
- name: haml-rails
43
+ name: haml
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - ">="
@@ -118,7 +118,7 @@ files:
118
118
  - app/assets/fonts/icomoon.woff
119
119
  - app/assets/images/phrasing_icon_edit_all.png
120
120
  - app/assets/javascripts/editor.js
121
- - app/assets/javascripts/phrasing.js.erb
121
+ - app/assets/javascripts/phrasing.js
122
122
  - app/assets/javascripts/phrasing_engine.js
123
123
  - app/assets/stylesheets/phrasing.css.scss
124
124
  - app/assets/stylesheets/phrasing_edit_mode_bubble.css.scss
@@ -149,6 +149,7 @@ files:
149
149
  - lib/phrasing/serializer.rb
150
150
  - lib/phrasing/version.rb
151
151
  - phrasing.gemspec
152
+ - spec/controllers/phrasing_phrases_controller.rb
152
153
  - spec/dummy/Rakefile
153
154
  - spec/dummy/app/assets/javascripts/application.js
154
155
  - spec/dummy/app/assets/stylesheets/application.css
@@ -1,127 +0,0 @@
1
- //= require editor
2
-
3
- function StatusBubble(){
4
- var $headline = $('#phrasing-edit-mode-bubble #phrasing-saved-status-headline p');
5
- var $circle = $('#phrasing-saved-status-indicator-circle');
6
-
7
- var alterStatus = function(text, color){
8
- $headline.text(text);
9
- $circle.css('background-color', color);
10
- }
11
-
12
- this.saving = function(){
13
- alterStatus('Saving', 'orange');
14
- }
15
-
16
- this.saved = function(){
17
- alterStatus('Saved', '#56AE45');
18
- }
19
-
20
- this.error = function(){
21
- alterStatus('Error', 'red');
22
- }
23
- }
24
-
25
- var phrasing_setup = function(){
26
- var status = new StatusBubble();
27
-
28
- // Initialize the editing bubble
29
- editor.init();
30
-
31
- // Making sure to send csrf token from layout file.
32
- $(document).ajaxSend(function(e, xhr, options) {
33
- var token = $("meta[name='csrf-token']").attr("content");
34
- xhr.setRequestHeader("X-CSRF-Token", token);
35
- });
36
-
37
- // Hash size function
38
- Object.size = function(obj){
39
- var size = 0, key;
40
- for (key in obj) { if (obj.hasOwnProperty(key)) size++; }
41
- return size;
42
- };
43
-
44
- // Trigger AJAX on textchange
45
- var trigger_binded_events_for_phrasable_class = 1;
46
- var timer = {}
47
- var timer_status = {}
48
-
49
- $('.phrasable').on('DOMNodeInserted DOMNodeRemoved DOMCharacterDataModified', function(e){
50
- status.saving();
51
-
52
- if (trigger_binded_events_for_phrasable_class == 1){
53
-
54
- var record = this;
55
-
56
- clearTimeout(timer[$(record).data("url")]);
57
- timer_status[$(record).data("url")] = 0;
58
-
59
- timer[$(record).data("url")] = setTimeout(function(){
60
- savePhraseViaAjax(record);
61
- delete timer_status[$(record).data("url")]
62
- },2500)
63
- timer_status[$(record).data("url")] = 1;
64
- }
65
-
66
- });
67
-
68
- // AJAX Request
69
- function savePhraseViaAjax(record){
70
-
71
- var url = $(record).data("url");
72
-
73
- var content = record.innerHTML;
74
-
75
- if(content.length == 0){
76
- content = "Empty"
77
- }
78
-
79
- $.ajax({
80
- type: "PUT",
81
- url: url,
82
- data: { new_value: content },
83
- success: function(e){
84
- trigger_binded_events_for_phrasable_class = 0;
85
- if(content === "Empty"){
86
- $('span.phrasable[data-url="'+ url +'"]').html(content)
87
- }else{
88
- // Not to lose the cursor on the current contenteditable element
89
- $('span.phrasable[data-url="'+ url +'"]').not(record).html(content)
90
- }
91
- trigger_binded_events_for_phrasable_class = 1;
92
-
93
- if (Object.size(timer_status) == 0){
94
- status.saved();
95
- }
96
- },
97
- error: function(e){
98
- status.error();
99
- }
100
- });
101
- }
102
-
103
- // Edit Mode On/Off Button
104
- $('#edit-mode-onoffswitch').on('change', function(){
105
- if(this.checked){
106
- $('.phrasable').addClass("phrasable_on").attr("contenteditable", "true");
107
- $.cookie("editing_mode", "true");
108
- }
109
- else{
110
- $('.phrasable').removeClass("phrasable_on").attr("contenteditable", "false");
111
- $.cookie("editing_mode", "false");
112
- }
113
- });
114
-
115
- if($.cookie("editing_mode") === null){
116
- $.cookie("editing_mode", "true");
117
- $('#edit-mode-onoffswitch').prop('checked', true).change();
118
- }
119
- else if($.cookie("editing_mode") == "true"){
120
- $('#edit-mode-onoffswitch').prop('checked', true).change();
121
- }else{
122
- $('#edit-mode-onoffswitch').prop('checked', false).change();
123
- }
124
-
125
- };
126
-
127
- $(document).ready(phrasing_setup)