-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
merging ramps-583-implement-relative-order-column-in-allocations_proc…
…ess_resources to ramps-100-variable-marketplace
- Loading branch information
Showing
24 changed files
with
3,863 additions
and
7,886 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
import PropTypes from "prop-types"; | ||
|
||
export const AddNewModal = ({ show, onClose, title, children, onSave }) => { | ||
if (!show) { | ||
return null; | ||
} | ||
|
||
return ( | ||
<div | ||
style={{ | ||
position: "fixed", | ||
top: 0, | ||
left: 0, | ||
width: "100%", | ||
height: "100%", | ||
backgroundColor: "rgba(0, 0, 0, 0.8)", | ||
display: "flex", | ||
alignItems: "center", | ||
zIndex: 1050, | ||
}} | ||
> | ||
<div | ||
className="modal fade in" | ||
tabIndex="-1" | ||
role="dialog" | ||
aria-hidden="true" | ||
style={{ | ||
width: "90%", | ||
maxWidth: "600px", | ||
maxHeight: "90%", | ||
overflow: "auto", | ||
backgroundColor: "white", | ||
position: "relative", | ||
}} | ||
> | ||
<div className="modal-dialog" role="document"> | ||
<div className="modal-content"> | ||
<div className="modal-header"> | ||
<button | ||
type="button" | ||
className="close" | ||
data-dismiss="modal" | ||
onClick={onClose} | ||
aria-label="Close" | ||
> | ||
<h3 aria-hidden="true" className="text-danger"> | ||
× | ||
</h3> | ||
</button> | ||
<h3 className="modal-title">{title}</h3> | ||
</div> | ||
<div className="modal-body">{children}</div> | ||
<div | ||
className="modal-footer" | ||
style={{ | ||
padding: "15px", | ||
textAlign: "right", | ||
borderTop: "1px solid #e5e5e5", | ||
backgroundColor: "#f8f9fa", | ||
}} | ||
> | ||
<button className="btn btn-success" onClick={onSave}> | ||
Save | ||
</button> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
</div> | ||
); | ||
}; | ||
|
||
AddNewModal.propTypes = { | ||
show: PropTypes.bool.isRequired, | ||
onClose: PropTypes.func.isRequired, | ||
title: PropTypes.string.isRequired, | ||
children: PropTypes.node.isRequired, | ||
onSave: PropTypes.func.isRequired, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import Grid from "../shared/Grid"; | ||
import style from "./AllocationTypesGrid.module.scss"; | ||
|
||
export const AllocationGrid = React.memo(function AllocationGrid({ | ||
columns, | ||
rows, | ||
onAddRequiredResource, | ||
onAddAllocationType, | ||
}) { | ||
return ( | ||
<div className={style["allocation-types-grid"]}> | ||
<div className={style["header-container"]}> | ||
<h2 className={style["header-title"]}>Allocation Types</h2> | ||
<div className={style["header-buttons"]}> | ||
<button className="btn btn-primary" onClick={onAddAllocationType}> | ||
<i className="fa fa-plus"></i> Add Allocation Type | ||
</button> | ||
<button className="btn btn-primary" onClick={onAddRequiredResource}> | ||
<i className="fa fa-plus"></i> Add Required Resource | ||
</button> | ||
</div> | ||
</div> | ||
<Grid | ||
classes={style["no-scroll-grid"]} | ||
columns={columns} | ||
rows={rows} | ||
rowClasses={Array(rows.length).fill(style["vertical-align-center"])} | ||
/> | ||
</div> | ||
); | ||
}); | ||
|
||
AllocationGrid.propTypes = { | ||
columns: PropTypes.array.isRequired, | ||
rows: PropTypes.array.isRequired, | ||
onAddRequiredResource: PropTypes.func.isRequired, | ||
onAddAllocationType: PropTypes.func.isRequired, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
.header-container { | ||
display: flex; | ||
justify-content: space-between; | ||
align-items: center; | ||
margin-bottom: 1rem; | ||
} | ||
|
||
.header-buttons { | ||
display: flex; | ||
gap: 1rem; /* Space between the buttons */ | ||
} | ||
|
||
.no-scroll-grid { | ||
overflow: auto; //hidden for no-scroll | ||
height: auto; | ||
} | ||
|
||
.allocation-types-grid { | ||
margin-bottom: 0.8rem; | ||
margin-top: 0.8rem; | ||
} | ||
|
||
.vertical-align-center td { | ||
vertical-align: middle; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,185 @@ | ||
import { useEffect } from "react"; | ||
import PropTypes from "prop-types"; | ||
import LoadingSpinner from "../shared/LoadingSpinner"; | ||
import { SelectInput } from "../shared/SelectInput/SelectInput"; | ||
import { ResourceForm } from "./ResourceForm"; | ||
import { AllocationGrid } from "./AllocationTypesGrid"; | ||
import { AddNewModal } from "./AddNewModal"; | ||
import { ExchangeRates } from "./ExchangeRates"; | ||
import Alert from "../shared/Alert"; | ||
import { | ||
useResourceData, | ||
useResourceOptions, | ||
useAllocationGrid, | ||
useResourceSubmit, | ||
useAllocationRowsAndColumns, | ||
} from "./helpers/hooks"; | ||
import { useExchangeRates } from "./helpers/useExchangeRates"; | ||
export default function EditResource({ | ||
resourceId, | ||
relativeUrlRoot, | ||
setExternalSubmit, | ||
}) { | ||
const { state, dispatch, handleError, fetchData } = useResourceData( | ||
resourceId, | ||
relativeUrlRoot | ||
); | ||
const { resourceData, loading, errors, successMessage } = state; | ||
const resourceDetails = resourceData?.resource_details; | ||
|
||
const { | ||
allowedActionsOptions, | ||
resourceTypesOptions, | ||
unitTypesOptions, | ||
availableResources, | ||
availableAllocationTypes, | ||
} = useResourceOptions(resourceData); | ||
|
||
const { | ||
showAddResourceModal, | ||
setShowAddResourceModal, | ||
showAddAllocationTypeModal, | ||
setShowAddAllocationTypeModal, | ||
selectedNewResource, | ||
handleSelectNewResource, | ||
handleSaveResources, | ||
selectedNewAllocationType, | ||
handleSelectNewAllocationType, | ||
handleSaveAllocationType, | ||
handleAllowedActionChange, | ||
handleCommentChange, | ||
handleRequiredResourceChange, | ||
} = useAllocationGrid(resourceData, resourceDetails, dispatch); | ||
|
||
const { exchangeRateColumns, exchangeRateRows, handleAddDiscountRate } = | ||
useExchangeRates(resourceData, dispatch); | ||
|
||
const handleSubmit = useResourceSubmit( | ||
resourceDetails, | ||
resourceId, | ||
relativeUrlRoot, | ||
fetchData, | ||
handleError, | ||
dispatch | ||
); | ||
|
||
// Expose handleSubmit to external Rails template script | ||
useEffect(() => { | ||
if (setExternalSubmit) { | ||
setExternalSubmit(handleSubmit); | ||
} | ||
}, [handleSubmit, setExternalSubmit]); | ||
|
||
const { allocationColumns, allocationRows } = useAllocationRowsAndColumns( | ||
resourceDetails, | ||
availableResources, | ||
selectedNewResource, | ||
allowedActionsOptions, | ||
handleAllowedActionChange, | ||
handleCommentChange, | ||
handleRequiredResourceChange | ||
); | ||
|
||
if (loading) return <LoadingSpinner />; | ||
if (errors.length > 0) { | ||
return ( | ||
<div> | ||
{errors.map((error, index) => ( | ||
<Alert key={index} color="danger"> | ||
{error} | ||
</Alert> | ||
))} | ||
</div> | ||
); | ||
} | ||
if (!resourceData) return <div>No resource data available.</div>; | ||
|
||
return ( | ||
<div className="edit-resource"> | ||
{successMessage.message && ( | ||
<Alert color={successMessage.color}>{successMessage.message}</Alert> | ||
)} | ||
<div> | ||
<h2>Edit Resource</h2> | ||
<ResourceForm | ||
resourceDetails={resourceDetails} | ||
resourceTypesOptions={resourceTypesOptions} | ||
unitTypesOptions={unitTypesOptions} | ||
dispatch={dispatch} | ||
/> | ||
</div> | ||
|
||
<AllocationGrid | ||
columns={allocationColumns} | ||
rows={allocationRows} | ||
onAddRequiredResource={() => setShowAddResourceModal(true)} | ||
onAddAllocationType={() => setShowAddAllocationTypeModal(true)} | ||
/> | ||
|
||
<AddNewModal | ||
show={showAddResourceModal} | ||
onClose={() => setShowAddResourceModal(false)} | ||
title="Add Required Resource" | ||
onSave={handleSaveResources} | ||
> | ||
<div> | ||
{availableResources.map((resource) => ( | ||
<label | ||
key={resource.resource_id} | ||
style={{ display: "flex", alignItems: "center", gap: "0.5rem" }} | ||
> | ||
<input | ||
type="checkbox" | ||
style={{ margin: 0 }} | ||
checked={selectedNewResource.includes(resource.resource_id)} | ||
onChange={(e) => | ||
handleSelectNewResource( | ||
resource.resource_id, | ||
e.target.checked | ||
) | ||
} | ||
/> | ||
{resource.resource_name} | ||
</label> | ||
))} | ||
</div> | ||
</AddNewModal> | ||
|
||
<AddNewModal | ||
show={showAddAllocationTypeModal} | ||
onClose={() => setShowAddAllocationTypeModal(false)} | ||
title="Add Allocation Type" | ||
onSave={handleSaveAllocationType} | ||
> | ||
<SelectInput | ||
label="Select Allocation Type" | ||
options={[ | ||
{ | ||
value: "", | ||
label: "Select an allocation type to add", | ||
disabled: true, | ||
}, | ||
...availableAllocationTypes.map((at) => ({ | ||
value: at.allocation_type_id, | ||
label: at.display_name, | ||
})), | ||
]} | ||
value={selectedNewAllocationType} | ||
onChange={handleSelectNewAllocationType} | ||
/> | ||
</AddNewModal> | ||
|
||
<ExchangeRates | ||
columns={exchangeRateColumns} | ||
rows={exchangeRateRows} | ||
onAddDiscountRate={handleAddDiscountRate} | ||
/> | ||
</div> | ||
); | ||
} | ||
|
||
EditResource.propTypes = { | ||
resourceId: PropTypes.number.isRequired, | ||
relativeUrlRoot: PropTypes.string.isRequired, | ||
setExternalSubmit: PropTypes.func, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import React from "react"; | ||
import PropTypes from "prop-types"; | ||
import Grid from "../shared/Grid"; | ||
import style from "./ExchangeRatesGrid.module.scss"; | ||
|
||
export const ExchangeRates = React.memo(function ExchangeRatesGrid({ | ||
columns, | ||
rows, | ||
onAddDiscountRate, | ||
}) { | ||
return ( | ||
<div className={style["exchange-rates-grid"]}> | ||
<div className={style["header-container"]}> | ||
<h2 className={style["header-title"]}>Exchange Rates</h2> | ||
<div className={style["header-buttons"]}> | ||
<button className="btn btn-primary" onClick={onAddDiscountRate}> | ||
<i className="fa fa-plus"></i> Add Discount Rate | ||
</button> | ||
</div> | ||
</div> | ||
<Grid | ||
classes={style["no-scroll-grid"]} | ||
columns={columns} | ||
rows={rows} | ||
rowClasses={Array(rows.length).fill(style["vertical-align-center"])} | ||
/> | ||
</div> | ||
); | ||
}); | ||
|
||
ExchangeRates.propTypes = { | ||
columns: PropTypes.array.isRequired, | ||
rows: PropTypes.array.isRequired, | ||
onAddDiscountRate: PropTypes.func.isRequired, | ||
}; |
Oops, something went wrong.