city, graphics page, errors on graphics still

This commit is contained in:
2025-07-27 21:10:01 +03:00
parent 972c62a1c0
commit bc22bc8a9b
7 changed files with 1654 additions and 1033 deletions

View File

@@ -242,6 +242,117 @@ export const getAreasWithCriteria = (organizationId) => {
}; };
}; };
export const getAreasByDataCenter = (dataCenterId) => {
return async (dispatch) => {
// Don't make the request if dataCenterId is undefined, null, or empty
if (!dataCenterId || dataCenterId === "undefined") {
dispatch({
type: "GET_AREAS_WITH_CRITERIA",
payload: {
getAreasWithCriteria: [],
},
});
return;
}
ApplicationService.http()
.post(
"/graphql",
{
query: `
{
dataCenter(id: "${dataCenterId}") {
id
dataCenter
area {
id
tag
countries {
id
countryCode
name
}
cities {
id
name
coordinates
country{
id
name
}
}
districts {
id
name
coordinates
city{
id
name
country{
id
name
}
}
}
neighborhoods {
id
name
minLong
maxLong
minLat
maxLat
district{
id
name
city{
id
name
country{
id
name
}
}
}
}
isDeleted
}
}
}
`,
},
{
headers: {
Authorization: "Bearer " + localStorage.getItem("accessToken"),
},
}
)
.then((response) => {
const dataCenter = response?.data?.data?.dataCenter;
let areas = [];
if (dataCenter && dataCenter.area && !dataCenter.area.isDeleted) {
areas = [dataCenter.area];
}
dispatch({
type: "GET_AREAS_WITH_CRITERIA",
payload: {
getAreasWithCriteria: areas,
},
});
})
.catch((error) => {
console.error("Error fetching areas by data center:", error);
dispatch({
type: "GET_AREAS_WITH_CRITERIA",
payload: {
getAreasWithCriteria: [],
},
});
});
};
};
export const addArea = (data) => { export const addArea = (data) => {
const dataToJSON = JSON.stringify(data); const dataToJSON = JSON.stringify(data);
const deleteQuotesFromKey = dataToJSON.replace(/"([^(")"]+)":/g, "$1:"); const deleteQuotesFromKey = dataToJSON.replace(/"([^(")"]+)":/g, "$1:");

View File

@@ -170,7 +170,8 @@ export const createDataCenter = (dataCenterData) => {
areaId: dataCenterData.areaId, areaId: dataCenterData.areaId,
address: dataCenterData.address || "", address: dataCenterData.address || "",
latitude: dataCenterData.latitude ? parseFloat(dataCenterData.latitude) : null, latitude: dataCenterData.latitude ? parseFloat(dataCenterData.latitude) : null,
longitude: dataCenterData.longitude ? parseFloat(dataCenterData.longitude) : null longitude: dataCenterData.longitude ? parseFloat(dataCenterData.longitude) : null,
city: dataCenterData.city
} }
} }
}, },
@@ -254,7 +255,8 @@ export const updateDataCenter = (id, dataCenterData) => {
areaId: dataCenterData.areaId, areaId: dataCenterData.areaId,
address: dataCenterData.address || "", address: dataCenterData.address || "",
latitude: dataCenterData.latitude ? parseFloat(dataCenterData.latitude) : null, latitude: dataCenterData.latitude ? parseFloat(dataCenterData.latitude) : null,
longitude: dataCenterData.longitude ? parseFloat(dataCenterData.longitude) : null longitude: dataCenterData.longitude ? parseFloat(dataCenterData.longitude) : null,
city: dataCenterData.city
} }
} }
}, },
@@ -336,3 +338,87 @@ export const deleteDataCenter = (id) => {
} }
}; };
}; };
export const getDataCenterVMs = (dataCenterId) => {
return new Promise(async (resolve, reject) => {
// Don't make the request if dataCenterId is undefined, null, or empty
if (!dataCenterId || dataCenterId === "undefined") {
console.log('getDataCenterVMs: No dataCenterId provided');
resolve([]);
return;
}
try {
console.log('getDataCenterVMs: Fetching VMs for data center:', dataCenterId);
const response = await ApplicationService.http()
.post(
"/graphql",
{
query: `
{
dataCenter(id: "${dataCenterId}") {
id
dataCenter
projects {
id
name
physicalMachines {
id
name
vms {
active {
id
name
status
power
}
inactive {
id
name
status
power
}
}
}
}
}
}
`,
},
{
headers: {
Authorization: "Bearer " + localStorage.getItem("accessToken"),
},
}
);
const dataCenter = response?.data?.data?.dataCenter;
console.log('getDataCenterVMs: Data center response:', dataCenter);
let allVMs = [];
if (dataCenter && dataCenter.projects) {
dataCenter.projects.forEach(project => {
if (project.physicalMachines) {
project.physicalMachines.forEach(pm => {
if (pm.vms) {
if (pm.vms.active) {
allVMs = allVMs.concat(pm.vms.active);
}
if (pm.vms.inactive) {
allVMs = allVMs.concat(pm.vms.inactive);
}
}
});
}
});
}
console.log('getDataCenterVMs: Found VMs:', allVMs);
resolve(allVMs);
} catch (error) {
console.error("Error fetching VMs by data center:", error);
resolve([]);
}
});
};

View File

@@ -161,7 +161,7 @@ export const getSubSectorById = (id) => {
dispatch({ dispatch({
type: "GET_SUBSECTOR_BY_ID", type: "GET_SUBSECTOR_BY_ID",
payload: { payload: {
subSector, subSector: subSector || {},
}, },
}); });
}); });

View File

@@ -689,3 +689,119 @@ export const deleteDataInput = (dataId) => {
}); });
}; };
}; };
export const getMainDataTablesByVMs = (data) => {
return async (dispatch) => {
const { filterOptions } = data;
try {
const response = await ApplicationService.http()
.post(
"/graphql",
{
query: `
{
mainDataTables(
criteria: {
year: "${filterOptions?.year?.value}"
deleted: false
}
) {
year
sector { id tag }
subSector{ id tag }
activitySubUnit{ id tag }
totalEmission
emissionScope{ tag }
emissionSource{ id tag }
vm { id name status power }
}
}
`,
},
{
headers: {
Authorization: "Bearer " + localStorage.getItem("accessToken"),
},
}
);
const allMainDataTables = response.data.data.mainDataTables || [];
dispatch({
type: "GET_MAIN_TABLES",
payload: {
mainDataTables: allMainDataTables,
},
});
} catch (error) {
console.error("Error fetching main data tables:", error);
dispatch({
type: "GET_MAIN_TABLES",
payload: {
mainDataTables: [],
},
});
}
};
};
export const testMainDataTables = () => {
return async (dispatch) => {
try {
console.log('testMainDataTables: Testing basic mainDataTables query');
const response = await ApplicationService.http()
.post(
"/graphql",
{
query: `
{
mainDataTables(
criteria: {
deleted: false
}
) {
id
year
totalEmission
vm {
id
name
status
power
}
}
}
`,
},
{
headers: {
Authorization: "Bearer " + localStorage.getItem("accessToken"),
},
}
);
console.log('testMainDataTables: Response:', response.data);
if (response.data.errors) {
console.error('testMainDataTables: GraphQL Errors:', response.data.errors);
}
const allData = response.data.data.mainDataTables || [];
console.log('testMainDataTables: All mainDataTables:', allData);
console.log('testMainDataTables: Count:', allData.length);
// Check which records have VM data
const recordsWithVM = allData.filter(record => record.vm);
console.log('testMainDataTables: Records with VM:', recordsWithVM);
console.log('testMainDataTables: Records with VM count:', recordsWithVM.length);
dispatch({
type: "GET_MAIN_TABLES",
payload: {
mainDataTables: allData,
},
});
} catch (error) {
console.error("testMainDataTables: Error:", error);
}
};
};

View File

@@ -30,7 +30,7 @@ const datasReducer = (state = initialState, action) => {
case "GET_SUBSECTOR_BY_ID": case "GET_SUBSECTOR_BY_ID":
return { return {
...state, ...state,
subSector: action.payload.subSector, subSector: action.payload.subSector || {},
}; };
case "GET_ACTIVITY_SUBUNITS": case "GET_ACTIVITY_SUBUNITS":
return { return {

View File

@@ -31,6 +31,8 @@ import withReactContent from "sweetalert2-react-content";
import { getDataCenters, createDataCenter, updateDataCenter, deleteDataCenter } from "../redux/actions/dataCenter"; import { getDataCenters, createDataCenter, updateDataCenter, deleteDataCenter } from "../redux/actions/dataCenter";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { getAreas } from "../redux/actions/areas"; import { getAreas } from "../redux/actions/areas";
import { getSectors, getSectorById, getSubSectorById, getConsuptionUnits } from "../redux/actions/datas";
import { getAllEmissionSources } from "../redux/actions/emissionSources";
import { permissionCheck } from "../components/permission-check"; import { permissionCheck } from "../components/permission-check";
import { customFilterForSelect } from "../utility/Utils"; import { customFilterForSelect } from "../utility/Utils";
import { MapContainer, TileLayer, Marker, useMapEvents } from 'react-leaflet'; import { MapContainer, TileLayer, Marker, useMapEvents } from 'react-leaflet';
@@ -107,14 +109,33 @@ const DataCenterManagement = () => {
address: "", address: "",
latitude: null, latitude: null,
longitude: null, longitude: null,
ayposURL: "" ayposURL: "",
city: "",
emissionScopeId: null,
sectorId: null,
subSectorId: null,
emissionSourceId: null,
consuptionUnitId: null,
activitySubUnitId: null
}); });
const [mapPosition, setMapPosition] = useState(null); const [mapPosition, setMapPosition] = useState(null);
const dataCenterStore = useSelector((state) => state.dataCenter); const dataCenterStore = useSelector((state) => state.dataCenter);
const areasStore = useSelector((state) => state.areas); const areasStore = useSelector((state) => state.areas);
const datasStore = useSelector((state) => state.datas);
const emissionSourceStore = useSelector((state) => state.emissionSources);
const [areasOptions, setAreasOptions] = useState([]); const [areasOptions, setAreasOptions] = useState([]);
const [sectorsOptions, setSectorsOptions] = useState([]);
const [subSectorsOptions, setSubSectorsOptions] = useState([]);
const [emissionSourcesOptions, setEmissionSourcesOptions] = useState([]);
const [consuptionUnitsOptions, setConsuptionUnitsOptions] = useState([]);
const [activitySubUnitsOptions, setActivitySubUnitsOptions] = useState([]);
const [emissionScopesOptions, setEmissionScopesOptions] = useState([]);
// Add state for selected sector and sub sector like in data input
const [selectedSector, setSelectedSector] = useState(null);
const [selectedSubSector, setSelectedSubSector] = useState(null);
const [editingDataCenter, setEditingDataCenter] = useState(null); const [editingDataCenter, setEditingDataCenter] = useState(null);
@@ -205,6 +226,7 @@ const DataCenterManagement = () => {
useEffect(() => { useEffect(() => {
dispatch(getDataCenters()); dispatch(getDataCenters());
dispatch(getAreas()); dispatch(getAreas());
dispatch(getSectors());
}, [dispatch]); }, [dispatch]);
useEffect(() => { useEffect(() => {
@@ -216,6 +238,96 @@ const DataCenterManagement = () => {
); );
}, [areasStore]); }, [areasStore]);
useEffect(() => {
setSectorsOptions(
datasStore?.sectors?.map((sector) => ({
value: sector?.id,
label: sector?.tag,
}))
);
}, [datasStore?.sectors]);
useEffect(() => {
setSubSectorsOptions([]);
setSubSectorsOptions(
datasStore?.sector?.subSectors?.map((subSector) => ({
value: subSector?.id,
label: subSector?.tag,
}))
);
}, [datasStore?.sector]);
useEffect(() => {
setActivitySubUnitsOptions(
datasStore?.subSector?.activitySubUnits?.map((activitySubUnit) => ({
value: activitySubUnit?.id,
label: activitySubUnit?.tag,
}))
);
}, [datasStore?.subSector]);
useEffect(() => {
setEmissionSourcesOptions(
emissionSourceStore?.emissionSources
?.filter((source) => source.convertUnitCheck != false)
?.map((source) => ({
value: source?.id,
label: source?.tag,
}))
);
}, [emissionSourceStore?.emissionSources]);
useEffect(() => {
if (selectedDataCenter?.emissionSourceId) {
dispatch(
getConsuptionUnits({
id: selectedDataCenter?.emissionSourceId,
sector: selectedDataCenter?.sectorId,
})
);
}
}, [selectedDataCenter?.emissionSourceId]);
useEffect(() => {
if (selectedSubSector != null) {
dispatch(getAllEmissionSources(selectedSubSector));
}
}, [selectedSubSector]);
useEffect(() => {
if (selectedSector != null) {
dispatch(getSectorById(selectedSector));
}
}, [selectedSector]);
useEffect(() => {
if (selectedSubSector != null) {
dispatch(getSubSectorById(selectedSubSector));
}
}, [selectedSubSector]);
useEffect(() => {
setConsuptionUnitsOptions(
datasStore?.consuptionUnits?.map((consuptionUnit) => ({
value: consuptionUnit?.unit?.id,
label: consuptionUnit?.unit?.description,
}))
);
}, [datasStore?.consuptionUnits]);
useEffect(() => {
setEmissionScopesOptions([
{
label: "Şehir İçi",
value: false,
},
{
label: "Şehir Dışı",
value: true,
},
]);
}, []);
const handleEditDataCenter = (row) => { const handleEditDataCenter = (row) => {
setEditingDataCenter(row); setEditingDataCenter(row);
setSelectedDataCenter({ setSelectedDataCenter({
@@ -226,8 +338,20 @@ const DataCenterManagement = () => {
address: row.address, address: row.address,
latitude: row.latitude, latitude: row.latitude,
longitude: row.longitude, longitude: row.longitude,
ayposURL: row.ayposURL ayposURL: row.ayposURL,
city: row.city,
emissionScopeId: row.emissionScope?.id,
sectorId: row.sector?.id,
subSectorId: row.subSector?.id,
emissionSourceId: row.emissionSource?.id,
consuptionUnitId: row.consuptionUnit?.id,
activitySubUnitId: row.activitySubUnit?.id
}); });
// Set the selected sector and sub sector for cascading dropdowns
setSelectedSector(row.sector?.id);
setSelectedSubSector(row.subSector?.id);
// Only set map position if we have both address and valid coordinates // Only set map position if we have both address and valid coordinates
setMapPosition(row.address && row.latitude && row.longitude ? [row.latitude, row.longitude] : null); setMapPosition(row.address && row.latitude && row.longitude ? [row.latitude, row.longitude] : null);
setShowAddModal(true); setShowAddModal(true);
@@ -272,7 +396,14 @@ const DataCenterManagement = () => {
// Ensure number is set for new data centers // Ensure number is set for new data centers
const dataToSubmit = { const dataToSubmit = {
...selectedDataCenter, ...selectedDataCenter,
number: selectedDataCenter.number || 1 // Default to 1 if not set number: selectedDataCenter.number || 1, // Default to 1 if not set
city: selectedDataCenter.city, // Add city to the payload
emissionScopeId: selectedDataCenter.emissionScopeId,
sectorId: selectedDataCenter.sectorId,
subSectorId: selectedDataCenter.subSectorId,
emissionSourceId: selectedDataCenter.emissionSourceId,
consuptionUnitId: selectedDataCenter.consuptionUnitId,
activitySubUnitId: selectedDataCenter.activitySubUnitId
}; };
if (editingDataCenter) { if (editingDataCenter) {
@@ -284,12 +415,12 @@ const DataCenterManagement = () => {
await dispatch(createDataCenter(dataToSubmit)); await dispatch(createDataCenter(dataToSubmit));
enqueueSnackbar(t("DataCenter.createSuccess"), { variant: "success" }); enqueueSnackbar(t("DataCenter.createSuccess"), { variant: "success" });
} }
handleCloseModal(); handleCloseModal();
} catch (error) { } catch (error) {
console.error("Operation error:", error); console.error("Submit error:", error);
enqueueSnackbar( enqueueSnackbar(
error?.message || (editingDataCenter ? t("DataCenter.updateError") : t("DataCenter.createError")), error?.message || t("DataCenter.submitError"),
{ variant: "error" } { variant: "error" }
); );
} }
@@ -305,7 +436,8 @@ const DataCenterManagement = () => {
address: "", address: "",
latitude: null, latitude: null,
longitude: null, longitude: null,
ayposURL: "" ayposURL: "",
city: ""
}); });
setMapPosition(null); setMapPosition(null);
setEditingDataCenter(null); setEditingDataCenter(null);
@@ -352,7 +484,7 @@ const DataCenterManagement = () => {
try { try {
const response = await nominatimAxios.get(`/search?format=json&q=${encodeURIComponent(address)}`); const response = await nominatimAxios.get(`/search?format=json&q=${encodeURIComponent(address)}`);
if (response.data && response.data[0]) { if (response.data && response.data[0]) {
const { lat, lon } = response.data[0]; const { lat, lon } = response.data[0];
const newPosition = [parseFloat(lat), parseFloat(lon)]; const newPosition = [parseFloat(lat), parseFloat(lon)];
@@ -364,7 +496,7 @@ const DataCenterManagement = () => {
})); }));
return true; return true;
} }
// If no results found, clear the coordinates // If no results found, clear the coordinates
setMapPosition(null); setMapPosition(null);
setSelectedDataCenter(prev => ({ setSelectedDataCenter(prev => ({
@@ -393,7 +525,7 @@ const DataCenterManagement = () => {
...prev, ...prev,
address: newAddress address: newAddress
})); }));
// If address is empty, clear the coordinates // If address is empty, clear the coordinates
if (!newAddress.trim()) { if (!newAddress.trim()) {
setMapPosition(null); setMapPosition(null);
@@ -488,6 +620,24 @@ const DataCenterManagement = () => {
/> />
</FormGroup> </FormGroup>
</Col> </Col>
<Col sm="6">
<FormGroup>
<Label for="city">{t("DataCenter.city")}</Label>
<Input
type="text"
name="city"
id="city"
placeholder={t("DataCenter.city")}
value={selectedDataCenter.city}
onChange={(e) =>
setSelectedDataCenter({
...selectedDataCenter,
city: e.target.value,
})
}
/>
</FormGroup>
</Col>
<Col sm="12"> <Col sm="12">
<FormGroup> <FormGroup>
<Label for="area">{t("DataCenter.area")}</Label> <Label for="area">{t("DataCenter.area")}</Label>
@@ -536,6 +686,158 @@ const DataCenterManagement = () => {
</div> </div>
</FormGroup> </FormGroup>
</Col> </Col>
{/* Emission Scope Section */}
<Col sm="12">
<h5 className="mt-3 mb-2 text-primary">Emission Scope Configuration</h5>
</Col>
<Col sm="6">
<FormGroup>
<Label for="emissionScope">Emission Scope</Label>
<Select
id="emissionScope"
name="emissionScope"
placeholder="Select emission scope"
options={emissionScopesOptions}
value={emissionScopesOptions?.find(
(option) => option.value === selectedDataCenter.emissionScopeId
)}
onChange={(option) =>
setSelectedDataCenter({
...selectedDataCenter,
emissionScopeId: option?.value,
})
}
isClearable
filterOption={customFilterForSelect}
/>
</FormGroup>
</Col>
<Col sm="6">
<FormGroup>
<Label for="sector">Sector</Label>
<Select
id="sector"
name="sector"
placeholder="Select sector"
options={sectorsOptions}
value={sectorsOptions?.find(
(option) => option.value === selectedDataCenter.sectorId
)}
onChange={(option) => {
setSelectedSector(option?.value);
setSelectedDataCenter({
...selectedDataCenter,
sectorId: option?.value,
subSectorId: null,
emissionSourceId: null,
consuptionUnitId: null,
activitySubUnitId: null,
});
}}
isClearable
filterOption={customFilterForSelect}
/>
</FormGroup>
</Col>
<Col sm="6">
<FormGroup>
<Label for="subSector">Sub Sector</Label>
<Select
id="subSector"
name="subSector"
placeholder="Select sub sector"
options={subSectorsOptions}
value={subSectorsOptions?.find(
(option) => option.value === selectedDataCenter.subSectorId
)}
onChange={(option) => {
setSelectedSubSector(option?.value);
setSelectedDataCenter({
...selectedDataCenter,
subSectorId: option?.value,
emissionSourceId: null,
consuptionUnitId: null,
activitySubUnitId: null,
});
}}
isClearable
filterOption={customFilterForSelect}
isDisabled={!selectedDataCenter.sectorId}
/>
</FormGroup>
</Col>
<Col sm="6">
<FormGroup>
<Label for="emissionSource">Emission Source</Label>
<Select
id="emissionSource"
name="emissionSource"
placeholder="Select emission source"
options={emissionSourcesOptions}
value={emissionSourcesOptions?.find(
(option) => option.value === selectedDataCenter.emissionSourceId
)}
onChange={(option) => {
setSelectedDataCenter({
...selectedDataCenter,
emissionSourceId: option?.value,
consuptionUnitId: null,
});
}}
isClearable
filterOption={customFilterForSelect}
isDisabled={!selectedDataCenter.subSectorId}
/>
</FormGroup>
</Col>
<Col sm="6">
<FormGroup>
<Label for="consuptionUnit">Consumption Unit</Label>
<Select
id="consuptionUnit"
name="consuptionUnit"
placeholder="Select consumption unit"
options={consuptionUnitsOptions}
value={consuptionUnitsOptions?.find(
(option) => option.value === selectedDataCenter.consuptionUnitId
)}
onChange={(option) => {
setSelectedDataCenter({
...selectedDataCenter,
consuptionUnitId: option?.value,
});
}}
isClearable
filterOption={customFilterForSelect}
isDisabled={!selectedDataCenter.emissionSourceId}
/>
</FormGroup>
</Col>
<Col sm="12">
<FormGroup>
<Label for="activitySubUnit">Activity Sub Unit</Label>
<Select
id="activitySubUnit"
name="activitySubUnit"
placeholder="Select activity sub unit"
options={activitySubUnitsOptions}
value={activitySubUnitsOptions?.find(
(option) => option.value === selectedDataCenter.activitySubUnitId
)}
onChange={(option) => {
setSelectedDataCenter({
...selectedDataCenter,
activitySubUnitId: option?.value,
});
}}
isClearable
filterOption={customFilterForSelect}
isDisabled={!selectedDataCenter.subSectorId}
/>
</FormGroup>
</Col>
<Col sm="12"> <Col sm="12">
<FormGroup> <FormGroup>
<Label>{t("DataCenter.location")}</Label> <Label>{t("DataCenter.location")}</Label>

File diff suppressed because it is too large Load Diff