diff --git a/app/frontend/src/javascript/components/plans/plan-form.tsx b/app/frontend/src/javascript/components/plans/plan-form.tsx index 082dcefce..a41731269 100644 --- a/app/frontend/src/javascript/components/plans/plan-form.tsx +++ b/app/frontend/src/javascript/components/plans/plan-form.tsx @@ -26,6 +26,8 @@ import { PlanPricingForm } from './plan-pricing-form'; import { AdvancedAccountingForm } from '../accounting/advanced-accounting-form'; import { FabTabs } from '../base/fab-tabs'; import { PlanLimitForm } from './plan-limit-form'; +import { UnsavedFormAlert } from '../form/unsaved-form-alert'; +import { UIRouter } from '@uirouter/angularjs'; declare const Application: IApplication; @@ -35,12 +37,13 @@ interface PlanFormProps { onError: (message: string) => void, onSuccess: (message: string) => void, beforeSubmit?: (data: Plan) => void, + uiRouter: UIRouter } /** * Form to edit or create subscription plans */ -export const PlanForm: React.FC = ({ action, plan, onError, onSuccess, beforeSubmit }) => { +export const PlanForm: React.FC = ({ action, plan, onError, onSuccess, beforeSubmit, uiRouter }) => { const { handleSubmit, register, control, formState, setValue } = useForm({ defaultValues: { ...plan } }); const output = useWatch({ control }); // eslint-disable-line const { t } = useTranslation('admin'); @@ -316,6 +319,7 @@ export const PlanForm: React.FC = ({ action, plan, onError, onSuc
+ = (props) => { ); }; -Application.Components.component('planForm', react2angular(PlanFormWrapper, ['action', 'plan', 'onError', 'onSuccess'])); +Application.Components.component('planForm', react2angular(PlanFormWrapper, ['action', 'plan', 'onError', 'onSuccess', 'uiRouter'])); diff --git a/app/frontend/src/javascript/controllers/admin/plans.js b/app/frontend/src/javascript/controllers/admin/plans.js index ab80d0824..5ef815c29 100644 --- a/app/frontend/src/javascript/controllers/admin/plans.js +++ b/app/frontend/src/javascript/controllers/admin/plans.js @@ -21,11 +21,14 @@ /** * Controller used in the plan creation form */ -Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal', 'groups', 'prices', 'partners', 'CSRF', '$state', 'growl', '_t', 'planCategories', - function ($scope, $uibModal, groups, prices, partners, CSRF, $state, growl, _t, planCategories) { +Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal', 'groups', 'prices', 'partners', 'CSRF', '$state', 'growl', '_t', '$uiRouter', + function ($scope, $uibModal, groups, prices, partners, CSRF, $state, growl, _t, $uiRouter) { // protection against request forgery CSRF.setMetaTags(); + // the following item is used by the UnsavedFormAlert component to detect a page change + $scope.uiRouter = $uiRouter; + /** * Shows an error message forwarded from a child component */ @@ -46,13 +49,16 @@ Application.Controllers.controller('NewPlanController', ['$scope', '$uibModal', /** * Controller used in the plan edition form */ -Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'plans', 'planPromise', 'machines', 'spaces', 'prices', 'partners', 'CSRF', '$state', '$transition$', 'growl', '$filter', '_t', 'Plan', 'planCategories', - function ($scope, groups, plans, planPromise, machines, spaces, prices, partners, CSRF, $state, $transition$, growl, $filter, _t, Plan, planCategories) { +Application.Controllers.controller('EditPlanController', ['$scope', 'groups', 'plans', 'planPromise', 'machines', 'spaces', 'prices', 'partners', 'CSRF', '$state', '$transition$', 'growl', '$filter', '_t', '$uiRouter', + function ($scope, groups, plans, planPromise, machines, spaces, prices, partners, CSRF, $state, $transition$, growl, $filter, _t, $uiRouter) { // protection against request forgery CSRF.setMetaTags(); $scope.suscriptionPlan = cleanPlan(planPromise); + // the following item is used by the UnsavedFormAlert component to detect a page change + $scope.uiRouter = $uiRouter; + /** * Shows an error message forwarded from a child component */ diff --git a/app/frontend/src/javascript/models/plan.ts b/app/frontend/src/javascript/models/plan.ts index 8c469610a..a93b07059 100644 --- a/app/frontend/src/javascript/models/plan.ts +++ b/app/frontend/src/javascript/models/plan.ts @@ -44,7 +44,7 @@ export interface Plan { partnership?: boolean, partners?: Array, advanced_accounting_attributes?: AdvancedAccounting, - plan_limitations_attributes: Array + plan_limitations_attributes?: Array } export interface PlansDuration { diff --git a/app/frontend/templates/admin/plans/edit.html b/app/frontend/templates/admin/plans/edit.html index 161d1bd59..9ad6077a8 100644 --- a/app/frontend/templates/admin/plans/edit.html +++ b/app/frontend/templates/admin/plans/edit.html @@ -13,4 +13,4 @@ - + diff --git a/app/frontend/templates/admin/plans/new.html b/app/frontend/templates/admin/plans/new.html index a5cddf0f6..7315fe38b 100644 --- a/app/frontend/templates/admin/plans/new.html +++ b/app/frontend/templates/admin/plans/new.html @@ -14,4 +14,4 @@ - + diff --git a/test/frontend/components/plans/plan-form.test.tsx b/test/frontend/components/plans/plan-form.test.tsx index 66af009ff..1ef115d8d 100644 --- a/test/frontend/components/plans/plan-form.test.tsx +++ b/test/frontend/components/plans/plan-form.test.tsx @@ -7,6 +7,7 @@ import userEvent from '@testing-library/user-event'; import plans from '../../__fixtures__/plans'; import machines from '../../__fixtures__/machines'; import { tiptapEvent } from '../../__lib__/tiptap'; +import { uiRouter } from '../../__lib__/ui-router'; describe('PlanForm', () => { const onError = jest.fn(); @@ -14,7 +15,7 @@ describe('PlanForm', () => { const beforeSubmit = jest.fn(); test('render create PlanForm', async () => { - render(); + render(); await waitFor(() => screen.getByRole('combobox', { name: /app.admin.plan_form.group/ })); expect(screen.getByLabelText(/app.admin.plan_form.name/)).toBeInTheDocument(); expect(screen.getByLabelText(/app.admin.plan_form.transversal/)).toBeInTheDocument(); @@ -35,7 +36,7 @@ describe('PlanForm', () => { }); test('create new plan', async () => { - render(); + render(); await waitFor(() => screen.getByRole('combobox', { name: /app.admin.plan_form.group/ })); const user = userEvent.setup(); // base_name @@ -98,7 +99,7 @@ describe('PlanForm', () => { test('render update PlanForm with partner', async () => { const plan = plans[1]; - render(); + render(); await waitFor(() => screen.getByRole('combobox', { name: /app.admin.plan_pricing_form.copy_prices_from/ })); expect(screen.getByLabelText(/app.admin.plan_form.name/)).toBeInTheDocument(); expect(screen.queryByLabelText(/app.admin.plan_form.transversal/)).toBeNull(); @@ -123,14 +124,14 @@ describe('PlanForm', () => { }); test('selecting transversal plan disables group select', async () => { - render(); + render(); await waitFor(() => screen.getByRole('combobox', { name: /app.admin.plan_form.group/ })); fireEvent.click(screen.getByRole('switch', { name: /app.admin.plan_form.transversal/ })); expect(screen.queryByRole('combobox', { name: /app.admin.plan_form.group/ })).toBeNull(); }); test('selecting partner plan shows partner selection', async () => { - render(); + render(); await waitFor(() => screen.getByRole('combobox', { name: /app.admin.plan_form.group/ })); fireEvent.click(screen.getByRole('switch', { name: /app.admin.plan_form.partner_plan/ })); expect(screen.getByLabelText(/app.admin.plan_form.notified_partner/)); @@ -138,7 +139,7 @@ describe('PlanForm', () => { }); test('creating a new partner selects him by default', async () => { - render(); + render(); await waitFor(() => screen.getByRole('combobox', { name: /app.admin.plan_form.group/ })); fireEvent.click(screen.getByRole('switch', { name: /app.admin.plan_form.partner_plan/ })); fireEvent.click(screen.getByRole('button', { name: /app.admin.plan_form.new_user/ })); @@ -157,7 +158,7 @@ describe('PlanForm', () => { test('update plan prices', async () => { const plan = plans[1]; const machine = machines[1]; - render(); + render(); await waitFor(() => screen.getByLabelText(new RegExp(machine.name))); // update machine price fireEvent.change(screen.getByLabelText(new RegExp(machine.name)), { target: { value: 42.42 } });