diff --git a/resources/assets/js/helpers/utilities.js b/resources/assets/js/helpers/utilities.js
index 442af4c4..be9afd51 100644
--- a/resources/assets/js/helpers/utilities.js
+++ b/resources/assets/js/helpers/utilities.js
@@ -1,16 +1,16 @@
export default {
- toggleSidebar () {
+ toggleSidebar() {
let icon = document.getElementsByClassName('hamburger')[0]
document.body.classList.toggle('sidebar-open')
icon.classList.toggle('is-active')
},
- addClass (el, className) {
+ addClass(el, className) {
if (el.classList) el.classList.add(className)
else el.className += ' ' + className
},
- hasClass (el, className) {
+ hasClass(el, className) {
const hasClass = el.classList
? el.classList.contains(className)
: new RegExp('(^| )' + className + '( |$)', 'gi').test(el.className)
@@ -18,33 +18,38 @@ export default {
return hasClass
},
- reset (prefix) {
+ reset(prefix) {
let regx = new RegExp('\\b' + prefix + '(.*)?\\b', 'g')
document.body.className = document.body.className.replace(regx, '')
},
- setLayout (layoutName) {
+ setLayout(layoutName) {
this.reset('layout-')
document.body.classList.add('layout-' + layoutName)
},
- setSkin (skinName) {
+ setSkin(skinName) {
this.reset('skin-')
document.body.classList.add('skin-' + skinName)
},
- setLogo (logoSrc) {
+ setLogo(logoSrc) {
document.getElementById('logo-desk').src = logoSrc
},
- formatMoney (amount, currency = 0) {
+ formatMoney(amount, currency = 0) {
if (!currency) {
- currency = {precision: 2, thousand_separator: ',', decimal_separator: '.', symbol: '$'}
+ currency = {
+ precision: 2,
+ thousand_separator: ',',
+ decimal_separator: '.',
+ symbol: '$',
+ }
}
amount = amount / 100
- let {precision, decimal_separator, thousand_separator, symbol} = currency
+ let { precision, decimal_separator, thousand_separator, symbol } = currency
try {
precision = Math.abs(precision)
@@ -52,25 +57,44 @@ export default {
const negativeSign = amount < 0 ? '-' : ''
- let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(precision)).toString()
- let j = (i.length > 3) ? i.length % 3 : 0
+ let i = parseInt(
+ (amount = Math.abs(Number(amount) || 0).toFixed(precision))
+ ).toString()
+ let j = i.length > 3 ? i.length % 3 : 0
let moneySymbol = `${symbol}`
- return moneySymbol + ' ' + negativeSign + (j ? i.substr(0, j) + thousand_separator : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator) + (precision ? decimal_separator + Math.abs(amount - i).toFixed(precision).slice(2) : '')
+ return (
+ moneySymbol +
+ ' ' +
+ negativeSign +
+ (j ? i.substr(0, j) + thousand_separator : '') +
+ i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator) +
+ (precision
+ ? decimal_separator +
+ Math.abs(amount - i)
+ .toFixed(precision)
+ .slice(2)
+ : '')
+ )
} catch (e) {
console.log(e)
}
},
- formatGraphMoney (amount, currency = 0) {
+ formatGraphMoney(amount, currency = 0) {
if (!currency) {
- currency = {precision: 2, thousand_separator: ',', decimal_separator: '.', symbol: '$'}
+ currency = {
+ precision: 2,
+ thousand_separator: ',',
+ decimal_separator: '.',
+ symbol: '$',
+ }
}
amount = amount / 100
- let {precision, decimal_separator, thousand_separator, symbol} = currency
+ let { precision, decimal_separator, thousand_separator, symbol } = currency
try {
precision = Math.abs(precision)
@@ -78,25 +102,76 @@ export default {
const negativeSign = amount < 0 ? '-' : ''
- let i = parseInt(amount = Math.abs(Number(amount) || 0).toFixed(precision)).toString()
- let j = (i.length > 3) ? i.length % 3 : 0
+ let i = parseInt(
+ (amount = Math.abs(Number(amount) || 0).toFixed(precision))
+ ).toString()
+ let j = i.length > 3 ? i.length % 3 : 0
let moneySymbol = `${symbol}`
- return moneySymbol + ' ' + negativeSign + (j ? i.substr(0, j) + thousand_separator : '') + i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator) + (precision ? decimal_separator + Math.abs(amount - i).toFixed(precision).slice(2) : '')
+ return (
+ moneySymbol +
+ ' ' +
+ negativeSign +
+ (j ? i.substr(0, j) + thousand_separator : '') +
+ i.substr(j).replace(/(\d{3})(?=\d)/g, '$1' + thousand_separator) +
+ (precision
+ ? decimal_separator +
+ Math.abs(amount - i)
+ .toFixed(precision)
+ .slice(2)
+ : '')
+ )
} catch (e) {
console.log(e)
}
},
- checkValidUrl (url) {
- let pattern = new RegExp('^(https?:\\/\\/)?' + // protocol
+ checkValidUrl(url) {
+ let pattern = new RegExp(
+ '^(https?:\\/\\/)?' + // protocol
'((([a-z\\d]([a-z\\d-]*[a-z\\d])*)\\.)+[a-z]{2,}|' + // domain name
'((\\d{1,3}\\.){3}\\d{1,3}))' + // OR ip (v4) address
'(\\:\\d+)?(\\/[-a-z\\d%_.~+]*)*' + // port and path
'(\\?[;&a-z\\d%_.~+=-]*)?' + // query string
- '(\\#[-a-z\\d_]*)?$', 'i') // fragment locator
+ '(\\#[-a-z\\d_]*)?$',
+ 'i'
+ ) // fragment locator
return !!pattern.test(url)
- }
+ },
+
+ fallbackCopyTextToClipboard(text) {
+ var textArea = document.createElement('textarea')
+ textArea.value = text
+ // Avoid scrolling to bottom
+ textArea.style.top = '0'
+ textArea.style.left = '0'
+ textArea.style.position = 'fixed'
+ document.body.appendChild(textArea)
+ textArea.focus()
+ textArea.select()
+ try {
+ var successful = document.execCommand('copy')
+ var msg = successful ? 'successful' : 'unsuccessful'
+ console.log('Fallback: Copying text command was ' + msg)
+ } catch (err) {
+ console.error('Fallback: Oops, unable to copy', err)
+ }
+ document.body.removeChild(textArea)
+ },
+ copyTextToClipboard(text) {
+ if (!navigator.clipboard) {
+ this.fallbackCopyTextToClipboard(text)
+ return
+ }
+ navigator.clipboard.writeText(text).then(
+ function () {
+ return true
+ },
+ function (err) {
+ return false
+ }
+ )
+ },
}
diff --git a/resources/assets/js/plugins/en.json b/resources/assets/js/plugins/en.json
index 93ca0834..43109607 100644
--- a/resources/assets/js/plugins/en.json
+++ b/resources/assets/js/plugins/en.json
@@ -13,6 +13,7 @@
},
"general": {
"view_pdf": "View PDF",
+ "copy_pdf_url": "Copy PDF Url",
"download_pdf": "Download PDF",
"save": "Save",
"cancel": "Cancel",
@@ -230,6 +231,7 @@
"convert_to_invoice": "Convert to Invoice",
"mark_as_sent": "Mark as Sent",
"send_estimate": "Send Estimate",
+ "resend_estimate": "Resend Estimate",
"record_payment": "Record Payment",
"add_estimate": "Add Estimate",
"save_estimate": "Save Estimate",
@@ -316,6 +318,7 @@
"notes": "Notes",
"view": "View",
"send_invoice": "Send Invoice",
+ "resend_invoice": "Resend Invoice",
"invoice_template": "Invoice Template",
"template": "Template",
"mark_as_sent": "Mark as sent",
diff --git a/resources/assets/js/views/estimates/Index.vue b/resources/assets/js/views/estimates/Index.vue
index 2ca0cd1d..96cb300d 100644
--- a/resources/assets/js/views/estimates/Index.vue
+++ b/resources/assets/js/views/estimates/Index.vue
@@ -4,16 +4,12 @@
{{ $t('estimates.title') }}
-
-
+
{{ $t('general.home') }}
-
-
+
{{ $tc('estimates.estimate', 2) }}
@@ -33,11 +29,9 @@
-
- {{ $t('estimates.new_estimate') }}
+
+ {{ $t('estimates.new_estimate') }}
@@ -46,7 +40,7 @@
-
+
-
+
-
+
-
-
+
+
-
+
-
{{ $t('general.showing') }}: {{ estimates.length }} {{ $t('general.of') }} {{ totalEstimates }}
+
+ {{ $t('general.showing') }}: {{ estimates.length }}
+ {{ $t('general.of') }} {{ totalEstimates }}
+
-
+
{{ $t('general.actions') }}
-
+
{{ $t('general.delete') }}
@@ -153,8 +183,12 @@
type="checkbox"
class="custom-control-input"
@change="selectAllEstimates"
+ />
+
@@ -178,7 +212,7 @@
:value="row.id"
type="checkbox"
class="custom-control-input"
- >
+ />
@@ -186,30 +220,30 @@
+ show="formattedEstimateDate"
+ />
+ show="name"
+ />
-
-
+
+
{{ $t('estimates.status') }}
- {{ row.status }}
+ {{
+ row.status
+ }}
-
+ show="estimate_number"
+ />
+
{{ $t('estimates.total') }}
@@ -227,50 +261,114 @@
-
-
+
+
{{ $t('general.edit') }}
-
+
{{ $t('general.delete') }}
-
+
{{ $t('general.view') }}
-
-
+
+
{{ $t('estimates.convert_to_invoice') }}
-
-
+
+
{{ $t('estimates.mark_as_sent') }}
-
-
-
+
+
+
{{ $t('estimates.send_estimate') }}
+
+
+
+
+ {{ $t('estimates.resend_estimate') }}
+
+
+
-
-
+
+
{{ $t('estimates.mark_as_accepted') }}
-
-
+
+
{{ $t('estimates.mark_as_rejected') }}
diff --git a/resources/assets/js/views/estimates/View.vue b/resources/assets/js/views/estimates/View.vue
index 1525ba9e..58ff3271 100644
--- a/resources/assets/js/views/estimates/View.vue
+++ b/resources/assets/js/views/estimates/View.vue
@@ -1,7 +1,7 @@
@@ -289,6 +338,13 @@ export default {
}
})
},
+ copyPdfUrl () {
+ let pdfUrl = `${window.location.origin}/estimates/pdf/${this.estimate.unique_hash}`
+
+ let response = this.$utils.copyTextToClipboard(pdfUrl)
+
+ window.toastr['success'](this.$tc('Copied PDF url to clipboard!'))
+ },
async removeEstimate (id) {
window.swal({
title: 'Deleted',
diff --git a/resources/assets/js/views/invoices/Index.vue b/resources/assets/js/views/invoices/Index.vue
index 5a59f728..b116fc71 100644
--- a/resources/assets/js/views/invoices/Index.vue
+++ b/resources/assets/js/views/invoices/Index.vue
@@ -1,19 +1,15 @@
-
+
{{ $t('invoices.new_invoice') }}
@@ -44,7 +44,7 @@
-
{{ $tc('customers.customer',1) }}
+
{{ $tc('customers.customer', 1) }}
{{ $t('invoices.invoice_number') }}
-
+
-
{{ $t('general.clear_all') }}
+
{{
+ $t('general.clear_all')
+ }}
-
-
+
+
{{ $t('invoices.no_invoices') }}
- {{ $t('invoices.list_of_invoices') }}
+ {{
+ $t('invoices.list_of_invoices')
+ }}
-
{{ $t('general.showing') }}: {{ invoices.length }} {{ $t('general.of') }} {{ totalInvoices }}
+
+ {{ $t('general.showing') }}: {{ invoices.length }}
+ {{ $t('general.of') }} {{ totalInvoices }}
+
-
+
{{ $t('general.actions') }}
-
+
{{ $t('general.delete') }}
@@ -155,8 +199,12 @@
type="checkbox"
class="custom-control-input"
@change="selectAllInvoices"
+ />
+
-
{{ $t('general.select_all') }}
@@ -180,8 +228,8 @@
:value="row.id"
type="checkbox"
class="custom-control-input"
- >
-
+ />
+
@@ -195,35 +243,33 @@
width="20%"
show="name"
/>
-
-
+
+
{{ $t('invoices.status') }}
- {{ (row.status != 'PARTIALLY_PAID')? row.status : row.status.replace('_', ' ') }}
+ {{
+ row.status != 'PARTIALLY_PAID'
+ ? row.status
+ : row.status.replace('_', ' ')
+ }}
-
+
{{ $t('invoices.paid_status') }}
- {{ (row.paid_status != 'PARTIALLY_PAID')? row.paid_status : row.paid_status.replace('_', ' ') }}
+ {{
+ row.paid_status != 'PARTIALLY_PAID'
+ ? row.paid_status
+ : row.paid_status.replace('_', ' ')
+ }}
-
-
+
+
{{ $t('invoices.amount_due') }}
-
+
-
-
+
+
{{ $t('general.edit') }}
-
+
{{ $t('invoices.view') }}
-
-
+
+
{{ $t('invoices.send_invoice') }}
+
+
+
+ {{ $t('invoices.resend_invoice') }}
+
+
-
-
+
+
{{ $t('invoices.mark_as_sent') }}
-
-
-
+
+
+
{{ $t('payments.record_payment') }}
-
+
{{ $t('invoices.clone_invoice') }}
-
+
{{ $t('general.delete') }}
diff --git a/resources/assets/js/views/invoices/View.vue b/resources/assets/js/views/invoices/View.vue
index e62a91b3..384d843e 100644
--- a/resources/assets/js/views/invoices/View.vue
+++ b/resources/assets/js/views/invoices/View.vue
@@ -1,7 +1,7 @@