Compare commits

...
3 Commits
4 changed files with 86 additions and 23 deletions

No files matched your search

+26 -9
View File
@@ -8,7 +8,6 @@
#
#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# This controller class will handle map management
class CustomersController < ApplicationController
include AuthHelper
@@ -26,8 +25,8 @@ class CustomersController < ApplicationController
include SortHelper
helper :timelog
before_action :add_customer, only: :new
before_action :view_customer, except: [:new, :view]
before_action :add_customer, only: [:new, :create]
before_action :view_customer, except: [:new, :create, :view]
skip_before_action :verify_authenticity_token, :check_if_login_required, only: [:view]
def address_to_s(address)
@@ -75,14 +74,28 @@ class CustomersController < ApplicationController
def create
@customer = Customer.new(allowed_params)
@customer.save
log "Customer ##{@customer.id} created successfully."
flash[:notice] = t :notice_customer_created
redirect_to @customer
respond_to do |format|
if @customer.save
log "Customer ##{@customer.id} created successfully."
format.html { redirect_to @customer, notice: l(:notice_successful_create) }
format.json { render json: { id: @customer.id, name: @customer.name }, status: :created }
else
format.html { render :new }
format.json { render json: { errors: @customer.errors.full_messages }, status: :unprocessable_entity }
end
end
rescue => e
log "Failed to create customer: #{e.message}"
flash[:error] = e.message
redirect_to new_customer_path
respond_to do |format|
format.html {
flash[:error] = e.message
redirect_to new_customer_path
}
format.json {
render json: { errors: [e.message] }, status: :internal_server_error
}
end
end
def edit
@@ -136,6 +149,10 @@ class CustomersController < ApplicationController
def new
@customer = Customer.new
if request.xhr?
render partial: 'form', layout: false, locals: { hide_submit: true, hide_toolbar: true }
end
end
def only_one_non_zero?(array)
+17 -13
View File
@@ -32,23 +32,27 @@
</div>
</div>
<div class="clearfix">
<%=t(:field_notes)%>:
<div class="clearfix">
<%= t(:field_notes) %>:
<div class="input">
<p>
<%= f.text_area :notes,
rows: 8,
class: 'wiki-edit',
style: 'width: 95%;',
id: 'customer_appointment_description' %>
<%= wikitoolbar_for 'customer_appointment_description' %>
</p>
<p>
<%= f.text_area :notes,
rows: 8,
class: 'wiki-edit',
style: 'width: 95%;',
id: 'customer_notes' %>
<% unless local_assigns[:hide_toolbar] %>
<%= wikitoolbar_for 'customer_notes' %>
<% end %>
</p>
</div>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% unless local_assigns[:hide_submit] %>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
<% end %>
</fieldset>
+1 -1
View File
@@ -14,7 +14,7 @@ Redmine::Plugin.register :redmine_qbo do
name 'Redmine QBO plugin'
author 'Rick Barrette'
description 'A pluging for Redmine to connect with QuickBooks Online to create Time Activity Entries for billable hours logged when an Issue is closed'
version '2026.8.1'
version '2026.8.2'
url 'https://github.com/rickbarrette/redmine_qbo'
author_url 'https://barrettefabrication.com'
settings default: {empty: true}, partial: 'qbo/settings'
+42
View File
@@ -176,6 +176,10 @@ module RedmineQbo
edit_section_links: false,
headings: false,
inline_attachments: false)
# Apply the fix here
text = sanitize_html_for_pdf(text)
pdf.RDMwriteFormattedCell(190, 5, '', '', text, issue.attachments, "LRB")
end
@@ -275,6 +279,10 @@ module RedmineQbo
pdf.ln unless journal.details.empty?
pdf.SetFontStyle('', 8)
text = textilizable(journal, :notes, only_path: false, edit_section_links: false, headings: false, inline_attachments: false)
# Apply the fix here
text = sanitize_html_for_pdf(text)
pdf.RDMwriteFormattedCell(190, 5, '', '', text, issue.attachments, "")
end
pdf.ln
@@ -309,6 +317,40 @@ module RedmineQbo
end
end
private
# NEW HELPER: Aggressively cleans up HTML so RBPDF doesn't crash on tables
def sanitize_html_for_pdf(text)
clean_text = text.to_s.dup
# 1. RBPDF layout engine hates div wrappers. Strip all opening and closing divs.
clean_text.gsub!(/<\/?div[^>]*>/i, '')
# 2. Rebuild tables into a completely flat, pure HTML structure that TCPDF supports
clean_text.gsub!(/<table[^>]*>.*?<\/table>/mi) do |match|
table_html = match.dup
# Strip thead and tbody tags completely
table_html.gsub!(/<\/?thead[^>]*>/i, '')
table_html.gsub!(/<\/?tbody[^>]*>/i, '')
# TCPDF cell width calculations crash on <th> tags. Convert them to <td> + bold.
table_html.gsub!(/<th([^>]*)>/i, '<td\1><strong>')
table_html.gsub!(/<\/th>/i, '</strong></td>')
# Remove all newlines and spaces between tags to prevent stray text nodes crashing the parser
table_html.gsub!(/>\s+</m, '><')
table_html.gsub!(/\r?\n/, '')
# Inject a standardized <table> tag with borders so the table actually renders visibly
table_html.sub!(/<table[^>]*>/i, '<table border="1" cellpadding="4" style="border-collapse: collapse;">')
table_html
end
clean_text
end
end
end
end