Skip to content

Commit 706d545

Browse files
committed
improve listing usage plans and apis in catalog and allow for Swagger in YAML awslabs#6
1 parent 9f14722 commit 706d545

File tree

11 files changed

+471
-280
lines changed

11 files changed

+471
-280
lines changed

README.md

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,17 @@ First, ensure you have the [latest AWS CLI installed](http://docs.aws.amazon.com
1616

1717
### List your products (APIs/Usage Plans)
1818

19-
Add your API Gateway APIs to the array in the `lambdas/backend/catalog.json` file, using the following format. If you have not yet created an API and Usage Plan, see [Generate Your Own API Gateway Developer Portal](https://aws.amazon.com/blogs/compute/generate-your-own-api-gateway-developer-portal/) for a detailed walkthrough. Alternatively, skip this step for now if you just want to get started with your developer portal (A placeholder API with swagger definition is provided for you for demonstration purposes, however, some features such as __Subscribe__ will not work)
19+
Add your API Gateway Usage Plans and APIs to `lambdas/backend/catalog/index.js`, using the format below, and add your Swagger files to `lambdas/backend/catalog/` directory. If you have not yet created an API and Usage Plan, see [Generate Your Own API Gateway Developer Portal](https://aws.amazon.com/blogs/compute/generate-your-own-api-gateway-developer-portal/) for a detailed walkthrough. Alternatively, skip this step for now if you just want to get started with your developer portal (A placeholder API with swagger definition is provided for you for demonstration purposes, however, some features such as __Subscribe__ will not work)
2020

2121
```json
2222
{
23-
"apiId": "YOUR_API_ID",
24-
"usagePlanId": "YOUR_USAGE_PLAN_ID",
25-
"image": "http://example.com/your-api-product-image.svg",
26-
"swagger": {
27-
"swagger": "2.0",
28-
...
29-
}
23+
"id": "YOUR_USAGE_PLAN_ID",
24+
"name": "Free",
25+
"apis": [{
26+
"id": "YOUR_API_ID",
27+
"image": "/sam-logo.png",
28+
"swagger": petStoreSwaggerDefinition
29+
}]
3030
}
3131
```
3232

dev-portal/src/components/ApiCatalog/index.js

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,43 +5,43 @@ import { addSubscription, unsubscribe, isSubscribed } from '../../services/api-c
55
import { isAuthenticated } from '../../services/self'
66
import Usage from '../Usage'
77

8-
function handleSubscribe(event, api) {
8+
function handleSubscribe(event, usagePlan) {
99
event.preventDefault()
1010

11-
addSubscription(api.usagePlanId)
11+
addSubscription(usagePlan.id)
1212
}
1313

14-
function handleUnsubscribe(event, api) {
14+
function handleUnsubscribe(event, usagePlan) {
1515
event.preventDefault()
1616

17-
unsubscribe(api.usagePlanId)
17+
unsubscribe(usagePlan.id)
1818
}
1919

20-
const SubscribedApiActionsDropdown = ({api}) => (
20+
const SubscribedApiActionsDropdown = ({usagePlan, api}) => (
2121
<Dropdown text='Actions' button>
2222
<Dropdown.Menu>
23-
<Usage api={api} />
24-
<Dropdown.Item onClick={event => handleUnsubscribe(event, api)}>Unsubscribe</Dropdown.Item>
23+
<Usage usagePlanId={usagePlan.id} />
24+
<Dropdown.Item onClick={event => handleUnsubscribe(event, usagePlan)}>Unsubscribe</Dropdown.Item>
2525
</Dropdown.Menu>
2626
</Dropdown>)
2727

2828

29-
const ApiCard = api => (
30-
<Card key={api.apiId} style={{textAlign: 'center'}}>
31-
<Link to={`apis/${api.apiId}`} style={{background: 'rgba(0, 0, 0, 0.05)'}}>{ api.image ? <Image src={api.image} style={{margin: 'auto'}} /> : ''}</Link>
29+
const ApiCard = ({usagePlan, api}) => (
30+
<Card key={api.id} style={{textAlign: 'center'}}>
31+
<Link to={`apis/${api.id}`} style={{background: 'rgba(0, 0, 0, 0.05)'}}>{ api.image ? <Image src={api.image} style={{margin: 'auto'}} /> : ''}</Link>
3232
<Card.Content>
33-
<Card.Header><Link to={`apis/${api.apiId}`}>{api.swagger.info.title}</Link></Card.Header>
33+
<Card.Header><Link to={`apis/${api.id}`}>{api.swagger.info.title}</Link></Card.Header>
3434
<Card.Meta>
3535
<span className='date'>Version {api.swagger.info.version}</span>
3636
</Card.Meta>
3737
<Card.Description>{api.swagger.info.description}</Card.Description>
3838
</Card.Content>
3939
{ isAuthenticated() ? (<Card.Content extra>
40-
{ isSubscribed(api) ? <SubscribedApiActionsDropdown api={api} /> : <Button onClick={event => handleSubscribe(event, api)}>Subscribe</Button>}
40+
{ isSubscribed(usagePlan.id) ? <SubscribedApiActionsDropdown api={api} usagePlan={usagePlan} /> : <Button onClick={event => handleSubscribe(event, usagePlan)}>Subscribe</Button>}
4141
</Card.Content>) : ''}
4242
</Card>)
4343

44-
export default ({ apis }) => (
44+
export default ({ catalog }) => (
4545
<Card.Group itemsPerRow={3} stackable doubling>
46-
{apis.map(ApiCard)}
46+
{catalog.map(usagePlan => usagePlan.apis.map(api => ApiCard({usagePlan, api})))}
4747
</Card.Group>)

dev-portal/src/components/Usage/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { fetchUsage, mapUsageByDate } from '../../services/api-catalog'
1616
loadUsage(event) {
1717
event.preventDefault()
1818
this.setState({isLoading: true})
19-
fetchUsage(this.props.api.usagePlanId)
19+
fetchUsage(this.props.usagePlanId)
2020
.then((result) => {
2121
const data = mapUsageByDate(result.data, 'used')
2222
const ctx = document.getElementById('api-usage-chart-container')

dev-portal/src/pages/Apis/index.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,16 @@ import React from 'react'
22
import { Dimmer, Loader } from 'semantic-ui-react'
33
import ApiCatalog from '../../components/ApiCatalog'
44
import { isAuthenticated } from '../../services/self'
5-
import { getApis, fetchSubscriptions } from '../../services/api-catalog'
5+
import { getCatalog, fetchSubscriptions } from '../../services/api-catalog'
66
import Head from '../../components/Head'
77

88
export default class ApisPage extends React.Component {
99
constructor(props) {
1010
super(props)
1111
this.state = {}
1212

13-
getApis().then(apis => {
14-
this.setState({ apis })
13+
getCatalog().then(catalog => {
14+
this.setState({ catalog })
1515
})
1616

1717
if (isAuthenticated()) {
@@ -24,7 +24,7 @@ export default class ApisPage extends React.Component {
2424
render() {
2525
return (<div>
2626
<Head {...this.props} />
27-
{this.state.apis && (!isAuthenticated() || this.state.subscriptions) ? <ApiCatalog apis={this.state.apis} /> : (<Dimmer active>
27+
{this.state.catalog && (!isAuthenticated() || this.state.subscriptions) ? <ApiCatalog catalog={this.state.catalog} /> : (<Dimmer active>
2828
<Loader content='Loading' />
2929
</Dimmer>)}
3030
</div>)

dev-portal/src/services/api-catalog.js

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,32 @@
11
import { getApiGatewayClient } from './api'
22
export let subscriptions
3-
let apis
3+
let catalog
44

5-
export function getApis() {
6-
if (apis) return Promise.resolve(apis)
5+
export function getCatalog() {
6+
if (catalog) return Promise.resolve(catalog)
77

8-
return fetchApis()
8+
return fetchCatalog()
99
.then(({data}) => {
10-
apis = data
10+
catalog = data
1111
return data
1212
})
1313
}
1414

15-
export function getApi(id) {
16-
return getApis()
17-
.then(() => apis.find(api => api.apiId === id))
15+
export function getApi(apiId) {
16+
return getCatalog()
17+
.then(() => {
18+
let _api
19+
20+
catalog.forEach(c => {
21+
if (_api) return
22+
_api = c.apis.find(a => a.id === apiId)
23+
})
24+
25+
return _api
26+
})
1827
}
1928

20-
export function fetchApis() {
29+
export function fetchCatalog() {
2130
return getApiGatewayClient().then(apiGatewayClient => {
2231
return apiGatewayClient.get('/catalog', {}, {}, {})
2332
})
@@ -38,18 +47,18 @@ export function clearSubscriptions() {
3847
subscriptions = null
3948
}
4049

41-
export function isSubscribed(api) {
42-
return !!getSubscribedUsagePlan(api)
50+
export function isSubscribed(usagePlanId) {
51+
return !!getSubscribedUsagePlan(usagePlanId)
4352
}
4453

45-
export function getUsagePlanApiStages(api) {
46-
const subscribedUsagePlan = getSubscribedUsagePlan(api)
47-
48-
return (subscribedUsagePlan && subscribedUsagePlan.apiStages) || []
49-
}
54+
// export function getUsagePlanApiStages(usagePlanId) {
55+
// const subscribedUsagePlan = getSubscribedUsagePlan(usagePlanId)
56+
//
57+
// return (subscribedUsagePlan && subscribedUsagePlan.apiStages) || []
58+
// }
5059

51-
export function getSubscribedUsagePlan(api) {
52-
const subscribedUsagePlan = subscriptions && subscriptions.find && subscriptions.find(s => s.id === api.usagePlanId)
60+
export function getSubscribedUsagePlan(usagePlanId) {
61+
const subscribedUsagePlan = subscriptions && subscriptions.find && subscriptions.find(s => s.id === usagePlanId)
5362
return subscribedUsagePlan
5463
}
5564

0 commit comments

Comments
 (0)