1
0
mirror of https://github.com/LaCasemate/fab-manager.git synced 2025-01-18 07:52:23 +01:00

(bug) unable to select a new machine for an existing category

This commit is contained in:
Sylvain 2023-03-07 11:39:36 +01:00
parent 317e23255e
commit c2739f73a7
11 changed files with 34 additions and 117 deletions

View File

@ -6,6 +6,7 @@
- OpenAPI users endpoint now returns the ID of the InvoicingProfile
- Fix a bug: URL validation regex was wrong
- Fix a bug: privileged users cannot order free carts for themselves in the store
- Fix a bug: unable to select a new machine for an existing category
- Fix a bug: wrong counting of minutes used when using a prepaid pack
- Fix a bug: empty advanced accounting code is not defaulted to the general setting
- Fix a bug: invalid style in accounting codes settings

View File

@ -1,43 +0,0 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { FabModal } from '../base/fab-modal';
import MachineCategoryAPI from '../../api/machine-category';
interface DeleteMachineCategoryModalProps {
isOpen: boolean,
machineCategoryId: number,
toggleModal: () => void,
onSuccess: (message: string) => void,
onError: (message: string) => void,
}
/**
* Modal dialog to remove a requested machine category
*/
export const DeleteMachineCategoryModal: React.FC<DeleteMachineCategoryModalProps> = ({ isOpen, toggleModal, onSuccess, machineCategoryId, onError }) => {
const { t } = useTranslation('admin');
/**
* The user has confirmed the deletion of the requested machine category
*/
const handleDeleteMachineCategory = async (): Promise<void> => {
try {
await MachineCategoryAPI.destroy(machineCategoryId);
onSuccess(t('app.admin.delete_machine_category_modal.deleted'));
} catch (e) {
onError(t('app.admin.delete_machine_category_modal.unable_to_delete') + e);
}
};
return (
<FabModal title={t('app.admin.delete_machine_category_modal.confirmation_required')}
isOpen={isOpen}
toggleModal={toggleModal}
closeButton={true}
confirmButton={t('app.admin.delete_machine_category_modal.confirm')}
onConfirm={handleDeleteMachineCategory}
className="delete-machine-category-modal">
<p>{t('app.admin.delete_machine_category_modal.confirm_machine_category')}</p>
</FabModal>
);
};

View File

@ -1,15 +1,13 @@
import React, { useEffect, useState } from 'react';
import { MachineCategory } from '../../models/machine-category';
import { Machine } from '../../models/machine';
import { IApplication } from '../../models/application';
import { react2angular } from 'react2angular';
import { Loader } from '../base/loader';
import MachineCategoryAPI from '../../api/machine-category';
import MachineAPI from '../../api/machine';
import { useTranslation } from 'react-i18next';
import { FabButton } from '../base/fab-button';
import { MachineCategoryModal } from './machine-category-modal';
import { DeleteMachineCategoryModal } from './delete-machine-category-modal';
import { EditDestroyButtons } from '../base/edit-destroy-buttons';
declare const Application: IApplication;
@ -26,25 +24,16 @@ export const MachineCategoriesList: React.FC<MachineCategoriesListProps> = ({ on
// shown machine categories
const [machineCategories, setMachineCategories] = useState<Array<MachineCategory>>([]);
// all machines, for assign to category
const [machines, setMachines] = useState<Array<Machine>>([]);
// creation/edition modal
const [modalIsOpen, setModalIsOpen] = useState<boolean>(false);
// currently added/edited category
const [machineCategory, setMachineCategory] = useState<MachineCategory>(null);
// deletion modal
const [destroyModalIsOpen, setDestroyModalIsOpen] = useState<boolean>(false);
// currently deleted machine category
const [machineCategoryId, setMachineCategoryId] = useState<number>(null);
// retrieve the full list of machine categories on component mount
useEffect(() => {
MachineCategoryAPI.index()
.then(setMachineCategories)
.catch(onError);
MachineAPI.index({ category: 'none' })
.then(setMachines)
.catch(onError);
}, []);
/**
@ -59,7 +48,6 @@ export const MachineCategoriesList: React.FC<MachineCategoriesListProps> = ({ on
*/
const onSaveTypeSuccess = (message: string): void => {
setModalIsOpen(false);
MachineAPI.index({ category: 'none' }).then(setMachines).catch(onError);
MachineCategoryAPI.index().then(data => {
setMachineCategories(data);
onSuccess(message);
@ -86,28 +74,10 @@ export const MachineCategoriesList: React.FC<MachineCategoriesListProps> = ({ on
};
};
/**
* Init the process of deleting a machine category (ask for confirmation)
*/
const destroyMachineCategory = (id: number): () => void => {
return (): void => {
setMachineCategoryId(id);
setDestroyModalIsOpen(true);
};
};
/**
* Open/closes the confirmation before deletion modal
*/
const toggleDestroyModal = (): void => {
setDestroyModalIsOpen(!destroyModalIsOpen);
};
/**
* Callback triggred when the current machine category was successfully deleted
*/
const onDestroySuccess = (message: string): void => {
setDestroyModalIsOpen(false);
MachineCategoryAPI.index().then(data => {
setMachineCategories(data);
onSuccess(message);
@ -125,16 +95,10 @@ export const MachineCategoriesList: React.FC<MachineCategoriesListProps> = ({ on
</div>
</header>
<MachineCategoryModal isOpen={modalIsOpen}
machines={machines}
machineCategory={machineCategory}
toggleModal={toggleCreateAndEditModal}
onSuccess={onSaveTypeSuccess}
onError={onError} />
<DeleteMachineCategoryModal isOpen={destroyModalIsOpen}
machineCategoryId={machineCategoryId}
toggleModal={toggleDestroyModal}
onSuccess={onDestroySuccess}
onError={onError}/>
<table className="machine-categories-table">
<thead>
<tr>
@ -155,12 +119,12 @@ export const MachineCategoriesList: React.FC<MachineCategoriesListProps> = ({ on
</td>
<td>
<div className="buttons">
<FabButton className="edit-btn" onClick={editMachineCategory(category)}>
<i className="fa fa-edit" /> {t('app.admin.machine_categories_list.edit')}
</FabButton>
<FabButton className="delete-btn" onClick={destroyMachineCategory(category.id)}>
<i className="fa fa-trash" />
</FabButton>
<EditDestroyButtons onDeleteSuccess={onDestroySuccess}
onError={onError}
onEdit={editMachineCategory(category)}
itemId={category.id}
itemType={t('app.admin.machine_categories_list.machine_category')}
apiDestroy={MachineCategoryAPI.destroy} />
</div>
</td>
</tr>

View File

@ -1,25 +1,36 @@
import React from 'react';
import React, { useEffect, useState } from 'react';
import { useTranslation } from 'react-i18next';
import { FabModal, ModalSize } from '../base/fab-modal';
import { MachineCategory } from '../../models/machine-category';
import { Machine } from '../../models/machine';
import MachineCategoryAPI from '../../api/machine-category';
import { MachineCategoryForm } from './machine-category-form';
import MachineAPI from '../../api/machine';
interface MachineCategoryModalProps {
isOpen: boolean,
toggleModal: () => void,
onSuccess: (message: string) => void,
onError: (message: string) => void,
machines: Array<Machine>,
machineCategory?: MachineCategory,
}
/**
* Modal dialog to create/edit a machine category
*/
export const MachineCategoryModal: React.FC<MachineCategoryModalProps> = ({ isOpen, toggleModal, onSuccess, onError, machines, machineCategory }) => {
export const MachineCategoryModal: React.FC<MachineCategoryModalProps> = ({ isOpen, toggleModal, onSuccess, onError, machineCategory }) => {
const { t } = useTranslation('admin');
// all machines, to assign to the category
const [machines, setMachines] = useState<Array<Machine>>([]);
// retrieve the full list of machines on component mount
useEffect(() => {
if (!isOpen) return;
MachineAPI.index({ category: [machineCategory?.id, 'none'] })
.then(setMachines)
.catch(onError);
}, [isOpen]);
/**
* Save the current machine category to the API

View File

@ -75,7 +75,7 @@ export const ConfigurePacksButton: React.FC<ConfigurePacksButtonProps> = ({ pack
};
/**
* When the user clicks on the edition button, query the full data of the current pack from the API, then open te edition modal
* When the user clicks on the edition button, query the full data of the current pack from the API, then open the edition modal
*/
const handleRequestEdit = (pack: PrepaidPack): void => {
PrepaidPackAPI.get(pack.id)

View File

@ -5,7 +5,7 @@ import { AdvancedAccounting } from './advanced-accounting';
export interface MachineIndexFilter extends ApiFilter {
disabled?: boolean,
category?: number | 'none'
category?: number | 'none' | Array<number|'none'>
}
export interface Machine {

View File

@ -1,4 +1,6 @@
.edit-destroy-buttons {
border-radius: var(--border-radius-sm);
overflow: hidden;
button {
@include btn;
border-radius: 0;

View File

@ -14,18 +14,6 @@
display: flex;
justify-content: flex-end;
align-items: center;
button {
border-radius: 5;
&:hover { opacity: 0.75; }
}
.edit-btn {
color: var(--gray-hard-darkest);
margin-right: 10px;
}
.delete-btn {
color: var(--gray-soft-lightest);
background: var(--main);
}
}
.machine-categories-table {

View File

@ -74,7 +74,7 @@ module ApplicationHelper
def may_array(param)
return param if param.is_a?(Array)
return param unless param&.chars&.first == '[' && param&.chars&.last == ']'
return param unless param.chars&.first == '[' && param.chars&.last == ']'
param.gsub(/[\[\]]/i, '').split(',')
end

View File

@ -3,6 +3,8 @@
# Provides methods for Machines
class MachineService
class << self
include ApplicationHelper
# @param filters [ActionController::Parameters]
def list(filters)
sort_by = Setting.get('machines_sort_by') || 'default'
@ -15,7 +17,7 @@ class MachineService
machines = machines.where(deleted_at: nil)
machines = filter_by_disabled(machines, filters)
filter_by_category(machines, filters)
filter_by_categories(machines, filters)
end
private
@ -31,12 +33,10 @@ class MachineService
# @param machines [ActiveRecord::Relation<Machine>]
# @param filters [ActionController::Parameters]
def filter_by_category(machines, filters)
def filter_by_categories(machines, filters)
return machines if filters[:category].blank?
return machines.where(machine_category_id: nil) if filters[:category] == 'none'
machines.where(machine_category_id: filters[:category])
machines.where(machine_category_id: filters[:category].split(',').map { |id| id == 'none' ? nil : id })
end
end
end

View File

@ -28,7 +28,7 @@ en:
add_a_machine_category: "Add a machine category"
name: "Name"
machines_number: "Number of machines"
edit: "Edit"
machine_category: "Machine category"
machine_category_modal:
new_machine_category: "New category"
edit_machine_category: "Edit category"
@ -40,12 +40,6 @@ en:
name: "Name of category"
assigning_machines: "Assign machines to this category"
save: "Save"
delete_machine_category_modal:
confirmation_required: "Confirmation required"
confirm: "Confirm"
deleted: "The machine category has been successfully deleted."
unable_to_delete: "Unable to delete the machine category: "
confirm_machine_category: "Do you really want to remove this machine category?"
machine_form:
ACTION_title: "{ACTION, select, create{New} other{Update the}} machine"
watch_out_when_creating_a_new_machine_its_prices_are_initialized_at_0_for_all_subscriptions: "Watch out! When creating a new machine, its prices are initialized at 0 for all subscriptions."