diff --git a/database/install/myems_system_db.sql b/database/install/myems_system_db.sql index 7515312b..5e35f3bd 100644 --- a/database/install/myems_system_db.sql +++ b/database/install/myems_system_db.sql @@ -431,6 +431,7 @@ VALUES (309,'Offline Meter Cost','/meter/offlinemetercost',300,0), (310,'Batch Analysis','/meter/batch',300,0), (311,'Meter Tracking','/meter/tracking',300,0), +(312,'Meter Carbon','/meter/metercarbon',300,0), (400,'Tenant Data','/tenant',NULL,0), (401,'Energy Category Data','/tenant/energycategory',400,0), (402,'Energy Item Data','/tenant/energyitem',400,0), diff --git a/database/upgrade/upgrade1.8.0.sql b/database/upgrade/upgrade1.8.0.sql new file mode 100644 index 00000000..0c0be5d5 --- /dev/null +++ b/database/upgrade/upgrade1.8.0.sql @@ -0,0 +1,16 @@ +-- --------------------------------------------------------------------------------------------------------------------- +-- WARNING: BACKUP YOUR DATABASE BEFORE UPGRADING +-- THIS SCRIPT IS ONLY FOR UPGRADING 1.7.1 TO 1.7.2 +-- THE CURRENT VERSION CAN BE FOUND AT `myems_system_db`.`tbl_versions` +-- --------------------------------------------------------------------------------------------------------------------- + +START TRANSACTION; + +INSERT INTO myems_system_db.tbl_menus (id,name,route, parent_menu_id,is_hidden) +VALUES +(312,'Meter Carbon','/meter/metercarbon',300,0); + +-- UPDATE VERSION NUMBER +UPDATE `myems_system_db`.`tbl_versions` SET version='1.8.0', release_date='2022-02-28' WHERE id=1; + +COMMIT; diff --git a/myems-api/core/version.py b/myems-api/core/version.py index eb2d9e26..3f0ed69b 100644 --- a/myems-api/core/version.py +++ b/myems-api/core/version.py @@ -15,8 +15,8 @@ class VersionItem: @staticmethod def on_get(req, resp): - result = {"version": 'MyEMS v1.7.2', - "release-date": '2022-02-19', + result = {"version": 'MyEMS v1.8.0', + "release-date": '2022-02-28', "website": "https://myems.io"} resp.text = json.dumps(result) diff --git a/myems-api/excelexporters/metercarbon.py b/myems-api/excelexporters/metercarbon.py index c97f1ced..10645cf3 100644 --- a/myems-api/excelexporters/metercarbon.py +++ b/myems-api/excelexporters/metercarbon.py @@ -62,7 +62,7 @@ def generate_excel(report, name, reporting_start_datetime_local, reporting_end_d # todo ws = wb.active - ws.title = "MeterCarbon" + ws.title = "MeterCarbonDioxideEmissions" # Row height ws.row_dimensions[1].height = 102 for i in range(2, 2000 + 1): @@ -166,7 +166,7 @@ def generate_excel(report, name, reporting_start_datetime_local, reporting_end_d ws['B8'].font = title_font ws['B8'].alignment = c_c_alignment - ws['B8'] = 'Carbon Dioxide Emission' + ws['B8'] = 'Carbon Dioxide Emissions' ws['B8'].border = f_border ws['B9'].font = title_font diff --git a/web/src/components/MyEMS/Meter/MeterCarbon.js b/web/src/components/MyEMS/Meter/MeterCarbon.js new file mode 100644 index 00000000..fb29de42 --- /dev/null +++ b/web/src/components/MyEMS/Meter/MeterCarbon.js @@ -0,0 +1,642 @@ +import React, { Fragment, useEffect, useState } from 'react'; +import { + Breadcrumb, + BreadcrumbItem, + Row, + Col, + Card, + CardBody, + Button, + ButtonGroup, + Form, + FormGroup, + Input, + Label, + CustomInput, + Spinner, +} from 'reactstrap'; +import CountUp from 'react-countup'; +import Datetime from 'react-datetime'; +import moment from 'moment'; +import loadable from '@loadable/component'; +import Cascader from 'rc-cascader'; +import CardSummary from '../common/CardSummary'; +import LineChart from '../common/LineChart'; +import { getCookieValue, createCookie } from '../../../helpers/utils'; +import withRedirect from '../../../hoc/withRedirect'; +import { withTranslation } from 'react-i18next'; +import { toast } from 'react-toastify'; +import ButtonIcon from '../../common/ButtonIcon'; +import { APIBaseURL } from '../../../config'; +import { periodTypeOptions } from '../common/PeriodTypeOptions'; +import { comparisonTypeOptions } from '../common/ComparisonTypeOptions'; + + +const DetailedDataTable = loadable(() => import('../common/DetailedDataTable')); + +const MeterCarbon = ({ setRedirect, setRedirectUrl, t }) => { + let current_moment = moment(); + useEffect(() => { + let is_logged_in = getCookieValue('is_logged_in'); + let user_name = getCookieValue('user_name'); + let user_display_name = getCookieValue('user_display_name'); + let user_uuid = getCookieValue('user_uuid'); + let token = getCookieValue('token'); + if (is_logged_in === null || !is_logged_in) { + setRedirectUrl(`/authentication/basic/login`); + setRedirect(true); + } else { + //update expires time of cookies + createCookie('is_logged_in', true, 1000 * 60 * 60 * 8); + createCookie('user_name', user_name, 1000 * 60 * 60 * 8); + createCookie('user_display_name', user_display_name, 1000 * 60 * 60 * 8); + createCookie('user_uuid', user_uuid, 1000 * 60 * 60 * 8); + createCookie('token', token, 1000 * 60 * 60 * 8); + } + }); + + // State + //Query From + const [selectedSpaceName, setSelectedSpaceName] = useState(undefined); + const [selectedSpaceID, setSelectedSpaceID] = useState(undefined); + const [meterList, setMeterList] = useState([]); + const [filteredMeterList, setFilteredMeterList] = useState([]); + const [selectedMeter, setSelectedMeter] = useState(undefined); + const [comparisonType, setComparisonType] = useState('month-on-month'); + const [periodType, setPeriodType] = useState('daily'); + const [basePeriodBeginsDatetime, setBasePeriodBeginsDatetime] = useState(current_moment.clone().subtract(1, 'months').startOf('month')); + const [basePeriodEndsDatetime, setBasePeriodEndsDatetime] = useState(current_moment.clone().subtract(1, 'months')); + const [basePeriodBeginsDatetimeDisabled, setBasePeriodBeginsDatetimeDisabled] = useState(true); + const [basePeriodEndsDatetimeDisabled, setBasePeriodEndsDatetimeDisabled] = useState(true); + const [reportingPeriodBeginsDatetime, setReportingPeriodBeginsDatetime] = useState(current_moment.clone().startOf('month')); + const [reportingPeriodEndsDatetime, setReportingPeriodEndsDatetime] = useState(current_moment); + const [cascaderOptions, setCascaderOptions] = useState(undefined); + + // buttons + const [submitButtonDisabled, setSubmitButtonDisabled] = useState(true); + const [spinnerHidden, setSpinnerHidden] = useState(true); + const [exportButtonHidden, setExportButtonHidden] = useState(true); + + //Results + const [meterEnergyCategory, setMeterEnergyCategory] = useState({ 'name': '', 'unit': '' }); + const [reportingPeriodEnergyCarbonInCategory, setReportingPeriodEnergyCarbonInCategory] = useState(0); + const [reportingPeriodEnergyCarbonRate, setReportingPeriodEnergyCarbonRate] = useState(''); + const [reportingPeriodEnergyConsumptionInTCE, setReportingPeriodEnergyConsumptionInTCE] = useState(0); + const [reportingPeriodEnergyConsumptionInCO2, setReportingPeriodEnergyConsumptionInCO2] = useState(0); + const [basePeriodEnergyCarbonInCategory, setBasePeriodEnergyCarbonInCategory] = useState(0); + const [meterLineChartOptions, setMeterLineChartOptions] = useState([]); + const [meterLineChartData, setMeterLineChartData] = useState({}); + const [meterLineChartLabels, setMeterLineChartLabels] = useState([]); + const [parameterLineChartOptions, setParameterLineChartOptions] = useState([]); + const [parameterLineChartData, setParameterLineChartData] = useState({}); + const [parameterLineChartLabels, setParameterLineChartLabels] = useState([]); + const [detailedDataTableColumns, setDetailedDataTableColumns] = useState([{dataField: 'startdatetime', text: t('Datetime'), sort: true}]); + const [detailedDataTableData, setDetailedDataTableData] = useState([]); + const [excelBytesBase64, setExcelBytesBase64] = useState(undefined); + + useEffect(() => { + let isResponseOK = false; + fetch(APIBaseURL + '/spaces/tree', { + method: 'GET', + headers: { + "Content-type": "application/json", + "User-UUID": getCookieValue('user_uuid'), + "Token": getCookieValue('token') + }, + body: null, + + }).then(response => { + console.log(response); + if (response.ok) { + isResponseOK = true; + } + return response.json(); + }).then(json => { + console.log(json); + if (isResponseOK) { + // rename keys + json = JSON.parse(JSON.stringify([json]).split('"id":').join('"value":').split('"name":').join('"label":')); + setCascaderOptions(json); + setSelectedSpaceName([json[0]].map(o => o.label)); + setSelectedSpaceID([json[0]].map(o => o.value)); + // get Meters by root Space ID + let isResponseOK = false; + fetch(APIBaseURL + '/spaces/' + [json[0]].map(o => o.value) + '/meters', { + method: 'GET', + headers: { + "Content-type": "application/json", + "User-UUID": getCookieValue('user_uuid'), + "Token": getCookieValue('token') + }, + body: null, + + }).then(response => { + if (response.ok) { + isResponseOK = true; + } + return response.json(); + }).then(json => { + if (isResponseOK) { + json = JSON.parse(JSON.stringify([json]).split('"id":').join('"value":').split('"name":').join('"label":')); + console.log(json); + setMeterList(json[0]); + setFilteredMeterList(json[0]); + if (json[0].length > 0) { + setSelectedMeter(json[0][0].value); + // enable submit button + setSubmitButtonDisabled(false); + } else { + setSelectedMeter(undefined); + // disable submit button + setSubmitButtonDisabled(true); + } + } else { + toast.error(json.description) + } + }).catch(err => { + console.log(err); + }); + // end of get Meters by root Space ID + } else { + toast.error(json.description); + } + }).catch(err => { + console.log(err); + }); + }, [t, ]); + + const labelClasses = 'ls text-uppercase text-600 font-weight-semi-bold mb-0'; + + + let onSpaceCascaderChange = (value, selectedOptions) => { + setSelectedSpaceName(selectedOptions.map(o => o.label).join('/')); + setSelectedSpaceID(value[value.length - 1]); + + let isResponseOK = false; + fetch(APIBaseURL + '/spaces/' + value[value.length - 1] + '/meters', { + method: 'GET', + headers: { + "Content-type": "application/json", + "User-UUID": getCookieValue('user_uuid'), + "Token": getCookieValue('token') + }, + body: null, + + }).then(response => { + if (response.ok) { + isResponseOK = true; + } + return response.json(); + }).then(json => { + if (isResponseOK) { + json = JSON.parse(JSON.stringify([json]).split('"id":').join('"value":').split('"name":').join('"label":')); + console.log(json) + setMeterList(json[0]); + setFilteredMeterList(json[0]); + if (json[0].length > 0) { + setSelectedMeter(json[0][0].value); + // enable submit button + setSubmitButtonDisabled(false); + } else { + setSelectedMeter(undefined); + // disable submit button + setSubmitButtonDisabled(true); + } + } else { + toast.error(json.description) + } + }).catch(err => { + console.log(err); + }); + }; + + const onSearchMeter = ({ target }) => { + const keyword = target.value.toLowerCase(); + const filteredResult = meterList.filter( + meter => meter.label.toLowerCase().includes(keyword) + ); + setFilteredMeterList(keyword.length ? filteredResult : meterList); + if (filteredResult.length > 0) { + setSelectedMeter(filteredResult[0].value); + // enable submit button + setSubmitButtonDisabled(false); + } else { + setSelectedMeter(undefined); + // disable submit button + setSubmitButtonDisabled(true); + }; + }; + + let onComparisonTypeChange = ({ target }) => { + console.log(target.value); + setComparisonType(target.value); + if (target.value === 'year-over-year') { + setBasePeriodBeginsDatetimeDisabled(true); + setBasePeriodEndsDatetimeDisabled(true); + setBasePeriodBeginsDatetime(moment(reportingPeriodBeginsDatetime).subtract(1, 'years')); + setBasePeriodEndsDatetime(moment(reportingPeriodEndsDatetime).subtract(1, 'years')); + } else if (target.value === 'month-on-month') { + setBasePeriodBeginsDatetimeDisabled(true); + setBasePeriodEndsDatetimeDisabled(true); + setBasePeriodBeginsDatetime(moment(reportingPeriodBeginsDatetime).subtract(1, 'months')); + setBasePeriodEndsDatetime(moment(reportingPeriodEndsDatetime).subtract(1, 'months')); + } else if (target.value === 'free-comparison') { + setBasePeriodBeginsDatetimeDisabled(false); + setBasePeriodEndsDatetimeDisabled(false); + } else if (target.value === 'none-comparison') { + setBasePeriodBeginsDatetime(undefined); + setBasePeriodEndsDatetime(undefined); + setBasePeriodBeginsDatetimeDisabled(true); + setBasePeriodEndsDatetimeDisabled(true); + } + }; + + let onBasePeriodBeginsDatetimeChange = (newDateTime) => { + setBasePeriodBeginsDatetime(newDateTime); + }; + + let onBasePeriodEndsDatetimeChange = (newDateTime) => { + setBasePeriodEndsDatetime(newDateTime); + }; + + let onReportingPeriodBeginsDatetimeChange = (newDateTime) => { + setReportingPeriodBeginsDatetime(newDateTime); + if (comparisonType === 'year-over-year') { + setBasePeriodBeginsDatetime(newDateTime.clone().subtract(1, 'years')); + } else if (comparisonType === 'month-on-month') { + setBasePeriodBeginsDatetime(newDateTime.clone().subtract(1, 'months')); + } + }; + + let onReportingPeriodEndsDatetimeChange = (newDateTime) => { + setReportingPeriodEndsDatetime(newDateTime); + if (comparisonType === 'year-over-year') { + setBasePeriodEndsDatetime(newDateTime.clone().subtract(1, 'years')); + } else if (comparisonType === 'month-on-month') { + setBasePeriodEndsDatetime(newDateTime.clone().subtract(1, 'months')); + } + }; + + var getValidBasePeriodBeginsDatetimes = function (currentDate) { + return currentDate.isBefore(moment(basePeriodEndsDatetime, 'MM/DD/YYYY, hh:mm:ss a')); + }; + + var getValidBasePeriodEndsDatetimes = function (currentDate) { + return currentDate.isAfter(moment(basePeriodBeginsDatetime, 'MM/DD/YYYY, hh:mm:ss a')); + }; + + var getValidReportingPeriodBeginsDatetimes = function (currentDate) { + return currentDate.isBefore(moment(reportingPeriodEndsDatetime, 'MM/DD/YYYY, hh:mm:ss a')); + }; + + var getValidReportingPeriodEndsDatetimes = function (currentDate) { + return currentDate.isAfter(moment(reportingPeriodBeginsDatetime, 'MM/DD/YYYY, hh:mm:ss a')); + }; + + // Handler + const handleSubmit = e => { + e.preventDefault(); + console.log('handleSubmit'); + console.log(selectedSpaceID); + console.log(selectedMeter); + console.log(comparisonType); + console.log(periodType); + console.log(basePeriodBeginsDatetime != null ? basePeriodBeginsDatetime.format('YYYY-MM-DDTHH:mm:ss') : undefined); + console.log(basePeriodEndsDatetime != null ? basePeriodEndsDatetime.format('YYYY-MM-DDTHH:mm:ss') : undefined); + console.log(reportingPeriodBeginsDatetime.format('YYYY-MM-DDTHH:mm:ss')); + console.log(reportingPeriodEndsDatetime.format('YYYY-MM-DDTHH:mm:ss')); + + // disable submit button + setSubmitButtonDisabled(true); + // show spinner + setSpinnerHidden(false); + // hide export button + setExportButtonHidden(true) + + // Reinitialize tables + setDetailedDataTableData([]); + + let isResponseOK = false; + fetch(APIBaseURL + '/reports/metercarbon?' + + 'meterid=' + selectedMeter + + '&periodtype=' + periodType + + '&baseperiodstartdatetime=' + (basePeriodBeginsDatetime != null ? basePeriodBeginsDatetime.format('YYYY-MM-DDTHH:mm:ss') : '') + + '&baseperiodenddatetime=' + (basePeriodEndsDatetime != null ? basePeriodEndsDatetime.format('YYYY-MM-DDTHH:mm:ss') : '') + + '&reportingperiodstartdatetime=' + reportingPeriodBeginsDatetime.format('YYYY-MM-DDTHH:mm:ss') + + '&reportingperiodenddatetime=' + reportingPeriodEndsDatetime.format('YYYY-MM-DDTHH:mm:ss'), { + method: 'GET', + headers: { + "Content-type": "application/json", + "User-UUID": getCookieValue('user_uuid'), + "Token": getCookieValue('token') + }, + body: null, + + }).then(response => { + if (response.ok) { + isResponseOK = true; + }; + return response.json(); + }).then(json => { + if (isResponseOK) { + console.log(json) + setMeterEnergyCategory({ + 'name': json['meter']['energy_category_name'], + 'unit': json['meter']['unit_of_measure'] + }); + setReportingPeriodEnergyCarbonRate(parseFloat(json['reporting_period']['increment_rate']*100).toFixed(2) + "%"); + setReportingPeriodEnergyCarbonInCategory(json['reporting_period']['total_in_category']); + setReportingPeriodEnergyConsumptionInTCE(json['reporting_period']['total_in_kgce'] / 1000); + setReportingPeriodEnergyConsumptionInCO2(json['reporting_period']['total_in_kgco2e'] / 1000); + setBasePeriodEnergyCarbonInCategory(json['base_period']['total_in_category']); + + let names = Array(); + names.push({ 'value': 'a0', 'label': json['meter']['energy_category_name'] }); + setMeterLineChartOptions(names); + + let timestamps = { 'a0': [] } + json['reporting_period']['timestamps'].forEach((currentValue, index) => { + timestamps['a0'][index] = currentValue; + }); + setMeterLineChartLabels(timestamps); + + let values = {'a0':[]} + json['reporting_period']['values'].forEach((currentValue, index) => { + values['a0'][index] = currentValue.toFixed(2); + }); + setMeterLineChartData(values) + + names = Array(); + json['parameters']['names'].forEach((currentValue, index) => { + names.push({ 'value': 'a' + index, 'label': currentValue }); + }); + setParameterLineChartOptions(names); + + timestamps = {} + json['parameters']['timestamps'].forEach((currentValue, index) => { + timestamps['a' + index] = currentValue; + }); + setParameterLineChartLabels(timestamps); + + values = {} + json['parameters']['values'].forEach((currentValue, index) => { + values['a' + index] = currentValue; + }); + setParameterLineChartData(values); + + setDetailedDataTableColumns([{ + dataField: 'startdatetime', + text: t('Datetime'), + sort: true + }, { + dataField: 'a0', + text: json['meter']['energy_category_name'] + ' (' + json['meter']['unit_of_measure'] + ')', + sort: true, + formatter: function (decimalValue) { + if (decimalValue !== null) { + return decimalValue.toFixed(2); + } else { + return null; + } + } + }]); + + let detailed_value_list = []; + json['reporting_period']['timestamps'].forEach((currentTimestamp, timestampIndex) => { + let detailed_value = {}; + detailed_value['id'] = timestampIndex; + detailed_value['startdatetime'] = currentTimestamp; + detailed_value['a0'] = json['reporting_period']['values'][timestampIndex]; + detailed_value_list.push(detailed_value); + }); + + let detailed_value = {}; + detailed_value['id'] = detailed_value_list.length; + detailed_value['startdatetime'] = t('Total'); + detailed_value['a0'] = json['reporting_period']['total_in_category']; + detailed_value_list.push(detailed_value); + setDetailedDataTableData(detailed_value_list); + + setExcelBytesBase64(json['excel_bytes_base64']); + + // enable submit button + setSubmitButtonDisabled(false); + // hide spinner + setSpinnerHidden(true); + // show export button + setExportButtonHidden(false); + + } else { + toast.error(json.description) + } + }).catch(err => { + console.log(err); + }); + }; + + const handleExport = e => { + e.preventDefault(); + const mimeType='application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' + const fileName = 'metercarbon.xlsx' + var fileUrl = "data:" + mimeType + ";base64," + excelBytesBase64; + fetch(fileUrl) + .then(response => response.blob()) + .then(blob => { + var link = window.document.createElement("a"); + link.href = window.URL.createObjectURL(blob, { type: mimeType }); + link.download = fileName; + document.body.appendChild(link); + link.click(); + document.body.removeChild(link); + }); + }; + + + return ( + +
+ + {t('Meter Data')}{t('Meter Carbon')} + +
+ + +
+ + + + +
+ + + +
+ + + + + + + setSelectedMeter(target.value)} + > + {filteredMeterList.map((meter, index) => ( + + ))} + + + + + + + + + {comparisonTypeOptions.map((comparisonType, index) => ( + + ))} + + + + + + + setPeriodType(target.value)} + > + {periodTypeOptions.map((periodType, index) => ( + + ))} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

+ + + +
+ + + +

+
+ + +

+ + +
+ +
+
+
+ + + + + + + + + +
+ + + + + + +
+ + + +
+ ); +}; + +export default withTranslation()(withRedirect(MeterCarbon)); diff --git a/web/src/i18n.js b/web/src/i18n.js index 29591c47..8b2f413f 100644 --- a/web/src/i18n.js +++ b/web/src/i18n.js @@ -32,6 +32,7 @@ const resources = { 'Saving': 'Saving', 'Equipment Tracking': 'Equipment Tracking', 'Meter Energy': 'Meter Energy', + 'Meter Carbon': 'Meter Carbon Dioxide Emission', 'Meter Cost': 'Meter Cost', 'Meter Trend': 'Meter Trend', 'Meter Realtime': 'Meter Realtime', @@ -165,6 +166,9 @@ const resources = { 'Base Period Consumption {{ITEM}} {{CATEGORY}} {{VALUE}} {{UNIT}}', 'Child Space Proportion CATEGORY UNIT': 'Child Space Proportion by Energy Category {{CATEGORY}} {{UNIT}}', 'Child Space Total Proportion': 'Child Space Total Proportion', + 'Reporting Period Carbon Dioxide Emissions CATEGORY UNIT': 'Reporting Period Carbon Dioxide Emissions {{CATEGORY}} {{UNIT}}', + 'Reporting Period Carbon Dioxide Emissions CATEGORY VALUE UNIT': 'Reporting Period Carbon Dioxide Emissions {{CATEGORY}} {{VALUE}} {{UNIT}}', + 'Base Period Carbon Dioxide Emissions CATEGORY VALUE UNIT': 'Base Period Carbon Dioxide Emissions {{CATEGORY}} {{VALUE}} {{UNIT}}', 'Reporting Period Costs CATEGORY UNIT': 'Reporting Period Costs {{CATEGORY}} {{UNIT}}', 'Reporting Period Costs CATEGORY VALUE UNIT': 'Reporting Period Costs {{CATEGORY}} {{VALUE}} {{UNIT}}', 'Base Period Costs CATEGORY VALUE UNIT': 'Base Period Costs {{CATEGORY}} {{VALUE}} {{UNIT}}', @@ -812,6 +816,7 @@ const resources = { 'Saving': 'Sparen', 'Equipment Tracking': 'Ausrüstung Datei', 'Meter Energy': 'Meter Energie ', + 'Meter Carbon': 'Meter Kohlendioxidemission', 'Meter Cost': 'Meter Kosten', 'Meter Trend': 'Meter Trend', 'Meter Realtime': 'Meter Echtzeit', @@ -947,6 +952,9 @@ const resources = { 'Verbrauch des Basiszeitraums {{ITEM}} {{CATEGORY}} {{VALUE}} {{UNIT}}', 'Child Space Proportion CATEGORY UNIT': 'Anteil des Teil Platz nach Energiekategorie {{CATEGORY}} {{UNIT}}', 'Child Space Total Proportion': 'Anteil des Teil Platz Gesamtanteil', + 'Reporting Period Carbon Dioxide Emissions CATEGORY UNIT': 'Berichtszeitraum Kohlendioxidemissionen {{CATEGORY}} {{UNIT}}', + 'Reporting Period Carbon Dioxide Emissions CATEGORY VALUE UNIT': 'Berichtszeitraum Kohlendioxidemissionen {{CATEGORY}} {{VALUE}} {{UNIT}}', + 'Base Period Carbon Dioxide Emissions CATEGORY VALUE UNIT': 'Basiszeitraum Kohlendioxidemissionen {{CATEGORY}} {{VALUE}} {{UNIT}}', 'Reporting Period Costs CATEGORY UNIT': 'Berichtszeitraumkosten {{CATEGORY}} {{UNIT}}', 'Reporting Period Costs CATEGORY VALUE UNIT': 'Berichtszeitraumkosten {{CATEGORY}} {{VALUE}} {{UNIT}}', 'Base Period Costs CATEGORY VALUE UNIT': 'Kosten des Basiszeitraums {{CATEGORY}} {{VALUE}} {{UNIT}}', @@ -1602,6 +1610,7 @@ const resources = { 'Saving': '节能分析', 'Equipment Tracking': '设备台账', 'Meter Energy': '计量表能耗分析', + 'Meter Carbon': '计量表碳排放分析', 'Meter Cost': '计量表成本分析', 'Meter Trend': '计量表趋势分析', 'Meter Realtime': '计量表实时分析', @@ -1728,6 +1737,9 @@ const resources = { 'Base Period Consumption ITEM CATEGORY VALUE UNIT': '基准期消耗 {{ITEM}} {{CATEGORY}} {{VALUE}} {{UNIT}}', 'Child Space Proportion CATEGORY UNIT': '子空间分类占比 {{CATEGORY}} {{UNIT}}', 'Child Space Total Proportion': '子空间总计占比', + 'Reporting Period Carbon Dioxide Emissions CATEGORY UNIT': '报告期二氧化碳排放 {{CATEGORY}} {{UNIT}}', + 'Reporting Period Carbon Dioxide Emissions CATEGORY VALUE UNIT': '报告期二氧化碳排放 {{CATEGORY}} {{VALUE}} {{UNIT}}', + 'Base Period Carbon Dioxide Emissions CATEGORY VALUE UNIT': '基准期二氧化碳排放 {{CATEGORY}} {{VALUE}} {{UNIT}}', 'Reporting Period Costs CATEGORY UNIT': '报告期成本 {{CATEGORY}} {{UNIT}}', 'Reporting Period Costs CATEGORY VALUE UNIT': '报告期成本 {{CATEGORY}} {{VALUE}} {{UNIT}}', 'Base Period Costs CATEGORY VALUE UNIT': '基准期成本 {{CATEGORY}} {{VALUE}} {{UNIT}}', diff --git a/web/src/layouts/MyEMSRoutes.js b/web/src/layouts/MyEMSRoutes.js index e8c17674..b690cbda 100644 --- a/web/src/layouts/MyEMSRoutes.js +++ b/web/src/layouts/MyEMSRoutes.js @@ -126,6 +126,7 @@ import EquipmentStatistics from '../components/MyEMS/Equipment/EquipmentStatisti import EquipmentTracking from '../components/MyEMS/Equipment/EquipmentTracking'; // Meter import MeterBatch from '../components/MyEMS/Meter/MeterBatch'; +import MeterCarbon from '../components/MyEMS/Meter/MeterCarbon'; import MeterCost from '../components/MyEMS/Meter/MeterCost'; import MeterEnergy from '../components/MyEMS/Meter/MeterEnergy'; import MeterRealtime from '../components/MyEMS/Meter/MeterRealtime'; @@ -365,6 +366,7 @@ const MyEMSRoutes = () => ( {/*Meter*/} + diff --git a/web/src/routes.js b/web/src/routes.js index 2774f061..fa33dfc4 100644 --- a/web/src/routes.js +++ b/web/src/routes.js @@ -358,6 +358,7 @@ export const meterRoutes = { icon: 'chart-pie', children: [ { to: '/meter/meterenergy', name: 'Meter Energy' }, + { to: '/meter/metercarbon', name: 'Meter Carbon' }, { to: '/meter/metercost', name: 'Meter Cost' }, { to: '/meter/metertrend', name: 'Meter Trend' }, { to: '/meter/meterrealtime', name: 'Meter Realtime' }, @@ -448,7 +449,7 @@ export const auxiliarySystemRoutes = { export const fddRoutes = { name: 'Fault Detection & Diagnostics', to: '/fdd', - icon: 'chart-pie', + icon: 'bell', children: [ { to: '/fdd/space', name: 'Space Faults Data' }, { to: '/fdd/equipment', name: 'Equipment Faults Data' },