Git Product home page Git Product logo

jspdf-invoice-template's Introduction

Cover .NET & React

Welcome 👋

  • 🔭 Currently working with .NET 5 & ReactJs. Recently worked on Sharepoint Framework.
  • 🌱 I’m currently learning React Native.
  • 👯 I’m looking to collaborate on open source projects.
  • 💬 Ask me about projects 😊...

jspdf-invoice-template's People

Contributors

edisonneza avatar eduardozgz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar

jspdf-invoice-template's Issues

1.4.0 invoice header is expecting string[] but demo site given as object[]

The types of 'invoice.header' are incompatible between these types.

    Type '({ title: string; style: { width: number; }; } | { title: string; style?: undefined; })[]' is not assignable to type 'string[]'.

This source header definition is expecting string[]
Source code (zip)
Snippet from above source

 invDate?: string,
 *       invGenDate?: string,
 *       headerBorder?: boolean,
 *       tableBodyBorder?: boolean,
 *       header?: string[],
 *       table?: any,
 *       invTotalLabel?: string,
 *       invTotal?: string,

I get the exception for this

header: [
          {
            title: "#",
            style: {
              width: 10
            }
          },
          {
            title: "Title",
            style: {
              width: 30
            }
          },
          {

Add or remove columns?

Hi, thank you for the great work. I can see that you have defined 6 columns for the table. I am just wondering if there is any easy way to remove the "item number" and "unit" ? It seems that these 6 columns are hard coded in the index.js file isn't it?

code-review: jsPDF.text(...), is the parameter out of order?

doc.text(docWidth - 10, currentHeight, param.business.address, "right");

  doc.text(docWidth - 10, currentHeight, param.business.address, "right");

Multiple usages of .text() in this (undocumented?) order still appear to work

Dynamic js library is forgiving and the types are often not up to date either; however, I believe the documented types and .text() function signature implementation desire the text variable as the first parameter

Unless I am looking at a different utility, as the end result appears to still work!

https://github.com/MrRio/jsPDF/blob/cef97fb34eda41a8704c9f3983e680919a328ce4/src/jspdf.js#L3421

  API.__private__.text = API.text = function(text, x, y, options, transform) {

jspdf types index.d.ts

    text(
      text: string | string[],
      x: number,
      y: number,
      options?: TextOptionsLight,
      transform?: number | any
    ): jsPDF;

I am currently refactoring while customising in TypeScript and will see what happens

Also decomposing into separate files.

Set row height/padding

Screenshot 2022-06-18 at 3 04 01 PM

Is there a way to add space between the "variations" text of the Title column and the line below it? Any way to make the text not touch the row lines?

Angular 13 Support

Thanks for this amazing library!

After updating from angular v12 to v13, we started to face this issue:

Error: Uncaught (in promise): TypeError: Cannot read properties of undefined (reading 'webpackChunkjsPDFInvoiceTemplate')
TypeError: Cannot read properties of undefined (reading 'webpackChunkjsPDFInvoiceTemplate')

Does it tell much?

Is there any solution?

CSS Customization

Hi Edison,

First of all, many thanks for your package. Really a timesaver!

Is there a way I add custom styling (font-family, size, colors, weights) or integrate with Bootstrap?

Config Table Width

Shqipe thnx for this :)
I really appreciate what you have done here, that saved me a lot of time!!

I have 1 question though:

  1. Is it possible to change width of each table since even in your example the # (number) column is taking same space just as Description and in my case I would like to make that width smaller

Looking forward to receive back,
thnx in advance
Cheers

Node.js - Image is undefined

Hey there, thanks a lot for creating this template! 👍

My use case is running this on a Node.js server (well, a single script for now 😅), and I ran into the issue that Node.js can't create new Image() objects since it's missing the DOM/window references.

I wanted to share the quick fix I applied on my end, it's a bit rough, so I didn't open a PR for it:

  if (param.logo.src) {
    var imageHeader;
    if(typeof window === "undefined") {
      imageHeader = param.logo.src;
    } else {
      imageHeader = new Image();
      imageHeader.src = param.logo.src;
    }
    //doc.text(htmlDoc.sessionDateText, docWidth - (doc.getTextWidth(htmlDoc.sessionDateText) + 10), currentHeight);
    doc.addImage(
      imageHeader,
      10 + param.logo.margin.left,
      currentHeight - 5 + param.logo.margin.top,
      param.logo.width,
      param.logo.height
    );
  }

This enables me to pass either a base64-encoded image, or an Uint8Array in Node.js, essentially exposing the first argument of the doc.addImage() function.

Trouble writing Arabic

‏‏لقطة الشاشة (289)
When entering text in Arabic, it appears in this form (þñþªþôþ³ þ•þ•þíþüþë þŽþ)
‏‏لقطة الشاشة (290)

Japanese language

Hi may I know this package can use Japanese language for pdf file such as for column. example quantity word to Japanese. Thank you

Nice!!!

Really nice template, you saved me a bunch of time!! A few tweaks are needed to run on node.js for me but great work, thanks

Invoice Template via Google Cloud Functions

Hi again,
While I love your package I was trying to get off the load from browser and create background functions using Google Cloud Functions to generate new Invoices and thus update the Invoice URL in database.

The problem I am facing with my test script is that I get this error

Error: Automatic publicPath is not supported in this browser

My function is nothing fancy, a simple exppressjs route

app.get('/generateInvoice', (req, res) => {
 const jsPDFInvoiceTemplate = require("jspdf-invoice-template");
 const props = {
  outputType: 'blob',
  ...otherProps
  }
  const pdfCreated = jsPDFInvoiceTemplate(props);
  const blob = pdfCreated.blob
  res.send(blob)
})

This is working perfectly in Browser but when I try on Cloud Function I got that error.

Error: Automatic publicPath is not supported in this browser
    at /home/besnik/Desktop/Nap Inc/functions/node_modules/jspdf-invoice-template/dist/index.js:2:351320
    at /home/besnik/Desktop/Nap Inc/functions/node_modules/jspdf-invoice-template/dist/index.js:2:351462
    at /home/besnik/Desktop/Nap Inc/functions/node_modules/jspdf-invoice-template/dist/index.js:2:352242
    at /home/besnik/Desktop/Nap Inc/functions/node_modules/jspdf-invoice-template/dist/index.js:2:81
    at Object.<anonymous> (/home/besnik/Desktop/Nap Inc/functions/node_modules/jspdf-invoice-template/dist/index.js:2:221)
    at Module._compile (internal/modules/cjs/loader.js:1085:14)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1114:10)
    at Module.load (internal/modules/cjs/loader.js:950:32)
    at Function.Module._load (internal/modules/cjs/loader.js:790:14)
    at Module.require (internal/modules/cjs/loader.js:974:19)

If I could manage to make it work, I would share the function here as well for others :)

Cheers,

Possibility to add a new table or more

I think it could be a good idea to give the possibility to add multiple table. For example some information's cannot have the same column designation name.

Generate 2 PDF Everytime

Hello,

When I'm using this template, it keeps generating two files every time I download it, save it, or open it in a new URL. Maybe you are calling a function or variable twice in your code? BTW, great project and keep the work up!

Uncaught TypeError: t is undefined

I followed the installation correctly but still have this issue of Uncaught TypeError: t is undefined index.js:2:340710 below is my code

const generatePdf = () => {
  var pdfObject = jsPDFInvoiceTemplate.default(props);
  console.log(pdfObject)
  var props = {
    outputType: jsPDFInvoiceTemplate.OutputType.Save,
    returnJsPDFDocObject: true,
    fileName: "Invoice 2021",
    orientationLandscape: false,
    logo: {
        src: "https://raw.githubusercontent.com/edisonneza/jspdf-invoice-template/demo/images/logo.png",
        type: 'PNG', //optional, when src= data:uri (nodejs case)
        width: 53.33, //aspect ratio = width/height
        height: 26.66,
        margin: {
            top: 0, //negative or positive num, from the current position
            left: 0 //negative or positive num, from the current position
        }
    },
    stamp: {
        inAllPages: true, //by default = false, just in the last page
        src: "https://raw.githubusercontent.com/edisonneza/jspdf-invoice-template/demo/images/qr_code.jpg",
        type: 'JPG', //optional, when src= data:uri (nodejs case)
        width: 20, //aspect ratio = width/height
        height: 20,
        margin: {
            top: 0, //negative or positive num, from the current position
            left: 0 //negative or positive num, from the current position
        }
    },
    business: {
        name: "Business Name",
        address: "Albania, Tirane ish-Dogana, Durres 2001",
        phone: "(+355) 069 11 11 111",
        email: "[email protected]",
        email_1: "[email protected]",
        website: "www.example.al",
    },
    contact: {
        label: "Invoice issued for:",
        name: "Client Name",
        address: "Albania, Tirane, Astir",
        phone: "(+355) 069 22 22 222",
        email: "[email protected]",
        otherInfo: "www.website.al",
    },
    invoice: {
        label: "Invoice #: ",
        num: 19,
        invDate: "Payment Date: 01/01/2021 18:12",
        invGenDate: "Invoice Date: 02/02/2021 10:17",
        headerBorder: false,
        tableBodyBorder: false,
        header: [
          {
            title: "#", 
            style: { 
              width: 10 
            } 
          }, 
          { 
            title: "Title",
            style: {
              width: 30
            } 
          }, 
          { 
            title: "Description",
            style: {
              width: 80
            } 
          }, 
          { title: "Price"},
          { title: "Quantity"},
          { title: "Unit"},
          { title: "Total"}
        ],
        table: Array.from(Array(10), (item, index)=>([
            index + 1,
            "There are many variations ",
            "Lorem Ipsum is simply dummy text dummy text ",
            200.5,
            4.5,
            "m2",
            400.5
        ])),
        additionalRows: [{
            col1: 'Total:',
            col2: '145,250.50',
            col3: 'ALL',
            style: {
                fontSize: 14 //optional, default 12
            }
        },
        {
            col1: 'VAT:',
            col2: '20',
            col3: '%',
            style: {
                fontSize: 10 //optional, default 12
            }
        },
        {
            col1: 'SubTotal:',
            col2: '116,199.90',
            col3: 'ALL',
            style: {
                fontSize: 10 //optional, default 12
            }
        }],
        invDescLabel: "Invoice Note",
        invDesc: "There are many variations of passages of Lorem Ipsum available, but the majority have suffered alteration in some form, by injected humour, or randomised words which don't look even slightly believable. If you are going to use a passage of Lorem Ipsum, you need to be sure there isn't anything embarrassing hidden in the middle of text. All the Lorem Ipsum generators on the Internet tend to repeat predefined chunks as necessary.",
    },
    footer: {
        text: "The invoice is created on a computer and is valid without the signature and stamp.",
    },
    pageEnable: true,
    pageLabel: "Page ",
};
}


Semi missing license

The package.json specifies the ISC License, however the Readme.md only includes a part of the relevant legal text.
https://en.wikipedia.org/wiki/ISC_license#License_terms

Especially the following part is missing

Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.

Add a stamp

Hi @edisonneza

thanks for your package, it is very useful

I suggest the feature of adding a stamp as an image below the rows

nextjs ERROR

TypeError: Cannot read property 'bind' of undefined

NodeJS support

I am getting this error when I try to use this on NodeJS (ExpressJS)

"Error: Automatic publicPath is not supported in this browser"

Adding Columns to Footer

Can you enhance the footer?
Instead of only the text to a maybe 3-4 line height text with styling and font sizes?
Often you need to put legal information on an invoice like tax-numbers and stuff like this.
Also the text then should adjustable in the row or table with an option to align it left, center, right.

That would be awesome!

Example:

https://www.whmcs-deutschland.eu/wcf/index.php?attachment/204-rechnung-762-page-001-jpg/

maybe like this:

footer?: {
 *       text?: string,
 *   },
 *   footer1?: {
 *       text?: string,
 *       align?: string,
 *       style?: { width?: number },
 *       margin?: {
 *        bottom?: number,
 *        left?: number
 *      }
 *   },
 *   footer2?: {
 *       text?: string,
 *       align?: string,
 *       style?: { width?: number },
 *       margin?: {
 *        bottom?: number,
 *        left?: number
 *      }
 *   },
 *   footer3?: {
 *       text?: string,
 *       align?: string,
 *       style?: { width?: number },
 *       margin?: {
 *        bottom?: number,
 *        left?: number
 *      }
 *   },
 //...
 
  if (param.pageEnable) {
        // current state:
        //doc.text(docWidth / 2, docHeight - 10, param.footer.text, "left");
        //added here also with the margin.
        doc.text(docWidth / 2, docHeight - 10, param.footer1.text, param.footer1.align);
        doc.text(docWidth / 2, docHeight - 10, param.footer2.text, param.footer2.align);
        doc.text(docWidth / 2, docHeight - 10, param.footer3.text, param.footer3.align);
        doc.setPage(i);
        doc.text(
          param.pageLabel + " " + i + " / " + doc.getNumberOfPages(),
          docWidth - 20,
          doc.internal.pageSize.height - 6
        );
      }
```

Invalid Hook Call

I created an arrow function called PdfObject, which loops through an array and calls the jsPDFInvoiceTemplate. However, I also put a use state hook (a hook), and I try to set some state and modify the values. However, I get the
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:

  1. You might have mismatching versions of React and the renderer (such as React DOM)
  2. You might be breaking the Rules of Hooks
  3. You might have more than one copy of React in the same app

const PdfObject = () => {
const [newState, setNewState] = useState(
{..some value})

array.forEach((item) => {

setNewState(...)

var props = {
  ...
}

//Calls The PDF generation
jsPDFInvoiceTemplate(props)

})
}

Question

Hi!

I like your template, but i want to create a little bit different template for my website like in video. Do you know where to do that? Any video link?

Using Data URLS for the Logo

When configuring the props for the jsPDFInvoiceTemplate, is it possible to use a data URL for the source in a logo?

var props = {

logo: {
src: '',
type: 'JPEG', //optional, when src= data:uri (nodejs case)
width: 80, //aspect ratio = width/height
height: 30,
margin: {
top: 0, //negative or positive num, from the current position
left: 0, //negative or positive num, from the current position
},
},
}

In the src, I want to add a data URL rather than a URL link. Thanks!

For Loop Dynamic Rendering, Saves Only 10 Times

Hello, I have an issue where when I loop through an array of items, the output type of "Save" can only download the different pdfs 10 times. So, if I have 20 items in the array, it can only download 10 of them. However, if I have 4 items in the array, it can download all 4 because it's less than 10. Idk if this is an issue with the jspdf save function since when I do OutputType of DataUrlNewWindow, it can open all 20 jsPDFInvoiceTemplate in the browser. I want to be able to use the output type of Save and download all the pdfs in the for loop

Code example:

//Loop through each item and generate PDF for each vendor

array.forEach((item) => {
quoteCounter++

var props = {
  outputType: OutputType.Save,
  returnJsPDFDocObject: true,
  fileName: `Quote #${quoteCounter} ${vendor.slice(0, 3).toUpperCase()}`,
 ...
}
jsPDFInvoiceTemplate(props)

})

Error when running Angular Cordova application

I followed the documentation and imported jspdf-invoice-template, but getting below error

ERROR in ./node_modules/jspdf-invoice-template/src/index.js 90:22
Module parse failed: Unexpected token (90:22)
You may need an appropriate loader to handle this file type, currently no loaders are configured to process this file. See https://webpack.js.org/concepts#loaders
| orientationLandscape: props.orientationLandscape || false,
| logo: {

  src: props.logo?.src || "",

| width: props.logo?.width || "",
| height: props.logo?.height || "",

Please let me know what i am missing?

Printable safe area paddings - Magic numbers manual page break wrap around for invoice description footer aesthetic?

if (param.orientationLandscape && currentHeight + invDescSize > 183) {

if (!param.orientationLandscape && currentHeight + invDescSize > 270) {

Would we be correct in assuming that these magic numbers for 183mm and 270mm are directly proportional to the A4 dimensions for sizing?

both are 27mm below A4 paper dimensions 210mm 270mm

My first impression is that the y-coord (currentHeight) potentially near the end of page should wrap to the next page.

Appears to be a hard-coded 27mm condition which may equate to about three lines of text?

Printable "safe area" aesthetic adjustments?

--

There are other number constants used to adjust as well throughout the code, I thought I would suggest this as one of the more accessible places to refactor

Directly saving as PDF - Node

Hi this code works in Node 18 to generate the datauri string.

var pdfCreated = jsPDFInvoiceTemplate.default({
    ...invoiceObject,
    outputType: OutputType.DataUriString,
    returnJsPDFDocObject: true,
    fileName: "Invoice 2024",
    orientationLandscape: false,
    compress: true
});

console.log(pdfCreated.dataUriString);

How to save this directly as pdf? I think there is a function but I dont get it.
Thanks!

using blob , prepend an image and upload to firebase storage doesn't work, but saving locally works

hi,

Thanks for the great work.
I'm trying to prepend a signature image at the bottom, and able to get it work when save locally

var img = resizeBase64(imageURL, 128, 128);
var props = {
        outputType: "blob",
        returnJsPDFDocObject: true,
...
const pdfObject = jsPDFInvoiceTemplate(props);
pdfObject.jsPDFDocObject.addImage(img, "jpeg", 10, 250); 
pdfObject.jsPDFDocObject.save(`${newFileName}.pdf`);  // this works correctly, with the image at the bottom.

var blob = pdfObject.blob; 
var path = `pdfs/${newFileName}.pdf`; 
const pdfRef = ref(storage, path);

uploadBytes(pdfRef, blob) // blob here seems still refer to the original PDF, not the one with addImage
      .then(() => {
        toast.success("PDF uploaded successfully");
      })
      .catch(() => {
        toast.error("PDF upload failed");
      });

However the PDF on the firebase is missing the image (it's the original PDF) , I suspect the way I use blob maybe incorrect, could you advise?

Compress PDF

Hi Edison, thank you for this!

I would like we had a boolean option to compress the PDF.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.