add the ticket route

pull/141/MERGE^2
hyh123a 2022-04-16 18:30:41 +08:00
parent 56bfd7ac81
commit 097aae2322
8 changed files with 1476 additions and 498 deletions

View File

@ -0,0 +1,361 @@
import React, { createRef, Fragment, useEffect, useState } from 'react';
import {
Breadcrumb,
BreadcrumbItem,
Card,
CardBody,
Col,
DropdownItem,
DropdownMenu,
DropdownToggle,
Form,
FormGroup,
Input,
Label,
Media,
Row,
UncontrolledDropdown,
Spinner
} from 'reactstrap';
import Cascader from 'rc-cascader';
import loadable from '@loadable/component';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Link } from 'react-router-dom';
import Flex from '../../common/Flex';
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';
const TicketAgent = ({ setRedirect, setRedirectUrl, t }) => {
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);
}
});
let table = createRef();
// State
const [selectedSpaceName, setSelectedSpaceName] = useState(undefined);
const [cascaderOptions, setCascaderOptions] = useState(undefined);
const [equipmentList, setEquipmentList] = useState([]);
const [spinnerHidden, setSpinnerHidden] = useState(false);
const [exportButtonHidden, setExportButtonHidden] = useState(true);
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));
let selectedSpaceID = [json[0]].map(o => o.value);
// begin of getting equipment list
let isSecondResponseOK = false;
fetch(APIBaseURL + '/reports/TicketAgent?' + 'spaceid=' + selectedSpaceID, {
method: 'GET',
headers: {
'Content-type': 'application/json',
'User-UUID': getCookieValue('user_uuid'),
Token: getCookieValue('token')
},
body: null
})
.then(response => {
if (response.ok) {
isSecondResponseOK = true;
}
return response.json();
})
.then(json => {
if (isSecondResponseOK) {
let json_equipments = JSON.parse(
JSON.stringify([json['equipments']])
.split('"id":')
.join('"value":')
.split('"name":')
.join('"label":')
);
console.log(json);
let equipments = [];
json_equipments[0].forEach((currentValue, index) => {
equipments.push({
key: index,
id: currentValue['id'],
name: currentValue['equipment_name'],
space: currentValue['space_name'],
costcenter: currentValue['cost_center_name'],
description: currentValue['description']
});
});
setEquipmentList(equipments);
setExcelBytesBase64(json['excel_bytes_base64']);
// hide spinner
setSpinnerHidden(true);
// show export button
setExportButtonHidden(false);
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
// end of getting equipment list
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
}, []);
const DetailedDataTable = loadable(() => import('../common/DetailedDataTable'));
const nameFormatter = (dataField, { name }) => (
<Link to="#">
<Media tag={Flex} align="center">
<Media body className="ml-2">
<h5 className="mb-0 fs--1">{name}</h5>
</Media>
</Media>
</Link>
);
const actionFormatter = (dataField, { id }) => (
// Control your row with this id
<UncontrolledDropdown>
<DropdownToggle color="link" size="sm" className="text-600 btn-reveal mr-3">
<FontAwesomeIcon icon="ellipsis-h" className="fs--1" />
</DropdownToggle>
<DropdownMenu right className="border py-2">
<DropdownItem onClick={() => console.log('Edit: ', id)}>{t('Edit Equipment')}</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
);
const columns = [
{
key: 'a0',
dataField: 'equipmentname',
headerClasses: 'border-0',
text: t('Name'),
classes: 'border-0 py-2 align-middle',
formatter: nameFormatter,
sort: true
},
{
key: 'a1',
dataField: 'space',
headerClasses: 'border-0',
text: t('Space'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a2',
dataField: 'costcenter',
headerClasses: 'border-0',
text: t('Cost Center'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a3',
dataField: 'description',
headerClasses: 'border-0',
text: t('Description'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a4',
dataField: '',
headerClasses: 'border-0',
text: '',
classes: 'border-0 py-2 align-middle',
formatter: actionFormatter,
align: 'right'
}
];
const labelClasses = 'ls text-uppercase text-600 font-weight-semi-bold mb-0';
let onSpaceCascaderChange = (value, selectedOptions) => {
setSelectedSpaceName(selectedOptions.map(o => o.label).join('/'));
let selectedSpaceID = value[value.length - 1];
// show spinner
setSpinnerHidden(false);
// hide export button
setExportButtonHidden(true);
// begin of getting equipment list
let isResponseOK = false;
fetch(APIBaseURL + '/reports/TicketAgent?' + 'spaceid=' + selectedSpaceID, {
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) {
let json_equipments = JSON.parse(
JSON.stringify([json['equipments']])
.split('"id":')
.join('"value":')
.split('"name":')
.join('"label":')
);
console.log(json);
let equipments = [];
json_equipments[0].forEach((currentValue, index) => {
equipments.push({
key: index,
id: currentValue['id'],
name: currentValue['equipment_name'],
space: currentValue['space_name'],
costcenter: currentValue['cost_center_name'],
description: currentValue['description']
});
});
setEquipmentList(equipments);
setExcelBytesBase64(json['excel_bytes_base64']);
// hide spinner
setSpinnerHidden(true);
// show export button
setExportButtonHidden(false);
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
// end of getting equipment list
};
const handleExport = e => {
e.preventDefault();
const mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
const fileName = 'TicketAgent.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 (
<Fragment>
<div>
<Breadcrumb>
<BreadcrumbItem>{t('Ticket')}</BreadcrumbItem>
<BreadcrumbItem active>{t('My Agent')}</BreadcrumbItem>
</Breadcrumb>
</div>
<Card className="bg-light mb-3">
<CardBody className="p-3">
<Form>
<Row form>
<Col xs={6} sm={3}>
<FormGroup className="form-group">
<Label className={labelClasses} for="space">
{t('Ticket List')}
</Label>
<br />
<Cascader
options={cascaderOptions}
onChange={onSpaceCascaderChange}
changeOnSelect
expandTrigger="hover"
>
<Input value={selectedSpaceName || ''} readOnly />
</Cascader>
</FormGroup>
</Col>
<Col xs="auto">
<FormGroup>
<br />
<Spinner color="primary" hidden={spinnerHidden} />
</FormGroup>
</Col>
<Col xs="auto">
<br />
<ButtonIcon
icon="external-link-alt"
transform="shrink-3 down-2"
color="falcon-default"
hidden={exportButtonHidden}
onClick={handleExport}
>
{t('Export')}
</ButtonIcon>
</Col>
</Row>
</Form>
</CardBody>
</Card>
<DetailedDataTable data={equipmentList} title={t('Ticket List')} columns={columns} pagesize={10} />
</Fragment>
);
};
export default withTranslation()(withRedirect(TicketAgent));

View File

@ -0,0 +1,361 @@
import React, { createRef, Fragment, useEffect, useState } from 'react';
import {
Breadcrumb,
BreadcrumbItem,
Card,
CardBody,
Col,
DropdownItem,
DropdownMenu,
DropdownToggle,
Form,
FormGroup,
Input,
Label,
Media,
Row,
UncontrolledDropdown,
Spinner
} from 'reactstrap';
import Cascader from 'rc-cascader';
import loadable from '@loadable/component';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Link } from 'react-router-dom';
import Flex from '../../common/Flex';
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';
const TicketApplication = ({ setRedirect, setRedirectUrl, t }) => {
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);
}
});
let table = createRef();
// State
const [selectedSpaceName, setSelectedSpaceName] = useState(undefined);
const [cascaderOptions, setCascaderOptions] = useState(undefined);
const [equipmentList, setEquipmentList] = useState([]);
const [spinnerHidden, setSpinnerHidden] = useState(false);
const [exportButtonHidden, setExportButtonHidden] = useState(true);
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));
let selectedSpaceID = [json[0]].map(o => o.value);
// begin of getting equipment list
let isSecondResponseOK = false;
fetch(APIBaseURL + '/reports/Ticket?' + 'spaceid=' + selectedSpaceID, {
method: 'GET',
headers: {
'Content-type': 'application/json',
'User-UUID': getCookieValue('user_uuid'),
Token: getCookieValue('token')
},
body: null
})
.then(response => {
if (response.ok) {
isSecondResponseOK = true;
}
return response.json();
})
.then(json => {
if (isSecondResponseOK) {
let json_equipments = JSON.parse(
JSON.stringify([json['equipments']])
.split('"id":')
.join('"value":')
.split('"name":')
.join('"label":')
);
console.log(json);
let equipments = [];
json_equipments[0].forEach((currentValue, index) => {
equipments.push({
key: index,
id: currentValue['id'],
name: currentValue['equipment_name'],
space: currentValue['space_name'],
costcenter: currentValue['cost_center_name'],
description: currentValue['description']
});
});
setEquipmentList(equipments);
setExcelBytesBase64(json['excel_bytes_base64']);
// hide spinner
setSpinnerHidden(true);
// show export button
setExportButtonHidden(false);
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
// end of getting equipment list
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
}, []);
const DetailedDataTable = loadable(() => import('../common/DetailedDataTable'));
const nameFormatter = (dataField, { name }) => (
<Link to="#">
<Media tag={Flex} align="center">
<Media body className="ml-2">
<h5 className="mb-0 fs--1">{name}</h5>
</Media>
</Media>
</Link>
);
const actionFormatter = (dataField, { id }) => (
// Control your row with this id
<UncontrolledDropdown>
<DropdownToggle color="link" size="sm" className="text-600 btn-reveal mr-3">
<FontAwesomeIcon icon="ellipsis-h" className="fs--1" />
</DropdownToggle>
<DropdownMenu right className="border py-2">
<DropdownItem onClick={() => console.log('Edit: ', id)}>{t('Edit Equipment')}</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
);
const columns = [
{
key: 'a0',
dataField: 'equipmentname',
headerClasses: 'border-0',
text: t('Name'),
classes: 'border-0 py-2 align-middle',
formatter: nameFormatter,
sort: true
},
{
key: 'a1',
dataField: 'space',
headerClasses: 'border-0',
text: t('Space'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a2',
dataField: 'costcenter',
headerClasses: 'border-0',
text: t('Cost Center'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a3',
dataField: 'description',
headerClasses: 'border-0',
text: t('Description'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a4',
dataField: '',
headerClasses: 'border-0',
text: '',
classes: 'border-0 py-2 align-middle',
formatter: actionFormatter,
align: 'right'
}
];
const labelClasses = 'ls text-uppercase text-600 font-weight-semi-bold mb-0';
let onSpaceCascaderChange = (value, selectedOptions) => {
setSelectedSpaceName(selectedOptions.map(o => o.label).join('/'));
let selectedSpaceID = value[value.length - 1];
// show spinner
setSpinnerHidden(false);
// hide export button
setExportButtonHidden(true);
// begin of getting equipment list
let isResponseOK = false;
fetch(APIBaseURL + '/reports/Ticket?' + 'spaceid=' + selectedSpaceID, {
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) {
let json_equipments = JSON.parse(
JSON.stringify([json['equipments']])
.split('"id":')
.join('"value":')
.split('"name":')
.join('"label":')
);
console.log(json);
let equipments = [];
json_equipments[0].forEach((currentValue, index) => {
equipments.push({
key: index,
id: currentValue['id'],
name: currentValue['equipment_name'],
space: currentValue['space_name'],
costcenter: currentValue['cost_center_name'],
description: currentValue['description']
});
});
setEquipmentList(equipments);
setExcelBytesBase64(json['excel_bytes_base64']);
// hide spinner
setSpinnerHidden(true);
// show export button
setExportButtonHidden(false);
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
// end of getting equipment list
};
const handleExport = e => {
e.preventDefault();
const mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
const fileName = 'Ticket.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 (
<Fragment>
<div>
<Breadcrumb>
<BreadcrumbItem>{t('Ticket')}</BreadcrumbItem>
<BreadcrumbItem active>{t('My Application')}</BreadcrumbItem>
</Breadcrumb>
</div>
<Card className="bg-light mb-3">
<CardBody className="p-3">
<Form>
<Row form>
<Col xs={6} sm={3}>
<FormGroup className="form-group">
<Label className={labelClasses} for="space">
{t('Ticket List')}
</Label>
<br />
<Cascader
options={cascaderOptions}
onChange={onSpaceCascaderChange}
changeOnSelect
expandTrigger="hover"
>
<Input value={selectedSpaceName || ''} readOnly />
</Cascader>
</FormGroup>
</Col>
<Col xs="auto">
<FormGroup>
<br />
<Spinner color="primary" hidden={spinnerHidden} />
</FormGroup>
</Col>
<Col xs="auto">
<br />
<ButtonIcon
icon="external-link-alt"
transform="shrink-3 down-2"
color="falcon-default"
hidden={exportButtonHidden}
onClick={handleExport}
>
{t('Export')}
</ButtonIcon>
</Col>
</Row>
</Form>
</CardBody>
</Card>
<DetailedDataTable data={equipmentList} title={t('Ticket List')} columns={columns} pagesize={10} />
</Fragment>
);
};
export default withTranslation()(withRedirect(TicketApplication));

View File

@ -0,0 +1,361 @@
import React, { createRef, Fragment, useEffect, useState } from 'react';
import {
Breadcrumb,
BreadcrumbItem,
Card,
CardBody,
Col,
DropdownItem,
DropdownMenu,
DropdownToggle,
Form,
FormGroup,
Input,
Label,
Media,
Row,
UncontrolledDropdown,
Spinner
} from 'reactstrap';
import Cascader from 'rc-cascader';
import loadable from '@loadable/component';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Link } from 'react-router-dom';
import Flex from '../../common/Flex';
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';
const TicketIntervention = ({ setRedirect, setRedirectUrl, t }) => {
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);
}
});
let table = createRef();
// State
const [selectedSpaceName, setSelectedSpaceName] = useState(undefined);
const [cascaderOptions, setCascaderOptions] = useState(undefined);
const [equipmentList, setEquipmentList] = useState([]);
const [spinnerHidden, setSpinnerHidden] = useState(false);
const [exportButtonHidden, setExportButtonHidden] = useState(true);
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));
let selectedSpaceID = [json[0]].map(o => o.value);
// begin of getting equipment list
let isSecondResponseOK = false;
fetch(APIBaseURL + '/reports/Ticket?' + 'spaceid=' + selectedSpaceID, {
method: 'GET',
headers: {
'Content-type': 'application/json',
'User-UUID': getCookieValue('user_uuid'),
Token: getCookieValue('token')
},
body: null
})
.then(response => {
if (response.ok) {
isSecondResponseOK = true;
}
return response.json();
})
.then(json => {
if (isSecondResponseOK) {
let json_equipments = JSON.parse(
JSON.stringify([json['equipments']])
.split('"id":')
.join('"value":')
.split('"name":')
.join('"label":')
);
console.log(json);
let equipments = [];
json_equipments[0].forEach((currentValue, index) => {
equipments.push({
key: index,
id: currentValue['id'],
name: currentValue['equipment_name'],
space: currentValue['space_name'],
costcenter: currentValue['cost_center_name'],
description: currentValue['description']
});
});
setEquipmentList(equipments);
setExcelBytesBase64(json['excel_bytes_base64']);
// hide spinner
setSpinnerHidden(true);
// show export button
setExportButtonHidden(false);
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
// end of getting equipment list
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
}, []);
const DetailedDataTable = loadable(() => import('../common/DetailedDataTable'));
const nameFormatter = (dataField, { name }) => (
<Link to="#">
<Media tag={Flex} align="center">
<Media body className="ml-2">
<h5 className="mb-0 fs--1">{name}</h5>
</Media>
</Media>
</Link>
);
const actionFormatter = (dataField, { id }) => (
// Control your row with this id
<UncontrolledDropdown>
<DropdownToggle color="link" size="sm" className="text-600 btn-reveal mr-3">
<FontAwesomeIcon icon="ellipsis-h" className="fs--1" />
</DropdownToggle>
<DropdownMenu right className="border py-2">
<DropdownItem onClick={() => console.log('Edit: ', id)}>{t('Edit Equipment')}</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
);
const columns = [
{
key: 'a0',
dataField: 'equipmentname',
headerClasses: 'border-0',
text: t('Name'),
classes: 'border-0 py-2 align-middle',
formatter: nameFormatter,
sort: true
},
{
key: 'a1',
dataField: 'space',
headerClasses: 'border-0',
text: t('Space'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a2',
dataField: 'costcenter',
headerClasses: 'border-0',
text: t('Cost Center'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a3',
dataField: 'description',
headerClasses: 'border-0',
text: t('Description'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a4',
dataField: '',
headerClasses: 'border-0',
text: '',
classes: 'border-0 py-2 align-middle',
formatter: actionFormatter,
align: 'right'
}
];
const labelClasses = 'ls text-uppercase text-600 font-weight-semi-bold mb-0';
let onSpaceCascaderChange = (value, selectedOptions) => {
setSelectedSpaceName(selectedOptions.map(o => o.label).join('/'));
let selectedSpaceID = value[value.length - 1];
// show spinner
setSpinnerHidden(false);
// hide export button
setExportButtonHidden(true);
// begin of getting equipment list
let isResponseOK = false;
fetch(APIBaseURL + '/reports/Ticket?' + 'spaceid=' + selectedSpaceID, {
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) {
let json_equipments = JSON.parse(
JSON.stringify([json['equipments']])
.split('"id":')
.join('"value":')
.split('"name":')
.join('"label":')
);
console.log(json);
let equipments = [];
json_equipments[0].forEach((currentValue, index) => {
equipments.push({
key: index,
id: currentValue['id'],
name: currentValue['equipment_name'],
space: currentValue['space_name'],
costcenter: currentValue['cost_center_name'],
description: currentValue['description']
});
});
setEquipmentList(equipments);
setExcelBytesBase64(json['excel_bytes_base64']);
// hide spinner
setSpinnerHidden(true);
// show export button
setExportButtonHidden(false);
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
// end of getting equipment list
};
const handleExport = e => {
e.preventDefault();
const mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
const fileName = 'Ticket.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 (
<Fragment>
<div>
<Breadcrumb>
<BreadcrumbItem>{t('Ticket')}</BreadcrumbItem>
<BreadcrumbItem active>{t('Ticket Intervention')}</BreadcrumbItem>
</Breadcrumb>
</div>
<Card className="bg-light mb-3">
<CardBody className="p-3">
<Form>
<Row form>
<Col xs={6} sm={3}>
<FormGroup className="form-group">
<Label className={labelClasses} for="space">
{t('Ticket List')}
</Label>
<br />
<Cascader
options={cascaderOptions}
onChange={onSpaceCascaderChange}
changeOnSelect
expandTrigger="hover"
>
<Input value={selectedSpaceName || ''} readOnly />
</Cascader>
</FormGroup>
</Col>
<Col xs="auto">
<FormGroup>
<br />
<Spinner color="primary" hidden={spinnerHidden} />
</FormGroup>
</Col>
<Col xs="auto">
<br />
<ButtonIcon
icon="external-link-alt"
transform="shrink-3 down-2"
color="falcon-default"
hidden={exportButtonHidden}
onClick={handleExport}
>
{t('Export')}
</ButtonIcon>
</Col>
</Row>
</Form>
</CardBody>
</Card>
<DetailedDataTable data={equipmentList} title={t('Ticket List')} columns={columns} pagesize={10} />
</Fragment>
);
};
export default withTranslation()(withRedirect(TicketIntervention));

View File

@ -0,0 +1,361 @@
import React, { createRef, Fragment, useEffect, useState } from 'react';
import {
Breadcrumb,
BreadcrumbItem,
Card,
CardBody,
Col,
DropdownItem,
DropdownMenu,
DropdownToggle,
Form,
FormGroup,
Input,
Label,
Media,
Row,
UncontrolledDropdown,
Spinner
} from 'reactstrap';
import Cascader from 'rc-cascader';
import loadable from '@loadable/component';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Link } from 'react-router-dom';
import Flex from '../../common/Flex';
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';
const TicketList = ({ setRedirect, setRedirectUrl, t }) => {
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);
}
});
let table = createRef();
// State
const [selectedSpaceName, setSelectedSpaceName] = useState(undefined);
const [cascaderOptions, setCascaderOptions] = useState(undefined);
const [equipmentList, setEquipmentList] = useState([]);
const [spinnerHidden, setSpinnerHidden] = useState(false);
const [exportButtonHidden, setExportButtonHidden] = useState(true);
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));
let selectedSpaceID = [json[0]].map(o => o.value);
// begin of getting equipment list
let isSecondResponseOK = false;
fetch(APIBaseURL + '/reports/Ticket?' + 'spaceid=' + selectedSpaceID, {
method: 'GET',
headers: {
'Content-type': 'application/json',
'User-UUID': getCookieValue('user_uuid'),
Token: getCookieValue('token')
},
body: null
})
.then(response => {
if (response.ok) {
isSecondResponseOK = true;
}
return response.json();
})
.then(json => {
if (isSecondResponseOK) {
let json_equipments = JSON.parse(
JSON.stringify([json['equipments']])
.split('"id":')
.join('"value":')
.split('"name":')
.join('"label":')
);
console.log(json);
let equipments = [];
json_equipments[0].forEach((currentValue, index) => {
equipments.push({
key: index,
id: currentValue['id'],
name: currentValue['equipment_name'],
space: currentValue['space_name'],
costcenter: currentValue['cost_center_name'],
description: currentValue['description']
});
});
setEquipmentList(equipments);
setExcelBytesBase64(json['excel_bytes_base64']);
// hide spinner
setSpinnerHidden(true);
// show export button
setExportButtonHidden(false);
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
// end of getting equipment list
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
}, []);
const DetailedDataTable = loadable(() => import('../common/DetailedDataTable'));
const nameFormatter = (dataField, { name }) => (
<Link to="#">
<Media tag={Flex} align="center">
<Media body className="ml-2">
<h5 className="mb-0 fs--1">{name}</h5>
</Media>
</Media>
</Link>
);
const actionFormatter = (dataField, { id }) => (
// Control your row with this id
<UncontrolledDropdown>
<DropdownToggle color="link" size="sm" className="text-600 btn-reveal mr-3">
<FontAwesomeIcon icon="ellipsis-h" className="fs--1" />
</DropdownToggle>
<DropdownMenu right className="border py-2">
<DropdownItem onClick={() => console.log('Edit: ', id)}>{t('Edit Equipment')}</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
);
const columns = [
{
key: 'a0',
dataField: 'equipmentname',
headerClasses: 'border-0',
text: t('Name'),
classes: 'border-0 py-2 align-middle',
formatter: nameFormatter,
sort: true
},
{
key: 'a1',
dataField: 'space',
headerClasses: 'border-0',
text: t('Space'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a2',
dataField: 'costcenter',
headerClasses: 'border-0',
text: t('Cost Center'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a3',
dataField: 'description',
headerClasses: 'border-0',
text: t('Description'),
classes: 'border-0 py-2 align-middle',
sort: true
},
{
key: 'a4',
dataField: '',
headerClasses: 'border-0',
text: '',
classes: 'border-0 py-2 align-middle',
formatter: actionFormatter,
align: 'right'
}
];
const labelClasses = 'ls text-uppercase text-600 font-weight-semi-bold mb-0';
let onSpaceCascaderChange = (value, selectedOptions) => {
setSelectedSpaceName(selectedOptions.map(o => o.label).join('/'));
let selectedSpaceID = value[value.length - 1];
// show spinner
setSpinnerHidden(false);
// hide export button
setExportButtonHidden(true);
// begin of getting equipment list
let isResponseOK = false;
fetch(APIBaseURL + '/reports/Ticket?' + 'spaceid=' + selectedSpaceID, {
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) {
let json_equipments = JSON.parse(
JSON.stringify([json['equipments']])
.split('"id":')
.join('"value":')
.split('"name":')
.join('"label":')
);
console.log(json);
let equipments = [];
json_equipments[0].forEach((currentValue, index) => {
equipments.push({
key: index,
id: currentValue['id'],
name: currentValue['equipment_name'],
space: currentValue['space_name'],
costcenter: currentValue['cost_center_name'],
description: currentValue['description']
});
});
setEquipmentList(equipments);
setExcelBytesBase64(json['excel_bytes_base64']);
// hide spinner
setSpinnerHidden(true);
// show export button
setExportButtonHidden(false);
} else {
toast.error(json.description);
}
})
.catch(err => {
console.log(err);
});
// end of getting equipment list
};
const handleExport = e => {
e.preventDefault();
const mimeType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';
const fileName = 'Ticket.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 (
<Fragment>
<div>
<Breadcrumb>
<BreadcrumbItem>{t('Ticket')}</BreadcrumbItem>
<BreadcrumbItem active>{t('Ticket List')}</BreadcrumbItem>
</Breadcrumb>
</div>
<Card className="bg-light mb-3">
<CardBody className="p-3">
<Form>
<Row form>
<Col xs={6} sm={3}>
<FormGroup className="form-group">
<Label className={labelClasses} for="space">
{t('Ticket List')}
</Label>
<br />
<Cascader
options={cascaderOptions}
onChange={onSpaceCascaderChange}
changeOnSelect
expandTrigger="hover"
>
<Input value={selectedSpaceName || ''} readOnly />
</Cascader>
</FormGroup>
</Col>
<Col xs="auto">
<FormGroup>
<br />
<Spinner color="primary" hidden={spinnerHidden} />
</FormGroup>
</Col>
<Col xs="auto">
<br />
<ButtonIcon
icon="external-link-alt"
transform="shrink-3 down-2"
color="falcon-default"
hidden={exportButtonHidden}
onClick={handleExport}
>
{t('Export')}
</ButtonIcon>
</Col>
</Row>
</Form>
</CardBody>
</Card>
<DetailedDataTable data={equipmentList} title={t('Ticket List')} columns={columns} pagesize={10} />
</Fragment>
);
};
export default withTranslation()(withRedirect(TicketList));

View File

@ -1,492 +0,0 @@
import React, { Fragment, useEffect, useState } from 'react';
import CountUp from 'react-countup';
import {
Col,
Row,
Spinner, } from 'reactstrap';
import CardSummary from '../common/CardSummary';
import LineChart from '../common/LineChart';
import { toast } from 'react-toastify';
import SharePie from '../common/SharePie';
import loadable from '@loadable/component';
import { getCookieValue, createCookie } from '../../../helpers/utils';
import withRedirect from '../../../hoc/withRedirect';
import { withTranslation } from 'react-i18next';
import moment from 'moment';
import { APIBaseURL } from '../../../config';
import uuid from 'uuid/v1';
const ChildSpacesTable = loadable(() => import('../common/ChildSpacesTable'));
const Workflow = ({ setRedirect, setRedirectUrl, t }) => {
let current_moment = moment();
const [fetchSuccess, setFetchSuccess] = useState(false);
const [periodType, setPeriodType] = useState('monthly');
const [basePeriodBeginsDatetime, setBasePeriodBeginsDatetime] = useState(current_moment.clone().subtract(1, 'years').startOf('year'));
const [basePeriodEndsDatetime, setBasePeriodEndsDatetime] = useState(current_moment.clone().subtract(1, 'years'));
const [reportingPeriodBeginsDatetime, setReportingPeriodBeginsDatetime] = useState(current_moment.clone().startOf('year'));
const [reportingPeriodEndsDatetime, setReportingPeriodEndsDatetime] = useState(current_moment);
const [spinnerHidden, setSpinnerHidden] = useState(false);
//Results
const [costShareData, setCostShareData] = useState([]);
const [timeOfUseShareData, setTimeOfUseShareData] = useState([]);
const [TCEShareData, setTCEShareData] = useState([]);
const [TCO2EShareData, setTCO2EShareData] = useState([]);
const [thisYearInputCardSummaryList, setThisYearInputCardSummaryList] = useState([]);
const [thisYearCostCardSummaryList, setThisYearCostCardSummaryList] = useState([]);
const [lastYearInputCardSummaryList, setLastYearInputCardSummaryList] = useState([]);
const [lastYearCostCardSummaryList, setLastYearCostCardSummaryList] = useState([]);
const [totalInTCE, setTotalInTCE] = useState({});
const [totalInTCO2E, setTotalInTCO2E] = useState({});
const [spaceInputLineChartLabels, setSpaceInputLineChartLabels] = useState([]);
const [spaceInputLineChartData, setSpaceInputLineChartData] = useState({});
const [spaceInputLineChartOptions, setSpaceInputLineChartOptions] = useState([]);
const [spaceCostLineChartLabels, setSpaceCostLineChartLabels] = useState([]);
const [spaceCostLineChartData, setSpaceCostLineChartData] = useState({});
const [spaceCostLineChartOptions, setSpaceCostLineChartOptions] = useState([]);
const [detailedDataTableData, setDetailedDataTableData] = useState([]);
const [detailedDataTableColumns, setDetailedDataTableColumns] = useState(
[{dataField: 'startdatetime', text: t('Datetime'), sort: true}]);
const [childSpacesTableData, setChildSpacesTableData] = useState([]);
const [childSpacesTableColumns, setChildSpacesTableColumns] = useState(
[{dataField: 'name', text: t('Child Spaces'), sort: true }]);
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');
console.log(is_logged_in);
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);
let isResponseOK = false;
if (!fetchSuccess) {
toast(
<Fragment>
{t("Welcome to MyEMS")}!<br />
{t("An Industry Leading Open Source Energy Management System")}
</Fragment>
);
fetch(APIBaseURL + '/reports/workflow?' +
'useruuid=' + user_uuid +
'&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);
setFetchSuccess(true);
// hide spinner
setSpinnerHidden(true);
let thisYearInputCardSummaryArray = []
json['reporting_period_input']['names'].forEach((currentValue, index) => {
let cardSummaryItem = {}
cardSummaryItem['name'] = json['reporting_period_input']['names'][index];
cardSummaryItem['unit'] = json['reporting_period_input']['units'][index];
cardSummaryItem['subtotal'] = json['reporting_period_input']['subtotals'][index];
cardSummaryItem['increment_rate'] = parseFloat(json['reporting_period_input']['increment_rates'][index] * 100).toFixed(2) + "%";
cardSummaryItem['subtotal_per_unit_area'] = json['reporting_period_input']['subtotals_per_unit_area'][index];
thisYearInputCardSummaryArray.push(cardSummaryItem);
});
setThisYearInputCardSummaryList(thisYearInputCardSummaryArray);
let thisYearCostCardSummaryArray = []
json['reporting_period_cost']['names'].forEach((currentValue, index) => {
let cardSummaryItem = {}
cardSummaryItem['name'] = json['reporting_period_cost']['names'][index];
cardSummaryItem['unit'] = json['reporting_period_cost']['units'][index];
cardSummaryItem['subtotal'] = json['reporting_period_cost']['subtotals'][index];
cardSummaryItem['increment_rate'] = parseFloat(json['reporting_period_cost']['increment_rates'][index] * 100).toFixed(2) + "%";
cardSummaryItem['subtotal_per_unit_area'] = json['reporting_period_cost']['subtotals_per_unit_area'][index];
thisYearCostCardSummaryArray.push(cardSummaryItem);
});
setThisYearCostCardSummaryList(thisYearCostCardSummaryArray);
let lastYearInputCardSummaryArray = []
json['base_period_input']['names'].forEach((currentValue, index) => {
let cardSummaryItem = {}
cardSummaryItem['name'] = json['base_period_input']['names'][index];
cardSummaryItem['unit'] = json['base_period_input']['units'][index];
cardSummaryItem['subtotal'] = json['base_period_input']['subtotals'][index];
cardSummaryItem['increment_rate'] = null;
cardSummaryItem['subtotal_per_unit_area'] = json['base_period_input']['subtotals_per_unit_area'][index];
lastYearInputCardSummaryArray.push(cardSummaryItem);
});
setLastYearInputCardSummaryList(lastYearInputCardSummaryArray);
let lastYearCostCardSummaryArray = []
json['base_period_cost']['names'].forEach((currentValue, index) => {
let cardSummaryItem = {}
cardSummaryItem['name'] = json['base_period_cost']['names'][index];
cardSummaryItem['unit'] = json['base_period_cost']['units'][index];
cardSummaryItem['subtotal'] = json['base_period_cost']['subtotals'][index];
cardSummaryItem['increment_rate'] = null;
cardSummaryItem['subtotal_per_unit_area'] = json['base_period_cost']['subtotals_per_unit_area'][index];
lastYearCostCardSummaryArray.push(cardSummaryItem);
});
setLastYearCostCardSummaryList(lastYearCostCardSummaryArray);
let timeOfUseArray = [];
json['reporting_period_input']['energy_category_ids'].forEach((currentValue, index) => {
if(currentValue === 1) {
// energy_category_id 1 electricity
let timeOfUseItem = {}
timeOfUseItem['id'] = 1;
timeOfUseItem['name'] = t('Top-Peak');
timeOfUseItem['value'] = json['reporting_period_input']['toppeaks'][index];
timeOfUseItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
timeOfUseArray.push(timeOfUseItem);
timeOfUseItem = {}
timeOfUseItem['id'] = 2;
timeOfUseItem['name'] = t('On-Peak');
timeOfUseItem['value'] = json['reporting_period_input']['onpeaks'][index];
timeOfUseItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
timeOfUseArray.push(timeOfUseItem);
timeOfUseItem = {}
timeOfUseItem['id'] = 3;
timeOfUseItem['name'] = t('Mid-Peak');
timeOfUseItem['value'] = json['reporting_period_input']['midpeaks'][index];
timeOfUseItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
timeOfUseArray.push(timeOfUseItem);
timeOfUseItem = {}
timeOfUseItem['id'] = 4;
timeOfUseItem['name'] = t('Off-Peak');
timeOfUseItem['value'] = json['reporting_period_input']['offpeaks'][index];
timeOfUseItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
timeOfUseArray.push(timeOfUseItem);
}
});
setTimeOfUseShareData(timeOfUseArray);
let totalInTCE = {};
totalInTCE['value'] = json['reporting_period_input']['total_in_kgce'] / 1000; // convert from kg to t
totalInTCE['increment_rate'] = parseFloat(json['reporting_period_input']['increment_rate_in_kgce'] * 100).toFixed(2) + "%";
totalInTCE['value_per_unit_area'] = json['reporting_period_input']['total_in_kgce_per_unit_area'] / 1000; // convert from kg to t
setTotalInTCE(totalInTCE);
let costDataArray = [];
json['reporting_period_cost']['names'].forEach((currentValue, index) => {
let costDataItem = {}
costDataItem['id'] = index;
costDataItem['name'] = currentValue;
costDataItem['value'] = json['reporting_period_cost']['subtotals'][index];
costDataItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
costDataArray.push(costDataItem);
});
setCostShareData(costDataArray);
let totalInTCO2E = {};
totalInTCO2E['value'] = json['reporting_period_input']['total_in_kgco2e'] / 1000; // convert from kg to t
totalInTCO2E['increment_rate'] = parseFloat(json['reporting_period_input']['increment_rate_in_kgco2e'] * 100).toFixed(2) + "%";
totalInTCO2E['value_per_unit_area'] = json['reporting_period_input']['total_in_kgco2e_per_unit_area'] / 1000; // convert from kg to t
setTotalInTCO2E(totalInTCO2E);
let TCEDataArray = [];
json['reporting_period_input']['names'].forEach((currentValue, index) => {
let TCEDataItem = {}
TCEDataItem['id'] = index;
TCEDataItem['name'] = currentValue;
TCEDataItem['value'] = json['reporting_period_input']['subtotals_in_kgce'][index] / 1000;
TCEDataItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
TCEDataArray.push(TCEDataItem);
});
setTCEShareData(TCEDataArray);
let TCO2EDataArray = [];
json['reporting_period_input']['names'].forEach((currentValue, index) => {
let TCO2EDataItem = {}
TCO2EDataItem['id'] = index;
TCO2EDataItem['name'] = currentValue;
TCO2EDataItem['value'] = json['reporting_period_input']['subtotals_in_kgco2e'][index] / 1000; // convert from kg to t
TCO2EDataItem['color'] = "#"+((1<<24)*Math.random()|0).toString(16);
TCO2EDataArray.push(TCO2EDataItem);
});
setTCO2EShareData(TCO2EDataArray);
let timestamps = {}
json['reporting_period_input']['timestamps'].forEach((currentValue, index) => {
timestamps['a' + index] = currentValue;
});
setSpaceInputLineChartLabels(timestamps);
let values = {}
json['reporting_period_input']['values'].forEach((currentValue, index) => {
values['a' + index] = currentValue;
});
setSpaceInputLineChartData(values);
let names = Array();
json['reporting_period_input']['names'].forEach((currentValue, index) => {
let unit = json['reporting_period_input']['units'][index];
names.push({ 'value': 'a' + index, 'label': currentValue + ' (' + unit + ')'});
});
setSpaceInputLineChartOptions(names);
timestamps = {}
json['reporting_period_cost']['timestamps'].forEach((currentValue, index) => {
timestamps['a' + index] = currentValue;
});
setSpaceCostLineChartLabels(timestamps);
values = {}
json['reporting_period_cost']['values'].forEach((currentValue, index) => {
values['a' + index] = currentValue;
});
setSpaceCostLineChartData(values);
names = Array();
json['reporting_period_cost']['names'].forEach((currentValue, index) => {
let unit = json['reporting_period_cost']['units'][index];
names.push({ 'value': 'a' + index, 'label': currentValue + ' (' + unit + ')'});
});
setSpaceCostLineChartOptions(names);
let detailed_value_list = [];
if (json['reporting_period_input']['timestamps'].length > 0 ) {
json['reporting_period_input']['timestamps'][0].forEach((currentTimestamp, timestampIndex) => {
let detailed_value = {};
detailed_value['id'] = timestampIndex;
detailed_value['startdatetime'] = currentTimestamp;
json['reporting_period_input']['values'].forEach((currentValue, energyCategoryIndex) => {
detailed_value['a' + energyCategoryIndex] = json['reporting_period_input']['values'][energyCategoryIndex][timestampIndex].toFixed(2);
});
detailed_value_list.push(detailed_value);
});
}
let detailed_value = {};
detailed_value['id'] = detailed_value_list.length;
detailed_value['startdatetime'] = t('Subtotal');
json['reporting_period_input']['subtotals'].forEach((currentValue, index) => {
detailed_value['a' + index] = currentValue.toFixed(2);
});
detailed_value_list.push(detailed_value);
setDetailedDataTableData(detailed_value_list);
let detailed_column_list = [];
detailed_column_list.push({
dataField: 'startdatetime',
text: t('Datetime'),
sort: true
})
json['reporting_period_input']['names'].forEach((currentValue, index) => {
let unit = json['reporting_period_input']['units'][index];
detailed_column_list.push({
dataField: 'a' + index,
text: currentValue + ' (' + unit + ')',
sort: true
})
});
setDetailedDataTableColumns(detailed_column_list);
let child_space_value_list = [];
if (json['child_space_input']['child_space_names_array'].length > 0) {
json['child_space_input']['child_space_names_array'][0].forEach((currentSpaceName, spaceIndex) => {
let child_space_value = {};
child_space_value['id'] = spaceIndex;
child_space_value['name'] = currentSpaceName;
json['child_space_input']['energy_category_names'].forEach((currentValue, energyCategoryIndex) => {
child_space_value['a' + energyCategoryIndex] = json['child_space_input']['subtotals_array'][energyCategoryIndex][spaceIndex];
child_space_value['b' + energyCategoryIndex] = json['child_space_cost']['subtotals_array'][energyCategoryIndex][spaceIndex];
});
child_space_value_list.push(child_space_value);
});
}
setChildSpacesTableData(child_space_value_list);
let child_space_column_list = [];
child_space_column_list.push({
dataField: 'name',
text: t('Child Spaces'),
sort: true
});
json['child_space_input']['energy_category_names'].forEach((currentValue, index) => {
let unit = json['child_space_input']['units'][index];
child_space_column_list.push({
dataField: 'a' + index,
text: currentValue + ' (' + unit + ')',
sort: true,
formatter: function (decimalValue) {
if (typeof decimalValue === 'number') {
return decimalValue.toFixed(2);
} else {
return null;
}
}
});
});
json['child_space_cost']['energy_category_names'].forEach((currentValue, index) => {
let unit = json['child_space_cost']['units'][index];
child_space_column_list.push({
dataField: 'b' + index,
text: currentValue + ' (' + unit + ')',
sort: true,
formatter: function (decimalValue) {
if (typeof decimalValue === 'number') {
return decimalValue.toFixed(2);
} else {
return null;
}
}
});
});
setChildSpacesTableColumns(child_space_column_list);
}
});
};
};
}, );
return (
<Fragment>
<div className="card-deck">
<Spinner color="primary" hidden={spinnerHidden} />
<Spinner color="secondary" hidden={spinnerHidden} />
<Spinner color="success" hidden={spinnerHidden} />
<Spinner color="danger" hidden={spinnerHidden} />
<Spinner color="warning" hidden={spinnerHidden} />
<Spinner color="info" hidden={spinnerHidden} />
<Spinner color="light" hidden={spinnerHidden} />
{thisYearInputCardSummaryList.map(cardSummaryItem => (
<CardSummary key={uuid()}
rate={cardSummaryItem['increment_rate']}
title={t("This Year's Consumption CATEGORY VALUE UNIT", { 'CATEGORY': cardSummaryItem['name'], 'VALUE': null, 'UNIT': '(' + cardSummaryItem['unit'] + ')' })}
color="success"
footnote={t('Per Unit Area')}
footvalue={cardSummaryItem['subtotal_per_unit_area']}
footunit={"(" + cardSummaryItem['unit'] + "/M²)"} >
{cardSummaryItem['subtotal'] && <CountUp end={cardSummaryItem['subtotal']} duration={2} prefix="" separator="," decimal="." decimals={0} />}
</CardSummary>
))}
{thisYearCostCardSummaryList.map(cardSummaryItem => (
<CardSummary key={uuid()}
rate={cardSummaryItem['increment_rate']}
title={t("This Year's Costs CATEGORY VALUE UNIT", { 'CATEGORY': cardSummaryItem['name'], 'VALUE': null, 'UNIT': '(' + cardSummaryItem['unit'] + ')' })}
color="success"
footnote={t('Per Unit Area')}
footvalue={cardSummaryItem['subtotal_per_unit_area']}
footunit={"(" + cardSummaryItem['unit'] + "/M²)"} >
{cardSummaryItem['subtotal'] && <CountUp end={cardSummaryItem['subtotal']} duration={2} prefix="" separator="," decimal="." decimals={0} />}
</CardSummary>
))}
</div>
<div className="card-deck">
{lastYearInputCardSummaryList.map(cardSummaryItem => (
<CardSummary key={uuid()}
rate={cardSummaryItem['increment_rate']}
title={t("Consumption CATEGORY VALUE UNIT in The Same Period Last Year", { 'CATEGORY': cardSummaryItem['name'], 'VALUE': null, 'UNIT': '(' + cardSummaryItem['unit'] + ')' })}
color="success"
footnote={t('Per Unit Area')}
footvalue={cardSummaryItem['subtotal_per_unit_area']}
footunit={"(" + cardSummaryItem['unit'] + "/M²)"} >
{cardSummaryItem['subtotal'] && <CountUp end={cardSummaryItem['subtotal']} duration={2} prefix="" separator="," decimal="." decimals={0} />}
</CardSummary>
))}
{lastYearCostCardSummaryList.map(cardSummaryItem => (
<CardSummary key={uuid()}
rate={cardSummaryItem['increment_rate']}
title={t("Costs CATEGORY VALUE UNIT in The Same Period Last Year", { 'CATEGORY': cardSummaryItem['name'], 'VALUE': null, 'UNIT': '(' + cardSummaryItem['unit'] + ')' })}
color="success"
footnote={t('Per Unit Area')}
footvalue={cardSummaryItem['subtotal_per_unit_area']}
footunit={"(" + cardSummaryItem['unit'] + "/M²)"} >
{cardSummaryItem['subtotal'] && <CountUp end={cardSummaryItem['subtotal']} duration={2} prefix="" separator="," decimal="." decimals={0} />}
</CardSummary>
))}
</div>
<div className="card-deck">
<CardSummary
rate={totalInTCE['increment_rate'] || ''}
title={t("This Year's Consumption CATEGORY VALUE UNIT", { 'CATEGORY': t('Ton of Standard Coal'), 'UNIT': '(TCE)' })}
color="warning"
footnote={t('Per Unit Area')}
footvalue={totalInTCE['value_per_unit_area']}
footunit="(TCE/M²)">
{totalInTCE['value'] && <CountUp end={totalInTCE['value']} duration={2} prefix="" separator="," decimal="." decimals={2} />}
</CardSummary>
<CardSummary
rate={totalInTCO2E['increment_rate'] || ''}
title={t("This Year's Consumption CATEGORY VALUE UNIT", { 'CATEGORY': t('Ton of Carbon Dioxide Emissions'), 'UNIT': '(TCO2E)' })}
color="warning"
footnote={t('Per Unit Area')}
footvalue={totalInTCO2E['value_per_unit_area']}
footunit="(TCO2E/M²)">
{totalInTCO2E['value'] && <CountUp end={totalInTCO2E['value']} duration={2} prefix="" separator="," decimal="." decimals={2} />}
</CardSummary>
</div>
<Row noGutters>
<Col className="mb-3 pr-lg-2 mb-3">
<SharePie data={timeOfUseShareData} title={t('Electricity Consumption by Time-Of-Use')} />
</Col>
<Col className="mb-3 pr-lg-2 mb-3">
<SharePie data={costShareData} title={t('Costs by Energy Category')} />
</Col>
<Col className="mb-3 pr-lg-2 mb-3">
<SharePie data={TCEShareData} title={t('Ton of Standard Coal by Energy Category')} />
</Col>
<Col className="mb-3 pr-lg-2 mb-3">
<SharePie data={TCO2EShareData} title={t('Ton of Carbon Dioxide Emissions by Energy Category')} />
</Col>
</Row>
<LineChart reportingTitle={t("This Year's Consumption CATEGORY VALUE UNIT", { 'CATEGORY': null, 'VALUE': null, 'UNIT': null })}
baseTitle=''
labels={spaceInputLineChartLabels}
data={spaceInputLineChartData}
options={spaceInputLineChartOptions}>
</LineChart>
<LineChart reportingTitle={t("This Year's Costs CATEGORY VALUE UNIT", { 'CATEGORY': null, 'VALUE': null, 'UNIT': null })}
baseTitle=''
labels={spaceCostLineChartLabels}
data={spaceCostLineChartData}
options={spaceCostLineChartOptions}>
</LineChart>
<ChildSpacesTable data={childSpacesTableData}
title={t('Child Spaces Data')}
columns={childSpacesTableColumns}>
</ChildSpacesTable>
</Fragment>
);
};
export default withTranslation()(withRedirect(Workflow));

View File

@ -58,6 +58,11 @@ const resources = {
'Tenant Equipments': 'Tenant Equipments', 'Tenant Equipments': 'Tenant Equipments',
'Store Equipments': 'Store Equipments', 'Store Equipments': 'Store Equipments',
'Shopfloor Equipments': 'Shopfloor Equipments', 'Shopfloor Equipments': 'Shopfloor Equipments',
'Ticket': 'Ticket',
'My Agent': 'My Agent',
'My Application': 'My Application',
'Ticket List': 'Ticket List',
'Ticket Intervention': 'Ticket Intervention',
// Dashboard // Dashboard
'Welcome to MyEMS': 'Welcome to MyEMS', 'Welcome to MyEMS': 'Welcome to MyEMS',
'An Industry Leading Open Source Energy Management System': 'An Industry Leading Open Source Energy Management System':
@ -857,6 +862,11 @@ const resources = {
'Tenant Equipments': 'Mieter Ausrüstung', 'Tenant Equipments': 'Mieter Ausrüstung',
'Store Equipments': 'Geschäft Ausrüstung', 'Store Equipments': 'Geschäft Ausrüstung',
'Shopfloor Equipments': 'Werkstatt Ausrüstung', 'Shopfloor Equipments': 'Werkstatt Ausrüstung',
'Ticket': 'Ticket',
'My Agent': 'My Agent',
'My Application': 'My Application',
'Ticket List': 'Ticket List',
'Ticket Intervention': 'Ticket Intervention',
// Dashboard // Dashboard
'Welcome to MyEMS': 'Willkommen bei MyEMS', 'Welcome to MyEMS': 'Willkommen bei MyEMS',
'An Industry Leading Open Source Energy Management System': 'Ein branchenführendes Open Source Energie Management System', 'An Industry Leading Open Source Energy Management System': 'Ein branchenführendes Open Source Energie Management System',
@ -1667,6 +1677,11 @@ const resources = {
'Tenant Equipments': '租户设备', 'Tenant Equipments': '租户设备',
'Store Equipments': '门店设备', 'Store Equipments': '门店设备',
'Shopfloor Equipments': '车间设备', 'Shopfloor Equipments': '车间设备',
'Ticket': '工单',
'My Agent': '我的代办',
'My Application': '我的申请',
'Ticket List': '工单列表',
'Ticket Intervention': '工单干预',
// Dashboard // Dashboard
'Welcome to MyEMS': '欢迎使用MyEMS', 'Welcome to MyEMS': '欢迎使用MyEMS',
'An Industry Leading Open Source Energy Management System': '行业领先的开源能源管理系统', 'An Industry Leading Open Source Energy Management System': '行业领先的开源能源管理系统',

View File

@ -197,7 +197,12 @@ import KnowledgeBase from '../components/MyEMS/KnowledgeBase/KnowledgeBase';
// Notification // Notification
import Notification from '../components/MyEMS/Notification/Notification'; import Notification from '../components/MyEMS/Notification/Notification';
// Workflow // Workflow
import Workflow from '../components/MyEMS/Workflow/Workflow'; import Workflow from '../components/MyEMS/Ticket/TicketList';
import Ticket from '../components/MyEMS/Ticket/TicketList';
import TicketList from '../components/MyEMS/Ticket/TicketList';
import TicketAgent from '../components/MyEMS/Ticket/TicketAgent';
import TicketApplication from '../components/MyEMS/Ticket/TicketApplication';
import TicketIntervention from '../components/MyEMS/Ticket/TicketIntervention';
// const InboxRoutes = ({ match: { url } }) => ( // const InboxRoutes = ({ match: { url } }) => (
// <InboxProvider> // <InboxProvider>
@ -449,8 +454,11 @@ const MyEMSRoutes = () => (
{/* Notification */} {/* Notification */}
<Route path="/notification" exact component={Notification} /> <Route path="/notification" exact component={Notification} />
{/* Workflow */} {/* Ticket */}
<Route path="/workflow/list" exact component={Workflow} /> <Route path="/ticket/agent" exact component={TicketAgent} />
<Route path="/ticket/application" exact component={TicketApplication} />
<Route path="/ticket/list" exact component={TicketList} />
<Route path="/ticket/intervention" exact component={TicketIntervention} />
{/*Redirect*/} {/*Redirect*/}
<Redirect to="/errors/404" /> <Redirect to="/errors/404" />

View File

@ -489,11 +489,14 @@ export const knowledgeBaseRoutes = {
}; };
export const workflowRoutes = { export const workflowRoutes = {
name: 'Workflow', name: 'Ticket',
to: '/workflow', to: '/ticket',
icon: 'chart-pie', icon: 'chart-pie',
children: [ children: [
{ to: '/workflow/list', name: 'Workflow List' }, { to: '/ticket/agent', name: 'My Agent' },
{ to: '/ticket/application', name: 'My Application' },
{ to: '/ticket/list', name: 'Ticket List' },
{ to: '/ticket/intervention', name: 'Ticket Intervention' }
] ]
}; };