phrasing 2.1.3 → 3.0.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.
- data/Gemfile.lock +11 -6
- data/README.md +28 -3
- data/app/assets/javascripts/editor.js +1 -9
- data/app/assets/javascripts/phrasing.js.erb +6 -2
- data/app/assets/javascripts/phrasing_engine.js +2 -0
- data/app/assets/stylesheets/phrasing.css.scss +5 -0
- data/app/assets/stylesheets/phrasing_edit_mode_bubble.css.scss +1 -1
- data/app/assets/stylesheets/phrasing_engine.css +583 -292
- data/app/controllers/phrasing_phrase_versions_controller.rb +9 -0
- data/app/controllers/phrasing_phrases_controller.rb +10 -4
- data/app/helpers/inline_helper.rb +23 -9
- data/app/models/phrasing_phrase.rb +24 -63
- data/app/models/phrasing_phrase_version.rb +3 -0
- data/app/views/layouts/phrasing.html.haml +1 -0
- data/app/views/phrasing/_menu.html.haml +3 -3
- data/app/views/phrasing_phrases/edit.html.haml +19 -3
- data/app/views/phrasing_phrases/index.html.haml +13 -10
- data/config/routes.rb +1 -0
- data/db/migrate/20120313191745_create_phrasing_phrases.rb +0 -1
- data/db/migrate/20131010101010_create_phrasing_phrase_versions.rb +9 -0
- data/lib/phrasing.rb +3 -1
- data/lib/phrasing/implementation.rb +5 -1
- data/lib/phrasing/version.rb +1 -1
- data/lib/tasks/phrasing_tasks.rake +26 -13
- data/phrasing.gemspec +5 -2
- metadata +59 -14
- checksums.yaml +0 -7
@@ -0,0 +1,9 @@
|
|
1
|
+
class PhrasingPhraseVersionsController < ActionController::Base
|
2
|
+
|
3
|
+
def destroy
|
4
|
+
@phrasing_phrase_version = PhrasingPhraseVersion.find(params[:id])
|
5
|
+
@phrasing_phrase_version.destroy
|
6
|
+
redirect_to edit_phrasing_phrase_path(@phrasing_phrase_version.phrasing_phrase.id)
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
@@ -16,7 +16,7 @@ class PhrasingPhrasesController < ActionController::Base
|
|
16
16
|
value_like = PhrasingPhrase.arel_table[:value].matches("%#{params[:search]}%")
|
17
17
|
@phrasing_phrases = query.where(key_like.or(value_like)).order(:key)
|
18
18
|
else
|
19
|
-
@phrasing_phrases = query.order(:key)
|
19
|
+
@phrasing_phrases = query.where("value is not null").order(:key) + query.where("value is null").order(:key)
|
20
20
|
end
|
21
21
|
|
22
22
|
@locale_names = PhrasingPhrase.uniq.pluck(:locale)
|
@@ -53,11 +53,17 @@ class PhrasingPhrasesController < ActionController::Base
|
|
53
53
|
end
|
54
54
|
|
55
55
|
def upload
|
56
|
-
PhrasingPhrase.import_yaml(params["file"].tempfile)
|
57
|
-
redirect_to phrasing_phrases_path, notice: "YAML file uploaded successfully!"
|
56
|
+
number_of_changes = PhrasingPhrase.import_yaml(params["file"].tempfile)
|
57
|
+
redirect_to phrasing_phrases_path, notice: "YAML file uploaded successfully! Number of phrases changed: #{number_of_changes}."
|
58
58
|
rescue Exception => e
|
59
59
|
logger.info "\n#{e.class}\n#{e.message}"
|
60
|
-
|
60
|
+
message = if params[:file].nil?
|
61
|
+
"Please choose a file."
|
62
|
+
else
|
63
|
+
"Please upload a valid YAML file."
|
64
|
+
end
|
65
|
+
|
66
|
+
flash[:alert] = "There was an error processing your upload! #{message}"
|
61
67
|
render action: 'import_export', status: 400
|
62
68
|
end
|
63
69
|
|
@@ -1,12 +1,17 @@
|
|
1
1
|
module InlineHelper
|
2
|
+
# Normal phrase
|
3
|
+
# phrase("headline", url: www.infinum.co/yabadaba, inverse: true, interpolation: {min: 15, max: 20})
|
2
4
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
# Data model phrase
|
6
|
+
# phrase(@record, :title, inverse: true, class: phrase-record-title)
|
7
|
+
|
8
|
+
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
12
|
else
|
9
|
-
|
13
|
+
record, field_name, options = args[0], args[1], args[2]
|
14
|
+
inline(record, field_name, options || {})
|
10
15
|
end
|
11
16
|
end
|
12
17
|
|
@@ -16,18 +21,28 @@ module InlineHelper
|
|
16
21
|
klass = 'phrasable'
|
17
22
|
klass += ' phrasable_on' if edit_mode_on?
|
18
23
|
klass += ' inverse' if options[:inverse]
|
24
|
+
klass += options[:class] if options[:class]
|
19
25
|
|
20
26
|
url = phrasing_polymorphic_url(record, field_name)
|
21
27
|
|
22
28
|
content_tag(:span, { class: klass, contenteditable: edit_mode_on?, spellcheck: false, "data-url" => url}) do
|
23
|
-
(record.send(field_name) || record.try(:key)
|
29
|
+
(record.send(field_name) || record.try(:key)).to_s.html_safe
|
24
30
|
end
|
25
|
-
|
26
31
|
end
|
27
32
|
|
28
33
|
alias_method :model_phrase, :inline
|
29
34
|
|
30
35
|
private
|
36
|
+
|
37
|
+
def phrasing_phrase(key, options = {})
|
38
|
+
key = key.to_s
|
39
|
+
if can_edit_phrases?
|
40
|
+
@record = PhrasingPhrase.where(key: key).first || PhrasingPhrase.create_phrase(key)
|
41
|
+
inline(@record, :value, options || {})
|
42
|
+
else
|
43
|
+
options.try(:[], :interpolation) ? t(key, options[:interpolation]).html_safe : t(key).html_safe
|
44
|
+
end
|
45
|
+
end
|
31
46
|
|
32
47
|
def edit_mode_on?
|
33
48
|
if cookies["editing_mode"].nil?
|
@@ -38,7 +53,6 @@ module InlineHelper
|
|
38
53
|
end
|
39
54
|
end
|
40
55
|
|
41
|
-
|
42
56
|
def phrasing_polymorphic_url(record, attribute)
|
43
57
|
resource = Phrasing.route
|
44
58
|
"#{root_url}#{resource}/remote_update_phrase?klass=#{record.class.to_s}&id=#{record.id}&attribute=#{attribute}"
|
@@ -1,20 +1,18 @@
|
|
1
1
|
class PhrasingPhrase < ActiveRecord::Base
|
2
2
|
|
3
|
-
unless ENV['PHRASING_DEBUG']
|
4
|
-
self.logger = Logger.new('/dev/null')
|
5
|
-
end
|
6
|
-
|
7
3
|
validates_presence_of :key, :locale
|
8
4
|
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
validate :uniqueness_of_key_on_locale_scope, on: :create
|
6
|
+
|
7
|
+
has_many :versions, dependent: :destroy, class_name: "PhrasingPhraseVersion"
|
8
|
+
|
9
|
+
after_update :version_it
|
12
10
|
|
13
11
|
def self.create_phrase(key)
|
14
12
|
phrasing_phrase = PhrasingPhrase.new
|
15
|
-
phrasing_phrase.key = key.to_s
|
16
|
-
phrasing_phrase.value = key.to_s.humanize
|
17
13
|
phrasing_phrase.locale = I18n.locale
|
14
|
+
phrasing_phrase.key = key.to_s
|
15
|
+
phrasing_phrase.value = key.to_s
|
18
16
|
phrasing_phrase.save!
|
19
17
|
phrasing_phrase
|
20
18
|
end
|
@@ -22,80 +20,43 @@ class PhrasingPhrase < ActiveRecord::Base
|
|
22
20
|
module Serialize
|
23
21
|
|
24
22
|
def import_yaml(yaml)
|
23
|
+
number_of_changes = 0
|
25
24
|
hash = YAML.load(yaml)
|
26
25
|
hash.each do |locale, data|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
# {"foo"=>{"a"=>"1", "b"=>"2"}} ----> {"foo.a"=>1, "foo.b"=>2}
|
37
|
-
def hash_flatten(hash)
|
38
|
-
result = {}
|
39
|
-
hash.each do |key, value|
|
40
|
-
if value.is_a? Hash
|
41
|
-
hash_flatten(value).each { |k,v| result["#{key}.#{k}"] = v }
|
42
|
-
else
|
43
|
-
result[key] = value
|
26
|
+
data.each do |key, value|
|
27
|
+
phrase = where(key: key, locale: locale).first || new(key: key, locale: locale)
|
28
|
+
if phrase.value != value
|
29
|
+
phrase.value = value
|
30
|
+
number_of_changes += 1
|
31
|
+
phrase.save
|
32
|
+
end
|
44
33
|
end
|
45
34
|
end
|
46
|
-
|
35
|
+
number_of_changes
|
47
36
|
end
|
48
37
|
|
49
38
|
def export_yaml
|
50
39
|
hash = {}
|
51
|
-
where("value is not null").each do |
|
52
|
-
|
40
|
+
where("value is not null").each do |phrase|
|
41
|
+
hash[phrase.locale] ||= {}
|
42
|
+
hash[phrase.locale][phrase.key] = phrase.value
|
53
43
|
end
|
54
44
|
hash.to_yaml
|
55
45
|
end
|
56
46
|
|
57
|
-
# ({"a"=>{"b"=>{"e"=>"f"}}}, ["a","b","c"], "d") ----> {"a"=>{"b"=>{"c"=>"d", "e"=>"f"}}}
|
58
|
-
def hash_fatten!(hash, keys, value)
|
59
|
-
if keys.length == 1
|
60
|
-
hash[keys.first] = value
|
61
|
-
else
|
62
|
-
head = keys.first
|
63
|
-
rest = keys[1..-1]
|
64
|
-
hash[head] ||= {}
|
65
|
-
hash_fatten!(hash[head], rest, value)
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
47
|
end
|
70
48
|
|
71
49
|
extend Serialize
|
72
50
|
|
73
51
|
private
|
74
52
|
|
75
|
-
def
|
76
|
-
|
77
|
-
check_ambiguity_on_successors
|
78
|
-
end
|
79
|
-
|
80
|
-
def check_ambiguity_on_ancestors
|
81
|
-
stripped_key = key
|
82
|
-
while stripped_key.include?('.')
|
83
|
-
stripped_key = stripped_key.split('.')[0..-2].join('.')
|
84
|
-
if PhrasingPhrase.where(key: stripped_key).count > 0
|
85
|
-
errors.add(:key, "can't be named '#{key}', there already exists a key named '#{stripped_key}'. Ambiguous calling!")
|
86
|
-
end
|
87
|
-
end
|
53
|
+
def uniqueness_of_key_on_locale_scope
|
54
|
+
errors.add(:key, "Duplicate entry #{key} for locale #{locale}") unless PhrasingPhrase.where(key: key).where(locale: locale).empty?
|
88
55
|
end
|
89
56
|
|
90
|
-
def
|
91
|
-
|
92
|
-
|
93
|
-
errors.add(:key, "can't be named '#{key}', there already exists one or multiple keys beginning with '#{key_successor}'. Ambiguous calling!")
|
57
|
+
def version_it
|
58
|
+
if value_was != value
|
59
|
+
PhrasingPhraseVersion.create(phrasing_phrase_id: id,value: value)
|
94
60
|
end
|
95
61
|
end
|
96
|
-
|
97
|
-
def key_muts_not_end_with_a_dot
|
98
|
-
errors.add(:key, "mustn't end with a dot") if key[-1] == "."
|
99
|
-
end
|
100
|
-
|
101
62
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
#header
|
2
2
|
%h1= link_to "Phrasing", phrasing_phrases_path
|
3
3
|
%ul
|
4
|
-
- if root_path
|
5
|
-
%li= link_to "Home page", root_path
|
6
4
|
%li= link_to "Phrases", phrasing_phrases_path
|
7
5
|
%li= link_to "Import / Export", import_export_phrasing_phrases_path
|
8
|
-
%li= link_to "Help", help_phrasing_phrases_path
|
6
|
+
%li= link_to "Help", help_phrasing_phrases_path
|
7
|
+
- if root_path
|
8
|
+
%li= link_to "Home page", root_path
|
@@ -1,7 +1,23 @@
|
|
1
1
|
.edit
|
2
2
|
%h2= @phrasing_phrase.key
|
3
|
-
=
|
3
|
+
= link_to "Delete Phrase", phrasing_phrase_path(@phrasing_phrase), class: "btn btn-danger delete-phrase", method: :delete, onclick: "return confirm('Are you sure?');"
|
4
4
|
= form_for @phrasing_phrase, :url => { :action => "update" } do |f|
|
5
5
|
= f.text_area :value, :rows => 12
|
6
|
-
= f.submit "Update"
|
7
|
-
|
6
|
+
= f.submit "Update", class: "btn btn-success submit-edit-phrase"
|
7
|
+
%br
|
8
|
+
- unless @phrasing_phrase.versions.empty?
|
9
|
+
%br
|
10
|
+
%h2 Previous Versions
|
11
|
+
%br
|
12
|
+
%table.phrase-versions
|
13
|
+
%tr
|
14
|
+
%th Value
|
15
|
+
%th Created_at
|
16
|
+
%th
|
17
|
+
%th
|
18
|
+
- @phrasing_phrase.versions.reverse.each do |version|
|
19
|
+
%tr
|
20
|
+
%td.phrasing-version-value= version.value.html_safe
|
21
|
+
%td.phrasing-version-created_at= version.created_at.strftime("%d-%m-%Y %H:%M:%S")
|
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?');"
|
@@ -3,15 +3,18 @@
|
|
3
3
|
- locale_options = options_for_select([nil] + @locale_names.map{|l| [l,l]}, params[:locale])
|
4
4
|
= select_tag 'locale', locale_options
|
5
5
|
= text_field_tag :search, params[:search], :placeholder => 'Search for keys or values', :size => 40
|
6
|
-
= submit_tag 'Search'
|
6
|
+
= submit_tag 'Search', class: "btn btn-success"
|
7
7
|
- if @phrasing_phrases.any?
|
8
|
-
%table
|
9
|
-
%
|
10
|
-
%th Key
|
11
|
-
%th Value
|
12
|
-
- @phrasing_phrases.each do |t|
|
8
|
+
%table.all-phrases
|
9
|
+
%thead
|
13
10
|
%tr
|
14
|
-
%
|
15
|
-
|
16
|
-
|
17
|
-
|
11
|
+
%th Key
|
12
|
+
%th Value
|
13
|
+
%tbody
|
14
|
+
- @phrasing_phrases.each do |t|
|
15
|
+
%tr{onclick: "document.location = '/#{Phrasing.route}/#{t.id}/edit'"}
|
16
|
+
%td.key
|
17
|
+
= link_to edit_phrasing_phrase_path(t) do
|
18
|
+
= t.key
|
19
|
+
%td.value
|
20
|
+
= t.value.try(:html_safe)
|
data/config/routes.rb
CHANGED
data/lib/phrasing.rb
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
require 'phrasing'
|
2
2
|
require "phrasing/implementation"
|
3
3
|
require "phrasing/simple"
|
4
|
+
require 'jquery-rails'
|
5
|
+
require 'jquery-cookie-rails'
|
4
6
|
|
5
7
|
module Phrasing
|
6
8
|
module Rails
|
@@ -8,7 +10,7 @@ module Phrasing
|
|
8
10
|
initializer :assets, :group => :all do
|
9
11
|
::Rails.application.config.assets.paths << ::Rails.root.join('app', 'assets', 'fonts')
|
10
12
|
::Rails.application.config.assets.paths << ::Rails.root.join('app', 'assets', 'images')
|
11
|
-
::Rails.application.config.assets.precompile += ['editor.js', 'phrasing_engine.css', 'icomoon.dev.svg', 'icomoon.svg', 'icomoon.eot', 'icomoon.ttf', 'icomoon.woff', 'phrasing_information_icon.png']
|
13
|
+
::Rails.application.config.assets.precompile += ['editor.js', 'phrasing_engine.css', 'phrasing_engine.js', 'icomoon.dev.svg', 'icomoon.svg', 'icomoon.eot', 'icomoon.ttf', 'icomoon.woff', 'phrasing_information_icon.png']
|
12
14
|
end
|
13
15
|
end
|
14
16
|
end
|
@@ -11,7 +11,11 @@ module Phrasing
|
|
11
11
|
|
12
12
|
value = super(locale, key, scope, options)
|
13
13
|
if value.is_a?(String) || value.nil?
|
14
|
-
PhrasingPhrase.
|
14
|
+
phrasing_phrase = PhrasingPhrase.new
|
15
|
+
phrasing_phrase.locale = locale.to_s
|
16
|
+
phrasing_phrase.key = scoped_key
|
17
|
+
phrasing_phrase.value = value
|
18
|
+
phrasing_phrase.save
|
15
19
|
end
|
16
20
|
value
|
17
21
|
end
|
data/lib/phrasing/version.rb
CHANGED
@@ -3,14 +3,17 @@ namespace :phrasing do
|
|
3
3
|
task :install do
|
4
4
|
Rake::Task["phrasing_rails_engine:install:migrations"].invoke
|
5
5
|
Rake::Task["phrasing:install_initializer"].invoke
|
6
|
-
Rake::Task["phrasing:
|
6
|
+
Rake::Task["phrasing:install_phrasing_helper"].invoke
|
7
7
|
end
|
8
8
|
|
9
9
|
desc "Create the initializer file"
|
10
10
|
task :install_initializer do
|
11
11
|
filepath = Rails.root.join *%w(config initializers phrasing.rb)
|
12
|
-
File.
|
13
|
-
|
12
|
+
if File.exists?(filepath)
|
13
|
+
alert "Phrasing config file already exists.\n"
|
14
|
+
else
|
15
|
+
File.open(filepath, 'w') do |f|
|
16
|
+
f << <<-CONFIG
|
14
17
|
Phrasing.setup do |config|
|
15
18
|
config.route = 'phrasing'
|
16
19
|
end
|
@@ -20,17 +23,21 @@ end
|
|
20
23
|
Phrasing.whitelist = []
|
21
24
|
# Phrasing.allow_update_on_all_models_and_attributes = true;
|
22
25
|
CONFIG
|
26
|
+
end
|
27
|
+
notice("created")
|
28
|
+
puts " config/intiializers/phrasing.rb"
|
23
29
|
end
|
24
|
-
greenify("You can change the default route and whitelist editable attributes in the phrasing initializer created in the config/intiializers folder.")
|
25
30
|
end
|
26
31
|
|
27
32
|
|
28
33
|
desc "Create the PhrasingHelper file"
|
29
|
-
task :
|
34
|
+
task :install_phrasing_helper do
|
30
35
|
filepath = Rails.root.join *%w(app helpers phrasing_helper.rb)
|
31
|
-
|
32
|
-
|
33
|
-
|
36
|
+
if File.exists?(filepath)
|
37
|
+
alert "Phrasing helper file already exists.\n"
|
38
|
+
else
|
39
|
+
File.open(filepath, 'w') do |f|
|
40
|
+
f << <<-MODULE
|
34
41
|
module PhrasingHelper
|
35
42
|
# You must implement the can_edit_phrases? method.
|
36
43
|
# Example:
|
@@ -44,14 +51,20 @@ module PhrasingHelper
|
|
44
51
|
end
|
45
52
|
end
|
46
53
|
MODULE
|
47
|
-
|
48
|
-
|
49
|
-
|
54
|
+
end
|
55
|
+
notice("created")
|
56
|
+
puts " app/helpers/phrasing_helper.rb"
|
57
|
+
notice "Now run 'rake db:migrate'.\n"
|
58
|
+
end
|
50
59
|
end
|
51
60
|
|
52
61
|
|
53
62
|
end
|
54
63
|
|
55
|
-
def
|
56
|
-
|
64
|
+
def notice(text)
|
65
|
+
print "\033[#{32}m#{text}\033[0m"
|
66
|
+
end
|
67
|
+
|
68
|
+
def alert(text)
|
69
|
+
print "\033[#{31}m#{text}\033[0m"
|
57
70
|
end
|