Compare commits

..

14 Commits

Author SHA1 Message Date
ricky a6751d3f41 simplified appointment link javascript 2026-02-09 21:43:29 -05:00
ricky 8944e92ffc Use html data attributes 2026-02-09 20:52:27 -05:00
ricky f0c0a42c96 2026.2.4 2026-02-09 20:04:47 -05:00
ricky a4b51457bb moved controller_issues_new_before_save nito issues_hook_listener 2026-02-09 20:04:16 -05:00
ricky fb4a883b43 Added logging 2026-02-09 14:31:56 -05:00
ricky c24ec93335 force a tracker if still nil 2026-02-09 14:21:50 -05:00
ricky df49964bf9 added tracker nil check 2026-02-09 14:19:31 -05:00
ricky 502ba94465 Readded missing controller_issues_new_before_save 2026-02-09 14:12:01 -05:00
ricky ff038fe5ae removed method: :get from estimate link 2026-02-09 10:41:48 -05:00
ricky 3eed122598 fixed typo 2026-02-09 10:38:10 -05:00
ricky d8d34540a9 use link_to, as button_to doesn't allow for openign links in a new tab 2026-02-09 10:35:12 -05:00
ricky c01cc5ca97 2026.2.3 2026-02-09 09:36:50 -05:00
ricky 6a2f7a1146 initialize string link 2026-02-09 09:21:42 -05:00
ricky f4c844f097 2026.2.2 2026-02-08 19:59:28 -05:00
8 changed files with 31 additions and 31 deletions
+1 -1
View File
@@ -3,7 +3,7 @@
<br/> <br/>
<br/> <br/>
<%= button_to t(:label_create_estimate), "https://qbo.intuit.com/app/estimate?nameId=#{@customer.id}", target: :_blank, method: :get %> <%= link_to t(:label_create_estimate), "https://qbo.intuit.com/app/estimate?nameId=#{@customer.id}", target: :_blank %>
<br/> <br/>
<br/> <br/>
+1 -1
View File
@@ -2,7 +2,7 @@
<% estimates.sort.reverse.each do |estimate| %> <% estimates.sort.reverse.each do |estimate| %>
<div class="row"> <div class="row">
<%= check_box_tag "estimate_ids[]", estimate.id, false, onchange: "updateLink()", class: "estimate-checkbox" %> <%= check_box_tag "estimate_ids[]", estimate.id, false, onchange: "updateLink()", data: { url: estimate_path(estimate), text: "Estimate ##{estimate.to_s}" }, class: "estimate-checkbox appointment" %>
<b><%= link_to "##{estimate.doc_number}", estimate_path(estimate), target: :_blank %></b> <%= estimate.txn_date %> <b><%= link_to "##{estimate.doc_number}", estimate_path(estimate), target: :_blank %></b> <%= estimate.txn_date %>
</div> </div>
<% end %> <% end %>
+1 -1
View File
@@ -12,7 +12,7 @@
<% invoices.sort.reverse.each do |invoice| %> <% invoices.sort.reverse.each do |invoice| %>
<div class="row"> <div class="row">
<%= check_box_tag "invoice_ids[]", invoice.id, false, onchange: "updateLink()", class: "invoice-checkbox" if invoices.count > 1 %> <%= check_box_tag "invoice_ids[]", invoice.id, false, onchange: "updateLink()", data: { url: invoice_path(invoice), text: "Invoice ##{invoice.to_s}" }, class: "invoice-checkbox appointment" if invoices.count > 1 %>
<b><%= link_to "##{invoice.doc_number}", invoice_path(invoice), target: :_blank %></b> <%= invoice.txn_date %> <b><%= link_to "##{invoice.doc_number}", invoice_path(invoice), target: :_blank %></b> <%= invoice.txn_date %>
</div> </div>
<% end %> <% end %>
+7 -16
View File
@@ -1,30 +1,21 @@
function updateLink() { function updateLink() {
console.log("updateLink called");
const linkElement = document.getElementById("appointment_link"); const linkElement = document.getElementById("appointment_link");
const regex = /((?:<br\/>|%3Cbr\/?%3E))([\s\S]*?)(&dates)/gi; const regex = /((?:<br\/>|%3Cbr\/?%3E))([\s\S]*?)(&dates)/gi;
linkElement.href = linkElement.href.replace(regex, `$1${getSelectedDocs()}$3`); linkElement.href = linkElement.href.replace(regex, `$1${getSelectedDocs()}$3`);
} }
function getSelectedDocs() { function getSelectedDocs() {
const invoices = document.querySelectorAll('.invoice-checkbox'); const appointent_extras = document.querySelectorAll('.appointment');
const estimates = document.querySelectorAll('.estimate-checkbox');
const invoiceIds = Array.from(invoices)
.filter(checkbox => checkbox.checked)
.map(checkbox => checkbox.value);
const estimateIds = Array.from(estimates)
.filter(checkbox => checkbox.checked)
.map(checkbox => checkbox.value);
let output = ''; let output = '';
for (const item of appointent_extras) {
for (const value of invoiceIds) { if (item.checked) {
output += `%0A<a href="${window.location.origin}/invoices/${value}">Invoice:%20${value}</a>%0A`; console.log(`Checked item: ${item.dataset.text} with URL: ${item.dataset.url}`);
output += `%0A`+ encodeURIComponent(`<a href="${window.location.origin}${item.dataset.url}">${item.dataset.text}</a>`) +`%0A`;
}
} }
for (const value of estimateIds) {
output += `%0A<a href="${window.location.origin}/estimates/${value}">Estimate:%20${value}</a>%0A`;
}
// You can return the array or use it as needed // You can return the array or use it as needed
return output; return output;
+1
View File
@@ -101,3 +101,4 @@ en:
notice_issue_not_found: "Issue not found" notice_issue_not_found: "Issue not found"
customer_details: "Customer Details" customer_details: "Customer Details"
notice_error_project_nil: "The issue's project is nil, set project to: " notice_error_project_nil: "The issue's project is nil, set project to: "
notice_error_tracker_nil: "The issue's tracker is nil, set tracker to: "
+1 -1
View File
@@ -14,7 +14,7 @@ Redmine::Plugin.register :redmine_qbo do
name 'Redmine QBO plugin' name 'Redmine QBO plugin'
author 'Rick Barrette' 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' 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.2.1' version '2026.2.4'
url 'https://github.com/rickbarrette/redmine_qbo' url 'https://github.com/rickbarrette/redmine_qbo'
author_url 'https://barrettefabrication.com' author_url 'https://barrettefabrication.com'
settings default: {empty: true}, partial: 'qbo/settings' settings default: {empty: true}, partial: 'qbo/settings'
@@ -20,9 +20,16 @@ module RedmineQbo
def controller_issues_new_before_save(context={}) def controller_issues_new_before_save(context={})
if context[:issue].project.nil? if context[:issue].project.nil?
context[:issue].project = projects_for_select(context[:issue]).first context[:issue].project = projects_for_select(context[:issue]).first
Rails.logger.error I18n.t(:notice_error_project_nil) + context[:issue].project.to_s
context[:controller].flash[:error] = I18n.t(:notice_error_project_nil) + context[:issue].project.to_s context[:controller].flash[:error] = I18n.t(:notice_error_project_nil) + context[:issue].project.to_s
end end
if context[:issue].tracker.nil?
context[:issue].tracker = trackers_for_select(context[:issue]).first
Rails.logger.error I18n.t(:notice_error_tracker_nil) + context[:issue].tracker.to_s
context[:controller].flash[:error] = I18n.t(:notice_error_tracker_nil) + context[:issue].tracker.to_s
end
return context return context
end end
@@ -15,6 +15,7 @@ module RedmineQbo
module Helper module Helper
def watcher_link(issue, user) def watcher_link(issue, user)
link = ''
link = link_to(I18n.t(:label_bill_time), bill_path( issue.id ), method: :get, class: 'icon icon-email-add') if user.admin? link = link_to(I18n.t(:label_bill_time), bill_path( issue.id ), method: :get, class: 'icon icon-email-add') if user.admin?
link << link_to(I18n.t(:label_share), share_path( issue.id ), method: :get, target: :_blank, class: 'icon icon-shared') if user.logged? link << link_to(I18n.t(:label_share), share_path( issue.id ), method: :get, target: :_blank, class: 'icon icon-shared') if user.logged?
link.html_safe + super link.html_safe + super