diff options
Diffstat (limited to 'app/models/concerns')
| -rw-r--r-- | app/models/concerns/file_attachment.rb | 12 | ||||
| -rw-r--r-- | app/models/concerns/nested_tree.rb | 8 | ||||
| -rw-r--r-- | app/models/concerns/rrule_humanizer.rb | 49 |
3 files changed, 51 insertions, 18 deletions
diff --git a/app/models/concerns/file_attachment.rb b/app/models/concerns/file_attachment.rb index 0e99fa2..3c09456 100644 --- a/app/models/concerns/file_attachment.rb +++ b/app/models/concerns/file_attachment.rb | |||
| @@ -23,9 +23,10 @@ module FileAttachment | |||
| 23 | extend ActiveSupport::Concern | 23 | extend ActiveSupport::Concern |
| 24 | 24 | ||
| 25 | STYLES = { | 25 | STYLES = { |
| 26 | medium: { geometry: "300x300>", format: nil }, | 26 | medium: { args: ["-resize", "300x300>"] }, |
| 27 | thumb: { geometry: "100x100>", format: nil }, | 27 | thumb: { args: ["-resize", "100x100>"] }, |
| 28 | headline: { geometry: "460x250!", format: nil } | 28 | headline: { args: ["-resize", "460x250^", "-gravity", "center", "-extent", "460x250"] }, |
| 29 | large: { args: ["-resize", "1600x1600>"] } | ||
| 29 | }.freeze | 30 | }.freeze |
| 30 | 31 | ||
| 31 | IMAGE_CONTENT_TYPES = %w[image/jpeg image/gif image/png image/webp].freeze | 32 | IMAGE_CONTENT_TYPES = %w[image/jpeg image/gif image/png image/webp].freeze |
| @@ -80,7 +81,7 @@ module FileAttachment | |||
| 80 | STYLES.each do |style, options| | 81 | STYLES.each do |style, options| |
| 81 | dest_path = file_path(style) | 82 | dest_path = file_path(style) |
| 82 | FileUtils.mkdir_p(File.dirname(dest_path)) | 83 | FileUtils.mkdir_p(File.dirname(dest_path)) |
| 83 | system("magick", original_path, "-resize", options[:geometry], dest_path) | 84 | system("magick", original_path, *options[:args], dest_path) |
| 84 | end | 85 | end |
| 85 | end | 86 | end |
| 86 | 87 | ||
| @@ -105,7 +106,8 @@ module FileAttachment | |||
| 105 | end | 106 | end |
| 106 | 107 | ||
| 107 | def sanitize_filename(filename) | 108 | def sanitize_filename(filename) |
| 108 | File.basename(filename).gsub(/[^\w\.\-]/, '_') | 109 | name = File.basename(filename).unicode_normalize(:nfc) |
| 110 | name.gsub(/(?u)[^\w\.\-]/, '_') | ||
| 109 | end | 111 | end |
| 110 | 112 | ||
| 111 | # Proxy object returned by asset.upload, providing the Paperclip-compatible | 113 | # Proxy object returned by asset.upload, providing the Paperclip-compatible |
diff --git a/app/models/concerns/nested_tree.rb b/app/models/concerns/nested_tree.rb index 9a2eb0e..befcdb3 100644 --- a/app/models/concerns/nested_tree.rb +++ b/app/models/concerns/nested_tree.rb | |||
| @@ -9,8 +9,6 @@ module NestedTree | |||
| 9 | included do | 9 | included do |
| 10 | belongs_to :parent, class_name: name, foreign_key: :parent_id, optional: true, inverse_of: :children | 10 | belongs_to :parent, class_name: name, foreign_key: :parent_id, optional: true, inverse_of: :children |
| 11 | has_many :children, -> { order(:id) }, class_name: name, foreign_key: :parent_id, inverse_of: :parent | 11 | has_many :children, -> { order(:id) }, class_name: name, foreign_key: :parent_id, inverse_of: :parent |
| 12 | |||
| 13 | before_destroy :delete_descendants | ||
| 14 | end | 12 | end |
| 15 | 13 | ||
| 16 | class_methods do | 14 | class_methods do |
| @@ -77,10 +75,4 @@ module NestedTree | |||
| 77 | def move_to_child_of(new_parent) | 75 | def move_to_child_of(new_parent) |
| 78 | update!(parent_id: new_parent.id) | 76 | update!(parent_id: new_parent.id) |
| 79 | end | 77 | end |
| 80 | |||
| 81 | private | ||
| 82 | |||
| 83 | def delete_descendants | ||
| 84 | self.class.where(id: descendants.pluck(:id)).delete_all | ||
| 85 | end | ||
| 86 | end | 78 | end |
diff --git a/app/models/concerns/rrule_humanizer.rb b/app/models/concerns/rrule_humanizer.rb index 8231de8..07141c1 100644 --- a/app/models/concerns/rrule_humanizer.rb +++ b/app/models/concerns/rrule_humanizer.rb | |||
| @@ -15,8 +15,8 @@ module RruleHumanizer | |||
| 15 | }.freeze | 15 | }.freeze |
| 16 | 16 | ||
| 17 | ORDINAL_NAMES = { | 17 | ORDINAL_NAMES = { |
| 18 | de: { 1=>"ersten", 2=>"zweiten", 3=>"dritten", 4=>"vierten", -1=>"letzten", -2=>"vorletzten" }, | 18 | de: { 1=>"ersten", 2=>"zweiten", 3=>"dritten", 4=>"vierten", 5=>"fünften", -1=>"letzten", -2=>"vorletzten" }, |
| 19 | en: { 1=>"first", 2=>"second", 3=>"third", 4=>"fourth", -1=>"last", -2=>"second-to-last" } | 19 | en: { 1=>"first", 2=>"second", 3=>"third", 4=>"fourth", 5=>"fifth", -1=>"last", -2=>"second-to-last" } |
| 20 | }.freeze | 20 | }.freeze |
| 21 | 21 | ||
| 22 | MONTH_NAMES = { | 22 | MONTH_NAMES = { |
| @@ -35,7 +35,8 @@ module RruleHumanizer | |||
| 35 | ordinals = ORDINAL_NAMES[loc] || ORDINAL_NAMES[:en] | 35 | ordinals = ORDINAL_NAMES[loc] || ORDINAL_NAMES[:en] |
| 36 | months = MONTH_NAMES[loc] || MONTH_NAMES[:en] | 36 | months = MONTH_NAMES[loc] || MONTH_NAMES[:en] |
| 37 | 37 | ||
| 38 | days = byday&.split(",")&.map do |d| | 38 | byday_values = byday&.split(",") |
| 39 | days = byday_values&.map do |d| | ||
| 39 | if d =~ /^(-?\d+)([A-Z]{2})$/ | 40 | if d =~ /^(-?\d+)([A-Z]{2})$/ |
| 40 | "#{ordinals[$1.to_i]} #{weekdays[$2]}" | 41 | "#{ordinals[$1.to_i]} #{weekdays[$2]}" |
| 41 | else | 42 | else |
| @@ -43,6 +44,32 @@ module RruleHumanizer | |||
| 43 | end | 44 | end |
| 44 | end | 45 | end |
| 45 | 46 | ||
| 47 | excluded_monthly_ordinal = nil | ||
| 48 | excluded_monthly_weekday = nil | ||
| 49 | selected_monthly_ordinals = nil | ||
| 50 | selected_monthly_weekday = nil | ||
| 51 | if freq == "MONTHLY" && byday_values.present? | ||
| 52 | ordinal_days = byday_values.map { |d| d.match(/^([1-5])([A-Z]{2})$/) } | ||
| 53 | if ordinal_days.all? | ||
| 54 | positions = ordinal_days.map { |match| match[1].to_i }.uniq.sort | ||
| 55 | weekdays_in_rule = ordinal_days.map { |match| match[2] }.uniq | ||
| 56 | if weekdays_in_rule.size == 1 | ||
| 57 | selected_monthly_ordinals = positions | ||
| 58 | selected_monthly_weekday = weekdays_in_rule.first | ||
| 59 | missing_positions = (1..5).to_a - positions | ||
| 60 | if positions.size == 4 && missing_positions.size == 1 | ||
| 61 | excluded_monthly_ordinal = missing_positions.first | ||
| 62 | excluded_monthly_weekday = selected_monthly_weekday | ||
| 63 | end | ||
| 64 | end | ||
| 65 | end | ||
| 66 | end | ||
| 67 | |||
| 68 | join_ordinals = lambda do |ordinal_values, conjunction| | ||
| 69 | names = ordinal_values.map { |ordinal| ordinals[ordinal] } | ||
| 70 | names.size > 1 ? "#{names[0..-2].join(', ')} #{conjunction} #{names.last}" : names.first | ||
| 71 | end | ||
| 72 | |||
| 46 | base = | 73 | base = |
| 47 | case loc | 74 | case loc |
| 48 | when :de | 75 | when :de |
| @@ -59,14 +86,26 @@ module RruleHumanizer | |||
| 59 | interval == 2 ? "Alle zwei Wochen" : "Wöchentlich" | 86 | interval == 2 ? "Alle zwei Wochen" : "Wöchentlich" |
| 60 | end | 87 | end |
| 61 | when "MONTHLY" | 88 | when "MONTHLY" |
| 62 | days ? "Jeden #{days.join(' und ')} im Monat" : "Monatlich" | 89 | if excluded_monthly_ordinal |
| 90 | "Jeden #{weekdays[excluded_monthly_weekday]} im Monat, außer dem #{ordinals[excluded_monthly_ordinal]} #{weekdays[excluded_monthly_weekday]}" | ||
| 91 | elsif selected_monthly_ordinals | ||
| 92 | "Jeden #{join_ordinals.call(selected_monthly_ordinals, 'und')} #{weekdays[selected_monthly_weekday]} im Monat" | ||
| 93 | else | ||
| 94 | days ? "Jeden #{days.join(' und ')} im Monat" : "Monatlich" | ||
| 95 | end | ||
| 63 | end | 96 | end |
| 64 | else | 97 | else |
| 65 | case freq | 98 | case freq |
| 66 | when "WEEKLY" | 99 | when "WEEKLY" |
| 67 | days ? "#{interval == 2 ? 'Every other' : 'Every'} #{days.join(' and ')}" : (interval == 2 ? "Every other week" : "Weekly") | 100 | days ? "#{interval == 2 ? 'Every other' : 'Every'} #{days.join(' and ')}" : (interval == 2 ? "Every other week" : "Weekly") |
| 68 | when "MONTHLY" | 101 | when "MONTHLY" |
| 69 | days ? "Every #{days.join(' and ')} of the month" : "Monthly" | 102 | if excluded_monthly_ordinal |
| 103 | "Every #{weekdays[excluded_monthly_weekday]} of the month, except the #{ordinals[excluded_monthly_ordinal]} #{weekdays[excluded_monthly_weekday]}" | ||
| 104 | elsif selected_monthly_ordinals | ||
| 105 | "Every #{join_ordinals.call(selected_monthly_ordinals, 'and')} #{weekdays[selected_monthly_weekday]} of the month" | ||
| 106 | else | ||
| 107 | days ? "Every #{days.join(' and ')} of the month" : "Monthly" | ||
| 108 | end | ||
| 70 | end | 109 | end |
| 71 | end | 110 | end |
| 72 | return nil unless base | 111 | return nil unless base |
