diff --git a/packages/server/src/api/controllers/Sales/SalesInvoices.ts b/packages/server/src/api/controllers/Sales/SalesInvoices.ts index 4393b21ff..999806a17 100644 --- a/packages/server/src/api/controllers/Sales/SalesInvoices.ts +++ b/packages/server/src/api/controllers/Sales/SalesInvoices.ts @@ -450,15 +450,15 @@ export default class SaleInvoicesController extends BaseController { ACCEPT_TYPE.APPLICATION_JSON, ACCEPT_TYPE.APPLICATION_PDF, ]); - // Retrieves invoice in pdf format. - if (true) { + // Retrieves invoice in PDF format. + if (ACCEPT_TYPE.APPLICATION_PDF === acceptType) { const [pdfContent, filename] = await this.saleInvoiceApplication.saleInvoicePdf( tenantId, saleInvoiceId ); res.set({ - 'Content-Type': 'text/html', + 'Content-Type': 'application/pdf', 'Content-Length': pdfContent.length, 'Content-Disposition': `attachment; filename="${filename}"`, }); diff --git a/packages/server/src/services/Sales/Invoices/SaleInvoicePdf.ts b/packages/server/src/services/Sales/Invoices/SaleInvoicePdf.ts index c2e66557a..394c8c222 100644 --- a/packages/server/src/services/Sales/Invoices/SaleInvoicePdf.ts +++ b/packages/server/src/services/Sales/Invoices/SaleInvoicePdf.ts @@ -47,16 +47,9 @@ export class SaleInvoicePdf { tenantId, invoiceId ); - // const htmlContent = await this.templateInjectable.render( - // tenantId, - // 'modules/invoice-standard', - // brandingAttributes - // ); - - const htmlContent = renderInvoicePaperTemplateHtml({}); - - console.log(htmlContent); - + const htmlContent = renderInvoicePaperTemplateHtml({ + ...brandingAttributes, + }); // Converts the given html content to pdf document. const buffer = await this.chromiumlyTenancy.convertHtmlContent( tenantId, @@ -69,7 +62,7 @@ export class SaleInvoicePdf { events.saleInvoice.onPdfViewed, eventPayload ); - return [htmlContent, filename]; + return [buffer, filename]; } /** diff --git a/shared/pdf-templates/src/components/InvoicePaperTemplate.tsx b/shared/pdf-templates/src/components/InvoicePaperTemplate.tsx index 0c0dbfa4b..5e718b107 100644 --- a/shared/pdf-templates/src/components/InvoicePaperTemplate.tsx +++ b/shared/pdf-templates/src/components/InvoicePaperTemplate.tsx @@ -243,15 +243,15 @@ export function InvoicePaperTemplate({ {data.item} {data.description} ), }, - { label: lineQuantityLabel, accessor: 'quantity' }, + { label: lineQuantityLabel, accessor: 'quantity', align: 'right' }, { label: lineRateLabel, accessor: 'rate', align: 'right' }, { label: lineTotalLabel, accessor: 'total', align: 'right' }, ]} diff --git a/shared/pdf-templates/src/components/PaperTemplate.tsx b/shared/pdf-templates/src/components/PaperTemplate.tsx index d51a7ca3b..1953959f6 100644 --- a/shared/pdf-templates/src/components/PaperTemplate.tsx +++ b/shared/pdf-templates/src/components/PaperTemplate.tsx @@ -20,10 +20,9 @@ export function PaperTemplate({ }: PaperTemplateProps) { return ( {children} @@ -39,16 +46,6 @@ export function PaperTemplate({ ); } -interface PaperTemplateTableProps { - columns: Array<{ - accessor: string | ((data: Record) => JSX.Element); - label: string; - value?: JSX.Element; - align?: 'left' | 'center' | 'right'; - }>; - data: Array>; -} - interface PaperTemplateBigTitleProps { title: string; } @@ -86,6 +83,16 @@ PaperTemplate.Logo = ({ logoUri }: PaperTemplateLogoProps) => { ); }; +interface PaperTemplateTableProps { + columns: Array<{ + accessor: string | ((data: Record) => JSX.Element); + label: string; + value?: JSX.Element; + align?: 'left' | 'center' | 'right'; + }>; + data: Array>; +} + PaperTemplate.Table = ({ columns, data }: PaperTemplateTableProps) => { return ( { {columns.map((col, index) => ( - + ))} @@ -144,11 +151,11 @@ PaperTemplate.Table = ({ columns, data }: PaperTemplateTableProps) => { {data.map((_data: any) => ( {columns.map((column, index) => ( - + ))} ))} @@ -183,6 +190,7 @@ const totalBottomBordered = css` const totalBottomGrayBordered = css` border-bottom: 1px solid #dadada; `; + PaperTemplate.TotalLine = ({ label, amount, @@ -262,7 +270,9 @@ PaperTemplate.TermsItem = ({ }) => { return ( - {label} + + {label} + {children} ); diff --git a/shared/pdf-templates/src/components/PaperTemplateLayout.tsx b/shared/pdf-templates/src/components/PaperTemplateLayout.tsx index 5d8c233af..07e1ad2de 100644 --- a/shared/pdf-templates/src/components/PaperTemplateLayout.tsx +++ b/shared/pdf-templates/src/components/PaperTemplateLayout.tsx @@ -1,7 +1,7 @@ import { CacheProvider, ThemeProvider } from '@emotion/react'; import { EmotionCache } from '@emotion/cache'; import { defaultTheme } from '@xstyled/system'; -import { Preflight } from '@xstyled/emotion'; +import { createGlobalStyle, Preflight } from '@xstyled/emotion'; const theme = { ...defaultTheme, @@ -17,8 +17,50 @@ export function PaperTemplateLayout({ + + {children} ); } + +// Create global styles to set the body font +const GlobalStyles = createGlobalStyle` +*, +*::before, +*::after { + box-sizing: border-box; +} +th { + text-align: inherit; + text-align: -webkit-match-parent; +} +thead, +tbody, +tfoot, +tr, +td, +th { + border-color: inherit; + border-style: solid; + border-width: 0; +} + +body{ + margin: 0; + font-size: 1rem; + font-weight: 400; + line-height: 1.5; + color: #000; + background-color: #fff; + -webkit-text-size-adjust: 100%; + -webkit-tap-highlight-color: transparent; +} + +body, h1, h2, h3, h4, h5, h6{ + font-family: "Open Sans", sans-serif; + font-optical-sizing: auto; + font-style: normal; +} +`; diff --git a/shared/pdf-templates/src/constants.ts b/shared/pdf-templates/src/constants.ts new file mode 100644 index 000000000..839b3949f --- /dev/null +++ b/shared/pdf-templates/src/constants.ts @@ -0,0 +1,5 @@ +export const OpenSansFontLink = ` + + + +`; diff --git a/shared/pdf-templates/src/lib/text/Text.tsx b/shared/pdf-templates/src/lib/text/Text.tsx index eabe132cf..e65b05472 100644 --- a/shared/pdf-templates/src/lib/text/Text.tsx +++ b/shared/pdf-templates/src/lib/text/Text.tsx @@ -1,5 +1,9 @@ -import { x } from '@xstyled/emotion'; +import { SystemProps, x } from '@xstyled/emotion'; -export const Text = ({ children }: { children: React.ReactNode }) => { - return {children}; +export interface TextProps extends SystemProps { + children?: React.ReactNode; +} + +export const Text = ({ children, ...restProps }: TextProps) => { + return {children}; }; diff --git a/shared/pdf-templates/src/renders/render-invoice-paper-template.tsx b/shared/pdf-templates/src/renders/render-invoice-paper-template.tsx index dea926919..e34d85e25 100644 --- a/shared/pdf-templates/src/renders/render-invoice-paper-template.tsx +++ b/shared/pdf-templates/src/renders/render-invoice-paper-template.tsx @@ -1,36 +1,21 @@ import { renderToString } from 'react-dom/server'; import createCache from '@emotion/cache'; +import { css } from '@emotion/css'; import { InvoicePaperTemplate, InvoicePaperTemplateProps, } from '../components/InvoicePaperTemplate'; import { PaperTemplateLayout } from '../components/PaperTemplateLayout'; import { extractCritical } from '@emotion/server'; +import { OpenSansFontLink } from '../constants'; +import { renderSSR } from './render-ssr'; export const renderInvoicePaperTemplateHtml = ( props: InvoicePaperTemplateProps ) => { - const key = 'invoice-paper-template'; - const cache = createCache({ key }); - - const renderedHtml = renderToString( - - - + return renderSSR( + ); - const { html, css, ids } = extractCritical(renderedHtml); - - return ` - - - - - - Invoice - - - -
${html}
- -`; }; diff --git a/shared/pdf-templates/src/renders/render-ssr.tsx b/shared/pdf-templates/src/renders/render-ssr.tsx new file mode 100644 index 000000000..25a067e3b --- /dev/null +++ b/shared/pdf-templates/src/renders/render-ssr.tsx @@ -0,0 +1,31 @@ +import { renderToString } from 'react-dom/server'; +import createCache from '@emotion/cache'; +import { extractCritical } from '@emotion/server'; +import { OpenSansFontLink } from '../constants'; +import { PaperTemplateLayout } from '../components/PaperTemplateLayout'; + +export const renderSSR = (children: React.ReactNode) => { + const key = 'invoice-paper-template'; + const cache = createCache({ key }); + + const renderedHtml = renderToString( + {children} + ); + const extractedHtml = extractCritical(renderedHtml); + + return ` + + + + + + Invoice + ${OpenSansFontLink} + + + +
${extractedHtml.html}
+ +`; +};
+ {col.label} -
+ {isFunction(column?.accessor) ? column?.accessor(_data) : get(_data, column.accessor)} -