Skip to content

Commit

Permalink
Merge pull request #762 from invoiceninja/develop
Browse files Browse the repository at this point in the history
Sync main and develop
  • Loading branch information
beganovich authored Jun 15, 2023
2 parents af7c875 + cf6608e commit 8cd5794
Show file tree
Hide file tree
Showing 30 changed files with 1,740 additions and 129 deletions.
1,584 changes: 1,572 additions & 12 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
"@sentry/tracing": "^7.24.1",
"@tinymce/tinymce-react": "^4.3.0",
"@tippyjs/react": "^4.2.6",
"antd": "^5.6.1",
"array-move": "^4.0.0",
"axios": "^0.27.2",
"classnames": "^2.3.2",
Expand Down
4 changes: 2 additions & 2 deletions renovate.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"updateTypes": ["minor", "patch", "pin", "digest"]
}
],
"prHourlyLimit": 5,
"prConcurrentLimit": 5,
"prHourlyLimit": 1,
"prConcurrentLimit": 1,
"rangeStrategy": "auto"
}
23 changes: 23 additions & 0 deletions src/common/hooks/useInjectUserChanges.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Invoice Ninja (https://invoiceninja.com).
*
* @link https://github.com/invoiceninja/invoiceninja source repository
*
* @copyright Copyright (c) 2022. Invoice Ninja LLC (https://invoiceninja.com)
*
* @license https://www.elastic.co/licensing/elastic-license
*/

import { useEffect } from 'react';
import { useDispatch } from 'react-redux';
import { injectInChanges } from '../stores/slices/user';
import { useCurrentUser } from './useCurrentUser';

export function useInjectUserChanges() {
const user = useCurrentUser();
const dispatch = useDispatch();

useEffect(() => {
dispatch(injectInChanges());
}, [user]);
}
11 changes: 11 additions & 0 deletions src/common/hooks/useReactSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,28 @@
import { ReactSettings } from '$app/common/interfaces/company-user';
import { RootState } from '$app/common/stores/store';
import { useSelector } from 'react-redux';
import { useCurrentUser } from './useCurrentUser';

export function useReactSettings() {
const currentUser = useCurrentUser();

const reactSettings =
useSelector(
(state: RootState) => state.user.changes?.company_user?.react_settings
) || {};

const previousReactTableColumns =
currentUser?.company_user?.settings?.react_table_columns;

const settings: ReactSettings = {
show_pdf_preview: true,
react_notification_link: true,
...reactSettings,
// This is legacy fallback for old settings location. If you see this in 2 years, feel free to remove it.
react_table_columns: {
...previousReactTableColumns,
...reactSettings.react_table_columns,
},
};

return settings;
Expand Down
1 change: 1 addition & 0 deletions src/common/interfaces/company-user.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import { User } from './user';

export interface ReactSettings {
show_pdf_preview: boolean;
react_table_columns?: Record<ReactTableColumns, string[]>;
react_notification_link: boolean;
}

Expand Down
13 changes: 9 additions & 4 deletions src/components/DataTableColumnsPicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,8 @@ import {
DropResult,
} from '@hello-pangea/dnd';
import { arrayMoveImmutable } from 'array-move';
import { useReactSettings } from '$app/common/hooks/useReactSettings';
import { useInjectUserChanges } from '$app/common/hooks/useInjectUserChanges';

interface Props {
columns: string[];
Expand All @@ -51,12 +53,15 @@ export function DataTableColumnsPicker(props: Props) {
const { t } = useTranslation();
const { table, defaultColumns } = props;

useInjectUserChanges();

const reactSettings = useReactSettings();

const [filteredColumns, setFilteredColumns] = useState(props.columns);

const [currentColumns, setCurrentColumns] = useState<string[]>(
currentUser?.company_user?.settings?.react_table_columns?.[
table as ReactTableColumns
] || defaultColumns
reactSettings?.react_table_columns?.[table as ReactTableColumns] ||
defaultColumns
);

const [isModalVisible, setIsModalVisible] = useState(false);
Expand All @@ -76,7 +81,7 @@ export function DataTableColumnsPicker(props: Props) {

set(
user,
`company_user.settings.react_table_columns.${table}`,
`company_user.react_settings.react_table_columns.${table}`,
currentColumns
);

Expand Down
69 changes: 27 additions & 42 deletions src/components/DropdownDateRangePicker.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,14 @@
* @license https://www.elastic.co/licensing/elastic-license
*/

import { Button, InputField, SelectField } from '$app/components/forms';
import { Modal } from '$app/components/Modal';
import dayjs from 'dayjs';
import { ChangeEvent, useEffect, useState } from 'react';
import { Calendar } from 'react-feather';
import { useTranslation } from 'react-i18next';
import { DatePicker } from 'antd';
import { useCurrentCompanyDateFormats } from '$app/common/hooks/useCurrentCompanyDateFormats';
import customParseFormat from 'dayjs/plugin/customParseFormat'
import { SelectField } from './forms';

type Props = {
startDate: string;
Expand All @@ -23,20 +26,32 @@ type Props = {
export function DropdownDateRangePicker(props: Props) {
const [t] = useTranslation();
const [isOpenModal, setisOpenModal] = useState(false);
const { RangePicker } = DatePicker;

const now = new Date();
const quarter = Math.floor(now.getMonth() / 3);

const [customStartDate, setCustomStartDate] = useState<string>();
const [customEndDate, setCustomEndDate] = useState<string>();

const { dateFormat } = useCurrentCompanyDateFormats();

useEffect(() => {
setCustomStartDate(props.startDate);
setCustomEndDate(props.endDate);
}, [props.startDate, props.endDate]);

const handleCustomDateChange = (value: [string, string]) => {
dayjs.extend(customParseFormat)
if (value[0] === '' || value[1] === '') {
return;
}

props.handleDateChange(dayjs(value[0]).format('YYYY-MM-DD') + ',' + dayjs(value[1]).format('YYYY-MM-DD'));
}

return (
<div className=" flex justify-end items-center">
<div className="flex justify-end items-center">
<Calendar className="mx-2" />{' '}
<SelectField
defaultValue={props.startDate + '/' + props.startDate}
Expand All @@ -48,6 +63,7 @@ export function DropdownDateRangePicker(props: Props) {
if (event.target.value === 'Custom') {
setisOpenModal(true);
} else {
setisOpenModal(false);
props.handleDateChange(event.target.value);
}
}}
Expand Down Expand Up @@ -151,47 +167,16 @@ export function DropdownDateRangePicker(props: Props) {
</option>
<option value={'Custom'}>{`${t('custom_range')}`}</option>
</SelectField>
<Modal
title={t('custom_range')}
visible={isOpenModal}
onClose={() => {
setisOpenModal(false);
}}
overflowVisible
>
<div className="flex justify-center flex-col my-3">
<InputField
type="date"
label={`${t('start')} ${t('date')}`}
value={customStartDate}
onValueChange={(value) => setCustomStartDate(value)}
{isOpenModal && (
<div className="flex flex-row space-x-2">
<RangePicker
size="large"
defaultValue={[dayjs(customStartDate), dayjs(customEndDate)]}
format={dateFormat}
onChange={(dates, dateString) => handleCustomDateChange(dateString)}
/>

<br></br>

<InputField
type="date"
label={`${t('end')} ${t('date')}`}
value={customEndDate}
onValueChange={(value) => setCustomEndDate(value)}
/>

<br></br>

<Button
className="my-2"
type="primary"
disableWithoutIcon
disabled={!customStartDate || !customEndDate}
onClick={() => {
props.handleDateChange(customStartDate + ',' + customEndDate);
setisOpenModal(false);
}}
>
{t('ok')}
</Button>
</div>
</Modal>
)}
</div>
);
}
6 changes: 4 additions & 2 deletions src/components/PasswordConfirmation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { useCurrentCompany } from '$app/common/hooks/useCurrentCompany';
import dayjs from 'dayjs';
import { useAtom } from 'jotai';
import { lastPasswordEntryTimeAtom } from '$app/common/atoms/password-confirmation';
import { useCurrentUser } from '$app/common/hooks/useCurrentUser';

interface Props {
show?: boolean;
Expand All @@ -28,7 +29,8 @@ export function PasswordConfirmation(props: Props) {
const navigate = useNavigate();
const location = useLocation();
const company = useCurrentCompany();

const user = useCurrentUser();

const [isModalOpen, setIsModalOpen] = useState(props.show ?? false);
const [currentPassword, setCurrentPassword] = useState('');

Expand Down Expand Up @@ -59,7 +61,7 @@ export function PasswordConfirmation(props: Props) {
};

useEffect(() => {
if (isModalOpen && !isPasswordTimeoutExpired) {
if (isModalOpen && !isPasswordTimeoutExpired || (!user?.has_password && user?.oauth_provider_id && user.oauth_provider_id.length > 1)) {
handleConfirm();
}
}, [isModalOpen]);
Expand Down
7 changes: 3 additions & 4 deletions src/pages/clients/common/hooks/useClientColumns.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { route } from '$app/common/helpers/route';
import { useFormatMoney } from '$app/common/hooks/money/useFormatMoney';
import { useCurrentCompany } from '$app/common/hooks/useCurrentCompany';
import { useCurrentCompanyDateFormats } from '$app/common/hooks/useCurrentCompanyDateFormats';
import { useCurrentUser } from '$app/common/hooks/useCurrentUser';
import { useResolveCountry } from '$app/common/hooks/useResolveCountry';
import { useResolveCurrency } from '$app/common/hooks/useResolveCurrency';
import { useResolveLanguage } from '$app/common/hooks/useResolveLanguage';
Expand All @@ -28,6 +27,7 @@ import { useCallback } from 'react';
import { ExternalLink } from 'react-feather';
import { useTranslation } from 'react-i18next';
import { useEntityCustomFields } from '$app/common/hooks/useEntityCustomFields';
import { useReactSettings } from '$app/common/hooks/useReactSettings';

export const defaultColumns: string[] = [
'name',
Expand Down Expand Up @@ -92,8 +92,8 @@ export function useClientColumns() {
const { t } = useTranslation();
const { dateFormat } = useCurrentCompanyDateFormats();

const currentUser = useCurrentUser();
const company = useCurrentCompany();
const reactSettings = useReactSettings();

const formatMoney = useFormatMoney();
const resolveCountry = useResolveCountry();
Expand Down Expand Up @@ -360,8 +360,7 @@ export function useClientColumns() {
];

const list: string[] =
currentUser?.company_user?.settings?.react_table_columns?.client ||
defaultColumns;
reactSettings?.react_table_columns?.client || defaultColumns;

return columns
.filter((column) => list.includes(column.column))
Expand Down
6 changes: 3 additions & 3 deletions src/pages/credits/common/components/CreditFooter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,9 @@ export function CreditFooter(props: Props) {

<div className="pt-9">
<Toggle
label={t('auto_bill_enabled')}
checked={credit?.auto_bill_enabled || false}
onChange={(value) => handleChange('auto_bill_enabled', value)}
label={t('inclusive_taxes')}
checked={credit?.uses_inclusive_taxes || false}
onChange={(value) => handleChange('uses_inclusive_taxes', value)}
/>
</div>
</div>
Expand Down
8 changes: 4 additions & 4 deletions src/pages/credits/common/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { request } from '$app/common/helpers/request';
import { route } from '$app/common/helpers/route';
import { toast } from '$app/common/helpers/toast/toast';
import { useCurrentCompany } from '$app/common/hooks/useCurrentCompany';
import { useCurrentUser } from '$app/common/hooks/useCurrentUser';
import { useInjectCompanyChanges } from '$app/common/hooks/useInjectCompanyChanges';
import { useResolveCurrency } from '$app/common/hooks/useResolveCurrency';
import { Client } from '$app/common/interfaces/client';
Expand Down Expand Up @@ -84,6 +83,7 @@ import { useScheduleEmailRecord } from '$app/pages/invoices/common/hooks/useSche
import { usePrintPdf } from '$app/pages/invoices/common/hooks/usePrintPdf';
import { EntityState } from '$app/common/enums/entity-state';
import { isDeleteActionTriggeredAtom } from '$app/pages/invoices/common/components/ProductsTable';
import { useReactSettings } from '$app/common/hooks/useReactSettings';

interface CreditUtilitiesProps {
client?: Client;
Expand Down Expand Up @@ -545,11 +545,12 @@ export function useCreditColumns() {
const creditColumns = useAllCreditColumns();
type CreditColumns = (typeof creditColumns)[number];

const currentUser = useCurrentUser();
const company = useCurrentCompany();
const formatMoney = useFormatMoney();
const resolveCountry = useResolveCountry();

const reactSettings = useReactSettings();

const [firstCustom, secondCustom, thirdCustom, fourthCustom] =
useEntityCustomFields({
entity: 'credit',
Expand Down Expand Up @@ -803,8 +804,7 @@ export function useCreditColumns() {
];

const list: string[] =
currentUser?.company_user?.settings?.react_table_columns?.credit ||
defaultColumns;
reactSettings?.react_table_columns?.credit || defaultColumns;

return columns
.filter((column) => list.includes(column.column))
Expand Down
2 changes: 1 addition & 1 deletion src/pages/dashboard/components/Totals.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ export function Totals() {
</Button>
</div>

<div className="flex justify-center sm:col-start-3 ">
<div className="flex flex-auto justify-center sm:col-start-3 ">
<DropdownDateRangePicker
handleDateChange={handleDateChange}
startDate={body.start_date}
Expand Down
8 changes: 4 additions & 4 deletions src/pages/expenses/common/hooks.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import { route } from '$app/common/helpers/route';
import { useFormatMoney } from '$app/common/hooks/money/useFormatMoney';
import { useCurrentCompany } from '$app/common/hooks/useCurrentCompany';
import { useCurrentCompanyDateFormats } from '$app/common/hooks/useCurrentCompanyDateFormats';
import { useCurrentUser } from '$app/common/hooks/useCurrentUser';
import { Expense } from '$app/common/interfaces/expense';
import { RecurringExpense } from '$app/common/interfaces/recurring-expense';
import { ValidationBag } from '$app/common/interfaces/validation-bag';
Expand Down Expand Up @@ -44,6 +43,7 @@ import { useSetAtom } from 'jotai';
import { useBulk } from '$app/common/queries/expenses';
import { Divider } from '$app/components/cards/Divider';
import { EntityState } from '$app/common/enums/entity-state';
import { useReactSettings } from '$app/common/hooks/useReactSettings';

export function useActions() {
const [t] = useTranslation();
Expand Down Expand Up @@ -190,10 +190,11 @@ export function useExpenseColumns() {
const { t } = useTranslation();
const { dateFormat } = useCurrentCompanyDateFormats();

const currentUser = useCurrentUser();
const formatMoney = useFormatMoney();
const company = useCurrentCompany();

const reactSettings = useReactSettings();

const expenseColumns = useAllExpenseColumns();
type ExpenseColumns = (typeof expenseColumns)[number];

Expand Down Expand Up @@ -415,8 +416,7 @@ export function useExpenseColumns() {
];

const list: string[] =
currentUser?.company_user?.settings?.react_table_columns?.expense ||
defaultColumns;
reactSettings?.react_table_columns?.expense || defaultColumns;

return columns
.filter((column) => list.includes(column.column))
Expand Down
Loading

0 comments on commit 8cd5794

Please sign in to comment.