feat(scaffolder): mocked fe flow
This commit is contained in:
+1
-1
@@ -33,7 +33,7 @@
|
||||
"version": "1.0.0",
|
||||
"devDependencies": {
|
||||
"@spotify/eslint-config-oss": "^1.0.1",
|
||||
"@spotify/prettier-config": "^7.0.0",
|
||||
"@spotify/prettier-config": "^8.0.0",
|
||||
"husky": "^4.2.3",
|
||||
"lerna": "^3.20.2",
|
||||
"lint-staged": "^10.1.0",
|
||||
|
||||
@@ -51,6 +51,10 @@ import {
|
||||
graphQlBrowseApiRef,
|
||||
GraphQLEndpoints,
|
||||
} from '@backstage/plugin-graphiql';
|
||||
import {
|
||||
scaffolderApiRef,
|
||||
ScaffolderApi,
|
||||
} from '@backstage/plugin-scaffolder/src/api';
|
||||
|
||||
export const apis = (config: ConfigApi) => {
|
||||
// eslint-disable-next-line no-console
|
||||
@@ -113,8 +117,16 @@ export const apis = (config: ConfigApi) => {
|
||||
builder.add(
|
||||
catalogApiRef,
|
||||
new CatalogClient({
|
||||
apiOrigin: 'http://localhost:3000',
|
||||
basePath: '/catalog/api',
|
||||
apiOrigin: 'http://localhost:7000',
|
||||
basePath: '/catalog',
|
||||
}),
|
||||
);
|
||||
|
||||
builder.add(
|
||||
scaffolderApiRef,
|
||||
new ScaffolderApi({
|
||||
apiOrigin: 'http://localhost:7000',
|
||||
basePath: '/scaffolder/v1',
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -11,3 +11,8 @@ spec:
|
||||
processor: cookiecutter
|
||||
type: website
|
||||
path: '.'
|
||||
parameters:
|
||||
component_name:
|
||||
title: Component name
|
||||
type: string
|
||||
description: Name of the component
|
||||
|
||||
@@ -28,6 +28,8 @@
|
||||
"@material-ui/core": "^4.9.1",
|
||||
"@material-ui/icons": "^4.9.1",
|
||||
"@material-ui/lab": "4.0.0-alpha.45",
|
||||
"@rjsf/core": "^2.1.0",
|
||||
"@rjsf/material-ui": "^2.1.0",
|
||||
"react": "^16.13.1",
|
||||
"react-dom": "^16.13.1",
|
||||
"react-router-dom": "6.0.0-alpha.5",
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createApiRef } from '@backstage/core';
|
||||
import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
|
||||
|
||||
export const scaffolderApiRef = createApiRef<ScaffolderApi>({
|
||||
id: 'plugin.scaffolder.service',
|
||||
description: 'Used to make requests towards the scaffolder backend',
|
||||
});
|
||||
|
||||
export class ScaffolderApi {
|
||||
private apiOrigin: string;
|
||||
private basePath: string;
|
||||
|
||||
constructor({
|
||||
apiOrigin,
|
||||
basePath,
|
||||
}: {
|
||||
apiOrigin: string;
|
||||
basePath: string;
|
||||
}) {
|
||||
this.apiOrigin = apiOrigin;
|
||||
this.basePath = basePath;
|
||||
}
|
||||
|
||||
async scaffold(
|
||||
template: TemplateEntityV1alpha1,
|
||||
values: Record<string, any>,
|
||||
) {
|
||||
const url = `${this.apiOrigin}${this.basePath}/jobs`;
|
||||
const jobId = await fetch(url, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ template, values }),
|
||||
}).then(x => x.json());
|
||||
|
||||
return jobId;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
import React, { useState } from 'react';
|
||||
import useStaleWhileRevalidate from 'swr';
|
||||
import { useParams } from 'react-router-dom';
|
||||
import { LinearProgress, Button } from '@material-ui/core';
|
||||
import { catalogApiRef } from '@backstage/plugin-catalog';
|
||||
import {
|
||||
useApi,
|
||||
SimpleStepper,
|
||||
SimpleStepperStep,
|
||||
Page,
|
||||
Content,
|
||||
ContentHeader,
|
||||
Header,
|
||||
Lifecycle,
|
||||
} from '@backstage/core';
|
||||
import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
|
||||
import { withTheme, IChangeEvent } from '@rjsf/core';
|
||||
import { Theme as MuiTheme } from '@rjsf/material-ui';
|
||||
import { JobStatusModal } from '../JobStatusModal';
|
||||
import { scaffolderApiRef } from '../../api';
|
||||
|
||||
const Form = withTheme(MuiTheme);
|
||||
|
||||
export const CreatePage = () => {
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
const scaffolderApi = useApi(scaffolderApiRef);
|
||||
const { templateName } = useParams();
|
||||
const {
|
||||
data: [template] = [] as TemplateEntityV1alpha1[],
|
||||
isValidating,
|
||||
} = useStaleWhileRevalidate(
|
||||
`templates/${templateName}`,
|
||||
async () =>
|
||||
(catalogApi.getEntities({
|
||||
kind: 'Template',
|
||||
'metadata.name': templateName,
|
||||
}) as any) as Promise<TemplateEntityV1alpha1[]>,
|
||||
);
|
||||
const [formState, setFormState] = useState({});
|
||||
|
||||
const handleChange = (e: IChangeEvent) =>
|
||||
setFormState({ ...formState, ...e.formData });
|
||||
|
||||
const [jobId, setJobId] = useState<string | null>(null);
|
||||
const handleClose = () => setJobId(null);
|
||||
if (!template && isValidating) return <LinearProgress />;
|
||||
if (!template || !template?.spec?.parameters) return null;
|
||||
|
||||
const handleCreate = async () => {
|
||||
const job = await scaffolderApi.scaffold(template, formState);
|
||||
setJobId(job);
|
||||
};
|
||||
|
||||
return (
|
||||
<Page>
|
||||
<Header
|
||||
pageTitleOverride="Create a new component"
|
||||
title={
|
||||
<>
|
||||
Create a new component <Lifecycle alpha shorthand />
|
||||
</>
|
||||
}
|
||||
subtitle="Create new software components using standard templates"
|
||||
/>
|
||||
<Content>
|
||||
<ContentHeader
|
||||
title={template.metadata.title as string}
|
||||
></ContentHeader>
|
||||
{jobId && <JobStatusModal jobId={jobId} onClose={handleClose} />}
|
||||
<SimpleStepper
|
||||
onStepChange={(_prevStep, nextStep) => {
|
||||
if (nextStep === 2) {
|
||||
handleCreate();
|
||||
}
|
||||
}}
|
||||
>
|
||||
<SimpleStepperStep title="Configure your component">
|
||||
<Form
|
||||
formData={formState}
|
||||
onChange={handleChange}
|
||||
schema={{
|
||||
$schema: 'http://json-schema.org/draft-07/schema#',
|
||||
properties: template?.spec?.parameters,
|
||||
}}
|
||||
>
|
||||
<Button hidden />
|
||||
</Form>
|
||||
</SimpleStepperStep>
|
||||
<SimpleStepperStep title="Choose repository">
|
||||
<Form
|
||||
formData={formState}
|
||||
onChange={handleChange}
|
||||
schema={{
|
||||
$schema: 'http://json-schema.org/draft-07/schema#',
|
||||
properties: {
|
||||
repo: {
|
||||
type: 'string',
|
||||
description:
|
||||
'Path to the repo where to upload created component',
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Button hidden />
|
||||
</Form>
|
||||
</SimpleStepperStep>
|
||||
</SimpleStepper>
|
||||
</Content>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { CreatePage } from './CreatePage';
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright 2020 Spotify AB
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React, { useEffect, useState, Suspense } from 'react';
|
||||
import {
|
||||
ExpansionPanel,
|
||||
ExpansionPanelSummary,
|
||||
Typography,
|
||||
ExpansionPanelDetails,
|
||||
LinearProgress,
|
||||
} from '@material-ui/core';
|
||||
import moment from 'moment';
|
||||
import ExpandMoreIcon from '@material-ui/icons/ExpandMore';
|
||||
import { makeStyles } from '@material-ui/core/styles';
|
||||
import { Job } from './types';
|
||||
|
||||
const LazyLog = React.lazy(() => import('react-lazylog/build/LazyLog'));
|
||||
moment.relativeTimeThreshold('ss', 0);
|
||||
const useStyles = makeStyles(theme => ({
|
||||
expansionPanelDetails: {
|
||||
padding: 0,
|
||||
},
|
||||
button: {
|
||||
order: -1,
|
||||
marginRight: 0,
|
||||
marginLeft: '-20px',
|
||||
},
|
||||
neutral: {},
|
||||
failed: {
|
||||
position: 'relative',
|
||||
'&:after': {
|
||||
pointerEvents: 'none',
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
boxShadow: `inset 4px 0px 0px ${theme.palette.error.main}`,
|
||||
},
|
||||
},
|
||||
running: {
|
||||
position: 'relative',
|
||||
'&:after': {
|
||||
pointerEvents: 'none',
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
boxShadow: `inset 4px 0px 0px ${theme.palette.info.main}`,
|
||||
},
|
||||
},
|
||||
cardContent: {
|
||||
backgroundColor: theme.palette.background.default,
|
||||
},
|
||||
success: {
|
||||
position: 'relative',
|
||||
'&:after': {
|
||||
pointerEvents: 'none',
|
||||
content: '""',
|
||||
position: 'absolute',
|
||||
top: 0,
|
||||
right: 0,
|
||||
left: 0,
|
||||
bottom: 0,
|
||||
boxShadow: `inset 4px 0px 0px ${theme.palette.success.main}`,
|
||||
},
|
||||
},
|
||||
}));
|
||||
|
||||
type Props = {
|
||||
name: string;
|
||||
className?: string;
|
||||
log: string[];
|
||||
startedAt: string;
|
||||
finishedAt?: string;
|
||||
status?: Job['status'];
|
||||
};
|
||||
export const JobStage = ({
|
||||
finishedAt,
|
||||
startedAt,
|
||||
name,
|
||||
log,
|
||||
status,
|
||||
}: Props) => {
|
||||
const classes = useStyles();
|
||||
|
||||
const [expanded, setExpanded] = useState(false);
|
||||
useEffect(() => {
|
||||
if (status === 'FAILED') setExpanded(true);
|
||||
}, [status === 'FAILED', setExpanded]);
|
||||
|
||||
const timeElapsed = moment
|
||||
.duration(moment(finishedAt ?? moment()).diff(moment(startedAt)))
|
||||
.humanize();
|
||||
|
||||
return (
|
||||
<ExpansionPanel
|
||||
TransitionProps={{ unmountOnExit: true }}
|
||||
className={
|
||||
status === 'COMPLETE'
|
||||
? classes.success
|
||||
: status === 'FAILED'
|
||||
? classes.failed
|
||||
: classes.neutral
|
||||
}
|
||||
expanded={expanded}
|
||||
onChange={(_, newState) => setExpanded(newState)}
|
||||
>
|
||||
<ExpansionPanelSummary
|
||||
expandIcon={<ExpandMoreIcon />}
|
||||
aria-controls={`panel-${name}-content`}
|
||||
id={`panel-${name}-header`}
|
||||
IconButtonProps={{
|
||||
className: classes.button,
|
||||
}}
|
||||
>
|
||||
<Typography variant="button">
|
||||
{name} ({timeElapsed})
|
||||
</Typography>
|
||||
</ExpansionPanelSummary>
|
||||
<ExpansionPanelDetails className={classes.expansionPanelDetails}>
|
||||
{log.length === 0 ? (
|
||||
'Nothing here...'
|
||||
) : (
|
||||
<Suspense fallback={<LinearProgress />}>
|
||||
<div style={{ height: '20vh', width: '100%' }}>
|
||||
<LazyLog text={log.join('\n')} extraLines={1} enableSearch />
|
||||
</div>
|
||||
</Suspense>
|
||||
)}
|
||||
</ExpansionPanelDetails>
|
||||
</ExpansionPanel>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1,41 @@
|
||||
import React from 'react';
|
||||
import {
|
||||
Dialog,
|
||||
LinearProgress,
|
||||
DialogTitle,
|
||||
DialogContent,
|
||||
} from '@material-ui/core';
|
||||
import { JobStage } from './JobStage';
|
||||
import { useJob } from './jobMocks';
|
||||
|
||||
type Props = {
|
||||
onClose: () => void;
|
||||
jobId: string;
|
||||
};
|
||||
|
||||
export const JobStatusModal = ({ onClose, jobId }: Props) => {
|
||||
const job = useJob(jobId);
|
||||
return (
|
||||
<Dialog open onClose={onClose} fullWidth>
|
||||
<DialogTitle id="responsive-dialog-title">
|
||||
Creating component...
|
||||
</DialogTitle>
|
||||
<DialogContent>
|
||||
{!job ? (
|
||||
<LinearProgress />
|
||||
) : (
|
||||
(job?.stages ?? []).map(step => (
|
||||
<JobStage
|
||||
log={step.log}
|
||||
name={step.name}
|
||||
key={step.name}
|
||||
startedAt={step.startedAt}
|
||||
finishedAt={step.finishedAt}
|
||||
status={step.status}
|
||||
/>
|
||||
))
|
||||
)}
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
);
|
||||
};
|
||||
@@ -0,0 +1 @@
|
||||
export { JobStatusModal } from './JobStatusModal';
|
||||
@@ -0,0 +1,78 @@
|
||||
import { useMemo, useState, useEffect } from 'react';
|
||||
import { Job } from './types';
|
||||
|
||||
function* emulatePoll() {
|
||||
const now = () => new Date().toString();
|
||||
const job: Job = {
|
||||
id: '132536-42362-4253532',
|
||||
metadata: { entity: {}, values: {} },
|
||||
status: 'STARTED',
|
||||
stages: [
|
||||
{
|
||||
name: 'created',
|
||||
startedAt: now(),
|
||||
log: [
|
||||
'Job id #rw-tstywe-tdsy was successfully created and placed in the queue',
|
||||
],
|
||||
status: 'STARTED',
|
||||
},
|
||||
],
|
||||
};
|
||||
let newTime = now();
|
||||
job.stages[0].finishedAt = newTime;
|
||||
job.stages.push({
|
||||
startedAt: newTime,
|
||||
name: 'preparing',
|
||||
log: ['preparing blahblah', 'some other stuuff'],
|
||||
status: 'COMPLETE',
|
||||
});
|
||||
yield job;
|
||||
|
||||
newTime = now();
|
||||
job.stages[1].finishedAt = newTime;
|
||||
job.stages.push({
|
||||
startedAt: newTime,
|
||||
name: 'templating',
|
||||
log: ['templating blahblah', 'some other stuuff'],
|
||||
status: 'COMPLETE',
|
||||
});
|
||||
yield job;
|
||||
|
||||
newTime = now();
|
||||
job.stages[2].finishedAt = newTime;
|
||||
job.stages.push({
|
||||
startedAt: newTime,
|
||||
name: 'pushing',
|
||||
log: ['pushing blahblah', 'some other stuuff'],
|
||||
status: 'STARTED',
|
||||
});
|
||||
yield job;
|
||||
yield job;
|
||||
job.stages[3].status = 'FAILED';
|
||||
job.stages[3].log.push('ERROR OCCURED');
|
||||
|
||||
while (true) yield job;
|
||||
}
|
||||
|
||||
export const useJob = (jobId: string | null) => {
|
||||
const apiMock = useMemo(() => emulatePoll(), [jobId]);
|
||||
const [job, setJob] = useState<Job | void>(undefined);
|
||||
useEffect(() => {
|
||||
if (!jobId) return;
|
||||
const nextJobState = apiMock.next().value as Job;
|
||||
setJob({ ...nextJobState });
|
||||
const intervalId = setInterval(() => {
|
||||
const nextJobState = apiMock.next().value as Job;
|
||||
|
||||
if (nextJobState?.status === 'FAILED') {
|
||||
clearInterval(intervalId);
|
||||
}
|
||||
|
||||
setJob({ ...nextJobState });
|
||||
}, 3000);
|
||||
return () => {
|
||||
clearInterval(intervalId);
|
||||
};
|
||||
}, [jobId, setJob]);
|
||||
return job;
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
import { Writable } from 'stream';
|
||||
import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
|
||||
|
||||
export type Job = {
|
||||
id: string;
|
||||
metadata: {
|
||||
entity: any;
|
||||
values: any;
|
||||
};
|
||||
status: 'PENDING' | 'STARTED' | 'COMPLETE' | 'FAILED';
|
||||
stages: Stage[];
|
||||
logStream?: Writable;
|
||||
logger?: Logger;
|
||||
error?: Error;
|
||||
};
|
||||
|
||||
export type Stage = {
|
||||
name: string;
|
||||
log: string[];
|
||||
status: 'PENDING' | 'STARTED' | 'COMPLETE' | 'FAILED';
|
||||
startedAt: string;
|
||||
finishedAt?: string;
|
||||
};
|
||||
+13
-5
@@ -13,8 +13,11 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
import React, { FC } from 'react';
|
||||
import { Button, Card, Chip, Typography, makeStyles } from '@material-ui/core';
|
||||
import React from 'react';
|
||||
import { generatePath } from 'react-router-dom';
|
||||
import { Button } from '@backstage/core';
|
||||
import { Card, Chip, Typography, makeStyles } from '@material-ui/core';
|
||||
import { createTemplateRoute } from '../../routes';
|
||||
|
||||
const useStyles = makeStyles(theme => ({
|
||||
header: {
|
||||
@@ -42,14 +45,17 @@ type TemplateCardProps = {
|
||||
tags: string[];
|
||||
title: string;
|
||||
type: string;
|
||||
name: string;
|
||||
};
|
||||
const TemplateCard: FC<TemplateCardProps> = ({
|
||||
const TemplateCard = ({
|
||||
description,
|
||||
tags,
|
||||
title,
|
||||
type,
|
||||
}) => {
|
||||
name,
|
||||
}: TemplateCardProps) => {
|
||||
const classes = useStyles();
|
||||
const href = generatePath(createTemplateRoute.path, { templateName: name });
|
||||
|
||||
return (
|
||||
<Card>
|
||||
@@ -65,7 +71,9 @@ const TemplateCard: FC<TemplateCardProps> = ({
|
||||
{description}
|
||||
</Typography>
|
||||
<div className={classes.footer}>
|
||||
<Button color="primary">Choose</Button>
|
||||
<Button color="primary" variant="contained" to={href}>
|
||||
Choose
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
@@ -35,11 +35,11 @@ import {
|
||||
LinearProgress,
|
||||
} from '@material-ui/core';
|
||||
import { Link as RouterLink } from 'react-router-dom';
|
||||
import TemplateCard from '../TemplateCard';
|
||||
import TemplateCard from './TemplateCard';
|
||||
import useStaleWhileRevalidate from 'swr';
|
||||
import { TemplateEntityV1alpha1 } from '@backstage/catalog-model';
|
||||
|
||||
const ScaffolderPage: React.FC<{}> = () => {
|
||||
export const ScaffolderPage: React.FC<{}> = () => {
|
||||
const catalogApi = useApi(catalogApiRef);
|
||||
const errorApi = useApi(errorApiRef);
|
||||
|
||||
@@ -98,6 +98,7 @@ const ScaffolderPage: React.FC<{}> = () => {
|
||||
<Grid item xs={12} sm={6} md={3}>
|
||||
<TemplateCard
|
||||
key={template.metadata.uid}
|
||||
name={template.metadata.name}
|
||||
title={`${
|
||||
(template.metadata.title || template.metadata.name) ?? ''
|
||||
}`}
|
||||
@@ -113,5 +114,3 @@ const ScaffolderPage: React.FC<{}> = () => {
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default ScaffolderPage;
|
||||
|
||||
@@ -14,4 +14,5 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
export { plugin, rootRoute } from './plugin';
|
||||
export { plugin } from './plugin';
|
||||
export { rootRoute, createTemplateRoute } from './routes';
|
||||
|
||||
@@ -14,18 +14,15 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
import { createPlugin, createRouteRef } from '@backstage/core';
|
||||
import ScaffolderPage from './components/ScaffolderPage';
|
||||
|
||||
export const rootRoute = createRouteRef({
|
||||
icon: () => null,
|
||||
path: '/create',
|
||||
title: 'Create entity',
|
||||
});
|
||||
import { createPlugin } from '@backstage/core';
|
||||
import { ScaffolderPage } from './components/ScaffolderPage';
|
||||
import { CreatePage } from './components/CreatePage';
|
||||
import { rootRoute, createTemplateRoute } from './routes';
|
||||
|
||||
export const plugin = createPlugin({
|
||||
id: 'scaffolder',
|
||||
register({ router }) {
|
||||
router.addRoute(rootRoute, ScaffolderPage);
|
||||
router.addRoute(createTemplateRoute, CreatePage);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
import { createRouteRef } from '@backstage/core';
|
||||
|
||||
export const rootRoute = createRouteRef({
|
||||
icon: () => null,
|
||||
path: '/create',
|
||||
title: 'Create new entity',
|
||||
});
|
||||
export const createTemplateRoute = createRouteRef({
|
||||
icon: () => null,
|
||||
path: '/create/:templateName',
|
||||
title: 'Entity creation',
|
||||
});
|
||||
@@ -876,6 +876,14 @@
|
||||
core-js "^2.6.5"
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime-corejs2@^7.8.7":
|
||||
version "7.10.3"
|
||||
resolved "https://registry.npmjs.org/@babel/runtime-corejs2/-/runtime-corejs2-7.10.3.tgz#81bc99a96bfcb6db3f0dcf73fdc577cc554d341b"
|
||||
integrity sha512-enKvnR/kKFbZFgXYo165wtSA5OeiTlgsnU4jV3vpKRhfWUJjLS6dfVcjIPeRcgJbgEgdgu0I+UyBWqu6c0GumQ==
|
||||
dependencies:
|
||||
core-js "^2.6.5"
|
||||
regenerator-runtime "^0.13.4"
|
||||
|
||||
"@babel/runtime-corejs3@^7.10.2":
|
||||
version "7.10.3"
|
||||
resolved "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.10.3.tgz#931ed6941d3954924a7aa967ee440e60c507b91a"
|
||||
@@ -2454,6 +2462,28 @@
|
||||
prop-types "^15.6.1"
|
||||
react-lifecycles-compat "^3.0.4"
|
||||
|
||||
"@rjsf/core@^2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/@rjsf/core/-/core-2.1.0.tgz#00130c89959850cc90224fd14c82feaecc2b9dc8"
|
||||
integrity sha512-2A65RZ3I/RVVNfJUTYUkFs4snX02GHzql6o/KcLBBoG8G8+gr9ZeIi3+JEbe2mOEN02rIPnyJtBkl6C7QajyAw==
|
||||
dependencies:
|
||||
"@babel/runtime-corejs2" "^7.8.7"
|
||||
"@types/json-schema" "^7.0.4"
|
||||
ajv "^6.7.0"
|
||||
core-js "^2.5.7"
|
||||
json-schema-merge-allof "^0.6.0"
|
||||
jsonpointer "^4.0.1"
|
||||
lodash "^4.17.15"
|
||||
prop-types "^15.7.2"
|
||||
react-app-polyfill "^1.0.4"
|
||||
react-is "^16.9.0"
|
||||
shortid "^2.2.14"
|
||||
|
||||
"@rjsf/material-ui@^2.1.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.npmjs.org/@rjsf/material-ui/-/material-ui-2.1.0.tgz#a361b125af3a383b7f671634b8d254345f9f9311"
|
||||
integrity sha512-9mMttnPNP6GiP7BtZGimYcYsbWwjyviqg/PD8oxrkEtZykULXOIdC3WDMJ3nPSym8RvZsgSnB8bajCpa5iSYQQ==
|
||||
|
||||
"@rollup/plugin-commonjs@^13.0.0":
|
||||
version "13.0.0"
|
||||
resolved "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-13.0.0.tgz#8a1d684ba6848afe8b9e3d85649d4b2f6f7217ec"
|
||||
@@ -2561,10 +2591,10 @@
|
||||
eslint-plugin-react "^7.12.4"
|
||||
eslint-plugin-react-hooks "^4.0.0"
|
||||
|
||||
"@spotify/prettier-config@^7.0.0":
|
||||
version "7.0.0"
|
||||
resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-7.0.0.tgz#47750979d1282197295108b6958360660a955c16"
|
||||
integrity sha512-lIMcx/2oDqTtW84iHKkRJe+8U6HK6GPwWH5sJp9UEHcDpdXomOQYvwcGXy2I2zwPQQ14gYYE6nEJuSnnYqsYRw==
|
||||
"@spotify/prettier-config@^8.0.0":
|
||||
version "8.0.0"
|
||||
resolved "https://registry.npmjs.org/@spotify/prettier-config/-/prettier-config-8.0.0.tgz#8b6c2bd579ddc54887155a0721fe04e96c89f7f2"
|
||||
integrity sha512-so8w32ZV42CHWxOEXcBtbNO/hLXFrQNXVmhfzhUI6dVB9cq2xjRaiqu8GjFj8LvKbWpPj+S+KwTIS4aDVWqrFQ==
|
||||
|
||||
"@spotify/web-scripts-utils@^7.0.0":
|
||||
version "7.0.0"
|
||||
@@ -3653,6 +3683,11 @@
|
||||
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.4.tgz#38fd73ddfd9b55abb1e1b2ed578cb55bd7b7d339"
|
||||
integrity sha512-8+KAKzEvSUdeo+kmqnKrqgeE+LcA0tjYWFY7RPProVYwnqDjukzO+3b6dLD56rYX5TdWejnEOLJYOIeh4CXKuA==
|
||||
|
||||
"@types/json-schema@^7.0.4":
|
||||
version "7.0.5"
|
||||
resolved "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.5.tgz#dcce4430e64b443ba8945f0290fb564ad5bac6dd"
|
||||
integrity sha512-7+2BITlgjgDhH0vvwZU/HZJVyk+2XUlvxXe8dFMedNX/aMkaOq++rMAFXc0tM7ij15QaWlbdQASBR9dihi+bDQ==
|
||||
|
||||
"@types/json5@^0.0.29":
|
||||
version "0.0.29"
|
||||
resolved "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee"
|
||||
@@ -4519,7 +4554,7 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
|
||||
resolved "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz#ef916e271c64ac12171fd8384eaae6b2345854da"
|
||||
integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==
|
||||
|
||||
ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.5.5:
|
||||
ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.5.5, ajv@^6.7.0:
|
||||
version "6.12.2"
|
||||
resolved "https://registry.npmjs.org/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd"
|
||||
integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ==
|
||||
@@ -4810,7 +4845,7 @@ arrify@^1.0.1:
|
||||
resolved "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d"
|
||||
integrity sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=
|
||||
|
||||
asap@^2.0.0, asap@~2.0.3:
|
||||
asap@^2.0.0, asap@~2.0.3, asap@~2.0.6:
|
||||
version "2.0.6"
|
||||
resolved "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz#e50347611d7e690943208bbdafebcbc2fb866d46"
|
||||
integrity sha1-5QNHYR1+aQlDIIu9r+vLwvuGbUY=
|
||||
@@ -6380,6 +6415,25 @@ compression@^1.7.4:
|
||||
safe-buffer "5.1.2"
|
||||
vary "~1.1.2"
|
||||
|
||||
compute-gcd@^1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/compute-gcd/-/compute-gcd-1.2.0.tgz#fc1ede5b65001e950226502f46543863e4fea10e"
|
||||
integrity sha1-/B7eW2UAHpUCJlAvRlQ4Y+T+oQ4=
|
||||
dependencies:
|
||||
validate.io-array "^1.0.3"
|
||||
validate.io-function "^1.0.2"
|
||||
validate.io-integer-array "^1.0.0"
|
||||
|
||||
compute-lcm@^1.1.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.npmjs.org/compute-lcm/-/compute-lcm-1.1.0.tgz#abd96d040b41b0a166f89944b5c8b7c511e21ad5"
|
||||
integrity sha1-q9ltBAtBsKFm+JlEtci3xRHiGtU=
|
||||
dependencies:
|
||||
compute-gcd "^1.2.0"
|
||||
validate.io-array "^1.0.3"
|
||||
validate.io-function "^1.0.2"
|
||||
validate.io-integer-array "^1.0.0"
|
||||
|
||||
concat-map@0.0.1:
|
||||
version "0.0.1"
|
||||
resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
|
||||
@@ -6629,7 +6683,7 @@ core-js-pure@^3.0.0, core-js-pure@^3.0.1:
|
||||
resolved "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.4.tgz#4bf1ba866e25814f149d4e9aaa08c36173506e3a"
|
||||
integrity sha512-epIhRLkXdgv32xIUFaaAry2wdxZYBi6bgM7cB136dzzXXa+dFyRLTZeLUJxnd8ShrmyVXBub63n2NHo2JAt8Cw==
|
||||
|
||||
core-js@^2.4.0, core-js@^2.6.5:
|
||||
core-js@^2.4.0, core-js@^2.5.7, core-js@^2.6.5:
|
||||
version "2.6.11"
|
||||
resolved "https://registry.npmjs.org/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
|
||||
integrity sha512-5wjnpaT/3dV+XB4borEsnAYQchn00XSgTAWKDkEqv+K8KevjbzmofK6hfJ9TZIlpj2N0xQpazy7PiRQiWHqzWg==
|
||||
@@ -6639,6 +6693,11 @@ core-js@^3.0.1, core-js@^3.0.4:
|
||||
resolved "https://registry.npmjs.org/core-js/-/core-js-3.6.4.tgz#440a83536b458114b9cb2ac1580ba377dc470647"
|
||||
integrity sha512-4paDGScNgZP2IXXilaffL9X7968RuvwlkK3xWtZRVqgd8SYNiVKRJvkFd1aqqEuPfN7E68ZHEp9hDj6lHj4Hyw==
|
||||
|
||||
core-js@^3.5.0:
|
||||
version "3.6.5"
|
||||
resolved "https://registry.npmjs.org/core-js/-/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a"
|
||||
integrity sha512-vZVEEwZoIsI+vPEuoF9Iqf5H7/M3eeQqWlQnYa8FSKKePuYTf5MWnxb5SDAzCa60b3JBRS5g9b+Dq7b1y/RCrA==
|
||||
|
||||
core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||
@@ -11644,6 +11703,22 @@ json-parse-better-errors@^1.0.0, json-parse-better-errors@^1.0.1, json-parse-bet
|
||||
resolved "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz#bb867cfb3450e69107c131d1c514bab3dc8bcaa9"
|
||||
integrity sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==
|
||||
|
||||
json-schema-compare@^0.2.2:
|
||||
version "0.2.2"
|
||||
resolved "https://registry.npmjs.org/json-schema-compare/-/json-schema-compare-0.2.2.tgz#dd601508335a90c7f4cfadb6b2e397225c908e56"
|
||||
integrity sha512-c4WYmDKyJXhs7WWvAWm3uIYnfyWFoIp+JEoX34rctVvEkMYCPGhXtvmFFXiffBbxfZsvQ0RNnV5H7GvDF5HCqQ==
|
||||
dependencies:
|
||||
lodash "^4.17.4"
|
||||
|
||||
json-schema-merge-allof@^0.6.0:
|
||||
version "0.6.0"
|
||||
resolved "https://registry.npmjs.org/json-schema-merge-allof/-/json-schema-merge-allof-0.6.0.tgz#64d48820fec26b228db837475ce3338936bf59a5"
|
||||
integrity sha512-LEw4VMQVRceOPLuGRWcxW5orTTiR9ZAtqTAe4rQUjNADTeR81bezBVFa0MqIwp0YmHIM1KkhSjZM7o+IQhaPbQ==
|
||||
dependencies:
|
||||
compute-lcm "^1.1.0"
|
||||
json-schema-compare "^0.2.2"
|
||||
lodash "^4.17.4"
|
||||
|
||||
json-schema-traverse@^0.4.1:
|
||||
version "0.4.1"
|
||||
resolved "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660"
|
||||
@@ -11718,6 +11793,11 @@ jsonparse@^1.2.0:
|
||||
resolved "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
|
||||
integrity sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=
|
||||
|
||||
jsonpointer@^4.0.1:
|
||||
version "4.0.1"
|
||||
resolved "https://registry.npmjs.org/jsonpointer/-/jsonpointer-4.0.1.tgz#4fd92cb34e0e9db3c89c8622ecf51f9b978c6cb9"
|
||||
integrity sha1-T9kss04OnbPInIYi7PUfm5eMbLk=
|
||||
|
||||
jsprim@^1.2.2:
|
||||
version "1.4.1"
|
||||
resolved "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2"
|
||||
@@ -13087,6 +13167,11 @@ nano-css@^5.2.1:
|
||||
stacktrace-js "^2.0.0"
|
||||
stylis "3.5.0"
|
||||
|
||||
nanoid@^2.1.0:
|
||||
version "2.1.11"
|
||||
resolved "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz#ec24b8a758d591561531b4176a01e3ab4f0f0280"
|
||||
integrity sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA==
|
||||
|
||||
nanomatch@^1.2.9:
|
||||
version "1.2.13"
|
||||
resolved "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz#b87a8aa4fc0de8fe6be88895b38983ff265bd119"
|
||||
@@ -15008,6 +15093,13 @@ promise.series@^0.2.0:
|
||||
resolved "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz#2cc7ebe959fc3a6619c04ab4dbdc9e452d864bbd"
|
||||
integrity sha1-LMfr6Vn8OmYZwEq029yeRS2GS70=
|
||||
|
||||
promise@^8.0.3:
|
||||
version "8.1.0"
|
||||
resolved "https://registry.npmjs.org/promise/-/promise-8.1.0.tgz#697c25c3dfe7435dd79fcd58c38a135888eaf05e"
|
||||
integrity sha512-W04AqnILOL/sPRXziNicCjSNRruLAuIHEOVBazepu0545DDNGYHz7ar9ZgZ1fMU8/MA4mVxp5rkBWRi6OXIy3Q==
|
||||
dependencies:
|
||||
asap "~2.0.6"
|
||||
|
||||
promisify-node@~0.3.0:
|
||||
version "0.3.0"
|
||||
resolved "https://registry.npmjs.org/promisify-node/-/promisify-node-0.3.0.tgz#b4b55acf90faa7d2b8b90ca396899086c03060cf"
|
||||
@@ -15218,6 +15310,13 @@ raf-schd@^4.0.0:
|
||||
resolved "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.2.tgz#bd44c708188f2e84c810bf55fcea9231bcaed8a0"
|
||||
integrity sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ==
|
||||
|
||||
raf@^3.4.1:
|
||||
version "3.4.1"
|
||||
resolved "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39"
|
||||
integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==
|
||||
dependencies:
|
||||
performance-now "^2.1.0"
|
||||
|
||||
ramda@0.26.1, ramda@^0.26:
|
||||
version "0.26.1"
|
||||
resolved "https://registry.npmjs.org/ramda/-/ramda-0.26.1.tgz#8d41351eb8111c55353617fc3bbffad8e4d35d06"
|
||||
@@ -15296,6 +15395,18 @@ rc@^1.2.7, rc@^1.2.8:
|
||||
minimist "^1.2.0"
|
||||
strip-json-comments "~2.0.1"
|
||||
|
||||
react-app-polyfill@^1.0.4:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.npmjs.org/react-app-polyfill/-/react-app-polyfill-1.0.6.tgz#890f8d7f2842ce6073f030b117de9130a5f385f0"
|
||||
integrity sha512-OfBnObtnGgLGfweORmdZbyEz+3dgVePQBb3zipiaDsMHV1NpWm0rDFYIVXFV/AK+x4VIIfWHhrdMIeoTLyRr2g==
|
||||
dependencies:
|
||||
core-js "^3.5.0"
|
||||
object-assign "^4.1.1"
|
||||
promise "^8.0.3"
|
||||
raf "^3.4.1"
|
||||
regenerator-runtime "^0.13.3"
|
||||
whatwg-fetch "^3.0.0"
|
||||
|
||||
react-beautiful-dnd@11.0.3:
|
||||
version "11.0.3"
|
||||
resolved "https://registry.npmjs.org/react-beautiful-dnd/-/react-beautiful-dnd-11.0.3.tgz#5678bb3e725d8b56cb7cf57f56e952105fc4f2af"
|
||||
@@ -16799,6 +16910,13 @@ shellwords@^0.1.1:
|
||||
resolved "https://registry.npmjs.org/shellwords/-/shellwords-0.1.1.tgz#d6b9181c1a48d397324c84871efbcfc73fc0654b"
|
||||
integrity sha512-vFwSUfQvqybiICwZY5+DAWIPLKsWO31Q91JSKl3UYv+K5c2QRPzn0qzec6QPu1Qc9eHYItiP3NdJqNVqetYAww==
|
||||
|
||||
shortid@^2.2.14:
|
||||
version "2.2.15"
|
||||
resolved "https://registry.npmjs.org/shortid/-/shortid-2.2.15.tgz#2b902eaa93a69b11120373cd42a1f1fe4437c122"
|
||||
integrity sha512-5EaCy2mx2Jgc/Fdn9uuDuNIIfWBpzY4XIlhoqtXF6qsf+/+SGZ+FxDdX/ZsMZiWupIWNqAEmiNY4RC+LSmCeOw==
|
||||
dependencies:
|
||||
nanoid "^2.1.0"
|
||||
|
||||
side-channel@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz#df5d1abadb4e4bf4af1cd8852bf132d2f7876947"
|
||||
@@ -18800,6 +18918,36 @@ validate-npm-package-name@^3.0.0:
|
||||
dependencies:
|
||||
builtins "^1.0.3"
|
||||
|
||||
validate.io-array@^1.0.3:
|
||||
version "1.0.6"
|
||||
resolved "https://registry.npmjs.org/validate.io-array/-/validate.io-array-1.0.6.tgz#5b5a2cafd8f8b85abb2f886ba153f2d93a27774d"
|
||||
integrity sha1-W1osr9j4uFq7L4hroVPy2Tond00=
|
||||
|
||||
validate.io-function@^1.0.2:
|
||||
version "1.0.2"
|
||||
resolved "https://registry.npmjs.org/validate.io-function/-/validate.io-function-1.0.2.tgz#343a19802ed3b1968269c780e558e93411c0bad7"
|
||||
integrity sha1-NDoZgC7TsZaCaceA5VjpNBHAutc=
|
||||
|
||||
validate.io-integer-array@^1.0.0:
|
||||
version "1.0.0"
|
||||
resolved "https://registry.npmjs.org/validate.io-integer-array/-/validate.io-integer-array-1.0.0.tgz#2cabde033293a6bcbe063feafe91eaf46b13a089"
|
||||
integrity sha1-LKveAzKTpry+Bj/q/pHq9GsToIk=
|
||||
dependencies:
|
||||
validate.io-array "^1.0.3"
|
||||
validate.io-integer "^1.0.4"
|
||||
|
||||
validate.io-integer@^1.0.4:
|
||||
version "1.0.5"
|
||||
resolved "https://registry.npmjs.org/validate.io-integer/-/validate.io-integer-1.0.5.tgz#168496480b95be2247ec443f2233de4f89878068"
|
||||
integrity sha1-FoSWSAuVviJH7EQ/IjPeT4mHgGg=
|
||||
dependencies:
|
||||
validate.io-number "^1.0.3"
|
||||
|
||||
validate.io-number@^1.0.3:
|
||||
version "1.0.3"
|
||||
resolved "https://registry.npmjs.org/validate.io-number/-/validate.io-number-1.0.3.tgz#f63ffeda248bf28a67a8d48e0e3b461a1665baf8"
|
||||
integrity sha1-9j/+2iSL8opnqNSODjtGGhZluvg=
|
||||
|
||||
value-equal@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.npmjs.org/value-equal/-/value-equal-1.0.1.tgz#1e0b794c734c5c0cade179c437d356d931a34d6c"
|
||||
|
||||
Reference in New Issue
Block a user