Skip to content

Commit

Permalink
Merge pull request #463 from invoiceninja/develop
Browse files Browse the repository at this point in the history
Sync develop with main
  • Loading branch information
beganovich authored Feb 10, 2023
2 parents c8ae47f + 4450e17 commit 16dcaaa
Show file tree
Hide file tree
Showing 33 changed files with 405 additions and 325 deletions.
1 change: 0 additions & 1 deletion .env.example
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
VITE_API_URL=
VITE_IS_HOSTED=false
VITE_APP_TITLE="Invoice Ninja"
VITE_IS_PRODUCTION=false

# Supported values: "browser", "hash"
VITE_ROUTER=hash
Expand Down
2 changes: 1 addition & 1 deletion src/common/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,5 +105,5 @@ export function isDemo() {
}

export function isProduction() {
return import.meta.env.VITE_IS_PRODUCTION === 'true';
return import.meta.env.PROD;
}
10 changes: 7 additions & 3 deletions src/common/queries/products.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { route } from 'common/helpers/route';
import { endpoint } from '../helpers';
import { Product } from 'common/interfaces/product';
import { GenericSingleResourceResponse } from 'common/interfaces/generic-api-response';
import { GenericQueryOptions } from './invoices';

export function useProductsQuery() {
return useQuery<Product[]>(
Expand All @@ -35,11 +36,14 @@ export function useProductQuery(params: { id: string | undefined }) {
{ staleTime: Infinity }
);
}
export function useBlankProductQuery() {
export function useBlankProductQuery(options?: GenericQueryOptions) {
return useQuery(
route('/api/v1/products/create'),
() => request('GET', endpoint('/api/v1/products/create')),
{ staleTime: Infinity }
() =>
request('GET', endpoint('/api/v1/products/create')).then(
(response: GenericSingleResourceResponse<Product>) => response.data.data
),
{ ...options, staleTime: Infinity }
);
}

Expand Down
8 changes: 5 additions & 3 deletions src/common/queries/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,17 @@ import { request } from 'common/helpers/request';
import { Project } from 'common/interfaces/project';
import { useQuery } from 'react-query';
import { route } from 'common/helpers/route';
import { GenericQueryOptions } from './invoices';
import { GenericSingleResourceResponse } from 'common/interfaces/generic-api-response';

export function useBlankProjectQuery() {
export function useBlankProjectQuery(options?: GenericQueryOptions) {
return useQuery<Project>(
'/api/v1/projects/create',
() =>
request('GET', endpoint('/api/v1/projects/create')).then(
(response) => response.data.data
(response: GenericSingleResourceResponse<Project>) => response.data.data
),
{ staleTime: Infinity }
{ ...options, staleTime: Infinity }
);
}

Expand Down
15 changes: 10 additions & 5 deletions src/common/queries/tasks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { GenericManyResponse } from 'common/interfaces/generic-many-response';
import { Task } from 'common/interfaces/task';
import { useQuery } from 'react-query';
import { route } from 'common/helpers/route';
import { GenericQueryOptions } from './invoices';
import { GenericSingleResourceResponse } from 'common/interfaces/generic-api-response';

interface TaskParams {
id?: string;
Expand All @@ -31,11 +33,14 @@ export function useTaskQuery(params: TaskParams) {
);
}

export function useBlankTaskQuery() {
return useQuery<Task>(route('/api/v1/tasks/create'), () =>
request('GET', endpoint('/api/v1/tasks/create')).then(
(response) => response.data.data
)
export function useBlankTaskQuery(options?: GenericQueryOptions) {
return useQuery(
route('/api/v1/tasks/create'),
() =>
request('GET', endpoint('/api/v1/tasks/create')).then(
(response: GenericSingleResourceResponse<Task>) => response.data.data
),
{ ...options, staleTime: Infinity }
);
}

Expand Down
2 changes: 2 additions & 0 deletions src/components/clients/ClientSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export interface ClientSelectorProps extends GenericSelectorProps<Client> {
withoutAction?: boolean;
exclude?: (string | number)[];
staleTime?: number;
disableWithSpinner?: boolean;
}

export function ClientSelector(props: ClientSelectorProps) {
Expand Down Expand Up @@ -52,6 +53,7 @@ export function ClientSelector(props: ClientSelectorProps) {
sortBy="display_name|asc"
exclude={props.exclude}
staleTime={props.staleTime || 500}
disableWithSpinner={props.disableWithSpinner}
/>
</>
);
Expand Down
7 changes: 4 additions & 3 deletions src/components/forms/DebouncedCombobox.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ interface Props {
withProperty?: string;
sortBy?: string;
staleTime?: number; // in ms
disableWithSpinner?: boolean;
}

export function DebouncedCombobox(props: Props) {
Expand Down Expand Up @@ -304,7 +305,7 @@ export function DebouncedCombobox(props: Props) {

{(!props.clearButton || (!props.defaultValue && !props.value)) &&
!isLoading && (
<div className="absolute inset-y-0 right-0 mt-2.5 mr-1 cursor-pointer">
<div className="absolute inset-y-0 right-0 mt-2.5 mr-1 cursor-pointer bg-white">
<ChevronDown
className="absolute inset-y-0 right-0 text-gray-400 h-4"
aria-hidden="true"
Expand All @@ -313,8 +314,8 @@ export function DebouncedCombobox(props: Props) {
</div>
)}

{isLoading && (
<div className="absolute inset-y-0 right-0 mt-2 mr-1.5 cursor-pointer">
{(isLoading || (props.disabled && props.disableWithSpinner)) && (
<div className="absolute inset-y-0 right-0 mt-2 mr-1.5 cursor-pointer bg-white">
<Spinner />
</div>
)}
Expand Down
12 changes: 6 additions & 6 deletions src/pages/credits/common/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -273,19 +273,19 @@ export function useActions() {
const cloneToCredit = (credit: Credit) => {
setCredit({ ...credit, number: '', documents: [] });

navigate('/credits/create');
navigate('/credits/create?action=clone');
};

const cloneToInvoice = (credit: Credit) => {
setInvoice({ ...credit, number: '', documents: [] });

navigate('/invoices/create');
navigate('/invoices/create?action=clone');
};

const cloneToQuote = (credit: Credit) => {
setQuote({ ...(credit as Quote), number: '', documents: [] });

navigate('/quotes/create');
navigate('/quotes/create?action=clone');
};

const cloneToRecurringInvoice = (credit: Credit) => {
Expand All @@ -295,7 +295,7 @@ export function useActions() {
documents: [],
});

navigate('/recurring_invoices/create');
navigate('/recurring_invoices/create?action=clone');
};

const cloneToPurchaseOrder = (credit: Credit) => {
Expand All @@ -305,7 +305,7 @@ export function useActions() {
documents: [],
});

navigate('/purchase_orders/create');
navigate('/purchase_orders/create?action=clone');
};

const actions: Action<Credit>[] = [
Expand Down Expand Up @@ -482,7 +482,7 @@ export const creditColumns = [
// 'vendor', @Todo: Need to fetch the relationship
] as const;

type CreditColumns = typeof creditColumns[number];
type CreditColumns = (typeof creditColumns)[number];

export const defaultColumns: CreditColumns[] = [
'status',
Expand Down
40 changes: 26 additions & 14 deletions src/pages/credits/create/Create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
*/

import { blankInvitation } from 'common/constants/blank-invitation';
import { isProduction } from 'common/helpers';
import { useClientResolver } from 'common/hooks/clients/useClientResolver';
import { useTitle } from 'common/hooks/useTitle';
import { Client } from 'common/interfaces/client';
Expand Down Expand Up @@ -49,7 +48,7 @@ export function Create() {
const [searchParams] = useSearchParams();

const [credit, setCredit] = useAtom(creditAtom);
const [invoiceSum] = useAtom(invoiceSumAtom);
const [invoiceSum, setInvoiceSum] = useAtom(invoiceSumAtom);

const [client, setClient] = useState<Client>();
const [errors, setErrors] = useState<ValidationBag>();
Expand All @@ -74,23 +73,35 @@ export function Create() {
});

useEffect(() => {
if (typeof data !== 'undefined' && typeof credit === 'undefined') {
const _credit = cloneDeep(data);
setInvoiceSum(undefined);

if (typeof _credit.line_items === 'string') {
_credit.line_items = [];
}
setCredit((current) => {
let value = current;

if (searchParams.get('client')) {
_credit.client_id = searchParams.get('client')!;
if (searchParams.get('action') !== 'clone') {
value = undefined;
}

setCredit(_credit);
}
if (
typeof data !== 'undefined' &&
typeof value === 'undefined' &&
searchParams.get('action') !== 'clone'
) {
const _credit = cloneDeep(data);

if (typeof _credit.line_items === 'string') {
_credit.line_items = [];
}

if (searchParams.get('client')) {
_credit.client_id = searchParams.get('client')!;
}

value = _credit;
}

return () => {
isProduction() && setCredit(undefined);
};
return value;
});
}, [data]);

useEffect(() => {
Expand Down Expand Up @@ -135,6 +146,7 @@ export function Create() {
onClearButtonClick={() => handleChange('client_id', '')}
onContactCheckboxChange={handleInvitationChange}
errorMessage={errors?.errors.client_id}
disableWithSpinner={searchParams.get('action') === 'create'}
/>

<CreditDetails handleChange={handleChange} errors={errors} />
Expand Down
4 changes: 2 additions & 2 deletions src/pages/expenses/common/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export function useActions() {
const cloneToExpense = (expense: Expense) => {
setExpense({ ...expense, documents: [], number: '' });

navigate('/expenses/create');
navigate('/expenses/create?action=clone');
};

const cloneToRecurringExpense = (expense: Expense) => {
Expand All @@ -99,7 +99,7 @@ export function useActions() {
number: '',
});

navigate('/recurring_expenses/create');
navigate('/recurring_expenses/create?action=clone');
};

const actions: Action<Expense>[] = [
Expand Down
61 changes: 32 additions & 29 deletions src/pages/expenses/create/Create.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { Details } from './components/Details';
import { Notes } from './components/Notes';
import { AdditionalInfo } from './components/AdditionalInfo';
import { request } from 'common/helpers/request';
import { endpoint, isProduction } from 'common/helpers';
import { endpoint } from 'common/helpers';
import { toast } from 'common/helpers/toast/toast';
import { useNavigate, useSearchParams } from 'react-router-dom';
import { GenericSingleResourceResponse } from 'common/interfaces/generic-api-response';
Expand All @@ -29,6 +29,7 @@ import { route } from 'common/helpers/route';
import { useAtom } from 'jotai';
import { expenseAtom } from '../common/atoms';
import { useHandleChange } from '../common/hooks';
import { cloneDeep } from 'lodash';

export function Create() {
const [t] = useTranslation();
Expand All @@ -46,7 +47,9 @@ export function Create() {

const [expense, setExpense] = useAtom(expenseAtom);

const { data } = useBlankExpenseQuery({ enabled: !expense });
const { data } = useBlankExpenseQuery({
enabled: typeof expense === 'undefined',
});

const [taxInputType, setTaxInputType] = useState<'by_rate' | 'by_amount'>(
'by_rate'
Expand All @@ -57,33 +60,33 @@ export function Create() {
const handleChange = useHandleChange({ setExpense, setErrors });

useEffect(() => {
if (data && !expense) {
setExpense(data);
}

if (searchParams.has('vendor')) {
setExpense(
(current) =>
current && {
...current,
vendor_id: searchParams.get('vendor') as string,
}
);
}

if (searchParams.has('client')) {
setExpense(
(prevState) =>
prevState && {
...prevState,
client_id: searchParams.get('client') as string,
}
);
}

return () => {
isProduction() && setExpense(undefined);
};
setExpense((current) => {
let value = current;

if (searchParams.get('action') !== 'clone') {
value = undefined;
}

if (
typeof data !== 'undefined' &&
typeof value === 'undefined' &&
searchParams.get('action') !== 'clone'
) {
const _expense = cloneDeep(data);

if (searchParams.has('vendor')) {
_expense.vendor_id = searchParams.get('vendor') as string;
}

if (searchParams.has('client')) {
_expense.vendor_id = searchParams.get('client') as string;
}

value = _expense;
}

return value;
});
}, [data]);

const onSave = (expense: Expense) => {
Expand Down
4 changes: 3 additions & 1 deletion src/pages/invoices/common/components/ClientSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ interface Props {
onClearButtonClick: () => unknown;
onContactCheckboxChange: (contactId: string, value: boolean) => unknown;
errorMessage?: string | string[];
disableWithSpinner?: boolean;
}

export function ClientSelector(props: Props) {
Expand Down Expand Up @@ -58,11 +59,12 @@ export function ClientSelector(props: Props) {
inputLabel={t('client')}
onChange={(client) => props.onChange(client.id)}
value={resource?.client_id}
readonly={props.readonly}
readonly={props.readonly || !resource}
clearButton={Boolean(resource?.client_id)}
onClearButtonClick={props.onClearButtonClick}
initiallyVisible={!resource?.client_id}
errorMessage={props.errorMessage}
disableWithSpinner={props.disableWithSpinner}
/>

{client && (
Expand Down
2 changes: 1 addition & 1 deletion src/pages/invoices/common/components/ProductCreate.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export function ProductCreate(props: Props) {

useEffect(() => {
if (blankProduct) {
setProduct(blankProduct.data.data);
setProduct(blankProduct);
}
}, [blankProduct]);

Expand Down
Loading

0 comments on commit 16dcaaa

Please sign in to comment.