From 78adb790f7bc8532e27c6b92287e4a9938ffa313 Mon Sep 17 00:00:00 2001 From: Govert Versluis Date: Fri, 13 Mar 2015 16:41:16 +0100 Subject: [PATCH 1/4] Added missing Dutch translations. This commit adds >90% of the missing strings. I tried to stay faithful to the already present translations as much as posssible. --- app/lang/nl/texts.php | 314 +++++++++++++++++++++--------------------- 1 file changed, 157 insertions(+), 157 deletions(-) diff --git a/app/lang/nl/texts.php b/app/lang/nl/texts.php index 45304e64b143..d85afb607e25 100644 --- a/app/lang/nl/texts.php +++ b/app/lang/nl/texts.php @@ -307,18 +307,18 @@ return array( 'close' => 'Sluiten', 'pro_plan_product' => 'Pro Plan', - 'pro_plan_description' => 'One year enrollment in the Invoice Ninja Pro Plan.', - 'pro_plan_success' => 'Thanks for joining! Once the invoice is paid your Pro Plan membership will begin.', + 'pro_plan_description' => 'Één jaar abbonnement op het Invoice Ninja Pro Plan.', + 'pro_plan_success' => 'Bedankt voor het aanmelden! Zodra je factuur betaald is zal je Pro Plan lidmaatschap beginnen.', - 'unsaved_changes' => 'You have unsaved changes', + 'unsaved_changes' => 'Je hebt niet bewaarde wijzigingen', 'custom_fields' => 'Custom fields', 'company_fields' => 'Company Fields', 'client_fields' => 'Client Fields', 'field_label' => 'Field Label', 'field_value' => 'Field Value', - 'edit' => 'Edit', - 'view_invoice' => 'View invoice', - 'view_as_recipient' => 'View as recipient', + 'edit' => 'Bewerk', + 'view_invoice' => 'Bekijk factuur', + 'view_as_recipient' => 'Bekijk als ontvanger', // product management 'product_library' => 'Product Library', @@ -336,105 +336,105 @@ return array( 'archived_product' => 'Successfully archived product', 'pro_plan_custom_fields' => ':link to enable custom fields by joining the Pro Plan', - 'advanced_settings' => 'Advanced Settings', + 'advanced_settings' => 'Geavanceerde instellingen', 'pro_plan_advanced_settings' => ':link to enable the advanced settings by joining the Pro Plan', - 'invoice_design' => 'Invoice Design', - 'specify_colors' => 'Specify colors', - 'specify_colors_label' => 'Select the colors used in the invoice', + 'invoice_design' => 'Factuur ontwerp', + 'specify_colors' => 'Kies kleuren', + 'specify_colors_label' => 'Kies de kleuren die in de factuur gebruikt worden', 'chart_builder' => 'Chart Builder', - 'ninja_email_footer' => 'Use :site to invoice your clients and get paid online for free!', + 'ninja_email_footer' => 'Gebruik :site om uw klanten gratis te factureren en betalingen te ontvangen!', 'go_pro' => 'Go Pro', // Quotes - 'quote' => 'Quote', - 'quotes' => 'Quotes', - 'quote_number' => 'Quote Number', - 'quote_number_short' => 'Quote #', - 'quote_date' => 'Quote Date', - 'quote_total' => 'Quote Total', - 'your_quote' => 'Your Quote', - 'total' => 'Total', - 'clone' => 'Clone', + 'quote' => 'Offerte', + 'quotes' => 'Offertes', + 'quote_number' => 'Offerte Number', + 'quote_number_short' => 'Offerte #', + 'quote_date' => 'Offerte Datum', + 'quote_total' => 'Offerte Totaal', + 'your_quote' => 'Uw Offerte', + 'total' => 'Totaal', + 'clone' => 'Kloon', - 'new_quote' => 'New Quote', - 'create_quote' => 'Create Quote', - 'edit_quote' => 'Edit Quote', - 'archive_quote' => 'Archive Quote', - 'delete_quote' => 'Delete Quote', - 'save_quote' => 'Save Quote', - 'email_quote' => 'Email Quote', - 'clone_quote' => 'Clone Quote', - 'convert_to_invoice' => 'Convert to Invoice', - 'view_invoice' => 'View Invoice', - 'view_quote' => 'View Quote', - 'view_client' => 'View Client', + 'new_quote' => 'Nieuwe Offerte', + 'create_quote' => 'Maak offerte aan', + 'edit_quote' => 'Bewerk Offecte', + 'archive_quote' => 'Archiveer Offerte', + 'delete_quote' => 'Verwijder Offerte', + 'save_quote' => 'Bewaar Offerte', + 'email_quote' => 'Email Offerte', + 'clone_quote' => 'Kloon Offerte', + 'convert_to_invoice' => 'Zet om naar Factuur', + 'view_invoice' => 'Bekijk Factuur', + 'view_quote' => 'Bekijk Offerte', + 'view_client' => 'Bekijk Klant', - 'updated_quote' => 'Successfully updated quote', - 'created_quote' => 'Successfully created quote', - 'cloned_quote' => 'Successfully cloned quote', - 'emailed_quote' => 'Successfully emailed quote', - 'archived_quote' => 'Successfully archived quote', - 'archived_quotes' => 'Successfully archived :count quotes', - 'deleted_quote' => 'Successfully deleted quote', - 'deleted_quotes' => 'Successfully deleted :count quotes', - 'converted_to_invoice' => 'Successfully converted quote to invoice', + 'updated_quote' => 'Offerte succesvol bijgewerkt', + 'created_quote' => 'Offerte succesvol aangemaakt', + 'cloned_quote' => 'Offerte succesvol gekopieerd', + 'emailed_quote' => 'Offerte succesvol gemaild', + 'archived_quote' => 'Offerte succesvol gearchiveerd', + 'archived_quotes' => ':count offertes succesvol gearchiveerd', + 'deleted_quote' => 'Offerte succesvol verwijderd', + 'deleted_quotes' => ':count offertes succesvol verwijderd', + 'converted_to_invoice' => 'Offerte succesvol omgezet naar factuur', - 'quote_subject' => 'New quote from :account', - 'quote_message' => 'To view your quote for :amount, click the link below.', - 'quote_link_message' => 'To view your client quote click the link below:', - 'notification_quote_sent_subject' => 'Quote :invoice was sent to :client', - 'notification_quote_viewed_subject' => 'Quote :invoice was viewed by :client', - 'notification_quote_sent' => 'The following client :client was emailed Quote :invoice for :amount.', - 'notification_quote_viewed' => 'The following client :client viewed Quote :invoice for :amount.', + 'quote_subject' => 'Nieuwe offerte van :account', + 'quote_message' => 'Om uw offerte voor :amount te bekijken, klik op de link hieronder.', + 'quote_link_message' => 'Klik op de link hieronder om de offerte te bekijken:', + 'notification_quote_sent_subject' => 'Offerte :invoice is verstuurd naar :client', + 'notification_quote_viewed_subject' => 'Offerte :invoice is bekeken door :client', + 'notification_quote_sent' => 'Klant :client heeft offerte :invoice voor :amount per email ontvangen.', + 'notification_quote_viewed' => 'Klant :client heeft offerte :invoice voor :amount bekeken.', - 'session_expired' => 'Your session has expired.', + 'session_expired' => 'Uw sessie is verlopen.', - 'invoice_fields' => 'Invoice Fields', - 'invoice_options' => 'Invoice Options', - 'hide_quantity' => 'Hide quantity', - 'hide_quantity_help' => 'If your line items quantities are always 1, then you can declutter invoices by no longer displaying this field.', + 'invoice_fields' => 'Factuur Velden', + 'invoice_options' => 'Factuur Opties', + 'hide_quantity' => 'Verberg aantallen', + 'hide_quantity_help' => 'Als us artikel-aantallen altijd 1 zijn, kunt u uw facturen er netter uit laten zien door dit veld te verbergen.', 'hide_paid_to_date' => 'Hide paid to date', 'hide_paid_to_date_help' => 'Only display the "Paid to Date" area on your invoices once a payment has been received.', 'charge_taxes' => 'Charge taxes', - 'user_management' => 'User Management', - 'add_user' => 'Add User', - 'send_invite' => 'Send invitation', - 'sent_invite' => 'Successfully sent invitation', - 'updated_user' => 'Successfully updated user', - 'invitation_message' => 'You\'ve been invited by :invitor. ', - 'register_to_add_user' => 'Please sign up to add a user', - 'user_state' => 'State', - 'edit_user' => 'Edit User', - 'delete_user' => 'Delete User', - 'active' => 'Active', + 'user_management' => 'Gebruikersbeheer', + 'add_user' => 'Nieuwe gebruiker', + 'send_invite' => 'Verstuur uitnodiging', + 'sent_invite' => 'Uitnodiging succesvol verzonden', + 'updated_user' => 'Gebruiker succesvol aangepast', + 'invitation_message' => 'U bent uigenodigd door :invitor. ', + 'register_to_add_user' => 'Meld u aan om een gebruiker toe te voegen', + 'user_state' => 'Status', + 'edit_user' => 'Bewerk Gebruiker', + 'delete_user' => 'Verwijder Gebruiker', + 'active' => 'Actief', 'pending' => 'Pending', - 'deleted_user' => 'Successfully deleted user', - 'limit_users' => 'Sorry, this will exceed the limit of ' . MAX_NUM_USERS . ' users', + 'deleted_user' => 'Gebruiker succesvol verwijderd', + 'limit_users' => 'Sorry, dit zou de limiet van ' . MAX_NUM_USERS . ' gebruikers overschrijden', - 'confirm_email_invoice' => 'Are you sure you want to email this invoice?', - 'confirm_email_quote' => 'Are you sure you want to email this quote?', - 'confirm_recurring_email_invoice' => 'Recurring is enabled, are you sure you want this invoice emailed?', + 'confirm_email_invoice' => 'Weet u zeker dat u deze factuur wilt mailen?', + 'confirm_email_quote' => 'Weet u zeker dat u deze offerte wilt mailen?', + 'confirm_recurring_email_invoice' => 'Terugkeren (herhalen) staat aan, weet u zeker dat u deze factuur wilt mailen?', - 'cancel_account' => 'Cancel Account', - 'cancel_account_message' => 'Warning: This will permanently erase all of your data, there is no undo.', - 'go_back' => 'Go Back', + 'cancel_account' => 'Zeg Account Op', + 'cancel_account_message' => 'Waarschuwing: Dit zal al uw data verwijderen. Er is geen manier om dit ongedaan te maken', + 'go_back' => 'Ga Terug', - 'data_visualizations' => 'Data Visualizations', - 'sample_data' => 'Sample data shown', - 'hide' => 'Hide', - 'new_version_available' => 'A new version of :releases_link is available. You\'re running v:user_version, the latest is v:latest_version', + 'data_visualizations' => 'Data Visualisaties', + 'sample_data' => 'Voorbeelddata getoond', + 'hide' => 'Verberg', + 'new_version_available' => 'Een nieuwe versie van :releases_link is beschikbaar. U gebruikt nu v:user_version, de laatste versie is v:latest_version', - 'invoice_settings' => 'Invoice Settings', - 'invoice_number_prefix' => 'Invoice Number Prefix', - 'invoice_number_counter' => 'Invoice Number Counter', - 'quote_number_prefix' => 'Quote Number Prefix', - 'quote_number_counter' => 'Quote Number Counter', - 'share_invoice_counter' => 'Share invoice counter', - 'invoice_issued_to' => 'Invoice issued to', - 'invalid_counter' => 'To prevent a possible conflict please set either an invoice or quote number prefix', - 'mark_sent' => 'Mark sent', + 'invoice_settings' => 'Factuur Instellingen', + 'invoice_number_prefix' => 'Factuurnummer Prefix', + 'invoice_number_counter' => 'Factuurnummer Teller', + 'quote_number_prefix' => 'Offertenummer Prefix', + 'quote_number_counter' => 'Offertenummer Teller', + 'share_invoice_counter' => 'Deel factuur teller', + 'invoice_issued_to' => 'Factuur uitgegeven aan', + 'invalid_counter' => 'Stel een factuurnummer prefix of offertenummer prefix in om een mogelijk conflict te voorkomen.', + 'mark_sent' => 'Markeer als verzonden', 'gateway_help_1' => ':link to sign up for Authorize.net.', @@ -443,17 +443,17 @@ return array( 'gateway_help_23' => 'Note: use your secret API key, not your publishable API key.', 'gateway_help_27' => ':link to sign up for TwoCheckout.', - 'more_designs' => 'More designs', - 'more_designs_title' => 'Additional Invoice Designs', + 'more_designs' => 'Meer ontwerpen', + 'more_designs_title' => 'Aanvullende Factuur Ontwerpen', 'more_designs_cloud_header' => 'Go Pro for more invoice designs', 'more_designs_cloud_text' => '', - 'more_designs_self_host_header' => 'Get 6 more invoice designs for just $'.INVOICE_DESIGNS_PRICE, + 'more_designs_self_host_header' => 'Krijg 6 extra factuurontwerpen voor maar $'.INVOICE_DESIGNS_PRICE, 'more_designs_self_host_text' => '', - 'buy' => 'Buy', - 'bought_designs' => 'Successfully added additional invoice designs', + 'buy' => 'Koop', + 'bought_designs' => 'Aanvullende factuurontwerpen succesvol toegevoegd', - 'sent' => 'sent', + 'sent' => 'verzonden', 'timesheets' => 'Timesheets', 'payment_title' => 'Enter Your Billing Address and Credit Card information', @@ -464,47 +464,47 @@ return array( 'id_number' => 'ID Number', 'white_label_link' => 'White label', - 'white_label_text' => 'Purchase a white label license for $'.WHITE_LABEL_PRICE.' to remove the Invoice Ninja branding from the top of the client pages.', + 'white_label_text' => 'Koop een white label licentie voor $'.WHITE_LABEL_PRICE.' om de Invoice Ninja merknaam te verwijderen uit de bovenkant van de klantenpagina\'s.', 'white_label_header' => 'White Label', - 'bought_white_label' => 'Successfully enabled white label license', + 'bought_white_label' => 'White label licentie succesvol geactiveerd', 'white_labeled' => 'White labeled', - 'restore' => 'Restore', - 'restore_invoice' => 'Restore Invoice', - 'restore_quote' => 'Restore Quote', - 'restore_client' => 'Restore Client', - 'restore_credit' => 'Restore Credit', - 'restore_payment' => 'Restore Payment', + 'restore' => 'Herstel', + 'restore_invoice' => 'Herstel Factuur', + 'restore_quote' => 'Herstel Offerte', + 'restore_client' => 'Herstel Klant', + 'restore_credit' => 'Herstel Kredietnota', + 'restore_payment' => 'Herstel Betaling', - 'restored_invoice' => 'Successfully restored invoice', - 'restored_quote' => 'Successfully restored quote', - 'restored_client' => 'Successfully restored client', - 'restored_payment' => 'Successfully restored payment', - 'restored_credit' => 'Successfully restored credit', + 'restored_invoice' => 'Factuur succesvol hersteld', + 'restored_quote' => 'Offerte succesvol hersteld', + 'restored_client' => 'Klant succesvol hersteld', + 'restored_payment' => 'Betaling succesvol hersteld', + 'restored_credit' => 'Kredietnota succesvol hersteld', - 'reason_for_canceling' => 'Help us improve our site by telling us why you\'re leaving.', - 'discount_percent' => 'Percent', - 'discount_amount' => 'Amount', + 'reason_for_canceling' => 'Help ons om onze site te verbeteren door ons te vertellen waarom u weggaat.', + 'discount_percent' => 'Percentage', + 'discount_amount' => 'Bedrag', - 'invoice_history' => 'Invoice History', - 'quote_history' => 'Quote History', - 'current_version' => 'Current version', - 'select_versiony' => 'Select version', - 'view_history' => 'View History', + 'invoice_history' => 'Factuur geschiedenis', + 'quote_history' => 'Offerte Geschiedenis', + 'current_version' => 'Huidige Versie', + 'select_versiony' => 'Selecteer versie', + 'view_history' => 'Bekijk Geschiedenis', - 'edit_payment' => 'Edit Payment', - 'updated_payment' => 'Successfully updated payment', - 'deleted' => 'Deleted', - 'restore_user' => 'Restore User', - 'restored_user' => 'Successfully restored user', - 'show_deleted_users' => 'Show deleted users', + 'edit_payment' => 'Bewerk Betaling', + 'updated_payment' => 'Betaling succesvol bijgewerkt', + 'deleted' => 'Verwijderd', + 'restore_user' => 'Herstel gebruiker', + 'restored_user' => 'Gebruiker succesvol hersteld', + 'show_deleted_users' => 'Toon verwijderde gebruikers', 'email_templates' => 'Email Templates', - 'invoice_email' => 'Invoice Email', - 'payment_email' => 'Payment Email', - 'quote_email' => 'Quote Email', - 'reset_all' => 'Reset All', - 'approve' => 'Approve', + 'invoice_email' => 'Factuur Email', + 'payment_email' => 'Betaling Email', + 'quote_email' => 'Offerte Email', + 'reset_all' => 'Reset Alles', + 'approve' => 'Goedkeuren', 'token_billing_type_id' => 'Token Billing', 'token_billing_help' => 'Enables you to store credit cards with your gateway, and charge them at a later date.', @@ -519,29 +519,29 @@ return array( 'token_billing' => 'Save card details', 'token_billing_secure' => 'The data is stored securely by :stripe_link', - 'support' => 'Support', - 'contact_information' => 'Contact information', - '256_encryption' => '256-Bit Encryption', - 'amount_due' => 'Amount due', - 'billing_address' => 'Billing address', - 'billing_method' => 'Billing method', - 'order_overview' => 'Order overview', - 'match_address' => '*Address must match address associated with credit card.', + 'support' => 'Ondersteuning', + 'contact_information' => 'Contact informatie', + '256_encryption' => '256-Bit Encryptie', + 'amount_due' => 'Te betalen bedrag', + 'billing_address' => 'Facturatie adres', + 'billing_method' => 'Betaalmethode', + 'order_overview' => 'Order overzicht', + 'match_address' => '*Addres moet overeenkomen met adres van creditcard.', 'click_once' => '*Please click "PAY NOW" only once - transaction may take up to 1 minute to process.', - 'default_invoice_footer' => 'Set default invoice footer', - 'invoice_footer' => 'Invoice footer', - 'save_as_default_footer' => 'Save as default footer', + 'default_invoice_footer' => 'Stel standaard factuur-footer in', + 'invoice_footer' => 'Factuur footer', + 'save_as_default_footer' => 'Bewaar als standaard footer', - 'token_management' => 'Token Management', + 'token_management' => 'Token Beheer', 'tokens' => 'Tokens', - 'add_token' => 'Add Token', - 'show_deleted_tokens' => 'Show deleted tokens', - 'deleted_token' => 'Successfully deleted token', - 'created_token' => 'Successfully created token', - 'updated_token' => 'Successfully updated token', - 'edit_token' => 'Edit Token', - 'delete_token' => 'Delete Token', + 'add_token' => 'Voeg Token Toe', + 'show_deleted_tokens' => 'Toon verwijderde tokens', + 'deleted_token' => 'Token succesvol verwijderd', + 'created_token' => 'Token succesvol aangemaakt', + 'updated_token' => 'Token succesvol aangepast', + 'edit_token' => 'Bewerk Token', + 'delete_token' => 'Verwijder Token', 'token' => 'Token', 'add_gateway' => 'Add Gateway', @@ -553,25 +553,25 @@ return array( 'pay_with_paypal' => 'PayPal', 'pay_with_card' => 'Credit card', - 'change_password' => 'Change password', - 'current_password' => 'Current password', - 'new_password' => 'New password', - 'confirm_password' => 'Confirm password', - 'password_error_incorrect' => 'The current password is incorrect.', - 'password_error_invalid' => 'The new password is invalid.', - 'updated_password' => 'Successfully updated password', + 'change_password' => 'Verander wachtwoord', + 'current_password' => 'Huidig wachtwoord', + 'new_password' => 'Nieuw wachtwoord', + 'confirm_password' => 'Bevestig wachtwoord', + 'password_error_incorrect' => 'Het huidige wachtwoord is niet.', + 'password_error_invalid' => 'Het nieuwe wachtwoord is ongeldig.', + 'updated_password' => 'Wachtwoord succesvol aangepast', 'api_tokens' => 'API Tokens', - 'users_and_tokens' => 'Users & Tokens', + 'users_and_tokens' => 'Gebruikers & Tokens', 'account_login' => 'Account Login', - 'recover_password' => 'Recover your password', - 'forgot_password' => 'Forgot your password?', - 'email_address' => 'Email address', + 'recover_password' => 'Wachtwoordherstel', + 'forgot_password' => 'Wachtwoord vergeten?', + 'email_address' => 'Emailadres', 'lets_go' => 'Let’s go', - 'password_recovery' => 'Password Recovery', - 'send_email' => 'Send email', - 'set_password' => 'Set Password', - 'converted' => 'Converted', + 'password_recovery' => 'Wachtwoord Herstel', + 'send_email' => 'Verstuur email', + 'set_password' => 'Stel wachtwoord in', + 'converted' => 'Omgezet', From 00fb18a52f2b3eedbbacbf8c62529c64dc7b6fe1 Mon Sep 17 00:00:00 2001 From: Viktor Rennert Date: Sun, 15 Mar 2015 13:01:13 +0100 Subject: [PATCH 2/4] Added ability to attach invoice as pdf to email templates. Added flag in setting to turn pdf attachments on/off. Client side generated pdf is uploaded on send email action. Backend will check for actuall pdf. Added dummy strings to all languages. Added migration. --- app/controllers/AccountController.php | 2 ++ app/controllers/AjaxController.php | 23 +++++++++++++ ...174122_add_pdf_email_attachment_option.php | 34 +++++++++++++++++++ app/lang/da/texts.php | 2 ++ app/lang/de/texts.php | 2 ++ app/lang/en/texts.php | 2 ++ app/lang/es/texts.php | 2 ++ app/lang/fr/texts.php | 2 ++ app/lang/it/texts.php | 2 ++ app/lang/lt/texts.php | 2 ++ app/lang/nb_NO/texts.php | 2 ++ app/lang/nl/texts.php | 2 ++ app/lang/pt_BR/texts.php | 2 ++ app/models/Invoice.php | 16 ++++++--- app/ninja/mailers/ContactMailer.php | 1 + app/ninja/mailers/Mailer.php | 17 +++++++++- app/routes.php | 2 ++ app/views/accounts/invoice_settings.blade.php | 4 +++ app/views/invoices/edit.blade.php | 26 +++++++++++--- 19 files changed, 135 insertions(+), 10 deletions(-) create mode 100644 app/controllers/AjaxController.php create mode 100644 app/database/migrations/2015_03_15_174122_add_pdf_email_attachment_option.php diff --git a/app/controllers/AccountController.php b/app/controllers/AccountController.php index 6036a93b3753..4747146dbd65 100755 --- a/app/controllers/AccountController.php +++ b/app/controllers/AccountController.php @@ -263,6 +263,8 @@ class AccountController extends \BaseController $account->invoice_number_counter = Input::get('invoice_number_counter'); $account->quote_number_prefix = Input::get('quote_number_prefix'); $account->share_counter = Input::get('share_counter') ? true : false; + + $account->pdf_email_attachment = Input::get('pdf_email_attachment') ? true : false; if (!$account->share_counter) { $account->quote_number_counter = Input::get('quote_number_counter'); diff --git a/app/controllers/AjaxController.php b/app/controllers/AjaxController.php new file mode 100644 index 000000000000..0e502220474c --- /dev/null +++ b/app/controllers/AjaxController.php @@ -0,0 +1,23 @@ +file($tmpName) === 'application/pdf; charset=binary') { + move_uploaded_file($tmpName, $uploadsDir.$name); + } + } + } +} \ No newline at end of file diff --git a/app/database/migrations/2015_03_15_174122_add_pdf_email_attachment_option.php b/app/database/migrations/2015_03_15_174122_add_pdf_email_attachment_option.php new file mode 100644 index 000000000000..de89c6475a19 --- /dev/null +++ b/app/database/migrations/2015_03_15_174122_add_pdf_email_attachment_option.php @@ -0,0 +1,34 @@ +smallInteger('pdf_email_attachment')->default(0); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('accounts', function($table) + { + $table->dropColumn('pdf_email_attachment'); + }); + } + +} diff --git a/app/lang/da/texts.php b/app/lang/da/texts.php index 9df8d9e79d82..e52e94cf3e3a 100644 --- a/app/lang/da/texts.php +++ b/app/lang/da/texts.php @@ -208,6 +208,8 @@ return array( 'import_to' => 'Importer til', 'client_will_create' => 'Klient vil blive oprettet', 'clients_will_create' => 'Klienter vil blive oprettet', + 'email_settings' => 'Email Settings', + 'pdf_email_attachment' => 'Attach PDF to Emails', // application messages 'created_client' => 'Klient oprettet succesfuldt', diff --git a/app/lang/de/texts.php b/app/lang/de/texts.php index 87de74960d85..7260f383be13 100644 --- a/app/lang/de/texts.php +++ b/app/lang/de/texts.php @@ -205,6 +205,8 @@ return array( 'import_to' => 'Importieren nach', 'client_will_create' => 'Kunde wird erstellt', 'clients_will_create' => 'Kunden werden erstellt', + 'email_settings' => 'E-Mail Einstellungen', + 'pdf_email_attachment' => 'PDF an E-Mails anhängen', // application messages 'created_client' => 'Kunde erfolgreich angelegt', diff --git a/app/lang/en/texts.php b/app/lang/en/texts.php index 50727cfdd6c2..3f00ff7b80ee 100644 --- a/app/lang/en/texts.php +++ b/app/lang/en/texts.php @@ -206,6 +206,8 @@ return array( 'import_to' => 'Import to', 'client_will_create' => 'client will be created', 'clients_will_create' => 'clients will be created', + 'email_settings' => 'Email Settings', + 'pdf_email_attachment' => 'Attach PDF to Emails', // application messages 'created_client' => 'Successfully created client', diff --git a/app/lang/es/texts.php b/app/lang/es/texts.php index 5d5a04863c32..2bc9984cd7cc 100644 --- a/app/lang/es/texts.php +++ b/app/lang/es/texts.php @@ -205,6 +205,8 @@ return array( 'import_to' => 'Importar a', 'client_will_create' => 'cliente se creará', //What is this for, context of it's use 'clients_will_create' => 'clientes se crearan', //What is this for, context of it's use + 'email_settings' => 'Email Settings', + 'pdf_email_attachment' => 'Attach PDF to Emails', // application messages 'created_client' => 'cliente creado con éxito', diff --git a/app/lang/fr/texts.php b/app/lang/fr/texts.php index 9c78aa59e0ff..011c3793f1be 100644 --- a/app/lang/fr/texts.php +++ b/app/lang/fr/texts.php @@ -206,6 +206,8 @@ return array( 'import_to' => 'Importer en tant que', 'client_will_create' => 'client sera créé', 'clients_will_create' => 'clients seront créés', + 'email_settings' => 'Email Settings', + 'pdf_email_attachment' => 'Attach PDF to Emails', // application messages 'created_client' => 'Client créé avec succès', diff --git a/app/lang/it/texts.php b/app/lang/it/texts.php index b3c96be0a247..0c9123b8abb2 100644 --- a/app/lang/it/texts.php +++ b/app/lang/it/texts.php @@ -206,6 +206,8 @@ return array( 'import_to' => 'Importa in', 'client_will_create' => 'il cliente sarà creato', 'clients_will_create' => 'i clienti saranno creati', + 'email_settings' => 'Email Settings', + 'pdf_email_attachment' => 'Attach PDF to Emails', // application messages 'created_client' => 'Cliente creato con successo', diff --git a/app/lang/lt/texts.php b/app/lang/lt/texts.php index 81cfdee8f893..79811bf4f1da 100644 --- a/app/lang/lt/texts.php +++ b/app/lang/lt/texts.php @@ -206,6 +206,8 @@ return array( 'import_to' => 'Import to', 'client_will_create' => 'client will be created', 'clients_will_create' => 'clients will be created', + 'email_settings' => 'Email Settings', + 'pdf_email_attachment' => 'Attach PDF to Emails', // application messages 'created_client' => 'Successfully created client', diff --git a/app/lang/nb_NO/texts.php b/app/lang/nb_NO/texts.php index 2d066fc016d7..a978a7b3ec75 100644 --- a/app/lang/nb_NO/texts.php +++ b/app/lang/nb_NO/texts.php @@ -206,6 +206,8 @@ return array( 'import_to' => 'Importer til', 'client_will_create' => 'Klient vil bli opprettet', 'clients_will_create' => 'Klienter vil bli opprettet', + 'email_settings' => 'Email Settings', + 'pdf_email_attachment' => 'Attach PDF to Emails', // application messages 'created_client' => 'Klient opprettet suksessfullt', diff --git a/app/lang/nl/texts.php b/app/lang/nl/texts.php index 45304e64b143..c335331e7b13 100644 --- a/app/lang/nl/texts.php +++ b/app/lang/nl/texts.php @@ -205,6 +205,8 @@ return array( 'import_to' => 'Importeer naar', 'client_will_create' => 'klant zal aangemaakt worden', 'clients_will_create' => 'klanten zullen aangemaakt worden', + 'email_settings' => 'Email Settings', + 'pdf_email_attachment' => 'Attach PDF to Emails', // application messages 'created_client' => 'Klant succesvol aangemaakt', diff --git a/app/lang/pt_BR/texts.php b/app/lang/pt_BR/texts.php index 47ff16ff5dd6..bfafbed7cc9f 100644 --- a/app/lang/pt_BR/texts.php +++ b/app/lang/pt_BR/texts.php @@ -204,6 +204,8 @@ return array( 'import_to' => 'Importar para', 'client_will_create' => 'cliente será criado', 'clients_will_create' => 'clientes serão criados', + 'email_settings' => 'Email Settings', + 'pdf_email_attachment' => 'Attach PDF to Emails', // application messages 'created_client' => 'Cliente criado com sucesso', diff --git a/app/models/Invoice.php b/app/models/Invoice.php index 09e1f887d34d..8aca78ea0c5e 100755 --- a/app/models/Invoice.php +++ b/app/models/Invoice.php @@ -93,7 +93,8 @@ class Invoice extends EntityModel 'custom_value1', 'custom_value2', 'custom_taxes1', - 'custom_taxes2', ]); + 'custom_taxes2', + ]); $this->client->setVisible([ 'name', @@ -110,7 +111,8 @@ class Invoice extends EntityModel 'country', 'currency_id', 'custom_value1', - 'custom_value2', ]); + 'custom_value2', + ]); $this->account->setVisible([ 'name', @@ -136,7 +138,9 @@ class Invoice extends EntityModel 'hide_quantity', 'hide_paid_to_date', 'custom_invoice_label1', - 'custom_invoice_label2', ]); + 'custom_invoice_label2', + 'pdf_email_attachment', + ]); foreach ($this->invoice_items as $invoiceItem) { $invoiceItem->setVisible([ @@ -145,7 +149,8 @@ class Invoice extends EntityModel 'cost', 'qty', 'tax_name', - 'tax_rate', ]); + 'tax_rate', + ]); } foreach ($this->client->contacts as $contact) { @@ -153,7 +158,8 @@ class Invoice extends EntityModel 'first_name', 'last_name', 'email', - 'phone', ]); + 'phone', + ]); } return $this; diff --git a/app/ninja/mailers/ContactMailer.php b/app/ninja/mailers/ContactMailer.php index 0a262aecba08..fe91c8e4b848 100755 --- a/app/ninja/mailers/ContactMailer.php +++ b/app/ninja/mailers/ContactMailer.php @@ -43,6 +43,7 @@ class ContactMailer extends Mailer $data['body'] = str_replace(array_keys($variables), array_values($variables), $emailTemplate); $data['link'] = $invitation->getLink(); $data['entityType'] = $entityType; + $data['id'] = $invoice->getAttributes()['id']; $fromEmail = $invitation->user->email; $this->sendTo($invitation->contact->email, $fromEmail, $accountName, $subject, $view, $data); diff --git a/app/ninja/mailers/Mailer.php b/app/ninja/mailers/Mailer.php index 16264d91cc55..20b7d5b11f7a 100755 --- a/app/ninja/mailers/Mailer.php +++ b/app/ninja/mailers/Mailer.php @@ -2,6 +2,7 @@ use Mail; use Utils; +use Invoice; class Mailer { @@ -12,13 +13,27 @@ class Mailer 'emails.'.$view.'_text', ]; - Mail::send($views, $data, function ($message) use ($toEmail, $fromEmail, $fromName, $subject) { + Mail::send($views, $data, function ($message) use ($toEmail, $fromEmail, $fromName, $subject, $data) { $replyEmail = $fromEmail; // http://stackoverflow.com/questions/2421234/gmail-appearing-to-ignore-reply-to if (Utils::isNinja() && $toEmail != CONTACT_EMAIL) { $fromEmail = NINJA_FROM_EMAIL; } + + if(isset($data['id'])) { + $invoice = Invoice::find($data['id']); + $invoice->load('account'); + $accountAttributes = $invoice->account()->getParent()->getRelations()['account']->getAttributes(); + $pdfPath = storage_path().'/pdfcache/cache-'.$invoice->getAttributes()['public_id'].'.pdf'; + + if($accountAttributes['pdf_email_attachment'] === 1 && file_exists($pdfPath)) { + $message->attach( + $pdfPath, + array('as' => $accountAttributes['name'].'_'.$accountAttributes['invoice_number_prefix'].$invoice->getName().'.pdf', 'mime' => 'application/pdf') + ); + } + } //$message->setEncoder(\Swift_Encoding::get8BitEncoding()); $message->to($toEmail)->from($fromEmail, $fromName)->replyTo($replyEmail, $fromName)->subject($subject); diff --git a/app/routes.php b/app/routes.php index fc436e177b86..0d7c1997cd78 100755 --- a/app/routes.php +++ b/app/routes.php @@ -147,6 +147,8 @@ Route::group(array('before' => 'auth'), function() { Route::get('api/credits/{client_id?}', array('as'=>'api.credits', 'uses'=>'CreditController@getDatatable')); Route::post('credits/bulk', 'CreditController@bulk'); + Route::post('ajax/pdfupload', 'AjaxController@pdfupload'); + //Route::resource('timesheets', 'TimesheetController'); }); diff --git a/app/views/accounts/invoice_settings.blade.php b/app/views/accounts/invoice_settings.blade.php index bf789be9be32..beb4fef9e022 100644 --- a/app/views/accounts/invoice_settings.blade.php +++ b/app/views/accounts/invoice_settings.blade.php @@ -42,6 +42,10 @@ ->append(Former::checkbox('share_counter')->raw()->onclick('setQuoteNumberEnabled()') . ' ' . trans('texts.share_invoice_counter')) }}

 

+ {{ Former::legend('email_settings') }} + {{ Former::checkbox('pdf_email_attachment') }} +

 

+ @if (Auth::user()->isPro()) {{ Former::actions( Button::lg_success_submit(trans('texts.save'))->append_with_icon('floppy-disk') ) }} @else diff --git a/app/views/invoices/edit.blade.php b/app/views/invoices/edit.blade.php index 93a6e3da8f7a..f2b7c40e101f 100755 --- a/app/views/invoices/edit.blade.php +++ b/app/views/invoices/edit.blade.php @@ -718,16 +718,34 @@ } function onEmailClick() { - if (confirm('{{ trans("texts.confirm_email_$entityType") }}')) { - submitAction('email'); + if (confirm('{{ trans("texts.confirm_email_$entityType") }}')) { + var invoice = createInvoiceModel(); + var design = getDesignJavascript(); + if (!design) return; + var doc = generatePDF(invoice, design, true); + + var formdata = new FormData(); + formdata.append('filename', 'cache-' + invoice.public_id + '.pdf'); + formdata.append('fileblob', doc.output('blob')); + + $.ajax({ + type: 'POST', + url: '{{ URL::to("ajax/pdfupload") }}', + data: formdata, + processData: false, + contentType: false + }).done(function( data ) { + submitAction('email'); + }); + } } function onSaveClick() { if (model.invoice().is_recurring()) { - if (confirm('{{ trans("texts.confirm_recurring_email_$entityType") }}')) { + if (confirm('{{ trans("texts.confirm_recurring_email_$entityType") }}')) { submitAction(''); - } + } } else { submitAction(''); } From 2a6f7e00b5f14e9e36160ef5999fd3111fd88f24 Mon Sep 17 00:00:00 2001 From: Viktor Rennert Date: Wed, 18 Mar 2015 13:20:02 +0100 Subject: [PATCH 3/4] Reworked pdf store flow from AjaxController to invoice save. --- app/controllers/AjaxController.php | 23 ---------------------- app/controllers/InvoiceController.php | 18 +++++++++++++++++ app/routes.php | 2 -- app/views/invoices/edit.blade.php | 28 ++++++++------------------- 4 files changed, 26 insertions(+), 45 deletions(-) delete mode 100644 app/controllers/AjaxController.php diff --git a/app/controllers/AjaxController.php b/app/controllers/AjaxController.php deleted file mode 100644 index 0e502220474c..000000000000 --- a/app/controllers/AjaxController.php +++ /dev/null @@ -1,23 +0,0 @@ -file($tmpName) === 'application/pdf; charset=binary') { - move_uploaded_file($tmpName, $uploadsDir.$name); - } - } - } -} \ No newline at end of file diff --git a/app/controllers/InvoiceController.php b/app/controllers/InvoiceController.php index 28a04b3cbaf9..6d6598842256 100755 --- a/app/controllers/InvoiceController.php +++ b/app/controllers/InvoiceController.php @@ -397,6 +397,10 @@ class InvoiceController extends \BaseController Utils::trackViewed($client->getDisplayName(), ENTITY_CLIENT, $url); } + if (!empty(Input::get('pdfupload')) && strpos(Input::get('pdfupload'), 'data:application/pdf;base64,') === 0) { + $this->storePDF(Input::get('pdfupload'), $input->invoice->public_id); + } + if ($action == 'clone') { return $this->cloneInvoice($publicId); } elseif ($action == 'convert') { @@ -539,4 +543,18 @@ class InvoiceController extends \BaseController return View::make('invoices.history', $data); } + + private function storePDF($encodedString, $public_id) + { + $uploadsDir = storage_path().'/pdfcache/'; + $encodedString = str_replace('data:application/pdf;base64,', '', $encodedString); + $name = 'cache-'.$public_id.'.pdf'; + + if (file_put_contents($uploadsDir.$name, base64_decode($encodedString)) !== false) { + $finfo = new finfo(FILEINFO_MIME); + if ($finfo->file($uploadsDir.$name) !== 'application/pdf; charset=binary') { + unlink($uploadsDir.$name); + } + } + } } diff --git a/app/routes.php b/app/routes.php index 0d7c1997cd78..fc436e177b86 100755 --- a/app/routes.php +++ b/app/routes.php @@ -147,8 +147,6 @@ Route::group(array('before' => 'auth'), function() { Route::get('api/credits/{client_id?}', array('as'=>'api.credits', 'uses'=>'CreditController@getDatatable')); Route::post('credits/bulk', 'CreditController@bulk'); - Route::post('ajax/pdfupload', 'AjaxController@pdfupload'); - //Route::resource('timesheets', 'TimesheetController'); }); diff --git a/app/views/invoices/edit.blade.php b/app/views/invoices/edit.blade.php index f2b7c40e101f..b21174fee1c4 100755 --- a/app/views/invoices/edit.blade.php +++ b/app/views/invoices/edit.blade.php @@ -719,25 +719,7 @@ function onEmailClick() { if (confirm('{{ trans("texts.confirm_email_$entityType") }}')) { - var invoice = createInvoiceModel(); - var design = getDesignJavascript(); - if (!design) return; - var doc = generatePDF(invoice, design, true); - - var formdata = new FormData(); - formdata.append('filename', 'cache-' + invoice.public_id + '.pdf'); - formdata.append('fileblob', doc.output('blob')); - - $.ajax({ - type: 'POST', - url: '{{ URL::to("ajax/pdfupload") }}', - data: formdata, - processData: false, - contentType: false - }).done(function( data ) { - submitAction('email'); - }); - + submitAction('email'); } } @@ -747,6 +729,12 @@ submitAction(''); } } else { + var invoice = createInvoiceModel(); + var design = getDesignJavascript(); + if (!design) return; + var doc = generatePDF(invoice, design, true); + + $('form.form-horizontal.warn-on-exit').append(''); submitAction(''); } } @@ -757,7 +745,7 @@ return; } $('#action').val(value); - $('#submitButton').click(); + $('#submitButton').click(); } function isSaveValid() { From f190762787c7e8f65d2946d4f0aae9d79f3f2411 Mon Sep 17 00:00:00 2001 From: Hillel Coren Date: Mon, 23 Mar 2015 14:13:13 +0200 Subject: [PATCH 4/4] Updated to https urls in the readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 628553614448..d492455541cd 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ If you'd like to use our code to sell your own invoicing app we have an affiliat Most online invoicing sites are expensive. They shouldn't be. The aim of this project is to provide a free, open-source alternative. Additionally, the hope is the codebase will serve as a sample site for Laravel as well as other JavaScript technologies. -To setup the site you can either use this [zip file](http://www.invoiceninja.com/knowledgebase/self-host/) (easier to setup) or checkout the code from GitHub following the instructions below (easier to stay up to date). +To setup the site you can either use this [zip file](https://www.invoiceninja.com/knowledgebase/self-host/) (easier to setup) or checkout the code from GitHub following the instructions below (easier to stay up to date). For a WAMP/MAMP/LAMP setup you can one-click install using Softaculous's [AMPPS](http://www.ampps.com/). To deploy the app with [Docker](http://www.docker.com/) you can use [this project](https://github.com/rollbrettler/Dockerfiles/tree/master/invoice-ninja). @@ -39,9 +39,9 @@ Developed by [@hillelcoren](https://twitter.com/hillelcoren) | Designed by [kant ### Documentation -* [Self Host](http://www.invoiceninja.com/knowledgebase/self-host/) -* [API Documentation](http://www.invoiceninja.com/knowledgebase/api-documentation/) -* [Developer Guide](http://www.invoiceninja.com/knowledgebase/developer-guide/) +* [Self Host](https://www.invoiceninja.com/knowledgebase/self-host/) +* [API Documentation](https://www.invoiceninja.com/knowledgebase/api-documentation/) +* [Developer Guide](https://www.invoiceninja.com/knowledgebase/developer-guide/) ### Steps to setup from GitHub