From c68a44bbfba643b0e963924a9c902d6093416758 Mon Sep 17 00:00:00 2001
From: Vadym <30234255+vadkor@users.noreply.github.com>
Date: Tue, 12 Dec 2023 18:01:18 +1100
Subject: [PATCH 1/2] Added AEMO Status & Outages
---
src/components/Page.js | 5 +
.../data/discovery/AEMODiscoveryInfo.js | 128 ++++++++++++++++++
src/store/aemo_discovery/actions.js | 70 ++++++++++
src/store/aemo_discovery/index.js | 2 +
src/store/aemo_discovery/reducer.js | 28 ++++
src/store/index.js | 2 +
6 files changed, 235 insertions(+)
create mode 100644 src/components/data/discovery/AEMODiscoveryInfo.js
create mode 100644 src/store/aemo_discovery/actions.js
create mode 100644 src/store/aemo_discovery/index.js
create mode 100644 src/store/aemo_discovery/reducer.js
diff --git a/src/components/Page.js b/src/components/Page.js
index 33c20ba..52e2ae4 100644
--- a/src/components/Page.js
+++ b/src/components/Page.js
@@ -12,6 +12,7 @@ import AppBar from '@material-ui/core/AppBar'
import Tabs from '@material-ui/core/Tabs'
import Tab from '@material-ui/core/Tab'
import DiscoveryInfo from './data/discovery/DiscoveryInfo'
+import AEMODiscoveryInfo from './data/discovery/AEMODiscoveryInfo'
const useStyles = makeStyles(theme => ({
hidden: {
@@ -37,6 +38,7 @@ function Page() {
+
@@ -50,6 +52,9 @@ function Page() {
+
);
}
diff --git a/src/components/data/discovery/AEMODiscoveryInfo.js b/src/components/data/discovery/AEMODiscoveryInfo.js
new file mode 100644
index 0000000..b4ac302
--- /dev/null
+++ b/src/components/data/discovery/AEMODiscoveryInfo.js
@@ -0,0 +1,128 @@
+import React from 'react'
+import Accordion from '@material-ui/core/Accordion'
+import AccordionSummary from '@material-ui/core/AccordionSummary'
+import AccordionActions from '@material-ui/core/AccordionActions'
+import ExpandMoreIcon from '@material-ui/icons/ExpandMore'
+import SubjectIcon from '@material-ui/icons/Subject'
+import Typography from '@material-ui/core/Typography'
+import Divider from '@material-ui/core/Divider'
+import RefreshIcon from '@material-ui/icons/Refresh'
+import Fab from '@material-ui/core/Fab'
+import Tooltip from '@material-ui/core/Tooltip'
+import { makeStyles } from '@material-ui/core/styles'
+import { fade } from '@material-ui/core/styles/colorManipulator'
+import Duration from '../Duration'
+import DateTime from '../DateTime'
+import { connect } from 'react-redux'
+import { retrieveStatus, retrieveOutages } from '../../../store/aemo_discovery'
+import { translateDiscoveryStatus } from '../../../utils/dict'
+
+const useStyles = makeStyles(theme => ({
+ container: {
+ marginLeft: theme.typography.pxToRem(20),
+ marginRight: theme.typography.pxToRem(20)
+ },
+ panel: {
+ backgroundColor: fade('#fff', 0.9)
+ },
+ heading: {
+ display: 'flex',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ fontSize: theme.typography.pxToRem(20),
+ },
+ details: {
+ maxWidth:'95%',
+ marginLeft: 'auto',
+ marginRight: 'auto',
+ marginBottom: 20
+ }
+}))
+
+const AEMODiscoveryInfo = (props) => {
+
+ const classes = useStyles()
+ const [expanded, setExpanded] = React.useState(true)
+ const {statusDetails, outagesDetails} = props.data
+
+ const toggleExpansion = (event, newExpanded) => {
+ setExpanded(newExpanded)
+ }
+
+ const refreshStatusOutages = () => {
+ props.retrieveStatus()
+ props.retrieveOutages()
+ }
+
+ React.useEffect(() => {
+ refreshStatusOutages()
+ // eslint-disable-next-line
+ }, [])
+
+ return (
+
+ }
+ aria-controls='panel1c-content'
+ >
+
+ Status & Outages
+
+
+
+
Secondary Data Holders provide data to Data Holders via CDR requests, who in turn provide the data to ADRs. Such data is called Shared Responsibility Data (SR data).
+
Currently, only the energy sector has a designated secondary data holder: AEMO. This page lists the status and outages for AEMO.
+
+
+ {!!statusDetails &&
+ <>
+
Status
+
+
Status: {translateDiscoveryStatus(statusDetails.status)}{!!statusDetails.explanation && - {statusDetails.explanation}}
+ {!!statusDetails.detectionTime &&
Detection Time:
}
+ {!!statusDetails.expectedResolutionTime &&
Expected Resolution Time:
}
+ {!!statusDetails.updateTime &&
Update Time:
}
+
+ >
+ }
+
+ {!!outagesDetails && !!outagesDetails.outages && !!outagesDetails.outages.length &&
+ <>
+
Scheduled Outages
+
+ >
+ }
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+const mapStateToProps = state => ({
+ data: state.aemoDiscovery
+})
+
+const mapDispatchToProps = {
+ retrieveStatus,
+ retrieveOutages
+}
+
+export default connect(mapStateToProps, mapDispatchToProps)(AEMODiscoveryInfo)
\ No newline at end of file
diff --git a/src/store/aemo_discovery/actions.js b/src/store/aemo_discovery/actions.js
new file mode 100644
index 0000000..f69a03e
--- /dev/null
+++ b/src/store/aemo_discovery/actions.js
@@ -0,0 +1,70 @@
+import {conoutInfo, conoutHtmlError, conoutError} from '../conout/actions'
+
+const AEMO_URL = 'https://api.aemo.com.au/NEMRetail/cds-au/v1'
+
+export const RETRIEVE_AEMO_STATUS = 'RETRIEVE_AEMO_STATUS'
+export const RETRIEVE_AEMO_OUTAGES = 'RETRIEVE_AEMO_OUTAGES'
+
+const headers = {
+ 'Accept': 'application/json',
+ 'x-v': 1
+}
+
+function createConoutError(error, url) {
+ return conoutError('Caught ' + error + ' while requesting ' + url + (error.name === 'TypeError' ?
+ ' Possibly caused by the endpoint not supporting Cross-Origin Requests (CORS)' : ''))
+}
+
+export const retrieveStatus = () => dispatch => {
+ const fullUrl = AEMO_URL + '/discovery/status'
+ const request = new Request(fullUrl, {headers})
+ dispatch(conoutInfo('Requesting retrieveStatus(): ' + fullUrl))
+ dispatch({
+ type: RETRIEVE_AEMO_STATUS,
+ payload: fetch(request)
+ .then(response => {
+ if (response.ok) {
+ return response.json()
+ }
+ throw new Error(`Response not OK. Status: ${response.status} (${response.statusText})`)
+ })
+ .then(obj => {
+ dispatch(conoutInfo(`Received response for ${fullUrl}:`, obj))
+ return obj
+ })
+ .catch(error => {
+ dispatch(createConoutError(error, fullUrl))
+ })
+ })
+}
+
+export const retrieveOutages = () => dispatch => {
+ const fullUrl = AEMO_URL + '/discovery/outages'
+ const request = new Request(fullUrl, {headers})
+ dispatch(conoutInfo('Requesting retrieveOutages(): ' + fullUrl))
+ dispatch({
+ type: RETRIEVE_AEMO_OUTAGES,
+ payload: fetch(request)
+ .then(response => {
+ if (response.ok) {
+ if (!response.headers['x-v']) {
+ const msg = `Response for ${fullUrl}: doesn't expose header x-v: possibly caused by incomplete `
+ const corsSupport = 'CORS support'
+ dispatch(conoutHtmlError(
+ msg + corsSupport,
+ `${msg}
${corsSupport}`
+ ))
+ }
+ return response.json()
+ }
+ throw new Error(`Response not OK. Status: ${response.status} (${response.statusText})`)
+ })
+ .then(obj => {
+ dispatch(conoutInfo(`Received response for ${fullUrl}:`, obj))
+ return obj
+ })
+ .catch(error => {
+ dispatch(createConoutError(error, fullUrl))
+ })
+ })
+}
diff --git a/src/store/aemo_discovery/index.js b/src/store/aemo_discovery/index.js
new file mode 100644
index 0000000..0a77bab
--- /dev/null
+++ b/src/store/aemo_discovery/index.js
@@ -0,0 +1,2 @@
+export * from './actions'
+export * from './reducer'
diff --git a/src/store/aemo_discovery/reducer.js b/src/store/aemo_discovery/reducer.js
new file mode 100644
index 0000000..c1c1d86
--- /dev/null
+++ b/src/store/aemo_discovery/reducer.js
@@ -0,0 +1,28 @@
+import {
+ RETRIEVE_AEMO_STATUS,
+ RETRIEVE_AEMO_OUTAGES
+} from './actions'
+import {fulfilled} from '../../utils/async-actions'
+
+export default function discovery(state = {}, action) {
+ switch (action.type) {
+ case fulfilled(RETRIEVE_AEMO_STATUS): {
+ const s = {...state}
+ if (action.payload) {
+ const response = action.payload
+ s.statusDetails = response ? response.data : null
+ }
+ return s
+ }
+ case fulfilled(RETRIEVE_AEMO_OUTAGES): {
+ const s = {...state}
+ if (action.payload) {
+ const response = action.payload
+ s.outagesDetails = response ? response.data : null
+ }
+ return s
+ }
+ default:
+ return state
+ }
+}
diff --git a/src/store/index.js b/src/store/index.js
index 0572799..a553bf6 100644
--- a/src/store/index.js
+++ b/src/store/index.js
@@ -9,6 +9,7 @@ import banking from './banking/data/reducer'
import energy from './energy/data/reducer'
import energySelection from './energy/selection/reducer'
import discovery from './discovery/reducer'
+import aemoDiscovery from './aemo_discovery/reducer'
import bankingSelection from './banking/selection/reducer'
import bankingComparison from './banking/comparison/reducer'
import energyComparison from './energy/comparison/reducer'
@@ -20,6 +21,7 @@ const rootReducer = combineReducers({
banking,
energy,
discovery,
+ aemoDiscovery,
bankingSelection,
energySelection,
bankingComparison,
From 3024265a1c21bd1e811d49a8d449ed45356d3944 Mon Sep 17 00:00:00 2001
From: Vadym <30234255+vadkor@users.noreply.github.com>
Date: Wed, 13 Dec 2023 16:02:17 +1100
Subject: [PATCH 2/2] Generalised CORS messaging, reused StatusOutages
---
.../data/discovery/AEMODiscoveryInfo.js | 32 ++-----------------
.../data/discovery/DiscoveryInfo.js | 24 ++++++++++----
.../data/discovery/StatusOutages.js | 19 +----------
src/store/aemo_discovery/actions.js | 18 +++--------
src/store/banking/data/actions.js | 17 ++--------
src/store/discovery/actions.js | 18 +++--------
src/store/energy/data/actions.js | 17 ++--------
src/utils/cors.js | 17 ++++++++++
8 files changed, 52 insertions(+), 110 deletions(-)
create mode 100644 src/utils/cors.js
diff --git a/src/components/data/discovery/AEMODiscoveryInfo.js b/src/components/data/discovery/AEMODiscoveryInfo.js
index b4ac302..2717e25 100644
--- a/src/components/data/discovery/AEMODiscoveryInfo.js
+++ b/src/components/data/discovery/AEMODiscoveryInfo.js
@@ -11,11 +11,9 @@ import Fab from '@material-ui/core/Fab'
import Tooltip from '@material-ui/core/Tooltip'
import { makeStyles } from '@material-ui/core/styles'
import { fade } from '@material-ui/core/styles/colorManipulator'
-import Duration from '../Duration'
-import DateTime from '../DateTime'
+import StatusOutages from './StatusOutages'
import { connect } from 'react-redux'
import { retrieveStatus, retrieveOutages } from '../../../store/aemo_discovery'
-import { translateDiscoveryStatus } from '../../../utils/dict'
const useStyles = makeStyles(theme => ({
container: {
@@ -74,33 +72,7 @@ const AEMODiscoveryInfo = (props) => {
Currently, only the energy sector has a designated secondary data holder: AEMO. This page lists the status and outages for AEMO.
- {!!statusDetails &&
- <>
-
Status
-
-
Status: {translateDiscoveryStatus(statusDetails.status)}{!!statusDetails.explanation && - {statusDetails.explanation}}
- {!!statusDetails.detectionTime &&
Detection Time:
}
- {!!statusDetails.expectedResolutionTime &&
Expected Resolution Time:
}
- {!!statusDetails.updateTime &&
Update Time:
}
-
- >
- }
-
- {!!outagesDetails && !!outagesDetails.outages && !!outagesDetails.outages.length &&
- <>
-
Scheduled Outages
-
- >
- }
+