Notes![what is notes.io? What is notes.io?](/theme/images/whatisnotesio.png)
![]() ![]() Notes - notes.io |
Fragment,
useEffect,
useContext,
MouseEventHandler,
} from "react";
import Grid from "@mui/material/Unstable_Grid2";
import Box from "@mui/material/Box";
import ToggleButton from "@mui/material/ToggleButton";
import ToggleButtonGroup from "@mui/material/ToggleButtonGroup";
import AddIcon from "../../images/add.svg";
import Button from "@mui/material/Button";
import TextField from "@mui/material/TextField";
import Autocomplete from "@mui/material/Autocomplete";
import IconButton from "@mui/material/IconButton/IconButton";
import SearchIcon from "@mui/icons-material/Search";
import Table from "@mui/material/Table";
import TableBody from "@mui/material/TableBody";
import TableCell from "@mui/material/TableCell";
import TableContainer from "@mui/material/TableContainer";
import TableHead from "@mui/material/TableHead";
import TableRow from "@mui/material/TableRow";
import Paper from "@mui/material/Paper";
import MultiSelect from "../common/MultiSelect";
import AddBoxSharpIcon from "@mui/icons-material/AddBoxSharp";
import DeleteSharpIcon from "@mui/icons-material/DeleteSharp";
import _ from "lodash";
import ProjectContext from "../../context/project/ProjectContext";
import IProjectContext from "../../types/ProjectState";
import {
AssetUnitsMaster,
Suffix,
AssetUnitsSuffix,
ProjectUnitSuffix,
} from "../../types/project";
import { AlertColor, Icon } from "@mui/material";
import LoadingButton from "@mui/lab/LoadingButton/LoadingButton";
import { ServiceIndex } from "../../config/APIRoutes";
import Alert from "../common/Alert";
function UnitsConfiguration() {
const projectContext = useContext<IProjectContext>(ProjectContext);
const {
assetLookup,
assetSuffixes,
projectSuffixes,
getProjectAssetsV2,
getProjectRawAssetsV2,
getAssetLookupV2,
clearProjectAssets,
selectedProject,
loading,
addProjectUnitsV2,
deleteProjectUnitsV2,
} = projectContext;
const topSearches = [];
const [rows, setRows] = React.useState<AssetUnitsMaster[]>(
assetLookup ? assetLookup : []
);
const [projectAssets, setProjectAssets] = React.useState<AssetUnitsMaster[]>(
[]
);
const [projectRawAssets, setProjectRawAssets] = React.useState<
ProjectUnitSuffix[]
>([]);
const [projectSuffixLookup, setProjectSuffixLookup] = React.useState<
ProjectUnitSuffix[]
>([]);
const [updatedConfig, setUpdatedConfig] = React.useState<ProjectUnitSuffix[]>(
[]
);
const [addRecords, setAddRecords] = React.useState<ProjectUnitSuffix[]>([]);
const [deleteRecords, setDeleteRecords] = React.useState<ProjectUnitSuffix[]>(
[]
);
const [searchTerm, setSearchTerm] = React.useState("");
const searchRef = React.useRef<HTMLInputElement>(null);
const [view, setView] = React.useState("All");
const [configLoaded, setConfigLoaded] = React.useState(false);
const [configUpdated, setConfigUpdated] = React.useState(false);
const [showAlert, setShowAlert] = React.useState<boolean>(false);
const [alertMessage, setAlertMessage] = React.useState<{
message: string;
type: AlertColor;
}>({ message: "", type: "success" });
const handleChange = (
event: React.MouseEvent<HTMLElement>,
newView: string
) => {
setView(newView);
};
const handleSuffixChanges = (
values: string[],
keys: { AssetGroupID: string; AssetTypeID: string },
action: string
) => {
let records: ProjectUnitSuffix[] = [];
if (action === "ADD") {
values.forEach((item) => {
let record: ProjectUnitSuffix = {};
record.SuffixID = item;
record.AssetGroupID = keys.AssetGroupID;
record.AssetTypeID = keys.AssetTypeID;
record.ProjectID = selectedProject?.ID;
records.push(record);
});
setUpdatedConfig((oldRecords) => [...oldRecords, ...records]);
} else {
setUpdatedConfig((oldRecords) => {
values.forEach((item) => {
_.remove(oldRecords, (record) => item === record.SuffixID);
});
return [...oldRecords];
});
}
};
// const handleSearchChange: React.ChangeEventHandler<HTMLInputElement> = (
// event
// ) => {
// setRows(
// rows.filter(
// (row) =>
// row.category === event.currentTarget.value ||
// row.unitType === event.currentTarget.value ||
// row.alias === event.currentTarget.value
// )
// );
// };
const handleSearchChange = (event: React.MouseEvent<HTMLElement>) => {
if (searchRef.current) {
setSearchTerm(searchRef.current.value);
// console.log("Set SEARCH Term:", searchRef.current.value);
}
};
const showNewUnit = (event: React.MouseEvent<HTMLElement>) => {
event.preventDefault();
// navigate("/new-unit");
};
const showNewSuffix = (event: React.MouseEvent<HTMLElement>) => {
event.preventDefault();
//navigate("/new-suffix");
};
const fetchProjectAssets = async (projectId) => {
console.log("@@@@FETCHING PROJECT ASSET CONFIG:", projectId);
if (getProjectAssetsV2) {
try {
const assets = await getProjectAssetsV2(projectId);
// console.log("@@Assetd Lookup:", assets);
setProjectAssets(assets);
} catch (error) {
// console.log("@@Service Areas Error:", error);
}
}
if (getProjectRawAssetsV2) {
try {
const assets = await getProjectRawAssetsV2(projectId);
console.log("@@##Assetd rawLookup:", assets);
setProjectRawAssets(assets);
} catch (error) {
console.log("@@Units RAW Error:", error);
}
}
};
useEffect(() => {
console.log("&&&USEE DEFUALT:", selectedProject);
if (selectedProject) {
console.log("$$$UNits loading Proj:", selectedProject);
fetchProjectAssets(selectedProject.ID);
}
return () => {
console.log("$$$UNits clearing Proj:");
if (clearProjectAssets) clearProjectAssets();
};
//eslint-disable-next-line
}, []);
useEffect(() => {
console.log("&&&USEE PRJ SUFFIX:", projectSuffixes);
if (projectSuffixes && projectSuffixes.length > 0) {
setProjectSuffixLookup((suffixes) => [...projectSuffixes]);
}
// setConfigLoaded(true);
// if (projectAssets) {
// setProjectSuffixes(_.flatten(projectAssets, false));
// }
//eslint-disable-next-line
}, [projectSuffixes]);
useEffect(() => {
console.log("&&&USEE PRJ SUFFIX LKP:", projectSuffixLookup);
if (projectSuffixLookup && projectSuffixLookup.length > 0) {
// setProjectSuffixLookup(projectSuffixes);
console.log("$$$Config Load Completed:", projectSuffixLookup);
// setConfigLoaded(true);
}
setConfigLoaded(() => true);
// if (projectAssets) {
// setProjectSuffixes(_.flatten(projectAssets, false));
// }
//eslint-disable-next-line
}, [projectSuffixLookup]);
useEffect(() => {
console.log("&&&USEE PRJ CNF UPDTD:", updatedConfig);
if (updatedConfig && updatedConfig.length > 0) {
// setProjectSuffixLookup(projectSuffixes);
console.log("$$$Config updated:", updatedConfig);
setConfigUpdated(true);
}
// if (projectAssets) {
// setProjectSuffixes(_.flatten(projectAssets, false));
// }
//eslint-disable-next-line
}, [updatedConfig]);
useEffect(() => {
console.log("&&&USEE VIEW CHANGE:", view);
if (view && view === "All" && assetLookup) {
console.log("$$$changing view asset:", assetLookup);
console.log("$$$changing view suffix:", assetSuffixes);
console.log("$$$changing view proj suffix:", projectSuffixes);
// console.log("$copy of proj suffix:", projectSuffixLookup);
setRows(assetLookup);
} else {
// console.log("$$$changing view:", projectAssets);
// console.log("$$$changing view:", projectSuffixes);
setRows(projectAssets);
}
if (showAlert) {
setTimeout(() => {
setShowAlert(false);
}, 10000);
}
//eslint-disable-next-line
}, [view, assetLookup, projectAssets]);
useEffect(() => {
if (searchTerm && searchTerm !== "") {
setRows(assetLookup ? assetLookup && assetLookup.map((element) => {
return {
...element,
AssetTypes: element.AssetTypes && element.AssetTypes.filter((AssetTypes) =>
AssetTypes.AssetName && AssetTypes.AssetName.includes(searchTerm)
),
};
}
) : []);
}
}, [searchTerm]);
const fetchAssets = async () => {
console.log("@@Fetch Assetd:");
if (getAssetLookupV2) {
try {
const assetLookup = await getAssetLookupV2();
console.log("@@Assetd Lookup:", assetLookup);
} catch (error) {
console.log("@@Service Areas Error:", error);
}
}
};
const configExists = (AssetGroupID: string, AssetTypeID: string): boolean => {
if (projectSuffixes) {
let filteredList = _.filter(
projectSuffixes,
(item) =>
item.AssetGroupID === AssetGroupID && item.AssetTypeID === AssetTypeID
);
return filteredList.length > 0;
}
return false;
};
const getConfigSuffixes = (
AssetGroupID: string,
AssetTypeID: string
): any | undefined => {
// console.log("Project Suffix Lkp:", projectSuffixLookup);
// console.log("AssetGroupID:", AssetGroupID);
// console.log("AssetTypeID:", AssetTypeID);
if (projectSuffixes) {
let filteredList = projectSuffixes
.filter(
(item) =>
item.AssetGroupID === AssetGroupID &&
item.AssetTypeID === AssetTypeID
)
.map((item) => {
// console.log("## FILLL ITEM: ", item);
// {name:item.Suffixes});
let retValue: { name: string; value: string } = {
name: "",
value: "",
};
retValue.name = item.SuffixName ? item.SuffixName : "";
retValue.value = item.SuffixID ? item.SuffixID : "";
return retValue;
});
// console.log("## FILLL: ", filteredList);
if (filteredList.length > 0) return filteredList;
}
return [];
};
const extractSuffixLookup = (
suffixes: Suffix[]
): { name: string; value: string }[] => {
// console.log("###SUFFIX LOOKUP LIST:", suffixes);
const sx = suffixes?.map((item) => {
let retValue: { name: string; value: string } = { name: "", value: "" };
retValue.name = item.SuffixName ? item.SuffixName : "";
retValue.value = item.SuffixID ? item.SuffixID : "";
return retValue;
});
// console.log("###SUFFIX LOOKUP INPUT:", sx);
return sx;
};
const configSuffixesValues = (
AssetGroupID: string | undefined,
AssetTypeID: string | undefined
): string[] => {
let retValue = [];
if (AssetGroupID && AssetTypeID) {
retValue = getConfigSuffixes(AssetGroupID, AssetTypeID);
retValue = _.map(retValue, "value");
// console.log("## Final Entry Suffix: ", retValue);
}
return retValue;
};
const handleAddRow = (
event: React.MouseEvent<HTMLButtonElement>,
AssetGroupID: string | undefined,
AssetTypeID: string | undefined
) => {
// console.log(`## Add Row for: ${AssetGroupID} , ${AssetTypeID}`);
setAddRecords((records) => [...records, { AssetGroupID, AssetTypeID }]);
console.log("## INT OPS ADD Records: ", addRecords);
console.log("## INT OPS UPD RECORDS: ", updatedConfig);
setConfigUpdated(true);
//check if the entry exist in
};
const handleDeleteRow = (
event: React.MouseEvent<HTMLButtonElement>,
AssetGroupID: string | undefined,
AssetTypeID: string | undefined
) => {
console.log(`## Delete Row for: ${AssetGroupID} , ${AssetTypeID}`);
setDeleteRecords((records) => [...records, { AssetGroupID, AssetTypeID }]);
console.log("## INT OPS DEL Records: ", deleteRecords);
console.log("## INT OPS UPD RECORDS: ", updatedConfig);
setConfigUpdated(true);
};
const saveUnits = async (event: React.MouseEvent<HTMLElement>) => {
//Consolidate Items to be saved to the DB
console.log("## DB OPS Add Records: ", addRecords);
console.log("## DB OPS DEL Records: ", deleteRecords);
console.log("## DB OPS UPD RECORDS: ", updatedConfig);
//Add Items to DB
//Delete items from DB
await Promise.all([SaveAddRecords(), SaveDeleteRecords()]);
setConfigUpdated(() => false);
console.log(
`##*** Fetching Assets for Project ID: ${selectedProject ? selectedProject.ID : ""
}
PROJECT: ${JSON.stringify(selectedProject)}`
);
fetchAssets();
if (selectedProject) fetchProjectAssets(selectedProject.ID);
// setConfigLoaded(true);
};
const SaveAddRecords = () => {
return new Promise(async (resolve, reject) => {
if (addRecords.length > 0) {
let records;
addRecords.forEach((recGroup) => {
records = updatedConfig.filter(
(item) =>
item.AssetGroupID === recGroup.AssetGroupID &&
item.AssetTypeID === recGroup.AssetTypeID
);
});
console.log(`## Add Rows to DB: ${records}`);
try {
if (addProjectUnitsV2) {
const result = await addProjectUnitsV2(records);
console.log(`## Add Rows to DB is: ${result}`);
if (result)
setAlertMessage({
message: "Successfully Added records",
type: "success",
});
setShowAlert(true);
setAddRecords((old) => []);
setUpdatedConfig((old) => []);
resolve(true);
}
} catch (error) {
console.log(`## Error Addign Rows to DB: ${records}`);
reject(false);
}
}
resolve(true);
// setAddRecords((old) => []);
});
};
const SaveDeleteRecords = () => {
return new Promise(async (resolve, reject) => {
if (deleteRecords.length > 0) {
console.log(`## Delete Rows Ref: ${JSON.stringify(projectRawAssets)}`);
let records = projectRawAssets.filter((item) => {
let found = deleteRecords.findIndex(
(rec) =>
item.AssetGroupID === rec.AssetGroupID &&
item.AssetTypeID === rec.AssetTypeID
);
console.log(`## Delete Rows Found: ${found}`);
return found >= 0;
});
console.log(`## Delete Rows from DB: ${JSON.stringify(records)}`);
try {
if (deleteProjectUnitsV2) {
const result = await deleteProjectUnitsV2(records);
console.log(`## DELETE Rows to DB is: ${result}`);
if (result)
setAlertMessage({
message: "Successfully Deleted records",
type: "success",
});
setShowAlert(true);
setDeleteRecords((old) => []);
resolve(true);
}
} catch (error) {
console.log(`## Error Addign Rows to DB: ${records}`);
reject(false);
}
}
resolve(true);
});
};
const loadingButton = () => {
return (
<LoadingButton size='small' loading={loading} variant='outlined' disabled>
<span>disabled</span>
</LoadingButton>
);
};
const showSelect = (AssetGroupID, AssetTypeID) => {
const deletedRecord = _.findIndex(projectAssets, {
AssetGroupID,
AssetTypeID,
});
console.log(
"SHOW? AssetGroupID:",
AssetGroupID,
" AssetTypeID:",
AssetTypeID,
"#",
deletedRecord
);
return !deletedRecord;
};
const displayActions = (AssetGroupID, AssetTypeID) => {
//check if project config exists
let icon: any;
// console.log(
// "## IconDisp:",
// projectAssets,
// "AssetGroupID:",
// AssetGroupID,
// ",AssetTypeID:",
// AssetTypeID
// );
if (projectAssets) {
if (configExists(AssetGroupID, AssetTypeID)) {
// console.log(
// "## IconDisp Exists: AssetGroupID:",
// AssetGroupID,
// ",AssetTypeID:",
// AssetTypeID
// );
icon = (
<IconButton
className='nav-bar__logo__img'
sx={{ display: { xs: "none", md: "flex" }, mr: 1 }}
onClick={(e) => handleDeleteRow(e, AssetGroupID, AssetTypeID)}
>
<DeleteSharpIcon />
</IconButton>
);
} else {
// console.log(
// "## IconDisp Not Exists: AssetGroupID:",
// AssetGroupID,
// ",AssetTypeID:",
// AssetTypeID
// );
icon = (
<IconButton
className='nav-bar__logo__img'
sx={{ display: { xs: "none", md: "flex" }, mr: 1 }}
onClick={(e) => handleAddRow(e, AssetGroupID, AssetTypeID)}
>
<AddBoxSharpIcon />
</IconButton>
);
}
} else {
icon = loadingButton();
}
// if so, check if record exists => displa delete / Add
//Otherwise display loading Icon...
return icon;
};
return (
<Fragment>
{showAlert && (
<Alert message={alertMessage?.message} type={alertMessage?.type} />
)}
<Grid
container
display='flex'
flexDirection='row'
justifyContent='space-between'
width='100%'
>
<Grid md={4} sx={{ margin: 2, px: 2 }}>
<ToggleButtonGroup
color='primary'
value={view}
exclusive
onChange={handleChange}
aria-label='Units Tab'
>
<ToggleButton size='large' value='All'>
ALL UNITS
</ToggleButton>
<ToggleButton size='large' value='Configured'>
CONFIGURED UNITS
</ToggleButton>
</ToggleButtonGroup>
</Grid>
{/* <Grid md={4} sx={{ margin: 2, px: 2 }}>
<Button
sx={{ p: 1, mx: 2 }}
onClick={showNewSuffix}
color='secondary'
variant='contained'
disabled
>
<img
src={AddIcon}
alt='Create New Suffix'
className='nav-bar__menu__button_icon'
/>
Add Suffix
</Button>
<Button
sx={{ p: 1, mx: 2 }}
onClick={showNewUnit}
color='secondary'
variant='contained'
disabled
>
<img
src={AddIcon}
alt='Create New Unit'
className='nav-bar__menu__button_icon'
/>
Add Unit
</Button>
</Grid> */}
<Grid
md={3}
sx={{
margin: 2,
px: 2,
display: "flex",
flexDirection: "row",
}}
>
<Autocomplete
id='search-auto-complete'
fullWidth
freeSolo
options={topSearches.map((option) => option)}
renderInput={(params) => (
<TextField
{...params}
label='Search'
InputProps={{
...params.InputProps,
type: "search",
}}
inputRef={searchRef}
/>
)}
/>
<Button
variant='contained'
color='secondary'
sx={{ mb: 9 }}
onClick={handleSearchChange}
>
<IconButton
aria-label='search'
component='label'
sx={{ backgroundColor: "secondary" }}
>
<SearchIcon />
</IconButton>
</Button>
</Grid>
</Grid>
<Grid container sx={{ mx: 2, px: 2 }}>
<TableContainer component={Paper} sx={{ mx: 2, px: 2 }}>
<Table sx={{ minWidth: 700 }} aria-label='spanning table'>
<TableHead>
<TableRow>
<TableCell sx={{ fontSize: "large" }}>Category</TableCell>
<TableCell sx={{ fontSize: "large" }} align='left'>
Unit Type
</TableCell>
{/* <TableCell sx={{ fontSize: "large" }} align='left'>
Unit Type Alias
</TableCell> */}
<TableCell sx={{ fontSize: "large" }} align='left'>
Suffix
</TableCell>
<TableCell sx={{ fontSize: "large" }} align='right'>
Action
</TableCell>
</TableRow>
</TableHead>
<TableBody>
{rows.map(({ AssetGroupType, AssetGroupID, AssetTypes }) => (
<Fragment>
{AssetTypes && AssetTypes.length > 0 && (
<TableRow key={AssetGroupID}>
<TableCell rowSpan={AssetTypes.length + 1}>
{AssetGroupType}
</TableCell>
</TableRow>
)}
{AssetTypes &&
AssetTypes.map((assetType) => (
<Fragment>
<TableRow key={assetType.AssetTypeID}>
<TableCell align='left'>
{assetType.AssetName}
</TableCell>
<TableCell align='left'>
{configLoaded ? (
<MultiSelect
key={assetType.AssetTypeID}
inputs={extractSuffixLookup(
assetType.Suffixes ? assetType.Suffixes : []
)}
// values={_.map(
// getConfiguredSuffices(assetType.AssetTypeID),
// "SuffixName"
// )}
values={configSuffixesValues(
AssetGroupID,
assetType.AssetTypeID
)}
keys={{
AssetGroupID: AssetGroupID
? AssetGroupID
: "",
AssetTypeID: assetType.AssetTypeID
? assetType.AssetTypeID
: "",
}}
updateSuffixSelection={handleSuffixChanges}
/>
) : (
<MultiSelect
key={assetType.AssetTypeID}
// inputs={extractSuffixLookup(
// assetType.Suffixes ? assetType.Suffixes : []
// )}
// values={_.map(
// getConfiguredSuffices(assetType.AssetTypeID),
// "SuffixName"
// )}
// values={configSuffixesValues(
// AssetGroupID,
// assetType.AssetTypeID
// )}
/>
)}
</TableCell>
{configLoaded && (
<TableCell align='left'>
{displayActions(
AssetGroupID,
assetType.AssetTypeID
)}
</TableCell>
)}
</TableRow>
</Fragment>
))}
</Fragment>
))}
</TableBody>
</Table>
</TableContainer>
{/* <Grid
container
sx={{ margin: 2, px: 2 }}
display='flex'
flexDirection='row'
justifyContent='flex-end'
> */}
<Box
display='flex'
width='100%'
flexDirection='row'
justifyContent='flex-end'
sx={{ margin: 1, padding: 3 }}
>
<Button
variant='contained'
color='secondary'
sx={{ margin: 1, padding: 1 }}
>
Cancel
</Button>
<Button
variant='contained'
color='primary'
onClick={saveUnits}
disabled={!configUpdated}
sx={{ margin: 1, padding: 1 }}
>
Save
</Button>
</Box>
{/* </Grid> */}
</Grid>
</Fragment>
);
}
export default UnitsConfiguration;
![]() |
Notes is a web-based application for online taking notes. You can take your notes and share with others people. If you like taking long notes, notes.io is designed for you. To date, over 8,000,000,000+ notes created and continuing...
With notes.io;
- * You can take a note from anywhere and any device with internet connection.
- * You can share the notes in social platforms (YouTube, Facebook, Twitter, instagram etc.).
- * You can quickly share your contents without website, blog and e-mail.
- * You don't need to create any Account to share a note. As you wish you can use quick, easy and best shortened notes with sms, websites, e-mail, or messaging services (WhatsApp, iMessage, Telegram, Signal).
- * Notes.io has fabulous infrastructure design for a short link and allows you to share the note as an easy and understandable link.
Fast: Notes.io is built for speed and performance. You can take a notes quickly and browse your archive.
Easy: Notes.io doesn’t require installation. Just write and share note!
Short: Notes.io’s url just 8 character. You’ll get shorten link of your note when you want to share. (Ex: notes.io/q )
Free: Notes.io works for 14 years and has been free since the day it was started.
You immediately create your first note and start sharing with the ones you wish. If you want to contact us, you can use the following communication channels;
Email: [email protected]
Twitter: http://twitter.com/notesio
Instagram: http://instagram.com/notes.io
Facebook: http://facebook.com/notesio
Regards;
Notes.io Team