mirror of
https://github.com/LaCasemate/fab-manager.git
synced 2025-02-26 20:54:21 +01:00
(wip) unsaved form alert
This commit is contained in:
parent
feabded2a0
commit
c381c985d2
@ -0,0 +1,28 @@
|
||||
import React, { PropsWithChildren, useEffect } from 'react';
|
||||
import { UIRouter } from '@uirouter/angularjs';
|
||||
import { FormState } from 'react-hook-form/dist/types/form';
|
||||
import { FieldValues } from 'react-hook-form/dist/types/fields';
|
||||
|
||||
interface UnsavedFormAlertProps<TFieldValues> {
|
||||
uiRouter: UIRouter,
|
||||
formState: FormState<TFieldValues>,
|
||||
}
|
||||
|
||||
/**
|
||||
* Alert the user about unsaved changes in the given form, before leaving the current page
|
||||
*/
|
||||
export const UnsavedFormAlert = <TFieldValues extends FieldValues>({ uiRouter, formState, children }: PropsWithChildren<UnsavedFormAlertProps<TFieldValues>>) => {
|
||||
useEffect(() => {
|
||||
const { transitionService, globals: { current } } = uiRouter;
|
||||
transitionService.onBefore({ from: current.name }, () => {
|
||||
const { isDirty } = formState;
|
||||
console.log('transition start', isDirty);
|
||||
});
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className="unsaved-form-alert">
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
};
|
@ -6,6 +6,7 @@ import { IApplication } from '../../models/application';
|
||||
import { ProductForm } from './product-form';
|
||||
import { Product } from '../../models/product';
|
||||
import ProductAPI from '../../api/product';
|
||||
import { UIRouter } from '@uirouter/angularjs';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
@ -13,12 +14,13 @@ interface EditProductProps {
|
||||
productId: number,
|
||||
onSuccess: (message: string) => void,
|
||||
onError: (message: string) => void,
|
||||
uiRouter: UIRouter
|
||||
}
|
||||
|
||||
/**
|
||||
* This component show edit product form
|
||||
*/
|
||||
const EditProduct: React.FC<EditProductProps> = ({ productId, onSuccess, onError }) => {
|
||||
const EditProduct: React.FC<EditProductProps> = ({ productId, onSuccess, onError, uiRouter }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
const [product, setProduct] = useState<Product>();
|
||||
@ -40,19 +42,23 @@ const EditProduct: React.FC<EditProductProps> = ({ productId, onSuccess, onError
|
||||
if (product) {
|
||||
return (
|
||||
<div className="edit-product">
|
||||
<ProductForm product={product} title={product.name} onSuccess={saveProductSuccess} onError={onError} />
|
||||
<ProductForm product={product}
|
||||
title={product.name}
|
||||
onSuccess={saveProductSuccess}
|
||||
onError={onError}
|
||||
uiRouter={uiRouter} />
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
const EditProductWrapper: React.FC<EditProductProps> = ({ productId, onSuccess, onError }) => {
|
||||
const EditProductWrapper: React.FC<EditProductProps> = (props) => {
|
||||
return (
|
||||
<Loader>
|
||||
<EditProduct productId={productId} onSuccess={onSuccess} onError={onError} />
|
||||
<EditProduct {...props} />
|
||||
</Loader>
|
||||
);
|
||||
};
|
||||
|
||||
Application.Components.component('editProduct', react2angular(EditProductWrapper, ['productId', 'onSuccess', 'onError']));
|
||||
Application.Components.component('editProduct', react2angular(EditProductWrapper, ['productId', 'onSuccess', 'onError', 'uiRouter']));
|
||||
|
@ -4,18 +4,20 @@ import { react2angular } from 'react2angular';
|
||||
import { Loader } from '../base/loader';
|
||||
import { IApplication } from '../../models/application';
|
||||
import { ProductForm } from './product-form';
|
||||
import { UIRouter } from '@uirouter/angularjs';
|
||||
|
||||
declare const Application: IApplication;
|
||||
|
||||
interface NewProductProps {
|
||||
onSuccess: (message: string) => void,
|
||||
onError: (message: string) => void,
|
||||
uiRouter: UIRouter,
|
||||
}
|
||||
|
||||
/**
|
||||
* This component show new product form
|
||||
*/
|
||||
const NewProduct: React.FC<NewProductProps> = ({ onSuccess, onError }) => {
|
||||
const NewProduct: React.FC<NewProductProps> = ({ onSuccess, onError, uiRouter }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
const product = {
|
||||
@ -46,17 +48,21 @@ const NewProduct: React.FC<NewProductProps> = ({ onSuccess, onError }) => {
|
||||
|
||||
return (
|
||||
<div className="new-product">
|
||||
<ProductForm product={product} title={t('app.admin.store.new_product.add_a_new_product')} onSuccess={saveProductSuccess} onError={onError} />
|
||||
<ProductForm product={product}
|
||||
title={t('app.admin.store.new_product.add_a_new_product')}
|
||||
onSuccess={saveProductSuccess}
|
||||
onError={onError}
|
||||
uiRouter={uiRouter} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
const NewProductWrapper: React.FC<NewProductProps> = ({ onSuccess, onError }) => {
|
||||
const NewProductWrapper: React.FC<NewProductProps> = (props) => {
|
||||
return (
|
||||
<Loader>
|
||||
<NewProduct onSuccess={onSuccess} onError={onError} />
|
||||
<NewProduct {...props} />
|
||||
</Loader>
|
||||
);
|
||||
};
|
||||
|
||||
Application.Components.component('newProduct', react2angular(NewProductWrapper, ['onSuccess', 'onError']));
|
||||
Application.Components.component('newProduct', react2angular(NewProductWrapper, ['onSuccess', 'onError', 'uiRouter']));
|
||||
|
@ -20,12 +20,15 @@ import ProductAPI from '../../api/product';
|
||||
import { Plus } from 'phosphor-react';
|
||||
import { ProductStockForm } from './product-stock-form';
|
||||
import ProductLib from '../../lib/product';
|
||||
import { UnsavedFormAlert } from '../form/unsaved-form-alert';
|
||||
import { UIRouter } from '@uirouter/angularjs';
|
||||
|
||||
interface ProductFormProps {
|
||||
product: Product,
|
||||
title: string,
|
||||
onSuccess: (product: Product) => void,
|
||||
onError: (message: string) => void,
|
||||
uiRouter: UIRouter
|
||||
}
|
||||
|
||||
/**
|
||||
@ -42,7 +45,7 @@ type checklistOption = { value: number, label: string };
|
||||
/**
|
||||
* Form component to create or update a product
|
||||
*/
|
||||
export const ProductForm: React.FC<ProductFormProps> = ({ product, title, onSuccess, onError }) => {
|
||||
export const ProductForm: React.FC<ProductFormProps> = ({ product, title, onSuccess, onError, uiRouter }) => {
|
||||
const { t } = useTranslation('admin');
|
||||
|
||||
const { handleSubmit, register, control, formState, setValue, reset } = useForm<Product>({ defaultValues: { ...product } });
|
||||
@ -224,6 +227,7 @@ export const ProductForm: React.FC<ProductFormProps> = ({ product, title, onSucc
|
||||
<FabButton className="main-action-btn" onClick={handleSubmit(saveProduct)}>{t('app.admin.store.product_form.save')}</FabButton>
|
||||
</div>
|
||||
</header>
|
||||
<UnsavedFormAlert uiRouter={uiRouter} formState={formState} />
|
||||
<form className="product-form" onSubmit={handleSubmit(onSubmit)}>
|
||||
<div className='tabs'>
|
||||
<p className={!stockTab ? 'is-active' : ''} onClick={() => setStockTab(false)}>{t('app.admin.store.product_form.product_parameters')}</p>
|
||||
|
@ -4,11 +4,14 @@
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
Application.Controllers.controller('AdminStoreProductController', ['$scope', 'CSRF', 'growl', '$state', '$transition$',
|
||||
function ($scope, CSRF, growl, $state, $transition$) {
|
||||
Application.Controllers.controller('AdminStoreProductController', ['$scope', 'CSRF', 'growl', '$state', '$transition$', '$uiRouter',
|
||||
function ($scope, CSRF, growl, $state, $transition$, $uiRouter) {
|
||||
/* PUBLIC SCOPE */
|
||||
$scope.productId = $transition$.params().id;
|
||||
|
||||
// the following item is used by the UnsavedFormAlert component to detect a page change
|
||||
$scope.uiRouter = $uiRouter;
|
||||
|
||||
/**
|
||||
* Callback triggered in case of error
|
||||
*/
|
||||
|
@ -60,5 +60,5 @@ export interface Product {
|
||||
_destroy?: boolean,
|
||||
is_main?: boolean
|
||||
}>,
|
||||
product_stock_movements_attributes: Array<ProductStockMovement>,
|
||||
product_stock_movements_attributes?: Array<ProductStockMovement>,
|
||||
}
|
||||
|
@ -15,5 +15,5 @@
|
||||
<span translate>{{ 'app.admin.store.back_products_list' }}</span>
|
||||
</a>
|
||||
</div>
|
||||
<edit-product product-id="productId" on-success="onSuccess" on-error="onError"/>
|
||||
</section>
|
||||
<edit-product product-id="productId" on-success="onSuccess" on-error="onError" ui-router="uiRouter" />
|
||||
</section>
|
||||
|
@ -15,5 +15,5 @@
|
||||
<span translate>{{ 'app.admin.store.back_products_list' }}</span>
|
||||
</a>
|
||||
</div>
|
||||
<new-product on-success="onSuccess" on-error="onError"/>
|
||||
</section>
|
||||
<new-product on-success="onSuccess" on-error="onError" ui-router="uiRouter"/>
|
||||
</section>
|
||||
|
Loading…
x
Reference in New Issue
Block a user