Skip to content

Commit cfe0299

Browse files
authored
5.2 release (#62)
5.2 release
1 parent fe978cf commit cfe0299

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+3200
-785
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ const App = () => {
181181
};
182182
```
183183

184-
6. Add the mock server to the `index.js` file:
184+
6. Add the mock server to the `index.js` file
185185
```js
186186
// in packages/my-own-apihub/src/index.js
187187
import { startApiHubMockedServer } from 'layer7-apihub-mock';

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@
4343
"date-fns": "~2.9.0",
4444
"es-abstract": "~1.19.0",
4545
"get-intrinsic": "~1.1.3",
46-
"serialize-javascript": "~3.1.0"
46+
"serialize-javascript": "~3.1.0",
47+
"qs": "6.9.7",
48+
"url-parse": "^1.5.9",
49+
"fast-json-patch": "3.1.1"
4750
}
4851
}

packages/layer7-apihub-mock/src/defaultData.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -898,7 +898,7 @@
898898
"id": "8282683c-ea5e-4451-95bc-b562598fd5ee",
899899
"uuid": "8282683c-ea5e-4451-95bc-b562598fd5ee",
900900
"name": "EXE Future Marketing",
901-
"status": "DISABLED",
901+
"status": "DELETE_FAILED",
902902
"disabledByType": null,
903903
"description": "Sharable cohesive capability",
904904
"OauthCallbackUrl": "https://example.com/oauthCallback",

packages/layer7-apihub-mock/src/index.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -384,7 +384,7 @@ export const startApiHubMockedServer = async (
384384
);
385385

386386
this.delete(
387-
`${urlPrefix}api/apim/Applications(':uuid')`,
387+
`${urlPrefix}/api-management/1.0/applications/:uuid`,
388388
deleteApplication(database),
389389
options
390390
);

packages/layer7-apihub/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"react-dnd-html5-backend": "~10.0.2",
3030
"react-markdown-editor-lite": "~1.0.2",
3131
"trim": "0.0.3",
32-
"remark-parse": "7.0.2",
32+
"remark-parse": "9.0.0",
3333
"remark-react": "~7.0.1",
3434
"remove-markdown": "~0.3.0",
3535
"slugify": "~1.4.4",

packages/layer7-apihub/src/apis/Application/ApiApplicationCredentials.js

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { useTranslate, useDataProvider } from 'react-admin';
33
import { makeStyles } from '@material-ui/core/styles';
44
import CircularProgress from '@material-ui/core/CircularProgress';
55
import Typography from '@material-ui/core/Typography';
6+
import sortBy from 'lodash/sortBy';
67

78
import { useLayer7Notify } from '../../useLayer7Notify';
89
/**
@@ -15,6 +16,7 @@ export const ApiApplicationCredentials = ({ id }) => {
1516
const dataProvider = useDataProvider();
1617
const notify = useLayer7Notify();
1718
const [application, setApplication] = useState();
19+
const [apiKey, setApiKey] = useState({});
1820

1921
const fetchApplication = async id => {
2022
const { data } = await dataProvider.getOne(
@@ -30,11 +32,28 @@ export const ApiApplicationCredentials = ({ id }) => {
3032
return data;
3133
};
3234

35+
const fetchApiKeys = async (appId) => {
36+
const { data } = await dataProvider.getList(
37+
'apiKeys',
38+
{
39+
applicationUuid: appId,
40+
pagination: { page: 1, perPage: 100 },
41+
sort: { field: 'createTs', order: 'DESC' },
42+
},
43+
{
44+
onFailure: error => notify(error),
45+
}
46+
);
47+
const apiKeys = sortBy(data, ({ defaultKey }) => !defaultKey);
48+
setApiKey(apiKeys.length > 0 ? apiKeys[0] : {});
49+
};
50+
3351
React.useEffect(() => {
3452
(async () => {
3553
const data = await fetchApplication(id);
3654
setApplication(data);
3755
})();
56+
fetchApiKeys(id);
3857
}, [id]);
3958

4059
if (!application) {
@@ -47,16 +66,14 @@ export const ApiApplicationCredentials = ({ id }) => {
4766
<span className={classes.label}>
4867
{translate('resources.applications.fields.apiKey')}
4968
</span>
50-
<span id={`api-key-${application.id}`}>
51-
{application.apiKey}
52-
</span>
69+
<span id={`api-key-${application.id}`}>{apiKey.apiKey}</span>
5370
</Typography>
5471
<Typography variant="body2" className={classes.secondaryKey}>
5572
<span className={classes.label}>
5673
{translate('resources.applications.fields.keySecret')}
5774
</span>
5875
<span id={`shared-secret-${application.id}`}>
59-
{application.keySecret}
76+
{apiKey.keySecret}
6077
</span>
6178
</Typography>
6279
</div>

packages/layer7-apihub/src/apis/Application/ApiApplications.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ export const ApiApplications = ({ id }) => {
7272
setLoading(false);
7373
} else if (applications.length < total) {
7474
setApplications(
75-
uniqBy([ ...applications, ...data ], 'id')
75+
uniqBy([ ...applications, ...data ], 'uuid')
7676
);
7777
setCurrentPage(currentPage+1);
7878
} else {

packages/layer7-apihub/src/applications/ApiSelector/ApiChoiceItem.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ export function ApiChoiceItem(props) {
2929
<IconButton
3030
aria-label={translate('ra.action.add')}
3131
className={classes.add}
32-
disabled={selected}
32+
disabled={selected || props.disabled}
3333
onClick={onAdd}
3434
color="primary"
3535
>

packages/layer7-apihub/src/applications/ApiSelector/ApiGroupChoiceItem.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ export function ApiGroupChoiceItem(props) {
3333
<IconButton
3434
aria-label={translate('ra.action.add')}
3535
className={classes.add}
36-
disabled={selected}
36+
disabled={selected || props.disabled}
3737
onClick={onAdd}
3838
color="primary"
3939
>

packages/layer7-apihub/src/applications/ApiSelector/ApiSelector.js

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,17 @@ import { ApiGroupSelectionModal } from './ApiGroupSelectionModal';
2626
import { useLayer7Notify } from '../../useLayer7Notify';
2727

2828
export function ApiSelector(props) {
29-
const { application, resource = '', orgUuid, apis = [] } = props;
29+
const {
30+
application,
31+
resource = '',
32+
orgUuid,
33+
apiIds = [],
34+
ApiGroupIds = [],
35+
ApiApiPlanIds = [],
36+
isEditApisLocked = false,
37+
isEditApiGroupsLocked = false,
38+
} = props;
39+
const apis = apiIds;
3040
const translate = useTranslate();
3141
const [selectedTab, setSelectedTab] = React.useState('apis');
3242
const [selectedItems, setSelectedItems] = React.useState(apis);
@@ -35,11 +45,14 @@ export function ApiSelector(props) {
3545
const [apiPlansEnabled, setApiPlansEnabled] = React.useState(false);
3646
const [tags, setTags] = React.useState([]);
3747
const [filterTags, setFilterTags] = React.useState([]);
38-
3948
const form = useForm();
4049
const classes = useStyles(props);
4150
const dataProvider = useDataProvider();
4251
const notify = useLayer7Notify();
52+
const [
53+
isLoadedApiPlansFeatureFlag,
54+
setIsLoadedApiPlansFeatureFlag,
55+
] = React.useState(false);
4356

4457
const {
4558
data: apiPlanFeatureFlag,
@@ -52,6 +65,7 @@ export function ApiSelector(props) {
5265

5366
React.useEffect(() => {
5467
if (apiPlanFeatureFlag) {
68+
setIsLoadedApiPlansFeatureFlag(true);
5569
setApiPlansEnabled(apiPlanFeatureFlag.value === 'true');
5670
}
5771
}, [apiPlanFeatureFlag]);
@@ -78,32 +92,28 @@ export function ApiSelector(props) {
7892
// to avoid dealing with many loaded/loading states and prevent some rerender issues
7993
React.useEffect(() => {
8094
async function fetchInitialSelectedItems() {
81-
if (application.ApiIds && application.ApiIds.results.length > 0) {
95+
if (apiIds && apiIds.length > 0) {
8296
const { data: selectedApis } = await dataProvider.getMany(
8397
'apis',
8498
{
85-
ids: application.ApiIds.results || [],
99+
ids: apiIds || [],
86100
},
87101
{
88102
onFailure: error => notify(error),
89103
}
90104
);
91105

92106
let selectedApiPlans = [];
93-
if (get(application, 'ApiApiPlanIds.results.length', 0)) {
94-
form.change(
95-
'ApiApiPlanIds',
96-
Array.from(application.ApiApiPlanIds.results)
97-
);
98-
107+
if (ApiApiPlanIds.length) {
108+
form.change('ApiApiPlanIds', Array.from(ApiApiPlanIds));
99109
const { data: apiPlans } = await dataProvider.getMany(
100110
'apiPlans',
101111
{
102112
ids: Array.from(
103113
new Set(
104-
application.ApiApiPlanIds.results
105-
.map(result => result.ApiPlanUuid)
106-
.filter(uuid => uuid)
114+
ApiApiPlanIds.map(
115+
result => result.ApiPlanUuid
116+
).filter(uuid => uuid)
107117
)
108118
),
109119
},
@@ -113,17 +123,13 @@ export function ApiSelector(props) {
113123
);
114124
selectedApiPlans = apiPlans;
115125
}
116-
117126
setInitialSelectedApis(
118127
selectedApis,
119128
selectedApiPlans,
120-
get(application, 'ApiApiPlanIds.results', [])
129+
ApiApiPlanIds
121130
);
122131
}
123-
if (
124-
application.ApiGroupIds &&
125-
application.ApiGroupIds.results.length > 0
126-
) {
132+
if (ApiGroupIds && ApiGroupIds.length > 0) {
127133
const { data: apiGroups } = await dataProvider.getList(
128134
'apiGroups',
129135
{
@@ -138,32 +144,29 @@ export function ApiSelector(props) {
138144
}
139145
);
140146
const selectedApiGroups = apiGroups.filter(apiGroup =>
141-
application.ApiGroupIds.results.find(
142-
id => apiGroup.id === id
143-
)
147+
ApiGroupIds.find(id => apiGroup.id === id)
144148
);
145149
setInitialSelectedApiGroups(selectedApiGroups);
146150
}
147151
}
148152

149-
if (application) {
153+
if (isLoadedApiPlansFeatureFlag) {
150154
fetchInitialSelectedItems();
151155
}
152-
}, [JSON.stringify(application)]); // eslint-disable-line
156+
}, [isLoadedApiPlansFeatureFlag]); // eslint-disable-line
153157

154158
React.useEffect(() => {
155159
setSelectedItems([]);
156160
setSelectedApi(undefined);
157161
setSelectedApiGroup(undefined);
158162
setSelectedTab('apis');
159-
form.change('ApiIds', undefined);
163+
form.change('apiIds', undefined);
160164
form.change('ApiGroupIds', undefined);
161165
}, [form, orgUuid]);
162166

163167
const setInitialSelectedApis = (records, apiPlans, results) => {
164168
const apiIds = records.map(item => item.id);
165-
form.change('ApiIds', Array.from(apiIds));
166-
169+
form.change('apiIds', Array.from(apiIds));
167170
setSelectedItems(previousSelectedItems => {
168171
const newSelectedItems = new Set(previousSelectedItems);
169172
records.forEach(record => {
@@ -222,11 +225,11 @@ export function ApiSelector(props) {
222225

223226
const handleApiConfirmed = event => {
224227
// Get the current list of ApiIds
225-
const selectedApis = new Set(form.getState().values.ApiIds || []);
228+
const selectedApis = new Set(form.getState().values.apiIds || []);
226229
selectedApis.add(selectedApi.id);
227230

228231
// Update the form by adding the selected API
229-
form.change('ApiIds', Array.from(selectedApis));
232+
form.change('apiIds', Array.from(selectedApis));
230233

231234
const selectedApiPlans = new Set(
232235
form.getState().values.ApiApiPlanIds || []
@@ -328,7 +331,7 @@ export function ApiSelector(props) {
328331
})
329332
);
330333

331-
let field = itemToRemove.type === 'apis' ? 'ApiIds' : 'ApiGroupIds';
334+
let field = itemToRemove.type === 'apis' ? 'apiIds' : 'ApiGroupIds';
332335
// We can't use form.getFieldState here because the tab containing
333336
// the input for the field may not be active and getFieldState returns
334337
// undefined in this case.
@@ -339,10 +342,13 @@ export function ApiSelector(props) {
339342
);
340343

341344
if (apiPlansEnabled) {
342-
const selectedApiPlanIds = form.getState().values['ApiApiPlanIds'] || [];
345+
const selectedApiPlanIds =
346+
form.getState().values['ApiApiPlanIds'] || [];
343347
form.change(
344348
'ApiApiPlanIds',
345-
selectedApiPlanIds.filter(object => object.ApiUuid !== itemToRemove.record.id)
349+
selectedApiPlanIds.filter(
350+
object => object.ApiUuid !== itemToRemove.record.id
351+
)
346352
);
347353
}
348354
};
@@ -403,6 +409,8 @@ export function ApiSelector(props) {
403409
onItemRemoved={handleItemRemoved}
404410
onApiPlanChanged={handleApiPlanChanged}
405411
orgUuid={orgUuid}
412+
isEditApisLocked={isEditApisLocked}
413+
isEditApiGroupsLocked={isEditApiGroupsLocked}
406414
/>
407415
</Grid>
408416
<Grid item xs={7}>
@@ -436,7 +444,7 @@ export function ApiSelector(props) {
436444
{orgUuid && (
437445
<ReferenceArrayInput
438446
label=""
439-
source="ApiIds"
447+
source="apiIds"
440448
reference="apis"
441449
resource={resource}
442450
perPage={5}
@@ -450,7 +458,9 @@ export function ApiSelector(props) {
450458
filters={<TagSelector />}
451459
onAdd={handleApiAdded}
452460
>
453-
<ApiChoiceItem />
461+
<ApiChoiceItem
462+
disabled={isEditApisLocked}
463+
/>
454464
</ListArrayInput>
455465
</ReferenceArrayInput>
456466
)}
@@ -470,7 +480,9 @@ export function ApiSelector(props) {
470480
filters={<ListArrayInputFilter />}
471481
onAdd={handleApiGroupAdded}
472482
>
473-
<ApiGroupChoiceItem />
483+
<ApiGroupChoiceItem
484+
disabled={isEditApiGroupsLocked}
485+
/>
474486
</ListArrayInput>
475487
</ReferenceArrayInput>
476488
)}

packages/layer7-apihub/src/applications/ApiSelector/SelectionList/ApiGroupSelectionListItem.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import { ApiGroupSelectedItem } from './ApiGroupSelectedItem';
2020
import { ApiStatus } from '../../../apis/ApiStatus';
2121

2222
export function ApiGroupSelectionListItem(props) {
23-
const { className, onRemoved, item } = props;
23+
const { className, onRemoved, item, disabled } = props;
2424
const translate = useTranslate();
2525
const classes = useStyles(props);
2626

@@ -38,6 +38,7 @@ export function ApiGroupSelectionListItem(props) {
3838
className={classes.delete}
3939
>
4040
<IconButton
41+
disabled={disabled}
4142
onClick={handleItemRemoved}
4243
edge="end"
4344
aria-label={translate('ra.action.delete')}

packages/layer7-apihub/src/applications/ApiSelector/SelectionList/ApiSelectionListItem.js

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,14 @@ import { ApiSelectionModal } from '../ApiSelectionModal';
2020
import { ApiStatus } from '../../../apis/ApiStatus';
2121

2222
export function ApiSelectionListItem(props) {
23-
const { className, onRemoved, onApiPlanChanged, item, orgUuid } = props;
23+
const {
24+
className,
25+
onRemoved,
26+
onApiPlanChanged,
27+
item,
28+
orgUuid,
29+
disabled,
30+
} = props;
2431
const { record } = item;
2532
const [editApiPlan, setEditApiPlan] = React.useState(false);
2633
const translate = useTranslate();
@@ -57,6 +64,7 @@ export function ApiSelectionListItem(props) {
5764
className={classes.delete}
5865
>
5966
<IconButton
67+
disabled={disabled}
6068
onClick={handleItemRemoved}
6169
edge="end"
6270
aria-label={translate('ra.action.delete')}

0 commit comments

Comments
 (0)