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..2717e25
--- /dev/null
+++ b/src/components/data/discovery/AEMODiscoveryInfo.js
@@ -0,0 +1,100 @@
+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 StatusOutages from './StatusOutages'
+import { connect } from 'react-redux'
+import { retrieveStatus, retrieveOutages } from '../../../store/aemo_discovery'
+
+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.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ )
+}
+
+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/components/data/discovery/DiscoveryInfo.js b/src/components/data/discovery/DiscoveryInfo.js
index 55369b5..3651193 100644
--- a/src/components/data/discovery/DiscoveryInfo.js
+++ b/src/components/data/discovery/DiscoveryInfo.js
@@ -49,6 +49,11 @@ const DiscoveryInfo = (props) => {
setExpanded(newExpanded)
}
+ React.useEffect(() => {
+ refreshStatusOutages()
+ // eslint-disable-next-line
+ }, [props.dataSources])
+
const getWidth = (dataSourceCount, min) => {
return Math.max(12 / dataSourceCount, min)
}
@@ -78,8 +83,13 @@ const DiscoveryInfo = (props) => {
{
savedDataSourcesCount > 0 &&
- {dataSources.map((dataSource, index) => (
- !dataSource.unsaved && dataSource.enabled && !dataSource.deleted &&
+ {dataSources.map((dataSource, index) => {
+ const data = props.data[index]
+ if (!data) {
+ return false
+ }
+ const {statusDetails, outagesDetails} = data
+ return (!dataSource.unsaved && dataSource.enabled && !dataSource.deleted &&
{
xl={getWidth(savedDataSourcesCount, 3)}
>
{!!dataSource.icon &&
}
{dataSource.name}
-
+
- ))}
+ )
+ })}
}
@@ -108,10 +119,11 @@ const DiscoveryInfo = (props) => {
)
}
-const mapStateToProps = state=>({
+const mapStateToProps = state => ({
dataSources : state.dataSources,
savedDataSourcesCount: state.dataSources.filter(dataSource => !dataSource.unsaved && !dataSource.deleted && dataSource.enabled).length,
- versionInfo: state.versionInfo.vHeaders
+ versionInfo: state.versionInfo.vHeaders,
+ data: state.discovery
})
const mapDispatchToProps = {
diff --git a/src/components/data/discovery/StatusOutages.js b/src/components/data/discovery/StatusOutages.js
index 8154624..76c13ef 100644
--- a/src/components/data/discovery/StatusOutages.js
+++ b/src/components/data/discovery/StatusOutages.js
@@ -2,25 +2,12 @@ import React from 'react'
import DateTime from '../DateTime'
import Duration from '../Duration'
import { connect } from 'react-redux'
-import { normalise } from '../../../utils/url'
-import { retrieveStatus, retrieveOutages } from '../../../store/discovery'
import { translateDiscoveryStatus } from '../../../utils/dict'
class StatusOutages extends React.Component {
- componentDidMount() {
- const { dataSourceIndex, dataSource, versionInfo } = this.props
- const url = normalise(dataSource.url)
- this.props.retrieveStatus(dataSourceIndex, url, versionInfo.xV, versionInfo.xMinV)
- this.props.retrieveOutages(dataSourceIndex, url, versionInfo.xV, versionInfo.xMinV)
- }
-
render() {
- let data = this.props.data[this.props.dataSourceIndex]
- if (!data) {
- return false
- }
- const {statusDetails, outagesDetails} = data
+ const { statusDetails, outagesDetails } = this.props
return (
<>
{!!statusDetails &&
@@ -63,13 +50,9 @@ const Outage = props => {
}
const mapStateToProps = state => ({
- versionInfo: state.versionInfo.vHeaders,
- data: state.discovery
})
const mapDispatchToProps = {
- retrieveStatus,
- retrieveOutages
}
export default connect(mapStateToProps, mapDispatchToProps)(StatusOutages)
\ 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..ad010e6
--- /dev/null
+++ b/src/store/aemo_discovery/actions.js
@@ -0,0 +1,60 @@
+import {conoutInfo} from '../conout/actions'
+import {createConoutError, checkExposedHeaders} from '../../utils/cors'
+
+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
+}
+
+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) {
+ checkExposedHeaders(response, fullUrl, dispatch)
+ 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) {
+ checkExposedHeaders(response, fullUrl, dispatch)
+ 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/banking/data/actions.js b/src/store/banking/data/actions.js
index 787660b..a73f560 100644
--- a/src/store/banking/data/actions.js
+++ b/src/store/banking/data/actions.js
@@ -1,4 +1,5 @@
-import {conoutInfo, conoutError, conoutHtmlError, conoutWarn} from '../../conout/actions'
+import {conoutInfo, conoutError, conoutWarn} from '../../conout/actions'
+import {createConoutError, checkExposedHeaders} from '../../../utils/cors'
import {encodeRFC3986URIComponent} from '../../../utils/url'
export const START_RETRIEVE_PRODUCT_LIST = 'START_RETRIEVE_PRODUCT_LIST'
@@ -17,11 +18,6 @@ const headers = {
'Accept': 'application/json'
}
-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 retrieveProductList = (dataSourceIdx, baseUrl, productListUrl, xV, xMinV) =>
(dispatch) => {
const request = new Request(productListUrl, {headers: new Headers({...headers, 'x-v': xV, 'x-min-v': xMinV})})
@@ -31,14 +27,7 @@ export const retrieveProductList = (dataSourceIdx, baseUrl, productListUrl, xV,
payload: fetch(request)
.then(response => {
if (response.ok) {
- if (!response.headers['x-v']) {
- const msg = `Response for ${productListUrl}: doesn't expose header x-v: possibly caused by incomplete `
- const corsSupport = 'CORS support'
- dispatch(conoutHtmlError(
- msg + corsSupport,
- `${msg}