mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2024-11-08 20:22:42 +01:00
Improved handling of various document types; better documents zip
This commit is contained in:
parent
e6056104bd
commit
1c5c45a1e1
@ -46,7 +46,7 @@ class DocumentController extends BaseController
|
|||||||
|
|
||||||
if($stream){
|
if($stream){
|
||||||
$headers = [
|
$headers = [
|
||||||
'Content-Type' => $document->type,
|
'Content-Type' => Document::$types[$document->type]['mime'],
|
||||||
'Content-Length' => $document->size,
|
'Content-Length' => $document->size,
|
||||||
];
|
];
|
||||||
|
|
||||||
@ -56,7 +56,7 @@ class DocumentController extends BaseController
|
|||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
$response = Response::make($document->getRaw(), 200);
|
$response = Response::make($document->getRaw(), 200);
|
||||||
$response->header('content-type', $document->type);
|
$response->header('content-type', Document::$types[$document->type]['mime']);
|
||||||
}
|
}
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
@ -80,9 +80,9 @@ class DocumentController extends BaseController
|
|||||||
return redirect($direct_url);
|
return redirect($direct_url);
|
||||||
}
|
}
|
||||||
|
|
||||||
$extension = pathinfo($document->preview, PATHINFO_EXTENSION);
|
$previewType = pathinfo($document->preview, PATHINFO_EXTENSION);
|
||||||
$response = Response::make($document->getRawPreview(), 200);
|
$response = Response::make($document->getRawPreview(), 200);
|
||||||
$response->header('content-type', Document::$extensions[$extension]);
|
$response->header('content-type', Document::$types[$previewType]['mime']);
|
||||||
|
|
||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
@ -99,7 +99,7 @@ class DocumentController extends BaseController
|
|||||||
return $response;
|
return $response;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(substr($document->type, 0, 6) != 'image/'){
|
if(!$document->isPDFEmbeddable()){
|
||||||
return Response::view('error', array('error'=>'Image does not exist!'), 404);
|
return Response::view('error', array('error'=>'Image does not exist!'), 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,7 @@ use App\Ninja\Repositories\ActivityRepository;
|
|||||||
use App\Events\InvoiceInvitationWasViewed;
|
use App\Events\InvoiceInvitationWasViewed;
|
||||||
use App\Events\QuoteInvitationWasViewed;
|
use App\Events\QuoteInvitationWasViewed;
|
||||||
use App\Services\PaymentService;
|
use App\Services\PaymentService;
|
||||||
use League\Flysystem\Filesystem;
|
use Barracuda\ArchiveStream\ZipArchive;
|
||||||
use League\Flysystem\ZipArchive\ZipArchiveAdapter;
|
|
||||||
|
|
||||||
class PublicClientController extends BaseController
|
class PublicClientController extends BaseController
|
||||||
{
|
{
|
||||||
@ -138,8 +137,13 @@ class PublicClientController extends BaseController
|
|||||||
'phantomjs' => Input::has('phantomjs'),
|
'phantomjs' => Input::has('phantomjs'),
|
||||||
);
|
);
|
||||||
|
|
||||||
if($account->isPro() && $this->canCreateInvoiceDocsZip($invoice)){
|
if($account->isPro() && $this->canCreateZip()){
|
||||||
|
$zipDocs = $this->getInvoiceZipDocuments($invoice, $size);
|
||||||
|
|
||||||
|
if(count($zipDocs) > 1){
|
||||||
$data['documentsZipURL'] = URL::to("client/documents/{$invitation->invitation_key}");
|
$data['documentsZipURL'] = URL::to("client/documents/{$invitation->invitation_key}");
|
||||||
|
$data['documentsZipSize'] = $size;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return View::make('invoices.view', $data);
|
return View::make('invoices.view', $data);
|
||||||
@ -173,6 +177,12 @@ class PublicClientController extends BaseController
|
|||||||
return $paymentTypes;
|
return $paymentTypes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected function humanFilesize($bytes, $decimals = 2) {
|
||||||
|
$size = array('B','kB','MB','GB','TB','PB','EB','ZB','YB');
|
||||||
|
$factor = floor((strlen($bytes) - 1) / 3);
|
||||||
|
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . @$size[$factor];
|
||||||
|
}
|
||||||
|
|
||||||
public function download($invitationKey)
|
public function download($invitationKey)
|
||||||
{
|
{
|
||||||
if (!$invitation = $this->invoiceRepo->findInvoiceByInvitation($invitationKey)) {
|
if (!$invitation = $this->invoiceRepo->findInvoiceByInvitation($invitationKey)) {
|
||||||
@ -391,7 +401,7 @@ class PublicClientController extends BaseController
|
|||||||
$document = Document::scope($publicId, $invitation->account_id)->first();
|
$document = Document::scope($publicId, $invitation->account_id)->first();
|
||||||
|
|
||||||
|
|
||||||
if(!$document || substr($document->type, 0, 6) != 'image/'){
|
if(!$document->isPDFEmbeddable()){
|
||||||
return Response::view('error', array('error'=>'Image does not exist!'), 404);
|
return Response::view('error', array('error'=>'Image does not exist!'), 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -423,19 +433,43 @@ class PublicClientController extends BaseController
|
|||||||
return function_exists('gmp_init');
|
return function_exists('gmp_init');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function canCreateInvoiceDocsZip($invoice){
|
protected function getInvoiceZipDocuments($invoice, &$size=0){
|
||||||
if(!$this->canCreateZip())return false;
|
$documents = $invoice->documents->sortBy('size');
|
||||||
if(count($invoice->documents) == 1)return false;
|
|
||||||
|
|
||||||
|
$size = 0;
|
||||||
$maxSize = MAX_ZIP_DOCUMENTS_SIZE * 1000;
|
$maxSize = MAX_ZIP_DOCUMENTS_SIZE * 1000;
|
||||||
$i = 0;
|
$toZip = array();
|
||||||
foreach($invoice->documents as $document){
|
foreach($documents as $document){
|
||||||
if($document->size <= $maxSize)$i++;
|
if($size + $document->size > $maxSize)break;
|
||||||
if($i > 1){
|
|
||||||
return true;
|
if(!empty($toZip[$document->name])){
|
||||||
|
// This name is taken
|
||||||
|
if($toZip[$document->name]->hash != $document->hash){
|
||||||
|
// 2 different files with the same name
|
||||||
|
$nameInfo = pathinfo($document->name);
|
||||||
|
|
||||||
|
for($i = 1;; $i++){
|
||||||
|
$name = $nameInfo['filename'].' ('.$i.').'.$nameInfo['extension'];
|
||||||
|
|
||||||
|
if(empty($toZip[$name])){
|
||||||
|
$toZip[$name] = $document;
|
||||||
|
$size += $document->size;
|
||||||
|
break;
|
||||||
|
} else if ($toZip[$name]->hash == $document->hash){
|
||||||
|
// We're not adding this after all
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$toZip[$document->name] = $document;
|
||||||
|
$size += $document->size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $toZip;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getInvoiceDocumentsZip($invitationKey){
|
public function getInvoiceDocumentsZip($invitationKey){
|
||||||
@ -451,58 +485,19 @@ class PublicClientController extends BaseController
|
|||||||
return Response::view('error', array('error'=>'No documents'), 404);
|
return Response::view('error', array('error'=>'No documents'), 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$documents = $invoice->documents->sortBy('size');
|
$toZip = $this->getInvoiceZipDocuments($invoice);
|
||||||
|
|
||||||
$size = 0;
|
|
||||||
$maxSize = MAX_ZIP_DOCUMENTS_SIZE * 1000;
|
|
||||||
$toZip = array();
|
|
||||||
foreach($documents as $document){
|
|
||||||
$size += $document->size;
|
|
||||||
if($size > $maxSize)break;
|
|
||||||
|
|
||||||
if(!empty($toZip[$document->name])){
|
|
||||||
$hasSameHash = false;
|
|
||||||
foreach($toZip[$document->name] as $sameName){
|
|
||||||
if($sameName->hash == $document->hash){
|
|
||||||
$hasSameHash = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!$hasSameHash){
|
|
||||||
// 2 different files with the same name
|
|
||||||
$toZip[$document->name][] = $document;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
// We're not adding this after all
|
|
||||||
$size -= $document->size;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
$toZip[$document->name] = array($document);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!count($toZip)){
|
if(!count($toZip)){
|
||||||
return Response::view('error', array('error'=>'No documents small enough'), 404);
|
return Response::view('error', array('error'=>'No documents small enough'), 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
$zip = new \Barracuda\ArchiveStream\ZipArchive($invitation->account->name.' Invoice '.$invoice->invoice_number.'.zip');
|
$zip = new ZipArchive($invitation->account->name.' Invoice '.$invoice->invoice_number.'.zip');
|
||||||
return Response::stream(function() use ($toZip, $zip) {
|
return Response::stream(function() use ($toZip, $zip) {
|
||||||
foreach($toZip as $documentsSameName){
|
foreach($toZip as $name=>$document){
|
||||||
$i = 0;
|
|
||||||
foreach($documentsSameName as $document){
|
|
||||||
$name = $document->name;
|
|
||||||
|
|
||||||
if($i){
|
|
||||||
$nameInfo = pathinfo($document->name);
|
|
||||||
$name = $nameInfo['filename'].' ('.$i.').'.$nameInfo['extension'];
|
|
||||||
}
|
|
||||||
|
|
||||||
$fileStream = $document->getStream();
|
$fileStream = $document->getStream();
|
||||||
if($fileStream){
|
if($fileStream){
|
||||||
$zip->init_file_stream_transfer($name, $document->size);
|
$zip->init_file_stream_transfer($name, $document->size, array('time'=>$document->created_at->timestamp));
|
||||||
while ($buffer = fread($fileStream, 8192))$zip->stream_file_part($buffer);
|
while ($buffer = fread($fileStream, 256000))$zip->stream_file_part($buffer);
|
||||||
fclose($fileStream);
|
fclose($fileStream);
|
||||||
$zip->complete_file_stream();
|
$zip->complete_file_stream();
|
||||||
}
|
}
|
||||||
@ -510,7 +505,6 @@ class PublicClientController extends BaseController
|
|||||||
$zip->add_file($name, $document->getRaw());
|
$zip->add_file($name, $document->getRaw());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
$zip->finish();
|
$zip->finish();
|
||||||
}, 200);
|
}, 200);
|
||||||
}
|
}
|
||||||
|
@ -5,31 +5,68 @@ use DB;
|
|||||||
|
|
||||||
class Document extends EntityModel
|
class Document extends EntityModel
|
||||||
{
|
{
|
||||||
public static $extensions = array(
|
public static $extraExtensions = array(
|
||||||
'png' => 'image/png',
|
'jpg' => 'jpeg',
|
||||||
'jpg' => 'image/jpeg',
|
'tif' => 'tiff',
|
||||||
'jpeg' => 'image/jpeg',
|
);
|
||||||
'tiff' => 'image/tiff',
|
|
||||||
'tif' => 'image/tiff',
|
public static $allowedMimes = array(// Used by Dropzone.js; does not affect what the server accepts
|
||||||
'pdf' => 'application/pdf',
|
'image/png', 'image/jpeg', 'image/tiff', 'application/pdf', 'image/gif', 'image/vnd.adobe.photoshop', 'text/plain',
|
||||||
'gif' => 'image/gif'
|
'application/zip', 'application/msword',
|
||||||
|
'application/excel', 'application/vnd.ms-excel', 'application/x-excel', 'application/x-msexcel',
|
||||||
|
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet','application/postscript', 'image/svg+xml',
|
||||||
|
'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'application/vnd.ms-powerpoint',
|
||||||
);
|
);
|
||||||
|
|
||||||
public static $types = array(
|
public static $types = array(
|
||||||
'image/png' => array(
|
'png' => array(
|
||||||
'extension' => 'png',
|
'mime' => 'image/png',
|
||||||
),
|
),
|
||||||
'image/jpeg' => array(
|
'ai' => array(
|
||||||
'extension' => 'jpeg',
|
'mime' => 'application/postscript',
|
||||||
),
|
),
|
||||||
'image/tiff' => array(
|
'svg' => array(
|
||||||
'extension' => 'tiff',
|
'mime' => 'image/svg+xml',
|
||||||
),
|
),
|
||||||
'image/gif' => array(
|
'jpeg' => array(
|
||||||
'extension' => 'gif',
|
'mime' => 'image/jpeg',
|
||||||
),
|
),
|
||||||
'application/pdf' => array(
|
'tiff' => array(
|
||||||
'extension' => 'pdf',
|
'mime' => 'image/tiff',
|
||||||
|
),
|
||||||
|
'pdf' => array(
|
||||||
|
'mime' => 'application/pdf',
|
||||||
|
),
|
||||||
|
'gif' => array(
|
||||||
|
'mime' => 'image/gif',
|
||||||
|
),
|
||||||
|
'psd' => array(
|
||||||
|
'mime' => 'image/vnd.adobe.photoshop',
|
||||||
|
),
|
||||||
|
'txt' => array(
|
||||||
|
'mime' => 'text/plain',
|
||||||
|
),
|
||||||
|
'zip' => array(
|
||||||
|
'mime' => 'application/zip',
|
||||||
|
),
|
||||||
|
'doc' => array(
|
||||||
|
'mime' => 'application/msword',
|
||||||
|
),
|
||||||
|
'xls' => array(
|
||||||
|
'mime' => 'application/vnd.ms-excel',
|
||||||
|
),
|
||||||
|
'ppt' => array(
|
||||||
|
'mime' => 'application/vnd.ms-powerpoint',
|
||||||
|
),
|
||||||
|
'xlsx' => array(
|
||||||
|
'mime' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
),
|
||||||
|
'docx' => array(
|
||||||
|
'mime' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||||
|
),
|
||||||
|
'pptx' => array(
|
||||||
|
'mime' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -142,11 +179,17 @@ class Document extends EntityModel
|
|||||||
return url('client/document/'.$invitation->invitation_key.'/'.$this->public_id.'/'.$this->name);
|
return url('client/document/'.$invitation->invitation_key.'/'.$this->public_id.'/'.$this->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function isPDFEmbeddable(){
|
||||||
|
return $this->type == 'jpeg' || $this->type == 'png' || $this->preview;
|
||||||
|
}
|
||||||
|
|
||||||
public function getVFSJSUrl(){
|
public function getVFSJSUrl(){
|
||||||
|
if(!$this->isPDFEmbeddable())return null;
|
||||||
return url('document/js/'.$this->public_id.'/'.$this->name.'.js');
|
return url('document/js/'.$this->public_id.'/'.$this->name.'.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getClientVFSJSUrl(){
|
public function getClientVFSJSUrl(){
|
||||||
|
if(!$this->isPDFEmbeddable())return null;
|
||||||
return url('client/document/js/'.$this->public_id.'/'.$this->name.'.js');
|
return url('client/document/js/'.$this->public_id.'/'.$this->name.'.js');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,14 +61,22 @@ class DocumentRepository extends BaseRepository
|
|||||||
$uploaded = $input['file'];
|
$uploaded = $input['file'];
|
||||||
|
|
||||||
$extension = strtolower($uploaded->extension());
|
$extension = strtolower($uploaded->extension());
|
||||||
if(empty(Document::$extensions[$extension])){
|
if(empty(Document::$types[$extension]) && !empty(Document::$extraExtensions[$extension])){
|
||||||
|
$documentType = Document::$extraExtensions[$extension];
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
$documentType = $extension;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(empty(Document::$types[$documentType])){
|
||||||
return Response::json([
|
return Response::json([
|
||||||
'error' => 'Unsupported extension',
|
'error' => 'Unsupported extension',
|
||||||
'code' => 400
|
'code' => 400
|
||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$documentType = Document::$extensions[$extension];
|
$documentTypeData = Document::$types[$documentType];
|
||||||
|
|
||||||
$filePath = $uploaded->path();
|
$filePath = $uploaded->path();
|
||||||
$name = $uploaded->getClientOriginalName();
|
$name = $uploaded->getClientOriginalName();
|
||||||
$size = filesize($filePath);
|
$size = filesize($filePath);
|
||||||
@ -80,10 +88,10 @@ class DocumentRepository extends BaseRepository
|
|||||||
], 400);
|
], 400);
|
||||||
}
|
}
|
||||||
|
|
||||||
$documentTypeData = Document::$types[$documentType];
|
|
||||||
|
|
||||||
$hash = sha1_file($filePath);
|
$hash = sha1_file($filePath);
|
||||||
$filename = \Auth::user()->account->account_key.'/'.$hash.'.'.$documentTypeData['extension'];
|
$filename = \Auth::user()->account->account_key.'/'.$hash.'.'.$documentType;
|
||||||
|
|
||||||
$document = Document::createNew();
|
$document = Document::createNew();
|
||||||
$disk = $document->getDisk();
|
$disk = $document->getDisk();
|
||||||
@ -94,20 +102,20 @@ class DocumentRepository extends BaseRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
// This is an image; check if we need to create a preview
|
// This is an image; check if we need to create a preview
|
||||||
if(in_array($documentType, array('image/jpeg','image/png','image/gif','image/bmp','image/tiff'))){
|
if(in_array($documentType, array('jpeg','png','gif','bmp','tiff','psd'))){
|
||||||
$makePreview = false;
|
$makePreview = false;
|
||||||
$imageSize = getimagesize($filePath);
|
$imageSize = getimagesize($filePath);
|
||||||
$width = $imageSize[0];
|
$width = $imageSize[0];
|
||||||
$height = $imageSize[1];
|
$height = $imageSize[1];
|
||||||
$imgManagerConfig = array();
|
$imgManagerConfig = array();
|
||||||
if(in_array($documentType, array('image/gif','image/bmp','image/tiff'))){
|
if(in_array($documentType, array('gif','bmp','tiff','psd'))){
|
||||||
// Needs to be converted
|
// Needs to be converted
|
||||||
$makePreview = true;
|
$makePreview = true;
|
||||||
} else if($width > DOCUMENT_PREVIEW_SIZE || $height > DOCUMENT_PREVIEW_SIZE){
|
} else if($width > DOCUMENT_PREVIEW_SIZE || $height > DOCUMENT_PREVIEW_SIZE){
|
||||||
$makePreview = true;
|
$makePreview = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if($documentType == 'image/bmp' || $documentType == 'image/tiff'){
|
if(in_array($documentType,array('bmp','tiff','psd'))){
|
||||||
if(!class_exists('Imagick')){
|
if(!class_exists('Imagick')){
|
||||||
// Cant't read this
|
// Cant't read this
|
||||||
$makePreview = false;
|
$makePreview = false;
|
||||||
@ -117,13 +125,13 @@ class DocumentRepository extends BaseRepository
|
|||||||
}
|
}
|
||||||
|
|
||||||
if($makePreview){
|
if($makePreview){
|
||||||
$previewType = 'jpg';
|
$previewType = 'jpeg';
|
||||||
if(in_array($documentType, array('image/png','image/gif','image/bmp','image/tiff'))){
|
if(in_array($documentType, array('png','gif','tiff','psd'))){
|
||||||
// Has transparency
|
// Has transparency
|
||||||
$previewType = 'png';
|
$previewType = 'png';
|
||||||
}
|
}
|
||||||
|
|
||||||
$document->preview = \Auth::user()->account->account_key.'/'.$hash.'.'.$documentTypeData['extension'].'.x'.DOCUMENT_PREVIEW_SIZE.'.'.$previewType;
|
$document->preview = \Auth::user()->account->account_key.'/'.$hash.'.'.$documentType.'.x'.DOCUMENT_PREVIEW_SIZE.'.'.$previewType;
|
||||||
if(!$disk->exists($document->preview)){
|
if(!$disk->exists($document->preview)){
|
||||||
// We haven't created a preview yet
|
// We haven't created a preview yet
|
||||||
$imgManager = new ImageManager($imgManagerConfig);
|
$imgManager = new ImageManager($imgManagerConfig);
|
||||||
@ -170,7 +178,7 @@ class DocumentRepository extends BaseRepository
|
|||||||
$doc_array = $document->toArray();
|
$doc_array = $document->toArray();
|
||||||
|
|
||||||
if(!empty($base64)){
|
if(!empty($base64)){
|
||||||
$mime = !empty($previewType)?Document::$extensions[$previewType]:$documentType;
|
$mime = Document::$types[!empty($previewType)?$previewType:$documentType]['mime'];
|
||||||
$doc_array['base64'] = 'data:'.$mime.';base64,'.$base64;
|
$doc_array['base64'] = 'data:'.$mime.';base64,'.$base64;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,6 +159,12 @@ class AppServiceProvider extends ServiceProvider {
|
|||||||
return $str . '</ol>';
|
return $str . '</ol>';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Form::macro('human_filesize', function($bytes, $decimals = 1) {
|
||||||
|
$size = array('B','kB','MB','GB','TB','PB','EB','ZB','YB');
|
||||||
|
$factor = floor((strlen($bytes) - 1) / 3);
|
||||||
|
return sprintf("%.{$decimals}f", $bytes / pow(1024, $factor)) . ' ' . @$size[$factor];
|
||||||
|
});
|
||||||
|
|
||||||
Validator::extend('positive', function($attribute, $value, $parameters) {
|
Validator::extend('positive', function($attribute, $value, $parameters) {
|
||||||
return Utils::parseFloat($value) >= 0;
|
return Utils::parseFloat($value) >= 0;
|
||||||
});
|
});
|
||||||
|
@ -31404,10 +31404,10 @@ NINJA.invoiceDocuments = function(invoice) {
|
|||||||
for (var i = 0; i < invoice.documents.length; i++) {
|
for (var i = 0; i < invoice.documents.length; i++) {
|
||||||
var document = invoice.documents[i];
|
var document = invoice.documents[i];
|
||||||
var path = document.base64;
|
var path = document.base64;
|
||||||
if(!path && (document.preview_url || document.type == 'image/png' || document.type == 'image/jpeg')){
|
|
||||||
path = 'docs/'+document.public_id+'/'+document.name;
|
if(!path)path = 'docs/'+document.public_id+'/'+document.name;
|
||||||
}
|
|
||||||
if(path && (window.pdfMake.vfs[path] || document.base64)){
|
if(path && (window.pdfMake.vfs[path] || document.base64)){
|
||||||
|
// Only embed if we actually have an image for it
|
||||||
if(j%3==0){
|
if(j%3==0){
|
||||||
stackItem = {columns:[]};
|
stackItem = {columns:[]};
|
||||||
stack.push(stackItem);
|
stack.push(stackItem);
|
||||||
|
@ -412,10 +412,10 @@ NINJA.invoiceDocuments = function(invoice) {
|
|||||||
for (var i = 0; i < invoice.documents.length; i++) {
|
for (var i = 0; i < invoice.documents.length; i++) {
|
||||||
var document = invoice.documents[i];
|
var document = invoice.documents[i];
|
||||||
var path = document.base64;
|
var path = document.base64;
|
||||||
if(!path && (document.preview_url || document.type == 'image/png' || document.type == 'image/jpeg')){
|
|
||||||
path = 'docs/'+document.public_id+'/'+document.name;
|
if(!path)path = 'docs/'+document.public_id+'/'+document.name;
|
||||||
}
|
|
||||||
if(path && (window.pdfMake.vfs[path] || document.base64)){
|
if(path && (window.pdfMake.vfs[path] || document.base64)){
|
||||||
|
// Only embed if we actually have an image for it
|
||||||
if(j%3==0){
|
if(j%3==0){
|
||||||
stackItem = {columns:[]};
|
stackItem = {columns:[]};
|
||||||
stack.push(stackItem);
|
stack.push(stackItem);
|
||||||
|
@ -1107,7 +1107,7 @@ $LANG = array(
|
|||||||
'invoice_embed_documents' => 'Embed Documents',
|
'invoice_embed_documents' => 'Embed Documents',
|
||||||
'invoice_embed_documents_help' => 'Include attached images in the invoice.',
|
'invoice_embed_documents_help' => 'Include attached images in the invoice.',
|
||||||
'document_email_attachment' => 'Attach Documents',
|
'document_email_attachment' => 'Attach Documents',
|
||||||
'download_documents' => 'Download Documents',
|
'download_documents' => 'Download Documents (:size)',
|
||||||
);
|
);
|
||||||
|
|
||||||
return $LANG;
|
return $LANG;
|
||||||
|
@ -930,7 +930,7 @@
|
|||||||
params:{
|
params:{
|
||||||
_token:"{{ Session::getToken() }}"
|
_token:"{{ Session::getToken() }}"
|
||||||
},
|
},
|
||||||
acceptedFiles:{!! json_encode(implode(',',array_keys(\App\Models\Document::$types))) !!},
|
acceptedFiles:{!! json_encode(implode(',',\App\Models\Document::$allowedMimes)) !!},
|
||||||
addRemoveLinks:true,
|
addRemoveLinks:true,
|
||||||
maxFileSize:{{floatval(MAX_DOCUMENT_SIZE/1000)}},
|
maxFileSize:{{floatval(MAX_DOCUMENT_SIZE/1000)}},
|
||||||
dictDefaultMessage:{!! json_encode(trans('texts.document_upload_message')) !!}
|
dictDefaultMessage:{!! json_encode(trans('texts.document_upload_message')) !!}
|
||||||
@ -955,9 +955,12 @@
|
|||||||
|
|
||||||
dropzone.emit('addedfile', mockFile);
|
dropzone.emit('addedfile', mockFile);
|
||||||
dropzone.emit('complete', mockFile);
|
dropzone.emit('complete', mockFile);
|
||||||
if(document.type().match(/image.*/)){
|
if(document.preview_url()){
|
||||||
dropzone.emit('thumbnail', mockFile, document.preview_url()||document.url());
|
dropzone.emit('thumbnail', mockFile, document.preview_url()||document.url());
|
||||||
}
|
}
|
||||||
|
else if(document.type()=='jpeg' || document.type()=='png' || document.type()=='svg'){
|
||||||
|
dropzone.emit('thumbnail', mockFile, document.url());
|
||||||
|
}
|
||||||
dropzone.files.push(mockFile);
|
dropzone.files.push(mockFile);
|
||||||
}
|
}
|
||||||
@endif
|
@endif
|
||||||
@ -1005,7 +1008,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
function createInvoiceModel() {
|
function createInvoiceModel() {
|
||||||
var invoice = ko.toJS(window.model).invoice;
|
var model = ko.toJS(window.model);
|
||||||
|
if(!model)return;
|
||||||
|
var invoice = model.invoice;
|
||||||
invoice.is_pro = {{ Auth::user()->isPro() ? 'true' : 'false' }};
|
invoice.is_pro = {{ Auth::user()->isPro() ? 'true' : 'false' }};
|
||||||
invoice.is_quote = {{ $entityType == ENTITY_QUOTE ? 'true' : 'false' }};
|
invoice.is_quote = {{ $entityType == ENTITY_QUOTE ? 'true' : 'false' }};
|
||||||
invoice.contact = _.findWhere(invoice.client.contacts, {send_invoice: true});
|
invoice.contact = _.findWhere(invoice.client.contacts, {send_invoice: true});
|
||||||
@ -1335,13 +1340,19 @@
|
|||||||
file.public_id = response.document.public_id
|
file.public_id = response.document.public_id
|
||||||
model.invoice().documents()[file.index].update(response.document);
|
model.invoice().documents()[file.index].update(response.document);
|
||||||
refreshPDF(true);
|
refreshPDF(true);
|
||||||
|
|
||||||
|
if(response.document.preview_url){
|
||||||
|
dropzone.emit('thumbnail', file, response.document.preview_url);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
@if ($account->isPro() && $account->invoice_embed_documents)
|
@if ($account->isPro() && $account->invoice_embed_documents)
|
||||||
@foreach ($invoice->documents as $document)
|
@foreach ($invoice->documents as $document)
|
||||||
|
@if($document->isPDFEmbeddable())
|
||||||
<script src="{{ $document->getVFSJSUrl() }}" type="text/javascript" async></script>
|
<script src="{{ $document->getVFSJSUrl() }}" type="text/javascript" async></script>
|
||||||
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
@endif
|
@endif
|
||||||
|
|
||||||
|
@ -59,7 +59,9 @@
|
|||||||
|
|
||||||
@if (Auth::user()->account->isPro() && Auth::user()->account->invoice_embed_documents)
|
@if (Auth::user()->account->isPro() && Auth::user()->account->invoice_embed_documents)
|
||||||
@foreach ($invoice->documents as $document)
|
@foreach ($invoice->documents as $document)
|
||||||
|
@if($document->isPDFEmbeddable())
|
||||||
<script src="{{ $document->getVFSJSUrl() }}" type="text/javascript" async></script>
|
<script src="{{ $document->getVFSJSUrl() }}" type="text/javascript" async></script>
|
||||||
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
@endif
|
@endif
|
||||||
@stop
|
@stop
|
@ -43,7 +43,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pull-left">
|
<div class="pull-left">
|
||||||
@if(!empty($documentsZipURL))
|
@if(!empty($documentsZipURL))
|
||||||
{!! Button::normal(trans('texts.download_documents'))->asLinkTo($documentsZipURL)->large() !!}
|
{!! Button::normal(trans('texts.download_documents', array('size'=>Form::human_filesize($documentsZipSize))))->asLinkTo($documentsZipURL)->large() !!}
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
@endif
|
@endif
|
||||||
@ -54,7 +54,7 @@
|
|||||||
<h3>{{ trans('texts.documents_header') }}</h3>
|
<h3>{{ trans('texts.documents_header') }}</h3>
|
||||||
<ul>
|
<ul>
|
||||||
@foreach ($invoice->documents as $document)
|
@foreach ($invoice->documents as $document)
|
||||||
<li><a target="_blank" href="{{ $document->getClientUrl($invitation) }}">{{$document->name}}</a></li>
|
<li><a target="_blank" href="{{ $document->getClientUrl($invitation) }}">{{$document->name}} ({{Form::human_filesize($document->size)}})</a></li>
|
||||||
@endforeach
|
@endforeach
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -62,7 +62,9 @@
|
|||||||
|
|
||||||
@if ($account->isPro() && $account->invoice_embed_documents)
|
@if ($account->isPro() && $account->invoice_embed_documents)
|
||||||
@foreach ($invoice->documents as $document)
|
@foreach ($invoice->documents as $document)
|
||||||
|
@if($document->isPDFEmbeddable())
|
||||||
<script src="{{ $document->getClientVFSJSUrl() }}" type="text/javascript" {{ Input::has('phantomjs')?'':'async' }}></script>
|
<script src="{{ $document->getClientVFSJSUrl() }}" type="text/javascript" {{ Input::has('phantomjs')?'':'async' }}></script>
|
||||||
|
@endif
|
||||||
@endforeach
|
@endforeach
|
||||||
@endif
|
@endif
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
|
Loading…
Reference in New Issue
Block a user