PluginProbe
Easy Invoice – Invoice Generator, PDF Quotes & Payments / 2.4.2
Easy Invoice – Invoice Generator, PDF Quotes & Payments v2.4.2
2.4.3 2.4.4 2.4.2 2.4.0 2.4.1 2.3.8 2.3.7 2.3.6 2.3.5 2.3.4 2.3.3 2.3.2 2.3.1 2.2.0 2.1.21 2.1.20 2.1.19 2.1.18 2.1.0 2.1.1 2.1.10 2.1.11 2.1.12 2.1.13 2.1.14 All 60 releases
← All changes | assets/js/invoice-save.js +29 -12 2.1.1 → 2.4.2 View file →
@@ -5,8 +5,17 @@
5 5 */
6 6 (function($) {
7 7 'use strict';
8 8
9 + function eiBuilderI18n(key, fallback) {
10 + if (typeof easyInvoice !== 'undefined' && easyInvoice.i18n && easyInvoice.i18n[key]) {
11 + return easyInvoice.i18n[key];
12 + }
13 + return fallback || '';
14 + }
15 +
16 + var spinnerSvg = '<svg class="ei-btn-spinner h-4 w-4 animate-spin" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" aria-hidden="true"><circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"></circle><path class="opacity-75" fill="currentColor" d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"></path></svg>';
17 +
9 18 // Check if we're on an invoice page
10 19 const isInvoicePage = window.location.href.includes('easy-invoice-builder') ||
11 20 window.location.href.includes('easy-invoice-new') ||
12 21 $('#invoice-form').length > 0;
@@ -112,10 +121,10 @@
112 121
113 122 // Show loading state
114 123 const $saveBtn = $('#save-invoice-btn');
115 124 const originalBtnText = $saveBtn.html();
116 - $saveBtn.html('<i class="fas fa-spinner fa-spin mr-2"></i> Saving...');
117 - $saveBtn.prop('disabled', true);
125 + $saveBtn.html('<span class="inline-flex items-center gap-2">' + spinnerSvg + '<span>' + eiBuilderI18n('saving', 'Saving…') + '</span></span>');
126 + $saveBtn.prop('disabled', true).attr('aria-busy', 'true');
118 127
119 128 // Collect form data
120 129 const formData = this.collectFormData();
121 130
@@ -142,9 +151,9 @@
142 151 success: (response) => {
143 152
144 153 // Restore button state
145 154 $saveBtn.html(originalBtnText);
146 - $saveBtn.prop('disabled', false);
155 + $saveBtn.prop('disabled', false).removeAttr('aria-busy');
147 156
148 157 if (response.success) {
149 158 // Clear any previous error states
150 159 this.clearErrorStates();
@@ -152,20 +161,24 @@
152 161 // If this is a new invoice (no invoice_id in form), update URL without redirect
153 162
154 163 // Do not show toast here; global handler will do it
155 164
156 - // If the button says "Save Invoice", update it to "Update Invoice"
157 - if ($saveBtn.text().trim() === 'Save Invoice') {
158 - $saveBtn.html('<i class="fas fa-save mr-2"></i> Update Invoice');
165 + var invId = $('#invoice-id').val();
166 + if (response.data.invoice && response.data.invoice.id) {
167 + $('#invoice-id').val(response.data.invoice.id);
168 + invId = response.data.invoice.id;
159 169 }
170 + if (invId && String(invId) !== '0') {
171 + // Put the id in the address bar so a refresh, a bookmark or a
172 + // second Save reopens this invoice instead of a blank builder.
173 + if (window.history && window.history.replaceState && !/[?&]invoice_id=/.test(window.location.search)) {
174 + var eiUrl = new URL(window.location.href); eiUrl.searchParams.set('invoice_id', String(invId)); window.history.replaceState({}, '', eiUrl.toString());
175 + }
176 + $saveBtn.html('<span class="inline-flex items-center gap-2"><svg class="h-4 w-4 text-gray-600" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7H5a2 2 0 00-2 2v9a2 2 0 002 2h14a2 2 0 002-2V9a2 2 0 00-2-2h-3m-1 4l-3 3m0 0l-3-3m3 3V4" /></svg><span>' + eiBuilderI18n('update_invoice', 'Update Invoice') + '</span></span>');
177 + }
160 178
161 179 // Update form with any returned data if needed
162 180 if (response.data.invoice) {
163 - // Update the invoice ID if it was newly created
164 - if (response.data.invoice.id && !$('#invoice-id').val()) {
165 - $('#invoice-id').val(response.data.invoice.id);
166 - }
167 -
168 181 // Update the invoice status display if available
169 182 if (response.data.invoice.status) {
170 183 $('#payment-status').val(response.data.invoice.status);
171 184 }
@@ -185,9 +198,12 @@
185 198 }
186 199
187 200 // Update any other fields if needed
188 201 }
202 +
203 + $(document).trigger('easy-invoice-saved', [response]);
189 204 } else {
205 + $(document).trigger('easy-invoice-save-failed', [response]);
190 206 // Show error message
191 207 const errorMessage = response.data && response.data.message ? response.data.message : 'Failed to save invoice';
192 208 if (typeof EasyInvoiceToast !== 'undefined') {
193 209 EasyInvoiceToast.show('error', errorMessage);
@@ -199,12 +215,13 @@
199 215 }
200 216 }
201 217 },
202 218 error: (xhr, status, error) => {
219 + $(document).trigger('easy-invoice-save-failed', [xhr]);
203 220
204 221 // Restore button state
205 222 $saveBtn.html(originalBtnText);
206 - $saveBtn.prop('disabled', false);
223 + $saveBtn.prop('disabled', false).removeAttr('aria-busy');
207 224
208 225 // Try to parse the response text as JSON
209 226 let errorMessage = 'An error occurred while saving the invoice';
210 227 try {