mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 21:00:31 +00:00
feat: rendering pdf templates on the server-side
This commit is contained in:
@@ -12,10 +12,15 @@ import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
} from '@blueprintjs/core';
|
||||
import { If, Icon, FormattedMessage as T, Group } from '@/components';
|
||||
import { If, Icon, FormattedMessage as T, Group, FSelect } from '@/components';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import classNames from 'classnames';
|
||||
import { useCreditNoteFormContext } from './CreditNoteFormProvider';
|
||||
import {
|
||||
BrandingThemeFormGroup,
|
||||
BrandingThemeSelectButton,
|
||||
} from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
import { useCreditNoteFormBrandingTemplatesOptions } from './utils';
|
||||
|
||||
/**
|
||||
* Credit note floating actions.
|
||||
@@ -74,6 +79,8 @@ export default function CreditNoteFloatingActions() {
|
||||
resetForm();
|
||||
};
|
||||
|
||||
const brandingTemplatesOptions = useCreditNoteFormBrandingTemplatesOptions();
|
||||
|
||||
return (
|
||||
<Group
|
||||
spacing={10}
|
||||
@@ -190,6 +197,25 @@ export default function CreditNoteFloatingActions() {
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOptions}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ import {
|
||||
useSettingsCreditNotes,
|
||||
useInvoice,
|
||||
} from '@/hooks/query';
|
||||
import { useGetPdfTemplates } from '@/hooks/query/pdf-templates';
|
||||
|
||||
const CreditNoteFormContext = React.createContext();
|
||||
|
||||
@@ -73,6 +74,10 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
||||
isSuccess: isBranchesSuccess,
|
||||
} = useBranches({}, { enabled: isBranchFeatureCan });
|
||||
|
||||
// Fetches branding templates of invoice.
|
||||
const { data: brandingTemplates, isLoading: isBrandingTemplatesLoading } =
|
||||
useGetPdfTemplates({ resource: 'PaymentReceive' });
|
||||
|
||||
// Handle fetching settings.
|
||||
useSettingsCreditNotes();
|
||||
|
||||
@@ -115,13 +120,18 @@ function CreditNoteFormProvider({ creditNoteId, ...props }) {
|
||||
createCreditNoteMutate,
|
||||
editCreditNoteMutate,
|
||||
setSubmitPayload,
|
||||
|
||||
// Branding templates.
|
||||
brandingTemplates,
|
||||
isBrandingTemplatesLoading,
|
||||
};
|
||||
|
||||
const isLoading =
|
||||
isItemsLoading ||
|
||||
isCustomersLoading ||
|
||||
isCreditNoteLoading ||
|
||||
isInvoiceLoading;
|
||||
isInvoiceLoading ||
|
||||
isBrandingTemplatesLoading;
|
||||
|
||||
return (
|
||||
<DashboardInsider loading={isLoading} name={'credit-note-form'}>
|
||||
|
||||
@@ -24,6 +24,7 @@ import {
|
||||
transformAttachmentsToForm,
|
||||
transformAttachmentsToRequest,
|
||||
} from '@/containers/Attachments/utils';
|
||||
import { convertBrandingTemplatesToOptions } from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
|
||||
export const MIN_LINES_NUMBER = 1;
|
||||
|
||||
@@ -54,7 +55,8 @@ export const defaultCreditNote = {
|
||||
exchange_rate: 1,
|
||||
currency_code: '',
|
||||
entries: [...repeatValue(defaultCreditNoteEntry, MIN_LINES_NUMBER)],
|
||||
attachments: []
|
||||
attachments: [],
|
||||
pdf_template_id: '',
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -214,3 +216,13 @@ export const useCreditNoteIsForeignCustomer = () => {
|
||||
);
|
||||
return isForeignCustomer;
|
||||
};
|
||||
|
||||
|
||||
export const useCreditNoteFormBrandingTemplatesOptions = () => {
|
||||
const { brandingTemplates } = useCreditNoteFormContext();
|
||||
|
||||
return React.useMemo(
|
||||
() => convertBrandingTemplatesToOptions(brandingTemplates),
|
||||
[brandingTemplates],
|
||||
);
|
||||
};
|
||||
|
||||
@@ -11,11 +11,16 @@ import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
} from '@blueprintjs/core';
|
||||
import { If, Icon, FormattedMessage as T, Group } from '@/components';
|
||||
import { If, Icon, FormattedMessage as T, Group, FSelect } from '@/components';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { useEstimateFormContext } from './EstimateFormProvider';
|
||||
import { useEstimateFormBrandingTemplatesOptions } from './utils';
|
||||
import {
|
||||
BrandingThemeFormGroup,
|
||||
BrandingThemeSelectButton,
|
||||
} from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
|
||||
/**
|
||||
* Estimate floating actions bar.
|
||||
@@ -73,6 +78,8 @@ export default function EstimateFloatingActions() {
|
||||
resetForm();
|
||||
};
|
||||
|
||||
const brandingTemplatesOptions = useEstimateFormBrandingTemplatesOptions();
|
||||
|
||||
return (
|
||||
<Group
|
||||
spacing={10}
|
||||
@@ -193,6 +200,25 @@ export default function EstimateFloatingActions() {
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOptions}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -12,8 +12,9 @@ import {
|
||||
useCreateEstimate,
|
||||
useEditEstimate,
|
||||
} from '@/hooks/query';
|
||||
import { Features } from '@/constants';
|
||||
import { useProjects } from '@/containers/Projects/hooks';
|
||||
import { useGetPdfTemplates } from '@/hooks/query/pdf-templates';
|
||||
import { Features } from '@/constants';
|
||||
import { useFeatureCan } from '@/hooks/state';
|
||||
import { ITEMS_FILTER_ROLES } from './utils';
|
||||
|
||||
@@ -71,6 +72,10 @@ function EstimateFormProvider({ query, estimateId, ...props }) {
|
||||
isLoading: isProjectsLoading,
|
||||
} = useProjects({}, { enabled: !!isProjectsFeatureCan });
|
||||
|
||||
// Fetches branding templates of invoice.
|
||||
const { data: brandingTemplates, isLoading: isBrandingTemplatesLoading } =
|
||||
useGetPdfTemplates({ resource: 'SaleEstimate' });
|
||||
|
||||
// Handle fetch settings.
|
||||
useSettingsEstimates();
|
||||
|
||||
@@ -112,13 +117,19 @@ function EstimateFormProvider({ query, estimateId, ...props }) {
|
||||
|
||||
createEstimateMutate,
|
||||
editEstimateMutate,
|
||||
|
||||
brandingTemplates,
|
||||
isBrandingTemplatesLoading,
|
||||
};
|
||||
|
||||
const isLoading =
|
||||
isCustomersLoading ||
|
||||
isItemsLoading ||
|
||||
isEstimateLoading ||
|
||||
isBrandingTemplatesLoading;
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={isCustomersLoading || isItemsLoading || isEstimateLoading}
|
||||
name={'estimate-form'}
|
||||
>
|
||||
<DashboardInsider loading={isLoading} name={'estimate-form'}>
|
||||
<EstimateFormContext.Provider value={provider} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
transformAttachmentsToForm,
|
||||
transformAttachmentsToRequest,
|
||||
} from '@/containers/Attachments/utils';
|
||||
import { convertBrandingTemplatesToOptions } from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
|
||||
export const MIN_LINES_NUMBER = 1;
|
||||
|
||||
@@ -60,7 +61,8 @@ export const defaultEstimate = {
|
||||
exchange_rate: 1,
|
||||
currency_code: '',
|
||||
entries: [...repeatValue(defaultEstimateEntry, MIN_LINES_NUMBER)],
|
||||
attachments: []
|
||||
attachments: [],
|
||||
pdf_template_id: '',
|
||||
};
|
||||
|
||||
const ERRORS = {
|
||||
@@ -262,3 +264,12 @@ export const resetFormState = ({ initialValues, values, resetForm }) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useEstimateFormBrandingTemplatesOptions = () => {
|
||||
const { brandingTemplates } = useEstimateFormContext();
|
||||
|
||||
return React.useMemo(
|
||||
() => convertBrandingTemplatesToOptions(brandingTemplates),
|
||||
[brandingTemplates],
|
||||
);
|
||||
};
|
||||
|
||||
@@ -25,6 +25,7 @@ import {
|
||||
DashboardFilterButton,
|
||||
DashboardRowsHeightButton,
|
||||
DashboardActionsBar,
|
||||
FSelect,
|
||||
} from '@/components';
|
||||
|
||||
import withEstimates from './withEstimates';
|
||||
@@ -42,6 +43,10 @@ import { compose } from '@/utils';
|
||||
import { DialogsName } from '@/constants/dialogs';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
import {
|
||||
BrandingThemeFormGroup,
|
||||
BrandingThemeSelectButton,
|
||||
} from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
|
||||
/**
|
||||
* Estimates list actions bar.
|
||||
|
||||
@@ -12,10 +12,15 @@ import {
|
||||
MenuItem,
|
||||
} from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { Group, Icon, FormattedMessage as T } from '@/components';
|
||||
import { FSelect, Group, Icon, FormattedMessage as T } from '@/components';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { usePaymentReceiveFormContext } from './PaymentReceiveFormProvider';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import {
|
||||
BrandingThemeFormGroup,
|
||||
BrandingThemeSelectButton,
|
||||
} from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
import { usePaymentReceivedFormBrandingTemplatesOptions } from './utils';
|
||||
|
||||
/**
|
||||
* Payment receive floating actions bar.
|
||||
@@ -53,6 +58,9 @@ export default function PaymentReceiveFormFloatingActions() {
|
||||
submitForm();
|
||||
};
|
||||
|
||||
const brandingTemplatesOpts =
|
||||
usePaymentReceivedFormBrandingTemplatesOptions();
|
||||
|
||||
return (
|
||||
<Group
|
||||
spacing={10}
|
||||
@@ -109,6 +117,25 @@ export default function PaymentReceiveFormFloatingActions() {
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOpts}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import {
|
||||
useCreatePaymentReceive,
|
||||
useEditPaymentReceive,
|
||||
} from '@/hooks/query';
|
||||
import { useGetPdfTemplates } from '@/hooks/query/pdf-templates';
|
||||
|
||||
// Payment receive form context.
|
||||
const PaymentReceiveFormContext = createContext();
|
||||
@@ -65,6 +66,10 @@ function PaymentReceiveFormProvider({ query, paymentReceiveId, ...props }) {
|
||||
isLoading: isProjectsLoading,
|
||||
} = useProjects({}, { enabled: !!isProjectsFeatureCan });
|
||||
|
||||
// Fetches branding templates of payment received module.
|
||||
const { data: brandingTemplates, isLoading: isBrandingTemplatesLoading } =
|
||||
useGetPdfTemplates({ resource: 'PaymentReceive' });
|
||||
|
||||
// Detarmines whether the new mode.
|
||||
const isNewMode = !paymentReceiveId;
|
||||
|
||||
@@ -102,13 +107,20 @@ function PaymentReceiveFormProvider({ query, paymentReceiveId, ...props }) {
|
||||
|
||||
isExcessConfirmed,
|
||||
setIsExcessConfirmed,
|
||||
|
||||
// Branding templates
|
||||
brandingTemplates,
|
||||
isBrandingTemplatesLoading,
|
||||
};
|
||||
|
||||
const isLoading =
|
||||
isPaymentLoading ||
|
||||
isAccountsLoading ||
|
||||
isCustomersLoading ||
|
||||
isBrandingTemplatesLoading;
|
||||
|
||||
return (
|
||||
<DashboardInsider
|
||||
loading={isPaymentLoading || isAccountsLoading || isCustomersLoading}
|
||||
name={'payment-receive-form'}
|
||||
>
|
||||
<DashboardInsider loading={isLoading} name={'payment-receive-form'}>
|
||||
<PaymentReceiveFormContext.Provider value={provider} {...props} />
|
||||
</DashboardInsider>
|
||||
);
|
||||
|
||||
@@ -19,6 +19,7 @@ import {
|
||||
transformAttachmentsToForm,
|
||||
transformAttachmentsToRequest,
|
||||
} from '@/containers/Attachments/utils';
|
||||
import { convertBrandingTemplatesToOptions } from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
|
||||
// Default payment receive entry.
|
||||
export const defaultPaymentReceiveEntry = {
|
||||
@@ -44,10 +45,11 @@ export const defaultPaymentReceive = {
|
||||
statement: '',
|
||||
amount: '',
|
||||
currency_code: '',
|
||||
branch_id: '',
|
||||
exchange_rate: 1,
|
||||
entries: [],
|
||||
attachments: [],
|
||||
branch_id: '',
|
||||
pdf_template_id: '',
|
||||
};
|
||||
|
||||
export const defaultRequestPaymentEntry = {
|
||||
@@ -303,3 +305,12 @@ export const getExceededAmountFromValues = (values) => {
|
||||
|
||||
return totalAmount - totalApplied;
|
||||
};
|
||||
|
||||
export const usePaymentReceivedFormBrandingTemplatesOptions = () => {
|
||||
const { brandingTemplates } = usePaymentReceiveFormContext();
|
||||
|
||||
return React.useMemo(
|
||||
() => convertBrandingTemplatesToOptions(brandingTemplates),
|
||||
[brandingTemplates],
|
||||
);
|
||||
};
|
||||
|
||||
@@ -11,12 +11,17 @@ import {
|
||||
Menu,
|
||||
MenuItem,
|
||||
} from '@blueprintjs/core';
|
||||
import { Group, FormattedMessage as T } from '@/components';
|
||||
import { FSelect, Group, FormattedMessage as T } from '@/components';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { If, Icon } from '@/components';
|
||||
import { useReceiptFormContext } from './ReceiptFormProvider';
|
||||
import { useReceiptFormBrandingTemplatesOptions } from './utils';
|
||||
import {
|
||||
BrandingThemeFormGroup,
|
||||
BrandingThemeSelectButton,
|
||||
} from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
|
||||
/**
|
||||
* Receipt floating actions bar.
|
||||
@@ -76,6 +81,8 @@ export default function ReceiptFormFloatingActions() {
|
||||
resetForm();
|
||||
};
|
||||
|
||||
const brandingTemplatesOptions = useReceiptFormBrandingTemplatesOptions();
|
||||
|
||||
return (
|
||||
<Group
|
||||
spacing={10}
|
||||
@@ -191,6 +198,25 @@ export default function ReceiptFormFloatingActions() {
|
||||
onClick={handleCancelBtnClick}
|
||||
text={<T id={'cancel'} />}
|
||||
/>
|
||||
|
||||
{/* ----------- Branding Template Select ----------- */}
|
||||
<BrandingThemeFormGroup
|
||||
name={'pdf_template_id'}
|
||||
label={'Branding'}
|
||||
inline
|
||||
fastField
|
||||
style={{ marginLeft: 20 }}
|
||||
>
|
||||
<FSelect
|
||||
name={'pdf_template_id'}
|
||||
items={brandingTemplatesOptions}
|
||||
input={({ activeItem, text, label, value }) => (
|
||||
<BrandingThemeSelectButton text={text || 'Brand Theme'} minimal />
|
||||
)}
|
||||
filterable={false}
|
||||
popoverProps={{ minimal: true }}
|
||||
/>
|
||||
</BrandingThemeFormGroup>
|
||||
</Group>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
useEditReceipt,
|
||||
} from '@/hooks/query';
|
||||
import { useProjects } from '@/containers/Projects/hooks';
|
||||
import { useGetPdfTemplates } from '@/hooks/query/pdf-templates';
|
||||
|
||||
const ReceiptFormContext = createContext();
|
||||
|
||||
@@ -77,7 +78,7 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
[],
|
||||
);
|
||||
|
||||
// Handle fetch Items data table or list
|
||||
// Handle fetch Items data table or list.
|
||||
const {
|
||||
data: { items },
|
||||
isLoading: isItemsLoading,
|
||||
@@ -85,13 +86,16 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
page_size: 10000,
|
||||
stringified_filter_roles: stringifiedFilterRoles,
|
||||
});
|
||||
|
||||
// Fetch project list.
|
||||
const {
|
||||
data: { projects },
|
||||
isLoading: isProjectsLoading,
|
||||
} = useProjects({}, { enabled: !!isProjectsFeatureCan });
|
||||
|
||||
// Fetches branding templates of receipt.
|
||||
const { data: brandingTemplates, isLoading: isBrandingTemplatesLoading } =
|
||||
useGetPdfTemplates({ resource: 'SaleReceipt' });
|
||||
|
||||
// Fetch receipt settings.
|
||||
const { isLoading: isSettingLoading } = useSettingsReceipts();
|
||||
|
||||
@@ -101,7 +105,6 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
const [submitPayload, setSubmitPayload] = useState({});
|
||||
|
||||
const isNewMode = !receiptId;
|
||||
|
||||
const isFeatureLoading = isWarehouesLoading || isBranchesLoading;
|
||||
|
||||
const provider = {
|
||||
@@ -130,6 +133,10 @@ function ReceiptFormProvider({ receiptId, ...props }) {
|
||||
createReceiptMutate,
|
||||
editReceiptMutate,
|
||||
setSubmitPayload,
|
||||
|
||||
// Branding templates
|
||||
brandingTemplates,
|
||||
isBrandingTemplatesLoading
|
||||
};
|
||||
return (
|
||||
<DashboardInsider
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
transformAttachmentsToForm,
|
||||
transformAttachmentsToRequest,
|
||||
} from '@/containers/Attachments/utils';
|
||||
import { convertBrandingTemplatesToOptions } from '@/containers/BrandingTemplates/BrandingTemplatesSelectFields';
|
||||
|
||||
export const MIN_LINES_NUMBER = 1;
|
||||
|
||||
@@ -61,6 +62,7 @@ export const defaultReceipt = {
|
||||
currency_code: '',
|
||||
entries: [...repeatValue(defaultReceiptEntry, MIN_LINES_NUMBER)],
|
||||
attachments: [],
|
||||
pdf_template_id: '',
|
||||
};
|
||||
|
||||
const ERRORS = {
|
||||
@@ -272,3 +274,12 @@ export const resetFormState = ({ initialValues, values, resetForm }) => {
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useReceiptFormBrandingTemplatesOptions = () => {
|
||||
const { brandingTemplates } = useReceiptFormContext();
|
||||
|
||||
return React.useMemo(
|
||||
() => convertBrandingTemplatesToOptions(brandingTemplates),
|
||||
[brandingTemplates],
|
||||
);
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user