23 Commits

Author SHA1 Message Date
a14bc4e73a Add cityID in creation and update and edit some graphics in the map 2025-08-19 09:24:29 +03:00
50c6a2ef5b cloudsystem column added 2025-08-19 07:36:45 +03:00
d4e40f5a6b just pushing this to resolve merge conflict i have no changes made in this commit 2025-08-19 07:33:53 +03:00
bbb0976aa1 added the cloudsystem column 2025-08-19 07:16:17 +03:00
085a417016 Fix dropdown selection overflow while scrolling 2025-08-19 06:51:50 +03:00
edd8feb4d2 Add optimization to show data faster using Memo 2025-08-19 06:43:22 +03:00
2d39883b7f filtering raw data page 2025-08-19 06:17:37 +03:00
21b757cf77 Fix small translation in Map 2025-08-19 05:39:16 +03:00
8bd6d94174 Fix the DataCenterOverview tab display by removing project relation 2025-08-19 05:39:02 +03:00
Ali Sadeghi
b5901a049c Merge: Add city to datacenter, cloudsystem to summary, fix listener 2025-08-19 04:43:53 +03:00
82f86a62ca Fix issue in updating datacenter
Found a hibernate cascade issue and was fixed by reuse the existing collection instaed of creating a new one in updating the datacenter entity
2025-08-19 00:15:51 +03:00
47959fb35f Make the datacenter creation modal mobile friendly 2025-08-19 00:08:42 +03:00
2257ec79f6 Make creation of default area nested in city initialization 2025-08-19 00:08:01 +03:00
17d77fcda7 Fix message queue data misnaming 2025-08-19 00:07:20 +03:00
92d88df213 Fix Backend error:
Error loading data: Exception while fetching data (/vmEmissionSummary) : org.hibernate.exception.SQLGrammarException: could not extract ResultSet
2025-08-18 08:03:40 +03:00
a66b01334d Small bug fix 2025-08-18 08:02:34 +03:00
c7e60c25eb Add datacenter with multiple emission source and inputs 2025-08-18 06:12:19 +03:00
ebd997a33d Fix the datacenter query according to the changes in backend 2025-08-18 05:38:51 +03:00
dd04a057b1 Comment not needed orgnization code 2025-08-18 05:38:39 +03:00
d224905ba0 Make the Datacenter module structure following the whole code structure 2025-08-18 05:38:20 +03:00
b5ceb1591e Merge Backend Updates 2025-08-18 04:28:45 +03:00
89b4644983 few translation edits and changing it to use vmEmission query 2025-08-09 20:08:56 +03:00
39fffadbd2 fixed issue GUI and Datacenter tab related 2025-08-07 19:28:56 +03:00
37 changed files with 2515 additions and 1027 deletions

39
docker-compose.yml Normal file
View File

@@ -0,0 +1,39 @@
services:
backend:
build:
context: ./sge-backend
dockerfile: Dockerfile
ports:
- "8080:8080"
env_file:
- ./config.conf
environment:
SPRING_PROFILES_ACTIVE: docker
depends_on:
- database
restart: unless-stopped
frontend:
build:
context: ./sge-frontend
dockerfile: Dockerfile
ports:
- "80:80"
env_file:
- ./config.conf
restart: unless-stopped
database:
image: postgres:15
environment:
POSTGRES_DB: sge
POSTGRES_USER: sge
POSTGRES_PASSWORD: 147
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
restart: unless-stopped
volumes:
postgres_data:

View File

@@ -121,7 +121,8 @@ public class SgsApplication implements CommandLineRunner {
@Autowired @Autowired
public SgsApplication(RoleService roleService, PermissionService permissionService, RoleRepo roleRepo, public SgsApplication(RoleService roleService, PermissionService permissionService, RoleRepo roleRepo,
AreaService areaService, NeighborhoodRepo neighborhoodRepo, NeighborhoodService neighborhoodService, CityService cityService, AreaService areaService, NeighborhoodRepo neighborhoodRepo, NeighborhoodService neighborhoodService,
CityService cityService,
CityRepo cityRepo, DistrictRepo districtRepo, DistrictService districtService, CountryRepo countryRepo, CityRepo cityRepo, DistrictRepo districtRepo, DistrictService districtService, CountryRepo countryRepo,
CountryService countryService, OrganizationService organizationService, UserService userService, CountryService countryService, OrganizationService organizationService, UserService userService,
PasswordEncoder passwordEncoder, SectorService sectorService, SubSectorService subSectorService, PasswordEncoder passwordEncoder, SectorService sectorService, SubSectorService subSectorService,
@@ -789,7 +790,7 @@ public class SgsApplication implements CommandLineRunner {
paginate_datacenters_get.setDescription(PermissionDescription.PAGINATE_DATACENTERS_GET); paginate_datacenters_get.setDescription(PermissionDescription.PAGINATE_DATACENTERS_GET);
permissionService.save(paginate_datacenters_get); permissionService.save(paginate_datacenters_get);
} }
// Ensure SUPER_ADMIN has all permissions // Ensure SUPER_ADMIN has all permissions
Optional<Role> superAdminRole = roleRepo.findByTag("SUPER_ADMIN"); Optional<Role> superAdminRole = roleRepo.findByTag("SUPER_ADMIN");
if (superAdminRole.isPresent()) { if (superAdminRole.isPresent()) {
@@ -858,6 +859,7 @@ public class SgsApplication implements CommandLineRunner {
} }
if (cityService.findAll().isEmpty()) { if (cityService.findAll().isEmpty()) {
createCitiesFromJson(); createCitiesFromJson();
createDefaultArea();
} }
if (districtService.findAll().isEmpty()) { if (districtService.findAll().isEmpty()) {
createDistrictFromJson(); createDistrictFromJson();
@@ -865,33 +867,30 @@ public class SgsApplication implements CommandLineRunner {
if (neighborhoodService.findAll().isEmpty()) { if (neighborhoodService.findAll().isEmpty()) {
createNeighborhoodsFromJson(); createNeighborhoodsFromJson();
} }
if (!cityService.findAll().isEmpty()) {
createDefaultArea();
}
} }
void createDefaultArea() { void createDefaultArea() {
// Check if default area already exists // Check if default area already exists
List<Area> existingAreas = areaService.findAll(); List<Area> existingAreas = areaService.findAll();
boolean defaultAreaExists = existingAreas.stream() boolean defaultAreaExists = existingAreas.stream()
.anyMatch(area -> "Turkiye".equals(area.getTag()) && area.isDefaultArea()); .anyMatch(area -> "Turkiye".equals(area.getTag()) && area.isDefaultArea());
if (!defaultAreaExists) { if (!defaultAreaExists) {
Area defaultArea = new Area(); Area defaultArea = new Area();
defaultArea.setTag("Turkiye"); defaultArea.setTag("Turkiye");
defaultArea.setDefaultArea(true); defaultArea.setDefaultArea(true);
defaultArea.setDeleted(false); defaultArea.setDeleted(false);
// Get all cities to add to the default area // Get all cities to add to the default area
List<City> allCities = cityService.findAll(); List<City> allCities = cityService.findAll();
defaultArea.setCities(allCities); defaultArea.setCities(allCities);
// Get the Turkey country to add to the default area // Get the Turkey country to add to the default area
List<Country> countries = countryService.findAll(); List<Country> countries = countryService.findAll();
if (!countries.isEmpty()) { if (!countries.isEmpty()) {
defaultArea.setCountries(countries); defaultArea.setCountries(countries);
} }
areaService.save(defaultArea); areaService.save(defaultArea);
} }
} }

View File

@@ -1,4 +1,5 @@
package com.sgs.graphql.dataCenter.domain; package com.sgs.graphql.dataCenter.domain;
import com.fasterxml.jackson.annotation.JsonBackReference; import com.fasterxml.jackson.annotation.JsonBackReference;
import com.fasterxml.jackson.annotation.JsonManagedReference; import com.fasterxml.jackson.annotation.JsonManagedReference;
import com.sgs.graphql.area.domain.Area; import com.sgs.graphql.area.domain.Area;
@@ -15,7 +16,6 @@ import org.hibernate.annotations.LazyCollection;
import org.hibernate.annotations.LazyCollectionOption; import org.hibernate.annotations.LazyCollectionOption;
import org.hibernate.annotations.Fetch; import org.hibernate.annotations.Fetch;
import org.hibernate.annotations.FetchMode; import org.hibernate.annotations.FetchMode;
import org.springframework.transaction.annotation.Transactional;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -27,7 +27,7 @@ public class DataCenter extends BaseDomain {
@Column(unique = true) @Column(unique = true)
private Integer externalId; private Integer externalId;
private Integer number; private Integer number;
private Area area; private Area area;
private City city; private City city;
@@ -39,16 +39,14 @@ public class DataCenter extends BaseDomain {
private EmissionScope emissionScope; private EmissionScope emissionScope;
private Double consuptionAmount; private Double consuptionAmount;
private ActivitySubUnit activitySubUnit; private ActivitySubUnit activitySubUnit;
// New attributes // New attributes
private String ayposURL; private String ayposURL;
private String address; private String address;
private Double latitude; private Double latitude;
private Double longitude; private Double longitude;
@Column(name = "data_center_name") @Column(name = "data_center_name")
@Transactional
public String getDataCenter() { public String getDataCenter() {
return dataCenter; return dataCenter;
} }
@@ -96,7 +94,6 @@ public class DataCenter extends BaseDomain {
this.number = number; this.number = number;
} }
@ManyToOne(fetch = FetchType.EAGER) @ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "sector_id") @JoinColumn(name = "sector_id")
public Sector getSector() { public Sector getSector() {

View File

@@ -17,10 +17,10 @@ public class DataCenterDto {
private Integer externalId; private Integer externalId;
private Integer number; private Integer number;
private AreaDto area; private AreaDto area;
@JsonProperty("physical_machines") @JsonProperty("physical_machines")
private Map<String, PhysicalMachineDto> physicalMachine; private Map<String, PhysicalMachineDto> physicalMachine;
// Emission calculation fields // Emission calculation fields
private SectorDto sector; private SectorDto sector;
private SubSectorDto subSector; private SubSectorDto subSector;
@@ -62,12 +62,12 @@ public class DataCenterDto {
this.number = number; this.number = number;
} }
public AreaDto getArea() { public AreaDto getArea() {
return area; return area;
} }
public void setArea(AreaDto area) { public void setArea(AreaDto area) {
this.area = area; this.area = area;
} }
public Map<String, PhysicalMachineDto> getPhysicalMachine() { public Map<String, PhysicalMachineDto> getPhysicalMachine() {

View File

@@ -1,18 +1,26 @@
package com.sgs.graphql.dataCenter.mutation; package com.sgs.graphql.dataCenter.mutation;
import com.sgs.exception.GraphQLCustomException;
import com.sgs.graphql.dataCenter.mutation.mapper.DataCenterMapper; import com.sgs.graphql.dataCenter.mutation.mapper.DataCenterMapper;
import com.sgs.graphql.dataCenter.service.DataCenterService; import com.sgs.graphql.dataCenter.service.DataCenterService;
import com.sgs.graphql.dataCenter.domain.DataCenter; import com.sgs.graphql.dataCenter.domain.DataCenter;
import com.sgs.graphql.dataCenter.mutation.input.DataCenterCreateInput; import com.sgs.graphql.dataCenter.mutation.input.DataCenterCreateInput;
import com.sgs.graphql.dataCenter.mutation.input.DataCenterUpdateInput; import com.sgs.graphql.dataCenter.mutation.input.DataCenterUpdateInput;
import com.sgs.graphql.permission.domain.PermissionName; import com.sgs.graphql.permission.domain.PermissionName;
import com.sgs.graphql.systemHistory.enums.LogType;
import com.sgs.graphql.systemHistory.mutation.SystemLogger;
import com.sgs.graphql.userHistory.mutation.UserLogger;
import com.sgs.graphql.userNotification.mutation.UserNotificationMutation;
import graphql.kickstart.tools.GraphQLMutationResolver; import graphql.kickstart.tools.GraphQLMutationResolver;
import graphql.schema.DataFetchingEnvironment;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.transaction.Transactional;
import javax.validation.Valid; import javax.validation.Valid;
import java.util.NoSuchElementException;
import java.util.UUID; import java.util.UUID;
@Validated @Validated
@@ -21,57 +29,128 @@ public class DataCenterMutation implements GraphQLMutationResolver {
private final DataCenterService dataCenterService; private final DataCenterService dataCenterService;
private final DataCenterMapper dataCenterMapper; private final DataCenterMapper dataCenterMapper;
private final SystemLogger systemLogger;
private final UserLogger userLogger;
private final UserNotificationMutation notificationMutation;
@Autowired @Autowired
public DataCenterMutation(DataCenterService dataCenterService, DataCenterMapper dataCenterMapper) { public DataCenterMutation(DataCenterService dataCenterService, DataCenterMapper dataCenterMapper,
SystemLogger systemLogger, UserLogger userLogger,
UserNotificationMutation notificationMutation) {
this.dataCenterService = dataCenterService; this.dataCenterService = dataCenterService;
this.dataCenterMapper = dataCenterMapper; this.dataCenterMapper = dataCenterMapper;
this.systemLogger = systemLogger;
this.userLogger = userLogger;
this.notificationMutation = notificationMutation;
} }
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_CREATE + "')") @PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_CREATE + "')")
public DataCenter createDataCenter(@Valid DataCenterCreateInput input) { @Transactional
// Check for duplicate externalId public DataCenter createDataCenter(@Valid DataCenterCreateInput input, DataFetchingEnvironment environment) {
if (input.getExternalId() != null && dataCenterService.existsByExternalId(input.getExternalId())) { try {
throw new RuntimeException("This external id already exists: " + input.getExternalId()); // Check for duplicate externalId
if (input.getExternalId() != null && dataCenterService.existsByExternalId(input.getExternalId())) {
throw new GraphQLCustomException("2010", input.getExternalId().toString());
}
DataCenter dataCenter = dataCenterMapper.toEntity(input);
// Set auto-generated number if not provided
if (dataCenter.getNumber() == null) {
Integer maxNumber = dataCenterService.findMaxNumber();
dataCenter.setNumber((maxNumber == null) ? 1 : maxNumber + 1);
}
DataCenter savedDataCenter = dataCenterService.save(dataCenter);
// Log and notify
String dataCenterName = savedDataCenter.getDataCenter() != null ? savedDataCenter.getDataCenter()
: "DataCenter #" + savedDataCenter.getNumber();
systemLogger.createSystemLog(LogType.INFO, dataCenterName + " adlı veri merkezi oluşturuldu");
userLogger.createUserLog(LogType.INFO, dataCenterName + " adlı veri merkezi oluşturuldu", environment);
notificationMutation.createNotification(environment, "Veri Merkezi",
dataCenterName + " adlı veri merkezi oluşturuldu", "Yeni kayıt");
return savedDataCenter;
} catch (GraphQLCustomException e) {
throw e;
} catch (Exception e) {
systemLogger.createSystemLog(LogType.ERROR,
"Yeni veri merkezi oluşturulurken hata oluştu: " + e.getMessage());
throw e;
} }
DataCenter dataCenter = dataCenterMapper.toEntity(input);
// Set auto-generated number if not provided
if (dataCenter.getNumber() == null) {
Integer maxNumber = dataCenterService.getRepository().findMaxNumber();
dataCenter.setNumber((maxNumber == null) ? 1 : maxNumber + 1);
}
return dataCenterService.save(dataCenter);
} }
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_UPDATE + "')") @PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_UPDATE + "')")
public DataCenter updateDataCenter(UUID id, @Valid DataCenterUpdateInput input) { @Transactional
return dataCenterService.findById(id) public DataCenter updateDataCenter(UUID id, @Valid DataCenterUpdateInput input,
.map(dataCenter -> { DataFetchingEnvironment environment) {
// Check for duplicate externalId if it's being updated try {
if (input.getExternalId() != null && DataCenter dataCenter = dataCenterService.findById(id)
!input.getExternalId().equals(dataCenter.getExternalId()) && .orElseThrow(() -> new NoSuchElementException("Data center not found with ID: " + id));
dataCenterService.existsByExternalId(input.getExternalId())) {
throw new RuntimeException("This external id already exists: " + input.getExternalId()); // Check for duplicate externalId if it's being updated
} if (input.getExternalId() != null &&
return dataCenterService.update(dataCenterMapper.updateEntity(dataCenter, input)); !input.getExternalId().equals(dataCenter.getExternalId()) &&
}) dataCenterService.existsByExternalId(input.getExternalId())) {
.orElseThrow(() -> new RuntimeException("Data center not found with ID: " + id)); throw new GraphQLCustomException("2010", input.getExternalId().toString());
}
DataCenter updatedDataCenter = dataCenterService.update(dataCenterMapper.updateEntity(dataCenter, input));
// Log and notify
String dataCenterName = updatedDataCenter.getDataCenter() != null ? updatedDataCenter.getDataCenter()
: "DataCenter #" + updatedDataCenter.getNumber();
systemLogger.createSystemLog(LogType.INFO, dataCenterName + " adlı veri merkezi güncellendi");
userLogger.createUserLog(LogType.INFO, dataCenterName + " adlı veri merkezi güncellendi", environment);
notificationMutation.createNotification(environment, "Veri Merkezi",
dataCenterName + " adlı veri merkezi güncellendi", "Güncelleme");
return updatedDataCenter;
} catch (GraphQLCustomException e) {
throw e;
} catch (NoSuchElementException e) {
systemLogger.createSystemLog(LogType.ERROR, "Veri merkezi bulunamadı: " + id);
throw e;
} catch (Exception e) {
systemLogger.createSystemLog(LogType.ERROR, "Veri merkezi güncellenirken hata oluştu: " + e.getMessage());
throw e;
}
} }
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_DELETE + "')") @PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_DELETE + "')")
public Boolean deleteDataCenter(UUID id) { @Transactional
public String deleteDataCenter(UUID id, DataFetchingEnvironment environment) {
String dataCenterName = "";
try { try {
DataCenter dataCenter = dataCenterService.findById(id) DataCenter dataCenter = dataCenterService.findById(id)
.orElseThrow(() -> new RuntimeException("Data center not found with ID: " + id)); .orElseThrow(() -> new NoSuchElementException("Data center not found with ID: " + id));
dataCenterName = dataCenter.getDataCenter() != null ? dataCenter.getDataCenter()
: "DataCenter #" + dataCenter.getNumber();
// Check if data center has physical machines or other dependencies
if (dataCenter.getPhysicalMachines() != null && !dataCenter.getPhysicalMachines().isEmpty()) {
String message = "Silinmeye çalışılan veri merkezinin fiziksel makineleri olduğu için silinememektedir";
systemLogger.createSystemLog(LogType.WARN, dataCenterName + ": " + message);
return message;
}
dataCenterService.delete(dataCenter); dataCenterService.delete(dataCenter);
return true;
// Log and notify
systemLogger.createSystemLog(LogType.INFO, dataCenterName + " adlı veri merkezi silindi");
userLogger.createUserLog(LogType.INFO, dataCenterName + " adlı veri merkezi silindi", environment);
notificationMutation.createNotification(environment, "Veri Merkezi",
dataCenterName + " adlı veri merkezi silindi", "Silme");
return "true";
} catch (NoSuchElementException e) {
systemLogger.createSystemLog(LogType.ERROR, "Veri merkezi bulunamadı: " + id);
return "false";
} catch (Exception e) { } catch (Exception e) {
System.out.println("DataCenter deletion error: " + e.getMessage()); systemLogger.createSystemLog(LogType.ERROR, "Veri merkezi silinirken hata oluştu: " + e.getMessage());
return false; return "false";
} }
} }
} }

View File

@@ -16,7 +16,6 @@ public class DataCenterCreateInput extends BaseCreateInput {
private Integer number; private Integer number;
private Double consuptionAmount; private Double consuptionAmount;
@NotNull(message = "Alan ID gereklidir")
private UUID areaId; private UUID areaId;
private UUID cityId; private UUID cityId;

View File

@@ -4,6 +4,8 @@ import com.sgs.lib.dao.mutation.input.BaseUpdateInput;
import java.util.List; import java.util.List;
import java.util.UUID; import java.util.UUID;
import javax.validation.constraints.NotNull;
public class DataCenterUpdateInput extends BaseUpdateInput { public class DataCenterUpdateInput extends BaseUpdateInput {
private String dataCenter; private String dataCenter;
private Integer externalId; private Integer externalId;
@@ -12,6 +14,7 @@ public class DataCenterUpdateInput extends BaseUpdateInput {
private UUID areaId; private UUID areaId;
private UUID cityId; private UUID cityId;
@NotNull(message = "Sektör ID gereklidir")
private UUID sectorId; private UUID sectorId;
private UUID subSectorId; private UUID subSectorId;
private UUID emissionScopeId; private UUID emissionScopeId;

View File

@@ -50,13 +50,13 @@ public class DataCenterMapper extends BaseCreateUpdateMapper<DataCenter, DataCen
@Override @Override
public DataCenter toEntity(DataCenterCreateInput input) { public DataCenter toEntity(DataCenterCreateInput input) {
DataCenter entity = new DataCenter(); DataCenter entity = new DataCenter();
// Basic fields // Basic fields
entity.setDataCenter(input.getDataCenter()); entity.setDataCenter(input.getDataCenter());
entity.setExternalId(input.getExternalId()); entity.setExternalId(input.getExternalId());
entity.setNumber(input.getNumber()); entity.setNumber(input.getNumber());
entity.setConsuptionAmount(input.getConsuptionAmount()); entity.setConsuptionAmount(input.getConsuptionAmount());
// Convert ID references to entities // Convert ID references to entities
if (input.getAreaId() != null) { if (input.getAreaId() != null) {
entity.setArea(areaService.findById(input.getAreaId()).orElse(null)); entity.setArea(areaService.findById(input.getAreaId()).orElse(null));
@@ -68,53 +68,56 @@ public class DataCenterMapper extends BaseCreateUpdateMapper<DataCenter, DataCen
if (input.getSectorId() != null) { if (input.getSectorId() != null) {
entity.setSector(sectorService.findById(input.getSectorId()).orElse(null)); entity.setSector(sectorService.findById(input.getSectorId()).orElse(null));
} }
if (input.getSubSectorId() != null) { if (input.getSubSectorId() != null) {
entity.setSubSector(subSectorService.findById(input.getSubSectorId()).orElse(null)); entity.setSubSector(subSectorService.findById(input.getSubSectorId()).orElse(null));
} }
if (input.getEmissionScopeId() != null) { if (input.getEmissionScopeId() != null) {
entity.setEmissionScope(emissionScopeService.findById(input.getEmissionScopeId()).orElse(null)); entity.setEmissionScope(emissionScopeService.findById(input.getEmissionScopeId()).orElse(null));
} }
if (input.getActivitySubUnitId() != null) { if (input.getActivitySubUnitId() != null) {
entity.setActivitySubUnit(activitySubUnitService.findById(input.getActivitySubUnitId()).orElse(null)); entity.setActivitySubUnit(activitySubUnitService.findById(input.getActivitySubUnitId()).orElse(null));
} }
// New attributes // New attributes
entity.setAyposURL(input.getAyposURL()); entity.setAyposURL(input.getAyposURL());
entity.setAddress(input.getAddress()); entity.setAddress(input.getAddress());
entity.setLatitude(input.getLatitude()); entity.setLatitude(input.getLatitude());
entity.setLongitude(input.getLongitude()); entity.setLongitude(input.getLongitude());
// Handle multiple emission sources if provided // Handle multiple emission sources if provided
if (input.getDataCenterEmissionSources() != null && !input.getDataCenterEmissionSources().isEmpty()) { if (input.getDataCenterEmissionSources() != null && !input.getDataCenterEmissionSources().isEmpty()) {
List<DataCenterEmissionSource> dataCenterEmissionSources = new ArrayList<>(); List<DataCenterEmissionSource> dataCenterEmissionSources = new ArrayList<>();
for (DataCenterEmissionSourceInput emissionSourceInput : input.getDataCenterEmissionSources()) { for (DataCenterEmissionSourceInput emissionSourceInput : input.getDataCenterEmissionSources()) {
DataCenterEmissionSource dcEmissionSource = new DataCenterEmissionSource(); DataCenterEmissionSource dcEmissionSource = new DataCenterEmissionSource();
dcEmissionSource.setDataCenter(entity); dcEmissionSource.setDataCenter(entity);
// Set EmissionSource // Set EmissionSource
if (emissionSourceInput.getEmissionSourceId() != null) { if (emissionSourceInput.getEmissionSourceId() != null) {
dcEmissionSource.setEmissionSource(emissionSourceService.findById(UUID.fromString(emissionSourceInput.getEmissionSourceId())).orElse(null)); dcEmissionSource.setEmissionSource(emissionSourceService
.findById(UUID.fromString(emissionSourceInput.getEmissionSourceId())).orElse(null));
} }
// Set ConsuptionUnit // Set ConsuptionUnit
if (emissionSourceInput.getConsuptionUnitId() != null) { if (emissionSourceInput.getConsuptionUnitId() != null) {
dcEmissionSource.setConsuptionUnit(consuptionUnitService.findById(UUID.fromString(emissionSourceInput.getConsuptionUnitId())).orElse(null)); dcEmissionSource.setConsuptionUnit(consuptionUnitService
.findById(UUID.fromString(emissionSourceInput.getConsuptionUnitId())).orElse(null));
} }
// Set optional fields // Set optional fields
dcEmissionSource.setIsDefault(emissionSourceInput.getIsDefault() != null ? emissionSourceInput.getIsDefault() : false); dcEmissionSource.setIsDefault(
emissionSourceInput.getIsDefault() != null ? emissionSourceInput.getIsDefault() : false);
dcEmissionSource.setPercentage(emissionSourceInput.getPercentage()); dcEmissionSource.setPercentage(emissionSourceInput.getPercentage());
dataCenterEmissionSources.add(dcEmissionSource); dataCenterEmissionSources.add(dcEmissionSource);
} }
entity.setDataCenterEmissionSources(dataCenterEmissionSources); entity.setDataCenterEmissionSources(dataCenterEmissionSources);
} }
return entity; return entity;
} }
@@ -124,19 +127,19 @@ public class DataCenterMapper extends BaseCreateUpdateMapper<DataCenter, DataCen
if (input.getDataCenter() != null) { if (input.getDataCenter() != null) {
entity.setDataCenter(input.getDataCenter()); entity.setDataCenter(input.getDataCenter());
} }
if (input.getExternalId() != null) { if (input.getExternalId() != null) {
entity.setExternalId(input.getExternalId()); entity.setExternalId(input.getExternalId());
} }
if (input.getNumber() != null) { if (input.getNumber() != null) {
entity.setNumber(input.getNumber()); entity.setNumber(input.getNumber());
} }
if (input.getConsuptionAmount() != null) { if (input.getConsuptionAmount() != null) {
entity.setConsuptionAmount(input.getConsuptionAmount()); entity.setConsuptionAmount(input.getConsuptionAmount());
} }
// Update relationships only if provided // Update relationships only if provided
if (input.getAreaId() != null) { if (input.getAreaId() != null) {
entity.setArea(areaService.findById(input.getAreaId()).orElse(null)); entity.setArea(areaService.findById(input.getAreaId()).orElse(null));
@@ -148,62 +151,65 @@ public class DataCenterMapper extends BaseCreateUpdateMapper<DataCenter, DataCen
if (input.getSectorId() != null) { if (input.getSectorId() != null) {
entity.setSector(sectorService.findById(input.getSectorId()).orElse(null)); entity.setSector(sectorService.findById(input.getSectorId()).orElse(null));
} }
if (input.getSubSectorId() != null) { if (input.getSubSectorId() != null) {
entity.setSubSector(subSectorService.findById(input.getSubSectorId()).orElse(null)); entity.setSubSector(subSectorService.findById(input.getSubSectorId()).orElse(null));
} }
if (input.getEmissionScopeId() != null) { if (input.getEmissionScopeId() != null) {
entity.setEmissionScope(emissionScopeService.findById(input.getEmissionScopeId()).orElse(null)); entity.setEmissionScope(emissionScopeService.findById(input.getEmissionScopeId()).orElse(null));
} }
if (input.getActivitySubUnitId() != null) { if (input.getActivitySubUnitId() != null) {
entity.setActivitySubUnit(activitySubUnitService.findById(input.getActivitySubUnitId()).orElse(null)); entity.setActivitySubUnit(activitySubUnitService.findById(input.getActivitySubUnitId()).orElse(null));
} }
// Handle multiple emission sources update if provided // Handle multiple emission sources update if provided
if (input.getDataCenterEmissionSources() != null) { if (input.getDataCenterEmissionSources() != null) {
// Clear existing emission sources and add new ones // Clear existing emission sources from the managed collection
entity.getDataCenterEmissionSources().clear(); entity.getDataCenterEmissionSources().clear();
List<DataCenterEmissionSource> dataCenterEmissionSources = new ArrayList<>(); // Add new emission sources to the same managed collection
for (DataCenterEmissionSourceInput emissionSourceInput : input.getDataCenterEmissionSources()) { for (DataCenterEmissionSourceInput emissionSourceInput : input.getDataCenterEmissionSources()) {
DataCenterEmissionSource dcEmissionSource = new DataCenterEmissionSource(); DataCenterEmissionSource dcEmissionSource = new DataCenterEmissionSource();
dcEmissionSource.setDataCenter(entity); dcEmissionSource.setDataCenter(entity);
if (emissionSourceInput.getEmissionSourceId() != null) { if (emissionSourceInput.getEmissionSourceId() != null) {
dcEmissionSource.setEmissionSource(emissionSourceService.findById(UUID.fromString(emissionSourceInput.getEmissionSourceId())).orElse(null)); dcEmissionSource.setEmissionSource(emissionSourceService
.findById(UUID.fromString(emissionSourceInput.getEmissionSourceId())).orElse(null));
} }
if (emissionSourceInput.getConsuptionUnitId() != null) { if (emissionSourceInput.getConsuptionUnitId() != null) {
dcEmissionSource.setConsuptionUnit(consuptionUnitService.findById(UUID.fromString(emissionSourceInput.getConsuptionUnitId())).orElse(null)); dcEmissionSource.setConsuptionUnit(consuptionUnitService
.findById(UUID.fromString(emissionSourceInput.getConsuptionUnitId())).orElse(null));
} }
dcEmissionSource.setIsDefault(emissionSourceInput.getIsDefault() != null ? emissionSourceInput.getIsDefault() : false); dcEmissionSource.setIsDefault(
emissionSourceInput.getIsDefault() != null ? emissionSourceInput.getIsDefault() : false);
dcEmissionSource.setPercentage(emissionSourceInput.getPercentage()); dcEmissionSource.setPercentage(emissionSourceInput.getPercentage());
dataCenterEmissionSources.add(dcEmissionSource); // Add to the existing managed collection instead of creating a new one
entity.getDataCenterEmissionSources().add(dcEmissionSource);
} }
entity.setDataCenterEmissionSources(dataCenterEmissionSources);
} }
// New attributes (partial update - only if provided) // New attributes (partial update - only if provided)
if (input.getAyposURL() != null) { if (input.getAyposURL() != null) {
entity.setAyposURL(input.getAyposURL()); entity.setAyposURL(input.getAyposURL());
} }
if (input.getAddress() != null) { if (input.getAddress() != null) {
entity.setAddress(input.getAddress()); entity.setAddress(input.getAddress());
} }
if (input.getLatitude() != null) { if (input.getLatitude() != null) {
entity.setLatitude(input.getLatitude()); entity.setLatitude(input.getLatitude());
} }
if (input.getLongitude() != null) { if (input.getLongitude() != null) {
entity.setLongitude(input.getLongitude()); entity.setLongitude(input.getLongitude());
} }
return entity; return entity;
} }
} }

View File

@@ -11,17 +11,16 @@ import javax.transaction.Transactional;
import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.ObjectUtils;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Sort; import org.springframework.data.domain.Sort;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import com.sgs.graphql.auth.service.AuthorizationService;
import com.sgs.graphql.dataCenter.domain.DataCenter; import com.sgs.graphql.dataCenter.domain.DataCenter;
import com.sgs.graphql.dataCenter.domain.PhysicalMachine; import com.sgs.graphql.dataCenter.domain.PhysicalMachine;
import com.sgs.graphql.dataCenter.query.pagination.DataCenterPageable; import com.sgs.graphql.dataCenter.query.pagination.DataCenterPageable;
import com.sgs.graphql.dataCenter.repo.DataCenterRepo;
import com.sgs.graphql.dataCenter.repo.PhysicalMachineRepo;
import com.sgs.graphql.dataCenter.repo.criteria.DataCenterCriteria; import com.sgs.graphql.dataCenter.repo.criteria.DataCenterCriteria;
import com.sgs.graphql.dataCenter.service.DataCenterService; import com.sgs.graphql.dataCenter.service.DataCenterService;
import com.sgs.graphql.systemHistory.mutation.SystemLogger; import com.sgs.graphql.dataCenter.service.PhysicalMachineService;
import com.sgs.graphql.permission.domain.PermissionName;
import com.sgs.lib.dao.query.pagination.Pagination; import com.sgs.lib.dao.query.pagination.Pagination;
import com.sgs.lib.dao.query.sort.SortBy; import com.sgs.lib.dao.query.sort.SortBy;
@@ -30,48 +29,46 @@ import graphql.kickstart.tools.GraphQLQueryResolver;
@Component @Component
public class DataCenterQueryResolver implements GraphQLQueryResolver { public class DataCenterQueryResolver implements GraphQLQueryResolver {
private final DataCenterService DataCenterService; private final DataCenterService dataCenterService;
private final DataCenterRepo dataCenterRepo; private final PhysicalMachineService physicalMachineService;
private final PhysicalMachineRepo physicalMachineRepo;
private final AuthorizationService authorizationService;
private final SystemLogger systemLogger;
@Autowired @Autowired
public DataCenterQueryResolver(AuthorizationService authorizationService, SystemLogger systemLogger, DataCenterService DataCenterService, DataCenterRepo dataCenterRepo, PhysicalMachineRepo physicalMachineRepo) { public DataCenterQueryResolver(DataCenterService dataCenterService, PhysicalMachineService physicalMachineService) {
this.DataCenterService = DataCenterService; this.dataCenterService = dataCenterService;
this.dataCenterRepo = dataCenterRepo; this.physicalMachineService = physicalMachineService;
this.physicalMachineRepo = physicalMachineRepo;
this.authorizationService = authorizationService;
this.systemLogger = systemLogger;
} }
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_READ + "')")
public DataCenter dataCenter(UUID id) { public DataCenter dataCenter(UUID id) {
return DataCenterService.findById(id).orElse(null); return dataCenterService.findById(id).orElse(null);
} }
@Transactional @Transactional
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_READ + "')")
public List<DataCenter> dataCenters(DataCenterCriteria criteria, List<SortBy> sortBy) { public List<DataCenter> dataCenters(DataCenterCriteria criteria, List<SortBy> sortBy) {
List<DataCenter> dataCenters = DataCenterService.filterWithSort(ObjectUtils.defaultIfNull(criteria, new DataCenterCriteria()), return dataCenterService.filterWithSort(ObjectUtils.defaultIfNull(criteria, new DataCenterCriteria()),
Sort.by(ObjectUtils.defaultIfNull(sortBy, new ArrayList<SortBy>()) Sort.by(ObjectUtils.defaultIfNull(sortBy, new ArrayList<SortBy>())
.stream() .stream()
.map(SortBy::toOrder) .map(SortBy::toOrder)
.collect(Collectors.toList()))); .collect(Collectors.toList())));
return dataCenters;
} }
public DataCenterPageable paginateDataCenters(Pagination pagination, DataCenterCriteria criteria, List<SortBy> sortBy) { @PreAuthorize("hasAuthority('" + PermissionName.PAGINATE_DATACENTERS_GET + "')")
return new DataCenterPageable(DataCenterService.filterWithPaginate(ObjectUtils.defaultIfNull(criteria, new DataCenterCriteria()), public DataCenterPageable paginateDataCenters(Pagination pagination, DataCenterCriteria criteria,
Pagination.toPageRequest(pagination, sortBy))); List<SortBy> sortBy) {
return new DataCenterPageable(
dataCenterService.filterWithPaginate(ObjectUtils.defaultIfNull(criteria, new DataCenterCriteria()),
Pagination.toPageRequest(pagination, sortBy)));
} }
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_READ + "')")
public Optional<DataCenter> getByNumber(Integer id) { public Optional<DataCenter> getByNumber(Integer number) {
return dataCenterRepo.findByNumber(id).stream().findFirst(); return dataCenterService.findByNumber(number);
} }
@PreAuthorize("hasAuthority('" + PermissionName.DATA_CENTER_READ + "')")
public List<PhysicalMachine> physicalMachines(UUID datacenterId) { public List<PhysicalMachine> physicalMachines(UUID datacenterId) {
return physicalMachineRepo.findByDatacenterId(datacenterId); return physicalMachineService.findByDatacenterId(datacenterId);
} }
} }

View File

@@ -2,7 +2,8 @@ package com.sgs.graphql.dataCenter.repo;
import com.sgs.graphql.dataCenter.domain.DataCenter; import com.sgs.graphql.dataCenter.domain.DataCenter;
import com.sgs.graphql.dataCenter.domain.DataCenterEmissionSource; import com.sgs.graphql.dataCenter.domain.DataCenterEmissionSource;
import org.springframework.data.jpa.repository.JpaRepository; import com.sgs.lib.dao.repo.BaseRepo;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository; import org.springframework.stereotype.Repository;
@@ -11,14 +12,14 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
@Repository @Repository
public interface DataCenterEmissionSourceRepo extends JpaRepository<DataCenterEmissionSource, String> { public interface DataCenterEmissionSourceRepo extends BaseRepo<DataCenterEmissionSource> {
List<DataCenterEmissionSource> findByDataCenter(DataCenter dataCenter); List<DataCenterEmissionSource> findByDataCenter(DataCenter dataCenter);
Optional<DataCenterEmissionSource> findByDataCenterAndIsDefaultTrue(DataCenter dataCenter); Optional<DataCenterEmissionSource> findByDataCenterAndIsDefaultTrue(DataCenter dataCenter);
@Query("SELECT dces FROM DataCenterEmissionSource dces WHERE dces.dataCenter.id = :dataCenterId") @Query("SELECT dces FROM DataCenterEmissionSource dces WHERE dces.dataCenter.id = :dataCenterId")
List<DataCenterEmissionSource> findByDataCenterId(@Param("dataCenterId") String dataCenterId); List<DataCenterEmissionSource> findByDataCenterId(@Param("dataCenterId") String dataCenterId);
void deleteByDataCenter(DataCenter dataCenter); void deleteByDataCenter(DataCenter dataCenter);
} }

View File

@@ -0,0 +1,6 @@
package com.sgs.graphql.dataCenter.repo.criteria;
import com.sgs.lib.dao.repo.criteria.BaseCriteria;
public class DataCenterEmissionSourceCriteria extends BaseCriteria {
}

View File

@@ -0,0 +1,6 @@
package com.sgs.graphql.dataCenter.repo.criteria;
import com.sgs.lib.dao.repo.criteria.BaseCriteria;
public class PhysicalMachineCriteria extends BaseCriteria {
}

View File

@@ -0,0 +1,6 @@
package com.sgs.graphql.dataCenter.repo.criteria;
import com.sgs.lib.dao.repo.criteria.BaseCriteria;
public class VMCriteria extends BaseCriteria {
}

View File

@@ -0,0 +1,17 @@
package com.sgs.graphql.dataCenter.repo.criteria.spec;
import com.sgs.graphql.dataCenter.domain.DataCenterEmissionSource;
import com.sgs.graphql.dataCenter.repo.criteria.DataCenterEmissionSourceCriteria;
import com.sgs.lib.dao.repo.criteria.spec.BaseCriteriaSpec;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
@Component
public class DataCenterEmissionSourceCriteriaSpec
extends BaseCriteriaSpec<DataCenterEmissionSource, DataCenterEmissionSourceCriteria> {
@Override
public Specification<DataCenterEmissionSource> createForAll(DataCenterEmissionSourceCriteria criteria) {
return null;
}
}

View File

@@ -0,0 +1,16 @@
package com.sgs.graphql.dataCenter.repo.criteria.spec;
import com.sgs.graphql.dataCenter.domain.PhysicalMachine;
import com.sgs.graphql.dataCenter.repo.criteria.PhysicalMachineCriteria;
import com.sgs.lib.dao.repo.criteria.spec.BaseCriteriaSpec;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
@Component
public class PhysicalMachineCriteriaSpec extends BaseCriteriaSpec<PhysicalMachine, PhysicalMachineCriteria> {
@Override
public Specification<PhysicalMachine> createForAll(PhysicalMachineCriteria criteria) {
return null;
}
}

View File

@@ -0,0 +1,16 @@
package com.sgs.graphql.dataCenter.repo.criteria.spec;
import com.sgs.graphql.dataCenter.domain.VM;
import com.sgs.graphql.dataCenter.repo.criteria.VMCriteria;
import com.sgs.lib.dao.repo.criteria.spec.BaseCriteriaSpec;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Component;
@Component
public class VMCriteriaSpec extends BaseCriteriaSpec<VM, VMCriteria> {
@Override
public Specification<VM> createForAll(VMCriteria criteria) {
return null;
}
}

View File

@@ -0,0 +1,40 @@
package com.sgs.graphql.dataCenter.service;
import com.sgs.graphql.dataCenter.domain.DataCenter;
import com.sgs.graphql.dataCenter.domain.DataCenterEmissionSource;
import com.sgs.graphql.dataCenter.repo.DataCenterEmissionSourceRepo;
import com.sgs.graphql.dataCenter.repo.criteria.DataCenterEmissionSourceCriteria;
import com.sgs.graphql.dataCenter.repo.criteria.spec.DataCenterEmissionSourceCriteriaSpec;
import com.sgs.lib.dao.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class DataCenterEmissionSourceService extends
BaseService<DataCenterEmissionSource, DataCenterEmissionSourceRepo, DataCenterEmissionSourceCriteria, DataCenterEmissionSourceCriteriaSpec> {
@Autowired
public DataCenterEmissionSourceService(DataCenterEmissionSourceRepo repository,
DataCenterEmissionSourceCriteriaSpec criteriaSpec) {
super(repository, criteriaSpec);
}
public List<DataCenterEmissionSource> findByDataCenter(DataCenter dataCenter) {
return getRepository().findByDataCenter(dataCenter);
}
public Optional<DataCenterEmissionSource> findByDataCenterAndIsDefaultTrue(DataCenter dataCenter) {
return getRepository().findByDataCenterAndIsDefaultTrue(dataCenter);
}
public List<DataCenterEmissionSource> findByDataCenterId(String dataCenterId) {
return getRepository().findByDataCenterId(dataCenterId);
}
public void deleteByDataCenter(DataCenter dataCenter) {
getRepository().deleteByDataCenter(dataCenter);
}
}

View File

@@ -8,15 +8,26 @@ import com.sgs.lib.dao.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import java.util.Optional;
@Service @Service
public class DataCenterService extends BaseService<DataCenter, DataCenterRepo, DataCenterCriteria, DataCenterCriteriaSpec> { public class DataCenterService
extends BaseService<DataCenter, DataCenterRepo, DataCenterCriteria, DataCenterCriteriaSpec> {
@Autowired @Autowired
public DataCenterService(DataCenterRepo repository, DataCenterCriteriaSpec criteriaSpec) { public DataCenterService(DataCenterRepo repository, DataCenterCriteriaSpec criteriaSpec) {
super(repository, criteriaSpec); super(repository, criteriaSpec);
} }
public boolean existsByExternalId(Integer externalId) { public boolean existsByExternalId(Integer externalId) {
return getRepository().existsByExternalId(externalId); return getRepository().existsByExternalId(externalId);
} }
public Optional<DataCenter> findByNumber(Integer number) {
return getRepository().findByNumber(number);
}
public Integer findMaxNumber() {
return getRepository().findMaxNumber();
}
} }

View File

@@ -0,0 +1,26 @@
package com.sgs.graphql.dataCenter.service;
import com.sgs.graphql.dataCenter.domain.PhysicalMachine;
import com.sgs.graphql.dataCenter.repo.PhysicalMachineRepo;
import com.sgs.graphql.dataCenter.repo.criteria.PhysicalMachineCriteria;
import com.sgs.graphql.dataCenter.repo.criteria.spec.PhysicalMachineCriteriaSpec;
import com.sgs.lib.dao.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.UUID;
@Service
public class PhysicalMachineService extends
BaseService<PhysicalMachine, PhysicalMachineRepo, PhysicalMachineCriteria, PhysicalMachineCriteriaSpec> {
@Autowired
public PhysicalMachineService(PhysicalMachineRepo repository, PhysicalMachineCriteriaSpec criteriaSpec) {
super(repository, criteriaSpec);
}
public List<PhysicalMachine> findByDatacenterId(UUID datacenterId) {
return getRepository().findByDatacenterId(datacenterId);
}
}

View File

@@ -0,0 +1,29 @@
package com.sgs.graphql.dataCenter.service;
import com.sgs.graphql.dataCenter.domain.VM;
import com.sgs.graphql.dataCenter.repo.VMRepo;
import com.sgs.graphql.dataCenter.repo.criteria.VMCriteria;
import com.sgs.graphql.dataCenter.repo.criteria.spec.VMCriteriaSpec;
import com.sgs.lib.dao.service.BaseService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Optional;
@Service
public class VMService extends BaseService<VM, VMRepo, VMCriteria, VMCriteriaSpec> {
@Autowired
public VMService(VMRepo repository, VMCriteriaSpec criteriaSpec) {
super(repository, criteriaSpec);
}
public List<VM> findAllByVmName(String vmName) {
return getRepository().findAllByVmName(vmName);
}
public Optional<VM> findFirstByVmNameOrderByIdDesc(String vmName) {
return getRepository().findFirstByVmNameOrderByIdDesc(vmName);
}
}

View File

@@ -22,7 +22,8 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@Service @Service
public class MainDataTableService extends BaseService<MainDataTable, MainDataTableRepo, MainDataTableCriteria, MainDataTableCriteriaSpec> { public class MainDataTableService
extends BaseService<MainDataTable, MainDataTableRepo, MainDataTableCriteria, MainDataTableCriteriaSpec> {
@PersistenceContext @PersistenceContext
private EntityManager entityManager; private EntityManager entityManager;
@@ -35,10 +36,10 @@ public class MainDataTableService extends BaseService<MainDataTable, MainDataTab
public List<VMEmissionSummary> getVMEmissionSummaries() { public List<VMEmissionSummary> getVMEmissionSummaries() {
return getVMEmissionSummaries(null); return getVMEmissionSummaries(null);
} }
public List<VMEmissionSummary> getVMEmissionSummaries(UUID datacenterId) { public List<VMEmissionSummary> getVMEmissionSummaries(UUID datacenterId) {
List<String> whereConditions = new ArrayList<>(); List<String> whereConditions = new ArrayList<>();
if (datacenterId != null) { if (datacenterId != null) {
whereConditions.add("dc.id = decode(replace(:datacenterId, '-', ''), 'hex')"); whereConditions.add("dc.id = decode(replace(:datacenterId, '-', ''), 'hex')");
} }
@@ -69,7 +70,7 @@ public class MainDataTableService extends BaseService<MainDataTable, MainDataTab
"""; """;
Query query = entityManager.createNativeQuery(sql); Query query = entityManager.createNativeQuery(sql);
// Add parameters if provided // Add parameters if provided
if (datacenterId != null) { if (datacenterId != null) {
query.setParameter("datacenterId", datacenterId.toString()); query.setParameter("datacenterId", datacenterId.toString());
@@ -77,41 +78,42 @@ public class MainDataTableService extends BaseService<MainDataTable, MainDataTab
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Object[]> results = query.getResultList(); List<Object[]> results = query.getResultList();
return results.stream().map(row -> { return results.stream().map(row -> {
VMEmissionSummary summary = new VMEmissionSummary(); VMEmissionSummary summary = new VMEmissionSummary();
// Handle UUID conversion from hex format // Handle UUID conversion from hex format
String uuidStr = (String) row[0]; String uuidStr = (String) row[0];
UUID vmId = convertHexToUUID(uuidStr); UUID vmId = convertHexToUUID(uuidStr);
summary.setVmId(vmId); summary.setVmId(vmId);
summary.setVmName((String) row[1]); summary.setVmName((String) row[1]);
summary.setVmPower((Double) row[2]); summary.setVmPower((Double) row[2]);
summary.setVmStatus((String) row[3]); summary.setVmStatus((String) row[3]);
summary.setTotalEmission((Double) row[4]); summary.setTotalEmission((Double) row[4]);
// Convert Timestamp to LocalDateTime for created_date // Convert Timestamp to LocalDateTime for created_date
Timestamp timestamp = (Timestamp) row[5]; Timestamp timestamp = (Timestamp) row[5];
if (timestamp != null) { if (timestamp != null) {
summary.setCreatedDate(timestamp.toLocalDateTime()); summary.setCreatedDate(timestamp.toLocalDateTime());
} }
summary.setPhysicalMachine((String) row[6]); summary.setPhysicalMachine((String) row[6]);
summary.setCloudSystem((String) row[7]); summary.setCloudSystem((String) row[7]);
summary.setDataCenter((String) row[8]); summary.setDataCenter((String) row[8]);
// Individual emission values // Individual emission values
summary.setCo2((Double) row[9]); summary.setCo2((Double) row[9]);
summary.setCh4((Double) row[10]); summary.setCh4((Double) row[10]);
summary.setN2o((Double) row[11]); summary.setN2o((Double) row[11]);
return summary; return summary;
}).collect(Collectors.toList()); }).collect(Collectors.toList());
} }
/** /**
* Converts PostgreSQL hex format UUID to proper UUID format * Converts PostgreSQL hex format UUID to proper UUID format
*
* @param hexUuid UUID in hex format (e.g., \x6205c18b8d1e4f0fa5154212fb44050b) * @param hexUuid UUID in hex format (e.g., \x6205c18b8d1e4f0fa5154212fb44050b)
* @return UUID object * @return UUID object
*/ */
@@ -121,11 +123,11 @@ public class MainDataTableService extends BaseService<MainDataTable, MainDataTab
String hex = hexUuid.substring(2); String hex = hexUuid.substring(2);
// Insert hyphens to make it a proper UUID format // Insert hyphens to make it a proper UUID format
// UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx // UUID format: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
String formatted = hex.substring(0, 8) + "-" + String formatted = hex.substring(0, 8) + "-" +
hex.substring(8, 12) + "-" + hex.substring(8, 12) + "-" +
hex.substring(12, 16) + "-" + hex.substring(12, 16) + "-" +
hex.substring(16, 20) + "-" + hex.substring(16, 20) + "-" +
hex.substring(20); hex.substring(20);
return UUID.fromString(formatted); return UUID.fromString(formatted);
} else { } else {
// If it's already in proper format, parse directly // If it's already in proper format, parse directly

View File

@@ -838,8 +838,8 @@ public class MessageListener {
input.setVmId(vm.getId()); input.setVmId(vm.getId());
System.out.println("🔍 Setting VM ID: " + vm.getId()); System.out.println("🔍 Setting VM ID: " + vm.getId());
// Use the source-specific power consumption (percentage of total VM power) // Use the source-specific power consumption (percentage of total VM power)
// Format to 6 decimal places to avoid very long strings // Format to 6 decimal places to avoid very long strings
String formattedPower = String.format("%.6f", sourceSpecificPower); String formattedPower = String.format("%.6f", sourceSpecificPower);
input.setConsuptionAmount(formattedPower); input.setConsuptionAmount(formattedPower);
System.out.println("🔍 Setting Consumption Amount: " + formattedPower + "W"); System.out.println("🔍 Setting Consumption Amount: " + formattedPower + "W");
@@ -849,7 +849,8 @@ public class MessageListener {
System.out.println(" Year: " + (input.getYear() != null ? input.getYear().length() : "null")); System.out.println(" Year: " + (input.getYear() != null ? input.getYear().length() : "null"));
System.out.println(" Month: " + (input.getMonth() != null ? input.getMonth().length() : "null")); System.out.println(" Month: " + (input.getMonth() != null ? input.getMonth().length() : "null"));
System.out.println(" ConsuptionAmount: " + (input.getConsuptionAmount() != null ? input.getConsuptionAmount().length() : "null")); System.out.println(" ConsuptionAmount: " + (input.getConsuptionAmount() != null ? input.getConsuptionAmount().length() : "null"));
System.out.println("🔍 VM Emission Input for Source:"); System.out.println("🔍 VM Emission Input for Source:");
System.out.println(" VM ID: " + vm.getId()); System.out.println(" VM ID: " + vm.getId());
System.out.println(" VM Name: " + vm.getVmName()); System.out.println(" VM Name: " + vm.getVmName());

View File

@@ -17,16 +17,10 @@ security.jwt.token.secret-key=secret
app.survey.base-url=http://localhost.com app.survey.base-url=http://localhost.com
# spring.rabbitmq.host=188.132.198.145 spring.rabbitmq.host=188.132.198.145
# spring.rabbitmq.port=5672
# spring.rabbitmq.username=testuser
# spring.rabbitmq.password=JGasF24561AZv2894De
#spring.rabbitmq.host=rabbitmq
spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672 spring.rabbitmq.port=5672
spring.rabbitmq.username=guest spring.rabbitmq.username=testuser
spring.rabbitmq.password=guest spring.rabbitmq.password=JGasF24561AZv2894De
spring.rabbitmq.virtual-host=/ spring.rabbitmq.virtual-host=/
spring.rabbitmq.connection-timeout=20000 spring.rabbitmq.connection-timeout=20000
spring.rabbitmq.template.retry.enabled=true spring.rabbitmq.template.retry.enabled=true
@@ -34,3 +28,6 @@ spring.rabbitmq.template.retry.max-attempts=3
spring.rabbitmq.template.retry.initial-interval=1000ms spring.rabbitmq.template.retry.initial-interval=1000ms
logging.level.org.springframework.amqp=DEBUG logging.level.org.springframework.amqp=DEBUG
spring.jpa.show-sql=true
logging.level.org.hibernate.SQL=DEBUG
logging.level.org.hibernate.type.descriptor.sql.BasicBinder=TRACE

View File

@@ -67,7 +67,11 @@
"Common": { "Common": {
"save": "Save", "save": "Save",
"cancel": "Cancel" "cancel": "Cancel",
"yes": "Yes",
"no": "No",
"areYouSure": "Are you sure?",
"cantRevert": "This action cannot be undone!"
}, },
"DataInput": { "DataInput": {

View File

@@ -1,311 +1,315 @@
{ {
"Actions": "Aksiyonlar", "Actions": "Aksiyonlar",
"Active": "Aktif", "Active": "Aktif",
"ByName": "İsme Göre", "ByName": "İsme Göre",
"CreatedTime": "Oluşturulma Zamanı", "CreatedTime": "Oluşturulma Zamanı",
"Description": " Açıklaması", "Description": " Açıklaması",
"Filter": "Filtrele", "Filter": "Filtrele",
"Management": "Yönetim", "Management": "Yönetim",
"Passive": "Pasif", "Passive": "Pasif",
"Show": "Göster", "Show": "Göster",
"Status": "Durum", "Status": "Durum",
"Time": "Zaman ", "Time": "Zaman ",
"Activities": { "Activities": {
"activity": "Aktivite ", "activity": "Aktivite ",
"activities": "Aktiviteler ", "activities": "Aktiviteler ",
"type": "Log Tipi", "type": "Log Tipi",
"message": "Log Mesajı" "message": "Log Mesajı"
}, },
"Areas": { "Areas": {
"addArea": "Alan Ekle", "addArea": "Alan Ekle",
"area": "Alan ", "area": "Alan ",
"areas": "Alanlar ", "areas": "Alanlar ",
"areaName": "Alan Adı ", "areaName": "Alan Adı ",
"city": "Şehir ", "city": "Şehir ",
"cities": "Şehirler ", "cities": "Şehirler ",
"cityName": "Şehir Adı ", "cityName": "Şehir Adı ",
"country": "Ülke ", "country": "Ülke ",
"countries": "Ülkeler ", "countries": "Ülkeler ",
"countryName": "Ülke Adı ", "countryName": "Ülke Adı ",
"countryCode": "Ülke Kodu ", "countryCode": "Ülke Kodu ",
"district": "İlçe ", "district": "İlçe ",
"districts": "İlçeler", "districts": "İlçeler",
"districtName": "İlçe Adı", "districtName": "İlçe Adı",
"neighborhood": "Mahalle ", "neighborhood": "Mahalle ",
"neighborhoods": "Mahalleler ", "neighborhoods": "Mahalleler ",
"neighborhoodName": "Mahalle Adı", "neighborhoodName": "Mahalle Adı",
"addNeighborhood": "Mahalle Ekle", "addNeighborhood": "Mahalle Ekle",
"latitude": "Enlem", "latitude": "Enlem",
"longitude": "Boylam" "longitude": "Boylam"
}, },
"Auth": { "Auth": {
"authorized": "Devam etmek için yetkilendirilmiş kullanıcı bilgilerinizi giriniz.", "authorized": "Devam etmek için yetkilendirilmiş kullanıcı bilgilerinizi giriniz.",
"didUForgotPassword": "Şifrenizi mi unuttunuz?", "didUForgotPassword": "Şifrenizi mi unuttunuz?",
"logout": ıkış Yap", "logout": ıkış Yap",
"logoutMessage": " Çıkış yaptınız. Yönlendiriliyorsunuz...", "logoutMessage": " Çıkış yaptınız. Yönlendiriliyorsunuz...",
"login": "Giriş Yap", "login": "Giriş Yap",
"loginMessage": " Giriş başarılı yönlendiriliyorsunuz...", "loginMessage": " Giriş başarılı yönlendiriliyorsunuz...",
"password": "Şifre ", "password": "Şifre ",
"welcome": "Hoşgeldiniz", "welcome": "Hoşgeldiniz",
"incorrectForm": "Kullanıcı bilgileri hatalıdır. Lütfen tekrar deneyiniz." "incorrectForm": "Kullanıcı bilgileri hatalıdır. Lütfen tekrar deneyiniz."
}, },
"Cruds": { "Cruds": {
"add": " Ekle", "add": " Ekle",
"cancel": " İptal", "cancel": " İptal",
"delete": "Sil", "delete": "Sil",
"edit": "Düzenle", "edit": "Düzenle",
"reactive": "Aktif Et", "reactive": "Aktif Et",
"save": "Kaydet", "save": "Kaydet",
"saving": "Kaydediliyor..", "saving": "Kaydediliyor..",
"update": "Güncelle" "update": "Güncelle"
}, },
"Common": { "Common": {
"save": "Kaydet", "save": "Kaydet",
"cancel": " İptal" "cancel": "İptal",
}, "yes": "Evet",
"no": "Hayır",
"DataInput": { "areYouSure": "Emin misiniz?",
"area": "Bölge ", "cantRevert": "Bu işlem geri alınamaz!"
"report": "Rapor ", },
"reports": "Raw Data",
"data": "Veri ", "DataInput": {
"datas": "Veriler ", "area": "Bölge ",
"dataInput": "Veri Girişi", "report": "Rapor ",
"year": "Yıl", "reports": "Raw Data",
"month": "Ay", "data": "Veri ",
"consumptionAmount": "Tüketim Miktarı", "datas": "Veriler ",
"consumptionUnit": "Tüketim Birimi", "dataInput": "Veri Girişi",
"gpcReference": "GPC Referans", "year": "Yıl",
"total": "Toplam ", "month": "Ay",
"save": "Veriyi Kaydet", "consumptionAmount": "Tüketim Miktarı",
"update": "Veriyi Güncelle", "consumptionUnit": "Tüketim Birimi",
"showDeleted": "Silinen Raporları Göster", "gpcReference": "GPC Referans",
"result": "Sonuç", "total": "Toplam ",
"directToAllDatas": "Tüm Verileri Gör", "save": "Veriyi Kaydet",
"addNewData": "Yeni Veri Ekle", "update": "Veriyi Güncelle",
"failUploadExcel": "Dosya yüklenirken hata oluştu!" "showDeleted": "Silinen Raporları Göster",
}, "result": "Sonuç",
"directToAllDatas": "Tüm Verileri Gör",
"Graphics": { "addNewData": "Yeni Veri Ekle",
"graphics": "Raporlar", "failUploadExcel": "Dosya yüklenirken hata oluştu!"
"reports": "Raporlar" },
},
"Graphics": {
"EmissionSources": { "graphics": "Raporlar",
"dataSet": "Veri Seti", "reports": "Raporlar"
"emissionSource": "Emisyon Kaynağı ", },
"emissionSources": "Emisyon Kaynakları ",
"emissionSourceName": "Emisyon Kaynağı Adı", "EmissionSources": {
"addEmissionSource": "Emisyon Kaynağı Ekle", "dataSet": "Veri Seti",
"existingEmissionName": "Bu isimde bir emisyon kaynağı mevcuttur!", "emissionSource": "Emisyon Kaynağı ",
"sector": "Veri Sektörü ", "emissionSources": "Emisyon Kaynakları ",
"sectors": "Veri Sektörleri ", "emissionSourceName": "Emisyon Kaynağı Adı",
"subSector": "Sektör Alt Birimi ", "addEmissionSource": "Emisyon Kaynağı Ekle",
"subSectors": "Sektör Alt Birimleri ", "existingEmissionName": "Bu isimde bir emisyon kaynağı mevcuttur!",
"subUnit": "Faaliyet Alt Birimi ", "sector": "Veri Sektörü ",
"subUnits": "Faaliyet Alt Birimleri ", "sectors": "Veri Sektörleri ",
"emissionScopes": "Emisyon Kapsamı ", "subSector": "Sektör Alt Birimi ",
"emissionFactors": "Emisyon Faktörleri ", "subSectors": "Sektör Alt Birimleri ",
"showDeletedEmissionSource": "Silinen Emisyon Kaynaklarını Göster" "subUnit": "Faaliyet Alt Birimi ",
}, "subUnits": "Faaliyet Alt Birimleri ",
"emissionScopes": "Emisyon Kapsamı ",
"Map": { "emissionFactors": "Emisyon Faktörleri ",
"map": "Harita", "showDeletedEmissionSource": "Silinen Emisyon Kaynaklarını Göster"
"goBack": "Geri dön", },
"reference": "Referans",
"title": "Harita" "Map": {
}, "map": "Harita",
"goBack": "Geri dön",
"Months": { "reference": "Referans",
"1": "Ocak", "title": "Harita"
"2": "Şubat", },
"3": "Mart",
"4": "Nisan", "Months": {
"5": "Mayıs", "1": "Ocak",
"6": "Haziran", "2": "Şubat",
"7": "Temmuz", "3": "Mart",
"8": "Ağustos", "4": "Nisan",
"9": "Eylül", "5": "Mayıs",
"10": "Ekim", "6": "Haziran",
"11": "Kasım", "7": "Temmuz",
"12": "Aralık", "8": "Ağustos",
"null": "Yıl Geneli", "9": "Eylül",
"0": "Yıl Geneli" "10": "Ekim",
}, "11": "Kasım",
"12": "Aralık",
"Notifications": { "null": "Yıl Geneli",
"content": "İçerik ", "0": "Yıl Geneli"
"notification": "Bildirim ", },
"notifications": "Bildirimler ",
"showAll": "Tüm Bildirimleri Göster", "Notifications": {
"title": "Başlık ", "content": "İçerik ",
"notificationType": "Bildirim Tipi " "notification": "Bildirim ",
}, "notifications": "Bildirimler ",
"showAll": "Tüm Bildirimleri Göster",
"Organizations": { "title": "Başlık ",
"organization": "Organizasyon ", "notificationType": "Bildirim Tipi "
"organizations": "Organizasyonlar", },
"organizationName": "Organizasyon Adı",
"parentOrganization": "Bağlı Olduğu Organizasyon", "Organizations": {
"childOrganization": "Alt Organizasyonu", "organization": "Organizasyon ",
"addOrganization": "Organizasyon Ekle", "organizations": "Organizasyonlar",
"existingName": "Bu isimde bir organizasyon mevcuttur!.", "organizationName": "Organizasyon Adı",
"showDeletedOrganizations": "Silinen Organizasyonları Göster" "parentOrganization": "Bağlı Olduğu Organizasyon",
}, "childOrganization": "Alt Organizasyonu",
"addOrganization": "Organizasyon Ekle",
"PasswordLabel": { "existingName": "Bu isimde bir organizasyon mevcuttur!.",
"passwordLabel": "Şifre", "showDeletedOrganizations": "Silinen Organizasyonları Göster"
"confirmPassword": "Şifre Tekrar", },
"oldPassword": "Eski Şifre",
"newPassword": "Yeni Şifre", "PasswordLabel": {
"newConfirmPassword": "Yeni Şifre Tekrar", "passwordLabel": "Şifre",
"verificationCode": "Doğrulama Kodu", "confirmPassword": "Şifre Tekrar",
"cannotbeleftblank": " Boş Bırakılamaz ", "oldPassword": "Eski Şifre",
"passwordNotSame": "Şifreler aynı değil", "newPassword": "Yeni Şifre",
"passwordValidation": "Şifre 6-20 karakter uzunluğunda, en az 1 sayı, 1 büyük harf ve 1 küçük harf içermelidir!", "newConfirmPassword": "Yeni Şifre Tekrar",
"verificationCode": "Doğrulama Kodu",
"forgotPassword": "Şifremi Unuttum", "cannotbeleftblank": " Boş Bırakılamaz ",
"enterEmail": "Geçerli bir email giriniz.", "passwordNotSame": "Şifreler aynı değil",
"send": "Gönder", "passwordValidation": "Şifre 6-20 karakter uzunluğunda, en az 1 sayı, 1 büyük harf ve 1 küçük harf içermelidir!",
"redirectToReset": "Şifre sıfırlama ekranına yönlendiriliyorsunuz..",
"forgotPassword": "Şifremi Unuttum",
"resetPassword": "Şifre Sıfırlama", "enterEmail": "Geçerli bir email giriniz.",
"resend": "Doğrulama Kodunu Tekrar Gönder", "send": "Gönder",
"invalidVerificationCode": "Geçersiz doğrulama kodu!", "redirectToReset": "Şifre sıfırlama ekranına yönlendiriliyorsunuz..",
"redirectToLogin": "Giriş ekranına yönlendiriliyorsunuz.."
}, "resetPassword": "Şifre Sıfırlama",
"resend": "Doğrulama Kodunu Tekrar Gönder",
"Roles": { "invalidVerificationCode": "Geçersiz doğrulama kodu!",
"role": "Rol ", "redirectToLogin": "Giriş ekranına yönlendiriliyorsunuz.."
"roles": "Roller", },
"roleName": "Rol Adı",
"addRole": "Rol Ekle", "Roles": {
"permissions": "Yetkiler", "role": "Rol ",
"existingRole": "Bu rol zaten mevcuttur." "roles": "Roller",
}, "roleName": "Rol Adı",
"addRole": "Rol Ekle",
"Survey": { "permissions": "Yetkiler",
"addAnswer": "Cevap Ekle", "existingRole": "Bu rol zaten mevcuttur."
"addSurvey": "Anket Ekle", },
"addQuestion": "Soru Ekle",
"answer": "Cevap ", "Survey": {
"answers": "Cevaplar", "addAnswer": "Cevap Ekle",
"survey": "Anket", "addSurvey": "Anket Ekle",
"surveys": "Anketler ", "addQuestion": "Soru Ekle",
"surveyName": "Anket Adı", "answer": "Cevap ",
"question": "Soru ", "answers": "Cevaplar",
"questions": "Sorular", "survey": "Anket",
"tag": "Etiket", "surveys": "Anketler ",
"value": "Değer" "surveyName": "Anket Adı",
}, "question": "Soru ",
"questions": "Sorular",
"Contact": { "tag": "Etiket",
"contact": "İletişim", "value": "Değer"
"contactInfo": "İletişim Bilgileri", },
"contactEmail": "E-posta Adresi",
"contactPhoneNumber": "Telefon Numarası", "Contact": {
"contactAddress": "Adres" "contact": "İletişim",
}, "contactInfo": "İletişim Bilgileri",
"MailSettings": { "contactEmail": "E-posta Adresi",
"mailSettings": "E-posta Ayarları", "contactPhoneNumber": "Telefon Numarası",
"editMailInfo": "E-posta Bilgilerini Düzenle", "contactAddress": "Adres"
"hostName": "Sunucu Adı", },
"smtpPort": "SMTP Portu", "MailSettings": {
"emailAddress": "E-posta Adresi", "mailSettings": "E-posta Ayarları",
"emailPassword": "E-posta Şifresi", "editMailInfo": "E-posta Bilgilerini Düzenle",
"leaveBlankNote": "(Mevcut şifreyi korumak için boş bırakın)", "hostName": "Sunucu Adı",
"mainMail": "Ana e-posta yapılandırması olarak ayarla", "smtpPort": "SMTP Portu",
"saveSettings": "Ayarları Kaydet", "emailAddress": "E-posta Adresi",
"notConfigured": "E-posta yapılandırılmamış", "emailPassword": "E-posta Şifresi",
"noMailsRegistered": "Kayıtlı e-posta bulunamadı" "leaveBlankNote": "(Mevcut şifreyi korumak için boş bırakın)",
}, "mainMail": "Ana e-posta yapılandırması olarak ayarla",
"saveSettings": "Ayarları Kaydet",
"Timer": { "notConfigured": "E-posta yapılandırılmamış",
"continue": "Devam Et ", "noMailsRegistered": "Kayıtlı e-posta bulunamadı"
"expire": "Oturum süreniz dolmak üzeredir.." },
},
"Timer": {
"Users": { "continue": "Devam Et ",
"user": "Kullanıcı ", "expire": "Oturum süreniz dolmak üzeredir.."
"users": "Kullanıcılar ", },
"userName": "Kullanıcı Adı ",
"addUser": "Kullanıcı Ekle", "Users": {
"existingEmail": "Bu e-mail zaten mevcuttur.", "user": "Kullanıcı ",
"existingPhoneNumber": "Bu telefon numarası zaten mevcuttur.", "users": "Kullanıcılar ",
"showDeletedUsers": "Silinen Kullanıcıları Göster" "userName": "Kullanıcı Adı ",
}, "addUser": "Kullanıcı Ekle",
"existingEmail": "Bu e-mail zaten mevcuttur.",
"UserProfile": { "existingPhoneNumber": "Bu telefon numarası zaten mevcuttur.",
"myProfile": "Profilim", "showDeletedUsers": "Silinen Kullanıcıları Göster"
"firstName": "Ad", },
"lastName": "Soyad",
"phoneNumber": "Telefon Numarası", "UserProfile": {
"avatar": "Profil Fotoğrafı", "myProfile": "Profilim",
"status": "Durum", "firstName": "Ad",
"changePassword": "Şifre Değiştir", "lastName": "Soyad",
"communicationPreferences": "İletişim Tercihleri", "phoneNumber": "Telefon Numarası",
"updateAvatar": "Profil Resmini Güncelle" "avatar": "Profil Fotoğrafı",
}, "status": "Durum",
"changePassword": "Şifre Değiştir",
"Warnings": { "communicationPreferences": "İletişim Tercihleri",
"addedFail": " Eklenirken hata meydana geldi, lütfen tekrar deneyiniz.", "updateAvatar": "Profil Resmini Güncelle"
"addedSuccessfully": " Başarıyla Eklendi!", },
"updatedSuccessfully": " Başarıyla Güncellendi!", "Warnings": {
"updatedFail": " Güncellenirken hata meydana geldi, lütfen tekrar deneyiniz.", "addedFail": " Eklenirken hata meydana geldi, lütfen tekrar deneyiniz.",
"addedSuccessfully": " Başarıyla Eklendi!",
"deletedSuccessfully": " Başarıyla Silindi!",
"deletedFail": " Silinirken hata meydana geldi, lütfen tekrar deneyiniz.", "updatedSuccessfully": " Başarıyla Güncellendi!",
"updatedFail": " Güncellenirken hata meydana geldi, lütfen tekrar deneyiniz.",
"genericUpdateFailed": "Güncelleme başarısız oldu. Lütfen tekrar deneyiniz.",
"notFound": "Bulunamadı", "deletedSuccessfully": " Başarıyla Silindi!",
"notUndone": "Bu işlem geri alınamaz!", "deletedFail": " Silinirken hata meydana geldi, lütfen tekrar deneyiniz.",
"required": "Tüm Alanlar Zorunludur!",
"sureForDelete": " Silmek İstediğinize Emin Misiniz?", "genericUpdateFailed": "Güncelleme başarısız oldu. Lütfen tekrar deneyiniz.",
"uniqueName": " Benzersiz bir isim veriniz! " "notFound": "Bulunamadı",
}, "notUndone": "Bu işlem geri alınamaz!",
"required": "Tüm Alanlar Zorunludur!",
"UserActivities": { "sureForDelete": " Silmek İstediğinize Emin Misiniz?",
"title": "Kullanıcı Aktiviteleri" "uniqueName": " Benzersiz bir isim veriniz! "
}, },
"SystemActivities": {
"title": "Sistem Aktiviteleri" "UserActivities": {
}, "title": "Kullanıcı Aktiviteleri"
},
"DataCenter": { "SystemActivities": {
"title": "Veri Merkezleri", "title": "Sistem Aktiviteleri"
"create": "Veri Merkezi Ekle", },
"name": "İsim",
"namePlaceholder": "Veri merkezi ismini girin", "DataCenter": {
"externalId": "Harici ID", "title": "Veri Merkezleri",
"externalIdPlaceholder": "Harici ID girin", "create": "Veri Merkezi Ekle",
"number": "Numara", "name": "İsim",
"numberPlaceholder": "Numara girin", "namePlaceholder": "Veri merkezi ismini girin",
"url": "URL", "externalId": "Harici ID",
"urlPlaceholder": "URL girin", "externalIdPlaceholder": "Harici ID girin",
"createSuccess": "Veri merkezi başarıyla oluşturuldu", "number": "Numara",
"deleteSuccess": "Veri merkezi başarıyla silindi", "numberPlaceholder": "Numara girin",
"searchPlaceholder": "Veri merkezlerinde ara..." "url": "URL",
}, "urlPlaceholder": "URL girin",
"createSuccess": "Veri merkezi başarıyla oluşturuldu",
"DataCenters": { "deleteSuccess": "Veri merkezi başarıyla silindi",
"title": "Veri Merkezleri", "searchPlaceholder": "Veri merkezlerinde ara..."
"create": "Veri Merkezi Ekle", },
"name": "İsim",
"namePlaceholder": "Veri merkezi ismini girin", "DataCenters": {
"externalId": "Harici ID", "title": "Veri Merkezleri",
"externalIdPlaceholder": "Harici ID girin", "create": "Veri Merkezi Ekle",
"number": "Numara", "name": "İsim",
"numberPlaceholder": "Numara girin", "namePlaceholder": "Veri merkezi ismini girin",
"url": "URL", "externalId": "Harici ID",
"urlPlaceholder": "URL girin", "externalIdPlaceholder": "Harici ID girin",
"createSuccess": "Veri merkezi başarıyla oluşturuldu", "number": "Numara",
"deleteSuccess": "Veri merkezi başarıyla silindi", "numberPlaceholder": "Numara girin",
"searchPlaceholder": "Veri merkezlerinde ara..." "url": "URL",
} "urlPlaceholder": "URL girin",
} "createSuccess": "Veri merkezi başarıyla oluşturuldu",
"deleteSuccess": "Veri merkezi başarıyla silindi",
"searchPlaceholder": "Veri merkezlerinde ara..."
}
}

View File

@@ -49,9 +49,9 @@ export default [
permissionCheck("paginate_roles_get")) && [ permissionCheck("paginate_roles_get")) && [
{ {
id: "Organizations", id: "Organizations",
title: "DataCenters.title", title: "Data Center Management",
icon: <Home size={20} />, icon: <Home size={20} />,
navLink: "/organizasyonlar", navLink: "/veri-merkezi-yonetimi",
display: (permissionCheck("paginate_datacenters_get") || display: (permissionCheck("paginate_datacenters_get") ||
permissionCheck("data_center_create") || permissionCheck("data_center_create") ||
permissionCheck("data_center_update") || permissionCheck("data_center_update") ||
@@ -142,9 +142,63 @@ export default [
}, },
{ {
id: "DataCenter", id: "DataCenter",
title: "Data Centers", title: "Data Center Overview",
icon: <Zap size={20} />, icon: <Zap size={20} />,
navLink: "/verimerkezi", navLink: "/veri-merkezi-genel",
},
{
id: "Areas",
title: "Areas.areas",
icon: <Map size={20} />,
display:
permissionCheck("paginate_areas_get") ||
permissionCheck("paginate_countries_get") ||
permissionCheck("paginate_cities_get") ||
permissionCheck("paginate_districts_get") ||
permissionCheck("paginate_neighborhoods_get")
? ""
: "none",
children: (permissionCheck("paginate_areas_get") ||
permissionCheck("paginate_countries_get") ||
permissionCheck("paginate_cities_get") ||
permissionCheck("paginate_districts_get") ||
permissionCheck("paginate_neighborhoods_get")) && [
{
id: "AreasManagement",
title: "Areas.areas",
icon: <ArrowRight size={20} />,
navLink: "/alanlar",
display: permissionCheck("paginate_areas_get") ? "" : "none",
},
{
id: "Countries",
title: "Areas.countries",
icon: <ArrowRight size={20} />,
navLink: "/ulkeler",
display: permissionCheck("paginate_countries_get") ? "" : "none",
},
{
id: "Cities",
title: "Areas.cities",
icon: <ArrowRight size={20} />,
navLink: "/iller",
display: permissionCheck("paginate_cities_get") ? "" : "none",
},
{
id: "Districts",
title: "Areas.districts",
icon: <ArrowRight size={20} />,
navLink: "/ilceler",
display: permissionCheck("paginate_districts_get") ? "" : "none",
},
{
id: "Neighborhoods",
title: "Areas.neighborhoods",
icon: <ArrowRight size={20} />,
navLink: "/mahalleler",
display: permissionCheck("paginate_neighborhoods_get") ? "" : "none",
},
],
}, },
{ {
id: "Survey", id: "Survey",

View File

@@ -49,9 +49,9 @@ export default [
permissionCheck("paginate_roles_get")) && [ permissionCheck("paginate_roles_get")) && [
{ {
id: "DataCenters", id: "DataCenters",
title: "DataCenters.title", title: "Data Center Management",
icon: <Zap size={20} />, icon: <Zap size={20} />,
navLink: "/organizasyonlar", navLink: "/veri-merkezi-yonetimi",
display: (permissionCheck("paginate_datacenters_get") || display: (permissionCheck("paginate_datacenters_get") ||
permissionCheck("data_center_create") || permissionCheck("data_center_create") ||
permissionCheck("data_center_update") || permissionCheck("data_center_update") ||
@@ -142,9 +142,63 @@ export default [
}, },
{ {
id: "DataCenter", id: "DataCenter",
title: "DataCenters", title: "Data Center Overview",
icon: <Zap size={20} />, icon: <Zap size={20} />,
navLink: "/verimerkezi", navLink: "/veri-merkezi-genel",
},
{
id: "Areas",
title: "Areas.areas",
icon: <Map size={20} />,
display:
permissionCheck("paginate_areas_get") ||
permissionCheck("paginate_countries_get") ||
permissionCheck("paginate_cities_get") ||
permissionCheck("paginate_districts_get") ||
permissionCheck("paginate_neighborhoods_get")
? ""
: "none",
children: (permissionCheck("paginate_areas_get") ||
permissionCheck("paginate_countries_get") ||
permissionCheck("paginate_cities_get") ||
permissionCheck("paginate_districts_get") ||
permissionCheck("paginate_neighborhoods_get")) && [
{
id: "AreasManagement",
title: "Areas.areas",
icon: <ArrowRight size={20} />,
navLink: "/alanlar",
display: permissionCheck("paginate_areas_get") ? "" : "none",
},
{
id: "Countries",
title: "Areas.countries",
icon: <ArrowRight size={20} />,
navLink: "/ulkeler",
display: permissionCheck("paginate_countries_get") ? "" : "none",
},
{
id: "Cities",
title: "Areas.cities",
icon: <ArrowRight size={20} />,
navLink: "/iller",
display: permissionCheck("paginate_cities_get") ? "" : "none",
},
{
id: "Districts",
title: "Areas.districts",
icon: <ArrowRight size={20} />,
navLink: "/ilceler",
display: permissionCheck("paginate_districts_get") ? "" : "none",
},
{
id: "Neighborhoods",
title: "Areas.neighborhoods",
icon: <ArrowRight size={20} />,
navLink: "/mahalleler",
display: permissionCheck("paginate_neighborhoods_get") ? "" : "none",
},
],
}, },
{ {
id: "Survey", id: "Survey",

View File

@@ -12,6 +12,15 @@ export const getAreas = () => {
id id
tag tag
isDeleted isDeleted
cities {
id
name
coordinates
country {
id
name
}
}
} }
} }
`, `,

View File

@@ -34,30 +34,69 @@ export const getDataCenters = () => {
latitude latitude
longitude longitude
area { area {
tag
name
cityId
districtId
}
projects {
id id
name tag
physicalMachines { cities {
id id
name name
vms { }
active { districts {
id id
status name
name }
power }
config { city {
id id
cpu name
ram }
disk emissionScope {
} id
} tag
description
}
sector {
id
tag
}
subSector {
id
tag
}
dataCenterEmissionSources {
id
emissionSource {
id
tag
}
consuptionUnit {
id
description
}
isDefault
percentage
}
activitySubUnit {
id
tag
}
physicalMachines {
id
name
vms {
id
vmName
state
power
calcOn
hostingPm
host
flavorName
tag
config {
id
cpu
ram
disk
} }
} }
} }
@@ -77,7 +116,7 @@ export const getDataCenters = () => {
console.log("GraphQL Response:", { console.log("GraphQL Response:", {
status: response.status, status: response.status,
data: response.data, data: response.data,
errors: response.data?.errors errors: response.data?.errors,
}); });
// Check for GraphQL errors // Check for GraphQL errors
@@ -91,7 +130,7 @@ export const getDataCenters = () => {
} }
const dataCenters = response.data.data.dataCenters; const dataCenters = response.data.data.dataCenters;
// Validate dataCenters is an array // Validate dataCenters is an array
if (!Array.isArray(dataCenters)) { if (!Array.isArray(dataCenters)) {
throw new Error("Invalid response: dataCenters is not an array"); throw new Error("Invalid response: dataCenters is not an array");
@@ -110,7 +149,7 @@ export const getDataCenters = () => {
message: error.message, message: error.message,
response: error.response?.data, response: error.response?.data,
status: error.response?.status, status: error.response?.status,
stack: error.stack stack: error.stack,
}); });
// Check for specific error types // Check for specific error types
@@ -155,10 +194,50 @@ export const createDataCenter = (dataCenterData) => {
latitude latitude
longitude longitude
area { area {
id
tag tag
cities {
id
name
}
districts {
id
name
}
}
city {
id
name name
cityId }
districtId emissionScope {
id
tag
description
}
sector {
id
tag
}
subSector {
id
tag
}
dataCenterEmissionSources {
id
emissionSource {
id
tag
}
consuptionUnit {
id
description
}
isDefault
percentage
}
activitySubUnit {
id
tag
} }
} }
} }
@@ -169,13 +248,23 @@ export const createDataCenter = (dataCenterData) => {
externalId: parseInt(dataCenterData.externalId), externalId: parseInt(dataCenterData.externalId),
ayposURL: dataCenterData.ayposURL || "", ayposURL: dataCenterData.ayposURL || "",
number: parseInt(dataCenterData.number) || 1, number: parseInt(dataCenterData.number) || 1,
areaId: dataCenterData.areaId, areaId: dataCenterData.areaId || null,
cityId: dataCenterData.cityId || null,
address: dataCenterData.address || "", address: dataCenterData.address || "",
latitude: dataCenterData.latitude ? parseFloat(dataCenterData.latitude) : null, latitude: dataCenterData.latitude
longitude: dataCenterData.longitude ? parseFloat(dataCenterData.longitude) : null, ? parseFloat(dataCenterData.latitude)
city: dataCenterData.city : null,
} longitude: dataCenterData.longitude
} ? parseFloat(dataCenterData.longitude)
: null,
emissionScopeId: dataCenterData.emissionScopeId || null,
sectorId: dataCenterData.sectorId || null,
subSectorId: dataCenterData.subSectorId || null,
dataCenterEmissionSources:
dataCenterData.dataCenterEmissionSources || [],
activitySubUnitId: dataCenterData.activitySubUnitId || null,
},
},
}, },
{ {
headers: { headers: {
@@ -188,7 +277,7 @@ export const createDataCenter = (dataCenterData) => {
console.log("Create Response:", { console.log("Create Response:", {
status: response.status, status: response.status,
data: response.data, data: response.data,
errors: response.data?.errors errors: response.data?.errors,
}); });
if (response.data?.errors) { if (response.data?.errors) {
@@ -240,10 +329,50 @@ export const updateDataCenter = (id, dataCenterData) => {
latitude latitude
longitude longitude
area { area {
id
tag tag
cities {
id
name
}
districts {
id
name
}
}
city {
id
name name
cityId }
districtId emissionScope {
id
tag
description
}
sector {
id
tag
}
subSector {
id
tag
}
dataCenterEmissionSources {
id
emissionSource {
id
tag
}
consuptionUnit {
id
description
}
isDefault
percentage
}
activitySubUnit {
id
tag
} }
} }
} }
@@ -255,13 +384,23 @@ export const updateDataCenter = (id, dataCenterData) => {
externalId: parseInt(dataCenterData.externalId), externalId: parseInt(dataCenterData.externalId),
ayposURL: dataCenterData.ayposURL || "", ayposURL: dataCenterData.ayposURL || "",
number: parseInt(dataCenterData.number) || 1, number: parseInt(dataCenterData.number) || 1,
areaId: dataCenterData.areaId, areaId: dataCenterData.areaId || null,
cityId: dataCenterData.cityId || null,
address: dataCenterData.address || "", address: dataCenterData.address || "",
latitude: dataCenterData.latitude ? parseFloat(dataCenterData.latitude) : null, latitude: dataCenterData.latitude
longitude: dataCenterData.longitude ? parseFloat(dataCenterData.longitude) : null, ? parseFloat(dataCenterData.latitude)
city: dataCenterData.city : null,
} longitude: dataCenterData.longitude
} ? parseFloat(dataCenterData.longitude)
: null,
emissionScopeId: dataCenterData.emissionScopeId || null,
sectorId: dataCenterData.sectorId || null,
subSectorId: dataCenterData.subSectorId || null,
dataCenterEmissionSources:
dataCenterData.dataCenterEmissionSources || [],
activitySubUnitId: dataCenterData.activitySubUnitId || null,
},
},
}, },
{ {
headers: { headers: {
@@ -276,7 +415,7 @@ export const updateDataCenter = (id, dataCenterData) => {
dispatch({ dispatch({
type: "UPDATE_DATA_CENTER_SUCCESS", type: "UPDATE_DATA_CENTER_SUCCESS",
payload: response.data.data.updateDataCenter payload: response.data.data.updateDataCenter,
}); });
return response.data.data.updateDataCenter; return response.data.data.updateDataCenter;
@@ -309,8 +448,8 @@ export const deleteDataCenter = (id) => {
} }
`, `,
variables: { variables: {
id: id id: id,
} },
}, },
{ {
headers: { headers: {
@@ -325,7 +464,7 @@ export const deleteDataCenter = (id) => {
dispatch({ dispatch({
type: "DELETE_DATA_CENTER_SUCCESS", type: "DELETE_DATA_CENTER_SUCCESS",
payload: id payload: id,
}); });
return true; return true;
@@ -342,69 +481,113 @@ export const deleteDataCenter = (id) => {
}; };
}; };
export const getEmissionScopes = () => {
return async (dispatch) => {
dispatch({
type: "GET_EMISSION_SCOPES_LOADING",
});
try {
const response = await ApplicationService.http().post(
"/graphql",
{
query: `
query GetEmissionScopes {
emissionScopes {
id
tag
description
}
}
`,
},
{
headers: {
Authorization: "Bearer " + localStorage.getItem("accessToken"),
},
}
);
if (response.data?.errors) {
throw new Error(response.data.errors[0].message);
}
dispatch({
type: "GET_EMISSION_SCOPES_SUCCESS",
payload: response.data.data.emissionScopes,
});
return response.data.data.emissionScopes;
} catch (error) {
console.error("Error fetching emission scopes:", error);
dispatch({
type: "GET_EMISSION_SCOPES_ERROR",
payload: {
error: error.message || "Failed to fetch emission scopes",
},
});
throw error;
}
};
};
export const getDataCenterVMs = (dataCenterId) => { export const getDataCenterVMs = (dataCenterId) => {
return new Promise(async (resolve, reject) => { return new Promise(async (resolve, reject) => {
// Don't make the request if dataCenterId is undefined, null, or empty // Don't make the request if dataCenterId is undefined, null, or empty
if (!dataCenterId || dataCenterId === "undefined") { if (!dataCenterId || dataCenterId === "undefined") {
console.log('getDataCenterVMs: No dataCenterId provided'); console.log("getDataCenterVMs: No dataCenterId provided");
resolve([]); resolve([]);
return; return;
} }
try { try {
console.log('getDataCenterVMs: Fetching VMs for data center:', dataCenterId); console.log(
const response = await ApplicationService.http() "getDataCenterVMs: Fetching VMs for data center:",
.post( dataCenterId
"/graphql", );
{ const response = await ApplicationService.http().post(
query: ` "/graphql",
{
query: `
{ {
dataCenter(id: "${dataCenterId}") { dataCenter(id: "${dataCenterId}") {
id id
dataCenter dataCenter
projects { physicalMachines {
id id
name name
physicalMachines { vms {
id id
name vmName
vms { state
id power
name
status
power
}
} }
} }
} }
} }
`, `,
},
{
headers: {
Authorization: "Bearer " + localStorage.getItem("accessToken"),
}, },
{ }
headers: { );
Authorization: "Bearer " + localStorage.getItem("accessToken"),
},
}
);
const dataCenter = response?.data?.data?.dataCenter; const dataCenter = response?.data?.data?.dataCenter;
console.log('getDataCenterVMs: Data center response:', dataCenter); console.log("getDataCenterVMs: Data center response:", dataCenter);
let allVMs = []; let allVMs = [];
if (dataCenter && dataCenter.projects) { if (dataCenter && dataCenter.physicalMachines) {
dataCenter.projects.forEach(project => { dataCenter.physicalMachines.forEach((pm) => {
if (project.physicalMachines) { if (pm.vms) {
project.physicalMachines.forEach(pm => { allVMs = allVMs.concat(pm.vms);
if (pm.vms) {
allVMs = allVMs.concat(pm.vms);
}
});
} }
}); });
} }
console.log('getDataCenterVMs: Found VMs:', allVMs); console.log("getDataCenterVMs: Found VMs:", allVMs);
resolve(allVMs); resolve(allVMs);
} catch (error) { } catch (error) {
console.error("Error fetching VMs by data center:", error); console.error("Error fetching VMs by data center:", error);

View File

@@ -1,6 +1,6 @@
import ApplicationService from "../../../services/ApplicationService"; import ApplicationService from "../../../services/ApplicationService";
export const getVMEmissionSummary = () => { export const getVMEmissionSummary = (datacenterId) => {
return async (dispatch) => { return async (dispatch) => {
try { try {
const response = await ApplicationService.http() const response = await ApplicationService.http()
@@ -8,8 +8,8 @@ export const getVMEmissionSummary = () => {
"/graphql", "/graphql",
{ {
query: ` query: `
{ query GetVMEmissions($datacenterId: ID) {
vmEmissionSummary { vmEmissionSummary(datacenterId: $datacenterId) {
vmId vmId
vmName vmName
vmPower vmPower
@@ -17,7 +17,7 @@ export const getVMEmissionSummary = () => {
totalEmission totalEmission
createdDate createdDate
physicalMachine physicalMachine
project cloudSystem
dataCenter dataCenter
co2 co2
ch4 ch4
@@ -25,7 +25,10 @@ export const getVMEmissionSummary = () => {
reportGeneratedTime reportGeneratedTime
} }
} }
` `,
variables: {
datacenterId: datacenterId
}
}, },
{ {
headers: { headers: {
@@ -125,11 +128,12 @@ export const getMainDataTablesWithPaginate = (data) => {
{ {
paginateMainDataTables( paginateMainDataTables(
pagination: { page: 0, rowsPerPage: 100 } pagination: { page: 0, rowsPerPage: 100 }
criteria: { deleted: false } criteria: { deleted: false, hasVm: true }
sortBy: [{ field: "createdDate", direction: DESC }] sortBy: [{ field: "createdDate", direction: DESC }]
) { ) {
content { content {
id id
year
sector { sector {
id id
tag tag
@@ -138,11 +142,40 @@ export const getMainDataTablesWithPaginate = (data) => {
id id
tag tag
} }
activitySubUnit {
id
tag
}
emissionSource {
id
tag
}
emissionScope {
id
tag
}
co2 co2
ch4 ch4
n2o n2o
totalEmission totalEmission
createdDate createdDate
vm {
id
vmName
state
power
calcOn
hostingPm
host
flavorName
tag
config {
id
cpu
ram
disk
}
}
} }
pageInfo { pageInfo {
totalElements totalElements

View File

@@ -0,0 +1,33 @@
const initialState = {
emissionScopes: [],
loading: false,
error: null,
};
const emissionScopeReducer = (state = initialState, action) => {
switch (action.type) {
case "GET_EMISSION_SCOPES_LOADING":
return {
...state,
loading: true,
error: null,
};
case "GET_EMISSION_SCOPES_SUCCESS":
return {
...state,
loading: false,
emissionScopes: action.payload,
error: null,
};
case "GET_EMISSION_SCOPES_ERROR":
return {
...state,
loading: false,
error: action.payload.error,
};
default:
return state;
}
};
export default emissionScopeReducer;

View File

@@ -27,6 +27,7 @@ import surveys from "./surveys";
import uploads from "./upload"; import uploads from "./upload";
import mailSettings from "./mailSettings"; import mailSettings from "./mailSettings";
import dataCenter from "./dataCenter"; import dataCenter from "./dataCenter";
import emissionScope from "./emissionScope";
const rootReducer = combineReducers({ const rootReducer = combineReducers({
accessToken, accessToken,
@@ -57,6 +58,7 @@ const rootReducer = combineReducers({
uploads, uploads,
mailSettings, mailSettings,
dataCenter, dataCenter,
emissionScope,
}); });
export default rootReducer; export default rootReducer;

View File

@@ -25,7 +25,7 @@ const Routes = [
display: permissionCheck("paginate_users_get"), display: permissionCheck("paginate_users_get"),
}, },
{ {
path: "/organizasyonlar", path: "/veri-merkezi-yonetimi",
component: lazy(() => import("../../views/DataCenterManagement")), component: lazy(() => import("../../views/DataCenterManagement")),
display: permissionCheck("paginate_datacenters_get") || display: permissionCheck("paginate_datacenters_get") ||
permissionCheck("data_center_create") || permissionCheck("data_center_create") ||
@@ -74,7 +74,7 @@ const Routes = [
display: permissionCheck("activity_sub_units_get"), display: permissionCheck("activity_sub_units_get"),
}, },
{ {
path: "/verimerkezi", path: "/veri-merkezi-genel",
component: lazy(() => import("../../views/DataCenter")), component: lazy(() => import("../../views/DataCenter")),
}, },
{ {

View File

@@ -18,17 +18,16 @@ const DataCenter = () => {
const [refreshInterval, setRefreshInterval] = useState(null); const [refreshInterval, setRefreshInterval] = useState(null);
const getAllPhysicalMachines = (dataCenter) => { const getAllPhysicalMachines = (dataCenter) => {
if (!dataCenter.projects) return []; // Physical machines are directly in the dataCenter object, not in projects
return dataCenter.projects.flatMap(project => const pms = dataCenter.physicalMachines || [];
project.physicalMachines || [] return pms;
);
}; };
// Table columns following your pattern // Table columns following your pattern
const initialColumns = [ const initialColumns = [
{ {
name: "Number", name: "External ID",
selector: (row) => row.number, selector: (row) => row.externalId,
sortable: true, sortable: true,
minWidth: "100px", minWidth: "100px",
}, },
@@ -38,19 +37,33 @@ const DataCenter = () => {
sortable: true, sortable: true,
minWidth: "200px", minWidth: "200px",
}, },
// Projects // Projects - Based on API response, this field might not exist or be structured differently
{ // {
name: "Projects", // name: "Projects",
selector: (row) => // selector: (row) => row.projects?.length || 0,
(row.projects || []).map((p) => p.name).join(", "), // sortable: true,
sortable: false, // minWidth: "200px",
minWidth: "200px", // cell: (row) => (
cell: (row) => ( // <div>
<span> // {row.projects && row.projects.length > 0 ? (
{(row.projects || []).map((p) => p.name).join(", ") || "-"} // <div className="d-flex flex-column">
</span> // {row.projects.map((project, index) => (
), // <div
}, // key={project.id}
// className={`badge badge-light-primary ${
// index > 0 ? "mt-1" : ""
// }`}
// >
// {project.name}
// </div>
// ))}
// </div>
// ) : (
// <span className="text-muted">-</span>
// )}
// </div>
// ),
// },
// Physical Machines // Physical Machines
{ {
name: "Physical Machines", name: "Physical Machines",
@@ -68,26 +81,55 @@ const DataCenter = () => {
}, },
}, },
{ {
name: "Total Active VMs", name: "Virtual Machines",
selector: (row) => { selector: (row) => {
const pms = getAllPhysicalMachines(row); const pms = getAllPhysicalMachines(row);
return pms.reduce( const vms = pms.reduce(
(total, pm) => total + (pm.vms?.active?.length || 0), (acc, pm) => {
0 if (!pm.vms) return acc;
return {
active:
acc.active +
pm.vms.filter((vm) => vm.state?.toLowerCase() === "active")
.length,
total: acc.total + pm.vms.length,
};
},
{ active: 0, total: 0 }
); );
return vms.total;
}, },
sortable: true, sortable: true,
minWidth: "150px", minWidth: "200px",
cell: (row) => { cell: (row) => {
const pms = getAllPhysicalMachines(row); const pms = getAllPhysicalMachines(row);
const totalVMs = pms.reduce( const vms = pms.reduce(
(total, pm) => total + (pm.vms?.active?.length || 0), (acc, pm) => {
0 if (!pm.vms) return acc;
return {
active:
acc.active +
pm.vms.filter((vm) => vm.state?.toLowerCase() === "active")
.length,
total: acc.total + pm.vms.length,
};
},
{ active: 0, total: 0 }
); );
return ( return (
<div className="d-flex align-items-center"> <div className="d-flex align-items-center">
<Monitor size={16} className="mr-1" /> <Monitor size={16} className="mr-2" />
<span>{totalVMs}</span> <div>
<div className="font-weight-bold">{vms.total} Total</div>
<div className="small">
<span className="text-success">{vms.active} Active</span>
<span className="text-muted mx-1"></span>
<span className="text-warning">
{vms.total - vms.active} Inactive
</span>
</div>
</div>
</div> </div>
); );
}, },
@@ -138,76 +180,112 @@ const DataCenter = () => {
<div key={pm.id} className="mb-3 border rounded p-3"> <div key={pm.id} className="mb-3 border rounded p-3">
<h6 className="text-primary">{pm.name}</h6> <h6 className="text-primary">{pm.name}</h6>
{/* Active VMs */} {/* All VMs */}
<p className="mb-2"> <div className="mb-2 d-flex justify-content-between align-items-center">
<strong>Active VMs ({pm.vms?.active?.length || 0}):</strong> <h6 className="mb-0">
</p> <Monitor size={16} className="mr-1" />
{pm.vms?.active?.length > 0 ? ( Virtual Machines ({pm.vms?.length || 0})
<div className="ml-3"> </h6>
{pm.vms.active.map((vm) => ( </div>
<div {pm.vms?.length > 0 ? (
key={vm.id} <div className="table-responsive mt-2">
className="mb-2 p-2 border-left border-success" <table className="table table-bordered table-hover">
> <thead className="thead-light">
<div className="row"> <tr>
<div className="col-md-3"> <th>Name</th>
<strong>Name:</strong> {vm.name} <th>Status</th>
</div> <th>Power (W)</th>
<div className="col-md-2"> <th>Configuration</th>
<strong>Status:</strong> <th>Host</th>
<span className="badge badge-success ml-1"> </tr>
{vm.status} </thead>
</span> <tbody>
</div> {pm.vms.map((vm) => {
<div className="col-md-2"> const isActive =
<strong>Power:</strong> {vm.power} vm.state && ["ACTIVE", "active"].includes(vm.state);
</div> return (
<div className="col-md-5"> <tr key={vm.id}>
<strong>Config:</strong> CPU: {vm.config?.cpu}, RAM:{" "} <td>
{vm.config?.ram}, Disk: {vm.config?.disk} <span className="font-weight-bold">
</div> {vm.vmName || vm.vm_name}
</div> </span>
</div> </td>
))} <td>
<div
className={`d-inline-block px-2 py-1 rounded-pill ${
isActive
? "bg-light-success text-success"
: "bg-light-warning text-warning"
}`}
>
{vm.state}
</div>
</td>
<td>
{vm.power ? (
<span>{vm.power.toFixed(2)}</span>
) : (
<span className="text-muted">-</span>
)}
</td>
<td>
<div className="d-flex align-items-center">
<div className="mr-3">
<small className="text-muted d-block">
CPU
</small>
<span>
{vm.config?.cpu ||
(vm.confg && vm.confg[1]) ||
"-"}
</span>
</div>
<div className="mr-3">
<small className="text-muted d-block">
RAM
</small>
<span>
{vm.config?.ram ||
(vm.confg && vm.confg[2]) ||
"-"}{" "}
GB
</span>
</div>
<div>
<small className="text-muted d-block">
Disk
</small>
<span>
{vm.config?.disk ||
(vm.confg && vm.confg[3]) ||
"-"}{" "}
GB
</span>
</div>
</div>
</td>
<td>
<div className="d-flex align-items-center">
<Server size={14} className="mr-1" />
<span>
{vm.host ||
vm.hostingPm ||
(vm.confg && vm.confg[4]) ||
"-"}
</span>
</div>
</td>
</tr>
);
})}
</tbody>
</table>
</div> </div>
) : ( ) : (
<p className="text-muted ml-3">No active VMs</p> <div className="text-center p-3 bg-light-secondary rounded">
)} <Monitor size={24} className="text-muted mb-1" />
<p className="text-muted mb-0">No virtual machines found</p>
{/* Inactive VMs */}
<p className="mb-2 mt-3">
<strong>Inactive VMs ({pm.vms?.inactive?.length || 0}):</strong>
</p>
{pm.vms?.inactive?.length > 0 ? (
<div className="ml-3">
{pm.vms.inactive.map((vm) => (
<div
key={vm.id}
className="mb-2 p-2 border-left border-warning"
>
<div className="row">
<div className="col-md-3">
<strong>Name:</strong> {vm.name}
</div>
<div className="col-md-2">
<strong>Status:</strong>
<span className="badge badge-warning ml-1">
{vm.status}
</span>
</div>
<div className="col-md-2">
<strong>Power:</strong> {vm.power}
</div>
<div className="col-md-5">
<strong>Config:</strong> CPU: {vm.config?.cpu}, RAM:{" "}
{vm.config?.ram}, Disk: {vm.config?.disk}
</div>
</div>
</div>
))}
</div> </div>
) : (
<p className="text-muted ml-3">No inactive VMs</p>
)} )}
</div> </div>
))} ))}
@@ -215,8 +293,6 @@ const DataCenter = () => {
); );
}; };
return ( return (
<div style={{ marginTop: "2%" }}> <div style={{ marginTop: "2%" }}>
<Card> <Card>

File diff suppressed because it is too large Load Diff

View File

@@ -1,101 +1,157 @@
import React, { useState, useEffect } from "react"; import React, { useState, useEffect, useMemo } from "react";
import { MaterialReactTable } from "material-react-table"; import { MaterialReactTable } from "material-react-table";
import { useDispatch, useSelector } from "react-redux"; import { useDispatch, useSelector } from "react-redux";
import { useTranslation } from "react-i18next"; import { useTranslation } from "react-i18next";
import { Card, CardHeader, CardTitle, Alert } from "reactstrap"; import {
Card,
CardHeader,
CardTitle,
Alert,
Row,
Col,
Label,
} from "reactstrap";
import { getVMEmissionSummary } from "../../redux/actions/mainDataTables/index"; import { getVMEmissionSummary } from "../../redux/actions/mainDataTables/index";
import { getDataCenters } from "../../redux/actions/dataCenter";
import { editNumbers } from "../../components/edit-numbers"; import { editNumbers } from "../../components/edit-numbers";
import Select from "react-select";
function MainDataTables() { function MainDataTables() {
const { t } = useTranslation(); const { t } = useTranslation();
const dispatch = useDispatch(); const dispatch = useDispatch();
const mainDataTablesStore = useSelector((state) => state.mainDataTables); const mainDataTablesStore = useSelector((state) => state.mainDataTables);
const dataCenterStore = useSelector((state) => state.dataCenter);
const [error, setError] = useState(null); const [error, setError] = useState(null);
const [selectedDataCenter, setSelectedDataCenter] = useState(null);
const [dataCenterOptions, setDataCenterOptions] = useState([]);
const [loading, setLoading] = useState(false);
// Fetch datacenters on component mount
useEffect(() => { useEffect(() => {
try { dispatch(getDataCenters());
// Fetch VM emission data
dispatch(getVMEmissionSummary());
} catch (err) {
console.error('Error in MainDataTables:', err);
setError(err.message);
}
}, [dispatch]); }, [dispatch]);
// Debug log for store data // Update datacenter options when datacenters are loaded
useEffect(() => { useEffect(() => {
console.log('Current store data:', mainDataTablesStore); if (dataCenterStore?.dataCenters?.length > 0) {
}, [mainDataTablesStore]); const options = dataCenterStore.dataCenters.map((dataCenter) => ({
value: dataCenter.id,
label: dataCenter.dataCenter,
externalId: dataCenter.externalId,
}));
setDataCenterOptions(options);
}
}, [dataCenterStore?.dataCenters]);
const columns = [ // Fetch VM emission data when datacenter is selected
{ useEffect(() => {
header: "VM ID", if (selectedDataCenter?.value) {
accessorKey: "vmId", const fetchData = async () => {
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>, try {
}, setLoading(true);
{ setError(null);
header: "Data Center", await dispatch(getVMEmissionSummary(selectedDataCenter.value));
accessorKey: "dataCenter", } catch (err) {
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>, console.error("Error in MainDataTables:", err);
}, setError(err.message);
{ } finally {
header: "Project", setLoading(false);
accessorKey: "project", }
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>, };
}, fetchData();
{ }
header: "Physical Machine", }, [selectedDataCenter, dispatch]);
accessorKey: "physicalMachine",
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: "Virtual Machine",
accessorKey: "vmName",
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: "VM Power (W)",
accessorKey: "vmPower",
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "VM Status",
accessorKey: "vmStatus",
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: "Total Emissions",
accessorKey: "totalEmission",
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "CO2",
accessorKey: "co2",
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "CH4",
accessorKey: "ch4",
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "N2O",
accessorKey: "n2o",
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "Created Date",
accessorKey: "createdDate",
Cell: ({ cell }) => (
<span>
{cell.getValue() ? new Date(cell.getValue()).toLocaleString() : "-"}
</span>
),
},
];
const tableData = mainDataTablesStore?.vmEmissionSummary || []; // Memoize columns to prevent re-renders
console.log('VM Emission data:', tableData); const columns = useMemo(
() => [
{
header: t("VM ID"),
accessorKey: "vmId",
size: 150,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: t("VM Name"),
accessorKey: "vmName",
size: 200,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: t("VM Power"),
accessorKey: "vmPower",
size: 120,
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: t("VM Status"),
accessorKey: "vmStatus",
size: 100,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: t("Total Emission"),
accessorKey: "totalEmission",
size: 150,
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: t("Physical Machine"),
accessorKey: "physicalMachine",
size: 150,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: t("Cloud System"),
accessorKey: "cloudSystem",
size: 150,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: t("Data Center"),
accessorKey: "dataCenter",
size: 150,
Cell: ({ cell }) => <span>{cell.getValue() || "-"}</span>,
},
{
header: "CO2",
accessorKey: "co2",
size: 100,
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "CH4",
accessorKey: "ch4",
size: 100,
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: "N2O",
accessorKey: "n2o",
size: 100,
Cell: ({ cell }) => <span>{editNumbers(cell.getValue()) || "-"}</span>,
},
{
header: t("Created Date"),
accessorKey: "createdDate",
size: 180,
Cell: ({ cell }) => (
<span>
{cell.getValue() ? new Date(cell.getValue()).toLocaleString() : "-"}
</span>
),
sortable: true,
},
],
[t]
);
// Memoize table data to prevent unnecessary re-renders
const tableData = useMemo(() => {
const data = mainDataTablesStore?.vmEmissionSummary || [];
console.log("VM Emission data count:", data.length);
return data;
}, [mainDataTablesStore?.vmEmissionSummary]);
if (error) { if (error) {
return ( return (
@@ -109,37 +165,109 @@ function MainDataTables() {
<div style={{ marginTop: "2%" }}> <div style={{ marginTop: "2%" }}>
<Card> <Card>
<CardHeader className="border-bottom"> <CardHeader className="border-bottom">
<CardTitle tag="h4">{t("Carbon Emission Data")}</CardTitle> <CardTitle tag="h4">{t("Raw Data")}</CardTitle>
{tableData.length > 0 && (
<small className="text-muted">
{tableData.length} records loaded
</small>
)}
</CardHeader> </CardHeader>
<MaterialReactTable
columns={columns} {/* Datacenter Selection */}
data={tableData} <div className="p-3 border-bottom">
enableColumnFilters={true} <Row>
enableFilters={true} <Col md="6">
enableGlobalFilter={true} <Label for="datacenter-select">{t("Data Center")}</Label>
enablePagination={true} <Select
enableColumnResizing={true} id="datacenter-select"
enableStickyHeader={true} value={selectedDataCenter}
muiTableContainerProps={{ sx: { maxHeight: 'calc(100vh - 180px)' } }} onChange={setSelectedDataCenter}
muiTableProps={{ options={dataCenterOptions}
sx: { placeholder={t("Select a data center...")}
tableLayout: 'auto', isClearable
}, isSearchable
}} isLoading={dataCenterStore?.loading}
initialState={{ noOptionsMessage={() => t("No data centers available")}
pagination: { styles={{
pageSize: 100, menu: (provided) => ({
pageIndex: 0 ...provided,
}, zIndex: 9999, // Ensure dropdown appears above other elements
sorting: [ }),
{ id: 'dataCenter', desc: false } }}
], menuPortalTarget={document.body} // Render dropdown in body to avoid container overflow
density: 'compact' />
}} </Col>
state={{ </Row>
isLoading: !mainDataTablesStore?.vmEmissionSummary </div>
}}
/> {selectedDataCenter ? (
<MaterialReactTable
columns={columns}
data={tableData}
// Performance optimizations for large datasets
enableColumnFilters={true}
enableFilters={true}
enableGlobalFilter={true}
enablePagination={true}
enableColumnResizing={true} // Disable resizing for better performance
enableStickyHeader={true}
enableRowVirtualization={true} // Enable virtualization for large datasets
enableColumnVirtualization={false} // Keep columns visible
// Pagination settings for large datasets
initialState={{
pagination: {
pageSize: 100, // Reduce page size for better performance
pageIndex: 0,
},
sorting: [{ id: "createdDate", desc: true }],
density: "compact",
}}
// Performance-optimized table props
muiTableContainerProps={{
sx: {
maxHeight: "calc(100vh - 250px)",
minHeight: "400px",
},
}}
muiTableProps={{
sx: {
tableLayout: "fixed", // Better performance with fixed layout
},
}}
// Pagination options
muiTablePaginationProps={{
rowsPerPageOptions: [10, 25, 50, 100],
showFirstButton: true,
showLastButton: true,
}}
// Loading and error states
state={{
isLoading: loading || mainDataTablesStore?.loading,
showProgressBars: loading || mainDataTablesStore?.loading,
showSkeletons: loading || mainDataTablesStore?.loading,
}}
// Disable features that can slow down large tables
enableRowSelection={false}
enableColumnOrdering={true}
enableColumnDragging={false}
enableDensityToggle={false}
enableFullScreenToggle={false}
// Custom loading overlay
renderProgressBarCell={({ cell }) => (
<div
style={{
width: "100%",
height: "20px",
backgroundColor: "#f0f0f0",
}}
/>
)}
/>
) : (
<div className="p-4 text-center text-muted">
{t("Please select a data center to view raw data")}
</div>
)}
</Card> </Card>
</div> </div>
); );

View File

@@ -32,15 +32,87 @@ import { getCities } from "../redux/actions/cities";
import { v4 as uuidv4 } from "uuid"; import { v4 as uuidv4 } from "uuid";
import { getCity } from "../redux/actions/city"; import { getCity } from "../redux/actions/city";
import { getDistrict } from "../redux/actions/district"; import { getDistrict } from "../redux/actions/district";
import { // import {
getOrganisations, // getOrganisations,
getOrganisationById, // getOrganisationById,
} from "../redux/actions/organisations"; // } from "../redux/actions/organisations";
import { getAreasWithCriteria } from "../redux/actions/areas"; import { getAreasWithCriteria } from "../redux/actions/areas";
import { ChromePicker } from "react-color"; import { ChromePicker } from "react-color";
import { customFilterForSelect } from "../utility/Utils"; import { customFilterForSelect } from "../utility/Utils";
import { permissionCheck } from "../components/permission-check"; import { permissionCheck } from "../components/permission-check";
import { getDataCenters } from "../redux/actions/dataCenter"; import { getDataCenters } from "../redux/actions/dataCenter";
import L from "leaflet";
// Custom data center icon
const dataCenterIcon = new L.Icon({
iconUrl:
"data:image/svg+xml;base64," +
btoa(`
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 48 48" width="48" height="48">
<defs>
<linearGradient id="serverGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#4A90E2;stop-opacity:1" />
<stop offset="100%" style="stop-color:#2E5BBA;stop-opacity:1" />
</linearGradient>
<linearGradient id="rackGradient" x1="0%" y1="0%" x2="0%" y2="100%">
<stop offset="0%" style="stop-color:#F5F5F5;stop-opacity:1" />
<stop offset="100%" style="stop-color:#E0E0E0;stop-opacity:1" />
</linearGradient>
</defs>
<!-- Main server rack -->
<rect x="8" y="4" width="32" height="40" rx="2" ry="2" fill="url(#rackGradient)" stroke="#B0B0B0" stroke-width="1"/>
<!-- Server units -->
<rect x="10" y="6" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<rect x="10" y="12" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<rect x="10" y="18" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<rect x="10" y="24" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<rect x="10" y="30" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<rect x="10" y="36" width="28" height="4" rx="1" fill="url(#serverGradient)" stroke="#2E5BBA" stroke-width="0.5"/>
<!-- LED indicators -->
<circle cx="13" cy="8" r="0.8" fill="#00FF00"/>
<circle cx="13" cy="14" r="0.8" fill="#00FF00"/>
<circle cx="13" cy="20" r="0.8" fill="#FFFF00"/>
<circle cx="13" cy="26" r="0.8" fill="#00FF00"/>
<circle cx="13" cy="32" r="0.8" fill="#FF0000"/>
<circle cx="13" cy="38" r="0.8" fill="#00FF00"/>
<!-- Power indicators -->
<circle cx="35" cy="8" r="0.6" fill="#0080FF"/>
<circle cx="35" cy="14" r="0.6" fill="#0080FF"/>
<circle cx="35" cy="20" r="0.6" fill="#0080FF"/>
<circle cx="35" cy="26" r="0.6" fill="#0080FF"/>
<circle cx="35" cy="32" r="0.6" fill="#0080FF"/>
<circle cx="35" cy="38" r="0.6" fill="#0080FF"/>
<!-- Ventilation grilles -->
<rect x="16" y="7" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="8.5" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="13" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="14.5" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="19" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="20.5" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="25" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="26.5" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="31" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="32.5" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="37" width="16" height="0.5" fill="#1A4A8A"/>
<rect x="16" y="38.5" width="16" height="0.5" fill="#1A4A8A"/>
<!-- Base/feet -->
<rect x="6" y="42" width="4" height="2" rx="1" fill="#808080"/>
<rect x="38" y="42" width="4" height="2" rx="1" fill="#808080"/>
<!-- Shadow -->
<ellipse cx="24" cy="45" rx="18" ry="2" fill="#000000" opacity="0.2"/>
</svg>
`),
iconSize: [48, 48],
iconAnchor: [18, 36],
popupAnchor: [0, -36],
});
const ColorPicker = ({ selectedColors, setSelectedColors, index }) => { const ColorPicker = ({ selectedColors, setSelectedColors, index }) => {
const [showColorPicker, setShowColorPicker] = useState(false); const [showColorPicker, setShowColorPicker] = useState(false);
@@ -117,20 +189,20 @@ const Map = () => {
const citiesStore = useSelector((state) => state.cities); const citiesStore = useSelector((state) => state.cities);
const cityStore = useSelector((state) => state.city); const cityStore = useSelector((state) => state.city);
const districtStore = useSelector((state) => state.district); const districtStore = useSelector((state) => state.district);
const OrganisationsStore = useSelector((state) => state.organizations); // const OrganisationsStore = useSelector((state) => state.organizations);
const areasStore = useSelector((state) => state.areas); const areasStore = useSelector((state) => state.areas);
const dataCenterStore = useSelector((state) => state.dataCenter); const dataCenterStore = useSelector((state) => state.dataCenter);
const [cities, setCities] = useState([]); const [cities, setCities] = useState([]);
const [districts, setDistricts] = useState([]); const [districts, setDistricts] = useState([]);
const [neighborhoods, setNeighborhoods] = useState([]); const [neighborhoods, setNeighborhoods] = useState([]);
const [organizationOptions, setOrganizationOptions] = useState([]); // const [organizationOptions, setOrganizationOptions] = useState([]);
const organizationId = localStorage.getItem("organizationId"); // const organizationId = localStorage.getItem("organizationId");
const roleTag = localStorage.getItem("roleTag"); // const roleTag = localStorage.getItem("roleTag");
const [selectedOrganization, setSelectedOrganization] = useState({ // const [selectedOrganization, setSelectedOrganization] = useState({
label: localStorage.getItem("organizationName"), // label: localStorage.getItem("organizationName"),
value: organizationId, // value: organizationId,
}); // });
const [areasOptions, setAreasOptions] = useState([]); const [areasOptions, setAreasOptions] = useState([]);
const [done, setDone] = useState(false); const [done, setDone] = useState(false);
@@ -146,7 +218,7 @@ const Map = () => {
const [showDataInputModal, setShowDataInputModal] = useState(false); const [showDataInputModal, setShowDataInputModal] = useState(false);
const [inputData, setInputData] = useState({ const [inputData, setInputData] = useState({
organization: selectedOrganization, // organization: selectedOrganization,
}); });
const [referance, setReferance] = useState( const [referance, setReferance] = useState(
Number(localStorage.getItem("referance")) || 1000 Number(localStorage.getItem("referance")) || 1000
@@ -176,15 +248,17 @@ const Map = () => {
dispatch(getDataCenters()); dispatch(getDataCenters());
}, []); }, []);
useEffect(() => { // useEffect(() => {
if (selectedOrganization?.value != "undefined") { // if (selectedOrganization?.value != "undefined") {
dispatch(getAreasWithCriteria(selectedOrganization.value)); // dispatch(getAreasWithCriteria(selectedOrganization.value));
} // }
}, [selectedOrganization]); // }, [selectedOrganization]);
useEffect(() => { useEffect(() => {
setAreasOptions([]); setAreasOptions([]);
// Load all areas without organization filter for now
// You may want to add organization filtering back later if needed
const citiesOptions = const citiesOptions =
areasStore?.areasWithCriteria areasStore?.areasWithCriteria
?.map((area) => ?.map((area) =>
@@ -235,13 +309,13 @@ const Map = () => {
]); ]);
}, [areasStore]); }, [areasStore]);
useEffect(() => { // useEffect(() => {
if (roleTag === "SUPER_ADMIN") { // if (roleTag === "SUPER_ADMIN") {
dispatch(getOrganisations()); // dispatch(getOrganisations());
} else { // } else {
dispatch(getOrganisationById(organizationId)); // dispatch(getOrganisationById(organizationId));
} // }
}, []); // }, []);
const handleDataInputButtonPressed = ({ area, type }) => { const handleDataInputButtonPressed = ({ area, type }) => {
const areaName = const areaName =
@@ -348,38 +422,38 @@ const Map = () => {
}); });
}, [selectedDistrict, districtStore?.district, year.value]); }, [selectedDistrict, districtStore?.district, year.value]);
useEffect(() => { // useEffect(() => {
let organizationOptions = []; // let organizationOptions = [];
if ( // if (
OrganisationsStore.organization && // OrganisationsStore.organization &&
OrganisationsStore.organization.length !== 0 // OrganisationsStore.organization.length !== 0
) { // ) {
organizationOptions.push({ // organizationOptions.push({
value: OrganisationsStore.organization.id, // value: OrganisationsStore.organization.id,
label: OrganisationsStore.organization.tag, // label: OrganisationsStore.organization.tag,
}); // });
if (OrganisationsStore.organization.children) { // if (OrganisationsStore.organization.children) {
organizationOptions = [ // organizationOptions = [
...organizationOptions, // ...organizationOptions,
...OrganisationsStore.organization.children.map((organization) => ({ // ...OrganisationsStore.organization.children.map((organization) => ({
value: organization.child.id, // value: organization.child.id,
label: organization.child.tag, // label: organization.child.tag,
})), // })),
]; // ];
} // }
} else { // } else {
organizationOptions = OrganisationsStore.dataOrganization.map( // organizationOptions = OrganisationsStore.dataOrganization.map(
(organization) => ({ // (organization) => ({
value: organization.id, // value: organization.id,
label: organization.tag, // label: organization.tag,
}) // })
); // );
} // }
setOrganizationOptions(organizationOptions); // setOrganizationOptions(organizationOptions);
}, [OrganisationsStore]); // }, [OrganisationsStore]);
const renderDataInputModal = () => { const renderDataInputModal = () => {
return ( return (
@@ -623,29 +697,60 @@ const Map = () => {
<LayerGroup> <LayerGroup>
{dataCenterStore.dataCenters.map((dc) => { {dataCenterStore.dataCenters.map((dc) => {
if (!dc.latitude || !dc.longitude) return null; if (!dc.latitude || !dc.longitude) return null;
return ( return (
<Marker <Marker
key={dc.id} key={dc.id}
position={[dc.latitude, dc.longitude]} position={[dc.latitude, dc.longitude]}
icon={dataCenterIcon}
> >
<Popup> <Popup>
<div className="data-center-popup"> <div className="data-center-popup">
<h5 className="mb-2">{dc.dataCenter}</h5> <h5 className="mb-2 text-primary">{dc.dataCenter}</h5>
<p className="mb-1"><strong>{t('DataCenter.number')}:</strong> {dc.number}</p> <div className="mb-2">
<p className="mb-1"><strong>{t('DataCenter.externalId')}:</strong> {dc.externalId}</p>
<p className="mb-1"><strong>{t('DataCenter.city')}:</strong> {dc.area?.cities?.map(city => city.name).join(', ') || "-"}</p>
{dc.area && <p className="mb-1"><strong>{t('Area')}:</strong> {dc.area.tag}</p>}
{dc.projects?.length > 0 && (
<p className="mb-1"> <p className="mb-1">
<strong>{t('Projects')}:</strong> {dc.projects.length} <strong>{t("DataCenter.city")}:</strong>{" "}
<span>{dc.city?.name || "-"}</span>
</p>
{dc.address && (
<p className="mb-1 small text-muted">
<strong>{t("Address")}:</strong> {dc.address}
</p>
)}
</div>
<p className="mb-1">
<strong>{t("DataCenter.number")}:</strong> {dc.number}
</p>
<p className="mb-1">
<strong>{t("DataCenter.externalId")}:</strong>{" "}
{dc.externalId}
</p>
{dc.area && (
<p className="mb-1">
<strong>{t("Area")}:</strong> {dc.area.tag}
</p>
)}
{dc.physicalMachines?.length > 0 && (
<p className="mb-1">
<strong>{t("Physical Machines")}:</strong>{" "}
<span className="badge badge-secondary">
{dc.physicalMachines.length}
</span>
</p>
)}
{dc.dataCenterEmissionSources?.length > 0 && (
<p className="mb-1">
<strong>{t("EmissionSources.emissionSources")}:</strong>{" "}
<span className="badge badge-info">
{dc.dataCenterEmissionSources.length}
</span>
</p> </p>
)} )}
{dc.ayposURL && ( {dc.ayposURL && (
<Button <Button
className="w-100 mb-1" className="w-100 mb-1"
color="primary" color="primary"
onClick={() => window.open(dc.ayposURL, '_blank')} onClick={() => window.open(dc.ayposURL, "_blank")}
> >
Dashboard Dashboard
</Button> </Button>
@@ -699,7 +804,9 @@ const Map = () => {
setDistrictView(true); setDistrictView(true);
setZoom(8.0); setZoom(8.0);
let convertCordinates = convertCoordinates(city.coordinates); let convertCordinates = convertCoordinates(
city.coordinates
);
let length = convertCordinates[0][0][0].length; let length = convertCordinates[0][0][0].length;
let mlength = ((length + 1) / 2).toFixed(0); let mlength = ((length + 1) / 2).toFixed(0);
let lat1 = convertCordinates[0][0][0][0]; let lat1 = convertCordinates[0][0][0][0];
@@ -710,7 +817,7 @@ const Map = () => {
lat: ((lat1 + lat2) / 2).toFixed(2), lat: ((lat1 + lat2) / 2).toFixed(2),
lng: ((lng1 + lng2) / 2).toFixed(2), lng: ((lng1 + lng2) / 2).toFixed(2),
}); });
} },
}} }}
> >
<Tooltip permanent direction="center"> <Tooltip permanent direction="center">